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