Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-dcom.c
blob6eaa3018cefa4d320f4ae65e8430b9109d7e3300
1 /* packet-dcom.c
2 * Routines for DCOM generics
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 /* A few words about DCOM:
13 * DCOM uses DCERPC as its underlying "transport" protocol.
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")
20 * DCOM defines itself some interfaces: oxid, remact, remunk and others
22 * Implemented is currently "only" a static dissection of packet fields
23 * (no "object recognition" included)
25 * User's of DCOM can define their own interface's using Microsoft IDL.
27 * Hint: The registered DCOM interface names can be found in the
28 * windows registry at: "HKEY_CLASSES_ROOT\Interface"
31 * Resources on the web:
33 * "Understanding the DCOM Wire Protocol by Analyzing Network Data Packets"
34 * http:// www.microsoft.com/msj/0398/dcom.htm
36 * "Distributed Component Object Model Protocol -- DCOM/1.0"
37 * http://www.microsoft.com/com/resources/specs.asp (link is currently down)
41 /* Files involved dissecting DCOM:
43 * packet-dcom.c: generic DCOM things (this, that, ...) and
44 * generic DCOM datatype (DWORD, VARIANT, ...)
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
55 #include "config.h"
57 #include <epan/packet.h>
58 #include <epan/addr_resolv.h>
59 #include <epan/expert.h>
60 #include <epan/tfs.h>
62 #include <epan/prefs.h>
63 #include "packet-dcerpc.h"
64 #include "packet-dcom.h"
66 void proto_register_dcom (void);
67 void proto_reg_handoff_dcom (void);
69 static int proto_dcom;
71 bool dcom_prefs_display_unmarshalling_details;
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;
81 static int ett_dcom_that;
82 static int hf_dcom_that_flags;
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;
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;
97 /* COMVERSION */
98 static int hf_dcom_version_major;
99 static int hf_dcom_version_minor;
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; */
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;
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;
126 static int ett_dcom_custobjref;
127 static int hf_dcom_custobjref;
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;
141 static int ett_dcom_interface_pointer;
142 static int hf_dcom_interface_pointer;
143 static int hf_dcom_ip_cnt_data;
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;
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;
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;
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;
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;
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} };
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
217 static GList *dcom_machines;
218 static GList *dcom_interfaces;
219 static GList *dcom_marshalers;
221 static const value_string dcom_thisthat_flag_vals[] = {
222 { 0, "INFO_NULL" },
223 { 1, "INFO_LOCAL" },
224 { 0, NULL }
227 #if 0
228 static const value_string dcom_boolean_flag_vals[] = {
229 { 0x00000001, "TRUE" },
230 { 0x00000000, "FALSE" },
231 { 0, NULL }
233 #endif
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;
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));*/
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);*/
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));*/
262 #endif
264 dcom_interface_t *dcom_interface_find(packet_info *pinfo _U_, const address *addr _U_, e_guid_t *ipid)
266 dcom_interface_t *interf;
267 GList *interfaces;
270 if(memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
272 return NULL;
275 for(interfaces = dcom_interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
276 interf = (dcom_interface_t *)interfaces->data;
278 if(memcmp(&interf->ipid, ipid, sizeof(e_guid_t)) == 0) {
279 return interf;
283 return NULL;
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)
289 GList *dcom_iter;
290 dcom_machine_t *machine;
291 dcom_object_t *object;
292 dcom_interface_t *interf;
295 if( memcmp(iid, &uuid_null, sizeof(uuid_null)) == 0 ||
296 memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
298 return NULL;
301 if(oxid == 0 || oid == 0) {
302 /*ws_warning("interface_new#%u", pinfo->num);*/
304 interf = wmem_new(wmem_file_scope(), dcom_interface_t);
305 interf->parent = NULL;
306 interf->private_data = NULL;
307 interf->first_packet = pinfo->num;
308 interf->iid = *iid;
309 interf->ipid = *ipid;
311 dcom_interfaces = g_list_append(dcom_interfaces, interf);
312 return interf;
315 /* find machine */
316 dcom_iter = dcom_machines;
317 while(dcom_iter != NULL) {
318 machine = (dcom_machine_t *)dcom_iter->data;
319 if(cmp_address(&machine->ip, addr) == 0) {
320 break;
322 dcom_iter = g_list_next(dcom_iter);
325 /* create new machine if not found */
326 if(dcom_iter == NULL) {
327 machine = g_new(dcom_machine_t,1);
328 copy_address(&machine->ip, addr);
329 machine->objects = NULL;
330 machine->first_packet = pinfo->num;
331 dcom_machines = g_list_append(dcom_machines, machine);
334 /* find object */
335 dcom_iter = machine->objects;
336 while(dcom_iter != NULL) {
337 object = (dcom_object_t *)dcom_iter->data;
338 if(object->oid == oid) {
339 break;
341 dcom_iter = g_list_next(dcom_iter);
344 /* create new object if not found */
345 if(dcom_iter == NULL) {
346 object = g_new(dcom_object_t,1);
347 object->parent = machine;
348 object->interfaces = NULL;
349 object->private_data = NULL;
350 object->first_packet = pinfo->num;
351 object->oid = oid;
352 object->oxid = oxid;
354 machine->objects = g_list_append(machine->objects, object);
357 /* find interface */
358 dcom_iter = object->interfaces;
359 while(dcom_iter != NULL) {
360 interf = (dcom_interface_t *)dcom_iter->data;
361 if(memcmp(&interf->ipid, ipid, sizeof(e_guid_t)) == 0) {
362 break;
364 dcom_iter = g_list_next(dcom_iter);
367 /* create new interface if not found */
368 if(dcom_iter == NULL) {
369 interf = g_new(dcom_interface_t,1);
370 interf->parent = object;
371 interf->private_data = NULL;
372 interf->first_packet = pinfo->num;
373 interf->iid = *iid;
374 interf->ipid = *ipid;
376 object->interfaces = g_list_append(object->interfaces, interf);
377 dcom_interfaces = g_list_append(dcom_interfaces, interf);
380 return interf;
385 * Flag bits in connection-oriented PDU header.
387 #define WIRESHARK_FADF_AUTO 0x0001
388 #define WIRESHARK_FADF_STATIC 0x0002
389 #define WIRESHARK_FADF_EMBEDDED 0x0004
390 #define WIRESHARK_FADF_FIXEDSIZE 0x0010
391 #define WIRESHARK_FADF_RECORD 0x0020
392 #define WIRESHARK_FADF_HAVEIID 0x0040
393 #define WIRESHARK_FADF_HAVEVARTYPE 0x0080
394 #define WIRESHARK_FADF_BSTR 0x0100
395 #define WIRESHARK_FADF_UNKNOWN 0x0200
396 #define WIRESHARK_FADF_DISPATCH 0x0400
397 #define WIRESHARK_FADF_VARIANT 0x0800
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,
443 WIRESHARK_VT_BSTR_BLOB = 0x0fff,
445 WIRESHARK_VT_VECTOR = 0x1000,
446 WIRESHARK_VT_ARRAY = 0x2000,
447 WIRESHARK_VT_BYREF = 0x4000,
448 WIRESHARK_VT_RESERVED = 0x8000,
450 WIRESHARK_VT_ILLEGAL = 0xffff,
451 WIRESHARK_VT_ILLEGALMASKED = 0x0fff,
452 WIRESHARK_VT_TYPEMASK = 0x0fff
453 } dcom_vartype_t;
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"},
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"},
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 */
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" },
519 { 0x80010108, "RPC_E_DISCONNECTED" },
520 { 0x80010113, "RPC_E_INVALID_IPID" },
521 { 0x8001011F, "RPC_E_TIMEOUT" },
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" },
531 { 0x8002801D, "TYPE_E_LIBNOTREGISTERED" },
533 { 0x80040154, "REGDB_E_CLASSNOTREG" },
534 { 0x80040201, "CO_E_FAILEDTOGETSECCTX" },
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" },
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" },
584 { 0x80080004, "CO_E_BAD_PATH" },
586 { 0, NULL }
589 static const value_string dcom_objref_flag_vals[] = {
590 { 0x1, "OBJREF_STANDARD" },
591 { 0x2, "OBJREF_HANDLER" },
592 { 0x4, "OBJREF_CUSTOM" },
593 { 0, NULL }
596 static const value_string dcom_objref_signature_vals[] = {
597 { 0x574f454d, "MEOW" },
598 { 0, NULL }
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 }
616 static const value_string dcom_dcerpc_pointer_vals[] = {
617 { 0x72657355, "User" },
618 { 0x42535452, "BSTR" },
619 { 0x00000000, "NULL" },
620 { 0, NULL }
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}
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}
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 }
660 static const value_string dcom_vt_bool_vals[] = {
661 { 0x0000, "FALSE" },
662 { 0xFFFF, "TRUE" },
663 { 0, NULL }
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)
673 uint32_t u32ArraySize;
674 uint32_t u32ArraySize2;
675 uint32_t u32Pointer;
676 uint32_t u32VariableOffset;
677 uint32_t u32Idx;
678 uint32_t u32SubStart;
679 proto_item *sub_item;
680 proto_tree *sub_tree;
682 uint32_t u32ArrayCount;
683 uint32_t u32ArrayRes;
685 uint32_t u32ExtentSize;
686 e_guid_t uuidExtend;
687 const char *uuid_name;
690 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
692 if (u32Pointer == 0) {
693 return offset;
696 offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
697 hf_dcom_extent_array_count, &u32ArrayCount);
698 offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
699 hf_dcom_extent_array_res, &u32ArrayRes);
701 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
703 if (u32Pointer == 0) {
704 return offset;
707 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
708 &u32ArraySize);
710 u32VariableOffset = offset + u32ArraySize*4;
712 u32Idx = 1;
713 while (u32ArraySize--) {
714 sub_item = proto_tree_add_item(tree, hf_dcom_extent, tvb, offset, 0, ENC_NA);
715 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_extent);
716 u32SubStart = offset;
718 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
720 if(u32Pointer != 0) {
721 u32VariableOffset = dissect_dcom_DWORD(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
722 hf_dcom_extent_size, &u32ExtentSize);
724 dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, NULL, di, drep,
725 hf_dcom_extent_id, &uuidExtend);
727 /* look for a registered uuid name */
728 if((uuid_name = guids_get_uuid_name(&uuidExtend, pinfo->pool)) != NULL) {
729 proto_tree_add_guid_format_value(sub_tree, hf_dcom_extent_id, tvb,
730 offset, sizeof(e_guid_t), (e_guid_t *) &uuidExtend,
731 "%s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
732 uuid_name,
733 uuidExtend.data1, uuidExtend.data2, uuidExtend.data3,
734 uuidExtend.data4[0], uuidExtend.data4[1],
735 uuidExtend.data4[2], uuidExtend.data4[3],
736 uuidExtend.data4[4], uuidExtend.data4[5],
737 uuidExtend.data4[6], uuidExtend.data4[7]);
738 u32VariableOffset += 16;
739 } else {
740 u32VariableOffset = dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
741 hf_dcom_extent_id, &uuidExtend);
745 u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
746 &u32ArraySize2);
747 u32VariableOffset = dissect_dcom_nospec_data(tvb, u32VariableOffset, pinfo, sub_tree, drep, u32ArraySize2);
749 /* update subtree header */
750 if(uuid_name != NULL) {
751 proto_item_append_text(sub_item, "[%u]: %s, Bytes=%u",
752 u32Idx, uuid_name, u32ArraySize2);
753 } else {
754 proto_item_append_text(sub_item, "[%u]: Bytes=%u",
755 u32Idx, u32ArraySize2);
757 proto_item_set_len(sub_item, offset - u32SubStart);
758 } else {
759 /* update subtree header */
760 proto_item_append_text(sub_item, "[%u]: NULL", u32Idx);
761 proto_item_set_len(sub_item, offset - u32SubStart);
764 u32Idx++;
767 return u32VariableOffset;
771 /* dissect DCOM "this" (start of every DCOM request) */
773 dissect_dcom_this(tvbuff_t *tvb, int offset,
774 packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep)
776 uint16_t u16VersionMajor;
777 uint16_t u16VersionMinor;
778 uint32_t u32Flags;
779 uint32_t u32Res;
780 e_guid_t uuidCausality;
781 proto_item *sub_item;
782 proto_tree *sub_tree;
783 uint32_t u32SubStart;
784 proto_item *pi;
786 sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
787 "DCOM, ORPCThis");
788 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_this);
790 offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, sub_tree, di, drep,
791 &u16VersionMajor, &u16VersionMinor);
792 u32SubStart = offset - 4;
794 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
795 hf_dcom_this_flags, &u32Flags);
796 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
797 hf_dcom_this_res, &u32Res);
799 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
800 hf_dcom_this_cid, &uuidCausality);
802 offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep);
804 /* update subtree header */
805 proto_item_append_text(sub_item, ", V%u.%u, Causality ID: %s",
806 u16VersionMajor, u16VersionMinor, guids_resolve_guid_to_str(&uuidCausality, pinfo->pool));
807 proto_item_set_len(sub_item, offset - u32SubStart);
809 if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
810 pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
811 (e_guid_t *) &di->call_data->object_uuid,
812 "Object UUID/IPID: %s", guids_resolve_guid_to_str(&di->call_data->object_uuid, pinfo->pool));
813 proto_item_set_generated(pi);
816 return offset;
820 /* dissect DCOM "that" (start of every DCOM response) */
822 dissect_dcom_that(tvbuff_t *tvb, int offset,
823 packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep) {
824 uint32_t u32Flags;
825 proto_item *sub_item;
826 proto_tree *sub_tree;
827 uint32_t u32SubStart;
828 proto_item *pi;
830 sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
831 "DCOM, ORPCThat");
832 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_that);
834 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
835 hf_dcom_that_flags, &u32Flags);
836 u32SubStart = offset - 4;
838 offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep);
840 /* update subtree header */
841 proto_item_set_len(sub_item, offset - u32SubStart);
843 if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
844 pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
845 (e_guid_t *) &di->call_data->object_uuid,
846 "Object UUID/IPID: %s", guids_resolve_guid_to_str(&di->call_data->object_uuid, pinfo->pool));
847 proto_item_set_generated(pi);
850 return offset;
854 /* dissect simple dcom request, DCOM "this" only */
856 dissect_dcom_simple_rqst(tvbuff_t *tvb, int offset,
857 packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep)
860 offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep);
862 return offset;
866 /* dissect simple dcom response, DCOM "that" and returned HRESULT only */
868 dissect_dcom_simple_resp(tvbuff_t *tvb, int offset,
869 packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep)
871 uint32_t u32HResult;
874 offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);
876 offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
877 &u32HResult);
879 col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
880 val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
883 return offset;
887 /* dissect a dcerpc array size */
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)
894 /* en-/disable this by preference setting */
895 if (!dcom_prefs_display_unmarshalling_details) {
896 /* this will read in the data, but prevent output to tree */
897 tree = NULL;
900 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
901 hf_dcom_array_size, pu32ArraySize);
903 return offset;
907 /* dissect a dcerpc pointer value */
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)
913 /* en-/disable this by preference setting */
914 if (!dcom_prefs_display_unmarshalling_details) {
915 /* this will read in the data, but prevent output to tree */
916 tree = NULL;
919 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
920 hf_dcom_pointer_val, pu32Pointer);
922 return offset;
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)
932 proto_item *item;
935 item = proto_tree_add_item(tree, hf_dcom_tobedone, tvb, offset, length, ENC_NA);
936 proto_item_set_generated(item);
937 expert_add_info(pinfo, item, &ei_dcom_dissection_incomplete);
939 offset += length;
941 return offset;
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)
951 proto_item *item;
954 item = proto_tree_add_item(tree, hf_dcom_nospec, tvb, offset, length, ENC_NA);
955 proto_item_set_generated(item);
956 expert_add_info(pinfo, item, &ei_dcom_no_spec);
958 offset += length;
960 return offset;
964 /* dissect an indexed WORD, something like: "FieldName[1]: 0x1234" */
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)
970 uint16_t u16WORD;
973 /* dissect the WORD, but don't add to tree */
974 dissect_dcom_WORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
975 hfindex, &u16WORD);
977 if (tree) {
978 /* special formatted output of indexed value */
979 proto_tree_add_uint_format(tree, hfindex, tvb, offset, 2, u16WORD,
980 "%s[%u]: 0x%04x",
981 proto_registrar_get_name(hfindex),
982 field_index, u16WORD);
985 offset += 2;
987 if (pu16WORD)
988 *pu16WORD = u16WORD;
990 return offset;
994 /* dissect an indexed DWORD, something like: "FieldName[1]: 0x12345678" */
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)
1000 uint32_t u32DWORD;
1003 /* dissect the DWORD, but don't add to tree */
1004 dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1005 hfindex, &u32DWORD);
1007 if (tree) {
1008 /* special formatted output of indexed value */
1009 proto_tree_add_uint_format(tree, hfindex, tvb, offset, 4, u32DWORD,
1010 "%s[%u]: 0x%08x",
1011 proto_registrar_get_name(hfindex),
1012 field_index, u32DWORD);
1015 offset += 4;
1017 if (pu32DWORD)
1018 *pu32DWORD = u32DWORD;
1020 return offset;
1024 /* dissect hresult field of a usual DCOM call (create "raw" item) */
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)
1030 uint32_t u32HResult;
1032 /* dissect the DWORD, but don't add to tree */
1033 offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1034 field_index, &u32HResult);
1036 if (tree) {
1037 /* special formatted output of indexed value */
1038 *item = proto_tree_add_item (tree, field_index, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
1041 if (pu32HResult)
1042 *pu32HResult = u32HResult;
1044 return offset;
1048 /* dissect hresult field of a usual DCOM call (separate method, because often used) */
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)
1054 uint32_t u32HResult;
1055 proto_item *item = NULL;
1057 /* dissect the DWORD, but don't add to tree */
1058 offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1059 hf_dcom_hresult, &u32HResult);
1061 if (tree) {
1062 /* special formatted output of indexed value */
1063 item = proto_tree_add_item (tree, hf_dcom_hresult, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
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 if(u32HResult & 0x80000000) {
1069 expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s",
1070 val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
1072 if (pu32HResult)
1073 *pu32HResult = u32HResult;
1075 return offset;
1079 /* partial results of indexed DCOM subcalls (e.g.: from a kind of array) */
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)
1085 uint32_t u32HResult;
1086 proto_item *item = NULL;
1089 /* dissect the DWORD, but don't add to tree */
1090 offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1091 hf_dcom_hresult, &u32HResult);
1093 if (tree) {
1094 /* special formatted output of indexed value */
1095 item = proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset-4, 4, u32HResult,
1096 "HResult[%u]: %s (0x%08x)", field_index,
1097 val_to_str_const(u32HResult, dcom_hresult_vals, "Unknown"),
1098 u32HResult);
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 if(u32HResult & 0x80000000) {
1103 expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s",
1104 val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
1106 if (pu32HResult)
1107 *pu32HResult = u32HResult;
1109 return offset;
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)
1120 offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1121 hf_dcom_version_major, pu16VersionMajor);
1122 offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1123 hf_dcom_version_minor, pu16VersionMinor);
1125 return offset;
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)
1133 uint32_t u32Dims;
1134 uint16_t u16Dims;
1135 uint16_t u16Features;
1136 uint32_t u32ElementSize;
1137 uint32_t u32VarType;
1138 uint32_t u32Elements;
1139 uint32_t u32Pointer;
1140 uint32_t u32BoundElements;
1141 uint32_t u32LowBound;
1142 char cData[100];
1143 uint32_t u32ArraySize;
1144 uint32_t u32VariableOffset;
1145 uint32_t u32Data;
1146 uint16_t u16Data;
1147 uint8_t u8Data;
1148 uint16_t u16Locks;
1149 uint16_t u16VarType;
1150 proto_item *sub_item;
1151 proto_tree *sub_tree;
1152 uint32_t u32SubStart;
1153 uint32_t u32TmpOffset;
1155 static int * const features[] = {
1156 &hf_dcom_sa_features_variant,
1157 &hf_dcom_sa_features_dispatch,
1158 &hf_dcom_sa_features_unknown,
1159 &hf_dcom_sa_features_bstr,
1160 &hf_dcom_sa_features_have_vartype,
1161 &hf_dcom_sa_features_have_iid,
1162 &hf_dcom_sa_features_record,
1163 &hf_dcom_sa_features_fixedsize,
1164 &hf_dcom_sa_features_embedded,
1165 &hf_dcom_sa_features_static,
1166 &hf_dcom_sa_features_auto,
1167 NULL
1171 /* XXX: which alignment do we need here? */
1173 sub_item = proto_tree_add_item(tree, hf_dcom_safearray, tvb, offset, 0, ENC_NA);
1174 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_safearray);
1175 u32SubStart = offset;
1177 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1178 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1180 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1181 hf_dcom_sa_dims32, &u32Dims);
1182 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1183 hf_dcom_sa_dims16, &u16Dims);
1185 /* feature flags */
1186 u32TmpOffset = dissect_dcom_WORD(tvb, offset, pinfo, NULL, di, drep, -1, &u16Features);
1188 proto_tree_add_bitmask_value_with_flags(sub_tree, tvb, offset, hf_dcom_sa_features,
1189 ett_dcom_sa_features, features, u16Features, BMT_NO_APPEND);
1190 offset = u32TmpOffset;
1192 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1193 hf_dcom_sa_element_size, &u32ElementSize);
1194 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1195 hf_dcom_sa_locks, &u16Locks);
1196 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1197 hf_dcom_sa_vartype16, &u16VarType);
1198 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1199 hf_dcom_sa_vartype32, &u32VarType);
1200 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1201 hf_dcom_sa_elements, &u32Elements);
1202 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1204 u32BoundElements = 0;
1205 while(u32Dims--) {
1206 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1207 hf_dcom_sa_bound_elements, &u32BoundElements);
1208 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1209 hf_dcom_sa_low_bound, &u32LowBound);
1212 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize);
1214 tvb_ensure_bytes_exist(tvb, offset, u32ArraySize * u32ElementSize);
1215 u32VariableOffset = offset + u32ArraySize * u32ElementSize;
1217 if(sacb) {
1218 sacb(tvb, offset, pinfo, tree, di, drep, u32VarType, u32ArraySize);
1221 while(u32ArraySize--) {
1222 switch(u32VarType) {
1223 case(WIRESHARK_VT_ERROR):
1224 offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
1225 &u32Data);
1226 break;
1227 case(WIRESHARK_VT_I1):
1228 offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1229 hf_dcom_vt_i1, &u8Data);
1230 break;
1231 case(WIRESHARK_VT_I2):
1232 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1233 hf_dcom_vt_i2, &u16Data);
1234 break;
1235 case(WIRESHARK_VT_I4):
1236 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1237 hf_dcom_vt_i4, &u32Data);
1238 break;
1239 case(WIRESHARK_VT_I8):
1240 offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
1241 hf_dcom_vt_i8, NULL);
1242 /* take care of the 8 byte alignment */
1243 u32VariableOffset = offset;
1244 break;
1245 case(WIRESHARK_VT_BSTR):
1246 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1247 if (u32Pointer) {
1248 u32VariableOffset = dissect_dcom_BSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
1249 hf_dcom_vt_bstr, cData, sizeof(cData) );
1251 break;
1252 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
1260 u32VariableOffset = dissect_dcom_tobedone_data(tvb, u32VariableOffset, pinfo, sub_tree, drep,
1261 10000);
1265 /* update subtree header */
1266 proto_item_append_text(sub_item, ": Elements: %u/%u VarType: %s",
1267 u32Elements, u32BoundElements,
1268 val_to_str(u32VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
1270 proto_item_set_len(sub_item, u32VariableOffset - u32SubStart);
1272 return u32VariableOffset;
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)
1283 offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1284 hf_dcom_variant_type, pu16VarType);
1286 return offset;
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)
1295 uint32_t u32Size;
1296 uint32_t u32RPCRes;
1297 uint16_t u16Res;
1298 uint32_t u32SubStart;
1299 proto_item *sub_item;
1300 proto_tree *sub_tree;
1301 uint16_t u16VarType;
1302 uint32_t u32VarType;
1304 uint8_t u8Data;
1305 uint16_t u16Data;
1306 uint32_t u32Data;
1307 uint64_t u64Data;
1308 int64_t cyData;
1309 char cData[500];
1310 uint32_t u32Pointer;
1311 float f32Data;
1312 double f64Data;
1315 /* alignment of 8 needed for a VARIANT */
1316 if (offset % 8) {
1317 offset += 8 - (offset % 8);
1320 sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
1321 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_variant);
1322 u32SubStart = offset;
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 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1331 hf_dcom_variant_size, &u32Size);
1332 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1333 hf_dcom_variant_rpc_res, &u32RPCRes);
1334 offset = dissect_dcom_VARTYPE(tvb, offset, pinfo, sub_tree, di, drep,
1335 &u16VarType);
1336 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1337 hf_dcom_variant_wres, &u16Res);
1338 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1339 hf_dcom_variant_wres, &u16Res);
1340 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1341 hf_dcom_variant_wres, &u16Res);
1343 /* 32 bit VarType (slightly different to the 16 bit one) */
1344 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1345 hf_dcom_variant_type32, &u32VarType);
1347 if (u32VarType & WIRESHARK_VT_BYREF) {
1348 u32VarType &=~WIRESHARK_VT_BYREF;
1349 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1352 increment_dissection_depth(pinfo);
1353 switch (u32VarType) {
1354 case(WIRESHARK_VT_EMPTY):
1355 break;
1356 case(WIRESHARK_VT_BOOL):
1357 offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, sub_tree, di, drep,
1358 hf_dcom_vt_bool, &u16Data);
1359 break;
1360 case(WIRESHARK_VT_I1):
1361 offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1362 hf_dcom_vt_i1, &u8Data);
1363 break;
1364 case(WIRESHARK_VT_UI1):
1365 offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1366 hf_dcom_vt_ui1, &u8Data);
1367 break;
1368 case(WIRESHARK_VT_I2):
1369 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1370 hf_dcom_vt_i2, &u16Data);
1371 break;
1372 case(WIRESHARK_VT_UI2):
1373 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1374 hf_dcom_vt_ui2, &u16Data);
1375 break;
1376 case(WIRESHARK_VT_I4):
1377 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1378 hf_dcom_vt_i4, &u32Data);
1379 break;
1380 case(WIRESHARK_VT_I8):
1381 offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
1382 hf_dcom_vt_i8, &u64Data);
1383 break;
1384 case(WIRESHARK_VT_CY):
1385 offset = dissect_dcom_I8(tvb, offset, pinfo, NULL, di, drep,
1386 0, &cyData);
1387 proto_tree_add_int64_format(sub_tree, hf_dcom_vt_cy, tvb, offset - 8,
1388 8, cyData, "%s: %" PRId64 ".%.04" PRId64,
1389 proto_registrar_get_name(hf_dcom_vt_cy),
1390 cyData / 10000, ABS(cyData % 10000));
1391 break;
1392 case(WIRESHARK_VT_UI4):
1393 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1394 hf_dcom_vt_ui4, &u32Data);
1395 break;
1396 case(WIRESHARK_VT_UI8):
1397 offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
1398 hf_dcom_vt_ui8, &u64Data);
1399 break;
1400 case(WIRESHARK_VT_R4):
1401 offset = dissect_dcom_FLOAT(tvb, offset, pinfo, sub_tree, di, drep,
1402 hf_dcom_vt_r4, &f32Data);
1403 break;
1404 case(WIRESHARK_VT_R8):
1405 offset = dissect_dcom_DOUBLE(tvb, offset, pinfo, sub_tree, di, drep,
1406 hf_dcom_vt_r8, &f64Data);
1407 break;
1408 case(WIRESHARK_VT_DATE):
1409 offset = dissect_dcom_DATE(tvb, offset, pinfo, sub_tree, di, drep,
1410 hf_dcom_vt_date, &f64Data);
1411 break;
1412 case(WIRESHARK_VT_BSTR):
1413 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1414 if (u32Pointer) {
1415 offset = dissect_dcom_BSTR(tvb, offset, pinfo, sub_tree, di, drep,
1416 hf_dcom_vt_bstr, cData, sizeof(cData) );
1418 break;
1419 case(WIRESHARK_VT_DISPATCH):
1420 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1421 if (u32Pointer) {
1422 offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, sub_tree, di, drep,
1423 hf_dcom_vt_dispatch, NULL); /* XXX - how to handle this? */
1425 break;
1426 case(WIRESHARK_VT_ARRAY):
1427 offset = dissect_dcom_SAFEARRAY(tvb, offset, pinfo, sub_tree, di, drep,
1428 0, NULL);
1429 break;
1430 case(WIRESHARK_VT_ERROR):
1431 offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
1433 break;
1434 case(WIRESHARK_VT_VARIANT):
1435 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1436 if (u32Pointer) {
1437 offset = dissect_dcom_VARIANT(tvb, offset, pinfo, sub_tree, di, drep,
1438 hf_dcom_vt_byref /* must be BYREF */);
1440 break;
1441 case(WIRESHARK_VT_UNKNOWN):
1442 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1443 break;
1444 default:
1445 /* XXX: add more types here! */
1446 offset = dissect_dcom_tobedone_data(tvb, offset, pinfo, sub_tree, drep,
1447 10000);
1449 decrement_dissection_depth(pinfo);
1451 /* update subtree header */
1452 proto_item_append_text(sub_item, ": %s",
1453 val_to_str(u16VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
1455 proto_item_set_len(sub_item, offset - u32SubStart);
1457 return offset;
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)
1466 const char *uuid_name;
1467 header_field_info *hfi;
1468 e_guid_t uuid;
1471 /* get the UUID, but don't put it into the tree */
1472 offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep,
1473 hfindex, &uuid);
1475 /* add to the tree */
1476 hfi = proto_registrar_get_nth(hfindex);
1477 uuid_name = guids_get_uuid_name(&uuid, pinfo->pool);
1478 if(uuid_name) {
1479 proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
1480 "%s: %s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
1481 hfi->name, uuid_name,
1482 uuid.data1, uuid.data2, uuid.data3,
1483 uuid.data4[0], uuid.data4[1],
1484 uuid.data4[2], uuid.data4[3],
1485 uuid.data4[4], uuid.data4[5],
1486 uuid.data4[6], uuid.data4[7]);
1487 } else {
1488 proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
1489 "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1490 hfi->name,
1491 uuid.data1, uuid.data2, uuid.data3,
1492 uuid.data4[0], uuid.data4[1],
1493 uuid.data4[2], uuid.data4[3],
1494 uuid.data4[4], uuid.data4[5],
1495 uuid.data4[6], uuid.data4[7]);
1498 if(pdata != NULL) {
1499 *pdata = uuid;
1502 return offset;
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)
1511 const char *uuid_name;
1512 proto_item *pi;
1513 header_field_info *hfi;
1516 /* XXX - this is far from being performance optimized! */
1518 /* get the UUID, but don't put it into the tree */
1519 offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep,
1520 hfindex, uuid);
1522 /* look for a registered uuid name */
1523 uuid_name = guids_get_uuid_name(uuid, pinfo->pool);
1525 /* add to the tree */
1526 hfi = proto_registrar_get_nth(hfindex);
1527 pi = proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) uuid, "%s", hfi->name);
1529 if (field_index != -1) {
1530 proto_item_append_text(pi, "[%u]: ", field_index);
1531 } else {
1532 proto_item_append_text(pi, ": ");
1535 if(uuid_name) {
1536 proto_item_append_text(pi, "%s (", uuid_name);
1539 proto_item_append_text(pi, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1540 uuid->data1, uuid->data2, uuid->data3,
1541 uuid->data4[0], uuid->data4[1],
1542 uuid->data4[2], uuid->data4[3],
1543 uuid->data4[4], uuid->data4[5],
1544 uuid->data4[6], uuid->data4[7]);
1546 if(uuid_name) {
1547 proto_item_append_text(pi, ")");
1550 /* update column info now */
1551 if (field_index != -1) {
1552 col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]=%s",
1553 hfi->name, field_index, (uuid_name) ? uuid_name : "???");
1554 } else {
1555 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%s",
1556 hfi->name, (uuid_name) ? uuid_name : "???");
1559 return offset;
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)
1569 uint32_t u32Idx;
1570 uint32_t u32IdxA;
1571 uint32_t u32IdxW;
1572 uint32_t inLengthWithoutNullDelimiter = 0;
1574 uint8_t u8Tmp1;
1575 uint8_t u8Tmp2;
1578 *isPrintable = true;
1579 inLengthWithoutNullDelimiter = inLength == 0 ? 0 : inLength -1;
1581 /* we must have at least the space for the zero termination */
1582 DISSECTOR_ASSERT(outLength >= 1);
1584 /* determine length and printablility of the string */
1585 for(u32Idx = 0; u32Idx < inLengthWithoutNullDelimiter; u32Idx+=2) {
1586 /* the marshalling direction of a WCHAR is fixed! */
1587 u8Tmp1 = tvb_get_uint8(tvb, offset+u32Idx);
1588 u8Tmp2 = tvb_get_uint8(tvb, offset+u32Idx+1);
1590 /* is this the zero termination? */
1591 if (u8Tmp1 == 0 && u8Tmp2 == 0) {
1592 u32Idx+=2;
1593 break;
1596 /* is this character printable? */
1597 /* 10 = New Line, 13 = Carriage Return */
1598 /* XXX - there are probably more printable chars than isprint() */
1599 if(!(g_ascii_isprint(u8Tmp1) || u8Tmp1 == 10 || u8Tmp1 == 13)|| u8Tmp2 != 0) {
1600 *isPrintable = false;
1604 /* u32Idx now contains the string length in bytes */
1605 /* (including optional zero termination) */
1607 /* if this is a printable string? */
1608 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 for(u32IdxA = 0, u32IdxW = 0;
1612 u32IdxW < u32Idx && u32IdxA < outLength-2;
1613 u32IdxW+=2, u32IdxA++) {
1614 pszStr[u32IdxA] = tvb_get_uint8(tvb, offset+u32IdxW);
1616 } else {
1617 /* convert to hexdump */
1618 for(u32IdxA = 0, u32IdxW = 0;
1619 u32IdxW < u32Idx && u32IdxA < outLength-2;
1620 u32IdxW++, u32IdxA+=2) {
1621 snprintf(&pszStr[u32IdxA], 3, "%02X", tvb_get_uint8(tvb, offset+u32IdxW));
1625 /* zero terminate the string, space must be available */
1626 DISSECTOR_ASSERT(u32IdxA < outLength);
1627 pszStr[u32IdxA] = 0;
1629 return offset + u32Idx;
1633 /* dissect a LPWSTR into a given buffer */
1634 /* use FT_STRING for hfindex */
1635 /* u32MaxStr is maximum length of string (including trailing zero) */
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)
1641 uint32_t u32MaxCount;
1642 uint32_t u32Offset;
1643 uint32_t u32ArraySize;
1644 uint32_t u32StrStart;
1645 proto_item *sub_item;
1646 proto_tree *sub_tree;
1647 uint32_t u32SubStart;
1648 bool isPrintable;
1651 /* alignment of 4 needed */
1652 if (offset % 4) {
1653 offset += 4 - (offset % 4);
1656 /* add subtree item */
1657 sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
1658 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
1659 u32SubStart = offset;
1661 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1662 hf_dcom_max_count, &u32MaxCount);
1663 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1664 hf_dcom_offset, &u32Offset);
1665 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep,
1666 &u32ArraySize);
1668 u32StrStart = offset;
1669 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1671 proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszStr);
1673 /* update subtree header */
1674 if (field_index != -1) {
1675 proto_item_set_text(sub_item, "%s[%u]: %s%s%s",
1676 proto_registrar_get_name(hfindex),
1677 field_index,
1678 isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1679 } else {
1680 proto_item_append_text(sub_item, "%s%s%s",
1681 isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1683 proto_item_set_len(sub_item, offset - u32SubStart);
1685 return offset;
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)
1696 return dissect_dcom_indexed_LPWSTR(tvb, offset, pinfo, tree, di, drep,
1697 hfindex, pszStr, u32MaxStr, -1);
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) */
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)
1709 uint32_t u32MaxCount;
1710 uint32_t u32ArraySize;
1711 int strStart, subStart, realOffset;
1712 proto_item *sub_item;
1713 proto_tree *sub_tree;
1714 uint32_t u32ByteLength;
1715 bool isPrintable;
1717 /* alignment of 4 needed */
1718 if (offset % 4) {
1719 offset += 4 - (offset % 4);
1722 /* add subtree item */
1723 sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
1724 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
1725 subStart = offset;
1727 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1728 hf_dcom_max_count, &u32MaxCount);
1729 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1730 hf_dcom_byte_length, &u32ByteLength);
1731 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep,
1732 &u32ArraySize);
1734 if ((uint32_t)offset + u32ArraySize*2 > INT_MAX) {
1735 pszStr[0] = 0;
1736 return offset;
1739 realOffset = offset + u32ArraySize*2;
1741 strStart = offset;
1742 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1744 proto_tree_add_string(sub_tree, hfindex, tvb, strStart, offset - strStart, pszStr);
1746 /* update subtree header */
1747 proto_item_append_text(sub_item, "%s%s%s",
1748 isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1749 if (realOffset <= subStart) {
1750 /* XXX - expert info */
1751 return offset;
1753 proto_item_set_len(sub_item, realOffset - subStart);
1755 return realOffset;
1759 /* dissect an DUALSTRINGARRAY */
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)
1764 uint16_t u16NumEntries;
1765 uint16_t u16SecurityOffset;
1766 char szStr[1000];
1767 uint32_t u32MaxStr = sizeof(szStr);
1768 uint32_t u32Start;
1769 uint16_t u16TowerId;
1770 uint16_t u16SecurityAuthnSvc;
1771 uint16_t u16SecurityAuthzSvc;
1772 proto_item *sub_item;
1773 proto_tree *sub_tree;
1774 uint32_t u32SubStart;
1775 uint32_t u32StringBindings = 0;
1776 uint32_t u32SecurityBindings = 0;
1777 proto_item *subsub_item;
1778 proto_tree *subsub_tree;
1779 uint32_t u32SubSubStart;
1780 bool isPrintable;
1781 uint32_t first_ip = 0;
1782 uint32_t curr_ip = 0;
1783 uint32_t ipaddr;
1784 proto_item *pi;
1787 /* add subtree header */
1788 sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
1789 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_dualstringarray);
1791 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1792 hf_dcom_dualstringarray_num_entries, &u16NumEntries);
1793 /* from here, alignment is ok */
1794 u32SubStart = offset - 2;
1795 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1796 hf_dcom_dualstringarray_security_offset, &u16SecurityOffset);
1798 /* STRINGBINDINGs until first wchar zero */
1799 while ( tvb_get_ntohs(tvb, offset) ) {
1800 u32StringBindings++;
1802 subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_string, tvb, offset, 0, ENC_NA);
1803 subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
1804 u32SubSubStart = offset;
1806 offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1807 hf_dcom_dualstringarray_string_tower_id, &u16TowerId);
1808 u32Start = offset;
1809 /* we don't know the (zero terminated) input length, use the buffer length instead */
1810 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
1811 pi = proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_string_network_addr,
1812 tvb, u32Start, offset - u32Start, szStr);
1814 /* convert ip address (if it is dotted decimal) */
1815 /* XXX - this conversion is ugly */
1816 if (ws_inet_pton4(szStr, &ipaddr)) {
1817 if(get_host_ipaddr(szStr, &curr_ip)) {
1819 /*expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "DUALSTRINGARRAY: IP:%s",
1820 ip_to_str( (uint8_t *) &curr_ip));*/
1822 if(first_ip == 0) {
1823 if(ip != NULL) {
1824 memcpy(ip, &curr_ip, sizeof(curr_ip));
1826 first_ip = curr_ip;
1827 } else {
1828 if(first_ip != curr_ip) {
1829 address first_ip_addr, curr_ip_addr;
1831 set_address(&first_ip_addr, AT_IPv4, 4, &first_ip);
1832 set_address(&curr_ip_addr, AT_IPv4, 4, &curr_ip);
1833 expert_add_info_format(pinfo, pi, &ei_dcom_dualstringarray_mult_ip,
1834 "DUALSTRINGARRAY: multiple IP's %s %s",
1835 address_to_str(pinfo->pool, &first_ip_addr), address_to_str(pinfo->pool, &curr_ip_addr));
1841 proto_item_append_text(subsub_item, "[%u]: TowerId=%s, NetworkAddr=\"%s\"",
1842 u32StringBindings,
1843 val_to_str(u16TowerId, dcom_protseq_vals, "Unknown (0x%04x"),
1844 szStr);
1845 proto_item_set_len(subsub_item, offset - u32SubSubStart);
1847 offset += 2;
1849 /* SECURITYBINDINGs until first wchar zero */
1850 while ( tvb_get_ntohs(tvb, offset) ) {
1851 u32SecurityBindings++;
1853 subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_security, tvb, offset, 0, ENC_NA);
1854 subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
1855 u32SubSubStart = offset;
1857 offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1858 hf_dcom_dualstringarray_security_authn_svc,
1859 &u16SecurityAuthnSvc);
1860 offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1861 hf_dcom_dualstringarray_security_authz_svc,
1862 &u16SecurityAuthzSvc);
1864 u32Start = offset;
1865 /* we don't know the (zero terminated) input length, use the buffer length instead */
1866 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
1867 proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_security_princ_name,
1868 tvb, u32Start, offset - u32Start, szStr);
1870 proto_item_append_text(subsub_item, "[%u]: AuthnSvc=0x%04x, AuthzSvc=0x%04x, PrincName=\"%s\"",
1871 u32SecurityBindings, u16SecurityAuthnSvc, u16SecurityAuthzSvc, szStr);
1872 proto_item_set_len(subsub_item, offset - u32SubSubStart);
1874 offset += 2;
1876 /* append info to subtree header */
1877 proto_item_append_text(sub_item, ": STRINGBINDINGs=%u, SECURITYBINDINGs=%u",
1878 u32StringBindings, u32SecurityBindings);
1879 proto_item_set_len(sub_item, offset - u32SubStart);
1881 return offset;
1885 /* dissect an STDOBJREF */
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)
1891 uint32_t u32Flags;
1892 uint32_t u32PublicRefs;
1893 proto_item *sub_item;
1894 proto_tree *sub_tree;
1895 uint32_t u32SubStart;
1898 /* add subtree header */
1899 sub_item = proto_tree_add_item(tree, hf_dcom_stdobjref, tvb, offset, 0, ENC_NA);
1900 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_stdobjref);
1902 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1903 hf_dcom_stdobjref_flags, &u32Flags);
1904 /* from here, alignment is ok */
1905 u32SubStart = offset - 4;
1906 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1907 hf_dcom_stdobjref_public_refs, &u32PublicRefs);
1908 offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep,
1909 hf_dcom_oxid, oxid);
1910 offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep,
1911 hf_dcom_oid, oid);
1912 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
1913 hf_dcom_ipid, ipid);
1915 /* append info to subtree header */
1916 proto_item_append_text(sub_item, ": PublicRefs=%u IPID=%s",
1917 u32PublicRefs, guids_resolve_guid_to_str(ipid, pinfo->pool));
1918 proto_item_set_len(sub_item, offset - u32SubStart);
1920 return offset;
1927 *static void
1928 *print_uuid(const e_guid_t* uuid)
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]);
1937 * return;
1943 dcom_register_routine(dcom_dissect_fn_t routine, e_guid_t* uuid)
1945 dcom_marshaler_t *marshaler;
1948 /* check if exists already */
1949 if (dcom_get_routine_by_uuid(uuid))
1950 return -1;
1952 marshaler = wmem_new(wmem_file_scope(), dcom_marshaler_t);
1953 if (!marshaler) {
1954 /*memory error*/
1955 return -1;
1958 marshaler->parent = NULL;
1959 marshaler->private_data = NULL;
1960 marshaler->uuid = *uuid;
1961 marshaler->routine = routine;
1963 dcom_marshalers = g_list_append(dcom_marshalers, marshaler);
1965 return 0;
1969 dcom_dissect_fn_t
1970 dcom_get_routine_by_uuid(const e_guid_t* uuid)
1972 dcom_marshaler_t *marsh;
1973 GList *marshalers;
1975 if(memcmp(uuid, &uuid_null, sizeof(uuid_null)) == 0) {
1976 return NULL;
1979 for(marshalers = dcom_marshalers; marshalers!= NULL;
1980 marshalers = g_list_next(marshalers)) {
1981 marsh = (dcom_marshaler_t *)marshalers->data;
1982 /*print_uuid(&marsh->uuid);*/
1983 /*print_uuid(uuid);*/
1984 if(memcmp(&marsh->uuid, uuid, sizeof(e_guid_t)) == 0) {
1985 return marsh->routine;
1989 return NULL;
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)
1998 uint32_t u32CBExtension;
1999 uint32_t u32Size;
2000 uint32_t u32SubStart;
2001 proto_item *sub_item;
2002 proto_tree *sub_tree;
2003 dcom_dissect_fn_t routine = NULL;
2006 /* add subtree header */
2007 hfindex = hf_dcom_custobjref;
2008 sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_NA);
2009 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_custobjref);
2011 u32SubStart = offset;
2012 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2013 hf_dcom_clsid, clsid);
2014 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2015 hf_dcom_objref_cbextension, &u32CBExtension);
2016 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2017 hf_dcom_objref_size, &u32Size);
2019 /* the following data depends on the iid, get the routine by iid */
2020 routine = dcom_get_routine_by_uuid(iid);
2021 if (routine){
2022 offset = routine(tvb, offset, pinfo, sub_tree, di, drep, u32Size);
2025 /* append info to subtree header */
2026 /* proto_item_append_text(sub_item, ": ActivationPropertiesIn"); */
2027 proto_item_set_len(sub_item, offset - u32SubStart);
2029 return offset;
2032 /* dissect an OBJREF */
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)
2037 uint32_t u32Signature;
2038 uint32_t u32Flags;
2039 e_guid_t iid;
2040 e_guid_t clsid;
2041 proto_item *sub_item;
2042 proto_tree *sub_tree;
2043 uint32_t u32SubStart;
2044 uint64_t oxid = 0;
2045 uint64_t oid = 0;
2046 e_guid_t ipid;
2047 dcom_interface_t *dcom_if = NULL;
2048 char ip[4];
2050 memset(&ipid, 0, sizeof(ipid));
2051 memset(ip, 0, sizeof(ip));
2053 /* add subtree header */
2054 sub_item = proto_tree_add_item(tree, hf_dcom_objref, tvb, offset, 0, ENC_NA);
2055 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_objref);
2057 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2058 hf_dcom_objref_signature, &u32Signature);
2059 /* from here, alignment is ok */
2060 u32SubStart = offset - 4;
2061 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2062 hf_dcom_objref_flags, &u32Flags);
2063 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2064 hf_dcom_iid, &iid);
2066 switch(u32Flags) {
2067 case(0x1): /* standard */
2068 offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2069 &oxid, &oid, &ipid);
2070 offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep,
2071 hf_dcom_objref_resolver_address, ip);
2072 break;
2073 case(0x2): /* handler (untested) */
2074 offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2075 &oxid, &oid, &iid);
2076 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2077 hf_dcom_clsid, &clsid);
2078 offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep,
2079 hf_dcom_objref_resolver_address, ip);
2080 break;
2081 case(0x4): /* custom */
2082 offset = dissect_dcom_CUSTOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2083 &clsid, &iid);
2084 break;
2087 if(u32Flags == 0x1 || u32Flags == 0x2) {
2088 /* add interface instance to database (we currently only handle IPv4) */
2089 if(pinfo->net_src.type == AT_IPv4) {
2090 address addr;
2092 set_address(&addr, AT_IPv4, 4, ip);
2093 dcom_if = dcom_interface_new(pinfo,
2094 &addr,
2095 &iid, oxid, oid, &ipid);
2099 if(interf != NULL) {
2100 *interf = dcom_if;
2103 /* append info to subtree header */
2104 proto_item_set_len(sub_item, offset - u32SubStart);
2106 return offset;
2109 /* dissect an MInterfacePointer */
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)
2114 uint32_t u32CntData;
2115 uint32_t u32ArraySize;
2116 proto_item *sub_item;
2117 proto_tree *sub_tree;
2118 uint32_t u32SubStart;
2121 if (!hfindex) {
2122 hfindex = hf_dcom_interface_pointer;
2125 /* add subtree header */
2126 sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
2127 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_interface_pointer);
2129 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize);
2130 u32SubStart = offset - 4; /* should use this trick to deal with align pad if any */
2132 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2133 hf_dcom_ip_cnt_data, &u32CntData);
2135 offset = dissect_dcom_OBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex, interf);
2137 /* append info to subtree header */
2138 proto_item_set_len(sub_item, offset - u32SubStart);
2140 return offset;
2143 /* dissect a pointer to a MInterfacePointer */
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)
2148 uint32_t u32Pointer;
2151 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
2153 if (u32Pointer) {
2154 offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, di, drep, hfindex, interf);
2155 } else {
2156 if(interf != NULL) {
2157 *interf = NULL;
2161 return offset;
2164 static void dcom_cleanup(void) {
2165 if (dcom_machines != NULL) {
2166 GList *machines;
2168 for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
2169 dcom_machine_t *machine = (dcom_machine_t *)machines->data;
2171 if (machine->objects != NULL) {
2172 GList *objects;
2173 for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
2174 dcom_object_t *object = (dcom_object_t *)objects->data;
2176 if (object->interfaces != NULL) {
2177 GList *interface;
2178 for(interface = object->interfaces; interface != NULL; interface = g_list_next(interface)) {
2179 g_free(interface->data);
2180 interface->data = NULL; /* for good measure */
2182 g_list_free(object->interfaces);
2183 object->interfaces = NULL; /* for good measure */
2186 g_free(objects->data);
2187 objects->data = NULL; /* for good measure */
2189 g_list_free(machine->objects);
2190 free_address(&machine->ip);
2191 machine->objects = NULL; /* for good measure */
2194 g_free(machines->data);
2195 machines->data = NULL; /* for good measure */
2197 g_list_free(dcom_machines);
2198 dcom_machines = NULL;
2201 /* The data in dcom_interfaces is wmem_file_scoped so there's no need to free
2202 * the data pointers.
2204 if (dcom_interfaces != NULL) {
2205 g_list_free(dcom_interfaces);
2206 dcom_interfaces = NULL;
2209 /* The data in dcom_marshalers is wmem_file_scoped so there's no need to free
2210 * the data pointers.
2212 if (dcom_marshalers != NULL) {
2213 g_list_free(dcom_marshalers);
2214 dcom_marshalers = NULL;
2218 void
2219 proto_register_dcom (void)
2221 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 { &hf_dcom_this_flags,
2231 { "Flags", "dcom.this.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }},
2232 { &hf_dcom_this_res,
2233 { "Reserved", "dcom.this.res", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2234 { &hf_dcom_this_cid,
2235 { "Causality ID", "dcom.this.uuid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2238 static hf_register_info hf_dcom_that_array[] = {
2239 { &hf_dcom_that_flags,
2240 { "Flags", "dcom.that.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }}
2243 static hf_register_info hf_dcom_extent_array[] = {
2244 { &hf_dcom_extent,
2245 { "Extension", "dcom.extent", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2246 { &hf_dcom_extent_array_count,
2247 { "Extension Count", "dcom.extent.array_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2248 { &hf_dcom_extent_array_res,
2249 { "Reserved", "dcom.extent.array_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2250 { &hf_dcom_extent_size,
2251 { "Extension Size", "dcom.extent.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2252 { &hf_dcom_extent_id,
2253 { "Extension Id", "dcom.extent.id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2256 static hf_register_info hf_dcom_array[] = {
2257 { &hf_dcom_version_major,
2258 { "VersionMajor", "dcom.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2259 { &hf_dcom_version_minor,
2260 { "VersionMinor", "dcom.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2261 { &hf_dcom_hresult,
2262 { "HResult", "dcom.hresult", FT_UINT32, BASE_HEX, VALS(dcom_hresult_vals), 0x0, NULL, HFILL }},
2263 { &hf_dcom_max_count,
2264 { "MaxCount", "dcom.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2265 { &hf_dcom_offset,
2266 { "Offset", "dcom.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2267 { &hf_dcom_byte_length,
2268 { "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 { &hf_dcom_tobedone,
2274 { "To Be Done", "dcom.tobedone", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2275 { &hf_dcom_nospec,
2276 { "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 { &hf_dcom_variant_type,
2282 { "VarType", "dcom.variant_type", FT_UINT16, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2283 { &hf_dcom_variant_type32,
2284 { "VarType32", "dcom.variant_type32", FT_UINT32, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2285 { &hf_dcom_variant_size,
2286 { "Size", "dcom.variant_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2287 { &hf_dcom_variant_rpc_res,
2288 { "RPC-Reserved", "dcom.variant_rpc_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2289 { &hf_dcom_variant_wres,
2290 { "Reserved", "dcom.variant_wres", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2291 { &hf_dcom_array_size,
2292 { "(ArraySize)", "dcom.array_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2293 { &hf_dcom_pointer_val,
2294 { "(PointerVal)", "dcom.pointer_val", FT_UINT32, BASE_HEX, VALS(dcom_dcerpc_pointer_vals), 0x0, NULL, HFILL }}
2297 static hf_register_info hf_dcom_interface_pointer_array[] = {
2298 { &hf_dcom_interface_pointer,
2299 { "InterfacePointer", "dcom.ifp", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2300 { &hf_dcom_ip_cnt_data,
2301 { "CntData", "dcom.ip_cnt_data", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
2304 static hf_register_info hf_dcom_objref_array[] = {
2305 { &hf_dcom_objref,
2306 { "OBJREF", "dcom.objref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2307 { &hf_dcom_objref_signature,
2308 { "Signature", "dcom.objref.signature", FT_UINT32, BASE_HEX, VALS(dcom_objref_signature_vals), 0x0, NULL, HFILL }},
2309 { &hf_dcom_objref_flags,
2310 { "Flags", "dcom.objref.flags", FT_UINT32, BASE_HEX, VALS(dcom_objref_flag_vals), 0x0, NULL, HFILL }},
2311 { &hf_dcom_iid,
2312 { "IID", "dcom.iid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2313 { &hf_dcom_clsid,
2314 { "CLSID", "dcom.clsid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2315 { &hf_dcom_objref_resolver_address,
2316 { "ResolverAddress", "dcom.objref.resolver_address", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2317 { &hf_dcom_objref_cbextension,
2318 { "CBExtension", "dcom.objref.cbextension", FT_UINT32, BASE_DEC, NULL, 0x0, "Size of extension data", HFILL }},
2319 { &hf_dcom_objref_size,
2320 { "Size", "dcom.objref.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
2323 static hf_register_info hf_dcom_stdobjref_array[] = {
2324 { &hf_dcom_stdobjref,
2325 { "STDOBJREF", "dcom.stdobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2326 { &hf_dcom_stdobjref_flags,
2327 { "Flags", "dcom.stdobjref.flags", FT_UINT32, BASE_HEX, VALS(dcom_stdobjref_flag_vals), 0x0, NULL, HFILL }},
2328 { &hf_dcom_stdobjref_public_refs,
2329 { "PublicRefs", "dcom.stdobjref.public_refs", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2330 { &hf_dcom_oxid,
2331 { "OXID", "dcom.oxid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2332 { &hf_dcom_oid,
2333 { "OID", "dcom.oid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2334 { &hf_dcom_ipid,
2335 { "IPID", "dcom.ipid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2338 static hf_register_info hf_dcom_custobjref_array[] = {
2339 { &hf_dcom_custobjref,
2340 { "CUSTOMOBJREF", "dcom.custobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2344 static hf_register_info hf_dcom_dualstringarray_array[] = {
2345 { &hf_dcom_dualstringarray_num_entries,
2346 { "NumEntries", "dcom.dualstringarray.num_entries", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2347 { &hf_dcom_dualstringarray_security_offset,
2348 { "SecurityOffset", "dcom.dualstringarray.security_offset", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2349 { &hf_dcom_dualstringarray_string,
2350 { "StringBinding", "dcom.dualstringarray.string", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2351 { &hf_dcom_dualstringarray_string_tower_id,
2352 { "TowerId", "dcom.dualstringarray.tower_id", FT_UINT16, BASE_HEX, VALS(dcom_protseq_vals), 0x0, NULL, HFILL }},
2353 { &hf_dcom_dualstringarray_string_network_addr,
2354 { "NetworkAddr", "dcom.dualstringarray.network_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2355 { &hf_dcom_dualstringarray_security,
2356 { "SecurityBinding", "dcom.dualstringarray.security", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2357 { &hf_dcom_dualstringarray_security_authn_svc,
2358 { "AuthnSvc", "dcom.dualstringarray.security_authn_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authn), 0x0, NULL, HFILL }},
2359 { &hf_dcom_dualstringarray_security_authz_svc,
2360 { "AuthzSvc", "dcom.dualstringarray.security_authz_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authz), 0x0, NULL, HFILL }},
2361 { &hf_dcom_dualstringarray_security_princ_name,
2362 { "PrincName", "dcom.dualstringarray.security_princ_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2365 static hf_register_info hf_dcom_vt_array[] = {
2366 { &hf_dcom_vt_bool,
2367 { "VT_BOOL", "dcom.vt.bool", FT_UINT16, BASE_HEX, VALS(dcom_vt_bool_vals), 0x0, NULL, HFILL }},
2368 { &hf_dcom_vt_i1,
2369 { "VT_I1", "dcom.vt.i1", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2370 { &hf_dcom_vt_i2,
2371 { "VT_I2", "dcom.vt.i2", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2372 { &hf_dcom_vt_i4,
2373 { "VT_I4", "dcom.vt.i4", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2374 { &hf_dcom_vt_i8,
2375 { "VT_I8", "dcom.vt.i8", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2376 { &hf_dcom_vt_cy,
2377 { "VT_CY", "dcom.vt.cy", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2378 { &hf_dcom_vt_ui1,
2379 { "VT_UI1", "dcom.vt.ui1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2380 { &hf_dcom_vt_ui2,
2381 { "VT_UI2", "dcom.vt.ui2", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2382 { &hf_dcom_vt_ui4,
2383 { "VT_UI4", "dcom.vt.ui4", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2384 { &hf_dcom_vt_ui8,
2385 { "VT_UI8", "dcom.vt.ui8", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2386 { &hf_dcom_vt_r4,
2387 { "VT_R4", "dcom.vt.r4", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2388 { &hf_dcom_vt_r8,
2389 { "VT_R8", "dcom.vt.r8", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2390 { &hf_dcom_vt_date,
2391 { "VT_DATE", "dcom.vt.date", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2392 { &hf_dcom_vt_bstr,
2393 { "VT_BSTR", "dcom.vt.bstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2394 { &hf_dcom_vt_byref,
2395 { "BYREF", "dcom.vt.byref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2396 { &hf_dcom_vt_dispatch,
2397 { "VT_DISPATCH", "dcom.vt.dispatch", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2400 static hf_register_info hf_dcom_sa_array[] = {
2401 { &hf_dcom_safearray,
2402 { "SAFEARRAY", "dcom.sa", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2403 { &hf_dcom_sa_dims32,
2404 { "Dims32", "dcom.sa.dims32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2405 { &hf_dcom_sa_dims16,
2406 { "Dims16", "dcom.sa.dims16", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2407 { &hf_dcom_sa_features,
2408 { "Features", "dcom.sa.features", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2409 { &hf_dcom_sa_element_size,
2410 { "ElementSize", "dcom.sa.element_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2411 { &hf_dcom_sa_locks,
2412 { "Locks", "dcom.sa.locks", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2413 { &hf_dcom_sa_vartype32,
2414 { "VarType32", "dcom.sa.vartype", FT_UINT32, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2415 { &hf_dcom_sa_vartype16,
2416 { "VarType16", "dcom.sa.vartype", FT_UINT16, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2417 { &hf_dcom_sa_elements,
2418 { "Elements", "dcom.sa.elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2419 { &hf_dcom_sa_bound_elements,
2420 { "BoundElements", "dcom.sa.bound_elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2421 { &hf_dcom_sa_low_bound,
2422 { "LowBound", "dcom.sa.low_bound", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2424 { &hf_dcom_sa_features_auto,
2425 { "AUTO", "dcom.sa.features_auto", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_AUTO, NULL, HFILL }},
2426 { &hf_dcom_sa_features_static,
2427 { "STATIC", "dcom.sa.features_static", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_STATIC, NULL, HFILL }},
2428 { &hf_dcom_sa_features_embedded,
2429 { "EMBEDDED", "dcom.sa.features_embedded", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_EMBEDDED, NULL, HFILL }},
2430 { &hf_dcom_sa_features_fixedsize,
2431 { "FIXEDSIZE", "dcom.sa.features_fixedsize", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_FIXEDSIZE, NULL, HFILL }},
2432 { &hf_dcom_sa_features_record,
2433 { "RECORD", "dcom.sa.features_record", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_RECORD, NULL, HFILL }},
2434 { &hf_dcom_sa_features_have_iid,
2435 { "HAVEIID", "dcom.sa.features_have_iid", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEIID, NULL, HFILL }},
2436 { &hf_dcom_sa_features_have_vartype,
2437 { "HAVEVARTYPE", "dcom.sa.features_have_vartype", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEVARTYPE, NULL, HFILL }},
2438 { &hf_dcom_sa_features_bstr,
2439 { "BSTR", "dcom.sa.features_bstr", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_BSTR, NULL, HFILL }},
2440 { &hf_dcom_sa_features_unknown,
2441 { "UNKNOWN", "dcom.sa.features_unknown", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_UNKNOWN, NULL, HFILL }},
2442 { &hf_dcom_sa_features_dispatch,
2443 { "DISPATCH", "dcom.sa.features_dispatch", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_DISPATCH, NULL, HFILL }},
2444 { &hf_dcom_sa_features_variant,
2445 { "VARIANT", "dcom.sa.features_variant", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_VARIANT, NULL, HFILL }}
2448 static int *ett_dcom[] = {
2449 &ett_dcom_this,
2450 &ett_dcom_that,
2451 &ett_dcom_extent,
2452 &ett_dcom_lpwstr,
2453 &ett_dcom_interface_pointer,
2454 &ett_dcom_objref,
2455 &ett_dcom_stdobjref,
2456 &ett_dcom_custobjref,
2457 &ett_dcom_dualstringarray,
2458 &ett_dcom_dualstringarray_binding,
2459 &ett_dcom_variant,
2460 &ett_dcom_safearray,
2461 &ett_dcom_sa_features,
2464 static ei_register_info ei[] = {
2465 { &ei_dcom_dissection_incomplete, { "dcom.dissection_incomplete", PI_UNDECODED, PI_WARN, "Dissection incomplete", EXPFILL }},
2466 { &ei_dcom_no_spec, { "dcom.no_spec", PI_UNDECODED, PI_NOTE, "No specification available, dissection not possible", EXPFILL }},
2467 { &ei_dcom_hresult_expert, { "dcom.hresult.expert", PI_RESPONSE_CODE, PI_NOTE, "Hresult", EXPFILL }},
2468 { &ei_dcom_dualstringarray_mult_ip, { "dcom.dualstringarray.mult_ip", PI_UNDECODED, PI_NOTE, "DUALSTRINGARRAY Multiple IP", EXPFILL }},
2471 module_t *dcom_module;
2472 expert_module_t* expert_dcom;
2474 /* currently, the DCOM protocol "itself" has no real protocol dissector */
2475 /* we only need this, to register some generic elements */
2476 proto_dcom = proto_register_protocol ("DCOM", "DCOM", "dcom");
2477 proto_register_field_array(proto_dcom, hf_dcom_this_array, array_length(hf_dcom_this_array));
2478 proto_register_field_array(proto_dcom, hf_dcom_that_array, array_length(hf_dcom_that_array));
2479 proto_register_field_array(proto_dcom, hf_dcom_extent_array, array_length(hf_dcom_extent_array));
2480 proto_register_field_array(proto_dcom, hf_dcom_array, array_length(hf_dcom_array));
2481 proto_register_field_array(proto_dcom, hf_dcom_objref_array, array_length(hf_dcom_objref_array));
2482 proto_register_field_array(proto_dcom, hf_dcom_stdobjref_array, array_length(hf_dcom_stdobjref_array));
2483 proto_register_field_array(proto_dcom, hf_dcom_custobjref_array, array_length(hf_dcom_custobjref_array));
2484 proto_register_field_array(proto_dcom, hf_dcom_dualstringarray_array, array_length(hf_dcom_dualstringarray_array));
2485 proto_register_field_array(proto_dcom, hf_dcom_interface_pointer_array, array_length(hf_dcom_interface_pointer_array));
2486 proto_register_field_array(proto_dcom, hf_dcom_vt_array, array_length(hf_dcom_vt_array));
2487 proto_register_field_array(proto_dcom, hf_dcom_sa_array, array_length(hf_dcom_sa_array));
2488 proto_register_subtree_array (ett_dcom, array_length (ett_dcom));
2490 expert_dcom = expert_register_protocol(proto_dcom);
2491 expert_register_field_array(expert_dcom, ei, array_length(ei));
2493 /* preferences */
2494 dcom_module = prefs_register_protocol(proto_dcom, NULL);
2496 prefs_register_bool_preference(dcom_module, "display_unmarshalling_details",
2497 "Display DCOM unmarshalling details",
2498 "Display some DCOM unmarshalled fields "
2499 "usually hidden",
2500 &dcom_prefs_display_unmarshalling_details);
2502 register_cleanup_routine(dcom_cleanup);
2506 void
2507 proto_reg_handoff_dcom (void)
2509 /* register some "well known" UUID's */
2510 guids_add_uuid(&uuid_debug_ext, "Debug Information Body Extension");
2511 guids_add_uuid(&uuid_ext_error_ext, "Extended Error Info Body Extension");
2512 guids_add_uuid(&ipid_rem_unknown, "IRemUnknown");
2513 guids_add_uuid(&iid_unknown, "IUnknown");
2514 guids_add_uuid(&uuid_null, "NULL");
2515 guids_add_uuid(&iid_class_factory, "IClassFactory");
2516 guids_add_uuid(&iid_type_info, "ITypeInfo");
2517 guids_add_uuid(&iid_provide_class_info, "IProvideClassInfo");
2519 /* Currently, we have nothing to register for DCOM */
2523 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2525 * Local variables:
2526 * c-basic-offset: 8
2527 * tab-width: 8
2528 * indent-tabs-mode: t
2529 * End:
2531 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2532 * :indentSize=8:tabSize=8:noTabs=false: