Coverage Report

Created: 2025-02-15 06:25

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