Fix for bug 5422:
[obnox/wireshark/wip.git] / epan / dissectors / packet-spnego.c
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/asn2wrs.py -b -p spnego -c ./spnego.cnf -s ./packet-spnego-template -D . spnego.asn */
5
6 /* Input file: packet-spnego-template.c */
7
8 #line 1 "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)
17  *
18  * $Id$
19  *
20  * Wireshark - Network traffic analyzer
21  * By Gerald Combs <gerald@wireshark.org>
22  * Copyright 1998 Gerald Combs
23  *
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.
28  *
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.
33  *
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.
37  */
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.
40 */
41
42 #ifdef HAVE_CONFIG_H
43 # include "config.h"
44 #endif
45
46 #include <glib.h>
47 #include <epan/packet.h>
48 #include <epan/asn1.h>
49 #include "packet-dcerpc.h"
50 #include "packet-gssapi.h"
51 #include "packet-kerberos.h"
52 #include <epan/crypt/crypt-rc4.h>
53 #include <epan/conversation.h>
54 #include <epan/emem.h>
55 #include <epan/asn1.h>
56
57 #include <string.h>
58
59 #include "packet-ber.h"
60
61
62 #define PNAME  "Simple Protected Negotiation"
63 #define PSNAME "SPNEGO"
64 #define PFNAME "spnego"
65
66 /* Initialize the protocol and registered fields */
67 static int proto_spnego = -1;
68 static int proto_spnego_krb5 = -1;
69
70
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;
88
89
90 /*--- Included file: packet-spnego-hf.c ---*/
91 #line 1 "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;
114
115 /*--- End of included file: packet-spnego-hf.c ---*/
116 #line 82 "packet-spnego-template.c"
117
118 /* Global variables */
119 static const char *MechType_oid;
120 gssapi_oid_value *next_level_value;
121 gboolean saw_mechanism = FALSE;
122
123
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;
129
130
131 /*--- Included file: packet-spnego-ett.c ---*/
132 #line 1 "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;
140
141 /*--- End of included file: packet-spnego-ett.c ---*/
142 #line 96 "packet-spnego-template.c"
143
144 /*
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.
148  */
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);
152
153
154 /*--- Included file: packet-spnego-fn.c ---*/
155 #line 1 "packet-spnego-fn.c"
156
157
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 "spnego.cnf"
161
162   gssapi_oid_value *value;
163
164   offset = dissect_ber_object_identifier_str(implicit_tag, actx, tree, tvb, offset, hf_index, &MechType_oid);
165
166
167   value = gssapi_lookup_oid_str(MechType_oid);
168
169   /*
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.)
179    */
180   if (!saw_mechanism) {
181     if (value)
182       next_level_value = value;
183     saw_mechanism = TRUE;
184   }
185
186
187
188   return offset;
189 }
190
191
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 },
194 };
195
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 "spnego.cnf"
199
200   conversation_t *conversation;
201
202   saw_mechanism = FALSE;
203
204   offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset,
205                                       MechTypeList_sequence_of, hf_index, ett_spnego_MechTypeList);
206
207
208   /*
209    * If we saw a mechType we need to store it in case the negTokenTarg
210    * does not provide a supportedMech.
211    */
212   if(saw_mechanism){
213     conversation = find_or_create_conversation(actx->pinfo);
214     conversation_add_proto_data(conversation, proto_spnego, next_level_value);
215   }
216
217
218
219   return offset;
220 }
221
222
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 }
232 };
233
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);
239
240   return offset;
241 }
242
243
244
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 "spnego.cnf"
248
249   tvbuff_t *mechToken_tvb = NULL;
250
251   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
252                                        &mechToken_tvb);
253
254
255   /*
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.
258    */
259   if (mechToken_tvb && next_level_value)
260      call_dissector(next_level_value->handle, mechToken_tvb, actx->pinfo, tree);
261
262
263
264
265   return offset;
266 }
267
268
269
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 "spnego.cnf"
273
274   gint8 class;
275   gboolean pc;
276   gint32 tag;
277   tvbuff_t *mechListMIC_tvb;
278
279   /*
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.
283    *
284    * Peek at the header, and then decide which it is we're seeing.
285    */
286   get_ber_identifier(tvb, offset, &class, &pc, &tag);
287   if (class == BER_CLASS_UNI && pc && tag == BER_UNI_TAG_SEQUENCE) {
288     /*
289      * It's a sequence.
290      */
291     return dissect_spnego_PrincipalSeq(FALSE, tvb, offset, actx, tree,
292                                        hf_spnego_mechListMIC);
293   } else {
294     /*
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.
298      */
299     offset = dissect_ber_octet_string(FALSE, actx, tree, tvb, offset,
300                                       hf_spnego_mechListMIC, &mechListMIC_tvb);
301
302     /*
303      * Now, we should be able to dispatch with that tvbuff.
304      */
305     if (mechListMIC_tvb && next_level_value)
306       call_dissector(next_level_value->handle, mechListMIC_tvb, actx->pinfo, tree);
307     return offset;
308   }
309
310
311
312   return offset;
313 }
314
315
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 }
322 };
323
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);
328
329   return offset;
330 }
331
332
333 static const value_string spnego_T_negResult_vals[] = {
334   {   0, "accept-completed" },
335   {   1, "accept-incomplete" },
336   {   2, "reject" },
337   { 0, NULL }
338 };
339
340
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);
345
346   return offset;
347 }
348
349
350
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 "spnego.cnf"
354
355   conversation_t *conversation;
356
357   saw_mechanism = FALSE;
358
359   offset = dissect_spnego_MechType(implicit_tag, tvb, offset, actx, tree, hf_index);
360
361
362   /*
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.
366    */
367   if(saw_mechanism){
368     conversation = find_or_create_conversation(actx->pinfo);
369     conversation_add_proto_data(conversation, proto_spnego, next_level_value);
370   }
371
372
373
374
375   return offset;
376 }
377
378
379
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 "spnego.cnf"
383
384   tvbuff_t *responseToken_tvb;
385
386
387   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
388                                        &responseToken_tvb);
389
390
391
392   /*
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 ...
397    */
398   if (responseToken_tvb && (tvb_reported_length(responseToken_tvb) > 0) ){
399     gssapi_oid_value *value=next_level_value;
400
401     if(value){
402       call_dissector(value->handle, responseToken_tvb, actx->pinfo, tree);
403     }
404   }
405
406
407
408
409   return offset;
410 }
411
412
413
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 "spnego.cnf"
417
418   tvbuff_t *mechListMIC_tvb;
419
420
421   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
422                                        &mechListMIC_tvb);
423
424
425
426   /*
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.
429    */
430   if (mechListMIC_tvb && (tvb_reported_length(mechListMIC_tvb) > 0) ){
431     gssapi_oid_value *value=next_level_value;
432
433     if(value){
434       call_dissector(value->handle, mechListMIC_tvb, actx->pinfo, tree);
435     }
436   }
437
438
439
440
441   return offset;
442 }
443
444
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 }
451 };
452
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);
457
458   return offset;
459 }
460
461
462 static const value_string spnego_NegotiationToken_vals[] = {
463   {   0, "negTokenInit" },
464   {   1, "negTokenTarg" },
465   { 0, NULL }
466 };
467
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 }
472 };
473
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);
479
480   return offset;
481 }
482
483
484
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);
490
491   return offset;
492 }
493
494
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 }
498 };
499
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);
504
505   return offset;
506 }
507
508
509
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 "spnego.cnf"
513
514   gssapi_oid_value *next_level_value_lcl;
515   proto_item *item;
516   proto_tree *subtree;
517   tvbuff_t *token_tvb;
518   int len;
519
520   /*
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?
527    */
528   next_level_value_lcl = gssapi_lookup_oid_str(MechType_oid);
529
530   /*
531    * Now dissect the GSS_Wrap token; it's assumed to be in the
532    * rest of the tvbuff.
533    */
534   item = proto_tree_add_item(tree, hf_spnego_wraptoken, tvb, offset, -1, FALSE);
535
536   subtree = proto_item_add_subtree(item, ett_spnego_wraptoken);
537
538   /*
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.
543    */
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);
554
555
556
557   return offset;
558 }
559
560
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 }
565 };
566
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);
571
572   return offset;
573 }
574
575
576
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);
581
582   return offset;
583 }
584
585
586 /*--- End of included file: packet-spnego-fn.c ---*/
587 #line 107 "packet-spnego-template.c"
588 /*
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.
592  */
593
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
602
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}
613 };
614
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
619
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}
626 };
627
628 #define KRB_SEAL_ALG_DES_CBC    0x0000
629 #define KRB_SEAL_ALG_RC4        0x0010
630 #define KRB_SEAL_ALG_NONE       0xffff
631
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}
637 };
638
639 /*
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.
645  */
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);
654
655 static void
656 dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
657 {
658         proto_item *item;
659         proto_tree *subtree;
660         int offset = 0;
661         guint16 token_id;
662         const char *oid;
663         gssapi_oid_value *value;
664         tvbuff_t *krb5_tvb;
665         gint8 class;
666         gboolean pc, ind = 0;
667         gint32 tag;
668         guint32 len;
669         asn1_ctx_t asn1_ctx;
670         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
671
672         item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, offset,
673                                    -1, FALSE);
674
675         subtree = proto_item_add_subtree(item, ett_spnego_krb5);
676
677         /*
678          * The KRB5 blob conforms to RFC1964:
679          * [APPLICATION 0] {
680          *   OID,
681          *   USHORT (0x0001 == AP-REQ, 0x0002 == AP-REP, 0x0003 == ERROR),
682          *   OCTET STRING }
683          *
684          * However, for some protocols, the KRB5 blob starts at the SHORT
685          * and has no DER encoded header etc.
686          *
687          * It appears that for some other protocols the KRB5 blob is just
688          * a Kerberos message, with no [APPLICATION 0] header, no OID,
689          * and no USHORT.
690          *
691          * So:
692          *
693          *      If we see an [APPLICATION 0] HEADER, we show the OID and
694          *      the USHORT, and then dissect the rest as a Kerberos message.
695          *
696          *      If we see an [APPLICATION 14] or [APPLICATION 15] header,
697          *      we assume it's an AP-REQ or AP-REP message, and dissect
698          *      it all as a Kerberos message.
699          *
700          *      Otherwise, we show the USHORT, and then dissect the rest
701          *      as a Kerberos message.
702          */
703
704         /*
705          * Get the first header ...
706          */
707         get_ber_identifier(tvb, offset, &class, &pc, &tag);
708         if (class == BER_CLASS_APP && pc) {
709             /*
710              * [APPLICATION <tag>]
711              */
712             offset = dissect_ber_identifier(pinfo, subtree, tvb, offset, &class, &pc, &tag);
713             offset = dissect_ber_length(pinfo, subtree, tvb, offset, &len, &ind);
714
715             switch (tag) {
716
717             case 0:
718                 /*
719                  * [APPLICATION 0]
720                  */
721
722                 /* Next, the OID */
723                 offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, subtree, tvb, offset, hf_spnego_krb5_oid, &oid);
724
725                 value = gssapi_lookup_oid_str(oid);
726
727                 token_id = tvb_get_letohs(tvb, offset);
728                 proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
729                                     token_id);
730
731                 offset += 2;
732
733                 break;
734
735             case 14:    /* [APPLICATION 14] */
736             case 15:    /* [APPLICATION 15] */
737                 /*
738                  * No token ID - just dissect as a Kerberos message and
739                  * return.
740                  */
741                 offset = dissect_kerberos_main(tvb, pinfo, subtree, FALSE, NULL);
742                 return;
743
744             default:
745                 proto_tree_add_text(subtree, tvb, offset, 0,
746                         "Unknown header (class=%d, pc=%d, tag=%d)",
747                         class, pc, tag);
748                 goto done;
749             }
750         } else {
751             /* Next, the token ID ... */
752
753             token_id = tvb_get_letohs(tvb, offset);
754             proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
755                                 token_id);
756
757             offset += 2;
758         }
759
760         switch (token_id) {
761
762         case KRB_TOKEN_AP_REQ:
763         case KRB_TOKEN_AP_REP:
764         case KRB_TOKEN_AP_ERR:
765           krb5_tvb = tvb_new_subset_remaining(tvb, offset);
766           offset = dissect_kerberos_main(krb5_tvb, pinfo, subtree, FALSE, NULL);
767           break;
768
769         case KRB_TOKEN_GETMIC:
770           offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
771           break;
772
773         case KRB_TOKEN_WRAP:
774           offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
775           break;
776
777         case KRB_TOKEN_DELETE_SEC_CONTEXT:
778
779           break;
780
781         case KRB_TOKEN_CFX_GETMIC:
782           offset = dissect_spnego_krb5_cfx_getmic_base(tvb, offset, pinfo, subtree);
783           break;
784
785         case KRB_TOKEN_CFX_WRAP:
786           offset = dissect_spnego_krb5_cfx_wrap_base(tvb, offset, pinfo, subtree, token_id);
787           break;
788
789         default:
790
791           break;
792         }
793
794  done:
795         proto_item_set_len(item, offset);
796         return;
797 }
798
799 #ifdef HAVE_KERBEROS
800 #include <epan/crypt/crypt-md5.h>
801
802 #ifndef KEYTYPE_ARCFOUR_56
803 # define KEYTYPE_ARCFOUR_56 24
804 #endif
805 /* XXX - We should probably do a configure-time check for this instead */
806 #ifndef KRB5_KU_USAGE_SEAL
807 # define KRB5_KU_USAGE_SEAL 22
808 #endif
809
810 static int
811 arcfour_mic_key(void *key_data, size_t key_size, int key_type,
812                 void *cksum_data, size_t cksum_size,
813                 void *key6_data)
814 {
815     guint8 k5_data[16];
816     guint8 T[4];
817
818     memset(T, 0, 4);
819
820     if (key_type == KEYTYPE_ARCFOUR_56) {
821         guint8 L40[14] = "fortybits";
822
823         memcpy(L40 + 10, T, sizeof(T));
824         md5_hmac(
825                 L40, 14,
826                 key_data,
827                 key_size,
828                 k5_data);
829         memset(&k5_data[7], 0xAB, 9);
830     } else {
831         md5_hmac(
832                 T, 4,
833                 key_data,
834                 key_size,
835                 k5_data);
836     }
837
838     md5_hmac(
839         cksum_data, cksum_size,
840         k5_data,
841         16,
842         key6_data);
843
844     return 0;
845 }
846
847 static int
848 usage2arcfour(int usage)
849 {
850     switch (usage) {
851     case 3: /*KRB5_KU_AS_REP_ENC_PART 3 */
852     case 9: /*KRB5_KU_TGS_REP_ENC_PART_SUB_KEY 9 */
853         return 8;
854     case 22: /*KRB5_KU_USAGE_SEAL 22 */
855         return 13;
856     case 23: /*KRB5_KU_USAGE_SIGN 23 */
857         return 15;
858     case 24: /*KRB5_KU_USAGE_SEQ 24 */
859         return 0;
860     default :
861         return 0;
862     }
863 }
864
865 static int
866 arcfour_mic_cksum(guint8 *key_data, int key_length,
867                   unsigned usage,
868                   guint8 sgn_cksum[8],
869                   const void *v1, size_t l1,
870                   const void *v2, size_t l2,
871                   const void *v3, size_t l3)
872 {
873     const guint8 signature[] = "signaturekey";
874     guint8 ksign_c[16];
875     unsigned char t[4];
876     md5_state_t ms;
877     unsigned char digest[16];
878     int rc4_usage;
879     guint8 cksum[16];
880
881     rc4_usage=usage2arcfour(usage);
882     md5_hmac(signature, sizeof(signature),
883                 key_data, key_length,
884                 ksign_c);
885     md5_init(&ms);
886     t[0] = (rc4_usage >>  0) & 0xFF;
887     t[1] = (rc4_usage >>  8) & 0xFF;
888     t[2] = (rc4_usage >> 16) & 0xFF;
889     t[3] = (rc4_usage >> 24) & 0xFF;
890     md5_append(&ms, t, 4);
891     md5_append(&ms, v1, l1);
892     md5_append(&ms, v2, l2);
893     md5_append(&ms, v3, l3);
894     md5_finish(&ms, digest);
895     md5_hmac(digest, 16, ksign_c, 16, cksum);
896
897     memcpy(sgn_cksum, cksum, 8);
898
899     return 0;
900 }
901
902 /*
903  * Verify padding of a gss wrapped message and return its length.
904  */
905 static int
906 gssapi_verify_pad(unsigned char *wrapped_data, int wrapped_length,
907                    size_t datalen,
908                    size_t *padlen)
909 {
910     unsigned char *pad;
911     size_t padlength;
912     int i;
913
914     pad = wrapped_data + wrapped_length - 1;
915     padlength = *pad;
916
917     if (padlength > datalen)
918         return 1;
919
920     for (i = padlength; i > 0 && *pad == padlength; i--, pad--)
921         ;
922     if (i != 0)
923         return 2;
924
925     *padlen = padlength;
926
927     return 0;
928 }
929
930 static int
931 decrypt_arcfour(packet_info *pinfo,
932          guint8 *input_message_buffer,
933          guint8 *output_message_buffer,
934          guint8 *key_value, int key_size, int key_type)
935 {
936     guint8 Klocaldata[16];
937     int ret;
938     gint32 seq_number;
939     size_t datalen;
940     guint8 k6_data[16];
941     guint32 SND_SEQ[2];
942     guint8 Confounder[8];
943     guint8 cksum_data[8];
944     int cmp;
945     int conf_flag;
946     size_t padlen = 0;
947
948     datalen = tvb_length(pinfo->gssapi_encrypted_tvb);
949
950     if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0x1000){
951         conf_flag=1;
952     } else if (tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0xffff){
953         conf_flag=0;
954     } else {
955         return -3;
956     }
957
958     if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 6)!=0xffff){
959         return -4;
960     }
961
962     ret = arcfour_mic_key(key_value, key_size, key_type,
963                           (void *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
964                           8, /* SGN_CKSUM */
965                           k6_data);
966     if (ret) {
967         return -5;
968     }
969
970     {
971         rc4_state_struct rc4_state;
972
973         crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
974         memcpy(SND_SEQ, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 8, 8), 8);
975         crypt_rc4(&rc4_state, (unsigned char *)SND_SEQ, 8);
976
977         memset(k6_data, 0, sizeof(k6_data));
978     }
979
980     seq_number=g_ntohl(SND_SEQ[0]);
981
982     if (SND_SEQ[1] != 0xFFFFFFFF && SND_SEQ[1] != 0x00000000) {
983         return -6;
984     }
985
986     {
987         int i;
988
989         for (i = 0; i < 16; i++)
990             Klocaldata[i] = ((guint8 *)key_value)[i] ^ 0xF0;
991     }
992     ret = arcfour_mic_key(Klocaldata,sizeof(Klocaldata),key_type,
993                           (unsigned char *)SND_SEQ, 4,
994                           k6_data);
995     memset(Klocaldata, 0, sizeof(Klocaldata));
996     if (ret) {
997         return -7;
998     }
999
1000     if(conf_flag) {
1001         rc4_state_struct rc4_state;
1002
1003         crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
1004         memcpy(Confounder, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8), 8);
1005         crypt_rc4(&rc4_state, Confounder, 8);
1006         memcpy(output_message_buffer, input_message_buffer, datalen);
1007         crypt_rc4(&rc4_state, output_message_buffer, datalen);
1008     } else {
1009         memcpy(Confounder,
1010                 tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8),
1011                 8); /* Confounder */
1012         memcpy(output_message_buffer,
1013                 input_message_buffer,
1014                 datalen);
1015     }
1016     memset(k6_data, 0, sizeof(k6_data));
1017
1018     /* only normal (i.e. non DCE style  wrapping use padding ? */
1019     if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
1020         ret = gssapi_verify_pad(output_message_buffer,datalen,datalen, &padlen);
1021         if (ret) {
1022             return -9;
1023         }
1024         datalen -= padlen;
1025     }
1026
1027     /* dont know what the checksum looks like for dce style gssapi */
1028     if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
1029         ret = arcfour_mic_cksum(key_value, key_size,
1030                             KRB5_KU_USAGE_SEAL,
1031                             cksum_data,
1032                             tvb_get_ptr(pinfo->gssapi_wrap_tvb, 0, 8), 8,
1033                             Confounder, sizeof(Confounder),
1034                             output_message_buffer,
1035                             datalen + padlen);
1036         if (ret) {
1037             return -10;
1038         }
1039
1040         cmp = memcmp(cksum_data,
1041             tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
1042             8); /* SGN_CKSUM */
1043         if (cmp) {
1044             return -11;
1045         }
1046     }
1047
1048     return datalen;
1049 }
1050
1051
1052
1053 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1054
1055 static void
1056 decrypt_gssapi_krb_arcfour_wrap(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int keytype)
1057 {
1058         int ret;
1059         enc_key_t *ek;
1060         int length;
1061         const guint8 *original_data;
1062
1063         static int omb_index=0;
1064         static guint8 *omb_arr[4]={NULL,NULL,NULL,NULL};
1065         static guint8 *cryptocopy=NULL; /* workaround for pre-0.6.1 heimdal bug */
1066         guint8 *output_message_buffer;
1067
1068         omb_index++;
1069         if(omb_index>=4){
1070                 omb_index=0;
1071         }
1072         output_message_buffer=omb_arr[omb_index];
1073
1074
1075         length=tvb_length(pinfo->gssapi_encrypted_tvb);
1076         original_data=tvb_get_ptr(pinfo->gssapi_encrypted_tvb, 0, length);
1077
1078         /* dont do anything if we are not attempting to decrypt data */
1079 /*
1080         if(!krb_decrypt){
1081                 return;
1082         }
1083 */
1084         /* XXX we should only do this for first time, then store somewhere */
1085         /* XXX We also need to re-read the keytab when the preference changes */
1086
1087         cryptocopy=ep_alloc(length);
1088         if(output_message_buffer){
1089                 g_free(output_message_buffer);
1090                 output_message_buffer=NULL;
1091         }
1092         output_message_buffer=g_malloc(length);
1093
1094         for(ek=enc_key_list;ek;ek=ek->next){
1095                 /* shortcircuit and bail out if enctypes are not matching */
1096                 if(ek->keytype!=keytype){
1097                         continue;
1098                 }
1099
1100                 /* pre-0.6.1 versions of Heimdal would sometimes change
1101                   the cryptotext data even when the decryption failed.
1102                   This would obviously not work since we iterate over the
1103                   keys. So just give it a copy of the crypto data instead.
1104                   This has been seen for RC4-HMAC blobs.
1105                 */
1106                 memcpy(cryptocopy, original_data, length);
1107                 ret=decrypt_arcfour(pinfo,
1108                                 cryptocopy,
1109                                 output_message_buffer,
1110                                 ek->keyvalue,
1111                                 ek->keylength,
1112                                 ek->keytype
1113                                             );
1114                 if (ret >= 0) {
1115                         proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
1116                         pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(tvb,
1117                                 output_message_buffer,
1118                                 ret, ret);
1119                         tvb_set_free_cb(pinfo->gssapi_decrypted_tvb, g_free);
1120                         add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
1121                         return;
1122                 }
1123         }
1124         return;
1125 }
1126
1127 /* borrowed from heimdal */
1128 static int
1129 rrc_rotate(void *data, int len, guint16 rrc, int unrotate)
1130 {
1131         unsigned char *tmp, buf[256];
1132         size_t left;
1133
1134         if (len == 0)
1135                 return 0;
1136
1137         rrc %= len;
1138
1139         if (rrc == 0)
1140                 return 0;
1141
1142         left = len - rrc;
1143
1144         if (rrc <= sizeof(buf)) {
1145                 tmp = buf;
1146         } else {
1147                 tmp = g_malloc(rrc);
1148                 if (tmp == NULL)
1149                         return -1;
1150         }
1151
1152         if (unrotate) {
1153                 memcpy(tmp, data, rrc);
1154                 memmove(data, (unsigned char *)data + rrc, left);
1155                 memcpy((unsigned char *)data + left, tmp, rrc);
1156         } else {
1157                 memcpy(tmp, (unsigned char *)data + left, rrc);
1158                 memmove((unsigned char *)data + rrc, data, left);
1159                 memcpy(data, tmp, rrc);
1160         }
1161
1162         if (rrc > sizeof(buf))
1163                 g_free(tmp);
1164
1165         return 0;
1166 }
1167
1168
1169 #define KRB5_KU_USAGE_ACCEPTOR_SEAL     22
1170 #define KRB5_KU_USAGE_ACCEPTOR_SIGN     23
1171 #define KRB5_KU_USAGE_INITIATOR_SEAL    24
1172 #define KRB5_KU_USAGE_INITIATOR_SIGN    25
1173
1174 static void
1175 decrypt_gssapi_krb_cfx_wrap(proto_tree *tree _U_,
1176                             packet_info *pinfo,
1177                             tvbuff_t *checksum_tvb,
1178                             tvbuff_t *encrypted_tvb,
1179                             guint16 ec,
1180                             guint16 rrc,
1181                             gboolean is_dce,
1182                             int keytype,
1183                             unsigned int usage)
1184 {
1185         int res;
1186         guint8 *rotated;
1187         guint8 *output;
1188         int datalen;
1189         tvbuff_t *next_tvb;
1190
1191         /* dont do anything if we are not attempting to decrypt data */
1192         if(!krb_decrypt){
1193                 return;
1194         }
1195
1196         datalen = tvb_length(checksum_tvb) + tvb_length(encrypted_tvb);
1197
1198         rotated = g_malloc(datalen);
1199
1200         tvb_memcpy(checksum_tvb, rotated,
1201                    0, tvb_length(checksum_tvb));
1202         tvb_memcpy(encrypted_tvb, rotated + tvb_length(checksum_tvb),
1203                    0, tvb_length(encrypted_tvb));
1204
1205         if (is_dce) {
1206                 rrc += ec;
1207         }
1208
1209         res = rrc_rotate(rotated, datalen, rrc, TRUE);
1210
1211         next_tvb=tvb_new_child_real_data(encrypted_tvb, rotated,
1212                                          datalen, datalen);
1213         tvb_set_free_cb(next_tvb, g_free);
1214         add_new_data_source(pinfo, next_tvb, "GSSAPI CFX");
1215
1216         output = decrypt_krb5_data(tree, pinfo, usage, next_tvb,
1217                   keytype, &datalen);
1218
1219         if (output) {
1220                 guint8 *outdata;
1221
1222                 outdata = g_memdup(output, tvb_length(encrypted_tvb));
1223                 g_free(output);
1224
1225                 pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(encrypted_tvb,
1226                         outdata,
1227                         tvb_length(encrypted_tvb),
1228                         tvb_length(encrypted_tvb));
1229                 add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
1230                 tvb_set_free_cb(pinfo->gssapi_decrypted_tvb, g_free);
1231                 return;
1232         }
1233         return;
1234 }
1235
1236 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1237
1238
1239 #endif
1240
1241 /*
1242  * This is for GSSAPI Wrap tokens ...
1243  */
1244 static int
1245 dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
1246 #ifndef HAVE_KERBEROS
1247         _U_
1248 #endif
1249     , proto_tree *tree, guint16 token_id
1250 #ifndef HAVE_KERBEROS
1251         _U_
1252 #endif
1253     )
1254 {
1255         guint16 sgn_alg, seal_alg;
1256 #ifdef HAVE_KERBEROS
1257         int start_offset=offset;
1258 #endif
1259
1260         /*
1261          * The KRB5 blob conforms to RFC1964:
1262          *   USHORT (0x0102 == GSS_Wrap)
1263          *   and so on }
1264          */
1265
1266         /* Now, the sign and seal algorithms ... */
1267
1268         sgn_alg = tvb_get_letohs(tvb, offset);
1269         proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
1270                             sgn_alg);
1271
1272         offset += 2;
1273
1274         seal_alg = tvb_get_letohs(tvb, offset);
1275         proto_tree_add_uint(tree, hf_spnego_krb5_seal_alg, tvb, offset, 2,
1276                             seal_alg);
1277
1278         offset += 2;
1279
1280         /* Skip the filler */
1281
1282         offset += 2;
1283
1284         /* Encrypted sequence number */
1285
1286         proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
1287                             TRUE);
1288
1289         offset += 8;
1290
1291         /* Checksum of plaintext padded data */
1292
1293         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
1294                             TRUE);
1295
1296         offset += 8;
1297
1298         /*
1299          * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
1300          * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
1301          * extra 8 bytes of "Random confounder" after the checksum.
1302          * It certainly confounds code expecting all Kerberos 5
1303          * GSS_Wrap() tokens to look the same....
1304          */
1305         if ((sgn_alg == KRB_SGN_ALG_HMAC) ||
1306             /* there also seems to be a confounder for DES MAC MD5 - certainly seen when using with
1307                SASL with LDAP between a Java client and Active Directory. If this breaks other things
1308                we may need to make this an option. gal 17/2/06 */
1309             (sgn_alg == KRB_SGN_ALG_DES_MAC_MD5)) {
1310           proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
1311                               TRUE);
1312           offset += 8;
1313         }
1314
1315         /* Is the data encrypted? */
1316         pinfo->gssapi_data_encrypted=(seal_alg!=KRB_SEAL_ALG_NONE);
1317
1318 #ifdef HAVE_KERBEROS
1319 #define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
1320         if(pinfo->decrypt_gssapi_tvb){
1321                 /* if the caller did not provide a tvb, then we just use
1322                    whatever is left of our current tvb.
1323                 */
1324                 if(!pinfo->gssapi_encrypted_tvb){
1325                         int len;
1326                         len=tvb_reported_length_remaining(tvb,offset);
1327                         if(len>tvb_length_remaining(tvb, offset)){
1328                                 /* no point in trying to decrypt,
1329                                    we dont have the full pdu.
1330                                 */
1331                                 return offset;
1332                         }
1333                         pinfo->gssapi_encrypted_tvb = tvb_new_subset(
1334                                         tvb, offset, len, len);
1335                 }
1336
1337                 /* if this is KRB5 wrapped rc4-hmac */
1338                 if((token_id==KRB_TOKEN_WRAP)
1339                  &&(sgn_alg==KRB_SGN_ALG_HMAC)
1340                  &&(seal_alg==KRB_SEAL_ALG_RC4)){
1341                         /* do we need to create a tvb for the wrapper
1342                            as well ?
1343                         */
1344                         if(!pinfo->gssapi_wrap_tvb){
1345                                 pinfo->gssapi_wrap_tvb = tvb_new_subset(
1346                                         tvb, start_offset-2,
1347                                         GSS_ARCFOUR_WRAP_TOKEN_SIZE,
1348                                         GSS_ARCFOUR_WRAP_TOKEN_SIZE);
1349                         }
1350 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1351                         decrypt_gssapi_krb_arcfour_wrap(tree,
1352                                 pinfo,
1353                                 tvb,
1354                                 23 /* rc4-hmac */);
1355 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1356                 }
1357         }
1358 #endif
1359         /*
1360          * Return the offset past the checksum, so that we know where
1361          * the data we're wrapped around starts.  Also, set the length
1362          * of our top-level item to that offset, so it doesn't cover
1363          * the data we're wrapped around.
1364          *
1365          * Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
1366          * not before.
1367          */
1368         return offset;
1369 }
1370
1371 /*
1372  * XXX - This is for GSSAPI GetMIC tokens ...
1373  */
1374 static int
1375 dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
1376 {
1377         guint16 sgn_alg;
1378
1379         /*
1380          * The KRB5 blob conforms to RFC1964:
1381          *   USHORT (0x0101 == GSS_GetMIC)
1382          *   and so on }
1383          */
1384
1385         /* Now, the sign algorithm ... */
1386
1387         sgn_alg = tvb_get_letohs(tvb, offset);
1388         proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
1389                             sgn_alg);
1390
1391         offset += 2;
1392
1393         /* Skip the filler */
1394
1395         offset += 4;
1396
1397         /* Encrypted sequence number */
1398
1399         proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
1400                             TRUE);
1401
1402         offset += 8;
1403
1404         /* Checksum of plaintext padded data */
1405
1406         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
1407                             TRUE);
1408
1409         offset += 8;
1410
1411         /*
1412          * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
1413          * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
1414          * extra 8 bytes of "Random confounder" after the checksum.
1415          * It certainly confounds code expecting all Kerberos 5
1416          * GSS_Wrap() tokens to look the same....
1417          *
1418          * The exception is DNS/TSIG where there is no such confounder
1419          * so we need to test here if there are more bytes in our tvb or not.
1420          *  -- ronnie
1421          */
1422         if (tvb_length_remaining(tvb, offset)) {
1423           if (sgn_alg == KRB_SGN_ALG_HMAC) {
1424             proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
1425                               TRUE);
1426
1427             offset += 8;
1428           }
1429         }
1430
1431         /*
1432          * Return the offset past the checksum, so that we know where
1433          * the data we're wrapped around starts.  Also, set the length
1434          * of our top-level item to that offset, so it doesn't cover
1435          * the data we're wrapped around.
1436          */
1437
1438         return offset;
1439 }
1440
1441 static int
1442 dissect_spnego_krb5_cfx_flags(tvbuff_t *tvb, int offset,
1443                               proto_tree *spnego_krb5_tree,
1444                               guint8 cfx_flags)
1445 {
1446         proto_tree *cfx_flags_tree = NULL;
1447         proto_item *tf = NULL;
1448
1449         if (spnego_krb5_tree) {
1450                 tf = proto_tree_add_uint(spnego_krb5_tree,
1451                                          hf_spnego_krb5_cfx_flags,
1452                                          tvb, offset, 1, cfx_flags);
1453                 cfx_flags_tree = proto_item_add_subtree(tf, ett_spnego_krb5_cfx_flags);
1454         }
1455
1456         proto_tree_add_boolean(cfx_flags_tree,
1457                                hf_spnego_krb5_cfx_flags_04,
1458                                tvb, offset, 1, cfx_flags);
1459         proto_tree_add_boolean(cfx_flags_tree,
1460                                hf_spnego_krb5_cfx_flags_02,
1461                                tvb, offset, 1, cfx_flags);
1462         proto_tree_add_boolean(cfx_flags_tree,
1463                                hf_spnego_krb5_cfx_flags_01,
1464                                tvb, offset, 1, cfx_flags);
1465
1466         return (offset + 1);
1467 }
1468
1469 /*
1470  * This is for GSSAPI CFX Wrap tokens ...
1471  */
1472 static int
1473 dissect_spnego_krb5_cfx_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
1474 #ifndef HAVE_KERBEROS
1475         _U_
1476 #endif
1477     , proto_tree *tree, guint16 token_id _U_
1478     )
1479 {
1480         guint8 flags;
1481         guint16 ec;
1482         guint16 rrc;
1483         int checksum_size;
1484         int start_offset=offset;
1485
1486         /*
1487          * The KRB5 blob conforms to RFC4121:
1488          *   USHORT (0x0504)
1489          *   and so on }
1490          */
1491
1492         /* Now, the sign and seal algorithms ... */
1493
1494         flags = tvb_get_guint8(tvb, offset);
1495         offset = dissect_spnego_krb5_cfx_flags(tvb, offset, tree, flags);
1496
1497         pinfo->gssapi_data_encrypted=(flags & 2);
1498
1499         /* Skip the filler */
1500
1501         proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 1,
1502                             FALSE);
1503         offset += 1;
1504
1505         /* EC */
1506         ec = tvb_get_ntohs(tvb, offset);
1507         proto_tree_add_item(tree, hf_spnego_krb5_cfx_ec, tvb, offset, 2,
1508                             FALSE);
1509         offset += 2;
1510
1511         /* RRC */
1512         rrc = tvb_get_ntohs(tvb, offset);
1513         proto_tree_add_item(tree, hf_spnego_krb5_cfx_rrc, tvb, offset, 2,
1514                             FALSE);
1515         offset += 2;
1516
1517         /* sequence number */
1518
1519         proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
1520                             FALSE);
1521         offset += 8;
1522
1523         /* Checksum of plaintext padded data */
1524
1525         if (pinfo->gssapi_data_encrypted) {
1526                 checksum_size = 44 + ec;
1527         } else {
1528                 checksum_size = 12;
1529         }
1530
1531         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
1532                             checksum_size, FALSE);
1533         offset += checksum_size;
1534
1535         if(pinfo->decrypt_gssapi_tvb){
1536                 /* if the caller did not provide a tvb, then we just use
1537                    whatever is left of our current tvb.
1538                 */
1539                 if(!pinfo->gssapi_encrypted_tvb){
1540                         int len;
1541                         len=tvb_reported_length_remaining(tvb,offset);
1542                         if(len>tvb_length_remaining(tvb, offset)){
1543                                 /* no point in trying to decrypt,
1544                                    we dont have the full pdu.
1545                                 */
1546                                 return offset;
1547                         }
1548                         pinfo->gssapi_encrypted_tvb = tvb_new_subset(
1549                                         tvb, offset, len, len);
1550                 }
1551
1552                 if (pinfo->gssapi_data_encrypted) {
1553                         /* do we need to create a tvb for the wrapper
1554                            as well ?
1555                         */
1556                         if(!pinfo->gssapi_wrap_tvb){
1557                                 pinfo->gssapi_wrap_tvb = tvb_new_subset(
1558                                         tvb, start_offset-2,
1559                                         offset - (start_offset-2),
1560                                         offset - (start_offset-2));
1561                         }
1562                 }
1563         }
1564
1565 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1566 {
1567         tvbuff_t *checksum_tvb = tvb_new_subset(tvb, 16, checksum_size, checksum_size);
1568
1569         if (pinfo->gssapi_data_encrypted) {
1570                 if(pinfo->gssapi_encrypted_tvb){
1571                         decrypt_gssapi_krb_cfx_wrap(tree,
1572                                 pinfo,
1573                                 checksum_tvb,
1574                                 pinfo->gssapi_encrypted_tvb,
1575                                 ec,
1576                                 rrc,
1577                                 (pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_DCE)?TRUE:FALSE,
1578                                 -1,
1579                                 (flags & 0x0001)?
1580                                 KRB5_KU_USAGE_ACCEPTOR_SEAL:
1581                                 KRB5_KU_USAGE_INITIATOR_SEAL);
1582                 }
1583         }
1584 }
1585 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1586
1587         /*
1588          * Return the offset past the checksum, so that we know where
1589          * the data we're wrapped around starts.  Also, set the length
1590          * of our top-level item to that offset, so it doesn't cover
1591          * the data we're wrapped around.
1592          *
1593          * Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
1594          * not before.
1595          */
1596         return offset;
1597 }
1598
1599 /*
1600  * XXX - This is for GSSAPI CFX GetMIC tokens ...
1601  */
1602 static int
1603 dissect_spnego_krb5_cfx_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
1604 {
1605         guint8 flags;
1606         int checksum_size;
1607
1608         /*
1609          * The KRB5 blob conforms to RFC4121:
1610          *   USHORT (0x0404 == GSS_GetMIC)
1611          *   and so on }
1612          */
1613
1614         flags = tvb_get_guint8(tvb, offset);
1615         offset = dissect_spnego_krb5_cfx_flags(tvb, offset, tree, flags);
1616
1617         /* Skip the filler */
1618
1619         proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 5,
1620                             FALSE);
1621         offset += 5;
1622
1623         /* sequence number */
1624
1625         proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
1626                             FALSE);
1627         offset += 8;
1628
1629         /* Checksum of plaintext padded data */
1630
1631         checksum_size = tvb_length_remaining(tvb, offset);
1632
1633         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
1634                             checksum_size, FALSE);
1635         offset += checksum_size;
1636
1637         /*
1638          * Return the offset past the checksum, so that we know where
1639          * the data we're wrapped around starts.  Also, set the length
1640          * of our top-level item to that offset, so it doesn't cover
1641          * the data we're wrapped around.
1642          */
1643
1644         return offset;
1645 }
1646
1647 /*
1648  * XXX - is this for SPNEGO or just GSS-API?
1649  * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
1650  * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
1651  * than designating SPNEGO as the mechanism, offering Kerberos V5, and
1652  * getting it accepted.
1653  */
1654 static int
1655 dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1656 {
1657         proto_item *item;
1658         proto_tree *subtree;
1659         int offset = 0;
1660         guint16 token_id;
1661
1662         item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, 0, -1, FALSE);
1663
1664         subtree = proto_item_add_subtree(item, ett_spnego_krb5);
1665
1666         /*
1667          * The KRB5 blob conforms to RFC1964:
1668          *   USHORT (0x0102 == GSS_Wrap)
1669          *   and so on }
1670          */
1671
1672         /* First, the token ID ... */
1673
1674         token_id = tvb_get_letohs(tvb, offset);
1675         proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
1676                             token_id);
1677
1678         offset += 2;
1679
1680         switch (token_id) {
1681         case KRB_TOKEN_GETMIC:
1682           offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
1683           break;
1684
1685         case KRB_TOKEN_WRAP:
1686           offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
1687           break;
1688
1689         case KRB_TOKEN_CFX_GETMIC:
1690           offset = dissect_spnego_krb5_cfx_getmic_base(tvb, offset, pinfo, subtree);
1691           break;
1692
1693         case KRB_TOKEN_CFX_WRAP:
1694           offset = dissect_spnego_krb5_cfx_wrap_base(tvb, offset, pinfo, subtree, token_id);
1695           break;
1696
1697         default:
1698
1699           break;
1700         }
1701
1702         /*
1703          * Return the offset past the checksum, so that we know where
1704          * the data we're wrapped around starts.  Also, set the length
1705          * of our top-level item to that offset, so it doesn't cover
1706          * the data we're wrapped around.
1707          */
1708         proto_item_set_len(item, offset);
1709         return offset;
1710 }
1711
1712 /* Spnego stuff from here */
1713
1714 static int
1715 dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1716 {
1717         proto_item *item;
1718         proto_tree *subtree;
1719         int offset = 0;
1720         asn1_ctx_t asn1_ctx;
1721         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1722
1723         MechType_oid = NULL;
1724
1725         /*
1726          * We need this later, so lets get it now ...
1727          * It has to be per-frame as there can be more than one GSS-API
1728          * negotiation in a conversation.
1729          */
1730
1731
1732         item = proto_tree_add_item(tree, proto_spnego, tvb, offset,
1733                                    -1, FALSE);
1734
1735         subtree = proto_item_add_subtree(item, ett_spnego);
1736         /*
1737          * The TVB contains a [0] header and a sequence that consists of an
1738          * object ID and a blob containing the data ...
1739          * XXX - is this RFC 2743's "Mechanism-Independent Token Format",
1740          * with the "optional" "use in non-initial tokens" being chosen.
1741          * ASN1 code addet to spnego.asn to handle this.
1742          */
1743
1744         offset = dissect_spnego_InitialContextToken(FALSE, tvb, offset, &asn1_ctx , subtree, -1);
1745
1746         return offset;
1747 }
1748
1749
1750 static void
1751 dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
1752 {
1753         proto_item *item;
1754         proto_tree *subtree;
1755         int offset = 0;
1756         conversation_t *conversation;
1757         asn1_ctx_t asn1_ctx;
1758         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1759
1760         /*
1761          * We need this later, so lets get it now ...
1762          * It has to be per-frame as there can be more than one GSS-API
1763          * negotiation in a conversation.
1764          */
1765         next_level_value = p_get_proto_data(pinfo->fd, proto_spnego);
1766         if (!next_level_value && !pinfo->fd->flags.visited) {
1767             /*
1768              * No handle attached to this frame, but it's the first
1769              * pass, so it'd be attached to the conversation.
1770              * If we have a conversation, try to get the handle,
1771              * and if we get one, attach it to the frame.
1772              */
1773             conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1774                                              pinfo->ptype, pinfo->srcport,
1775                                              pinfo->destport, 0);
1776
1777             if (conversation) {
1778                 next_level_value = conversation_get_proto_data(conversation,
1779                                                                proto_spnego);
1780                 if (next_level_value)
1781                     p_add_proto_data(pinfo->fd, proto_spnego, next_level_value);
1782             }
1783         }
1784
1785         item = proto_tree_add_item(parent_tree, proto_spnego, tvb, offset,
1786                                    -1, FALSE);
1787
1788         subtree = proto_item_add_subtree(item, ett_spnego);
1789
1790         /*
1791          * The TVB contains a [0] header and a sequence that consists of an
1792          * object ID and a blob containing the data ...
1793          * Actually, it contains, according to RFC2478:
1794          * NegotiationToken ::= CHOICE {
1795          *          negTokenInit [0] NegTokenInit,
1796          *          negTokenTarg [1] NegTokenTarg }
1797          * NegTokenInit ::= SEQUENCE {
1798          *          mechTypes [0] MechTypeList OPTIONAL,
1799          *          reqFlags [1] ContextFlags OPTIONAL,
1800          *          mechToken [2] OCTET STRING OPTIONAL,
1801          *          mechListMIC [3] OCTET STRING OPTIONAL }
1802          * NegTokenTarg ::= SEQUENCE {
1803          *          negResult [0] ENUMERATED {
1804          *              accept_completed (0),
1805          *              accept_incomplete (1),
1806          *              reject (2) } OPTIONAL,
1807          *          supportedMech [1] MechType OPTIONAL,
1808          *          responseToken [2] OCTET STRING OPTIONAL,
1809          *          mechListMIC [3] OCTET STRING OPTIONAL }
1810          *
1811          * Windows typically includes mechTypes and mechListMic ('NONE'
1812          * in the case of NTLMSSP only).
1813          * It seems to duplicate the responseToken into the mechListMic field
1814          * as well. Naughty, naughty.
1815          *
1816          */
1817         offset = dissect_spnego_NegotiationToken(FALSE, tvb, offset, &asn1_ctx, subtree, -1);
1818
1819 }
1820
1821 /*--- proto_register_spnego -------------------------------------------*/
1822 void proto_register_spnego(void) {
1823
1824         /* List of fields */
1825         static hf_register_info hf[] = {
1826                 { &hf_spnego_wraptoken,
1827                   { "wrapToken", "spnego.wraptoken",
1828                     FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO wrapToken",
1829                     HFILL}},
1830                 { &hf_spnego_krb5,
1831                   { "krb5_blob", "spnego.krb5.blob", FT_BYTES,
1832                     BASE_NONE, NULL, 0, NULL, HFILL }},
1833                 { &hf_spnego_krb5_oid,
1834                   { "KRB5 OID", "spnego.krb5_oid", FT_STRING,
1835                     BASE_NONE, NULL, 0, NULL, HFILL }},
1836                 { &hf_spnego_krb5_tok_id,
1837                   { "krb5_tok_id", "spnego.krb5.tok_id", FT_UINT16, BASE_HEX,
1838                     VALS(spnego_krb5_tok_id_vals), 0, "KRB5 Token Id", HFILL}},
1839                 { &hf_spnego_krb5_sgn_alg,
1840                   { "krb5_sgn_alg", "spnego.krb5.sgn_alg", FT_UINT16, BASE_HEX,
1841                     VALS(spnego_krb5_sgn_alg_vals), 0, "KRB5 Signing Algorithm", HFILL}},
1842                 { &hf_spnego_krb5_seal_alg,
1843                   { "krb5_seal_alg", "spnego.krb5.seal_alg", FT_UINT16, BASE_HEX,
1844                     VALS(spnego_krb5_seal_alg_vals), 0, "KRB5 Sealing Algorithm", HFILL}},
1845                 { &hf_spnego_krb5_snd_seq,
1846                   { "krb5_snd_seq", "spnego.krb5.snd_seq", FT_BYTES, BASE_NONE,
1847                     NULL, 0, "KRB5 Encrypted Sequence Number", HFILL}},
1848                 { &hf_spnego_krb5_sgn_cksum,
1849                   { "krb5_sgn_cksum", "spnego.krb5.sgn_cksum", FT_BYTES, BASE_NONE,
1850                     NULL, 0, "KRB5 Data Checksum", HFILL}},
1851                 { &hf_spnego_krb5_confounder,
1852                   { "krb5_confounder", "spnego.krb5.confounder", FT_BYTES, BASE_NONE,
1853                     NULL, 0, "KRB5 Confounder", HFILL}},
1854                 { &hf_spnego_krb5_filler,
1855                   { "krb5_filler", "spnego.krb5.filler", FT_BYTES, BASE_NONE,
1856                     NULL, 0, "KRB5 Filler", HFILL}},
1857                 { &hf_spnego_krb5_cfx_flags,
1858                   { "krb5_cfx_flags", "spnego.krb5.cfx_flags", FT_UINT8, BASE_HEX,
1859                     NULL, 0, "KRB5 CFX Flags", HFILL}},
1860                 { &hf_spnego_krb5_cfx_flags_01,
1861                   { "SendByAcceptor", "spnego.krb5.send_by_acceptor", FT_BOOLEAN, 8,
1862                     TFS (&tfs_set_notset), 0x01, NULL, HFILL}},
1863                 { &hf_spnego_krb5_cfx_flags_02,
1864                   { "Sealed", "spnego.krb5.sealed", FT_BOOLEAN, 8,
1865                     TFS (&tfs_set_notset), 0x02, NULL, HFILL}},
1866                 { &hf_spnego_krb5_cfx_flags_04,
1867                   { "AcceptorSubkey", "spnego.krb5.acceptor_subkey", FT_BOOLEAN, 8,
1868                     TFS (&tfs_set_notset), 0x04, NULL, HFILL}},
1869                 { &hf_spnego_krb5_cfx_ec,
1870                   { "krb5_cfx_ec", "spnego.krb5.cfx_ec", FT_UINT16, BASE_DEC,
1871                     NULL, 0, "KRB5 CFX Extra Count", HFILL}},
1872                 { &hf_spnego_krb5_cfx_rrc,
1873                   { "krb5_cfx_rrc", "spnego.krb5.cfx_rrc", FT_UINT16, BASE_DEC,
1874                     NULL, 0, "KRB5 CFX Right Rotation Count", HFILL}},
1875                 { &hf_spnego_krb5_cfx_seq,
1876                   { "krb5_cfx_seq", "spnego.krb5.cfx_seq", FT_UINT64, BASE_DEC,
1877                     NULL, 0, "KRB5 Sequence Number", HFILL}},
1878
1879
1880 /*--- Included file: packet-spnego-hfarr.c ---*/
1881 #line 1 "packet-spnego-hfarr.c"
1882     { &hf_spnego_negTokenInit,
1883       { "negTokenInit", "spnego.negTokenInit",
1884         FT_NONE, BASE_NONE, NULL, 0,
1885         NULL, HFILL }},
1886     { &hf_spnego_negTokenTarg,
1887       { "negTokenTarg", "spnego.negTokenTarg",
1888         FT_NONE, BASE_NONE, NULL, 0,
1889         NULL, HFILL }},
1890     { &hf_spnego_MechTypeList_item,
1891       { "MechType", "spnego.MechType",
1892         FT_OID, BASE_NONE, NULL, 0,
1893         NULL, HFILL }},
1894     { &hf_spnego_principal,
1895       { "principal", "spnego.principal",
1896         FT_STRING, BASE_NONE, NULL, 0,
1897         "GeneralString", HFILL }},
1898     { &hf_spnego_mechTypes,
1899       { "mechTypes", "spnego.mechTypes",
1900         FT_UINT32, BASE_DEC, NULL, 0,
1901         "MechTypeList", HFILL }},
1902     { &hf_spnego_reqFlags,
1903       { "reqFlags", "spnego.reqFlags",
1904         FT_BYTES, BASE_NONE, NULL, 0,
1905         "ContextFlags", HFILL }},
1906     { &hf_spnego_mechToken,
1907       { "mechToken", "spnego.mechToken",
1908         FT_BYTES, BASE_NONE, NULL, 0,
1909         NULL, HFILL }},
1910     { &hf_spnego_negTokenInit_mechListMIC,
1911       { "mechListMIC", "spnego.mechListMIC",
1912         FT_BYTES, BASE_NONE, NULL, 0,
1913         "T_NegTokenInit_mechListMIC", HFILL }},
1914     { &hf_spnego_negResult,
1915       { "negResult", "spnego.negResult",
1916         FT_UINT32, BASE_DEC, VALS(spnego_T_negResult_vals), 0,
1917         NULL, HFILL }},
1918     { &hf_spnego_supportedMech,
1919       { "supportedMech", "spnego.supportedMech",
1920         FT_OID, BASE_NONE, NULL, 0,
1921         NULL, HFILL }},
1922     { &hf_spnego_responseToken,
1923       { "responseToken", "spnego.responseToken",
1924         FT_BYTES, BASE_NONE, NULL, 0,
1925         NULL, HFILL }},
1926     { &hf_spnego_mechListMIC,
1927       { "mechListMIC", "spnego.mechListMIC",
1928         FT_BYTES, BASE_NONE, NULL, 0,
1929         NULL, HFILL }},
1930     { &hf_spnego_thisMech,
1931       { "thisMech", "spnego.thisMech",
1932         FT_OID, BASE_NONE, NULL, 0,
1933         "MechType", HFILL }},
1934     { &hf_spnego_innerContextToken,
1935       { "innerContextToken", "spnego.innerContextToken",
1936         FT_NONE, BASE_NONE, NULL, 0,
1937         NULL, HFILL }},
1938     { &hf_spnego_ContextFlags_delegFlag,
1939       { "delegFlag", "spnego.delegFlag",
1940         FT_BOOLEAN, 8, NULL, 0x80,
1941         NULL, HFILL }},
1942     { &hf_spnego_ContextFlags_mutualFlag,
1943       { "mutualFlag", "spnego.mutualFlag",
1944         FT_BOOLEAN, 8, NULL, 0x40,
1945         NULL, HFILL }},
1946     { &hf_spnego_ContextFlags_replayFlag,
1947       { "replayFlag", "spnego.replayFlag",
1948         FT_BOOLEAN, 8, NULL, 0x20,
1949         NULL, HFILL }},
1950     { &hf_spnego_ContextFlags_sequenceFlag,
1951       { "sequenceFlag", "spnego.sequenceFlag",
1952         FT_BOOLEAN, 8, NULL, 0x10,
1953         NULL, HFILL }},
1954     { &hf_spnego_ContextFlags_anonFlag,
1955       { "anonFlag", "spnego.anonFlag",
1956         FT_BOOLEAN, 8, NULL, 0x08,
1957         NULL, HFILL }},
1958     { &hf_spnego_ContextFlags_confFlag,
1959       { "confFlag", "spnego.confFlag",
1960         FT_BOOLEAN, 8, NULL, 0x04,
1961         NULL, HFILL }},
1962     { &hf_spnego_ContextFlags_integFlag,
1963       { "integFlag", "spnego.integFlag",
1964         FT_BOOLEAN, 8, NULL, 0x02,
1965         NULL, HFILL }},
1966
1967 /*--- End of included file: packet-spnego-hfarr.c ---*/
1968 #line 1399 "packet-spnego-template.c"
1969         };
1970
1971         /* List of subtrees */
1972         static gint *ett[] = {
1973                 &ett_spnego,
1974                 &ett_spnego_wraptoken,
1975                 &ett_spnego_krb5,
1976                 &ett_spnego_krb5_cfx_flags,
1977
1978
1979 /*--- Included file: packet-spnego-ettarr.c ---*/
1980 #line 1 "packet-spnego-ettarr.c"
1981     &ett_spnego_NegotiationToken,
1982     &ett_spnego_MechTypeList,
1983     &ett_spnego_PrincipalSeq,
1984     &ett_spnego_NegTokenInit,
1985     &ett_spnego_ContextFlags,
1986     &ett_spnego_NegTokenTarg,
1987     &ett_spnego_InitialContextToken_U,
1988
1989 /*--- End of included file: packet-spnego-ettarr.c ---*/
1990 #line 1409 "packet-spnego-template.c"
1991         };
1992
1993         /* Register protocol */
1994         proto_spnego = proto_register_protocol(PNAME, PSNAME, PFNAME);
1995
1996         register_dissector("spnego", dissect_spnego, proto_spnego);
1997
1998         proto_spnego_krb5 = proto_register_protocol("SPNEGO-KRB5",
1999                                                     "SPNEGO-KRB5",
2000                                                     "spnego-krb5");
2001
2002         register_dissector("spnego-krb5", dissect_spnego_krb5, proto_spnego_krb5);
2003         new_register_dissector("spnego-krb5-wrap", dissect_spnego_krb5_wrap, proto_spnego_krb5);
2004
2005         /* Register fields and subtrees */
2006         proto_register_field_array(proto_spnego, hf, array_length(hf));
2007         proto_register_subtree_array(ett, array_length(ett));
2008 }
2009
2010
2011 /*--- proto_reg_handoff_spnego ---------------------------------------*/
2012 void proto_reg_handoff_spnego(void) {
2013
2014         dissector_handle_t spnego_handle, spnego_wrap_handle;
2015         dissector_handle_t spnego_krb5_handle, spnego_krb5_wrap_handle;
2016
2017         /* Register protocol with GSS-API module */
2018
2019         spnego_handle = find_dissector("spnego");
2020         spnego_wrap_handle = new_create_dissector_handle(dissect_spnego_wrap,  proto_spnego);
2021         gssapi_init_oid("1.3.6.1.5.5.2", proto_spnego, ett_spnego,
2022             spnego_handle, spnego_wrap_handle,
2023             "SPNEGO - Simple Protected Negotiation");
2024
2025         /* Register both the one MS created and the real one */
2026         /*
2027          * Thanks to Jean-Baptiste Marchand and Richard B Ward, the
2028          * mystery of the MS KRB5 OID is cleared up. It was due to a library
2029          * that did not handle OID components greater than 16 bits, and was
2030          * fixed in Win2K SP2 as well as WinXP.
2031          * See the archive of <ietf-krb-wg@anl.gov> for the thread topic
2032          * SPNEGO implementation issues. 3-Dec-2002.
2033          */
2034         spnego_krb5_handle = find_dissector("spnego-krb5");
2035         spnego_krb5_wrap_handle = find_dissector("spnego-krb5-wrap");
2036         gssapi_init_oid("1.2.840.48018.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
2037                         spnego_krb5_handle, spnego_krb5_wrap_handle,
2038                         "MS KRB5 - Microsoft Kerberos 5");
2039         gssapi_init_oid("1.2.840.113554.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
2040                         spnego_krb5_handle, spnego_krb5_wrap_handle,
2041                         "KRB5 - Kerberos 5");
2042         gssapi_init_oid("1.2.840.113554.1.2.2.3", proto_spnego_krb5, ett_spnego_krb5,
2043                         spnego_krb5_handle, spnego_krb5_wrap_handle,
2044                         "KRB5 - Kerberos 5 - User to User");
2045
2046 }