* Copyright 2001, Todd Sabin <tas@webspan.net>
* Copyright 2003, Tim Potter <tpot@samba.org>
*
- * $Id: packet-dcerpc.c,v 1.138 2003/08/04 02:48:59 tpot Exp $
+ * $Id: packet-dcerpc.c,v 1.158 2003/12/08 20:58:01 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
static int dcerpc_tap = -1;
+
static const value_string pckt_vals[] = {
{ PDU_REQ, "Request"},
{ PDU_PING, "Ping"},
static gint ett_dcerpc = -1;
static gint ett_dcerpc_cn_flags = -1;
+static gint ett_dcerpc_cn_ctx = -1;
+static gint ett_dcerpc_cn_iface = -1;
static gint ett_dcerpc_drep = -1;
static gint ett_dcerpc_dg_flags1 = -1;
static gint ett_dcerpc_dg_flags2 = -1;
"fragments"
};
-typedef struct _dcerpc_auth_info {
- guint8 auth_pad_len;
- guint8 auth_level;
- guint8 auth_type;
- guint32 auth_size;
-} dcerpc_auth_info;
+
+
+static dcerpc_info *
+get_next_di(void)
+{
+ static dcerpc_info di[20];
+ static int di_counter=0;
+
+ di_counter++;
+ if(di_counter>=20){
+ di_counter=0;
+ }
+ return &di[di_counter];
+}
/* try to desegment big DCE/RPC packets over TCP? */
static gboolean dcerpc_cn_desegment = TRUE;
e_dce_cn_common_hdr_t *hdr,
dcerpc_auth_info *auth_info)
{
- dcerpc_dissect_fnct_t *fn = NULL;
+ dcerpc_dissect_fnct_t *volatile fn = NULL;
switch (hdr->ptype) {
case PDU_BIND:
/* Hand off payload data to a registered dissector */
-static void dissect_encrypted_data(tvbuff_t *enc_tvb, packet_info *pinfo,
- proto_tree *tree,
- dcerpc_auth_subdissector_fns *auth_fns,
- guint8 ptype, char *drep)
+static tvbuff_t *decode_encrypted_data(tvbuff_t *enc_tvb,
+ packet_info *pinfo,
+ dcerpc_auth_subdissector_fns *auth_fns,
+ gboolean is_request,
+ dcerpc_auth_info *auth_info)
{
- dcerpc_dissect_fnct_t *fn = NULL;
+ dcerpc_decode_data_fnct_t *fn;
- switch (ptype) {
- case PDU_REQ:
+ if (is_request)
fn = auth_fns->req_data_fn;
- break;
- case PDU_RESP:
+ else
fn = auth_fns->resp_data_fn;
- break;
- default:
- g_warning("attempt to dissect %s pdu encrypted data",
- val_to_str(ptype, pckt_vals, "Unknown (%u)"));
- break;
- }
if (fn)
- fn(enc_tvb, 0, pinfo, tree, drep);
+ return fn(enc_tvb, 0, pinfo, auth_info);
+
+ return NULL;
}
/*
key->uuid = *uuid;
key->ver = ver;
- value->proto = proto;
+ value->proto = find_protocol_by_id(proto);
+ value->proto_id = proto;
value->ett = ett;
- value->name = proto_get_protocol_short_name (proto);
+ value->name = proto_get_protocol_short_name (value->proto);
value->procs = procs;
value->opnum_hf = opnum_hf;
return sub_proto->name;
}
+/* Function to find the opnum hf-field of a registered protocol
+ * or -1 if the protocol/version is not known to ethereal.
+ */
+int
+dcerpc_get_proto_hf_opnum(e_uuid_t *uuid, guint16 ver)
+{
+ dcerpc_uuid_key key;
+ dcerpc_uuid_value *sub_proto;
+
+ key.uuid = *uuid;
+ key.ver = ver;
+ if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
+ return -1;
+ }
+ return sub_proto->opnum_hf;
+}
+
/* Create a value_string consisting of DCERPC opnum and name from a
subdissector array. */
int found_new_pointer;
dcerpc_info *di;
int old_offset;
+ int next_pointer;
+ next_pointer=0;
di=pinfo->private_data;
do{
int i, len;
found_new_pointer=0;
len=g_slist_length(ndr_pointer_list);
- for(i=0;i<len;i++){
+ for(i=next_pointer;i<len;i++){
ndr_pointer_data_t *tnpd;
tnpd=g_slist_nth_data(ndr_pointer_list, i);
if(tnpd->fnct){
dcerpc_dissect_fnct_t *fnct;
+ next_pointer=i+1;
found_new_pointer=1;
fnct=tnpd->fnct;
tnpd->fnct=NULL;
static void
show_stub_data (tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
- dcerpc_auth_info *auth_info)
+ dcerpc_auth_info *auth_info, gboolean is_encrypted)
{
int length;
length = tvb_reported_length_remaining (tvb, offset);
if (auth_info != NULL &&
auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
- proto_tree_add_text(dcerpc_tree, tvb, offset, -1,
- "Encrypted stub data (%d byte%s)",
- length, plurality(length, "", "s"));
+ if (is_encrypted) {
+ proto_tree_add_text(dcerpc_tree, tvb, offset, -1,
+ "Encrypted stub data (%d byte%s)",
+ length, plurality(length, "", "s"));
+ } else {
+ proto_tree_add_text(dcerpc_tree, tvb, offset, -1,
+ "Decrypted stub data (%d byte%s)",
+ length, plurality(length, "", "s"));
+ }
} else {
proto_tree_add_text (dcerpc_tree, tvb, offset, -1,
"Stub data (%d byte%s)", length,
static int
dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
proto_tree *dcerpc_tree,
- tvbuff_t *volatile tvb, volatile gint offset,
+ tvbuff_t *volatile tvb, tvbuff_t *decrypted_tvb,
char *drep, dcerpc_info *info,
dcerpc_auth_info *auth_info)
{
+ volatile gint offset = 0;
dcerpc_uuid_key key;
dcerpc_uuid_value *sub_proto;
- int length;
proto_tree *volatile sub_tree = NULL;
dcerpc_sub_dissector *proc;
gchar *name = NULL;
dcerpc_dissect_fnct_t *volatile sub_dissect;
const char *volatile saved_proto;
void *volatile saved_private_data;
+ guint length, reported_length;
+ tvbuff_t *volatile stub_tvb;
+ volatile guint auth_pad_len;
+ volatile int auth_pad_offset;
key.uuid = info->call_data->uuid;
key.ver = info->call_data->ver;
* We don't have a dissector for this UUID, or the protocol
* for that UUID is disabled.
*/
- show_stub_data (tvb, offset, dcerpc_tree, auth_info);
+ if (decrypted_tvb != NULL) {
+ show_stub_data (decrypted_tvb, 0, dcerpc_tree, auth_info,
+ FALSE);
+ } else
+ show_stub_data (tvb, 0, dcerpc_tree, auth_info, TRUE);
return -1;
}
if (tree) {
proto_item *sub_item;
- sub_item = proto_tree_add_item (tree, sub_proto->proto, tvb, offset,
+ sub_item = proto_tree_add_item (tree, sub_proto->proto_id, tvb, 0,
-1, FALSE);
if (sub_item) {
*/
if (sub_proto->opnum_hf != -1)
- proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
- tvb, 0, 0, info->call_data->opnum,
- "Operation: %s (%u)",
- name, info->call_data->opnum);
+ proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
+ tvb, 0, 0, info->call_data->opnum,
+ "Operation: %s (%u)",
+ name, info->call_data->opnum);
else
- proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
- 0, 0, info->call_data->opnum,
- "Operation: %s (%u)",
- name, info->call_data->opnum);
- }
-
- /*
- * If the authentication level is DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
- * the stub data is encrypted, and we'd have to decrypt it in
- * order to dissect it.
- */
- if (auth_info != NULL &&
- auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
- length = tvb_length_remaining (tvb, offset);
-
- if (length > 0) {
- dcerpc_auth_subdissector_fns *auth_fns;
- decrypted_info_t *dit;
- tvbuff_t *enc_tvb;
-
- enc_tvb = tvb_new_subset(tvb, offset, length, length);
-
- proto_tree_add_text(sub_tree, enc_tvb, 0, length,
- "Encrypted stub data (%d byte%s)",
- length, plurality(length, "", "s"));
-
- pinfo->decrypted_data = NULL;
-
- if ((auth_fns = get_auth_subdissector_fns(
- auth_info->auth_level, auth_info->auth_type)))
- dissect_encrypted_data(
- enc_tvb, pinfo, sub_tree, auth_fns,
- info->request ? PDU_REQ : PDU_RESP, drep);
-
- /* No decrypted data so don't try and call a subdissector */
-
- if (!pinfo->decrypted_data)
- goto done;
-
- dit = (decrypted_info_t *)pinfo->decrypted_data;
- tvb = dit->decr_tvb;
- sub_tree = dit->decr_tree;
- }
+ proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
+ 0, 0, info->call_data->opnum,
+ "Operation: %s (%u)",
+ name, info->call_data->opnum);
}
sub_dissect = info->request ? proc->dissect_rqst : proc->dissect_resp;
- if (sub_dissect) {
+
+ if (decrypted_tvb != NULL) {
+ /* Either there was no encryption or we successfully decrypted
+ the entrypted payload. */
+ if (sub_dissect) {
+ /* We have a subdissector - call it. */
saved_proto = pinfo->current_proto;
saved_private_data = pinfo->private_data;
pinfo->current_proto = sub_proto->name;
pinfo->private_data = (void *)info;
init_ndr_pointer_list(pinfo);
+
/*
- * Catch ReportedBoundsError, so that even if the stub
- * data is bad, we still show the verifier.
+ * Remove the authentication padding from the stub data.
*/
- TRY {
- offset = sub_dissect (tvb, offset, pinfo, sub_tree, drep);
- } CATCH(BoundsError) {
- RETHROW;
- } CATCH(ReportedBoundsError) {
- show_reported_bounds_error(tvb, pinfo, tree);
- } ENDTRY;
-
- /* If there is auth padding at the end of the stub, display it */
if (auth_info != NULL && auth_info->auth_pad_len != 0) {
- proto_tree_add_text (sub_tree, tvb, offset,
- auth_info->auth_pad_len,
- "Auth Padding (%u byte%s)",
- auth_info->auth_pad_len,
- plurality(auth_info->auth_pad_len, "", "s"));
- offset += auth_info->auth_pad_len;
+ length = tvb_length(decrypted_tvb);
+ reported_length = tvb_reported_length(decrypted_tvb);
+ if (reported_length >= 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.
+ */
+ reported_length -= 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 (length > reported_length)
+ length = reported_length;
+
+ stub_tvb = tvb_new_subset(tvb, 0, length, reported_length);
+ auth_pad_len = auth_info->auth_pad_len;
+ 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.
+ */
+ stub_tvb = NULL;
+ auth_pad_len = reported_length;
+ auth_pad_offset = 0;
+ }
+ } else {
+ /*
+ * No authentication padding.
+ */
+ stub_tvb = decrypted_tvb;
+ auth_pad_len = 0;
+ auth_pad_offset = 0;
}
- /* If we have a subdissector and it didn't dissect all data in
- the tvb, make a note of it. */
+ 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.
+ */
+ TRY {
+ offset = sub_dissect (decrypted_tvb, 0, pinfo, sub_tree,
+ drep);
+
+ /* If we have a subdissector and it didn't dissect all
+ data in the tvb, make a note of it. */
+
+ if (tvb_reported_length_remaining(stub_tvb, offset) > 0) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "[Long frame (%d bytes)]",
+ tvb_reported_length_remaining(stub_tvb, offset));
+ }
+ } CATCH(BoundsError) {
+ RETHROW;
+ } CATCH_ALL {
+ show_exception(decrypted_tvb, pinfo, tree, EXCEPT_CODE);
+ } ENDTRY;
+ }
- if (tvb_length_remaining(tvb, offset)) {
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_fstr(pinfo->cinfo, COL_INFO,
- "[Long frame (%d bytes)]",
- tvb_length_remaining(tvb, offset));
- }
+ /* If there is auth padding at the end of the stub, display it */
+ if (auth_pad_len != 0) {
+ proto_tree_add_text (sub_tree, decrypted_tvb, auth_pad_offset,
+ auth_pad_len,
+ "Auth Padding (%u byte%s)",
+ auth_pad_len,
+ plurality(auth_pad_len, "", "s"));
+ }
pinfo->current_proto = saved_proto;
pinfo->private_data = saved_private_data;
} else {
- length = tvb_length_remaining (tvb, offset);
- if (length > 0) {
- proto_tree_add_text (sub_tree, tvb, offset, length,
- "Stub data (%d byte%s)", length,
- plurality(length, "", "s"));
+ /* No subdissector - show it as stub data. */
+ if(decrypted_tvb){
+ show_stub_data (decrypted_tvb, 0, sub_tree, auth_info, FALSE);
+ } else {
+ show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
}
}
+ } else
+ show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
- done:
tap_queue_packet(dcerpc_tap, pinfo, info);
return 0;
}
{
int auth_offset;
+ auth_info->auth_data = NULL;
+
if (auth_info->auth_size != 0) {
- dcerpc_auth_subdissector_fns *auth_fns;
- tvbuff_t *auth_tvb;
+ dcerpc_auth_subdissector_fns *auth_fns;
+ tvbuff_t *auth_tvb;
+
+ auth_offset = hdr->frag_len - hdr->auth_len;
- auth_offset = hdr->frag_len - hdr->auth_len;
+ auth_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_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)))
- dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
- hdr, auth_info);
- else
- proto_tree_add_text (dcerpc_tree, auth_tvb, 0, hdr->auth_len,
- "Auth Verifier");
+ if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
+ auth_info->auth_type))) {
+ /*
+ * Catch all 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_ALL {
+ show_exception(auth_tvb, pinfo, dcerpc_tree, EXCEPT_CODE);
+ } ENDTRY;
+ } else {
+ proto_tree_add_text (dcerpc_tree, auth_tvb, 0, hdr->auth_len,
+ "Auth Verifier");
+ }
}
return hdr->auth_len;
}
static void
-dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
- e_dce_cn_common_hdr_t *hdr, gboolean are_credentials,
- dcerpc_auth_info *auth_info)
+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)
{
- int offset;
+ volatile int offset;
/*
- * Initially set auth_level to -1 to indicate that we haven't
- * yet seen any authentication level information.
+ * 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 = -1;
-
+ auth_info->auth_level = 0;
+ auth_info->auth_type = 0;
+ auth_info->auth_size = 0;
+ auth_info->auth_pad_len = 0;
+
/*
* The authentication information is at the *end* of the PDU; in
* request and response PDUs, the request and response stub data
* come before it.
*
- * If the full packet is here, and we've got an auth len, and it's
- * valid, then dissect the auth info.
+ * Is there any authentication data (i.e., is the authentication length
+ * non-zero), and is the authentication length valid (i.e., is it, plus
+ * 8 bytes for the type/level/pad length/reserved/context id, less than
+ * or equal to the fragment length minus the starting offset of the
+ * stub data?)
*/
- if (tvb_length (tvb) >= hdr->frag_len
- && hdr->auth_len
- && (hdr->auth_len + 8 <= hdr->frag_len)) {
-
- offset = hdr->frag_len - (hdr->auth_len + 8);
-
- offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
- hf_dcerpc_auth_type,
- &auth_info->auth_type);
- offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
- hf_dcerpc_auth_level,
- &auth_info->auth_level);
-
- offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
- hf_dcerpc_auth_pad_len,
- &auth_info->auth_pad_len);
- offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_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);
-
- /*
- * Dissect the authentication data.
- */
- if (are_credentials) {
- tvbuff_t *auth_tvb;
- dcerpc_auth_subdissector_fns *auth_fns;
- auth_tvb = tvb_new_subset(
- tvb, offset, hdr->auth_len, hdr->auth_len);
+ if (hdr->auth_len
+ && (hdr->auth_len + 8 <= hdr->frag_len - stub_offset)) {
- 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_text (dcerpc_tree, tvb, offset, hdr->auth_len,
- "Auth Credentials");
- }
+ /*
+ * Yes, there is authentication data, and the length is valid.
+ * Do we have all the bytes of stub data?
+ * (If not, we'd throw an exception dissecting *that*, so don't
+ * bother trying to dissect the authentication information and
+ * throwing another exception there.)
+ */
+ offset = hdr->frag_len - (hdr->auth_len + 8);
+ if (offset == 0 || tvb_offset_exists(tvb, offset - 1)) {
+ /*
+ * Either there's no stub data, or the last byte of the stub
+ * data is present in the captured data, so we shouldn't
+ * get a BoundsError dissecting the stub data.
+ *
+ * Try dissecting the authentication data.
+ * Catch all exceptions, so that even if the auth info is bad
+ * or we don't have all of it, we still show the stuff we
+ * dissect after this, such as stub data.
+ */
+ TRY {
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_auth_type,
+ &auth_info->auth_type);
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_auth_level,
+ &auth_info->auth_level);
+
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_auth_pad_len,
+ &auth_info->auth_pad_len);
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_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);
+
+ /*
+ * Dissect the authentication data.
+ */
+ if (are_credentials) {
+ tvbuff_t *auth_tvb;
+ dcerpc_auth_subdissector_fns *auth_fns;
+
+ auth_tvb = tvb_new_subset(tvb, offset, hdr->auth_len,
+ 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_text (dcerpc_tree, tvb, offset, hdr->auth_len,
+ "Auth Credentials");
+ }
- /* 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;
- } else {
- auth_info->auth_size = 0;
- auth_info->auth_pad_len = 0;
+ /* 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_ALL {
+ show_exception(tvb, pinfo, dcerpc_tree, EXCEPT_CODE);
+ } ENDTRY;
+ }
}
}
proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
{
conversation_t *conv = NULL;
- guint8 num_ctx_items;
+ guint8 num_ctx_items = 0;
guint i;
gboolean saw_ctx_item = FALSE;
guint16 ctx_id;
offset += 3;
for (i = 0; i < num_ctx_items; i++) {
- offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ proto_tree *ctx_tree = NULL, *iface_tree = NULL;
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, NULL, hdr->drep,
hf_dcerpc_cn_ctx_id, &ctx_id);
- offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ if (dcerpc_tree) {
+ proto_item *ctx_item;
+
+ ctx_item = proto_tree_add_item(dcerpc_tree, hf_dcerpc_cn_ctx_id,
+ tvb, offset - 2, 2,
+ hdr->drep[0] & 0x10);
+
+ ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
+ }
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree, hdr->drep,
hf_dcerpc_cn_num_trans_items, &num_trans_items);
/* XXX - use "dissect_ndr_uuid_t()"? */
dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
- if (dcerpc_tree) {
+ if (ctx_tree) {
+ proto_item *iface_item;
+
uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN,
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
if_id.Data1, if_id.Data2, if_id.Data3,
if_id.Data4[2], if_id.Data4[3],
if_id.Data4[4], if_id.Data4[5],
if_id.Data4[6], if_id.Data4[7]);
+
if (uuid_str_len >= DCERPC_UUID_STR_LEN)
memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
- proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_if_id, tvb,
+
+ iface_item = proto_tree_add_string_format (ctx_tree, hf_dcerpc_cn_bind_if_id, tvb,
offset, 16, uuid_str, "Interface UUID: %s", uuid_str);
+ iface_tree = proto_item_add_subtree(iface_item, ett_dcerpc_cn_iface);
}
offset += 16;
if (hdr->drep[0] & 0x10) {
- offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
hf_dcerpc_cn_bind_if_ver, &if_ver);
- offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
} else {
- offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
- offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
hf_dcerpc_cn_bind_if_ver, &if_ver);
}
key.uuid = if_id;
key.ver = if_ver;
+ if (num_ctx_items > 1)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %u context items, 1st", num_ctx_items);
+
if ((value = g_hash_table_lookup(dcerpc_uuids, &key)))
col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %s", value->name);
else
for (j = 0; j < num_trans_items; j++) {
/* XXX - use "dissect_ndr_uuid_t()"? */
dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
- if (dcerpc_tree) {
+ if (iface_tree) {
uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN,
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
trans_id.Data1, trans_id.Data2, trans_id.Data3,
trans_id.Data4[6], trans_id.Data4[7]);
if (uuid_str_len >= DCERPC_UUID_STR_LEN)
memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
- proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_trans_id, tvb,
+ proto_tree_add_string_format (iface_tree, hf_dcerpc_cn_bind_trans_id, tvb,
offset, 16, uuid_str, "Transfer Syntax: %s", uuid_str);
}
offset += 16;
- offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, iface_tree, hdr->drep,
hf_dcerpc_cn_bind_trans_ver, &trans_ver);
}
}
* an authentication header, and associate it with an authentication
* context, so subsequent PDUs can use that context.
*/
- dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &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, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
if (check_col (pinfo->cinfo, COL_INFO)) {
if (num_results != 0 && result == 0) {
return "unknown";
}
+/* Dissect stub data (payload) of a DCERPC packet. */
+
static void
dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *dcerpc_tree, proto_tree *tree,
dcerpc_auth_info *auth_info, guint32 alloc_hint,
guint32 frame)
{
- int length, reported_length, stub_length;
gboolean save_fragmented;
fragment_data *fd_head=NULL;
guint32 tot_len;
+ tvbuff_t *payload_tvb, *decrypted_tvb;
+ save_fragmented = pinfo->fragmented;
- length = tvb_length_remaining(tvb, offset);
- reported_length = tvb_reported_length_remaining(tvb, offset);
- stub_length = hdr->frag_len - offset - auth_info->auth_size;
- if (length > stub_length)
- length = stub_length;
- if (reported_length > stub_length)
- reported_length = stub_length;
+ payload_tvb = tvb_new_subset(
+ tvb, offset, tvb_length_remaining(tvb, offset) -
+ auth_info->auth_size, tvb_length_remaining(tvb, offset) -
+ auth_info->auth_size);
- save_fragmented = pinfo->fragmented;
+ /* 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. */
+ decrypted_tvb = NULL;
+
+ if ((auth_fns = get_auth_subdissector_fns(
+ auth_info->auth_level, auth_info->auth_type))) {
+ tvbuff_t *result;
+
+ result = decode_encrypted_data(
+ payload_tvb, pinfo, auth_fns,
+ hdr->ptype == PDU_REQ, auth_info);
+
+ if (result) {
+ if (dcerpc_tree)
+ proto_tree_add_text(
+ dcerpc_tree, payload_tvb, 0, -1,
+ "Encrypted stub data (%d byte%s)",
+ tvb_reported_length(payload_tvb),
+
+ plurality(tvb_length(payload_tvb), "", "s"));
+
+ add_new_data_source(
+ pinfo, result, "Decrypted stub data");
+
+ /* We succeeded. */
+ decrypted_tvb = result;
+ }
+ }
+ } else
+ decrypted_tvb = payload_tvb;
/* if this packet is not fragmented, just dissect it and exit */
if(PFC_NOT_FRAGMENTED(hdr)){
pinfo->fragmented = FALSE;
- dcerpc_try_handoff (pinfo, tree, dcerpc_tree,
- tvb_new_subset (tvb, offset, length, reported_length),
- 0, hdr->drep, di, auth_info);
+ dcerpc_try_handoff(
+ pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
+ hdr->drep, di, auth_info);
+
pinfo->fragmented = save_fragmented;
return;
}
/* if we are not doing reassembly and this is the first fragment
then just dissect it and exit
+ XXX - if we're not doing reassembly, can we decrypt an
+ encrypted stub?
*/
if( (!dcerpc_reassemble) && hdr->flags&PFC_FIRST_FRAG ){
- dcerpc_try_handoff (pinfo, tree, dcerpc_tree,
- tvb_new_subset (tvb, offset, length,
- reported_length),
- 0, hdr->drep, di, auth_info);
+
+ dcerpc_try_handoff(
+ pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
+ hdr->drep, di, auth_info);
+
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO,
" [DCE/RPC %s fragment]", fragment_type(hdr->flags));
*/
if(pinfo->fd->flags.visited){
fd_head=fragment_get(pinfo, frame, dcerpc_co_reassemble_table);
-
goto end_cn_stub;
}
-
/* if we are not doing reassembly and it was neither a complete PDU
nor the first fragment then there is nothing more we can do
so we just have to exit
*/
- if( !dcerpc_reassemble ){
+ if( !dcerpc_reassemble )
goto end_cn_stub;
- }
/* if we didnt get 'frame' we dont know where the PDU started and thus
it is pointless to continue
*/
- if(!frame){
+ if(!frame)
goto end_cn_stub;
- }
-
/* from now on we must attempt to reassemble the PDU
*/
-
- /* we dont have the full fragment so we just have to abort and exit
- */
- if( !tvb_bytes_exist(tvb, offset, stub_length) ){
- goto end_cn_stub;
- }
-
-
/* if we get here we know it is the first time we see the packet
and we also know it is only a fragment and not a full PDU,
thus we must reassemble it.
*/
+ /* Do we have any non-encrypted data to reassemble? */
+ if (decrypted_tvb == NULL) {
+ /* No. We can't even try to reassemble. */
+ goto end_cn_stub;
+ }
/* if this is the first fragment we need to start reassembly
*/
if(hdr->flags&PFC_FIRST_FRAG){
- fragment_add(tvb, offset, pinfo, frame,
- dcerpc_co_reassemble_table,
- 0, stub_length, TRUE);
+ fragment_add(decrypted_tvb, 0, pinfo, frame, dcerpc_co_reassemble_table,
+ 0, tvb_length(decrypted_tvb), TRUE);
fragment_set_tot_len(pinfo, frame,
dcerpc_co_reassemble_table, alloc_hint);
if(!(hdr->flags&PFC_LAST_FRAG)){
tot_len = fragment_get_tot_len(pinfo, frame,
dcerpc_co_reassemble_table);
- fragment_add(tvb, offset, pinfo, frame,
+ fragment_add(decrypted_tvb, 0, pinfo, frame,
dcerpc_co_reassemble_table,
- tot_len-alloc_hint,
- stub_length,
+ tot_len-alloc_hint, tvb_length(decrypted_tvb),
TRUE);
goto end_cn_stub;
*/
tot_len = fragment_get_tot_len(pinfo, frame,
dcerpc_co_reassemble_table);
- fd_head = fragment_add(tvb, offset, pinfo,
+ fd_head = fragment_add(decrypted_tvb, 0, pinfo,
frame,
dcerpc_co_reassemble_table,
- tot_len-alloc_hint,
- stub_length,
+ tot_len-alloc_hint, tvb_length(decrypted_tvb),
TRUE);
end_cn_stub:
- /* Show the fragment data. */
- if (dcerpc_tree) {
- if (length > 0) {
- proto_tree_add_text (dcerpc_tree, tvb, offset, length,
- "Fragment data (%d byte%s)",
- stub_length,
- plurality(stub_length, "", "s"));
- }
- }
-
/* if reassembly is complete, dissect the full PDU
*/
if(fd_head && (fd_head->flags&FD_DEFRAGMENTED) ){
+
if(pinfo->fd->num==fd_head->reassembled_in){
tvbuff_t *next_tvb;
next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
- tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+ tvb_set_child_real_data_tvbuff(decrypted_tvb, next_tvb);
add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
show_fragment_tree(fd_head, &dcerpc_frag_items,
dcerpc_tree, pinfo, next_tvb);
pinfo->fragmented = FALSE;
+
dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
- 0, hdr->drep, di, auth_info);
+ next_tvb, hdr->drep, di, auth_info);
+
} else {
- proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in, tvb, 0, 0, fd_head->reassembled_in);
+ proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
+ decrypted_tvb, 0, 0, fd_head->reassembled_in);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO,
" [DCE/RPC %s fragment]", fragment_type(hdr->flags));
}
} else {
/* Reassembly not complete - some fragments
- are missing */
+ are missing. Just show the stub data. */
+
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO,
" [DCE/RPC %s fragment]", fragment_type(hdr->flags));
}
+
+ if(decrypted_tvb){
+ show_stub_data (decrypted_tvb, 0, tree, auth_info, FALSE);
+ } else {
+ show_stub_data (payload_tvb, 0, tree, auth_info, TRUE);
+ }
}
pinfo->fragmented = save_fragmented;
* XXX - what if this was set when the connection was set up,
* and we just have a security context?
*/
- dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
+ dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
pinfo->srcport, pinfo->destport, 0);
if (!conv)
- show_stub_data (tvb, offset, dcerpc_tree, &auth_info);
+ show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
else {
dcerpc_matched_key matched_key, *new_matched_key;
dcerpc_call_value *value;
}
if (value) {
- dcerpc_info di;
+ dcerpc_info *di;
+ di=get_next_di();
/* handoff this call */
- di.conv = conv;
- di.call_id = hdr->call_id;
- di.smb_fid = get_smb_fid(pinfo->private_data);
- di.request = TRUE;
- di.call_data = value;
- di.hf_index = -1;
+ di->conv = conv;
+ di->call_id = hdr->call_id;
+ di->smb_fid = get_smb_fid(pinfo->private_data);
+ di->request = TRUE;
+ di->call_data = value;
+ di->hf_index = -1;
if(value->rep_frame!=0){
proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
tvb, 0, 0, value->rep_frame);
}
-/*qqq request, broken*/
+
dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
- hdr, &di, &auth_info, alloc_hint,
+ hdr, di, &auth_info, alloc_hint,
value->req_frame);
} else
- show_stub_data (tvb, offset, dcerpc_tree, &auth_info);
+ show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
}
-
- /* Decrypt the verifier, if present */
- 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, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
+ dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
conv = find_conversation (&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);
+ show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
} else {
dcerpc_matched_key matched_key, *new_matched_key;
}
if (value) {
- dcerpc_info di;
+ dcerpc_info *di;
+ di=get_next_di();
/* handoff this call */
- di.conv = conv;
- di.call_id = hdr->call_id;
- di.smb_fid = get_smb_fid(pinfo->private_data);
- di.request = FALSE;
- di.call_data = value;
+ di->conv = conv;
+ di->call_id = hdr->call_id;
+ di->smb_fid = get_smb_fid(pinfo->private_data);
+ di->request = FALSE;
+ di->call_data = value;
proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
if(value->req_frame!=0){
proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &ns);
}
-/*qqq response ok*/
dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
- hdr, &di, &auth_info, alloc_hint,
+ hdr, di, &auth_info, alloc_hint,
value->rep_frame);
} else
- show_stub_data (tvb, offset, dcerpc_tree, &auth_info);
+ show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
}
-
- /* Decrypt the verifier, if present */
- 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, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
pinfo->srcport, pinfo->destport, 0);
if (value) {
int length, reported_length, stub_length;
- dcerpc_info di;
+ dcerpc_info *di;
+ di=get_next_di();
/* handoff this call */
- di.conv = conv;
- di.call_id = hdr->call_id;
- di.smb_fid = get_smb_fid(pinfo->private_data);
- di.request = FALSE;
- di.call_data = value;
+ di->conv = conv;
+ di->call_id = hdr->call_id;
+ di->smb_fid = get_smb_fid(pinfo->private_data);
+ di->request = FALSE;
+ di->call_data = value;
proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
if(value->req_frame!=0){
/*
* DCERPC dissector for connection oriented calls
*/
-static int
+static gboolean
dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, gboolean can_desegment)
+ proto_tree *tree, gboolean can_desegment, int *pkt_len)
{
static char nulls[4] = { 0 };
int start_offset;
* Check if this looks like a C/O DCERPC call
*/
if (!tvb_bytes_exist (tvb, offset, sizeof (hdr))) {
- return -1;
+ return FALSE; /* not enough information to check */
}
start_offset = offset;
hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
if (hdr.rpc_ver != 5)
- return -1;
+ return FALSE;
hdr.rpc_ver_minor = tvb_get_guint8 (tvb, offset++);
if (hdr.rpc_ver_minor != 0 && hdr.rpc_ver_minor != 1)
- return -1;
+ return FALSE;
hdr.ptype = tvb_get_guint8 (tvb, offset++);
if (hdr.ptype > 19)
- return -1;
+ return FALSE;
hdr.flags = tvb_get_guint8 (tvb, offset++);
tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
&& !tvb_bytes_exist(tvb, start_offset, hdr.frag_len)) {
pinfo->desegment_offset = start_offset;
pinfo->desegment_len = hdr.frag_len - tvb_length_remaining (tvb, start_offset);
- return 0; /* desegmentation required */
+ *pkt_len = 0; /* desegmentation required */
+ return TRUE;
}
if (check_col (pinfo->cinfo, COL_PROTOCOL))
pckt_vals[hdr.ptype].strptr, hdr.call_id);
if (tree) {
- offset = start_offset;
+ offset = start_offset;
ti = proto_tree_add_item (tree, proto_dcerpc, tvb, offset, hdr.frag_len, FALSE);
if (ti) {
dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
offset += 4;
}
+ /*
+ * None of the stuff done above should throw an exception, because
+ * we would have rejected this as "not DCE RPC" if we didn't have all
+ * of it. (XXX - perhaps we should request reassembly if we have
+ * enough of the header to consider it DCE RPC but not enough to
+ * get the fragment length; in that case the stuff still wouldn't
+ * throw an exception.)
+ *
+ * The rest of the stuff might, so return the PDU length to our caller.
+ * XXX - should we construct a tvbuff containing only the PDU and
+ * use that? Or should we have separate "is this a DCE RPC PDU",
+ * "how long is it", and "dissect it" routines - which might let us
+ * do most of the work in "tcp_dissect_pdus()"?
+ */
+ if (pkt_len != NULL)
+ *pkt_len = hdr.frag_len + padding;
+
/*
* Packet type specific stuff is next.
*/
/*
* Nothing after the common header other than credentials.
*/
- dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, TRUE,
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, &hdr, TRUE,
&auth_info);
break;
* Nothing after the common header other than an authentication
* verifier.
*/
- dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, FALSE,
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
&auth_info);
break;
default:
/* might as well dissect the auth info */
- dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, FALSE,
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
&auth_info);
break;
}
- return hdr.frag_len + padding;
+ return TRUE;
}
/*
* Only one PDU per transport packet, and only one transport
* packet per PDU.
*/
- if (dissect_dcerpc_cn (tvb, 0, pinfo, tree, FALSE) == -1) {
+ if (!dissect_dcerpc_cn (tvb, 0, pinfo, tree, FALSE, NULL)) {
/*
* It wasn't a DCERPC PDU.
*/
static gboolean
dissect_dcerpc_cn_bs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- int offset = 0;
+ volatile int offset = 0;
int pdu_len;
- gboolean ret = FALSE;
+ volatile gboolean is_dcerpc_pdu;
+ volatile gboolean ret = FALSE;
/*
* There may be multiple PDUs per transport packet; keep
* processing them.
*/
while (tvb_reported_length_remaining(tvb, offset) != 0) {
- pdu_len = dissect_dcerpc_cn (tvb, offset, pinfo, tree,
- dcerpc_cn_desegment);
- if (pdu_len == -1) {
+ /*
+ * Catch ReportedBoundsError, so that even if the stub data is bad,
+ * we don't abort the full DCE RPC dissection - there might be more
+ * than one DCE RPC PDU in the data being dissected.
+ *
+ * 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.
+ */
+ is_dcerpc_pdu = FALSE;
+ TRY {
+ is_dcerpc_pdu = dissect_dcerpc_cn (tvb, offset, pinfo, tree,
+ dcerpc_cn_desegment, &pdu_len);
+ } CATCH(BoundsError) {
+ RETHROW;
+ } CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ } ENDTRY;
+
+ if (!is_dcerpc_pdu) {
/*
* Not a DCERPC PDU.
*/
int length, reported_length, stub_length;
gboolean save_fragmented;
fragment_data *fd_head;
+ tvbuff_t *next_tvb;
- if (check_col (pinfo->cinfo, COL_INFO)) {
- col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u",
- di->call_data->opnum);
- }
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u", di->call_data->opnum );
length = tvb_length_remaining (tvb, offset);
reported_length = tvb_reported_length_remaining (tvb, offset);
if( (!dcerpc_reassemble) || !(hdr->flags1 & PFCL1_FRAG) ||
!tvb_bytes_exist(tvb, offset, stub_length) ){
if(hdr->frag_num == 0) {
+
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " UNKUUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x rpcver: %u",
+ di->call_data->uuid.Data1, di->call_data->uuid.Data2, di->call_data->uuid.Data3, di->call_data->uuid.Data4[0],
+ di->call_data->uuid.Data4[1], di->call_data->uuid.Data4[2], di->call_data->uuid.Data4[3],
+ di->call_data->uuid.Data4[4], di->call_data->uuid.Data4[5], di->call_data->uuid.Data4[6],
+ di->call_data->uuid.Data4[7], di->call_data->ver);
+
+
/* First fragment, possibly the only fragment */
/*
* XXX - authentication info?
*/
pinfo->fragmented = (hdr->flags1 & PFCL1_FRAG);
- dcerpc_try_handoff (pinfo, tree, dcerpc_tree,
- tvb_new_subset (tvb, offset, length,
- reported_length),
- 0, hdr->drep, di, NULL);
+ next_tvb = tvb_new_subset (tvb, offset, length,
+ reported_length);
+ dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
+ next_tvb, hdr->drep, di, NULL);
} else {
/* PDU is fragmented and this isn't the first fragment */
if (check_col(pinfo->cinfo, COL_INFO)) {
!(hdr->flags1 & PFCL1_LASTFRAG));
if (fd_head != NULL) {
/* We completed reassembly */
- tvbuff_t *next_tvb;
-
next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
tvb_set_child_real_data_tvbuff(tvb, next_tvb);
add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
*/
pinfo->fragmented = FALSE;
dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
- 0, hdr->drep, di, NULL);
+ next_tvb, hdr->drep, di, NULL);
} else {
/* Reassembly isn't completed yet */
if (check_col(pinfo->cinfo, COL_INFO)) {
proto_tree *dcerpc_tree, proto_tree *tree,
e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
{
- dcerpc_info di;
+ dcerpc_info *di;
dcerpc_call_value *value, v;
dcerpc_matched_key matched_key, *new_matched_key;
+ di=get_next_di();
if(!(pinfo->fd->flags.visited)){
dcerpc_call_value *call_value;
dcerpc_call_key *call_key;
value = &v;
}
- di.conv = conv;
- di.call_id = hdr->seqnum;
- di.smb_fid = -1;
- di.request = TRUE;
- di.call_data = value;
+ di->conv = conv;
+ di->call_id = hdr->seqnum;
+ di->smb_fid = -1;
+ di->request = TRUE;
+ di->call_data = value;
if(value->rep_frame!=0){
proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
tvb, 0, 0, value->rep_frame);
}
- dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, &di);
+ dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
}
static void
proto_tree *dcerpc_tree, proto_tree *tree,
e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
{
- dcerpc_info di;
+ dcerpc_info *di;
dcerpc_call_value *value, v;
dcerpc_matched_key matched_key, *new_matched_key;
+ di=get_next_di();
if(!(pinfo->fd->flags.visited)){
dcerpc_call_value *call_value;
dcerpc_call_key call_key;
value = &v;
}
- di.conv = conv;
- di.call_id = 0;
- di.smb_fid = -1;
- di.request = FALSE;
- di.call_data = value;
+ di->conv = conv;
+ di->call_id = 0;
+ di->smb_fid = -1;
+ di->request = FALSE;
+ di->call_data = value;
if(value->req_frame!=0){
nstime_t ns;
}
proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &ns);
}
- dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, &di);
+ dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
}
/*
{ "FACK Version", "dcerpc.fack_vers", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
{ &hf_dcerpc_dg_fack_window_size,
- { "Window Size", "dcerpc.fack_window size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { "Window Size", "dcerpc.fack_window_size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
{ &hf_dcerpc_dg_fack_max_tsdu,
{ "Max TSDU", "dcerpc.fack_max_tsdu", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
static gint *ett[] = {
&ett_dcerpc,
&ett_dcerpc_cn_flags,
+ &ett_dcerpc_cn_ctx,
+ &ett_dcerpc_cn_iface,
&ett_dcerpc_drep,
&ett_dcerpc_dg_flags1,
&ett_dcerpc_dg_flags2,