1 /* packet-smb-sidsnooping.c
2 * Routines for snooping SID to name mappings
3 * Copyright 2003, Ronnie Sahlberg
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include <epan/epan_dissect.h>
17 #include <wsutil/report_message.h>
18 #include "packet-dcerpc.h"
19 #include "packet-dcerpc-nt.h"
20 #include "packet-smb.h"
21 #include "packet-smb-sidsnooping.h"
23 void proto_register_smb_sidsnooping(void);
27 static int hf_lsa_opnum
;
29 static int hf_lsa_info_level
;
30 static int hf_lsa_domain
;
31 static int hf_nt_domain_sid
;
32 static int hf_samr_hnd
;
33 static int hf_samr_rid
;
34 static int hf_samr_acct_name
;
35 static int hf_samr_level
;
38 GHashTable
*sid_name_table
;
41 static GHashTable
*ctx_handle_table
;
44 static bool lsa_policy_information_tap_installed
;
45 static bool samr_query_dispinfo_tap_installed
;
49 find_sid_name(const char *sid
)
51 return (const char *)g_hash_table_lookup(sid_name_table
, sid
);
55 add_sid_name_mapping(const char *sid
, const char *name
)
57 if (find_sid_name(sid
)) {
61 g_hash_table_insert(sid_name_table
, g_strdup(sid
), g_strdup(name
));
68 * level 1 : user displayinfo 1
70 static tap_packet_status
71 samr_query_dispinfo(void *dummy _U_
, packet_info
*pinfo
, epan_dissect_t
*edt
, const void *pri
, tap_flags_t flags _U_
)
73 const dcerpc_info
*ri
=(const dcerpc_info
*)pri
;
86 char sid_name_str
[256];
89 gp
=proto_get_finfo_ptr_array(edt
->tree
, hf_samr_level
);
90 if(!gp
|| gp
->len
!=1){
91 return TAP_PACKET_DONT_REDRAW
;
93 fi
=(field_info
*)gp
->pdata
[0];
94 info_level
= fvalue_get_sinteger(fi
->value
);
97 return TAP_PACKET_DONT_REDRAW
;
101 return TAP_PACKET_DONT_REDRAW
;
104 return TAP_PACKET_DONT_REDRAW
;
106 if(ri
->ptype
== PDU_REQ
){
107 gp
=proto_get_finfo_ptr_array(edt
->tree
, hf_samr_hnd
);
108 if(!gp
|| gp
->len
!=1){
109 return TAP_PACKET_DONT_REDRAW
;
111 fi
=(field_info
*)gp
->pdata
[0];
113 old_ctx
=g_hash_table_lookup(ctx_handle_table
, GINT_TO_POINTER(pinfo
->num
));
115 g_hash_table_remove(ctx_handle_table
, GINT_TO_POINTER(pinfo
->num
));
118 old_ctx
=wmem_memdup(wmem_file_scope(), fvalue_get_bytes_data(fi
->value
), 20);
120 g_hash_table_insert(ctx_handle_table
, GINT_TO_POINTER(pinfo
->num
), old_ctx
);
122 return TAP_PACKET_DONT_REDRAW
;
125 if(!ri
->call_data
->req_frame
){
126 return TAP_PACKET_DONT_REDRAW
;
129 old_ctx
=g_hash_table_lookup(ctx_handle_table
, GINT_TO_POINTER(ri
->call_data
->req_frame
));
131 return TAP_PACKET_DONT_REDRAW
;
134 if (!dcerpc_fetch_polhnd_data((e_ctx_hnd
*)old_ctx
, &pol_name
, NULL
, NULL
, NULL
, ri
->call_data
->req_frame
)) {
135 return TAP_PACKET_DONT_REDRAW
;
139 return TAP_PACKET_DONT_REDRAW
;
141 sid
=strstr(pol_name
,"S-1-5");
143 return TAP_PACKET_DONT_REDRAW
;
146 for(sid_len
=4;1;sid_len
++){
147 if((sid
[sid_len
]>='0') && (sid
[sid_len
]<='9')){
150 if(sid
[sid_len
]=='-'){
156 gp_rids
=proto_get_finfo_ptr_array(edt
->tree
, hf_samr_rid
);
157 if(!gp_rids
|| gp_rids
->len
<1){
158 return TAP_PACKET_DONT_REDRAW
;
160 num_rids
=gp_rids
->len
;
161 gp_names
=proto_get_finfo_ptr_array(edt
->tree
, hf_samr_acct_name
);
162 if(!gp_names
|| gp_names
->len
<1){
163 return TAP_PACKET_DONT_REDRAW
;
165 num_names
=gp_names
->len
;
167 if(num_rids
>num_names
){
171 for(;num_rids
;num_rids
--){
176 fi_rid
=(field_info
*)gp_rids
->pdata
[num_rids
-1];
177 fi_name
=(field_info
*)gp_names
->pdata
[num_rids
-1];
178 (void) g_strlcpy(sid_name_str
, sid
, 256);
179 sid_name_str
[len
++]='-';
180 snprintf(sid_name_str
+len
, 256-len
, "%d", fvalue_get_sinteger(fi_rid
->value
));
181 add_sid_name_mapping(sid_name_str
, fvalue_get_string(fi_name
->value
));
183 return TAP_PACKET_REDRAW
;
187 * PolicyInformation :
188 * level 3 : PRIMARY_DOMAIN_INFO lsa.domain_sid -> lsa.domain
189 * level 5 : ACCOUNT_DOMAIN_INFO lsa.domain_sid -> lsa.domain
190 * level 12 : DNS_DOMAIN_INFO lsa.domain_sid -> lsa.domain
192 static tap_packet_status
193 lsa_policy_information(void *dummy _U_
, packet_info
*pinfo _U_
, epan_dissect_t
*edt
, const void *pri _U_
, tap_flags_t flags _U_
)
201 gp
=proto_get_finfo_ptr_array(edt
->tree
, hf_lsa_info_level
);
202 if(!gp
|| gp
->len
!=1){
203 return TAP_PACKET_DONT_REDRAW
;
205 fi
=(field_info
*)gp
->pdata
[0];
206 info_level
= fvalue_get_sinteger(fi
->value
);
212 gp
=proto_get_finfo_ptr_array(edt
->tree
, hf_lsa_domain
);
213 if(!gp
|| gp
->len
!=1){
214 return TAP_PACKET_DONT_REDRAW
;
216 fi
=(field_info
*)gp
->pdata
[0];
217 domain
=fvalue_get_string(fi
->value
);
219 gp
=proto_get_finfo_ptr_array(edt
->tree
, hf_nt_domain_sid
);
220 if(!gp
|| gp
->len
!=1){
221 return TAP_PACKET_DONT_REDRAW
;
223 fi
=(field_info
*)gp
->pdata
[0];
224 sid
=fvalue_get_string(fi
->value
);
226 add_sid_name_mapping(sid
, domain
);
229 return TAP_PACKET_DONT_REDRAW
;
234 ctx_handle_equal(const void *k1
, const void *k2
)
236 int sn1
= GPOINTER_TO_INT(k1
);
237 int sn2
= GPOINTER_TO_INT(k2
);
243 ctx_handle_hash(const void *k
)
245 int sn
= GPOINTER_TO_INT(k
);
252 sid_snooping_init(void)
254 GString
*error_string
;
256 if(lsa_policy_information_tap_installed
){
257 remove_tap_listener(&lsa_policy_information_tap_installed
);
258 lsa_policy_information_tap_installed
=false;
260 if(samr_query_dispinfo_tap_installed
){
261 remove_tap_listener(&samr_query_dispinfo_tap_installed
);
262 samr_query_dispinfo_tap_installed
=false;
265 sid_name_table
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
267 ctx_handle_table
= g_hash_table_new(ctx_handle_hash
, ctx_handle_equal
);
268 /* TODO this code needs to be rewritten from scratch
269 disabling it now so that it won't cause wireshark to abort due to
272 sid_name_snooping
=false;
274 if(!sid_name_snooping
){
281 hf_lsa
= proto_get_id_by_filter_name("lsa");
282 hf_lsa_opnum
= proto_registrar_get_id_byname("lsa.opnum");
284 hf_nt_domain_sid
= proto_registrar_get_id_byname("nt.domain_sid");
285 hf_lsa_domain
= proto_registrar_get_id_byname("lsa.domain");
286 hf_lsa_info_level
= proto_registrar_get_id_byname("lsa.info.level");
287 hf_samr_hnd
= proto_registrar_get_id_byname("samr.handle");
288 hf_samr_rid
= proto_registrar_get_id_byname("samr.rid");
289 hf_samr_acct_name
= proto_registrar_get_id_byname("samr.acct_name");
290 hf_samr_level
= proto_registrar_get_id_byname("samr.level");
293 error_string
=register_tap_listener("dcerpc",
294 &lsa_policy_information_tap_installed
,
295 "lsa.policy_information and ( lsa.info.level or lsa.domain or nt.domain_sid )",
296 TL_REQUIRES_PROTO_TREE
, NULL
, lsa_policy_information
, NULL
, NULL
);
298 /* error, we failed to attach to the tap. clean up */
300 report_failure( "Couldn't register proto_reg_handoff_smb_sidsnooping()/lsa_policy_information tap: %s\n",
302 g_string_free(error_string
, true);
305 lsa_policy_information_tap_installed
=true;
307 error_string
=register_tap_listener("dcerpc",
308 &samr_query_dispinfo_tap_installed
,
309 "samr and samr.opnum==40 and ( samr.handle or samr.rid or samr.acct_name or samr.level )",
310 TL_REQUIRES_PROTO_TREE
, NULL
, samr_query_dispinfo
, NULL
, NULL
);
312 /* error, we failed to attach to the tap. clean up */
314 report_failure( "Couldn't register proto_reg_handoff_smb_sidsnooping()/samr_query_dispinfo tap: %s\n",
316 g_string_free(error_string
, true);
319 samr_query_dispinfo_tap_installed
=true;
323 sid_snooping_cleanup(void)
325 g_hash_table_destroy(sid_name_table
);
326 g_hash_table_destroy(ctx_handle_table
);
330 proto_register_smb_sidsnooping(void)
332 register_init_routine(sid_snooping_init
);
333 register_cleanup_routine(sid_snooping_cleanup
);
337 * Editor modelines - https://www.wireshark.org/tools/modelines.html
342 * indent-tabs-mode: t
345 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
346 * :indentSize=8:tabSize=8:noTabs=false: