HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-smb-sidsnooping.c
blob5a8963e592c9eb2e1b218dff0168db36201e62db
1 /* packet-smb-sidsnooping.c
2 * Routines for snooping SID to name mappings
3 * Copyright 2003, Ronnie Sahlberg
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <stdio.h>
29 #include <string.h>
30 #include <epan/packet_info.h>
31 #include <epan/epan_dissect.h>
32 #include <epan/proto.h>
33 #include <epan/tap.h>
34 #include <epan/emem.h>
35 #include <epan/strutil.h>
36 #include "packet-dcerpc.h"
37 #include "packet-dcerpc-nt.h"
38 #include "register.h"
39 #include <epan/dissectors/packet-smb.h>
40 #include "packet-smb-sidsnooping.h"
42 #if 0
43 static int hf_lsa = -1;
44 static int hf_lsa_opnum = -1;
45 #endif
46 static int hf_lsa_info_level = -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;
55 GHashTable *sid_name_table = NULL;
58 static GHashTable *ctx_handle_table = NULL;
61 static gboolean lsa_policy_information_tap_installed = FALSE;
62 static gboolean samr_query_dispinfo_tap_installed = FALSE;
65 char *
66 find_sid_name(const char *sid)
68 sid_name *sn;
69 sid_name old_sn;
71 old_sn.sid=(char*)sid;
72 sn=(sid_name *)g_hash_table_lookup(sid_name_table, &old_sn);
73 if(!sn){
74 return NULL;
76 return sn->name;
79 static void
80 add_sid_name_mapping(char *sid, char *name)
82 sid_name *sn;
83 sid_name old_sn;
85 old_sn.sid=sid;
86 sn=(sid_name *)g_hash_table_lookup(sid_name_table, &old_sn);
87 if(sn){
88 return;
91 sn=wmem_new(wmem_file_scope(), sid_name);
92 sn->sid=g_strdup(sid);
93 sn->name=g_strdup(name);
94 g_hash_table_insert(sid_name_table, sn, sn);
100 * QueryDispInfo :
101 * level 1 : user displayinfo 1
103 static int
104 samr_query_dispinfo(void *dummy _U_, packet_info *pinfo, epan_dissect_t *edt, const void *pri)
106 const dcerpc_info *ri=(const dcerpc_info *)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_str[256];
120 int info_level;
122 gp=proto_get_finfo_ptr_array(edt->tree, hf_samr_level);
123 if(!gp || gp->len!=1){
124 return 0;
126 fi=(field_info *)gp->pdata[0];
127 info_level=fi->value.value.sinteger;
129 if(info_level!=1){
130 return 0;
133 if(!ri){
134 return 0;
136 if(!ri->call_data){
137 return 0;
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;
144 fi=(field_info *)gp->pdata[0];
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));
150 if(!old_ctx){
151 old_ctx=wmem_memdup(wmem_file_scope(), fi->value.value.bytes->data, 20);
153 g_hash_table_insert(ctx_handle_table, GINT_TO_POINTER(pinfo->fd->num), old_ctx);
155 return 0;
158 if(!ri->call_data->req_frame){
159 return 0;
162 old_ctx=g_hash_table_lookup(ctx_handle_table, GINT_TO_POINTER(ri->call_data->req_frame));
163 if(!old_ctx){
164 return 0;
167 if (!dcerpc_fetch_polhnd_data((e_ctx_hnd *)old_ctx, &pol_name, NULL, NULL, NULL, ri->call_data->req_frame)) {
168 return 0;
171 if (!pol_name)
172 return 0;
174 sid=strstr(pol_name,"S-1-5");
175 if(!sid){
176 return 0;
179 for(sid_len=4;1;sid_len++){
180 if((sid[sid_len]>='0') && (sid[sid_len]<='9')){
181 continue;
183 if(sid[sid_len]=='-'){
184 continue;
186 break;
189 gp_rids=proto_get_finfo_ptr_array(edt->tree, hf_samr_rid);
190 if(!gp_rids || gp_rids->len<1){
191 return 0;
193 num_rids=gp_rids->len;
194 gp_names=proto_get_finfo_ptr_array(edt->tree, hf_samr_acct_name);
195 if(!gp_names || gp_names->len<1){
196 return 0;
198 num_names=gp_names->len;
200 if(num_rids>num_names){
201 num_rids=num_names;
204 for(;num_rids;num_rids--){
205 int len=sid_len;
206 if (len > 247)
207 len = 247;
209 fi_rid=(field_info *)gp_rids->pdata[num_rids-1];
210 fi_name=(field_info *)gp_names->pdata[num_rids-1];
211 g_strlcpy(sid_name_str, sid, 256);
212 sid_name_str[len++]='-';
213 g_snprintf(sid_name_str+len, 256-len, "%d",fi_rid->value.value.sinteger);
214 add_sid_name_mapping(sid_name_str, fi_name->value.value.string);
216 return 1;
220 * PolicyInformation :
221 * level 3 : PRIMARY_DOMAIN_INFO lsa.domain_sid -> lsa.domain
222 * level 5 : ACCOUNT_DOMAIN_INFO lsa.domain_sid -> lsa.domain
223 * level 12 : DNS_DOMAIN_INFO lsa.domain_sid -> lsa.domain
225 static int
226 lsa_policy_information(void *dummy _U_, packet_info *pinfo _U_, epan_dissect_t *edt, const void *pri _U_)
228 GPtrArray *gp;
229 field_info *fi;
230 char *domain;
231 char *sid;
232 int info_level;
234 gp=proto_get_finfo_ptr_array(edt->tree, hf_lsa_info_level);
235 if(!gp || gp->len!=1){
236 return 0;
238 fi=(field_info *)gp->pdata[0];
239 info_level=fi->value.value.sinteger;
241 switch(info_level){
242 case 3:
243 case 5:
244 case 12:
245 gp=proto_get_finfo_ptr_array(edt->tree, hf_lsa_domain);
246 if(!gp || gp->len!=1){
247 return 0;
249 fi=(field_info *)gp->pdata[0];
250 domain=fi->value.value.string;
252 gp=proto_get_finfo_ptr_array(edt->tree, hf_nt_domain_sid);
253 if(!gp || gp->len!=1){
254 return 0;
256 fi=(field_info *)gp->pdata[0];
257 sid=fi->value.value.string;
259 add_sid_name_mapping(sid, domain);
260 break;
262 return 0;
265 static gboolean
266 free_all_sid_names(gpointer key_arg, gpointer value _U_, gpointer user_data _U_)
268 sid_name *sn = (sid_name *)key_arg;
270 if(sn->sid){
271 g_free((gpointer)sn->sid);
272 sn->sid=NULL;
274 if(sn->name){
275 g_free((gpointer)sn->name);
276 sn->name=NULL;
278 return TRUE;
281 static gint
282 sid_name_equal(gconstpointer k1, gconstpointer k2)
284 const sid_name *sn1 = (const sid_name *)k1;
285 const sid_name *sn2 = (const sid_name *)k2;
287 return !strcmp(sn1->sid, sn2->sid);
290 static guint
291 sid_name_hash(gconstpointer k)
293 const sid_name *sn = (const sid_name *)k;
294 int i, sum;
296 for(sum=0,i=(int)strlen(sn->sid)-1;i>=0;i--){
297 sum+=sn->sid[i];
300 return sum;
304 static gboolean
305 free_all_ctx_handle(gpointer key_arg _U_, gpointer value _U_, gpointer user_data _U_)
307 return TRUE;
309 static gint
310 ctx_handle_equal(gconstpointer k1, gconstpointer k2)
312 int sn1 = GPOINTER_TO_INT(k1);
313 int sn2 = GPOINTER_TO_INT(k2);
315 return sn1==sn2;
318 static guint
319 ctx_handle_hash(gconstpointer k)
321 int sn = GPOINTER_TO_INT(k);
323 return sn;
327 static void
328 sid_snooping_init(void)
330 GString *error_string;
332 if(lsa_policy_information_tap_installed){
333 remove_tap_listener(&lsa_policy_information_tap_installed);
334 lsa_policy_information_tap_installed=FALSE;
336 if(samr_query_dispinfo_tap_installed){
337 remove_tap_listener(&samr_query_dispinfo_tap_installed);
338 samr_query_dispinfo_tap_installed=FALSE;
341 if(sid_name_table){
342 g_hash_table_foreach_remove(sid_name_table, free_all_sid_names, NULL);
343 sid_name_table=NULL;
345 if(ctx_handle_table){
346 g_hash_table_foreach_remove(ctx_handle_table, free_all_ctx_handle, NULL);
347 ctx_handle_table=NULL;
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
355 sid_name_snooping=0;
357 if(!sid_name_snooping){
358 return;
361 sid_name_table=g_hash_table_new(sid_name_hash, sid_name_equal);
364 ctx_handle_table=g_hash_table_new(ctx_handle_hash, ctx_handle_equal);
367 #if 0
368 hf_lsa = proto_get_id_by_filter_name("lsa");
369 hf_lsa_opnum = proto_registrar_get_id_byname("lsa.opnum");
370 #endif
371 hf_nt_domain_sid = proto_registrar_get_id_byname("nt.domain_sid");
372 hf_lsa_domain = proto_registrar_get_id_byname("lsa.domain");
373 hf_lsa_info_level = proto_registrar_get_id_byname("lsa.info.level");
374 hf_samr_hnd = proto_registrar_get_id_byname("samr.handle");
375 hf_samr_rid = proto_registrar_get_id_byname("samr.rid");
376 hf_samr_acct_name = proto_registrar_get_id_byname("samr.acct_name");
377 hf_samr_level = proto_registrar_get_id_byname("samr.level");
380 error_string=register_tap_listener("dcerpc",
381 &lsa_policy_information_tap_installed,
382 "lsa.policy_information and ( lsa.info.level or lsa.domain or nt.domain_sid )",
383 TL_REQUIRES_PROTO_TREE, NULL, lsa_policy_information, NULL);
384 if(error_string){
385 /* error, we failed to attach to the tap. clean up */
387 fprintf(stderr, "tshark: Couldn't register proto_reg_handoff_smb_sidsnooping()/lsa_policy_information tap: %s\n",
388 error_string->str);
389 g_string_free(error_string, TRUE);
390 return;
392 lsa_policy_information_tap_installed=TRUE;
394 error_string=register_tap_listener("dcerpc",
395 &samr_query_dispinfo_tap_installed,
396 "samr and samr.opnum==40 and ( samr.handle or samr.rid or samr.acct_name or samr.level )",
397 TL_REQUIRES_PROTO_TREE, NULL, samr_query_dispinfo, NULL);
398 if(error_string){
399 /* error, we failed to attach to the tap. clean up */
401 fprintf(stderr, "tshark: Couldn't register proto_reg_handoff_smb_sidsnooping()/samr_query_dispinfo tap: %s\n",
402 error_string->str);
403 g_string_free(error_string, TRUE);
404 return;
406 samr_query_dispinfo_tap_installed=TRUE;
409 void
410 proto_register_smb_sidsnooping(void)
412 register_init_routine(sid_snooping_init);
415 void
416 proto_reg_handoff_smb_sidsnooping(void)