summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-dcom.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-dcom.c')
-rw-r--r--epan/dissectors/packet-dcom.c2531
1 files changed, 2531 insertions, 0 deletions
diff --git a/epan/dissectors/packet-dcom.c b/epan/dissectors/packet-dcom.c
new file mode 100644
index 00000000..14f7d601
--- /dev/null
+++ b/epan/dissectors/packet-dcom.c
@@ -0,0 +1,2531 @@
+/* packet-dcom.c
+ * Routines for DCOM generics
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+/* A few words about DCOM:
+ *
+ * DCOM uses DCERPC as its underlying "transport" protocol.
+ *
+ * The DCOM dissectors are called by DCERPC request and response calls.
+ * DCOM uses a small header after the DCERPC calls.
+ * (for a DCERPC request call it's called "this",
+ * for a DCERPC response call it's called "that")
+ *
+ * DCOM defines itself some interfaces: oxid, remact, remunk and others
+ *
+ * Implemented is currently "only" a static dissection of packet fields
+ * (no "object recognition" included)
+ *
+ * User's of DCOM can define their own interface's using Microsoft IDL.
+ *
+ * Hint: The registered DCOM interface names can be found in the
+ * windows registry at: "HKEY_CLASSES_ROOT\Interface"
+ *
+ *
+ * Resources on the web:
+ *
+ * "Understanding the DCOM Wire Protocol by Analyzing Network Data Packets"
+ * http:// www.microsoft.com/msj/0398/dcom.htm
+ *
+ * "Distributed Component Object Model Protocol -- DCOM/1.0"
+ * http://www.microsoft.com/com/resources/specs.asp (link is currently down)
+ *
+ */
+
+/* Files involved dissecting DCOM:
+ *
+ * packet-dcom.c: generic DCOM things (this, that, ...) and
+ * generic DCOM datatype (DWORD, VARIANT, ...)
+ *
+ * DCOM common Interfaces:
+ * packet-dcom-oxid.c: IOXIDResolver
+ * packet-dcom-remact.c: IRemoteActivation
+ * packet-dcom-remunk.c: IRemUnknown, IRemUnknown2
+ * packet-dcom-dispatch.c: IDispatch
+ * packet-dcom-sysact.c: ISystemActivator
+ * packet-dcom-typeinfo.c: ITypeInfo
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <epan/packet.h>
+#include <epan/exceptions.h>
+#include <epan/addr_resolv.h>
+#include <epan/expert.h>
+#include <epan/prefs.h>
+#include "packet-dcerpc.h"
+#include "packet-dcom.h"
+
+void proto_register_dcom (void);
+void proto_reg_handoff_dcom (void);
+
+static int proto_dcom = -1;
+
+gboolean dcom_prefs_display_unmarshalling_details = FALSE;
+
+
+static gint ett_dcom_this = -1;
+/* static int hf_dcom_this_version_major = -1; */
+/* static int hf_dcom_this_version_minor = -1; */
+static int hf_dcom_this_flags = -1;
+static int hf_dcom_this_res = -1;
+static int hf_dcom_this_cid = -1;
+
+static gint ett_dcom_that = -1;
+static int hf_dcom_that_flags = -1;
+
+static gint ett_dcom_extent = -1;
+static int hf_dcom_extent = -1;
+static int hf_dcom_extent_array_count = -1;
+static int hf_dcom_extent_array_res = -1;
+static int hf_dcom_extent_size = -1;
+static int hf_dcom_extent_id = -1;
+
+static int hf_dcom_hresult = -1;
+static int hf_dcom_tobedone = -1;
+static int hf_dcom_nospec = -1;
+static int hf_dcom_array_size = -1;
+static int hf_dcom_pointer_val = -1;
+
+/* COMVERSION */
+static int hf_dcom_version_major = -1;
+static int hf_dcom_version_minor = -1;
+
+static gint ett_dcom_lpwstr = -1;
+static int hf_dcom_max_count = -1;
+static int hf_dcom_offset = -1;
+static int hf_dcom_byte_length = -1;
+/* static int hf_dcom_actual_count = -1; */
+
+static gint ett_dcom_objref = -1;
+static int hf_dcom_objref = -1;
+static int hf_dcom_objref_signature = -1;
+static int hf_dcom_objref_flags = -1;
+int hf_dcom_iid = -1;
+int hf_dcom_clsid = -1;
+static int hf_dcom_objref_resolver_address = -1;
+static int hf_dcom_objref_cbextension = -1;
+static int hf_dcom_objref_size = -1;
+
+static gint ett_dcom_stdobjref = -1;
+static int hf_dcom_stdobjref = -1;
+static int hf_dcom_stdobjref_flags = -1;
+static int hf_dcom_stdobjref_public_refs = -1;
+int hf_dcom_oxid = -1;
+int hf_dcom_oid = -1;
+int hf_dcom_ipid = -1;
+
+
+static gint ett_dcom_custobjref = -1;
+static int hf_dcom_custobjref = -1;
+
+static gint ett_dcom_dualstringarray = -1;
+static gint ett_dcom_dualstringarray_binding = -1;
+static int hf_dcom_dualstringarray_num_entries = -1;
+static int hf_dcom_dualstringarray_security_offset = -1;
+static int hf_dcom_dualstringarray_string = -1;
+static int hf_dcom_dualstringarray_string_network_addr = -1;
+static int hf_dcom_dualstringarray_string_tower_id = -1;
+static int hf_dcom_dualstringarray_security = -1;
+static int hf_dcom_dualstringarray_security_authn_svc = -1;
+static int hf_dcom_dualstringarray_security_authz_svc = -1;
+static int hf_dcom_dualstringarray_security_princ_name = -1;
+
+static gint ett_dcom_interface_pointer = -1;
+static int hf_dcom_interface_pointer = -1;
+static int hf_dcom_ip_cnt_data = -1;
+
+static gint ett_dcom_safearray = -1;
+static int hf_dcom_safearray = -1;
+static int hf_dcom_sa_dims32 = -1;
+static int hf_dcom_sa_dims16 = -1;
+static int hf_dcom_sa_features = -1;
+static int hf_dcom_sa_element_size = -1;
+static int hf_dcom_sa_locks = -1;
+static int hf_dcom_sa_vartype32 = -1;
+static int hf_dcom_sa_vartype16 = -1;
+static int hf_dcom_sa_elements = -1;
+static int hf_dcom_sa_bound_elements = -1;
+static int hf_dcom_sa_low_bound = -1;
+
+static gint ett_dcom_sa_features = -1;
+static int hf_dcom_sa_features_auto = -1;
+static int hf_dcom_sa_features_static = -1;
+static int hf_dcom_sa_features_embedded = -1;
+static int hf_dcom_sa_features_fixedsize = -1;
+static int hf_dcom_sa_features_record = -1;
+static int hf_dcom_sa_features_have_iid = -1;
+static int hf_dcom_sa_features_have_vartype = -1;
+static int hf_dcom_sa_features_bstr = -1;
+static int hf_dcom_sa_features_unknown = -1;
+static int hf_dcom_sa_features_dispatch = -1;
+static int hf_dcom_sa_features_variant = -1;
+
+static gint ett_dcom_variant = -1;
+/* static int hf_dcom_variant = -1; */
+static int hf_dcom_variant_type = -1;
+static int hf_dcom_variant_size = -1;
+static int hf_dcom_variant_rpc_res = -1;
+static int hf_dcom_variant_wres = -1;
+static int hf_dcom_variant_type32 = -1;
+
+static int hf_dcom_vt_bool = -1;
+static int hf_dcom_vt_i1 = -1;
+static int hf_dcom_vt_i2 = -1;
+static int hf_dcom_vt_i4 = -1;
+static int hf_dcom_vt_i8 = -1; /* only inside a SAFEARRAY, not in VARIANTs */
+static int hf_dcom_vt_cy = -1;
+static int hf_dcom_vt_ui1 = -1;
+static int hf_dcom_vt_ui2 = -1;
+static int hf_dcom_vt_ui4 = -1;
+static int hf_dcom_vt_ui8 = -1;
+static int hf_dcom_vt_r4 = -1;
+static int hf_dcom_vt_r8 = -1;
+static int hf_dcom_vt_date = -1;
+static int hf_dcom_vt_bstr = -1;
+static int hf_dcom_vt_byref = -1;
+static int hf_dcom_vt_dispatch = -1;
+
+static expert_field ei_dcom_dissection_incomplete = EI_INIT;
+static expert_field ei_dcom_no_spec = EI_INIT;
+static expert_field ei_dcom_hresult_expert = EI_INIT;
+static expert_field ei_dcom_dualstringarray_mult_ip = EI_INIT;
+
+/* this/that extension UUIDs */
+static e_guid_t uuid_debug_ext = { 0xf1f19680, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} };
+static e_guid_t uuid_ext_error_ext ={ 0xf1f19681, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} };
+
+/* general DCOM UUIDs */
+static const e_guid_t ipid_rem_unknown = { 0x00000131, 0x1234, 0x5678, { 0xCA, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
+static const e_guid_t iid_unknown = { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
+static const e_guid_t uuid_null = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
+static const e_guid_t iid_class_factory = { 0x00000001, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
+static const e_guid_t iid_type_info = { 0x00020401, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
+static const e_guid_t iid_provide_class_info = { 0xb196b283, 0xbab4, 0x101a, { 0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07} };
+#if 0
+static const e_guid_t iid_act_prop_in = { 0x000001A2, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
+static const e_guid_t iid_act_prop_out = { 0x000001A3, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
+#endif
+
+static GList *dcom_machines = NULL;
+static GList *dcom_interfaces = NULL;
+static GList *dcom_marshalers = NULL;
+
+static const value_string dcom_thisthat_flag_vals[] = {
+ { 0, "INFO_NULL" },
+ { 1, "INFO_LOCAL" },
+ { 0, NULL }
+};
+
+#if 0
+static const value_string dcom_boolean_flag_vals[] = {
+ { 0x00000001, "TRUE" },
+ { 0x00000000, "FALSE" },
+ { 0, NULL }
+};
+#endif
+
+#ifdef DEBUG
+void dcom_interface_dump(void) {
+ dcom_machine_t *machine;
+ dcom_object_t *object;
+ dcom_interface_t *interf;
+ GList *machines;
+ GList *objects;
+ GList *interfaces;
+
+
+ for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
+ machine = (dcom_machine_t *)machines->data;
+ /*ws_warning("Machine(#%4u): IP:%s", machine->first_packet, address_to_str(pinfo->pool, &machine->ip));*/
+
+ for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
+ object = (dcom_object_t *)objects->data;
+ /*ws_warning(" Object(#%4u): OID:0x%" PRIx64 " private:%p", object->first_packet, object->oid, object->private_data);*/
+
+ for(interfaces = object->interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
+ interf = (dcom_interface_t *)interfaces->data;
+ /*ws_warning(" Interface(#%4u): iid:%s",
+ interf->first_packet, guids_resolve_guid_to_str(&interf->iid));
+ ws_warning(" ipid:%s", guids_resolve_guid_to_str(&interf->ipid));*/
+ }
+ }
+ }
+}
+#endif
+
+dcom_interface_t *dcom_interface_find(packet_info *pinfo _U_, const address *addr _U_, e_guid_t *ipid)
+{
+ dcom_interface_t *interf;
+ GList *interfaces;
+
+
+ if(memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
+ {
+ return NULL;
+ }
+
+ for(interfaces = dcom_interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) {
+ interf = (dcom_interface_t *)interfaces->data;
+
+ if(memcmp(&interf->ipid, ipid, sizeof(e_guid_t)) == 0) {
+ return interf;
+ }
+ }
+
+ return NULL;
+}
+
+
+dcom_interface_t *dcom_interface_new(packet_info *pinfo, const address *addr, e_guid_t *iid, guint64 oxid, guint64 oid, e_guid_t *ipid)
+{
+ GList *dcom_iter;
+ dcom_machine_t *machine;
+ dcom_object_t *object;
+ dcom_interface_t *interf;
+
+
+ if( memcmp(iid, &uuid_null, sizeof(uuid_null)) == 0 ||
+ memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0)
+ {
+ return NULL;
+ }
+
+ if(oxid == 0 || oid == 0) {
+ /*ws_warning("interface_new#%u", pinfo->num);*/
+
+ interf = wmem_new(wmem_file_scope(), dcom_interface_t);
+ interf->parent = NULL;
+ interf->private_data = NULL;
+ interf->first_packet = pinfo->num;
+ interf->iid = *iid;
+ interf->ipid = *ipid;
+
+ dcom_interfaces = g_list_append(dcom_interfaces, interf);
+ return interf;
+ }
+
+ /* find machine */
+ dcom_iter = dcom_machines;
+ while(dcom_iter != NULL) {
+ machine = (dcom_machine_t *)dcom_iter->data;
+ if(cmp_address(&machine->ip, addr) == 0) {
+ break;
+ }
+ dcom_iter = g_list_next(dcom_iter);
+ }
+
+ /* create new machine if not found */
+ if(dcom_iter == NULL) {
+ machine = g_new(dcom_machine_t,1);
+ copy_address(&machine->ip, addr);
+ machine->objects = NULL;
+ machine->first_packet = pinfo->num;
+ dcom_machines = g_list_append(dcom_machines, machine);
+ }
+
+ /* find object */
+ dcom_iter = machine->objects;
+ while(dcom_iter != NULL) {
+ object = (dcom_object_t *)dcom_iter->data;
+ if(object->oid == oid) {
+ break;
+ }
+ dcom_iter = g_list_next(dcom_iter);
+ }
+
+ /* create new object if not found */
+ if(dcom_iter == NULL) {
+ object = g_new(dcom_object_t,1);
+ object->parent = machine;
+ object->interfaces = NULL;
+ object->private_data = NULL;
+ object->first_packet = pinfo->num;
+ object->oid = oid;
+ object->oxid = oxid;
+
+ machine->objects = g_list_append(machine->objects, object);
+ }
+
+ /* find interface */
+ dcom_iter = object->interfaces;
+ while(dcom_iter != NULL) {
+ interf = (dcom_interface_t *)dcom_iter->data;
+ if(memcmp(&interf->ipid, ipid, sizeof(e_guid_t)) == 0) {
+ break;
+ }
+ dcom_iter = g_list_next(dcom_iter);
+ }
+
+ /* create new interface if not found */
+ if(dcom_iter == NULL) {
+ interf = g_new(dcom_interface_t,1);
+ interf->parent = object;
+ interf->private_data = NULL;
+ interf->first_packet = pinfo->num;
+ interf->iid = *iid;
+ interf->ipid = *ipid;
+
+ object->interfaces = g_list_append(object->interfaces, interf);
+ dcom_interfaces = g_list_append(dcom_interfaces, interf);
+ }
+
+ return interf;
+}
+
+
+/*
+ * Flag bits in connection-oriented PDU header.
+ */
+#define WIRESHARK_FADF_AUTO 0x0001
+#define WIRESHARK_FADF_STATIC 0x0002
+#define WIRESHARK_FADF_EMBEDDED 0x0004
+#define WIRESHARK_FADF_FIXEDSIZE 0x0010
+#define WIRESHARK_FADF_RECORD 0x0020
+#define WIRESHARK_FADF_HAVEIID 0x0040
+#define WIRESHARK_FADF_HAVEVARTYPE 0x0080
+#define WIRESHARK_FADF_BSTR 0x0100
+#define WIRESHARK_FADF_UNKNOWN 0x0200
+#define WIRESHARK_FADF_DISPATCH 0x0400
+#define WIRESHARK_FADF_VARIANT 0x0800
+
+
+typedef enum {
+ WIRESHARK_VT_EMPTY = 0,
+ WIRESHARK_VT_NULL = 1,
+ WIRESHARK_VT_I2 = 2,
+ WIRESHARK_VT_I4 = 3,
+ WIRESHARK_VT_R4 = 4,
+ WIRESHARK_VT_R8 = 5,
+ WIRESHARK_VT_CY = 6,
+ WIRESHARK_VT_DATE = 7,
+ WIRESHARK_VT_BSTR = 8,
+ WIRESHARK_VT_DISPATCH = 9,
+ WIRESHARK_VT_ERROR = 10,
+ WIRESHARK_VT_BOOL = 11,
+ WIRESHARK_VT_VARIANT = 12,
+ WIRESHARK_VT_UNKNOWN = 13,
+ WIRESHARK_VT_DECIMAL = 14,
+ WIRESHARK_VT_I1 = 16,
+ WIRESHARK_VT_UI1 = 17,
+ WIRESHARK_VT_UI2 = 18,
+ WIRESHARK_VT_UI4 = 19,
+ WIRESHARK_VT_I8 = 20,
+ WIRESHARK_VT_UI8 = 21,
+ WIRESHARK_VT_INT = 22,
+ WIRESHARK_VT_UINT = 23,
+ WIRESHARK_VT_VOID = 24,
+ WIRESHARK_VT_HRESULT = 25,
+ WIRESHARK_VT_PTR = 26,
+ WIRESHARK_VT_SAFEARRAY = 27,
+ WIRESHARK_VT_CARRAY = 28,
+ WIRESHARK_VT_USERDEFINED = 29,
+ WIRESHARK_VT_LPSTR = 30,
+ WIRESHARK_VT_LPWSTR = 31,
+ WIRESHARK_VT_RECORD = 36,
+ WIRESHARK_VT_FILETIME = 64,
+ WIRESHARK_VT_BLOB = 65,
+ WIRESHARK_VT_STREAM = 66,
+ WIRESHARK_VT_STORAGE = 67,
+ WIRESHARK_VT_STREAMED_OBJECT = 68,
+ WIRESHARK_VT_STORED_OBJECT = 69,
+ WIRESHARK_VT_BLOB_OBJECT = 70,
+ WIRESHARK_VT_CF = 71,
+ WIRESHARK_VT_CLSID = 72,
+
+ WIRESHARK_VT_BSTR_BLOB = 0x0fff,
+
+ WIRESHARK_VT_VECTOR = 0x1000,
+ WIRESHARK_VT_ARRAY = 0x2000,
+ WIRESHARK_VT_BYREF = 0x4000,
+ WIRESHARK_VT_RESERVED = 0x8000,
+
+ WIRESHARK_VT_ILLEGAL = 0xffff,
+ WIRESHARK_VT_ILLEGALMASKED = 0x0fff,
+ WIRESHARK_VT_TYPEMASK = 0x0fff
+} dcom_vartype_t;
+
+const value_string dcom_variant_type_vals[] = {
+ { WIRESHARK_VT_EMPTY, "VT_EMPTY"},
+ { WIRESHARK_VT_NULL, "VT_NULL"},
+ { WIRESHARK_VT_I2, "VT_I2"},
+ { WIRESHARK_VT_I4, "VT_I4"},
+ { WIRESHARK_VT_R4, "VT_R4"},
+ { WIRESHARK_VT_R8, "VT_R8"},
+ { WIRESHARK_VT_CY, "VT_CY"},
+ { WIRESHARK_VT_DATE, "VT_DATE"},
+ { WIRESHARK_VT_BSTR, "VT_BSTR"},
+ { WIRESHARK_VT_DISPATCH, "VT_DISPATCH"},
+ { WIRESHARK_VT_ERROR, "VT_ERROR"},
+ { WIRESHARK_VT_BOOL, "VT_BOOL"},
+ { WIRESHARK_VT_I1, "VT_I1"},
+ { WIRESHARK_VT_UI1, "VT_UI1"},
+ { WIRESHARK_VT_UI2, "VT_UI2"},
+ { WIRESHARK_VT_UI4, "VT_UI4"},
+ { WIRESHARK_VT_I8, "VT_I8"},
+ { WIRESHARK_VT_UI8, "VT_UI8"},
+ { WIRESHARK_VT_ARRAY, "VT_ARRAY"},
+ { WIRESHARK_VT_UNKNOWN, "VT_UNKNOWN"},
+ { WIRESHARK_VT_USERDEFINED, "VT_USERDEFINED"},
+ { WIRESHARK_VT_PTR, "VT_PTR"},
+
+ /* XXX: this could be done better */
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I2, "VT_ARRAY|VT_I2"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I4, "VT_ARRAY|VT_I4"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_R4, "VT_ARRAY|VT_R4"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_R8, "VT_ARRAY|VT_R8"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_DATE, "VT_ARRAY|VT_DATE"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_BSTR, "VT_ARRAY|VT_BSTR"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_ERROR, "VT_ARRAY|VT_ERROR"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_BOOL, "VT_ARRAY|VT_BOOL"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I1, "VT_ARRAY|VT_I1"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI1, "VT_ARRAY|VT_UI1"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI2, "VT_ARRAY|VT_UI2"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI4, "VT_ARRAY|VT_UI4"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I8, "VT_ARRAY|VT_I8"},
+ { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI8, "VT_ARRAY|VT_UI8"},
+
+ { WIRESHARK_VT_BYREF | WIRESHARK_VT_I2, "VT_BYREF|VT_I2"},
+ { WIRESHARK_VT_BYREF | WIRESHARK_VT_BSTR, "VT_BYREF|VT_BSTR"},
+ { WIRESHARK_VT_BYREF | WIRESHARK_VT_VARIANT, "VT_BYREF|VT_VARIANT"},
+ { 0, NULL }
+/* XXX: append more types here */
+};
+
+
+
+/* we need an extension mechanism here (be able to append entries by user protocol) */
+const value_string dcom_hresult_vals[] = {
+ { 0x00000000, "S_OK" },
+ { 0x00000001, "S_FALSE" },
+ { 0x8000FFFF, "E_UNEXPECTED" },
+ { 0x80004001, "E_NOTIMPL" },
+ { 0x80004002, "E_NOINTERFACE" },
+ { 0x80004003, "E_POINTER" },
+ { 0x80004004, "E_ABORT" },
+ { 0x80004005, "E_FAIL" },
+ { 0x80070005, "E_ACCESSDENIED" },
+ { 0x80070006, "E_HANDLE" },
+ { 0x8007000E, "E_OUTOFMEMORY" },
+ { 0x80070057, "E_INVALIDARG" },
+
+ { 0x80010108, "RPC_E_DISCONNECTED" },
+ { 0x80010113, "RPC_E_INVALID_IPID" },
+ { 0x8001011F, "RPC_E_TIMEOUT" },
+
+ { 0x80020003, "DISP_E_MEMBERNOTFOUND" },
+ { 0x80020004, "DISP_E_PARAMNOTFOUND" },
+ { 0x80020005, "DISP_E_TYPEMISMATCH" },
+ { 0x80020006, "DISP_E_UNKNOWNNAME" },
+ { 0x80020008, "DISP_E_BADVARTYPE" },
+ { 0x80020009, "DISP_E_EXCEPTION" },
+ { 0x8002000A, "DISP_E_OVERFLOW" },
+
+ { 0x8002801D, "TYPE_E_LIBNOTREGISTERED" },
+
+ { 0x80040154, "REGDB_E_CLASSNOTREG" },
+ { 0x80040201, "CO_E_FAILEDTOGETSECCTX" },
+
+/* following are CBA application specific values */
+ { 0x0004CA00, "CBA_S_PERSISTPENDING" },
+ { 0x0004CA01, "CBA_S_ESTABLISHING" },
+ { 0x0004CA02, "CBA_S_NOCONNECTION" },
+ { 0x0004CA03, "CBA_S_VALUEBUFFERED" },
+ { 0x0004CA04, "CBA_S_VALUEUNCERTAIN" },
+ { 0x0004CA05, "CBA_S_NOCONNECTIONDATA" },
+ { 0x0004CA06, "CBA_S_FRAMEEMPTY" },
+
+ { 0x8004CB00, "CBA_E_MALFORMED" },
+ { 0x8004CB01, "CBA_E_UNKNOWNOBJECT" },
+ { 0x8004CB02, "CBA_E_UNKNOWNMEMBER" },
+ { 0x8004CB03, "CBA_E_TYPEMISMATCH" },
+ { 0x8004CB04, "CBA_E_INVALIDENUMVALUE" },
+ { 0x8004CB05, "CBA_E_INVALIDID" },
+ { 0x8004CB06, "CBA_E_INVALIDEPSILON" },
+ { 0x8004CB07, "CBA_E_INVALIDSUBSTITUTE" },
+ { 0x8004CB08, "CBA_E_INVALIDCONNECTION" },
+ { 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
+ { 0x8004CB0A, "CBA_E_TIMEVALUEUNSUPPORTED" },
+ { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
+ { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
+ { 0x8004CB0D, "CBA_E_PERSISTRUNNING" },
+ { 0x8004CB0E, "CBA_E_INUSE" },
+ { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
+ { 0x8004CB10, "CBA_E_NONACCESSIBLE" },
+ { 0x8004CB11, "CBA_E_DEFECT" },
+ { 0x8004CB12, "CBA_E_LIMITVIOLATION" },
+ { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" },
+ { 0x8004CB14, "CBA_E_QCNOTAPPLICABLE" },
+ { 0x8004CB15, "CBA_E_ACCESSBLOCKED" },
+ { 0x8004CB16, "CBA_E_COUNTEXCEEDED" },
+ { 0x8004CB17, "CBA_E_SIZEEXCEEDED" },
+ { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" },
+ { 0x8004CB19, "CBA_E_OUTOFACCOPAIRS" },
+ { 0x8004CB1A, "CBA_E_ITEMTOOLARGE" },
+ { 0x8004CB1B, "CBA_E_CRDATALENGTH" },
+ { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" },
+ { 0x8004CB1D, "CBA_E_CAPACITYEXCEEDED" },
+ { 0x8004CB1E, "CBA_E_SUBELEMENTMISMATCH" },
+ { 0x8004CB1F, "CBA_E_STATIONFAILURE" },
+ { 0x8004CB20, "CBA_E_NOTROUTABLE" },
+ { 0x8004CB21, "CBA_E_DISCONNECTRUNNING" },
+ { 0x8004CB22, "CBA_E_LOCATIONCHANGED" },
+ { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
+ { 0x8004CB24, "CBA_E_LINKFAILURE" },
+ { 0x8004CB25, "CBA_E_MODECHANGE" },
+
+ { 0x80080004, "CO_E_BAD_PATH" },
+
+ { 0, NULL }
+};
+
+static const value_string dcom_objref_flag_vals[] = {
+ { 0x1, "OBJREF_STANDARD" },
+ { 0x2, "OBJREF_HANDLER" },
+ { 0x4, "OBJREF_CUSTOM" },
+ { 0, NULL }
+};
+
+static const value_string dcom_objref_signature_vals[] = {
+ { 0x574f454d, "MEOW" },
+ { 0, NULL }
+};
+
+/* although flags, they doesn't seem to be used as such */
+static const value_string dcom_stdobjref_flag_vals[] = {
+ { 0x0000, "SORF_NULL" },
+ { 0x0001, "SORF_OXRES1" },
+ { 0x0020, "SORF_OXRES2" },
+ { 0x0040, "SORF_OXRES3" },
+ { 0x0080, "SORF_OXRES4" },
+ { 0x0100, "SORF_OXRES5" },
+ { 0x0200, "SORF_OXRES6" },
+ { 0x0400, "SORF_OXRES7" },
+ { 0x0800, "SORF_OXRES8" },
+ { 0x1000, "SORF_NOPING" },
+ { 0, NULL }
+};
+
+static const value_string dcom_dcerpc_pointer_vals[] = {
+ { 0x72657355, "User" },
+ { 0x42535452, "BSTR" },
+ { 0x00000000, "NULL" },
+ { 0, NULL }
+};
+
+static const value_string dcom_dualstringarray_authz[] = {
+ { 0x0000, "RPC_C_AUTHZ_NONE" },
+ { 0x0001, "RPC_C_AUTHZ_NAME"},
+ { 0x0002, "RPC_C_AUTHZ_DCE"},
+ { 0xffff, "Default"},
+ { 0, NULL}
+};
+
+static const value_string dcom_dualstringarray_authn[] = {
+ { 00, "RPC_C_AUTHN_NONE" },
+ { 1, "RPC_C_AUTHN_DCE_PRIVATE"},
+ { 2, "RPC_C_AUTHN_DCE_PUBLIC"},
+ { 4, "RPC_C_AUTHN_DEC_PUBLIC"},
+ { 9, "RPC_C_AUTHN_GSS_NEGOTIATE"},
+ { 10, "RPC_C_AUTH_WINNT"},
+ { 14, "RPC_C_AUTHN_GSS_SCHANNEL"},
+ { 16, "RPC_C_AUTHN_GSS_KERBEROS"},
+ { 17, "RPC_C_AUTHN_MSN"},
+ { 18, "RPC_C_AUTHN_DPA"},
+ { 100, "RPC_C_AUTHN_MQ"},
+ { 0xffff, "RPC_C_AUTHN_DEFAULT"},
+ { 0, NULL}
+};
+
+const value_string dcom_protseq_vals[] = {
+ { 0x04, "NCACN_DNET_NSP" },
+ { 0x07, "NCACN_IP_TCP" },
+ { 0x08, "NCADG_IP_UDP" },
+ { 0x09, "NCACN_IP" },
+ { 0x0C, "NCACN_SPX" },
+ { 0x0D, "NCACN_NB_IPX" },
+ { 0x0E, "NCADG_IPX" },
+ { 0x12, "NCACN_NB_NB" },
+ { 0x1F, "NCACN_HTTP" },
+ { 0, NULL }
+};
+
+static const value_string dcom_vt_bool_vals[] = {
+ { 0x0000, "FALSE" },
+ { 0xFFFF, "TRUE" },
+ { 0, NULL }
+};
+
+
+
+/* dissect extension to DCOM "this" and "that" */
+static int
+dissect_dcom_extent(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
+{
+ guint32 u32ArraySize;
+ guint32 u32ArraySize2;
+ guint32 u32Pointer;
+ guint32 u32VariableOffset;
+ guint32 u32Idx;
+ guint32 u32SubStart;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+
+ guint32 u32ArrayCount;
+ guint32 u32ArrayRes;
+
+ guint32 u32ExtentSize;
+ e_guid_t uuidExtend;
+ const char *uuid_name;
+
+
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
+
+ if (u32Pointer == 0) {
+ return offset;
+ }
+
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
+ hf_dcom_extent_array_count, &u32ArrayCount);
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
+ hf_dcom_extent_array_res, &u32ArrayRes);
+
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
+
+ if (u32Pointer == 0) {
+ return offset;
+ }
+
+ offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
+ &u32ArraySize);
+
+ u32VariableOffset = offset + u32ArraySize*4;
+
+ u32Idx = 1;
+ while (u32ArraySize--) {
+ sub_item = proto_tree_add_item(tree, hf_dcom_extent, tvb, offset, 0, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_extent);
+ u32SubStart = offset;
+
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
+
+ if(u32Pointer != 0) {
+ u32VariableOffset = dissect_dcom_DWORD(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
+ hf_dcom_extent_size, &u32ExtentSize);
+
+ dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, NULL, di, drep,
+ hf_dcom_extent_id, &uuidExtend);
+
+ /* look for a registered uuid name */
+ if((uuid_name = guids_get_uuid_name(&uuidExtend, pinfo->pool)) != NULL) {
+ proto_tree_add_guid_format_value(sub_tree, hf_dcom_extent_id, tvb,
+ offset, sizeof(e_guid_t), (e_guid_t *) &uuidExtend,
+ "%s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
+ uuid_name,
+ uuidExtend.data1, uuidExtend.data2, uuidExtend.data3,
+ uuidExtend.data4[0], uuidExtend.data4[1],
+ uuidExtend.data4[2], uuidExtend.data4[3],
+ uuidExtend.data4[4], uuidExtend.data4[5],
+ uuidExtend.data4[6], uuidExtend.data4[7]);
+ u32VariableOffset += 16;
+ } else {
+ u32VariableOffset = dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
+ hf_dcom_extent_id, &uuidExtend);
+ }
+
+
+ u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
+ &u32ArraySize2);
+ u32VariableOffset = dissect_dcom_nospec_data(tvb, u32VariableOffset, pinfo, sub_tree, drep, u32ArraySize2);
+
+ /* update subtree header */
+ if(uuid_name != NULL) {
+ proto_item_append_text(sub_item, "[%u]: %s, Bytes=%u",
+ u32Idx, uuid_name, u32ArraySize2);
+ } else {
+ proto_item_append_text(sub_item, "[%u]: Bytes=%u",
+ u32Idx, u32ArraySize2);
+ }
+ proto_item_set_len(sub_item, offset - u32SubStart);
+ } else {
+ /* update subtree header */
+ proto_item_append_text(sub_item, "[%u]: NULL", u32Idx);
+ proto_item_set_len(sub_item, offset - u32SubStart);
+ }
+
+ u32Idx++;
+ }
+
+ return u32VariableOffset;
+}
+
+
+/* dissect DCOM "this" (start of every DCOM request) */
+int
+dissect_dcom_this(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
+{
+ guint16 u16VersionMajor;
+ guint16 u16VersionMinor;
+ guint32 u32Flags;
+ guint32 u32Res;
+ e_guid_t uuidCausality;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ guint32 u32SubStart;
+ proto_item *pi;
+
+ sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
+ "DCOM, ORPCThis");
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_this);
+
+ offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, sub_tree, di, drep,
+ &u16VersionMajor, &u16VersionMinor);
+ u32SubStart = offset - 4;
+
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_this_flags, &u32Flags);
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_this_res, &u32Res);
+
+ offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_this_cid, &uuidCausality);
+
+ offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep);
+
+ /* update subtree header */
+ proto_item_append_text(sub_item, ", V%u.%u, Causality ID: %s",
+ u16VersionMajor, u16VersionMinor, guids_resolve_guid_to_str(&uuidCausality, pinfo->pool));
+ proto_item_set_len(sub_item, offset - u32SubStart);
+
+ if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
+ pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
+ (e_guid_t *) &di->call_data->object_uuid,
+ "Object UUID/IPID: %s", guids_resolve_guid_to_str(&di->call_data->object_uuid, pinfo->pool));
+ proto_item_set_generated(pi);
+ }
+
+ return offset;
+}
+
+
+/* dissect DCOM "that" (start of every DCOM response) */
+int
+dissect_dcom_that(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) {
+ guint32 u32Flags;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ guint32 u32SubStart;
+ proto_item *pi;
+
+ sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0,
+ "DCOM, ORPCThat");
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_that);
+
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_that_flags, &u32Flags);
+ u32SubStart = offset - 4;
+
+ offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep);
+
+ /* update subtree header */
+ proto_item_set_len(sub_item, offset - u32SubStart);
+
+ if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) {
+ pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0,
+ (e_guid_t *) &di->call_data->object_uuid,
+ "Object UUID/IPID: %s", guids_resolve_guid_to_str(&di->call_data->object_uuid, pinfo->pool));
+ proto_item_set_generated(pi);
+ }
+
+ return offset;
+}
+
+
+/* dissect simple dcom request, DCOM "this" only */
+int
+dissect_dcom_simple_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
+{
+
+ offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep);
+
+ return offset;
+}
+
+
+/* dissect simple dcom response, DCOM "that" and returned HRESULT only */
+int
+dissect_dcom_simple_resp(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
+{
+ guint32 u32HResult;
+
+
+ offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);
+
+ offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
+ &u32HResult);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
+ val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
+
+
+ return offset;
+}
+
+
+/* dissect a dcerpc array size */
+int
+dissect_dcom_dcerpc_array_size(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, dcerpc_info *di, guint8 *drep, guint32 *pu32ArraySize)
+{
+
+
+ /* en-/disable this by preference setting */
+ if (!dcom_prefs_display_unmarshalling_details) {
+ /* this will read in the data, but prevent output to tree */
+ tree = NULL;
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
+ hf_dcom_array_size, pu32ArraySize);
+
+ return offset;
+}
+
+
+/* dissect a dcerpc pointer value */
+int
+dissect_dcom_dcerpc_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, dcerpc_info *di, guint8 *drep, guint32 *pu32Pointer)
+{
+
+ /* en-/disable this by preference setting */
+ if (!dcom_prefs_display_unmarshalling_details) {
+ /* this will read in the data, but prevent output to tree */
+ tree = NULL;
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
+ hf_dcom_pointer_val, pu32Pointer);
+
+ return offset;
+}
+
+
+/* mark data as "ToBeDone" */
+/* XXX: handout data to generic "unknown data" dissector? */
+extern int
+dissect_dcom_tobedone_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep _U_, int length)
+{
+ proto_item *item;
+
+
+ item = proto_tree_add_item(tree, hf_dcom_tobedone, tvb, offset, length, ENC_NA);
+ proto_item_set_generated(item);
+ expert_add_info(pinfo, item, &ei_dcom_dissection_incomplete);
+
+ offset += length;
+
+ return offset;
+}
+
+
+/* mark data as "No Specification Available" */
+/* XXX: handout data to generic "unknown data" dissector? */
+extern int
+dissect_dcom_nospec_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep _U_, int length)
+{
+ proto_item *item;
+
+
+ item = proto_tree_add_item(tree, hf_dcom_nospec, tvb, offset, length, ENC_NA);
+ proto_item_set_generated(item);
+ expert_add_info(pinfo, item, &ei_dcom_no_spec);
+
+ offset += length;
+
+ return offset;
+}
+
+
+/* dissect an indexed WORD, something like: "FieldName[1]: 0x1234" */
+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)
+{
+ guint16 u16WORD;
+
+
+ /* dissect the WORD, but don't add to tree */
+ dissect_dcom_WORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
+ hfindex, &u16WORD);
+
+ if (tree) {
+ /* special formatted output of indexed value */
+ proto_tree_add_uint_format(tree, hfindex, tvb, offset, 2, u16WORD,
+ "%s[%u]: 0x%04x",
+ proto_registrar_get_name(hfindex),
+ field_index, u16WORD);
+ }
+
+ offset += 2;
+
+ if (pu16WORD)
+ *pu16WORD = u16WORD;
+
+ return offset;
+}
+
+
+/* dissect an indexed DWORD, something like: "FieldName[1]: 0x12345678" */
+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)
+{
+ guint32 u32DWORD;
+
+
+ /* dissect the DWORD, but don't add to tree */
+ dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
+ hfindex, &u32DWORD);
+
+ if (tree) {
+ /* special formatted output of indexed value */
+ proto_tree_add_uint_format(tree, hfindex, tvb, offset, 4, u32DWORD,
+ "%s[%u]: 0x%08x",
+ proto_registrar_get_name(hfindex),
+ field_index, u32DWORD);
+ }
+
+ offset += 4;
+
+ if (pu32DWORD)
+ *pu32DWORD = u32DWORD;
+
+ return offset;
+}
+
+
+/* dissect hresult field of a usual DCOM call (create "raw" item) */
+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)
+{
+ guint32 u32HResult;
+
+ /* dissect the DWORD, but don't add to tree */
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
+ field_index, &u32HResult);
+
+ if (tree) {
+ /* special formatted output of indexed value */
+ *item = proto_tree_add_item (tree, field_index, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
+ }
+
+ if (pu32HResult)
+ *pu32HResult = u32HResult;
+
+ return offset;
+}
+
+
+/* dissect hresult field of a usual DCOM call (separate method, because often used) */
+int
+dissect_dcom_HRESULT(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, dcerpc_info *di, guint8 *drep,
+ guint32 * pu32HResult)
+{
+ guint32 u32HResult;
+ proto_item *item = NULL;
+
+ /* dissect the DWORD, but don't add to tree */
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
+ hf_dcom_hresult, &u32HResult);
+
+ if (tree) {
+ /* special formatted output of indexed value */
+ item = proto_tree_add_item (tree, hf_dcom_hresult, tvb, offset-4, 4, DREP_ENC_INTEGER(drep));
+ }
+
+ /* expert info only if severity is set */
+ /* XXX - move this to the callers of this function, to provide a more detailed error output */
+ if(u32HResult & 0x80000000) {
+ expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s",
+ val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
+ }
+ if (pu32HResult)
+ *pu32HResult = u32HResult;
+
+ return offset;
+}
+
+
+/* partial results of indexed DCOM subcalls (e.g.: from a kind of array) */
+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)
+{
+ guint32 u32HResult;
+ proto_item *item = NULL;
+
+
+ /* dissect the DWORD, but don't add to tree */
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep,
+ hf_dcom_hresult, &u32HResult);
+
+ if (tree) {
+ /* special formatted output of indexed value */
+ item = proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset-4, 4, u32HResult,
+ "HResult[%u]: %s (0x%08x)", field_index,
+ val_to_str_const(u32HResult, dcom_hresult_vals, "Unknown"),
+ u32HResult);
+ }
+ /* expert info only if severity flag is set */
+ /* XXX - move this to the callers of this function, to provide a more detailed error output */
+ if(u32HResult & 0x80000000) {
+ expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s",
+ val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%x)"));
+ }
+ if (pu32HResult)
+ *pu32HResult = u32HResult;
+
+ return offset;
+}
+
+
+
+int
+dissect_dcom_COMVERSION(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, dcerpc_info *di, guint8 *drep,
+ guint16 * pu16VersionMajor, guint16 * pu16VersionMinor)
+{
+
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
+ hf_dcom_version_major, pu16VersionMajor);
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
+ hf_dcom_version_minor, pu16VersionMinor);
+
+ return offset;
+}
+
+
+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)
+{
+ guint32 u32Dims;
+ guint16 u16Dims;
+ guint16 u16Features;
+ guint32 u32ElementSize;
+ guint32 u32VarType;
+ guint32 u32Elements;
+ guint32 u32Pointer;
+ guint32 u32BoundElements;
+ guint32 u32LowBound;
+ gchar cData[100];
+ guint32 u32ArraySize;
+ guint32 u32VariableOffset;
+ guint32 u32Data;
+ guint16 u16Data;
+ guint8 u8Data;
+ guint16 u16Locks;
+ guint16 u16VarType;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ guint32 u32SubStart;
+ guint32 u32TmpOffset;
+
+ static int * const features[] = {
+ &hf_dcom_sa_features_variant,
+ &hf_dcom_sa_features_dispatch,
+ &hf_dcom_sa_features_unknown,
+ &hf_dcom_sa_features_bstr,
+ &hf_dcom_sa_features_have_vartype,
+ &hf_dcom_sa_features_have_iid,
+ &hf_dcom_sa_features_record,
+ &hf_dcom_sa_features_fixedsize,
+ &hf_dcom_sa_features_embedded,
+ &hf_dcom_sa_features_static,
+ &hf_dcom_sa_features_auto,
+ NULL
+ };
+
+
+ /* XXX: which alignment do we need here? */
+
+ sub_item = proto_tree_add_item(tree, hf_dcom_safearray, tvb, offset, 0, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_safearray);
+ u32SubStart = offset;
+
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
+
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_sa_dims32, &u32Dims);
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_sa_dims16, &u16Dims);
+
+ /* feature flags */
+ u32TmpOffset = dissect_dcom_WORD(tvb, offset, pinfo, NULL, di, drep, -1, &u16Features);
+
+ proto_tree_add_bitmask_value_with_flags(sub_tree, tvb, offset, hf_dcom_sa_features,
+ ett_dcom_sa_features, features, u16Features, BMT_NO_APPEND);
+ offset = u32TmpOffset;
+
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_sa_element_size, &u32ElementSize);
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_sa_locks, &u16Locks);
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_sa_vartype16, &u16VarType);
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_sa_vartype32, &u32VarType);
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_sa_elements, &u32Elements);
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
+
+ u32BoundElements = 0;
+ while(u32Dims--) {
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_sa_bound_elements, &u32BoundElements);
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_sa_low_bound, &u32LowBound);
+ }
+
+ offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize);
+
+ tvb_ensure_bytes_exist(tvb, offset, u32ArraySize * u32ElementSize);
+ u32VariableOffset = offset + u32ArraySize * u32ElementSize;
+
+ if(sacb) {
+ sacb(tvb, offset, pinfo, tree, di, drep, u32VarType, u32ArraySize);
+ }
+
+ while(u32ArraySize--) {
+ switch(u32VarType) {
+ case(WIRESHARK_VT_ERROR):
+ offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
+ &u32Data);
+ break;
+ case(WIRESHARK_VT_I1):
+ offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_i1, &u8Data);
+ break;
+ case(WIRESHARK_VT_I2):
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_i2, &u16Data);
+ break;
+ case(WIRESHARK_VT_I4):
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_i4, &u32Data);
+ break;
+ case(WIRESHARK_VT_I8):
+ offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_i8, NULL);
+ /* take care of the 8 byte alignment */
+ u32VariableOffset = offset;
+ break;
+ case(WIRESHARK_VT_BSTR):
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
+ if (u32Pointer) {
+ u32VariableOffset = dissect_dcom_BSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_bstr, cData, sizeof(cData) );
+ }
+ break;
+ default:
+ /* XXX: other types possible, but still not implemented:
+ VT_UNKNOWN
+ VT_DISPATCH
+ VT_VARIANT
+ VT_RECORD
+ VT_UNKNOWN|VT_RESERVED
+ */
+ u32VariableOffset = dissect_dcom_tobedone_data(tvb, u32VariableOffset, pinfo, sub_tree, drep,
+ 10000);
+ }
+ }
+
+ /* update subtree header */
+ proto_item_append_text(sub_item, ": Elements: %u/%u VarType: %s",
+ u32Elements, u32BoundElements,
+ val_to_str(u32VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
+
+ proto_item_set_len(sub_item, u32VariableOffset - u32SubStart);
+
+ return u32VariableOffset;
+}
+
+
+
+int
+dissect_dcom_VARTYPE(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, dcerpc_info *di, guint8 *drep,
+ guint16 *pu16VarType)
+{
+
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
+ hf_dcom_variant_type, pu16VarType);
+
+ return offset;
+}
+
+
+int
+dissect_dcom_VARIANT(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex)
+{
+ guint32 u32Size;
+ guint32 u32RPCRes;
+ guint16 u16Res;
+ guint32 u32SubStart;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ guint16 u16VarType;
+ guint32 u32VarType;
+
+ guint8 u8Data;
+ guint16 u16Data;
+ guint32 u32Data;
+ guint64 u64Data;
+ gint64 cyData;
+ gchar cData[500];
+ guint32 u32Pointer;
+ gfloat f32Data;
+ gdouble f64Data;
+
+
+ /* alignment of 8 needed for a VARIANT */
+ if (offset % 8) {
+ offset += 8 - (offset % 8);
+ }
+
+ sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_variant);
+ u32SubStart = offset;
+
+ /* the following size can be VERY confusing:
+ * It is NOT the maximum size of the variant, as one could expect,
+ * but the current size of the variant padded to 8 bytes.
+ * BUT: The following data does not start AFTER this padding,
+ * it starts just after the variant-data (without padding)!!! */
+ /* Conclusion: the size given here can be LONGER than the actual size */
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_variant_size, &u32Size);
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_variant_rpc_res, &u32RPCRes);
+ offset = dissect_dcom_VARTYPE(tvb, offset, pinfo, sub_tree, di, drep,
+ &u16VarType);
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_variant_wres, &u16Res);
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_variant_wres, &u16Res);
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_variant_wres, &u16Res);
+
+ /* 32 bit VarType (slightly different to the 16 bit one) */
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_variant_type32, &u32VarType);
+
+ if (u32VarType & WIRESHARK_VT_BYREF) {
+ u32VarType &=~WIRESHARK_VT_BYREF;
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
+ }
+
+ switch (u32VarType) {
+ case(WIRESHARK_VT_EMPTY):
+ break;
+ case(WIRESHARK_VT_BOOL):
+ offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_bool, &u16Data);
+ break;
+ case(WIRESHARK_VT_I1):
+ offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_i1, &u8Data);
+ break;
+ case(WIRESHARK_VT_UI1):
+ offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_ui1, &u8Data);
+ break;
+ case(WIRESHARK_VT_I2):
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_i2, &u16Data);
+ break;
+ case(WIRESHARK_VT_UI2):
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_ui2, &u16Data);
+ break;
+ case(WIRESHARK_VT_I4):
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_i4, &u32Data);
+ break;
+ case(WIRESHARK_VT_I8):
+ offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_i8, &u64Data);
+ break;
+ case(WIRESHARK_VT_CY):
+ offset = dissect_dcom_I8(tvb, offset, pinfo, NULL, di, drep,
+ 0, &cyData);
+ proto_tree_add_int64_format(sub_tree, hf_dcom_vt_cy, tvb, offset - 8,
+ 8, cyData, "%s: %" PRId64 ".%.04" PRId64,
+ proto_registrar_get_name(hf_dcom_vt_cy),
+ cyData / 10000, ABS(cyData % 10000));
+ break;
+ case(WIRESHARK_VT_UI4):
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_ui4, &u32Data);
+ break;
+ case(WIRESHARK_VT_UI8):
+ offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_ui8, &u64Data);
+ break;
+ case(WIRESHARK_VT_R4):
+ offset = dissect_dcom_FLOAT(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_r4, &f32Data);
+ break;
+ case(WIRESHARK_VT_R8):
+ offset = dissect_dcom_DOUBLE(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_r8, &f64Data);
+ break;
+ case(WIRESHARK_VT_DATE):
+ offset = dissect_dcom_DATE(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_date, &f64Data);
+ break;
+ case(WIRESHARK_VT_BSTR):
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
+ if (u32Pointer) {
+ offset = dissect_dcom_BSTR(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_bstr, cData, sizeof(cData) );
+ }
+ break;
+ case(WIRESHARK_VT_DISPATCH):
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
+ if (u32Pointer) {
+ offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_dispatch, NULL); /* XXX - how to handle this? */
+ }
+ break;
+ case(WIRESHARK_VT_ARRAY):
+ offset = dissect_dcom_SAFEARRAY(tvb, offset, pinfo, sub_tree, di, drep,
+ 0, NULL);
+ break;
+ case(WIRESHARK_VT_ERROR):
+ offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
+ 0);
+ break;
+ case(WIRESHARK_VT_VARIANT):
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
+ if (u32Pointer) {
+ offset = dissect_dcom_VARIANT(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_vt_byref /* must be BYREF */);
+ }
+ break;
+ case(WIRESHARK_VT_UNKNOWN):
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer);
+ break;
+ default:
+ /* XXX: add more types here! */
+ offset = dissect_dcom_tobedone_data(tvb, offset, pinfo, sub_tree, drep,
+ 10000);
+ }
+
+ /* update subtree header */
+ proto_item_append_text(sub_item, ": %s",
+ val_to_str(u16VarType, dcom_variant_type_vals, "Unknown (0x%08x)") );
+
+ proto_item_set_len(sub_item, offset - u32SubStart);
+
+ return offset;
+}
+
+
+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)
+{
+ const gchar *uuid_name;
+ header_field_info *hfi;
+ e_guid_t uuid;
+
+
+ /* get the UUID, but don't put it into the tree */
+ offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep,
+ hfindex, &uuid);
+
+ /* add to the tree */
+ hfi = proto_registrar_get_nth(hfindex);
+ uuid_name = guids_get_uuid_name(&uuid, pinfo->pool);
+ if(uuid_name) {
+ proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
+ "%s: %s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
+ hfi->name, uuid_name,
+ uuid.data1, uuid.data2, uuid.data3,
+ uuid.data4[0], uuid.data4[1],
+ uuid.data4[2], uuid.data4[3],
+ uuid.data4[4], uuid.data4[5],
+ uuid.data4[6], uuid.data4[7]);
+ } else {
+ proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid,
+ "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ hfi->name,
+ uuid.data1, uuid.data2, uuid.data3,
+ uuid.data4[0], uuid.data4[1],
+ uuid.data4[2], uuid.data4[3],
+ uuid.data4[4], uuid.data4[5],
+ uuid.data4[6], uuid.data4[7]);
+ }
+
+ if(pdata != NULL) {
+ *pdata = uuid;
+ }
+
+ return offset;
+}
+
+
+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)
+{
+ const gchar *uuid_name;
+ proto_item *pi;
+ header_field_info *hfi;
+
+
+ /* XXX - this is far from being performance optimized! */
+
+ /* get the UUID, but don't put it into the tree */
+ offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep,
+ hfindex, uuid);
+
+ /* look for a registered uuid name */
+ uuid_name = guids_get_uuid_name(uuid, pinfo->pool);
+
+ /* add to the tree */
+ hfi = proto_registrar_get_nth(hfindex);
+ pi = proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) uuid, "%s", hfi->name);
+
+ if (field_index != -1) {
+ proto_item_append_text(pi, "[%u]: ", field_index);
+ } else {
+ proto_item_append_text(pi, ": ");
+ }
+
+ if(uuid_name) {
+ proto_item_append_text(pi, "%s (", uuid_name);
+ }
+
+ proto_item_append_text(pi, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid->data1, uuid->data2, uuid->data3,
+ uuid->data4[0], uuid->data4[1],
+ uuid->data4[2], uuid->data4[3],
+ uuid->data4[4], uuid->data4[5],
+ uuid->data4[6], uuid->data4[7]);
+
+ if(uuid_name) {
+ proto_item_append_text(pi, ")");
+ }
+
+ /* update column info now */
+ if (field_index != -1) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]=%s",
+ hfi->name, field_index, (uuid_name) ? uuid_name : "???");
+ } else {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%s",
+ hfi->name, (uuid_name) ? uuid_name : "???");
+ }
+
+ return offset;
+}
+
+
+/* get a wide character string from tvb (zero terminated or limited through inLength) */
+/* the string will be converted to ASCII if possible or simple hexdump otherwise */
+/* outLength is in output bytes including zero termination output */
+static int
+dcom_tvb_get_nwstringz0(tvbuff_t *tvb, gint offset, guint32 inLength, gchar *pszStr, guint32 outLength, gboolean *isPrintable)
+{
+ guint32 u32Idx;
+ guint32 u32IdxA;
+ guint32 u32IdxW;
+ guint32 inLengthWithoutNullDelimiter = 0;
+
+ guint8 u8Tmp1;
+ guint8 u8Tmp2;
+
+
+ *isPrintable = TRUE;
+ inLengthWithoutNullDelimiter = inLength == 0 ? 0 : inLength -1;
+
+ /* we must have at least the space for the zero termination */
+ DISSECTOR_ASSERT(outLength >= 1);
+
+ /* determine length and printablility of the string */
+ for(u32Idx = 0; u32Idx < inLengthWithoutNullDelimiter; u32Idx+=2) {
+ /* the marshalling direction of a WCHAR is fixed! */
+ u8Tmp1 = tvb_get_guint8(tvb, offset+u32Idx);
+ u8Tmp2 = tvb_get_guint8(tvb, offset+u32Idx+1);
+
+ /* is this the zero termination? */
+ if (u8Tmp1 == 0 && u8Tmp2 == 0) {
+ u32Idx+=2;
+ break;
+ }
+
+ /* is this character printable? */
+ /* 10 = New Line, 13 = Carriage Return */
+ /* XXX - there are probably more printable chars than isprint() */
+ if(!(g_ascii_isprint(u8Tmp1) || u8Tmp1 == 10 || u8Tmp1 == 13)|| u8Tmp2 != 0) {
+ *isPrintable = FALSE;
+ }
+ }
+
+ /* u32Idx now contains the string length in bytes */
+ /* (including optional zero termination) */
+
+ /* if this is a printable string? */
+ if(*isPrintable == TRUE) {
+ /* convert to ascii (every "2nd char") */
+ /* XXX - is it possible to convert to UTF8, so the output functions work with it? */
+ for(u32IdxA = 0, u32IdxW = 0;
+ u32IdxW < u32Idx && u32IdxA < outLength-2;
+ u32IdxW+=2, u32IdxA++) {
+ pszStr[u32IdxA] = tvb_get_guint8(tvb, offset+u32IdxW);
+ }
+ } else {
+ /* convert to hexdump */
+ for(u32IdxA = 0, u32IdxW = 0;
+ u32IdxW < u32Idx && u32IdxA < outLength-2;
+ u32IdxW++, u32IdxA+=2) {
+ snprintf(&pszStr[u32IdxA], 3, "%02X", tvb_get_guint8(tvb, offset+u32IdxW));
+ }
+ }
+
+ /* zero terminate the string, space must be available */
+ DISSECTOR_ASSERT(u32IdxA < outLength);
+ pszStr[u32IdxA] = 0;
+
+ return offset + u32Idx;
+}
+
+
+/* dissect a LPWSTR into a given buffer */
+/* use FT_STRING for hfindex */
+/* u32MaxStr is maximum length of string (including trailing zero) */
+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)
+{
+ guint32 u32MaxCount;
+ guint32 u32Offset;
+ guint32 u32ArraySize;
+ guint32 u32StrStart;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ guint32 u32SubStart;
+ gboolean isPrintable;
+
+
+ /* alignment of 4 needed */
+ if (offset % 4) {
+ offset += 4 - (offset % 4);
+ }
+
+ /* add subtree item */
+ sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
+ u32SubStart = offset;
+
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_max_count, &u32MaxCount);
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_offset, &u32Offset);
+ offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep,
+ &u32ArraySize);
+
+ u32StrStart = offset;
+ offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
+
+ proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszStr);
+
+ /* update subtree header */
+ if (field_index != -1) {
+ proto_item_set_text(sub_item, "%s[%u]: %s%s%s",
+ proto_registrar_get_name(hfindex),
+ field_index,
+ isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
+ } else {
+ proto_item_append_text(sub_item, "%s%s%s",
+ isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
+ }
+ proto_item_set_len(sub_item, offset - u32SubStart);
+
+ return offset;
+}
+
+
+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)
+{
+
+
+ return dissect_dcom_indexed_LPWSTR(tvb, offset, pinfo, tree, di, drep,
+ hfindex, pszStr, u32MaxStr, -1);
+}
+
+
+/* dissect a BSTR to tree and into a given buffer (use FT_STRING for hfindex) */
+/* u32MaxStr is maximum length of string (including trailing zero) */
+/* (Hint: the BSTR space is always as long as the maximum size) */
+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)
+{
+ guint32 u32MaxCount;
+ guint32 u32ArraySize;
+ gint strStart, subStart, realOffset;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ guint32 u32ByteLength;
+ gboolean isPrintable;
+
+ /* alignment of 4 needed */
+ if (offset % 4) {
+ offset += 4 - (offset % 4);
+ }
+
+ /* add subtree item */
+ sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, "");
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr);
+ subStart = offset;
+
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_max_count, &u32MaxCount);
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_byte_length, &u32ByteLength);
+ offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep,
+ &u32ArraySize);
+
+ if ((guint32)offset + u32ArraySize*2 > G_MAXINT) {
+ pszStr[0] = 0;
+ return offset;
+ }
+
+ realOffset = offset + u32ArraySize*2;
+
+ strStart = offset;
+ offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable);
+
+ proto_tree_add_string(sub_tree, hfindex, tvb, strStart, offset - strStart, pszStr);
+
+ /* update subtree header */
+ proto_item_append_text(sub_item, "%s%s%s",
+ isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : "");
+ if (realOffset <= subStart) {
+ /* XXX - expert info */
+ return offset;
+ }
+ proto_item_set_len(sub_item, realOffset - subStart);
+
+ return realOffset;
+}
+
+
+/* dissect an DUALSTRINGARRAY */
+int
+dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex, gchar *ip)
+{
+ guint16 u16NumEntries;
+ guint16 u16SecurityOffset;
+ gchar szStr[1000];
+ guint32 u32MaxStr = sizeof(szStr);
+ guint32 u32Start;
+ guint16 u16TowerId;
+ guint16 u16SecurityAuthnSvc;
+ guint16 u16SecurityAuthzSvc;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ guint32 u32SubStart;
+ guint32 u32StringBindings = 0;
+ guint32 u32SecurityBindings = 0;
+ proto_item *subsub_item;
+ proto_tree *subsub_tree;
+ guint32 u32SubSubStart;
+ gboolean isPrintable;
+ guint32 first_ip = 0;
+ guint32 curr_ip = 0;
+ guint32 ipaddr;
+ proto_item *pi;
+
+
+ /* add subtree header */
+ sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_dualstringarray);
+
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_dualstringarray_num_entries, &u16NumEntries);
+ /* from here, alignment is ok */
+ u32SubStart = offset - 2;
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_dualstringarray_security_offset, &u16SecurityOffset);
+
+ /* STRINGBINDINGs until first wchar zero */
+ while ( tvb_get_ntohs(tvb, offset) ) {
+ u32StringBindings++;
+
+ subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_string, tvb, offset, 0, ENC_NA);
+ subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
+ u32SubSubStart = offset;
+
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
+ hf_dcom_dualstringarray_string_tower_id, &u16TowerId);
+ u32Start = offset;
+ /* we don't know the (zero terminated) input length, use the buffer length instead */
+ offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
+ pi = proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_string_network_addr,
+ tvb, u32Start, offset - u32Start, szStr);
+
+ /* convert ip address (if it is dotted decimal) */
+ /* XXX - this conversion is ugly */
+ if (ws_inet_pton4(szStr, &ipaddr)) {
+ if(get_host_ipaddr(szStr, &curr_ip)) {
+
+ /*expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "DUALSTRINGARRAY: IP:%s",
+ ip_to_str( (guint8 *) &curr_ip));*/
+
+ if(first_ip == 0) {
+ if(ip != NULL) {
+ memcpy(ip, &curr_ip, sizeof(curr_ip));
+ }
+ first_ip = curr_ip;
+ } else {
+ if(first_ip != curr_ip) {
+ address first_ip_addr, curr_ip_addr;
+
+ set_address(&first_ip_addr, AT_IPv4, 4, &first_ip);
+ set_address(&curr_ip_addr, AT_IPv4, 4, &curr_ip);
+ expert_add_info_format(pinfo, pi, &ei_dcom_dualstringarray_mult_ip,
+ "DUALSTRINGARRAY: multiple IP's %s %s",
+ address_to_str(pinfo->pool, &first_ip_addr), address_to_str(pinfo->pool, &curr_ip_addr));
+ }
+ }
+ }
+ }
+
+ proto_item_append_text(subsub_item, "[%u]: TowerId=%s, NetworkAddr=\"%s\"",
+ u32StringBindings,
+ val_to_str(u16TowerId, dcom_protseq_vals, "Unknown (0x%04x"),
+ szStr);
+ proto_item_set_len(subsub_item, offset - u32SubSubStart);
+ }
+ offset += 2;
+
+ /* SECURITYBINDINGs until first wchar zero */
+ while ( tvb_get_ntohs(tvb, offset) ) {
+ u32SecurityBindings++;
+
+ subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_security, tvb, offset, 0, ENC_NA);
+ subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding);
+ u32SubSubStart = offset;
+
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
+ hf_dcom_dualstringarray_security_authn_svc,
+ &u16SecurityAuthnSvc);
+ offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep,
+ hf_dcom_dualstringarray_security_authz_svc,
+ &u16SecurityAuthzSvc);
+
+ u32Start = offset;
+ /* we don't know the (zero terminated) input length, use the buffer length instead */
+ offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable);
+ proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_security_princ_name,
+ tvb, u32Start, offset - u32Start, szStr);
+
+ proto_item_append_text(subsub_item, "[%u]: AuthnSvc=0x%04x, AuthzSvc=0x%04x, PrincName=\"%s\"",
+ u32SecurityBindings, u16SecurityAuthnSvc, u16SecurityAuthzSvc, szStr);
+ proto_item_set_len(subsub_item, offset - u32SubSubStart);
+ }
+ offset += 2;
+
+ /* append info to subtree header */
+ proto_item_append_text(sub_item, ": STRINGBINDINGs=%u, SECURITYBINDINGs=%u",
+ u32StringBindings, u32SecurityBindings);
+ proto_item_set_len(sub_item, offset - u32SubStart);
+
+ return offset;
+}
+
+
+/* dissect an STDOBJREF */
+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)
+{
+ guint32 u32Flags;
+ guint32 u32PublicRefs;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ guint32 u32SubStart;
+
+
+ /* add subtree header */
+ sub_item = proto_tree_add_item(tree, hf_dcom_stdobjref, tvb, offset, 0, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_stdobjref);
+
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_stdobjref_flags, &u32Flags);
+ /* from here, alignment is ok */
+ u32SubStart = offset - 4;
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_stdobjref_public_refs, &u32PublicRefs);
+ offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_oxid, oxid);
+ offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_oid, oid);
+ offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_ipid, ipid);
+
+ /* append info to subtree header */
+ proto_item_append_text(sub_item, ": PublicRefs=%u IPID=%s",
+ u32PublicRefs, guids_resolve_guid_to_str(ipid, pinfo->pool));
+ proto_item_set_len(sub_item, offset - u32SubStart);
+
+ return offset;
+}
+
+
+
+/*
+ *
+ *static void
+ *print_uuid(const e_guid_t* uuid)
+*{
+ * proto_tree_add_debug_text(NULL, "UUID:(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)\n",
+ * uuid->data1, uuid->data2, uuid->data3,
+ * uuid->data4[0], uuid->data4[1],
+ * uuid->data4[2], uuid->data4[3],
+ * uuid->data4[4], uuid->data4[5],
+ * uuid->data4[6], uuid->data4[7]);
+ *
+ * return;
+ *}
+ *
+ */
+
+int
+dcom_register_routine(dcom_dissect_fn_t routine, e_guid_t* uuid)
+{
+ dcom_marshaler_t *marshaler;
+
+
+ /* check if exists already */
+ if (dcom_get_routine_by_uuid(uuid))
+ return -1;
+
+ marshaler = wmem_new(wmem_file_scope(), dcom_marshaler_t);
+ if (!marshaler) {
+ /*memory error*/
+ return -1;
+ }
+
+ marshaler->parent = NULL;
+ marshaler->private_data = NULL;
+ marshaler->uuid = *uuid;
+ marshaler->routine = routine;
+
+ dcom_marshalers = g_list_append(dcom_marshalers, marshaler);
+
+ return 0;
+}
+
+
+dcom_dissect_fn_t
+dcom_get_routine_by_uuid(const e_guid_t* uuid)
+{
+ dcom_marshaler_t *marsh;
+ GList *marshalers;
+
+ if(memcmp(uuid, &uuid_null, sizeof(uuid_null)) == 0) {
+ return NULL;
+ }
+
+ for(marshalers = dcom_marshalers; marshalers!= NULL;
+ marshalers = g_list_next(marshalers)) {
+ marsh = (dcom_marshaler_t *)marshalers->data;
+ /*print_uuid(&marsh->uuid);*/
+ /*print_uuid(uuid);*/
+ if(memcmp(&marsh->uuid, uuid, sizeof(e_guid_t)) == 0) {
+ return marsh->routine;
+ }
+ }
+
+ return NULL;
+}
+
+/* dissect an CUSTOM */
+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)
+{
+ guint32 u32CBExtension;
+ guint32 u32Size;
+ guint32 u32SubStart;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ dcom_dissect_fn_t routine = NULL;
+
+
+ /* add subtree header */
+ hfindex = hf_dcom_custobjref;
+ sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_custobjref);
+
+ u32SubStart = offset;
+ offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_clsid, clsid);
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_objref_cbextension, &u32CBExtension);
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_objref_size, &u32Size);
+
+ /* the following data depends on the iid, get the routine by iid */
+ routine = dcom_get_routine_by_uuid(iid);
+ if (routine){
+ offset = routine(tvb, offset, pinfo, sub_tree, di, drep, 0);
+ }
+
+ /* append info to subtree header */
+ /* proto_item_append_text(sub_item, ": ActivationPropertiesIn"); */
+ proto_item_set_len(sub_item, offset - u32SubStart);
+
+ return offset;
+}
+
+/* dissect an OBJREF */
+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)
+{
+ guint32 u32Signature;
+ guint32 u32Flags;
+ e_guid_t iid;
+ e_guid_t clsid;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ guint32 u32SubStart;
+ guint64 oxid = 0;
+ guint64 oid = 0;
+ e_guid_t ipid;
+ dcom_interface_t *dcom_if = NULL;
+ gchar ip[4];
+
+ memset(&ipid, 0, sizeof(ipid));
+ memset(ip, 0, sizeof(ip));
+
+ /* add subtree header */
+ sub_item = proto_tree_add_item(tree, hf_dcom_objref, tvb, offset, 0, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_objref);
+
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_objref_signature, &u32Signature);
+ /* from here, alignment is ok */
+ u32SubStart = offset - 4;
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_objref_flags, &u32Flags);
+ offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_iid, &iid);
+
+ switch(u32Flags) {
+ case(0x1): /* standard */
+ offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
+ &oxid, &oid, &ipid);
+ offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_objref_resolver_address, ip);
+ break;
+ case(0x2): /* handler (untested) */
+ offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
+ &oxid, &oid, &iid);
+ offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_clsid, &clsid);
+ offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_objref_resolver_address, ip);
+ break;
+ case(0x4): /* custom */
+ offset = dissect_dcom_CUSTOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex,
+ &clsid, &iid);
+ break;
+ }
+
+ if(u32Flags == 0x1 || u32Flags == 0x2) {
+ /* add interface instance to database (we currently only handle IPv4) */
+ if(pinfo->net_src.type == AT_IPv4) {
+ address addr;
+
+ set_address(&addr, AT_IPv4, 4, ip);
+ dcom_if = dcom_interface_new(pinfo,
+ &addr,
+ &iid, oxid, oid, &ipid);
+ }
+ }
+
+ if(interf != NULL) {
+ *interf = dcom_if;
+ }
+
+ /* append info to subtree header */
+ proto_item_set_len(sub_item, offset - u32SubStart);
+
+ return offset;
+}
+
+/* dissect an MInterfacePointer */
+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)
+{
+ guint32 u32CntData;
+ guint32 u32ArraySize;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ guint32 u32SubStart;
+
+
+ if (!hfindex) {
+ hfindex = hf_dcom_interface_pointer;
+ }
+
+ /* add subtree header */
+ sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN);
+ sub_tree = proto_item_add_subtree(sub_item, ett_dcom_interface_pointer);
+
+ offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize);
+ u32SubStart = offset - 4; /* should use this trick to deal with align pad if any */
+
+ offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
+ hf_dcom_ip_cnt_data, &u32CntData);
+
+ offset = dissect_dcom_OBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex, interf);
+
+ /* append info to subtree header */
+ proto_item_set_len(sub_item, offset - u32SubStart);
+
+ return offset;
+}
+
+/* dissect a pointer to a MInterfacePointer */
+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)
+{
+ guint32 u32Pointer;
+
+
+ offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer);
+
+ if (u32Pointer) {
+ offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, di, drep, hfindex, interf);
+ } else {
+ if(interf != NULL) {
+ *interf = NULL;
+ }
+ }
+
+ return offset;
+}
+
+static void dcom_cleanup(void) {
+ if (dcom_machines != NULL) {
+ GList *machines;
+
+ for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) {
+ dcom_machine_t *machine = (dcom_machine_t *)machines->data;
+
+ if (machine->objects != NULL) {
+ GList *objects;
+ for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) {
+ dcom_object_t *object = (dcom_object_t *)objects->data;
+
+ if (object->interfaces != NULL) {
+ GList *interface;
+ for(interface = object->interfaces; interface != NULL; interface = g_list_next(interface)) {
+ g_free(interface->data);
+ interface->data = NULL; /* for good measure */
+ }
+ g_list_free(object->interfaces);
+ object->interfaces = NULL; /* for good measure */
+ }
+
+ g_free(objects->data);
+ objects->data = NULL; /* for good measure */
+ }
+ g_list_free(machine->objects);
+ free_address(&machine->ip);
+ machine->objects = NULL; /* for good measure */
+ }
+
+ g_free(machines->data);
+ machines->data = NULL; /* for good measure */
+ }
+ g_list_free(dcom_machines);
+ dcom_machines = NULL;
+ }
+
+ /* The data in dcom_interfaces is wmem_file_scoped so there's no need to free
+ * the data pointers.
+ */
+ if (dcom_interfaces != NULL) {
+ g_list_free(dcom_interfaces);
+ dcom_interfaces = NULL;
+ }
+
+ /* The data in dcom_marshalers is wmem_file_scoped so there's no need to free
+ * the data pointers.
+ */
+ if (dcom_marshalers != NULL) {
+ g_list_free(dcom_marshalers);
+ dcom_marshalers = NULL;
+ }
+}
+
+void
+proto_register_dcom (void)
+{
+ static hf_register_info hf_dcom_this_array[] = {
+#if 0
+ { &hf_dcom_this_version_major,
+ { "VersionMajor", "dcom.this.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+#endif
+#if 0
+ { &hf_dcom_this_version_minor,
+ { "VersionMinor", "dcom.this.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+#endif
+ { &hf_dcom_this_flags,
+ { "Flags", "dcom.this.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }},
+ { &hf_dcom_this_res,
+ { "Reserved", "dcom.this.res", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_this_cid,
+ { "Causality ID", "dcom.this.uuid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
+ };
+
+ static hf_register_info hf_dcom_that_array[] = {
+ { &hf_dcom_that_flags,
+ { "Flags", "dcom.that.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }}
+ };
+
+ static hf_register_info hf_dcom_extent_array[] = {
+ { &hf_dcom_extent,
+ { "Extension", "dcom.extent", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_extent_array_count,
+ { "Extension Count", "dcom.extent.array_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_extent_array_res,
+ { "Reserved", "dcom.extent.array_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_extent_size,
+ { "Extension Size", "dcom.extent.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_extent_id,
+ { "Extension Id", "dcom.extent.id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
+ };
+
+ static hf_register_info hf_dcom_array[] = {
+ { &hf_dcom_version_major,
+ { "VersionMajor", "dcom.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_version_minor,
+ { "VersionMinor", "dcom.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_hresult,
+ { "HResult", "dcom.hresult", FT_UINT32, BASE_HEX, VALS(dcom_hresult_vals), 0x0, NULL, HFILL }},
+ { &hf_dcom_max_count,
+ { "MaxCount", "dcom.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_offset,
+ { "Offset", "dcom.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_byte_length,
+ { "ByteLength", "dcom.byte_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+#if 0
+ { &hf_dcom_actual_count,
+ { "ActualCount", "dcom.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+#endif
+ { &hf_dcom_tobedone,
+ { "To Be Done", "dcom.tobedone", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_nospec,
+ { "No Specification Available", "dcom.nospec", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+#if 0
+ { &hf_dcom_variant,
+ { "Variant", "dcom.variant", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+#endif
+ { &hf_dcom_variant_type,
+ { "VarType", "dcom.variant_type", FT_UINT16, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
+ { &hf_dcom_variant_type32,
+ { "VarType32", "dcom.variant_type32", FT_UINT32, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
+ { &hf_dcom_variant_size,
+ { "Size", "dcom.variant_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_variant_rpc_res,
+ { "RPC-Reserved", "dcom.variant_rpc_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_variant_wres,
+ { "Reserved", "dcom.variant_wres", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_array_size,
+ { "(ArraySize)", "dcom.array_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_pointer_val,
+ { "(PointerVal)", "dcom.pointer_val", FT_UINT32, BASE_HEX, VALS(dcom_dcerpc_pointer_vals), 0x0, NULL, HFILL }}
+ };
+
+ static hf_register_info hf_dcom_interface_pointer_array[] = {
+ { &hf_dcom_interface_pointer,
+ { "InterfacePointer", "dcom.ifp", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_ip_cnt_data,
+ { "CntData", "dcom.ip_cnt_data", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
+ };
+
+ static hf_register_info hf_dcom_objref_array[] = {
+ { &hf_dcom_objref,
+ { "OBJREF", "dcom.objref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_objref_signature,
+ { "Signature", "dcom.objref.signature", FT_UINT32, BASE_HEX, VALS(dcom_objref_signature_vals), 0x0, NULL, HFILL }},
+ { &hf_dcom_objref_flags,
+ { "Flags", "dcom.objref.flags", FT_UINT32, BASE_HEX, VALS(dcom_objref_flag_vals), 0x0, NULL, HFILL }},
+ { &hf_dcom_iid,
+ { "IID", "dcom.iid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_clsid,
+ { "CLSID", "dcom.clsid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_objref_resolver_address,
+ { "ResolverAddress", "dcom.objref.resolver_address", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_objref_cbextension,
+ { "CBExtension", "dcom.objref.cbextension", FT_UINT32, BASE_DEC, NULL, 0x0, "Size of extension data", HFILL }},
+ { &hf_dcom_objref_size,
+ { "Size", "dcom.objref.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
+ };
+
+ static hf_register_info hf_dcom_stdobjref_array[] = {
+ { &hf_dcom_stdobjref,
+ { "STDOBJREF", "dcom.stdobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_stdobjref_flags,
+ { "Flags", "dcom.stdobjref.flags", FT_UINT32, BASE_HEX, VALS(dcom_stdobjref_flag_vals), 0x0, NULL, HFILL }},
+ { &hf_dcom_stdobjref_public_refs,
+ { "PublicRefs", "dcom.stdobjref.public_refs", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_oxid,
+ { "OXID", "dcom.oxid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_oid,
+ { "OID", "dcom.oid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_ipid,
+ { "IPID", "dcom.ipid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}
+ };
+
+ static hf_register_info hf_dcom_custobjref_array[] = {
+ { &hf_dcom_custobjref,
+ { "CUSTOMOBJREF", "dcom.custobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ };
+
+
+ static hf_register_info hf_dcom_dualstringarray_array[] = {
+ { &hf_dcom_dualstringarray_num_entries,
+ { "NumEntries", "dcom.dualstringarray.num_entries", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_dualstringarray_security_offset,
+ { "SecurityOffset", "dcom.dualstringarray.security_offset", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_dualstringarray_string,
+ { "StringBinding", "dcom.dualstringarray.string", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_dualstringarray_string_tower_id,
+ { "TowerId", "dcom.dualstringarray.tower_id", FT_UINT16, BASE_HEX, VALS(dcom_protseq_vals), 0x0, NULL, HFILL }},
+ { &hf_dcom_dualstringarray_string_network_addr,
+ { "NetworkAddr", "dcom.dualstringarray.network_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_dualstringarray_security,
+ { "SecurityBinding", "dcom.dualstringarray.security", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_dualstringarray_security_authn_svc,
+ { "AuthnSvc", "dcom.dualstringarray.security_authn_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authn), 0x0, NULL, HFILL }},
+ { &hf_dcom_dualstringarray_security_authz_svc,
+ { "AuthzSvc", "dcom.dualstringarray.security_authz_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authz), 0x0, NULL, HFILL }},
+ { &hf_dcom_dualstringarray_security_princ_name,
+ { "PrincName", "dcom.dualstringarray.security_princ_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}
+ };
+
+ static hf_register_info hf_dcom_vt_array[] = {
+ { &hf_dcom_vt_bool,
+ { "VT_BOOL", "dcom.vt.bool", FT_UINT16, BASE_HEX, VALS(dcom_vt_bool_vals), 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_i1,
+ { "VT_I1", "dcom.vt.i1", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_i2,
+ { "VT_I2", "dcom.vt.i2", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_i4,
+ { "VT_I4", "dcom.vt.i4", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_i8,
+ { "VT_I8", "dcom.vt.i8", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_cy,
+ { "VT_CY", "dcom.vt.cy", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_ui1,
+ { "VT_UI1", "dcom.vt.ui1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_ui2,
+ { "VT_UI2", "dcom.vt.ui2", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_ui4,
+ { "VT_UI4", "dcom.vt.ui4", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_ui8,
+ { "VT_UI8", "dcom.vt.ui8", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_r4,
+ { "VT_R4", "dcom.vt.r4", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_r8,
+ { "VT_R8", "dcom.vt.r8", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_date,
+ { "VT_DATE", "dcom.vt.date", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_bstr,
+ { "VT_BSTR", "dcom.vt.bstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_byref,
+ { "BYREF", "dcom.vt.byref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_vt_dispatch,
+ { "VT_DISPATCH", "dcom.vt.dispatch", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}
+ };
+
+ static hf_register_info hf_dcom_sa_array[] = {
+ { &hf_dcom_safearray,
+ { "SAFEARRAY", "dcom.sa", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_sa_dims32,
+ { "Dims32", "dcom.sa.dims32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_sa_dims16,
+ { "Dims16", "dcom.sa.dims16", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_sa_features,
+ { "Features", "dcom.sa.features", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_sa_element_size,
+ { "ElementSize", "dcom.sa.element_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_sa_locks,
+ { "Locks", "dcom.sa.locks", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_sa_vartype32,
+ { "VarType32", "dcom.sa.vartype", FT_UINT32, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
+ { &hf_dcom_sa_vartype16,
+ { "VarType16", "dcom.sa.vartype", FT_UINT16, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }},
+ { &hf_dcom_sa_elements,
+ { "Elements", "dcom.sa.elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_sa_bound_elements,
+ { "BoundElements", "dcom.sa.bound_elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcom_sa_low_bound,
+ { "LowBound", "dcom.sa.low_bound", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_dcom_sa_features_auto,
+ { "AUTO", "dcom.sa.features_auto", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_AUTO, NULL, HFILL }},
+ { &hf_dcom_sa_features_static,
+ { "STATIC", "dcom.sa.features_static", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_STATIC, NULL, HFILL }},
+ { &hf_dcom_sa_features_embedded,
+ { "EMBEDDED", "dcom.sa.features_embedded", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_EMBEDDED, NULL, HFILL }},
+ { &hf_dcom_sa_features_fixedsize,
+ { "FIXEDSIZE", "dcom.sa.features_fixedsize", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_FIXEDSIZE, NULL, HFILL }},
+ { &hf_dcom_sa_features_record,
+ { "RECORD", "dcom.sa.features_record", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_RECORD, NULL, HFILL }},
+ { &hf_dcom_sa_features_have_iid,
+ { "HAVEIID", "dcom.sa.features_have_iid", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEIID, NULL, HFILL }},
+ { &hf_dcom_sa_features_have_vartype,
+ { "HAVEVARTYPE", "dcom.sa.features_have_vartype", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEVARTYPE, NULL, HFILL }},
+ { &hf_dcom_sa_features_bstr,
+ { "BSTR", "dcom.sa.features_bstr", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_BSTR, NULL, HFILL }},
+ { &hf_dcom_sa_features_unknown,
+ { "UNKNOWN", "dcom.sa.features_unknown", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_UNKNOWN, NULL, HFILL }},
+ { &hf_dcom_sa_features_dispatch,
+ { "DISPATCH", "dcom.sa.features_dispatch", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_DISPATCH, NULL, HFILL }},
+ { &hf_dcom_sa_features_variant,
+ { "VARIANT", "dcom.sa.features_variant", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_VARIANT, NULL, HFILL }}
+ };
+
+ static gint *ett_dcom[] = {
+ &ett_dcom_this,
+ &ett_dcom_that,
+ &ett_dcom_extent,
+ &ett_dcom_lpwstr,
+ &ett_dcom_interface_pointer,
+ &ett_dcom_objref,
+ &ett_dcom_stdobjref,
+ &ett_dcom_custobjref,
+ &ett_dcom_dualstringarray,
+ &ett_dcom_dualstringarray_binding,
+ &ett_dcom_variant,
+ &ett_dcom_safearray,
+ &ett_dcom_sa_features,
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_dcom_dissection_incomplete, { "dcom.dissection_incomplete", PI_UNDECODED, PI_WARN, "Dissection incomplete", EXPFILL }},
+ { &ei_dcom_no_spec, { "dcom.no_spec", PI_UNDECODED, PI_NOTE, "No specification available, dissection not possible", EXPFILL }},
+ { &ei_dcom_hresult_expert, { "dcom.hresult.expert", PI_RESPONSE_CODE, PI_NOTE, "Hresult", EXPFILL }},
+ { &ei_dcom_dualstringarray_mult_ip, { "dcom.dualstringarray.mult_ip", PI_UNDECODED, PI_NOTE, "DUALSTRINGARRAY Multiple IP", EXPFILL }},
+ };
+
+ module_t *dcom_module;
+ expert_module_t* expert_dcom;
+
+ /* currently, the DCOM protocol "itself" has no real protocol dissector */
+ /* we only need this, to register some generic elements */
+ proto_dcom = proto_register_protocol ("DCOM", "DCOM", "dcom");
+ proto_register_field_array(proto_dcom, hf_dcom_this_array, array_length(hf_dcom_this_array));
+ proto_register_field_array(proto_dcom, hf_dcom_that_array, array_length(hf_dcom_that_array));
+ proto_register_field_array(proto_dcom, hf_dcom_extent_array, array_length(hf_dcom_extent_array));
+ proto_register_field_array(proto_dcom, hf_dcom_array, array_length(hf_dcom_array));
+ proto_register_field_array(proto_dcom, hf_dcom_objref_array, array_length(hf_dcom_objref_array));
+ proto_register_field_array(proto_dcom, hf_dcom_stdobjref_array, array_length(hf_dcom_stdobjref_array));
+ proto_register_field_array(proto_dcom, hf_dcom_custobjref_array, array_length(hf_dcom_custobjref_array));
+ proto_register_field_array(proto_dcom, hf_dcom_dualstringarray_array, array_length(hf_dcom_dualstringarray_array));
+ proto_register_field_array(proto_dcom, hf_dcom_interface_pointer_array, array_length(hf_dcom_interface_pointer_array));
+ proto_register_field_array(proto_dcom, hf_dcom_vt_array, array_length(hf_dcom_vt_array));
+ proto_register_field_array(proto_dcom, hf_dcom_sa_array, array_length(hf_dcom_sa_array));
+ proto_register_subtree_array (ett_dcom, array_length (ett_dcom));
+
+ expert_dcom = expert_register_protocol(proto_dcom);
+ expert_register_field_array(expert_dcom, ei, array_length(ei));
+
+ /* preferences */
+ dcom_module = prefs_register_protocol(proto_dcom, NULL);
+
+ prefs_register_bool_preference(dcom_module, "display_unmarshalling_details",
+ "Display DCOM unmarshalling details",
+ "Display some DCOM unmarshalled fields "
+ "usually hidden",
+ &dcom_prefs_display_unmarshalling_details);
+
+ register_cleanup_routine(dcom_cleanup);
+}
+
+
+void
+proto_reg_handoff_dcom (void)
+{
+ /* register some "well known" UUID's */
+ guids_add_uuid(&uuid_debug_ext, "Debug Information Body Extension");
+ guids_add_uuid(&uuid_ext_error_ext, "Extended Error Info Body Extension");
+ guids_add_uuid(&ipid_rem_unknown, "IRemUnknown");
+ guids_add_uuid(&iid_unknown, "IUnknown");
+ guids_add_uuid(&uuid_null, "NULL");
+ guids_add_uuid(&iid_class_factory, "IClassFactory");
+ guids_add_uuid(&iid_type_info, "ITypeInfo");
+ guids_add_uuid(&iid_provide_class_info, "IProvideClassInfo");
+
+ /* Currently, we have nothing to register for DCOM */
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */