14ba0da06358c4024078ef72d04c4a2558b58a66
[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 . -O ../../epan/dissectors spnego.asn */
5
6 /* Input file: packet-spnego-template.c */
7
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)
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 "../../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;
114
115 /*--- End of included file: packet-spnego-hf.c ---*/
116 #line 82 "../../asn1/spnego/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 "../../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;
140
141 /*--- End of included file: packet-spnego-ett.c ---*/
142 #line 96 "../../asn1/spnego/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 "../../asn1/spnego/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 "../../asn1/spnego/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 "../../asn1/spnego/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 "../../asn1/spnego/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 "../../asn1/spnego/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 "../../asn1/spnego/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 "../../asn1/spnego/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 "../../asn1/spnego/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 "../../asn1/spnego/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 "../../asn1/spnego/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         tvbuff_t *krb5_tvb;
664         gint8 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);
670
671         item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, offset,
672                                    -1, ENC_NA);
673
674         subtree = proto_item_add_subtree(item, ett_spnego_krb5);
675
676         /*
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 }
682          *
683          * However, for some protocols, the KRB5 blob starts at the SHORT
684          * and has no DER encoded header etc.
685          *
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.
689          *
690          * So:
691          *
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.
694          *
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.
698          *
699          *      Otherwise, we show the USHORT, and then dissect the rest
700          *      as a Kerberos message.
701          */
702
703         /*
704          * Get the first header ...
705          */
706         get_ber_identifier(tvb, offset, &class, &pc, &tag);
707         if (class == BER_CLASS_APP && pc) {
708             /*
709              * [APPLICATION <tag>]
710              */
711             offset = dissect_ber_identifier(pinfo, subtree, tvb, offset, &class, &pc, &tag);
712             offset = dissect_ber_length(pinfo, subtree, tvb, offset, &len, &ind);
713
714             switch (tag) {
715
716             case 0:
717                 /*
718                  * [APPLICATION 0]
719                  */
720
721                 /* Next, the OID */
722                 offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, subtree, tvb, offset, hf_spnego_krb5_oid, &oid);
723
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);
727
728                 offset += 2;
729
730                 break;
731
732             case 14:    /* [APPLICATION 14] */
733             case 15:    /* [APPLICATION 15] */
734                 /*
735                  * No token ID - just dissect as a Kerberos message and
736                  * return.
737                  */
738                 dissect_kerberos_main(tvb, pinfo, subtree, FALSE, NULL);
739                 return;
740
741             default:
742                 proto_tree_add_text(subtree, tvb, offset, 0,
743                         "Unknown header (class=%d, pc=%d, tag=%d)",
744                         class, pc, tag);
745                 goto done;
746             }
747         } else {
748             /* Next, the token ID ... */
749
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);
753
754             offset += 2;
755         }
756
757         switch (token_id) {
758
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;
765
766         case KRB_TOKEN_GETMIC:
767           offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
768           break;
769
770         case KRB_TOKEN_WRAP:
771           offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
772           break;
773
774         case KRB_TOKEN_DELETE_SEC_CONTEXT:
775
776           break;
777
778         case KRB_TOKEN_CFX_GETMIC:
779           offset = dissect_spnego_krb5_cfx_getmic_base(tvb, offset, pinfo, subtree);
780           break;
781
782         case KRB_TOKEN_CFX_WRAP:
783           offset = dissect_spnego_krb5_cfx_wrap_base(tvb, offset, pinfo, subtree, token_id);
784           break;
785
786         default:
787
788           break;
789         }
790
791  done:
792         proto_item_set_len(item, offset);
793         return;
794 }
795
796 #ifdef HAVE_KERBEROS
797 #include <epan/crypt/crypt-md5.h>
798
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
806
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)
811 {
812     guint8 k5_data[16];
813     guint8 T[4];
814
815     memset(T, 0, 4);
816
817     if (key_type == KEYTYPE_ARCFOUR_56) {
818         guint8 L40[14] = "fortybits";
819
820         memcpy(L40 + 10, T, sizeof(T));
821         md5_hmac(
822                 L40, 14,
823                 key_data,
824                 key_size,
825                 k5_data);
826         memset(&k5_data[7], 0xAB, 9);
827     } else {
828         md5_hmac(
829                 T, 4,
830                 key_data,
831                 key_size,
832                 k5_data);
833     }
834
835     md5_hmac(
836         cksum_data, cksum_size,
837         k5_data,
838         16,
839         key6_data);
840
841     return 0;
842 }
843
844 static int
845 usage2arcfour(int usage)
846 {
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;
859     }
860 }
861
862 static int
863 arcfour_mic_cksum(guint8 *key_data, int key_length,
864                   unsigned 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)
869 {
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];
877
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, v1, l1);
889     md5_append(&ms, v2, l2);
890     md5_append(&ms, v3, l3);
891     md5_finish(&ms, digest);
892     md5_hmac(digest, 16, ksign_c, 16, cksum);
893
894     memcpy(sgn_cksum, cksum, 8);
895
896     return 0;
897 }
898
899 /*
900  * Verify padding of a gss wrapped message and return its length.
901  */
902 static int
903 gssapi_verify_pad(unsigned char *wrapped_data, int wrapped_length,
904                    size_t datalen,
905                    size_t *padlen)
906 {
907     unsigned char *pad;
908     size_t padlength;
909     int i;
910
911     pad = wrapped_data + wrapped_length - 1;
912     padlength = *pad;
913
914     if (padlength > datalen)
915         return 1;
916
917     for (i = padlength; i > 0 && *pad == padlength; i--, pad--)
918         ;
919     if (i != 0)
920         return 2;
921
922     *padlen = padlength;
923
924     return 0;
925 }
926
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)
932 {
933     guint8 Klocaldata[16];
934     int ret;
935     size_t 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     size_t padlen = 0;
943
944     datalen = tvb_length(pinfo->gssapi_encrypted_tvb);
945
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;
952     }
953
954     if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 6)!=0xffff){
955         return -4;
956     }
957
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;
964     }
965
966     {
967         rc4_state_struct rc4_state;
968
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);
972
973         memset(k6_data, 0, sizeof(k6_data));
974     }
975
976
977     if (SND_SEQ[1] != 0xFFFFFFFF && SND_SEQ[1] != 0x00000000) {
978         return -6;
979     }
980
981     {
982         int i;
983
984         for (i = 0; i < 16; i++)
985             Klocaldata[i] = ((guint8 *)key_value)[i] ^ 0xF0;
986     }
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;
993     }
994
995     if(conf_flag) {
996         rc4_state_struct rc4_state;
997
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);
1008     }
1009     memset(k6_data, 0, sizeof(k6_data));
1010
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;
1016         }
1017         datalen -= padlen;
1018     }
1019
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;
1031         }
1032
1033         cmp = tvb_memeql(pinfo->gssapi_wrap_tvb, 16, cksum_data, 8); /* SGN_CKSUM */
1034         if (cmp) {
1035             return -11;
1036         }
1037     }
1038
1039     return datalen;
1040 }
1041
1042
1043
1044 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1045
1046 static void
1047 decrypt_gssapi_krb_arcfour_wrap(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int keytype)
1048 {
1049         int ret;
1050         enc_key_t *ek;
1051         int length;
1052         const guint8 *original_data;
1053
1054         static int omb_index=0;
1055         static guint8 *omb_arr[4]={NULL,NULL,NULL,NULL};
1056         static guint8 *cryptocopy=NULL; /* workaround for pre-0.6.1 heimdal bug */
1057         guint8 *output_message_buffer;
1058
1059         omb_index++;
1060         if(omb_index>=4){
1061                 omb_index=0;
1062         }
1063         output_message_buffer=omb_arr[omb_index];
1064
1065
1066         length=tvb_length(pinfo->gssapi_encrypted_tvb);
1067         original_data=tvb_get_ptr(pinfo->gssapi_encrypted_tvb, 0, length);
1068
1069         /* dont do anything if we are not attempting to decrypt data */
1070 /*
1071         if(!krb_decrypt){
1072                 return;
1073         }
1074 */
1075         /* XXX we should only do this for first time, then store somewhere */
1076         /* XXX We also need to re-read the keytab when the preference changes */
1077
1078         cryptocopy=ep_alloc(length);
1079         if(output_message_buffer){
1080                 g_free(output_message_buffer);
1081                 output_message_buffer=NULL;
1082         }
1083         output_message_buffer=g_malloc(length);
1084
1085         for(ek=enc_key_list;ek;ek=ek->next){
1086                 /* shortcircuit and bail out if enctypes are not matching */
1087                 if(ek->keytype!=keytype){
1088                         continue;
1089                 }
1090
1091                 /* pre-0.6.1 versions of Heimdal would sometimes change
1092                   the cryptotext data even when the decryption failed.
1093                   This would obviously not work since we iterate over the
1094                   keys. So just give it a copy of the crypto data instead.
1095                   This has been seen for RC4-HMAC blobs.
1096                 */
1097                 memcpy(cryptocopy, original_data, length);
1098                 ret=decrypt_arcfour(pinfo,
1099                                 cryptocopy,
1100                                 output_message_buffer,
1101                                 ek->keyvalue,
1102                                 ek->keylength,
1103                                 ek->keytype
1104                                             );
1105                 if (ret >= 0) {
1106                         proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
1107                         pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(tvb,
1108                                 output_message_buffer,
1109                                 ret, ret);
1110                         tvb_set_free_cb(pinfo->gssapi_decrypted_tvb, g_free);
1111                         add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
1112                         return;
1113                 }
1114         }
1115         return;
1116 }
1117
1118 /* borrowed from heimdal */
1119 static int
1120 rrc_rotate(void *data, int len, guint16 rrc, int unrotate)
1121 {
1122         unsigned char *tmp, buf[256];
1123         size_t left;
1124
1125         if (len == 0)
1126                 return 0;
1127
1128         rrc %= len;
1129
1130         if (rrc == 0)
1131                 return 0;
1132
1133         left = len - rrc;
1134
1135         if (rrc <= sizeof(buf)) {
1136                 tmp = buf;
1137         } else {
1138                 tmp = g_malloc(rrc);
1139                 if (tmp == NULL)
1140                         return -1;
1141         }
1142
1143         if (unrotate) {
1144                 memcpy(tmp, data, rrc);
1145                 memmove(data, (unsigned char *)data + rrc, left);
1146                 memcpy((unsigned char *)data + left, tmp, rrc);
1147         } else {
1148                 memcpy(tmp, (unsigned char *)data + left, rrc);
1149                 memmove((unsigned char *)data + rrc, data, left);
1150                 memcpy(data, tmp, rrc);
1151         }
1152
1153         if (rrc > sizeof(buf))
1154                 g_free(tmp);
1155
1156         return 0;
1157 }
1158
1159
1160 #define KRB5_KU_USAGE_ACCEPTOR_SEAL     22
1161 #define KRB5_KU_USAGE_ACCEPTOR_SIGN     23
1162 #define KRB5_KU_USAGE_INITIATOR_SEAL    24
1163 #define KRB5_KU_USAGE_INITIATOR_SIGN    25
1164
1165 static void
1166 decrypt_gssapi_krb_cfx_wrap(proto_tree *tree _U_,
1167                             packet_info *pinfo,
1168                             tvbuff_t *checksum_tvb,
1169                             tvbuff_t *encrypted_tvb,
1170                             guint16 ec,
1171                             guint16 rrc,
1172                             gboolean is_dce,
1173                             int keytype,
1174                             unsigned int usage)
1175 {
1176         guint8 *rotated;
1177         guint8 *output;
1178         int datalen;
1179         tvbuff_t *next_tvb;
1180
1181         /* dont do anything if we are not attempting to decrypt data */
1182         if(!krb_decrypt){
1183                 return;
1184         }
1185
1186         datalen = tvb_length(checksum_tvb) + tvb_length(encrypted_tvb);
1187
1188         rotated = g_malloc(datalen);
1189
1190         tvb_memcpy(checksum_tvb, rotated,
1191                    0, tvb_length(checksum_tvb));
1192         tvb_memcpy(encrypted_tvb, rotated + tvb_length(checksum_tvb),
1193                    0, tvb_length(encrypted_tvb));
1194
1195         if (is_dce) {
1196                 rrc += ec;
1197         }
1198
1199         rrc_rotate(rotated, datalen, rrc, TRUE);
1200
1201         next_tvb=tvb_new_child_real_data(encrypted_tvb, rotated,
1202                                          datalen, datalen);
1203         tvb_set_free_cb(next_tvb, g_free);
1204         add_new_data_source(pinfo, next_tvb, "GSSAPI CFX");
1205
1206         output = decrypt_krb5_data(tree, pinfo, usage, next_tvb,
1207                   keytype, &datalen);
1208
1209         if (output) {
1210                 guint8 *outdata;
1211
1212                 outdata = g_memdup(output, tvb_length(encrypted_tvb));
1213                 g_free(output);
1214
1215                 pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(encrypted_tvb,
1216                         outdata,
1217                         tvb_length(encrypted_tvb),
1218                         tvb_length(encrypted_tvb));
1219                 add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
1220                 tvb_set_free_cb(pinfo->gssapi_decrypted_tvb, g_free);
1221                 return;
1222         }
1223         return;
1224 }
1225
1226 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1227
1228
1229 #endif
1230
1231 /*
1232  * This is for GSSAPI Wrap tokens ...
1233  */
1234 static int
1235 dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
1236 #ifndef HAVE_KERBEROS
1237         _U_
1238 #endif
1239     , proto_tree *tree, guint16 token_id
1240 #ifndef HAVE_KERBEROS
1241         _U_
1242 #endif
1243     )
1244 {
1245         guint16 sgn_alg, seal_alg;
1246 #ifdef HAVE_KERBEROS
1247         int start_offset=offset;
1248 #endif
1249
1250         /*
1251          * The KRB5 blob conforms to RFC1964:
1252          *   USHORT (0x0102 == GSS_Wrap)
1253          *   and so on }
1254          */
1255
1256         /* Now, the sign and seal algorithms ... */
1257
1258         sgn_alg = tvb_get_letohs(tvb, offset);
1259         proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
1260                             sgn_alg);
1261
1262         offset += 2;
1263
1264         seal_alg = tvb_get_letohs(tvb, offset);
1265         proto_tree_add_uint(tree, hf_spnego_krb5_seal_alg, tvb, offset, 2,
1266                             seal_alg);
1267
1268         offset += 2;
1269
1270         /* Skip the filler */
1271
1272         offset += 2;
1273
1274         /* Encrypted sequence number */
1275
1276         proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
1277                             ENC_NA);
1278
1279         offset += 8;
1280
1281         /* Checksum of plaintext padded data */
1282
1283         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
1284                             ENC_NA);
1285
1286         offset += 8;
1287
1288         /*
1289          * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
1290          * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
1291          * extra 8 bytes of "Random confounder" after the checksum.
1292          * It certainly confounds code expecting all Kerberos 5
1293          * GSS_Wrap() tokens to look the same....
1294          */
1295         if ((sgn_alg == KRB_SGN_ALG_HMAC) ||
1296             /* there also seems to be a confounder for DES MAC MD5 - certainly seen when using with
1297                SASL with LDAP between a Java client and Active Directory. If this breaks other things
1298                we may need to make this an option. gal 17/2/06 */
1299             (sgn_alg == KRB_SGN_ALG_DES_MAC_MD5)) {
1300           proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
1301                               ENC_NA);
1302           offset += 8;
1303         }
1304
1305         /* Is the data encrypted? */
1306         pinfo->gssapi_data_encrypted=(seal_alg!=KRB_SEAL_ALG_NONE);
1307
1308 #ifdef HAVE_KERBEROS
1309 #define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
1310         if(pinfo->decrypt_gssapi_tvb){
1311                 /* if the caller did not provide a tvb, then we just use
1312                    whatever is left of our current tvb.
1313                 */
1314                 if(!pinfo->gssapi_encrypted_tvb){
1315                         int len;
1316                         len=tvb_reported_length_remaining(tvb,offset);
1317                         if(len>tvb_length_remaining(tvb, offset)){
1318                                 /* no point in trying to decrypt,
1319                                    we dont have the full pdu.
1320                                 */
1321                                 return offset;
1322                         }
1323                         pinfo->gssapi_encrypted_tvb = tvb_new_subset(
1324                                         tvb, offset, len, len);
1325                 }
1326
1327                 /* if this is KRB5 wrapped rc4-hmac */
1328                 if((token_id==KRB_TOKEN_WRAP)
1329                  &&(sgn_alg==KRB_SGN_ALG_HMAC)
1330                  &&(seal_alg==KRB_SEAL_ALG_RC4)){
1331                         /* do we need to create a tvb for the wrapper
1332                            as well ?
1333                         */
1334                         if(!pinfo->gssapi_wrap_tvb){
1335                                 pinfo->gssapi_wrap_tvb = tvb_new_subset(
1336                                         tvb, start_offset-2,
1337                                         GSS_ARCFOUR_WRAP_TOKEN_SIZE,
1338                                         GSS_ARCFOUR_WRAP_TOKEN_SIZE);
1339                         }
1340 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1341                         decrypt_gssapi_krb_arcfour_wrap(tree,
1342                                 pinfo,
1343                                 tvb,
1344                                 23 /* rc4-hmac */);
1345 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1346                 }
1347         }
1348 #endif
1349         /*
1350          * Return the offset past the checksum, so that we know where
1351          * the data we're wrapped around starts.  Also, set the length
1352          * of our top-level item to that offset, so it doesn't cover
1353          * the data we're wrapped around.
1354          *
1355          * Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
1356          * not before.
1357          */
1358         return offset;
1359 }
1360
1361 /*
1362  * XXX - This is for GSSAPI GetMIC tokens ...
1363  */
1364 static int
1365 dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
1366 {
1367         guint16 sgn_alg;
1368
1369         /*
1370          * The KRB5 blob conforms to RFC1964:
1371          *   USHORT (0x0101 == GSS_GetMIC)
1372          *   and so on }
1373          */
1374
1375         /* Now, the sign algorithm ... */
1376
1377         sgn_alg = tvb_get_letohs(tvb, offset);
1378         proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
1379                             sgn_alg);
1380
1381         offset += 2;
1382
1383         /* Skip the filler */
1384
1385         offset += 4;
1386
1387         /* Encrypted sequence number */
1388
1389         proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
1390                             ENC_NA);
1391
1392         offset += 8;
1393
1394         /* Checksum of plaintext padded data */
1395
1396         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
1397                             ENC_NA);
1398
1399         offset += 8;
1400
1401         /*
1402          * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
1403          * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
1404          * extra 8 bytes of "Random confounder" after the checksum.
1405          * It certainly confounds code expecting all Kerberos 5
1406          * GSS_Wrap() tokens to look the same....
1407          *
1408          * The exception is DNS/TSIG where there is no such confounder
1409          * so we need to test here if there are more bytes in our tvb or not.
1410          *  -- ronnie
1411          */
1412         if (tvb_length_remaining(tvb, offset)) {
1413           if (sgn_alg == KRB_SGN_ALG_HMAC) {
1414             proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
1415                               ENC_NA);
1416
1417             offset += 8;
1418           }
1419         }
1420
1421         /*
1422          * Return the offset past the checksum, so that we know where
1423          * the data we're wrapped around starts.  Also, set the length
1424          * of our top-level item to that offset, so it doesn't cover
1425          * the data we're wrapped around.
1426          */
1427
1428         return offset;
1429 }
1430
1431 static int
1432 dissect_spnego_krb5_cfx_flags(tvbuff_t *tvb, int offset,
1433                               proto_tree *spnego_krb5_tree,
1434                               guint8 cfx_flags)
1435 {
1436         proto_tree *cfx_flags_tree = NULL;
1437         proto_item *tf = NULL;
1438
1439         if (spnego_krb5_tree) {
1440                 tf = proto_tree_add_uint(spnego_krb5_tree,
1441                                          hf_spnego_krb5_cfx_flags,
1442                                          tvb, offset, 1, cfx_flags);
1443                 cfx_flags_tree = proto_item_add_subtree(tf, ett_spnego_krb5_cfx_flags);
1444         }
1445
1446         proto_tree_add_boolean(cfx_flags_tree,
1447                                hf_spnego_krb5_cfx_flags_04,
1448                                tvb, offset, 1, cfx_flags);
1449         proto_tree_add_boolean(cfx_flags_tree,
1450                                hf_spnego_krb5_cfx_flags_02,
1451                                tvb, offset, 1, cfx_flags);
1452         proto_tree_add_boolean(cfx_flags_tree,
1453                                hf_spnego_krb5_cfx_flags_01,
1454                                tvb, offset, 1, cfx_flags);
1455
1456         return (offset + 1);
1457 }
1458
1459 /*
1460  * This is for GSSAPI CFX Wrap tokens ...
1461  */
1462 static int
1463 dissect_spnego_krb5_cfx_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
1464 #ifndef HAVE_KERBEROS
1465         _U_
1466 #endif
1467     , proto_tree *tree, guint16 token_id _U_
1468     )
1469 {
1470         guint8 flags;
1471         guint16 ec;
1472 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1473         guint16 rrc;
1474 #endif
1475         int checksum_size;
1476         int start_offset=offset;
1477
1478         /*
1479          * The KRB5 blob conforms to RFC4121:
1480          *   USHORT (0x0504)
1481          *   and so on }
1482          */
1483
1484         /* Now, the sign and seal algorithms ... */
1485
1486         flags = tvb_get_guint8(tvb, offset);
1487         offset = dissect_spnego_krb5_cfx_flags(tvb, offset, tree, flags);
1488
1489         pinfo->gssapi_data_encrypted=(flags & 2);
1490
1491         /* Skip the filler */
1492
1493         proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 1,
1494                             ENC_NA);
1495         offset += 1;
1496
1497         /* EC */
1498         ec = tvb_get_ntohs(tvb, offset);
1499         proto_tree_add_item(tree, hf_spnego_krb5_cfx_ec, tvb, offset, 2,
1500                             ENC_BIG_ENDIAN);
1501         offset += 2;
1502
1503         /* RRC */
1504 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1505         rrc = tvb_get_ntohs(tvb, offset);
1506 #endif
1507         proto_tree_add_item(tree, hf_spnego_krb5_cfx_rrc, tvb, offset, 2,
1508                             ENC_BIG_ENDIAN);
1509         offset += 2;
1510
1511         /* sequence number */
1512
1513         proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
1514                             ENC_BIG_ENDIAN);
1515         offset += 8;
1516
1517         /* Checksum of plaintext padded data */
1518
1519         if (pinfo->gssapi_data_encrypted) {
1520                 checksum_size = 44 + ec;
1521         } else {
1522                 checksum_size = 12;
1523         }
1524
1525         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
1526                             checksum_size, ENC_NA);
1527         offset += checksum_size;
1528
1529         if(pinfo->decrypt_gssapi_tvb){
1530                 /* if the caller did not provide a tvb, then we just use
1531                    whatever is left of our current tvb.
1532                 */
1533                 if(!pinfo->gssapi_encrypted_tvb){
1534                         int len;
1535                         len=tvb_reported_length_remaining(tvb,offset);
1536                         if(len>tvb_length_remaining(tvb, offset)){
1537                                 /* no point in trying to decrypt,
1538                                    we dont have the full pdu.
1539                                 */
1540                                 return offset;
1541                         }
1542                         pinfo->gssapi_encrypted_tvb = tvb_new_subset(
1543                                         tvb, offset, len, len);
1544                 }
1545
1546                 if (pinfo->gssapi_data_encrypted) {
1547                         /* do we need to create a tvb for the wrapper
1548                            as well ?
1549                         */
1550                         if(!pinfo->gssapi_wrap_tvb){
1551                                 pinfo->gssapi_wrap_tvb = tvb_new_subset(
1552                                         tvb, start_offset-2,
1553                                         offset - (start_offset-2),
1554                                         offset - (start_offset-2));
1555                         }
1556                 }
1557         }
1558
1559 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1560 {
1561         tvbuff_t *checksum_tvb = tvb_new_subset(tvb, 16, checksum_size, checksum_size);
1562
1563         if (pinfo->gssapi_data_encrypted) {
1564                 if(pinfo->gssapi_encrypted_tvb){
1565                         decrypt_gssapi_krb_cfx_wrap(tree,
1566                                 pinfo,
1567                                 checksum_tvb,
1568                                 pinfo->gssapi_encrypted_tvb,
1569                                 ec,
1570                                 rrc,
1571                                 (pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_DCE)?TRUE:FALSE,
1572                                 -1,
1573                                 (flags & 0x0001)?
1574                                 KRB5_KU_USAGE_ACCEPTOR_SEAL:
1575                                 KRB5_KU_USAGE_INITIATOR_SEAL);
1576                 }
1577         }
1578 }
1579 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1580
1581         /*
1582          * Return the offset past the checksum, so that we know where
1583          * the data we're wrapped around starts.  Also, set the length
1584          * of our top-level item to that offset, so it doesn't cover
1585          * the data we're wrapped around.
1586          *
1587          * Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
1588          * not before.
1589          */
1590         return offset;
1591 }
1592
1593 /*
1594  * XXX - This is for GSSAPI CFX GetMIC tokens ...
1595  */
1596 static int
1597 dissect_spnego_krb5_cfx_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
1598 {
1599         guint8 flags;
1600         int checksum_size;
1601
1602         /*
1603          * The KRB5 blob conforms to RFC4121:
1604          *   USHORT (0x0404 == GSS_GetMIC)
1605          *   and so on }
1606          */
1607
1608         flags = tvb_get_guint8(tvb, offset);
1609         offset = dissect_spnego_krb5_cfx_flags(tvb, offset, tree, flags);
1610
1611         /* Skip the filler */
1612
1613         proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 5,
1614                             ENC_NA);
1615         offset += 5;
1616
1617         /* sequence number */
1618
1619         proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
1620                             ENC_BIG_ENDIAN);
1621         offset += 8;
1622
1623         /* Checksum of plaintext padded data */
1624
1625         checksum_size = tvb_length_remaining(tvb, offset);
1626
1627         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
1628                             checksum_size, ENC_NA);
1629         offset += checksum_size;
1630
1631         /*
1632          * Return the offset past the checksum, so that we know where
1633          * the data we're wrapped around starts.  Also, set the length
1634          * of our top-level item to that offset, so it doesn't cover
1635          * the data we're wrapped around.
1636          */
1637
1638         return offset;
1639 }
1640
1641 /*
1642  * XXX - is this for SPNEGO or just GSS-API?
1643  * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
1644  * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
1645  * than designating SPNEGO as the mechanism, offering Kerberos V5, and
1646  * getting it accepted.
1647  */
1648 static int
1649 dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1650 {
1651         proto_item *item;
1652         proto_tree *subtree;
1653         int offset = 0;
1654         guint16 token_id;
1655
1656         item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, 0, -1, ENC_NA);
1657
1658         subtree = proto_item_add_subtree(item, ett_spnego_krb5);
1659
1660         /*
1661          * The KRB5 blob conforms to RFC1964:
1662          *   USHORT (0x0102 == GSS_Wrap)
1663          *   and so on }
1664          */
1665
1666         /* First, the token ID ... */
1667
1668         token_id = tvb_get_letohs(tvb, offset);
1669         proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
1670                             token_id);
1671
1672         offset += 2;
1673
1674         switch (token_id) {
1675         case KRB_TOKEN_GETMIC:
1676           offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
1677           break;
1678
1679         case KRB_TOKEN_WRAP:
1680           offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
1681           break;
1682
1683         case KRB_TOKEN_CFX_GETMIC:
1684           offset = dissect_spnego_krb5_cfx_getmic_base(tvb, offset, pinfo, subtree);
1685           break;
1686
1687         case KRB_TOKEN_CFX_WRAP:
1688           offset = dissect_spnego_krb5_cfx_wrap_base(tvb, offset, pinfo, subtree, token_id);
1689           break;
1690
1691         default:
1692
1693           break;
1694         }
1695
1696         /*
1697          * Return the offset past the checksum, so that we know where
1698          * the data we're wrapped around starts.  Also, set the length
1699          * of our top-level item to that offset, so it doesn't cover
1700          * the data we're wrapped around.
1701          */
1702         proto_item_set_len(item, offset);
1703         return offset;
1704 }
1705
1706 /* Spnego stuff from here */
1707
1708 static int
1709 dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1710 {
1711         proto_item *item;
1712         proto_tree *subtree;
1713         int offset = 0;
1714         asn1_ctx_t asn1_ctx;
1715         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1716
1717         MechType_oid = NULL;
1718
1719         /*
1720          * We need this later, so lets get it now ...
1721          * It has to be per-frame as there can be more than one GSS-API
1722          * negotiation in a conversation.
1723          */
1724
1725
1726         item = proto_tree_add_item(tree, proto_spnego, tvb, offset,
1727                                    -1, ENC_NA);
1728
1729         subtree = proto_item_add_subtree(item, ett_spnego);
1730         /*
1731          * The TVB contains a [0] header and a sequence that consists of an
1732          * object ID and a blob containing the data ...
1733          * XXX - is this RFC 2743's "Mechanism-Independent Token Format",
1734          * with the "optional" "use in non-initial tokens" being chosen.
1735          * ASN1 code addet to spnego.asn to handle this.
1736          */
1737
1738         offset = dissect_spnego_InitialContextToken(FALSE, tvb, offset, &asn1_ctx , subtree, -1);
1739
1740         return offset;
1741 }
1742
1743
1744 static void
1745 dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
1746 {
1747         proto_item *item;
1748         proto_tree *subtree;
1749         int offset = 0;
1750         conversation_t *conversation;
1751         asn1_ctx_t asn1_ctx;
1752         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1753
1754         /*
1755          * We need this later, so lets get it now ...
1756          * It has to be per-frame as there can be more than one GSS-API
1757          * negotiation in a conversation.
1758          */
1759         next_level_value = p_get_proto_data(pinfo->fd, proto_spnego);
1760         if (!next_level_value && !pinfo->fd->flags.visited) {
1761             /*
1762              * No handle attached to this frame, but it's the first
1763              * pass, so it'd be attached to the conversation.
1764              * If we have a conversation, try to get the handle,
1765              * and if we get one, attach it to the frame.
1766              */
1767             conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1768                                              pinfo->ptype, pinfo->srcport,
1769                                              pinfo->destport, 0);
1770
1771             if (conversation) {
1772                 next_level_value = conversation_get_proto_data(conversation,
1773                                                                proto_spnego);
1774                 if (next_level_value)
1775                     p_add_proto_data(pinfo->fd, proto_spnego, next_level_value);
1776             }
1777         }
1778
1779         item = proto_tree_add_item(parent_tree, proto_spnego, tvb, offset,
1780                                    -1, ENC_NA);
1781
1782         subtree = proto_item_add_subtree(item, ett_spnego);
1783
1784         /*
1785          * The TVB contains a [0] header and a sequence that consists of an
1786          * object ID and a blob containing the data ...
1787          * Actually, it contains, according to RFC2478:
1788          * NegotiationToken ::= CHOICE {
1789          *          negTokenInit [0] NegTokenInit,
1790          *          negTokenTarg [1] NegTokenTarg }
1791          * NegTokenInit ::= SEQUENCE {
1792          *          mechTypes [0] MechTypeList OPTIONAL,
1793          *          reqFlags [1] ContextFlags OPTIONAL,
1794          *          mechToken [2] OCTET STRING OPTIONAL,
1795          *          mechListMIC [3] OCTET STRING OPTIONAL }
1796          * NegTokenTarg ::= SEQUENCE {
1797          *          negResult [0] ENUMERATED {
1798          *              accept_completed (0),
1799          *              accept_incomplete (1),
1800          *              reject (2) } OPTIONAL,
1801          *          supportedMech [1] MechType OPTIONAL,
1802          *          responseToken [2] OCTET STRING OPTIONAL,
1803          *          mechListMIC [3] OCTET STRING OPTIONAL }
1804          *
1805          * Windows typically includes mechTypes and mechListMic ('NONE'
1806          * in the case of NTLMSSP only).
1807          * It seems to duplicate the responseToken into the mechListMic field
1808          * as well. Naughty, naughty.
1809          *
1810          */
1811         offset = dissect_spnego_NegotiationToken(FALSE, tvb, offset, &asn1_ctx, subtree, -1);
1812
1813 }
1814
1815 /*--- proto_register_spnego -------------------------------------------*/
1816 void proto_register_spnego(void) {
1817
1818         /* List of fields */
1819         static hf_register_info hf[] = {
1820                 { &hf_spnego_wraptoken,
1821                   { "wrapToken", "spnego.wraptoken",
1822                     FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO wrapToken",
1823                     HFILL}},
1824                 { &hf_spnego_krb5,
1825                   { "krb5_blob", "spnego.krb5.blob", FT_BYTES,
1826                     BASE_NONE, NULL, 0, NULL, HFILL }},
1827                 { &hf_spnego_krb5_oid,
1828                   { "KRB5 OID", "spnego.krb5_oid", FT_STRING,
1829                     BASE_NONE, NULL, 0, NULL, HFILL }},
1830                 { &hf_spnego_krb5_tok_id,
1831                   { "krb5_tok_id", "spnego.krb5.tok_id", FT_UINT16, BASE_HEX,
1832                     VALS(spnego_krb5_tok_id_vals), 0, "KRB5 Token Id", HFILL}},
1833                 { &hf_spnego_krb5_sgn_alg,
1834                   { "krb5_sgn_alg", "spnego.krb5.sgn_alg", FT_UINT16, BASE_HEX,
1835                     VALS(spnego_krb5_sgn_alg_vals), 0, "KRB5 Signing Algorithm", HFILL}},
1836                 { &hf_spnego_krb5_seal_alg,
1837                   { "krb5_seal_alg", "spnego.krb5.seal_alg", FT_UINT16, BASE_HEX,
1838                     VALS(spnego_krb5_seal_alg_vals), 0, "KRB5 Sealing Algorithm", HFILL}},
1839                 { &hf_spnego_krb5_snd_seq,
1840                   { "krb5_snd_seq", "spnego.krb5.snd_seq", FT_BYTES, BASE_NONE,
1841                     NULL, 0, "KRB5 Encrypted Sequence Number", HFILL}},
1842                 { &hf_spnego_krb5_sgn_cksum,
1843                   { "krb5_sgn_cksum", "spnego.krb5.sgn_cksum", FT_BYTES, BASE_NONE,
1844                     NULL, 0, "KRB5 Data Checksum", HFILL}},
1845                 { &hf_spnego_krb5_confounder,
1846                   { "krb5_confounder", "spnego.krb5.confounder", FT_BYTES, BASE_NONE,
1847                     NULL, 0, "KRB5 Confounder", HFILL}},
1848                 { &hf_spnego_krb5_filler,
1849                   { "krb5_filler", "spnego.krb5.filler", FT_BYTES, BASE_NONE,
1850                     NULL, 0, "KRB5 Filler", HFILL}},
1851                 { &hf_spnego_krb5_cfx_flags,
1852                   { "krb5_cfx_flags", "spnego.krb5.cfx_flags", FT_UINT8, BASE_HEX,
1853                     NULL, 0, "KRB5 CFX Flags", HFILL}},
1854                 { &hf_spnego_krb5_cfx_flags_01,
1855                   { "SendByAcceptor", "spnego.krb5.send_by_acceptor", FT_BOOLEAN, 8,
1856                     TFS (&tfs_set_notset), 0x01, NULL, HFILL}},
1857                 { &hf_spnego_krb5_cfx_flags_02,
1858                   { "Sealed", "spnego.krb5.sealed", FT_BOOLEAN, 8,
1859                     TFS (&tfs_set_notset), 0x02, NULL, HFILL}},
1860                 { &hf_spnego_krb5_cfx_flags_04,
1861                   { "AcceptorSubkey", "spnego.krb5.acceptor_subkey", FT_BOOLEAN, 8,
1862                     TFS (&tfs_set_notset), 0x04, NULL, HFILL}},
1863                 { &hf_spnego_krb5_cfx_ec,
1864                   { "krb5_cfx_ec", "spnego.krb5.cfx_ec", FT_UINT16, BASE_DEC,
1865                     NULL, 0, "KRB5 CFX Extra Count", HFILL}},
1866                 { &hf_spnego_krb5_cfx_rrc,
1867                   { "krb5_cfx_rrc", "spnego.krb5.cfx_rrc", FT_UINT16, BASE_DEC,
1868                     NULL, 0, "KRB5 CFX Right Rotation Count", HFILL}},
1869                 { &hf_spnego_krb5_cfx_seq,
1870                   { "krb5_cfx_seq", "spnego.krb5.cfx_seq", FT_UINT64, BASE_DEC,
1871                     NULL, 0, "KRB5 Sequence Number", HFILL}},
1872
1873
1874 /*--- Included file: packet-spnego-hfarr.c ---*/
1875 #line 1 "../../asn1/spnego/packet-spnego-hfarr.c"
1876     { &hf_spnego_negTokenInit,
1877       { "negTokenInit", "spnego.negTokenInit",
1878         FT_NONE, BASE_NONE, NULL, 0,
1879         NULL, HFILL }},
1880     { &hf_spnego_negTokenTarg,
1881       { "negTokenTarg", "spnego.negTokenTarg",
1882         FT_NONE, BASE_NONE, NULL, 0,
1883         NULL, HFILL }},
1884     { &hf_spnego_MechTypeList_item,
1885       { "MechType", "spnego.MechType",
1886         FT_OID, BASE_NONE, NULL, 0,
1887         NULL, HFILL }},
1888     { &hf_spnego_principal,
1889       { "principal", "spnego.principal",
1890         FT_STRING, BASE_NONE, NULL, 0,
1891         "GeneralString", HFILL }},
1892     { &hf_spnego_mechTypes,
1893       { "mechTypes", "spnego.mechTypes",
1894         FT_UINT32, BASE_DEC, NULL, 0,
1895         "MechTypeList", HFILL }},
1896     { &hf_spnego_reqFlags,
1897       { "reqFlags", "spnego.reqFlags",
1898         FT_BYTES, BASE_NONE, NULL, 0,
1899         "ContextFlags", HFILL }},
1900     { &hf_spnego_mechToken,
1901       { "mechToken", "spnego.mechToken",
1902         FT_BYTES, BASE_NONE, NULL, 0,
1903         NULL, HFILL }},
1904     { &hf_spnego_negTokenInit_mechListMIC,
1905       { "mechListMIC", "spnego.mechListMIC",
1906         FT_BYTES, BASE_NONE, NULL, 0,
1907         "T_NegTokenInit_mechListMIC", HFILL }},
1908     { &hf_spnego_negResult,
1909       { "negResult", "spnego.negResult",
1910         FT_UINT32, BASE_DEC, VALS(spnego_T_negResult_vals), 0,
1911         NULL, HFILL }},
1912     { &hf_spnego_supportedMech,
1913       { "supportedMech", "spnego.supportedMech",
1914         FT_OID, BASE_NONE, NULL, 0,
1915         NULL, HFILL }},
1916     { &hf_spnego_responseToken,
1917       { "responseToken", "spnego.responseToken",
1918         FT_BYTES, BASE_NONE, NULL, 0,
1919         NULL, HFILL }},
1920     { &hf_spnego_mechListMIC,
1921       { "mechListMIC", "spnego.mechListMIC",
1922         FT_BYTES, BASE_NONE, NULL, 0,
1923         NULL, HFILL }},
1924     { &hf_spnego_thisMech,
1925       { "thisMech", "spnego.thisMech",
1926         FT_OID, BASE_NONE, NULL, 0,
1927         "MechType", HFILL }},
1928     { &hf_spnego_innerContextToken,
1929       { "innerContextToken", "spnego.innerContextToken",
1930         FT_NONE, BASE_NONE, NULL, 0,
1931         NULL, HFILL }},
1932     { &hf_spnego_ContextFlags_delegFlag,
1933       { "delegFlag", "spnego.delegFlag",
1934         FT_BOOLEAN, 8, NULL, 0x80,
1935         NULL, HFILL }},
1936     { &hf_spnego_ContextFlags_mutualFlag,
1937       { "mutualFlag", "spnego.mutualFlag",
1938         FT_BOOLEAN, 8, NULL, 0x40,
1939         NULL, HFILL }},
1940     { &hf_spnego_ContextFlags_replayFlag,
1941       { "replayFlag", "spnego.replayFlag",
1942         FT_BOOLEAN, 8, NULL, 0x20,
1943         NULL, HFILL }},
1944     { &hf_spnego_ContextFlags_sequenceFlag,
1945       { "sequenceFlag", "spnego.sequenceFlag",
1946         FT_BOOLEAN, 8, NULL, 0x10,
1947         NULL, HFILL }},
1948     { &hf_spnego_ContextFlags_anonFlag,
1949       { "anonFlag", "spnego.anonFlag",
1950         FT_BOOLEAN, 8, NULL, 0x08,
1951         NULL, HFILL }},
1952     { &hf_spnego_ContextFlags_confFlag,
1953       { "confFlag", "spnego.confFlag",
1954         FT_BOOLEAN, 8, NULL, 0x04,
1955         NULL, HFILL }},
1956     { &hf_spnego_ContextFlags_integFlag,
1957       { "integFlag", "spnego.integFlag",
1958         FT_BOOLEAN, 8, NULL, 0x02,
1959         NULL, HFILL }},
1960
1961 /*--- End of included file: packet-spnego-hfarr.c ---*/
1962 #line 1393 "../../asn1/spnego/packet-spnego-template.c"
1963         };
1964
1965         /* List of subtrees */
1966         static gint *ett[] = {
1967                 &ett_spnego,
1968                 &ett_spnego_wraptoken,
1969                 &ett_spnego_krb5,
1970                 &ett_spnego_krb5_cfx_flags,
1971
1972
1973 /*--- Included file: packet-spnego-ettarr.c ---*/
1974 #line 1 "../../asn1/spnego/packet-spnego-ettarr.c"
1975     &ett_spnego_NegotiationToken,
1976     &ett_spnego_MechTypeList,
1977     &ett_spnego_PrincipalSeq,
1978     &ett_spnego_NegTokenInit,
1979     &ett_spnego_ContextFlags,
1980     &ett_spnego_NegTokenTarg,
1981     &ett_spnego_InitialContextToken_U,
1982
1983 /*--- End of included file: packet-spnego-ettarr.c ---*/
1984 #line 1403 "../../asn1/spnego/packet-spnego-template.c"
1985         };
1986
1987         /* Register protocol */
1988         proto_spnego = proto_register_protocol(PNAME, PSNAME, PFNAME);
1989
1990         register_dissector("spnego", dissect_spnego, proto_spnego);
1991
1992         proto_spnego_krb5 = proto_register_protocol("SPNEGO-KRB5",
1993                                                     "SPNEGO-KRB5",
1994                                                     "spnego-krb5");
1995
1996         register_dissector("spnego-krb5", dissect_spnego_krb5, proto_spnego_krb5);
1997         new_register_dissector("spnego-krb5-wrap", dissect_spnego_krb5_wrap, proto_spnego_krb5);
1998
1999         /* Register fields and subtrees */
2000         proto_register_field_array(proto_spnego, hf, array_length(hf));
2001         proto_register_subtree_array(ett, array_length(ett));
2002 }
2003
2004
2005 /*--- proto_reg_handoff_spnego ---------------------------------------*/
2006 void proto_reg_handoff_spnego(void) {
2007
2008         dissector_handle_t spnego_handle, spnego_wrap_handle;
2009         dissector_handle_t spnego_krb5_handle, spnego_krb5_wrap_handle;
2010
2011         /* Register protocol with GSS-API module */
2012
2013         spnego_handle = find_dissector("spnego");
2014         spnego_wrap_handle = new_create_dissector_handle(dissect_spnego_wrap,  proto_spnego);
2015         gssapi_init_oid("1.3.6.1.5.5.2", proto_spnego, ett_spnego,
2016             spnego_handle, spnego_wrap_handle,
2017             "SPNEGO - Simple Protected Negotiation");
2018
2019         /* Register both the one MS created and the real one */
2020         /*
2021          * Thanks to Jean-Baptiste Marchand and Richard B Ward, the
2022          * mystery of the MS KRB5 OID is cleared up. It was due to a library
2023          * that did not handle OID components greater than 16 bits, and was
2024          * fixed in Win2K SP2 as well as WinXP.
2025          * See the archive of <ietf-krb-wg@anl.gov> for the thread topic
2026          * SPNEGO implementation issues. 3-Dec-2002.
2027          */
2028         spnego_krb5_handle = find_dissector("spnego-krb5");
2029         spnego_krb5_wrap_handle = find_dissector("spnego-krb5-wrap");
2030         gssapi_init_oid("1.2.840.48018.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
2031                         spnego_krb5_handle, spnego_krb5_wrap_handle,
2032                         "MS KRB5 - Microsoft Kerberos 5");
2033         gssapi_init_oid("1.2.840.113554.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
2034                         spnego_krb5_handle, spnego_krb5_wrap_handle,
2035                         "KRB5 - Kerberos 5");
2036         gssapi_init_oid("1.2.840.113554.1.2.2.3", proto_spnego_krb5, ett_spnego_krb5,
2037                         spnego_krb5_handle, spnego_krb5_wrap_handle,
2038                         "KRB5 - Kerberos 5 - User to User");
2039
2040 }