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