1 /* Do not modify this file. */
2 /* It is created automatically by the ASN.1 to Wireshark dissector compiler */
3 /* ./packet-spnego.c */
4 /* ../../tools/asn2eth.py -X -b -e -p spnego -c spnego.cnf -s packet-spnego-template spnego.asn */
6 /* Input file: packet-spnego-template.c */
8 #line 1 "packet-spnego-template.c"
10 * Routines for the simple and protected GSS-API negotiation mechanism
11 * as described in RFC 2478.
12 * Copyright 2002, Tim Potter <tpot@samba.org>
13 * Copyright 2002, Richard Sharpe <rsharpe@ns.aus.com>
14 * Copyright 2003, Richard Sharpe <rsharpe@richardsharpe.com>
15 * Copyright 2005, Ronnie Sahlberg (krb decryption)
16 * Copyright 2005, Anders Broman (converted to asn2eth generated dissector)
20 * Wireshark - Network traffic analyzer
21 * By Gerald Combs <gerald@wireshark.org>
22 * Copyright 1998 Gerald Combs
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * as published by the Free Software Foundation; either version 2
27 * of the License, or (at your option) any later version.
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
34 * You should have received a copy of the GNU General Public License
35 * along with this program; if not, write to the Free Software
36 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 /* The heimdal code for decryption of GSSAPI wrappers using heimdal comes from
39 Heimdal 1.6 and has been modified for wireshark's requirements.
47 #include <epan/packet.h>
48 #include "packet-dcerpc.h"
49 #include "packet-gssapi.h"
50 #include "packet-kerberos.h"
51 #include <epan/crypt-rc4.h>
52 #include <epan/conversation.h>
53 #include <epan/emem.h>
58 #include "packet-ber.h"
61 #define PNAME "Simple Protected Negotiation"
62 #define PSNAME "SPNEGO"
63 #define PFNAME "spnego"
65 /* Initialize the protocol and registered fields */
66 static int proto_spnego = -1;
67 static int proto_spnego_krb5 = -1;
70 static int hf_spnego = -1;
71 static int hf_spnego_wraptoken = -1;
72 static int hf_spnego_krb5_oid;
73 static int hf_spnego_krb5 = -1;
74 static int hf_spnego_krb5_tok_id = -1;
75 static int hf_spnego_krb5_sgn_alg = -1;
76 static int hf_spnego_krb5_seal_alg = -1;
77 static int hf_spnego_krb5_snd_seq = -1;
78 static int hf_spnego_krb5_sgn_cksum = -1;
79 static int hf_spnego_krb5_confounder = -1;
82 /*--- Included file: packet-spnego-hf.c ---*/
83 #line 1 "packet-spnego-hf.c"
84 static int hf_spnego_negTokenInit = -1; /* NegTokenInit */
85 static int hf_spnego_negTokenTarg = -1; /* NegTokenTarg */
86 static int hf_spnego_MechTypeList_item = -1; /* MechType */
87 static int hf_spnego_principal = -1; /* GeneralString */
88 static int hf_spnego_mechTypes = -1; /* MechTypeList */
89 static int hf_spnego_reqFlags = -1; /* ContextFlags */
90 static int hf_spnego_mechToken = -1; /* T_mechToken */
91 static int hf_spnego_negTokenInit_mechListMIC = -1; /* T_NegTokenInit_mechListMIC */
92 static int hf_spnego_negResult = -1; /* T_negResult */
93 static int hf_spnego_supportedMech = -1; /* T_supportedMech */
94 static int hf_spnego_responseToken = -1; /* T_responseToken */
95 static int hf_spnego_mechListMIC = -1; /* T_mechListMIC */
96 static int hf_spnego_thisMech = -1; /* MechType */
97 static int hf_spnego_innerContextToken = -1; /* InnerContextToken */
99 static int hf_spnego_ContextFlags_delegFlag = -1;
100 static int hf_spnego_ContextFlags_mutualFlag = -1;
101 static int hf_spnego_ContextFlags_replayFlag = -1;
102 static int hf_spnego_ContextFlags_sequenceFlag = -1;
103 static int hf_spnego_ContextFlags_anonFlag = -1;
104 static int hf_spnego_ContextFlags_confFlag = -1;
105 static int hf_spnego_ContextFlags_integFlag = -1;
107 /*--- End of included file: packet-spnego-hf.c ---*/
108 #line 74 "packet-spnego-template.c"
110 /* Global variables */
111 static const char *MechType_oid;
112 gssapi_oid_value *next_level_value;
113 gboolean saw_mechanism = FALSE;
116 /* Initialize the subtree pointers */
117 static gint ett_spnego;
118 static gint ett_spnego_wraptoken;
119 static gint ett_spnego_krb5 = -1;
122 /*--- Included file: packet-spnego-ett.c ---*/
123 #line 1 "packet-spnego-ett.c"
124 static gint ett_spnego_NegotiationToken = -1;
125 static gint ett_spnego_MechTypeList = -1;
126 static gint ett_spnego_PrincipalSeq = -1;
127 static gint ett_spnego_NegTokenInit = -1;
128 static gint ett_spnego_ContextFlags = -1;
129 static gint ett_spnego_NegTokenTarg = -1;
130 static gint ett_spnego_InitialContextToken = -1;
132 /*--- End of included file: packet-spnego-ett.c ---*/
133 #line 87 "packet-spnego-template.c"
135 static dissector_handle_t data_handle;
138 * Unfortunately, we have to have a forward declaration of this,
139 * as the code generated by asn2eth includes a call before the
142 static int dissect_spnego_PrincipalSeq(gboolean implicit_tag, tvbuff_t *tvb,
143 int offset, packet_info *pinfo,
144 proto_tree *tree, int hf_index);
147 /*--- Included file: packet-spnego-fn.c ---*/
148 #line 1 "packet-spnego-fn.c"
149 /*--- Fields for imported types ---*/
155 dissect_spnego_MechType(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
156 #line 23 "spnego.cnf"
158 gssapi_oid_value *value;
160 offset = dissect_ber_object_identifier_str(implicit_tag, pinfo, tree, tvb, offset, hf_index, &MechType_oid);
163 value = gssapi_lookup_oid_str(MechType_oid);
166 * Tell our caller the first mechanism we see, so that if
167 * this is a negTokenInit with a mechToken, it can interpret
168 * the mechToken according to the first mechType. (There
169 * might not have been any indication of the mechType
170 * in prior frames, so we can't necessarily use the
171 * mechanism from the conversation; i.e., a negTokenInit
172 * can contain the initial security token for the desired
173 * mechanism of the initiator - that's the first mechanism
176 if (!saw_mechanism) {
178 next_level_value = value;
179 saw_mechanism = TRUE;
186 static int dissect_MechTypeList_item(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
187 return dissect_spnego_MechType(FALSE, tvb, offset, pinfo, tree, hf_spnego_MechTypeList_item);
189 static int dissect_thisMech(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
190 return dissect_spnego_MechType(FALSE, tvb, offset, pinfo, tree, hf_spnego_thisMech);
194 static const ber_sequence_t MechTypeList_sequence_of[1] = {
195 { BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_MechTypeList_item },
199 dissect_spnego_MechTypeList(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
200 #line 91 "spnego.cnf"
202 saw_mechanism = FALSE;
205 offset = dissect_ber_sequence_of(implicit_tag, pinfo, tree, tvb, offset,
206 MechTypeList_sequence_of, hf_index, ett_spnego_MechTypeList);
210 static int dissect_mechTypes(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
211 return dissect_spnego_MechTypeList(FALSE, tvb, offset, pinfo, tree, hf_spnego_mechTypes);
215 static const asn_namedbit ContextFlags_bits[] = {
216 { 0, &hf_spnego_ContextFlags_delegFlag, -1, -1, "delegFlag", NULL },
217 { 1, &hf_spnego_ContextFlags_mutualFlag, -1, -1, "mutualFlag", NULL },
218 { 2, &hf_spnego_ContextFlags_replayFlag, -1, -1, "replayFlag", NULL },
219 { 3, &hf_spnego_ContextFlags_sequenceFlag, -1, -1, "sequenceFlag", NULL },
220 { 4, &hf_spnego_ContextFlags_anonFlag, -1, -1, "anonFlag", NULL },
221 { 5, &hf_spnego_ContextFlags_confFlag, -1, -1, "confFlag", NULL },
222 { 6, &hf_spnego_ContextFlags_integFlag, -1, -1, "integFlag", NULL },
223 { 0, NULL, 0, 0, NULL, NULL }
227 dissect_spnego_ContextFlags(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
228 offset = dissect_ber_bitstring(implicit_tag, pinfo, tree, tvb, offset,
229 ContextFlags_bits, hf_index, ett_spnego_ContextFlags,
234 static int dissect_reqFlags(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
235 return dissect_spnego_ContextFlags(FALSE, tvb, offset, pinfo, tree, hf_spnego_reqFlags);
241 dissect_spnego_T_mechToken(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
242 #line 99 "spnego.cnf"
244 tvbuff_t *mechToken_tvb = NULL;
246 offset = dissect_ber_octet_string(implicit_tag, pinfo, tree, tvb, offset, hf_index,
251 * Now, we should be able to dispatch, if we've gotten a tvbuff for
252 * the token and we have information on how to dissect its contents.
254 if (mechToken_tvb && next_level_value)
255 call_dissector(next_level_value->handle, mechToken_tvb, pinfo, tree);
262 static int dissect_mechToken(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
263 return dissect_spnego_T_mechToken(FALSE, tvb, offset, pinfo, tree, hf_spnego_mechToken);
269 dissect_spnego_T_NegTokenInit_mechListMIC(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
270 #line 113 "spnego.cnf"
275 tvbuff_t *mechListMIC_tvb;
278 * There seems to be two different forms this can take,
279 * one as an octet string, and one as a general string in a
282 * Peek at the header, and then decide which it is we're seeing.
284 get_ber_identifier(tvb, offset, &class, &pc, &tag);
285 if (class == BER_CLASS_UNI && pc && tag == BER_UNI_TAG_SEQUENCE) {
289 return dissect_spnego_PrincipalSeq(FALSE, tvb, offset, pinfo, tree,
290 hf_spnego_mechListMIC);
293 * It's not a sequence, so dissect it as an octet string,
294 * which is what it's supposed to be; that'll cause the
295 * right error report if it's not an octet string, either.
297 offset = dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset,
298 hf_spnego_mechListMIC, &mechListMIC_tvb);
301 * Now, we should be able to dispatch with that tvbuff.
303 if (mechListMIC_tvb && next_level_value)
304 call_dissector(next_level_value->handle, mechListMIC_tvb, pinfo, tree);
312 static int dissect_negTokenInit_mechListMIC(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
313 return dissect_spnego_T_NegTokenInit_mechListMIC(FALSE, tvb, offset, pinfo, tree, hf_spnego_negTokenInit_mechListMIC);
317 static const ber_sequence_t NegTokenInit_sequence[] = {
318 { BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL, dissect_mechTypes },
319 { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_reqFlags },
320 { BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_mechToken },
321 { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL, dissect_negTokenInit_mechListMIC },
326 dissect_spnego_NegTokenInit(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
327 offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
328 NegTokenInit_sequence, hf_index, ett_spnego_NegTokenInit);
332 static int dissect_negTokenInit(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
333 return dissect_spnego_NegTokenInit(FALSE, tvb, offset, pinfo, tree, hf_spnego_negTokenInit);
337 static const value_string spnego_T_negResult_vals[] = {
338 { 0, "accept-completed" },
339 { 1, "accept-incomplete" },
346 dissect_spnego_T_negResult(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
347 offset = dissect_ber_integer(implicit_tag, pinfo, tree, tvb, offset, hf_index,
352 static int dissect_negResult(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
353 return dissect_spnego_T_negResult(FALSE, tvb, offset, pinfo, tree, hf_spnego_negResult);
359 dissect_spnego_T_supportedMech(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
360 #line 151 "spnego.cnf"
362 conversation_t *conversation;
364 saw_mechanism = FALSE;
366 offset = dissect_spnego_MechType(implicit_tag, tvb, offset, pinfo, tree, hf_index);
370 * Now, we need to save this in per-proto info in the
371 * conversation if it exists. We also should create a
372 * conversation if one does not exist. FIXME!
373 * Hmmm, might need to be smarter, because there can be
374 * multiple mechTypes in a negTokenInit with one being the
375 * default used in the Token if present. Then the negTokenTarg
376 * could override that. :-(
378 if ((conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
379 pinfo->ptype, pinfo->srcport,
380 pinfo->destport, 0))) {
381 conversation_add_proto_data(conversation, proto_spnego, next_level_value);
389 static int dissect_supportedMech(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
390 return dissect_spnego_T_supportedMech(FALSE, tvb, offset, pinfo, tree, hf_spnego_supportedMech);
396 dissect_spnego_T_responseToken(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
397 #line 179 "spnego.cnf"
399 tvbuff_t *responseToken_tvb;
402 offset = dissect_ber_octet_string(implicit_tag, pinfo, tree, tvb, offset, hf_index,
408 * Now, we should be able to dispatch, if we've gotten a tvbuff for
409 * the token and we have information on how to dissect its contents.
410 * However, we should make sure that there is something in the
413 if (responseToken_tvb && next_level_value) {
414 if (tvb_reported_length(responseToken_tvb) > 0)
415 call_dissector(next_level_value->handle, responseToken_tvb, pinfo, tree);
423 static int dissect_responseToken(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
424 return dissect_spnego_T_responseToken(FALSE, tvb, offset, pinfo, tree, hf_spnego_responseToken);
430 dissect_spnego_T_mechListMIC(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
431 #line 203 "spnego.cnf"
433 tvbuff_t *mechListMIC_tvb;
436 offset = dissect_ber_octet_string(implicit_tag, pinfo, tree, tvb, offset, hf_index,
442 * Now, we should be able to dispatch, if we've gotten a tvbuff for
443 * the MIC and we have information on how to dissect its contents.
445 if (mechListMIC_tvb && next_level_value)
446 call_dissector(next_level_value->handle, mechListMIC_tvb, pinfo, tree);
453 static int dissect_mechListMIC(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
454 return dissect_spnego_T_mechListMIC(FALSE, tvb, offset, pinfo, tree, hf_spnego_mechListMIC);
458 static const ber_sequence_t NegTokenTarg_sequence[] = {
459 { BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL, dissect_negResult },
460 { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_supportedMech },
461 { BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_responseToken },
462 { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL, dissect_mechListMIC },
467 dissect_spnego_NegTokenTarg(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
468 offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
469 NegTokenTarg_sequence, hf_index, ett_spnego_NegTokenTarg);
473 static int dissect_negTokenTarg(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
474 return dissect_spnego_NegTokenTarg(FALSE, tvb, offset, pinfo, tree, hf_spnego_negTokenTarg);
478 static const value_string spnego_NegotiationToken_vals[] = {
479 { 0, "negTokenInit" },
480 { 1, "negTokenTarg" },
484 static const ber_choice_t NegotiationToken_choice[] = {
485 { 0, BER_CLASS_CON, 0, 0, dissect_negTokenInit },
486 { 1, BER_CLASS_CON, 1, 0, dissect_negTokenTarg },
491 dissect_spnego_NegotiationToken(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
492 offset = dissect_ber_choice(pinfo, tree, tvb, offset,
493 NegotiationToken_choice, hf_index, ett_spnego_NegotiationToken,
502 dissect_spnego_GeneralString(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
503 offset = dissect_ber_restricted_string(implicit_tag, BER_UNI_TAG_GeneralString,
504 pinfo, tree, tvb, offset, hf_index,
509 static int dissect_principal(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
510 return dissect_spnego_GeneralString(FALSE, tvb, offset, pinfo, tree, hf_spnego_principal);
514 static const ber_sequence_t PrincipalSeq_sequence[] = {
515 { BER_CLASS_CON, 0, 0, dissect_principal },
520 dissect_spnego_PrincipalSeq(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
521 offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
522 PrincipalSeq_sequence, hf_index, ett_spnego_PrincipalSeq);
530 dissect_spnego_InnerContextToken(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
531 #line 48 "spnego.cnf"
533 gssapi_oid_value *next_level_value;
540 * XXX - what should we do if this OID doesn't match the value
541 * attached to the frame or conversation? (That would be
542 * bogus, but that's not impossible - some broken implementation
543 * might negotiate some security mechanism but put the OID
544 * for some other security mechanism in GSS_Wrap tokens.)
547 next_level_value = gssapi_lookup_oid_str(MechType_oid);
550 * Now dissect the GSS_Wrap token; it's assumed to be in the
551 * rest of the tvbuff.
553 item = proto_tree_add_item(tree, hf_spnego_wraptoken, tvb, offset, -1, FALSE);
555 subtree = proto_item_add_subtree(item, ett_spnego_wraptoken);
558 * Now, we should be able to dispatch after creating a new TVB.
559 * The subdissector must return the length of the part of the
560 * token it dissected, so we can return the length of the part
561 * we (and it) dissected.
563 token_tvb = tvb_new_subset(tvb, offset, -1, -1);
564 if (next_level_value && next_level_value->wrap_handle) {
565 len = call_dissector(next_level_value->wrap_handle, token_tvb, pinfo,
568 offset = tvb_length(tvb);
570 offset = offset + len;
572 offset = tvb_length(tvb);
578 static int dissect_innerContextToken(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) {
579 return dissect_spnego_InnerContextToken(FALSE, tvb, offset, pinfo, tree, hf_spnego_innerContextToken);
583 static const ber_sequence_t InitialContextToken_sequence[] = {
584 { BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_thisMech },
585 { BER_CLASS_ANY, 0, BER_FLAGS_NOOWNTAG, dissect_innerContextToken },
590 dissect_spnego_InitialContextToken(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index _U_) {
591 offset = dissect_ber_sequence(implicit_tag, pinfo, tree, tvb, offset,
592 InitialContextToken_sequence, hf_index, ett_spnego_InitialContextToken);
598 /*--- End of included file: packet-spnego-fn.c ---*/
599 #line 100 "packet-spnego-template.c"
601 * This is the SPNEGO KRB5 dissector. It is not true KRB5, but some ASN.1
602 * wrapped blob with an OID, USHORT token ID, and a Ticket, that is also
603 * ASN.1 wrapped by the looks of it. It conforms to RFC1964.
606 #define KRB_TOKEN_AP_REQ 0x0001
607 #define KRB_TOKEN_AP_REP 0x0002
608 #define KRB_TOKEN_AP_ERR 0x0003
609 #define KRB_TOKEN_GETMIC 0x0101
610 #define KRB_TOKEN_WRAP 0x0102
611 #define KRB_TOKEN_DELETE_SEC_CONTEXT 0x0201
613 static const value_string spnego_krb5_tok_id_vals[] = {
614 { KRB_TOKEN_AP_REQ, "KRB5_AP_REQ"},
615 { KRB_TOKEN_AP_REP, "KRB5_AP_REP"},
616 { KRB_TOKEN_AP_ERR, "KRB5_ERROR"},
617 { KRB_TOKEN_GETMIC, "KRB5_GSS_GetMIC" },
618 { KRB_TOKEN_WRAP, "KRB5_GSS_Wrap" },
619 { KRB_TOKEN_DELETE_SEC_CONTEXT, "KRB5_GSS_Delete_sec_context" },
623 #define KRB_SGN_ALG_DES_MAC_MD5 0x0000
624 #define KRB_SGN_ALG_MD2_5 0x0001
625 #define KRB_SGN_ALG_DES_MAC 0x0002
626 #define KRB_SGN_ALG_HMAC 0x0011
628 static const value_string spnego_krb5_sgn_alg_vals[] = {
629 { KRB_SGN_ALG_DES_MAC_MD5, "DES MAC MD5"},
630 { KRB_SGN_ALG_MD2_5, "MD2.5"},
631 { KRB_SGN_ALG_DES_MAC, "DES MAC"},
632 { KRB_SGN_ALG_HMAC, "HMAC"},
636 #define KRB_SEAL_ALG_DES_CBC 0x0000
637 #define KRB_SEAL_ALG_RC4 0x0010
638 #define KRB_SEAL_ALG_NONE 0xffff
640 static const value_string spnego_krb5_seal_alg_vals[] = {
641 { KRB_SEAL_ALG_DES_CBC, "DES CBC"},
642 { KRB_SEAL_ALG_RC4, "RC4"},
643 { KRB_SEAL_ALG_NONE, "None"},
648 * XXX - is this for SPNEGO or just GSS-API?
649 * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
650 * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
651 * than designating SPNEGO as the mechanism, offering Kerberos V5, and
652 * getting it accepted.
655 dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
657 dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint16 token_id);
660 dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
667 gssapi_oid_value *value;
670 gboolean pc, ind = 0;
674 item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, offset,
677 subtree = proto_item_add_subtree(item, ett_spnego_krb5);
680 * The KRB5 blob conforms to RFC1964:
683 * USHORT (0x0001 == AP-REQ, 0x0002 == AP-REP, 0x0003 == ERROR),
686 * However, for some protocols, the KRB5 blob starts at the SHORT
687 * and has no DER encoded header etc.
689 * It appears that for some other protocols the KRB5 blob is just
690 * a Kerberos message, with no [APPLICATION 0] header, no OID,
695 * If we see an [APPLICATION 0] HEADER, we show the OID and
696 * the USHORT, and then dissect the rest as a Kerberos message.
698 * If we see an [APPLICATION 14] or [APPLICATION 15] header,
699 * we assume it's an AP-REQ or AP-REP message, and dissect
700 * it all as a Kerberos message.
702 * Otherwise, we show the USHORT, and then dissect the rest
703 * as a Kerberos message.
707 * Get the first header ...
709 get_ber_identifier(tvb, offset, &class, &pc, &tag);
710 if (class == BER_CLASS_APP && pc) {
712 * [APPLICATION <tag>]
714 offset = dissect_ber_identifier(pinfo, subtree, tvb, offset, &class, &pc, &tag);
715 offset = dissect_ber_length(pinfo, subtree, tvb, offset, &len, &ind);
725 offset=dissect_ber_object_identifier_str(FALSE, pinfo, subtree, tvb, offset, hf_spnego_krb5_oid, &oid);
727 value = gssapi_lookup_oid_str(oid);
729 token_id = tvb_get_letohs(tvb, offset);
730 proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
737 case 14: /* [APPLICATION 14] */
738 case 15: /* [APPLICATION 15] */
740 * No token ID - just dissect as a Kerberos message and
743 offset = dissect_kerberos_main(tvb, pinfo, subtree, FALSE, NULL);
747 proto_tree_add_text(subtree, tvb, offset, 0,
748 "Unknown header (class=%d, pc=%d, tag=%d)",
753 /* Next, the token ID ... */
755 token_id = tvb_get_letohs(tvb, offset);
756 proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
764 case KRB_TOKEN_AP_REQ:
765 case KRB_TOKEN_AP_REP:
766 case KRB_TOKEN_AP_ERR:
767 krb5_tvb = tvb_new_subset(tvb, offset, -1, -1);
768 offset = dissect_kerberos_main(krb5_tvb, pinfo, subtree, FALSE, NULL);
771 case KRB_TOKEN_GETMIC:
772 offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
776 offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
779 case KRB_TOKEN_DELETE_SEC_CONTEXT:
793 #include <epan/crypt-md5.h>
795 #ifndef KEYTYPE_ARCFOUR_56
796 # define KEYTYPE_ARCFOUR_56 24
798 /* XXX - We should probably do a configure-time check for this instead */
799 #ifndef KRB5_KU_USAGE_SEAL
800 # define KRB5_KU_USAGE_SEAL 22
804 arcfour_mic_key(void *key_data, size_t key_size, int key_type,
805 void *cksum_data, size_t cksum_size,
813 if (key_type == KEYTYPE_ARCFOUR_56) {
814 guint8 L40[14] = "fortybits";
816 memcpy(L40 + 10, T, sizeof(T));
822 memset(&k5_data[7], 0xAB, 9);
832 cksum_data, cksum_size,
841 usage2arcfour(int usage)
844 case 3: /*KRB5_KU_AS_REP_ENC_PART 3 */
845 case 9: /*KRB5_KU_TGS_REP_ENC_PART_SUB_KEY 9 */
847 case 22: /*KRB5_KU_USAGE_SEAL 22 */
849 case 23: /*KRB5_KU_USAGE_SIGN 23 */
851 case 24: /*KRB5_KU_USAGE_SEQ 24 */
859 arcfour_mic_cksum(guint8 *key_data, int key_length,
862 const void *v1, size_t l1,
863 const void *v2, size_t l2,
864 const void *v3, size_t l3)
866 const guint8 signature[] = "signaturekey";
870 unsigned char digest[16];
874 rc4_usage=usage2arcfour(usage);
875 md5_hmac(signature, sizeof(signature),
876 key_data, key_length,
879 t[0] = (rc4_usage >> 0) & 0xFF;
880 t[1] = (rc4_usage >> 8) & 0xFF;
881 t[2] = (rc4_usage >> 16) & 0xFF;
882 t[3] = (rc4_usage >> 24) & 0xFF;
883 md5_append(&ms, t, 4);
884 md5_append(&ms, v1, l1);
885 md5_append(&ms, v2, l2);
886 md5_append(&ms, v3, l3);
887 md5_finish(&ms, digest);
888 md5_hmac(digest, 16, ksign_c, 16, cksum);
890 memcpy(sgn_cksum, cksum, 8);
896 * Verify padding of a gss wrapped message and return its length.
899 gssapi_verify_pad(unsigned char *wrapped_data, int wrapped_length,
907 pad = wrapped_data + wrapped_length - 1;
910 if (padlength > datalen)
913 for (i = padlength; i > 0 && *pad == padlength; i--, pad--)
924 decrypt_arcfour(packet_info *pinfo,
925 guint8 *input_message_buffer,
926 guint8 *output_message_buffer,
927 guint8 *key_value, int key_size, int key_type)
929 guint8 Klocaldata[16];
933 guint8 k6_data[16], SND_SEQ[8], Confounder[8];
934 guint8 cksum_data[8];
939 datalen = tvb_length(pinfo->gssapi_encrypted_tvb);
941 if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0x1000){
943 } else if (tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0xffff){
949 if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 6)!=0xffff){
953 ret = arcfour_mic_key(key_value, key_size, key_type,
954 (void *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
962 rc4_state_struct rc4_state;
964 crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
965 memcpy(SND_SEQ, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 8, 8), 8);
966 crypt_rc4(&rc4_state, SND_SEQ, 8);
968 memset(k6_data, 0, sizeof(k6_data));
971 seq_number=g_ntohl(*((guint32 *)SND_SEQ));
973 cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4);
975 cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4);
985 for (i = 0; i < 16; i++)
986 Klocaldata[i] = ((guint8 *)key_value)[i] ^ 0xF0;
988 ret = arcfour_mic_key(Klocaldata,sizeof(Klocaldata),key_type,
991 memset(Klocaldata, 0, sizeof(Klocaldata));
997 rc4_state_struct rc4_state;
999 crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
1000 memcpy(Confounder, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8), 8);
1001 crypt_rc4(&rc4_state, Confounder, 8);
1002 memcpy(output_message_buffer, input_message_buffer, datalen);
1003 crypt_rc4(&rc4_state, output_message_buffer, datalen);
1006 tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8),
1007 8); /* Confounder */
1008 memcpy(output_message_buffer,
1009 input_message_buffer,
1012 memset(k6_data, 0, sizeof(k6_data));
1014 /* only normal (i.e. non DCE style wrapping use padding ? */
1015 if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
1016 ret = gssapi_verify_pad(output_message_buffer,datalen,datalen, &padlen);
1023 /* dont know what the checksum looks like for dce style gssapi */
1024 if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
1025 ret = arcfour_mic_cksum(key_value, key_size,
1028 tvb_get_ptr(pinfo->gssapi_wrap_tvb, 0, 8), 8,
1029 Confounder, sizeof(Confounder),
1030 output_message_buffer,
1036 cmp = memcmp(cksum_data,
1037 tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
1049 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1052 decrypt_gssapi_krb_arcfour_wrap(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int keytype)
1057 const guint8 *original_data;
1059 static int omb_index=0;
1060 static guint8 *omb_arr[4]={NULL,NULL,NULL,NULL};
1061 static guint8 *cryptocopy=NULL; /* workaround for pre-0.6.1 heimdal bug */
1062 guint8 *output_message_buffer;
1068 output_message_buffer=omb_arr[omb_index];
1071 length=tvb_length(pinfo->gssapi_encrypted_tvb);
1072 original_data=tvb_get_ptr(pinfo->gssapi_encrypted_tvb, 0, length);
1074 /* dont do anything if we are not attempting to decrypt data */
1080 /* XXX we should only do this for first time, then store somewhere */
1081 /* XXX We also need to re-read the keytab when the preference changes */
1083 cryptocopy=ep_alloc(length);
1084 if(output_message_buffer){
1085 g_free(output_message_buffer);
1086 output_message_buffer=NULL;
1088 output_message_buffer=g_malloc(length);
1090 for(ek=enc_key_list;ek;ek=ek->next){
1091 /* shortcircuit and bail out if enctypes are not matching */
1092 if(ek->keytype!=keytype){
1096 /* pre-0.6.1 versions of Heimdal would sometimes change
1097 the cryptotext data even when the decryption failed.
1098 This would obviously not work since we iterate over the
1099 keys. So just give it a copy of the crypto data instead.
1100 This has been seen for RC4-HMAC blobs.
1102 memcpy(cryptocopy, original_data, length);
1103 ret=decrypt_arcfour(pinfo,
1105 output_message_buffer,
1111 proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
1112 pinfo->gssapi_decrypted_tvb=tvb_new_real_data(
1113 output_message_buffer,
1115 tvb_set_child_real_data_tvbuff(tvb, pinfo->gssapi_decrypted_tvb);
1116 add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
1122 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1128 * XXX - This is for GSSAPI Wrap tokens ...
1131 dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
1132 #ifndef HAVE_KERBEROS
1135 , proto_tree *tree, guint16 token_id
1136 #ifndef HAVE_KERBEROS
1141 guint16 sgn_alg, seal_alg;
1142 #ifdef HAVE_KERBEROS
1143 int start_offset=offset;
1147 * The KRB5 blob conforms to RFC1964:
1148 * USHORT (0x0102 == GSS_Wrap)
1152 /* Now, the sign and seal algorithms ... */
1154 sgn_alg = tvb_get_letohs(tvb, offset);
1155 proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
1160 seal_alg = tvb_get_letohs(tvb, offset);
1161 proto_tree_add_uint(tree, hf_spnego_krb5_seal_alg, tvb, offset, 2,
1166 /* Skip the filler */
1170 /* Encrypted sequence number */
1172 proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
1177 /* Checksum of plaintext padded data */
1179 proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
1185 * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
1186 * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
1187 * extra 8 bytes of "Random confounder" after the checksum.
1188 * It certainly confounds code expecting all Kerberos 5
1189 * GSS_Wrap() tokens to look the same....
1191 if (sgn_alg == KRB_SGN_ALG_HMAC) {
1192 proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
1197 /* Is the data encrypted? */
1198 pinfo->gssapi_data_encrypted=(seal_alg!=KRB_SEAL_ALG_NONE);
1200 #ifdef HAVE_KERBEROS
1201 #define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
1202 if(pinfo->decrypt_gssapi_tvb){
1203 /* if the caller did not provide a tvb, then we just use
1204 whatever is left of our current tvb.
1206 if(!pinfo->gssapi_encrypted_tvb){
1208 len=tvb_reported_length_remaining(tvb,offset);
1209 if(len>tvb_length_remaining(tvb, offset)){
1210 /* no point in trying to decrypt,
1211 we dont have the full pdu.
1215 pinfo->gssapi_encrypted_tvb = tvb_new_subset(
1216 tvb, offset, len, len);
1219 /* if this is KRB5 wrapped rc4-hmac */
1220 if((token_id==KRB_TOKEN_WRAP)
1221 &&(sgn_alg==KRB_SGN_ALG_HMAC)
1222 &&(seal_alg==KRB_SEAL_ALG_RC4)){
1223 /* do we need to create a tvb for the wrapper
1226 if(!pinfo->gssapi_wrap_tvb){
1227 pinfo->gssapi_wrap_tvb = tvb_new_subset(
1228 tvb, start_offset-2,
1229 GSS_ARCFOUR_WRAP_TOKEN_SIZE,
1230 GSS_ARCFOUR_WRAP_TOKEN_SIZE);
1232 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1233 decrypt_gssapi_krb_arcfour_wrap(tree,
1237 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1242 * Return the offset past the checksum, so that we know where
1243 * the data we're wrapped around starts. Also, set the length
1244 * of our top-level item to that offset, so it doesn't cover
1245 * the data we're wrapped around.
1247 * Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
1254 * XXX - This is for GSSAPI GetMIC tokens ...
1257 dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
1262 * The KRB5 blob conforms to RFC1964:
1263 * USHORT (0x0101 == GSS_GetMIC)
1267 /* Now, the sign algorithm ... */
1269 sgn_alg = tvb_get_letohs(tvb, offset);
1270 proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
1275 /* Skip the filler */
1279 /* Encrypted sequence number */
1281 proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
1286 /* Checksum of plaintext padded data */
1288 proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
1294 * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
1295 * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
1296 * extra 8 bytes of "Random confounder" after the checksum.
1297 * It certainly confounds code expecting all Kerberos 5
1298 * GSS_Wrap() tokens to look the same....
1300 * The exception is DNS/TSIG where there is no such confounder
1301 * so we need to test here if there are more bytes in our tvb or not.
1304 if (tvb_length_remaining(tvb, offset)) {
1305 if (sgn_alg == KRB_SGN_ALG_HMAC) {
1306 proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
1314 * Return the offset past the checksum, so that we know where
1315 * the data we're wrapped around starts. Also, set the length
1316 * of our top-level item to that offset, so it doesn't cover
1317 * the data we're wrapped around.
1324 * XXX - is this for SPNEGO or just GSS-API?
1325 * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
1326 * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
1327 * than designating SPNEGO as the mechanism, offering Kerberos V5, and
1328 * getting it accepted.
1331 dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1334 proto_tree *subtree;
1338 item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, 0, -1, FALSE);
1340 subtree = proto_item_add_subtree(item, ett_spnego_krb5);
1343 * The KRB5 blob conforms to RFC1964:
1344 * USHORT (0x0102 == GSS_Wrap)
1348 /* First, the token ID ... */
1350 token_id = tvb_get_letohs(tvb, offset);
1351 proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
1356 offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
1359 * Return the offset past the checksum, so that we know where
1360 * the data we're wrapped around starts. Also, set the length
1361 * of our top-level item to that offset, so it doesn't cover
1362 * the data we're wrapped around.
1364 proto_item_set_len(item, offset);
1368 /* Spnego stuff from here */
1371 dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1374 proto_tree *subtree;
1380 * We need this later, so lets get it now ...
1381 * It has to be per-frame as there can be more than one GSS-API
1382 * negotiation in a conversation.
1386 item = proto_tree_add_item(tree, hf_spnego, tvb, offset,
1389 subtree = proto_item_add_subtree(item, ett_spnego);
1391 * The TVB contains a [0] header and a sequence that consists of an
1392 * object ID and a blob containing the data ...
1393 * XXX - is this RFC 2743's "Mechanism-Independent Token Format",
1394 * with the "optional" "use in non-initial tokens" being chosen.
1395 * ASN1 code addet to spnego.asn to handle this.
1398 offset = dissect_spnego_InitialContextToken(FALSE, tvb, offset, pinfo , subtree, -1);
1405 dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
1408 proto_tree *subtree;
1410 conversation_t *conversation;
1413 * We need this later, so lets get it now ...
1414 * It has to be per-frame as there can be more than one GSS-API
1415 * negotiation in a conversation.
1417 next_level_value = p_get_proto_data(pinfo->fd, proto_spnego);
1418 if (!next_level_value && !pinfo->fd->flags.visited) {
1420 * No handle attached to this frame, but it's the first
1421 * pass, so it'd be attached to the conversation.
1422 * If we have a conversation, try to get the handle,
1423 * and if we get one, attach it to the frame.
1425 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1426 pinfo->ptype, pinfo->srcport,
1427 pinfo->destport, 0);
1430 next_level_value = conversation_get_proto_data(conversation,
1432 if (next_level_value)
1433 p_add_proto_data(pinfo->fd, proto_spnego, next_level_value);
1437 item = proto_tree_add_item(parent_tree, hf_spnego, tvb, offset,
1440 subtree = proto_item_add_subtree(item, ett_spnego);
1443 * The TVB contains a [0] header and a sequence that consists of an
1444 * object ID and a blob containing the data ...
1445 * Actually, it contains, according to RFC2478:
1446 * NegotiationToken ::= CHOICE {
1447 * negTokenInit [0] NegTokenInit,
1448 * negTokenTarg [1] NegTokenTarg }
1449 * NegTokenInit ::= SEQUENCE {
1450 * mechTypes [0] MechTypeList OPTIONAL,
1451 * reqFlags [1] ContextFlags OPTIONAL,
1452 * mechToken [2] OCTET STRING OPTIONAL,
1453 * mechListMIC [3] OCTET STRING OPTIONAL }
1454 * NegTokenTarg ::= SEQUENCE {
1455 * negResult [0] ENUMERATED {
1456 * accept_completed (0),
1457 * accept_incomplete (1),
1458 * reject (2) } OPTIONAL,
1459 * supportedMech [1] MechType OPTIONAL,
1460 * responseToken [2] OCTET STRING OPTIONAL,
1461 * mechListMIC [3] OCTET STRING OPTIONAL }
1463 * Windows typically includes mechTypes and mechListMic ('NONE'
1464 * in the case of NTLMSSP only).
1465 * It seems to duplicate the responseToken into the mechListMic field
1466 * as well. Naughty, naughty.
1469 offset = dissect_spnego_NegotiationToken(FALSE, tvb, offset, pinfo, subtree, -1);
1473 /*--- proto_register_spnego -------------------------------------------*/
1474 void proto_register_spnego(void) {
1476 /* List of fields */
1477 static hf_register_info hf[] = {
1479 { "SPNEGO", "spnego", FT_NONE, BASE_NONE, NULL, 0x0,
1481 { &hf_spnego_wraptoken,
1482 { "wrapToken", "spnego.wraptoken",
1483 FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO wrapToken",
1486 { "krb5_blob", "spnego.krb5.blob", FT_BYTES,
1487 BASE_NONE, NULL, 0, "krb5_blob", HFILL }},
1488 { &hf_spnego_krb5_oid,
1489 { "KRB5 OID", "spnego.krb5_oid", FT_STRING,
1490 BASE_NONE, NULL, 0, "KRB5 OID", HFILL }},
1491 { &hf_spnego_krb5_tok_id,
1492 { "krb5_tok_id", "spnego.krb5.tok_id", FT_UINT16, BASE_HEX,
1493 VALS(spnego_krb5_tok_id_vals), 0, "KRB5 Token Id", HFILL}},
1494 { &hf_spnego_krb5_sgn_alg,
1495 { "krb5_sgn_alg", "spnego.krb5.sgn_alg", FT_UINT16, BASE_HEX,
1496 VALS(spnego_krb5_sgn_alg_vals), 0, "KRB5 Signing Algorithm", HFILL}},
1497 { &hf_spnego_krb5_seal_alg,
1498 { "krb5_seal_alg", "spnego.krb5.seal_alg", FT_UINT16, BASE_HEX,
1499 VALS(spnego_krb5_seal_alg_vals), 0, "KRB5 Sealing Algorithm", HFILL}},
1500 { &hf_spnego_krb5_snd_seq,
1501 { "krb5_snd_seq", "spnego.krb5.snd_seq", FT_BYTES, BASE_NONE,
1502 NULL, 0, "KRB5 Encrypted Sequence Number", HFILL}},
1503 { &hf_spnego_krb5_sgn_cksum,
1504 { "krb5_sgn_cksum", "spnego.krb5.sgn_cksum", FT_BYTES, BASE_NONE,
1505 NULL, 0, "KRB5 Data Checksum", HFILL}},
1506 { &hf_spnego_krb5_confounder,
1507 { "krb5_confounder", "spnego.krb5.confounder", FT_BYTES, BASE_NONE,
1508 NULL, 0, "KRB5 Confounder", HFILL}},
1511 /*--- Included file: packet-spnego-hfarr.c ---*/
1512 #line 1 "packet-spnego-hfarr.c"
1513 { &hf_spnego_negTokenInit,
1514 { "negTokenInit", "spnego.negTokenInit",
1515 FT_NONE, BASE_NONE, NULL, 0,
1516 "NegotiationToken/negTokenInit", HFILL }},
1517 { &hf_spnego_negTokenTarg,
1518 { "negTokenTarg", "spnego.negTokenTarg",
1519 FT_NONE, BASE_NONE, NULL, 0,
1520 "NegotiationToken/negTokenTarg", HFILL }},
1521 { &hf_spnego_MechTypeList_item,
1522 { "Item", "spnego.MechTypeList_item",
1523 FT_OID, BASE_NONE, NULL, 0,
1524 "MechTypeList/_item", HFILL }},
1525 { &hf_spnego_principal,
1526 { "principal", "spnego.principal",
1527 FT_STRING, BASE_NONE, NULL, 0,
1528 "PrincipalSeq/principal", HFILL }},
1529 { &hf_spnego_mechTypes,
1530 { "mechTypes", "spnego.mechTypes",
1531 FT_UINT32, BASE_DEC, NULL, 0,
1532 "NegTokenInit/mechTypes", HFILL }},
1533 { &hf_spnego_reqFlags,
1534 { "reqFlags", "spnego.reqFlags",
1535 FT_BYTES, BASE_HEX, NULL, 0,
1536 "NegTokenInit/reqFlags", HFILL }},
1537 { &hf_spnego_mechToken,
1538 { "mechToken", "spnego.mechToken",
1539 FT_BYTES, BASE_HEX, NULL, 0,
1540 "NegTokenInit/mechToken", HFILL }},
1541 { &hf_spnego_negTokenInit_mechListMIC,
1542 { "mechListMIC", "spnego.mechListMIC",
1543 FT_BYTES, BASE_HEX, NULL, 0,
1544 "NegTokenInit/mechListMIC", HFILL }},
1545 { &hf_spnego_negResult,
1546 { "negResult", "spnego.negResult",
1547 FT_UINT32, BASE_DEC, VALS(spnego_T_negResult_vals), 0,
1548 "NegTokenTarg/negResult", HFILL }},
1549 { &hf_spnego_supportedMech,
1550 { "supportedMech", "spnego.supportedMech",
1551 FT_OID, BASE_NONE, NULL, 0,
1552 "NegTokenTarg/supportedMech", HFILL }},
1553 { &hf_spnego_responseToken,
1554 { "responseToken", "spnego.responseToken",
1555 FT_BYTES, BASE_HEX, NULL, 0,
1556 "NegTokenTarg/responseToken", HFILL }},
1557 { &hf_spnego_mechListMIC,
1558 { "mechListMIC", "spnego.mechListMIC",
1559 FT_BYTES, BASE_HEX, NULL, 0,
1560 "NegTokenTarg/mechListMIC", HFILL }},
1561 { &hf_spnego_thisMech,
1562 { "thisMech", "spnego.thisMech",
1563 FT_OID, BASE_NONE, NULL, 0,
1564 "InitialContextToken/thisMech", HFILL }},
1565 { &hf_spnego_innerContextToken,
1566 { "innerContextToken", "spnego.innerContextToken",
1567 FT_NONE, BASE_NONE, NULL, 0,
1568 "InitialContextToken/innerContextToken", HFILL }},
1569 { &hf_spnego_ContextFlags_delegFlag,
1570 { "delegFlag", "spnego.delegFlag",
1571 FT_BOOLEAN, 8, NULL, 0x80,
1573 { &hf_spnego_ContextFlags_mutualFlag,
1574 { "mutualFlag", "spnego.mutualFlag",
1575 FT_BOOLEAN, 8, NULL, 0x40,
1577 { &hf_spnego_ContextFlags_replayFlag,
1578 { "replayFlag", "spnego.replayFlag",
1579 FT_BOOLEAN, 8, NULL, 0x20,
1581 { &hf_spnego_ContextFlags_sequenceFlag,
1582 { "sequenceFlag", "spnego.sequenceFlag",
1583 FT_BOOLEAN, 8, NULL, 0x10,
1585 { &hf_spnego_ContextFlags_anonFlag,
1586 { "anonFlag", "spnego.anonFlag",
1587 FT_BOOLEAN, 8, NULL, 0x08,
1589 { &hf_spnego_ContextFlags_confFlag,
1590 { "confFlag", "spnego.confFlag",
1591 FT_BOOLEAN, 8, NULL, 0x04,
1593 { &hf_spnego_ContextFlags_integFlag,
1594 { "integFlag", "spnego.integFlag",
1595 FT_BOOLEAN, 8, NULL, 0x02,
1598 /*--- End of included file: packet-spnego-hfarr.c ---*/
1599 #line 1011 "packet-spnego-template.c"
1602 /* List of subtrees */
1603 static gint *ett[] = {
1605 &ett_spnego_wraptoken,
1609 /*--- Included file: packet-spnego-ettarr.c ---*/
1610 #line 1 "packet-spnego-ettarr.c"
1611 &ett_spnego_NegotiationToken,
1612 &ett_spnego_MechTypeList,
1613 &ett_spnego_PrincipalSeq,
1614 &ett_spnego_NegTokenInit,
1615 &ett_spnego_ContextFlags,
1616 &ett_spnego_NegTokenTarg,
1617 &ett_spnego_InitialContextToken,
1619 /*--- End of included file: packet-spnego-ettarr.c ---*/
1620 #line 1020 "packet-spnego-template.c"
1623 /* Register protocol */
1624 proto_spnego = proto_register_protocol(PNAME, PSNAME, PFNAME);
1626 proto_spnego_krb5 = proto_register_protocol("SPNEGO-KRB5",
1629 /* Register fields and subtrees */
1630 proto_register_field_array(proto_spnego, hf, array_length(hf));
1631 proto_register_subtree_array(ett, array_length(ett));
1635 /*--- proto_reg_handoff_spnego ---------------------------------------*/
1636 void proto_reg_handoff_spnego(void) {
1638 dissector_handle_t spnego_handle, spnego_wrap_handle;
1639 dissector_handle_t spnego_krb5_handle, spnego_krb5_wrap_handle;
1641 /* Register protocol with GSS-API module */
1643 spnego_handle = create_dissector_handle(dissect_spnego, proto_spnego);
1644 spnego_wrap_handle = new_create_dissector_handle(dissect_spnego_wrap,
1646 gssapi_init_oid("1.3.6.1.5.5.2", proto_spnego, ett_spnego,
1647 spnego_handle, spnego_wrap_handle,
1648 "SPNEGO - Simple Protected Negotiation");
1650 /* Register both the one MS created and the real one */
1652 * Thanks to Jean-Baptiste Marchand and Richard B Ward, the
1653 * mystery of the MS KRB5 OID is cleared up. It was due to a library
1654 * that did not handle OID components greater than 16 bits, and was
1655 * fixed in Win2K SP2 as well as WinXP.
1656 * See the archive of <ietf-krb-wg@anl.gov> for the thread topic
1657 * SPNEGO implementation issues. 3-Dec-2002.
1659 spnego_krb5_handle = create_dissector_handle(dissect_spnego_krb5,
1661 spnego_krb5_wrap_handle = new_create_dissector_handle(dissect_spnego_krb5_wrap,
1663 gssapi_init_oid("1.2.840.48018.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
1664 spnego_krb5_handle, spnego_krb5_wrap_handle,
1665 "MS KRB5 - Microsoft Kerberos 5");
1666 gssapi_init_oid("1.2.840.113554.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
1667 spnego_krb5_handle, spnego_krb5_wrap_handle,
1668 "KRB5 - Kerberos 5");
1669 gssapi_init_oid("1.2.840.113554.1.2.2.3", proto_spnego_krb5, ett_spnego_krb5,
1670 spnego_krb5_handle, spnego_krb5_wrap_handle,
1671 "KRB5 - Kerberos 5 - User to User");
1674 * Find the data handle for some calls
1676 data_handle = find_dissector("data");