Sanitize epan includes
[obnox/wireshark/wip.git] / epan / dissectors / packet-smb-sidsnooping.c
1 /* packet-smb-sidsnooping.c
2  * Routines for snooping SID to name mappings
3  * Copyright 2003, Ronnie Sahlberg
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <epan/packet_info.h>
33 #include <epan/epan_dissect.h>
34 #include <epan/proto.h>
35 #include <epan/tap.h>
36 #include <epan/emem.h>
37 #include <epan/strutil.h>
38 #include "packet-dcerpc.h"
39 #include "packet-dcerpc-nt.h"
40 #include "register.h"
41 #include <epan/dissectors/packet-smb.h>
42 #include "packet-smb-sidsnooping.h"
43
44 static int hf_lsa = -1;
45 static int hf_lsa_info_level = -1;
46 static int hf_lsa_opnum = -1;
47 static int hf_lsa_domain = -1;
48 static int hf_nt_domain_sid = -1;
49 static int hf_samr_hnd = -1;
50 static int hf_samr_rid = -1;
51 static int hf_samr_acct_name = -1;
52 static int hf_samr_level = -1;
53
54
55 GHashTable *sid_name_table = NULL;
56
57
58 static GHashTable *ctx_handle_table = NULL;
59
60
61 static gboolean lsa_policy_information_tap_installed = FALSE;
62 static gboolean samr_query_dispinfo_tap_installed = FALSE;
63
64
65 char *
66 find_sid_name(char *sid)
67 {
68         sid_name *sn;
69         sid_name old_sn;
70
71         old_sn.sid=sid;
72         sn=g_hash_table_lookup(sid_name_table, &old_sn);
73         if(!sn){
74                 return NULL;
75         }
76         return sn->name;
77 }
78
79 static void
80 add_sid_name_mapping(char *sid, char *name)
81 {
82         sid_name *sn;
83         sid_name old_sn;
84
85         old_sn.sid=sid;
86         sn=g_hash_table_lookup(sid_name_table, &old_sn);
87         if(sn){
88                 return;
89         }
90
91         sn=se_alloc(sizeof(sid_name));
92         sn->sid=g_strdup(sid);
93         sn->name=g_strdup(name);
94         g_hash_table_insert(sid_name_table, sn, sn);
95 }
96
97
98
99 /*
100  * QueryDispInfo :
101  * level  1 : user displayinfo 1
102  */
103 static int
104 samr_query_dispinfo(void *dummy _U_, packet_info *pinfo, epan_dissect_t *edt, const void *pri)
105 {
106         const dcerpc_info *ri=pri;
107         void *old_ctx=NULL;
108         char *pol_name;
109         char *sid;
110         int sid_len;
111         int num_rids;
112         int num_names;
113         GPtrArray *gp;
114         GPtrArray *gp_rids;
115         GPtrArray *gp_names;
116         field_info *fi;
117         field_info *fi_rid;
118         field_info *fi_name;
119         char sid_name[256];
120         int info_level;
121
122         gp=proto_get_finfo_ptr_array(edt->tree, hf_samr_level);
123         if(!gp || gp->len!=1){
124                 return 0;
125         }
126         fi=gp->pdata[0];
127         info_level=fi->value.value.sinteger;
128
129         if(info_level!=1){
130                 return 0;
131         }
132
133         if(!ri){
134                 return 0;
135         }
136         if(!ri->call_data){
137                 return 0;
138         }
139         if(ri->ptype == PDU_REQ){
140                 gp=proto_get_finfo_ptr_array(edt->tree, hf_samr_hnd);
141                 if(!gp || gp->len!=1){
142                         return 0;
143                 }
144                 fi=gp->pdata[0];
145
146                 old_ctx=g_hash_table_lookup(ctx_handle_table, GINT_TO_POINTER(pinfo->fd->num));
147                 if(old_ctx){
148                         g_hash_table_remove(ctx_handle_table, GINT_TO_POINTER(pinfo->fd->num));
149                 }
150                 if(!old_ctx){
151                         old_ctx=se_alloc(20);
152                         memcpy(old_ctx, fi->value.value.bytes->data, 20);
153                 }
154                 g_hash_table_insert(ctx_handle_table, GINT_TO_POINTER(pinfo->fd->num), old_ctx);
155
156                 return 0;
157         }
158
159         if(!ri->call_data->req_frame){
160                 return 0;
161         }
162
163         old_ctx=g_hash_table_lookup(ctx_handle_table, GINT_TO_POINTER(ri->call_data->req_frame));
164         if(!old_ctx){
165                 return 0;
166         }
167
168         if (!dcerpc_fetch_polhnd_data(old_ctx, &pol_name, NULL, NULL, NULL, ri->call_data->req_frame)) {
169                 return 0;
170         }
171
172         if (!pol_name)
173                 return 0;
174
175         sid=strstr(pol_name,"S-1-5");
176         if(!sid){
177                 return 0;
178         }
179
180         for(sid_len=4;1;sid_len++){
181                 if((sid[sid_len]>='0') && (sid[sid_len]<='9')){
182                         continue;
183                 }
184                 if(sid[sid_len]=='-'){
185                         continue;
186                 }
187                 break;
188         }
189
190         gp_rids=proto_get_finfo_ptr_array(edt->tree, hf_samr_rid);
191         if(!gp_rids || gp_rids->len<1){
192                 return 0;
193         }
194         num_rids=gp_rids->len;
195         gp_names=proto_get_finfo_ptr_array(edt->tree, hf_samr_acct_name);
196         if(!gp_names || gp_names->len<1){
197                 return 0;
198         }
199         num_names=gp_names->len;
200
201         if(num_rids>num_names){
202                 num_rids=num_names;
203         }
204
205         for(;num_rids;num_rids--){
206                 int len=sid_len;
207
208                 fi_rid=gp_rids->pdata[num_rids-1];
209                 fi_name=gp_names->pdata[num_rids-1];
210                 g_strlcpy(sid_name, sid, 256);
211                 sid_name[len++]='-';
212                 g_snprintf(sid_name+len, 256-len, "%d",fi_rid->value.value.sinteger);
213                 add_sid_name_mapping(sid_name, fi_name->value.value.string);
214         }
215         return 1;
216 }
217
218 /*
219  * PolicyInformation :
220  * level  3 : PRIMARY_DOMAIN_INFO lsa.domain_sid -> lsa.domain
221  * level  5 : ACCOUNT_DOMAIN_INFO lsa.domain_sid -> lsa.domain
222  * level 12 : DNS_DOMAIN_INFO     lsa.domain_sid -> lsa.domain
223  */
224 static int
225 lsa_policy_information(void *dummy _U_, packet_info *pinfo _U_, epan_dissect_t *edt, const void *pri _U_)
226 {
227         GPtrArray *gp;
228         field_info *fi;
229         char *domain;
230         char *sid;
231         int info_level;
232
233         gp=proto_get_finfo_ptr_array(edt->tree, hf_lsa_info_level);
234         if(!gp || gp->len!=1){
235                 return 0;
236         }
237         fi=gp->pdata[0];
238         info_level=fi->value.value.sinteger;
239
240         switch(info_level){
241         case 3:
242         case 5:
243         case 12:
244                 gp=proto_get_finfo_ptr_array(edt->tree, hf_lsa_domain);
245                 if(!gp || gp->len!=1){
246                         return 0;
247                 }
248                 fi=gp->pdata[0];
249                 domain=fi->value.value.string;
250
251                 gp=proto_get_finfo_ptr_array(edt->tree, hf_nt_domain_sid);
252                 if(!gp || gp->len!=1){
253                         return 0;
254                 }
255                 fi=gp->pdata[0];
256                 sid=fi->value.value.string;
257
258                 add_sid_name_mapping(sid, domain);
259                 break;
260         }
261         return 0;
262 }
263
264 static gboolean
265 free_all_sid_names(gpointer key_arg, gpointer value _U_, gpointer user_data _U_)
266 {
267         sid_name *sn = (sid_name *)key_arg;
268
269         if(sn->sid){
270                 g_free((gpointer)sn->sid);
271                 sn->sid=NULL;
272         }
273         if(sn->name){
274                 g_free((gpointer)sn->name);
275                 sn->name=NULL;
276         }
277         return TRUE;
278 }
279
280 static gint
281 sid_name_equal(gconstpointer k1, gconstpointer k2)
282 {
283         const sid_name *sn1 = (const sid_name *)k1;
284         const sid_name *sn2 = (const sid_name *)k2;
285
286         return !strcmp(sn1->sid, sn2->sid);
287 }
288
289 static guint
290 sid_name_hash(gconstpointer k)
291 {
292         const sid_name *sn = (const sid_name *)k;
293         int i, sum;
294
295         for(sum=0,i=(int)strlen(sn->sid)-1;i>=0;i--){
296                 sum+=sn->sid[i];
297         }
298
299         return sum;
300 }
301
302
303 static gboolean
304 free_all_ctx_handle(gpointer key_arg _U_, gpointer value _U_, gpointer user_data _U_)
305 {
306         return TRUE;
307 }
308 static gint
309 ctx_handle_equal(gconstpointer k1, gconstpointer k2)
310 {
311         int sn1 = GPOINTER_TO_INT(k1);
312         int sn2 = GPOINTER_TO_INT(k2);
313
314         return sn1==sn2;
315 }
316
317 static guint
318 ctx_handle_hash(gconstpointer k)
319 {
320         int sn = GPOINTER_TO_INT(k);
321
322         return sn;
323 }
324
325
326 static void
327 sid_snooping_init(void)
328 {
329         header_field_info *hfi;
330         GString *error_string;
331
332         if(lsa_policy_information_tap_installed){
333                 remove_tap_listener(&lsa_policy_information_tap_installed);
334                 lsa_policy_information_tap_installed=FALSE;
335         }
336         if(samr_query_dispinfo_tap_installed){
337                 remove_tap_listener(&samr_query_dispinfo_tap_installed);
338                 samr_query_dispinfo_tap_installed=FALSE;
339         }
340
341         if(sid_name_table){
342                 g_hash_table_foreach_remove(sid_name_table, free_all_sid_names, NULL);
343                 sid_name_table=NULL;
344         }
345         if(ctx_handle_table){
346                 g_hash_table_foreach_remove(ctx_handle_table, free_all_ctx_handle, NULL);
347                 ctx_handle_table=NULL;
348         }
349
350
351 /* this code needs to be rewritten from scratch
352    disabling it now so that it wont cause wireshark to abort due to
353    unknown hf fields
354  */
355 sid_name_snooping=0;
356
357         if(!sid_name_snooping){
358                 return;
359         }
360
361         sid_name_table=g_hash_table_new(sid_name_hash, sid_name_equal);
362
363
364         ctx_handle_table=g_hash_table_new(ctx_handle_hash, ctx_handle_equal);
365
366
367         hf_lsa=proto_get_id_by_filter_name("lsa");
368
369         hfi=proto_registrar_get_byname("lsa.opnum");
370         if(hfi){
371                 hf_lsa_opnum=hfi->id;
372         }
373
374         hfi=proto_registrar_get_byname("nt.domain_sid");
375         if(hfi){
376                 hf_nt_domain_sid=hfi->id;
377         }
378
379         hfi=proto_registrar_get_byname("lsa.domain");
380         if(hfi){
381                 hf_lsa_domain=hfi->id;
382         }
383
384         hfi=proto_registrar_get_byname("lsa.info.level");
385         if(hfi){
386                 hf_lsa_info_level=hfi->id;
387         }
388
389         hfi=proto_registrar_get_byname("samr.handle");
390         if(hfi){
391                 hf_samr_hnd=hfi->id;
392         }
393         hfi=proto_registrar_get_byname("samr.rid");
394         if(hfi){
395                 hf_samr_rid=hfi->id;
396         }
397         hfi=proto_registrar_get_byname("samr.acct_name");
398         if(hfi){
399                 hf_samr_acct_name=hfi->id;
400         }
401         hfi=proto_registrar_get_byname("samr.level");
402         if(hfi){
403                 hf_samr_level=hfi->id;
404         }
405
406
407         error_string=register_tap_listener("dcerpc",
408             &lsa_policy_information_tap_installed,
409             "lsa.policy_information and ( lsa.info.level or lsa.domain or nt.domain_sid )",
410             TL_REQUIRES_PROTO_TREE, NULL, lsa_policy_information, NULL);
411         if(error_string){
412                 /* error, we failed to attach to the tap. clean up */
413
414                 fprintf(stderr, "tshark: Couldn't register proto_reg_handoff_smb_sidsnooping()/lsa_policy_information tap: %s\n",
415                     error_string->str);
416                 g_string_free(error_string, TRUE);
417                 return;
418         }
419         lsa_policy_information_tap_installed=TRUE;
420
421         error_string=register_tap_listener("dcerpc",
422             &samr_query_dispinfo_tap_installed,
423             "samr and samr.opnum==40 and ( samr.handle or samr.rid or samr.acct_name or samr.level )",
424             TL_REQUIRES_PROTO_TREE, NULL, samr_query_dispinfo, NULL);
425         if(error_string){
426                 /* error, we failed to attach to the tap. clean up */
427
428                 fprintf(stderr, "tshark: Couldn't register proto_reg_handoff_smb_sidsnooping()/samr_query_dispinfo tap: %s\n",
429                     error_string->str);
430                 g_string_free(error_string, TRUE);
431                 return;
432         }
433         samr_query_dispinfo_tap_installed=TRUE;
434 }
435
436 void
437 proto_register_smb_sidsnooping(void)
438 {
439         register_init_routine(sid_snooping_init);
440 }
441
442 void
443 proto_reg_handoff_smb_sidsnooping(void)
444 {
445 }
446