#include <epan/addr_resolv.h>
#include <epan/show_exception.h>
#include <epan/decode_as.h>
+#include <epan/proto_data.h>
+
#include <wsutil/str_util.h>
#include "packet-tcp.h"
#include "packet-dcerpc.h"
{ 0x00000005, "nca_s_fault_access_denied" },
{ 0x000006f7, "nca_s_fault_ndr" },
{ 0x000006d8, "nca_s_fault_cant_perform" },
+ { 0x00000721, "nca_s_fault_sec_pkg_error" },
{ 0x1c000001, "nca_s_fault_int_div_by_zero" },
{ 0x1c000002, "nca_s_fault_addr_error" },
{ 0x1c000003, "nca_s_fault_fp_div_zero" },
static int hf_dcerpc_reassembled_in = -1;
static int hf_dcerpc_reassembled_length = -1;
static int hf_dcerpc_unknown_if_id = -1;
+static int hf_dcerpc_sec_vt_signature = -1;
+static int hf_dcerpc_sec_vt_command = -1;
+static int hf_dcerpc_sec_vt_command_cmd = -1;
+static int hf_dcerpc_sec_vt_command_end = -1;
+static int hf_dcerpc_sec_vt_command_must = -1;
+static int hf_dcerpc_sec_vt_command_length = -1;
+static int hf_dcerpc_sec_vt_bitmask = -1;
+static int hf_dcerpc_sec_vt_bitmask_sign = -1;
+static int hf_dcerpc_sec_vt_pcontext_uuid = -1;
+static int hf_dcerpc_sec_vt_pcontext_ver = -1;
+
+static const int *sec_vt_command_fields[] = {
+ &hf_dcerpc_sec_vt_command_cmd,
+ &hf_dcerpc_sec_vt_command_end,
+ &hf_dcerpc_sec_vt_command_must,
+ NULL
+};
+static int hf_dcerpc_reserved = -1;
+static int hf_dcerpc_unknown = -1;
+static int hf_dcerpc_missalign = -1;
+
/* Generated from convert_proto_tree_add_text.pl */
static int hf_dcerpc_duplicate_ptr = -1;
static int hf_dcerpc_encrypted_stub_data = -1;
static int hf_dcerpc_decrypted_stub_data = -1;
+static int hf_dcerpc_payload_stub_data = -1;
+static int hf_dcerpc_stub_data_with_sec_vt = -1;
static int hf_dcerpc_stub_data = -1;
static int hf_dcerpc_auth_padding = -1;
static int hf_dcerpc_auth_verifier = -1;
+static int hf_dcerpc_auth_info = -1;
static int hf_dcerpc_auth_credentials = -1;
static int hf_dcerpc_fault_stub_data = -1;
static int hf_dcerpc_fragment_data = -1;
NULL
};
+static const int *sec_vt_bitmask_fields[] = {
+ &hf_dcerpc_sec_vt_bitmask_sign,
+ NULL
+};
+
+static const value_string sec_vt_command_cmd_vals[] = {
+ {1, "BITMASK_1"},
+ {2, "PCONTEXT"},
+ {3, "HEADER2"},
+ {0, NULL}
+};
+
static gint ett_dcerpc = -1;
static gint ett_dcerpc_cn_flags = -1;
static gint ett_dcerpc_cn_ctx = -1;
static gint ett_dcerpc_fragments = -1;
static gint ett_dcerpc_fragment = -1;
static gint ett_dcerpc_krb5_auth_verf = -1;
+static gint ett_dcerpc_auth_info = -1;
+static gint ett_dcerpc_verification_trailer = -1;
+static gint ett_dcerpc_sec_vt_command = -1;
+static gint ett_dcerpc_sec_vt_bitmask = -1;
+static gint ett_dcerpc_sec_vt_pcontext = -1;
+static gint ett_dcerpc_sec_vt_header = -1;
+static gint ett_dcerpc_complete_stub_data = -1;
static expert_field ei_dcerpc_fragment_multiple = EI_INIT;
static expert_field ei_dcerpc_cn_status = EI_INIT;
static expert_field ei_dcerpc_long_frame = EI_INIT;
static expert_field ei_dcerpc_cn_rts_command = EI_INIT;
+static const guint8 TRAILER_SIGNATURE[] = {0x8a, 0xe3, 0x13, 0x71, 0x02, 0xf4, 0x36, 0x71};
+static tvbuff_t *tvb_trailer_signature = NULL;
static GSList *decode_dcerpc_bindings = NULL;
/*
{
decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t *)binding_in;
- g_free((void *) binding->addr_a.data);
- g_free((void *) binding->addr_b.data);
+ free_address(&binding->addr_a);
+ free_address(&binding->addr_b);
if (binding->ifname)
g_string_free(binding->ifname, TRUE);
g_free(binding);
/* remove a binding (looking the same way as the given one) */
static gboolean
-decode_dcerpc_binding_reset(const char *name _U_, const gpointer pattern)
+decode_dcerpc_binding_reset(const char *name _U_, gconstpointer pattern)
{
- decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t*)pattern;
+ const decode_dcerpc_bind_values_t *binding = (const decode_dcerpc_bind_values_t *)pattern;
GSList *le;
decode_dcerpc_bind_values_t *old_binding;
decode_dcerpc_bindings = g_slist_remove(decode_dcerpc_bindings, le->data);
- g_free((void *) old_binding->addr_a.data);
- g_free((void *) old_binding->addr_b.data);
+ free_address(&old_binding->addr_a);
+ free_address(&old_binding->addr_b);
g_string_free(old_binding->ifname, TRUE);
g_free(old_binding);
return FALSE;
}
static gboolean
-dcerpc_decode_as_change(const char *name, const gpointer pattern, gpointer handle, gchar* list_name)
+dcerpc_decode_as_change(const char *name, gconstpointer pattern, gpointer handle, gchar* list_name)
{
decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t*)pattern;
decode_dcerpc_bind_values_t *stored_binding;
const void *data)
{
dcerpc_fragment_key *key = g_slice_new(dcerpc_fragment_key);
- e_dce_dg_common_hdr_t *hdr = (e_dce_dg_common_hdr_t *)data;
+ const e_dce_dg_common_hdr_t *hdr = (const e_dce_dg_common_hdr_t *)data;
- key->src = pinfo->src;
- key->dst = pinfo->dst;
+ copy_address_shallow(&key->src, &pinfo->src);
+ copy_address_shallow(&key->dst, &pinfo->dst);
key->id = id;
key->act_id = hdr->act_id;
const void *data)
{
dcerpc_fragment_key *key = g_slice_new(dcerpc_fragment_key);
- e_dce_dg_common_hdr_t *hdr = (e_dce_dg_common_hdr_t *)data;
+ const e_dce_dg_common_hdr_t *hdr = (const e_dce_dg_common_hdr_t *)data;
copy_address(&key->src, &pinfo->src);
copy_address(&key->dst, &pinfo->dst);
/*
* Free up the copies of the addresses from the old key.
*/
- g_free((gpointer)key->src.data);
- g_free((gpointer)key->dst.data);
+ free_address(&key->src);
+ free_address(&key->dst);
g_slice_free(dcerpc_fragment_key, key);
}
/* Hand off verifier data to a registered dissector */
-static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo,
- proto_tree *tree,
- dcerpc_auth_subdissector_fns *auth_fns,
+static void dissect_auth_verf(packet_info *pinfo,
e_dce_cn_common_hdr_t *hdr,
dcerpc_auth_info *auth_info)
{
*/
FAKE_DCERPC_INFO_STRUCTURE
+ if (auth_info == NULL) {
+ return;
+ }
+
+ if (auth_info->auth_fns == NULL) {
+ return;
+ }
+
switch (hdr->ptype) {
case PDU_BIND:
case PDU_ALTER:
- fn = auth_fns->bind_fn;
+ fn = auth_info->auth_fns->bind_fn;
break;
case PDU_BIND_ACK:
case PDU_ALTER_ACK:
- fn = auth_fns->bind_ack_fn;
+ fn = auth_info->auth_fns->bind_ack_fn;
break;
case PDU_AUTH3:
- fn = auth_fns->auth3_fn;
+ fn = auth_info->auth_fns->auth3_fn;
break;
case PDU_REQ:
- fn = auth_fns->req_verf_fn;
+ case PDU_CO_CANCEL:
+ case PDU_ORPHANED:
+ fn = auth_info->auth_fns->req_verf_fn;
break;
case PDU_RESP:
- fn = auth_fns->resp_verf_fn;
+ case PDU_FAULT:
+ fn = auth_info->auth_fns->resp_verf_fn;
break;
default:
/* Don't know how to handle authentication data in this
pdu type. */
- proto_tree_add_expert_format(tree, pinfo, &ei_dcerpc_invalid_pdu_authentication_attempt,
- auth_tvb, 0, 0,
+ proto_tree_add_expert_format(auth_info->auth_tree, pinfo,
+ &ei_dcerpc_invalid_pdu_authentication_attempt,
+ auth_info->auth_tvb, 0, 0,
"Don't know how to dissect authentication data for %s pdu type",
val_to_str(hdr->ptype, pckt_vals, "Unknown (%u)"));
return;
}
if (fn)
- fn(auth_tvb, 0, pinfo, tree, &di, hdr->drep);
- else {
- proto_tree_add_expert_format(tree, pinfo, &ei_dcerpc_verifier_unavailable,
- auth_tvb, 0, hdr->auth_len,
+ fn(auth_info->auth_tvb, 0, pinfo, auth_info->auth_tree, &di, hdr->drep);
+ else
+ proto_tree_add_expert_format(auth_info->auth_tree, pinfo,
+ &ei_dcerpc_verifier_unavailable,
+ auth_info->auth_tvb, 0, hdr->auth_len,
"%s Verifier unavailable",
val_to_str(auth_info->auth_type,
authn_protocol_vals,
"Unknown (%u)"));
- }
}
static proto_item*
/* Hand off payload data to a registered dissector */
static tvbuff_t *decode_encrypted_data(tvbuff_t *data_tvb,
- tvbuff_t *auth_tvb,
packet_info *pinfo,
- dcerpc_auth_subdissector_fns *auth_fns,
- gboolean is_request,
+ e_dce_cn_common_hdr_t *hdr,
dcerpc_auth_info *auth_info)
{
- dcerpc_decode_data_fnct_t *fn;
+ dcerpc_decode_data_fnct_t *fn = NULL;
- if (is_request)
- fn = auth_fns->req_data_fn;
- else
- fn = auth_fns->resp_data_fn;
+ if (auth_info == NULL)
+ return NULL;
+
+ if (auth_info->auth_fns == NULL)
+ return NULL;
+
+ switch (hdr->ptype) {
+ case PDU_REQ:
+ fn = auth_info->auth_fns->req_data_fn;
+ break;
+ case PDU_RESP:
+ case PDU_FAULT:
+ fn = auth_info->auth_fns->resp_data_fn;
+ break;
+ }
if (fn)
- return fn(data_tvb, auth_tvb, 0, pinfo, auth_info);
+ return fn(data_tvb, auth_info->auth_tvb, 0, pinfo, auth_info);
return NULL;
}
gboolean decrypted;
dcerpc_auth_info *auth_info;
guint8 *drep;
+ proto_tree *dcerpc_tree;
} dcerpc_dissector_data_t;
/*
return key->guid.data1;
}
+
+static int
+dissect_verification_trailer(packet_info *pinfo, tvbuff_t *tvb, int stub_offset,
+ proto_tree *parent_tree, int *signature_offset);
+
static void
-show_stub_data(tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
+show_stub_data(packet_info *pinfo, tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
dcerpc_auth_info *auth_info, gboolean is_encrypted)
{
int length, plain_length, auth_pad_len;
auth_pad_len = 0;
} else {
proto_tree_add_item(dcerpc_tree, hf_dcerpc_decrypted_stub_data, tvb, offset, plain_length, ENC_NA);
+ dissect_verification_trailer(pinfo, tvb, offset, dcerpc_tree, NULL);
}
} else {
proto_tree_add_item(dcerpc_tree, hf_dcerpc_stub_data, tvb, offset, plain_length, ENC_NA);
+ dissect_verification_trailer(pinfo, tvb, offset, dcerpc_tree, NULL);
}
/* If there is auth padding at the end of the stub, display it */
if (auth_pad_len != 0) {
dcerpc_dissector_data_t* dissector_data = (dcerpc_dissector_data_t*)data;
const gchar *name = NULL;
dcerpc_sub_dissector *proc;
- dcerpc_dissect_fnct_t *sub_dissect = NULL;
+ int (*volatile sub_dissect)(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) = NULL;
proto_item *pi, *sub_item;
proto_tree *sub_tree;
- guint length, reported_length;
+ volatile guint length;
+ guint reported_length;
volatile gint offset = 0;
tvbuff_t *volatile stub_tvb;
+ tvbuff_t *volatile payload_tvb = NULL;
volatile guint auth_pad_len;
volatile int auth_pad_offset;
const char *volatile saved_proto;
}
} /* tree */
- if (dissector_data->decrypted || (sub_dissect == NULL))
+ if (!dissector_data->decrypted || (sub_dissect == NULL))
{
- show_stub_data(tvb, 0, sub_tree, dissector_data->auth_info, !dissector_data->decrypted);
+ show_stub_data(pinfo, tvb, 0, sub_tree, dissector_data->auth_info, !dissector_data->decrypted);
return tvb_captured_length(tvb);
}
/* Either there was no encryption or we successfully decrypted
- the encrypted payload. */
+ the encrypted payload. */
/* We have a subdissector - call it. */
saved_proto = pinfo->current_proto;
reported_length = tvb_reported_length(tvb);
/*
- * Remove the authentication padding from the stub data.
- */
+ * Remove the authentication padding from the stub data.
+ */
if ((dissector_data->auth_info != NULL) && (dissector_data->auth_info->auth_pad_len != 0)) {
if (reported_length >= dissector_data->auth_info->auth_pad_len) {
/*
- * OK, the padding length isn't so big that it
- * exceeds the stub length. Trim the reported
- * length of the tvbuff.
- */
+ * OK, the padding length isn't so big that it
+ * exceeds the stub length. Trim the reported
+ * length of the tvbuff.
+ */
reported_length -= dissector_data->auth_info->auth_pad_len;
/*
- * If that exceeds the actual amount of data in
- * the tvbuff (which means we have at least one
- * byte of authentication padding in the tvbuff),
- * trim the actual amount.
- */
+ * If that exceeds the actual amount of data in
+ * the tvbuff (which means we have at least one
+ * byte of authentication padding in the tvbuff),
+ * trim the actual amount.
+ */
if (length > reported_length)
length = reported_length;
auth_pad_offset = reported_length;
} else {
/*
- * The padding length exceeds the stub length.
- * Don't bother dissecting the stub, trim the padding
- * length to what's in the stub data, and show the
- * entire stub as authentication padding.
- */
+ * The padding length exceeds the stub length.
+ * Don't bother dissecting the stub, trim the padding
+ * length to what's in the stub data, and show the
+ * entire stub as authentication padding.
+ */
stub_tvb = NULL;
auth_pad_len = reported_length;
auth_pad_offset = 0;
}
} else {
/*
- * No authentication padding.
- */
+ * No authentication padding.
+ */
stub_tvb = tvb;
auth_pad_len = 0;
auth_pad_offset = 0;
if (stub_tvb != NULL) {
/*
- * Catch all exceptions other than BoundsError, so that even
- * if the stub data is bad, we still show the authentication
- * padding, if any.
- *
- * If we get BoundsError, it means the frame was cut short
- * by a snapshot length, so there's nothing more to
- * dissect; just re-throw that exception.
- */
+ * Catch all exceptions other than BoundsError, so that even
+ * if the stub data is bad, we still show the authentication
+ * padding, if any.
+ *
+ * If we get BoundsError, it means the frame was cut short
+ * by a snapshot length, so there's nothing more to
+ * dissect; just re-throw that exception.
+ */
TRY {
+ proto_tree *stub_tree = NULL;
int remaining;
+ int trailer_start_offset = -1;
+ int trailer_end_offset = -1;
+
+ stub_tree = proto_tree_add_subtree_format(dissector_data->dcerpc_tree,
+ stub_tvb, 0, length,
+ ett_dcerpc_complete_stub_data, NULL,
+ "Complete stub data (%d byte%s)", length,
+ plurality(length, "", "s"));
+ trailer_end_offset = dissect_verification_trailer(pinfo,
+ stub_tvb, 0,
+ stub_tree,
+ &trailer_start_offset);
+
+ if (trailer_end_offset != -1) {
+ remaining = tvb_captured_length_remaining(stub_tvb,
+ trailer_start_offset);
+ length -= remaining;
+
+ if (sub_item) {
+ proto_item_set_len(sub_item, length);
+ }
+ } else {
+ proto_item *payload_item;
- offset = sub_dissect(stub_tvb, 0, pinfo, sub_tree,
- dissector_data->info, dissector_data->drep);
+ payload_item = proto_tree_add_item(stub_tree,
+ hf_dcerpc_payload_stub_data,
+ stub_tvb, 0, length, ENC_NA);
+ proto_item_append_text(payload_item, " (%d byte%s)",
+ length, plurality(length, "", "s"));
+ }
+
+ payload_tvb = tvb_new_subset(stub_tvb, 0, length, length);
+ offset = sub_dissect(payload_tvb, 0, pinfo, sub_tree,
+ dissector_data->info, dissector_data->drep);
/* If we have a subdissector and it didn't dissect all
data in the tvb, make a note of it. */
remaining = tvb_reported_length_remaining(stub_tvb, offset);
+
+ if (trailer_end_offset != -1) {
+ if (offset > trailer_start_offset) {
+ remaining = offset - trailer_start_offset;
+ proto_tree_add_item(sub_tree, hf_dcerpc_stub_data_with_sec_vt,
+ stub_tvb, trailer_start_offset, remaining, ENC_NA);
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "[Payload with Verification Trailer (%d byte%s)]",
+ remaining,
+ plurality(remaining, "", "s"));
+ remaining = 0;
+ } else {
+ remaining = trailer_start_offset - offset;
+ }
+ }
+
if (remaining > 0) {
proto_tree_add_expert(sub_tree, pinfo, &ei_dcerpc_long_frame, stub_tvb, offset, remaining);
col_append_fstr(pinfo->cinfo, COL_INFO,
"[Long frame (%d byte%s)]",
remaining,
plurality(remaining, "", "s"));
-
}
} CATCH_NONFATAL_ERRORS {
/*
- * Somebody threw an exception that means that there
- * was a problem dissecting the payload; that means
- * that a dissector was found, so we don't need to
- * dissect the payload as data or update the protocol
- * or info columns.
- *
- * Just show the exception and then drive on to show
- * the authentication padding.
- */
+ * Somebody threw an exception that means that there
+ * was a problem dissecting the payload; that means
+ * that a dissector was found, so we don't need to
+ * dissect the payload as data or update the protocol
+ * or info columns.
+ *
+ * Just show the exception and then drive on to show
+ * the authentication padding.
+ */
show_exception(stub_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
} ENDTRY;
}
hf_info->strings = value_string_from_subdissectors(procs);
/* Register the GUID with the dissector table */
- guid_handle = new_create_dissector_handle( dissect_dcerpc_guid, proto);
+ guid_handle = create_dissector_handle( dissect_dcerpc_guid, proto);
dissector_add_guid( "dcerpc.uuid", key, guid_handle );
/* add this GUID to the global name resolving */
const char *
dcerpc_get_proto_name(e_guid_t *uuid, guint16 ver)
{
+ dissector_handle_t handle;
guid_key key;
key.guid = *uuid;
key.ver = ver;
- return dissector_handle_get_short_name(dissector_get_guid_handle(uuid_dissector_table, &key));
+ handle = dissector_get_guid_handle(uuid_dissector_table, &key);
+ if (handle == NULL) {
+ return NULL;
+ }
+
+ return dissector_handle_get_short_name(handle);
}
/* Function to find the opnum hf-field of a registered protocol
guint i = 0;
srt_stat_table *dcerpc_srt_table;
srt_data_t *data = (srt_data_t *)pss;
- const dcerpc_info *ri = (dcerpc_info *)prv;
+ const dcerpc_info *ri = (const dcerpc_info *)prv;
dcerpcstat_tap_data_t* tap_data;
dcerpc_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
static guint
dcerpcstat_param(register_srt_t* srt, const char* opt_arg, char** err)
{
- guint pos = 0;
+ int pos = 0;
guint32 i, max_procs;
dcerpcstat_tap_data_t* tap_data;
guint d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
* Utility functions. Modeled after packet-rpc.c
*/
+int
+dissect_dcerpc_char(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint8 *pdata)
+{
+ guint8 data;
+
+ /*
+ * XXX - fix to handle EBCDIC if we ever support EBCDIC FT_CHAR.
+ */
+ data = tvb_get_guint8(tvb, offset);
+ if (hfindex != -1) {
+ proto_tree_add_item(tree, hfindex, tvb, offset, 1, ENC_ASCII|DREP_ENC_INTEGER(drep));
+ }
+ if (pdata)
+ *pdata = data;
+ tvb_ensure_bytes_exist(tvb, offset, 1);
+ return offset + 1;
+}
+
int
dissect_dcerpc_uint8(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
proto_tree *tree, guint8 *drep,
guint8 data;
data = tvb_get_guint8(tvb, offset);
- if (tree && hfindex != -1) {
+ if (hfindex != -1) {
proto_tree_add_item(tree, hfindex, tvb, offset, 1, DREP_ENC_INTEGER(drep));
}
if (pdata)
*pdata = data;
+ tvb_ensure_bytes_exist(tvb, offset, 1);
return offset + 1;
}
? tvb_get_letohs(tvb, offset)
: tvb_get_ntohs(tvb, offset));
- if (tree && hfindex != -1) {
+ if (hfindex != -1) {
proto_tree_add_item(tree, hfindex, tvb, offset, 2, DREP_ENC_INTEGER(drep));
}
if (pdata)
*pdata = data;
+ tvb_ensure_bytes_exist(tvb, offset, 2);
return offset + 2;
}
? tvb_get_letohl(tvb, offset)
: tvb_get_ntohl(tvb, offset));
- if (tree && hfindex != -1) {
+ if (hfindex != -1) {
proto_tree_add_item(tree, hfindex, tvb, offset, 4, DREP_ENC_INTEGER(drep));
}
if (pdata)
*pdata = data;
+ tvb_ensure_bytes_exist(tvb, offset, 4);
return offset+4;
}
tv.secs = data;
tv.nsecs = 0;
- if (tree && hfindex != -1) {
+ if (hfindex != -1) {
if (data == 0xffffffff) {
/* special case, no time specified */
proto_tree_add_time_format_value(tree, hfindex, tvb, offset, 4, &tv, "No time specified");
if (pdata)
*pdata = data;
+ tvb_ensure_bytes_exist(tvb, offset, 4);
return offset+4;
}
? tvb_get_letoh64(tvb, offset)
: tvb_get_ntoh64(tvb, offset));
- if (tree && hfindex != -1) {
+ if (hfindex != -1) {
header_field_info *hfinfo;
/* This might be a field that is either 32bit, in NDR or
}
if (pdata)
*pdata = data;
+ tvb_ensure_bytes_exist(tvb, offset, 8);
return offset+8;
}
}
if (pdata)
*pdata = data;
+ tvb_ensure_bytes_exist(tvb, offset, 4);
return offset + 4;
}
}
if (pdata)
*pdata = data;
+ tvb_ensure_bytes_exist(tvb, offset, 8);
return offset + 8;
}
int old_offset;
int conformance_size = 4;
+ /* ensure that just one pointer is set in the call */
+ DISSECTOR_ASSERT((fnct_bytes && !fnct_block) || (!fnct_bytes && fnct_block));
+
if (di->call_data->flags & DCERPC_IS_NDR64) {
conformance_size = 8;
}
/* real run, dissect the elements */
if (fnct_block) {
- old_offset = offset;
offset = (*fnct_block)(tvb, offset, di->array_max_count,
pinfo, tree, di, drep);
- if (offset <= old_offset)
- THROW(ReportedBoundsError);
} else {
for (i=0 ;i<di->array_max_count; i++) {
- old_offset = offset;
offset = (*fnct_bytes)(tvb, offset, pinfo, tree, di, drep);
- if (offset <= old_offset)
- THROW(ReportedBoundsError);
}
}
}
/* real run, dissect the elements */
if (fnct_block) {
- old_offset = offset;
offset = (*fnct_block)(tvb, offset, di->array_actual_count,
pinfo, tree, di, drep);
- if (offset <= old_offset)
- THROW(ReportedBoundsError);
- } else {
+ } else if (fnct_bytes) {
for (i=0 ;i<di->array_actual_count; i++) {
old_offset = offset;
offset = (*fnct_bytes)(tvb, offset, pinfo, tree, di, drep);
- if (offset <= old_offset)
- THROW(ReportedBoundsError);
+ /* Make sure we're moving forward */
+ if (old_offset >= offset)
+ break;
}
}
}
return ret;
}
+static void
+dissect_sec_vt_bitmask(proto_tree *tree, tvbuff_t *tvb)
+{
+ proto_tree_add_bitmask(tree, tvb, 0,
+ hf_dcerpc_sec_vt_bitmask,
+ ett_dcerpc_sec_vt_bitmask,
+ sec_vt_bitmask_fields,
+ ENC_LITTLE_ENDIAN);
+}
+
+static void
+dissect_sec_vt_pcontext(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+ proto_item *ti = NULL;
+ proto_tree *tr = proto_tree_add_subtree(tree, tvb, offset, -1,
+ ett_dcerpc_sec_vt_pcontext,
+ &ti, "pcontext");
+ e_guid_t uuid;
+ const char *uuid_name;
+
+ tvb_get_letohguid(tvb, offset, &uuid);
+ uuid_name = guids_get_uuid_name(&uuid);
+ if (!uuid_name) {
+ uuid_name = guid_to_str(wmem_packet_scope(), &uuid);
+ }
+
+ proto_tree_add_guid_format(tr, hf_dcerpc_sec_vt_pcontext_uuid, tvb,
+ offset, 16, &uuid, "Abstract Syntax: %s", uuid_name);
+ offset += 16;
+
+ proto_tree_add_item(tr, hf_dcerpc_sec_vt_pcontext_ver,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ tvb_get_letohguid(tvb, offset, &uuid);
+ uuid_name = guids_get_uuid_name(&uuid);
+ if (!uuid_name) {
+ uuid_name = guid_to_str(wmem_packet_scope(), &uuid);
+ }
+
+ proto_tree_add_guid_format(tr, hf_dcerpc_sec_vt_pcontext_uuid, tvb,
+ offset, 16, &uuid, "Transfer Syntax: %s", uuid_name);
+ offset += 16;
+
+ proto_tree_add_item(tr, hf_dcerpc_sec_vt_pcontext_ver,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_item_set_len(ti, offset);
+}
+
+static void
+dissect_sec_vt_header(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+ proto_item *ti = NULL;
+ proto_tree *tr = proto_tree_add_subtree(tree, tvb, offset, -1,
+ ett_dcerpc_sec_vt_header,
+ &ti, "header2");
+ guint8 drep[4];
+ guint8 ptype = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(tr, hf_dcerpc_packet_type, tvb, offset, 1, ptype);
+ offset += 1;
+
+ proto_tree_add_item(tr, hf_dcerpc_reserved, tvb, offset, 1, ENC_NA);
+ offset += 1;
+
+ proto_tree_add_item(tr, hf_dcerpc_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+
+ tvb_memcpy(tvb, drep, offset, 4);
+ proto_tree_add_dcerpc_drep(tr, tvb, offset, drep, 4);
+ offset += 4;
+
+ offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tr, drep,
+ hf_dcerpc_cn_call_id, NULL);
+
+ offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tr, drep,
+ hf_dcerpc_cn_ctx_id, NULL);
+
+ offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tr, drep,
+ hf_dcerpc_opnum, NULL);
+
+ proto_item_set_len(ti, offset);
+}
+
+static int
+dissect_verification_trailer_impl(packet_info *pinfo, tvbuff_t *tvb, int stub_offset,
+ proto_tree *parent_tree, int *signature_offset)
+{
+ int remaining = tvb_captured_length_remaining(tvb, stub_offset);
+ int offset;
+ gint signature_start;
+ gint payload_length;
+ typedef enum {
+ SEC_VT_COMMAND_BITMASK_1 = 0x0001,
+ SEC_VT_COMMAND_PCONTEXT = 0x0002,
+ SEC_VT_COMMAND_HEADER2 = 0x0003,
+ SEC_VT_COMMAND_END = 0x4000,
+ SEC_VT_MUST_PROCESS_COMMAND = 0x8000,
+ SEC_VT_COMMAND_MASK = 0x3fff,
+ } sec_vt_command;
+ proto_item *payload_item;
+ proto_item *item;
+ proto_tree *tree;
+
+ if (signature_offset != NULL) {
+ *signature_offset = -1;
+ }
+
+ /* We need at least signature + the header of one command */
+ if (remaining < (int)(sizeof(TRAILER_SIGNATURE) + 4)) {
+ return -1;
+ }
+
+ /* We only scan the last 512 bytes for a possible trailer */
+ if (remaining > 512) {
+ offset = remaining - 512;
+ remaining = 512;
+ } else {
+ offset = 0;
+ }
+ offset += stub_offset;
+
+ signature_start = tvb_find_tvb(tvb, tvb_trailer_signature, offset);
+ if (signature_start == -1) {
+ return -1;
+ }
+ payload_length = signature_start - stub_offset;
+ payload_item = proto_tree_add_item(parent_tree,
+ hf_dcerpc_payload_stub_data,
+ tvb, stub_offset, payload_length, ENC_NA);
+ proto_item_append_text(payload_item, " (%d byte%s)",
+ payload_length, plurality(payload_length, "", "s"));
+
+ if (signature_offset != NULL) {
+ *signature_offset = signature_start;
+ }
+ remaining -= (signature_start - offset);
+ offset = signature_start;
+
+ tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1,
+ ett_dcerpc_verification_trailer,
+ &item, "Verification Trailer");
+
+ proto_tree_add_item(tree, hf_dcerpc_sec_vt_signature,
+ tvb, offset, sizeof(TRAILER_SIGNATURE), ENC_NA);
+ offset += (int)sizeof(TRAILER_SIGNATURE);
+ remaining -= (int)sizeof(TRAILER_SIGNATURE);
+
+ while (remaining >= 4) {
+ sec_vt_command cmd;
+ guint16 len, len_missalign;
+ gboolean cmd_end, cmd_must;
+ proto_item *ti;
+ proto_tree *tr;
+ tvbuff_t *cmd_tvb = NULL;
+
+ cmd = (sec_vt_command)tvb_get_letohs(tvb, offset);
+ len = tvb_get_letohs(tvb, offset + 2);
+ cmd_end = cmd & SEC_VT_COMMAND_END;
+ cmd_must = cmd & SEC_VT_MUST_PROCESS_COMMAND;
+ cmd = (sec_vt_command)(cmd & SEC_VT_COMMAND_MASK);
+
+ tr = proto_tree_add_subtree_format(tree, tvb, offset, 4 + len,
+ ett_dcerpc_sec_vt_pcontext,
+ &ti, "Command: %s",
+ val_to_str(cmd, sec_vt_command_cmd_vals,
+ "Unknown (0x%04x)"));
+
+ if (cmd_must) {
+ proto_item_append_text(ti, "!!!");
+ }
+ if (cmd_end) {
+ proto_item_append_text(ti, ", END");
+ }
+
+ proto_tree_add_bitmask(tr, tvb, offset,
+ hf_dcerpc_sec_vt_command,
+ ett_dcerpc_sec_vt_command,
+ sec_vt_command_fields,
+ ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(tr, hf_dcerpc_sec_vt_command_length, tvb,
+ offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ cmd_tvb = tvb_new_subset_length(tvb, offset, len);
+ switch (cmd) {
+ case SEC_VT_COMMAND_BITMASK_1:
+ dissect_sec_vt_bitmask(tr, cmd_tvb);
+ break;
+ case SEC_VT_COMMAND_PCONTEXT:
+ dissect_sec_vt_pcontext(tr, cmd_tvb);
+ break;
+ case SEC_VT_COMMAND_HEADER2:
+ dissect_sec_vt_header(pinfo, tr, cmd_tvb);
+ break;
+ default:
+ proto_tree_add_item(tr, hf_dcerpc_unknown, cmd_tvb, 0, len, ENC_NA);
+ break;
+ }
+
+ offset += len;
+ remaining -= (4 + len);
+
+ len_missalign = len & 1;
+
+ if (len_missalign) {
+ int l = 2-len_missalign;
+ proto_tree_add_item(tr, hf_dcerpc_missalign, tvb, offset, l, ENC_NA);
+ offset += l;
+ remaining -= l;
+ }
+
+ if (cmd_end) {
+ break;
+ }
+ }
+
+ proto_item_set_end(item, tvb, offset);
+ return offset;
+}
+
+static int
+dissect_verification_trailer(packet_info *pinfo, tvbuff_t *tvb, int stub_offset,
+ proto_tree *parent_tree, int *signature_offset)
+{
+ volatile int ret = -1;
+ TRY {
+ /*
+ * Even if we found a signature we can't be sure to have a
+ * valid verification trailer, we're only relatively sure
+ * if we manage to dissect it completely, otherwise it
+ * may be part of the real payload. That's why we have
+ * a try/catch block here.
+ */
+ ret = dissect_verification_trailer_impl(pinfo, tvb, stub_offset, parent_tree, signature_offset);
+ } CATCH_NONFATAL_ERRORS {
+ } ENDTRY;
+ return ret;
+}
+
static int
dcerpc_try_handoff(packet_info *pinfo, proto_tree *tree,
proto_tree *dcerpc_tree,
dissector_data.decrypted = decrypted;
dissector_data.auth_info = auth_info;
dissector_data.drep = drep;
+ dissector_data.dcerpc_tree = dcerpc_tree;
/* Check the dissector table before the hash table. Hopefully the hash table entries can
all be converted to use dissector table */
col_append_fstr(pinfo->cinfo, COL_INFO, " %s V%u",
guids_resolve_guid_to_str(&info->call_data->uuid), info->call_data->ver);
- show_stub_data(tvb, 0, dcerpc_tree, auth_info, !decrypted);
+ show_stub_data(pinfo, tvb, 0, dcerpc_tree, auth_info, !decrypted);
return -1;
}
return 0;
}
-static int
-dissect_dcerpc_verifier(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
- dcerpc_auth_info *auth_info)
-{
- int auth_offset;
-
- auth_info->auth_data = NULL;
-
- if (auth_info->auth_size != 0) {
- dcerpc_auth_subdissector_fns *auth_fns;
- tvbuff_t *auth_tvb;
-
- auth_offset = hdr->frag_len - hdr->auth_len;
-
- auth_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len,
- hdr->auth_len);
-
- auth_info->auth_data = auth_tvb;
-
- if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
- auth_info->auth_type))) {
- /*
- * Catch all bounds-error exceptions, so that even if the
- * verifier is bad or we don't have all of it, we still
- * show the stub data.
- */
- TRY {
- dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
- hdr, auth_info);
- } CATCH_BOUNDS_ERRORS {
- show_exception(auth_tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
- } ENDTRY;
- } else {
- proto_tree_add_item(dcerpc_tree, hf_dcerpc_auth_verifier, auth_tvb, 0, hdr->auth_len, ENC_NA);
- }
- }
-
- return hdr->auth_len;
-}
-
static void
dissect_dcerpc_cn_auth(tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
- gboolean are_credentials, dcerpc_auth_info *auth_info)
+ dcerpc_auth_info *auth_info)
{
volatile int offset;
* Initially set auth_level and auth_type to zero to indicate that we
* haven't yet seen any authentication level information.
*/
- auth_info->auth_level = 0;
- auth_info->auth_type = 0;
- auth_info->auth_size = 0;
- auth_info->auth_pad_len = 0;
+ auth_info->auth_type = 0;
+ auth_info->auth_level = 0;
+ auth_info->auth_context_id = 0;
+ auth_info->auth_pad_len = 0;
+ auth_info->auth_size = 0;
+ auth_info->auth_fns = NULL;
+ auth_info->auth_tvb = NULL;
+ auth_info->auth_item = NULL;
+ auth_info->auth_tree = NULL;
/*
* The authentication information is at the *end* of the PDU; in
*/
offset = hdr->frag_len - (hdr->auth_len + 8);
if (offset == 0 || tvb_offset_exists(tvb, offset - 1)) {
+ /* Compute the size of the auth block. Note that this should not
+ include auth padding, since when NTLMSSP encryption is used, the
+ padding is actually inside the encrypted stub */
+ auth_info->auth_size = hdr->auth_len + 8;
+
+ auth_info->auth_item = proto_tree_add_item(dcerpc_tree, hf_dcerpc_auth_info,
+ tvb, offset, auth_info->auth_size, ENC_NA);
+ auth_info->auth_tree = proto_item_add_subtree(auth_info->auth_item, ett_dcerpc_auth_info);
+
/*
* Either there's no stub data, or the last byte of the stub
* data is present in the captured data, so we shouldn't
* dissect after this, such as stub data.
*/
TRY {
- offset = dissect_dcerpc_uint8(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ offset = dissect_dcerpc_uint8(tvb, offset, pinfo, auth_info->auth_tree, hdr->drep,
hf_dcerpc_auth_type,
&auth_info->auth_type);
- offset = dissect_dcerpc_uint8(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ offset = dissect_dcerpc_uint8(tvb, offset, pinfo, auth_info->auth_tree, hdr->drep,
hf_dcerpc_auth_level,
&auth_info->auth_level);
- offset = dissect_dcerpc_uint8(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ offset = dissect_dcerpc_uint8(tvb, offset, pinfo, auth_info->auth_tree, hdr->drep,
hf_dcerpc_auth_pad_len,
&auth_info->auth_pad_len);
- offset = dissect_dcerpc_uint8(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ offset = dissect_dcerpc_uint8(tvb, offset, pinfo, auth_info->auth_tree, hdr->drep,
hf_dcerpc_auth_rsrvd, NULL);
- offset = dissect_dcerpc_uint32(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
- hf_dcerpc_auth_ctx_id, NULL);
+ offset = dissect_dcerpc_uint32(tvb, offset, pinfo, auth_info->auth_tree, hdr->drep,
+ hf_dcerpc_auth_ctx_id,
+ &auth_info->auth_context_id);
+
+ proto_item_append_text(auth_info->auth_item,
+ ": %s, %s, AuthContextId(%d)",
+ val_to_str(auth_info->auth_type,
+ authn_protocol_vals,
+ "AuthType(%u)"),
+ val_to_str(auth_info->auth_level,
+ authn_level_vals,
+ "AuthLevel(%u)"),
+ auth_info->auth_context_id);
/*
* Dissect the authentication data.
*/
- if (are_credentials) {
- tvbuff_t *auth_tvb;
- dcerpc_auth_subdissector_fns *auth_fns;
-
- auth_tvb = tvb_new_subset(tvb, offset,
+ auth_info->auth_tvb = tvb_new_subset(tvb, offset,
MIN(hdr->auth_len,tvb_reported_length_remaining(tvb, offset)),
hdr->auth_len);
- if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
- auth_info->auth_type)))
- dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
- hdr, auth_info);
- else
- proto_tree_add_item(dcerpc_tree, hf_dcerpc_auth_credentials, tvb, offset, hdr->auth_len, ENC_NA);
- }
+ auth_info->auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
+ auth_info->auth_type);
+ if (auth_info->auth_fns != NULL)
+ dissect_auth_verf(pinfo, hdr, auth_info);
+ else
+ proto_tree_add_item(auth_info->auth_tree,
+ hf_dcerpc_auth_credentials,
+ auth_info->auth_tvb, 0,
+ hdr->auth_len, ENC_NA);
- /* Compute the size of the auth block. Note that this should not
- include auth padding, since when NTLMSSP encryption is used, the
- padding is actually inside the encrypted stub */
- auth_info->auth_size = hdr->auth_len + 8;
} CATCH_BOUNDS_ERRORS {
show_exception(tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
} ENDTRY;
* an authentication header, and associate it with an authentication
* context, so subsequent PDUs can use that context.
*/
- dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
+ dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, &auth_info);
}
static void
* XXX - do we need to do anything with the authentication level
* we get back from this?
*/
- dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
+ dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, &auth_info);
}
static void
gboolean save_fragmented;
fragment_head *fd_head = NULL;
- tvbuff_t *auth_tvb, *payload_tvb, *decrypted_tvb = NULL;
+ tvbuff_t *payload_tvb, *decrypted_tvb = NULL;
proto_item *pi;
proto_item *parent_pi;
proto_item *dcerpc_tree_item;
- gboolean decrypted = FALSE;
save_fragmented = pinfo->fragmented;
length = reported_length;
payload_tvb = tvb_new_subset(tvb, offset, length, reported_length);
- auth_tvb = NULL;
- /*don't bother if we don't have the entire tvb */
- /*XXX we should really make sure we calculate auth_info->auth_data
- and use that one instead of this auth_tvb hack
- */
- if (tvb_captured_length(tvb) == tvb_reported_length(tvb)) {
- if (tvb_reported_length_remaining(tvb, offset+length) > 8) {
- auth_tvb = tvb_new_subset_remaining(tvb, offset+length+8);
- }
- }
-
/* Decrypt the PDU if it is encrypted */
if (auth_info->auth_type &&
(auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY)) {
- /*
- * We know the authentication type, and the authentication
- * level is "Packet privacy", meaning the payload is
- * encrypted; attempt to decrypt it.
- */
- dcerpc_auth_subdissector_fns *auth_fns;
/* Start out assuming we won't succeed in decrypting. */
- /* Schannel needs information into the footer (verifier) in order to setup decryption keys
- * so we call it in order to have a chance to decipher the data
- */
- if (DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN == auth_info->auth_type) {
- dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, auth_info);
- }
-
- if ((auth_fns = get_auth_subdissector_fns(
- auth_info->auth_level, auth_info->auth_type))) {
+ if (auth_info->auth_fns != NULL) {
tvbuff_t *result;
- result = decode_encrypted_data(
- payload_tvb, auth_tvb, pinfo, auth_fns,
- hdr->ptype == PDU_REQ, auth_info);
-
+ result = decode_encrypted_data(payload_tvb, pinfo, hdr, auth_info);
if (result) {
- decrypted = TRUE;
proto_tree_add_item(dcerpc_tree, hf_dcerpc_encrypted_stub_data, payload_tvb, 0, -1, ENC_NA);
add_new_data_source(
if (PFC_NOT_FRAGMENTED(hdr)) {
pinfo->fragmented = FALSE;
- dcerpc_try_handoff(pinfo, tree, dcerpc_tree, ((decrypted_tvb != NULL) ? decrypted_tvb : payload_tvb), decrypted,
+ dcerpc_try_handoff(pinfo, tree, dcerpc_tree,
+ ((decrypted_tvb != NULL) ? decrypted_tvb : payload_tvb),
+ ((decrypted_tvb != NULL) ? TRUE : FALSE),
hdr->drep, di, auth_info);
pinfo->fragmented = save_fragmented;
/* debug output of essential fragment data. */
/* leave it here for future debugging sessions */
/*printf("DCE num:%u offset:%u frag_len:%u tvb_len:%u\n",
- pinfo->fd->num, offset, hdr->frag_len, tvb_reported_length(decrypted_tvb));*/
+ pinfo->num, offset, hdr->frag_len, tvb_reported_length(decrypted_tvb));*/
/* if we are not doing reassembly and this is the first fragment
then just dissect it and exit
*/
if ( (!dcerpc_reassemble) && (hdr->flags & PFC_FIRST_FRAG) ) {
- dcerpc_try_handoff(pinfo, tree, dcerpc_tree, ((decrypted_tvb != NULL) ? decrypted_tvb : payload_tvb), decrypted,
+ dcerpc_try_handoff(pinfo, tree, dcerpc_tree,
+ ((decrypted_tvb != NULL) ? decrypted_tvb : payload_tvb),
+ ((decrypted_tvb != NULL) ? TRUE : FALSE),
hdr->drep, di, auth_info);
expert_add_info_format(pinfo, NULL, &ei_dcerpc_fragment, "%s fragment", fragment_type(hdr->flags));
*/
if (fd_head && (fd_head->flags & FD_DEFRAGMENTED) ) {
- if ((pinfo->fd->num == fd_head->reassembled_in) && (hdr->flags & PFC_LAST_FRAG) ) {
+ if ((pinfo->num == fd_head->reassembled_in) && (hdr->flags & PFC_LAST_FRAG) ) {
tvbuff_t *next_tvb;
proto_item *frag_tree_item;
expert_add_info_format(pinfo, NULL, &ei_dcerpc_fragment, "%s fragment", fragment_type(hdr->flags));
if (decrypted_tvb) {
- show_stub_data(decrypted_tvb, 0, tree, auth_info, FALSE);
+ show_stub_data(pinfo, decrypted_tvb, 0, tree, auth_info, FALSE);
} else {
- show_stub_data(payload_tvb, 0, tree, auth_info, TRUE);
+ show_stub_data(pinfo, payload_tvb, 0, tree, auth_info, TRUE);
}
}
* XXX - what if this was set when the connection was set up,
* and we just have a security context?
*/
- dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
+ dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, &auth_info);
- conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
+ conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
pinfo->srcport, pinfo->destport, 0);
if (!conv)
- show_stub_data(tvb, offset, dcerpc_tree, &auth_info, TRUE);
+ show_stub_data(pinfo, tvb, offset, dcerpc_tree, &auth_info, TRUE);
else {
dcerpc_matched_key matched_key, *new_matched_key;
dcerpc_call_value *value;
and desegmented pdu's .
Instead we check if this pdu is already in the matched table or not
*/
- matched_key.frame = pinfo->fd->num;
+ matched_key.frame = pinfo->num;
matched_key.call_id = hdr->call_id;
value = (dcerpc_call_value *)g_hash_table_lookup(dcerpc_matched, &matched_key);
if (!value) {
call_value->ver = bind_value->ver;
call_value->object_uuid = obj_id;
call_value->opnum = opnum;
- call_value->req_frame = pinfo->fd->num;
- call_value->req_time = pinfo->fd->abs_ts;
+ call_value->req_frame = pinfo->num;
+ call_value->req_time = pinfo->abs_ts;
call_value->rep_frame = 0;
call_value->max_ptr = 0;
call_value->se_data = NULL;
} else {
/* no bind information, simply show stub data */
proto_tree_add_expert_format(dcerpc_tree, pinfo, &ei_dcerpc_cn_ctx_id_no_bind, tvb, offset, 0, "No bind info for interface Context ID %u - capture start too late?", ctx_id);
- show_stub_data(tvb, offset, dcerpc_tree, &auth_info, TRUE);
+ show_stub_data(pinfo, tvb, offset, dcerpc_tree, &auth_info, TRUE);
}
}
-
- /* Dissect the verifier */
- dissect_dcerpc_verifier(tvb, pinfo, dcerpc_tree, hdr, &auth_info);
-
}
static void
* XXX - what if this was set when the connection was set up,
* and we just have a security context?
*/
- dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
+ dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, &auth_info);
- conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
+ conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
pinfo->srcport, pinfo->destport, 0);
if (!conv) {
/* no point in creating one here, really */
- show_stub_data(tvb, offset, dcerpc_tree, &auth_info, TRUE);
+ show_stub_data(pinfo, tvb, offset, dcerpc_tree, &auth_info, TRUE);
} else {
dcerpc_matched_key matched_key, *new_matched_key;
and desegmented pdu's .
Instead we check if this pdu is already in the matched table or not
*/
- matched_key.frame = pinfo->fd->num;
+ matched_key.frame = pinfo->num;
matched_key.call_id = hdr->call_id;
value = (dcerpc_call_value *)g_hash_table_lookup(dcerpc_matched, &matched_key);
if (!value) {
if ((call_value = (dcerpc_call_value *)g_hash_table_lookup(dcerpc_cn_calls, &call_key))) {
/* extra sanity check, only match them if the reply
came after the request */
- if (call_value->req_frame<pinfo->fd->num) {
+ if (call_value->req_frame<pinfo->num) {
new_matched_key = (dcerpc_matched_key *)wmem_alloc(wmem_file_scope(), sizeof (dcerpc_matched_key));
*new_matched_key = matched_key;
g_hash_table_insert(dcerpc_matched, new_matched_key, call_value);
value = call_value;
if (call_value->rep_frame == 0) {
- call_value->rep_frame = pinfo->fd->num;
+ call_value->rep_frame = pinfo->num;
}
}
}
di->ptype = PDU_RESP;
di->call_data = value;
- proto_tree_add_uint(dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
+ pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
+ PROTO_ITEM_SET_GENERATED(pi);
/* (optional) "Object UUID" from request */
if (dcerpc_tree && (memcmp(&value->object_uuid, &obj_id_null, sizeof(obj_id_null)) != 0)) {
if (parent_pi != NULL) {
proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
}
- nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
+ nstime_delta(&delta_ts, &pinfo->abs_ts, &value->req_time);
pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
PROTO_ITEM_SET_GENERATED(pi);
} else {
} else {
/* no bind information, simply show stub data */
proto_tree_add_expert_format(dcerpc_tree, pinfo, &ei_dcerpc_cn_ctx_id_no_bind, tvb, offset, 0, "No bind info for interface Context ID %u - capture start too late?", ctx_id);
- show_stub_data(tvb, offset, dcerpc_tree, &auth_info, TRUE);
+ show_stub_data(pinfo, tvb, offset, dcerpc_tree, &auth_info, TRUE);
}
}
-
- /* Dissect the verifier */
- dissect_dcerpc_verifier(tvb, pinfo, dcerpc_tree, hdr, &auth_info);
}
static void
* XXX - what if this was set when the connection was set up,
* and we just have a security context?
*/
- dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
+ dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, &auth_info);
- conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
+ conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
pinfo->srcport, pinfo->destport, 0);
if (!conv) {
/* no point in creating one here, really */
and desegmented pdu's .
Instead we check if this pdu is already in the matched table or not
*/
- matched_key.frame = pinfo->fd->num;
+ matched_key.frame = pinfo->num;
matched_key.call_id = hdr->call_id;
value = (dcerpc_call_value *)g_hash_table_lookup(dcerpc_matched, &matched_key);
if (!value) {
value = call_value;
if (call_value->rep_frame == 0) {
- call_value->rep_frame = pinfo->fd->num;
+ call_value->rep_frame = pinfo->num;
}
}
di->ptype = PDU_FAULT;
di->call_data = value;
- proto_tree_add_uint(dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
+ pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
+ PROTO_ITEM_SET_GENERATED(pi);
if (value->req_frame != 0) {
nstime_t delta_ts;
pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
if (parent_pi != NULL) {
proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
}
- nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
+ nstime_delta(&delta_ts, &pinfo->abs_ts, &value->req_time);
pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
PROTO_ITEM_SET_GENERATED(pi);
} else {
const guint32 conformance_count = dcerpc_tvb_get_ntohl(tvb, offset, hdr->drep);
proto_tree_add_uint(cn_rts_command_tree, hf_dcerpc_cn_rts_command_conformancecount, tvb, offset, 4, conformance_count);
offset += 4;
- padding = (guint8 *)tvb_memdup(NULL, tvb, offset, conformance_count);
+ padding = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset, conformance_count);
proto_tree_add_bytes(cn_rts_command_tree, hf_dcerpc_cn_rts_command_padding, tvb, offset, conformance_count, padding);
offset += conformance_count;
} break;
offset += 16;
} break;
}
- padding = (guint8 *)tvb_memdup(NULL, tvb, offset, 12);
+ padding = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset, 12);
proto_tree_add_bytes(cn_rts_command_tree, hf_dcerpc_cn_rts_command_padding, tvb, offset, 12, padding);
offset += 12;
} break;
/*
* Nothing after the common header other than credentials.
*/
- dissect_dcerpc_cn_auth(fragment_tvb, MIN(offset - start_offset, subtvb_len), pinfo, dcerpc_tree, &hdr, TRUE,
+ dissect_dcerpc_cn_auth(fragment_tvb, MIN(offset - start_offset, subtvb_len), pinfo, dcerpc_tree, &hdr,
&auth_info);
break;
* Nothing after the common header other than an authentication
* verifier.
*/
- dissect_dcerpc_cn_auth(fragment_tvb, MIN(offset - start_offset, subtvb_len), pinfo, dcerpc_tree, &hdr, FALSE,
+ dissect_dcerpc_cn_auth(fragment_tvb, MIN(offset - start_offset, subtvb_len), pinfo, dcerpc_tree, &hdr,
&auth_info);
break;
default:
/* might as well dissect the auth info */
- dissect_dcerpc_cn_auth(fragment_tvb, MIN(offset - start_offset, subtvb_len), pinfo, dcerpc_tree, &hdr, FALSE,
+ dissect_dcerpc_cn_auth(fragment_tvb, MIN(offset - start_offset, subtvb_len), pinfo, dcerpc_tree, &hdr,
&auth_info);
break;
}
!(hdr->flags1 & PFCL1_LASTFRAG), 0);
if (fd_head != NULL) {
/* We completed reassembly... */
- if (pinfo->fd->num == fd_head->reassembled_in) {
+ if (pinfo->num == fd_head->reassembled_in) {
/* ...and this is the reassembled RPC PDU */
next_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
call_value->ver = hdr->if_ver;
call_value->object_uuid = hdr->obj_id;
call_value->opnum = hdr->opnum;
- call_value->req_frame = pinfo->fd->num;
- call_value->req_time = pinfo->fd->abs_ts;
+ call_value->req_frame = pinfo->num;
+ call_value->req_time = pinfo->abs_ts;
call_value->rep_frame = 0;
call_value->max_ptr = 0;
call_value->se_data = NULL;
g_hash_table_insert(dcerpc_dg_calls, call_key, call_value);
new_matched_key = (dcerpc_matched_key *)wmem_alloc(wmem_file_scope(), sizeof(dcerpc_matched_key));
- new_matched_key->frame = pinfo->fd->num;
+ new_matched_key->frame = pinfo->num;
new_matched_key->call_id = hdr->seqnum;
g_hash_table_insert(dcerpc_matched, new_matched_key, call_value);
}
- matched_key.frame = pinfo->fd->num;
+ matched_key.frame = pinfo->num;
matched_key.call_id = hdr->seqnum;
value = (dcerpc_call_value *)g_hash_table_lookup(dcerpc_matched, &matched_key);
if (!value) {
value->ver = hdr->if_ver;
value->object_uuid = hdr->obj_id;
value->opnum = hdr->opnum;
- value->req_frame = pinfo->fd->num;
+ value->req_frame = pinfo->num;
value->rep_frame = 0;
value->max_ptr = 0;
value->se_data = NULL;
if ((call_value = (dcerpc_call_value *)g_hash_table_lookup(dcerpc_dg_calls, &call_key))) {
new_matched_key = (dcerpc_matched_key *)wmem_alloc(wmem_file_scope(), sizeof (dcerpc_matched_key));
- new_matched_key->frame = pinfo->fd->num;
+ new_matched_key->frame = pinfo->num;
new_matched_key->call_id = hdr->seqnum;
g_hash_table_insert(dcerpc_matched, new_matched_key, call_value);
if (call_value->rep_frame == 0) {
- call_value->rep_frame = pinfo->fd->num;
+ call_value->rep_frame = pinfo->num;
}
}
}
- matched_key.frame = pinfo->fd->num;
+ matched_key.frame = pinfo->num;
matched_key.call_id = hdr->seqnum;
value = (dcerpc_call_value *)g_hash_table_lookup(dcerpc_matched, &matched_key);
if (!value) {
value->ver = hdr->if_ver;
value->object_uuid = hdr->obj_id;
value->opnum = hdr->opnum;
- value->rep_frame = pinfo->fd->num;
+ value->rep_frame = pinfo->num;
}
di = wmem_new0(wmem_packet_scope(), dcerpc_info);
if (parent_pi != NULL) {
proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
}
- nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
+ nstime_delta(&delta_ts, &pinfo->abs_ts, &value->req_time);
pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
PROTO_ITEM_SET_GENERATED(pi);
} else {
col_append_fstr(pinfo->cinfo, COL_INFO, " [req: #%u]", call_value->req_frame);
- nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &call_value->req_time);
+ nstime_delta(&delta_ts, &pinfo->abs_ts, &call_value->req_time);
pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
PROTO_ITEM_SET_GENERATED(pi);
/* }*/
{ "Referent ID", "dcerpc.referent_id", FT_UINT32, BASE_HEX,
NULL, 0, "Referent ID for this NDR encoded pointer", HFILL }},
{ &hf_dcerpc_referent_id64,
- { "Referent ID", "dcerpc.referent_id", FT_UINT64, BASE_HEX,
+ { "Referent ID", "dcerpc.referent_id64", FT_UINT64, BASE_HEX,
NULL, 0, "Referent ID for this NDR encoded pointer", HFILL }},
{ &hf_dcerpc_ver,
{ "Version", "dcerpc.ver", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{"Forward Destination", "dcerpc.cn_rts_command.forwarddestination", FT_UINT32, BASE_DEC, VALS(rts_forward_destination_vals), 0x0, NULL, HFILL }},
{ &hf_dcerpc_cn_rts_command_pingtrafficsentnotify,
{"Ping Traffic Sent Notify", "dcerpc.cn_rts_command.pingtrafficsentnotify", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcerpc_sec_vt_signature,
+ {"SEC_VT_SIGNATURE", "dcerpc.rpc_sec_vt.signature", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcerpc_sec_vt_command_end,
+ {"SEC_VT_COMMAND_END", "dcerpc.rpc_sec_vt.command.end", FT_BOOLEAN, 16, NULL, 0x4000, NULL, HFILL }},
+ { &hf_dcerpc_sec_vt_command_must,
+ {"SEC_VT_MUST_PROCESS_COMMAND", "dcerpc.rpc_sec_vt.command.must_process", FT_BOOLEAN, 16, NULL, 0x8000, NULL, HFILL }},
+ { &hf_dcerpc_sec_vt_command_cmd,
+ {"Cmd", "dcerpc.rpc_sec_vt.command.cmd", FT_UINT16, BASE_HEX, VALS(sec_vt_command_cmd_vals), 0x3fff, NULL, HFILL }},
+ { &hf_dcerpc_sec_vt_command,
+ {"Command", "dcerpc.rpc_sec_vt.command", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_dcerpc_sec_vt_command_length,
+ {"Length", "dcerpc.rpc_sec_vt.command.length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL}},
+ { &hf_dcerpc_sec_vt_bitmask,
+ {"rpc_sec_vt_bitmask", "dcerpc.rpc_sec_vt.bitmask", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_dcerpc_sec_vt_bitmask_sign,
+ {"CLIENT_SUPPORT_HEADER_SIGNING", "dcerpc.rpc_sec_vt.bitmask.sign", FT_BOOLEAN, 32, NULL, 0x1, NULL, HFILL }},
+ { &hf_dcerpc_sec_vt_pcontext_uuid,
+ {"UUID", "dcerpc.rpc_sec_vt.pcontext.interface.uuid", FT_GUID, BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_dcerpc_sec_vt_pcontext_ver,
+ {"Version", "dcerpc.rpc_sec_vt.pcontext.interface.ver", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_dcerpc_reserved,
+ {"Reserved", "dcerpc.reserved", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_dcerpc_unknown,
+ {"Unknown", "dcerpc.unknown", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_dcerpc_missalign,
+ {"missalign", "dcerpc.missalign", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
/* Generated from convert_proto_tree_add_text.pl */
{ &hf_dcerpc_duplicate_ptr, { "duplicate PTR", "dcerpc.duplicate_ptr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_dcerpc_encrypted_stub_data, { "Encrypted stub data", "dcerpc.encrypted_stub_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_dcerpc_decrypted_stub_data, { "Decrypted stub data", "dcerpc.decrypted_stub_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcerpc_payload_stub_data, { "Payload stub data", "dcerpc.payload_stub_data", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcerpc_stub_data_with_sec_vt, { "Stub data with rpc_sec_verification_trailer", "dcerpc.stub_data_with_sec_vt", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_dcerpc_stub_data, { "Stub data", "dcerpc.stub_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_dcerpc_auth_padding, { "Auth Padding", "dcerpc.auth_padding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcerpc_auth_info, { "Auth Info", "dcerpc.auth_info", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_dcerpc_auth_verifier, { "Auth Verifier", "dcerpc.auth_verifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_dcerpc_auth_credentials, { "Auth Credentials", "dcerpc.auth_credentials", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_dcerpc_fault_stub_data, { "Fault stub data", "dcerpc.fault_stub_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
&ett_dcerpc_fragments,
&ett_dcerpc_fragment,
&ett_dcerpc_krb5_auth_verf,
+ &ett_dcerpc_auth_info,
+ &ett_dcerpc_verification_trailer,
+ &ett_dcerpc_sec_vt_command,
+ &ett_dcerpc_sec_vt_bitmask,
+ &ett_dcerpc_sec_vt_pcontext,
+ &ett_dcerpc_sec_vt_header,
+ &ett_dcerpc_complete_stub_data,
};
static ei_register_info ei[] = {
- { &ei_dcerpc_fragment, { "dcerpc.fragment", PI_REASSEMBLE, PI_CHAT, "%s fragment", EXPFILL }},
+ { &ei_dcerpc_fragment, { "dcerpc.fragment.reassemble", PI_REASSEMBLE, PI_CHAT, "%s fragment", EXPFILL }},
{ &ei_dcerpc_fragment_reassembled, { "dcerpc.fragment_reassembled", PI_REASSEMBLE, PI_CHAT, "%s fragment, reassembled", EXPFILL }},
{ &ei_dcerpc_cn_ctx_id_no_bind, { "dcerpc.cn_ctx_id.no_bind", PI_UNDECODED, PI_NOTE, "No bind info for interface Context ID %u - capture start too late?", EXPFILL }},
{ &ei_dcerpc_no_request_found, { "dcerpc.no_request_found", PI_SEQUENCE, PI_NOTE, "No request to this DCE/RPC call found", EXPFILL }},
expert_dcerpc = expert_register_protocol(proto_dcerpc);
expert_register_field_array(expert_dcerpc, ei, array_length(ei));
- uuid_dissector_table = register_dissector_table("dcerpc.uuid", "DCE/RPC UUIDs", FT_GUID, BASE_HEX);
+ uuid_dissector_table = register_dissector_table("dcerpc.uuid", "DCE/RPC UUIDs", proto_dcerpc, FT_GUID, BASE_HEX);
register_init_routine(dcerpc_init_protocol);
register_cleanup_routine(dcerpc_cleanup_protocol);
register_decode_as(&dcerpc_da);
register_srt_table(proto_dcerpc, NULL, 1, dcerpcstat_packet, dcerpcstat_init, dcerpcstat_param);
+
+ tvb_trailer_signature = tvb_new_real_data(TRAILER_SIGNATURE,
+ sizeof(TRAILER_SIGNATURE),
+ sizeof(TRAILER_SIGNATURE));
}
void
heur_dissector_add("netbios", dissect_dcerpc_cn_pk, "DCE/RPC over NetBios", "dcerpc_netbios", proto_dcerpc, HEURISTIC_ENABLE);
heur_dissector_add("udp", dissect_dcerpc_dg, "DCE/RPC over UDP", "dcerpc_udp", proto_dcerpc, HEURISTIC_ENABLE);
heur_dissector_add("smb_transact", dissect_dcerpc_cn_smbpipe, "DCE/RPC over SMB", "dcerpc_smb_transact", proto_dcerpc, HEURISTIC_ENABLE);
- heur_dissector_add("smb2_heur_subdissectors", dissect_dcerpc_cn_smb2, "DCE/RPC over SMB2", "dcerpc_smb2", proto_dcerpc, HEURISTIC_ENABLE);
+ heur_dissector_add("smb2_pipe_subdissectors", dissect_dcerpc_cn_smb2, "DCE/RPC over SMB2", "dcerpc_smb2", proto_dcerpc, HEURISTIC_ENABLE);
heur_dissector_add("http", dissect_dcerpc_cn_bs, "DCE/RPC over HTTP", "dcerpc_http", proto_dcerpc, HEURISTIC_ENABLE);
dcerpc_smb_init(proto_dcerpc);