Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-dcom.c
Line
Count
Source
1
/* packet-dcom.c
2
 * Routines for DCOM generics
3
 *
4
 * Wireshark - Network traffic analyzer
5
 * By Gerald Combs <gerald@wireshark.org>
6
 * Copyright 1998 Gerald Combs
7
 *
8
 * SPDX-License-Identifier: GPL-2.0-or-later
9
 */
10
11
/* A few words about DCOM:
12
 *
13
 * DCOM uses DCERPC as its underlying "transport" protocol.
14
 *
15
 * The DCOM dissectors are called by DCERPC request and response calls.
16
 * DCOM uses a small header after the DCERPC calls.
17
 * (for a DCERPC request  call it's called "this",
18
 *  for a DCERPC response call it's called "that")
19
 *
20
 * DCOM defines itself some interfaces: oxid, remact, remunk and others
21
 *
22
 * Implemented is currently "only" a static dissection of packet fields
23
 * (no "object recognition" included)
24
 *
25
 * User's of DCOM can define their own interface's using Microsoft IDL.
26
 *
27
 * Hint: The registered DCOM interface names can be found in the
28
 * windows registry at: "HKEY_CLASSES_ROOT\Interface"
29
 *
30
 *
31
 * Resources on the web:
32
 *
33
 * "Understanding the DCOM Wire Protocol by Analyzing Network Data Packets"
34
 * http:// www.microsoft.com/msj/0398/dcom.htm
35
 *
36
 * "Distributed Component Object Model Protocol -- DCOM/1.0"
37
 * http://www.microsoft.com/com/resources/specs.asp (link is currently down)
38
 *
39
 */
40
41
/* Files involved dissecting DCOM:
42
 *
43
 * packet-dcom.c: generic DCOM things (this, that, ...) and
44
 *    generic DCOM datatype (DWORD, VARIANT, ...)
45
 *
46
 * DCOM common Interfaces:
47
 * packet-dcom-oxid.c:     IOXIDResolver
48
 * packet-dcom-remact.c:   IRemoteActivation
49
 * packet-dcom-remunk.c:   IRemUnknown, IRemUnknown2
50
 * packet-dcom-dispatch.c: IDispatch
51
 * packet-dcom-sysact.c:   ISystemActivator
52
 * packet-dcom-typeinfo.c: ITypeInfo
53
 */
54
55
#include "config.h"
56
57
#include <epan/packet.h>
58
#include <epan/addr_resolv.h>
59
#include <epan/expert.h>
60
#include <epan/tfs.h>
61
#include <epan/prefs.h>
62
63
#include <wsutil/ws_roundup.h>
64
65
#include "packet-dcerpc.h"
66
#include "packet-dcom.h"
67
68
void proto_register_dcom (void);
69
void proto_reg_handoff_dcom (void);
70
71
static int proto_dcom;
72
73
bool dcom_prefs_display_unmarshalling_details;
74
75
76
static int ett_dcom_this;
77
/* static int hf_dcom_this_version_major; */
78
/* static int hf_dcom_this_version_minor; */
79
static int hf_dcom_this_flags;
80
static int hf_dcom_this_res;
81
static int hf_dcom_this_cid;
82
83
static int ett_dcom_that;
84
static int hf_dcom_that_flags;
85
86
static int ett_dcom_extent;
87
static int hf_dcom_extent;
88
static int hf_dcom_extent_array_count;
89
static int hf_dcom_extent_array_res;
90
static int hf_dcom_extent_size;
91
static int hf_dcom_extent_id;
92
93
static int hf_dcom_hresult;
94
static int hf_dcom_tobedone;
95
static int hf_dcom_nospec;
96
static int hf_dcom_array_size;
97
static int hf_dcom_pointer_val;
98
99
/* COMVERSION */
100
static int hf_dcom_version_major;
101
static int hf_dcom_version_minor;
102
103
static int ett_dcom_lpwstr;
104
static int hf_dcom_max_count;
105
static int hf_dcom_offset;
106
static int hf_dcom_byte_length;
107
/* static int hf_dcom_actual_count; */
108
109
static int ett_dcom_objref;
110
static int hf_dcom_objref;
111
static int hf_dcom_objref_signature;
112
static int hf_dcom_objref_flags;
113
int hf_dcom_iid;
114
int hf_dcom_clsid;
115
static int hf_dcom_objref_resolver_address;
116
static int hf_dcom_objref_cbextension;
117
static int hf_dcom_objref_size;
118
119
static int ett_dcom_stdobjref;
120
static int hf_dcom_stdobjref;
121
static int hf_dcom_stdobjref_flags;
122
static int hf_dcom_stdobjref_public_refs;
123
int hf_dcom_oxid;
124
int hf_dcom_oid;
125
int hf_dcom_ipid;
126
127
128
static int ett_dcom_custobjref;
129
static int hf_dcom_custobjref;
130
131
static int ett_dcom_dualstringarray;
132
static int ett_dcom_dualstringarray_binding;
133
static int hf_dcom_dualstringarray_num_entries;
134
static int hf_dcom_dualstringarray_security_offset;
135
static int hf_dcom_dualstringarray_string;
136
static int hf_dcom_dualstringarray_string_network_addr;
137
static int hf_dcom_dualstringarray_string_tower_id;
138
static int hf_dcom_dualstringarray_security;
139
static int hf_dcom_dualstringarray_security_authn_svc;
140
static int hf_dcom_dualstringarray_security_authz_svc;
141
static int hf_dcom_dualstringarray_security_princ_name;
142
143
static int ett_dcom_interface_pointer;
144
static int hf_dcom_interface_pointer;
145
static int hf_dcom_ip_cnt_data;
146
147
static int ett_dcom_safearray;
148
static int hf_dcom_safearray;
149
static int hf_dcom_sa_dims32;
150
static int hf_dcom_sa_dims16;
151
static int hf_dcom_sa_features;
152
static int hf_dcom_sa_element_size;
153
static int hf_dcom_sa_locks;
154
static int hf_dcom_sa_vartype32;
155
static int hf_dcom_sa_vartype16;
156
static int hf_dcom_sa_elements;
157
static int hf_dcom_sa_bound_elements;
158
static int hf_dcom_sa_low_bound;
159
160
static int ett_dcom_sa_features;
161
static int hf_dcom_sa_features_auto;
162
static int hf_dcom_sa_features_static;
163
static int hf_dcom_sa_features_embedded;
164
static int hf_dcom_sa_features_fixedsize;
165
static int hf_dcom_sa_features_record;
166
static int hf_dcom_sa_features_have_iid;
167
static int hf_dcom_sa_features_have_vartype;
168
static int hf_dcom_sa_features_bstr;
169
static int hf_dcom_sa_features_unknown;
170
static int hf_dcom_sa_features_dispatch;
171
static int hf_dcom_sa_features_variant;
172
173
static int ett_dcom_variant;
174
/* static int hf_dcom_variant; */
175
static int hf_dcom_variant_type;
176
static int hf_dcom_variant_size;
177
static int hf_dcom_variant_rpc_res;
178
static int hf_dcom_variant_wres;
179
static int hf_dcom_variant_type32;
180
181
static int hf_dcom_vt_bool;
182
static int hf_dcom_vt_i1;
183
static int hf_dcom_vt_i2;
184
static int hf_dcom_vt_i4;
185
static int hf_dcom_vt_i8; /* only inside a SAFEARRAY, not in VARIANTs */
186
static int hf_dcom_vt_cy;
187
static int hf_dcom_vt_ui1;
188
static int hf_dcom_vt_ui2;
189
static int hf_dcom_vt_ui4;
190
static int hf_dcom_vt_ui8;
191
static int hf_dcom_vt_r4;
192
static int hf_dcom_vt_r8;
193
static int hf_dcom_vt_date;
194
static int hf_dcom_vt_bstr;
195
static int hf_dcom_vt_byref;
196
static int hf_dcom_vt_dispatch;
197
198
static expert_field ei_dcom_dissection_incomplete;
199
static expert_field ei_dcom_no_spec;
200
static expert_field ei_dcom_hresult_expert;
201
static expert_field ei_dcom_dualstringarray_mult_ip;
202
203
/* this/that extension UUIDs */
204
static e_guid_t uuid_debug_ext =    { 0xf1f19680, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} };
205
static e_guid_t uuid_ext_error_ext ={ 0xf1f19681, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} };
206
207
/* general DCOM UUIDs */
208
static const e_guid_t ipid_rem_unknown =  { 0x00000131, 0x1234, 0x5678, { 0xCA, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
209
static const e_guid_t iid_unknown =   { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
210
static const e_guid_t uuid_null =   { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
211
static const e_guid_t iid_class_factory = { 0x00000001, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
212
static const e_guid_t iid_type_info = { 0x00020401, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
213
static const e_guid_t iid_provide_class_info = { 0xb196b283, 0xbab4, 0x101a, { 0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07} };
214
#if 0
215
static const e_guid_t iid_act_prop_in =   { 0x000001A2, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
216
static const e_guid_t iid_act_prop_out =  { 0x000001A3, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
217
#endif
218
219
static GList *dcom_machines;
220
static GList *dcom_interfaces;
221
static GList *dcom_marshalers;
222
223
static const value_string dcom_thisthat_flag_vals[] = {
224
  { 0, "INFO_NULL" },
225
  { 1, "INFO_LOCAL" },
226
  { 0,  NULL }
227
};
228
229
#if 0
230
static const value_string dcom_boolean_flag_vals[] = {
231
  { 0x00000001, "TRUE" },
232
  { 0x00000000, "FALSE" },
233
  { 0,  NULL }
234
};
235
#endif
236
237
#ifdef DEBUG
238
void dcom_interface_dump(void) {
239
  dcom_machine_t *machine;
240
  dcom_object_t *object;
241
  dcom_interface_t *interf;
242
  GList *machines;
243
  GList *objects;
244
  GList *interfaces;
245
246
247
  for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
248
    machine = (dcom_machine_t *)machines->data;
249
    /*ws_warning("Machine(#%4u): IP:%s", machine->first_packet, address_to_str(pinfo->pool, &machine->ip));*/
250
251
    for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
252
      object = (dcom_object_t *)objects->data;
253
      /*ws_warning(" Object(#%4u): OID:0x%" PRIx64 " private:%p", object->first_packet, object->oid, object->private_data);*/
254
255
      for(interfaces = object->interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
256
        interf = (dcom_interface_t *)interfaces->data;
257
        /*ws_warning("  Interface(#%4u): iid:%s",
258
            interf->first_packet, guids_resolve_guid_to_str(&interf->iid));
259
        ws_warning("   ipid:%s", guids_resolve_guid_to_str(&interf->ipid));*/
260
      }
261
    }
262
  }
263
}
264
#endif
265
266
dcom_interface_t *dcom_interface_find(packet_info *pinfo _U_, const address *addr _U_, e_guid_t *ipid)
267
0
{
268
0
  dcom_interface_t *interf;
269
0
  GList *interfaces;
270
271
272
0
  if(memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
273
0
  {
274
0
    return NULL;
275
0
  }
276
277
0
  for(interfaces = dcom_interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
278
0
    interf = (dcom_interface_t *)interfaces->data;
279
280
0
    if(memcmp(&interf->ipid, ipid, sizeof(e_guid_t)) == 0) {
281
0
      return interf;
282
0
    }
283
0
  }
284
285
0
  return NULL;
286
0
}
287
288
289
dcom_interface_t *dcom_interface_new(packet_info *pinfo, const address *addr, e_guid_t *iid, uint64_t oxid, uint64_t oid, e_guid_t *ipid)
290
0
{
291
0
  GList *dcom_iter;
292
0
  dcom_machine_t *machine;
293
0
  dcom_object_t *object;
294
0
  dcom_interface_t *interf;
295
296
297
0
  if( memcmp(iid, &uuid_null, sizeof(uuid_null)) == 0 ||
298
0
      memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
299
0
  {
300
0
    return NULL;
301
0
  }
302
303
0
  if(oxid == 0 || oid == 0) {
304
    /*ws_warning("interface_new#%u", pinfo->num);*/
305
306
0
    interf = wmem_new(wmem_file_scope(), dcom_interface_t);
307
0
    interf->parent = NULL;
308
0
    interf->private_data = NULL;
309
0
    interf->first_packet = pinfo->num;
310
0
    interf->iid = *iid;
311
0
    interf->ipid = *ipid;
312
313
0
    dcom_interfaces = g_list_append(dcom_interfaces, interf);
314
0
    return interf;
315
0
  }
316
317
  /* find machine */
318
0
  dcom_iter = dcom_machines;
319
0
  while(dcom_iter != NULL) {
320
0
    machine = (dcom_machine_t *)dcom_iter->data;
321
0
    if(cmp_address(&machine->ip, addr) == 0) {
322
0
      break;
323
0
    }
324
0
    dcom_iter = g_list_next(dcom_iter);
325
0
  }
326
327
  /* create new machine if not found */
328
0
  if(dcom_iter == NULL) {
329
0
    machine = g_new(dcom_machine_t,1);
330
0
    copy_address(&machine->ip, addr);
331
0
    machine->objects = NULL;
332
0
    machine->first_packet = pinfo->num;
333
0
    dcom_machines = g_list_append(dcom_machines, machine);
334
0
  }
335
336
  /* find object */
337
0
  dcom_iter = machine->objects;
338
0
  while(dcom_iter != NULL) {
339
0
    object = (dcom_object_t *)dcom_iter->data;
340
0
    if(object->oid == oid) {
341
0
      break;
342
0
    }
343
0
    dcom_iter = g_list_next(dcom_iter);
344
0
  }
345
346
  /* create new object if not found */
347
0
  if(dcom_iter == NULL) {
348
0
    object = g_new(dcom_object_t,1);
349
0
    object->parent = machine;
350
0
    object->interfaces = NULL;
351
0
    object->private_data = NULL;
352
0
    object->first_packet = pinfo->num;
353
0
    object->oid = oid;
354
0
    object->oxid = oxid;
355
356
0
    machine->objects = g_list_append(machine->objects, object);
357
0
  }
358
359
  /* find interface */
360
0
  dcom_iter = object->interfaces;
361
0
  while(dcom_iter != NULL) {
362
0
    interf = (dcom_interface_t *)dcom_iter->data;
363
0
    if(memcmp(&interf->ipid, ipid, sizeof(e_guid_t)) == 0) {
364
0
      break;
365
0
    }
366
0
    dcom_iter = g_list_next(dcom_iter);
367
0
  }
368
369
  /* create new interface if not found */
370
0
  if(dcom_iter == NULL) {
371
0
    interf = g_new(dcom_interface_t,1);
372
0
    interf->parent = object;
373
0
    interf->private_data = NULL;
374
0
    interf->first_packet = pinfo->num;
375
0
    interf->iid = *iid;
376
0
    interf->ipid = *ipid;
377
378
0
    object->interfaces = g_list_append(object->interfaces, interf);
379
0
    dcom_interfaces = g_list_append(dcom_interfaces, interf);
380
0
  }
381
382
0
  return interf;
383
0
}
384
385
386
/*
387
 * Flag bits in connection-oriented PDU header.
388
 */
389
14
#define WIRESHARK_FADF_AUTO   0x0001
390
14
#define WIRESHARK_FADF_STATIC   0x0002
391
14
#define WIRESHARK_FADF_EMBEDDED   0x0004
392
14
#define WIRESHARK_FADF_FIXEDSIZE  0x0010
393
14
#define WIRESHARK_FADF_RECORD   0x0020
394
14
#define WIRESHARK_FADF_HAVEIID    0x0040
395
14
#define WIRESHARK_FADF_HAVEVARTYPE  0x0080
396
14
#define WIRESHARK_FADF_BSTR   0x0100
397
14
#define WIRESHARK_FADF_UNKNOWN    0x0200
398
14
#define WIRESHARK_FADF_DISPATCH   0x0400
399
14
#define WIRESHARK_FADF_VARIANT    0x0800
400
401
402
typedef enum {
403
  WIRESHARK_VT_EMPTY       = 0,
404
  WIRESHARK_VT_NULL      = 1,
405
  WIRESHARK_VT_I2        = 2,
406
  WIRESHARK_VT_I4        = 3,
407
  WIRESHARK_VT_R4        = 4,
408
  WIRESHARK_VT_R8        = 5,
409
  WIRESHARK_VT_CY        = 6,
410
  WIRESHARK_VT_DATE      = 7,
411
  WIRESHARK_VT_BSTR      = 8,
412
  WIRESHARK_VT_DISPATCH      = 9,
413
  WIRESHARK_VT_ERROR       = 10,
414
  WIRESHARK_VT_BOOL      = 11,
415
  WIRESHARK_VT_VARIANT       = 12,
416
  WIRESHARK_VT_UNKNOWN       = 13,
417
  WIRESHARK_VT_DECIMAL       = 14,
418
  WIRESHARK_VT_I1        = 16,
419
  WIRESHARK_VT_UI1       = 17,
420
  WIRESHARK_VT_UI2       = 18,
421
  WIRESHARK_VT_UI4       = 19,
422
  WIRESHARK_VT_I8        = 20,
423
  WIRESHARK_VT_UI8       = 21,
424
  WIRESHARK_VT_INT       = 22,
425
  WIRESHARK_VT_UINT      = 23,
426
  WIRESHARK_VT_VOID      = 24,
427
  WIRESHARK_VT_HRESULT       = 25,
428
  WIRESHARK_VT_PTR       = 26,
429
  WIRESHARK_VT_SAFEARRAY       = 27,
430
  WIRESHARK_VT_CARRAY      = 28,
431
  WIRESHARK_VT_USERDEFINED     = 29,
432
  WIRESHARK_VT_LPSTR       = 30,
433
  WIRESHARK_VT_LPWSTR      = 31,
434
  WIRESHARK_VT_RECORD      = 36,
435
  WIRESHARK_VT_FILETIME      = 64,
436
  WIRESHARK_VT_BLOB      = 65,
437
  WIRESHARK_VT_STREAM      = 66,
438
  WIRESHARK_VT_STORAGE       = 67,
439
  WIRESHARK_VT_STREAMED_OBJECT = 68,
440
  WIRESHARK_VT_STORED_OBJECT   = 69,
441
  WIRESHARK_VT_BLOB_OBJECT     = 70,
442
  WIRESHARK_VT_CF        = 71,
443
  WIRESHARK_VT_CLSID       = 72,
444
445
  WIRESHARK_VT_BSTR_BLOB       = 0x0fff,
446
447
  WIRESHARK_VT_VECTOR      = 0x1000,
448
  WIRESHARK_VT_ARRAY       = 0x2000,
449
  WIRESHARK_VT_BYREF       = 0x4000,
450
  WIRESHARK_VT_RESERVED      = 0x8000,
451
452
  WIRESHARK_VT_ILLEGAL       = 0xffff,
453
  WIRESHARK_VT_ILLEGALMASKED   = 0x0fff,
454
  WIRESHARK_VT_TYPEMASK      = 0x0fff
455
} dcom_vartype_t;
456
457
const value_string dcom_variant_type_vals[] = {
458
  { WIRESHARK_VT_EMPTY,   "VT_EMPTY"},
459
  { WIRESHARK_VT_NULL,    "VT_NULL"},
460
  { WIRESHARK_VT_I2,    "VT_I2"},
461
  { WIRESHARK_VT_I4,    "VT_I4"},
462
  { WIRESHARK_VT_R4,    "VT_R4"},
463
  { WIRESHARK_VT_R8,    "VT_R8"},
464
  { WIRESHARK_VT_CY,    "VT_CY"},
465
  { WIRESHARK_VT_DATE,    "VT_DATE"},
466
  { WIRESHARK_VT_BSTR,    "VT_BSTR"},
467
  { WIRESHARK_VT_DISPATCH,  "VT_DISPATCH"},
468
  { WIRESHARK_VT_ERROR,   "VT_ERROR"},
469
  { WIRESHARK_VT_BOOL,    "VT_BOOL"},
470
  { WIRESHARK_VT_I1,    "VT_I1"},
471
  { WIRESHARK_VT_UI1,   "VT_UI1"},
472
  { WIRESHARK_VT_UI2,   "VT_UI2"},
473
  { WIRESHARK_VT_UI4,   "VT_UI4"},
474
  { WIRESHARK_VT_I8,    "VT_I8"},
475
  { WIRESHARK_VT_UI8,   "VT_UI8"},
476
  { WIRESHARK_VT_ARRAY,   "VT_ARRAY"},
477
  { WIRESHARK_VT_UNKNOWN,   "VT_UNKNOWN"},
478
  { WIRESHARK_VT_USERDEFINED, "VT_USERDEFINED"},
479
  { WIRESHARK_VT_PTR,     "VT_PTR"},
480
481
  /* XXX: this could be done better */
482
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I2,      "VT_ARRAY|VT_I2"},
483
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I4,      "VT_ARRAY|VT_I4"},
484
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_R4,      "VT_ARRAY|VT_R4"},
485
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_R8,      "VT_ARRAY|VT_R8"},
486
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_DATE,    "VT_ARRAY|VT_DATE"},
487
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_BSTR,    "VT_ARRAY|VT_BSTR"},
488
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_ERROR,   "VT_ARRAY|VT_ERROR"},
489
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_BOOL,    "VT_ARRAY|VT_BOOL"},
490
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I1,      "VT_ARRAY|VT_I1"},
491
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI1,     "VT_ARRAY|VT_UI1"},
492
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI2,     "VT_ARRAY|VT_UI2"},
493
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI4,     "VT_ARRAY|VT_UI4"},
494
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I8,      "VT_ARRAY|VT_I8"},
495
  { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI8,     "VT_ARRAY|VT_UI8"},
496
497
  { WIRESHARK_VT_BYREF | WIRESHARK_VT_I2,      "VT_BYREF|VT_I2"},
498
  { WIRESHARK_VT_BYREF | WIRESHARK_VT_BSTR,    "VT_BYREF|VT_BSTR"},
499
  { WIRESHARK_VT_BYREF | WIRESHARK_VT_VARIANT, "VT_BYREF|VT_VARIANT"},
500
  { 0,        NULL }
501
/* XXX: append more types here */
502
};
503
504
505
506
/* we need an extension mechanism here (be able to append entries by user protocol) */
507
const value_string dcom_hresult_vals[] = {
508
  { 0x00000000, "S_OK" },
509
  { 0x00000001, "S_FALSE" },
510
  { 0x8000FFFF, "E_UNEXPECTED" },
511
  { 0x80004001, "E_NOTIMPL" },
512
  { 0x80004002, "E_NOINTERFACE" },
513
  { 0x80004003, "E_POINTER" },
514
  { 0x80004004, "E_ABORT" },
515
  { 0x80004005, "E_FAIL" },
516
  { 0x80070005, "E_ACCESSDENIED" },
517
  { 0x80070006, "E_HANDLE" },
518
  { 0x8007000E, "E_OUTOFMEMORY" },
519
  { 0x80070057, "E_INVALIDARG" },
520
521
  { 0x80010108, "RPC_E_DISCONNECTED" },
522
  { 0x80010113, "RPC_E_INVALID_IPID" },
523
  { 0x8001011F, "RPC_E_TIMEOUT" },
524
525
  { 0x80020003, "DISP_E_MEMBERNOTFOUND" },
526
  { 0x80020004, "DISP_E_PARAMNOTFOUND" },
527
  { 0x80020005, "DISP_E_TYPEMISMATCH" },
528
  { 0x80020006, "DISP_E_UNKNOWNNAME" },
529
  { 0x80020008, "DISP_E_BADVARTYPE" },
530
  { 0x80020009, "DISP_E_EXCEPTION" },
531
  { 0x8002000A, "DISP_E_OVERFLOW" },
532
533
  { 0x8002801D, "TYPE_E_LIBNOTREGISTERED" },
534
535
  { 0x80040154, "REGDB_E_CLASSNOTREG" },
536
  { 0x80040201, "CO_E_FAILEDTOGETSECCTX" },
537
538
/* following are CBA application specific values */
539
  { 0x0004CA00, "CBA_S_PERSISTPENDING" },
540
  { 0x0004CA01, "CBA_S_ESTABLISHING" },
541
  { 0x0004CA02, "CBA_S_NOCONNECTION" },
542
  { 0x0004CA03, "CBA_S_VALUEBUFFERED" },
543
  { 0x0004CA04, "CBA_S_VALUEUNCERTAIN" },
544
  { 0x0004CA05, "CBA_S_NOCONNECTIONDATA" },
545
  { 0x0004CA06, "CBA_S_FRAMEEMPTY" },
546
547
  { 0x8004CB00, "CBA_E_MALFORMED" },
548
  { 0x8004CB01, "CBA_E_UNKNOWNOBJECT" },
549
  { 0x8004CB02, "CBA_E_UNKNOWNMEMBER" },
550
  { 0x8004CB03, "CBA_E_TYPEMISMATCH" },
551
  { 0x8004CB04, "CBA_E_INVALIDENUMVALUE" },
552
  { 0x8004CB05, "CBA_E_INVALIDID" },
553
  { 0x8004CB06, "CBA_E_INVALIDEPSILON" },
554
  { 0x8004CB07, "CBA_E_INVALIDSUBSTITUTE" },
555
  { 0x8004CB08, "CBA_E_INVALIDCONNECTION" },
556
  { 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
557
  { 0x8004CB0A, "CBA_E_TIMEVALUEUNSUPPORTED" },
558
  { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
559
  { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
560
  { 0x8004CB0D, "CBA_E_PERSISTRUNNING" },
561
  { 0x8004CB0E, "CBA_E_INUSE" },
562
  { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
563
  { 0x8004CB10, "CBA_E_NONACCESSIBLE" },
564
  { 0x8004CB11, "CBA_E_DEFECT" },
565
  { 0x8004CB12, "CBA_E_LIMITVIOLATION" },
566
  { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" },
567
  { 0x8004CB14, "CBA_E_QCNOTAPPLICABLE" },
568
  { 0x8004CB15, "CBA_E_ACCESSBLOCKED" },
569
  { 0x8004CB16, "CBA_E_COUNTEXCEEDED" },
570
  { 0x8004CB17, "CBA_E_SIZEEXCEEDED" },
571
  { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" },
572
  { 0x8004CB19, "CBA_E_OUTOFACCOPAIRS" },
573
  { 0x8004CB1A, "CBA_E_ITEMTOOLARGE" },
574
  { 0x8004CB1B, "CBA_E_CRDATALENGTH" },
575
  { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" },
576
  { 0x8004CB1D, "CBA_E_CAPACITYEXCEEDED" },
577
  { 0x8004CB1E, "CBA_E_SUBELEMENTMISMATCH" },
578
  { 0x8004CB1F, "CBA_E_STATIONFAILURE" },
579
  { 0x8004CB20, "CBA_E_NOTROUTABLE" },
580
  { 0x8004CB21, "CBA_E_DISCONNECTRUNNING" },
581
  { 0x8004CB22, "CBA_E_LOCATIONCHANGED" },
582
  { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
583
  { 0x8004CB24, "CBA_E_LINKFAILURE" },
584
  { 0x8004CB25, "CBA_E_MODECHANGE" },
585
586
  { 0x80080004, "CO_E_BAD_PATH" },
587
588
  { 0,        NULL }
589
};
590
591
static const value_string dcom_objref_flag_vals[] = {
592
  { 0x1, "OBJREF_STANDARD" },
593
  { 0x2, "OBJREF_HANDLER" },
594
  { 0x4, "OBJREF_CUSTOM" },
595
  { 0,   NULL }
596
};
597
598
static const value_string dcom_objref_signature_vals[] = {
599
  { 0x574f454d, "MEOW" },
600
  { 0,        NULL }
601
};
602
603
/* although flags, they doesn't seem to be used as such */
604
static const value_string dcom_stdobjref_flag_vals[] = {
605
  { 0x0000, "SORF_NULL" },
606
  { 0x0001, "SORF_OXRES1" },
607
  { 0x0020, "SORF_OXRES2" },
608
  { 0x0040, "SORF_OXRES3" },
609
  { 0x0080, "SORF_OXRES4" },
610
  { 0x0100, "SORF_OXRES5" },
611
  { 0x0200, "SORF_OXRES6" },
612
  { 0x0400, "SORF_OXRES7" },
613
  { 0x0800, "SORF_OXRES8" },
614
  { 0x1000, "SORF_NOPING" },
615
  { 0,    NULL }
616
};
617
618
static const value_string dcom_dcerpc_pointer_vals[] = {
619
  { 0x72657355, "User" },
620
  { 0x42535452, "BSTR" },
621
  { 0x00000000, "NULL" },
622
  { 0,        NULL }
623
};
624
625
static const value_string dcom_dualstringarray_authz[] = {
626
  { 0x0000, "RPC_C_AUTHZ_NONE" },
627
  { 0x0001, "RPC_C_AUTHZ_NAME"},
628
  { 0x0002, "RPC_C_AUTHZ_DCE"},
629
  { 0xffff, "Default"},
630
  { 0,    NULL}
631
};
632
633
static const value_string dcom_dualstringarray_authn[] = {
634
  {  00, "RPC_C_AUTHN_NONE" },
635
  {   1, "RPC_C_AUTHN_DCE_PRIVATE"},
636
  {   2, "RPC_C_AUTHN_DCE_PUBLIC"},
637
  {   4, "RPC_C_AUTHN_DEC_PUBLIC"},
638
  {   9, "RPC_C_AUTHN_GSS_NEGOTIATE"},
639
  {  10, "RPC_C_AUTH_WINNT"},
640
  {  14, "RPC_C_AUTHN_GSS_SCHANNEL"},
641
  {  16, "RPC_C_AUTHN_GSS_KERBEROS"},
642
  {  17, "RPC_C_AUTHN_MSN"},
643
  {  18, "RPC_C_AUTHN_DPA"},
644
  { 100, "RPC_C_AUTHN_MQ"},
645
  { 0xffff, "RPC_C_AUTHN_DEFAULT"},
646
  { 0,   NULL}
647
};
648
649
const value_string dcom_protseq_vals[] = {
650
  { 0x04, "NCACN_DNET_NSP" },
651
  { 0x07, "NCACN_IP_TCP" },
652
  { 0x08, "NCADG_IP_UDP" },
653
  { 0x09, "NCACN_IP" },
654
  { 0x0C, "NCACN_SPX" },
655
  { 0x0D, "NCACN_NB_IPX" },
656
  { 0x0E, "NCADG_IPX" },
657
  { 0x12, "NCACN_NB_NB" },
658
  { 0x1F, "NCACN_HTTP" },
659
  { 0,  NULL }
660
};
661
662
static const value_string dcom_vt_bool_vals[] = {
663
  { 0x0000, "FALSE" },
664
  { 0xFFFF, "TRUE" },
665
  { 0,    NULL }
666
};
667
668
669
670
/* dissect extension to DCOM "this" and "that" */
671
static unsigned
672
dissect_dcom_extent(tvbuff_t *tvb, unsigned offset,
673
  packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep)
674
0
{
675
0
  uint32_t u32ArraySize;
676
0
  uint32_t u32ArraySize2;
677
0
  uint32_t u32Pointer;
678
0
  uint32_t u32VariableOffset;
679
0
  uint32_t u32Idx;
680
0
  uint32_t u32SubStart;
681
0
  proto_item *sub_item;
682
0
  proto_tree *sub_tree;
683
684
0
  uint32_t u32ArrayCount;
685
0
  uint32_t u32ArrayRes;
686
687
0
  uint32_t u32ExtentSize;
688
0
  e_guid_t uuidExtend;
689
0
  const char *uuid_name;
690
691
692
0
  offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
693
694
0
  if (u32Pointer == 0) {
695
0
    return offset;
696
0
  }
697
698
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
699
0
      hf_dcom_extent_array_count, &u32ArrayCount);
700
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
701
0
      hf_dcom_extent_array_res, &u32ArrayRes);
702
703
0
  offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
704
705
0
  if (u32Pointer == 0) {
706
0
    return offset;
707
0
  }
708
709
0
  offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
710
0
            &u32ArraySize);
711
712
0
  u32VariableOffset = offset + u32ArraySize*4;
713
714
0
  u32Idx = 1;
715
0
  while (u32ArraySize--) {
716
0
    sub_item = proto_tree_add_item(tree, hf_dcom_extent, tvb, offset, 0, ENC_NA);
717
0
    sub_tree = proto_item_add_subtree(sub_item, ett_dcom_extent);
718
0
    u32SubStart = offset;
719
720
0
    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
721
722
0
    if(u32Pointer != 0) {
723
0
      u32VariableOffset = dissect_dcom_DWORD(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
724
0
                     hf_dcom_extent_size, &u32ExtentSize);
725
726
0
      dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, NULL, di, drep,
727
0
            hf_dcom_extent_id, &uuidExtend);
728
729
      /* look for a registered uuid name */
730
0
      if((uuid_name = guids_get_guid_name(&uuidExtend, pinfo->pool)) != NULL) {
731
0
        proto_tree_add_guid_format_value(sub_tree, hf_dcom_extent_id, tvb,
732
0
                 offset, sizeof(e_guid_t), (e_guid_t *) &uuidExtend,
733
0
                 "%s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
734
0
                 uuid_name,
735
0
                 uuidExtend.data1, uuidExtend.data2, uuidExtend.data3,
736
0
                 uuidExtend.data4[0], uuidExtend.data4[1],
737
0
                 uuidExtend.data4[2], uuidExtend.data4[3],
738
0
                 uuidExtend.data4[4], uuidExtend.data4[5],
739
0
                 uuidExtend.data4[6], uuidExtend.data4[7]);
740
0
        u32VariableOffset += 16;
741
0
      } else {
742
0
        u32VariableOffset = dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
743
0
                      hf_dcom_extent_id, &uuidExtend);
744
0
      }
745
746
747
0
      u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
748
0
                     &u32ArraySize2);
749
0
      u32VariableOffset = dissect_dcom_nospec_data(tvb, u32VariableOffset, pinfo, sub_tree, drep, u32ArraySize2);
750
751
      /* update subtree header */
752
0
      if(uuid_name != NULL) {
753
0
        proto_item_append_text(sub_item, "[%u]: %s, Bytes=%u",
754
0
                   u32Idx, uuid_name, u32ArraySize2);
755
0
      } else {
756
0
        proto_item_append_text(sub_item, "[%u]: Bytes=%u",
757
0
                   u32Idx, u32ArraySize2);
758
0
      }
759
0
      proto_item_set_len(sub_item, offset - u32SubStart);
760
0
    } else {
761
      /* update subtree header */
762
0
      proto_item_append_text(sub_item, "[%u]: NULL", u32Idx);
763
0
      proto_item_set_len(sub_item, offset - u32SubStart);
764
0
    }
765
766
0
    u32Idx++;
767
0
  }
768
769
0
  return u32VariableOffset;
770
0
}
771
772
773
/* dissect DCOM "this" (start of every DCOM request) */
774
unsigned
775
dissect_dcom_this(tvbuff_t *tvb, unsigned offset,
776
  packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep)
777
0
{
778
0
  uint16_t u16VersionMajor;
779
0
  uint16_t u16VersionMinor;
780
0
  uint32_t u32Flags;
781
0
  uint32_t u32Res;
782
0
  e_guid_t uuidCausality;
783
0
  proto_item *sub_item;
784
0
  proto_tree *sub_tree;
785
0
  uint32_t u32SubStart;
786
0
  proto_item *pi;
787
788
0
  sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
789
0
              "DCOM, ORPCThis");
790
0
  sub_tree = proto_item_add_subtree(sub_item, ett_dcom_this);
791
792
0
  offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, sub_tree, di, drep,
793
0
        &u16VersionMajor, &u16VersionMinor);
794
0
  u32SubStart = offset - 4;
795
796
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
797
0
      hf_dcom_this_flags, &u32Flags);
798
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
799
0
      hf_dcom_this_res, &u32Res);
800
801
0
  offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
802
0
      hf_dcom_this_cid, &uuidCausality);
803
804
0
  offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep);
805
806
  /* update subtree header */
807
0
  proto_item_append_text(sub_item, ", V%u.%u, Causality ID: %s",
808
0
    u16VersionMajor, u16VersionMinor, guids_resolve_guid_to_str(&uuidCausality, pinfo->pool));
809
0
  proto_item_set_len(sub_item, offset - u32SubStart);
810
811
0
  if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
812
0
    pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
813
0
      (e_guid_t *) &di->call_data->object_uuid,
814
0
      "Object UUID/IPID: %s", guids_resolve_guid_to_str(&di->call_data->object_uuid, pinfo->pool));
815
0
    proto_item_set_generated(pi);
816
0
  }
817
818
0
  return offset;
819
0
}
820
821
822
/* dissect DCOM "that" (start of every DCOM response) */
823
unsigned
824
dissect_dcom_that(tvbuff_t *tvb, unsigned offset,
825
0
  packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep) {
826
0
  uint32_t u32Flags;
827
0
  proto_item *sub_item;
828
0
  proto_tree *sub_tree;
829
0
  uint32_t u32SubStart;
830
0
  proto_item *pi;
831
832
0
  sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
833
0
              "DCOM, ORPCThat");
834
0
  sub_tree = proto_item_add_subtree(sub_item, ett_dcom_that);
835
836
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
837
0
            hf_dcom_that_flags, &u32Flags);
838
0
  u32SubStart = offset - 4;
839
840
0
  offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep);
841
842
  /* update subtree header */
843
0
  proto_item_set_len(sub_item, offset - u32SubStart);
844
845
0
  if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
846
0
    pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
847
0
      (e_guid_t *) &di->call_data->object_uuid,
848
0
      "Object UUID/IPID: %s", guids_resolve_guid_to_str(&di->call_data->object_uuid, pinfo->pool));
849
0
    proto_item_set_generated(pi);
850
0
  }
851
852
0
  return offset;
853
0
}
854
855
856
/* dissect simple dcom request, DCOM "this" only */
857
unsigned
858
dissect_dcom_simple_rqst(tvbuff_t *tvb, unsigned offset,
859
  packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep)
860
0
{
861
862
0
  offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep);
863
864
0
  return offset;
865
0
}
866
867
868
/* dissect simple dcom response, DCOM "that" and returned HRESULT only */
869
unsigned
870
dissect_dcom_simple_resp(tvbuff_t *tvb, unsigned offset,
871
  packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep)
872
0
{
873
0
  uint32_t u32HResult;
874
875
876
0
  offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);
877
878
0
  offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
879
0
              &u32HResult);
880
881
0
  col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
882
0
      val_to_str(pinfo->pool, u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
883
884
885
0
  return offset;
886
0
}
887
888
889
/* dissect a dcerpc array size */
890
unsigned
891
dissect_dcom_dcerpc_array_size(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
892
           proto_tree *tree, dcerpc_info *di, uint8_t *drep, uint32_t *pu32ArraySize)
893
0
{
894
895
896
  /* en-/disable this by preference setting */
897
0
  if (!dcom_prefs_display_unmarshalling_details) {
898
    /* this will read in the data, but prevent output to tree */
899
0
    tree = NULL;
900
0
  }
901
902
0
  offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
903
0
              hf_dcom_array_size, pu32ArraySize);
904
905
0
  return offset;
906
0
}
907
908
909
/* dissect a dcerpc pointer value */
910
unsigned
911
dissect_dcom_dcerpc_pointer(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
912
           proto_tree *tree, dcerpc_info *di, uint8_t *drep, uint32_t *pu32Pointer)
913
0
{
914
915
  /* en-/disable this by preference setting */
916
0
  if (!dcom_prefs_display_unmarshalling_details) {
917
    /* this will read in the data, but prevent output to tree */
918
0
    tree = NULL;
919
0
  }
920
921
0
  offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
922
0
                hf_dcom_pointer_val, pu32Pointer);
923
924
0
  return offset;
925
0
}
926
927
928
/* mark data as "ToBeDone" */
929
/* XXX: handout data to generic "unknown data" dissector? */
930
extern unsigned
931
dissect_dcom_tobedone_data(tvbuff_t *tvb, unsigned offset,
932
  packet_info *pinfo, proto_tree *tree, uint8_t *drep _U_, int length)
933
0
{
934
0
  proto_item *item;
935
936
937
0
  item = proto_tree_add_item(tree, hf_dcom_tobedone, tvb, offset, length, ENC_NA);
938
0
  proto_item_set_generated(item);
939
0
  expert_add_info(pinfo, item, &ei_dcom_dissection_incomplete);
940
941
0
  offset += length;
942
943
0
  return offset;
944
0
}
945
946
947
/* mark data as "No Specification Available" */
948
/* XXX: handout data to generic "unknown data" dissector? */
949
extern unsigned
950
dissect_dcom_nospec_data(tvbuff_t *tvb, unsigned offset,
951
  packet_info *pinfo, proto_tree *tree, uint8_t *drep _U_, int length)
952
0
{
953
0
  proto_item *item;
954
955
956
0
  item = proto_tree_add_item(tree, hf_dcom_nospec, tvb, offset, length, ENC_NA);
957
0
  proto_item_set_generated(item);
958
0
  expert_add_info(pinfo, item, &ei_dcom_no_spec);
959
960
0
  offset += length;
961
962
0
  return offset;
963
0
}
964
965
966
/* dissect an indexed WORD, something like: "FieldName[1]: 0x1234" */
967
unsigned
968
dissect_dcom_indexed_WORD(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
969
           proto_tree *tree, dcerpc_info *di, uint8_t *drep,
970
           int hfindex, uint16_t * pu16WORD, int field_index)
971
0
{
972
0
  uint16_t u16WORD;
973
974
975
  /* dissect the WORD, but don't add to tree */
976
0
  dissect_dcom_WORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
977
0
          hfindex, &u16WORD);
978
979
0
  if (tree) {
980
    /* special formatted output of indexed value */
981
0
    proto_tree_add_uint_format(tree, hfindex, tvb, offset, 2, u16WORD,
982
0
      "%s[%u]: 0x%04x",
983
0
      proto_registrar_get_name(hfindex),
984
0
      field_index, u16WORD);
985
0
  }
986
987
0
  offset += 2;
988
989
0
  if (pu16WORD)
990
0
    *pu16WORD = u16WORD;
991
992
0
  return offset;
993
0
}
994
995
996
/* dissect an indexed DWORD, something like: "FieldName[1]: 0x12345678" */
997
unsigned
998
dissect_dcom_indexed_DWORD(tvbuff_t *tvb, unsigned offset,  packet_info *pinfo,
999
           proto_tree *tree, dcerpc_info *di, uint8_t *drep,
1000
           int hfindex, uint32_t * pu32DWORD, int field_index)
1001
0
{
1002
0
  uint32_t u32DWORD;
1003
1004
1005
  /* dissect the DWORD, but don't add to tree */
1006
0
  dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1007
0
          hfindex, &u32DWORD);
1008
1009
0
  if (tree) {
1010
    /* special formatted output of indexed value */
1011
0
    proto_tree_add_uint_format(tree, hfindex, tvb, offset, 4, u32DWORD,
1012
0
      "%s[%u]: 0x%08x",
1013
0
      proto_registrar_get_name(hfindex),
1014
0
      field_index, u32DWORD);
1015
0
  }
1016
1017
0
  offset += 4;
1018
1019
0
  if (pu32DWORD)
1020
0
    *pu32DWORD = u32DWORD;
1021
1022
0
  return offset;
1023
0
}
1024
1025
1026
/* dissect hresult field of a usual DCOM call (create "raw" item) */
1027
unsigned
1028
dissect_dcom_HRESULT_item(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
1029
           proto_tree *tree, dcerpc_info *di, uint8_t *drep,
1030
           uint32_t * pu32HResult, int field_index, proto_item **item)
1031
0
{
1032
0
  uint32_t u32HResult;
1033
1034
  /* dissect the DWORD, but don't add to tree */
1035
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1036
0
        field_index, &u32HResult);
1037
1038
0
  if (tree) {
1039
    /* special formatted output of indexed value */
1040
0
    *item = proto_tree_add_item (tree, field_index, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
1041
0
  }
1042
1043
0
  if (pu32HResult)
1044
0
    *pu32HResult = u32HResult;
1045
1046
0
  return offset;
1047
0
}
1048
1049
1050
/* dissect hresult field of a usual DCOM call (separate method, because often used) */
1051
unsigned
1052
dissect_dcom_HRESULT(tvbuff_t *tvb, unsigned offset,  packet_info *pinfo,
1053
           proto_tree *tree, dcerpc_info *di, uint8_t *drep,
1054
           uint32_t * pu32HResult)
1055
0
{
1056
0
  uint32_t u32HResult;
1057
0
  proto_item *item = NULL;
1058
1059
  /* dissect the DWORD, but don't add to tree */
1060
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1061
0
        hf_dcom_hresult, &u32HResult);
1062
1063
0
  if (tree) {
1064
    /* special formatted output of indexed value */
1065
0
    item = proto_tree_add_item (tree, hf_dcom_hresult, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
1066
0
  }
1067
1068
  /* expert info only if severity is set */
1069
  /* XXX - move this to the callers of this function, to provide a more detailed error output */
1070
0
  if(u32HResult & 0x80000000) {
1071
0
    expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s",
1072
0
      val_to_str(pinfo->pool, u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
1073
0
  }
1074
0
  if (pu32HResult)
1075
0
    *pu32HResult = u32HResult;
1076
1077
0
  return offset;
1078
0
}
1079
1080
1081
/* partial results of indexed DCOM subcalls (e.g.: from a kind of array) */
1082
unsigned
1083
dissect_dcom_indexed_HRESULT(tvbuff_t *tvb, unsigned offset,  packet_info *pinfo,
1084
           proto_tree *tree, dcerpc_info *di, uint8_t *drep,
1085
           uint32_t * pu32HResult, int field_index)
1086
0
{
1087
0
  uint32_t u32HResult;
1088
0
  proto_item *item = NULL;
1089
1090
1091
  /* dissect the DWORD, but don't add to tree */
1092
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1093
0
        hf_dcom_hresult, &u32HResult);
1094
1095
0
  if (tree) {
1096
    /* special formatted output of indexed value */
1097
0
    item = proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset-4, 4, u32HResult,
1098
0
      "HResult[%u]: %s (0x%08x)", field_index,
1099
0
      val_to_str_const(u32HResult, dcom_hresult_vals, "Unknown"),
1100
0
      u32HResult);
1101
0
  }
1102
  /* expert info only if severity flag is set */
1103
  /* XXX - move this to the callers of this function, to provide a more detailed error output */
1104
0
  if(u32HResult & 0x80000000) {
1105
0
    expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s",
1106
0
      val_to_str(pinfo->pool, u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
1107
0
  }
1108
0
  if (pu32HResult)
1109
0
    *pu32HResult = u32HResult;
1110
1111
0
  return offset;
1112
0
}
1113
1114
1115
1116
unsigned
1117
dissect_dcom_COMVERSION(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
1118
            proto_tree *tree, dcerpc_info *di, uint8_t *drep,
1119
            uint16_t  * pu16VersionMajor, uint16_t * pu16VersionMinor)
1120
0
{
1121
1122
0
  offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1123
0
      hf_dcom_version_major, pu16VersionMajor);
1124
0
  offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1125
0
      hf_dcom_version_minor, pu16VersionMinor);
1126
1127
0
  return offset;
1128
0
}
1129
1130
1131
unsigned
1132
dissect_dcom_SAFEARRAY(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
1133
            proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex _U_, sa_callback_t sacb)
1134
0
{
1135
0
  uint32_t u32Dims;
1136
0
  uint16_t u16Dims;
1137
0
  uint16_t u16Features;
1138
0
  uint32_t u32ElementSize;
1139
0
  uint32_t u32VarType;
1140
0
  uint32_t u32Elements;
1141
0
  uint32_t u32Pointer;
1142
0
  uint32_t u32BoundElements;
1143
0
  uint32_t u32LowBound;
1144
0
  char cData[100];
1145
0
  uint32_t u32ArraySize;
1146
0
  uint32_t u32VariableOffset;
1147
0
  uint32_t u32Data;
1148
0
  uint16_t u16Data;
1149
0
  uint8_t u8Data;
1150
0
  uint16_t u16Locks;
1151
0
  uint16_t u16VarType;
1152
0
  proto_item *sub_item;
1153
0
  proto_tree *sub_tree;
1154
0
  uint32_t u32SubStart;
1155
0
  uint32_t u32TmpOffset;
1156
1157
0
  static int * const features[] = {
1158
0
    &hf_dcom_sa_features_variant,
1159
0
    &hf_dcom_sa_features_dispatch,
1160
0
    &hf_dcom_sa_features_unknown,
1161
0
    &hf_dcom_sa_features_bstr,
1162
0
    &hf_dcom_sa_features_have_vartype,
1163
0
    &hf_dcom_sa_features_have_iid,
1164
0
    &hf_dcom_sa_features_record,
1165
0
    &hf_dcom_sa_features_fixedsize,
1166
0
    &hf_dcom_sa_features_embedded,
1167
0
    &hf_dcom_sa_features_static,
1168
0
    &hf_dcom_sa_features_auto,
1169
0
    NULL
1170
0
  };
1171
1172
1173
  /* XXX: which alignment do we need here? */
1174
1175
0
  sub_item = proto_tree_add_item(tree, hf_dcom_safearray, tvb, offset, 0, ENC_NA);
1176
0
  sub_tree = proto_item_add_subtree(sub_item, ett_dcom_safearray);
1177
0
  u32SubStart = offset;
1178
1179
0
  offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1180
0
  offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1181
1182
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1183
0
      hf_dcom_sa_dims32, &u32Dims);
1184
0
  offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1185
0
      hf_dcom_sa_dims16, &u16Dims);
1186
1187
  /* feature flags */
1188
0
  u32TmpOffset = dissect_dcom_WORD(tvb, offset, pinfo, NULL, di, drep, -1, &u16Features);
1189
1190
0
  proto_tree_add_bitmask_value_with_flags(sub_tree, tvb, offset, hf_dcom_sa_features,
1191
0
                ett_dcom_sa_features, features, u16Features, BMT_NO_APPEND);
1192
0
  offset = u32TmpOffset;
1193
1194
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1195
0
      hf_dcom_sa_element_size, &u32ElementSize);
1196
0
  offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1197
0
      hf_dcom_sa_locks, &u16Locks);
1198
0
  offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1199
0
      hf_dcom_sa_vartype16, &u16VarType);
1200
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1201
0
      hf_dcom_sa_vartype32, &u32VarType);
1202
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1203
0
      hf_dcom_sa_elements, &u32Elements);
1204
0
  offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1205
1206
0
  u32BoundElements = 0;
1207
0
  while(u32Dims != 0) {
1208
0
    offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1209
0
              hf_dcom_sa_bound_elements, &u32BoundElements);
1210
0
    offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1211
0
              hf_dcom_sa_low_bound, &u32LowBound);
1212
0
    u32Dims--;
1213
0
  }
1214
1215
0
  offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize);
1216
1217
0
  tvb_ensure_bytes_exist(tvb, offset, u32ArraySize * u32ElementSize);
1218
0
  u32VariableOffset = offset + u32ArraySize * u32ElementSize;
1219
1220
0
  if(sacb) {
1221
0
    sacb(tvb, offset, pinfo, tree, di, drep, u32VarType, u32ArraySize);
1222
0
  }
1223
1224
0
  while(u32ArraySize) {
1225
0
    switch(u32VarType) {
1226
0
      case(WIRESHARK_VT_ERROR):
1227
0
        offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
1228
0
                  &u32Data);
1229
0
        break;
1230
0
      case(WIRESHARK_VT_I1):
1231
0
        offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1232
0
                  hf_dcom_vt_i1, &u8Data);
1233
0
        break;
1234
0
      case(WIRESHARK_VT_I2):
1235
0
        offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1236
0
                  hf_dcom_vt_i2, &u16Data);
1237
0
        break;
1238
0
      case(WIRESHARK_VT_I4):
1239
0
        offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1240
0
                  hf_dcom_vt_i4, &u32Data);
1241
0
        break;
1242
0
      case(WIRESHARK_VT_I8):
1243
0
        offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
1244
0
                  hf_dcom_vt_i8, NULL);
1245
        /* take care of the 8 byte alignment */
1246
0
        u32VariableOffset = offset;
1247
0
        break;
1248
0
      case(WIRESHARK_VT_BSTR):
1249
0
        offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1250
0
        if (u32Pointer) {
1251
0
          u32VariableOffset = dissect_dcom_BSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
1252
0
                  hf_dcom_vt_bstr, cData, sizeof(cData) );
1253
0
        }
1254
0
        break;
1255
0
      default:
1256
        /* XXX: other types possible, but still not implemented:
1257
        VT_UNKNOWN
1258
        VT_DISPATCH
1259
        VT_VARIANT
1260
        VT_RECORD
1261
        VT_UNKNOWN|VT_RESERVED
1262
        */
1263
0
        u32VariableOffset = dissect_dcom_tobedone_data(tvb, u32VariableOffset, pinfo, sub_tree, drep,
1264
0
                10000);
1265
0
    }
1266
0
    u32ArraySize--;
1267
0
  }
1268
1269
  /* update subtree header */
1270
0
  proto_item_append_text(sub_item, ": Elements: %u/%u VarType: %s",
1271
0
             u32Elements, u32BoundElements,
1272
0
             val_to_str(pinfo->pool, u32VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
1273
1274
0
  proto_item_set_len(sub_item, u32VariableOffset - u32SubStart);
1275
1276
0
  return u32VariableOffset;
1277
0
}
1278
1279
1280
1281
unsigned
1282
dissect_dcom_VARTYPE(tvbuff_t *tvb, unsigned offset,  packet_info *pinfo,
1283
          proto_tree *tree, dcerpc_info *di, uint8_t *drep,
1284
          uint16_t *pu16VarType)
1285
0
{
1286
1287
0
  offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1288
0
      hf_dcom_variant_type, pu16VarType);
1289
1290
0
  return offset;
1291
0
}
1292
1293
1294
unsigned
1295
// NOLINTNEXTLINE(misc-no-recursion)
1296
dissect_dcom_VARIANT(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
1297
           proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex)
1298
0
{
1299
0
  uint32_t  u32Size;
1300
0
  uint32_t u32RPCRes;
1301
0
  uint16_t u16Res;
1302
0
  uint32_t u32SubStart;
1303
0
  proto_item *sub_item;
1304
0
  proto_tree *sub_tree;
1305
0
  uint16_t u16VarType;
1306
0
  uint32_t u32VarType;
1307
1308
0
  uint8_t u8Data;
1309
0
  uint16_t u16Data;
1310
0
  uint32_t u32Data;
1311
0
  uint64_t u64Data;
1312
0
  int64_t cyData;
1313
0
  char cData[500];
1314
0
  uint32_t u32Pointer;
1315
0
  float f32Data;
1316
0
  double f64Data;
1317
1318
1319
  /* alignment of 8 needed for a VARIANT */
1320
0
  offset = WS_ROUNDUP_8(offset);
1321
1322
0
  sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
1323
0
  sub_tree = proto_item_add_subtree(sub_item, ett_dcom_variant);
1324
0
  u32SubStart = offset;
1325
1326
  /* the following size can be VERY confusing:
1327
   * It is NOT the maximum size of the variant, as one could expect,
1328
   * but the current size of the variant padded to 8 bytes.
1329
   * BUT: The following data does not start AFTER this padding,
1330
   * it starts just after the variant-data (without padding)!!! */
1331
  /* Conclusion: the size given here can be LONGER than the actual size */
1332
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1333
0
      hf_dcom_variant_size, &u32Size);
1334
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1335
0
      hf_dcom_variant_rpc_res, &u32RPCRes);
1336
0
  offset = dissect_dcom_VARTYPE(tvb, offset, pinfo, sub_tree, di, drep,
1337
0
            &u16VarType);
1338
0
  offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1339
0
      hf_dcom_variant_wres, &u16Res);
1340
0
  offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1341
0
      hf_dcom_variant_wres, &u16Res);
1342
0
  offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1343
0
      hf_dcom_variant_wres, &u16Res);
1344
1345
  /* 32 bit VarType (slightly different to the 16 bit one) */
1346
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1347
0
      hf_dcom_variant_type32, &u32VarType);
1348
1349
0
  if (u32VarType & WIRESHARK_VT_BYREF) {
1350
0
    u32VarType &=~WIRESHARK_VT_BYREF;
1351
0
    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1352
0
  }
1353
1354
0
  increment_dissection_depth(pinfo);
1355
0
  switch (u32VarType) {
1356
0
    case(WIRESHARK_VT_EMPTY):
1357
0
      break;
1358
0
    case(WIRESHARK_VT_BOOL):
1359
0
      offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, sub_tree, di, drep,
1360
0
                hf_dcom_vt_bool, &u16Data);
1361
0
      break;
1362
0
    case(WIRESHARK_VT_I1):
1363
0
      offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1364
0
                hf_dcom_vt_i1, &u8Data);
1365
0
      break;
1366
0
    case(WIRESHARK_VT_UI1):
1367
0
      offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1368
0
                hf_dcom_vt_ui1, &u8Data);
1369
0
      break;
1370
0
    case(WIRESHARK_VT_I2):
1371
0
      offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1372
0
                hf_dcom_vt_i2, &u16Data);
1373
0
      break;
1374
0
    case(WIRESHARK_VT_UI2):
1375
0
      offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1376
0
                hf_dcom_vt_ui2, &u16Data);
1377
0
      break;
1378
0
    case(WIRESHARK_VT_I4):
1379
0
      offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1380
0
                hf_dcom_vt_i4, &u32Data);
1381
0
      break;
1382
0
    case(WIRESHARK_VT_I8):
1383
0
      offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
1384
0
                hf_dcom_vt_i8, &u64Data);
1385
0
      break;
1386
0
    case(WIRESHARK_VT_CY):
1387
0
        offset = dissect_dcom_I8(tvb, offset, pinfo, NULL, di, drep,
1388
0
            0, (uint64_t*)&cyData);
1389
0
        proto_tree_add_int64_format(sub_tree, hf_dcom_vt_cy, tvb, offset - 8,
1390
0
            8, cyData, "%s: %" PRId64 ".%.04" PRId64,
1391
0
            proto_registrar_get_name(hf_dcom_vt_cy),
1392
0
            cyData / 10000, ABS(cyData % 10000));
1393
0
      break;
1394
0
    case(WIRESHARK_VT_UI4):
1395
0
      offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1396
0
                hf_dcom_vt_ui4, &u32Data);
1397
0
      break;
1398
0
    case(WIRESHARK_VT_UI8):
1399
0
      offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
1400
0
          hf_dcom_vt_ui8, &u64Data);
1401
0
      break;
1402
0
    case(WIRESHARK_VT_R4):
1403
0
      offset = dissect_dcom_FLOAT(tvb, offset, pinfo, sub_tree, di, drep,
1404
0
                hf_dcom_vt_r4, &f32Data);
1405
0
      break;
1406
0
    case(WIRESHARK_VT_R8):
1407
0
      offset = dissect_dcom_DOUBLE(tvb, offset, pinfo, sub_tree, di, drep,
1408
0
                hf_dcom_vt_r8, &f64Data);
1409
0
      break;
1410
0
    case(WIRESHARK_VT_DATE):
1411
0
      offset = dissect_dcom_DATE(tvb, offset, pinfo, sub_tree, di, drep,
1412
0
                hf_dcom_vt_date, &f64Data);
1413
0
      break;
1414
0
    case(WIRESHARK_VT_BSTR):
1415
0
      offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1416
0
      if (u32Pointer) {
1417
0
        offset = dissect_dcom_BSTR(tvb, offset, pinfo, sub_tree, di, drep,
1418
0
                hf_dcom_vt_bstr, cData, sizeof(cData) );
1419
0
      }
1420
0
      break;
1421
0
    case(WIRESHARK_VT_DISPATCH):
1422
0
      offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1423
0
      if (u32Pointer) {
1424
0
        offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, sub_tree, di, drep,
1425
0
                hf_dcom_vt_dispatch, NULL); /* XXX - how to handle this? */
1426
0
      }
1427
0
      break;
1428
0
    case(WIRESHARK_VT_ARRAY):
1429
0
      offset = dissect_dcom_SAFEARRAY(tvb, offset, pinfo, sub_tree, di, drep,
1430
0
                0, NULL);
1431
0
      break;
1432
0
    case(WIRESHARK_VT_ERROR):
1433
0
      offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
1434
0
                0);
1435
0
      break;
1436
0
    case(WIRESHARK_VT_VARIANT):
1437
0
      offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1438
0
      if (u32Pointer) {
1439
0
          offset = dissect_dcom_VARIANT(tvb, offset, pinfo, sub_tree, di, drep,
1440
0
                    hf_dcom_vt_byref /* must be BYREF */);
1441
0
      }
1442
0
      break;
1443
0
    case(WIRESHARK_VT_UNKNOWN):
1444
0
      offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1445
0
      break;
1446
0
    default:
1447
      /* XXX: add more types here! */
1448
0
      offset = dissect_dcom_tobedone_data(tvb, offset, pinfo, sub_tree, drep,
1449
0
              10000);
1450
0
  }
1451
0
  decrement_dissection_depth(pinfo);
1452
1453
  /* update subtree header */
1454
0
  proto_item_append_text(sub_item, ": %s",
1455
0
    val_to_str(pinfo->pool, u16VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
1456
1457
0
  proto_item_set_len(sub_item, offset - u32SubStart);
1458
1459
0
  return offset;
1460
0
}
1461
1462
1463
unsigned
1464
dissect_dcom_UUID(tvbuff_t *tvb, unsigned offset,
1465
  packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep,
1466
  int hfindex, e_guid_t *pdata)
1467
0
{
1468
0
  const char *uuid_name;
1469
0
  header_field_info *hfi;
1470
0
  e_guid_t uuid;
1471
1472
1473
  /* get the UUID, but don't put it into the tree */
1474
0
  offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep,
1475
0
            hfindex, &uuid);
1476
1477
  /* add to the tree */
1478
0
  hfi = proto_registrar_get_nth(hfindex);
1479
0
  uuid_name = guids_get_guid_name(&uuid, pinfo->pool);
1480
0
  if(uuid_name) {
1481
0
    proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
1482
0
        "%s: %s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
1483
0
        hfi->name, uuid_name,
1484
0
        uuid.data1, uuid.data2, uuid.data3,
1485
0
        uuid.data4[0], uuid.data4[1],
1486
0
        uuid.data4[2], uuid.data4[3],
1487
0
        uuid.data4[4], uuid.data4[5],
1488
0
        uuid.data4[6], uuid.data4[7]);
1489
0
  } else {
1490
0
    proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
1491
0
        "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1492
0
        hfi->name,
1493
0
        uuid.data1, uuid.data2, uuid.data3,
1494
0
        uuid.data4[0], uuid.data4[1],
1495
0
        uuid.data4[2], uuid.data4[3],
1496
0
        uuid.data4[4], uuid.data4[5],
1497
0
        uuid.data4[6], uuid.data4[7]);
1498
0
  }
1499
1500
0
  if(pdata != NULL) {
1501
0
    *pdata = uuid;
1502
0
  }
1503
1504
0
  return offset;
1505
0
}
1506
1507
1508
unsigned
1509
dissect_dcom_append_UUID(tvbuff_t *tvb, unsigned offset,
1510
  packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep,
1511
  int hfindex, int field_index, e_guid_t *uuid)
1512
0
{
1513
0
  const char *uuid_name;
1514
0
  proto_item *pi;
1515
0
  header_field_info *hfi;
1516
1517
1518
  /* XXX - this is far from being performance optimized! */
1519
1520
  /* get the UUID, but don't put it into the tree */
1521
0
  offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep,
1522
0
            hfindex, uuid);
1523
1524
  /* look for a registered uuid name */
1525
0
  uuid_name = guids_get_guid_name(uuid, pinfo->pool);
1526
1527
  /* add to the tree */
1528
0
  hfi = proto_registrar_get_nth(hfindex);
1529
0
  pi = proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) uuid, "%s", hfi->name);
1530
1531
0
  if (field_index != -1) {
1532
0
    proto_item_append_text(pi, "[%u]: ", field_index);
1533
0
  } else {
1534
0
    proto_item_append_text(pi, ": ");
1535
0
  }
1536
1537
0
  if(uuid_name) {
1538
0
    proto_item_append_text(pi, "%s (", uuid_name);
1539
0
  }
1540
1541
0
  proto_item_append_text(pi, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1542
0
        uuid->data1, uuid->data2, uuid->data3,
1543
0
        uuid->data4[0], uuid->data4[1],
1544
0
        uuid->data4[2], uuid->data4[3],
1545
0
        uuid->data4[4], uuid->data4[5],
1546
0
        uuid->data4[6], uuid->data4[7]);
1547
1548
0
  if(uuid_name) {
1549
0
    proto_item_append_text(pi, ")");
1550
0
  }
1551
1552
  /* update column info now */
1553
0
  if (field_index != -1) {
1554
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]=%s",
1555
0
      hfi->name, field_index, (uuid_name) ? uuid_name : "???");
1556
0
  } else {
1557
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%s",
1558
0
      hfi->name, (uuid_name) ? uuid_name : "???");
1559
0
  }
1560
1561
0
  return offset;
1562
0
}
1563
1564
1565
/* get a wide character string from tvb (zero terminated or limited through inLength) */
1566
/* the string will be converted to ASCII if possible or simple hexdump otherwise */
1567
/* outLength is in output bytes including zero termination output */
1568
static unsigned
1569
dcom_tvb_get_nwstringz0(tvbuff_t *tvb, unsigned offset, uint32_t inLength, char *pszStr, uint32_t outLength, bool *isPrintable)
1570
0
{
1571
0
  uint32_t u32Idx;
1572
0
  uint32_t u32IdxA;
1573
0
  uint32_t u32IdxW;
1574
0
  uint32_t inLengthWithoutNullDelimiter = 0;
1575
1576
0
  uint8_t u8Tmp1;
1577
0
  uint8_t u8Tmp2;
1578
1579
1580
0
  *isPrintable = true;
1581
0
  inLengthWithoutNullDelimiter = inLength == 0 ? 0 : inLength -1;
1582
1583
  /* we must have at least the space for the zero termination */
1584
0
  DISSECTOR_ASSERT(outLength >= 1);
1585
1586
  /* determine length and printability of the string */
1587
0
  for(u32Idx = 0; u32Idx < inLengthWithoutNullDelimiter; u32Idx+=2) {
1588
    /* the marshalling direction of a WCHAR is fixed! */
1589
0
    u8Tmp1 = tvb_get_uint8(tvb, offset+u32Idx);
1590
0
    u8Tmp2 = tvb_get_uint8(tvb, offset+u32Idx+1);
1591
1592
    /* is this the zero termination? */
1593
0
    if (u8Tmp1 == 0 && u8Tmp2 == 0) {
1594
0
      u32Idx+=2;
1595
0
      break;
1596
0
    }
1597
1598
    /* is this character printable? */
1599
    /* 10 = New Line, 13 = Carriage Return */
1600
    /* XXX - there are probably more printable chars than isprint() */
1601
0
    if(!(g_ascii_isprint(u8Tmp1) || u8Tmp1 == 10 || u8Tmp1 == 13)|| u8Tmp2 != 0) {
1602
0
      *isPrintable = false;
1603
0
    }
1604
0
  }
1605
1606
  /* u32Idx now contains the string length in bytes */
1607
  /* (including optional zero termination) */
1608
1609
  /* if this is a printable string? */
1610
0
  if(*isPrintable == true) {
1611
    /* convert to ascii (every "2nd char") */
1612
    /* XXX - is it possible to convert to UTF8, so the output functions work with it? */
1613
0
    for(u32IdxA = 0, u32IdxW = 0;
1614
0
        u32IdxW < u32Idx && u32IdxA < outLength-2;
1615
0
        u32IdxW+=2, u32IdxA++) {
1616
0
      pszStr[u32IdxA] = tvb_get_uint8(tvb, offset+u32IdxW);
1617
0
    }
1618
0
  } else {
1619
    /* convert to hexdump */
1620
0
    for(u32IdxA = 0, u32IdxW = 0;
1621
0
        u32IdxW < u32Idx && u32IdxA < outLength-2;
1622
0
        u32IdxW++, u32IdxA+=2) {
1623
0
      snprintf(&pszStr[u32IdxA], 3, "%02X", tvb_get_uint8(tvb, offset+u32IdxW));
1624
0
    }
1625
0
  }
1626
1627
  /* zero terminate the string, space must be available */
1628
0
  DISSECTOR_ASSERT(u32IdxA < outLength);
1629
0
  pszStr[u32IdxA] = 0;
1630
1631
0
  return offset + u32Idx;
1632
0
}
1633
1634
1635
/* dissect a LPWSTR into a given buffer */
1636
/* use FT_STRING for hfindex */
1637
/* u32MaxStr is maximum length of string (including trailing zero) */
1638
unsigned
1639
dissect_dcom_indexed_LPWSTR(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
1640
           proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex,
1641
             char *pszStr, uint32_t u32MaxStr, int field_index)
1642
0
{
1643
0
  uint32_t u32MaxCount;
1644
0
  uint32_t u32Offset;
1645
0
  uint32_t u32ArraySize;
1646
0
  uint32_t u32StrStart;
1647
0
  proto_item *sub_item;
1648
0
  proto_tree *sub_tree;
1649
0
  uint32_t u32SubStart;
1650
0
  bool isPrintable;
1651
1652
1653
  /* alignment of 4 needed */
1654
0
  offset = WS_ROUNDUP_4(offset);
1655
1656
  /* add subtree item */
1657
0
  sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
1658
0
  sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
1659
0
  u32SubStart = offset;
1660
1661
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1662
0
      hf_dcom_max_count, &u32MaxCount);
1663
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1664
0
      hf_dcom_offset, &u32Offset);
1665
0
  offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep,
1666
0
      &u32ArraySize);
1667
1668
0
  u32StrStart = offset;
1669
0
  offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1670
1671
0
  proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszStr);
1672
1673
  /* update subtree header */
1674
0
  if (field_index != -1) {
1675
0
    proto_item_set_text(sub_item, "%s[%u]: %s%s%s",
1676
0
      proto_registrar_get_name(hfindex),
1677
0
      field_index,
1678
0
      isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1679
0
  } else {
1680
0
    proto_item_append_text(sub_item, "%s%s%s",
1681
0
               isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1682
0
  }
1683
0
  proto_item_set_len(sub_item, offset - u32SubStart);
1684
1685
0
  return offset;
1686
0
}
1687
1688
1689
unsigned
1690
dissect_dcom_LPWSTR(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
1691
           proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex,
1692
             char *pszStr, uint32_t u32MaxStr)
1693
0
{
1694
1695
1696
0
  return dissect_dcom_indexed_LPWSTR(tvb, offset, pinfo, tree, di, drep,
1697
0
            hfindex, pszStr, u32MaxStr, -1);
1698
0
}
1699
1700
1701
/* dissect a BSTR to tree and into a given buffer (use FT_STRING for hfindex) */
1702
/* u32MaxStr is maximum length of string (including trailing zero) */
1703
/* (Hint: the BSTR space is always as long as the maximum size) */
1704
unsigned
1705
dissect_dcom_BSTR(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
1706
           proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex,
1707
             char *pszStr, uint32_t u32MaxStr)
1708
0
{
1709
0
  uint32_t u32MaxCount;
1710
0
  uint32_t u32ArraySize;
1711
0
  int strStart, subStart, realOffset;
1712
0
  proto_item *sub_item;
1713
0
  proto_tree *sub_tree;
1714
0
  uint32_t u32ByteLength;
1715
0
  bool isPrintable;
1716
1717
  /* alignment of 4 needed */
1718
0
  offset = WS_ROUNDUP_4(offset);
1719
1720
  /* add subtree item */
1721
0
  sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
1722
0
  sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
1723
0
  subStart = offset;
1724
1725
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1726
0
      hf_dcom_max_count, &u32MaxCount);
1727
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1728
0
      hf_dcom_byte_length, &u32ByteLength);
1729
0
  offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep,
1730
0
      &u32ArraySize);
1731
1732
0
  if ((uint32_t)offset + u32ArraySize*2 > INT_MAX) {
1733
0
    pszStr[0] = 0;
1734
0
    return offset;
1735
0
  }
1736
1737
0
  realOffset = offset + u32ArraySize*2;
1738
1739
0
  strStart = offset;
1740
0
  offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1741
1742
0
  proto_tree_add_string(sub_tree, hfindex, tvb, strStart, offset - strStart, pszStr);
1743
1744
  /* update subtree header */
1745
0
  proto_item_append_text(sub_item, "%s%s%s",
1746
0
  isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1747
0
  if (realOffset <= subStart) {
1748
    /* XXX - expert info */
1749
0
    return offset;
1750
0
  }
1751
0
  proto_item_set_len(sub_item, realOffset - subStart);
1752
1753
0
  return realOffset;
1754
0
}
1755
1756
1757
/* dissect an DUALSTRINGARRAY */
1758
unsigned
1759
dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
1760
           proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, char *ip)
1761
0
{
1762
0
  uint16_t  u16NumEntries;
1763
0
  uint16_t  u16SecurityOffset;
1764
0
  char  szStr[1000];
1765
0
  uint32_t  u32MaxStr = sizeof(szStr);
1766
0
  uint32_t  u32Start;
1767
0
  uint16_t u16TowerId;
1768
0
  uint16_t u16SecurityAuthnSvc;
1769
0
  uint16_t u16SecurityAuthzSvc;
1770
0
  proto_item *sub_item;
1771
0
  proto_tree *sub_tree;
1772
0
  uint32_t  u32SubStart;
1773
0
  uint32_t  u32StringBindings = 0;
1774
0
  uint32_t  u32SecurityBindings = 0;
1775
0
  proto_item *subsub_item;
1776
0
  proto_tree *subsub_tree;
1777
0
  uint32_t  u32SubSubStart;
1778
0
  bool isPrintable;
1779
0
  uint32_t first_ip = 0;
1780
0
  uint32_t curr_ip = 0;
1781
0
  uint32_t ipaddr;
1782
0
  proto_item *pi;
1783
1784
1785
  /* add subtree header */
1786
0
  sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
1787
0
  sub_tree = proto_item_add_subtree(sub_item, ett_dcom_dualstringarray);
1788
1789
0
  offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1790
0
      hf_dcom_dualstringarray_num_entries, &u16NumEntries);
1791
  /* from here, alignment is ok */
1792
0
  u32SubStart = offset - 2;
1793
0
  offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1794
0
      hf_dcom_dualstringarray_security_offset, &u16SecurityOffset);
1795
1796
  /* STRINGBINDINGs until first wchar zero */
1797
0
  while ( tvb_get_ntohs(tvb, offset) ) {
1798
0
    u32StringBindings++;
1799
1800
0
    subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_string, tvb, offset, 0, ENC_NA);
1801
0
    subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
1802
0
    u32SubSubStart = offset;
1803
1804
0
    offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1805
0
              hf_dcom_dualstringarray_string_tower_id, &u16TowerId);
1806
0
    u32Start = offset;
1807
  /* we don't know the (zero terminated) input length, use the buffer length instead */
1808
0
    offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
1809
0
    pi = proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_string_network_addr,
1810
0
      tvb, u32Start, offset - u32Start, szStr);
1811
1812
  /* convert ip address (if it is dotted decimal) */
1813
  /* XXX - this conversion is ugly */
1814
0
    if (ws_inet_pton4(szStr, &ipaddr)) {
1815
0
      if(get_host_ipaddr(szStr, &curr_ip)) {
1816
1817
        /*expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "DUALSTRINGARRAY: IP:%s",
1818
          ip_to_str( (uint8_t *) &curr_ip));*/
1819
1820
0
        if(first_ip == 0) {
1821
0
          if(ip != NULL) {
1822
0
            memcpy(ip, &curr_ip, sizeof(curr_ip));
1823
0
          }
1824
0
          first_ip = curr_ip;
1825
0
        } else {
1826
0
          if(first_ip != curr_ip) {
1827
0
            address first_ip_addr, curr_ip_addr;
1828
1829
0
            set_address(&first_ip_addr, AT_IPv4, 4, &first_ip);
1830
0
            set_address(&curr_ip_addr, AT_IPv4, 4, &curr_ip);
1831
0
            expert_add_info_format(pinfo, pi, &ei_dcom_dualstringarray_mult_ip,
1832
0
                       "DUALSTRINGARRAY: multiple IP's %s %s",
1833
0
                       address_to_str(pinfo->pool, &first_ip_addr), address_to_str(pinfo->pool, &curr_ip_addr));
1834
0
          }
1835
0
        }
1836
0
      }
1837
0
    }
1838
1839
0
    proto_item_append_text(subsub_item, "[%u]: TowerId=%s, NetworkAddr=\"%s\"",
1840
0
      u32StringBindings,
1841
0
      val_to_str(pinfo->pool, u16TowerId, dcom_protseq_vals, "Unknown (0x%04x"),
1842
0
      szStr);
1843
0
    proto_item_set_len(subsub_item, offset - u32SubSubStart);
1844
0
  }
1845
0
  offset += 2;
1846
1847
  /* SECURITYBINDINGs until first wchar zero */
1848
0
  while ( tvb_get_ntohs(tvb, offset) ) {
1849
0
    u32SecurityBindings++;
1850
1851
0
    subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_security, tvb, offset, 0, ENC_NA);
1852
0
    subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
1853
0
    u32SubSubStart = offset;
1854
1855
0
    offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1856
0
      hf_dcom_dualstringarray_security_authn_svc,
1857
0
            &u16SecurityAuthnSvc);
1858
0
    offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1859
0
      hf_dcom_dualstringarray_security_authz_svc,
1860
0
            &u16SecurityAuthzSvc);
1861
1862
0
    u32Start = offset;
1863
  /* we don't know the (zero terminated) input length, use the buffer length instead */
1864
0
    offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
1865
0
    proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_security_princ_name,
1866
0
      tvb, u32Start, offset - u32Start, szStr);
1867
1868
0
    proto_item_append_text(subsub_item, "[%u]: AuthnSvc=0x%04x, AuthzSvc=0x%04x, PrincName=\"%s\"",
1869
0
      u32SecurityBindings, u16SecurityAuthnSvc, u16SecurityAuthzSvc, szStr);
1870
0
    proto_item_set_len(subsub_item, offset - u32SubSubStart);
1871
0
  }
1872
0
  offset += 2;
1873
1874
  /* append info to subtree header */
1875
0
  proto_item_append_text(sub_item, ": STRINGBINDINGs=%u, SECURITYBINDINGs=%u",
1876
0
    u32StringBindings, u32SecurityBindings);
1877
0
  proto_item_set_len(sub_item, offset - u32SubStart);
1878
1879
0
  return offset;
1880
0
}
1881
1882
1883
/* dissect an STDOBJREF */
1884
unsigned
1885
dissect_dcom_STDOBJREF(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
1886
           proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex _U_,
1887
           uint64_t *oxid, uint64_t *oid, e_guid_t *ipid)
1888
0
{
1889
0
  uint32_t  u32Flags;
1890
0
  uint32_t  u32PublicRefs;
1891
0
  proto_item *sub_item;
1892
0
  proto_tree *sub_tree;
1893
0
  uint32_t  u32SubStart;
1894
1895
1896
  /* add subtree header */
1897
0
  sub_item = proto_tree_add_item(tree, hf_dcom_stdobjref, tvb, offset, 0, ENC_NA);
1898
0
  sub_tree = proto_item_add_subtree(sub_item, ett_dcom_stdobjref);
1899
1900
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1901
0
      hf_dcom_stdobjref_flags, &u32Flags);
1902
  /* from here, alignment is ok */
1903
0
  u32SubStart = offset - 4;
1904
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1905
0
      hf_dcom_stdobjref_public_refs, &u32PublicRefs);
1906
0
  offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep,
1907
0
      hf_dcom_oxid, oxid);
1908
0
  offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep,
1909
0
      hf_dcom_oid, oid);
1910
0
  offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
1911
0
      hf_dcom_ipid, ipid);
1912
1913
  /* append info to subtree header */
1914
0
  proto_item_append_text(sub_item, ": PublicRefs=%u IPID=%s",
1915
0
    u32PublicRefs, guids_resolve_guid_to_str(ipid, pinfo->pool));
1916
0
  proto_item_set_len(sub_item, offset - u32SubStart);
1917
1918
0
  return offset;
1919
0
}
1920
1921
1922
1923
/*
1924
 *
1925
 *static void
1926
 *print_uuid(const e_guid_t* uuid)
1927
*{
1928
 *    proto_tree_add_debug_text(NULL, "UUID:(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)\n",
1929
 *            uuid->data1, uuid->data2, uuid->data3,
1930
 *            uuid->data4[0], uuid->data4[1],
1931
 *            uuid->data4[2], uuid->data4[3],
1932
 *            uuid->data4[4], uuid->data4[5],
1933
 *            uuid->data4[6], uuid->data4[7]);
1934
 *
1935
 *    return;
1936
 *}
1937
 *
1938
 */
1939
1940
unsigned
1941
dcom_register_routine(dcom_dissect_fn_t routine, e_guid_t* uuid)
1942
0
{
1943
0
  dcom_marshaler_t *marshaler;
1944
1945
1946
  /* check if exists already */
1947
0
  if (dcom_get_routine_by_uuid(uuid))
1948
0
    return -1;
1949
1950
0
  marshaler = wmem_new(wmem_file_scope(), dcom_marshaler_t);
1951
0
  if (!marshaler) {
1952
    /*memory error*/
1953
0
    return -1;
1954
0
  }
1955
1956
0
  marshaler->parent = NULL;
1957
0
  marshaler->private_data = NULL;
1958
0
  marshaler->uuid = *uuid;
1959
0
  marshaler->routine = routine;
1960
1961
0
  dcom_marshalers = g_list_append(dcom_marshalers, marshaler);
1962
1963
0
  return 0;
1964
0
}
1965
1966
1967
dcom_dissect_fn_t
1968
dcom_get_routine_by_uuid(const e_guid_t* uuid)
1969
0
{
1970
0
  dcom_marshaler_t *marsh;
1971
0
  GList *marshalers;
1972
1973
0
  if(memcmp(uuid, &uuid_null, sizeof(uuid_null)) == 0) {
1974
0
    return NULL;
1975
0
  }
1976
1977
0
  for(marshalers = dcom_marshalers; marshalers!= NULL;
1978
0
        marshalers = g_list_next(marshalers)) {
1979
0
    marsh = (dcom_marshaler_t *)marshalers->data;
1980
    /*print_uuid(&marsh->uuid);*/
1981
    /*print_uuid(uuid);*/
1982
0
    if(memcmp(&marsh->uuid, uuid, sizeof(e_guid_t)) == 0) {
1983
0
        return marsh->routine;
1984
0
    }
1985
0
  }
1986
1987
0
  return NULL;
1988
0
}
1989
1990
/* dissect an CUSTOM */
1991
static unsigned
1992
dissect_dcom_CUSTOBJREF(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
1993
                   proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex,
1994
                   e_guid_t *clsid, e_guid_t *iid)
1995
0
{
1996
0
  uint32_t   u32CBExtension;
1997
0
  uint32_t   u32Size;
1998
0
  uint32_t   u32SubStart;
1999
0
  proto_item *sub_item;
2000
0
  proto_tree *sub_tree;
2001
0
  dcom_dissect_fn_t routine = NULL;
2002
2003
2004
  /* add subtree header */
2005
0
  hfindex = hf_dcom_custobjref;
2006
0
  sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_NA);
2007
0
  sub_tree = proto_item_add_subtree(sub_item, ett_dcom_custobjref);
2008
2009
0
  u32SubStart = offset;
2010
0
  offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2011
0
        hf_dcom_clsid, clsid);
2012
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2013
0
        hf_dcom_objref_cbextension, &u32CBExtension);
2014
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2015
0
        hf_dcom_objref_size, &u32Size);
2016
2017
  /* the following data depends on the iid, get the routine by iid */
2018
0
  routine = dcom_get_routine_by_uuid(iid);
2019
0
  if (routine){
2020
0
    offset = routine(tvb, offset, pinfo, sub_tree, di, drep, u32Size);
2021
0
  }
2022
2023
  /* append info to subtree header */
2024
  /* proto_item_append_text(sub_item, ": ActivationPropertiesIn"); */
2025
0
  proto_item_set_len(sub_item, offset - u32SubStart);
2026
2027
0
  return offset;
2028
0
}
2029
2030
/* dissect an OBJREF */
2031
unsigned
2032
dissect_dcom_OBJREF(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
2033
           proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, dcom_interface_t **interf)
2034
0
{
2035
0
  uint32_t  u32Signature;
2036
0
  uint32_t  u32Flags;
2037
0
  e_guid_t iid;
2038
0
  e_guid_t clsid;
2039
0
  proto_item *sub_item;
2040
0
  proto_tree *sub_tree;
2041
0
  uint32_t  u32SubStart;
2042
0
  uint64_t oxid = 0;
2043
0
  uint64_t oid = 0;
2044
0
  e_guid_t ipid;
2045
0
  dcom_interface_t *dcom_if = NULL;
2046
0
  char ip[4];
2047
2048
0
  memset(&ipid, 0, sizeof(ipid));
2049
0
  memset(ip, 0, sizeof(ip));
2050
2051
  /* add subtree header */
2052
0
  sub_item = proto_tree_add_item(tree, hf_dcom_objref, tvb, offset, 0, ENC_NA);
2053
0
  sub_tree = proto_item_add_subtree(sub_item, ett_dcom_objref);
2054
2055
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2056
0
      hf_dcom_objref_signature, &u32Signature);
2057
  /* from here, alignment is ok */
2058
0
  u32SubStart = offset - 4;
2059
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2060
0
      hf_dcom_objref_flags, &u32Flags);
2061
0
  offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2062
0
      hf_dcom_iid, &iid);
2063
2064
0
  switch(u32Flags) {
2065
0
    case(0x1):  /* standard */
2066
0
      offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2067
0
                &oxid, &oid, &ipid);
2068
0
      offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep,
2069
0
                hf_dcom_objref_resolver_address, ip);
2070
0
    break;
2071
0
    case(0x2):  /* handler (untested) */
2072
0
      offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2073
0
                &oxid, &oid, &iid);
2074
0
      offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2075
0
                hf_dcom_clsid, &clsid);
2076
0
      offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep,
2077
0
                hf_dcom_objref_resolver_address, ip);
2078
0
    break;
2079
0
    case(0x4):  /* custom */
2080
0
        offset = dissect_dcom_CUSTOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2081
0
                            &clsid, &iid);
2082
0
        break;
2083
0
  }
2084
2085
0
  if(u32Flags == 0x1 || u32Flags == 0x2) {
2086
    /* add interface instance to database (we currently only handle IPv4) */
2087
0
    if(pinfo->net_src.type == AT_IPv4) {
2088
0
      address addr;
2089
2090
0
      set_address(&addr, AT_IPv4, 4, ip);
2091
0
      dcom_if = dcom_interface_new(pinfo,
2092
0
                 &addr,
2093
0
                 &iid, oxid, oid, &ipid);
2094
0
    }
2095
0
  }
2096
2097
0
  if(interf != NULL) {
2098
0
    *interf = dcom_if;
2099
0
  }
2100
2101
  /* append info to subtree header */
2102
0
  proto_item_set_len(sub_item, offset - u32SubStart);
2103
2104
0
  return offset;
2105
0
}
2106
2107
/* dissect an MInterfacePointer */
2108
unsigned
2109
dissect_dcom_MInterfacePointer(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
2110
           proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, dcom_interface_t **interf)
2111
0
{
2112
0
  uint32_t  u32CntData;
2113
0
  uint32_t  u32ArraySize;
2114
0
  proto_item *sub_item;
2115
0
  proto_tree *sub_tree;
2116
0
  uint32_t  u32SubStart;
2117
2118
2119
0
  if (!hfindex) {
2120
0
    hfindex = hf_dcom_interface_pointer;
2121
0
  }
2122
2123
  /* add subtree header */
2124
0
  sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
2125
0
  sub_tree = proto_item_add_subtree(sub_item, ett_dcom_interface_pointer);
2126
2127
0
  offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize);
2128
0
  u32SubStart = offset - 4; /* should use this trick to deal with align pad if any */
2129
2130
0
  offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2131
0
      hf_dcom_ip_cnt_data, &u32CntData);
2132
2133
0
  offset = dissect_dcom_OBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex, interf);
2134
2135
  /* append info to subtree header */
2136
0
  proto_item_set_len(sub_item, offset - u32SubStart);
2137
2138
0
  return offset;
2139
0
}
2140
2141
/* dissect a pointer to a MInterfacePointer */
2142
unsigned
2143
dissect_dcom_PMInterfacePointer(tvbuff_t *tvb, unsigned offset, packet_info *pinfo,
2144
           proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, dcom_interface_t **interf)
2145
0
{
2146
0
  uint32_t u32Pointer;
2147
2148
2149
0
  offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
2150
2151
0
  if (u32Pointer) {
2152
0
    offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, di, drep, hfindex, interf);
2153
0
  } else {
2154
0
    if(interf != NULL) {
2155
0
      *interf = NULL;
2156
0
    }
2157
0
  }
2158
2159
0
  return offset;
2160
0
}
2161
2162
0
static void dcom_cleanup(void) {
2163
0
  if (dcom_machines != NULL) {
2164
0
    GList *machines;
2165
2166
0
    for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
2167
0
      dcom_machine_t *machine = (dcom_machine_t *)machines->data;
2168
2169
0
      if (machine->objects != NULL) {
2170
0
        GList *objects;
2171
0
        for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
2172
0
          dcom_object_t *object = (dcom_object_t *)objects->data;
2173
2174
0
          if (object->interfaces != NULL) {
2175
0
            GList *interface;
2176
0
            for(interface = object->interfaces; interface != NULL; interface = g_list_next(interface)) {
2177
0
              g_free(interface->data);
2178
0
              interface->data = NULL; /* for good measure */
2179
0
            }
2180
0
            g_list_free(object->interfaces);
2181
0
            object->interfaces = NULL;  /* for good measure */
2182
0
          }
2183
2184
0
          g_free(objects->data);
2185
0
          objects->data = NULL; /* for good measure */
2186
0
        }
2187
0
        g_list_free(machine->objects);
2188
0
        free_address(&machine->ip);
2189
0
        machine->objects = NULL; /* for good measure */
2190
0
      }
2191
2192
0
      g_free(machines->data);
2193
0
      machines->data = NULL; /* for good measure */
2194
0
    }
2195
0
    g_list_free(dcom_machines);
2196
0
    dcom_machines = NULL;
2197
0
  }
2198
2199
  /*  The data in dcom_interfaces is wmem_file_scoped so there's no need to free
2200
   *  the data pointers.
2201
   */
2202
0
  if (dcom_interfaces != NULL) {
2203
0
    g_list_free(dcom_interfaces);
2204
0
    dcom_interfaces = NULL;
2205
0
  }
2206
2207
  /*  The data in dcom_marshalers is wmem_file_scoped so there's no need to free
2208
   *  the data pointers.
2209
   */
2210
0
  if (dcom_marshalers != NULL) {
2211
0
    g_list_free(dcom_marshalers);
2212
0
    dcom_marshalers = NULL;
2213
0
  }
2214
0
}
2215
2216
void
2217
proto_register_dcom (void)
2218
14
{
2219
14
  static hf_register_info hf_dcom_this_array[] = {
2220
#if 0
2221
    { &hf_dcom_this_version_major,
2222
    { "VersionMajor", "dcom.this.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2223
#endif
2224
#if 0
2225
    { &hf_dcom_this_version_minor,
2226
    { "VersionMinor", "dcom.this.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2227
#endif
2228
14
    { &hf_dcom_this_flags,
2229
14
    { "Flags", "dcom.this.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }},
2230
14
    { &hf_dcom_this_res,
2231
14
    { "Reserved", "dcom.this.res", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2232
14
    { &hf_dcom_this_cid,
2233
14
    { "Causality ID", "dcom.this.uuid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2234
14
  };
2235
2236
14
  static hf_register_info hf_dcom_that_array[] = {
2237
14
    { &hf_dcom_that_flags,
2238
14
    { "Flags", "dcom.that.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }}
2239
14
  };
2240
2241
14
  static hf_register_info hf_dcom_extent_array[] = {
2242
14
    { &hf_dcom_extent,
2243
14
    { "Extension", "dcom.extent", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2244
14
    { &hf_dcom_extent_array_count,
2245
14
    { "Extension Count", "dcom.extent.array_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2246
14
    { &hf_dcom_extent_array_res,
2247
14
    { "Reserved", "dcom.extent.array_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2248
14
    { &hf_dcom_extent_size,
2249
14
    { "Extension Size", "dcom.extent.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2250
14
    { &hf_dcom_extent_id,
2251
14
    { "Extension Id", "dcom.extent.id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2252
14
  };
2253
2254
14
  static hf_register_info hf_dcom_array[] = {
2255
14
    { &hf_dcom_version_major,
2256
14
    { "VersionMajor", "dcom.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2257
14
    { &hf_dcom_version_minor,
2258
14
    { "VersionMinor", "dcom.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2259
14
    { &hf_dcom_hresult,
2260
14
    { "HResult", "dcom.hresult", FT_UINT32, BASE_HEX, VALS(dcom_hresult_vals), 0x0, NULL, HFILL }},
2261
14
    { &hf_dcom_max_count,
2262
14
    { "MaxCount", "dcom.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2263
14
    { &hf_dcom_offset,
2264
14
    { "Offset", "dcom.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2265
14
    { &hf_dcom_byte_length,
2266
14
    { "ByteLength", "dcom.byte_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2267
#if 0
2268
    { &hf_dcom_actual_count,
2269
    { "ActualCount", "dcom.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2270
#endif
2271
14
    { &hf_dcom_tobedone,
2272
14
    { "To Be Done", "dcom.tobedone", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2273
14
    { &hf_dcom_nospec,
2274
14
    { "No Specification Available", "dcom.nospec", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2275
#if 0
2276
    { &hf_dcom_variant,
2277
    { "Variant", "dcom.variant", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2278
#endif
2279
14
    { &hf_dcom_variant_type,
2280
14
    { "VarType", "dcom.variant_type", FT_UINT16, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2281
14
    { &hf_dcom_variant_type32,
2282
14
    { "VarType32", "dcom.variant_type32", FT_UINT32, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2283
14
    { &hf_dcom_variant_size,
2284
14
    { "Size", "dcom.variant_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2285
14
    { &hf_dcom_variant_rpc_res,
2286
14
    { "RPC-Reserved", "dcom.variant_rpc_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2287
14
    { &hf_dcom_variant_wres,
2288
14
    { "Reserved", "dcom.variant_wres", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2289
14
    { &hf_dcom_array_size,
2290
14
    { "(ArraySize)", "dcom.array_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2291
14
    { &hf_dcom_pointer_val,
2292
14
    { "(PointerVal)", "dcom.pointer_val", FT_UINT32, BASE_HEX, VALS(dcom_dcerpc_pointer_vals), 0x0, NULL, HFILL }}
2293
14
  };
2294
2295
14
  static hf_register_info hf_dcom_interface_pointer_array[] = {
2296
14
    { &hf_dcom_interface_pointer,
2297
14
    { "InterfacePointer", "dcom.ifp", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2298
14
    { &hf_dcom_ip_cnt_data,
2299
14
    { "CntData", "dcom.ip_cnt_data", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
2300
14
  };
2301
2302
14
  static hf_register_info hf_dcom_objref_array[] = {
2303
14
    { &hf_dcom_objref,
2304
14
    { "OBJREF", "dcom.objref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2305
14
    { &hf_dcom_objref_signature,
2306
14
    { "Signature", "dcom.objref.signature", FT_UINT32, BASE_HEX, VALS(dcom_objref_signature_vals), 0x0, NULL, HFILL }},
2307
14
    { &hf_dcom_objref_flags,
2308
14
    { "Flags", "dcom.objref.flags", FT_UINT32, BASE_HEX, VALS(dcom_objref_flag_vals), 0x0, NULL, HFILL }},
2309
14
    { &hf_dcom_iid,
2310
14
    { "IID", "dcom.iid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2311
14
    { &hf_dcom_clsid,
2312
14
    { "CLSID", "dcom.clsid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2313
14
    { &hf_dcom_objref_resolver_address,
2314
14
    { "ResolverAddress", "dcom.objref.resolver_address", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2315
14
    { &hf_dcom_objref_cbextension,
2316
14
    { "CBExtension", "dcom.objref.cbextension", FT_UINT32, BASE_DEC, NULL, 0x0, "Size of extension data", HFILL }},
2317
14
    { &hf_dcom_objref_size,
2318
14
    { "Size", "dcom.objref.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
2319
14
  };
2320
2321
14
  static hf_register_info hf_dcom_stdobjref_array[] = {
2322
14
    { &hf_dcom_stdobjref,
2323
14
    { "STDOBJREF", "dcom.stdobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2324
14
    { &hf_dcom_stdobjref_flags,
2325
14
    { "Flags", "dcom.stdobjref.flags", FT_UINT32, BASE_HEX, VALS(dcom_stdobjref_flag_vals), 0x0, NULL, HFILL }},
2326
14
    { &hf_dcom_stdobjref_public_refs,
2327
14
    { "PublicRefs", "dcom.stdobjref.public_refs", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2328
14
    { &hf_dcom_oxid,
2329
14
    { "OXID", "dcom.oxid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2330
14
    { &hf_dcom_oid,
2331
14
    { "OID", "dcom.oid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2332
14
    { &hf_dcom_ipid,
2333
14
    { "IPID", "dcom.ipid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2334
14
  };
2335
2336
14
  static hf_register_info hf_dcom_custobjref_array[] = {
2337
14
    { &hf_dcom_custobjref,
2338
14
    { "CUSTOMOBJREF", "dcom.custobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2339
14
  };
2340
2341
2342
14
  static hf_register_info hf_dcom_dualstringarray_array[] = {
2343
14
    { &hf_dcom_dualstringarray_num_entries,
2344
14
    { "NumEntries", "dcom.dualstringarray.num_entries", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2345
14
    { &hf_dcom_dualstringarray_security_offset,
2346
14
    { "SecurityOffset", "dcom.dualstringarray.security_offset", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2347
14
    { &hf_dcom_dualstringarray_string,
2348
14
    { "StringBinding", "dcom.dualstringarray.string", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2349
14
    { &hf_dcom_dualstringarray_string_tower_id,
2350
14
    { "TowerId", "dcom.dualstringarray.tower_id", FT_UINT16, BASE_HEX, VALS(dcom_protseq_vals), 0x0, NULL, HFILL }},
2351
14
    { &hf_dcom_dualstringarray_string_network_addr,
2352
14
    { "NetworkAddr", "dcom.dualstringarray.network_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2353
14
    { &hf_dcom_dualstringarray_security,
2354
14
    { "SecurityBinding", "dcom.dualstringarray.security", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2355
14
    { &hf_dcom_dualstringarray_security_authn_svc,
2356
14
    { "AuthnSvc", "dcom.dualstringarray.security_authn_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authn), 0x0, NULL, HFILL }},
2357
14
    { &hf_dcom_dualstringarray_security_authz_svc,
2358
14
    { "AuthzSvc", "dcom.dualstringarray.security_authz_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authz), 0x0, NULL, HFILL }},
2359
14
    { &hf_dcom_dualstringarray_security_princ_name,
2360
14
    { "PrincName", "dcom.dualstringarray.security_princ_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2361
14
  };
2362
2363
14
  static hf_register_info hf_dcom_vt_array[] = {
2364
14
    { &hf_dcom_vt_bool,
2365
14
    { "VT_BOOL", "dcom.vt.bool", FT_UINT16, BASE_HEX, VALS(dcom_vt_bool_vals), 0x0, NULL, HFILL }},
2366
14
    { &hf_dcom_vt_i1,
2367
14
    { "VT_I1", "dcom.vt.i1", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2368
14
    { &hf_dcom_vt_i2,
2369
14
    { "VT_I2", "dcom.vt.i2", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2370
14
    { &hf_dcom_vt_i4,
2371
14
    { "VT_I4", "dcom.vt.i4", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2372
14
    { &hf_dcom_vt_i8,
2373
14
    { "VT_I8", "dcom.vt.i8", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2374
14
    { &hf_dcom_vt_cy,
2375
14
    { "VT_CY", "dcom.vt.cy", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2376
14
    { &hf_dcom_vt_ui1,
2377
14
    { "VT_UI1", "dcom.vt.ui1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2378
14
    { &hf_dcom_vt_ui2,
2379
14
    { "VT_UI2", "dcom.vt.ui2", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2380
14
    { &hf_dcom_vt_ui4,
2381
14
    { "VT_UI4", "dcom.vt.ui4", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2382
14
    { &hf_dcom_vt_ui8,
2383
14
    { "VT_UI8", "dcom.vt.ui8", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2384
14
    { &hf_dcom_vt_r4,
2385
14
    { "VT_R4", "dcom.vt.r4", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2386
14
    { &hf_dcom_vt_r8,
2387
14
    { "VT_R8", "dcom.vt.r8", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2388
14
    { &hf_dcom_vt_date,
2389
14
    { "VT_DATE", "dcom.vt.date", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2390
14
    { &hf_dcom_vt_bstr,
2391
14
    { "VT_BSTR", "dcom.vt.bstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2392
14
    { &hf_dcom_vt_byref,
2393
14
    { "BYREF", "dcom.vt.byref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2394
14
    { &hf_dcom_vt_dispatch,
2395
14
    { "VT_DISPATCH", "dcom.vt.dispatch", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2396
14
  };
2397
2398
14
  static hf_register_info hf_dcom_sa_array[] = {
2399
14
    { &hf_dcom_safearray,
2400
14
    { "SAFEARRAY", "dcom.sa", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2401
14
    { &hf_dcom_sa_dims32,
2402
14
    { "Dims32", "dcom.sa.dims32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2403
14
    { &hf_dcom_sa_dims16,
2404
14
    { "Dims16", "dcom.sa.dims16", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2405
14
    { &hf_dcom_sa_features,
2406
14
    { "Features", "dcom.sa.features", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2407
14
    { &hf_dcom_sa_element_size,
2408
14
    { "ElementSize", "dcom.sa.element_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2409
14
    { &hf_dcom_sa_locks,
2410
14
    { "Locks", "dcom.sa.locks", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2411
14
    { &hf_dcom_sa_vartype32,
2412
14
    { "VarType32", "dcom.sa.vartype", FT_UINT32, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2413
14
    { &hf_dcom_sa_vartype16,
2414
14
    { "VarType16", "dcom.sa.vartype", FT_UINT16, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2415
14
    { &hf_dcom_sa_elements,
2416
14
    { "Elements", "dcom.sa.elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2417
14
    { &hf_dcom_sa_bound_elements,
2418
14
    { "BoundElements", "dcom.sa.bound_elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2419
14
    { &hf_dcom_sa_low_bound,
2420
14
    { "LowBound", "dcom.sa.low_bound", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2421
2422
14
    { &hf_dcom_sa_features_auto,
2423
14
    { "AUTO", "dcom.sa.features_auto", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_AUTO, NULL, HFILL }},
2424
14
    { &hf_dcom_sa_features_static,
2425
14
    { "STATIC", "dcom.sa.features_static", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_STATIC, NULL, HFILL }},
2426
14
    { &hf_dcom_sa_features_embedded,
2427
14
    { "EMBEDDED", "dcom.sa.features_embedded", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_EMBEDDED, NULL, HFILL }},
2428
14
    { &hf_dcom_sa_features_fixedsize,
2429
14
    { "FIXEDSIZE", "dcom.sa.features_fixedsize", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_FIXEDSIZE, NULL, HFILL }},
2430
14
    { &hf_dcom_sa_features_record,
2431
14
    { "RECORD", "dcom.sa.features_record", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_RECORD, NULL, HFILL }},
2432
14
    { &hf_dcom_sa_features_have_iid,
2433
14
    { "HAVEIID", "dcom.sa.features_have_iid", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEIID, NULL, HFILL }},
2434
14
    { &hf_dcom_sa_features_have_vartype,
2435
14
    { "HAVEVARTYPE", "dcom.sa.features_have_vartype", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEVARTYPE, NULL, HFILL }},
2436
14
    { &hf_dcom_sa_features_bstr,
2437
14
    { "BSTR", "dcom.sa.features_bstr", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_BSTR, NULL, HFILL }},
2438
14
    { &hf_dcom_sa_features_unknown,
2439
14
    { "UNKNOWN", "dcom.sa.features_unknown", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_UNKNOWN, NULL, HFILL }},
2440
14
    { &hf_dcom_sa_features_dispatch,
2441
14
    { "DISPATCH", "dcom.sa.features_dispatch", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_DISPATCH, NULL, HFILL }},
2442
14
    { &hf_dcom_sa_features_variant,
2443
14
    { "VARIANT", "dcom.sa.features_variant", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_VARIANT, NULL, HFILL }}
2444
14
  };
2445
2446
14
  static int *ett_dcom[] = {
2447
14
    &ett_dcom_this,
2448
14
    &ett_dcom_that,
2449
14
    &ett_dcom_extent,
2450
14
    &ett_dcom_lpwstr,
2451
14
    &ett_dcom_interface_pointer,
2452
14
    &ett_dcom_objref,
2453
14
    &ett_dcom_stdobjref,
2454
14
    &ett_dcom_custobjref,
2455
14
    &ett_dcom_dualstringarray,
2456
14
    &ett_dcom_dualstringarray_binding,
2457
14
    &ett_dcom_variant,
2458
14
    &ett_dcom_safearray,
2459
14
    &ett_dcom_sa_features,
2460
14
  };
2461
2462
14
  static ei_register_info ei[] = {
2463
14
    { &ei_dcom_dissection_incomplete, { "dcom.dissection_incomplete", PI_UNDECODED, PI_WARN, "Dissection incomplete", EXPFILL }},
2464
14
    { &ei_dcom_no_spec, { "dcom.no_spec", PI_UNDECODED, PI_NOTE, "No specification available, dissection not possible", EXPFILL }},
2465
14
    { &ei_dcom_hresult_expert, { "dcom.hresult.expert", PI_RESPONSE_CODE, PI_NOTE, "Hresult", EXPFILL }},
2466
14
    { &ei_dcom_dualstringarray_mult_ip, { "dcom.dualstringarray.mult_ip", PI_UNDECODED, PI_NOTE, "DUALSTRINGARRAY Multiple IP", EXPFILL }},
2467
14
  };
2468
2469
14
  module_t *dcom_module;
2470
14
  expert_module_t* expert_dcom;
2471
2472
  /* currently, the DCOM protocol "itself" has no real protocol dissector */
2473
  /* we only need this, to register some generic elements */
2474
14
  proto_dcom = proto_register_protocol ("DCOM", "DCOM", "dcom");
2475
14
  proto_register_field_array(proto_dcom, hf_dcom_this_array, array_length(hf_dcom_this_array));
2476
14
  proto_register_field_array(proto_dcom, hf_dcom_that_array, array_length(hf_dcom_that_array));
2477
14
  proto_register_field_array(proto_dcom, hf_dcom_extent_array, array_length(hf_dcom_extent_array));
2478
14
  proto_register_field_array(proto_dcom, hf_dcom_array, array_length(hf_dcom_array));
2479
14
  proto_register_field_array(proto_dcom, hf_dcom_objref_array, array_length(hf_dcom_objref_array));
2480
14
  proto_register_field_array(proto_dcom, hf_dcom_stdobjref_array, array_length(hf_dcom_stdobjref_array));
2481
14
  proto_register_field_array(proto_dcom, hf_dcom_custobjref_array, array_length(hf_dcom_custobjref_array));
2482
14
  proto_register_field_array(proto_dcom, hf_dcom_dualstringarray_array, array_length(hf_dcom_dualstringarray_array));
2483
14
  proto_register_field_array(proto_dcom, hf_dcom_interface_pointer_array, array_length(hf_dcom_interface_pointer_array));
2484
14
  proto_register_field_array(proto_dcom, hf_dcom_vt_array, array_length(hf_dcom_vt_array));
2485
14
  proto_register_field_array(proto_dcom, hf_dcom_sa_array, array_length(hf_dcom_sa_array));
2486
14
  proto_register_subtree_array (ett_dcom, array_length (ett_dcom));
2487
2488
14
  expert_dcom = expert_register_protocol(proto_dcom);
2489
14
  expert_register_field_array(expert_dcom, ei, array_length(ei));
2490
2491
  /* preferences */
2492
14
  dcom_module = prefs_register_protocol(proto_dcom, NULL);
2493
2494
14
  prefs_register_bool_preference(dcom_module, "display_unmarshalling_details",
2495
14
    "Display DCOM unmarshalling details",
2496
14
    "Display some DCOM unmarshalled fields "
2497
14
    "usually hidden",
2498
14
    &dcom_prefs_display_unmarshalling_details);
2499
2500
14
  register_cleanup_routine(dcom_cleanup);
2501
14
}
2502
2503
2504
void
2505
proto_reg_handoff_dcom (void)
2506
14
{
2507
  /* register some "well known" UUID's */
2508
14
  guids_add_guid(&uuid_debug_ext, "Debug Information Body Extension");
2509
14
  guids_add_guid(&uuid_ext_error_ext, "Extended Error Info Body Extension");
2510
14
  guids_add_guid(&ipid_rem_unknown, "IRemUnknown");
2511
14
  guids_add_guid(&iid_unknown, "IUnknown");
2512
14
  guids_add_guid(&uuid_null, "NULL");
2513
14
  guids_add_guid(&iid_class_factory, "IClassFactory");
2514
14
  guids_add_guid(&iid_type_info, "ITypeInfo");
2515
14
  guids_add_guid(&iid_provide_class_info, "IProvideClassInfo");
2516
2517
  /* Currently, we have nothing to register for DCOM */
2518
14
}
2519
2520
/*
2521
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2522
 *
2523
 * Local variables:
2524
 * c-basic-offset: 8
2525
 * tab-width: 8
2526
 * indent-tabs-mode: t
2527
 * End:
2528
 *
2529
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2530
 * :indentSize=8:tabSize=8:noTabs=false:
2531
 */