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