MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-dcom.c
blob55fbc17fef2430457d36829a06fec9ff8fbf3380
1 /* packet-dcom.c
2 * Routines for DCOM generics
4 * $Id$
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 /* A few words about DCOM:
27 * DCOM uses DCERPC as its underlying "transport" protocol.
29 * The DCOM dissectors are called by DCERPC request and response calls.
30 * DCOM uses a small header after the DCERPC calls.
31 * (for a DCERPC request call it's called "this",
32 * for a DCERPC response call it's called "that")
34 * DCOM defines itself some interfaces: oxid, remact, remunk and others
36 * Implemented is currently "only" a static dissection of packet fields
37 * (no "object recognition" included)
39 * User's of DCOM can define their own interface's using Microsoft IDL.
41 * Hint: The registered DCOM interface names can be found in the
42 * windows registry at: "HKEY_CLASSES_ROOT\Interface"
45 * Ressources on the web:
47 * "Understanding the DCOM Wire Protocol by Analyzing Network Data Packets"
48 * http:// www.microsoft.com/msj/0398/dcom.htm
50 * "Distributed Component Object Model Protocol -- DCOM/1.0"
51 * http://www.microsoft.com/com/resources/specs.asp (link is currently down)
55 /* Files involved dissecting DCOM:
57 * packet-dcom.c: generic DCOM things (this, that, ...) and
58 * generic DCOM datatype (DWORD, VARIANT, ...)
60 * DCOM common Interfaces:
61 * packet-dcom-oxid.c: IOXIDResolver
62 * packet-dcom-remact.c: IRemoteActivation
63 * packet-dcom-remunk.c: IRemUnknown, IRemUnknown2
64 * packet-dcom-dispatch.c: IDispatch
65 * packet-dcom-sysact.c: ISystemActivator
68 #include "config.h"
71 * XXX - are the next two includes necessary?
73 #ifdef HAVE_SYS_TYPES_H
74 # include <sys/types.h>
75 #endif
77 #ifdef HAVE_NETINET_IN_H
78 #include <netinet/in.h>
79 #endif
81 #ifdef HAVE_WINSOCK2_H
82 #include <winsock2.h>
83 #endif
85 #include <string.h>
87 #include <glib.h>
89 #include <epan/packet.h>
90 #include <epan/exceptions.h>
91 #include <epan/wmem/wmem.h>
92 #include <epan/addr_resolv.h>
93 #include <wsutil/inet_aton.h>
94 #include <epan/expert.h>
95 #include <epan/prefs.h>
96 #include <ctype.h>
97 #include <isprint.h>
98 #include "packet-dcerpc.h"
99 #include "packet-dcom.h"
101 void proto_register_dcom (void);
102 void proto_reg_handoff_dcom (void);
104 static int proto_dcom = -1;
106 gboolean dcom_prefs_display_unmarshalling_details = FALSE;
109 static gint ett_dcom_this = -1;
110 /* static int hf_dcom_this_version_major = -1; */
111 /* static int hf_dcom_this_version_minor = -1; */
112 static int hf_dcom_this_flags = -1;
113 static int hf_dcom_this_res = -1;
114 static int hf_dcom_this_cid = -1;
116 static gint ett_dcom_that = -1;
117 static int hf_dcom_that_flags = -1;
119 static gint ett_dcom_extent = -1;
120 static int hf_dcom_extent = -1;
121 static int hf_dcom_extent_array_count = -1;
122 static int hf_dcom_extent_array_res = -1;
123 static int hf_dcom_extent_size = -1;
124 static int hf_dcom_extent_id = -1;
126 static int hf_dcom_hresult = -1;
127 static int hf_dcom_tobedone = -1;
128 static int hf_dcom_nospec = -1;
129 static int hf_dcom_array_size = -1;
130 static int hf_dcom_pointer_val = -1;
132 /* COMVERSION */
133 static int hf_dcom_version_major = -1;
134 static int hf_dcom_version_minor = -1;
136 static gint ett_dcom_lpwstr = -1;
137 static int hf_dcom_max_count = -1;
138 static int hf_dcom_offset = -1;
139 static int hf_dcom_byte_length = -1;
140 /* static int hf_dcom_actual_count = -1; */
142 static gint ett_dcom_objref = -1;
143 static int hf_dcom_objref = -1;
144 static int hf_dcom_objref_signature = -1;
145 static int hf_dcom_objref_flags = -1;
146 int hf_dcom_iid = -1;
147 int hf_dcom_clsid = -1;
148 static int hf_dcom_objref_resolver_address = -1;
149 static int hf_dcom_objref_cbextension = -1;
150 static int hf_dcom_objref_size = -1;
152 static gint ett_dcom_stdobjref = -1;
153 static int hf_dcom_stdobjref = -1;
154 static int hf_dcom_stdobjref_flags = -1;
155 static int hf_dcom_stdobjref_public_refs = -1;
156 int hf_dcom_oxid = -1;
157 int hf_dcom_oid = -1;
158 int hf_dcom_ipid = -1;
161 static gint ett_dcom_custobjref = -1;
162 static int hf_dcom_custobjref = -1;
164 static gint ett_dcom_dualstringarray = -1;
165 static gint ett_dcom_dualstringarray_binding = -1;
166 static int hf_dcom_dualstringarray_num_entries = -1;
167 static int hf_dcom_dualstringarray_security_offset = -1;
168 static int hf_dcom_dualstringarray_string = -1;
169 static int hf_dcom_dualstringarray_string_network_addr = -1;
170 static int hf_dcom_dualstringarray_string_tower_id = -1;
171 static int hf_dcom_dualstringarray_security = -1;
172 static int hf_dcom_dualstringarray_security_authn_svc = -1;
173 static int hf_dcom_dualstringarray_security_authz_svc = -1;
174 static int hf_dcom_dualstringarray_security_princ_name = -1;
176 static gint ett_dcom_interface_pointer = -1;
177 static int hf_dcom_interface_pointer = -1;
178 static int hf_dcom_ip_cnt_data = -1;
180 static gint ett_dcom_safearray = -1;
181 static int hf_dcom_safearray = -1;
182 static int hf_dcom_sa_dims32 = -1;
183 static int hf_dcom_sa_dims16 = -1;
184 static int hf_dcom_sa_features = -1;
185 static int hf_dcom_sa_element_size = -1;
186 static int hf_dcom_sa_locks = -1;
187 static int hf_dcom_sa_vartype32 = -1;
188 static int hf_dcom_sa_vartype16 = -1;
189 static int hf_dcom_sa_elements = -1;
190 static int hf_dcom_sa_bound_elements = -1;
191 static int hf_dcom_sa_low_bound = -1;
193 static gint ett_dcom_sa_features = -1;
194 static int hf_dcom_sa_features_auto = -1;
195 static int hf_dcom_sa_features_static = -1;
196 static int hf_dcom_sa_features_embedded = -1;
197 static int hf_dcom_sa_features_fixedsize = -1;
198 static int hf_dcom_sa_features_record = -1;
199 static int hf_dcom_sa_features_have_iid = -1;
200 static int hf_dcom_sa_features_have_vartype = -1;
201 static int hf_dcom_sa_features_bstr = -1;
202 static int hf_dcom_sa_features_unknown = -1;
203 static int hf_dcom_sa_features_dispatch = -1;
204 static int hf_dcom_sa_features_variant = -1;
206 static gint ett_dcom_variant = -1;
207 /* static int hf_dcom_variant = -1; */
208 static int hf_dcom_variant_type = -1;
209 static int hf_dcom_variant_size = -1;
210 static int hf_dcom_variant_rpc_res = -1;
211 static int hf_dcom_variant_wres = -1;
212 static int hf_dcom_variant_type32 = -1;
214 static int hf_dcom_vt_bool = -1;
215 static int hf_dcom_vt_i1 = -1;
216 static int hf_dcom_vt_i2 = -1;
217 static int hf_dcom_vt_i4 = -1;
218 static int hf_dcom_vt_i8 = -1; /* only inside a SAFEARRAY, not in VARIANTs */
219 static int hf_dcom_vt_ui1 = -1;
220 static int hf_dcom_vt_ui2 = -1;
221 static int hf_dcom_vt_ui4 = -1;
222 static int hf_dcom_vt_r4 = -1;
223 static int hf_dcom_vt_r8 = -1;
224 static int hf_dcom_vt_date = -1;
225 static int hf_dcom_vt_bstr = -1;
226 static int hf_dcom_vt_byref = -1;
227 static int hf_dcom_vt_dispatch = -1;
229 static expert_field ei_dcom_dissetion_incomplete = EI_INIT;
230 static expert_field ei_dcom_no_spec = EI_INIT;
231 static expert_field ei_dcom_hresult_expert = EI_INIT;
232 static expert_field ei_dcom_dualstringarray_mult_ip = EI_INIT;
234 /* this/that extension UUIDs */
235 static e_uuid_t uuid_debug_ext = { 0xf1f19680, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} };
236 static e_uuid_t uuid_ext_error_ext ={ 0xf1f19681, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} };
238 /* general DCOM UUIDs */
239 static const e_uuid_t ipid_rem_unknown = { 0x00000131, 0x1234, 0x5678, { 0xCA, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
240 static const e_uuid_t iid_unknown = { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
241 static const e_uuid_t uuid_null = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
242 static const e_uuid_t iid_class_factory = { 0x00000001, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
243 #if 0
244 static const e_uuid_t iid_act_prop_in = { 0x000001A2, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
245 static const e_uuid_t iid_act_prop_out = { 0x000001A3, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
246 #endif
248 static GList *dcom_machines = NULL;
249 static GList *dcom_interfaces = NULL;
250 static GList *dcom_marshalers = NULL;
252 static const value_string dcom_thisthat_flag_vals[] = {
253 { 0, "INFO_NULL" },
254 { 1, "INFO_LOCAL" },
255 { 0, NULL }
258 #if 0
259 static const value_string dcom_boolean_flag_vals[] = {
260 { 0x00000001, "TRUE" },
261 { 0x00000000, "FALSE" },
262 { 0, NULL }
264 #endif
266 void dcom_interface_dump(void) {
267 dcom_machine_t *machine;
268 dcom_object_t *object;
269 dcom_interface_t *interf;
270 GList *machines;
271 GList *objects;
272 GList *interfaces;
275 for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
276 machine = (dcom_machine_t *)machines->data;
277 g_warning("Machine(#%4u): IP:%s", machine->first_packet, ip_to_str(machine->ip));
279 for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
280 object = (dcom_object_t *)objects->data;
281 g_warning(" Object(#%4u): OID:0x%" G_GINT64_MODIFIER "x private:%p", object->first_packet, object->oid, object->private_data);
283 for(interfaces = object->interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
284 interf = (dcom_interface_t *)interfaces->data;
285 g_warning(" Interface(#%4u): iid:%s",
286 interf->first_packet, guids_resolve_uuid_to_str(&interf->iid));
287 g_warning(" ipid:%s", guids_resolve_uuid_to_str(&interf->ipid));
294 dcom_interface_t *dcom_interface_find(packet_info *pinfo _U_, const guint8 *ip _U_, e_uuid_t *ipid)
296 dcom_interface_t *interf;
297 GList *interfaces;
300 if(memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
302 return NULL;
305 for(interfaces = dcom_interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
306 interf = (dcom_interface_t *)interfaces->data;
308 if(memcmp(&interf->ipid, ipid, sizeof(e_uuid_t)) == 0) {
309 return interf;
313 return NULL;
317 dcom_interface_t *dcom_interface_new(packet_info *pinfo, const guint8 *ip, e_uuid_t *iid, guint64 oxid, guint64 oid, e_uuid_t *ipid)
319 GList *dcom_iter;
320 dcom_machine_t *machine;
321 dcom_object_t *object;
322 dcom_interface_t *interf;
325 if( memcmp(iid, &uuid_null, sizeof(uuid_null)) == 0 ||
326 memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
328 return NULL;
331 if(oxid == 0 || oid == 0) {
332 /*g_warning("interface_new#%u", pinfo->fd->num);*/
334 interf = wmem_new(wmem_file_scope(), dcom_interface_t);
335 interf->parent = NULL;
336 interf->private_data = NULL;
337 interf->first_packet = pinfo->fd->num;
338 interf->iid = *iid;
339 interf->ipid = *ipid;
341 dcom_interfaces = g_list_append(dcom_interfaces, interf);
342 return interf;
345 /* find machine */
346 dcom_iter = dcom_machines;
347 while(dcom_iter != NULL) {
348 machine = (dcom_machine_t *)dcom_iter->data;
349 if(memcmp(machine->ip, ip, 4) == 0) {
350 break;
352 dcom_iter = g_list_next(dcom_iter);
355 /* create new machine if not found */
356 if(dcom_iter == NULL) {
357 machine = g_new(dcom_machine_t,1);
358 memcpy(machine->ip, ip, 4);
359 machine->objects = NULL;
360 machine->first_packet = pinfo->fd->num;
361 dcom_machines = g_list_append(dcom_machines, machine);
364 /* find object */
365 dcom_iter = machine->objects;
366 while(dcom_iter != NULL) {
367 object = (dcom_object_t *)dcom_iter->data;
368 if(object->oid == oid) {
369 break;
371 dcom_iter = g_list_next(dcom_iter);
374 /* create new object if not found */
375 if(dcom_iter == NULL) {
376 object = g_new(dcom_object_t,1);
377 object->parent = machine;
378 object->interfaces = NULL;
379 object->private_data = NULL;
380 object->first_packet = pinfo->fd->num;
381 object->oid = oid;
382 object->oxid = oxid;
384 machine->objects = g_list_append(machine->objects, object);
387 /* find interface */
388 dcom_iter = object->interfaces;
389 while(dcom_iter != NULL) {
390 interf = (dcom_interface_t *)dcom_iter->data;
391 if(memcmp(&interf->ipid, ipid, sizeof(e_uuid_t)) == 0) {
392 break;
394 dcom_iter = g_list_next(dcom_iter);
397 /* create new interface if not found */
398 if(dcom_iter == NULL) {
399 interf = g_new(dcom_interface_t,1);
400 interf->parent = object;
401 interf->private_data = NULL;
402 interf->first_packet = pinfo->fd->num;
403 interf->iid = *iid;
404 interf->ipid = *ipid;
406 object->interfaces = g_list_append(object->interfaces, interf);
407 dcom_interfaces = g_list_append(dcom_interfaces, interf);
410 return interf;
415 * Flag bits in connection-oriented PDU header.
417 #define WIRESHARK_FADF_AUTO 0x0001
418 #define WIRESHARK_FADF_STATIC 0x0002
419 #define WIRESHARK_FADF_EMBEDDED 0x0004
420 #define WIRESHARK_FADF_FIXEDSIZE 0x0010
421 #define WIRESHARK_FADF_RECORD 0x0020
422 #define WIRESHARK_FADF_HAVEIID 0x0040
423 #define WIRESHARK_FADF_HAVEVARTYPE 0x0080
424 #define WIRESHARK_FADF_BSTR 0x0100
425 #define WIRESHARK_FADF_UNKNOWN 0x0200
426 #define WIRESHARK_FADF_DISPATCH 0x0400
427 #define WIRESHARK_FADF_VARIANT 0x0800
430 typedef enum {
431 WIRESHARK_VT_EMPTY = 0,
432 WIRESHARK_VT_NULL = 1,
433 WIRESHARK_VT_I2 = 2,
434 WIRESHARK_VT_I4 = 3,
435 WIRESHARK_VT_R4 = 4,
436 WIRESHARK_VT_R8 = 5,
437 WIRESHARK_VT_CY = 6,
438 WIRESHARK_VT_DATE = 7,
439 WIRESHARK_VT_BSTR = 8,
440 WIRESHARK_VT_DISPATCH = 9,
441 WIRESHARK_VT_ERROR = 10,
442 WIRESHARK_VT_BOOL = 11,
443 WIRESHARK_VT_VARIANT = 12,
444 WIRESHARK_VT_UNKNOWN = 13,
445 WIRESHARK_VT_DECIMAL = 14,
446 WIRESHARK_VT_I1 = 16,
447 WIRESHARK_VT_UI1 = 17,
448 WIRESHARK_VT_UI2 = 18,
449 WIRESHARK_VT_UI4 = 19,
450 WIRESHARK_VT_I8 = 20,
451 WIRESHARK_VT_UI8 = 21,
452 WIRESHARK_VT_INT = 22,
453 WIRESHARK_VT_UINT = 23,
454 WIRESHARK_VT_VOID = 24,
455 WIRESHARK_VT_HRESULT = 25,
456 WIRESHARK_VT_PTR = 26,
457 WIRESHARK_VT_SAFEARRAY = 27,
458 WIRESHARK_VT_CARRAY = 28,
459 WIRESHARK_VT_USERDEFINED = 29,
460 WIRESHARK_VT_LPSTR = 30,
461 WIRESHARK_VT_LPWSTR = 31,
462 WIRESHARK_VT_RECORD = 36,
463 WIRESHARK_VT_FILETIME = 64,
464 WIRESHARK_VT_BLOB = 65,
465 WIRESHARK_VT_STREAM = 66,
466 WIRESHARK_VT_STORAGE = 67,
467 WIRESHARK_VT_STREAMED_OBJECT = 68,
468 WIRESHARK_VT_STORED_OBJECT = 69,
469 WIRESHARK_VT_BLOB_OBJECT = 70,
470 WIRESHARK_VT_CF = 71,
471 WIRESHARK_VT_CLSID = 72,
473 WIRESHARK_VT_BSTR_BLOB = 0x0fff,
475 WIRESHARK_VT_VECTOR = 0x1000,
476 WIRESHARK_VT_ARRAY = 0x2000,
477 WIRESHARK_VT_BYREF = 0x4000,
478 WIRESHARK_VT_RESERVED = 0x8000,
480 WIRESHARK_VT_ILLEGAL = 0xffff,
481 WIRESHARK_VT_ILLEGALMASKED = 0x0fff,
482 WIRESHARK_VT_TYPEMASK = 0x0fff
483 } dcom_vartype_t;
485 const value_string dcom_variant_type_vals[] = {
486 { WIRESHARK_VT_EMPTY, "VT_EMPTY"},
487 { WIRESHARK_VT_NULL, "VT_NULL"},
488 { WIRESHARK_VT_I2, "VT_I2"},
489 { WIRESHARK_VT_I4, "VT_I4"},
490 { WIRESHARK_VT_R4, "VT_R4"},
491 { WIRESHARK_VT_R8, "VT_R8"},
492 { WIRESHARK_VT_CY, "VT_CY"},
493 { WIRESHARK_VT_DATE, "VT_DATE"},
494 { WIRESHARK_VT_BSTR, "VT_BSTR"},
495 { WIRESHARK_VT_DISPATCH, "VT_DISPATCH"},
496 { WIRESHARK_VT_ERROR, "VT_ERROR"},
497 { WIRESHARK_VT_BOOL, "VT_BOOL"},
498 { WIRESHARK_VT_I1, "VT_I1"},
499 { WIRESHARK_VT_UI1, "VT_UI1"},
500 { WIRESHARK_VT_UI2, "VT_UI2"},
501 { WIRESHARK_VT_UI4, "VT_UI4"},
502 { WIRESHARK_VT_I8, "VT_I8"},
503 { WIRESHARK_VT_UI8, "VT_UI8"},
504 { WIRESHARK_VT_ARRAY, "VT_ARRAY"},
505 { WIRESHARK_VT_UNKNOWN, "VT_UNKNOWN"},
506 { WIRESHARK_VT_USERDEFINED, "VT_USERDEFINED"},
508 /* XXX: this could be done better */
509 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I2, "VT_ARRAY|VT_I2"},
510 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I4, "VT_ARRAY|VT_I4"},
511 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_R4, "VT_ARRAY|VT_R4"},
512 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_R8, "VT_ARRAY|VT_R8"},
513 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_DATE, "VT_ARRAY|VT_DATE"},
514 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_BSTR, "VT_ARRAY|VT_BSTR"},
515 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_ERROR, "VT_ARRAY|VT_ERROR"},
516 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_BOOL, "VT_ARRAY|VT_BOOL"},
517 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I1, "VT_ARRAY|VT_I1"},
518 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI1, "VT_ARRAY|VT_UI1"},
519 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI2, "VT_ARRAY|VT_UI2"},
520 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI4, "VT_ARRAY|VT_UI4"},
521 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I8, "VT_ARRAY|VT_I8"},
522 { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI8, "VT_ARRAY|VT_UI8"},
524 { WIRESHARK_VT_BYREF | WIRESHARK_VT_I2, "VT_BYREF|VT_I2"},
525 { WIRESHARK_VT_BYREF | WIRESHARK_VT_BSTR, "VT_BYREF|VT_BSTR"},
526 { WIRESHARK_VT_BYREF | WIRESHARK_VT_VARIANT, "VT_BYREF|VT_VARIANT"},
527 { 0, NULL }
528 /* XXX: append more types here */
533 /* we need an extension mechanism here (be able to append entries by user protocol) */
534 const value_string dcom_hresult_vals[] = {
535 { 0x00000000, "S_OK" },
536 { 0x00000001, "S_FALSE" },
537 { 0x8000FFFF, "E_UNEXPECTED" },
538 { 0x80004001, "E_NOTIMPL" },
539 { 0x80004002, "E_NOINTERFACE" },
540 { 0x80004003, "E_POINTER" },
541 { 0x80004004, "E_ABORT" },
542 { 0x80004005, "E_FAIL" },
543 { 0x80070005, "E_ACCESSDENIED" },
544 { 0x80070006, "E_HANDLE" },
545 { 0x8007000E, "E_OUTOFMEMORY" },
546 { 0x80070057, "E_INVALIDARG" },
548 { 0x80010108, "RPC_E_DISCONNECTED" },
549 { 0x80010113, "RPC_E_INVALID_IPID" },
550 { 0x8001011F, "RPC_E_TIMEOUT" },
552 { 0x80020003, "DISP_E_MEMBERNOTFOUND" },
553 { 0x80020004, "DISP_E_PARAMNOTFOUND" },
554 { 0x80020005, "DISP_E_TYPEMISMATCH" },
555 { 0x80020006, "DISP_E_UNKNOWNNAME" },
556 { 0x80020008, "DISP_E_BADVARTYPE" },
557 { 0x80020009, "DISP_E_EXCEPTION" },
558 { 0x8002000A, "DISP_E_OVERFLOW" },
560 { 0x8002801D, "TYPE_E_LIBNOTREGISTERED" },
562 { 0x80040154, "REGDB_E_CLASSNOTREG" },
563 { 0x80040201, "CO_E_FAILEDTOGETSECCTX" },
565 /* following are CBA application specific values */
566 { 0x0004CA00, "CBA_S_PERSISTPENDING" },
567 { 0x0004CA01, "CBA_S_ESTABLISHING" },
568 { 0x0004CA02, "CBA_S_NOCONNECTION" },
569 { 0x0004CA03, "CBA_S_VALUEBUFFERED" },
570 { 0x0004CA04, "CBA_S_VALUEUNCERTAIN" },
571 { 0x0004CA05, "CBA_S_NOCONNECTIONDATA" },
572 { 0x0004CA06, "CBA_S_FRAMEEMPTY" },
574 { 0x8004CB00, "CBA_E_MALFORMED" },
575 { 0x8004CB01, "CBA_E_UNKNOWNOBJECT" },
576 { 0x8004CB02, "CBA_E_UNKNOWNMEMBER" },
577 { 0x8004CB03, "CBA_E_TYPEMISMATCH" },
578 { 0x8004CB04, "CBA_E_INVALIDENUMVALUE" },
579 { 0x8004CB05, "CBA_E_INVALIDID" },
580 { 0x8004CB06, "CBA_E_INVALIDEPSILON" },
581 { 0x8004CB07, "CBA_E_INVALIDSUBSTITUTE" },
582 { 0x8004CB08, "CBA_E_INVALIDCONNECTION" },
583 { 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
584 { 0x8004CB0A, "CBA_E_TIMEVALUEUNSUPPORTED" },
585 { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
586 { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
587 { 0x8004CB0D, "CBA_E_PERSISTRUNNING" },
588 { 0x8004CB0E, "CBA_E_INUSE" },
589 { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
590 { 0x8004CB10, "CBA_E_NONACCESSIBLE" },
591 { 0x8004CB11, "CBA_E_DEFECT" },
592 { 0x8004CB12, "CBA_E_LIMITVIOLATION" },
593 { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" },
594 { 0x8004CB14, "CBA_E_QCNOTAPPLICABLE" },
595 { 0x8004CB15, "CBA_E_ACCESSBLOCKED" },
596 { 0x8004CB16, "CBA_E_COUNTEXCEEDED" },
597 { 0x8004CB17, "CBA_E_SIZEEXCEEDED" },
598 { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" },
599 { 0x8004CB19, "CBA_E_OUTOFACCOPAIRS" },
600 { 0x8004CB1A, "CBA_E_ITEMTOOLARGE" },
601 { 0x8004CB1B, "CBA_E_CRDATALENGTH" },
602 { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" },
603 { 0x8004CB1D, "CBA_E_CAPACITYEXCEEDED" },
604 { 0x8004CB1E, "CBA_E_SUBELEMENTMISMATCH" },
605 { 0x8004CB1F, "CBA_E_STATIONFAILURE" },
606 { 0x8004CB20, "CBA_E_NOTROUTABLE" },
607 { 0x8004CB21, "CBA_E_DISCONNECTRUNNING" },
608 { 0x8004CB22, "CBA_E_LOCATIONCHANGED" },
609 { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
610 { 0x8004CB24, "CBA_E_LINKFAILURE" },
611 { 0x8004CB25, "CBA_E_MODECHANGE" },
613 { 0x80080004, "CO_E_BAD_PATH" },
615 { 0, NULL }
618 static const value_string dcom_objref_flag_vals[] = {
619 { 0x1, "OBJREF_STANDARD" },
620 { 0x2, "OBJREF_HANDLER" },
621 { 0x4, "OBJREF_CUSTOM" },
622 { 0, NULL }
625 static const value_string dcom_objref_signature_vals[] = {
626 { 0x574f454d, "MEOW" },
627 { 0, NULL }
630 /* although flags, they doesn't seem to be used as such */
631 static const value_string dcom_stdobjref_flag_vals[] = {
632 { 0x0000, "SORF_NULL" },
633 { 0x0001, "SORF_OXRES1" },
634 { 0x0020, "SORF_OXRES2" },
635 { 0x0040, "SORF_OXRES3" },
636 { 0x0080, "SORF_OXRES4" },
637 { 0x0100, "SORF_OXRES5" },
638 { 0x0200, "SORF_OXRES6" },
639 { 0x0400, "SORF_OXRES7" },
640 { 0x0800, "SORF_OXRES8" },
641 { 0x1000, "SORF_NOPING" },
642 { 0, NULL }
645 static const value_string dcom_dcerpc_pointer_vals[] = {
646 { 0x72657355, "User" },
647 { 0x42535452, "BSTR" },
648 { 0x00000000, "NULL" },
649 { 0, NULL }
652 static const value_string dcom_dualstringarray_authz[] = {
653 { 0x0000, "RPC_C_AUTHZ_NONE" },
654 { 0x0001, "RPC_C_AUTHZ_NAME"},
655 { 0x0002, "RPC_C_AUTHZ_DCE"},
656 { 0xffff, "Default"},
657 { 0, NULL}
660 static const value_string dcom_dualstringarray_authn[] = {
661 { 00, "RPC_C_AUTHN_NONE" },
662 { 1, "RPC_C_AUTHN_DCE_PRIVATE"},
663 { 2, "RPC_C_AUTHN_DCE_PUBLIC"},
664 { 4, "RPC_C_AUTHN_DEC_PUBLIC"},
665 { 9, "RPC_C_AUTHN_GSS_NEGOTIATE"},
666 { 10, "RPC_C_AUTH_WINNT"},
667 { 14, "RPC_C_AUTHN_GSS_SCHANNEL"},
668 { 16, "RPC_C_AUTHN_GSS_KERBEROS"},
669 { 17, "RPC_C_AUTHN_MSN"},
670 { 18, "RPC_C_AUTHN_DPA"},
671 { 100, "RPC_C_AUTHN_MQ"},
672 { 0xffff, "RPC_C_AUTHN_DEFAULT"},
673 { 0, NULL}
676 const value_string dcom_protseq_vals[] = {
677 { 0x04, "NCACN_DNET_NSP" },
678 { 0x07, "NCACN_IP_TCP" },
679 { 0x08, "NCADG_IP_UDP" },
680 { 0x09, "NCACN_IP" },
681 { 0x0C, "NCACN_SPX" },
682 { 0x0D, "NCACN_NB_IPX" },
683 { 0x0E, "NCADG_IPX" },
684 { 0x12, "NCACN_NB_NB" },
685 { 0x1F, "NCACN_HTTP" },
686 { 0, NULL }
689 static const value_string dcom_vt_bool_vals[] = {
690 { 0x0000, "FALSE" },
691 { 0xFFFF, "TRUE" },
692 { 0, NULL }
697 /* dissect extension to DCOM "this" and "that" */
698 static int
699 dissect_dcom_extent(tvbuff_t *tvb, int offset,
700 packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
702 guint32 u32ArraySize;
703 guint32 u32ArraySize2;
704 guint32 u32Pointer;
705 guint32 u32VariableOffset;
706 guint32 u32Idx;
707 guint32 u32SubStart;
708 proto_item *sub_item;
709 proto_tree *sub_tree;
711 guint32 u32ArrayCount;
712 guint32 u32ArrayRes;
714 guint32 u32ExtentSize;
715 e_uuid_t uuidExtend;
716 const char *uuid_name;
719 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
721 if (u32Pointer == 0) {
722 return offset;
725 offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
726 hf_dcom_extent_array_count, &u32ArrayCount);
727 offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
728 hf_dcom_extent_array_res, &u32ArrayRes);
730 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
732 if (u32Pointer == 0) {
733 return offset;
736 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
737 &u32ArraySize);
739 u32VariableOffset = offset + u32ArraySize*4;
741 u32Idx = 1;
742 while (u32ArraySize--) {
743 sub_item = proto_tree_add_item(tree, hf_dcom_extent, tvb, offset, 0, ENC_NA);
744 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_extent);
745 u32SubStart = offset;
747 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
749 if(u32Pointer != 0) {
750 u32VariableOffset = dissect_dcom_DWORD(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
751 hf_dcom_extent_size, &u32ExtentSize);
753 dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, NULL, di, drep,
754 hf_dcom_extent_id, &uuidExtend);
756 /* look for a registered uuid name */
757 if((uuid_name = guids_get_uuid_name(&uuidExtend)) != NULL) {
758 proto_tree_add_guid_format_value(sub_tree, hf_dcom_extent_id, tvb,
759 offset, sizeof(e_uuid_t), (e_guid_t *) &uuidExtend,
760 "%s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
761 uuid_name,
762 uuidExtend.Data1, uuidExtend.Data2, uuidExtend.Data3,
763 uuidExtend.Data4[0], uuidExtend.Data4[1],
764 uuidExtend.Data4[2], uuidExtend.Data4[3],
765 uuidExtend.Data4[4], uuidExtend.Data4[5],
766 uuidExtend.Data4[6], uuidExtend.Data4[7]);
767 u32VariableOffset += 16;
768 } else {
769 u32VariableOffset = dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
770 hf_dcom_extent_id, &uuidExtend);
774 u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
775 &u32ArraySize2);
776 u32VariableOffset = dissect_dcom_nospec_data(tvb, u32VariableOffset, pinfo, sub_tree, drep, u32ArraySize2);
778 /* update subtree header */
779 if(uuid_name != NULL) {
780 proto_item_append_text(sub_item, "[%u]: %s, Bytes=%u",
781 u32Idx, uuid_name, u32ArraySize2);
782 } else {
783 proto_item_append_text(sub_item, "[%u]: Bytes=%u",
784 u32Idx, u32ArraySize2);
786 proto_item_set_len(sub_item, offset - u32SubStart);
787 } else {
788 /* update subtree header */
789 proto_item_append_text(sub_item, "[%u]: NULL", u32Idx);
790 proto_item_set_len(sub_item, offset - u32SubStart);
793 u32Idx++;
796 return u32VariableOffset;
800 /* dissect DCOM "this" (start of every DCOM request) */
802 dissect_dcom_this(tvbuff_t *tvb, int offset,
803 packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
805 guint16 u16VersionMajor;
806 guint16 u16VersionMinor;
807 guint32 u32Flags;
808 guint32 u32Res;
809 e_uuid_t uuidCausality;
810 proto_item *sub_item;
811 proto_tree *sub_tree;
812 guint32 u32SubStart;
813 proto_item *pi;
815 sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
816 "DCOM, ORPCThis");
817 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_this);
819 offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, sub_tree, di, drep,
820 &u16VersionMajor, &u16VersionMinor);
821 u32SubStart = offset - 4;
823 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
824 hf_dcom_this_flags, &u32Flags);
825 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
826 hf_dcom_this_res, &u32Res);
828 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
829 hf_dcom_this_cid, &uuidCausality);
831 offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep);
833 /* update subtree header */
834 proto_item_append_text(sub_item, ", V%u.%u, Causality ID: %s",
835 u16VersionMajor, u16VersionMinor, guids_resolve_uuid_to_str(&uuidCausality));
836 proto_item_set_len(sub_item, offset - u32SubStart);
838 if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
839 pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
840 (e_guid_t *) &di->call_data->object_uuid,
841 "Object UUID/IPID: %s", guids_resolve_uuid_to_str(&di->call_data->object_uuid));
842 PROTO_ITEM_SET_GENERATED(pi);
845 return offset;
849 /* dissect DCOM "that" (start of every DCOM response) */
851 dissect_dcom_that(tvbuff_t *tvb, int offset,
852 packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) {
853 guint32 u32Flags;
854 proto_item *sub_item;
855 proto_tree *sub_tree;
856 guint32 u32SubStart;
857 proto_item *pi;
859 sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
860 "DCOM, ORPCThat");
861 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_that);
863 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
864 hf_dcom_that_flags, &u32Flags);
865 u32SubStart = offset - 4;
867 offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep);
869 /* update subtree header */
870 proto_item_set_len(sub_item, offset - u32SubStart);
872 if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
873 pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
874 (e_guid_t *) &di->call_data->object_uuid,
875 "Object UUID/IPID: %s", guids_resolve_uuid_to_str(&di->call_data->object_uuid));
876 PROTO_ITEM_SET_GENERATED(pi);
879 return offset;
883 /* dissect simple dcom request, DCOM "this" only */
885 dissect_dcom_simple_rqst(tvbuff_t *tvb, int offset,
886 packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
889 offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep);
891 return offset;
895 /* dissect simple dcom response, DCOM "that" and returned HRESULT only */
897 dissect_dcom_simple_resp(tvbuff_t *tvb, int offset,
898 packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
900 guint32 u32HResult;
903 offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);
905 offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
906 &u32HResult);
908 col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
909 val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
912 return offset;
916 /* dissect a dcerpc array size */
918 dissect_dcom_dcerpc_array_size(tvbuff_t *tvb, gint offset, packet_info *pinfo,
919 proto_tree *tree, dcerpc_info *di, guint8 *drep, guint32 *pu32ArraySize)
923 /* en-/disable this by preference setting */
924 if (!dcom_prefs_display_unmarshalling_details) {
925 /* this will read in the data, but prevent output to tree */
926 tree = NULL;
929 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
930 hf_dcom_array_size, pu32ArraySize);
932 return offset;
936 /* dissect a dcerpc pointer value */
938 dissect_dcom_dcerpc_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
939 proto_tree *tree, dcerpc_info *di, guint8 *drep, guint32 *pu32Pointer)
942 /* en-/disable this by preference setting */
943 if (!dcom_prefs_display_unmarshalling_details) {
944 /* this will read in the data, but prevent output to tree */
945 tree = NULL;
948 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
949 hf_dcom_pointer_val, pu32Pointer);
951 return offset;
955 /* mark data as "ToBeDone" */
956 /* XXX: handout data to generic "unknown data" dissector? */
957 extern int
958 dissect_dcom_tobedone_data(tvbuff_t *tvb, int offset,
959 packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, int length)
961 proto_item *item;
964 item = proto_tree_add_item(tree, hf_dcom_tobedone, tvb, offset, length, ENC_NA);
965 PROTO_ITEM_SET_GENERATED(item);
966 expert_add_info(pinfo, item, &ei_dcom_dissetion_incomplete);
968 offset += length;
970 return offset;
974 /* mark data as "No Specification Available" */
975 /* XXX: handout data to generic "unknown data" dissector? */
976 extern int
977 dissect_dcom_nospec_data(tvbuff_t *tvb, int offset,
978 packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, int length)
980 proto_item *item;
983 item = proto_tree_add_item(tree, hf_dcom_nospec, tvb, offset, length, ENC_NA);
984 PROTO_ITEM_SET_GENERATED(item);
985 expert_add_info(pinfo, item, &ei_dcom_no_spec);
987 offset += length;
989 return offset;
993 /* dissect an indexed WORD, something like: "FieldName[1]: 0x1234" */
995 dissect_dcom_indexed_WORD(tvbuff_t *tvb, int offset, packet_info *pinfo,
996 proto_tree *tree, dcerpc_info *di, guint8 *drep,
997 int hfindex, guint16 * pu16WORD, int field_index)
999 guint16 u16WORD;
1002 /* dissect the WORD, but don't add to tree */
1003 dissect_dcom_WORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1004 hfindex, &u16WORD);
1006 if (tree) {
1007 /* special formatted output of indexed value */
1008 proto_tree_add_uint_format(tree, hfindex, tvb, offset, 2, u16WORD,
1009 "%s[%u]: 0x%04x",
1010 proto_registrar_get_name(hfindex),
1011 field_index, u16WORD);
1014 offset += 2;
1016 if (pu16WORD)
1017 *pu16WORD = u16WORD;
1019 return offset;
1023 /* dissect an indexed DWORD, something like: "FieldName[1]: 0x12345678" */
1025 dissect_dcom_indexed_DWORD(tvbuff_t *tvb, int offset, packet_info *pinfo,
1026 proto_tree *tree, dcerpc_info *di, guint8 *drep,
1027 int hfindex, guint32 * pu32DWORD, int field_index)
1029 guint32 u32DWORD;
1032 /* dissect the DWORD, but don't add to tree */
1033 dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1034 hfindex, &u32DWORD);
1036 if (tree) {
1037 /* special formatted output of indexed value */
1038 proto_tree_add_uint_format(tree, hfindex, tvb, offset, 4, u32DWORD,
1039 "%s[%u]: 0x%08x",
1040 proto_registrar_get_name(hfindex),
1041 field_index, u32DWORD);
1044 offset += 4;
1046 if (pu32DWORD)
1047 *pu32DWORD = u32DWORD;
1049 return offset;
1053 /* dissect hresult field of a usual DCOM call (create "raw" item) */
1055 dissect_dcom_HRESULT_item(tvbuff_t *tvb, int offset, packet_info *pinfo,
1056 proto_tree *tree, dcerpc_info *di, guint8 *drep,
1057 guint32 * pu32HResult, int field_index, proto_item **item)
1059 guint32 u32HResult;
1061 /* dissect the DWORD, but don't add to tree */
1062 offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1063 field_index, &u32HResult);
1065 if (tree) {
1066 /* special formatted output of indexed value */
1067 *item = proto_tree_add_item (tree, field_index, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
1070 if (pu32HResult)
1071 *pu32HResult = u32HResult;
1073 return offset;
1077 /* dissect hresult field of a usual DCOM call (separate method, because often used) */
1079 dissect_dcom_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1080 proto_tree *tree, dcerpc_info *di, guint8 *drep,
1081 guint32 * pu32HResult)
1083 guint32 u32HResult;
1084 proto_item *item = NULL;
1086 /* dissect the DWORD, but don't add to tree */
1087 offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1088 hf_dcom_hresult, &u32HResult);
1090 if (tree) {
1091 /* special formatted output of indexed value */
1092 item = proto_tree_add_item (tree, hf_dcom_hresult, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
1095 /* expert info only if severity is set */
1096 /* XXX - move this to the callers of this function, to provide a more detailed error output */
1097 if(u32HResult & 0x80000000) {
1098 expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s",
1099 val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
1101 if (pu32HResult)
1102 *pu32HResult = u32HResult;
1104 return offset;
1108 /* partial results of indexed DCOM subcalls (e.g.: from a kind of array) */
1110 dissect_dcom_indexed_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1111 proto_tree *tree, dcerpc_info *di, guint8 *drep,
1112 guint32 * pu32HResult, int field_index)
1114 guint32 u32HResult;
1115 proto_item *item = NULL;
1118 /* dissect the DWORD, but don't add to tree */
1119 offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
1120 hf_dcom_hresult, &u32HResult);
1122 if (tree) {
1123 /* special formatted output of indexed value */
1124 item = proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset-4, 4, u32HResult,
1125 "HResult[%u]: %s (0x%08x)", field_index,
1126 val_to_str_const(u32HResult, dcom_hresult_vals, "Unknown"),
1127 u32HResult);
1129 /* expert info only if severity flag is set */
1130 /* XXX - move this to the callers of this function, to provide a more detailed error output */
1131 if(u32HResult & 0x80000000) {
1132 expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s",
1133 val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
1135 if (pu32HResult)
1136 *pu32HResult = u32HResult;
1138 return offset;
1144 dissect_dcom_COMVERSION(tvbuff_t *tvb, int offset, packet_info *pinfo,
1145 proto_tree *tree, dcerpc_info *di, guint8 *drep,
1146 guint16 * pu16VersionMajor, guint16 * pu16VersionMinor)
1149 offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1150 hf_dcom_version_major, pu16VersionMajor);
1151 offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1152 hf_dcom_version_minor, pu16VersionMinor);
1154 return offset;
1159 dissect_dcom_SAFEARRAY(tvbuff_t *tvb, int offset, packet_info *pinfo,
1160 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex _U_, sa_callback_t sacb)
1162 guint32 u32Dims;
1163 guint16 u16Dims;
1164 guint16 u16Features;
1165 guint32 u32ElementSize;
1166 guint32 u32VarType;
1167 guint32 u32Elements;
1168 guint32 u32Pointer;
1169 guint32 u32BoundElements;
1170 guint32 u32LowBound;
1171 gchar cData[100];
1172 guint32 u32ArraySize;
1173 guint32 u32VariableOffset;
1174 guint32 u32Data;
1175 guint16 u16Data;
1176 guint8 u8Data;
1177 guint16 u16Locks;
1178 guint16 u16VarType;
1179 proto_item *sub_item;
1180 proto_tree *sub_tree;
1181 guint32 u32SubStart;
1182 guint32 u32TmpOffset;
1184 proto_item *feature_item;
1185 proto_tree *feature_tree;
1188 /* XXX: which alignment do we need here? */
1190 sub_item = proto_tree_add_item(tree, hf_dcom_safearray, tvb, offset, 0, ENC_NA);
1191 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_safearray);
1192 u32SubStart = offset;
1194 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1195 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1197 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1198 hf_dcom_sa_dims32, &u32Dims);
1199 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1200 hf_dcom_sa_dims16, &u16Dims);
1202 /* feature flags */
1203 u32TmpOffset = dissect_dcom_WORD(tvb, offset, pinfo, NULL, di, drep,
1204 hf_dcom_sa_features, &u16Features);
1205 feature_item = proto_tree_add_uint (sub_tree, hf_dcom_sa_features, tvb, offset, 2, u16Features);
1206 feature_tree = proto_item_add_subtree (feature_item, ett_dcom_sa_features);
1207 if (feature_tree) {
1208 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_variant, tvb, offset, 2, u16Features);
1209 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_dispatch, tvb, offset, 2, u16Features);
1210 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_unknown, tvb, offset, 2, u16Features);
1211 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_bstr, tvb, offset, 2, u16Features);
1212 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_have_vartype, tvb, offset, 2, u16Features);
1213 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_have_iid, tvb, offset, 2, u16Features);
1214 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_record, tvb, offset, 2, u16Features);
1215 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_fixedsize, tvb, offset, 2, u16Features);
1216 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_embedded, tvb, offset, 2, u16Features);
1217 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_static, tvb, offset, 2, u16Features);
1218 proto_tree_add_boolean (feature_tree, hf_dcom_sa_features_auto, tvb, offset, 2, u16Features);
1220 offset = u32TmpOffset;
1222 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1223 hf_dcom_sa_element_size, &u32ElementSize);
1224 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1225 hf_dcom_sa_locks, &u16Locks);
1226 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1227 hf_dcom_sa_vartype16, &u16VarType);
1228 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1229 hf_dcom_sa_vartype32, &u32VarType);
1230 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1231 hf_dcom_sa_elements, &u32Elements);
1232 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1234 u32BoundElements = 0;
1235 while(u32Dims--) {
1236 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1237 hf_dcom_sa_bound_elements, &u32BoundElements);
1238 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1239 hf_dcom_sa_low_bound, &u32LowBound);
1242 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize);
1244 tvb_ensure_bytes_exist(tvb, offset, u32ArraySize * u32ElementSize);
1245 u32VariableOffset = offset + u32ArraySize * u32ElementSize;
1247 if(sacb) {
1248 sacb(tvb, offset, pinfo, tree, di, drep, u32VarType, u32ArraySize);
1251 while(u32ArraySize--) {
1252 switch(u32VarType) {
1253 case(WIRESHARK_VT_ERROR):
1254 offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
1255 &u32Data);
1256 break;
1257 case(WIRESHARK_VT_I1):
1258 offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1259 hf_dcom_vt_i1, &u8Data);
1260 break;
1261 case(WIRESHARK_VT_I2):
1262 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1263 hf_dcom_vt_i2, &u16Data);
1264 break;
1265 case(WIRESHARK_VT_I4):
1266 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1267 hf_dcom_vt_i4, &u32Data);
1268 break;
1269 case(WIRESHARK_VT_I8):
1270 offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
1271 hf_dcom_vt_i8, NULL);
1272 /* take care of the 8 byte alignment */
1273 u32VariableOffset = offset;
1274 break;
1275 case(WIRESHARK_VT_BSTR):
1276 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1277 if (u32Pointer) {
1278 u32VariableOffset = dissect_dcom_BSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
1279 hf_dcom_vt_bstr, cData, sizeof(cData) );
1281 break;
1282 default:
1283 /* XXX: other types possible, but still not implemented:
1284 VT_UNKNOWN
1285 VT_DISPATCH
1286 VT_VARIANT
1287 VT_RECORD
1288 VT_UNKNOWN|VT_RESERVED
1290 u32VariableOffset = dissect_dcom_tobedone_data(tvb, u32VariableOffset, pinfo, sub_tree, drep,
1291 10000);
1295 /* update subtree header */
1296 proto_item_append_text(sub_item, ": Elements: %u/%u VarType: %s",
1297 u32Elements, u32BoundElements,
1298 val_to_str(u32VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
1300 proto_item_set_len(sub_item, u32VariableOffset - u32SubStart);
1302 return u32VariableOffset;
1308 dissect_dcom_VARTYPE(tvbuff_t *tvb, int offset, packet_info *pinfo,
1309 proto_tree *tree, dcerpc_info *di, guint8 *drep,
1310 guint16 *pu16VarType)
1313 offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
1314 hf_dcom_variant_type, pu16VarType);
1316 return offset;
1321 dissect_dcom_VARIANT(tvbuff_t *tvb, int offset, packet_info *pinfo,
1322 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex)
1324 guint32 u32Size;
1325 guint32 u32RPCRes;
1326 guint16 u16Res;
1327 guint32 u32SubStart;
1328 proto_item *sub_item;
1329 proto_tree *sub_tree;
1330 guint16 u16VarType;
1331 guint32 u32VarType;
1333 guint8 u8Data;
1334 guint16 u16Data;
1335 guint32 u32Data;
1336 gchar cData[500];
1337 guint32 u32Pointer;
1338 gfloat f32Data;
1339 gdouble f64Data;
1342 /* alignment of 8 needed for a VARIANT */
1343 if (offset % 8) {
1344 offset += 8 - (offset % 8);
1347 sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
1348 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_variant);
1349 u32SubStart = offset;
1351 /* the following size can be VERY confusing:
1352 * It is NOT the maximum size of the variant, as one could expect,
1353 * but the current size of the variant padded to 8 bytes.
1354 * BUT: The following data does not start AFTER this padding,
1355 * it starts just after the variant-data (without padding)!!! */
1356 /* Conclusion: the size given here can be LONGER than the actual size */
1357 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1358 hf_dcom_variant_size, &u32Size);
1359 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1360 hf_dcom_variant_rpc_res, &u32RPCRes);
1361 offset = dissect_dcom_VARTYPE(tvb, offset, pinfo, sub_tree, di, drep,
1362 &u16VarType);
1363 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1364 hf_dcom_variant_wres, &u16Res);
1365 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1366 hf_dcom_variant_wres, &u16Res);
1367 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1368 hf_dcom_variant_wres, &u16Res);
1370 /* 32 bit VarType (slightly different to the 16 bit one) */
1371 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1372 hf_dcom_variant_type32, &u32VarType);
1374 if (u32VarType & WIRESHARK_VT_BYREF) {
1375 u32VarType &=~WIRESHARK_VT_BYREF;
1376 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1379 switch (u32VarType) {
1380 case(WIRESHARK_VT_EMPTY):
1381 break;
1382 case(WIRESHARK_VT_BOOL):
1383 offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, sub_tree, di, drep,
1384 hf_dcom_vt_bool, &u16Data);
1385 break;
1386 case(WIRESHARK_VT_I1):
1387 offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1388 hf_dcom_vt_i1, &u8Data);
1389 break;
1390 case(WIRESHARK_VT_UI1):
1391 offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
1392 hf_dcom_vt_ui1, &u8Data);
1393 break;
1394 case(WIRESHARK_VT_I2):
1395 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1396 hf_dcom_vt_i2, &u16Data);
1397 break;
1398 case(WIRESHARK_VT_UI2):
1399 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1400 hf_dcom_vt_ui2, &u16Data);
1401 break;
1402 case(WIRESHARK_VT_I4):
1403 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1404 hf_dcom_vt_i4, &u32Data);
1405 break;
1406 case(WIRESHARK_VT_UI4):
1407 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1408 hf_dcom_vt_ui4, &u32Data);
1409 break;
1410 case(WIRESHARK_VT_R4):
1411 offset = dissect_dcom_FLOAT(tvb, offset, pinfo, sub_tree, di, drep,
1412 hf_dcom_vt_r4, &f32Data);
1413 break;
1414 case(WIRESHARK_VT_R8):
1415 offset = dissect_dcom_DOUBLE(tvb, offset, pinfo, sub_tree, di, drep,
1416 hf_dcom_vt_r8, &f64Data);
1417 break;
1418 case(WIRESHARK_VT_DATE):
1419 offset = dissect_dcom_DATE(tvb, offset, pinfo, sub_tree, di, drep,
1420 hf_dcom_vt_date, &f64Data);
1421 break;
1422 case(WIRESHARK_VT_BSTR):
1423 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1424 if (u32Pointer) {
1425 offset = dissect_dcom_BSTR(tvb, offset, pinfo, sub_tree, di, drep,
1426 hf_dcom_vt_bstr, cData, sizeof(cData) );
1428 break;
1429 case(WIRESHARK_VT_DISPATCH):
1430 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1431 if (u32Pointer) {
1432 offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, sub_tree, di, drep,
1433 hf_dcom_vt_dispatch, NULL); /* XXX - how to handle this? */
1435 break;
1436 case(WIRESHARK_VT_ARRAY):
1437 offset = dissect_dcom_SAFEARRAY(tvb, offset, pinfo, sub_tree, di, drep,
1438 0, NULL);
1439 break;
1440 case(WIRESHARK_VT_ERROR):
1441 offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
1443 break;
1444 case(WIRESHARK_VT_VARIANT):
1445 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1446 if (u32Pointer) {
1447 offset = dissect_dcom_VARIANT(tvb, offset, pinfo, sub_tree, di, drep,
1448 hf_dcom_vt_byref /* must be BYREF */);
1450 break;
1451 case(WIRESHARK_VT_UNKNOWN):
1452 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
1453 break;
1454 default:
1455 /* XXX: add more types here! */
1456 offset = dissect_dcom_tobedone_data(tvb, offset, pinfo, sub_tree, drep,
1457 10000);
1460 /* update subtree header */
1461 proto_item_append_text(sub_item, ": %s",
1462 val_to_str(u16VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
1464 proto_item_set_len(sub_item, offset - u32SubStart);
1466 return offset;
1471 dissect_dcom_UUID(tvbuff_t *tvb, int offset,
1472 packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep,
1473 int hfindex, e_uuid_t *pdata)
1475 const gchar *uuid_name;
1476 header_field_info *hfi;
1477 e_uuid_t uuid;
1480 /* get the UUID, but don't put it into the tree */
1481 offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep,
1482 hfindex, &uuid);
1484 /* add to the tree */
1485 hfi = proto_registrar_get_nth(hfindex);
1486 uuid_name = guids_get_uuid_name(&uuid);
1487 if(uuid_name) {
1488 proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
1489 "%s: %s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
1490 hfi->name, uuid_name,
1491 uuid.Data1, uuid.Data2, uuid.Data3,
1492 uuid.Data4[0], uuid.Data4[1],
1493 uuid.Data4[2], uuid.Data4[3],
1494 uuid.Data4[4], uuid.Data4[5],
1495 uuid.Data4[6], uuid.Data4[7]);
1496 } else {
1497 proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
1498 "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1499 hfi->name,
1500 uuid.Data1, uuid.Data2, uuid.Data3,
1501 uuid.Data4[0], uuid.Data4[1],
1502 uuid.Data4[2], uuid.Data4[3],
1503 uuid.Data4[4], uuid.Data4[5],
1504 uuid.Data4[6], uuid.Data4[7]);
1507 if(pdata != NULL) {
1508 *pdata = uuid;
1511 return offset;
1516 dissect_dcom_append_UUID(tvbuff_t *tvb, int offset,
1517 packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep,
1518 int hfindex, int field_index, e_uuid_t *uuid)
1520 const gchar *uuid_name;
1521 proto_item *pi;
1522 header_field_info *hfi;
1525 /* XXX - this is far from being performance optimized! */
1527 /* get the UUID, but don't put it into the tree */
1528 offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep,
1529 hfindex, uuid);
1531 /* look for a registered uuid name */
1532 uuid_name = guids_get_uuid_name(uuid);
1534 /* add to the tree */
1535 hfi = proto_registrar_get_nth(hfindex);
1536 pi = proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) uuid, "%s", hfi->name);
1538 if (field_index != -1) {
1539 proto_item_append_text(pi, "[%u]: ", field_index);
1540 } else {
1541 proto_item_append_text(pi, ": ");
1544 if(uuid_name) {
1545 proto_item_append_text(pi, "%s (", uuid_name);
1548 proto_item_append_text(pi, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1549 uuid->Data1, uuid->Data2, uuid->Data3,
1550 uuid->Data4[0], uuid->Data4[1],
1551 uuid->Data4[2], uuid->Data4[3],
1552 uuid->Data4[4], uuid->Data4[5],
1553 uuid->Data4[6], uuid->Data4[7]);
1555 if(uuid_name) {
1556 proto_item_append_text(pi, ")");
1559 /* update column info now */
1560 if (field_index != -1) {
1561 col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]=%s",
1562 hfi->name, field_index, (uuid_name) ? uuid_name : "???");
1563 } else {
1564 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%s",
1565 hfi->name, (uuid_name) ? uuid_name : "???");
1568 return offset;
1572 /* get a wide character string from tvb (zero terminated or limited through inLength) */
1573 /* the string will be converted to ASCII if possible or simple hexdump otherwise */
1574 /* outLength is in output bytes including zero termination output */
1575 static int
1576 dcom_tvb_get_nwstringz0(tvbuff_t *tvb, gint offset, guint32 inLength, gchar *pszStr, guint32 outLength, gboolean *isPrintable)
1578 guint32 u32Idx;
1579 guint32 u32IdxA;
1580 guint32 u32IdxW;
1582 guint8 u8Tmp1;
1583 guint8 u8Tmp2;
1586 *isPrintable = TRUE;
1588 /* we must have at least the space for the zero termination */
1589 DISSECTOR_ASSERT(outLength >= 1);
1591 /* determine length and printablility of the string */
1592 for(u32Idx = 0; u32Idx < inLength-1; u32Idx+=2) {
1593 /* the marshalling direction of a WCHAR is fixed! */
1594 u8Tmp1 = tvb_get_guint8(tvb, offset+u32Idx);
1595 u8Tmp2 = tvb_get_guint8(tvb, offset+u32Idx+1);
1597 /* is this the zero termination? */
1598 if (u8Tmp1 == 0 && u8Tmp2 == 0) {
1599 u32Idx+=2;
1600 break;
1603 /* is this character printable? */
1604 /* XXX - there are probably more printable chars than isprint() */
1605 if(!isprint(u8Tmp1) || u8Tmp2 != 0) {
1606 *isPrintable = FALSE;
1610 /* u32Idx now contains the string length in bytes */
1611 /* (including optional zero termination) */
1613 /* if this is a printable string? */
1614 if(*isPrintable == TRUE) {
1615 /* convert to ascii (every "2nd char") */
1616 /* XXX - is it possible to convert to UTF8, so the output functions work with it? */
1617 for(u32IdxA = 0, u32IdxW = 0;
1618 u32IdxW < u32Idx && u32IdxA < outLength-2;
1619 u32IdxW+=2, u32IdxA++) {
1620 pszStr[u32IdxA] = tvb_get_guint8(tvb, offset+u32IdxW);
1622 } else {
1623 /* convert to hexdump */
1624 for(u32IdxA = 0, u32IdxW = 0;
1625 u32IdxW < u32Idx && u32IdxA < outLength-2;
1626 u32IdxW++, u32IdxA+=2) {
1627 g_snprintf(&pszStr[u32IdxA], 3, "%02X", tvb_get_guint8(tvb, offset+u32IdxW));
1631 /* zero terminate the string, space must be available */
1632 DISSECTOR_ASSERT(u32IdxA < outLength);
1633 pszStr[u32IdxA] = 0;
1635 return offset + u32Idx;
1639 /* dissect a LPWSTR into a given buffer */
1640 /* use FT_STRING for hfindex */
1641 /* u32MaxStr is maximum length of string (including trailing zero) */
1643 dissect_dcom_indexed_LPWSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1644 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex,
1645 gchar *pszStr, guint32 u32MaxStr, int field_index)
1647 guint32 u32MaxCount;
1648 guint32 u32Offset;
1649 guint32 u32ArraySize;
1650 guint32 u32StrStart;
1651 proto_item *sub_item;
1652 proto_tree *sub_tree;
1653 guint32 u32SubStart;
1654 gboolean isPrintable;
1657 /* alignment of 4 needed */
1658 if (offset % 4) {
1659 offset += 4 - (offset % 4);
1662 /* add subtree item */
1663 sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
1664 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
1665 u32SubStart = offset;
1667 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1668 hf_dcom_max_count, &u32MaxCount);
1669 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1670 hf_dcom_offset, &u32Offset);
1671 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep,
1672 &u32ArraySize);
1674 u32StrStart = offset;
1675 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1677 proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszStr);
1679 /* update subtree header */
1680 if (field_index != -1) {
1681 proto_item_set_text(sub_item, "%s[%u]: %s%s%s",
1682 proto_registrar_get_name(hfindex),
1683 field_index,
1684 isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1685 } else {
1686 proto_item_append_text(sub_item, "%s%s%s",
1687 isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1689 proto_item_set_len(sub_item, offset - u32SubStart);
1691 return offset;
1696 dissect_dcom_LPWSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1697 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex,
1698 gchar *pszStr, guint32 u32MaxStr)
1702 return dissect_dcom_indexed_LPWSTR(tvb, offset, pinfo, tree, di, drep,
1703 hfindex, pszStr, u32MaxStr, -1);
1707 /* dissect a BSTR to tree and into a given buffer (use FT_STRING for hfindex) */
1708 /* u32MaxStr is maximum length of string (including trailing zero) */
1709 /* (Hint: the BSTR space is always as long as the maximum size) */
1711 dissect_dcom_BSTR(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1712 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex,
1713 gchar *pszStr, guint32 u32MaxStr)
1715 guint32 u32MaxCount;
1716 guint32 u32ArraySize;
1717 guint32 u32StrStart;
1718 proto_item *sub_item;
1719 proto_tree *sub_tree;
1720 guint32 u32SubStart;
1721 guint32 u32ByteLength;
1722 guint32 u32RealOffset;
1723 gboolean isPrintable;
1725 /* alignment of 4 needed */
1726 if (offset % 4) {
1727 offset += 4 - (offset % 4);
1730 /* add subtree item */
1731 sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
1732 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
1733 u32SubStart = offset;
1735 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1736 hf_dcom_max_count, &u32MaxCount);
1737 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1738 hf_dcom_byte_length, &u32ByteLength);
1739 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep,
1740 &u32ArraySize);
1742 u32RealOffset = offset + u32ArraySize*2;
1744 u32StrStart = offset;
1745 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
1747 proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszStr);
1749 /* update subtree header */
1750 proto_item_append_text(sub_item, "%s%s%s",
1751 isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
1752 if ((int) (u32RealOffset - u32SubStart) <= 0)
1753 THROW(ReportedBoundsError);
1754 proto_item_set_len(sub_item, u32RealOffset - u32SubStart);
1756 return u32RealOffset;
1760 /* dissect an DUALSTRINGARRAY */
1762 dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1763 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex, gchar *ip)
1765 guint16 u16NumEntries;
1766 guint16 u16SecurityOffset;
1767 gchar szStr[1000];
1768 guint32 u32MaxStr = sizeof(szStr);
1769 guint32 u32Start;
1770 guint16 u16TowerId;
1771 guint16 u16SecurityAuthnSvc;
1772 guint16 u16SecurityAuthzSvc;
1773 proto_item *sub_item;
1774 proto_tree *sub_tree;
1775 guint32 u32SubStart;
1776 guint32 u32StringBindings = 0;
1777 guint32 u32SecurityBindings = 0;
1778 proto_item *subsub_item;
1779 proto_tree *subsub_tree;
1780 guint32 u32SubSubStart;
1781 gboolean isPrintable;
1782 guint32 first_ip = 0;
1783 guint32 curr_ip = 0;
1784 struct in_addr ipaddr;
1785 proto_item *pi;
1788 /* add subtree header */
1789 sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
1790 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_dualstringarray);
1792 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1793 hf_dcom_dualstringarray_num_entries, &u16NumEntries);
1794 /* from here, alignment is ok */
1795 u32SubStart = offset - 2;
1796 offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
1797 hf_dcom_dualstringarray_security_offset, &u16SecurityOffset);
1799 /* STRINGBINDINGs until first wchar zero */
1800 while ( tvb_get_ntohs(tvb, offset) ) {
1801 u32StringBindings++;
1803 subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_string, tvb, offset, 0, ENC_NA);
1804 subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
1805 u32SubSubStart = offset;
1807 offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1808 hf_dcom_dualstringarray_string_tower_id, &u16TowerId);
1809 u32Start = offset;
1810 /* we don't know the (zero terminated) input length, use the buffer length instead */
1811 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
1812 pi = proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_string_network_addr,
1813 tvb, u32Start, offset - u32Start, szStr);
1815 /* convert ip address (if it is dotted decimal) */
1816 /* XXX - this conversion is ugly */
1817 if (inet_aton(szStr, &ipaddr)) {
1818 if(get_host_ipaddr(szStr, &curr_ip)) {
1820 /*expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "DUALSTRINGARRAY: IP:%s",
1821 ip_to_str( (guint8 *) &curr_ip));*/
1823 if(first_ip == 0) {
1824 if(ip != NULL) {
1825 memcpy(ip, &curr_ip, sizeof(curr_ip));
1827 first_ip = curr_ip;
1828 } else {
1829 if(first_ip != curr_ip) {
1830 expert_add_info_format(pinfo, pi, &ei_dcom_dualstringarray_mult_ip,
1831 "DUALSTRINGARRAY: multiple IP's %s %s",
1832 ip_to_str( (guint8 *) &first_ip), ip_to_str( (guint8 *) &curr_ip));
1838 proto_item_append_text(subsub_item, "[%u]: TowerId=%s, NetworkAddr=\"%s\"",
1839 u32StringBindings,
1840 val_to_str(u16TowerId, dcom_protseq_vals, "Unknown (0x%04x"),
1841 szStr);
1842 proto_item_set_len(subsub_item, offset - u32SubSubStart);
1844 offset += 2;
1846 /* SECURITYBINDINGs until first wchar zero */
1847 while ( tvb_get_ntohs(tvb, offset) ) {
1848 u32SecurityBindings++;
1850 subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_security, tvb, offset, 0, ENC_NA);
1851 subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
1852 u32SubSubStart = offset;
1854 offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1855 hf_dcom_dualstringarray_security_authn_svc,
1856 &u16SecurityAuthnSvc);
1857 offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
1858 hf_dcom_dualstringarray_security_authz_svc,
1859 &u16SecurityAuthzSvc);
1861 u32Start = offset;
1862 /* we don't know the (zero terminated) input length, use the buffer length instead */
1863 offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
1864 proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_security_princ_name,
1865 tvb, u32Start, offset - u32Start, szStr);
1867 proto_item_append_text(subsub_item, "[%u]: AuthnSvc=0x%04x, AuthzSvc=0x%04x, PrincName=\"%s\"",
1868 u32SecurityBindings, u16SecurityAuthnSvc, u16SecurityAuthzSvc, szStr);
1869 proto_item_set_len(subsub_item, offset - u32SubSubStart);
1871 offset += 2;
1873 /* append info to subtree header */
1874 proto_item_append_text(sub_item, ": STRINGBINDINGs=%u, SECURITYBINDINGs=%u",
1875 u32StringBindings, u32SecurityBindings);
1876 proto_item_set_len(sub_item, offset - u32SubStart);
1878 return offset;
1882 /* dissect an STDOBJREF */
1884 dissect_dcom_STDOBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1885 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex _U_,
1886 guint64 *oxid, guint64 *oid, e_uuid_t *ipid)
1888 guint32 u32Flags;
1889 guint32 u32PublicRefs;
1890 proto_item *sub_item;
1891 proto_tree *sub_tree;
1892 guint32 u32SubStart;
1895 /* add subtree header */
1896 sub_item = proto_tree_add_item(tree, hf_dcom_stdobjref, tvb, offset, 0, ENC_NA);
1897 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_stdobjref);
1899 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1900 hf_dcom_stdobjref_flags, &u32Flags);
1901 /* from here, alignment is ok */
1902 u32SubStart = offset - 4;
1903 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
1904 hf_dcom_stdobjref_public_refs, &u32PublicRefs);
1905 offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep,
1906 hf_dcom_oxid, oxid);
1907 offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep,
1908 hf_dcom_oid, oid);
1909 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
1910 hf_dcom_ipid, ipid);
1912 /* append info to subtree header */
1913 proto_item_append_text(sub_item, ": PublicRefs=%u IPID=%s",
1914 u32PublicRefs, guids_resolve_uuid_to_str(ipid));
1915 proto_item_set_len(sub_item, offset - u32SubStart);
1917 return offset;
1924 *static void
1925 *print_uuid(const e_uuid_t* uuid)
1927 * proto_tree_add_debug_text(NULL, "UUID:(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)\n",
1928 * uuid->Data1, uuid->Data2, uuid->Data3,
1929 * uuid->Data4[0], uuid->Data4[1],
1930 * uuid->Data4[2], uuid->Data4[3],
1931 * uuid->Data4[4], uuid->Data4[5],
1932 * uuid->Data4[6], uuid->Data4[7]);
1934 * return;
1940 dcom_register_rountine(dcom_dissect_fn_t routine, e_uuid_t* uuid)
1942 dcom_marshaler_t *marshaler;
1945 /* check if exists already */
1946 if (dcom_get_rountine_by_uuid(uuid))
1947 return -1;
1949 marshaler = wmem_new(wmem_file_scope(), dcom_marshaler_t);
1950 if (!marshaler) {
1951 /*memory error*/
1952 return -1;
1955 marshaler->parent = NULL;
1956 marshaler->private_data = NULL;
1957 marshaler->uuid = *uuid;
1958 marshaler->routine = routine;
1960 dcom_marshalers = g_list_append(dcom_marshalers, marshaler);
1962 return 0;
1966 dcom_dissect_fn_t
1967 dcom_get_rountine_by_uuid(const e_uuid_t* uuid)
1969 dcom_marshaler_t *marsh;
1970 GList *marshalers;
1972 if(memcmp(uuid, &uuid_null, sizeof(uuid_null)) == 0) {
1973 return NULL;
1976 for(marshalers = dcom_marshalers; marshalers!= NULL;
1977 marshalers = g_list_next(marshalers)) {
1978 marsh = (dcom_marshaler_t *)marshalers->data;
1979 /*print_uuid(&marsh->uuid);*/
1980 /*print_uuid(uuid);*/
1981 if(memcmp(&marsh->uuid, uuid, sizeof(e_uuid_t)) == 0) {
1982 return marsh->routine;
1986 return NULL;
1989 /* dissect an CUSTOM */
1991 dissect_dcom_CUSTOBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1992 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex,
1993 e_uuid_t *clsid, e_uuid_t *iid)
1995 guint32 u32CBExtension;
1996 guint32 u32Size;
1997 guint32 u32SubStart;
1998 proto_item *sub_item;
1999 proto_tree *sub_tree;
2000 dcom_dissect_fn_t routine = NULL;
2003 /* add subtree header */
2004 hfindex = hf_dcom_custobjref;
2005 sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_NA);
2006 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_custobjref);
2008 u32SubStart = offset;
2009 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2010 hf_dcom_clsid, clsid);
2011 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2012 hf_dcom_objref_cbextension, &u32CBExtension);
2013 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2014 hf_dcom_objref_size, &u32Size);
2016 /* the following data depends on the iid, get the routine by iid */
2017 routine = dcom_get_rountine_by_uuid(iid);
2018 if (routine){
2019 offset = routine(tvb, offset, pinfo, sub_tree, di, drep, 0);
2022 /* append info to subtree header */
2023 /* proto_item_append_text(sub_item, ": ActivationPropertiesIn"); */
2024 proto_item_set_len(sub_item, offset - u32SubStart);
2026 return offset;
2029 /* dissect an OBJREF */
2031 dissect_dcom_OBJREF(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2032 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex, dcom_interface_t **interf)
2034 guint32 u32Signature;
2035 guint32 u32Flags;
2036 e_uuid_t iid;
2037 e_uuid_t clsid;
2038 proto_item *sub_item;
2039 proto_tree *sub_tree;
2040 guint32 u32SubStart;
2041 guint64 oxid;
2042 guint64 oid;
2043 e_uuid_t ipid;
2044 dcom_interface_t *dcom_if = NULL;
2045 gchar ip[4];
2047 memset(&ipid, 0, sizeof(ipid));
2049 /* add subtree header */
2050 sub_item = proto_tree_add_item(tree, hf_dcom_objref, tvb, offset, 0, ENC_NA);
2051 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_objref);
2053 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2054 hf_dcom_objref_signature, &u32Signature);
2055 /* from here, alignment is ok */
2056 u32SubStart = offset - 4;
2057 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2058 hf_dcom_objref_flags, &u32Flags);
2059 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2060 hf_dcom_iid, &iid);
2062 switch(u32Flags) {
2063 case(0x1): /* standard */
2064 offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2065 &oxid, &oid, &ipid);
2066 offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep,
2067 hf_dcom_objref_resolver_address, ip);
2068 break;
2069 case(0x2): /* handler (untested) */
2070 offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2071 &oxid, &oid, &iid);
2072 offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
2073 hf_dcom_clsid, &clsid);
2074 offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep,
2075 hf_dcom_objref_resolver_address, ip);
2076 break;
2077 case(0x4): /* custom */
2078 offset = dissect_dcom_CUSTOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
2079 &clsid, &iid);
2080 break;
2083 if(u32Flags == 0x1 || u32Flags == 0x2) {
2084 /* add interface instance to database (we currently only handle IPv4) */
2085 if(pinfo->net_src.type == AT_IPv4) {
2086 dcom_if = dcom_interface_new(pinfo,
2087 (guint8 *) ip,
2088 &iid, oxid, oid, &ipid);
2092 if(interf != NULL) {
2093 *interf = dcom_if;
2096 /* append info to subtree header */
2097 proto_item_set_len(sub_item, offset - u32SubStart);
2099 return offset;
2102 /* dissect an MInterfacePointer */
2104 dissect_dcom_MInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2105 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex, dcom_interface_t **interf)
2107 guint32 u32CntData;
2108 guint32 u32ArraySize;
2109 proto_item *sub_item;
2110 proto_tree *sub_tree;
2111 guint32 u32SubStart;
2114 if (!hfindex) {
2115 hfindex = hf_dcom_interface_pointer;
2118 /* add subtree header */
2119 sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
2120 sub_tree = proto_item_add_subtree(sub_item, ett_dcom_interface_pointer);
2122 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize);
2123 u32SubStart = offset - 4; /* should use this trick to deal with align pad if any */
2125 offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
2126 hf_dcom_ip_cnt_data, &u32CntData);
2128 offset = dissect_dcom_OBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex, interf);
2130 /* append info to subtree header */
2131 proto_item_set_len(sub_item, offset - u32SubStart);
2133 return offset;
2136 /* dissect a pointer to a MInterfacePointer */
2138 dissect_dcom_PMInterfacePointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2139 proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex, dcom_interface_t **interf)
2141 guint32 u32Pointer;
2144 offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
2146 if (u32Pointer) {
2147 offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, di, drep, hfindex, interf);
2148 } else {
2149 if(interf != NULL) {
2150 *interf = NULL;
2154 return offset;
2157 static void dcom_reinit( void) {
2159 if (dcom_machines != NULL) {
2160 GList *machines;
2162 for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
2163 dcom_machine_t *machine = (dcom_machine_t *)machines->data;
2165 if (machine->objects != NULL) {
2166 GList *objects;
2167 for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
2168 dcom_object_t *object = (dcom_object_t *)objects->data;
2170 if (object->interfaces != NULL) {
2171 GList *interface;
2172 for(interface = object->interfaces; interface != NULL; interface = g_list_next(interface)) {
2173 g_free(interface->data);
2174 interface->data = NULL; /* for good measure */
2176 g_list_free(object->interfaces);
2177 object->interfaces = NULL; /* for good measure */
2180 g_free(objects->data);
2181 objects->data = NULL; /* for good measure */
2183 g_list_free(machine->objects);
2184 machine->objects = NULL; /* for good measure */
2187 g_free(machines->data);
2188 machines->data = NULL; /* for good measure */
2190 g_list_free(dcom_machines);
2191 dcom_machines = NULL;
2194 /* The data in dcom_interfaces is se_alloc'd so there's no need to free
2195 * the data pointers.
2197 if (dcom_interfaces != NULL) {
2198 g_list_free(dcom_interfaces);
2199 dcom_interfaces = NULL;
2202 return;
2206 void
2207 proto_register_dcom (void)
2209 static hf_register_info hf_dcom_this_array[] = {
2210 #if 0
2211 { &hf_dcom_this_version_major,
2212 { "VersionMajor", "dcom.this.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2213 #endif
2214 #if 0
2215 { &hf_dcom_this_version_minor,
2216 { "VersionMinor", "dcom.this.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2217 #endif
2218 { &hf_dcom_this_flags,
2219 { "Flags", "dcom.this.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }},
2220 { &hf_dcom_this_res,
2221 { "Reserved", "dcom.this.res", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2222 { &hf_dcom_this_cid,
2223 { "Causality ID", "dcom.this.uuid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2226 static hf_register_info hf_dcom_that_array[] = {
2227 { &hf_dcom_that_flags,
2228 { "Flags", "dcom.that.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }}
2231 static hf_register_info hf_dcom_extent_array[] = {
2232 { &hf_dcom_extent,
2233 { "Extension", "dcom.extent", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2234 { &hf_dcom_extent_array_count,
2235 { "Extension Count", "dcom.extent.array_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2236 { &hf_dcom_extent_array_res,
2237 { "Reserved", "dcom.extent.array_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2238 { &hf_dcom_extent_size,
2239 { "Extension Size", "dcom.extent.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2240 { &hf_dcom_extent_id,
2241 { "Extension Id", "dcom.extent.id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2244 static hf_register_info hf_dcom_array[] = {
2245 { &hf_dcom_version_major,
2246 { "VersionMajor", "dcom.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2247 { &hf_dcom_version_minor,
2248 { "VersionMinor", "dcom.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2249 { &hf_dcom_hresult,
2250 { "HResult", "dcom.hresult", FT_UINT32, BASE_HEX, VALS(dcom_hresult_vals), 0x0, NULL, HFILL }},
2251 { &hf_dcom_max_count,
2252 { "MaxCount", "dcom.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2253 { &hf_dcom_offset,
2254 { "Offset", "dcom.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2255 { &hf_dcom_byte_length,
2256 { "ByteLength", "dcom.byte_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2257 #if 0
2258 { &hf_dcom_actual_count,
2259 { "ActualCount", "dcom.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2260 #endif
2261 { &hf_dcom_tobedone,
2262 { "To Be Done", "dcom.tobedone", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2263 { &hf_dcom_nospec,
2264 { "No Specification Available", "dcom.nospec", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2265 #if 0
2266 { &hf_dcom_variant,
2267 { "Variant", "dcom.variant", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2268 #endif
2269 { &hf_dcom_variant_type,
2270 { "VarType", "dcom.variant_type", FT_UINT16, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2271 { &hf_dcom_variant_type32,
2272 { "VarType32", "dcom.variant_type32", FT_UINT32, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2273 { &hf_dcom_variant_size,
2274 { "Size", "dcom.variant_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2275 { &hf_dcom_variant_rpc_res,
2276 { "RPC-Reserved", "dcom.variant_rpc_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2277 { &hf_dcom_variant_wres,
2278 { "Reserved", "dcom.variant_wres", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2279 { &hf_dcom_array_size,
2280 { "(ArraySize)", "dcom.array_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2281 { &hf_dcom_pointer_val,
2282 { "(PointerVal)", "dcom.pointer_val", FT_UINT32, BASE_HEX, VALS(dcom_dcerpc_pointer_vals), 0x0, NULL, HFILL }}
2285 static hf_register_info hf_dcom_interface_pointer_array[] = {
2286 { &hf_dcom_interface_pointer,
2287 { "InterfacePointer", "dcom.ifp", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2288 { &hf_dcom_ip_cnt_data,
2289 { "CntData", "dcom.ip_cnt_data", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
2292 static hf_register_info hf_dcom_objref_array[] = {
2293 { &hf_dcom_objref,
2294 { "OBJREF", "dcom.objref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2295 { &hf_dcom_objref_signature,
2296 { "Signature", "dcom.objref.signature", FT_UINT32, BASE_HEX, VALS(dcom_objref_signature_vals), 0x0, NULL, HFILL }},
2297 { &hf_dcom_objref_flags,
2298 { "Flags", "dcom.objref.flags", FT_UINT32, BASE_HEX, VALS(dcom_objref_flag_vals), 0x0, NULL, HFILL }},
2299 { &hf_dcom_iid,
2300 { "IID", "dcom.iid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2301 { &hf_dcom_clsid,
2302 { "CLSID", "dcom.clsid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2303 { &hf_dcom_objref_resolver_address,
2304 { "ResolverAddress", "dcom.objref.resolver_address", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2305 { &hf_dcom_objref_cbextension,
2306 { "CBExtension", "dcom.objref.cbextension", FT_UINT32, BASE_DEC, NULL, 0x0, "Size of extension data", HFILL }},
2307 { &hf_dcom_objref_size,
2308 { "Size", "dcom.objref.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
2311 static hf_register_info hf_dcom_stdobjref_array[] = {
2312 { &hf_dcom_stdobjref,
2313 { "STDOBJREF", "dcom.stdobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2314 { &hf_dcom_stdobjref_flags,
2315 { "Flags", "dcom.stdobjref.flags", FT_UINT32, BASE_HEX, VALS(dcom_stdobjref_flag_vals), 0x0, NULL, HFILL }},
2316 { &hf_dcom_stdobjref_public_refs,
2317 { "PublicRefs", "dcom.stdobjref.public_refs", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2318 { &hf_dcom_oxid,
2319 { "OXID", "dcom.oxid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2320 { &hf_dcom_oid,
2321 { "OID", "dcom.oid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2322 { &hf_dcom_ipid,
2323 { "IPID", "dcom.ipid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2326 static hf_register_info hf_dcom_custobjref_array[] = {
2327 { &hf_dcom_custobjref,
2328 { "CUSTOMOBJREF", "dcom.custobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2332 static hf_register_info hf_dcom_dualstringarray_array[] = {
2333 { &hf_dcom_dualstringarray_num_entries,
2334 { "NumEntries", "dcom.dualstringarray.num_entries", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2335 { &hf_dcom_dualstringarray_security_offset,
2336 { "SecurityOffset", "dcom.dualstringarray.security_offset", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2337 { &hf_dcom_dualstringarray_string,
2338 { "StringBinding", "dcom.dualstringarray.string", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2339 { &hf_dcom_dualstringarray_string_tower_id,
2340 { "TowerId", "dcom.dualstringarray.tower_id", FT_UINT16, BASE_HEX, VALS(dcom_protseq_vals), 0x0, NULL, HFILL }},
2341 { &hf_dcom_dualstringarray_string_network_addr,
2342 { "NetworkAddr", "dcom.dualstringarray.network_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2343 { &hf_dcom_dualstringarray_security,
2344 { "SecurityBinding", "dcom.dualstringarray.security", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2345 { &hf_dcom_dualstringarray_security_authn_svc,
2346 { "AuthnSvc", "dcom.dualstringarray.security_authn_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authn), 0x0, NULL, HFILL }},
2347 { &hf_dcom_dualstringarray_security_authz_svc,
2348 { "AuthzSvc", "dcom.dualstringarray.security_authz_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authz), 0x0, NULL, HFILL }},
2349 { &hf_dcom_dualstringarray_security_princ_name,
2350 { "PrincName", "dcom.dualstringarray.security_princ_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2353 static hf_register_info hf_dcom_vt_array[] = {
2354 { &hf_dcom_vt_bool,
2355 { "VT_BOOL", "dcom.vt.bool", FT_UINT16, BASE_HEX, VALS(dcom_vt_bool_vals), 0x0, NULL, HFILL }},
2356 { &hf_dcom_vt_i1,
2357 { "VT_I1", "dcom.vt.i1", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2358 { &hf_dcom_vt_i2,
2359 { "VT_I2", "dcom.vt.i2", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2360 { &hf_dcom_vt_i4,
2361 { "VT_I4", "dcom.vt.i4", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2362 { &hf_dcom_vt_i8,
2363 { "VT_I8", "dcom.vt.i8", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2364 { &hf_dcom_vt_ui1,
2365 { "VT_UI1", "dcom.vt.ui1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2366 { &hf_dcom_vt_ui2,
2367 { "VT_UI2", "dcom.vt.ui2", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2368 { &hf_dcom_vt_ui4,
2369 { "VT_UI4", "dcom.vt.ui4", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2370 { &hf_dcom_vt_r4,
2371 { "VT_R4", "dcom.vt.r4", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2372 { &hf_dcom_vt_r8,
2373 { "VT_R8", "dcom.vt.r8", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2374 { &hf_dcom_vt_date,
2375 { "VT_DATE", "dcom.vt.date", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2376 { &hf_dcom_vt_bstr,
2377 { "VT_BSTR", "dcom.vt.bstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2378 { &hf_dcom_vt_byref,
2379 { "BYREF", "dcom.vt.byref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2380 { &hf_dcom_vt_dispatch,
2381 { "VT_DISPATCH", "dcom.vt.dispatch", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}
2384 static hf_register_info hf_dcom_sa_array[] = {
2385 { &hf_dcom_safearray,
2386 { "SAFEARRAY", "dcom.sa", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2387 { &hf_dcom_sa_dims32,
2388 { "Dims32", "dcom.sa.dims32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2389 { &hf_dcom_sa_dims16,
2390 { "Dims16", "dcom.sa.dims16", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2391 { &hf_dcom_sa_features,
2392 { "Features", "dcom.sa.features", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2393 { &hf_dcom_sa_element_size,
2394 { "ElementSize", "dcom.sa.element_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2395 { &hf_dcom_sa_locks,
2396 { "Locks", "dcom.sa.locks", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2397 { &hf_dcom_sa_vartype32,
2398 { "VarType32", "dcom.sa.vartype", FT_UINT32, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2399 { &hf_dcom_sa_vartype16,
2400 { "VarType16", "dcom.sa.vartype", FT_UINT16, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
2401 { &hf_dcom_sa_elements,
2402 { "Elements", "dcom.sa.elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2403 { &hf_dcom_sa_bound_elements,
2404 { "BoundElements", "dcom.sa.bound_elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2405 { &hf_dcom_sa_low_bound,
2406 { "LowBound", "dcom.sa.low_bound", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2408 { &hf_dcom_sa_features_auto,
2409 { "AUTO", "dcom.sa.features_auto", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_AUTO, NULL, HFILL }},
2410 { &hf_dcom_sa_features_static,
2411 { "STATIC", "dcom.sa.features_static", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_STATIC, NULL, HFILL }},
2412 { &hf_dcom_sa_features_embedded,
2413 { "EMBEDDED", "dcom.sa.features_embedded", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_EMBEDDED, NULL, HFILL }},
2414 { &hf_dcom_sa_features_fixedsize,
2415 { "FIXEDSIZE", "dcom.sa.features_fixedsize", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_FIXEDSIZE, NULL, HFILL }},
2416 { &hf_dcom_sa_features_record,
2417 { "RECORD", "dcom.sa.features_record", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_RECORD, NULL, HFILL }},
2418 { &hf_dcom_sa_features_have_iid,
2419 { "HAVEIID", "dcom.sa.features_have_iid", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEIID, NULL, HFILL }},
2420 { &hf_dcom_sa_features_have_vartype,
2421 { "HAVEVARTYPE", "dcom.sa.features_have_vartype", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEVARTYPE, NULL, HFILL }},
2422 { &hf_dcom_sa_features_bstr,
2423 { "BSTR", "dcom.sa.features_bstr", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_BSTR, NULL, HFILL }},
2424 { &hf_dcom_sa_features_unknown,
2425 { "UNKNOWN", "dcom.sa.features_unknown", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_UNKNOWN, NULL, HFILL }},
2426 { &hf_dcom_sa_features_dispatch,
2427 { "DISPATCH", "dcom.sa.features_dispatch", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_DISPATCH, NULL, HFILL }},
2428 { &hf_dcom_sa_features_variant,
2429 { "VARIANT", "dcom.sa.features_variant", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_VARIANT, NULL, HFILL }}
2432 static gint *ett_dcom[] = {
2433 &ett_dcom_this,
2434 &ett_dcom_that,
2435 &ett_dcom_extent,
2436 &ett_dcom_lpwstr,
2437 &ett_dcom_interface_pointer,
2438 &ett_dcom_objref,
2439 &ett_dcom_stdobjref,
2440 &ett_dcom_custobjref,
2441 &ett_dcom_dualstringarray,
2442 &ett_dcom_dualstringarray_binding,
2443 &ett_dcom_variant,
2444 &ett_dcom_safearray,
2445 &ett_dcom_sa_features,
2448 static ei_register_info ei[] = {
2449 { &ei_dcom_dissetion_incomplete, { "dcom.dissetion_incomplete", PI_UNDECODED, PI_WARN, "Dissection incomplete", EXPFILL }},
2450 { &ei_dcom_no_spec, { "dcom.no_spec", PI_UNDECODED, PI_NOTE, "No specification available, dissection not possible", EXPFILL }},
2451 { &ei_dcom_hresult_expert, { "dcom.hresult.expert", PI_RESPONSE_CODE, PI_NOTE, "Hresult", EXPFILL }},
2452 { &ei_dcom_dualstringarray_mult_ip, { "dcom.dualstringarray.mult_ip", PI_UNDECODED, PI_NOTE, "DUALSTRINGARRAY Multiple IP", EXPFILL }},
2455 module_t *dcom_module;
2456 expert_module_t* expert_dcom;
2458 /* currently, the DCOM protocol "itself" has no real protocol dissector */
2459 /* we only need this, to register some generic elements */
2460 proto_dcom = proto_register_protocol ("DCOM", "DCOM", "dcom");
2461 proto_register_field_array(proto_dcom, hf_dcom_this_array, array_length(hf_dcom_this_array));
2462 proto_register_field_array(proto_dcom, hf_dcom_that_array, array_length(hf_dcom_that_array));
2463 proto_register_field_array(proto_dcom, hf_dcom_extent_array, array_length(hf_dcom_extent_array));
2464 proto_register_field_array(proto_dcom, hf_dcom_array, array_length(hf_dcom_array));
2465 proto_register_field_array(proto_dcom, hf_dcom_objref_array, array_length(hf_dcom_objref_array));
2466 proto_register_field_array(proto_dcom, hf_dcom_stdobjref_array, array_length(hf_dcom_stdobjref_array));
2467 proto_register_field_array(proto_dcom, hf_dcom_custobjref_array, array_length(hf_dcom_custobjref_array));
2468 proto_register_field_array(proto_dcom, hf_dcom_dualstringarray_array, array_length(hf_dcom_dualstringarray_array));
2469 proto_register_field_array(proto_dcom, hf_dcom_interface_pointer_array, array_length(hf_dcom_interface_pointer_array));
2470 proto_register_field_array(proto_dcom, hf_dcom_vt_array, array_length(hf_dcom_vt_array));
2471 proto_register_field_array(proto_dcom, hf_dcom_sa_array, array_length(hf_dcom_sa_array));
2472 proto_register_subtree_array (ett_dcom, array_length (ett_dcom));
2474 expert_dcom = expert_register_protocol(proto_dcom);
2475 expert_register_field_array(expert_dcom, ei, array_length(ei));
2477 /* preferences */
2478 dcom_module = prefs_register_protocol(proto_dcom, NULL);
2480 prefs_register_bool_preference(dcom_module, "display_unmarshalling_details",
2481 "Display DCOM unmarshalling details",
2482 "Display some DCOM unmarshalled fields "
2483 "usually hidden",
2484 &dcom_prefs_display_unmarshalling_details);
2486 register_init_routine(dcom_reinit);
2490 void
2491 proto_reg_handoff_dcom (void)
2493 /* register some "well known" UUID's */
2494 guids_add_uuid(&uuid_debug_ext, "Debug Information Body Extension");
2495 guids_add_uuid(&uuid_ext_error_ext, "Extended Error Info Body Extension");
2496 guids_add_uuid(&ipid_rem_unknown, "IRemUnknown");
2497 guids_add_uuid(&iid_unknown, "IUnknown");
2498 guids_add_uuid(&uuid_null, "NULL");
2499 guids_add_uuid(&iid_class_factory, "IClassFactory");
2501 /* Currently, we have nothing to register for DCOM */