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
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
57 #include <epan/packet.h>
58 #include <epan/addr_resolv.h>
59 #include <epan/expert.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
;
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
;
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
;
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} };
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} };
217 static GList
*dcom_machines
;
218 static GList
*dcom_interfaces
;
219 static GList
*dcom_marshalers
;
221 static const value_string dcom_thisthat_flag_vals
[] = {
228 static const value_string dcom_boolean_flag_vals
[] = {
229 { 0x00000001, "TRUE" },
230 { 0x00000000, "FALSE" },
236 void dcom_interface_dump(void) {
237 dcom_machine_t
*machine
;
238 dcom_object_t
*object
;
239 dcom_interface_t
*interf
;
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));*/
264 dcom_interface_t
*dcom_interface_find(packet_info
*pinfo _U_
, const address
*addr _U_
, e_guid_t
*ipid
)
266 dcom_interface_t
*interf
;
270 if(memcmp(ipid
, &uuid_null
, sizeof(uuid_null
)) == 0)
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) {
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
)
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)
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
;
309 interf
->ipid
= *ipid
;
311 dcom_interfaces
= g_list_append(dcom_interfaces
, interf
);
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) {
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
);
335 dcom_iter
= machine
->objects
;
336 while(dcom_iter
!= NULL
) {
337 object
= (dcom_object_t
*)dcom_iter
->data
;
338 if(object
->oid
== oid
) {
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
;
354 machine
->objects
= g_list_append(machine
->objects
, object
);
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) {
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
;
374 interf
->ipid
= *ipid
;
376 object
->interfaces
= g_list_append(object
->interfaces
, interf
);
377 dcom_interfaces
= g_list_append(dcom_interfaces
, 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
401 WIRESHARK_VT_EMPTY
= 0,
402 WIRESHARK_VT_NULL
= 1,
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
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"},
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" },
589 static const value_string dcom_objref_flag_vals
[] = {
590 { 0x1, "OBJREF_STANDARD" },
591 { 0x2, "OBJREF_HANDLER" },
592 { 0x4, "OBJREF_CUSTOM" },
596 static const value_string dcom_objref_signature_vals
[] = {
597 { 0x574f454d, "MEOW" },
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" },
616 static const value_string dcom_dcerpc_pointer_vals
[] = {
617 { 0x72657355, "User" },
618 { 0x42535452, "BSTR" },
619 { 0x00000000, "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"},
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"},
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" },
660 static const value_string dcom_vt_bool_vals
[] = {
668 /* dissect extension to DCOM "this" and "that" */
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
;
676 uint32_t u32VariableOffset
;
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
;
687 const char *uuid_name
;
690 offset
= dissect_dcom_dcerpc_pointer(tvb
, offset
, pinfo
, tree
, di
, drep
, &u32Pointer
);
692 if (u32Pointer
== 0) {
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) {
707 offset
= dissect_dcom_dcerpc_array_size(tvb
, offset
, pinfo
, tree
, di
, drep
,
710 u32VariableOffset
= offset
+ u32ArraySize
*4;
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)",
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;
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
,
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
);
754 proto_item_append_text(sub_item
, "[%u]: Bytes=%u",
755 u32Idx
, u32ArraySize2
);
757 proto_item_set_len(sub_item
, offset
- u32SubStart
);
759 /* update subtree header */
760 proto_item_append_text(sub_item
, "[%u]: NULL", u32Idx
);
761 proto_item_set_len(sub_item
, offset
- u32SubStart
);
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
;
780 e_guid_t uuidCausality
;
781 proto_item
*sub_item
;
782 proto_tree
*sub_tree
;
783 uint32_t u32SubStart
;
786 sub_item
= proto_tree_add_protocol_format(tree
, proto_dcom
, tvb
, offset
, 0,
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
);
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
) {
825 proto_item
*sub_item
;
826 proto_tree
*sub_tree
;
827 uint32_t u32SubStart
;
830 sub_item
= proto_tree_add_protocol_format(tree
, proto_dcom
, tvb
, offset
, 0,
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
);
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
);
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
)
874 offset
= dissect_dcom_that(tvb
, offset
, pinfo
, tree
, di
, drep
);
876 offset
= dissect_dcom_HRESULT(tvb
, offset
, pinfo
, tree
, di
, drep
,
879 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " -> %s",
880 val_to_str(u32HResult
, dcom_hresult_vals
, "Unknown (0x%08x)") );
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 */
900 offset
= dissect_ndr_uint32(tvb
, offset
, pinfo
, tree
, di
, drep
,
901 hf_dcom_array_size
, pu32ArraySize
);
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 */
919 offset
= dissect_ndr_uint32(tvb
, offset
, pinfo
, tree
, di
, drep
,
920 hf_dcom_pointer_val
, pu32Pointer
);
926 /* mark data as "ToBeDone" */
927 /* XXX: handout data to generic "unknown data" dissector? */
929 dissect_dcom_tobedone_data(tvbuff_t
*tvb
, int offset
,
930 packet_info
*pinfo
, proto_tree
*tree
, uint8_t *drep _U_
, int length
)
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
);
945 /* mark data as "No Specification Available" */
946 /* XXX: handout data to generic "unknown data" dissector? */
948 dissect_dcom_nospec_data(tvbuff_t
*tvb
, int offset
,
949 packet_info
*pinfo
, proto_tree
*tree
, uint8_t *drep _U_
, int length
)
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
);
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
)
973 /* dissect the WORD, but don't add to tree */
974 dissect_dcom_WORD(tvb
, offset
, pinfo
, NULL
/*tree*/, di
, drep
,
978 /* special formatted output of indexed value */
979 proto_tree_add_uint_format(tree
, hfindex
, tvb
, offset
, 2, u16WORD
,
981 proto_registrar_get_name(hfindex
),
982 field_index
, u16WORD
);
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
)
1003 /* dissect the DWORD, but don't add to tree */
1004 dissect_dcom_DWORD(tvb
, offset
, pinfo
, NULL
/*tree*/, di
, drep
,
1005 hfindex
, &u32DWORD
);
1008 /* special formatted output of indexed value */
1009 proto_tree_add_uint_format(tree
, hfindex
, tvb
, offset
, 4, u32DWORD
,
1011 proto_registrar_get_name(hfindex
),
1012 field_index
, u32DWORD
);
1018 *pu32DWORD
= u32DWORD
;
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
);
1037 /* special formatted output of indexed value */
1038 *item
= proto_tree_add_item (tree
, field_index
, tvb
, offset
-4, 4, DREP_ENC_INTEGER(drep
));
1042 *pu32HResult
= u32HResult
;
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
);
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)"));
1073 *pu32HResult
= u32HResult
;
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
);
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"),
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)"));
1107 *pu32HResult
= u32HResult
;
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
);
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
)
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
;
1143 uint32_t u32ArraySize
;
1144 uint32_t u32VariableOffset
;
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
,
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
);
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;
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
;
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
,
1227 case(WIRESHARK_VT_I1
):
1228 offset
= dissect_dcom_BYTE(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1229 hf_dcom_vt_i1
, &u8Data
);
1231 case(WIRESHARK_VT_I2
):
1232 offset
= dissect_dcom_WORD(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1233 hf_dcom_vt_i2
, &u16Data
);
1235 case(WIRESHARK_VT_I4
):
1236 offset
= dissect_dcom_DWORD(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1237 hf_dcom_vt_i4
, &u32Data
);
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
;
1245 case(WIRESHARK_VT_BSTR
):
1246 offset
= dissect_dcom_dcerpc_pointer(tvb
, offset
, pinfo
, sub_tree
, di
, drep
, &u32Pointer
);
1248 u32VariableOffset
= dissect_dcom_BSTR(tvb
, u32VariableOffset
, pinfo
, sub_tree
, di
, drep
,
1249 hf_dcom_vt_bstr
, cData
, sizeof(cData
) );
1253 /* XXX: other types possible, but still not implemented:
1258 VT_UNKNOWN|VT_RESERVED
1260 u32VariableOffset
= dissect_dcom_tobedone_data(tvb
, u32VariableOffset
, pinfo
, sub_tree
, drep
,
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
);
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
)
1298 uint32_t u32SubStart
;
1299 proto_item
*sub_item
;
1300 proto_tree
*sub_tree
;
1301 uint16_t u16VarType
;
1302 uint32_t u32VarType
;
1310 uint32_t u32Pointer
;
1315 /* alignment of 8 needed for a VARIANT */
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
,
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
):
1356 case(WIRESHARK_VT_BOOL
):
1357 offset
= dissect_dcom_VARIANT_BOOL(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1358 hf_dcom_vt_bool
, &u16Data
);
1360 case(WIRESHARK_VT_I1
):
1361 offset
= dissect_dcom_BYTE(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1362 hf_dcom_vt_i1
, &u8Data
);
1364 case(WIRESHARK_VT_UI1
):
1365 offset
= dissect_dcom_BYTE(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1366 hf_dcom_vt_ui1
, &u8Data
);
1368 case(WIRESHARK_VT_I2
):
1369 offset
= dissect_dcom_WORD(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1370 hf_dcom_vt_i2
, &u16Data
);
1372 case(WIRESHARK_VT_UI2
):
1373 offset
= dissect_dcom_WORD(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1374 hf_dcom_vt_ui2
, &u16Data
);
1376 case(WIRESHARK_VT_I4
):
1377 offset
= dissect_dcom_DWORD(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1378 hf_dcom_vt_i4
, &u32Data
);
1380 case(WIRESHARK_VT_I8
):
1381 offset
= dissect_dcom_I8(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1382 hf_dcom_vt_i8
, &u64Data
);
1384 case(WIRESHARK_VT_CY
):
1385 offset
= dissect_dcom_I8(tvb
, offset
, pinfo
, NULL
, di
, drep
,
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));
1392 case(WIRESHARK_VT_UI4
):
1393 offset
= dissect_dcom_DWORD(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1394 hf_dcom_vt_ui4
, &u32Data
);
1396 case(WIRESHARK_VT_UI8
):
1397 offset
= dissect_dcom_I8(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1398 hf_dcom_vt_ui8
, &u64Data
);
1400 case(WIRESHARK_VT_R4
):
1401 offset
= dissect_dcom_FLOAT(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1402 hf_dcom_vt_r4
, &f32Data
);
1404 case(WIRESHARK_VT_R8
):
1405 offset
= dissect_dcom_DOUBLE(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1406 hf_dcom_vt_r8
, &f64Data
);
1408 case(WIRESHARK_VT_DATE
):
1409 offset
= dissect_dcom_DATE(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1410 hf_dcom_vt_date
, &f64Data
);
1412 case(WIRESHARK_VT_BSTR
):
1413 offset
= dissect_dcom_dcerpc_pointer(tvb
, offset
, pinfo
, sub_tree
, di
, drep
, &u32Pointer
);
1415 offset
= dissect_dcom_BSTR(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1416 hf_dcom_vt_bstr
, cData
, sizeof(cData
) );
1419 case(WIRESHARK_VT_DISPATCH
):
1420 offset
= dissect_dcom_dcerpc_pointer(tvb
, offset
, pinfo
, sub_tree
, di
, drep
, &u32Pointer
);
1422 offset
= dissect_dcom_MInterfacePointer(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1423 hf_dcom_vt_dispatch
, NULL
); /* XXX - how to handle this? */
1426 case(WIRESHARK_VT_ARRAY
):
1427 offset
= dissect_dcom_SAFEARRAY(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1430 case(WIRESHARK_VT_ERROR
):
1431 offset
= dissect_dcom_HRESULT(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1434 case(WIRESHARK_VT_VARIANT
):
1435 offset
= dissect_dcom_dcerpc_pointer(tvb
, offset
, pinfo
, sub_tree
, di
, drep
, &u32Pointer
);
1437 offset
= dissect_dcom_VARIANT(tvb
, offset
, pinfo
, sub_tree
, di
, drep
,
1438 hf_dcom_vt_byref
/* must be BYREF */);
1441 case(WIRESHARK_VT_UNKNOWN
):
1442 offset
= dissect_dcom_dcerpc_pointer(tvb
, offset
, pinfo
, sub_tree
, di
, drep
, &u32Pointer
);
1445 /* XXX: add more types here! */
1446 offset
= dissect_dcom_tobedone_data(tvb
, offset
, pinfo
, sub_tree
, drep
,
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
);
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
;
1471 /* get the UUID, but don't put it into the tree */
1472 offset
= dissect_ndr_uuid_t(tvb
, offset
, pinfo
, NULL
, di
, drep
,
1475 /* add to the tree */
1476 hfi
= proto_registrar_get_nth(hfindex
);
1477 uuid_name
= guids_get_uuid_name(&uuid
, pinfo
->pool
);
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]);
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",
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]);
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
;
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
,
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
);
1532 proto_item_append_text(pi
, ": ");
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]);
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
: "???");
1555 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s=%s",
1556 hfi
->name
, (uuid_name
) ? uuid_name
: "???");
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 */
1567 dcom_tvb_get_nwstringz0(tvbuff_t
*tvb
, int offset
, uint32_t inLength
, char *pszStr
, uint32_t outLength
, bool *isPrintable
)
1572 uint32_t inLengthWithoutNullDelimiter
= 0;
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) {
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
);
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
;
1643 uint32_t u32ArraySize
;
1644 uint32_t u32StrStart
;
1645 proto_item
*sub_item
;
1646 proto_tree
*sub_tree
;
1647 uint32_t u32SubStart
;
1651 /* alignment of 4 needed */
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
,
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
),
1678 isPrintable
? "\"" : "", pszStr
, isPrintable
? "\"" : "");
1680 proto_item_append_text(sub_item
, "%s%s%s",
1681 isPrintable
? "\"" : "", pszStr
, isPrintable
? "\"" : "");
1683 proto_item_set_len(sub_item
, offset
- u32SubStart
);
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
;
1717 /* alignment of 4 needed */
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
);
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
,
1734 if ((uint32_t)offset
+ u32ArraySize
*2 > INT_MAX
) {
1739 realOffset
= offset
+ u32ArraySize
*2;
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 */
1753 proto_item_set_len(sub_item
, realOffset
- subStart
);
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
;
1767 uint32_t u32MaxStr
= sizeof(szStr
);
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
;
1781 uint32_t first_ip
= 0;
1782 uint32_t curr_ip
= 0;
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
);
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));*/
1824 memcpy(ip
, &curr_ip
, sizeof(curr_ip
));
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\"",
1843 val_to_str(u16TowerId
, dcom_protseq_vals
, "Unknown (0x%04x"),
1845 proto_item_set_len(subsub_item
, offset
- u32SubSubStart
);
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
);
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
);
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
);
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
)
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
,
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
);
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]);
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
))
1952 marshaler
= wmem_new(wmem_file_scope(), dcom_marshaler_t
);
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
);
1970 dcom_get_routine_by_uuid(const e_guid_t
* uuid
)
1972 dcom_marshaler_t
*marsh
;
1975 if(memcmp(uuid
, &uuid_null
, sizeof(uuid_null
)) == 0) {
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
;
1992 /* dissect an CUSTOM */
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
;
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
);
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
);
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
;
2041 proto_item
*sub_item
;
2042 proto_tree
*sub_tree
;
2043 uint32_t u32SubStart
;
2047 dcom_interface_t
*dcom_if
= NULL
;
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
,
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
);
2073 case(0x2): /* handler (untested) */
2074 offset
= dissect_dcom_STDOBJREF(tvb
, offset
, pinfo
, sub_tree
, di
, drep
, hfindex
,
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
);
2081 case(0x4): /* custom */
2082 offset
= dissect_dcom_CUSTOBJREF(tvb
, offset
, pinfo
, sub_tree
, di
, drep
, hfindex
,
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
) {
2092 set_address(&addr
, AT_IPv4
, 4, ip
);
2093 dcom_if
= dcom_interface_new(pinfo
,
2095 &iid
, oxid
, oid
, &ipid
);
2099 if(interf
!= NULL
) {
2103 /* append info to subtree header */
2104 proto_item_set_len(sub_item
, offset
- u32SubStart
);
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
;
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
);
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
);
2154 offset
= dissect_dcom_MInterfacePointer(tvb
, offset
, pinfo
, tree
, di
, drep
, hfindex
, interf
);
2156 if(interf
!= NULL
) {
2164 static void dcom_cleanup(void) {
2165 if (dcom_machines
!= NULL
) {
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
) {
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
) {
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
;
2219 proto_register_dcom (void)
2221 static hf_register_info hf_dcom_this_array
[] = {
2223 { &hf_dcom_this_version_major
,
2224 { "VersionMajor", "dcom.this.version_major", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2227 { &hf_dcom_this_version_minor
,
2228 { "VersionMinor", "dcom.this.version_minor", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
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
[] = {
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
}},
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
}},
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
}},
2270 { &hf_dcom_actual_count
,
2271 { "ActualCount", "dcom.actual_count", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2273 { &hf_dcom_tobedone
,
2274 { "To Be Done", "dcom.tobedone", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
2276 { "No Specification Available", "dcom.nospec", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
2279 { "Variant", "dcom.variant", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
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
[] = {
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
}},
2312 { "IID", "dcom.iid", FT_GUID
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
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
}},
2331 { "OXID", "dcom.oxid", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2333 { "OID", "dcom.oid", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
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
[] = {
2367 { "VT_BOOL", "dcom.vt.bool", FT_UINT16
, BASE_HEX
, VALS(dcom_vt_bool_vals
), 0x0, NULL
, HFILL
}},
2369 { "VT_I1", "dcom.vt.i1", FT_INT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2371 { "VT_I2", "dcom.vt.i2", FT_INT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2373 { "VT_I4", "dcom.vt.i4", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2375 { "VT_I8", "dcom.vt.i8", FT_INT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2377 { "VT_CY", "dcom.vt.cy", FT_INT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2379 { "VT_UI1", "dcom.vt.ui1", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2381 { "VT_UI2", "dcom.vt.ui2", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2383 { "VT_UI4", "dcom.vt.ui4", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2385 { "VT_UI8", "dcom.vt.ui8", FT_UINT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2387 { "VT_R4", "dcom.vt.r4", FT_FLOAT
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
2389 { "VT_R8", "dcom.vt.r8", FT_DOUBLE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
2391 { "VT_DATE", "dcom.vt.date", FT_DOUBLE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
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
[] = {
2453 &ett_dcom_interface_pointer
,
2455 &ett_dcom_stdobjref
,
2456 &ett_dcom_custobjref
,
2457 &ett_dcom_dualstringarray
,
2458 &ett_dcom_dualstringarray_binding
,
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
));
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 "
2500 &dcom_prefs_display_unmarshalling_details
);
2502 register_cleanup_routine(dcom_cleanup
);
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
2528 * indent-tabs-mode: t
2531 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2532 * :indentSize=8:tabSize=8:noTabs=false: