Coverage Report

Created: 2026-07-12 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-smb-sidsnooping.c
Line
Count
Source
1
/* packet-smb-sidsnooping.c
2
 * Routines for snooping SID to name mappings
3
 * Copyright 2003, Ronnie Sahlberg
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
#include <epan/packet.h>
15
#include <epan/epan_dissect.h>
16
#include <epan/tap.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"
22
23
void proto_register_smb_sidsnooping(void);
24
25
#if 0
26
static int hf_lsa;
27
static int hf_lsa_opnum;
28
#endif
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;
36
37
38
static GHashTable *sid_name_table;
39
40
41
static GHashTable *ctx_handle_table;
42
43
44
static bool lsa_policy_information_tap_installed;
45
static bool samr_query_dispinfo_tap_installed;
46
47
48
const char *
49
find_sid_name(const char *sid)
50
0
{
51
0
  return (const char *)g_hash_table_lookup(sid_name_table, sid);
52
0
}
53
54
static void
55
add_sid_name_mapping(const char *sid, const char *name)
56
0
{
57
0
  if (find_sid_name(sid)) {
58
0
    return;
59
0
  }
60
61
0
  g_hash_table_insert(sid_name_table, g_strdup(sid), g_strdup(name));
62
0
}
63
64
65
66
/*
67
 * QueryDispInfo :
68
 * level  1 : user displayinfo 1
69
 */
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_)
72
0
{
73
0
  const dcerpc_info *ri=(const dcerpc_info *)pri;
74
0
  void *old_ctx=NULL;
75
0
  char *pol_name;
76
0
  char *sid;
77
0
  int sid_len;
78
0
  int num_rids;
79
0
  int num_names;
80
0
  GPtrArray *gp;
81
0
  GPtrArray *gp_rids;
82
0
  GPtrArray *gp_names;
83
0
  field_info *fi;
84
0
  field_info *fi_rid;
85
0
  field_info *fi_name;
86
0
  char sid_name_str[256];
87
0
  int info_level;
88
89
0
  gp=proto_get_finfo_ptr_array(edt->tree, hf_samr_level);
90
0
  if(!gp || gp->len!=1){
91
0
    return TAP_PACKET_DONT_REDRAW;
92
0
  }
93
0
  fi=(field_info *)gp->pdata[0];
94
0
  info_level = fvalue_get_sinteger(fi->value);
95
96
0
  if(info_level!=1){
97
0
    return TAP_PACKET_DONT_REDRAW;
98
0
  }
99
100
0
  if(!ri){
101
0
    return TAP_PACKET_DONT_REDRAW;
102
0
  }
103
0
  if(!ri->call_data){
104
0
    return TAP_PACKET_DONT_REDRAW;
105
0
  }
106
0
  if(ri->ptype == PDU_REQ){
107
0
    gp=proto_get_finfo_ptr_array(edt->tree, hf_samr_hnd);
108
0
    if(!gp || gp->len!=1){
109
0
      return TAP_PACKET_DONT_REDRAW;
110
0
    }
111
0
    fi=(field_info *)gp->pdata[0];
112
113
0
    old_ctx=g_hash_table_lookup(ctx_handle_table, GINT_TO_POINTER(pinfo->num));
114
0
    if(old_ctx){
115
0
      g_hash_table_remove(ctx_handle_table, GINT_TO_POINTER(pinfo->num));
116
0
    }
117
0
    if(!old_ctx){
118
0
      old_ctx=wmem_memdup(wmem_file_scope(), fvalue_get_bytes_data(fi->value), 20);
119
0
    }
120
0
    g_hash_table_insert(ctx_handle_table, GINT_TO_POINTER(pinfo->num), old_ctx);
121
122
0
    return TAP_PACKET_DONT_REDRAW;
123
0
  }
124
125
0
  if(!ri->call_data->req_frame){
126
0
    return TAP_PACKET_DONT_REDRAW;
127
0
  }
128
129
0
  old_ctx=g_hash_table_lookup(ctx_handle_table, GINT_TO_POINTER(ri->call_data->req_frame));
130
0
  if(!old_ctx){
131
0
    return TAP_PACKET_DONT_REDRAW;
132
0
  }
133
134
0
  if (!dcerpc_fetch_polhnd_data((e_ctx_hnd *)old_ctx, &pol_name, NULL, NULL, NULL, ri->call_data->req_frame)) {
135
0
    return TAP_PACKET_DONT_REDRAW;
136
0
  }
137
138
0
  if (!pol_name)
139
0
    return TAP_PACKET_DONT_REDRAW;
140
141
0
  sid=strstr(pol_name,"S-1-5");
142
0
  if(!sid){
143
0
    return TAP_PACKET_DONT_REDRAW;
144
0
  }
145
146
0
  for(sid_len=4;1;sid_len++){
147
0
    if((sid[sid_len]>='0') && (sid[sid_len]<='9')){
148
0
      continue;
149
0
    }
150
0
    if(sid[sid_len]=='-'){
151
0
      continue;
152
0
    }
153
0
    break;
154
0
  }
155
156
0
  gp_rids=proto_get_finfo_ptr_array(edt->tree, hf_samr_rid);
157
0
  if(!gp_rids || gp_rids->len<1){
158
0
    return TAP_PACKET_DONT_REDRAW;
159
0
  }
160
0
  num_rids=gp_rids->len;
161
0
  gp_names=proto_get_finfo_ptr_array(edt->tree, hf_samr_acct_name);
162
0
  if(!gp_names || gp_names->len<1){
163
0
    return TAP_PACKET_DONT_REDRAW;
164
0
  }
165
0
  num_names=gp_names->len;
166
167
0
  if(num_rids>num_names){
168
0
    num_rids=num_names;
169
0
  }
170
171
0
  for(;num_rids;num_rids--){
172
0
    int len=sid_len;
173
0
    if (len > 247)
174
0
      len = 247;
175
176
0
    fi_rid=(field_info *)gp_rids->pdata[num_rids-1];
177
0
    fi_name=(field_info *)gp_names->pdata[num_rids-1];
178
0
    (void) g_strlcpy(sid_name_str, sid, 256);
179
0
    sid_name_str[len++]='-';
180
0
    snprintf(sid_name_str+len, 256-len, "%d", fvalue_get_sinteger(fi_rid->value));
181
0
    add_sid_name_mapping(sid_name_str, fvalue_get_string(fi_name->value));
182
0
  }
183
0
  return TAP_PACKET_REDRAW;
184
0
}
185
186
/*
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
191
 */
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_)
194
0
{
195
0
  GPtrArray *gp;
196
0
  field_info *fi;
197
0
  const char *domain;
198
0
  const char *sid;
199
0
  int info_level;
200
201
0
  gp=proto_get_finfo_ptr_array(edt->tree, hf_lsa_info_level);
202
0
  if(!gp || gp->len!=1){
203
0
    return TAP_PACKET_DONT_REDRAW;
204
0
  }
205
0
  fi=(field_info *)gp->pdata[0];
206
0
  info_level = fvalue_get_sinteger(fi->value);
207
208
0
  switch(info_level){
209
0
  case 3:
210
0
  case 5:
211
0
  case 12:
212
0
    gp=proto_get_finfo_ptr_array(edt->tree, hf_lsa_domain);
213
0
    if(!gp || gp->len!=1){
214
0
      return TAP_PACKET_DONT_REDRAW;
215
0
    }
216
0
    fi=(field_info *)gp->pdata[0];
217
0
    domain=fvalue_get_string(fi->value);
218
219
0
    gp=proto_get_finfo_ptr_array(edt->tree, hf_nt_domain_sid);
220
0
    if(!gp || gp->len!=1){
221
0
      return TAP_PACKET_DONT_REDRAW;
222
0
    }
223
0
    fi=(field_info *)gp->pdata[0];
224
0
    sid=fvalue_get_string(fi->value);
225
226
0
    add_sid_name_mapping(sid, domain);
227
0
    break;
228
0
  }
229
0
  return TAP_PACKET_DONT_REDRAW;
230
0
}
231
232
233
static int
234
ctx_handle_equal(const void *k1, const void *k2)
235
0
{
236
0
  int sn1 = GPOINTER_TO_INT(k1);
237
0
  int sn2 = GPOINTER_TO_INT(k2);
238
239
0
  return sn1==sn2;
240
0
}
241
242
static unsigned
243
ctx_handle_hash(const void *k)
244
0
{
245
0
  int sn = GPOINTER_TO_INT(k);
246
247
0
  return sn;
248
0
}
249
250
251
static void
252
sid_snooping_init(void)
253
15
{
254
15
  GString *error_string;
255
256
15
  if(lsa_policy_information_tap_installed){
257
0
    remove_tap_listener(&lsa_policy_information_tap_installed);
258
0
    lsa_policy_information_tap_installed=false;
259
0
  }
260
15
  if(samr_query_dispinfo_tap_installed){
261
0
    remove_tap_listener(&samr_query_dispinfo_tap_installed);
262
0
    samr_query_dispinfo_tap_installed=false;
263
0
  }
264
265
15
  sid_name_table = g_hash_table_new_full(g_str_hash, g_str_equal,
266
15
    g_free, g_free);
267
15
  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
270
   unknown hf fields
271
 */
272
15
sid_name_snooping=false;
273
274
15
  if(!sid_name_snooping){
275
15
    return;
276
15
  }
277
278
279
280
#if 0
281
  hf_lsa      = proto_get_id_by_filter_name("lsa");
282
  hf_lsa_opnum    = proto_registrar_get_id_byname("lsa.opnum");
283
#endif
284
0
  hf_nt_domain_sid  = proto_registrar_get_id_byname("nt.domain_sid");
285
0
  hf_lsa_domain   = proto_registrar_get_id_byname("lsa.domain");
286
0
  hf_lsa_info_level = proto_registrar_get_id_byname("lsa.info.level");
287
0
  hf_samr_hnd   = proto_registrar_get_id_byname("samr.handle");
288
0
  hf_samr_rid   = proto_registrar_get_id_byname("samr.rid");
289
0
  hf_samr_acct_name = proto_registrar_get_id_byname("samr.acct_name");
290
0
  hf_samr_level   = proto_registrar_get_id_byname("samr.level");
291
292
293
0
  error_string=register_tap_listener("dcerpc",
294
0
      &lsa_policy_information_tap_installed,
295
0
      "lsa.policy_information and ( lsa.info.level or lsa.domain or nt.domain_sid )",
296
0
      TL_REQUIRES_PROTO_TREE, NULL, lsa_policy_information, NULL, NULL);
297
0
  if(error_string){
298
    /* error, we failed to attach to the tap. clean up */
299
300
0
    report_failure( "Couldn't register proto_reg_handoff_smb_sidsnooping()/lsa_policy_information tap: %s\n",
301
0
        error_string->str);
302
0
    g_string_free(error_string, true);
303
0
    return;
304
0
  }
305
0
  lsa_policy_information_tap_installed=true;
306
307
0
  error_string=register_tap_listener("dcerpc",
308
0
      &samr_query_dispinfo_tap_installed,
309
0
      "samr and samr.opnum==40 and ( samr.handle or samr.rid or samr.acct_name or samr.level )",
310
0
      TL_REQUIRES_PROTO_TREE, NULL, samr_query_dispinfo, NULL, NULL);
311
0
  if(error_string){
312
    /* error, we failed to attach to the tap. clean up */
313
314
0
    report_failure( "Couldn't register proto_reg_handoff_smb_sidsnooping()/samr_query_dispinfo tap: %s\n",
315
0
        error_string->str);
316
0
    g_string_free(error_string, true);
317
0
    return;
318
0
  }
319
0
  samr_query_dispinfo_tap_installed=true;
320
0
}
321
322
static void
323
sid_snooping_cleanup(void)
324
0
{
325
0
  g_hash_table_destroy(sid_name_table);
326
0
  g_hash_table_destroy(ctx_handle_table);
327
0
}
328
329
void
330
proto_register_smb_sidsnooping(void)
331
15
{
332
15
  register_init_routine(sid_snooping_init);
333
15
  register_cleanup_routine(sid_snooping_cleanup);
334
15
}
335
336
/*
337
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
338
 *
339
 * Local variables:
340
 * c-basic-offset: 8
341
 * tab-width: 8
342
 * indent-tabs-mode: t
343
 * End:
344
 *
345
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
346
 * :indentSize=8:tabSize=8:noTabs=false:
347
 */