tvb_child_new_real_data() -> tvb_new_child_real_data()
[metze/wireshark/wip.git] / asn1 / spnego / packet-spnego-template.c
1 /* packet-spnego.c
2  * Routines for the simple and protected GSS-API negotiation mechanism
3  * as described in RFC 2478.
4  * Copyright 2002, Tim Potter <tpot@samba.org>
5  * Copyright 2002, Richard Sharpe <rsharpe@ns.aus.com>
6  * Copyright 2003, Richard Sharpe <rsharpe@richardsharpe.com>
7  * Copyright 2005, Ronnie Sahlberg (krb decryption)
8  * Copyright 2005, Anders Broman (converted to asn2wrs generated dissector)
9  *
10  * $Id$
11  *
12  * Wireshark - Network traffic analyzer
13  * By Gerald Combs <gerald@wireshark.org>
14  * Copyright 1998 Gerald Combs
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
29  */
30 /* The heimdal code for decryption of GSSAPI wrappers using heimdal comes from
31    Heimdal 1.6 and has been modified for wireshark's requirements.
32 */
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <glib.h>
39 #include <epan/packet.h>
40 #include <epan/asn1.h>
41 #include "packet-dcerpc.h"
42 #include "packet-gssapi.h"
43 #include "packet-kerberos.h"
44 #include <epan/crypt/crypt-rc4.h>
45 #include <epan/conversation.h>
46 #include <epan/emem.h>
47 #include <epan/asn1.h>
48
49 #include <stdio.h>
50 #include <string.h>
51
52 #include "packet-ber.h"
53
54
55 #define PNAME  "Simple Protected Negotiation"
56 #define PSNAME "SPNEGO"
57 #define PFNAME "spnego"
58
59 /* Initialize the protocol and registered fields */
60 static int proto_spnego = -1;
61 static int proto_spnego_krb5 = -1;
62
63
64 static int hf_spnego = -1;
65 static int hf_spnego_wraptoken = -1;
66 static int hf_spnego_krb5_oid;
67 static int hf_spnego_krb5 = -1;
68 static int hf_spnego_krb5_tok_id = -1;
69 static int hf_spnego_krb5_sgn_alg = -1;
70 static int hf_spnego_krb5_seal_alg = -1;
71 static int hf_spnego_krb5_snd_seq = -1;
72 static int hf_spnego_krb5_sgn_cksum = -1;
73 static int hf_spnego_krb5_confounder = -1;
74 static int hf_spnego_krb5_filler = -1;
75 static int hf_spnego_krb5_cfx_flags = -1;
76 static int hf_spnego_krb5_cfx_flags_01 = -1;
77 static int hf_spnego_krb5_cfx_flags_02 = -1;
78 static int hf_spnego_krb5_cfx_flags_04 = -1;
79 static int hf_spnego_krb5_cfx_ec = -1;
80 static int hf_spnego_krb5_cfx_rrc = -1;
81 static int hf_spnego_krb5_cfx_seq = -1;
82
83 #include "packet-spnego-hf.c"
84
85 /* Global variables */
86 static const char *MechType_oid;
87 gssapi_oid_value *next_level_value;
88 gboolean saw_mechanism = FALSE;
89
90
91 /* Initialize the subtree pointers */
92 static gint ett_spnego;
93 static gint ett_spnego_wraptoken;
94 static gint ett_spnego_krb5 = -1;
95 static gint ett_spnego_krb5_cfx_flags = -1;
96
97 #include "packet-spnego-ett.c"
98
99 /*
100  * Unfortunately, we have to have a forward declaration of this,
101  * as the code generated by asn2wrs includes a call before the
102  * definition.
103  */
104 static int dissect_spnego_PrincipalSeq(gboolean implicit_tag, tvbuff_t *tvb,
105                                        int offset, asn1_ctx_t *actx _U_,
106                                        proto_tree *tree, int hf_index);
107
108 #include "packet-spnego-fn.c"
109 /*
110  * This is the SPNEGO KRB5 dissector. It is not true KRB5, but some ASN.1
111  * wrapped blob with an OID, USHORT token ID, and a Ticket, that is also
112  * ASN.1 wrapped by the looks of it. It conforms to RFC1964.
113  */
114
115 #define KRB_TOKEN_AP_REQ                0x0001
116 #define KRB_TOKEN_AP_REP                0x0002
117 #define KRB_TOKEN_AP_ERR                0x0003
118 #define KRB_TOKEN_GETMIC                0x0101
119 #define KRB_TOKEN_WRAP                  0x0102
120 #define KRB_TOKEN_DELETE_SEC_CONTEXT    0x0201
121 #define KRB_TOKEN_CFX_GETMIC            0x0404
122 #define KRB_TOKEN_CFX_WRAP              0x0405
123
124 static const value_string spnego_krb5_tok_id_vals[] = {
125   { KRB_TOKEN_AP_REQ,             "KRB5_AP_REQ"},
126   { KRB_TOKEN_AP_REP,             "KRB5_AP_REP"},
127   { KRB_TOKEN_AP_ERR,             "KRB5_ERROR"},
128   { KRB_TOKEN_GETMIC,             "KRB5_GSS_GetMIC" },
129   { KRB_TOKEN_WRAP,               "KRB5_GSS_Wrap" },
130   { KRB_TOKEN_DELETE_SEC_CONTEXT, "KRB5_GSS_Delete_sec_context" },
131   { KRB_TOKEN_CFX_GETMIC,         "KRB_TOKEN_CFX_GetMic" },
132   { KRB_TOKEN_CFX_WRAP,           "KRB_TOKEN_CFX_WRAP" },
133   { 0, NULL}
134 };
135
136 #define KRB_SGN_ALG_DES_MAC_MD5 0x0000
137 #define KRB_SGN_ALG_MD2_5       0x0001
138 #define KRB_SGN_ALG_DES_MAC     0x0002
139 #define KRB_SGN_ALG_HMAC        0x0011
140
141 static const value_string spnego_krb5_sgn_alg_vals[] = {
142   { KRB_SGN_ALG_DES_MAC_MD5, "DES MAC MD5"},
143   { KRB_SGN_ALG_MD2_5,       "MD2.5"},
144   { KRB_SGN_ALG_DES_MAC,     "DES MAC"},
145   { KRB_SGN_ALG_HMAC,        "HMAC"},
146   { 0, NULL}
147 };
148
149 #define KRB_SEAL_ALG_DES_CBC    0x0000
150 #define KRB_SEAL_ALG_RC4        0x0010
151 #define KRB_SEAL_ALG_NONE       0xffff
152
153 static const value_string spnego_krb5_seal_alg_vals[] = {
154   { KRB_SEAL_ALG_DES_CBC, "DES CBC"},
155   { KRB_SEAL_ALG_RC4,     "RC4"},
156   { KRB_SEAL_ALG_NONE,    "None"},
157   { 0, NULL}
158 };
159
160 /*
161  * XXX - is this for SPNEGO or just GSS-API?
162  * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
163  * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
164  * than designating SPNEGO as the mechanism, offering Kerberos V5, and
165  * getting it accepted.
166  */
167 static int
168 dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
169 static int
170 dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint16 token_id);
171 static int
172 dissect_spnego_krb5_cfx_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
173 static int
174 dissect_spnego_krb5_cfx_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint16 token_id);
175
176 static void
177 dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
178 {
179         proto_item *item;
180         proto_tree *subtree;
181         int offset = 0;
182         guint16 token_id;
183         const char *oid;
184         gssapi_oid_value *value;
185         tvbuff_t *krb5_tvb;
186         gint8 class;
187         gboolean pc, ind = 0;
188         gint32 tag;
189         guint32 len;
190         asn1_ctx_t asn1_ctx;
191         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
192
193         item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, offset,
194                                    -1, FALSE);
195
196         subtree = proto_item_add_subtree(item, ett_spnego_krb5);
197
198         /*
199          * The KRB5 blob conforms to RFC1964:
200          * [APPLICATION 0] {
201          *   OID,
202          *   USHORT (0x0001 == AP-REQ, 0x0002 == AP-REP, 0x0003 == ERROR),
203          *   OCTET STRING }
204          *
205          * However, for some protocols, the KRB5 blob starts at the SHORT
206          * and has no DER encoded header etc.
207          *
208          * It appears that for some other protocols the KRB5 blob is just
209          * a Kerberos message, with no [APPLICATION 0] header, no OID,
210          * and no USHORT.
211          *
212          * So:
213          *
214          *      If we see an [APPLICATION 0] HEADER, we show the OID and
215          *      the USHORT, and then dissect the rest as a Kerberos message.
216          *
217          *      If we see an [APPLICATION 14] or [APPLICATION 15] header,
218          *      we assume it's an AP-REQ or AP-REP message, and dissect
219          *      it all as a Kerberos message.
220          *
221          *      Otherwise, we show the USHORT, and then dissect the rest
222          *      as a Kerberos message.
223          */
224
225         /*
226          * Get the first header ...
227          */
228         get_ber_identifier(tvb, offset, &class, &pc, &tag);
229         if (class == BER_CLASS_APP && pc) {
230             /*
231              * [APPLICATION <tag>]
232              */
233             offset = dissect_ber_identifier(pinfo, subtree, tvb, offset, &class, &pc, &tag);
234             offset = dissect_ber_length(pinfo, subtree, tvb, offset, &len, &ind);
235
236             switch (tag) {
237
238             case 0:
239                 /*
240                  * [APPLICATION 0]
241                  */
242
243                 /* Next, the OID */
244                 offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, subtree, tvb, offset, hf_spnego_krb5_oid, &oid);
245
246                 value = gssapi_lookup_oid_str(oid);
247
248                 token_id = tvb_get_letohs(tvb, offset);
249                 proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
250                                     token_id);
251
252                 offset += 2;
253
254                 break;
255
256             case 14:    /* [APPLICATION 14] */
257             case 15:    /* [APPLICATION 15] */
258                 /*
259                  * No token ID - just dissect as a Kerberos message and
260                  * return.
261                  */
262                 offset = dissect_kerberos_main(tvb, pinfo, subtree, FALSE, NULL);
263                 return;
264
265             default:
266                 proto_tree_add_text(subtree, tvb, offset, 0,
267                         "Unknown header (class=%d, pc=%d, tag=%d)",
268                         class, pc, tag);
269                 goto done;
270             }
271         } else {
272             /* Next, the token ID ... */
273
274             token_id = tvb_get_letohs(tvb, offset);
275             proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
276                                 token_id);
277
278             offset += 2;
279         }
280
281         switch (token_id) {
282
283         case KRB_TOKEN_AP_REQ:
284         case KRB_TOKEN_AP_REP:
285         case KRB_TOKEN_AP_ERR:
286           krb5_tvb = tvb_new_subset(tvb, offset, -1, -1);
287           offset = dissect_kerberos_main(krb5_tvb, pinfo, subtree, FALSE, NULL);
288           break;
289
290         case KRB_TOKEN_GETMIC:
291           offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
292           break;
293
294         case KRB_TOKEN_WRAP:
295           offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
296           break;
297
298         case KRB_TOKEN_DELETE_SEC_CONTEXT:
299
300           break;
301
302         case KRB_TOKEN_CFX_GETMIC:
303           offset = dissect_spnego_krb5_cfx_getmic_base(tvb, offset, pinfo, subtree);
304           break;
305
306         case KRB_TOKEN_CFX_WRAP:
307           offset = dissect_spnego_krb5_cfx_wrap_base(tvb, offset, pinfo, subtree, token_id);
308           break;
309
310         default:
311
312           break;
313         }
314
315  done:
316         proto_item_set_len(item, offset);
317         return;
318 }
319
320 #ifdef HAVE_KERBEROS
321 #include <epan/crypt/crypt-md5.h>
322
323 #ifndef KEYTYPE_ARCFOUR_56
324 # define KEYTYPE_ARCFOUR_56 24
325 #endif
326 /* XXX - We should probably do a configure-time check for this instead */
327 #ifndef KRB5_KU_USAGE_SEAL
328 # define KRB5_KU_USAGE_SEAL 22
329 #endif
330
331 static int
332 arcfour_mic_key(void *key_data, size_t key_size, int key_type,
333                 void *cksum_data, size_t cksum_size,
334                 void *key6_data)
335 {
336     guint8 k5_data[16];
337     guint8 T[4];
338
339     memset(T, 0, 4);
340
341     if (key_type == KEYTYPE_ARCFOUR_56) {
342         guint8 L40[14] = "fortybits";
343
344         memcpy(L40 + 10, T, sizeof(T));
345         md5_hmac(
346                 L40, 14,
347                 key_data,
348                 key_size,
349                 k5_data);
350         memset(&k5_data[7], 0xAB, 9);
351     } else {
352         md5_hmac(
353                 T, 4,
354                 key_data,
355                 key_size,
356                 k5_data);
357     }
358
359     md5_hmac(
360         cksum_data, cksum_size,
361         k5_data,
362         16,
363         key6_data);
364
365     return 0;
366 }
367
368 static int
369 usage2arcfour(int usage)
370 {
371     switch (usage) {
372     case 3: /*KRB5_KU_AS_REP_ENC_PART 3 */
373     case 9: /*KRB5_KU_TGS_REP_ENC_PART_SUB_KEY 9 */
374         return 8;
375     case 22: /*KRB5_KU_USAGE_SEAL 22 */
376         return 13;
377     case 23: /*KRB5_KU_USAGE_SIGN 23 */
378         return 15;
379     case 24: /*KRB5_KU_USAGE_SEQ 24 */
380         return 0;
381     default :
382         return 0;
383     }
384 }
385
386 static int
387 arcfour_mic_cksum(guint8 *key_data, int key_length,
388                   unsigned usage,
389                   guint8 sgn_cksum[8],
390                   const void *v1, size_t l1,
391                   const void *v2, size_t l2,
392                   const void *v3, size_t l3)
393 {
394     const guint8 signature[] = "signaturekey";
395     guint8 ksign_c[16];
396     unsigned char t[4];
397     md5_state_t ms;
398     unsigned char digest[16];
399     int rc4_usage;
400     guint8 cksum[16];
401
402     rc4_usage=usage2arcfour(usage);
403     md5_hmac(signature, sizeof(signature),
404                 key_data, key_length,
405                 ksign_c);
406     md5_init(&ms);
407     t[0] = (rc4_usage >>  0) & 0xFF;
408     t[1] = (rc4_usage >>  8) & 0xFF;
409     t[2] = (rc4_usage >> 16) & 0xFF;
410     t[3] = (rc4_usage >> 24) & 0xFF;
411     md5_append(&ms, t, 4);
412     md5_append(&ms, v1, l1);
413     md5_append(&ms, v2, l2);
414     md5_append(&ms, v3, l3);
415     md5_finish(&ms, digest);
416     md5_hmac(digest, 16, ksign_c, 16, cksum);
417
418     memcpy(sgn_cksum, cksum, 8);
419
420     return 0;
421 }
422
423 /*
424  * Verify padding of a gss wrapped message and return its length.
425  */
426 static int
427 gssapi_verify_pad(unsigned char *wrapped_data, int wrapped_length,
428                    size_t datalen,
429                    size_t *padlen)
430 {
431     unsigned char *pad;
432     size_t padlength;
433     int i;
434
435     pad = wrapped_data + wrapped_length - 1;
436     padlength = *pad;
437
438     if (padlength > datalen)
439         return 1;
440
441     for (i = padlength; i > 0 && *pad == padlength; i--, pad--)
442         ;
443     if (i != 0)
444         return 2;
445
446     *padlen = padlength;
447
448     return 0;
449 }
450
451 static int
452 decrypt_arcfour(packet_info *pinfo,
453          guint8 *input_message_buffer,
454          guint8 *output_message_buffer,
455          guint8 *key_value, int key_size, int key_type)
456 {
457     guint8 Klocaldata[16];
458     int ret;
459     gint32 seq_number;
460     size_t datalen;
461     guint8 k6_data[16];
462     guint32 SND_SEQ[2];
463     guint8 Confounder[8];
464     guint8 cksum_data[8];
465     int cmp;
466     int conf_flag;
467     size_t padlen = 0;
468
469     datalen = tvb_length(pinfo->gssapi_encrypted_tvb);
470
471     if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0x1000){
472         conf_flag=1;
473     } else if (tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0xffff){
474         conf_flag=0;
475     } else {
476         return -3;
477     }
478
479     if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 6)!=0xffff){
480         return -4;
481     }
482
483     ret = arcfour_mic_key(key_value, key_size, key_type,
484                           (void *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
485                           8, /* SGN_CKSUM */
486                           k6_data);
487     if (ret) {
488         return -5;
489     }
490
491     {
492         rc4_state_struct rc4_state;
493
494         crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
495         memcpy(SND_SEQ, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 8, 8), 8);
496         crypt_rc4(&rc4_state, (unsigned char *)SND_SEQ, 8);
497
498         memset(k6_data, 0, sizeof(k6_data));
499     }
500
501     seq_number=g_ntohl(SND_SEQ[0]);
502
503     if (SND_SEQ[1] != 0xFFFFFFFF && SND_SEQ[1] != 0x00000000) {
504         return -6;
505     }
506
507     {
508         int i;
509
510         for (i = 0; i < 16; i++)
511             Klocaldata[i] = ((guint8 *)key_value)[i] ^ 0xF0;
512     }
513     ret = arcfour_mic_key(Klocaldata,sizeof(Klocaldata),key_type,
514                           (unsigned char *)SND_SEQ, 4,
515                           k6_data);
516     memset(Klocaldata, 0, sizeof(Klocaldata));
517     if (ret) {
518         return -7;
519     }
520
521     if(conf_flag) {
522         rc4_state_struct rc4_state;
523
524         crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
525         memcpy(Confounder, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8), 8);
526         crypt_rc4(&rc4_state, Confounder, 8);
527         memcpy(output_message_buffer, input_message_buffer, datalen);
528         crypt_rc4(&rc4_state, output_message_buffer, datalen);
529     } else {
530         memcpy(Confounder,
531                 tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8),
532                 8); /* Confounder */
533         memcpy(output_message_buffer,
534                 input_message_buffer,
535                 datalen);
536     }
537     memset(k6_data, 0, sizeof(k6_data));
538
539     /* only normal (i.e. non DCE style  wrapping use padding ? */
540     if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
541         ret = gssapi_verify_pad(output_message_buffer,datalen,datalen, &padlen);
542         if (ret) {
543             return -9;
544         }
545         datalen -= padlen;
546     }
547
548     /* dont know what the checksum looks like for dce style gssapi */
549     if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
550         ret = arcfour_mic_cksum(key_value, key_size,
551                             KRB5_KU_USAGE_SEAL,
552                             cksum_data,
553                             tvb_get_ptr(pinfo->gssapi_wrap_tvb, 0, 8), 8,
554                             Confounder, sizeof(Confounder),
555                             output_message_buffer,
556                             datalen + padlen);
557         if (ret) {
558             return -10;
559         }
560
561         cmp = memcmp(cksum_data,
562             tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
563             8); /* SGN_CKSUM */
564         if (cmp) {
565             return -11;
566         }
567     }
568
569     return datalen;
570 }
571
572
573
574 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
575
576 static void
577 decrypt_gssapi_krb_arcfour_wrap(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int keytype)
578 {
579         int ret;
580         enc_key_t *ek;
581         int length;
582         const guint8 *original_data;
583
584         static int omb_index=0;
585         static guint8 *omb_arr[4]={NULL,NULL,NULL,NULL};
586         static guint8 *cryptocopy=NULL; /* workaround for pre-0.6.1 heimdal bug */
587         guint8 *output_message_buffer;
588
589         omb_index++;
590         if(omb_index>=4){
591                 omb_index=0;
592         }
593         output_message_buffer=omb_arr[omb_index];
594
595
596         length=tvb_length(pinfo->gssapi_encrypted_tvb);
597         original_data=tvb_get_ptr(pinfo->gssapi_encrypted_tvb, 0, length);
598
599         /* dont do anything if we are not attempting to decrypt data */
600 /*
601         if(!krb_decrypt){
602                 return;
603         }
604 */
605         /* XXX we should only do this for first time, then store somewhere */
606         /* XXX We also need to re-read the keytab when the preference changes */
607
608         cryptocopy=ep_alloc(length);
609         if(output_message_buffer){
610                 g_free(output_message_buffer);
611                 output_message_buffer=NULL;
612         }
613         output_message_buffer=g_malloc(length);
614
615         for(ek=enc_key_list;ek;ek=ek->next){
616                 /* shortcircuit and bail out if enctypes are not matching */
617                 if(ek->keytype!=keytype){
618                         continue;
619                 }
620
621                 /* pre-0.6.1 versions of Heimdal would sometimes change
622                   the cryptotext data even when the decryption failed.
623                   This would obviously not work since we iterate over the
624                   keys. So just give it a copy of the crypto data instead.
625                   This has been seen for RC4-HMAC blobs.
626                 */
627                 memcpy(cryptocopy, original_data, length);
628                 ret=decrypt_arcfour(pinfo,
629                                 cryptocopy,
630                                 output_message_buffer,
631                                 ek->keyvalue,
632                                 ek->keylength,
633                                 ek->keytype
634                                             );
635                 if (ret >= 0) {
636                         proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
637                         pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(tvb, 
638                                 output_message_buffer,
639                                 ret, ret);
640                         add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
641                         return;
642                 }
643         }
644         return;
645 }
646
647 /* borrowed from heimdal */
648 static int
649 rrc_rotate(void *data, int len, guint16 rrc, int unrotate)
650 {
651         unsigned char *tmp, buf[256];
652         size_t left;
653
654         if (len == 0)
655                 return 0;
656
657         rrc %= len;
658
659         if (rrc == 0)
660                 return 0;
661
662         left = len - rrc;
663
664         if (rrc <= sizeof(buf)) {
665                 tmp = buf;
666         } else {
667                 tmp = g_malloc(rrc);
668                 if (tmp == NULL)
669                         return -1;
670         }
671
672         if (unrotate) {
673                 memcpy(tmp, data, rrc);
674                 memmove(data, (unsigned char *)data + rrc, left);
675                 memcpy((unsigned char *)data + left, tmp, rrc);
676         } else {
677                 memcpy(tmp, (unsigned char *)data + left, rrc);
678                 memmove((unsigned char *)data + rrc, data, left);
679                 memcpy(data, tmp, rrc);
680         }
681
682         if (rrc > sizeof(buf))
683                 g_free(tmp);
684
685         return 0;
686 }
687
688
689 #define KRB5_KU_USAGE_ACCEPTOR_SEAL     22
690 #define KRB5_KU_USAGE_ACCEPTOR_SIGN     23
691 #define KRB5_KU_USAGE_INITIATOR_SEAL    24
692 #define KRB5_KU_USAGE_INITIATOR_SIGN    25
693
694 static void
695 decrypt_gssapi_krb_cfx_wrap(proto_tree *tree _U_, packet_info *pinfo _U_, tvbuff_t *tvb _U_, guint16 ec _U_, guint16 rrc _U_, int keytype, unsigned int usage)
696 {
697         int res;
698         char *rotated;
699         char *output;
700         int datalen;
701
702         /* dont do anything if we are not attempting to decrypt data */
703         if(!krb_decrypt){
704                 return;
705         }
706
707         rotated = ep_alloc(tvb_length(tvb));
708
709         tvb_memcpy(tvb, rotated, 0, tvb_length(tvb));
710         res = rrc_rotate(rotated, tvb_length(tvb), rrc, TRUE);
711
712         output = decrypt_krb5_data(tree, pinfo, usage, tvb_length(tvb),
713                   rotated, keytype, &datalen);
714
715         if (output) {
716                 char *outdata;
717
718                 outdata = ep_alloc(tvb_length(tvb));
719                 memcpy(outdata, output, tvb_length(tvb));
720                 g_free(output);
721
722                 pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(tvb,
723                         outdata,
724                         datalen-16,
725                         datalen-16);
726                 add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
727                 return;
728         }
729         return;
730 }
731
732 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
733
734
735 #endif
736
737 /*
738  * This is for GSSAPI Wrap tokens ...
739  */
740 static int
741 dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
742 #ifndef HAVE_KERBEROS
743         _U_
744 #endif
745     , proto_tree *tree, guint16 token_id
746 #ifndef HAVE_KERBEROS
747         _U_
748 #endif
749     )
750 {
751         guint16 sgn_alg, seal_alg;
752 #ifdef HAVE_KERBEROS
753         int start_offset=offset;
754 #endif
755
756         /*
757          * The KRB5 blob conforms to RFC1964:
758          *   USHORT (0x0102 == GSS_Wrap)
759          *   and so on }
760          */
761
762         /* Now, the sign and seal algorithms ... */
763
764         sgn_alg = tvb_get_letohs(tvb, offset);
765         proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
766                             sgn_alg);
767
768         offset += 2;
769
770         seal_alg = tvb_get_letohs(tvb, offset);
771         proto_tree_add_uint(tree, hf_spnego_krb5_seal_alg, tvb, offset, 2,
772                             seal_alg);
773
774         offset += 2;
775
776         /* Skip the filler */
777
778         offset += 2;
779
780         /* Encrypted sequence number */
781
782         proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
783                             TRUE);
784
785         offset += 8;
786
787         /* Checksum of plaintext padded data */
788
789         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
790                             TRUE);
791
792         offset += 8;
793
794         /*
795          * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
796          * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
797          * extra 8 bytes of "Random confounder" after the checksum.
798          * It certainly confounds code expecting all Kerberos 5
799          * GSS_Wrap() tokens to look the same....
800          */
801         if ((sgn_alg == KRB_SGN_ALG_HMAC) ||
802             /* there also seems to be a confounder for DES MAC MD5 - certainly seen when using with
803                SASL with LDAP between a Java client and Active Directory. If this breaks other things
804                we may need to make this an option. gal 17/2/06 */
805             (sgn_alg == KRB_SGN_ALG_DES_MAC_MD5)) {
806           proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
807                               TRUE);
808           offset += 8;
809         }
810
811         /* Is the data encrypted? */
812         pinfo->gssapi_data_encrypted=(seal_alg!=KRB_SEAL_ALG_NONE);
813
814 #ifdef HAVE_KERBEROS
815 #define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
816         if(pinfo->decrypt_gssapi_tvb){
817                 /* if the caller did not provide a tvb, then we just use
818                    whatever is left of our current tvb.
819                 */
820                 if(!pinfo->gssapi_encrypted_tvb){
821                         int len;
822                         len=tvb_reported_length_remaining(tvb,offset);
823                         if(len>tvb_length_remaining(tvb, offset)){
824                                 /* no point in trying to decrypt,
825                                    we dont have the full pdu.
826                                 */
827                                 return offset;
828                         }
829                         pinfo->gssapi_encrypted_tvb = tvb_new_subset(
830                                         tvb, offset, len, len);
831                 }
832
833                 /* if this is KRB5 wrapped rc4-hmac */
834                 if((token_id==KRB_TOKEN_WRAP)
835                  &&(sgn_alg==KRB_SGN_ALG_HMAC)
836                  &&(seal_alg==KRB_SEAL_ALG_RC4)){
837                         /* do we need to create a tvb for the wrapper
838                            as well ?
839                         */
840                         if(!pinfo->gssapi_wrap_tvb){
841                                 pinfo->gssapi_wrap_tvb = tvb_new_subset(
842                                         tvb, start_offset-2,
843                                         GSS_ARCFOUR_WRAP_TOKEN_SIZE,
844                                         GSS_ARCFOUR_WRAP_TOKEN_SIZE);
845                         }
846 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
847                         decrypt_gssapi_krb_arcfour_wrap(tree,
848                                 pinfo,
849                                 tvb,
850                                 23 /* rc4-hmac */);
851 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
852                 }
853         }
854 #endif
855         /*
856          * Return the offset past the checksum, so that we know where
857          * the data we're wrapped around starts.  Also, set the length
858          * of our top-level item to that offset, so it doesn't cover
859          * the data we're wrapped around.
860          *
861          * Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
862          * not before.
863          */
864         return offset;
865 }
866
867 /*
868  * XXX - This is for GSSAPI GetMIC tokens ...
869  */
870 static int
871 dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
872 {
873         guint16 sgn_alg;
874
875         /*
876          * The KRB5 blob conforms to RFC1964:
877          *   USHORT (0x0101 == GSS_GetMIC)
878          *   and so on }
879          */
880
881         /* Now, the sign algorithm ... */
882
883         sgn_alg = tvb_get_letohs(tvb, offset);
884         proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
885                             sgn_alg);
886
887         offset += 2;
888
889         /* Skip the filler */
890
891         offset += 4;
892
893         /* Encrypted sequence number */
894
895         proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
896                             TRUE);
897
898         offset += 8;
899
900         /* Checksum of plaintext padded data */
901
902         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
903                             TRUE);
904
905         offset += 8;
906
907         /*
908          * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
909          * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
910          * extra 8 bytes of "Random confounder" after the checksum.
911          * It certainly confounds code expecting all Kerberos 5
912          * GSS_Wrap() tokens to look the same....
913          *
914          * The exception is DNS/TSIG where there is no such confounder
915          * so we need to test here if there are more bytes in our tvb or not.
916          *  -- ronnie
917          */
918         if (tvb_length_remaining(tvb, offset)) {
919           if (sgn_alg == KRB_SGN_ALG_HMAC) {
920             proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
921                               TRUE);
922
923             offset += 8;
924           }
925         }
926
927         /*
928          * Return the offset past the checksum, so that we know where
929          * the data we're wrapped around starts.  Also, set the length
930          * of our top-level item to that offset, so it doesn't cover
931          * the data we're wrapped around.
932          */
933
934         return offset;
935 }
936
937 static int
938 dissect_spnego_krb5_cfx_flags(tvbuff_t *tvb, int offset,
939                               proto_tree *spnego_krb5_tree,
940                               guint8 cfx_flags)
941 {
942         proto_tree *cfx_flags_tree = NULL;
943         proto_item *tf = NULL;
944
945         if (spnego_krb5_tree) {
946                 tf = proto_tree_add_uint(spnego_krb5_tree,
947                                          hf_spnego_krb5_cfx_flags,
948                                          tvb, offset, 1, cfx_flags);
949                 cfx_flags_tree = proto_item_add_subtree(tf, ett_spnego_krb5_cfx_flags);
950         }
951
952         proto_tree_add_boolean(cfx_flags_tree,
953                                hf_spnego_krb5_cfx_flags_04,
954                                tvb, offset, 1, cfx_flags);
955         proto_tree_add_boolean(cfx_flags_tree,
956                                hf_spnego_krb5_cfx_flags_02,
957                                tvb, offset, 1, cfx_flags);
958         proto_tree_add_boolean(cfx_flags_tree,
959                                hf_spnego_krb5_cfx_flags_01,
960                                tvb, offset, 1, cfx_flags);
961
962         return (offset + 1);
963 }
964
965 /*
966  * This is for GSSAPI CFX Wrap tokens ...
967  */
968 static int
969 dissect_spnego_krb5_cfx_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
970 #ifndef HAVE_KERBEROS
971         _U_
972 #endif
973     , proto_tree *tree, guint16 token_id _U_
974     )
975 {
976         guint8 flags;
977         guint16 ec;
978         guint16 rrc;
979         int checksum_size;
980         int start_offset=offset;
981
982         /*
983          * The KRB5 blob conforms to RFC4121:
984          *   USHORT (0x0504)
985          *   and so on }
986          */
987
988         /* Now, the sign and seal algorithms ... */
989
990         flags = tvb_get_guint8(tvb, offset);
991         offset = dissect_spnego_krb5_cfx_flags(tvb, offset, tree, flags);
992
993         pinfo->gssapi_data_encrypted=(flags & 2);
994
995         /* Skip the filler */
996
997         proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 1,
998                             FALSE);
999         offset += 1;
1000
1001         /* EC */
1002         ec = tvb_get_ntohs(tvb, offset);
1003         proto_tree_add_item(tree, hf_spnego_krb5_cfx_ec, tvb, offset, 2,
1004                             FALSE);
1005         offset += 2;
1006
1007         /* RRC */
1008         rrc = tvb_get_ntohs(tvb, offset);
1009         proto_tree_add_item(tree, hf_spnego_krb5_cfx_rrc, tvb, offset, 2,
1010                             FALSE);
1011         offset += 2;
1012
1013         /* sequence number */
1014
1015         proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
1016                             FALSE);
1017         offset += 8;
1018
1019         /* Checksum of plaintext padded data */
1020
1021         if (pinfo->gssapi_data_encrypted) {
1022                 checksum_size = 44 + ec;
1023         } else {
1024                 checksum_size = 12;
1025         }
1026
1027         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
1028                             checksum_size, FALSE);
1029         offset += checksum_size;
1030
1031         if(pinfo->decrypt_gssapi_tvb){
1032                 /* if the caller did not provide a tvb, then we just use
1033                    whatever is left of our current tvb.
1034                 */
1035                 if(!pinfo->gssapi_encrypted_tvb){
1036                         int len;
1037                         len=tvb_reported_length_remaining(tvb,offset);
1038                         if(len>tvb_length_remaining(tvb, offset)){
1039                                 /* no point in trying to decrypt,
1040                                    we dont have the full pdu.
1041                                 */
1042                                 return offset;
1043                         }
1044                         pinfo->gssapi_encrypted_tvb = tvb_new_subset(
1045                                         tvb, offset, len, len);
1046                 }
1047
1048                 if (pinfo->gssapi_data_encrypted) {
1049                         /* do we need to create a tvb for the wrapper
1050                            as well ?
1051                         */
1052                         if(!pinfo->gssapi_wrap_tvb){
1053                                 pinfo->gssapi_wrap_tvb = tvb_new_subset(
1054                                         tvb, start_offset-2,
1055                                         offset - (start_offset-2),
1056                                         offset - (start_offset-2));
1057                         }
1058                 }
1059         }
1060
1061 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1062         pinfo->gssapi_encrypted_tvb = tvb_new_subset(tvb, 16, -1, -1);
1063
1064         if (flags & 0x0002) {
1065                 if(pinfo->gssapi_encrypted_tvb){
1066                         decrypt_gssapi_krb_cfx_wrap(tree,
1067                                 pinfo,
1068                                 pinfo->gssapi_encrypted_tvb,
1069                                 ec,
1070                                 rrc,
1071                                 -1,
1072                                 (flags & 0x0001)?
1073                                 KRB5_KU_USAGE_ACCEPTOR_SEAL:
1074                                 KRB5_KU_USAGE_INITIATOR_SEAL);
1075                 }
1076         }
1077 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1078
1079         /*
1080          * Return the offset past the checksum, so that we know where
1081          * the data we're wrapped around starts.  Also, set the length
1082          * of our top-level item to that offset, so it doesn't cover
1083          * the data we're wrapped around.
1084          *
1085          * Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
1086          * not before.
1087          */
1088         return offset;
1089 }
1090
1091 /*
1092  * XXX - This is for GSSAPI CFX GetMIC tokens ...
1093  */
1094 static int
1095 dissect_spnego_krb5_cfx_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
1096 {
1097         guint8 flags;
1098         int checksum_size;
1099
1100         /*
1101          * The KRB5 blob conforms to RFC4121:
1102          *   USHORT (0x0404 == GSS_GetMIC)
1103          *   and so on }
1104          */
1105
1106         flags = tvb_get_guint8(tvb, offset);
1107         offset = dissect_spnego_krb5_cfx_flags(tvb, offset, tree, flags);
1108
1109         /* Skip the filler */
1110
1111         proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 5,
1112                             FALSE);
1113         offset += 5;
1114
1115         /* sequence number */
1116
1117         proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
1118                             FALSE);
1119         offset += 8;
1120
1121         /* Checksum of plaintext padded data */
1122
1123         checksum_size = tvb_length_remaining(tvb, offset);
1124
1125         proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
1126                             checksum_size, FALSE);
1127         offset += checksum_size;
1128
1129         /*
1130          * Return the offset past the checksum, so that we know where
1131          * the data we're wrapped around starts.  Also, set the length
1132          * of our top-level item to that offset, so it doesn't cover
1133          * the data we're wrapped around.
1134          */
1135
1136         return offset;
1137 }
1138
1139 /*
1140  * XXX - is this for SPNEGO or just GSS-API?
1141  * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
1142  * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
1143  * than designating SPNEGO as the mechanism, offering Kerberos V5, and
1144  * getting it accepted.
1145  */
1146 static int
1147 dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1148 {
1149         proto_item *item;
1150         proto_tree *subtree;
1151         int offset = 0;
1152         guint16 token_id;
1153
1154         item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, 0, -1, FALSE);
1155
1156         subtree = proto_item_add_subtree(item, ett_spnego_krb5);
1157
1158         /*
1159          * The KRB5 blob conforms to RFC1964:
1160          *   USHORT (0x0102 == GSS_Wrap)
1161          *   and so on }
1162          */
1163
1164         /* First, the token ID ... */
1165
1166         token_id = tvb_get_letohs(tvb, offset);
1167         proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
1168                             token_id);
1169
1170         offset += 2;
1171
1172         switch (token_id) {
1173         case KRB_TOKEN_GETMIC:
1174           offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
1175           break;
1176
1177         case KRB_TOKEN_WRAP:
1178           offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
1179           break;
1180
1181         case KRB_TOKEN_CFX_GETMIC:
1182           offset = dissect_spnego_krb5_cfx_getmic_base(tvb, offset, pinfo, subtree);
1183           break;
1184
1185         case KRB_TOKEN_CFX_WRAP:
1186           offset = dissect_spnego_krb5_cfx_wrap_base(tvb, offset, pinfo, subtree, token_id);
1187           break;
1188
1189         default:
1190
1191           break;
1192         }
1193
1194         /*
1195          * Return the offset past the checksum, so that we know where
1196          * the data we're wrapped around starts.  Also, set the length
1197          * of our top-level item to that offset, so it doesn't cover
1198          * the data we're wrapped around.
1199          */
1200         proto_item_set_len(item, offset);
1201         return offset;
1202 }
1203
1204 /* Spnego stuff from here */
1205
1206 static int
1207 dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1208 {
1209         proto_item *item;
1210         proto_tree *subtree;
1211         int offset = 0;
1212         asn1_ctx_t asn1_ctx;
1213         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1214
1215
1216
1217         /*
1218          * We need this later, so lets get it now ...
1219          * It has to be per-frame as there can be more than one GSS-API
1220          * negotiation in a conversation.
1221          */
1222
1223
1224         item = proto_tree_add_item(tree, hf_spnego, tvb, offset,
1225                                    -1, FALSE);
1226
1227         subtree = proto_item_add_subtree(item, ett_spnego);
1228         /*
1229          * The TVB contains a [0] header and a sequence that consists of an
1230          * object ID and a blob containing the data ...
1231          * XXX - is this RFC 2743's "Mechanism-Independent Token Format",
1232          * with the "optional" "use in non-initial tokens" being chosen.
1233          * ASN1 code addet to spnego.asn to handle this.
1234          */
1235
1236         offset = dissect_spnego_InitialContextToken(FALSE, tvb, offset, &asn1_ctx , subtree, -1);
1237
1238         return offset;
1239 }
1240
1241
1242 static void
1243 dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
1244 {
1245         proto_item *item;
1246         proto_tree *subtree;
1247         int offset = 0;
1248         conversation_t *conversation;
1249         asn1_ctx_t asn1_ctx;
1250         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1251
1252         /*
1253          * We need this later, so lets get it now ...
1254          * It has to be per-frame as there can be more than one GSS-API
1255          * negotiation in a conversation.
1256          */
1257         next_level_value = p_get_proto_data(pinfo->fd, proto_spnego);
1258         if (!next_level_value && !pinfo->fd->flags.visited) {
1259             /*
1260              * No handle attached to this frame, but it's the first
1261              * pass, so it'd be attached to the conversation.
1262              * If we have a conversation, try to get the handle,
1263              * and if we get one, attach it to the frame.
1264              */
1265             conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1266                                              pinfo->ptype, pinfo->srcport,
1267                                              pinfo->destport, 0);
1268
1269             if (conversation) {
1270                 next_level_value = conversation_get_proto_data(conversation,
1271                                                                proto_spnego);
1272                 if (next_level_value)
1273                     p_add_proto_data(pinfo->fd, proto_spnego, next_level_value);
1274             }
1275         }
1276
1277         item = proto_tree_add_item(parent_tree, hf_spnego, tvb, offset,
1278                                    -1, FALSE);
1279
1280         subtree = proto_item_add_subtree(item, ett_spnego);
1281
1282         /*
1283          * The TVB contains a [0] header and a sequence that consists of an
1284          * object ID and a blob containing the data ...
1285          * Actually, it contains, according to RFC2478:
1286          * NegotiationToken ::= CHOICE {
1287          *          negTokenInit [0] NegTokenInit,
1288          *          negTokenTarg [1] NegTokenTarg }
1289          * NegTokenInit ::= SEQUENCE {
1290          *          mechTypes [0] MechTypeList OPTIONAL,
1291          *          reqFlags [1] ContextFlags OPTIONAL,
1292          *          mechToken [2] OCTET STRING OPTIONAL,
1293          *          mechListMIC [3] OCTET STRING OPTIONAL }
1294          * NegTokenTarg ::= SEQUENCE {
1295          *          negResult [0] ENUMERATED {
1296          *              accept_completed (0),
1297          *              accept_incomplete (1),
1298          *              reject (2) } OPTIONAL,
1299          *          supportedMech [1] MechType OPTIONAL,
1300          *          responseToken [2] OCTET STRING OPTIONAL,
1301          *          mechListMIC [3] OCTET STRING OPTIONAL }
1302          *
1303          * Windows typically includes mechTypes and mechListMic ('NONE'
1304          * in the case of NTLMSSP only).
1305          * It seems to duplicate the responseToken into the mechListMic field
1306          * as well. Naughty, naughty.
1307          *
1308          */
1309         offset = dissect_spnego_NegotiationToken(FALSE, tvb, offset, &asn1_ctx, subtree, -1);
1310
1311 }
1312
1313 /*--- proto_register_spnego -------------------------------------------*/
1314 void proto_register_spnego(void) {
1315
1316         /* List of fields */
1317         static hf_register_info hf[] = {
1318                 { &hf_spnego,
1319                   { "SPNEGO", "spnego", FT_NONE, BASE_NONE, NULL, 0x0,
1320                     NULL, HFILL }},
1321                 { &hf_spnego_wraptoken,
1322                   { "wrapToken", "spnego.wraptoken",
1323                     FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO wrapToken",
1324                     HFILL}},
1325                 { &hf_spnego_krb5,
1326                   { "krb5_blob", "spnego.krb5.blob", FT_BYTES,
1327                     BASE_NONE, NULL, 0, NULL, HFILL }},
1328                 { &hf_spnego_krb5_oid,
1329                   { "KRB5 OID", "spnego.krb5_oid", FT_STRING,
1330                     BASE_NONE, NULL, 0, NULL, HFILL }},
1331                 { &hf_spnego_krb5_tok_id,
1332                   { "krb5_tok_id", "spnego.krb5.tok_id", FT_UINT16, BASE_HEX,
1333                     VALS(spnego_krb5_tok_id_vals), 0, "KRB5 Token Id", HFILL}},
1334                 { &hf_spnego_krb5_sgn_alg,
1335                   { "krb5_sgn_alg", "spnego.krb5.sgn_alg", FT_UINT16, BASE_HEX,
1336                     VALS(spnego_krb5_sgn_alg_vals), 0, "KRB5 Signing Algorithm", HFILL}},
1337                 { &hf_spnego_krb5_seal_alg,
1338                   { "krb5_seal_alg", "spnego.krb5.seal_alg", FT_UINT16, BASE_HEX,
1339                     VALS(spnego_krb5_seal_alg_vals), 0, "KRB5 Sealing Algorithm", HFILL}},
1340                 { &hf_spnego_krb5_snd_seq,
1341                   { "krb5_snd_seq", "spnego.krb5.snd_seq", FT_BYTES, BASE_NONE,
1342                     NULL, 0, "KRB5 Encrypted Sequence Number", HFILL}},
1343                 { &hf_spnego_krb5_sgn_cksum,
1344                   { "krb5_sgn_cksum", "spnego.krb5.sgn_cksum", FT_BYTES, BASE_NONE,
1345                     NULL, 0, "KRB5 Data Checksum", HFILL}},
1346                 { &hf_spnego_krb5_confounder,
1347                   { "krb5_confounder", "spnego.krb5.confounder", FT_BYTES, BASE_NONE,
1348                     NULL, 0, "KRB5 Confounder", HFILL}},
1349                 { &hf_spnego_krb5_filler,
1350                   { "krb5_filler", "spnego.krb5.filler", FT_BYTES, BASE_NONE,
1351                     NULL, 0, "KRB5 Filler", HFILL}},
1352                 { &hf_spnego_krb5_cfx_flags,
1353                   { "krb5_cfx_flags", "spnego.krb5.cfx_flags", FT_UINT8, BASE_HEX,
1354                     NULL, 0, "KRB5 CFX Flags", HFILL}},
1355                 { &hf_spnego_krb5_cfx_flags_01,
1356                   { "SendByAcceptor", "spnego.krb5.send_by_acceptor", FT_BOOLEAN, 8,
1357                     TFS (&flags_set_truth), 0x01, NULL, HFILL}},
1358                 { &hf_spnego_krb5_cfx_flags_02,
1359                   { "Sealed", "spnego.krb5.sealed", FT_BOOLEAN, 8,
1360                     TFS (&flags_set_truth), 0x02, NULL, HFILL}},
1361                 { &hf_spnego_krb5_cfx_flags_04,
1362                   { "AcceptorSubkey", "spnego.krb5.acceptor_subkey", FT_BOOLEAN, 8,
1363                     TFS (&flags_set_truth), 0x04, NULL, HFILL}},
1364                 { &hf_spnego_krb5_cfx_ec,
1365                   { "krb5_cfx_ec", "spnego.krb5.cfx_ec", FT_UINT16, BASE_DEC,
1366                     NULL, 0, "KRB5 CFX Extra Count", HFILL}},
1367                 { &hf_spnego_krb5_cfx_rrc,
1368                   { "krb5_cfx_rrc", "spnego.krb5.cfx_rrc", FT_UINT16, BASE_DEC,
1369                     NULL, 0, "KRB5 CFX Right Rotation Count", HFILL}},
1370                 { &hf_spnego_krb5_cfx_seq,
1371                   { "krb5_cfx_seq", "spnego.krb5.cfx_seq", FT_UINT64, BASE_DEC,
1372                     NULL, 0, "KRB5 Sequence Number", HFILL}},
1373
1374 #include "packet-spnego-hfarr.c"
1375         };
1376
1377         /* List of subtrees */
1378         static gint *ett[] = {
1379                 &ett_spnego,
1380                 &ett_spnego_wraptoken,
1381                 &ett_spnego_krb5,
1382                 &ett_spnego_krb5_cfx_flags,
1383
1384 #include "packet-spnego-ettarr.c"
1385         };
1386
1387         /* Register protocol */
1388         proto_spnego = proto_register_protocol(PNAME, PSNAME, PFNAME);
1389
1390         register_dissector("spnego", dissect_spnego, proto_spnego);
1391
1392         proto_spnego_krb5 = proto_register_protocol("SPNEGO-KRB5",
1393                                                     "SPNEGO-KRB5",
1394                                                     "spnego-krb5");
1395
1396         register_dissector("spnego-krb5", dissect_spnego_krb5, proto_spnego_krb5);
1397         new_register_dissector("spnego-krb5-wrap", dissect_spnego_krb5_wrap, proto_spnego_krb5);
1398
1399         /* Register fields and subtrees */
1400         proto_register_field_array(proto_spnego, hf, array_length(hf));
1401         proto_register_subtree_array(ett, array_length(ett));
1402 }
1403
1404
1405 /*--- proto_reg_handoff_spnego ---------------------------------------*/
1406 void proto_reg_handoff_spnego(void) {
1407
1408         dissector_handle_t spnego_handle, spnego_wrap_handle;
1409         dissector_handle_t spnego_krb5_handle, spnego_krb5_wrap_handle;
1410
1411         /* Register protocol with GSS-API module */
1412
1413         spnego_handle = find_dissector("spnego");
1414         spnego_wrap_handle = new_create_dissector_handle(dissect_spnego_wrap,  proto_spnego);
1415         gssapi_init_oid("1.3.6.1.5.5.2", proto_spnego, ett_spnego,
1416             spnego_handle, spnego_wrap_handle,
1417             "SPNEGO - Simple Protected Negotiation");
1418
1419         /* Register both the one MS created and the real one */
1420         /*
1421          * Thanks to Jean-Baptiste Marchand and Richard B Ward, the
1422          * mystery of the MS KRB5 OID is cleared up. It was due to a library
1423          * that did not handle OID components greater than 16 bits, and was
1424          * fixed in Win2K SP2 as well as WinXP.
1425          * See the archive of <ietf-krb-wg@anl.gov> for the thread topic
1426          * SPNEGO implementation issues. 3-Dec-2002.
1427          */
1428         spnego_krb5_handle = find_dissector("spnego-krb5");
1429         spnego_krb5_wrap_handle = find_dissector("spnego-krb5-wrap");
1430         gssapi_init_oid("1.2.840.48018.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
1431                         spnego_krb5_handle, spnego_krb5_wrap_handle,
1432                         "MS KRB5 - Microsoft Kerberos 5");
1433         gssapi_init_oid("1.2.840.113554.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
1434                         spnego_krb5_handle, spnego_krb5_wrap_handle,
1435                         "KRB5 - Kerberos 5");
1436         gssapi_init_oid("1.2.840.113554.1.2.2.3", proto_spnego_krb5, ett_spnego_krb5,
1437                         spnego_krb5_handle, spnego_krb5_wrap_handle,
1438                         "KRB5 - Kerberos 5 - User to User");
1439
1440 }