2002-08-28 00:19:10 +00:00
|
|
|
/* packet-spnego.c
|
2002-08-27 15:46:17 +00:00
|
|
|
* Routines for the simple and protected GSS-API negotiation mechanism
|
2002-09-08 22:47:43 +00:00
|
|
|
* as described in RFC 2478.
|
2002-08-27 15:46:17 +00:00
|
|
|
* Copyright 2002, Tim Potter <tpot@samba.org>
|
2002-08-28 00:19:10 +00:00
|
|
|
* Copyright 2002, Richard Sharpe <rsharpe@ns.aus.com>
|
2003-05-24 05:05:26 +00:00
|
|
|
* Copyright 2003, Richard Sharpe <rsharpe@richardsharpe.com>
|
2005-06-20 09:43:29 +00:00
|
|
|
* Copyright 2005, Ronnie Sahlberg (krb decryption)
|
2002-08-27 15:46:17 +00:00
|
|
|
*
|
2004-07-18 00:24:25 +00:00
|
|
|
* $Id$
|
2002-08-27 15:46:17 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
|
|
|
* Copyright 1998 Gerald Combs
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
2002-08-27 15:46:17 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
2002-08-27 15:46:17 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
2002-08-27 15:46:17 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
2005-03-08 09:45:19 +00:00
|
|
|
/* The heimdal code for decryption of GSSAPI wrappers using heimdal comes from
|
|
|
|
Heimdal 1.6 and has been modified for ethereal's requirements.
|
|
|
|
*/
|
2002-08-27 15:46:17 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
# include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
|
2005-03-08 09:45:19 +00:00
|
|
|
#include <string.h>
|
2002-08-27 15:46:17 +00:00
|
|
|
#include <glib.h>
|
|
|
|
#include <epan/packet.h>
|
|
|
|
|
2005-02-09 23:38:00 +00:00
|
|
|
#include <epan/asn1.h>
|
2005-06-20 09:43:29 +00:00
|
|
|
#include "packet-ber.h"
|
2005-03-10 10:16:49 +00:00
|
|
|
#include "packet-dcerpc.h"
|
2002-08-27 15:46:17 +00:00
|
|
|
#include "packet-gssapi.h"
|
2002-09-07 00:29:29 +00:00
|
|
|
#include "packet-kerberos.h"
|
2005-03-08 23:47:29 +00:00
|
|
|
#include <epan/crypt-rc4.h>
|
2002-09-08 22:47:43 +00:00
|
|
|
#include <epan/conversation.h>
|
2005-08-19 23:03:56 +00:00
|
|
|
#include <epan/emem.h>
|
2002-08-27 15:46:17 +00:00
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
#define SPNEGO_negTokenInit 0
|
|
|
|
#define SPNEGO_negTokenTarg 1
|
|
|
|
#define SPNEGO_mechTypes 0
|
|
|
|
#define SPNEGO_reqFlags 1
|
|
|
|
#define SPNEGO_mechToken 2
|
|
|
|
#define SPNEGO_mechListMIC 3
|
|
|
|
#define SPNEGO_negResult 0
|
|
|
|
#define SPNEGO_supportedMech 1
|
|
|
|
#define SPNEGO_responseToken 2
|
2002-08-29 19:45:01 +00:00
|
|
|
#define SPNEGO_negResult_accept_completed 0
|
|
|
|
#define SPNEGO_negResult_accept_incomplete 1
|
|
|
|
#define SPNEGO_negResult_accept_reject 2
|
2002-08-28 00:19:10 +00:00
|
|
|
|
2002-08-27 23:21:53 +00:00
|
|
|
static int proto_spnego = -1;
|
2002-09-05 03:49:03 +00:00
|
|
|
static int proto_spnego_krb5 = -1;
|
2002-08-27 15:46:17 +00:00
|
|
|
|
2002-08-27 23:21:53 +00:00
|
|
|
static int hf_spnego = -1;
|
2005-06-20 10:22:03 +00:00
|
|
|
static int hf_spnego_mech = -1;
|
2005-09-11 21:10:20 +00:00
|
|
|
static int hf_spnego_supportedMech = -1;
|
|
|
|
static int hf_spnego_krb5_oid = -1;
|
2005-06-20 10:22:03 +00:00
|
|
|
static int hf_spnego_this_mech = -1;
|
2002-08-28 01:15:23 +00:00
|
|
|
static int hf_spnego_negtokeninit = -1;
|
2002-08-28 21:04:11 +00:00
|
|
|
static int hf_spnego_negtokentarg = -1;
|
2002-08-28 01:15:23 +00:00
|
|
|
static int hf_spnego_mechtype = -1;
|
2002-08-31 17:09:45 +00:00
|
|
|
static int hf_spnego_mechtoken = -1;
|
2002-08-29 22:53:06 +00:00
|
|
|
static int hf_spnego_negtokentarg_negresult = -1;
|
2002-08-31 17:09:45 +00:00
|
|
|
static int hf_spnego_mechlistmic = -1;
|
|
|
|
static int hf_spnego_responsetoken = -1;
|
2002-09-04 06:54:45 +00:00
|
|
|
static int hf_spnego_reqflags = -1;
|
2002-11-28 06:48:42 +00:00
|
|
|
static int hf_spnego_wraptoken = -1;
|
2002-09-05 03:49:03 +00:00
|
|
|
static int hf_spnego_krb5 = -1;
|
2002-09-06 05:41:17 +00:00
|
|
|
static int hf_spnego_krb5_tok_id = -1;
|
2002-11-28 06:48:42 +00:00
|
|
|
static int hf_spnego_krb5_sgn_alg = -1;
|
|
|
|
static int hf_spnego_krb5_seal_alg = -1;
|
|
|
|
static int hf_spnego_krb5_snd_seq = -1;
|
|
|
|
static int hf_spnego_krb5_sgn_cksum = -1;
|
|
|
|
static int hf_spnego_krb5_confounder = -1;
|
2003-05-24 23:26:17 +00:00
|
|
|
static int hf_gssapi_reqflags_deleg = -1;
|
|
|
|
static int hf_gssapi_reqflags_mutual = -1;
|
|
|
|
static int hf_gssapi_reqflags_replay = -1;
|
|
|
|
static int hf_gssapi_reqflags_sequence = -1;
|
|
|
|
static int hf_gssapi_reqflags_anon = -1;
|
|
|
|
static int hf_gssapi_reqflags_conf = -1;
|
|
|
|
static int hf_gssapi_reqflags_integ = -1;
|
2002-08-27 15:46:17 +00:00
|
|
|
|
2002-08-27 23:21:53 +00:00
|
|
|
static gint ett_spnego = -1;
|
2002-08-28 01:15:23 +00:00
|
|
|
static gint ett_spnego_negtokeninit = -1;
|
|
|
|
static gint ett_spnego_negtokentarg = -1;
|
|
|
|
static gint ett_spnego_mechtype = -1;
|
2002-08-31 17:09:45 +00:00
|
|
|
static gint ett_spnego_mechtoken = -1;
|
|
|
|
static gint ett_spnego_mechlistmic = -1;
|
|
|
|
static gint ett_spnego_responsetoken = -1;
|
2002-11-28 06:48:42 +00:00
|
|
|
static gint ett_spnego_wraptoken = -1;
|
2002-09-05 03:49:03 +00:00
|
|
|
static gint ett_spnego_krb5 = -1;
|
2003-05-25 00:59:15 +00:00
|
|
|
static gint ett_spnego_reqflags = -1;
|
2002-08-27 23:21:53 +00:00
|
|
|
|
2002-08-29 22:53:06 +00:00
|
|
|
static const value_string spnego_negResult_vals[] = {
|
|
|
|
{ SPNEGO_negResult_accept_completed, "Accept Completed" },
|
|
|
|
{ SPNEGO_negResult_accept_incomplete, "Accept Incomplete" },
|
|
|
|
{ SPNEGO_negResult_accept_reject, "Accept Reject"},
|
2002-08-30 10:31:13 +00:00
|
|
|
{ 0, NULL}
|
2002-08-29 22:53:06 +00:00
|
|
|
};
|
|
|
|
|
2003-05-24 23:26:17 +00:00
|
|
|
/*
|
|
|
|
* These should be in the GSSAPI dissector ... XXX
|
|
|
|
*/
|
|
|
|
|
|
|
|
static const true_false_string tfs_reqflags_deleg = {
|
|
|
|
"Delegation Requested",
|
|
|
|
"Delegation NOT Requested"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const true_false_string tfs_reqflags_mutual = {
|
|
|
|
"Mutual Authentication Requested",
|
|
|
|
"Mutual Authentication NOT Requested"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const true_false_string tfs_reqflags_replay = {
|
|
|
|
"Replay Detection Requested",
|
|
|
|
"Replay Detection NOT Requested"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const true_false_string tfs_reqflags_sequence = {
|
|
|
|
"Out-of-sequence Detection Requested",
|
|
|
|
"Out-of-sequence Detection NOT Requested"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const true_false_string tfs_reqflags_anon = {
|
|
|
|
"Anonymous Authentication Requested",
|
|
|
|
"Anonymous Authentication NOT Requested"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const true_false_string tfs_reqflags_conf = {
|
|
|
|
"Per-message Confidentiality Requested",
|
|
|
|
"Per-message Confidentiality NOT Requested"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const true_false_string tfs_reqflags_integ = {
|
|
|
|
"Per-message Integrity Requested",
|
|
|
|
"Per-message Integrity NOT Requested"
|
|
|
|
};
|
|
|
|
|
2005-06-20 05:28:56 +00:00
|
|
|
|
2002-08-27 23:21:53 +00:00
|
|
|
/* Display an ASN1 parse error. Taken from packet-snmp.c */
|
|
|
|
|
|
|
|
static dissector_handle_t data_handle;
|
|
|
|
|
2004-05-11 02:02:44 +00:00
|
|
|
static dissector_handle_t
|
|
|
|
gssapi_dissector_handle(gssapi_oid_value *next_level_value) {
|
|
|
|
if (next_level_value == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return next_level_value->handle;
|
|
|
|
}
|
|
|
|
|
2002-08-27 23:21:53 +00:00
|
|
|
static void
|
|
|
|
dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|
|
|
proto_tree *tree, const char *field_name, int ret)
|
|
|
|
{
|
2005-07-24 19:01:28 +00:00
|
|
|
const char *errstr;
|
2002-08-27 23:21:53 +00:00
|
|
|
|
|
|
|
errstr = asn1_err_to_str(ret);
|
|
|
|
|
|
|
|
if (tree != NULL) {
|
|
|
|
proto_tree_add_text(tree, tvb, offset, 0,
|
|
|
|
"ERROR: Couldn't parse %s: %s", field_name, errstr);
|
|
|
|
call_dissector(data_handle,
|
|
|
|
tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
|
|
|
|
}
|
|
|
|
}
|
2002-08-27 15:46:17 +00:00
|
|
|
|
2002-09-05 03:49:03 +00:00
|
|
|
/*
|
|
|
|
* This is the SPNEGO KRB5 dissector. It is not true KRB5, but some ASN.1
|
2002-12-25 20:58:06 +00:00
|
|
|
* wrapped blob with an OID, USHORT token ID, and a Ticket, that is also
|
|
|
|
* ASN.1 wrapped by the looks of it. It conforms to RFC1964.
|
2002-09-05 03:49:03 +00:00
|
|
|
*/
|
|
|
|
|
2002-11-28 06:48:42 +00:00
|
|
|
#define KRB_TOKEN_AP_REQ 0x0001
|
|
|
|
#define KRB_TOKEN_AP_REP 0x0002
|
|
|
|
#define KRB_TOKEN_AP_ERR 0x0003
|
|
|
|
#define KRB_TOKEN_GETMIC 0x0101
|
|
|
|
#define KRB_TOKEN_WRAP 0x0102
|
|
|
|
#define KRB_TOKEN_DELETE_SEC_CONTEXT 0x0201
|
2002-09-06 05:41:17 +00:00
|
|
|
|
|
|
|
static const value_string spnego_krb5_tok_id_vals[] = {
|
2002-11-28 06:48:42 +00:00
|
|
|
{ KRB_TOKEN_AP_REQ, "KRB5_AP_REQ"},
|
|
|
|
{ KRB_TOKEN_AP_REP, "KRB5_AP_REP"},
|
|
|
|
{ KRB_TOKEN_AP_ERR, "KRB5_ERROR"},
|
|
|
|
{ KRB_TOKEN_GETMIC, "KRB5_GSS_GetMIC" },
|
|
|
|
{ KRB_TOKEN_WRAP, "KRB5_GSS_Wrap" },
|
|
|
|
{ KRB_TOKEN_DELETE_SEC_CONTEXT, "KRB5_GSS_Delete_sec_context" },
|
2002-09-06 05:41:17 +00:00
|
|
|
{ 0, NULL}
|
|
|
|
};
|
|
|
|
|
2002-11-28 06:48:42 +00:00
|
|
|
#define KRB_SGN_ALG_DES_MAC_MD5 0x0000
|
|
|
|
#define KRB_SGN_ALG_MD2_5 0x0001
|
|
|
|
#define KRB_SGN_ALG_DES_MAC 0x0002
|
|
|
|
#define KRB_SGN_ALG_HMAC 0x0011
|
|
|
|
|
|
|
|
static const value_string spnego_krb5_sgn_alg_vals[] = {
|
|
|
|
{ KRB_SGN_ALG_DES_MAC_MD5, "DES MAC MD5"},
|
|
|
|
{ KRB_SGN_ALG_MD2_5, "MD2.5"},
|
|
|
|
{ KRB_SGN_ALG_DES_MAC, "DES MAC"},
|
|
|
|
{ KRB_SGN_ALG_HMAC, "HMAC"},
|
|
|
|
{ 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
#define KRB_SEAL_ALG_DES_CBC 0x0000
|
|
|
|
#define KRB_SEAL_ALG_RC4 0x0010
|
|
|
|
#define KRB_SEAL_ALG_NONE 0xffff
|
|
|
|
|
|
|
|
static const value_string spnego_krb5_seal_alg_vals[] = {
|
|
|
|
{ KRB_SEAL_ALG_DES_CBC, "DES CBC"},
|
|
|
|
{ KRB_SEAL_ALG_RC4, "RC4"},
|
|
|
|
{ KRB_SEAL_ALG_NONE, "None"},
|
|
|
|
{ 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX - is this for SPNEGO or just GSS-API?
|
|
|
|
* RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
|
|
|
|
* can directly designate Kerberos V5 as a mechanism in GSS-API, rather
|
|
|
|
* than designating SPNEGO as the mechanism, offering Kerberos V5, and
|
|
|
|
* getting it accepted.
|
|
|
|
*/
|
2003-05-23 18:34:58 +00:00
|
|
|
static int
|
|
|
|
dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
|
2003-05-24 05:05:26 +00:00
|
|
|
static int
|
2005-03-06 22:52:58 +00:00
|
|
|
dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint16 token_id);
|
2003-05-26 20:44:20 +00:00
|
|
|
|
2002-09-05 03:49:03 +00:00
|
|
|
static void
|
2002-11-28 06:48:42 +00:00
|
|
|
dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
2002-09-05 03:49:03 +00:00
|
|
|
{
|
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
|
|
|
int ret, offset = 0;
|
|
|
|
ASN1_SCK hnd;
|
|
|
|
gboolean def;
|
2005-09-11 21:10:20 +00:00
|
|
|
guint len1, cls, con, tag;
|
2003-05-26 20:44:20 +00:00
|
|
|
guint16 token_id;
|
2005-09-11 21:10:20 +00:00
|
|
|
gchar oid[MAX_OID_STR_LEN];
|
2002-09-05 03:49:03 +00:00
|
|
|
gssapi_oid_value *value;
|
2002-09-07 03:32:49 +00:00
|
|
|
tvbuff_t *krb5_tvb;
|
2002-09-05 03:49:03 +00:00
|
|
|
|
|
|
|
item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, offset,
|
2002-09-08 22:47:43 +00:00
|
|
|
-1, FALSE);
|
2002-09-05 03:49:03 +00:00
|
|
|
|
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego_krb5);
|
|
|
|
|
|
|
|
/*
|
2002-09-08 02:45:26 +00:00
|
|
|
* The KRB5 blob conforms to RFC1964:
|
2002-10-25 04:22:26 +00:00
|
|
|
* [APPLICATION 0] {
|
2002-09-05 03:49:03 +00:00
|
|
|
* OID,
|
2002-12-25 20:58:06 +00:00
|
|
|
* USHORT (0x0001 == AP-REQ, 0x0002 == AP-REP, 0x0003 == ERROR),
|
2002-09-05 03:49:03 +00:00
|
|
|
* OCTET STRING }
|
2002-10-05 06:26:42 +00:00
|
|
|
*
|
2002-12-25 20:58:06 +00:00
|
|
|
* However, for some protocols, the KRB5 blob starts at the SHORT
|
2002-10-05 06:26:42 +00:00
|
|
|
* and has no DER encoded header etc.
|
2002-10-25 04:22:26 +00:00
|
|
|
*
|
|
|
|
* It appears that for some other protocols the KRB5 blob is just
|
|
|
|
* a Kerberos message, with no [APPLICATION 0] header, no OID,
|
|
|
|
* and no USHORT.
|
|
|
|
*
|
|
|
|
* So:
|
|
|
|
*
|
|
|
|
* If we see an [APPLICATION 0] HEADER, we show the OID and
|
|
|
|
* the USHORT, and then dissect the rest as a Kerberos message.
|
|
|
|
*
|
|
|
|
* If we see an [APPLICATION 14] or [APPLICATION 15] header,
|
|
|
|
* we assume it's an AP-REQ or AP-REP message, and dissect
|
|
|
|
* it all as a Kerberos message.
|
|
|
|
*
|
|
|
|
* Otherwise, we show the USHORT, and then dissect the rest
|
|
|
|
* as a Kerberos message.
|
2002-09-05 03:49:03 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
asn1_open(&hnd, tvb, offset);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the first header ...
|
|
|
|
*/
|
|
|
|
|
|
|
|
ret = asn1_header_decode(&hnd, &cls, &con, &tag, &def, &len1);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, subtree,
|
|
|
|
"SPNEGO KRB5 Header", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2002-10-25 04:22:26 +00:00
|
|
|
if (cls == ASN1_APL && con == ASN1_CON) {
|
|
|
|
/*
|
|
|
|
* [APPLICATION <tag>]
|
|
|
|
*/
|
|
|
|
switch (tag) {
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
/*
|
|
|
|
* [APPLICATION 0]
|
|
|
|
*/
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-25 04:22:26 +00:00
|
|
|
offset = hnd.offset;
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-25 04:22:26 +00:00
|
|
|
/* Next, the OID */
|
2005-09-11 21:10:20 +00:00
|
|
|
offset=dissect_ber_object_identifier(FALSE, pinfo, subtree, tvb, offset, hf_spnego_krb5_oid, oid);
|
|
|
|
hnd.offset = offset;
|
2002-09-05 03:49:03 +00:00
|
|
|
|
|
|
|
|
2005-09-11 21:10:20 +00:00
|
|
|
value = gssapi_lookup_oid_str(oid);
|
2002-10-25 04:22:26 +00:00
|
|
|
|
2003-05-23 17:46:06 +00:00
|
|
|
token_id = tvb_get_letohs(tvb, offset);
|
2003-05-26 20:44:20 +00:00
|
|
|
proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
|
|
|
|
token_id);
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-25 04:22:26 +00:00
|
|
|
hnd.offset += 2;
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-25 04:22:26 +00:00
|
|
|
offset += 2;
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-25 04:22:26 +00:00
|
|
|
break;
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-25 04:22:26 +00:00
|
|
|
case 14: /* [APPLICATION 14] */
|
|
|
|
case 15: /* [APPLICATION 15] */
|
2003-05-26 20:44:20 +00:00
|
|
|
/*
|
|
|
|
* No token ID - just dissect as a Kerberos message and
|
|
|
|
* return.
|
|
|
|
*/
|
|
|
|
krb5_tvb = tvb_new_subset(tvb, offset, -1, -1);
|
2004-06-04 01:56:25 +00:00
|
|
|
offset = dissect_kerberos_main(krb5_tvb, pinfo, subtree, FALSE, NULL);
|
2003-05-26 20:44:20 +00:00
|
|
|
return;
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-25 04:22:26 +00:00
|
|
|
default:
|
|
|
|
proto_tree_add_text(subtree, tvb, offset, 0,
|
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d)",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Next, the token ID ... */
|
|
|
|
|
2003-05-23 17:46:06 +00:00
|
|
|
token_id = tvb_get_letohs(tvb, offset);
|
2003-05-26 20:44:20 +00:00
|
|
|
proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
|
|
|
|
token_id);
|
2002-10-25 04:22:26 +00:00
|
|
|
|
|
|
|
hnd.offset += 2;
|
|
|
|
|
|
|
|
offset += 2;
|
|
|
|
}
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2003-05-23 17:46:06 +00:00
|
|
|
switch (token_id) {
|
2002-09-07 03:32:49 +00:00
|
|
|
|
2003-05-23 17:46:06 +00:00
|
|
|
case KRB_TOKEN_AP_REQ:
|
|
|
|
case KRB_TOKEN_AP_REP:
|
|
|
|
case KRB_TOKEN_AP_ERR:
|
|
|
|
krb5_tvb = tvb_new_subset(tvb, offset, -1, -1);
|
2004-06-04 01:56:25 +00:00
|
|
|
offset = dissect_kerberos_main(krb5_tvb, pinfo, subtree, FALSE, NULL);
|
2003-05-23 17:46:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case KRB_TOKEN_GETMIC:
|
2003-05-23 18:34:58 +00:00
|
|
|
offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
|
2003-05-23 17:46:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case KRB_TOKEN_WRAP:
|
2005-03-06 22:52:58 +00:00
|
|
|
offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
|
2003-05-23 17:46:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case KRB_TOKEN_DELETE_SEC_CONTEXT:
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2002-09-05 03:49:03 +00:00
|
|
|
|
|
|
|
done:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-03-08 09:45:19 +00:00
|
|
|
#ifdef HAVE_KERBEROS
|
2005-03-09 11:59:40 +00:00
|
|
|
#include <epan/crypt-md5.h>
|
2005-03-08 09:45:19 +00:00
|
|
|
|
2005-03-21 10:07:55 +00:00
|
|
|
#ifndef KEYTYPE_ARCFOUR_56
|
2005-03-20 19:29:22 +00:00
|
|
|
# define KEYTYPE_ARCFOUR_56 24
|
|
|
|
#endif
|
2005-03-09 19:43:29 +00:00
|
|
|
/* XXX - We should probably do a configure-time check for this instead */
|
2005-03-21 10:07:55 +00:00
|
|
|
#ifndef KRB5_KU_USAGE_SEAL
|
2005-03-09 19:43:29 +00:00
|
|
|
# define KRB5_KU_USAGE_SEAL 22
|
|
|
|
#endif
|
|
|
|
|
2005-03-09 11:59:40 +00:00
|
|
|
static int
|
|
|
|
arcfour_mic_key(void *key_data, size_t key_size, int key_type,
|
2005-03-08 09:45:19 +00:00
|
|
|
void *cksum_data, size_t cksum_size,
|
2005-03-09 11:59:40 +00:00
|
|
|
void *key6_data)
|
2005-03-08 09:45:19 +00:00
|
|
|
{
|
2005-07-09 03:25:25 +00:00
|
|
|
guint8 k5_data[16];
|
|
|
|
guint8 T[4];
|
2005-03-08 09:45:19 +00:00
|
|
|
|
|
|
|
memset(T, 0, 4);
|
|
|
|
|
2005-03-09 11:59:40 +00:00
|
|
|
if (key_type == KEYTYPE_ARCFOUR_56) {
|
2005-07-09 03:25:25 +00:00
|
|
|
guint8 L40[14] = "fortybits";
|
2005-03-08 09:45:19 +00:00
|
|
|
|
|
|
|
memcpy(L40 + 10, T, sizeof(T));
|
2005-03-09 11:59:40 +00:00
|
|
|
md5_hmac(
|
|
|
|
L40, 14,
|
|
|
|
key_data,
|
|
|
|
key_size,
|
|
|
|
k5_data);
|
2005-03-08 09:45:19 +00:00
|
|
|
memset(&k5_data[7], 0xAB, 9);
|
|
|
|
} else {
|
2005-03-09 11:59:40 +00:00
|
|
|
md5_hmac(
|
|
|
|
T, 4,
|
|
|
|
key_data,
|
|
|
|
key_size,
|
|
|
|
k5_data);
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
|
|
|
|
2005-03-09 11:59:40 +00:00
|
|
|
md5_hmac(
|
|
|
|
cksum_data, cksum_size,
|
|
|
|
k5_data,
|
|
|
|
16,
|
|
|
|
key6_data);
|
2005-03-08 09:45:19 +00:00
|
|
|
|
2005-03-09 11:59:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2005-03-08 09:45:19 +00:00
|
|
|
|
2005-03-09 11:59:40 +00:00
|
|
|
static int
|
|
|
|
usage2arcfour(int usage)
|
|
|
|
{
|
|
|
|
switch (usage) {
|
|
|
|
case 3: /*KRB5_KU_AS_REP_ENC_PART 3 */
|
|
|
|
case 9: /*KRB5_KU_TGS_REP_ENC_PART_SUB_KEY 9 */
|
|
|
|
return 8;
|
|
|
|
case 22: /*KRB5_KU_USAGE_SEAL 22 */
|
|
|
|
return 13;
|
|
|
|
case 23: /*KRB5_KU_USAGE_SIGN 23 */
|
|
|
|
return 15;
|
|
|
|
case 24: /*KRB5_KU_USAGE_SEQ 24 */
|
|
|
|
return 0;
|
|
|
|
default :
|
|
|
|
return 0;
|
|
|
|
}
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
|
|
|
|
2005-03-09 11:59:40 +00:00
|
|
|
static int
|
2005-07-09 03:25:25 +00:00
|
|
|
arcfour_mic_cksum(guint8 *key_data, int key_length,
|
2005-03-09 11:59:40 +00:00
|
|
|
unsigned usage,
|
|
|
|
u_char sgn_cksum[8],
|
2005-07-09 03:25:25 +00:00
|
|
|
const void *v1, size_t l1,
|
2005-03-08 09:45:19 +00:00
|
|
|
const void *v2, size_t l2,
|
|
|
|
const void *v3, size_t l3)
|
|
|
|
{
|
2005-07-09 03:25:25 +00:00
|
|
|
const guint8 signature[] = "signaturekey";
|
|
|
|
guint8 ksign_c[16];
|
2005-03-09 11:59:40 +00:00
|
|
|
unsigned char t[4];
|
|
|
|
md5_state_t ms;
|
|
|
|
unsigned char digest[16];
|
|
|
|
int rc4_usage;
|
2005-07-09 03:25:25 +00:00
|
|
|
guint8 cksum[16];
|
2005-03-08 09:45:19 +00:00
|
|
|
|
2005-03-09 11:59:40 +00:00
|
|
|
rc4_usage=usage2arcfour(usage);
|
|
|
|
md5_hmac(signature, sizeof(signature),
|
|
|
|
key_data, key_length,
|
|
|
|
ksign_c);
|
|
|
|
md5_init(&ms);
|
|
|
|
t[0] = (rc4_usage >> 0) & 0xFF;
|
|
|
|
t[1] = (rc4_usage >> 8) & 0xFF;
|
|
|
|
t[2] = (rc4_usage >> 16) & 0xFF;
|
|
|
|
t[3] = (rc4_usage >> 24) & 0xFF;
|
|
|
|
md5_append(&ms, t, 4);
|
|
|
|
md5_append(&ms, v1, l1);
|
|
|
|
md5_append(&ms, v2, l2);
|
|
|
|
md5_append(&ms, v3, l3);
|
|
|
|
md5_finish(&ms, digest);
|
|
|
|
md5_hmac(digest, 16, ksign_c, 16, cksum);
|
|
|
|
|
|
|
|
memcpy(sgn_cksum, cksum, 8);
|
2005-03-08 09:45:19 +00:00
|
|
|
|
2005-03-08 21:13:14 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Verify padding of a gss wrapped message and return its length.
|
|
|
|
*/
|
2005-03-09 11:59:40 +00:00
|
|
|
static int
|
|
|
|
gssapi_verify_pad(unsigned char *wrapped_data, int wrapped_length,
|
2005-03-08 21:13:14 +00:00
|
|
|
size_t datalen,
|
|
|
|
size_t *padlen)
|
|
|
|
{
|
2005-03-09 11:59:40 +00:00
|
|
|
unsigned char *pad;
|
2005-03-08 21:13:14 +00:00
|
|
|
size_t padlength;
|
|
|
|
int i;
|
|
|
|
|
2005-03-09 11:59:40 +00:00
|
|
|
pad = wrapped_data + wrapped_length - 1;
|
2005-03-08 21:13:14 +00:00
|
|
|
padlength = *pad;
|
|
|
|
|
|
|
|
if (padlength > datalen)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
for (i = padlength; i > 0 && *pad == padlength; i--, pad--)
|
|
|
|
;
|
|
|
|
if (i != 0)
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
*padlen = padlength;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-03-08 09:45:19 +00:00
|
|
|
static int
|
2005-03-09 11:59:40 +00:00
|
|
|
decrypt_arcfour(packet_info *pinfo,
|
2005-07-09 03:25:25 +00:00
|
|
|
guint8 *input_message_buffer,
|
|
|
|
guint8 *output_message_buffer,
|
|
|
|
guint8 *key_value, int key_size, int key_type)
|
2005-03-08 09:45:19 +00:00
|
|
|
{
|
2005-07-09 03:25:25 +00:00
|
|
|
guint8 Klocaldata[16];
|
2005-03-09 11:59:40 +00:00
|
|
|
int ret;
|
2005-07-09 03:25:25 +00:00
|
|
|
gint32 seq_number;
|
2005-03-08 09:45:19 +00:00
|
|
|
size_t datalen;
|
2005-07-09 03:25:25 +00:00
|
|
|
guint8 k6_data[16], SND_SEQ[8], Confounder[8];
|
|
|
|
guint8 cksum_data[8];
|
2005-03-08 09:45:19 +00:00
|
|
|
int cmp;
|
|
|
|
int conf_flag;
|
2005-03-11 09:31:11 +00:00
|
|
|
size_t padlen = 0;
|
2005-03-08 09:45:19 +00:00
|
|
|
|
2005-03-09 11:59:40 +00:00
|
|
|
datalen = tvb_length(pinfo->gssapi_encrypted_tvb);
|
2005-03-08 09:45:19 +00:00
|
|
|
|
|
|
|
if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0x1000){
|
|
|
|
conf_flag=1;
|
|
|
|
} else if (tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0xffff){
|
|
|
|
conf_flag=0;
|
|
|
|
} else {
|
2005-03-11 09:31:11 +00:00
|
|
|
return -3;
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 6)!=0xffff){
|
2005-03-11 09:31:11 +00:00
|
|
|
return -4;
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
|
|
|
|
2005-03-09 11:59:40 +00:00
|
|
|
ret = arcfour_mic_key(key_value, key_size, key_type,
|
2005-03-08 09:45:19 +00:00
|
|
|
(void *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
|
|
|
|
8, /* SGN_CKSUM */
|
2005-03-09 11:59:40 +00:00
|
|
|
k6_data);
|
2005-03-08 09:45:19 +00:00
|
|
|
if (ret) {
|
2005-03-11 09:31:11 +00:00
|
|
|
return -5;
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2005-03-08 23:47:29 +00:00
|
|
|
rc4_state_struct rc4_state;
|
2005-03-08 09:45:19 +00:00
|
|
|
|
2005-03-08 23:47:29 +00:00
|
|
|
crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
|
|
|
|
memcpy(SND_SEQ, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 8, 8), 8);
|
|
|
|
crypt_rc4(&rc4_state, SND_SEQ, 8);
|
|
|
|
|
2005-03-08 09:45:19 +00:00
|
|
|
memset(k6_data, 0, sizeof(k6_data));
|
|
|
|
}
|
|
|
|
|
2005-03-09 11:59:40 +00:00
|
|
|
seq_number=g_ntohl(*((guint32 *)SND_SEQ));
|
2005-03-08 09:45:19 +00:00
|
|
|
|
|
|
|
cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4);
|
|
|
|
if(cmp){
|
|
|
|
cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmp != 0) {
|
2005-03-11 09:31:11 +00:00
|
|
|
return -6;
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 16; i++)
|
2005-03-09 11:59:40 +00:00
|
|
|
Klocaldata[i] = ((u_char *)key_value)[i] ^ 0xF0;
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
2005-03-09 11:59:40 +00:00
|
|
|
ret = arcfour_mic_key(Klocaldata,sizeof(Klocaldata),key_type,
|
2005-03-08 09:45:19 +00:00
|
|
|
SND_SEQ, 4,
|
2005-03-09 11:59:40 +00:00
|
|
|
k6_data);
|
2005-03-08 09:45:19 +00:00
|
|
|
memset(Klocaldata, 0, sizeof(Klocaldata));
|
|
|
|
if (ret) {
|
2005-03-11 09:31:11 +00:00
|
|
|
return -7;
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(conf_flag) {
|
2005-03-08 23:47:29 +00:00
|
|
|
rc4_state_struct rc4_state;
|
|
|
|
|
|
|
|
crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
|
|
|
|
memcpy(Confounder, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8), 8);
|
|
|
|
crypt_rc4(&rc4_state, Confounder, 8);
|
2005-03-09 11:59:40 +00:00
|
|
|
memcpy(output_message_buffer, input_message_buffer, datalen);
|
|
|
|
crypt_rc4(&rc4_state, output_message_buffer, datalen);
|
2005-03-08 09:45:19 +00:00
|
|
|
} else {
|
|
|
|
memcpy(Confounder,
|
|
|
|
tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8),
|
|
|
|
8); /* Confounder */
|
2005-03-09 11:59:40 +00:00
|
|
|
memcpy(output_message_buffer,
|
|
|
|
input_message_buffer,
|
2005-03-08 09:45:19 +00:00
|
|
|
datalen);
|
|
|
|
}
|
|
|
|
memset(k6_data, 0, sizeof(k6_data));
|
|
|
|
|
2005-03-10 10:16:49 +00:00
|
|
|
/* only normal (i.e. non DCE style wrapping use padding ? */
|
|
|
|
if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
|
|
|
|
ret = gssapi_verify_pad(output_message_buffer,datalen,datalen, &padlen);
|
|
|
|
if (ret) {
|
2005-03-11 09:31:11 +00:00
|
|
|
return -9;
|
2005-03-10 10:16:49 +00:00
|
|
|
}
|
2005-03-11 09:31:11 +00:00
|
|
|
datalen -= padlen;
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
|
|
|
|
2005-03-10 10:16:49 +00:00
|
|
|
/* dont know what the checksum looks like for dce style gssapi */
|
|
|
|
if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
|
|
|
|
ret = arcfour_mic_cksum(key_value, key_size,
|
2005-03-09 11:59:40 +00:00
|
|
|
KRB5_KU_USAGE_SEAL,
|
|
|
|
cksum_data,
|
2005-03-08 09:45:19 +00:00
|
|
|
tvb_get_ptr(pinfo->gssapi_wrap_tvb, 0, 8), 8,
|
|
|
|
Confounder, sizeof(Confounder),
|
2005-03-09 11:59:40 +00:00
|
|
|
output_message_buffer,
|
|
|
|
datalen + padlen);
|
2005-03-10 10:16:49 +00:00
|
|
|
if (ret) {
|
2005-03-11 09:31:11 +00:00
|
|
|
return -10;
|
2005-03-10 10:16:49 +00:00
|
|
|
}
|
2005-03-08 09:45:19 +00:00
|
|
|
|
2005-03-10 10:16:49 +00:00
|
|
|
cmp = memcmp(cksum_data,
|
|
|
|
tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
|
|
|
|
8); /* SGN_CKSUM */
|
|
|
|
if (cmp) {
|
2005-03-11 09:31:11 +00:00
|
|
|
return -11;
|
2005-03-10 10:16:49 +00:00
|
|
|
}
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
|
|
|
|
2005-03-11 09:31:11 +00:00
|
|
|
return datalen;
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
|
|
|
|
2005-03-10 10:16:49 +00:00
|
|
|
|
|
|
|
|
2005-03-21 10:52:57 +00:00
|
|
|
#if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
|
2005-03-09 11:59:40 +00:00
|
|
|
|
2005-03-08 09:45:19 +00:00
|
|
|
static void
|
2005-03-21 10:07:55 +00:00
|
|
|
decrypt_gssapi_krb_arcfour_wrap(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int keytype)
|
2005-03-08 09:45:19 +00:00
|
|
|
{
|
2005-03-09 11:59:40 +00:00
|
|
|
int ret;
|
2005-03-08 09:45:19 +00:00
|
|
|
enc_key_t *ek;
|
|
|
|
int length;
|
|
|
|
const guint8 *original_data;
|
|
|
|
|
|
|
|
static int omb_index=0;
|
2005-03-09 11:59:40 +00:00
|
|
|
static guint8 *omb_arr[4]={NULL,NULL,NULL,NULL};
|
2005-03-08 09:45:19 +00:00
|
|
|
static guint8 *cryptocopy=NULL; /* workaround for pre-0.6.1 heimdal bug */
|
2005-03-09 11:59:40 +00:00
|
|
|
guint8 *output_message_buffer;
|
|
|
|
|
2005-03-08 09:45:19 +00:00
|
|
|
omb_index++;
|
|
|
|
if(omb_index>=4){
|
|
|
|
omb_index=0;
|
|
|
|
}
|
2005-03-09 11:59:40 +00:00
|
|
|
output_message_buffer=omb_arr[omb_index];
|
|
|
|
|
2005-03-08 09:45:19 +00:00
|
|
|
|
|
|
|
length=tvb_length(pinfo->gssapi_encrypted_tvb);
|
|
|
|
original_data=tvb_get_ptr(pinfo->gssapi_encrypted_tvb, 0, length);
|
|
|
|
|
|
|
|
/* dont do anything if we are not attempting to decrypt data */
|
|
|
|
/*
|
|
|
|
if(!krb_decrypt){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
/* XXX we should only do this for first time, then store somewhere */
|
|
|
|
/* XXX We also need to re-read the keytab when the preference changes */
|
|
|
|
|
2005-08-19 23:03:56 +00:00
|
|
|
cryptocopy=ep_alloc(length);
|
2005-03-09 11:59:40 +00:00
|
|
|
if(output_message_buffer){
|
|
|
|
g_free(output_message_buffer);
|
|
|
|
output_message_buffer=NULL;
|
|
|
|
}
|
|
|
|
output_message_buffer=g_malloc(length);
|
2005-03-08 09:45:19 +00:00
|
|
|
|
|
|
|
for(ek=enc_key_list;ek;ek=ek->next){
|
|
|
|
/* shortcircuit and bail out if enctypes are not matching */
|
2005-03-21 10:07:55 +00:00
|
|
|
if(ek->keytype!=keytype){
|
2005-03-08 09:45:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* pre-0.6.1 versions of Heimdal would sometimes change
|
|
|
|
the cryptotext data even when the decryption failed.
|
|
|
|
This would obviously not work since we iterate over the
|
|
|
|
keys. So just give it a copy of the crypto data instead.
|
|
|
|
This has been seen for RC4-HMAC blobs.
|
|
|
|
*/
|
|
|
|
memcpy(cryptocopy, original_data, length);
|
2005-03-09 11:59:40 +00:00
|
|
|
ret=decrypt_arcfour(pinfo,
|
|
|
|
cryptocopy,
|
|
|
|
output_message_buffer,
|
2005-03-21 10:07:55 +00:00
|
|
|
ek->keyvalue,
|
|
|
|
ek->keylength,
|
|
|
|
ek->keytype
|
2005-03-09 11:59:40 +00:00
|
|
|
);
|
2005-03-11 09:31:11 +00:00
|
|
|
if (ret >= 0) {
|
2005-03-08 09:45:19 +00:00
|
|
|
proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
|
|
|
|
pinfo->gssapi_decrypted_tvb=tvb_new_real_data(
|
2005-03-09 11:59:40 +00:00
|
|
|
output_message_buffer,
|
2005-03-11 09:31:11 +00:00
|
|
|
ret, ret);
|
2005-03-08 09:45:19 +00:00
|
|
|
tvb_set_child_real_data_tvbuff(tvb, pinfo->gssapi_decrypted_tvb);
|
|
|
|
add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2005-03-21 10:52:57 +00:00
|
|
|
#endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
|
2005-03-08 09:45:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2003-05-23 18:34:58 +00:00
|
|
|
/*
|
2003-05-24 05:05:26 +00:00
|
|
|
* XXX - This is for GSSAPI Wrap tokens ...
|
2003-05-23 18:34:58 +00:00
|
|
|
*/
|
|
|
|
static int
|
2005-03-09 03:03:10 +00:00
|
|
|
dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
|
|
|
|
#ifndef HAVE_KERBEROS
|
|
|
|
_U_
|
|
|
|
#endif
|
|
|
|
, proto_tree *tree, guint16 token_id
|
|
|
|
#ifndef HAVE_KERBEROS
|
|
|
|
_U_
|
|
|
|
#endif
|
|
|
|
)
|
2003-05-23 18:34:58 +00:00
|
|
|
{
|
2005-03-08 09:45:19 +00:00
|
|
|
guint16 sgn_alg, seal_alg;
|
2005-03-09 03:03:10 +00:00
|
|
|
#ifdef HAVE_KERBEROS
|
2005-03-08 09:45:19 +00:00
|
|
|
int start_offset=offset;
|
2005-03-09 03:03:10 +00:00
|
|
|
#endif
|
2003-05-23 18:34:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The KRB5 blob conforms to RFC1964:
|
2003-05-24 05:05:26 +00:00
|
|
|
* USHORT (0x0102 == GSS_Wrap)
|
2003-05-23 18:34:58 +00:00
|
|
|
* and so on }
|
|
|
|
*/
|
|
|
|
|
2003-05-24 05:05:26 +00:00
|
|
|
/* Now, the sign and seal algorithms ... */
|
2003-05-23 18:34:58 +00:00
|
|
|
|
|
|
|
sgn_alg = tvb_get_letohs(tvb, offset);
|
|
|
|
proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
|
|
|
|
sgn_alg);
|
|
|
|
|
|
|
|
offset += 2;
|
|
|
|
|
2005-03-08 09:45:19 +00:00
|
|
|
seal_alg = tvb_get_letohs(tvb, offset);
|
2005-03-16 21:59:25 +00:00
|
|
|
proto_tree_add_uint(tree, hf_spnego_krb5_seal_alg, tvb, offset, 2,
|
|
|
|
seal_alg);
|
2003-05-24 05:05:26 +00:00
|
|
|
|
|
|
|
offset += 2;
|
|
|
|
|
2003-05-23 18:34:58 +00:00
|
|
|
/* Skip the filler */
|
|
|
|
|
2003-05-24 05:05:26 +00:00
|
|
|
offset += 2;
|
2003-05-23 18:34:58 +00:00
|
|
|
|
|
|
|
/* Encrypted sequence number */
|
|
|
|
|
|
|
|
proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
|
|
|
|
TRUE);
|
|
|
|
|
|
|
|
offset += 8;
|
|
|
|
|
|
|
|
/* Checksum of plaintext padded data */
|
|
|
|
|
|
|
|
proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
|
|
|
|
TRUE);
|
|
|
|
|
|
|
|
offset += 8;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* At least according to draft-brezak-win2k-krb-rc4-hmac-04,
|
|
|
|
* if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
|
|
|
|
* extra 8 bytes of "Random confounder" after the checksum.
|
|
|
|
* It certainly confounds code expecting all Kerberos 5
|
|
|
|
* GSS_Wrap() tokens to look the same....
|
|
|
|
*/
|
|
|
|
if (sgn_alg == KRB_SGN_ALG_HMAC) {
|
|
|
|
proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
|
|
|
|
TRUE);
|
|
|
|
offset += 8;
|
|
|
|
}
|
|
|
|
|
2005-03-16 21:59:25 +00:00
|
|
|
/* Is the data encrypted? */
|
|
|
|
pinfo->gssapi_data_encrypted=(seal_alg!=KRB_SEAL_ALG_NONE);
|
|
|
|
|
2005-03-08 09:45:19 +00:00
|
|
|
#ifdef HAVE_KERBEROS
|
2005-03-09 19:43:29 +00:00
|
|
|
#define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
|
2005-03-08 09:45:19 +00:00
|
|
|
if(pinfo->decrypt_gssapi_tvb){
|
|
|
|
/* if the caller did not provide a tvb, then we just use
|
|
|
|
whatever is left of our current tvb.
|
|
|
|
*/
|
|
|
|
if(!pinfo->gssapi_encrypted_tvb){
|
|
|
|
int len;
|
|
|
|
len=tvb_reported_length_remaining(tvb,offset);
|
|
|
|
if(len>tvb_length_remaining(tvb, offset)){
|
|
|
|
/* no point in trying to decrypt,
|
|
|
|
we dont have the full pdu.
|
|
|
|
*/
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
pinfo->gssapi_encrypted_tvb = tvb_new_subset(
|
|
|
|
tvb, offset, len, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if this is KRB5 wrapped rc4-hmac */
|
|
|
|
if((token_id==KRB_TOKEN_WRAP)
|
|
|
|
&&(sgn_alg==KRB_SGN_ALG_HMAC)
|
|
|
|
&&(seal_alg==KRB_SEAL_ALG_RC4)){
|
|
|
|
/* do we need to create a tvb for the wrapper
|
|
|
|
as well ?
|
|
|
|
*/
|
|
|
|
if(!pinfo->gssapi_wrap_tvb){
|
|
|
|
pinfo->gssapi_wrap_tvb = tvb_new_subset(
|
|
|
|
tvb, start_offset-2,
|
|
|
|
GSS_ARCFOUR_WRAP_TOKEN_SIZE,
|
|
|
|
GSS_ARCFOUR_WRAP_TOKEN_SIZE);
|
|
|
|
}
|
2005-03-21 10:52:57 +00:00
|
|
|
#if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
|
2005-03-21 10:07:55 +00:00
|
|
|
decrypt_gssapi_krb_arcfour_wrap(tree,
|
2005-03-08 09:45:19 +00:00
|
|
|
pinfo,
|
|
|
|
tvb,
|
|
|
|
23 /* rc4-hmac */);
|
2005-03-21 10:52:57 +00:00
|
|
|
#endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
|
2005-03-08 09:45:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2003-05-23 18:34:58 +00:00
|
|
|
/*
|
|
|
|
* Return the offset past the checksum, so that we know where
|
|
|
|
* the data we're wrapped around starts. Also, set the length
|
|
|
|
* of our top-level item to that offset, so it doesn't cover
|
|
|
|
* the data we're wrapped around.
|
2005-03-06 22:52:58 +00:00
|
|
|
*
|
|
|
|
* Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
|
|
|
|
* not before.
|
2003-05-23 18:34:58 +00:00
|
|
|
*/
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2002-11-28 06:48:42 +00:00
|
|
|
/*
|
2003-05-24 05:05:26 +00:00
|
|
|
* XXX - This is for GSSAPI GetMIC tokens ...
|
2002-11-28 06:48:42 +00:00
|
|
|
*/
|
|
|
|
static int
|
2003-05-24 05:05:26 +00:00
|
|
|
dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
|
2002-11-28 06:48:42 +00:00
|
|
|
{
|
|
|
|
guint16 sgn_alg;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The KRB5 blob conforms to RFC1964:
|
2003-05-24 05:05:26 +00:00
|
|
|
* USHORT (0x0101 == GSS_GetMIC)
|
2002-11-28 06:48:42 +00:00
|
|
|
* and so on }
|
|
|
|
*/
|
|
|
|
|
2003-05-24 05:05:26 +00:00
|
|
|
/* Now, the sign algorithm ... */
|
2002-11-28 06:48:42 +00:00
|
|
|
|
|
|
|
sgn_alg = tvb_get_letohs(tvb, offset);
|
2003-05-24 05:05:26 +00:00
|
|
|
proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
|
2002-11-28 06:48:42 +00:00
|
|
|
sgn_alg);
|
|
|
|
|
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
/* Skip the filler */
|
|
|
|
|
2003-05-24 05:05:26 +00:00
|
|
|
offset += 4;
|
2002-11-28 06:48:42 +00:00
|
|
|
|
|
|
|
/* Encrypted sequence number */
|
|
|
|
|
2003-05-24 05:05:26 +00:00
|
|
|
proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
|
2002-11-28 06:48:42 +00:00
|
|
|
TRUE);
|
|
|
|
|
|
|
|
offset += 8;
|
|
|
|
|
|
|
|
/* Checksum of plaintext padded data */
|
|
|
|
|
2003-05-24 05:05:26 +00:00
|
|
|
proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
|
2002-11-28 06:48:42 +00:00
|
|
|
TRUE);
|
|
|
|
|
|
|
|
offset += 8;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* At least according to draft-brezak-win2k-krb-rc4-hmac-04,
|
|
|
|
* if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
|
|
|
|
* extra 8 bytes of "Random confounder" after the checksum.
|
|
|
|
* It certainly confounds code expecting all Kerberos 5
|
|
|
|
* GSS_Wrap() tokens to look the same....
|
|
|
|
*/
|
|
|
|
if (sgn_alg == KRB_SGN_ALG_HMAC) {
|
2003-05-24 05:05:26 +00:00
|
|
|
proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
|
2002-11-28 06:48:42 +00:00
|
|
|
TRUE);
|
|
|
|
|
|
|
|
offset += 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the offset past the checksum, so that we know where
|
|
|
|
* the data we're wrapped around starts. Also, set the length
|
|
|
|
* of our top-level item to that offset, so it doesn't cover
|
|
|
|
* the data we're wrapped around.
|
|
|
|
*/
|
2003-05-24 05:05:26 +00:00
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX - is this for SPNEGO or just GSS-API?
|
|
|
|
* RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
|
|
|
|
* can directly designate Kerberos V5 as a mechanism in GSS-API, rather
|
|
|
|
* than designating SPNEGO as the mechanism, offering Kerberos V5, and
|
|
|
|
* getting it accepted.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
|
|
{
|
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
|
|
|
int offset = 0;
|
2005-03-06 22:52:58 +00:00
|
|
|
guint16 token_id;
|
2003-05-24 05:05:26 +00:00
|
|
|
|
|
|
|
item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, 0, -1, FALSE);
|
|
|
|
|
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego_krb5);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The KRB5 blob conforms to RFC1964:
|
|
|
|
* USHORT (0x0102 == GSS_Wrap)
|
|
|
|
* and so on }
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* First, the token ID ... */
|
|
|
|
|
2005-03-06 22:52:58 +00:00
|
|
|
token_id = tvb_get_letohs(tvb, offset);
|
2005-03-16 21:59:25 +00:00
|
|
|
proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
|
|
|
|
token_id);
|
2003-05-24 05:05:26 +00:00
|
|
|
|
|
|
|
offset += 2;
|
|
|
|
|
2005-03-06 22:52:58 +00:00
|
|
|
offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
|
2003-05-24 05:05:26 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the offset past the checksum, so that we know where
|
|
|
|
* the data we're wrapped around starts. Also, set the length
|
|
|
|
* of our top-level item to that offset, so it doesn't cover
|
|
|
|
* the data we're wrapped around.
|
|
|
|
*/
|
2002-11-28 06:48:42 +00:00
|
|
|
proto_item_set_len(item, offset);
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2002-09-05 03:49:03 +00:00
|
|
|
/* Spnego stuff from here */
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
static int
|
2002-11-28 06:48:42 +00:00
|
|
|
dissect_spnego_mechTypes(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
2005-06-20 10:22:03 +00:00
|
|
|
proto_tree *tree,
|
2002-11-28 06:48:42 +00:00
|
|
|
gssapi_oid_value **next_level_value_p)
|
2002-08-28 01:15:23 +00:00
|
|
|
{
|
2002-08-30 16:17:29 +00:00
|
|
|
proto_item *item = NULL;
|
|
|
|
proto_tree *subtree = NULL;
|
2002-09-08 22:47:43 +00:00
|
|
|
gboolean saw_mechanism = FALSE;
|
2005-07-12 01:01:19 +00:00
|
|
|
int start_offset, start_oid_offset, end_oid_offset;
|
2005-06-20 10:22:03 +00:00
|
|
|
gint8 class;
|
|
|
|
gboolean pc, ind_field;
|
|
|
|
gint32 tag;
|
2005-07-12 01:01:19 +00:00
|
|
|
guint32 len1;
|
2005-06-21 09:38:59 +00:00
|
|
|
gchar oid[MAX_OID_STR_LEN];
|
2002-08-30 16:17:29 +00:00
|
|
|
|
2005-06-20 10:22:03 +00:00
|
|
|
start_offset=offset;
|
2002-08-28 01:15:23 +00:00
|
|
|
/*
|
2002-08-28 21:04:11 +00:00
|
|
|
* MechTypeList ::= SEQUENCE OF MechType
|
2002-08-28 01:15:23 +00:00
|
|
|
*/
|
2005-06-20 10:22:03 +00:00
|
|
|
offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
|
|
|
|
offset = get_ber_length(tree, tvb, offset, &len1, &ind_field);
|
2002-08-28 01:15:23 +00:00
|
|
|
|
2005-06-20 10:22:03 +00:00
|
|
|
if (!(class == BER_CLASS_UNI && pc && tag == BER_UNI_TAG_SEQUENCE)) {
|
2002-08-28 01:15:23 +00:00
|
|
|
proto_tree_add_text(
|
2005-06-20 10:22:03 +00:00
|
|
|
tree, tvb, offset, 0,
|
|
|
|
"Unknown header (class=%d, pc=%d, tag=%d)",
|
|
|
|
class, pc, tag);
|
2002-08-28 01:15:23 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2005-06-20 10:22:03 +00:00
|
|
|
item = proto_tree_add_item(tree, hf_spnego_mechtype, tvb,
|
|
|
|
start_offset, len1, FALSE);
|
2002-08-29 00:35:55 +00:00
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego_mechtype);
|
|
|
|
|
2002-08-28 01:15:23 +00:00
|
|
|
/*
|
2005-06-20 10:22:03 +00:00
|
|
|
* Now, the object IDs ...
|
2002-08-28 01:15:23 +00:00
|
|
|
*/
|
2005-06-20 10:22:03 +00:00
|
|
|
start_oid_offset=offset;
|
2005-07-12 01:01:19 +00:00
|
|
|
end_oid_offset = start_oid_offset+len1;
|
|
|
|
while (offset<end_oid_offset) {
|
2002-09-04 21:34:38 +00:00
|
|
|
gssapi_oid_value *value;
|
2002-08-28 01:15:23 +00:00
|
|
|
|
2005-06-20 10:22:03 +00:00
|
|
|
offset=dissect_ber_object_identifier(FALSE, pinfo, subtree, tvb, offset, hf_spnego_mech, oid);
|
|
|
|
value = gssapi_lookup_oid_str(oid);
|
2002-09-08 01:43:44 +00:00
|
|
|
|
2002-09-08 22:47:43 +00:00
|
|
|
/*
|
|
|
|
* Tell our caller the first mechanism we see, so that if
|
|
|
|
* this is a negTokenInit with a mechToken, it can interpret
|
|
|
|
* the mechToken according to the first mechType. (There
|
|
|
|
* might not have been any indication of the mechType
|
|
|
|
* in prior frames, so we can't necessarily use the
|
|
|
|
* mechanism from the conversation; i.e., a negTokenInit
|
|
|
|
* can contain the initial security token for the desired
|
|
|
|
* mechanism of the initiator - that's the first mechanism
|
|
|
|
* in the list.)
|
|
|
|
*/
|
|
|
|
if (!saw_mechanism) {
|
|
|
|
if (value)
|
2002-11-28 06:48:42 +00:00
|
|
|
*next_level_value_p = value;
|
2002-09-08 22:47:43 +00:00
|
|
|
saw_mechanism = TRUE;
|
|
|
|
}
|
2002-08-28 01:15:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
static int
|
2002-08-28 01:15:23 +00:00
|
|
|
dissect_spnego_reqFlags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
|
|
|
|
proto_tree *tree, ASN1_SCK *hnd)
|
|
|
|
{
|
2002-09-04 06:54:45 +00:00
|
|
|
gboolean def;
|
2003-05-25 00:59:15 +00:00
|
|
|
guint len1, cls, con, tag, flags;
|
2002-09-04 06:54:45 +00:00
|
|
|
int ret;
|
2003-05-25 00:59:15 +00:00
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
2002-09-04 06:54:45 +00:00
|
|
|
|
|
|
|
ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len1);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, tree,
|
|
|
|
"SPNEGO reqFlags header", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
2002-08-28 01:15:23 +00:00
|
|
|
|
2002-09-04 06:54:45 +00:00
|
|
|
if (!(cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_BTS)) {
|
|
|
|
proto_tree_add_text(
|
|
|
|
tree, tvb, offset, 0,
|
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d)",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
|
|
|
}
|
2002-08-30 16:17:29 +00:00
|
|
|
|
2002-09-04 06:54:45 +00:00
|
|
|
/* We must have a Bit String ... insert it */
|
|
|
|
|
|
|
|
offset = hnd->offset;
|
|
|
|
|
2003-05-25 00:59:15 +00:00
|
|
|
flags = tvb_get_guint8(tvb, offset);
|
|
|
|
|
|
|
|
item = proto_tree_add_item(tree, hf_spnego_reqflags, tvb, offset, len1,
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego_reqflags);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now, the bits. XXX: Assume 8 bits. FIXME.
|
|
|
|
*/
|
|
|
|
|
|
|
|
proto_tree_add_boolean(subtree, hf_gssapi_reqflags_deleg, tvb, offset, len1, flags);
|
|
|
|
proto_tree_add_boolean(subtree, hf_gssapi_reqflags_mutual, tvb, offset, len1, flags);
|
|
|
|
proto_tree_add_boolean(subtree, hf_gssapi_reqflags_replay, tvb, offset, len1, flags);
|
|
|
|
proto_tree_add_boolean(subtree, hf_gssapi_reqflags_sequence, tvb, offset, len1, flags);
|
|
|
|
proto_tree_add_boolean(subtree, hf_gssapi_reqflags_anon, tvb, offset, len1, flags);
|
|
|
|
proto_tree_add_boolean(subtree, hf_gssapi_reqflags_conf, tvb, offset, len1, flags);
|
|
|
|
proto_tree_add_boolean(subtree, hf_gssapi_reqflags_integ, tvb, offset, len1, flags);
|
2002-09-04 06:54:45 +00:00
|
|
|
|
|
|
|
hnd->offset += len1;
|
|
|
|
|
|
|
|
done:
|
|
|
|
return offset + len1;
|
2002-08-28 01:15:23 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
static int
|
2002-08-28 01:15:23 +00:00
|
|
|
dissect_spnego_mechToken(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
|
2002-09-08 22:47:43 +00:00
|
|
|
proto_tree *tree, ASN1_SCK *hnd,
|
|
|
|
dissector_handle_t next_level_dissector)
|
2002-08-28 01:15:23 +00:00
|
|
|
{
|
2002-08-31 17:09:45 +00:00
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
2002-08-30 05:04:52 +00:00
|
|
|
gboolean def;
|
|
|
|
int ret;
|
2005-08-06 03:43:42 +00:00
|
|
|
guint cls, con, tag, nbytes = 0;
|
2004-04-30 22:19:43 +00:00
|
|
|
gint length_remaining, reported_length_remaining;
|
2002-08-30 05:04:52 +00:00
|
|
|
tvbuff_t *token_tvb;
|
2002-08-28 01:15:23 +00:00
|
|
|
|
2002-08-30 05:04:52 +00:00
|
|
|
/*
|
|
|
|
* This appears to be a simple octet string ...
|
|
|
|
*/
|
|
|
|
|
|
|
|
ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &nbytes);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, tree,
|
|
|
|
"SPNEGO sequence header", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)) {
|
|
|
|
proto_tree_add_text(
|
|
|
|
tree, tvb, offset, 0,
|
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d)",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = hnd->offset;
|
|
|
|
|
2004-04-02 22:01:21 +00:00
|
|
|
|
|
|
|
/* Dont try to create an item with more bytes than remains in the
|
|
|
|
* frame or we will not even attempt to dissect those bytes we
|
|
|
|
* do have. (since there will be an exception)
|
2004-04-30 22:19:43 +00:00
|
|
|
*
|
|
|
|
* We use "tvb_ensure_length_remaining()" so that we throw
|
|
|
|
* an exception if there's nothing to dissect.
|
2004-04-02 22:01:21 +00:00
|
|
|
*/
|
2004-04-30 22:19:43 +00:00
|
|
|
length_remaining = tvb_ensure_length_remaining(tvb,offset);
|
|
|
|
reported_length_remaining = tvb_reported_length_remaining(tvb,offset);
|
|
|
|
if ((guint)length_remaining > nbytes)
|
|
|
|
length_remaining = nbytes;
|
|
|
|
if ((guint)reported_length_remaining > nbytes)
|
|
|
|
reported_length_remaining = nbytes;
|
2002-08-31 17:09:45 +00:00
|
|
|
item = proto_tree_add_item(tree, hf_spnego_mechtoken, tvb, offset,
|
2004-04-30 22:19:43 +00:00
|
|
|
length_remaining, FALSE);
|
2002-08-31 17:09:45 +00:00
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego_mechtoken);
|
2002-08-30 05:04:52 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now, we should be able to dispatch after creating a new TVB.
|
|
|
|
*/
|
|
|
|
|
2004-04-30 22:19:43 +00:00
|
|
|
token_tvb = tvb_new_subset(tvb, offset, length_remaining,
|
|
|
|
reported_length_remaining);
|
2002-08-30 16:17:29 +00:00
|
|
|
if (next_level_dissector)
|
2002-08-31 17:09:45 +00:00
|
|
|
call_dissector(next_level_dissector, token_tvb, pinfo, subtree);
|
2002-08-30 05:04:52 +00:00
|
|
|
|
|
|
|
hnd->offset += nbytes; /* Update this ... */
|
|
|
|
|
2004-04-30 22:19:43 +00:00
|
|
|
done:
|
|
|
|
return offset + nbytes;
|
2002-08-28 01:15:23 +00:00
|
|
|
}
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
static int
|
2002-08-28 01:15:23 +00:00
|
|
|
dissect_spnego_mechListMIC(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
|
2002-09-08 22:47:43 +00:00
|
|
|
proto_tree *tree, ASN1_SCK *hnd,
|
|
|
|
dissector_handle_t next_level_dissector)
|
2002-08-28 01:15:23 +00:00
|
|
|
{
|
2002-08-30 16:17:29 +00:00
|
|
|
guint len1, cls, con, tag;
|
2002-08-28 05:02:41 +00:00
|
|
|
int ret;
|
|
|
|
gboolean def;
|
|
|
|
proto_tree *subtree = NULL;
|
2002-08-28 01:15:23 +00:00
|
|
|
|
2002-08-28 05:02:41 +00:00
|
|
|
/*
|
2002-08-30 00:32:11 +00:00
|
|
|
* Add the mechListMIC [3] Octet String or General String ...
|
2002-08-28 05:02:41 +00:00
|
|
|
*/
|
|
|
|
ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len1);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, subtree,
|
|
|
|
"SPNEGO sequence header", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = hnd->offset;
|
|
|
|
|
2002-08-30 06:11:35 +00:00
|
|
|
if (cls == ASN1_UNI && con == ASN1_CON && tag == ASN1_SEQ) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* There seems to be two different forms this can take
|
|
|
|
* One as an Octet string, and one as a general string in a
|
|
|
|
* sequence ... We will have to dissect this later
|
|
|
|
*/
|
|
|
|
|
|
|
|
proto_tree_add_text(tree, tvb, offset + 4, len1 - 4,
|
2002-09-03 16:45:31 +00:00
|
|
|
"mechListMIC: %s",
|
2002-09-04 05:46:02 +00:00
|
|
|
tvb_format_text(tvb, offset + 4, len1 - 4));
|
2002-08-30 06:11:35 +00:00
|
|
|
|
|
|
|
/* Naughty ... but we have to adjust for what we never took */
|
|
|
|
|
2002-08-31 07:26:10 +00:00
|
|
|
hnd->offset += len1;
|
2002-08-30 06:11:35 +00:00
|
|
|
offset += len1;
|
|
|
|
|
|
|
|
}
|
|
|
|
else if (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS) {
|
|
|
|
tvbuff_t *token_tvb;
|
2002-08-31 17:09:45 +00:00
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
2002-08-30 06:11:35 +00:00
|
|
|
|
2002-08-31 17:09:45 +00:00
|
|
|
item = proto_tree_add_item(tree, hf_spnego_mechlistmic, tvb, offset,
|
|
|
|
len1, FALSE);
|
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego_mechlistmic);
|
|
|
|
|
2002-08-30 00:32:11 +00:00
|
|
|
/*
|
2002-08-30 06:11:35 +00:00
|
|
|
* Now, we should be able to dispatch after creating a new TVB.
|
2002-08-30 00:32:11 +00:00
|
|
|
*/
|
2002-08-28 05:02:41 +00:00
|
|
|
|
2002-08-30 06:11:35 +00:00
|
|
|
token_tvb = tvb_new_subset(tvb, offset, len1, -1);
|
2002-08-30 16:17:29 +00:00
|
|
|
if (next_level_dissector)
|
2002-08-31 17:09:45 +00:00
|
|
|
call_dissector(next_level_dissector, token_tvb, pinfo, subtree);
|
2002-08-28 05:02:41 +00:00
|
|
|
|
2002-08-30 06:11:35 +00:00
|
|
|
hnd->offset += len1; /* Update this ... */
|
|
|
|
offset += len1;
|
2002-08-28 05:02:41 +00:00
|
|
|
|
2002-08-30 06:11:35 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
proto_tree_add_text(subtree, tvb, offset, 0,
|
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d)",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
|
|
|
}
|
2002-08-28 05:02:41 +00:00
|
|
|
|
|
|
|
done:
|
|
|
|
|
2002-08-30 06:11:35 +00:00
|
|
|
return offset;
|
2002-08-28 01:15:23 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2002-08-28 21:04:11 +00:00
|
|
|
dissect_spnego_negTokenInit(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
|
2002-09-08 22:47:43 +00:00
|
|
|
proto_tree *tree, ASN1_SCK *hnd,
|
2002-11-28 06:48:42 +00:00
|
|
|
gssapi_oid_value **next_level_value_p)
|
2002-08-27 15:46:17 +00:00
|
|
|
{
|
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
2002-08-27 23:21:53 +00:00
|
|
|
gboolean def;
|
2002-08-30 16:17:29 +00:00
|
|
|
guint len1, len, cls, con, tag;
|
2002-08-29 00:35:55 +00:00
|
|
|
int ret;
|
2002-08-28 01:15:23 +00:00
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
item = proto_tree_add_item( tree, hf_spnego_negtokeninit, tvb, offset,
|
2002-09-08 22:47:43 +00:00
|
|
|
-1, FALSE);
|
2002-08-28 01:15:23 +00:00
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego_negtokeninit);
|
2002-08-27 23:21:53 +00:00
|
|
|
|
|
|
|
/*
|
2002-08-28 00:19:10 +00:00
|
|
|
* Here is what we need to get ...
|
2002-08-28 21:04:11 +00:00
|
|
|
* NegTokenInit ::= SEQUENCE {
|
|
|
|
* mechTypes [0] MechTypeList OPTIONAL,
|
|
|
|
* reqFlags [1] ContextFlags OPTIONAL,
|
|
|
|
* mechToken [2] OCTET STRING OPTIONAL,
|
|
|
|
* mechListMIC [3] OCTET STRING OPTIONAL }
|
2002-08-27 23:21:53 +00:00
|
|
|
|
|
|
|
*/
|
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len1);
|
2002-08-27 23:21:53 +00:00
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, subtree,
|
2002-08-28 00:19:10 +00:00
|
|
|
"SPNEGO sequence header", ret);
|
2002-08-27 23:21:53 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
if (!(cls == ASN1_UNI && con == ASN1_CON && tag == ASN1_SEQ)) {
|
2002-08-27 23:21:53 +00:00
|
|
|
proto_tree_add_text(
|
|
|
|
subtree, tvb, offset, 0,
|
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d)",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2002-08-28 02:30:18 +00:00
|
|
|
offset = hnd->offset;
|
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
while (len1) {
|
2002-08-31 07:26:10 +00:00
|
|
|
int hdr_ofs;
|
|
|
|
|
|
|
|
hdr_ofs = hnd->offset;
|
2002-08-27 23:21:53 +00:00
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len);
|
2002-08-27 23:21:53 +00:00
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, subtree,
|
|
|
|
"SPNEGO context header", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
2002-08-27 23:21:53 +00:00
|
|
|
|
2002-08-28 05:02:41 +00:00
|
|
|
if (!(cls == ASN1_CTX && con == ASN1_CON)) {
|
2002-08-31 07:26:10 +00:00
|
|
|
proto_tree_add_text(subtree, tvb, offset, 0,
|
2002-08-28 00:19:10 +00:00
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d)",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
|
|
|
}
|
2002-08-27 23:21:53 +00:00
|
|
|
|
2002-08-31 07:26:10 +00:00
|
|
|
/* Adjust for the length of the header */
|
|
|
|
|
|
|
|
len1 -= (hnd->offset - hdr_ofs);
|
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
/* Should be one of the fields */
|
2002-08-27 23:21:53 +00:00
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
switch (tag) {
|
|
|
|
|
|
|
|
case SPNEGO_mechTypes:
|
|
|
|
|
2005-06-20 10:22:03 +00:00
|
|
|
offset = dissect_spnego_mechTypes(tvb, hnd->offset, pinfo,
|
|
|
|
subtree,
|
2002-11-28 06:48:42 +00:00
|
|
|
next_level_value_p);
|
2005-06-20 10:22:03 +00:00
|
|
|
hnd->offset=offset;
|
2002-08-28 01:15:23 +00:00
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPNEGO_reqFlags:
|
|
|
|
|
2002-09-04 06:54:45 +00:00
|
|
|
offset = dissect_spnego_reqFlags(tvb, offset, pinfo, subtree, hnd);
|
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPNEGO_mechToken:
|
|
|
|
|
2002-08-30 05:04:52 +00:00
|
|
|
offset = dissect_spnego_mechToken(tvb, offset, pinfo, subtree,
|
2004-05-11 02:02:44 +00:00
|
|
|
hnd, gssapi_dissector_handle(*next_level_value_p));
|
2002-08-28 00:19:10 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPNEGO_mechListMIC:
|
|
|
|
|
2002-08-28 05:02:41 +00:00
|
|
|
offset = dissect_spnego_mechListMIC(tvb, offset, pinfo, subtree,
|
2004-05-11 02:02:44 +00:00
|
|
|
hnd, gssapi_dissector_handle(*next_level_value_p));
|
2002-08-28 00:19:10 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-08-31 07:26:10 +00:00
|
|
|
len1 -= len;
|
2002-08-27 23:21:53 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
done:
|
2002-08-28 01:15:23 +00:00
|
|
|
|
|
|
|
return offset; /* Not sure this is right */
|
2002-08-28 21:04:11 +00:00
|
|
|
}
|
2002-08-28 00:19:10 +00:00
|
|
|
|
2002-08-29 22:53:06 +00:00
|
|
|
static int
|
|
|
|
dissect_spnego_negResult(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
|
|
|
|
proto_tree *tree, ASN1_SCK *hnd)
|
|
|
|
{
|
|
|
|
gboolean def;
|
|
|
|
int ret;
|
2002-08-30 16:17:29 +00:00
|
|
|
guint len, cls, con, tag, val;
|
2002-08-29 22:53:06 +00:00
|
|
|
|
|
|
|
ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, tree,
|
|
|
|
"SPNEGO context header", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_ENUM)) {
|
|
|
|
proto_tree_add_text(
|
|
|
|
tree, tvb, offset, 0,
|
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d) xxx",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = hnd->offset;
|
|
|
|
|
|
|
|
/* Now, get the value */
|
|
|
|
|
|
|
|
ret = asn1_uint32_value_decode(hnd, len, &val);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, tree,
|
|
|
|
"SPNEGO negResult value", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_tree_add_item(tree, hf_spnego_negtokentarg_negresult, tvb,
|
|
|
|
offset, 1, FALSE);
|
|
|
|
|
|
|
|
offset = hnd->offset;
|
|
|
|
|
|
|
|
done:
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
dissect_spnego_supportedMech(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
|
2002-09-08 22:47:43 +00:00
|
|
|
proto_tree *tree, ASN1_SCK *hnd,
|
2002-11-28 06:48:42 +00:00
|
|
|
gssapi_oid_value **next_level_value_p)
|
2002-08-29 22:53:06 +00:00
|
|
|
{
|
2005-09-11 21:10:20 +00:00
|
|
|
gchar oid[MAX_OID_STR_LEN];
|
2002-08-30 00:32:11 +00:00
|
|
|
gssapi_oid_value *value;
|
2002-08-30 04:04:39 +00:00
|
|
|
conversation_t *conversation;
|
2002-08-29 22:53:06 +00:00
|
|
|
|
2002-08-30 00:32:11 +00:00
|
|
|
/*
|
|
|
|
* Now, get the OID, and find the handle, if any
|
|
|
|
*/
|
2002-08-29 22:53:06 +00:00
|
|
|
|
2002-08-30 00:32:11 +00:00
|
|
|
offset = hnd->offset;
|
|
|
|
|
2005-09-11 21:10:20 +00:00
|
|
|
offset=dissect_ber_object_identifier(FALSE, pinfo, tree, tvb, offset, hf_spnego_supportedMech, oid);
|
|
|
|
value = gssapi_lookup_oid_str(oid);
|
|
|
|
/* put the right offset into asn1:s struct for now */
|
|
|
|
hnd->offset = offset;
|
2002-09-08 01:43:44 +00:00
|
|
|
|
2002-08-30 00:32:11 +00:00
|
|
|
/* Should check for an unrecognized OID ... */
|
|
|
|
|
2002-09-08 22:47:43 +00:00
|
|
|
if (value)
|
2002-11-28 06:48:42 +00:00
|
|
|
*next_level_value_p = value;
|
2002-08-30 00:32:11 +00:00
|
|
|
|
2002-08-30 04:04:39 +00:00
|
|
|
/*
|
|
|
|
* Now, we need to save this in per proto info in the
|
|
|
|
* conversation if it exists. We also should create a
|
|
|
|
* conversation if one does not exist. FIXME!
|
2002-08-30 05:04:52 +00:00
|
|
|
* Hmmm, might need to be smarter, because there can be
|
|
|
|
* multiple mechTypes in a negTokenInit with one being the
|
|
|
|
* default used in the Token if present. Then the negTokenTarg
|
|
|
|
* could override that. :-(
|
2002-08-30 04:04:39 +00:00
|
|
|
*/
|
|
|
|
|
2005-02-02 20:07:03 +00:00
|
|
|
if ((conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
|
2002-08-30 04:04:39 +00:00
|
|
|
pinfo->ptype, pinfo->srcport,
|
2002-08-30 16:17:29 +00:00
|
|
|
pinfo->destport, 0))) {
|
2002-08-30 00:32:11 +00:00
|
|
|
|
2002-08-30 04:04:39 +00:00
|
|
|
|
|
|
|
conversation_add_proto_data(conversation, proto_spnego,
|
2002-11-28 06:48:42 +00:00
|
|
|
*next_level_value_p);
|
2002-08-30 04:04:39 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
}
|
2002-08-30 00:32:11 +00:00
|
|
|
|
|
|
|
return offset;
|
2002-08-29 22:53:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
dissect_spnego_responseToken(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
|
2002-09-08 22:47:43 +00:00
|
|
|
proto_tree *tree, ASN1_SCK *hnd,
|
|
|
|
dissector_handle_t next_level_dissector)
|
2002-08-29 22:53:06 +00:00
|
|
|
{
|
2002-08-30 00:32:11 +00:00
|
|
|
gboolean def;
|
|
|
|
int ret;
|
2002-08-30 16:17:29 +00:00
|
|
|
guint cls, con, tag, nbytes;
|
2002-08-30 00:32:11 +00:00
|
|
|
tvbuff_t *token_tvb;
|
2002-08-31 17:09:45 +00:00
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
2002-08-29 22:53:06 +00:00
|
|
|
|
2002-08-30 00:32:11 +00:00
|
|
|
ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &nbytes);
|
2002-08-29 22:53:06 +00:00
|
|
|
|
2002-08-30 00:32:11 +00:00
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, tree,
|
|
|
|
"SPNEGO sequence header", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)) {
|
|
|
|
proto_tree_add_text(
|
|
|
|
tree, tvb, offset, 0,
|
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d)",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = hnd->offset;
|
|
|
|
|
2003-06-01 20:34:20 +00:00
|
|
|
item = proto_tree_add_item(tree, hf_spnego_responsetoken, tvb, offset -2 ,
|
|
|
|
nbytes + 2, FALSE);
|
2002-08-31 17:09:45 +00:00
|
|
|
|
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego_responsetoken);
|
2002-08-30 00:32:11 +00:00
|
|
|
|
2003-06-01 20:34:20 +00:00
|
|
|
|
2002-08-30 00:32:11 +00:00
|
|
|
/*
|
|
|
|
* Now, we should be able to dispatch after creating a new TVB.
|
2003-06-01 20:34:20 +00:00
|
|
|
* However, we should make sure that there is something in the
|
|
|
|
* response token ...
|
2002-08-30 00:32:11 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-01 20:34:20 +00:00
|
|
|
if (nbytes) {
|
|
|
|
token_tvb = tvb_new_subset(tvb, offset, nbytes, -1);
|
|
|
|
if (next_level_dissector)
|
|
|
|
call_dissector(next_level_dissector, token_tvb, pinfo, subtree);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
proto_tree_add_text(subtree, tvb, offset-2, 2, "<Empty String>");
|
|
|
|
}
|
2002-08-30 00:32:11 +00:00
|
|
|
hnd->offset += nbytes; /* Update this ... */
|
|
|
|
|
|
|
|
done:
|
2002-08-30 04:04:39 +00:00
|
|
|
return offset + nbytes;
|
2002-08-29 22:53:06 +00:00
|
|
|
}
|
|
|
|
|
2002-08-29 17:58:22 +00:00
|
|
|
static int
|
|
|
|
dissect_spnego_negTokenTarg(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
|
2002-09-08 22:47:43 +00:00
|
|
|
proto_tree *tree, ASN1_SCK *hnd,
|
2002-11-28 06:48:42 +00:00
|
|
|
gssapi_oid_value **next_level_value_p)
|
2002-08-28 00:19:10 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
2002-08-29 17:58:22 +00:00
|
|
|
gboolean def;
|
|
|
|
int ret;
|
2002-08-30 16:17:29 +00:00
|
|
|
guint len1, len, cls, con, tag;
|
2002-08-29 17:58:22 +00:00
|
|
|
|
|
|
|
item = proto_tree_add_item( tree, hf_spnego_negtokentarg, tvb, offset,
|
2002-09-08 22:47:43 +00:00
|
|
|
-1, FALSE);
|
2002-08-29 17:58:22 +00:00
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego_negtokentarg);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Here is what we need to get ...
|
|
|
|
* NegTokenTarg ::= SEQUENCE {
|
|
|
|
* negResult [0] ENUMERATED {
|
|
|
|
* accept_completed (0),
|
|
|
|
* accept_incomplete (1),
|
|
|
|
* reject (2) } OPTIONAL,
|
|
|
|
* supportedMech [1] MechType OPTIONAL,
|
|
|
|
* responseToken [2] OCTET STRING OPTIONAL,
|
|
|
|
* mechListMIC [3] OCTET STRING OPTIONAL }
|
|
|
|
*/
|
|
|
|
|
|
|
|
ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len1);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, subtree,
|
|
|
|
"SPNEGO sequence header", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(cls == ASN1_UNI && con == ASN1_CON && tag == ASN1_SEQ)) {
|
|
|
|
proto_tree_add_text(
|
|
|
|
subtree, tvb, offset, 0,
|
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d)",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2002-08-29 19:45:01 +00:00
|
|
|
offset = hnd->offset;
|
|
|
|
|
|
|
|
while (len1) {
|
2002-08-31 07:26:10 +00:00
|
|
|
int hdr_ofs;
|
|
|
|
|
|
|
|
hdr_ofs = hnd->offset;
|
2002-08-29 19:45:01 +00:00
|
|
|
|
|
|
|
ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, subtree,
|
|
|
|
"SPNEGO context header", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(cls == ASN1_CTX && con == ASN1_CON)) {
|
|
|
|
proto_tree_add_text(
|
|
|
|
subtree, tvb, offset, 0,
|
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d)",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2002-08-31 07:26:10 +00:00
|
|
|
/* Adjust for the length of the header */
|
|
|
|
|
|
|
|
len1 -= (hnd->offset - hdr_ofs);
|
|
|
|
|
2002-08-29 19:45:01 +00:00
|
|
|
/* Should be one of the fields */
|
|
|
|
|
|
|
|
switch (tag) {
|
|
|
|
|
|
|
|
case SPNEGO_negResult:
|
|
|
|
|
2002-08-29 22:53:06 +00:00
|
|
|
offset = dissect_spnego_negResult(tvb, offset, pinfo, subtree,
|
|
|
|
hnd);
|
2002-08-29 19:45:01 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPNEGO_supportedMech:
|
|
|
|
|
2002-08-29 22:53:06 +00:00
|
|
|
offset = dissect_spnego_supportedMech(tvb, offset, pinfo, subtree,
|
2002-11-28 06:48:42 +00:00
|
|
|
hnd, next_level_value_p);
|
2002-08-29 22:53:06 +00:00
|
|
|
|
2002-08-29 19:45:01 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPNEGO_responseToken:
|
|
|
|
|
2002-08-29 22:53:06 +00:00
|
|
|
offset = dissect_spnego_responseToken(tvb, offset, pinfo, subtree,
|
2004-05-11 02:02:44 +00:00
|
|
|
hnd, gssapi_dissector_handle(*next_level_value_p));
|
2002-08-29 19:45:01 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPNEGO_mechListMIC:
|
|
|
|
|
2002-08-29 22:53:06 +00:00
|
|
|
offset = dissect_spnego_mechListMIC(tvb, offset, pinfo, subtree,
|
2004-05-11 02:02:44 +00:00
|
|
|
hnd, gssapi_dissector_handle(*next_level_value_p));
|
2002-08-29 19:45:01 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-08-31 07:26:10 +00:00
|
|
|
len1 -= len;
|
2002-08-30 04:04:39 +00:00
|
|
|
|
2002-08-29 19:45:01 +00:00
|
|
|
}
|
2002-08-29 17:58:22 +00:00
|
|
|
|
|
|
|
done:
|
|
|
|
return offset;
|
2002-08-28 00:19:10 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2002-11-07 05:25:37 +00:00
|
|
|
dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
2002-08-28 00:19:10 +00:00
|
|
|
{
|
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
|
|
|
int ret, offset = 0;
|
|
|
|
ASN1_SCK hnd;
|
|
|
|
gboolean def;
|
2002-08-30 16:17:29 +00:00
|
|
|
guint len1, cls, con, tag;
|
2002-08-30 04:04:39 +00:00
|
|
|
conversation_t *conversation;
|
2002-11-28 06:48:42 +00:00
|
|
|
gssapi_oid_value *next_level_value;
|
2002-08-28 00:19:10 +00:00
|
|
|
|
2002-08-30 04:04:39 +00:00
|
|
|
/*
|
|
|
|
* We need this later, so lets get it now ...
|
2002-11-07 05:25:37 +00:00
|
|
|
* It has to be per-frame as there can be more than one GSS-API
|
|
|
|
* negotiation in a conversation.
|
2002-08-30 04:04:39 +00:00
|
|
|
*/
|
|
|
|
|
2002-11-28 06:48:42 +00:00
|
|
|
next_level_value = p_get_proto_data(pinfo->fd, proto_spnego);
|
|
|
|
if (!next_level_value && !pinfo->fd->flags.visited) {
|
2002-11-07 05:25:37 +00:00
|
|
|
/*
|
|
|
|
* No handle attached to this frame, but it's the first
|
|
|
|
* pass, so it'd be attached to the conversation.
|
|
|
|
* If we have a conversation, try to get the handle,
|
|
|
|
* and if we get one, attach it to the frame.
|
|
|
|
*/
|
2005-02-02 20:07:03 +00:00
|
|
|
conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
|
2002-11-07 05:25:37 +00:00
|
|
|
pinfo->ptype, pinfo->srcport,
|
|
|
|
pinfo->destport, 0);
|
2002-08-30 04:04:39 +00:00
|
|
|
|
2002-11-07 05:25:37 +00:00
|
|
|
if (conversation) {
|
2002-11-28 06:48:42 +00:00
|
|
|
next_level_value = conversation_get_proto_data(conversation,
|
|
|
|
proto_spnego);
|
|
|
|
if (next_level_value)
|
|
|
|
p_add_proto_data(pinfo->fd, proto_spnego, next_level_value);
|
2002-11-07 05:25:37 +00:00
|
|
|
}
|
|
|
|
}
|
2002-08-30 04:04:39 +00:00
|
|
|
|
2002-08-31 17:09:45 +00:00
|
|
|
item = proto_tree_add_item(tree, hf_spnego, tvb, offset,
|
2002-09-08 22:47:43 +00:00
|
|
|
-1, FALSE);
|
2002-08-28 00:19:10 +00:00
|
|
|
|
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego);
|
|
|
|
|
|
|
|
/*
|
2002-08-28 21:04:11 +00:00
|
|
|
* The TVB contains a [0] header and a sequence that consists of an
|
2002-08-28 00:19:10 +00:00
|
|
|
* object ID and a blob containing the data ...
|
|
|
|
* Actually, it contains, according to RFC2478:
|
2002-08-28 21:04:11 +00:00
|
|
|
* NegotiationToken ::= CHOICE {
|
|
|
|
* negTokenInit [0] NegTokenInit,
|
|
|
|
* negTokenTarg [1] NegTokenTarg }
|
|
|
|
* NegTokenInit ::= SEQUENCE {
|
|
|
|
* mechTypes [0] MechTypeList OPTIONAL,
|
|
|
|
* reqFlags [1] ContextFlags OPTIONAL,
|
|
|
|
* mechToken [2] OCTET STRING OPTIONAL,
|
|
|
|
* mechListMIC [3] OCTET STRING OPTIONAL }
|
|
|
|
* NegTokenTarg ::= SEQUENCE {
|
|
|
|
* negResult [0] ENUMERATED {
|
|
|
|
* accept_completed (0),
|
|
|
|
* accept_incomplete (1),
|
|
|
|
* reject (2) } OPTIONAL,
|
|
|
|
* supportedMech [1] MechType OPTIONAL,
|
|
|
|
* responseToken [2] OCTET STRING OPTIONAL,
|
2002-08-28 00:19:10 +00:00
|
|
|
* mechListMIC [3] OCTET STRING OPTIONAL }
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
|
|
|
* Windows typically includes mechTypes and mechListMic ('NONE'
|
2002-08-28 00:19:10 +00:00
|
|
|
* in the case of NTLMSSP only).
|
|
|
|
* It seems to duplicate the responseToken into the mechListMic field
|
|
|
|
* as well. Naughty, naughty.
|
|
|
|
*
|
|
|
|
*/
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
asn1_open(&hnd, tvb, offset);
|
|
|
|
|
|
|
|
/*
|
2002-08-28 21:04:11 +00:00
|
|
|
* Get the first header ...
|
2002-08-28 00:19:10 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
ret = asn1_header_decode(&hnd, &cls, &con, &tag, &def, &len1);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, subtree,
|
|
|
|
"SPNEGO context header", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2002-08-29 17:58:22 +00:00
|
|
|
if (!(cls == ASN1_CTX && con == ASN1_CON)) {
|
2002-08-28 00:19:10 +00:00
|
|
|
proto_tree_add_text(
|
|
|
|
subtree, tvb, offset, 0,
|
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d)",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2002-08-28 05:02:41 +00:00
|
|
|
offset = hnd.offset;
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
/*
|
2002-08-28 00:19:10 +00:00
|
|
|
* The Tag is one of negTokenInit or negTokenTarg
|
|
|
|
*/
|
|
|
|
|
|
|
|
switch (tag) {
|
|
|
|
|
|
|
|
case SPNEGO_negTokenInit:
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
offset = dissect_spnego_negTokenInit(tvb, offset, pinfo,
|
2002-09-08 22:47:43 +00:00
|
|
|
subtree, &hnd,
|
2002-11-28 06:48:42 +00:00
|
|
|
&next_level_value);
|
2002-08-28 01:15:23 +00:00
|
|
|
|
2002-08-28 00:19:10 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPNEGO_negTokenTarg:
|
|
|
|
|
2002-08-29 17:58:22 +00:00
|
|
|
offset = dissect_spnego_negTokenTarg(tvb, offset, pinfo,
|
2002-09-08 22:47:43 +00:00
|
|
|
subtree, &hnd,
|
2002-11-28 06:48:42 +00:00
|
|
|
&next_level_value);
|
2002-08-28 00:19:10 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* Broken, what to do? */
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-08-27 23:21:53 +00:00
|
|
|
done:
|
|
|
|
asn1_close(&hnd, &offset);
|
2002-08-27 15:46:17 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2002-11-28 06:48:42 +00:00
|
|
|
static int
|
|
|
|
dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
|
|
|
int return_offset;
|
|
|
|
conversation_t *conversation;
|
|
|
|
gssapi_oid_value *next_level_value;
|
|
|
|
tvbuff_t *token_tvb;
|
2005-06-20 10:22:03 +00:00
|
|
|
int len, offset, start_offset;
|
2005-06-20 09:43:29 +00:00
|
|
|
gint8 class;
|
|
|
|
gboolean pc, ind_field;
|
|
|
|
gint32 tag;
|
|
|
|
guint32 len1;
|
2005-06-21 09:38:59 +00:00
|
|
|
gchar oid[MAX_OID_STR_LEN];
|
2005-06-20 09:43:29 +00:00
|
|
|
|
|
|
|
start_offset=0;
|
|
|
|
offset=start_offset;
|
2002-11-28 06:48:42 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We need this later, so lets get it now ...
|
|
|
|
* It has to be per-frame as there can be more than one GSS-API
|
|
|
|
* negotiation in a conversation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
next_level_value = p_get_proto_data(pinfo->fd, proto_spnego);
|
|
|
|
if (!next_level_value && !pinfo->fd->flags.visited) {
|
|
|
|
/*
|
|
|
|
* No handle attached to this frame, but it's the first
|
|
|
|
* pass, so it'd be attached to the conversation.
|
|
|
|
* If we have a conversation, try to get the handle,
|
|
|
|
* and if we get one, attach it to the frame.
|
|
|
|
*/
|
2005-02-02 20:07:03 +00:00
|
|
|
conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
|
2002-11-28 06:48:42 +00:00
|
|
|
pinfo->ptype, pinfo->srcport,
|
|
|
|
pinfo->destport, 0);
|
|
|
|
|
|
|
|
if (conversation) {
|
|
|
|
next_level_value = conversation_get_proto_data(conversation,
|
|
|
|
proto_spnego);
|
|
|
|
if (next_level_value)
|
|
|
|
p_add_proto_data(pinfo->fd, proto_spnego, next_level_value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
item = proto_tree_add_item(tree, hf_spnego, tvb, offset,
|
|
|
|
-1, FALSE);
|
|
|
|
|
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The TVB contains a [0] header and a sequence that consists of an
|
|
|
|
* object ID and a blob containing the data ...
|
|
|
|
* XXX - is this RFC 2743's "Mechanism-Independent Token Format",
|
|
|
|
* with the "optional" "use in non-initial tokens" being chosen.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the first header ...
|
|
|
|
*/
|
2005-06-20 09:43:29 +00:00
|
|
|
offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
|
|
|
|
offset = get_ber_length(tree, tvb, offset, &len1, &ind_field);
|
2002-11-28 06:48:42 +00:00
|
|
|
|
2005-06-20 09:43:29 +00:00
|
|
|
if (!(class == BER_CLASS_APP && pc && tag == 0)) {
|
2002-11-28 06:48:42 +00:00
|
|
|
proto_tree_add_text(
|
2005-06-20 09:43:29 +00:00
|
|
|
subtree, tvb, start_offset, 0,
|
|
|
|
"Unknown header (class=%d, pc=%d, tag=%d)",
|
|
|
|
class, pc, tag);
|
2002-11-28 06:48:42 +00:00
|
|
|
return_offset = tvb_length(tvb);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the OID, and find the handle, if any
|
2005-06-20 09:43:29 +00:00
|
|
|
*
|
|
|
|
* XXX - what should we do if this OID doesn't match the value
|
2002-11-28 06:48:42 +00:00
|
|
|
* attached to the frame or conversation? (That would be
|
|
|
|
* bogus, but that's not impossible - some broken implementation
|
|
|
|
* might negotiate some security mechanism but put the OID
|
|
|
|
* for some other security mechanism in GSS_Wrap tokens.)
|
|
|
|
*/
|
2005-06-20 10:22:03 +00:00
|
|
|
offset=dissect_ber_object_identifier(FALSE, pinfo, subtree, tvb, offset, hf_spnego_this_mech, oid);
|
2005-06-20 09:43:29 +00:00
|
|
|
next_level_value = gssapi_lookup_oid_str(oid);
|
2002-11-28 06:48:42 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now dissect the GSS_Wrap token; it's assumed to be in the
|
|
|
|
* rest of the tvbuff.
|
|
|
|
*/
|
|
|
|
item = proto_tree_add_item(tree, hf_spnego_wraptoken, tvb, offset,
|
|
|
|
-1, FALSE);
|
|
|
|
|
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego_wraptoken);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now, we should be able to dispatch after creating a new TVB.
|
|
|
|
* The subdissector must return the length of the part of the
|
|
|
|
* token it dissected, so we can return the length of the part
|
|
|
|
* we (and it) dissected.
|
|
|
|
*/
|
|
|
|
|
|
|
|
token_tvb = tvb_new_subset(tvb, offset, -1, -1);
|
|
|
|
if (next_level_value->wrap_handle) {
|
|
|
|
len = call_dissector(next_level_value->wrap_handle, token_tvb, pinfo, subtree);
|
|
|
|
if (len == 0)
|
|
|
|
return_offset = tvb_length(tvb);
|
|
|
|
else
|
|
|
|
return_offset = offset + len;
|
|
|
|
} else
|
|
|
|
return_offset = tvb_length(tvb);
|
|
|
|
done:
|
|
|
|
|
|
|
|
return return_offset;
|
|
|
|
}
|
|
|
|
|
2002-08-27 15:46:17 +00:00
|
|
|
void
|
2002-08-28 02:30:18 +00:00
|
|
|
proto_register_spnego(void)
|
2002-08-27 15:46:17 +00:00
|
|
|
{
|
|
|
|
static hf_register_info hf[] = {
|
2002-08-27 23:21:53 +00:00
|
|
|
{ &hf_spnego,
|
2002-08-28 21:04:11 +00:00
|
|
|
{ "SPNEGO", "spnego", FT_NONE, BASE_NONE, NULL, 0x0,
|
2002-08-27 23:21:53 +00:00
|
|
|
"SPNEGO", HFILL }},
|
2005-06-20 10:22:03 +00:00
|
|
|
{ &hf_spnego_mech, {
|
|
|
|
"Mech", "spnego.mech", FT_STRING, BASE_NONE,
|
|
|
|
NULL, 0, "This is a SPNEGO Object Identifier", HFILL }},
|
2005-09-11 21:10:20 +00:00
|
|
|
{ &hf_spnego_supportedMech, {
|
|
|
|
"supportedMech", "spnego.supportedMech", FT_STRING, BASE_NONE,
|
|
|
|
NULL, 0, "This is a SPNEGO Object Identifier", HFILL }},
|
|
|
|
{&hf_spnego_krb5_oid, {
|
|
|
|
"KRB5 OID", "spnego.krb5_oid", FT_STRING, BASE_NONE,
|
|
|
|
NULL, 0, "KRB5 OID", HFILL }},
|
2005-06-20 10:22:03 +00:00
|
|
|
{ &hf_spnego_this_mech, {
|
|
|
|
"thisMech", "spnego.this_mech", FT_STRING, BASE_NONE,
|
2005-06-20 09:43:29 +00:00
|
|
|
NULL, 0, "This is a SPNEGO Object Identifier", HFILL }},
|
2002-08-28 21:04:11 +00:00
|
|
|
{ &hf_spnego_negtokeninit,
|
2002-08-28 01:15:23 +00:00
|
|
|
{ "negTokenInit", "spnego.negtokeninit", FT_NONE, BASE_NONE,
|
|
|
|
NULL, 0x0, "SPNEGO negTokenInit", HFILL}},
|
|
|
|
{ &hf_spnego_negtokentarg,
|
|
|
|
{ "negTokenTarg", "spnego.negtokentarg", FT_NONE, BASE_NONE,
|
|
|
|
NULL, 0x0, "SPNEGO negTokenTarg", HFILL}},
|
|
|
|
{ &hf_spnego_mechtype,
|
2002-08-28 21:04:11 +00:00
|
|
|
{ "mechType", "spnego.negtokeninit.mechtype", FT_NONE,
|
2002-08-28 01:15:23 +00:00
|
|
|
BASE_NONE, NULL, 0x0, "SPNEGO negTokenInit mechTypes", HFILL}},
|
2002-08-31 17:09:45 +00:00
|
|
|
{ &hf_spnego_mechtoken,
|
|
|
|
{ "mechToken", "spnego.negtokeninit.mechtoken", FT_NONE,
|
|
|
|
BASE_NONE, NULL, 0x0, "SPNEGO negTokenInit mechToken", HFILL}},
|
|
|
|
{ &hf_spnego_mechlistmic,
|
|
|
|
{ "mechListMIC", "spnego.mechlistmic", FT_NONE,
|
|
|
|
BASE_NONE, NULL, 0x0, "SPNEGO mechListMIC", HFILL}},
|
|
|
|
{ &hf_spnego_responsetoken,
|
|
|
|
{ "responseToken", "spnego.negtokentarg.responsetoken",
|
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO responseToken",
|
|
|
|
HFILL}},
|
2002-08-29 22:53:06 +00:00
|
|
|
{ &hf_spnego_negtokentarg_negresult,
|
|
|
|
{ "negResult", "spnego.negtokeninit.negresult", FT_UINT16,
|
|
|
|
BASE_HEX, VALS(spnego_negResult_vals), 0, "negResult", HFILL}},
|
2002-09-04 06:54:45 +00:00
|
|
|
{ &hf_spnego_reqflags,
|
|
|
|
{ "reqFlags", "spnego.negtokeninit.reqflags", FT_BYTES,
|
2002-09-05 03:49:03 +00:00
|
|
|
BASE_HEX, NULL, 0, "reqFlags", HFILL }},
|
2003-05-25 00:36:30 +00:00
|
|
|
{ &hf_gssapi_reqflags_deleg,
|
|
|
|
{ "Delegation", "gssapi.reqflags.deleg", FT_BOOLEAN, 8,
|
|
|
|
TFS(&tfs_reqflags_deleg), 0x01, "Delegation", HFILL }},
|
|
|
|
{ &hf_gssapi_reqflags_mutual,
|
|
|
|
{ "Mutual Authentication", "gssapi.reqflags.mutual", FT_BOOLEAN,
|
|
|
|
8, TFS(&tfs_reqflags_mutual), 0x02, "Mutual Authentication", HFILL}},
|
|
|
|
{ &hf_gssapi_reqflags_replay,
|
|
|
|
{ "Replay Detection", "gssapi.reqflags.replay", FT_BOOLEAN,
|
|
|
|
8, TFS(&tfs_reqflags_replay), 0x04, "Replay Detection", HFILL}},
|
|
|
|
{ &hf_gssapi_reqflags_sequence,
|
|
|
|
{ "Out-of-sequence Detection", "gssapi.reqflags.sequence",
|
|
|
|
FT_BOOLEAN, 8, TFS(&tfs_reqflags_sequence), 0x08,
|
|
|
|
"Out-of-sequence Detection", HFILL}},
|
|
|
|
{ &hf_gssapi_reqflags_anon,
|
|
|
|
{ "Anonymous Authentication", "gssapi.reqflags.anon",
|
|
|
|
FT_BOOLEAN, 8, TFS(&tfs_reqflags_anon), 0x10,
|
|
|
|
"Anonymous Authentication", HFILL}},
|
|
|
|
{ &hf_gssapi_reqflags_conf,
|
|
|
|
{ "Per-message Confidentiality", "gssapi.reqflags.conf",
|
|
|
|
FT_BOOLEAN, 8, TFS(&tfs_reqflags_conf), 0x20,
|
|
|
|
"Per-message Confidentiality", HFILL}},
|
|
|
|
{ &hf_gssapi_reqflags_integ,
|
|
|
|
{ "Per-message Integrity", "gssapi.reqflags.integ",
|
|
|
|
FT_BOOLEAN, 8, TFS(&tfs_reqflags_integ), 0x40,
|
|
|
|
"Per-message Integrity", HFILL}},
|
2002-11-28 06:48:42 +00:00
|
|
|
{ &hf_spnego_wraptoken,
|
|
|
|
{ "wrapToken", "spnego.wraptoken",
|
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO wrapToken",
|
|
|
|
HFILL}},
|
2002-09-05 03:49:03 +00:00
|
|
|
{ &hf_spnego_krb5,
|
|
|
|
{ "krb5_blob", "spnego.krb5.blob", FT_BYTES,
|
2002-11-28 06:48:42 +00:00
|
|
|
BASE_NONE, NULL, 0, "krb5_blob", HFILL }},
|
2002-09-06 05:41:17 +00:00
|
|
|
{ &hf_spnego_krb5_tok_id,
|
|
|
|
{ "krb5_tok_id", "spnego.krb5.tok_id", FT_UINT16, BASE_HEX,
|
2002-11-28 06:48:42 +00:00
|
|
|
VALS(spnego_krb5_tok_id_vals), 0, "KRB5 Token Id", HFILL}},
|
|
|
|
{ &hf_spnego_krb5_sgn_alg,
|
|
|
|
{ "krb5_sgn_alg", "spnego.krb5.sgn_alg", FT_UINT16, BASE_HEX,
|
|
|
|
VALS(spnego_krb5_sgn_alg_vals), 0, "KRB5 Signing Algorithm", HFILL}},
|
|
|
|
{ &hf_spnego_krb5_seal_alg,
|
|
|
|
{ "krb5_seal_alg", "spnego.krb5.seal_alg", FT_UINT16, BASE_HEX,
|
|
|
|
VALS(spnego_krb5_seal_alg_vals), 0, "KRB5 Sealing Algorithm", HFILL}},
|
|
|
|
{ &hf_spnego_krb5_snd_seq,
|
|
|
|
{ "krb5_snd_seq", "spnego.krb5.snd_seq", FT_BYTES, BASE_NONE,
|
|
|
|
NULL, 0, "KRB5 Encrypted Sequence Number", HFILL}},
|
|
|
|
{ &hf_spnego_krb5_sgn_cksum,
|
|
|
|
{ "krb5_sgn_cksum", "spnego.krb5.sgn_cksum", FT_BYTES, BASE_NONE,
|
|
|
|
NULL, 0, "KRB5 Data Checksum", HFILL}},
|
|
|
|
{ &hf_spnego_krb5_confounder,
|
|
|
|
{ "krb5_confounder", "spnego.krb5.confounder", FT_BYTES, BASE_NONE,
|
|
|
|
NULL, 0, "KRB5 Confounder", HFILL}},
|
2002-08-27 15:46:17 +00:00
|
|
|
};
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2002-08-27 15:46:17 +00:00
|
|
|
static gint *ett[] = {
|
2002-08-27 23:21:53 +00:00
|
|
|
&ett_spnego,
|
2002-08-28 01:15:23 +00:00
|
|
|
&ett_spnego_negtokeninit,
|
|
|
|
&ett_spnego_negtokentarg,
|
|
|
|
&ett_spnego_mechtype,
|
2002-08-31 17:09:45 +00:00
|
|
|
&ett_spnego_mechtoken,
|
|
|
|
&ett_spnego_mechlistmic,
|
|
|
|
&ett_spnego_responsetoken,
|
2002-11-28 06:48:42 +00:00
|
|
|
&ett_spnego_wraptoken,
|
2002-09-05 03:49:03 +00:00
|
|
|
&ett_spnego_krb5,
|
2002-08-27 15:46:17 +00:00
|
|
|
};
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2002-08-27 23:21:53 +00:00
|
|
|
proto_spnego = proto_register_protocol(
|
|
|
|
"Spnego", "Spnego", "spnego");
|
2002-09-05 03:49:03 +00:00
|
|
|
proto_spnego_krb5 = proto_register_protocol("SPNEGO-KRB5",
|
|
|
|
"SPNEGO-KRB5",
|
|
|
|
"spnego-krb5");
|
2002-08-27 15:46:17 +00:00
|
|
|
|
2002-08-27 23:21:53 +00:00
|
|
|
proto_register_field_array(proto_spnego, hf, array_length(hf));
|
2002-08-27 15:46:17 +00:00
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-08-27 23:21:53 +00:00
|
|
|
proto_reg_handoff_spnego(void)
|
2002-08-27 15:46:17 +00:00
|
|
|
{
|
2002-11-28 06:48:42 +00:00
|
|
|
dissector_handle_t spnego_handle, spnego_wrap_handle;
|
|
|
|
dissector_handle_t spnego_krb5_handle, spnego_krb5_wrap_handle;
|
2002-08-31 22:22:29 +00:00
|
|
|
|
2002-08-27 15:46:17 +00:00
|
|
|
/* Register protocol with GSS-API module */
|
|
|
|
|
2002-08-31 22:22:29 +00:00
|
|
|
spnego_handle = create_dissector_handle(dissect_spnego, proto_spnego);
|
2002-11-28 06:48:42 +00:00
|
|
|
spnego_wrap_handle = new_create_dissector_handle(dissect_spnego_wrap,
|
|
|
|
proto_spnego);
|
2002-08-31 22:22:29 +00:00
|
|
|
gssapi_init_oid("1.3.6.1.5.5.2", proto_spnego, ett_spnego,
|
2002-11-28 06:48:42 +00:00
|
|
|
spnego_handle, spnego_wrap_handle,
|
|
|
|
"SPNEGO - Simple Protected Negotiation");
|
2002-09-05 03:49:03 +00:00
|
|
|
|
|
|
|
/* Register both the one MS created and the real one */
|
2003-02-17 17:32:59 +00:00
|
|
|
/*
|
|
|
|
* Thanks to Jean-Baptiste Marchand and Richard B Ward, the
|
|
|
|
* mystery of the MS KRB5 OID is cleared up. It was due to a library
|
|
|
|
* that did not handle OID components greater than 16 bits, and was
|
|
|
|
* fixed in Win2K SP2 as well as WinXP.
|
|
|
|
* See the archive of <ietf-krb-wg@anl.gov> for the thread topic
|
|
|
|
* SPNEGO implementation issues. 3-Dec-2002.
|
|
|
|
*/
|
2002-11-28 06:48:42 +00:00
|
|
|
spnego_krb5_handle = create_dissector_handle(dissect_spnego_krb5,
|
|
|
|
proto_spnego_krb5);
|
|
|
|
spnego_krb5_wrap_handle = new_create_dissector_handle(dissect_spnego_krb5_wrap,
|
|
|
|
proto_spnego_krb5);
|
2002-09-05 03:49:03 +00:00
|
|
|
gssapi_init_oid("1.2.840.48018.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
|
2002-11-28 06:48:42 +00:00
|
|
|
spnego_krb5_handle, spnego_krb5_wrap_handle,
|
|
|
|
"MS KRB5 - Microsoft Kerberos 5");
|
2002-09-05 03:49:03 +00:00
|
|
|
gssapi_init_oid("1.2.840.113554.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
|
2002-11-28 06:48:42 +00:00
|
|
|
spnego_krb5_handle, spnego_krb5_wrap_handle,
|
|
|
|
"KRB5 - Kerberos 5");
|
2003-07-17 22:17:01 +00:00
|
|
|
gssapi_init_oid("1.2.840.113554.1.2.2.3", proto_spnego_krb5, ett_spnego_krb5,
|
|
|
|
spnego_krb5_handle, spnego_krb5_wrap_handle,
|
|
|
|
"KRB5 - Kerberos 5 - User to User");
|
2003-06-01 20:34:20 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the data handle for some calls
|
|
|
|
*/
|
|
|
|
data_handle = find_dissector("data");
|
2002-08-27 15:46:17 +00:00
|
|
|
}
|