aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-spnego.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-spnego.c')
-rw-r--r--epan/dissectors/packet-spnego.c1534
1 files changed, 519 insertions, 1015 deletions
diff --git a/epan/dissectors/packet-spnego.c b/epan/dissectors/packet-spnego.c
index abf57e6112..00ec3f5fce 100644
--- a/epan/dissectors/packet-spnego.c
+++ b/epan/dissectors/packet-spnego.c
@@ -1,3 +1,10 @@
+/* Do not modify this file. */
+/* It is created automatically by the ASN.1 to Ethereal dissector compiler */
+/* .\packet-spnego.c */
+/* ../../tools/asn2eth.py -X -b -e -p spnego -c spnego.cnf -s packet-spnego-template spnego.asn */
+
+/* Input file: packet-spnego-template.c */
+
/* packet-spnego.c
* Routines for the simple and protected GSS-API negotiation mechanism
* as described in RFC 2478.
@@ -5,6 +12,7 @@
* Copyright 2002, Richard Sharpe <rsharpe@ns.aus.com>
* Copyright 2003, Richard Sharpe <rsharpe@richardsharpe.com>
* Copyright 2005, Ronnie Sahlberg (krb decryption)
+ * Copyright 2005, Anders Broman (converted to asn2eth generated dissector)
*
* $Id$
*
@@ -29,20 +37,13 @@
/* The heimdal code for decryption of GSSAPI wrappers using heimdal comes from
Heimdal 1.6 and has been modified for ethereal's requirements.
*/
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#include <string.h>
#include <glib.h>
#include <epan/packet.h>
-
-#include <epan/asn1.h>
-#include "packet-ber.h"
#include "packet-dcerpc.h"
#include "packet-gssapi.h"
#include "packet-kerberos.h"
@@ -50,36 +51,24 @@
#include <epan/conversation.h>
#include <epan/emem.h>
-#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
-#define SPNEGO_negResult_accept_completed 0
-#define SPNEGO_negResult_accept_incomplete 1
-#define SPNEGO_negResult_accept_reject 2
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-ber.h"
+
+#define PNAME "Simple Protected Negotiation"
+#define PSNAME "SPNEGO"
+#define PFNAME "spnego"
+
+/* Initialize the protocol and registered fields */
static int proto_spnego = -1;
static int proto_spnego_krb5 = -1;
+
static int hf_spnego = -1;
-static int hf_spnego_mech = -1;
-static int hf_spnego_supportedMech = -1;
-static int hf_spnego_krb5_oid = -1;
-static int hf_spnego_this_mech = -1;
-static int hf_spnego_negtokeninit = -1;
-static int hf_spnego_negtokentarg = -1;
-static int hf_spnego_mechtype = -1;
-static int hf_spnego_mechtoken = -1;
-static int hf_spnego_negtokentarg_negresult = -1;
-static int hf_spnego_mechlistmic = -1;
-static int hf_spnego_responsetoken = -1;
-static int hf_spnego_reqflags = -1;
static int hf_spnego_wraptoken = -1;
+static int hf_spnego_krb5_oid;
static int hf_spnego_krb5 = -1;
static int hf_spnego_krb5_tok_id = -1;
static int hf_spnego_krb5_sgn_alg = -1;
@@ -87,100 +76,375 @@ 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;
-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;
-
-static gint ett_spnego = -1;
-static gint ett_spnego_negtokeninit = -1;
-static gint ett_spnego_negtokentarg = -1;
-static gint ett_spnego_mechtype = -1;
-static gint ett_spnego_mechtoken = -1;
-static gint ett_spnego_mechlistmic = -1;
-static gint ett_spnego_responsetoken = -1;
-static gint ett_spnego_wraptoken = -1;
+
+
+/*--- Included file: packet-spnego-hf.c ---*/
+
+static int hf_spnego_negTokenInit = -1; /* NegTokenInit */
+static int hf_spnego_negTokenTarg = -1; /* NegTokenTarg */
+static int hf_spnego_MechTypeList_item = -1; /* MechType */
+static int hf_spnego_mechTypes = -1; /* MechTypeList */
+static int hf_spnego_reqFlags = -1; /* ContextFlags */
+static int hf_spnego_mechToken = -1; /* T_mechToken */
+static int hf_spnego_mechListMIC = -1; /* OCTET_STRING */
+static int hf_spnego_negResult = -1; /* T_negResult */
+static int hf_spnego_supportedMech = -1; /* MechType */
+static int hf_spnego_responseToken = -1; /* OCTET_STRING */
+static int hf_spnego_thisMech = -1; /* MechType */
+static int hf_spnego_innerContextToken = -1; /* InnerContextToken */
+/* named bits */
+static int hf_spnego_ContextFlags_delegFlag = -1;
+static int hf_spnego_ContextFlags_mutualFlag = -1;
+static int hf_spnego_ContextFlags_replayFlag = -1;
+static int hf_spnego_ContextFlags_sequenceFlag = -1;
+static int hf_spnego_ContextFlags_anonFlag = -1;
+static int hf_spnego_ContextFlags_confFlag = -1;
+static int hf_spnego_ContextFlags_integFlag = -1;
+
+/*--- End of included file: packet-spnego-hf.c ---*/
+
+
+/* Global variables */
+gchar MechType_oid[MAX_OID_STR_LEN];
+gssapi_oid_value *next_level_value;
+gboolean saw_mechanism = FALSE;
+
+
+/* Initialize the subtree pointers */
+static gint ett_spnego;
+static gint ett_spnego_wraptoken;
static gint ett_spnego_krb5 = -1;
-static gint ett_spnego_reqflags = -1;
-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"},
- { 0, NULL}
-};
-/*
- * These should be in the GSSAPI dissector ... XXX
- */
+/*--- Included file: packet-spnego-ett.c ---*/
+
+static gint ett_spnego_NegotiationToken = -1;
+static gint ett_spnego_MechTypeList = -1;
+static gint ett_spnego_NegTokenInit = -1;
+static gint ett_spnego_ContextFlags = -1;
+static gint ett_spnego_NegTokenTarg = -1;
+static gint ett_spnego_InitialContextToken = -1;
+
+/*--- End of included file: packet-spnego-ett.c ---*/
+
+
+static dissector_handle_t data_handle;
+
+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;
+}
+
+
+
+/*--- Included file: packet-spnego-fn.c ---*/
+
+/*--- Fields for imported types ---*/
+
+
+
-static const true_false_string tfs_reqflags_deleg = {
- "Delegation Requested",
- "Delegation NOT Requested"
+static int
+dissect_spnego_MechType(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
+
+ gssapi_oid_value *value;
+
+ offset = dissect_ber_object_identifier(implicit_tag, pinfo, tree, tvb, offset, hf_index,
+ MechType_oid);
+
+
+ value = gssapi_lookup_oid_str(MechType_oid);
+
+ /*
+ * 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_value = value;
+ saw_mechanism = TRUE;
+ }
+
+
+ return offset;
+}
+static int dissect_MechTypeList_item(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_MechType(FALSE, tvb, offset, pinfo, tree, hf_spnego_MechTypeList_item);
+}
+static int dissect_supportedMech(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_MechType(FALSE, tvb, offset, pinfo, tree, hf_spnego_supportedMech);
+}
+static int dissect_thisMech(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_MechType(FALSE, tvb, offset, pinfo, tree, hf_spnego_thisMech);
+}
+
+
+static const ber_sequence_t MechTypeList_sequence_of[1] = {
+ { BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_MechTypeList_item },
};
-static const true_false_string tfs_reqflags_mutual = {
- "Mutual Authentication Requested",
- "Mutual Authentication NOT Requested"
+static int
+dissect_spnego_MechTypeList(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
+
+
+ saw_mechanism = FALSE;
+
+ offset = dissect_ber_sequence_of(implicit_tag, pinfo, tree, tvb, offset,
+ MechTypeList_sequence_of, hf_index, ett_spnego_MechTypeList);
+
+ return offset;
+}
+static int dissect_mechTypes(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_MechTypeList(FALSE, tvb, offset, pinfo, tree, hf_spnego_mechTypes);
+}
+
+
+static const asn_namedbit ContextFlags_bits[] = {
+ { 0, &hf_spnego_ContextFlags_delegFlag, -1, -1, "delegFlag", NULL },
+ { 1, &hf_spnego_ContextFlags_mutualFlag, -1, -1, "mutualFlag", NULL },
+ { 2, &hf_spnego_ContextFlags_replayFlag, -1, -1, "replayFlag", NULL },
+ { 3, &hf_spnego_ContextFlags_sequenceFlag, -1, -1, "sequenceFlag", NULL },
+ { 4, &hf_spnego_ContextFlags_anonFlag, -1, -1, "anonFlag", NULL },
+ { 5, &hf_spnego_ContextFlags_confFlag, -1, -1, "confFlag", NULL },
+ { 6, &hf_spnego_ContextFlags_integFlag, -1, -1, "integFlag", NULL },
+ { 0, NULL, 0, 0, NULL, NULL }
};
-static const true_false_string tfs_reqflags_replay = {
- "Replay Detection Requested",
- "Replay Detection NOT Requested"
+static int
+dissect_spnego_ContextFlags(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
+ offset = dissect_ber_bitstring(implicit_tag, pinfo, tree, tvb, offset,
+ ContextFlags_bits, hf_index, ett_spnego_ContextFlags,
+ NULL);
+
+ return offset;
+}
+static int dissect_reqFlags(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_ContextFlags(FALSE, tvb, offset, pinfo, tree, hf_spnego_reqFlags);
+}
+
+
+
+static int
+dissect_spnego_T_mechToken(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
+
+ tvbuff_t *mechToken_tvb;
+
+
+ offset = dissect_ber_octet_string(implicit_tag, pinfo, tree, tvb, offset, hf_index,
+ &mechToken_tvb);
+
+
+
+ /*
+ * Now, we should be able to dispatch after creating a new TVB.
+ */
+
+ if (next_level_value)
+ call_dissector(gssapi_dissector_handle(next_level_value), mechToken_tvb, pinfo, tree);
+
+
+
+ return offset;
+}
+static int dissect_mechToken(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_T_mechToken(FALSE, tvb, offset, pinfo, tree, hf_spnego_mechToken);
+}
+
+
+
+static int
+dissect_spnego_OCTET_STRING(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
+ offset = dissect_ber_octet_string(implicit_tag, pinfo, tree, tvb, offset, hf_index,
+ NULL);
+
+ return offset;
+}
+static int dissect_mechListMIC(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_OCTET_STRING(FALSE, tvb, offset, pinfo, tree, hf_spnego_mechListMIC);
+}
+static int dissect_responseToken(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_OCTET_STRING(FALSE, tvb, offset, pinfo, tree, hf_spnego_responseToken);
+}
+
+
+static const ber_sequence_t NegTokenInit_sequence[] = {
+ { BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL, dissect_mechTypes },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_reqFlags },
+ { BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_mechToken },
+ { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL, dissect_mechListMIC },
+ { 0, 0, 0, NULL }
};
-static const true_false_string tfs_reqflags_sequence = {
- "Out-of-sequence Detection Requested",
- "Out-of-sequence Detection NOT Requested"
+static int
+dissect_spnego_NegTokenInit(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
+ offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
+ NegTokenInit_sequence, hf_index, ett_spnego_NegTokenInit);
+
+ return offset;
+}
+static int dissect_negTokenInit(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_NegTokenInit(FALSE, tvb, offset, pinfo, tree, hf_spnego_negTokenInit);
+}
+
+
+static const value_string spnego_T_negResult_vals[] = {
+ { 0, "accept-completed" },
+ { 1, "accept-incomplete" },
+ { 2, "reject" },
+ { 0, NULL }
};
-static const true_false_string tfs_reqflags_anon = {
- "Anonymous Authentication Requested",
- "Anonymous Authentication NOT Requested"
+
+static int
+dissect_spnego_T_negResult(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
+ offset = dissect_ber_integer(implicit_tag, pinfo, tree, tvb, offset, hf_index,
+ NULL);
+
+ return offset;
+}
+static int dissect_negResult(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_T_negResult(FALSE, tvb, offset, pinfo, tree, hf_spnego_negResult);
+}
+
+
+static const ber_sequence_t NegTokenTarg_sequence[] = {
+ { BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL, dissect_negResult },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_supportedMech },
+ { BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_responseToken },
+ { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL, dissect_mechListMIC },
+ { 0, 0, 0, NULL }
};
-static const true_false_string tfs_reqflags_conf = {
- "Per-message Confidentiality Requested",
- "Per-message Confidentiality NOT Requested"
+static int
+dissect_spnego_NegTokenTarg(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
+ offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
+ NegTokenTarg_sequence, hf_index, ett_spnego_NegTokenTarg);
+
+ return offset;
+}
+static int dissect_negTokenTarg(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_NegTokenTarg(FALSE, tvb, offset, pinfo, tree, hf_spnego_negTokenTarg);
+}
+
+
+static const value_string spnego_NegotiationToken_vals[] = {
+ { 0, "negTokenInit" },
+ { 1, "negTokenTarg" },
+ { 0, NULL }
};
-static const true_false_string tfs_reqflags_integ = {
- "Per-message Integrity Requested",
- "Per-message Integrity NOT Requested"
+static const ber_choice_t NegotiationToken_choice[] = {
+ { 0, BER_CLASS_CON, 0, 0, dissect_negTokenInit },
+ { 1, BER_CLASS_CON, 1, 0, dissect_negTokenTarg },
+ { 0, 0, 0, 0, NULL }
};
+static int
+dissect_spnego_NegotiationToken(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
+ offset = dissect_ber_choice(pinfo, tree, tvb, offset,
+ NegotiationToken_choice, hf_index, ett_spnego_NegotiationToken,
+ NULL);
-/* Display an ASN1 parse error. Taken from packet-snmp.c */
+ return offset;
+}
-static dissector_handle_t data_handle;
-static dissector_handle_t
-gssapi_dissector_handle(gssapi_oid_value *next_level_value) {
- if (next_level_value == NULL) {
- return NULL;
+
+static int
+dissect_spnego_InnerContextToken(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
+
+ conversation_t *conversation;
+ gssapi_oid_value *next_level_value;
+ proto_item *item;
+ proto_tree *subtree;
+ tvbuff_t *token_tvb;
+ int len;
+
+ 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.
+ */
+ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+ 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);
+ }
}
- return next_level_value->handle;
+
+ next_level_value = gssapi_lookup_oid_str(MechType_oid);
+ /*
+ * 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)
+ offset = tvb_length(tvb);
+ else
+ offset = offset + len;
+ } else
+
+ offset = tvb_length(tvb);
+
+
+
+ return offset;
+}
+static int dissect_innerContextToken(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
+ return dissect_spnego_InnerContextToken(FALSE, tvb, offset, pinfo, tree, hf_spnego_innerContextToken);
}
-static void
-dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, const char *field_name, int ret)
-{
- const char *errstr;
- errstr = asn1_err_to_str(ret);
+static const ber_sequence_t InitialContextToken_sequence[] = {
+ { BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_thisMech },
+ { BER_CLASS_ANY, 0, BER_FLAGS_NOOWNTAG, dissect_innerContextToken },
+ { 0, 0, 0, NULL }
+};
- 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);
- }
+static int
+dissect_spnego_InitialContextToken(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
+ offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
+ InitialContextToken_sequence, hf_index, ett_spnego_InitialContextToken);
+
+ return offset;
}
+
+/*--- End of included file: packet-spnego-fn.c ---*/
+
/*
* This is the SPNEGO KRB5 dissector. It is not true KRB5, but some ASN.1
* wrapped blob with an OID, USHORT token ID, and a Ticket, that is also
@@ -245,14 +509,16 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_item *item;
proto_tree *subtree;
- int ret, offset = 0;
- ASN1_SCK hnd;
- gboolean def;
- guint len1, cls, con, tag;
+ int offset = 0;
guint16 token_id;
gchar oid[MAX_OID_STR_LEN];
gssapi_oid_value *value;
tvbuff_t *krb5_tvb;
+ gint8 class;
+ gboolean pc, ind = 0;
+ gint32 tag;
+ guint32 len;
+
item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, offset,
-1, FALSE);
@@ -286,21 +552,13 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* as a Kerberos message.
*/
- asn1_open(&hnd, tvb, offset);
-
/*
* Get the first header ...
*/
+ offset = dissect_ber_identifier(pinfo, subtree, tvb, offset, &class, &pc, &tag);
+ offset = dissect_ber_length(pinfo, subtree, tvb, offset, &len, &ind);
- 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;
- }
-
- if (cls == ASN1_APL && con == ASN1_CON) {
+ if (class == BER_CLASS_APP && pc == 1) {
/*
* [APPLICATION <tag>]
*/
@@ -311,12 +569,8 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* [APPLICATION 0]
*/
- offset = hnd.offset;
-
/* Next, the OID */
offset=dissect_ber_object_identifier(FALSE, pinfo, subtree, tvb, offset, hf_spnego_krb5_oid, oid);
- hnd.offset = offset;
-
value = gssapi_lookup_oid_str(oid);
@@ -324,8 +578,6 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
token_id);
- hnd.offset += 2;
-
offset += 2;
break;
@@ -341,8 +593,8 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
default:
proto_tree_add_text(subtree, tvb, offset, 0,
- "Unknown header (cls=%d, con=%d, tag=%d)",
- cls, con, tag);
+ "Unknown header (class=%d, pc=%d, tag=%d)",
+ class, pc, tag);
goto done;
}
} else {
@@ -352,8 +604,6 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
token_id);
- hnd.offset += 2;
-
offset += 2;
}
@@ -960,662 +1210,46 @@ dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree
/* Spnego stuff from here */
static int
-dissect_spnego_mechTypes(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree,
- gssapi_oid_value **next_level_value_p)
-{
- proto_item *item = NULL;
- proto_tree *subtree = NULL;
- gboolean saw_mechanism = FALSE;
- int start_offset, start_oid_offset, end_oid_offset;
- gint8 class;
- gboolean pc, ind_field;
- gint32 tag;
- guint32 len1;
- gchar oid[MAX_OID_STR_LEN];
-
- start_offset=offset;
- /*
- * MechTypeList ::= SEQUENCE OF MechType
- */
- offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
- offset = get_ber_length(tree, tvb, offset, &len1, &ind_field);
-
- if (!(class == BER_CLASS_UNI && pc && tag == BER_UNI_TAG_SEQUENCE)) {
- proto_tree_add_text(
- tree, tvb, offset, 0,
- "Unknown header (class=%d, pc=%d, tag=%d)",
- class, pc, tag);
- goto done;
- }
-
- item = proto_tree_add_item(tree, hf_spnego_mechtype, tvb,
- start_offset, len1, FALSE);
- subtree = proto_item_add_subtree(item, ett_spnego_mechtype);
-
- /*
- * Now, the object IDs ...
- */
- start_oid_offset=offset;
- end_oid_offset = start_oid_offset+len1;
- while (offset<end_oid_offset) {
- gssapi_oid_value *value;
-
- offset=dissect_ber_object_identifier(FALSE, pinfo, subtree, tvb, offset, hf_spnego_mech, oid);
- value = gssapi_lookup_oid_str(oid);
-
- /*
- * 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_value_p = value;
- saw_mechanism = TRUE;
- }
- }
-
- done:
-
- return offset;
-
-}
-
-static int
-dissect_spnego_reqFlags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, ASN1_SCK *hnd)
-{
- gboolean def;
- guint len1, cls, con, tag, flags;
- int ret;
- proto_item *item;
- proto_tree *subtree;
-
- 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;
- }
-
- 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;
- }
-
- /* We must have a Bit String ... insert it */
-
- offset = hnd->offset;
-
- 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);
-
- hnd->offset += len1;
-
- done:
- return offset + len1;
-
-}
-
-static int
-dissect_spnego_mechToken(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, ASN1_SCK *hnd,
- dissector_handle_t next_level_dissector)
-{
- proto_item *item;
- proto_tree *subtree;
- gboolean def;
- int ret;
- guint cls, con, tag, nbytes = 0;
- gint length_remaining, reported_length_remaining;
- tvbuff_t *token_tvb;
-
- /*
- * 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;
-
-
- /* 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)
- *
- * We use "tvb_ensure_length_remaining()" so that we throw
- * an exception if there's nothing to dissect.
- */
- 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;
- item = proto_tree_add_item(tree, hf_spnego_mechtoken, tvb, offset,
- length_remaining, FALSE);
- subtree = proto_item_add_subtree(item, ett_spnego_mechtoken);
-
- /*
- * Now, we should be able to dispatch after creating a new TVB.
- */
-
- token_tvb = tvb_new_subset(tvb, offset, length_remaining,
- reported_length_remaining);
- if (next_level_dissector)
- call_dissector(next_level_dissector, token_tvb, pinfo, subtree);
-
- hnd->offset += nbytes; /* Update this ... */
-
-done:
- return offset + nbytes;
-}
-
-static int
-dissect_spnego_mechListMIC(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, ASN1_SCK *hnd,
- dissector_handle_t next_level_dissector)
-{
- guint len1, cls, con, tag;
- int ret;
- gboolean def;
- proto_tree *subtree = NULL;
-
- /*
- * Add the mechListMIC [3] Octet String or General String ...
- */
- 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;
-
- 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,
- "mechListMIC: %s",
- tvb_format_text(tvb, offset + 4, len1 - 4));
-
- /* Naughty ... but we have to adjust for what we never took */
-
- hnd->offset += len1;
- offset += len1;
-
- }
- else if (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS) {
- tvbuff_t *token_tvb;
- proto_item *item;
- proto_tree *subtree;
-
- item = proto_tree_add_item(tree, hf_spnego_mechlistmic, tvb, offset,
- len1, FALSE);
- subtree = proto_item_add_subtree(item, ett_spnego_mechlistmic);
-
- /*
- * Now, we should be able to dispatch after creating a new TVB.
- */
-
- token_tvb = tvb_new_subset(tvb, offset, len1, -1);
- if (next_level_dissector)
- call_dissector(next_level_dissector, token_tvb, pinfo, subtree);
-
- hnd->offset += len1; /* Update this ... */
- offset += len1;
-
- }
- else {
-
- proto_tree_add_text(subtree, tvb, offset, 0,
- "Unknown header (cls=%d, con=%d, tag=%d)",
- cls, con, tag);
- goto done;
- }
-
- done:
-
- return offset;
-
-}
-
-static int
-dissect_spnego_negTokenInit(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, ASN1_SCK *hnd,
- gssapi_oid_value **next_level_value_p)
+dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_item *item;
proto_tree *subtree;
- gboolean def;
- guint len1, len, cls, con, tag;
- int ret;
-
- item = proto_tree_add_item( tree, hf_spnego_negtokeninit, tvb, offset,
- -1, FALSE);
- subtree = proto_item_add_subtree(item, ett_spnego_negtokeninit);
-
- /*
- * Here is what we need to get ...
- * NegTokenInit ::= SEQUENCE {
- * mechTypes [0] MechTypeList OPTIONAL,
- * reqFlags [1] ContextFlags OPTIONAL,
- * mechToken [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;
- }
-
- offset = hnd->offset;
-
- while (len1) {
- int hdr_ofs;
-
- hdr_ofs = hnd->offset;
-
- 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;
- }
-
- /* Adjust for the length of the header */
-
- len1 -= (hnd->offset - hdr_ofs);
-
- /* Should be one of the fields */
-
- switch (tag) {
-
- case SPNEGO_mechTypes:
-
- offset = dissect_spnego_mechTypes(tvb, hnd->offset, pinfo,
- subtree,
- next_level_value_p);
- hnd->offset=offset;
-
- break;
-
- case SPNEGO_reqFlags:
-
- offset = dissect_spnego_reqFlags(tvb, offset, pinfo, subtree, hnd);
-
- break;
-
- case SPNEGO_mechToken:
-
- offset = dissect_spnego_mechToken(tvb, offset, pinfo, subtree,
- hnd, gssapi_dissector_handle(*next_level_value_p));
- break;
-
- case SPNEGO_mechListMIC:
-
- offset = dissect_spnego_mechListMIC(tvb, offset, pinfo, subtree,
- hnd, gssapi_dissector_handle(*next_level_value_p));
- break;
-
- default:
-
- break;
- }
-
- len1 -= len;
-
- }
-
- done:
-
- return offset; /* Not sure this is right */
-}
-
-static int
-dissect_spnego_negResult(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, ASN1_SCK *hnd)
-{
- gboolean def;
- int ret;
- guint len, cls, con, tag, val;
-
- 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;
+ int offset = 0;
- done:
- return offset;
-}
-
-static int
-dissect_spnego_supportedMech(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, ASN1_SCK *hnd,
- gssapi_oid_value **next_level_value_p)
-{
- gchar oid[MAX_OID_STR_LEN];
- gssapi_oid_value *value;
- conversation_t *conversation;
/*
- * Now, get the OID, and find the handle, if any
+ * 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.
*/
- offset = hnd->offset;
-
- 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;
- /* Should check for an unrecognized OID ... */
-
- if (value)
- *next_level_value_p = value;
+ item = proto_tree_add_item(tree, hf_spnego, tvb, offset,
+ -1, FALSE);
+ subtree = proto_item_add_subtree(item, ett_spnego);
/*
- * 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!
- * 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. :-(
+ * 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.
+ * ASN1 code addet to spnego.asn to handle this.
*/
- if ((conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
- pinfo->ptype, pinfo->srcport,
- pinfo->destport, 0))) {
-
-
- conversation_add_proto_data(conversation, proto_spnego,
- *next_level_value_p);
- }
- else {
-
- }
+ offset = dissect_spnego_InitialContextToken(FALSE, tvb, offset, pinfo , subtree, -1);
return offset;
}
-static int
-dissect_spnego_responseToken(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, ASN1_SCK *hnd,
- dissector_handle_t next_level_dissector)
-{
- gboolean def;
- int ret;
- guint cls, con, tag, nbytes;
- tvbuff_t *token_tvb;
- proto_item *item;
- proto_tree *subtree;
-
- 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;
-
- item = proto_tree_add_item(tree, hf_spnego_responsetoken, tvb, offset -2 ,
- nbytes + 2, FALSE);
-
- subtree = proto_item_add_subtree(item, ett_spnego_responsetoken);
-
-
- /*
- * Now, we should be able to dispatch after creating a new TVB.
- * However, we should make sure that there is something in the
- * response token ...
- */
-
- 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>");
- }
- hnd->offset += nbytes; /* Update this ... */
-
- done:
- return offset + nbytes;
-}
-
-static int
-dissect_spnego_negTokenTarg(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, ASN1_SCK *hnd,
- gssapi_oid_value **next_level_value_p)
-
-{
- proto_item *item;
- proto_tree *subtree;
- gboolean def;
- int ret;
- guint len1, len, cls, con, tag;
-
- item = proto_tree_add_item( tree, hf_spnego_negtokentarg, tvb, offset,
- -1, FALSE);
- 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;
- }
-
- offset = hnd->offset;
-
- while (len1) {
- int hdr_ofs;
-
- hdr_ofs = hnd->offset;
-
- 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;
- }
-
- /* Adjust for the length of the header */
-
- len1 -= (hnd->offset - hdr_ofs);
-
- /* Should be one of the fields */
-
- switch (tag) {
-
- case SPNEGO_negResult:
-
- offset = dissect_spnego_negResult(tvb, offset, pinfo, subtree,
- hnd);
- break;
-
- case SPNEGO_supportedMech:
-
- offset = dissect_spnego_supportedMech(tvb, offset, pinfo, subtree,
- hnd, next_level_value_p);
-
- break;
-
- case SPNEGO_responseToken:
-
- offset = dissect_spnego_responseToken(tvb, offset, pinfo, subtree,
- hnd, gssapi_dissector_handle(*next_level_value_p));
- break;
-
- case SPNEGO_mechListMIC:
-
- offset = dissect_spnego_mechListMIC(tvb, offset, pinfo, subtree,
- hnd, gssapi_dissector_handle(*next_level_value_p));
- break;
-
- default:
-
- break;
- }
-
- len1 -= len;
-
- }
-
- done:
- return offset;
-
-}
static void
-dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
proto_item *item;
proto_tree *subtree;
- int ret, offset = 0;
- ASN1_SCK hnd;
- gboolean def;
- guint len1, cls, con, tag;
+ int offset = 0;
conversation_t *conversation;
- gssapi_oid_value *next_level_value;
/*
* We need this later, so lets get it now ...
@@ -1643,7 +1277,7 @@ dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
}
- item = proto_tree_add_item(tree, hf_spnego, tvb, offset,
+ item = proto_tree_add_item(parent_tree, hf_spnego, tvb, offset,
-1, FALSE);
subtree = proto_item_add_subtree(item, ett_spnego);
@@ -1652,7 +1286,7 @@ dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* The TVB contains a [0] header and a sequence that consists of an
* object ID and a blob containing the data ...
* Actually, it contains, according to RFC2478:
- * NegotiationToken ::= CHOICE {
+ * NegotiationToken ::= CHOICE {
* negTokenInit [0] NegTokenInit,
* negTokenTarg [1] NegTokenTarg }
* NegTokenInit ::= SEQUENCE {
@@ -1660,268 +1294,43 @@ dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* reqFlags [1] ContextFlags OPTIONAL,
* mechToken [2] OCTET STRING OPTIONAL,
* mechListMIC [3] OCTET STRING OPTIONAL }
- * NegTokenTarg ::= SEQUENCE {
+ * 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 }
- *
+ * supportedMech [1] MechType OPTIONAL,
+ * responseToken [2] OCTET STRING OPTIONAL,
+ * mechListMIC [3] OCTET STRING OPTIONAL }
+ *
* Windows typically includes mechTypes and mechListMic ('NONE'
* in the case of NTLMSSP only).
- * It seems to duplicate the responseToken into the mechListMic field
- * as well. Naughty, naughty.
- *
- */
-
- 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 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;
- }
-
- offset = hnd.offset;
-
- /*
- * The Tag is one of negTokenInit or negTokenTarg
+ * It seems to duplicate the responseToken into the mechListMic field
+ * as well. Naughty, naughty.
+ *
*/
-
- switch (tag) {
-
- case SPNEGO_negTokenInit:
-
- offset = dissect_spnego_negTokenInit(tvb, offset, pinfo,
- subtree, &hnd,
- &next_level_value);
-
- break;
-
- case SPNEGO_negTokenTarg:
-
- offset = dissect_spnego_negTokenTarg(tvb, offset, pinfo,
- subtree, &hnd,
- &next_level_value);
- break;
-
- default: /* Broken, what to do? */
-
- break;
- }
-
-
- done:
- asn1_close(&hnd, &offset);
+ offset = dissect_spnego_NegotiationToken(FALSE, tvb, offset, pinfo, subtree, -1);
}
-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;
- int len, offset, start_offset;
- gint8 class;
- gboolean pc, ind_field;
- gint32 tag;
- guint32 len1;
- gchar oid[MAX_OID_STR_LEN];
-
- start_offset=0;
- offset=start_offset;
-
- /*
- * 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.
- */
+/*--- proto_register_spnego -------------------------------------------*/
+void proto_register_spnego(void) {
- 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.
- */
- conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
- 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 ...
- */
- offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
- offset = get_ber_length(tree, tvb, offset, &len1, &ind_field);
-
- if (!(class == BER_CLASS_APP && pc && tag == 0)) {
- proto_tree_add_text(
- subtree, tvb, start_offset, 0,
- "Unknown header (class=%d, pc=%d, tag=%d)",
- class, pc, tag);
- return_offset = tvb_length(tvb);
- goto done;
- }
-
- /*
- * Get the OID, and find the handle, if any
- *
- * XXX - what should we do if this OID doesn't match the value
- * 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.)
- */
- offset=dissect_ber_object_identifier(FALSE, pinfo, subtree, tvb, offset, hf_spnego_this_mech, oid);
- next_level_value = gssapi_lookup_oid_str(oid);
-
- /*
- * 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;
-}
-
-void
-proto_register_spnego(void)
-{
- static hf_register_info hf[] = {
+ /* List of fields */
+ static hf_register_info hf[] = {
{ &hf_spnego,
{ "SPNEGO", "spnego", FT_NONE, BASE_NONE, NULL, 0x0,
"SPNEGO", HFILL }},
- { &hf_spnego_mech, {
- "Mech", "spnego.mech", FT_STRING, BASE_NONE,
- NULL, 0, "This is a SPNEGO Object Identifier", HFILL }},
- { &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 }},
- { &hf_spnego_this_mech, {
- "thisMech", "spnego.this_mech", FT_STRING, BASE_NONE,
- NULL, 0, "This is a SPNEGO Object Identifier", HFILL }},
- { &hf_spnego_negtokeninit,
- { "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,
- { "mechType", "spnego.negtokeninit.mechtype", FT_NONE,
- BASE_NONE, NULL, 0x0, "SPNEGO negTokenInit mechTypes", HFILL}},
- { &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}},
- { &hf_spnego_negtokentarg_negresult,
- { "negResult", "spnego.negtokeninit.negresult", FT_UINT16,
- BASE_HEX, VALS(spnego_negResult_vals), 0, "negResult", HFILL}},
- { &hf_spnego_reqflags,
- { "reqFlags", "spnego.negtokeninit.reqflags", FT_BYTES,
- BASE_HEX, NULL, 0, "reqFlags", HFILL }},
- { &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}},
- { &hf_spnego_wraptoken,
+ { &hf_spnego_wraptoken,
{ "wrapToken", "spnego.wraptoken",
FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO wrapToken",
HFILL}},
{ &hf_spnego_krb5,
{ "krb5_blob", "spnego.krb5.blob", FT_BYTES,
BASE_NONE, NULL, 0, "krb5_blob", HFILL }},
+ {&hf_spnego_krb5_oid,
+ {"KRB5 OID", "spnego.krb5_oid", FT_STRING,
+ BASE_NONE, NULL, 0, "KRB5 OID", HFILL }},
{ &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 Id", HFILL}},
@@ -1940,33 +1349,127 @@ proto_register_spnego(void)
{ &hf_spnego_krb5_confounder,
{ "krb5_confounder", "spnego.krb5.confounder", FT_BYTES, BASE_NONE,
NULL, 0, "KRB5 Confounder", HFILL}},
- };
- static gint *ett[] = {
+
+/*--- Included file: packet-spnego-hfarr.c ---*/
+
+ { &hf_spnego_negTokenInit,
+ { "negTokenInit", "spnego.negTokenInit",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "NegotiationToken/negTokenInit", HFILL }},
+ { &hf_spnego_negTokenTarg,
+ { "negTokenTarg", "spnego.negTokenTarg",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "NegotiationToken/negTokenTarg", HFILL }},
+ { &hf_spnego_MechTypeList_item,
+ { "Item", "spnego.MechTypeList_item",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "MechTypeList/_item", HFILL }},
+ { &hf_spnego_mechTypes,
+ { "mechTypes", "spnego.mechTypes",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "NegTokenInit/mechTypes", HFILL }},
+ { &hf_spnego_reqFlags,
+ { "reqFlags", "spnego.reqFlags",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "NegTokenInit/reqFlags", HFILL }},
+ { &hf_spnego_mechToken,
+ { "mechToken", "spnego.mechToken",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "NegTokenInit/mechToken", HFILL }},
+ { &hf_spnego_mechListMIC,
+ { "mechListMIC", "spnego.mechListMIC",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "", HFILL }},
+ { &hf_spnego_negResult,
+ { "negResult", "spnego.negResult",
+ FT_UINT32, BASE_DEC, VALS(spnego_T_negResult_vals), 0,
+ "NegTokenTarg/negResult", HFILL }},
+ { &hf_spnego_supportedMech,
+ { "supportedMech", "spnego.supportedMech",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "NegTokenTarg/supportedMech", HFILL }},
+ { &hf_spnego_responseToken,
+ { "responseToken", "spnego.responseToken",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "NegTokenTarg/responseToken", HFILL }},
+ { &hf_spnego_thisMech,
+ { "thisMech", "spnego.thisMech",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "InitialContextToken/thisMech", HFILL }},
+ { &hf_spnego_innerContextToken,
+ { "innerContextToken", "spnego.innerContextToken",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "InitialContextToken/innerContextToken", HFILL }},
+ { &hf_spnego_ContextFlags_delegFlag,
+ { "delegFlag", "spnego.delegFlag",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ "", HFILL }},
+ { &hf_spnego_ContextFlags_mutualFlag,
+ { "mutualFlag", "spnego.mutualFlag",
+ FT_BOOLEAN, 8, NULL, 0x40,
+ "", HFILL }},
+ { &hf_spnego_ContextFlags_replayFlag,
+ { "replayFlag", "spnego.replayFlag",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ "", HFILL }},
+ { &hf_spnego_ContextFlags_sequenceFlag,
+ { "sequenceFlag", "spnego.sequenceFlag",
+ FT_BOOLEAN, 8, NULL, 0x10,
+ "", HFILL }},
+ { &hf_spnego_ContextFlags_anonFlag,
+ { "anonFlag", "spnego.anonFlag",
+ FT_BOOLEAN, 8, NULL, 0x08,
+ "", HFILL }},
+ { &hf_spnego_ContextFlags_confFlag,
+ { "confFlag", "spnego.confFlag",
+ FT_BOOLEAN, 8, NULL, 0x04,
+ "", HFILL }},
+ { &hf_spnego_ContextFlags_integFlag,
+ { "integFlag", "spnego.integFlag",
+ FT_BOOLEAN, 8, NULL, 0x02,
+ "", HFILL }},
+
+/*--- End of included file: packet-spnego-hfarr.c ---*/
+
+ };
+
+ /* List of subtrees */
+ static gint *ett[] = {
&ett_spnego,
- &ett_spnego_negtokeninit,
- &ett_spnego_negtokentarg,
- &ett_spnego_mechtype,
- &ett_spnego_mechtoken,
- &ett_spnego_mechlistmic,
- &ett_spnego_responsetoken,
&ett_spnego_wraptoken,
&ett_spnego_krb5,
- };
- proto_spnego = proto_register_protocol(
- "Spnego", "Spnego", "spnego");
+
+/*--- Included file: packet-spnego-ettarr.c ---*/
+
+ &ett_spnego_NegotiationToken,
+ &ett_spnego_MechTypeList,
+ &ett_spnego_NegTokenInit,
+ &ett_spnego_ContextFlags,
+ &ett_spnego_NegTokenTarg,
+ &ett_spnego_InitialContextToken,
+
+/*--- End of included file: packet-spnego-ettarr.c ---*/
+
+ };
+
+ /* Register protocol */
+ proto_spnego = proto_register_protocol(PNAME, PSNAME, PFNAME);
+
proto_spnego_krb5 = proto_register_protocol("SPNEGO-KRB5",
"SPNEGO-KRB5",
"spnego-krb5");
+ /* Register fields and subtrees */
+ proto_register_field_array(proto_spnego, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
- proto_register_field_array(proto_spnego, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
}
-void
-proto_reg_handoff_spnego(void)
-{
+
+/*--- proto_reg_handoff_spnego ---------------------------------------*/
+void proto_reg_handoff_spnego(void) {
+
dissector_handle_t spnego_handle, spnego_wrap_handle;
dissector_handle_t spnego_krb5_handle, spnego_krb5_wrap_handle;
@@ -2006,4 +1509,5 @@ proto_reg_handoff_spnego(void)
* Find the data handle for some calls
*/
data_handle = find_dissector("data");
+
}