diff options
author | Stefan Metzmacher <metze@samba.org> | 2016-09-19 04:35:49 +0200 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2016-09-23 04:27:11 +0000 |
commit | 1ec28b4a084112e6ca4971300f17354e8c6cee3c (patch) | |
tree | 378fb30791025baa1602dacddc8d53137c357945 /epan/dissectors/packet-dcerpc.c | |
parent | 68dbc6431f5b391c05f27641ad5c11c378739648 (diff) |
packet-dcerpc: let dissect_dcerpc_cn_auth() always dissect the whole auth_info
As all this information belongs together I'm moving it into a subtree.
Change-Id: I839a5a6294360976a78b4b43f219e30381b4f516
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-on: https://code.wireshark.org/review/17878
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-dcerpc.c')
-rw-r--r-- | epan/dissectors/packet-dcerpc.c | 239 |
1 files changed, 101 insertions, 138 deletions
diff --git a/epan/dissectors/packet-dcerpc.c b/epan/dissectors/packet-dcerpc.c index 6d61158db3..a9f931fbfc 100644 --- a/epan/dissectors/packet-dcerpc.c +++ b/epan/dissectors/packet-dcerpc.c @@ -610,6 +610,7 @@ 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; @@ -653,6 +654,7 @@ static gint ett_dcerpc_string = -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; @@ -1204,9 +1206,7 @@ void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type, /* 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) { @@ -1217,33 +1217,42 @@ static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo, */ 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: case PDU_CO_CANCEL: case PDU_ORPHANED: - fn = auth_fns->req_verf_fn; + fn = auth_info->auth_fns->req_verf_fn; break; case PDU_RESP: case PDU_FAULT: - fn = auth_fns->resp_verf_fn; + 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; @@ -1251,15 +1260,15 @@ static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo, } 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* @@ -1285,21 +1294,30 @@ proto_tree_add_dcerpc_drep(proto_tree *tree, tvbuff_t *tvb, int offset, guint8 d /* 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; } @@ -3651,51 +3669,10 @@ dcerpc_try_handoff(packet_info *pinfo, proto_tree *tree, 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; @@ -3703,10 +3680,15 @@ dissect_dcerpc_cn_auth(tvbuff_t *tvb, int stub_offset, packet_info *pinfo, * 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 @@ -3732,6 +3714,15 @@ dissect_dcerpc_cn_auth(tvbuff_t *tvb, int stub_offset, packet_info *pinfo, */ 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 @@ -3743,44 +3734,49 @@ dissect_dcerpc_cn_auth(tvbuff_t *tvb, int stub_offset, packet_info *pinfo, * 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; @@ -4024,7 +4020,7 @@ dissect_dcerpc_cn_bind(tvbuff_t *tvb, gint offset, packet_info *pinfo, * 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 @@ -4132,7 +4128,7 @@ dissect_dcerpc_cn_bind_ack(tvbuff_t *tvb, gint offset, packet_info *pinfo, * 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 @@ -4196,7 +4192,7 @@ dissect_dcerpc_cn_stub(tvbuff_t *tvb, int offset, packet_info *pinfo, 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; @@ -4216,45 +4212,17 @@ dissect_dcerpc_cn_stub(tvbuff_t *tvb, int offset, packet_info *pinfo, 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) { proto_tree_add_item(dcerpc_tree, hf_dcerpc_encrypted_stub_data, payload_tvb, 0, -1, ENC_NA); @@ -4465,7 +4433,7 @@ dissect_dcerpc_cn_rqst(tvbuff_t *tvb, gint offset, packet_info *pinfo, * 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->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); @@ -4583,10 +4551,6 @@ dissect_dcerpc_cn_rqst(tvbuff_t *tvb, gint offset, packet_info *pinfo, 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 @@ -4628,7 +4592,7 @@ dissect_dcerpc_cn_resp(tvbuff_t *tvb, gint offset, packet_info *pinfo, * 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->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); @@ -4718,9 +4682,6 @@ dissect_dcerpc_cn_resp(tvbuff_t *tvb, gint offset, packet_info *pinfo, 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 @@ -4775,7 +4736,7 @@ dissect_dcerpc_cn_fault(tvbuff_t *tvb, gint offset, packet_info *pinfo, * 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->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); @@ -5491,7 +5452,7 @@ dissect_dcerpc_cn(tvbuff_t *tvb, int offset, packet_info *pinfo, /* * 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; @@ -5517,7 +5478,7 @@ dissect_dcerpc_cn(tvbuff_t *tvb, int offset, packet_info *pinfo, * 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; @@ -5533,7 +5494,7 @@ dissect_dcerpc_cn(tvbuff_t *tvb, int offset, packet_info *pinfo, 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; } @@ -6903,6 +6864,7 @@ proto_register_dcerpc(void) { &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 }}, @@ -6930,6 +6892,7 @@ proto_register_dcerpc(void) &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, |