FIXUP: WIP: verification_trailer
[wireshark-wip.git] / epan / dissectors / packet-spnego.c
blob012705f9cf39eba44c50da40ba79ad9fa8abe1cf
1 /* Do not modify this file. Changes will be overwritten. */
2 /* Generated automatically by the ASN.1 to Wireshark dissector compiler */
3 /* packet-spnego.c */
4 /* ../../tools/asn2wrs.py -b -p spnego -c ./spnego.cnf -s ./packet-spnego-template -D . -O ../../epan/dissectors spnego.asn */
6 /* Input file: packet-spnego-template.c */
8 #line 1 "../../asn1/spnego/packet-spnego-template.c"
9 /* packet-spnego.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 asn2wrs generated dissector)
18 * $Id$
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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.
42 #include "config.h"
44 #include <glib.h>
46 #include <wsutil/rc4.h>
48 #include <epan/packet.h>
49 #include <epan/asn1.h>
50 #include "packet-dcerpc.h"
51 #include "packet-gssapi.h"
52 #include "packet-kerberos.h"
53 #include <epan/conversation.h>
54 #include <epan/wmem/wmem.h>
55 #include <epan/asn1.h>
57 #include <string.h>
59 #include "packet-ber.h"
62 #define PNAME "Simple Protected Negotiation"
63 #define PSNAME "SPNEGO"
64 #define PFNAME "spnego"
66 /* Initialize the protocol and registered fields */
67 static int proto_spnego = -1;
68 static int proto_spnego_krb5 = -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;
80 static int hf_spnego_krb5_filler = -1;
81 static int hf_spnego_krb5_cfx_flags = -1;
82 static int hf_spnego_krb5_cfx_flags_01 = -1;
83 static int hf_spnego_krb5_cfx_flags_02 = -1;
84 static int hf_spnego_krb5_cfx_flags_04 = -1;
85 static int hf_spnego_krb5_cfx_ec = -1;
86 static int hf_spnego_krb5_cfx_rrc = -1;
87 static int hf_spnego_krb5_cfx_seq = -1;
90 /*--- Included file: packet-spnego-hf.c ---*/
91 #line 1 "../../asn1/spnego/packet-spnego-hf.c"
92 static int hf_spnego_negTokenInit = -1; /* NegTokenInit */
93 static int hf_spnego_negTokenTarg = -1; /* NegTokenTarg */
94 static int hf_spnego_MechTypeList_item = -1; /* MechType */
95 static int hf_spnego_principal = -1; /* GeneralString */
96 static int hf_spnego_mechTypes = -1; /* MechTypeList */
97 static int hf_spnego_reqFlags = -1; /* ContextFlags */
98 static int hf_spnego_mechToken = -1; /* T_mechToken */
99 static int hf_spnego_negTokenInit_mechListMIC = -1; /* T_NegTokenInit_mechListMIC */
100 static int hf_spnego_negResult = -1; /* T_negResult */
101 static int hf_spnego_supportedMech = -1; /* T_supportedMech */
102 static int hf_spnego_responseToken = -1; /* T_responseToken */
103 static int hf_spnego_mechListMIC = -1; /* T_mechListMIC */
104 static int hf_spnego_thisMech = -1; /* MechType */
105 static int hf_spnego_innerContextToken = -1; /* InnerContextToken */
106 /* named bits */
107 static int hf_spnego_ContextFlags_delegFlag = -1;
108 static int hf_spnego_ContextFlags_mutualFlag = -1;
109 static int hf_spnego_ContextFlags_replayFlag = -1;
110 static int hf_spnego_ContextFlags_sequenceFlag = -1;
111 static int hf_spnego_ContextFlags_anonFlag = -1;
112 static int hf_spnego_ContextFlags_confFlag = -1;
113 static int hf_spnego_ContextFlags_integFlag = -1;
115 /*--- End of included file: packet-spnego-hf.c ---*/
116 #line 82 "../../asn1/spnego/packet-spnego-template.c"
118 /* Global variables */
119 static const char *MechType_oid;
120 gssapi_oid_value *next_level_value;
121 gboolean saw_mechanism = FALSE;
124 /* Initialize the subtree pointers */
125 static gint ett_spnego = -1;
126 static gint ett_spnego_wraptoken = -1;
127 static gint ett_spnego_krb5 = -1;
128 static gint ett_spnego_krb5_cfx_flags = -1;
131 /*--- Included file: packet-spnego-ett.c ---*/
132 #line 1 "../../asn1/spnego/packet-spnego-ett.c"
133 static gint ett_spnego_NegotiationToken = -1;
134 static gint ett_spnego_MechTypeList = -1;
135 static gint ett_spnego_PrincipalSeq = -1;
136 static gint ett_spnego_NegTokenInit = -1;
137 static gint ett_spnego_ContextFlags = -1;
138 static gint ett_spnego_NegTokenTarg = -1;
139 static gint ett_spnego_InitialContextToken_U = -1;
141 /*--- End of included file: packet-spnego-ett.c ---*/
142 #line 96 "../../asn1/spnego/packet-spnego-template.c"
145 * Unfortunately, we have to have a forward declaration of this,
146 * as the code generated by asn2wrs includes a call before the
147 * definition.
149 static int dissect_spnego_PrincipalSeq(gboolean implicit_tag, tvbuff_t *tvb,
150 int offset, asn1_ctx_t *actx _U_,
151 proto_tree *tree, int hf_index);
154 /*--- Included file: packet-spnego-fn.c ---*/
155 #line 1 "../../asn1/spnego/packet-spnego-fn.c"
158 static int
159 dissect_spnego_MechType(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
160 #line 23 "../../asn1/spnego/spnego.cnf"
162 gssapi_oid_value *value;
164 offset = dissect_ber_object_identifier_str(implicit_tag, actx, tree, tvb, offset, hf_index, &MechType_oid);
167 value = gssapi_lookup_oid_str(MechType_oid);
170 * Tell our caller the first mechanism we see, so that if
171 * this is a negTokenInit with a mechToken, it can interpret
172 * the mechToken according to the first mechType. (There
173 * might not have been any indication of the mechType
174 * in prior frames, so we can't necessarily use the
175 * mechanism from the conversation; i.e., a negTokenInit
176 * can contain the initial security token for the desired
177 * mechanism of the initiator - that's the first mechanism
178 * in the list.)
180 if (!saw_mechanism) {
181 if (value)
182 next_level_value = value;
183 saw_mechanism = TRUE;
188 return offset;
192 static const ber_sequence_t MechTypeList_sequence_of[1] = {
193 { &hf_spnego_MechTypeList_item, BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_spnego_MechType },
196 static int
197 dissect_spnego_MechTypeList(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
198 #line 91 "../../asn1/spnego/spnego.cnf"
200 conversation_t *conversation;
202 saw_mechanism = FALSE;
204 offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset,
205 MechTypeList_sequence_of, hf_index, ett_spnego_MechTypeList);
209 * If we saw a mechType we need to store it in case the negTokenTarg
210 * does not provide a supportedMech.
212 if(saw_mechanism){
213 conversation = find_or_create_conversation(actx->pinfo);
214 conversation_add_proto_data(conversation, proto_spnego, next_level_value);
219 return offset;
223 static const asn_namedbit ContextFlags_bits[] = {
224 { 0, &hf_spnego_ContextFlags_delegFlag, -1, -1, "delegFlag", NULL },
225 { 1, &hf_spnego_ContextFlags_mutualFlag, -1, -1, "mutualFlag", NULL },
226 { 2, &hf_spnego_ContextFlags_replayFlag, -1, -1, "replayFlag", NULL },
227 { 3, &hf_spnego_ContextFlags_sequenceFlag, -1, -1, "sequenceFlag", NULL },
228 { 4, &hf_spnego_ContextFlags_anonFlag, -1, -1, "anonFlag", NULL },
229 { 5, &hf_spnego_ContextFlags_confFlag, -1, -1, "confFlag", NULL },
230 { 6, &hf_spnego_ContextFlags_integFlag, -1, -1, "integFlag", NULL },
231 { 0, NULL, 0, 0, NULL, NULL }
234 static int
235 dissect_spnego_ContextFlags(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
236 offset = dissect_ber_bitstring(implicit_tag, actx, tree, tvb, offset,
237 ContextFlags_bits, hf_index, ett_spnego_ContextFlags,
238 NULL);
240 return offset;
245 static int
246 dissect_spnego_T_mechToken(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
247 #line 112 "../../asn1/spnego/spnego.cnf"
249 tvbuff_t *mechToken_tvb = NULL;
251 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
252 &mechToken_tvb);
256 * Now, we should be able to dispatch, if we've gotten a tvbuff for
257 * the token and we have information on how to dissect its contents.
259 if (mechToken_tvb && next_level_value)
260 call_dissector(next_level_value->handle, mechToken_tvb, actx->pinfo, tree);
265 return offset;
270 static int
271 dissect_spnego_T_NegTokenInit_mechListMIC(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
272 #line 126 "../../asn1/spnego/spnego.cnf"
274 gint8 ber_class;
275 gboolean pc;
276 gint32 tag;
277 tvbuff_t *mechListMIC_tvb;
280 * There seems to be two different forms this can take,
281 * one as an octet string, and one as a general string in a
282 * sequence.
284 * Peek at the header, and then decide which it is we're seeing.
286 get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
287 if (ber_class == BER_CLASS_UNI && pc && tag == BER_UNI_TAG_SEQUENCE) {
289 * It's a sequence.
291 return dissect_spnego_PrincipalSeq(FALSE, tvb, offset, actx, tree,
292 hf_spnego_mechListMIC);
293 } else {
295 * It's not a sequence, so dissect it as an octet string,
296 * which is what it's supposed to be; that'll cause the
297 * right error report if it's not an octet string, either.
299 offset = dissect_ber_octet_string(FALSE, actx, tree, tvb, offset,
300 hf_spnego_mechListMIC, &mechListMIC_tvb);
303 * Now, we should be able to dispatch with that tvbuff.
305 if (mechListMIC_tvb && next_level_value)
306 call_dissector(next_level_value->handle, mechListMIC_tvb, actx->pinfo, tree);
307 return offset;
312 return offset;
316 static const ber_sequence_t NegTokenInit_sequence[] = {
317 { &hf_spnego_mechTypes , BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL, dissect_spnego_MechTypeList },
318 { &hf_spnego_reqFlags , BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_spnego_ContextFlags },
319 { &hf_spnego_mechToken , BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_spnego_T_mechToken },
320 { &hf_spnego_negTokenInit_mechListMIC, BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL, dissect_spnego_T_NegTokenInit_mechListMIC },
321 { NULL, 0, 0, 0, NULL }
324 static int
325 dissect_spnego_NegTokenInit(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
326 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
327 NegTokenInit_sequence, hf_index, ett_spnego_NegTokenInit);
329 return offset;
333 static const value_string spnego_T_negResult_vals[] = {
334 { 0, "accept-completed" },
335 { 1, "accept-incomplete" },
336 { 2, "reject" },
337 { 0, NULL }
341 static int
342 dissect_spnego_T_negResult(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
343 offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
344 NULL);
346 return offset;
351 static int
352 dissect_spnego_T_supportedMech(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
353 #line 164 "../../asn1/spnego/spnego.cnf"
355 conversation_t *conversation;
357 saw_mechanism = FALSE;
359 offset = dissect_spnego_MechType(implicit_tag, tvb, offset, actx, tree, hf_index);
363 * If we saw an explicit mechType we store this in the conversation so that
364 * it will override any mechType we might have picked up from the
365 * negTokenInit.
367 if(saw_mechanism){
368 conversation = find_or_create_conversation(actx->pinfo);
369 conversation_add_proto_data(conversation, proto_spnego, next_level_value);
375 return offset;
380 static int
381 dissect_spnego_T_responseToken(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
382 #line 187 "../../asn1/spnego/spnego.cnf"
384 tvbuff_t *responseToken_tvb;
387 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
388 &responseToken_tvb);
393 * Now, we should be able to dispatch, if we've gotten a tvbuff for
394 * the token and we have information on how to dissect its contents.
395 * However, we should make sure that there is something in the
396 * response token ...
398 if (responseToken_tvb && (tvb_reported_length(responseToken_tvb) > 0) ){
399 gssapi_oid_value *value=next_level_value;
401 if(value){
402 call_dissector(value->handle, responseToken_tvb, actx->pinfo, tree);
409 return offset;
414 static int
415 dissect_spnego_T_mechListMIC(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
416 #line 214 "../../asn1/spnego/spnego.cnf"
418 tvbuff_t *mechListMIC_tvb;
421 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
422 &mechListMIC_tvb);
427 * Now, we should be able to dispatch, if we've gotten a tvbuff for
428 * the MIC and we have information on how to dissect its contents.
430 if (mechListMIC_tvb && (tvb_reported_length(mechListMIC_tvb) > 0) ){
431 gssapi_oid_value *value=next_level_value;
433 if(value){
434 call_dissector(value->handle, mechListMIC_tvb, actx->pinfo, tree);
441 return offset;
445 static const ber_sequence_t NegTokenTarg_sequence[] = {
446 { &hf_spnego_negResult , BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL, dissect_spnego_T_negResult },
447 { &hf_spnego_supportedMech, BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_spnego_T_supportedMech },
448 { &hf_spnego_responseToken, BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_spnego_T_responseToken },
449 { &hf_spnego_mechListMIC , BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL, dissect_spnego_T_mechListMIC },
450 { NULL, 0, 0, 0, NULL }
453 static int
454 dissect_spnego_NegTokenTarg(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
455 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
456 NegTokenTarg_sequence, hf_index, ett_spnego_NegTokenTarg);
458 return offset;
462 static const value_string spnego_NegotiationToken_vals[] = {
463 { 0, "negTokenInit" },
464 { 1, "negTokenTarg" },
465 { 0, NULL }
468 static const ber_choice_t NegotiationToken_choice[] = {
469 { 0, &hf_spnego_negTokenInit , BER_CLASS_CON, 0, 0, dissect_spnego_NegTokenInit },
470 { 1, &hf_spnego_negTokenTarg , BER_CLASS_CON, 1, 0, dissect_spnego_NegTokenTarg },
471 { 0, NULL, 0, 0, 0, NULL }
474 static int
475 dissect_spnego_NegotiationToken(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
476 offset = dissect_ber_choice(actx, tree, tvb, offset,
477 NegotiationToken_choice, hf_index, ett_spnego_NegotiationToken,
478 NULL);
480 return offset;
485 static int
486 dissect_spnego_GeneralString(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
487 offset = dissect_ber_restricted_string(implicit_tag, BER_UNI_TAG_GeneralString,
488 actx, tree, tvb, offset, hf_index,
489 NULL);
491 return offset;
495 static const ber_sequence_t PrincipalSeq_sequence[] = {
496 { &hf_spnego_principal , BER_CLASS_CON, 0, 0, dissect_spnego_GeneralString },
497 { NULL, 0, 0, 0, NULL }
500 static int
501 dissect_spnego_PrincipalSeq(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
502 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
503 PrincipalSeq_sequence, hf_index, ett_spnego_PrincipalSeq);
505 return offset;
510 static int
511 dissect_spnego_InnerContextToken(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
512 #line 48 "../../asn1/spnego/spnego.cnf"
514 gssapi_oid_value *next_level_value_lcl;
515 proto_item *item;
516 proto_tree *subtree;
517 tvbuff_t *token_tvb;
518 int len;
521 * XXX - what should we do if this OID doesn't match the value
522 * attached to the frame or conversation? (That would be
523 * bogus, but that's not impossible - some broken implementation
524 * might negotiate some security mechanism but put the OID
525 * for some other security mechanism in GSS_Wrap tokens.)
526 * Does it matter?
528 next_level_value_lcl = gssapi_lookup_oid_str(MechType_oid);
531 * Now dissect the GSS_Wrap token; it's assumed to be in the
532 * rest of the tvbuff.
534 item = proto_tree_add_item(tree, hf_spnego_wraptoken, tvb, offset, -1, ENC_NA);
536 subtree = proto_item_add_subtree(item, ett_spnego_wraptoken);
539 * Now, we should be able to dispatch after creating a new TVB.
540 * The subdissector must return the length of the part of the
541 * token it dissected, so we can return the length of the part
542 * we (and it) dissected.
544 token_tvb = tvb_new_subset_remaining(tvb, offset);
545 if (next_level_value_lcl && next_level_value_lcl->wrap_handle) {
546 len = call_dissector(next_level_value_lcl->wrap_handle, token_tvb, actx->pinfo,
547 subtree);
548 if (len == 0)
549 offset = tvb_length(tvb);
550 else
551 offset = offset + len;
552 } else
553 offset = tvb_length(tvb);
557 return offset;
561 static const ber_sequence_t InitialContextToken_U_sequence[] = {
562 { &hf_spnego_thisMech , BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_spnego_MechType },
563 { &hf_spnego_innerContextToken, BER_CLASS_ANY, 0, BER_FLAGS_NOOWNTAG, dissect_spnego_InnerContextToken },
564 { NULL, 0, 0, 0, NULL }
567 static int
568 dissect_spnego_InitialContextToken_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
569 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
570 InitialContextToken_U_sequence, hf_index, ett_spnego_InitialContextToken_U);
572 return offset;
577 static int
578 dissect_spnego_InitialContextToken(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
579 offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
580 hf_index, BER_CLASS_APP, 0, TRUE, dissect_spnego_InitialContextToken_U);
582 return offset;
586 /*--- End of included file: packet-spnego-fn.c ---*/
587 #line 107 "../../asn1/spnego/packet-spnego-template.c"
589 * This is the SPNEGO KRB5 dissector. It is not true KRB5, but some ASN.1
590 * wrapped blob with an OID, USHORT token ID, and a Ticket, that is also
591 * ASN.1 wrapped by the looks of it. It conforms to RFC1964.
594 #define KRB_TOKEN_AP_REQ 0x0001
595 #define KRB_TOKEN_AP_REP 0x0002
596 #define KRB_TOKEN_AP_ERR 0x0003
597 #define KRB_TOKEN_GETMIC 0x0101
598 #define KRB_TOKEN_WRAP 0x0102
599 #define KRB_TOKEN_DELETE_SEC_CONTEXT 0x0201
600 #define KRB_TOKEN_CFX_GETMIC 0x0404
601 #define KRB_TOKEN_CFX_WRAP 0x0405
603 static const value_string spnego_krb5_tok_id_vals[] = {
604 { KRB_TOKEN_AP_REQ, "KRB5_AP_REQ"},
605 { KRB_TOKEN_AP_REP, "KRB5_AP_REP"},
606 { KRB_TOKEN_AP_ERR, "KRB5_ERROR"},
607 { KRB_TOKEN_GETMIC, "KRB5_GSS_GetMIC" },
608 { KRB_TOKEN_WRAP, "KRB5_GSS_Wrap" },
609 { KRB_TOKEN_DELETE_SEC_CONTEXT, "KRB5_GSS_Delete_sec_context" },
610 { KRB_TOKEN_CFX_GETMIC, "KRB_TOKEN_CFX_GetMic" },
611 { KRB_TOKEN_CFX_WRAP, "KRB_TOKEN_CFX_WRAP" },
612 { 0, NULL}
615 #define KRB_SGN_ALG_DES_MAC_MD5 0x0000
616 #define KRB_SGN_ALG_MD2_5 0x0001
617 #define KRB_SGN_ALG_DES_MAC 0x0002
618 #define KRB_SGN_ALG_HMAC 0x0011
620 static const value_string spnego_krb5_sgn_alg_vals[] = {
621 { KRB_SGN_ALG_DES_MAC_MD5, "DES MAC MD5"},
622 { KRB_SGN_ALG_MD2_5, "MD2.5"},
623 { KRB_SGN_ALG_DES_MAC, "DES MAC"},
624 { KRB_SGN_ALG_HMAC, "HMAC"},
625 { 0, NULL}
628 #define KRB_SEAL_ALG_DES_CBC 0x0000
629 #define KRB_SEAL_ALG_RC4 0x0010
630 #define KRB_SEAL_ALG_NONE 0xffff
632 static const value_string spnego_krb5_seal_alg_vals[] = {
633 { KRB_SEAL_ALG_DES_CBC, "DES CBC"},
634 { KRB_SEAL_ALG_RC4, "RC4"},
635 { KRB_SEAL_ALG_NONE, "None"},
636 { 0, NULL}
640 * XXX - is this for SPNEGO or just GSS-API?
641 * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
642 * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
643 * than designating SPNEGO as the mechanism, offering Kerberos V5, and
644 * getting it accepted.
646 static int
647 dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
648 static int
649 dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint16 token_id);
650 static int
651 dissect_spnego_krb5_cfx_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
652 static int
653 dissect_spnego_krb5_cfx_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint16 token_id);
655 static void
656 dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
658 proto_item *item;
659 proto_tree *subtree;
660 int offset = 0;
661 guint16 token_id;
662 const char *oid;
663 tvbuff_t *krb5_tvb;
664 gint8 ber_class;
665 gboolean pc, ind = 0;
666 gint32 tag;
667 guint32 len;
668 asn1_ctx_t asn1_ctx;
669 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
671 item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, offset,
672 -1, ENC_NA);
674 subtree = proto_item_add_subtree(item, ett_spnego_krb5);
677 * The KRB5 blob conforms to RFC1964:
678 * [APPLICATION 0] {
679 * OID,
680 * USHORT (0x0001 == AP-REQ, 0x0002 == AP-REP, 0x0003 == ERROR),
681 * OCTET STRING }
683 * However, for some protocols, the KRB5 blob starts at the SHORT
684 * and has no DER encoded header etc.
686 * It appears that for some other protocols the KRB5 blob is just
687 * a Kerberos message, with no [APPLICATION 0] header, no OID,
688 * and no USHORT.
690 * So:
692 * If we see an [APPLICATION 0] HEADER, we show the OID and
693 * the USHORT, and then dissect the rest as a Kerberos message.
695 * If we see an [APPLICATION 14] or [APPLICATION 15] header,
696 * we assume it's an AP-REQ or AP-REP message, and dissect
697 * it all as a Kerberos message.
699 * Otherwise, we show the USHORT, and then dissect the rest
700 * as a Kerberos message.
704 * Get the first header ...
706 get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
707 if (ber_class == BER_CLASS_APP && pc) {
709 * [APPLICATION <tag>]
711 offset = dissect_ber_identifier(pinfo, subtree, tvb, offset, &ber_class, &pc, &tag);
712 offset = dissect_ber_length(pinfo, subtree, tvb, offset, &len, &ind);
714 switch (tag) {
716 case 0:
718 * [APPLICATION 0]
721 /* Next, the OID */
722 offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, subtree, tvb, offset, hf_spnego_krb5_oid, &oid);
724 token_id = tvb_get_letohs(tvb, offset);
725 proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
726 token_id);
728 offset += 2;
730 break;
732 case 14: /* [APPLICATION 14] */
733 case 15: /* [APPLICATION 15] */
735 * No token ID - just dissect as a Kerberos message and
736 * return.
738 dissect_kerberos_main(tvb, pinfo, subtree, FALSE, NULL);
739 return;
741 default:
742 proto_tree_add_text(subtree, tvb, offset, 0,
743 "Unknown header (class=%d, pc=%d, tag=%d)",
744 ber_class, pc, tag);
745 goto done;
747 } else {
748 /* Next, the token ID ... */
750 token_id = tvb_get_letohs(tvb, offset);
751 proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
752 token_id);
754 offset += 2;
757 switch (token_id) {
759 case KRB_TOKEN_AP_REQ:
760 case KRB_TOKEN_AP_REP:
761 case KRB_TOKEN_AP_ERR:
762 krb5_tvb = tvb_new_subset_remaining(tvb, offset);
763 offset = dissect_kerberos_main(krb5_tvb, pinfo, subtree, FALSE, NULL);
764 break;
766 case KRB_TOKEN_GETMIC:
767 offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
768 break;
770 case KRB_TOKEN_WRAP:
771 offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
772 break;
774 case KRB_TOKEN_DELETE_SEC_CONTEXT:
776 break;
778 case KRB_TOKEN_CFX_GETMIC:
779 offset = dissect_spnego_krb5_cfx_getmic_base(tvb, offset, pinfo, subtree);
780 break;
782 case KRB_TOKEN_CFX_WRAP:
783 offset = dissect_spnego_krb5_cfx_wrap_base(tvb, offset, pinfo, subtree, token_id);
784 break;
786 default:
788 break;
791 done:
792 proto_item_set_len(item, offset);
793 return;
796 #ifdef HAVE_KERBEROS
797 #include <wsutil/md5.h>
799 #ifndef KEYTYPE_ARCFOUR_56
800 # define KEYTYPE_ARCFOUR_56 24
801 #endif
802 /* XXX - We should probably do a configure-time check for this instead */
803 #ifndef KRB5_KU_USAGE_SEAL
804 # define KRB5_KU_USAGE_SEAL 22
805 #endif
807 static int
808 arcfour_mic_key(void *key_data, size_t key_size, int key_type,
809 void *cksum_data, size_t cksum_size,
810 void *key6_data)
812 guint8 k5_data[16];
813 guint8 T[4];
815 memset(T, 0, 4);
817 if (key_type == KEYTYPE_ARCFOUR_56) {
818 guint8 L40[14] = "fortybits";
820 memcpy(L40 + 10, T, sizeof(T));
821 md5_hmac(
822 L40, 14,
823 (guint8 *)key_data,
824 key_size,
825 k5_data);
826 memset(&k5_data[7], 0xAB, 9);
827 } else {
828 md5_hmac(
829 T, 4,
830 (guint8 *)key_data,
831 key_size,
832 k5_data);
835 md5_hmac(
836 (guint8 *)cksum_data, cksum_size,
837 (guint8 *)k5_data,
839 (guint8 *)key6_data);
841 return 0;
844 static int
845 usage2arcfour(int usage)
847 switch (usage) {
848 case 3: /*KRB5_KU_AS_REP_ENC_PART 3 */
849 case 9: /*KRB5_KU_TGS_REP_ENC_PART_SUB_KEY 9 */
850 return 8;
851 case 22: /*KRB5_KU_USAGE_SEAL 22 */
852 return 13;
853 case 23: /*KRB5_KU_USAGE_SIGN 23 */
854 return 15;
855 case 24: /*KRB5_KU_USAGE_SEQ 24 */
856 return 0;
857 default :
858 return 0;
862 static int
863 arcfour_mic_cksum(guint8 *key_data, int key_length,
864 unsigned int usage,
865 guint8 sgn_cksum[8],
866 const void *v1, size_t l1,
867 const void *v2, size_t l2,
868 const void *v3, size_t l3)
870 const guint8 signature[] = "signaturekey";
871 guint8 ksign_c[16];
872 unsigned char t[4];
873 md5_state_t ms;
874 unsigned char digest[16];
875 int rc4_usage;
876 guint8 cksum[16];
878 rc4_usage=usage2arcfour(usage);
879 md5_hmac(signature, sizeof(signature),
880 key_data, key_length,
881 ksign_c);
882 md5_init(&ms);
883 t[0] = (rc4_usage >> 0) & 0xFF;
884 t[1] = (rc4_usage >> 8) & 0xFF;
885 t[2] = (rc4_usage >> 16) & 0xFF;
886 t[3] = (rc4_usage >> 24) & 0xFF;
887 md5_append(&ms, t, 4);
888 md5_append(&ms, (guint8 *)v1, l1);
889 md5_append(&ms, (guint8 *)v2, l2);
890 md5_append(&ms, (guint8 *)v3, l3);
891 md5_finish(&ms, digest);
892 md5_hmac(digest, 16, ksign_c, 16, cksum);
894 memcpy(sgn_cksum, cksum, 8);
896 return 0;
900 * Verify padding of a gss wrapped message and return its length.
902 static int
903 gssapi_verify_pad(unsigned char *wrapped_data, int wrapped_length,
904 int datalen,
905 int *padlen)
907 unsigned char *pad;
908 int padlength;
909 int i;
911 pad = wrapped_data + wrapped_length - 1;
912 padlength = *pad;
914 if (padlength > datalen)
915 return 1;
917 for (i = padlength; i > 0 && *pad == padlength; i--, pad--)
919 if (i != 0)
920 return 2;
922 *padlen = padlength;
924 return 0;
927 static int
928 decrypt_arcfour(packet_info *pinfo,
929 guint8 *input_message_buffer,
930 guint8 *output_message_buffer,
931 guint8 *key_value, int key_size, int key_type)
933 guint8 Klocaldata[16];
934 int ret;
935 int datalen;
936 guint8 k6_data[16];
937 guint32 SND_SEQ[2];
938 guint8 Confounder[8];
939 guint8 cksum_data[8];
940 int cmp;
941 int conf_flag;
942 int padlen = 0;
944 datalen = tvb_length(pinfo->gssapi_encrypted_tvb);
946 if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0x1000){
947 conf_flag=1;
948 } else if (tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0xffff){
949 conf_flag=0;
950 } else {
951 return -3;
954 if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 6)!=0xffff){
955 return -4;
958 ret = arcfour_mic_key(key_value, key_size, key_type,
959 (void *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
960 8, /* SGN_CKSUM */
961 k6_data);
962 if (ret) {
963 return -5;
967 rc4_state_struct rc4_state;
969 crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
970 tvb_memcpy(pinfo->gssapi_wrap_tvb, SND_SEQ, 8, 8);
971 crypt_rc4(&rc4_state, (unsigned char *)SND_SEQ, 8);
973 memset(k6_data, 0, sizeof(k6_data));
977 if (SND_SEQ[1] != 0xFFFFFFFF && SND_SEQ[1] != 0x00000000) {
978 return -6;
982 int i;
984 for (i = 0; i < 16; i++)
985 Klocaldata[i] = ((guint8 *)key_value)[i] ^ 0xF0;
987 ret = arcfour_mic_key(Klocaldata,sizeof(Klocaldata),key_type,
988 (unsigned char *)SND_SEQ, 4,
989 k6_data);
990 memset(Klocaldata, 0, sizeof(Klocaldata));
991 if (ret) {
992 return -7;
995 if(conf_flag) {
996 rc4_state_struct rc4_state;
998 crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
999 tvb_memcpy(pinfo->gssapi_wrap_tvb, Confounder, 24, 8);
1000 crypt_rc4(&rc4_state, Confounder, 8);
1001 memcpy(output_message_buffer, input_message_buffer, datalen);
1002 crypt_rc4(&rc4_state, output_message_buffer, datalen);
1003 } else {
1004 tvb_memcpy(pinfo->gssapi_wrap_tvb, Confounder, 24, 8);
1005 memcpy(output_message_buffer,
1006 input_message_buffer,
1007 datalen);
1009 memset(k6_data, 0, sizeof(k6_data));
1011 /* only normal (i.e. non DCE style wrapping use padding ? */
1012 if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
1013 ret = gssapi_verify_pad(output_message_buffer,datalen,datalen, &padlen);
1014 if (ret) {
1015 return -9;
1017 datalen -= padlen;
1020 /* dont know what the checksum looks like for dce style gssapi */
1021 if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
1022 ret = arcfour_mic_cksum(key_value, key_size,
1023 KRB5_KU_USAGE_SEAL,
1024 cksum_data,
1025 tvb_get_ptr(pinfo->gssapi_wrap_tvb, 0, 8), 8,
1026 Confounder, sizeof(Confounder),
1027 output_message_buffer,
1028 datalen + padlen);
1029 if (ret) {
1030 return -10;
1033 cmp = tvb_memeql(pinfo->gssapi_wrap_tvb, 16, cksum_data, 8); /* SGN_CKSUM */
1034 if (cmp) {
1035 return -11;
1039 return datalen;
1044 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1046 static void
1047 decrypt_gssapi_krb_arcfour_wrap(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int keytype)
1049 int ret;
1050 enc_key_t *ek;
1051 int length;
1052 const guint8 *original_data;
1054 guint8 *cryptocopy=NULL; /* workaround for pre-0.6.1 heimdal bug */
1055 guint8 *output_message_buffer;
1057 length=tvb_length(pinfo->gssapi_encrypted_tvb);
1058 original_data=tvb_get_ptr(pinfo->gssapi_encrypted_tvb, 0, length);
1060 /* dont do anything if we are not attempting to decrypt data */
1062 if(!krb_decrypt){
1063 return;
1066 /* XXX we should only do this for first time, then store somewhere */
1067 /* XXX We also need to re-read the keytab when the preference changes */
1069 cryptocopy=(guint8 *)wmem_alloc(wmem_packet_scope(), length);
1070 output_message_buffer=(guint8 *)wmem_alloc(pinfo->pool, length);
1072 for(ek=enc_key_list;ek;ek=ek->next){
1073 /* shortcircuit and bail out if enctypes are not matching */
1074 if(ek->keytype!=keytype){
1075 continue;
1078 /* pre-0.6.1 versions of Heimdal would sometimes change
1079 the cryptotext data even when the decryption failed.
1080 This would obviously not work since we iterate over the
1081 keys. So just give it a copy of the crypto data instead.
1082 This has been seen for RC4-HMAC blobs.
1084 memcpy(cryptocopy, original_data, length);
1085 ret=decrypt_arcfour(pinfo,
1086 cryptocopy,
1087 output_message_buffer,
1088 ek->keyvalue,
1089 ek->keylength,
1090 ek->keytype
1092 if (ret >= 0) {
1093 proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
1094 pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(tvb,
1095 output_message_buffer,
1096 ret, ret);
1097 add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
1098 return;
1101 return;
1104 /* borrowed from heimdal */
1105 static int
1106 rrc_rotate(void *data, int len, guint16 rrc, int unrotate)
1108 unsigned char *tmp, buf[256];
1109 size_t left;
1111 if (len == 0)
1112 return 0;
1114 rrc %= len;
1116 if (rrc == 0)
1117 return 0;
1119 left = len - rrc;
1121 if (rrc <= sizeof(buf)) {
1122 tmp = buf;
1123 } else {
1124 tmp = (unsigned char *)g_malloc(rrc);
1125 if (tmp == NULL)
1126 return -1;
1129 if (unrotate) {
1130 memcpy(tmp, data, rrc);
1131 memmove(data, (unsigned char *)data + rrc, left);
1132 memcpy((unsigned char *)data + left, tmp, rrc);
1133 } else {
1134 memcpy(tmp, (unsigned char *)data + left, rrc);
1135 memmove((unsigned char *)data + rrc, data, left);
1136 memcpy(data, tmp, rrc);
1139 if (rrc > sizeof(buf))
1140 g_free(tmp);
1142 return 0;
1146 #define KRB5_KU_USAGE_ACCEPTOR_SEAL 22
1147 #define KRB5_KU_USAGE_ACCEPTOR_SIGN 23
1148 #define KRB5_KU_USAGE_INITIATOR_SEAL 24
1149 #define KRB5_KU_USAGE_INITIATOR_SIGN 25
1151 static void
1152 decrypt_gssapi_krb_cfx_wrap(proto_tree *tree _U_,
1153 packet_info *pinfo,
1154 tvbuff_t *checksum_tvb,
1155 tvbuff_t *encrypted_tvb,
1156 guint16 ec,
1157 guint16 rrc,
1158 gboolean is_dce,
1159 int keytype,
1160 unsigned int usage)
1162 guint8 *rotated;
1163 guint8 *output;
1164 int datalen;
1165 tvbuff_t *next_tvb;
1167 /* dont do anything if we are not attempting to decrypt data */
1168 if(!krb_decrypt){
1169 return;
1172 datalen = tvb_length(checksum_tvb) + tvb_length(encrypted_tvb);
1174 rotated = (guint8 *)wmem_alloc(pinfo->pool, datalen);
1176 tvb_memcpy(checksum_tvb, rotated,
1177 0, tvb_length(checksum_tvb));
1178 tvb_memcpy(encrypted_tvb, rotated + tvb_length(checksum_tvb),
1179 0, tvb_length(encrypted_tvb));
1181 if (is_dce) {
1182 rrc += ec;
1185 rrc_rotate(rotated, datalen, rrc, TRUE);
1187 next_tvb=tvb_new_child_real_data(encrypted_tvb, rotated,
1188 datalen, datalen);
1189 add_new_data_source(pinfo, next_tvb, "GSSAPI CFX");
1191 output = decrypt_krb5_data(tree, pinfo, usage, next_tvb,
1192 keytype, &datalen);
1194 if (output) {
1195 guint8 *outdata;
1197 outdata = (guint8 *)g_memdup(output, tvb_length(encrypted_tvb));
1198 g_free(output);
1200 pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(encrypted_tvb,
1201 outdata,
1202 tvb_length(encrypted_tvb),
1203 tvb_length(encrypted_tvb));
1204 add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
1205 tvb_set_free_cb(pinfo->gssapi_decrypted_tvb, g_free);
1206 return;
1208 return;
1211 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1214 #endif
1217 * This is for GSSAPI Wrap tokens ...
1219 static int
1220 dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
1221 #ifndef HAVE_KERBEROS
1223 #endif
1224 , proto_tree *tree, guint16 token_id
1225 #ifndef HAVE_KERBEROS
1227 #endif
1230 guint16 sgn_alg, seal_alg;
1231 #ifdef HAVE_KERBEROS
1232 int start_offset=offset;
1233 #endif
1236 * The KRB5 blob conforms to RFC1964:
1237 * USHORT (0x0102 == GSS_Wrap)
1238 * and so on }
1241 /* Now, the sign and seal algorithms ... */
1243 sgn_alg = tvb_get_letohs(tvb, offset);
1244 proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
1245 sgn_alg);
1247 offset += 2;
1249 seal_alg = tvb_get_letohs(tvb, offset);
1250 proto_tree_add_uint(tree, hf_spnego_krb5_seal_alg, tvb, offset, 2,
1251 seal_alg);
1253 offset += 2;
1255 /* Skip the filler */
1257 offset += 2;
1259 /* Encrypted sequence number */
1261 proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
1262 ENC_NA);
1264 offset += 8;
1266 /* Checksum of plaintext padded data */
1268 proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
1269 ENC_NA);
1271 offset += 8;
1274 * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
1275 * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
1276 * extra 8 bytes of "Random confounder" after the checksum.
1277 * It certainly confounds code expecting all Kerberos 5
1278 * GSS_Wrap() tokens to look the same....
1280 if ((sgn_alg == KRB_SGN_ALG_HMAC) ||
1281 /* there also seems to be a confounder for DES MAC MD5 - certainly seen when using with
1282 SASL with LDAP between a Java client and Active Directory. If this breaks other things
1283 we may need to make this an option. gal 17/2/06 */
1284 (sgn_alg == KRB_SGN_ALG_DES_MAC_MD5)) {
1285 proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
1286 ENC_NA);
1287 offset += 8;
1290 /* Is the data encrypted? */
1291 pinfo->gssapi_data_encrypted=(seal_alg!=KRB_SEAL_ALG_NONE);
1293 #ifdef HAVE_KERBEROS
1294 #define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
1295 if(pinfo->decrypt_gssapi_tvb){
1296 /* if the caller did not provide a tvb, then we just use
1297 whatever is left of our current tvb.
1299 if(!pinfo->gssapi_encrypted_tvb){
1300 int len;
1301 len=tvb_reported_length_remaining(tvb,offset);
1302 if(len>tvb_length_remaining(tvb, offset)){
1303 /* no point in trying to decrypt,
1304 we dont have the full pdu.
1306 return offset;
1308 pinfo->gssapi_encrypted_tvb = tvb_new_subset(
1309 tvb, offset, len, len);
1312 /* if this is KRB5 wrapped rc4-hmac */
1313 if((token_id==KRB_TOKEN_WRAP)
1314 &&(sgn_alg==KRB_SGN_ALG_HMAC)
1315 &&(seal_alg==KRB_SEAL_ALG_RC4)){
1316 /* do we need to create a tvb for the wrapper
1317 as well ?
1319 if(!pinfo->gssapi_wrap_tvb){
1320 pinfo->gssapi_wrap_tvb = tvb_new_subset(
1321 tvb, start_offset-2,
1322 GSS_ARCFOUR_WRAP_TOKEN_SIZE,
1323 GSS_ARCFOUR_WRAP_TOKEN_SIZE);
1325 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1326 decrypt_gssapi_krb_arcfour_wrap(tree,
1327 pinfo,
1328 tvb,
1329 23 /* rc4-hmac */);
1330 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1333 #endif
1335 * Return the offset past the checksum, so that we know where
1336 * the data we're wrapped around starts. Also, set the length
1337 * of our top-level item to that offset, so it doesn't cover
1338 * the data we're wrapped around.
1340 * Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
1341 * not before.
1343 return offset;
1347 * XXX - This is for GSSAPI GetMIC tokens ...
1349 static int
1350 dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
1352 guint16 sgn_alg;
1355 * The KRB5 blob conforms to RFC1964:
1356 * USHORT (0x0101 == GSS_GetMIC)
1357 * and so on }
1360 /* Now, the sign algorithm ... */
1362 sgn_alg = tvb_get_letohs(tvb, offset);
1363 proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
1364 sgn_alg);
1366 offset += 2;
1368 /* Skip the filler */
1370 offset += 4;
1372 /* Encrypted sequence number */
1374 proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
1375 ENC_NA);
1377 offset += 8;
1379 /* Checksum of plaintext padded data */
1381 proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
1382 ENC_NA);
1384 offset += 8;
1387 * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
1388 * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
1389 * extra 8 bytes of "Random confounder" after the checksum.
1390 * It certainly confounds code expecting all Kerberos 5
1391 * GSS_Wrap() tokens to look the same....
1393 * The exception is DNS/TSIG where there is no such confounder
1394 * so we need to test here if there are more bytes in our tvb or not.
1395 * -- ronnie
1397 if (tvb_length_remaining(tvb, offset)) {
1398 if (sgn_alg == KRB_SGN_ALG_HMAC) {
1399 proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
1400 ENC_NA);
1402 offset += 8;
1407 * Return the offset past the checksum, so that we know where
1408 * the data we're wrapped around starts. Also, set the length
1409 * of our top-level item to that offset, so it doesn't cover
1410 * the data we're wrapped around.
1413 return offset;
1416 static int
1417 dissect_spnego_krb5_cfx_flags(tvbuff_t *tvb, int offset,
1418 proto_tree *spnego_krb5_tree,
1419 guint8 cfx_flags)
1421 proto_tree *cfx_flags_tree = NULL;
1422 proto_item *tf = NULL;
1424 if (spnego_krb5_tree) {
1425 tf = proto_tree_add_uint(spnego_krb5_tree,
1426 hf_spnego_krb5_cfx_flags,
1427 tvb, offset, 1, cfx_flags);
1428 cfx_flags_tree = proto_item_add_subtree(tf, ett_spnego_krb5_cfx_flags);
1431 proto_tree_add_boolean(cfx_flags_tree,
1432 hf_spnego_krb5_cfx_flags_04,
1433 tvb, offset, 1, cfx_flags);
1434 proto_tree_add_boolean(cfx_flags_tree,
1435 hf_spnego_krb5_cfx_flags_02,
1436 tvb, offset, 1, cfx_flags);
1437 proto_tree_add_boolean(cfx_flags_tree,
1438 hf_spnego_krb5_cfx_flags_01,
1439 tvb, offset, 1, cfx_flags);
1441 return (offset + 1);
1445 * This is for GSSAPI CFX Wrap tokens ...
1447 static int
1448 dissect_spnego_krb5_cfx_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
1449 #ifndef HAVE_KERBEROS
1451 #endif
1452 , proto_tree *tree, guint16 token_id _U_
1455 guint8 flags;
1456 guint16 ec;
1457 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1458 guint16 rrc;
1459 #endif
1460 int checksum_size;
1461 int start_offset=offset;
1464 * The KRB5 blob conforms to RFC4121:
1465 * USHORT (0x0504)
1466 * and so on }
1469 /* Now, the sign and seal algorithms ... */
1471 flags = tvb_get_guint8(tvb, offset);
1472 offset = dissect_spnego_krb5_cfx_flags(tvb, offset, tree, flags);
1474 pinfo->gssapi_data_encrypted=(flags & 2);
1476 /* Skip the filler */
1478 proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 1,
1479 ENC_NA);
1480 offset += 1;
1482 /* EC */
1483 ec = tvb_get_ntohs(tvb, offset);
1484 proto_tree_add_item(tree, hf_spnego_krb5_cfx_ec, tvb, offset, 2,
1485 ENC_BIG_ENDIAN);
1486 offset += 2;
1488 /* RRC */
1489 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1490 rrc = tvb_get_ntohs(tvb, offset);
1491 #endif
1492 proto_tree_add_item(tree, hf_spnego_krb5_cfx_rrc, tvb, offset, 2,
1493 ENC_BIG_ENDIAN);
1494 offset += 2;
1496 /* sequence number */
1498 proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
1499 ENC_BIG_ENDIAN);
1500 offset += 8;
1502 /* Checksum of plaintext padded data */
1504 if (pinfo->gssapi_data_encrypted) {
1505 checksum_size = 44 + ec;
1506 } else {
1507 checksum_size = 12;
1510 proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
1511 checksum_size, ENC_NA);
1512 offset += checksum_size;
1514 if(pinfo->decrypt_gssapi_tvb){
1515 /* if the caller did not provide a tvb, then we just use
1516 whatever is left of our current tvb.
1518 if(!pinfo->gssapi_encrypted_tvb){
1519 int len;
1520 len=tvb_reported_length_remaining(tvb,offset);
1521 if(len>tvb_length_remaining(tvb, offset)){
1522 /* no point in trying to decrypt,
1523 we dont have the full pdu.
1525 return offset;
1527 pinfo->gssapi_encrypted_tvb = tvb_new_subset(
1528 tvb, offset, len, len);
1531 if (pinfo->gssapi_data_encrypted) {
1532 /* do we need to create a tvb for the wrapper
1533 as well ?
1535 if(!pinfo->gssapi_wrap_tvb){
1536 pinfo->gssapi_wrap_tvb = tvb_new_subset(
1537 tvb, start_offset-2,
1538 offset - (start_offset-2),
1539 offset - (start_offset-2));
1544 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1546 tvbuff_t *checksum_tvb = tvb_new_subset(tvb, 16, checksum_size, checksum_size);
1548 if (pinfo->gssapi_data_encrypted) {
1549 if(pinfo->gssapi_encrypted_tvb){
1550 decrypt_gssapi_krb_cfx_wrap(tree,
1551 pinfo,
1552 checksum_tvb,
1553 pinfo->gssapi_encrypted_tvb,
1555 rrc,
1556 (pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_DCE)?TRUE:FALSE,
1558 (flags & 0x0001)?
1559 KRB5_KU_USAGE_ACCEPTOR_SEAL:
1560 KRB5_KU_USAGE_INITIATOR_SEAL);
1564 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1567 * Return the offset past the checksum, so that we know where
1568 * the data we're wrapped around starts. Also, set the length
1569 * of our top-level item to that offset, so it doesn't cover
1570 * the data we're wrapped around.
1572 * Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
1573 * not before.
1575 return offset;
1579 * XXX - This is for GSSAPI CFX GetMIC tokens ...
1581 static int
1582 dissect_spnego_krb5_cfx_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
1584 guint8 flags;
1585 int checksum_size;
1588 * The KRB5 blob conforms to RFC4121:
1589 * USHORT (0x0404 == GSS_GetMIC)
1590 * and so on }
1593 flags = tvb_get_guint8(tvb, offset);
1594 offset = dissect_spnego_krb5_cfx_flags(tvb, offset, tree, flags);
1596 /* Skip the filler */
1598 proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 5,
1599 ENC_NA);
1600 offset += 5;
1602 /* sequence number */
1604 proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
1605 ENC_BIG_ENDIAN);
1606 offset += 8;
1608 /* Checksum of plaintext padded data */
1610 checksum_size = tvb_length_remaining(tvb, offset);
1612 proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
1613 checksum_size, ENC_NA);
1614 offset += checksum_size;
1617 * Return the offset past the checksum, so that we know where
1618 * the data we're wrapped around starts. Also, set the length
1619 * of our top-level item to that offset, so it doesn't cover
1620 * the data we're wrapped around.
1623 return offset;
1627 * XXX - is this for SPNEGO or just GSS-API?
1628 * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
1629 * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
1630 * than designating SPNEGO as the mechanism, offering Kerberos V5, and
1631 * getting it accepted.
1633 static int
1634 dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
1636 proto_item *item;
1637 proto_tree *subtree;
1638 int offset = 0;
1639 guint16 token_id;
1641 item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, 0, -1, ENC_NA);
1643 subtree = proto_item_add_subtree(item, ett_spnego_krb5);
1646 * The KRB5 blob conforms to RFC1964:
1647 * USHORT (0x0102 == GSS_Wrap)
1648 * and so on }
1651 /* First, the token ID ... */
1653 token_id = tvb_get_letohs(tvb, offset);
1654 proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
1655 token_id);
1657 offset += 2;
1659 switch (token_id) {
1660 case KRB_TOKEN_GETMIC:
1661 offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
1662 break;
1664 case KRB_TOKEN_WRAP:
1665 offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
1666 break;
1668 case KRB_TOKEN_CFX_GETMIC:
1669 offset = dissect_spnego_krb5_cfx_getmic_base(tvb, offset, pinfo, subtree);
1670 break;
1672 case KRB_TOKEN_CFX_WRAP:
1673 offset = dissect_spnego_krb5_cfx_wrap_base(tvb, offset, pinfo, subtree, token_id);
1674 break;
1676 default:
1678 break;
1682 * Return the offset past the checksum, so that we know where
1683 * the data we're wrapped around starts. Also, set the length
1684 * of our top-level item to that offset, so it doesn't cover
1685 * the data we're wrapped around.
1687 proto_item_set_len(item, offset);
1688 return offset;
1691 /* Spnego stuff from here */
1693 static int
1694 dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1696 proto_item *item;
1697 proto_tree *subtree;
1698 int offset = 0;
1699 asn1_ctx_t asn1_ctx;
1700 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1702 MechType_oid = NULL;
1705 * We need this later, so lets get it now ...
1706 * It has to be per-frame as there can be more than one GSS-API
1707 * negotiation in a conversation.
1711 item = proto_tree_add_item(tree, proto_spnego, tvb, offset,
1712 -1, ENC_NA);
1714 subtree = proto_item_add_subtree(item, ett_spnego);
1716 * The TVB contains a [0] header and a sequence that consists of an
1717 * object ID and a blob containing the data ...
1718 * XXX - is this RFC 2743's "Mechanism-Independent Token Format",
1719 * with the "optional" "use in non-initial tokens" being chosen.
1720 * ASN1 code addet to spnego.asn to handle this.
1723 offset = dissect_spnego_InitialContextToken(FALSE, tvb, offset, &asn1_ctx , subtree, -1);
1725 return offset;
1729 static void
1730 dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
1732 proto_item *item;
1733 proto_tree *subtree;
1734 int offset = 0;
1735 conversation_t *conversation;
1736 asn1_ctx_t asn1_ctx;
1737 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1740 * We need this later, so lets get it now ...
1741 * It has to be per-frame as there can be more than one GSS-API
1742 * negotiation in a conversation.
1744 next_level_value = (gssapi_oid_value *)p_get_proto_data(pinfo->fd, proto_spnego, 0);
1745 if (!next_level_value && !pinfo->fd->flags.visited) {
1747 * No handle attached to this frame, but it's the first
1748 * pass, so it'd be attached to the conversation.
1749 * If we have a conversation, try to get the handle,
1750 * and if we get one, attach it to the frame.
1752 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1753 pinfo->ptype, pinfo->srcport,
1754 pinfo->destport, 0);
1756 if (conversation) {
1757 next_level_value = (gssapi_oid_value *)conversation_get_proto_data(conversation,
1758 proto_spnego);
1759 if (next_level_value)
1760 p_add_proto_data(pinfo->fd, proto_spnego, 0, next_level_value);
1764 item = proto_tree_add_item(parent_tree, proto_spnego, tvb, offset,
1765 -1, ENC_NA);
1767 subtree = proto_item_add_subtree(item, ett_spnego);
1770 * The TVB contains a [0] header and a sequence that consists of an
1771 * object ID and a blob containing the data ...
1772 * Actually, it contains, according to RFC2478:
1773 * NegotiationToken ::= CHOICE {
1774 * negTokenInit [0] NegTokenInit,
1775 * negTokenTarg [1] NegTokenTarg }
1776 * NegTokenInit ::= SEQUENCE {
1777 * mechTypes [0] MechTypeList OPTIONAL,
1778 * reqFlags [1] ContextFlags OPTIONAL,
1779 * mechToken [2] OCTET STRING OPTIONAL,
1780 * mechListMIC [3] OCTET STRING OPTIONAL }
1781 * NegTokenTarg ::= SEQUENCE {
1782 * negResult [0] ENUMERATED {
1783 * accept_completed (0),
1784 * accept_incomplete (1),
1785 * reject (2) } OPTIONAL,
1786 * supportedMech [1] MechType OPTIONAL,
1787 * responseToken [2] OCTET STRING OPTIONAL,
1788 * mechListMIC [3] OCTET STRING OPTIONAL }
1790 * Windows typically includes mechTypes and mechListMic ('NONE'
1791 * in the case of NTLMSSP only).
1792 * It seems to duplicate the responseToken into the mechListMic field
1793 * as well. Naughty, naughty.
1796 dissect_spnego_NegotiationToken(FALSE, tvb, offset, &asn1_ctx, subtree, -1);
1800 /*--- proto_register_spnego -------------------------------------------*/
1801 void proto_register_spnego(void) {
1803 /* List of fields */
1804 static hf_register_info hf[] = {
1805 { &hf_spnego_wraptoken,
1806 { "wrapToken", "spnego.wraptoken",
1807 FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO wrapToken",
1808 HFILL}},
1809 { &hf_spnego_krb5,
1810 { "krb5_blob", "spnego.krb5.blob", FT_BYTES,
1811 BASE_NONE, NULL, 0, NULL, HFILL }},
1812 { &hf_spnego_krb5_oid,
1813 { "KRB5 OID", "spnego.krb5_oid", FT_STRING,
1814 BASE_NONE, NULL, 0, NULL, HFILL }},
1815 { &hf_spnego_krb5_tok_id,
1816 { "krb5_tok_id", "spnego.krb5.tok_id", FT_UINT16, BASE_HEX,
1817 VALS(spnego_krb5_tok_id_vals), 0, "KRB5 Token Id", HFILL}},
1818 { &hf_spnego_krb5_sgn_alg,
1819 { "krb5_sgn_alg", "spnego.krb5.sgn_alg", FT_UINT16, BASE_HEX,
1820 VALS(spnego_krb5_sgn_alg_vals), 0, "KRB5 Signing Algorithm", HFILL}},
1821 { &hf_spnego_krb5_seal_alg,
1822 { "krb5_seal_alg", "spnego.krb5.seal_alg", FT_UINT16, BASE_HEX,
1823 VALS(spnego_krb5_seal_alg_vals), 0, "KRB5 Sealing Algorithm", HFILL}},
1824 { &hf_spnego_krb5_snd_seq,
1825 { "krb5_snd_seq", "spnego.krb5.snd_seq", FT_BYTES, BASE_NONE,
1826 NULL, 0, "KRB5 Encrypted Sequence Number", HFILL}},
1827 { &hf_spnego_krb5_sgn_cksum,
1828 { "krb5_sgn_cksum", "spnego.krb5.sgn_cksum", FT_BYTES, BASE_NONE,
1829 NULL, 0, "KRB5 Data Checksum", HFILL}},
1830 { &hf_spnego_krb5_confounder,
1831 { "krb5_confounder", "spnego.krb5.confounder", FT_BYTES, BASE_NONE,
1832 NULL, 0, "KRB5 Confounder", HFILL}},
1833 { &hf_spnego_krb5_filler,
1834 { "krb5_filler", "spnego.krb5.filler", FT_BYTES, BASE_NONE,
1835 NULL, 0, "KRB5 Filler", HFILL}},
1836 { &hf_spnego_krb5_cfx_flags,
1837 { "krb5_cfx_flags", "spnego.krb5.cfx_flags", FT_UINT8, BASE_HEX,
1838 NULL, 0, "KRB5 CFX Flags", HFILL}},
1839 { &hf_spnego_krb5_cfx_flags_01,
1840 { "SendByAcceptor", "spnego.krb5.send_by_acceptor", FT_BOOLEAN, 8,
1841 TFS (&tfs_set_notset), 0x01, NULL, HFILL}},
1842 { &hf_spnego_krb5_cfx_flags_02,
1843 { "Sealed", "spnego.krb5.sealed", FT_BOOLEAN, 8,
1844 TFS (&tfs_set_notset), 0x02, NULL, HFILL}},
1845 { &hf_spnego_krb5_cfx_flags_04,
1846 { "AcceptorSubkey", "spnego.krb5.acceptor_subkey", FT_BOOLEAN, 8,
1847 TFS (&tfs_set_notset), 0x04, NULL, HFILL}},
1848 { &hf_spnego_krb5_cfx_ec,
1849 { "krb5_cfx_ec", "spnego.krb5.cfx_ec", FT_UINT16, BASE_DEC,
1850 NULL, 0, "KRB5 CFX Extra Count", HFILL}},
1851 { &hf_spnego_krb5_cfx_rrc,
1852 { "krb5_cfx_rrc", "spnego.krb5.cfx_rrc", FT_UINT16, BASE_DEC,
1853 NULL, 0, "KRB5 CFX Right Rotation Count", HFILL}},
1854 { &hf_spnego_krb5_cfx_seq,
1855 { "krb5_cfx_seq", "spnego.krb5.cfx_seq", FT_UINT64, BASE_DEC,
1856 NULL, 0, "KRB5 Sequence Number", HFILL}},
1859 /*--- Included file: packet-spnego-hfarr.c ---*/
1860 #line 1 "../../asn1/spnego/packet-spnego-hfarr.c"
1861 { &hf_spnego_negTokenInit,
1862 { "negTokenInit", "spnego.negTokenInit_element",
1863 FT_NONE, BASE_NONE, NULL, 0,
1864 NULL, HFILL }},
1865 { &hf_spnego_negTokenTarg,
1866 { "negTokenTarg", "spnego.negTokenTarg_element",
1867 FT_NONE, BASE_NONE, NULL, 0,
1868 NULL, HFILL }},
1869 { &hf_spnego_MechTypeList_item,
1870 { "MechType", "spnego.MechType",
1871 FT_OID, BASE_NONE, NULL, 0,
1872 NULL, HFILL }},
1873 { &hf_spnego_principal,
1874 { "principal", "spnego.principal",
1875 FT_STRING, BASE_NONE, NULL, 0,
1876 "GeneralString", HFILL }},
1877 { &hf_spnego_mechTypes,
1878 { "mechTypes", "spnego.mechTypes",
1879 FT_UINT32, BASE_DEC, NULL, 0,
1880 "MechTypeList", HFILL }},
1881 { &hf_spnego_reqFlags,
1882 { "reqFlags", "spnego.reqFlags",
1883 FT_BYTES, BASE_NONE, NULL, 0,
1884 "ContextFlags", HFILL }},
1885 { &hf_spnego_mechToken,
1886 { "mechToken", "spnego.mechToken",
1887 FT_BYTES, BASE_NONE, NULL, 0,
1888 NULL, HFILL }},
1889 { &hf_spnego_negTokenInit_mechListMIC,
1890 { "mechListMIC", "spnego.mechListMIC",
1891 FT_BYTES, BASE_NONE, NULL, 0,
1892 "T_NegTokenInit_mechListMIC", HFILL }},
1893 { &hf_spnego_negResult,
1894 { "negResult", "spnego.negResult",
1895 FT_UINT32, BASE_DEC, VALS(spnego_T_negResult_vals), 0,
1896 NULL, HFILL }},
1897 { &hf_spnego_supportedMech,
1898 { "supportedMech", "spnego.supportedMech",
1899 FT_OID, BASE_NONE, NULL, 0,
1900 NULL, HFILL }},
1901 { &hf_spnego_responseToken,
1902 { "responseToken", "spnego.responseToken",
1903 FT_BYTES, BASE_NONE, NULL, 0,
1904 NULL, HFILL }},
1905 { &hf_spnego_mechListMIC,
1906 { "mechListMIC", "spnego.mechListMIC",
1907 FT_BYTES, BASE_NONE, NULL, 0,
1908 NULL, HFILL }},
1909 { &hf_spnego_thisMech,
1910 { "thisMech", "spnego.thisMech",
1911 FT_OID, BASE_NONE, NULL, 0,
1912 "MechType", HFILL }},
1913 { &hf_spnego_innerContextToken,
1914 { "innerContextToken", "spnego.innerContextToken_element",
1915 FT_NONE, BASE_NONE, NULL, 0,
1916 NULL, HFILL }},
1917 { &hf_spnego_ContextFlags_delegFlag,
1918 { "delegFlag", "spnego.delegFlag",
1919 FT_BOOLEAN, 8, NULL, 0x80,
1920 NULL, HFILL }},
1921 { &hf_spnego_ContextFlags_mutualFlag,
1922 { "mutualFlag", "spnego.mutualFlag",
1923 FT_BOOLEAN, 8, NULL, 0x40,
1924 NULL, HFILL }},
1925 { &hf_spnego_ContextFlags_replayFlag,
1926 { "replayFlag", "spnego.replayFlag",
1927 FT_BOOLEAN, 8, NULL, 0x20,
1928 NULL, HFILL }},
1929 { &hf_spnego_ContextFlags_sequenceFlag,
1930 { "sequenceFlag", "spnego.sequenceFlag",
1931 FT_BOOLEAN, 8, NULL, 0x10,
1932 NULL, HFILL }},
1933 { &hf_spnego_ContextFlags_anonFlag,
1934 { "anonFlag", "spnego.anonFlag",
1935 FT_BOOLEAN, 8, NULL, 0x08,
1936 NULL, HFILL }},
1937 { &hf_spnego_ContextFlags_confFlag,
1938 { "confFlag", "spnego.confFlag",
1939 FT_BOOLEAN, 8, NULL, 0x04,
1940 NULL, HFILL }},
1941 { &hf_spnego_ContextFlags_integFlag,
1942 { "integFlag", "spnego.integFlag",
1943 FT_BOOLEAN, 8, NULL, 0x02,
1944 NULL, HFILL }},
1946 /*--- End of included file: packet-spnego-hfarr.c ---*/
1947 #line 1378 "../../asn1/spnego/packet-spnego-template.c"
1950 /* List of subtrees */
1951 static gint *ett[] = {
1952 &ett_spnego,
1953 &ett_spnego_wraptoken,
1954 &ett_spnego_krb5,
1955 &ett_spnego_krb5_cfx_flags,
1958 /*--- Included file: packet-spnego-ettarr.c ---*/
1959 #line 1 "../../asn1/spnego/packet-spnego-ettarr.c"
1960 &ett_spnego_NegotiationToken,
1961 &ett_spnego_MechTypeList,
1962 &ett_spnego_PrincipalSeq,
1963 &ett_spnego_NegTokenInit,
1964 &ett_spnego_ContextFlags,
1965 &ett_spnego_NegTokenTarg,
1966 &ett_spnego_InitialContextToken_U,
1968 /*--- End of included file: packet-spnego-ettarr.c ---*/
1969 #line 1388 "../../asn1/spnego/packet-spnego-template.c"
1972 /* Register protocol */
1973 proto_spnego = proto_register_protocol(PNAME, PSNAME, PFNAME);
1975 register_dissector("spnego", dissect_spnego, proto_spnego);
1977 proto_spnego_krb5 = proto_register_protocol("SPNEGO-KRB5",
1978 "SPNEGO-KRB5",
1979 "spnego-krb5");
1981 register_dissector("spnego-krb5", dissect_spnego_krb5, proto_spnego_krb5);
1982 new_register_dissector("spnego-krb5-wrap", dissect_spnego_krb5_wrap, proto_spnego_krb5);
1984 /* Register fields and subtrees */
1985 proto_register_field_array(proto_spnego, hf, array_length(hf));
1986 proto_register_subtree_array(ett, array_length(ett));
1990 /*--- proto_reg_handoff_spnego ---------------------------------------*/
1991 void proto_reg_handoff_spnego(void) {
1993 dissector_handle_t spnego_handle, spnego_wrap_handle;
1994 dissector_handle_t spnego_krb5_handle, spnego_krb5_wrap_handle;
1996 /* Register protocol with GSS-API module */
1998 spnego_handle = find_dissector("spnego");
1999 spnego_wrap_handle = new_create_dissector_handle(dissect_spnego_wrap, proto_spnego);
2000 gssapi_init_oid("1.3.6.1.5.5.2", proto_spnego, ett_spnego,
2001 spnego_handle, spnego_wrap_handle,
2002 "SPNEGO - Simple Protected Negotiation");
2004 /* Register both the one MS created and the real one */
2006 * Thanks to Jean-Baptiste Marchand and Richard B Ward, the
2007 * mystery of the MS KRB5 OID is cleared up. It was due to a library
2008 * that did not handle OID components greater than 16 bits, and was
2009 * fixed in Win2K SP2 as well as WinXP.
2010 * See the archive of <ietf-krb-wg@anl.gov> for the thread topic
2011 * SPNEGO implementation issues. 3-Dec-2002.
2013 spnego_krb5_handle = find_dissector("spnego-krb5");
2014 spnego_krb5_wrap_handle = find_dissector("spnego-krb5-wrap");
2015 gssapi_init_oid("1.2.840.48018.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
2016 spnego_krb5_handle, spnego_krb5_wrap_handle,
2017 "MS KRB5 - Microsoft Kerberos 5");
2018 gssapi_init_oid("1.2.840.113554.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
2019 spnego_krb5_handle, spnego_krb5_wrap_handle,
2020 "KRB5 - Kerberos 5");
2021 gssapi_init_oid("1.2.840.113554.1.2.2.3", proto_spnego_krb5, ett_spnego_krb5,
2022 spnego_krb5_handle, spnego_krb5_wrap_handle,
2023 "KRB5 - Kerberos 5 - User to User");