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>
|
2002-08-27 15:46:17 +00:00
|
|
|
*
|
2002-10-05 06:26:42 +00:00
|
|
|
* $Id: packet-spnego.c,v 1.36 2002/10/05 06:26:42 sharpe Exp $
|
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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
# include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <epan/packet.h>
|
|
|
|
|
|
|
|
#include "asn1.h"
|
|
|
|
#include "format-oid.h"
|
|
|
|
#include "packet-gssapi.h"
|
2002-09-07 00:29:29 +00:00
|
|
|
#include "packet-kerberos.h"
|
2002-09-08 22:47:43 +00:00
|
|
|
#include <epan/conversation.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;
|
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-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-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-09-05 03:49:03 +00:00
|
|
|
static gint ett_spnego_krb5 = -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
|
|
|
};
|
|
|
|
|
2002-08-27 23:21:53 +00:00
|
|
|
/* Display an ASN1 parse error. Taken from packet-snmp.c */
|
|
|
|
|
|
|
|
static dissector_handle_t data_handle;
|
|
|
|
|
|
|
|
static void
|
|
|
|
dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|
|
|
proto_tree *tree, const char *field_name, int ret)
|
|
|
|
{
|
|
|
|
char *errstr;
|
|
|
|
|
|
|
|
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
|
|
|
|
* wrapped blob with an OID, Boolean, and a Ticket, that is also ASN.1 wrapped
|
|
|
|
* by the looks of it.
|
|
|
|
*/
|
|
|
|
|
2002-09-06 05:41:17 +00:00
|
|
|
#define KRB_TOKEN_AP_REQ 0x0001
|
|
|
|
#define KRB_TOKEN_AP_REP 0x0002
|
|
|
|
#define KRB_TOKEN_AP_ERR 0x0003
|
|
|
|
|
|
|
|
static const value_string spnego_krb5_tok_id_vals[] = {
|
|
|
|
{ KRB_TOKEN_AP_REQ, "KRB5_AP_REQ"},
|
|
|
|
{ KRB_TOKEN_AP_REP, "KRB5_AP_REP"},
|
|
|
|
{ KRB_TOKEN_AP_ERR, "KRB5_ERROR"},
|
|
|
|
{ 0, NULL}
|
|
|
|
};
|
|
|
|
|
2002-09-05 03:49:03 +00:00
|
|
|
static void
|
|
|
|
dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
|
|
{
|
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
|
|
|
int ret, offset = 0;
|
|
|
|
ASN1_SCK hnd;
|
|
|
|
gboolean def;
|
|
|
|
guint len1, cls, con, tag, oid_len, nbytes;
|
|
|
|
subid_t *oid;
|
|
|
|
gchar *oid_string;
|
|
|
|
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-09-05 03:49:03 +00:00
|
|
|
* APLICATION (0) {
|
|
|
|
* OID,
|
2002-09-08 02:45:26 +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
|
|
|
*
|
|
|
|
* However, for some protocols, the KRB5 blob stars at the SHORT
|
|
|
|
* and has no DER encoded header etc.
|
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-05 06:26:42 +00:00
|
|
|
if ((cls == ASN1_APL && con == ASN1_CON && tag == 0)) {
|
|
|
|
/* proto_tree_add_text(
|
2002-09-05 03:49:03 +00:00
|
|
|
subtree, tvb, offset, 0,
|
|
|
|
"Unknown header (cls=%d, con=%d, tag=%d)",
|
|
|
|
cls, con, tag);
|
|
|
|
goto done;
|
2002-10-05 06:26:42 +00:00
|
|
|
}*/
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-05 06:26:42 +00:00
|
|
|
offset = hnd.offset;
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-05 06:26:42 +00:00
|
|
|
/* Next, the OID */
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-05 06:26:42 +00:00
|
|
|
ret = asn1_oid_decode(&hnd, &oid, &oid_len, &nbytes);
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-05 06:26:42 +00:00
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, subtree,
|
|
|
|
"SPNEGO supportedMech token", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-05 06:26:42 +00:00
|
|
|
oid_string = format_oid(oid, oid_len);
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-05 06:26:42 +00:00
|
|
|
value = gssapi_lookup_oid(oid, oid_len);
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-05 06:26:42 +00:00
|
|
|
if (value)
|
|
|
|
proto_tree_add_text(subtree, tvb, offset, nbytes,
|
|
|
|
"OID: %s (%s)",
|
|
|
|
oid_string, value->comment);
|
|
|
|
else
|
|
|
|
proto_tree_add_text(subtree, tvb, offset, oid_len, "OID: %s",
|
|
|
|
oid_string);
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-10-05 06:26:42 +00:00
|
|
|
g_free(oid_string);
|
2002-09-08 01:43:44 +00:00
|
|
|
|
2002-10-05 06:26:42 +00:00
|
|
|
offset += nbytes;
|
|
|
|
}
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-09-06 05:41:17 +00:00
|
|
|
/* Next, the token ID ... */
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-09-06 05:41:17 +00:00
|
|
|
proto_tree_add_item(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
|
|
|
|
TRUE);
|
2002-09-05 03:49:03 +00:00
|
|
|
|
|
|
|
|
2002-09-06 05:41:17 +00:00
|
|
|
hnd.offset += 2;
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-09-06 05:41:17 +00:00
|
|
|
offset += 2;
|
2002-09-05 03:49:03 +00:00
|
|
|
|
2002-09-07 03:32:49 +00:00
|
|
|
krb5_tvb = tvb_new_subset(tvb, offset, -1, -1);
|
|
|
|
|
|
|
|
offset = dissect_kerberos_main(krb5_tvb, pinfo, subtree, FALSE);
|
2002-09-05 03:49:03 +00:00
|
|
|
|
|
|
|
done:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Spnego stuff from here */
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
static int
|
2002-08-28 01:15:23 +00:00
|
|
|
dissect_spnego_mechTypes(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_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-08-28 01:15:23 +00:00
|
|
|
gboolean def;
|
|
|
|
guint len1, len, cls, con, tag, nbytes;
|
|
|
|
subid_t *oid;
|
|
|
|
gchar *oid_string;
|
2002-08-30 00:32:11 +00:00
|
|
|
int ret;
|
2002-09-08 22:47:43 +00:00
|
|
|
gboolean saw_mechanism = FALSE;
|
2002-08-30 16:17:29 +00:00
|
|
|
|
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
|
|
|
*/
|
|
|
|
|
|
|
|
ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len1);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, subtree,
|
|
|
|
"SPNEGO last 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-28 05:02:41 +00:00
|
|
|
offset = hnd->offset;
|
|
|
|
|
2002-08-31 17:09:45 +00:00
|
|
|
item = proto_tree_add_item(tree, hf_spnego_mechtype, tvb, 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
|
|
|
/*
|
2002-08-28 21:04:11 +00:00
|
|
|
* Now, the object IDs ... We should translate them: FIXME
|
2002-08-28 01:15:23 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
while (len1) {
|
2002-09-04 21:34:38 +00:00
|
|
|
gssapi_oid_value *value;
|
2002-08-28 01:15:23 +00:00
|
|
|
|
|
|
|
ret = asn1_oid_decode(hnd, &oid, &len, &nbytes);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, subtree,
|
2002-08-31 20:50:08 +00:00
|
|
|
"SPNEGO mechTypes token", ret);
|
2002-08-28 01:15:23 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2002-08-28 02:30:18 +00:00
|
|
|
oid_string = format_oid(oid, len);
|
2002-09-08 01:43:44 +00:00
|
|
|
value = gssapi_lookup_oid(oid, len);
|
2002-09-04 21:34:38 +00:00
|
|
|
if (value)
|
|
|
|
proto_tree_add_text(subtree, tvb, offset, nbytes, "OID: %s (%s)",
|
|
|
|
oid_string, value->comment);
|
|
|
|
else
|
|
|
|
proto_tree_add_text(subtree, tvb, offset, nbytes, "OID: %s",
|
|
|
|
oid_string);
|
2002-08-28 01:15:23 +00:00
|
|
|
|
2002-09-08 01:43:44 +00:00
|
|
|
g_free(oid_string);
|
|
|
|
|
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)
|
|
|
|
*next_level_dissector_p = value->handle;
|
|
|
|
saw_mechanism = TRUE;
|
|
|
|
}
|
|
|
|
|
2002-08-28 01:15:23 +00:00
|
|
|
offset += nbytes;
|
|
|
|
len1 -= nbytes;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
guint len1, cls, con, tag;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
proto_tree_add_item(tree, hf_spnego_reqflags, tvb, offset, len1,
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
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;
|
2002-08-30 16:17:29 +00:00
|
|
|
guint cls, con, tag, nbytes;
|
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;
|
|
|
|
|
2002-08-31 17:09:45 +00:00
|
|
|
item = proto_tree_add_item(tree, hf_spnego_mechtoken, tvb, offset,
|
|
|
|
nbytes, FALSE);
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
token_tvb = tvb_new_subset(tvb, offset, nbytes, -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-30 05:04:52 +00:00
|
|
|
|
|
|
|
hnd->offset += nbytes; /* Update this ... */
|
|
|
|
|
|
|
|
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,
|
|
|
|
dissector_handle_t *next_level_dissector_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:
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
offset = dissect_spnego_mechTypes(tvb, offset, pinfo,
|
2002-09-08 22:47:43 +00:00
|
|
|
subtree, hnd,
|
|
|
|
next_level_dissector_p);
|
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,
|
2002-09-08 22:47:43 +00:00
|
|
|
hnd, *next_level_dissector_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,
|
2002-09-08 22:47:43 +00:00
|
|
|
hnd, *next_level_dissector_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,
|
|
|
|
dissector_handle_t *next_level_dissector_p)
|
2002-08-29 22:53:06 +00:00
|
|
|
{
|
2002-08-30 00:32:11 +00:00
|
|
|
int ret;
|
2002-09-08 01:43:44 +00:00
|
|
|
guint oid_len, nbytes;
|
2002-08-30 00:32:11 +00:00
|
|
|
subid_t *oid;
|
2002-09-08 01:43:44 +00:00
|
|
|
gchar *oid_string;
|
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;
|
|
|
|
|
|
|
|
ret = asn1_oid_decode(hnd, &oid, &oid_len, &nbytes);
|
|
|
|
|
|
|
|
if (ret != ASN1_ERR_NOERROR) {
|
|
|
|
dissect_parse_error(tvb, offset, pinfo, tree,
|
|
|
|
"SPNEGO supportedMech token", ret);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
oid_string = format_oid(oid, oid_len);
|
2002-09-08 01:43:44 +00:00
|
|
|
value = gssapi_lookup_oid(oid, oid_len);
|
2002-09-04 22:20:57 +00:00
|
|
|
|
2002-09-04 21:34:38 +00:00
|
|
|
if (value)
|
|
|
|
proto_tree_add_text(tree, tvb, offset, nbytes,
|
|
|
|
"supportedMech: %s (%s)",
|
|
|
|
oid_string, value->comment);
|
|
|
|
else
|
|
|
|
proto_tree_add_text(tree, tvb, offset, nbytes, "supportedMech: %s",
|
|
|
|
oid_string);
|
2002-08-30 00:32:11 +00:00
|
|
|
|
2002-09-08 01:43:44 +00:00
|
|
|
g_free(oid_string);
|
|
|
|
|
|
|
|
offset += nbytes;
|
|
|
|
|
2002-08-30 00:32:11 +00:00
|
|
|
/* Should check for an unrecognized OID ... */
|
|
|
|
|
2002-09-08 22:47:43 +00:00
|
|
|
if (value)
|
|
|
|
*next_level_dissector_p = value->handle;
|
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
|
|
|
*/
|
|
|
|
|
2002-08-30 16:17:29 +00:00
|
|
|
if ((conversation = find_conversation(&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-09-08 22:47:43 +00:00
|
|
|
*next_level_dissector_p);
|
2002-08-30 04:04:39 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
}
|
2002-08-30 00:32:11 +00:00
|
|
|
|
|
|
|
done:
|
|
|
|
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;
|
|
|
|
|
2002-08-31 17:09:45 +00:00
|
|
|
item = proto_tree_add_item(tree, hf_spnego_responsetoken, tvb, offset,
|
|
|
|
nbytes, FALSE);
|
|
|
|
|
|
|
|
subtree = proto_item_add_subtree(item, ett_spnego_responsetoken);
|
2002-08-30 00:32:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now, we should be able to dispatch after creating a new TVB.
|
|
|
|
*/
|
|
|
|
|
|
|
|
token_tvb = tvb_new_subset(tvb, offset, nbytes, -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-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,
|
|
|
|
dissector_handle_t *next_level_dissector_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-09-08 22:47:43 +00:00
|
|
|
hnd, next_level_dissector_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,
|
2002-09-08 22:47:43 +00:00
|
|
|
hnd, *next_level_dissector_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,
|
2002-09-08 22:47:43 +00:00
|
|
|
hnd, *next_level_dissector_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
|
|
|
|
dissect_spnego(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
|
|
{
|
|
|
|
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-09-08 22:47:43 +00:00
|
|
|
dissector_handle_t next_level_dissector = NULL;
|
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 ...
|
|
|
|
*/
|
|
|
|
|
|
|
|
conversation = find_conversation(&pinfo->src, &pinfo->dst,
|
|
|
|
pinfo->ptype, pinfo->srcport,
|
|
|
|
pinfo->destport, 0);
|
|
|
|
|
2002-09-08 22:47:43 +00:00
|
|
|
if (conversation)
|
|
|
|
next_level_dissector = conversation_get_proto_data(conversation,
|
|
|
|
proto_spnego);
|
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,
|
|
|
|
&next_level_dissector);
|
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,
|
|
|
|
&next_level_dissector);
|
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
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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 }},
|
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 }},
|
|
|
|
{ &hf_spnego_krb5,
|
|
|
|
{ "krb5_blob", "spnego.krb5.blob", FT_BYTES,
|
|
|
|
BASE_HEX, 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,
|
|
|
|
VALS(spnego_krb5_tok_id_vals), 0, "KRB5 Token Ids", 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-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-09-05 03:49:03 +00:00
|
|
|
dissector_handle_t spnego_handle, spnego_krb5_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-09-05 03:49:03 +00:00
|
|
|
spnego_krb5_handle = create_dissector_handle(dissect_spnego_krb5,
|
|
|
|
proto_spnego_krb5);
|
2002-08-31 22:22:29 +00:00
|
|
|
gssapi_init_oid("1.3.6.1.5.5.2", proto_spnego, ett_spnego,
|
2002-09-18 08:36:25 +00:00
|
|
|
spnego_handle, "SPNEGO - Simple Protected Negotiation");
|
2002-09-05 03:49:03 +00:00
|
|
|
|
|
|
|
/* Register both the one MS created and the real one */
|
|
|
|
gssapi_init_oid("1.2.840.48018.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
|
2002-09-18 08:36:25 +00:00
|
|
|
spnego_krb5_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-09-18 08:36:25 +00:00
|
|
|
spnego_krb5_handle, "KRB5 - Kerberos 5");
|
2002-08-27 15:46:17 +00:00
|
|
|
}
|