diff options
author | Guy Harris <guy@alum.mit.edu> | 2005-09-21 17:42:11 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2005-09-21 17:42:11 +0000 |
commit | 0fb81e221e18e15274da6e0360ed0bc77e93aeca (patch) | |
tree | 6666112c0e39f0d43d2e128d4941582af9c44bf2 /asn1/spnego | |
parent | fa2779e00deb88f9ee4cb0aca73ad4a4636a8811 (diff) | |
download | wireshark-0fb81e221e18e15274da6e0360ed0bc77e93aeca.tar.gz wireshark-0fb81e221e18e15274da6e0360ed0bc77e93aeca.tar.bz2 wireshark-0fb81e221e18e15274da6e0360ed0bc77e93aeca.zip |
An InnerContextToken comes with an OID for the mechanism, which is what
we use to determine how to interpret the token; don't bother fetching
the OID attached to the frame or conversation, as we're not using it.
Indent code in the .cnf file to match the code generated by asn2eth.
The mechListMIC in a NegTokenInit is sometimes a sequence containing a
string; check the header of the mechListMIC and dissect it as such a
sequence or as a regular item depending on whether it's a sequence or
not.
If we see a supportedMech in a NegTokenTarg, save next_level_value for
that OID with the conversation.
Dissect a responseToken in a NegTokenTarg, and a mechListMIC in a
NegTokenTarg, appropriately.
Get rid of "gssapi_dissector_handle()", and just use
next_level_value->handle - it was never being called if next_level_value
was null.
When we're dissecting a KRB5 blob, just use get_ber_identifier() to get
the header, so we don't report an ASN.1 error if there isn't a BER
identifier there; dissect the identifier and length only if we know we
have them.
svn path=/trunk/; revision=15937
Diffstat (limited to 'asn1/spnego')
-rw-r--r-- | asn1/spnego/packet-spnego-template.c | 71 | ||||
-rw-r--r-- | asn1/spnego/spnego.asn | 18 | ||||
-rw-r--r-- | asn1/spnego/spnego.cnf | 267 |
3 files changed, 225 insertions, 131 deletions
diff --git a/asn1/spnego/packet-spnego-template.c b/asn1/spnego/packet-spnego-template.c index 2a3ce34c17..e899e3f6e8 100644 --- a/asn1/spnego/packet-spnego-template.c +++ b/asn1/spnego/packet-spnego-template.c @@ -87,16 +87,6 @@ static gint ett_spnego_krb5 = -1; 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; -} - - #include "packet-spnego-fn.c" /* * This is the SPNEGO KRB5 dissector. It is not true KRB5, but some ASN.1 @@ -172,7 +162,6 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) gint32 tag; guint32 len; - item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, offset, -1, FALSE); @@ -208,13 +197,14 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) /* * 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); - - if (class == BER_CLASS_APP && pc == 1) { + get_ber_identifier(tvb, offset, &class, &pc, &tag); + if (class == BER_CLASS_APP && pc) { /* * [APPLICATION <tag>] */ + offset = dissect_ber_identifier(pinfo, subtree, tvb, offset, &class, &pc, &tag); + offset = dissect_ber_length(pinfo, subtree, tvb, offset, &len, &ind); + switch (tag) { case 0: @@ -909,7 +899,6 @@ dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) * It has to be per-frame as there can be more than one GSS-API * negotiation in a conversation. */ - next_level_value = p_get_proto_data(pinfo->fd, proto_spnego); if (!next_level_value && !pinfo->fd->flags.visited) { /* @@ -939,7 +928,7 @@ dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_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 { @@ -947,20 +936,20 @@ dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_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. - * + * It seems to duplicate the responseToken into the mechListMic field + * as well. Naughty, naughty. + * */ offset = dissect_spnego_NegotiationToken(FALSE, tvb, offset, pinfo, subtree, -1); @@ -969,21 +958,21 @@ dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) /*--- proto_register_spnego -------------------------------------------*/ void proto_register_spnego(void) { - /* List of fields */ - 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_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_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}}, @@ -1004,27 +993,26 @@ void proto_register_spnego(void) { NULL, 0, "KRB5 Confounder", HFILL}}, #include "packet-spnego-hfarr.c" - }; + }; - /* List of subtrees */ - static gint *ett[] = { + /* List of subtrees */ + static gint *ett[] = { &ett_spnego, &ett_spnego_wraptoken, &ett_spnego_krb5, #include "packet-spnego-ettarr.c" - }; + }; - /* Register protocol */ - proto_spnego = proto_register_protocol(PNAME, PSNAME, PFNAME); + /* 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)); - + /* Register fields and subtrees */ + proto_register_field_array(proto_spnego, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); } @@ -1070,5 +1058,4 @@ void proto_reg_handoff_spnego(void) { * Find the data handle for some calls */ data_handle = find_dissector("data"); - } diff --git a/asn1/spnego/spnego.asn b/asn1/spnego/spnego.asn index 8813fea9cc..190b3f1555 100644 --- a/asn1/spnego/spnego.asn +++ b/asn1/spnego/spnego.asn @@ -12,6 +12,22 @@ NegotiationToken ::= CHOICE { MechTypeList ::= SEQUENCE OF MechType +-- +-- In some cases, the mechListMIC is a sequence of GeneralString, +-- rather than an OCTET STRING. We define that sequence here so +-- that we can call its dissector. +-- The IRC discussion at +-- +-- http://irc.vernstok.nl/samba-technical.dy +-- +-- seems to suggest that it's a Kerberos principal of some sort, thanks +-- to some flavor of "embrace, extend, expectorate" sequence from +-- Microsoft. +-- +PrincipalSeq ::= SEQUENCE { + principal [0] GeneralString +} + NegTokenInit ::= SEQUENCE { mechTypes [0] MechTypeList OPTIONAL, reqFlags [1] ContextFlags OPTIONAL, @@ -82,4 +98,4 @@ InnerContextToken ::= ANY -- END GSS-API DEFINITIONS -END
\ No newline at end of file +END diff --git a/asn1/spnego/spnego.cnf b/asn1/spnego/spnego.cnf index ef523d665d..ac2ef47643 100644 --- a/asn1/spnego/spnego.cnf +++ b/asn1/spnego/spnego.cnf @@ -10,122 +10,213 @@ #.NO_EMIT #.TYPE_RENAME +NegTokenInit/mechListMIC T_NegTokenInit_mechListMIC #.FIELD_RENAME +NegTokenInit/mechListMIC negTokenInit_mechListMIC #.FN_PARS MechType - VAL_PTR = MechType_oid + VAL_PTR = MechType_oid #.FN_BODY MechType - gssapi_oid_value *value; + gssapi_oid_value *value; %(DEFAULT_BODY)s - 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; - } + 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; + } #.FN_BODY InnerContextToken - 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); - } - } - - 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 && 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); - + gssapi_oid_value *next_level_value; + proto_item *item; + proto_tree *subtree; + tvbuff_t *token_tvb; + int len; + + /* + * 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.) + * Does it matter? + */ + 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 && 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); #.FN_HDR MechTypeList - - saw_mechanism = FALSE; + saw_mechanism = FALSE; #.FN_PARS NegTokenInit/mechToken - VAL_PTR = &mechToken_tvb + VAL_PTR = &mechToken_tvb #.FN_BODY NegTokenInit/mechToken - tvbuff_t *mechToken_tvb = NULL; + tvbuff_t *mechToken_tvb = NULL; + +%(DEFAULT_BODY)s + + if (! mechToken_tvb) { + THROW(ReportedBoundsError); + } + + /* + * Now, we should be able to dispatch after creating a new TVB. + */ + if (next_level_value) + call_dissector(next_level_value->handle, mechToken_tvb, pinfo, tree); + + +#.FN_BODY NegTokenInit/mechListMIC + + gint8 class; + gboolean pc; + gint32 tag; + tvbuff_t *mechListMIC_tvb; + static int dissect_spnego_PrincipalSeq(gboolean implicit_tag, tvbuff_t *tvb, + int offset, packet_info *pinfo, + proto_tree *tree, int hf_index); + + /* + * There seems to be two different forms this can take, + * one as an octet string, and one as a general string in a + * sequence. + * + * Peek at the header, and then decide which it is we're seeing. + */ + get_ber_identifier(tvb, offset, &class, &pc, &tag); + if (class == BER_CLASS_UNI && pc && tag == BER_UNI_TAG_SEQUENCE) { + /* + * It's a sequence. + */ + return dissect_spnego_PrincipalSeq(FALSE, tvb, offset, pinfo, tree, + hf_spnego_mechListMIC); + } else { + /* + * It's not a sequence, so dissect it as an octet string, + * which is what it's supposed to be; that'll cause the + * right error report if it's not an octet string, either. + */ + offset = dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, + hf_spnego_mechListMIC, &mechListMIC_tvb); + + /* + * Now, we should be able to dispatch with that tvbuff. + */ + if (next_level_value) + call_dissector(next_level_value->handle, mechListMIC_tvb, pinfo, tree); + return offset; + } + +#.FN_BODY NegTokenTarg/supportedMech + + conversation_t *conversation; + + saw_mechanism = FALSE; + +%(DEFAULT_BODY)s + + /* + * 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. :-( + */ + 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); + } + + +#.FN_PARS NegTokenTarg/responseToken + + VAL_PTR = &responseToken_tvb + +#.FN_BODY NegTokenTarg/responseToken + tvbuff_t *responseToken_tvb; -%(DEFAULT_BODY)s - if (! mechToken_tvb) { - THROW(ReportedBoundsError); - } +%(DEFAULT_BODY)s + + + /* + * Now, we should be able to dispatch with that tvbuff. + * However, we should make sure that there is something in the + * response token ... + */ + if (tvb_reported_length(responseToken_tvb) > 0) { + if (next_level_value) + call_dissector(next_level_value->handle, responseToken_tvb, pinfo, tree); + } + + +#.FN_PARS NegTokenTarg/mechListMIC + + VAL_PTR = &mechListMIC_tvb + +#.FN_BODY NegTokenTarg/mechListMIC + + tvbuff_t *mechListMIC_tvb; + + +%(DEFAULT_BODY)s - /* - * 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); + /* + * Now, we should be able to dispatch with that tvbuff. + */ + if (next_level_value) + call_dissector(next_level_value->handle, mechListMIC_tvb, pinfo, tree); #.END |