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