#include <string.h> and/or #include <stdio.h> not needed.
[obnox/wireshark/wip.git] / epan / dissectors / packet-gpef.c
1 /* packet-gpef.c
2  * Routines for dissection of Group Policy : Encrypted File System Extension
3  * Described in Microsoft document MS-GPEF.pdf
4  * Copyright 2008, Ronnie Sahlberg
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <glib.h>
32 #include <epan/packet.h>
33 #include "packet-windows-common.h"
34 #include <epan/asn1.h>
35 #include "packet-x509af.h"
36 #include "packet-x509if.h"
37
38 static int proto_gpef = -1;
39 static int hf_gpef_keycount = -1;
40 static int hf_gpef_efskey = -1;
41 static int hf_gpef_efskey_length1 = -1;
42 static int hf_gpef_efskey_length2 = -1;
43 static int hf_gpef_efskey_sid_offset = -1;
44 static int hf_gpef_efskey_cert_offset = -1;
45 static int hf_gpef_efskey_cert_length = -1;
46 static int hf_gpef_efskey_certificate = -1;
47
48 static gint ett_gpef = -1;
49 static gint ett_gpef_efskey = -1;
50
51
52 /* MS-GPEF section 2.2.1.2.2 EfsKey*/
53 static int
54 dissect_gpef_efskey(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
55 {
56         proto_item *item = NULL;
57         proto_tree *tree = NULL;
58         int old_offset = offset;
59         guint32 length1, sid_offset;
60         guint32 cert_length, cert_offset;
61         tvbuff_t *next_tvb;
62         asn1_ctx_t asn1_ctx;
63         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
64
65         if (parent_tree) {
66                 item = proto_tree_add_item(parent_tree, hf_gpef_efskey, tvb, -1, -1, FALSE);
67                 tree = proto_item_add_subtree(item, ett_gpef_efskey);
68         }
69
70         /* length 1 */
71         length1 = tvb_get_letohl(tvb, offset);
72         proto_tree_add_item(tree, hf_gpef_efskey_length1, tvb, offset, 4, TRUE);
73         offset += 4;
74
75         /* length 2 */
76         proto_tree_add_item(tree, hf_gpef_efskey_length2, tvb, offset, 4, TRUE);
77         offset += 4;
78
79         /* sid offset */
80         sid_offset = tvb_get_letohl(tvb, offset);
81         proto_tree_add_item(tree, hf_gpef_efskey_sid_offset, tvb, offset, 4, TRUE);
82         offset += 4;
83
84         /* reserved */
85         offset += 4;
86
87         /* cert length */
88         cert_length = tvb_get_letohl(tvb, offset);
89         proto_tree_add_item(tree, hf_gpef_efskey_cert_length, tvb, offset, 4, TRUE);
90         offset += 4;
91
92         /* cert offset */
93         cert_offset = tvb_get_letohl(tvb, offset);
94         proto_tree_add_item(tree, hf_gpef_efskey_cert_offset, tvb, offset, 4, TRUE);
95         offset += 4;
96
97         /* reserved, must be 0x20 0x00 0x00 0x00 */
98         offset += 4;
99
100         /* sid */
101         dissect_nt_sid(tvb, old_offset+4+sid_offset, tree, "sid", NULL, -1);
102
103         /* certificate */
104         next_tvb = tvb_new_subset(tvb, old_offset+4+cert_offset, cert_length, cert_length);
105         (void)dissect_x509af_Certificate(FALSE, next_tvb, 0, &asn1_ctx, tree, hf_gpef_efskey_certificate);
106
107
108         offset = old_offset + length1;
109         proto_item_set_len(item, offset-old_offset);
110         return offset;
111 }
112
113 /* MS-GPEF section 2.2.1.2.1 */
114 static int
115 dissect_gpef_efsblob(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree)
116 {
117         int offset = 0;
118         proto_tree *tree = NULL;
119         proto_item *item = NULL;
120         guint32 count;
121
122         if (parent_tree) {
123                 item = proto_tree_add_item(parent_tree, proto_gpef, tvb, 0, -1, FALSE);
124                 tree = proto_item_add_subtree(item, ett_gpef);
125         }
126
127         /* reserved, must be 0x01 0x00 0x01 0x00 */
128         offset += 4;
129
130         /* key count */
131         count = tvb_get_letohl(tvb, offset);
132         proto_tree_add_item(tree, hf_gpef_keycount, tvb, offset, 4, TRUE);
133         offset += 4;
134
135         while (count--) {
136               offset = dissect_gpef_efskey(tvb, offset, pinfo, tree);
137         }
138
139         return offset;
140 }
141
142 void
143 proto_register_gpef(void)
144 {
145         static hf_register_info hf[] = {
146         { &hf_gpef_keycount,
147         { "Key Count",   "gpef.key_count", FT_UINT32, BASE_DEC, NULL,
148                 0x0, NULL, HFILL }},
149
150         { &hf_gpef_efskey_length1,
151         { "Length1",   "gpef.efskey.length1", FT_UINT32, BASE_DEC, NULL,
152                 0x0, NULL, HFILL }},
153
154         { &hf_gpef_efskey_length2,
155         { "Length2",   "gpef.efskey.length2", FT_UINT32, BASE_DEC, NULL,
156                 0x0, NULL, HFILL }},
157
158         { &hf_gpef_efskey_sid_offset,
159         { "SID Offset",   "gpef.efskey.sid_offset", FT_UINT32, BASE_DEC, NULL,
160                 0x0, NULL, HFILL }},
161
162         { &hf_gpef_efskey_cert_offset,
163         { "Cert Offset",   "gpef.efskey.cert_offset", FT_UINT32, BASE_DEC, NULL,
164                 0x0, NULL, HFILL }},
165
166         { &hf_gpef_efskey_cert_length,
167         { "Cert Length",   "gpef.efskey.cert_length", FT_UINT32, BASE_DEC, NULL,
168                 0x0, NULL, HFILL }},
169
170         { &hf_gpef_efskey,
171         { "EfsKey",   "gpef.efskey", FT_NONE, BASE_NONE, NULL,
172                 0x0, NULL, HFILL }},
173
174         { &hf_gpef_efskey_certificate,
175         { "Certificate", "gpef.efskey.certificate", FT_NONE, BASE_NONE, NULL,
176                 0x0, NULL, HFILL }},
177
178         };
179
180         static gint *ett[] = {
181                 &ett_gpef,
182                 &ett_gpef_efskey,
183         };
184
185         proto_gpef = proto_register_protocol("GPEF", "GPEF", "gpef");
186         proto_register_field_array(proto_gpef, hf, array_length(hf));
187         proto_register_subtree_array(ett, array_length(ett));
188
189         new_register_dissector("efsblob", dissect_gpef_efsblob, proto_gpef);
190 }
191
192 void
193 proto_reg_handoff_gpef(void)
194 {
195 }