aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2016-09-20 02:46:24 +0200
committerAlexis La Goutte <alexis.lagoutte@gmail.com>2017-07-09 12:05:30 +0000
commitfaf33d0d148a84cbd2d0367577b6ba59fe0fef17 (patch)
treeef0d4e1b7c34f776c4708fc5ab9292af2ba594b9 /epan/dissectors
parenta3b47316eb4f668e0ec92f9339bd914d28f934ff (diff)
packet-dcerpc: improve the dissection of DCERPC Fault pdus
Change-Id: I70786cc561d248529167445e12190159d818ebcb Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-on: https://code.wireshark.org/review/17811 Reviewed-by: Michael Mann <mmann78@netscape.net> Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Diffstat (limited to 'epan/dissectors')
-rw-r--r--epan/dissectors/packet-dcerpc.c72
1 files changed, 56 insertions, 16 deletions
diff --git a/epan/dissectors/packet-dcerpc.c b/epan/dissectors/packet-dcerpc.c
index 89d30ec321..f865dc3fe1 100644
--- a/epan/dissectors/packet-dcerpc.c
+++ b/epan/dissectors/packet-dcerpc.c
@@ -491,6 +491,8 @@ static int hf_dcerpc_cn_num_protocols = -1;
static int hf_dcerpc_cn_protocol_ver_major = -1;
static int hf_dcerpc_cn_protocol_ver_minor = -1;
static int hf_dcerpc_cn_cancel_count = -1;
+static int hf_dcerpc_cn_fault_flags = -1;
+static int hf_dcerpc_cn_fault_flags_extended_error_info = -1;
static int hf_dcerpc_cn_status = -1;
static int hf_dcerpc_cn_deseg_req = -1;
static int hf_dcerpc_cn_rts_flags = -1;
@@ -634,6 +636,11 @@ static const int *sec_vt_bitmask_fields[] = {
NULL
};
+static const int *dcerpc_cn_fault_flags_fields[] = {
+ &hf_dcerpc_cn_fault_flags_extended_error_info,
+ NULL
+};
+
static const value_string sec_vt_command_cmd_vals[] = {
{1, "BITMASK_1"},
{2, "PCONTEXT"},
@@ -666,13 +673,15 @@ 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 gint ett_dcerpc_fault_flags = -1;
+static gint ett_dcerpc_fault_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_fragment_reassembled = EI_INIT;
static expert_field ei_dcerpc_fragment = EI_INIT;
static expert_field ei_dcerpc_no_request_found = EI_INIT;
-/* static expert_field ei_dcerpc_context_change = EI_INIT */;
+/* static expert_field ei_dcerpc_context_change = EI_INIT; */
static expert_field ei_dcerpc_cn_ctx_id_no_bind = EI_INIT;
static expert_field ei_dcerpc_bind_not_acknowledged = EI_INIT;
static expert_field ei_dcerpc_verifier_unavailable = EI_INIT;
@@ -4782,6 +4791,8 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
guint32 status;
guint32 alloc_hint;
dcerpc_auth_info auth_info;
+ gint length, reported_length;
+ tvbuff_t *stub_tvb = NULL;
proto_item *pi = NULL;
dcerpc_decode_as_data* decode_data = dcerpc_get_decode_data(pinfo);
@@ -4793,8 +4804,12 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
offset = dissect_dcerpc_uint8(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
hf_dcerpc_cn_cancel_count, NULL);
- /* padding */
- offset++;
+ proto_tree_add_bitmask(dcerpc_tree, tvb, offset,
+ hf_dcerpc_cn_fault_flags,
+ ett_dcerpc_fault_flags,
+ dcerpc_cn_fault_flags_fields,
+ DREP_ENC_INTEGER(hdr->drep));
+ offset += 1;
#if 0
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
@@ -4818,6 +4833,7 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
"Unknown (0x%08x)"));
/* padding */
+ proto_tree_add_item(dcerpc_tree, hf_dcerpc_reserved, tvb, offset, 4, ENC_NA);
offset += 4;
/*
@@ -4826,6 +4842,19 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
*/
dissect_dcerpc_cn_auth(tvb, offset, pinfo, dcerpc_tree, hdr, &auth_info);
+ length = tvb_captured_length_remaining(tvb, offset);
+ reported_length = tvb_reported_length_remaining(tvb, offset);
+ if (reported_length < 0 ||
+ (guint32)reported_length < auth_info.auth_size) {
+ /* We don't even have enough bytes for the authentication
+ stuff. */
+ return;
+ }
+ reported_length -= auth_info.auth_size;
+ if (length > reported_length)
+ length = reported_length;
+ stub_tvb = tvb_new_subset_length_caplen(tvb, offset, length, reported_length);
+
conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
pinfo->srcport, pinfo->destport, 0);
if (!conv) {
@@ -4863,7 +4892,8 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
}
if (value) {
- int length, stub_length;
+ proto_tree *stub_tree = NULL;
+ gint stub_length;
dcerpc_info *di;
proto_item *parent_pi;
@@ -4894,7 +4924,7 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
proto_tree_add_expert(dcerpc_tree, pinfo, &ei_dcerpc_no_request_found, tvb, 0, 0);
}
- length = tvb_reported_length_remaining(tvb, offset);
+ length = tvb_reported_length_remaining(stub_tvb, 0);
/* as we now create a tvb in dissect_dcerpc_cn() containing only the
* stub_data, the following calculation is no longer valid:
* stub_length = hdr->frag_len - offset - auth_info.auth_size;
@@ -4902,15 +4932,19 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
* XXX - or better use the reported_length?!?
*/
stub_length = length;
- if (length > stub_length)
- length = stub_length;
+
+ stub_tree = proto_tree_add_subtree_format(dcerpc_tree,
+ stub_tvb, 0, stub_length,
+ ett_dcerpc_fault_stub_data, NULL,
+ "Fault stub data (%d byte%s)", stub_length,
+ plurality(stub_length, "", "s"));
/* If we don't have reassembly enabled, or this packet contains
the entire PDU, or if we don't have all the data in this
fragment, just call the handoff directly if this is the
first fragment or the PDU isn't fragmented. */
if ( (!dcerpc_reassemble) || PFC_NOT_FRAGMENTED(hdr) ||
- !tvb_bytes_exist(tvb, offset, stub_length) ) {
+ !tvb_bytes_exist(stub_tvb, 0, stub_length) ) {
if (hdr->flags&PFC_FIRST_FRAG) {
/* First fragment, possibly the only fragment */
/*
@@ -4924,12 +4958,12 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
* as well, as that might be protocol-specific.
*/
if (stub_length > 0) {
- proto_tree_add_item(dcerpc_tree, hf_dcerpc_fault_stub_data, tvb, offset, stub_length, ENC_NA);
+ proto_tree_add_item(stub_tree, hf_dcerpc_fault_stub_data, stub_tvb, 0, stub_length, ENC_NA);
}
} else {
/* PDU is fragmented and this isn't the first fragment */
if (stub_length > 0) {
- proto_tree_add_item(dcerpc_tree, hf_dcerpc_fragment_data, tvb, offset, stub_length, ENC_NA);
+ proto_tree_add_item(stub_tree, hf_dcerpc_fragment_data, stub_tvb, 0, stub_length, ENC_NA);
}
}
} else {
@@ -4939,13 +4973,13 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
third means we can attempt reassembly. */
if (dcerpc_tree) {
if (length > 0) {
- proto_tree_add_item(dcerpc_tree, hf_dcerpc_fragment_data, tvb, offset, stub_length, ENC_NA);
+ proto_tree_add_item(stub_tree, hf_dcerpc_fragment_data, stub_tvb, 0, stub_length, ENC_NA);
}
}
if (hdr->flags&PFC_FIRST_FRAG) { /* FIRST fragment */
if ( (!pinfo->fd->flags.visited) && value->rep_frame ) {
fragment_add_seq_next(&dcerpc_co_reassembly_table,
- tvb, offset,
+ stub_tvb, 0,
pinfo, value->rep_frame, NULL,
stub_length,
TRUE);
@@ -4955,7 +4989,7 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
fragment_head *fd_head;
fd_head = fragment_add_seq_next(&dcerpc_co_reassembly_table,
- tvb, offset,
+ stub_tvb, 0,
pinfo, value->rep_frame, NULL,
stub_length,
TRUE);
@@ -4965,7 +4999,7 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
tvbuff_t *next_tvb;
proto_item *frag_tree_item;
- next_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
+ next_tvb = tvb_new_chain(stub_tvb, fd_head->tvb_data);
add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
show_fragment_tree(fd_head, &dcerpc_frag_items,
dcerpc_tree, pinfo, next_tvb, &frag_tree_item);
@@ -4982,7 +5016,7 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
*/
if (dcerpc_tree) {
if (length > 0) {
- proto_tree_add_item(dcerpc_tree, hf_dcerpc_stub_data, tvb, offset, stub_length, ENC_NA);
+ proto_tree_add_item(dcerpc_tree, hf_dcerpc_stub_data, stub_tvb, 0, stub_length, ENC_NA);
}
}
}
@@ -4990,7 +5024,7 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo,
} else { /* MIDDLE fragment(s) */
if ( (!pinfo->fd->flags.visited) && value->rep_frame ) {
fragment_add_seq_next(&dcerpc_co_reassembly_table,
- tvb, offset,
+ stub_tvb, 0,
pinfo, value->rep_frame, NULL,
stub_length,
TRUE);
@@ -6690,6 +6724,10 @@ proto_register_dcerpc(void)
{ "Protocol minor version", "dcerpc.cn_protocol_ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_dcerpc_cn_cancel_count,
{ "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcerpc_cn_fault_flags,
+ { "Fault flags", "dcerpc.cn_fault_flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_dcerpc_cn_fault_flags_extended_error_info,
+ { "Extended error information present", "dcerpc.cn_fault_flags.extended_error", FT_BOOLEAN, 8, NULL, 0x1, NULL, HFILL }},
{ &hf_dcerpc_cn_status,
{ "Status", "dcerpc.cn_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, NULL, HFILL }},
{ &hf_dcerpc_cn_deseg_req,
@@ -6986,6 +7024,8 @@ proto_register_dcerpc(void)
&ett_dcerpc_sec_vt_pcontext,
&ett_dcerpc_sec_vt_header,
&ett_dcerpc_complete_stub_data,
+ &ett_dcerpc_fault_flags,
+ &ett_dcerpc_fault_stub_data,
};
static ei_register_info ei[] = {