forked from osmocom/wireshark
packet-dcerpc: pass down header/trailer for hdr_signing
Change-Id: I1d14ffe928e1b303eee7e95a45a9617ffcfb151b Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-on: https://code.wireshark.org/review/35707 Petri-Dish: Anders Broman <a.broman58@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
560f120946
commit
6afa37bb1a
|
@ -7923,15 +7923,24 @@ dissect_packet_data(tvbuff_t *tvb ,tvbuff_t *auth_tvb _U_,
|
|||
return(buf);
|
||||
}
|
||||
|
||||
static tvbuff_t* dissect_request_data( tvbuff_t *tvb ,tvbuff_t *auth_tvb ,
|
||||
int offset , packet_info *pinfo ,dcerpc_auth_info *auth_info )
|
||||
static tvbuff_t* dissect_request_data(tvbuff_t *header_tvb _U_,
|
||||
tvbuff_t *payload_tvb,
|
||||
tvbuff_t *trailer_tvb _U_,
|
||||
tvbuff_t *auth_tvb,
|
||||
packet_info *pinfo,
|
||||
dcerpc_auth_info *auth_info)
|
||||
{
|
||||
return dissect_packet_data(tvb,auth_tvb,offset,pinfo,auth_info,0);
|
||||
return dissect_packet_data(payload_tvb,auth_tvb,0,pinfo,auth_info,0);
|
||||
}
|
||||
static tvbuff_t* dissect_response_data( tvbuff_t *tvb ,tvbuff_t *auth_tvb ,
|
||||
int offset , packet_info *pinfo ,dcerpc_auth_info *auth_info )
|
||||
|
||||
static tvbuff_t* dissect_response_data(tvbuff_t *header_tvb _U_,
|
||||
tvbuff_t *payload_tvb,
|
||||
tvbuff_t *trailer_tvb _U_,
|
||||
tvbuff_t *auth_tvb,
|
||||
packet_info *pinfo,
|
||||
dcerpc_auth_info *auth_info)
|
||||
{
|
||||
return dissect_packet_data(tvb,auth_tvb,offset,pinfo,auth_info,1);
|
||||
return dissect_packet_data(payload_tvb,auth_tvb,0,pinfo,auth_info,1);
|
||||
}
|
||||
|
||||
/* MS-NRPC 2.2.1.3.2 */
|
||||
|
|
|
@ -179,6 +179,7 @@ static const value_string authn_level_vals[] = {
|
|||
#define PFC_FIRST_FRAG 0x01 /* First fragment */
|
||||
#define PFC_LAST_FRAG 0x02 /* Last fragment */
|
||||
#define PFC_PENDING_CANCEL 0x04 /* Cancel was pending at sender */
|
||||
#define PFC_HDR_SIGNING PFC_PENDING_CANCEL /* on bind and alter req */
|
||||
#define PFC_RESERVED_1 0x08
|
||||
#define PFC_CONC_MPX 0x10 /* supports concurrent multiplexing
|
||||
* of a single connection. */
|
||||
|
@ -704,6 +705,18 @@ typedef struct _dcerpc_bind_value {
|
|||
e_guid_t transport;
|
||||
} dcerpc_bind_value;
|
||||
|
||||
static wmem_map_t *dcerpc_auths = NULL;
|
||||
|
||||
typedef struct _dcerpc_auth_context {
|
||||
conversation_t *conv;
|
||||
guint64 transport_salt;
|
||||
guint8 auth_type;
|
||||
guint8 auth_level;
|
||||
guint32 auth_context_id;
|
||||
guint32 first_frame;
|
||||
gboolean hdr_signing;
|
||||
} dcerpc_auth_context;
|
||||
|
||||
/* Extra data for DCERPC handling and tracking of context ids */
|
||||
typedef struct _dcerpc_decode_as_data {
|
||||
guint16 dcectxid; /**< Context ID (DCERPC-specific) */
|
||||
|
@ -1278,7 +1291,9 @@ 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,
|
||||
static tvbuff_t *decode_encrypted_data(tvbuff_t *header_tvb,
|
||||
tvbuff_t *payload_tvb,
|
||||
tvbuff_t *trailer_tvb,
|
||||
packet_info *pinfo,
|
||||
e_dce_cn_common_hdr_t *hdr,
|
||||
dcerpc_auth_info *auth_info)
|
||||
|
@ -1302,7 +1317,7 @@ static tvbuff_t *decode_encrypted_data(tvbuff_t *data_tvb,
|
|||
}
|
||||
|
||||
if (fn)
|
||||
return fn(data_tvb, auth_info->auth_tvb, 0, pinfo, auth_info);
|
||||
return fn(header_tvb, payload_tvb, trailer_tvb, auth_info->auth_tvb, pinfo, auth_info);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1790,6 +1805,31 @@ dcerpc_bind_hash(gconstpointer k)
|
|||
return hash;
|
||||
}
|
||||
|
||||
static gint
|
||||
dcerpc_auth_context_equal(gconstpointer k1, gconstpointer k2)
|
||||
{
|
||||
const dcerpc_auth_context *key1 = (const dcerpc_auth_context *)k1;
|
||||
const dcerpc_auth_context *key2 = (const dcerpc_auth_context *)k2;
|
||||
return ((key1->conv == key2->conv)
|
||||
&& (key1->auth_context_id == key2->auth_context_id)
|
||||
&& (key1->transport_salt == key2->transport_salt));
|
||||
}
|
||||
|
||||
static guint
|
||||
dcerpc_auth_context_hash(gconstpointer k)
|
||||
{
|
||||
const dcerpc_auth_context *key = (const dcerpc_auth_context *)k;
|
||||
guint hash;
|
||||
|
||||
hash = GPOINTER_TO_UINT(key->conv);
|
||||
hash += key->auth_context_id;
|
||||
/* sizeof(guint) might be smaller than sizeof(guint64) */
|
||||
hash += (guint)key->transport_salt;
|
||||
hash += (guint)(key->transport_salt << sizeof(guint));
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/*
|
||||
* To keep track of callid mappings. Should really use some generic
|
||||
* conversation support instead.
|
||||
|
@ -3743,6 +3783,39 @@ dissect_dcerpc_cn_auth_move(dcerpc_auth_info *auth_info, proto_tree *dcerpc_tree
|
|||
}
|
||||
}
|
||||
|
||||
static dcerpc_auth_context *find_or_create_dcerpc_auth_context(packet_info *pinfo,
|
||||
dcerpc_auth_info *auth_info)
|
||||
{
|
||||
dcerpc_auth_context auth_key = {
|
||||
.conv = find_or_create_conversation(pinfo),
|
||||
.transport_salt = dcerpc_get_transport_salt(pinfo),
|
||||
.auth_type = auth_info->auth_type,
|
||||
.auth_level = auth_info->auth_level,
|
||||
.auth_context_id = auth_info->auth_context_id,
|
||||
.first_frame = G_MAXUINT32,
|
||||
};
|
||||
dcerpc_auth_context *auth_value = NULL;
|
||||
|
||||
auth_value = (dcerpc_auth_context *)wmem_map_lookup(dcerpc_auths, &auth_key);
|
||||
if (auth_value != NULL) {
|
||||
goto return_value;
|
||||
}
|
||||
|
||||
auth_value = (dcerpc_auth_context *)wmem_alloc(wmem_file_scope(), sizeof (dcerpc_auth_context));
|
||||
if (auth_value == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*auth_value = auth_key;
|
||||
wmem_map_insert(dcerpc_auths, auth_value, auth_value);
|
||||
|
||||
return_value:
|
||||
if (pinfo->fd->num < auth_value->first_frame) {
|
||||
auth_value->first_frame = pinfo->fd->num;
|
||||
}
|
||||
return auth_value;
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -3754,6 +3827,7 @@ 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->hdr_signing = FALSE;
|
||||
auth_info->auth_type = 0;
|
||||
auth_info->auth_level = 0;
|
||||
auth_info->auth_context_id = 0;
|
||||
|
@ -3788,6 +3862,9 @@ 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)) {
|
||||
dcerpc_auth_context *auth_context = NULL;
|
||||
int auth_offset = offset;
|
||||
|
||||
/* 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 */
|
||||
|
@ -3837,10 +3914,22 @@ dissect_dcerpc_cn_auth(tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
|
|||
/*
|
||||
* Dissect the authentication data.
|
||||
*/
|
||||
auth_info->auth_hdr_tvb = tvb_new_subset_length_caplen(tvb, auth_offset, 8, 8);
|
||||
auth_info->auth_tvb = tvb_new_subset_length_caplen(tvb, offset,
|
||||
MIN(hdr->auth_len,tvb_reported_length_remaining(tvb, offset)),
|
||||
hdr->auth_len);
|
||||
|
||||
auth_context = find_or_create_dcerpc_auth_context(pinfo, auth_info);
|
||||
if (auth_context != NULL) {
|
||||
if (hdr->ptype == PDU_BIND || hdr->ptype == PDU_ALTER) {
|
||||
if (auth_context->first_frame == pinfo->fd->num) {
|
||||
auth_context->hdr_signing = (hdr->flags & PFC_HDR_SIGNING);
|
||||
}
|
||||
}
|
||||
|
||||
auth_info->hdr_signing = auth_context->hdr_signing;
|
||||
}
|
||||
|
||||
auth_info->auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
|
||||
auth_info->auth_type);
|
||||
if (auth_info->auth_fns != NULL)
|
||||
|
@ -4266,6 +4355,7 @@ dissect_dcerpc_cn_stub(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
gboolean save_fragmented;
|
||||
fragment_head *fd_head = NULL;
|
||||
|
||||
tvbuff_t *header_tvb = NULL, *trailer_tvb = NULL;
|
||||
tvbuff_t *payload_tvb, *decrypted_tvb = NULL;
|
||||
proto_item *pi;
|
||||
proto_item *parent_pi;
|
||||
|
@ -4284,7 +4374,9 @@ dissect_dcerpc_cn_stub(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
reported_length -= auth_info->auth_size;
|
||||
if (length > reported_length)
|
||||
length = reported_length;
|
||||
header_tvb = tvb_new_subset_length_caplen(tvb, 0, offset, offset);
|
||||
payload_tvb = tvb_new_subset_length_caplen(tvb, offset, length, reported_length);
|
||||
trailer_tvb = auth_info->auth_hdr_tvb;
|
||||
|
||||
/* Decrypt the PDU if it is encrypted */
|
||||
|
||||
|
@ -4296,7 +4388,8 @@ dissect_dcerpc_cn_stub(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
if (auth_info->auth_fns != NULL) {
|
||||
tvbuff_t *result;
|
||||
|
||||
result = decode_encrypted_data(payload_tvb, pinfo, hdr, auth_info);
|
||||
result = decode_encrypted_data(header_tvb, payload_tvb, trailer_tvb,
|
||||
pinfo, hdr, auth_info);
|
||||
if (result) {
|
||||
proto_tree_add_item(dcerpc_tree, hf_dcerpc_encrypted_stub_data, payload_tvb, 0, -1, ENC_NA);
|
||||
|
||||
|
@ -7060,6 +7153,11 @@ proto_register_dcerpc(void)
|
|||
/* structures and data for BIND */
|
||||
dcerpc_binds = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), dcerpc_bind_hash, dcerpc_bind_equal);
|
||||
|
||||
dcerpc_auths = wmem_map_new_autoreset(wmem_epan_scope(),
|
||||
wmem_file_scope(),
|
||||
dcerpc_auth_context_hash,
|
||||
dcerpc_auth_context_equal);
|
||||
|
||||
/* structures and data for CALL */
|
||||
dcerpc_cn_calls = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), dcerpc_cn_call_hash, dcerpc_cn_call_equal);
|
||||
dcerpc_dg_calls = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), dcerpc_dg_call_hash, dcerpc_dg_call_equal);
|
||||
|
|
|
@ -91,12 +91,14 @@ typedef struct _e_dce_dg_common_hdr_t {
|
|||
struct _dcerpc_auth_subdissector_fns;
|
||||
|
||||
typedef struct _dcerpc_auth_info {
|
||||
gboolean hdr_signing;
|
||||
guint8 auth_type;
|
||||
guint8 auth_level;
|
||||
guint32 auth_context_id;
|
||||
guint8 auth_pad_len;
|
||||
guint32 auth_size;
|
||||
struct _dcerpc_auth_subdissector_fns *auth_fns;
|
||||
tvbuff_t *auth_hdr_tvb;
|
||||
tvbuff_t *auth_tvb;
|
||||
proto_item *auth_item;
|
||||
proto_tree *auth_tree;
|
||||
|
@ -425,9 +427,10 @@ typedef struct _dcerpc_uuid_value {
|
|||
|
||||
/* Authenticated pipe registration functions and miscellanea */
|
||||
|
||||
typedef tvbuff_t *(dcerpc_decode_data_fnct_t)(tvbuff_t *data_tvb,
|
||||
typedef tvbuff_t *(dcerpc_decode_data_fnct_t)(tvbuff_t *header_tvb,
|
||||
tvbuff_t *payload_tvb,
|
||||
tvbuff_t *trailer_tvb,
|
||||
tvbuff_t *auth_tvb,
|
||||
int offset,
|
||||
packet_info *pinfo,
|
||||
dcerpc_auth_info *auth_info);
|
||||
|
||||
|
|
|
@ -670,8 +670,11 @@ wrap_dissect_gssapi_verf(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
}
|
||||
|
||||
tvbuff_t *
|
||||
wrap_dissect_gssapi_payload(tvbuff_t *data_tvb, tvbuff_t *auth_tvb,
|
||||
int offset _U_, packet_info *pinfo,
|
||||
wrap_dissect_gssapi_payload(tvbuff_t *header_tvb _U_,
|
||||
tvbuff_t *payload_tvb,
|
||||
tvbuff_t *trailer_tvb _U_,
|
||||
tvbuff_t *auth_tvb,
|
||||
packet_info *pinfo,
|
||||
dcerpc_auth_info *auth_info _U_)
|
||||
{
|
||||
tvbuff_t *result;
|
||||
|
@ -682,12 +685,12 @@ wrap_dissect_gssapi_payload(tvbuff_t *data_tvb, tvbuff_t *auth_tvb,
|
|||
/* we need a full auth and a full data tvb or else we can't
|
||||
decrypt anything
|
||||
*/
|
||||
if((!auth_tvb)||(!data_tvb)){
|
||||
if((!auth_tvb)||(!payload_tvb)){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gssapi_encrypt.decrypt_gssapi_tvb=DECRYPT_GSSAPI_DCE;
|
||||
gssapi_encrypt.gssapi_encrypted_tvb=data_tvb;
|
||||
gssapi_encrypt.gssapi_encrypted_tvb=payload_tvb;
|
||||
|
||||
dissect_gssapi(auth_tvb, pinfo, NULL, &gssapi_encrypt);
|
||||
result=gssapi_encrypt.gssapi_decrypted_tvb;
|
||||
|
|
|
@ -57,10 +57,12 @@ int wrap_dissect_gssapi_verf(tvbuff_t *tvb, int offset,
|
|||
packet_info *pinfo,
|
||||
proto_tree *tree, dcerpc_info *di, guint8 *drep);
|
||||
|
||||
tvbuff_t *wrap_dissect_gssapi_payload(tvbuff_t *data_tvb,
|
||||
tvbuff_t *auth_tvb,
|
||||
int offset,
|
||||
packet_info *pinfo,
|
||||
dcerpc_auth_info *auth_info);
|
||||
tvbuff_t *
|
||||
wrap_dissect_gssapi_payload(tvbuff_t *header_tvb _U_,
|
||||
tvbuff_t *payload_tvb,
|
||||
tvbuff_t *trailer_tvb _U_,
|
||||
tvbuff_t *auth_tvb,
|
||||
packet_info *pinfo,
|
||||
dcerpc_auth_info *auth_info _U_);
|
||||
|
||||
#endif /* __PACKET_GSSAPI_H */
|
||||
|
|
|
@ -2618,13 +2618,16 @@ dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
|
|||
}
|
||||
|
||||
static tvbuff_t *
|
||||
wrap_dissect_ntlmssp_payload_only(tvbuff_t *tvb, tvbuff_t *auth_tvb _U_,
|
||||
int offset, packet_info *pinfo, dcerpc_auth_info *auth_info _U_)
|
||||
wrap_dissect_ntlmssp_payload_only(tvbuff_t *header_tvb _U_,
|
||||
tvbuff_t *payload_tvb,
|
||||
tvbuff_t *trailer_tvb _U_,
|
||||
tvbuff_t *auth_tvb _U_,
|
||||
packet_info *pinfo,
|
||||
dcerpc_auth_info *auth_info _U_)
|
||||
{
|
||||
tvbuff_t *data_tvb, *decrypted_tvb;
|
||||
tvbuff_t *decrypted_tvb;
|
||||
|
||||
data_tvb = tvb_new_subset_remaining(tvb, offset);
|
||||
dissect_ntlmssp_payload_only(data_tvb, pinfo, NULL, &decrypted_tvb);
|
||||
dissect_ntlmssp_payload_only(payload_tvb, pinfo, NULL, &decrypted_tvb);
|
||||
return decrypted_tvb;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue