In connection-oriented DCE RPC, the authentication data are credentials

only in bind, bind_ack, alter_context, alter_context_response, and auth3
PDUs; they're a verifier of some sort in other PDUs.  The verifier
appears to start with an OID for the real authentication mechanism if
the authentication type is SPNEGO.

svn path=/trunk/; revision=6563
This commit is contained in:
Guy Harris 2002-11-05 21:41:27 +00:00
parent e914e4fa6a
commit 3b71004a61
2 changed files with 108 additions and 53 deletions

View File

@ -2,7 +2,7 @@
* Routines for DCERPC packet disassembly * Routines for DCERPC packet disassembly
* Copyright 2001, Todd Sabin <tas@webspan.net> * Copyright 2001, Todd Sabin <tas@webspan.net>
* *
* $Id: packet-dcerpc.c,v 1.85 2002/11/03 20:34:54 guy Exp $ * $Id: packet-dcerpc.c,v 1.86 2002/11/05 21:41:26 guy Exp $
* *
* Ethereal - Network traffic analyzer * Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com> * By Gerald Combs <gerald@ethereal.com>
@ -404,7 +404,9 @@ static gint ett_dcerpc_fragments = -1;
static gint ett_dcerpc_fragment = -1; static gint ett_dcerpc_fragment = -1;
static gint ett_decrpc_krb5_auth_verf = -1; static gint ett_decrpc_krb5_auth_verf = -1;
static dissector_handle_t ntlmssp_handle, gssapi_handle; static dissector_handle_t ntlmssp_handle;
static dissector_handle_t gssapi_handle;
static dissector_handle_t gssapi_verf_handle;
static const fragment_items dcerpc_frag_items = { static const fragment_items dcerpc_frag_items = {
&ett_dcerpc_fragments, &ett_dcerpc_fragments,
@ -1429,7 +1431,8 @@ dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
static int static int
dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree, dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
e_dce_cn_common_hdr_t *hdr, int *auth_level_p) e_dce_cn_common_hdr_t *hdr, int *auth_level_p,
gboolean are_credentials)
{ {
int offset; int offset;
guint8 auth_pad_len; guint8 auth_pad_len;
@ -1470,13 +1473,17 @@ dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tr
offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep, offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
hf_dcerpc_auth_ctx_id, NULL); hf_dcerpc_auth_ctx_id, NULL);
/* Dissect the authentication data */ /*
* Dissect the authentication data.
switch(auth_type) { */
if (are_credentials) {
/*
* The authentication data are credentials.
*/
switch (auth_type) {
case DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP: {
/* NTLMSSP */ /* NTLMSSP */
case DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP: {
tvbuff_t *ntlmssp_tvb; tvbuff_t *ntlmssp_tvb;
ntlmssp_tvb = tvb_new_subset(tvb, offset, hdr->auth_len, ntlmssp_tvb = tvb_new_subset(tvb, offset, hdr->auth_len,
@ -1486,11 +1493,10 @@ dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tr
dcerpc_tree); dcerpc_tree);
break; break;
} }
case DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO: {
/* SPNEGO (rfc2478) */ /* SPNEGO (rfc2478) */
case DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO: {
tvbuff_t *gssapi_tvb; tvbuff_t *gssapi_tvb;
gssapi_tvb = tvb_new_subset(tvb, offset, hdr->auth_len, gssapi_tvb = tvb_new_subset(tvb, offset, hdr->auth_len,
@ -1499,11 +1505,34 @@ dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tr
call_dissector(gssapi_handle, gssapi_tvb, pinfo, dcerpc_tree); call_dissector(gssapi_handle, gssapi_tvb, pinfo, dcerpc_tree);
break; break;
} }
default: default:
proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len, proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
"Auth Data"); "Auth Credentials");
}
} else {
/*
* The authentication data are a verifier.
*/
switch (auth_type) {
case DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO: {
/* SPNEGO (rfc2478) */
tvbuff_t *gssapi_tvb;
gssapi_tvb = tvb_new_subset(tvb, offset, hdr->auth_len,
hdr->auth_len);
call_dissector(gssapi_verf_handle, gssapi_tvb, pinfo, dcerpc_tree);
break;
}
default:
proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
"Auth Verifier");
}
} }
/* figure out where the auth padding starts */ /* figure out where the auth padding starts */
@ -1700,7 +1729,7 @@ dissect_dcerpc_cn_bind (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tr
* an authentication header, and associate it with an authentication * an authentication header, and associate it with an authentication
* context, so subsequent PDUs can use that context. * context, so subsequent PDUs can use that context.
*/ */
dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, NULL); dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, NULL, TRUE);
} }
static void static void
@ -1788,7 +1817,7 @@ dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerp
* XXX - do we need to do anything with the authentication level * XXX - do we need to do anything with the authentication level
* we get back from this? * we get back from this?
*/ */
dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, NULL); dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, NULL, TRUE);
if (check_col (pinfo->cinfo, COL_INFO)) { if (check_col (pinfo->cinfo, COL_INFO)) {
if (num_results != 0 && result == 0) { if (num_results != 0 && result == 0) {
@ -2030,7 +2059,7 @@ dissect_dcerpc_cn_rqst (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tr
* and we just have a security context? * and we just have a security context?
*/ */
auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr,
&auth_level); &auth_level, FALSE);
conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype, conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
pinfo->srcport, pinfo->destport, 0); pinfo->srcport, pinfo->destport, 0);
@ -2150,7 +2179,7 @@ dissect_dcerpc_cn_resp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tr
* and we just have a security context? * and we just have a security context?
*/ */
auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr,
&auth_level); &auth_level, FALSE);
conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype, conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
pinfo->srcport, pinfo->destport, 0); pinfo->srcport, pinfo->destport, 0);
@ -2262,7 +2291,7 @@ dissect_dcerpc_cn_fault (tvbuff_t *tvb, packet_info *pinfo,
* and we just have a security context? * and we just have a security context?
*/ */
auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr,
&auth_level); &auth_level, FALSE);
conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype, conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
pinfo->srcport, pinfo->destport, 0); pinfo->srcport, pinfo->destport, 0);
@ -2599,6 +2628,13 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
dissect_dcerpc_cn_bind_ack (tvb, pinfo, dcerpc_tree, &hdr); dissect_dcerpc_cn_bind_ack (tvb, pinfo, dcerpc_tree, &hdr);
break; break;
case PDU_AUTH3:
/*
* Nothing after the common header other than credentials.
*/
dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, NULL, TRUE);
break;
case PDU_REQ: case PDU_REQ:
dissect_dcerpc_cn_rqst (tvb, pinfo, dcerpc_tree, tree, &hdr); dissect_dcerpc_cn_rqst (tvb, pinfo, dcerpc_tree, tree, &hdr);
break; break;
@ -2621,7 +2657,7 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
* Nothing after the common header other than an authentication * Nothing after the common header other than an authentication
* verifier. * verifier.
*/ */
dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, NULL); dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, NULL, FALSE);
break; break;
case PDU_SHUTDOWN: case PDU_SHUTDOWN:
@ -2633,7 +2669,7 @@ dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
default: default:
/* might as well dissect the auth info */ /* might as well dissect the auth info */
dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, NULL); dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, NULL, FALSE);
break; break;
} }
return hdr.frag_len + padding; return hdr.frag_len + padding;
@ -3771,4 +3807,5 @@ proto_reg_handoff_dcerpc (void)
heur_dissector_add ("smb_transact", dissect_dcerpc_cn_bs, proto_dcerpc); heur_dissector_add ("smb_transact", dissect_dcerpc_cn_bs, proto_dcerpc);
ntlmssp_handle = find_dissector("ntlmssp"); ntlmssp_handle = find_dissector("ntlmssp");
gssapi_handle = find_dissector("gssapi"); gssapi_handle = find_dissector("gssapi");
gssapi_verf_handle = find_dissector("gssapi_verf");
} }

View File

@ -4,7 +4,7 @@
* Copyright 2002, Richard Sharpe <rsharpe@samba.org> Added a few * Copyright 2002, Richard Sharpe <rsharpe@samba.org> Added a few
* bits and pieces ... * bits and pieces ...
* *
* $Id: packet-gssapi.c,v 1.20 2002/09/29 18:58:56 gerald Exp $ * $Id: packet-gssapi.c,v 1.21 2002/11/05 21:41:27 guy Exp $
* *
* Ethereal - Network traffic analyzer * Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com> * By Gerald Combs <gerald@ethereal.com>
@ -143,7 +143,8 @@ dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
} }
static void static void
dissect_gssapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) dissect_gssapi_work(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
gboolean is_verifier)
{ {
proto_item *item; proto_item *item;
proto_tree *subtree; proto_tree *subtree;
@ -156,6 +157,7 @@ dissect_gssapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
gssapi_oid_value *value; gssapi_oid_value *value;
volatile dissector_handle_t handle = NULL; volatile dissector_handle_t handle = NULL;
conversation_t *volatile conversation; conversation_t *volatile conversation;
tvbuff_t *oid_tvb;
/* /*
* We need this later, so lets get it now ... * We need this later, so lets get it now ...
@ -289,39 +291,42 @@ dissect_gssapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
handle = value->handle; handle = value->handle;
if (handle) { /*
tvbuff_t *oid_tvb; * Here we should create a conversation if needed and
* save the OID and dissector handle in it for the
* GSSAPI protocol.
*/
/* if (!conversation) { /* Create one */
* Here we should create a conversation if needed and conversation = conversation_new(&pinfo->src,
* save the OID and dissector handle in it for the &pinfo->dst,
* GSSAPI protocol. pinfo->ptype,
*/ pinfo->srcport,
pinfo->destport, 0);
if (!conversation) { /* Create one */
conversation = conversation_new(&pinfo->src,
&pinfo->dst,
pinfo->ptype,
pinfo->srcport,
pinfo->destport, 0);
}
/*
* Now add the proto data ...
* but only if it is not already there.
*/
if (!conversation_get_proto_data(conversation,
proto_gssapi)) {
conversation_add_proto_data(conversation,
proto_gssapi, handle);
}
oid_tvb = tvb_new_subset(tvb, offset, -1, -1);
call_dissector(handle, oid_tvb, pinfo, subtree);
} }
else { /* FIXME, do something if handle not found */
/*
* Now add the proto data ...
* but only if it is not already there.
*/
if (!conversation_get_proto_data(conversation,
proto_gssapi)) {
conversation_add_proto_data(conversation,
proto_gssapi, handle);
}
if (is_verifier) {
proto_tree_add_text(subtree, tvb, offset, -1,
"Authentication verifier");
} else {
if (handle != NULL) {
oid_tvb = tvb_new_subset(tvb, offset, -1, -1);
call_dissector(handle, oid_tvb, pinfo, subtree);
} else {
proto_tree_add_text(subtree, tvb, offset, -1,
"Authentication credentials");
}
} }
done: done:
@ -333,6 +338,18 @@ dissect_gssapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
} ENDTRY; } ENDTRY;
} }
static void
dissect_gssapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
dissect_gssapi_work(tvb, pinfo, tree, FALSE);
}
static void
dissect_gssapi_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
dissect_gssapi_work(tvb, pinfo, tree, TRUE);
}
void void
proto_register_gssapi(void) proto_register_gssapi(void)
{ {
@ -354,6 +371,7 @@ proto_register_gssapi(void)
proto_register_subtree_array(ett, array_length(ett)); proto_register_subtree_array(ett, array_length(ett));
register_dissector("gssapi", dissect_gssapi, proto_gssapi); register_dissector("gssapi", dissect_gssapi, proto_gssapi);
register_dissector("gssapi_verf", dissect_gssapi_verf, proto_gssapi);
gssapi_oids = g_hash_table_new(gssapi_oid_hash, gssapi_oid_equal); gssapi_oids = g_hash_table_new(gssapi_oid_hash, gssapi_oid_equal);
} }