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)
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 /* The heimdal code for decryption of GSSAPI wrappers using heimdal comes from
31 Heimdal 1.6 and has been modified for wireshark's requirements.
39 #include <epan/packet.h>
40 #include <epan/asn1.h>
41 #include "packet-dcerpc.h"
42 #include "packet-gssapi.h"
43 #include "packet-kerberos.h"
44 #include <epan/crypt/crypt-rc4.h>
45 #include <epan/conversation.h>
46 #include <epan/emem.h>
47 #include <epan/asn1.h>
52 #include "packet-ber.h"
55 #define PNAME "Simple Protected Negotiation"
56 #define PSNAME "SPNEGO"
57 #define PFNAME "spnego"
59 /* Initialize the protocol and registered fields */
60 static int proto_spnego = -1;
61 static int proto_spnego_krb5 = -1;
64 static int hf_spnego = -1;
65 static int hf_spnego_wraptoken = -1;
66 static int hf_spnego_krb5_oid;
67 static int hf_spnego_krb5 = -1;
68 static int hf_spnego_krb5_tok_id = -1;
69 static int hf_spnego_krb5_sgn_alg = -1;
70 static int hf_spnego_krb5_seal_alg = -1;
71 static int hf_spnego_krb5_snd_seq = -1;
72 static int hf_spnego_krb5_sgn_cksum = -1;
73 static int hf_spnego_krb5_confounder = -1;
74 static int hf_spnego_krb5_filler = -1;
75 static int hf_spnego_krb5_cfx_flags = -1;
76 static int hf_spnego_krb5_cfx_flags_01 = -1;
77 static int hf_spnego_krb5_cfx_flags_02 = -1;
78 static int hf_spnego_krb5_cfx_flags_04 = -1;
79 static int hf_spnego_krb5_cfx_ec = -1;
80 static int hf_spnego_krb5_cfx_rrc = -1;
81 static int hf_spnego_krb5_cfx_seq = -1;
83 #include "packet-spnego-hf.c"
85 /* Global variables */
86 static const char *MechType_oid;
87 gssapi_oid_value *next_level_value;
88 gboolean saw_mechanism = FALSE;
91 /* Initialize the subtree pointers */
92 static gint ett_spnego;
93 static gint ett_spnego_wraptoken;
94 static gint ett_spnego_krb5 = -1;
95 static gint ett_spnego_krb5_cfx_flags = -1;
97 #include "packet-spnego-ett.c"
100 * Unfortunately, we have to have a forward declaration of this,
101 * as the code generated by asn2wrs includes a call before the
104 static int dissect_spnego_PrincipalSeq(gboolean implicit_tag, tvbuff_t *tvb,
105 int offset, asn1_ctx_t *actx _U_,
106 proto_tree *tree, int hf_index);
108 #include "packet-spnego-fn.c"
110 * This is the SPNEGO KRB5 dissector. It is not true KRB5, but some ASN.1
111 * wrapped blob with an OID, USHORT token ID, and a Ticket, that is also
112 * ASN.1 wrapped by the looks of it. It conforms to RFC1964.
115 #define KRB_TOKEN_AP_REQ 0x0001
116 #define KRB_TOKEN_AP_REP 0x0002
117 #define KRB_TOKEN_AP_ERR 0x0003
118 #define KRB_TOKEN_GETMIC 0x0101
119 #define KRB_TOKEN_WRAP 0x0102
120 #define KRB_TOKEN_DELETE_SEC_CONTEXT 0x0201
121 #define KRB_TOKEN_CFX_GETMIC 0x0404
122 #define KRB_TOKEN_CFX_WRAP 0x0405
124 static const value_string spnego_krb5_tok_id_vals[] = {
125 { KRB_TOKEN_AP_REQ, "KRB5_AP_REQ"},
126 { KRB_TOKEN_AP_REP, "KRB5_AP_REP"},
127 { KRB_TOKEN_AP_ERR, "KRB5_ERROR"},
128 { KRB_TOKEN_GETMIC, "KRB5_GSS_GetMIC" },
129 { KRB_TOKEN_WRAP, "KRB5_GSS_Wrap" },
130 { KRB_TOKEN_DELETE_SEC_CONTEXT, "KRB5_GSS_Delete_sec_context" },
131 { KRB_TOKEN_CFX_GETMIC, "KRB_TOKEN_CFX_GetMic" },
132 { KRB_TOKEN_CFX_WRAP, "KRB_TOKEN_CFX_WRAP" },
136 #define KRB_SGN_ALG_DES_MAC_MD5 0x0000
137 #define KRB_SGN_ALG_MD2_5 0x0001
138 #define KRB_SGN_ALG_DES_MAC 0x0002
139 #define KRB_SGN_ALG_HMAC 0x0011
141 static const value_string spnego_krb5_sgn_alg_vals[] = {
142 { KRB_SGN_ALG_DES_MAC_MD5, "DES MAC MD5"},
143 { KRB_SGN_ALG_MD2_5, "MD2.5"},
144 { KRB_SGN_ALG_DES_MAC, "DES MAC"},
145 { KRB_SGN_ALG_HMAC, "HMAC"},
149 #define KRB_SEAL_ALG_DES_CBC 0x0000
150 #define KRB_SEAL_ALG_RC4 0x0010
151 #define KRB_SEAL_ALG_NONE 0xffff
153 static const value_string spnego_krb5_seal_alg_vals[] = {
154 { KRB_SEAL_ALG_DES_CBC, "DES CBC"},
155 { KRB_SEAL_ALG_RC4, "RC4"},
156 { KRB_SEAL_ALG_NONE, "None"},
161 * XXX - is this for SPNEGO or just GSS-API?
162 * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
163 * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
164 * than designating SPNEGO as the mechanism, offering Kerberos V5, and
165 * getting it accepted.
168 dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
170 dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint16 token_id);
172 dissect_spnego_krb5_cfx_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
174 dissect_spnego_krb5_cfx_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint16 token_id);
177 dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
184 gssapi_oid_value *value;
187 gboolean pc, ind = 0;
191 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
193 item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, offset,
196 subtree = proto_item_add_subtree(item, ett_spnego_krb5);
199 * The KRB5 blob conforms to RFC1964:
202 * USHORT (0x0001 == AP-REQ, 0x0002 == AP-REP, 0x0003 == ERROR),
205 * However, for some protocols, the KRB5 blob starts at the SHORT
206 * and has no DER encoded header etc.
208 * It appears that for some other protocols the KRB5 blob is just
209 * a Kerberos message, with no [APPLICATION 0] header, no OID,
214 * If we see an [APPLICATION 0] HEADER, we show the OID and
215 * the USHORT, and then dissect the rest as a Kerberos message.
217 * If we see an [APPLICATION 14] or [APPLICATION 15] header,
218 * we assume it's an AP-REQ or AP-REP message, and dissect
219 * it all as a Kerberos message.
221 * Otherwise, we show the USHORT, and then dissect the rest
222 * as a Kerberos message.
226 * Get the first header ...
228 get_ber_identifier(tvb, offset, &class, &pc, &tag);
229 if (class == BER_CLASS_APP && pc) {
231 * [APPLICATION <tag>]
233 offset = dissect_ber_identifier(pinfo, subtree, tvb, offset, &class, &pc, &tag);
234 offset = dissect_ber_length(pinfo, subtree, tvb, offset, &len, &ind);
244 offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, subtree, tvb, offset, hf_spnego_krb5_oid, &oid);
246 value = gssapi_lookup_oid_str(oid);
248 token_id = tvb_get_letohs(tvb, offset);
249 proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
256 case 14: /* [APPLICATION 14] */
257 case 15: /* [APPLICATION 15] */
259 * No token ID - just dissect as a Kerberos message and
262 offset = dissect_kerberos_main(tvb, pinfo, subtree, FALSE, NULL);
266 proto_tree_add_text(subtree, tvb, offset, 0,
267 "Unknown header (class=%d, pc=%d, tag=%d)",
272 /* Next, the token ID ... */
274 token_id = tvb_get_letohs(tvb, offset);
275 proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
283 case KRB_TOKEN_AP_REQ:
284 case KRB_TOKEN_AP_REP:
285 case KRB_TOKEN_AP_ERR:
286 krb5_tvb = tvb_new_subset(tvb, offset, -1, -1);
287 offset = dissect_kerberos_main(krb5_tvb, pinfo, subtree, FALSE, NULL);
290 case KRB_TOKEN_GETMIC:
291 offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
295 offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
298 case KRB_TOKEN_DELETE_SEC_CONTEXT:
302 case KRB_TOKEN_CFX_GETMIC:
303 offset = dissect_spnego_krb5_cfx_getmic_base(tvb, offset, pinfo, subtree);
306 case KRB_TOKEN_CFX_WRAP:
307 offset = dissect_spnego_krb5_cfx_wrap_base(tvb, offset, pinfo, subtree, token_id);
316 proto_item_set_len(item, offset);
321 #include <epan/crypt/crypt-md5.h>
323 #ifndef KEYTYPE_ARCFOUR_56
324 # define KEYTYPE_ARCFOUR_56 24
326 /* XXX - We should probably do a configure-time check for this instead */
327 #ifndef KRB5_KU_USAGE_SEAL
328 # define KRB5_KU_USAGE_SEAL 22
332 arcfour_mic_key(void *key_data, size_t key_size, int key_type,
333 void *cksum_data, size_t cksum_size,
341 if (key_type == KEYTYPE_ARCFOUR_56) {
342 guint8 L40[14] = "fortybits";
344 memcpy(L40 + 10, T, sizeof(T));
350 memset(&k5_data[7], 0xAB, 9);
360 cksum_data, cksum_size,
369 usage2arcfour(int usage)
372 case 3: /*KRB5_KU_AS_REP_ENC_PART 3 */
373 case 9: /*KRB5_KU_TGS_REP_ENC_PART_SUB_KEY 9 */
375 case 22: /*KRB5_KU_USAGE_SEAL 22 */
377 case 23: /*KRB5_KU_USAGE_SIGN 23 */
379 case 24: /*KRB5_KU_USAGE_SEQ 24 */
387 arcfour_mic_cksum(guint8 *key_data, int key_length,
390 const void *v1, size_t l1,
391 const void *v2, size_t l2,
392 const void *v3, size_t l3)
394 const guint8 signature[] = "signaturekey";
398 unsigned char digest[16];
402 rc4_usage=usage2arcfour(usage);
403 md5_hmac(signature, sizeof(signature),
404 key_data, key_length,
407 t[0] = (rc4_usage >> 0) & 0xFF;
408 t[1] = (rc4_usage >> 8) & 0xFF;
409 t[2] = (rc4_usage >> 16) & 0xFF;
410 t[3] = (rc4_usage >> 24) & 0xFF;
411 md5_append(&ms, t, 4);
412 md5_append(&ms, v1, l1);
413 md5_append(&ms, v2, l2);
414 md5_append(&ms, v3, l3);
415 md5_finish(&ms, digest);
416 md5_hmac(digest, 16, ksign_c, 16, cksum);
418 memcpy(sgn_cksum, cksum, 8);
424 * Verify padding of a gss wrapped message and return its length.
427 gssapi_verify_pad(unsigned char *wrapped_data, int wrapped_length,
435 pad = wrapped_data + wrapped_length - 1;
438 if (padlength > datalen)
441 for (i = padlength; i > 0 && *pad == padlength; i--, pad--)
452 decrypt_arcfour(packet_info *pinfo,
453 guint8 *input_message_buffer,
454 guint8 *output_message_buffer,
455 guint8 *key_value, int key_size, int key_type)
457 guint8 Klocaldata[16];
463 guint8 Confounder[8];
464 guint8 cksum_data[8];
469 datalen = tvb_length(pinfo->gssapi_encrypted_tvb);
471 if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0x1000){
473 } else if (tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 4)==0xffff){
479 if(tvb_get_ntohs(pinfo->gssapi_wrap_tvb, 6)!=0xffff){
483 ret = arcfour_mic_key(key_value, key_size, key_type,
484 (void *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
492 rc4_state_struct rc4_state;
494 crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
495 memcpy(SND_SEQ, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 8, 8), 8);
496 crypt_rc4(&rc4_state, (unsigned char *)SND_SEQ, 8);
498 memset(k6_data, 0, sizeof(k6_data));
501 seq_number=g_ntohl(SND_SEQ[0]);
503 if (SND_SEQ[1] != 0xFFFFFFFF && SND_SEQ[1] != 0x00000000) {
510 for (i = 0; i < 16; i++)
511 Klocaldata[i] = ((guint8 *)key_value)[i] ^ 0xF0;
513 ret = arcfour_mic_key(Klocaldata,sizeof(Klocaldata),key_type,
514 (unsigned char *)SND_SEQ, 4,
516 memset(Klocaldata, 0, sizeof(Klocaldata));
522 rc4_state_struct rc4_state;
524 crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
525 memcpy(Confounder, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8), 8);
526 crypt_rc4(&rc4_state, Confounder, 8);
527 memcpy(output_message_buffer, input_message_buffer, datalen);
528 crypt_rc4(&rc4_state, output_message_buffer, datalen);
531 tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8),
533 memcpy(output_message_buffer,
534 input_message_buffer,
537 memset(k6_data, 0, sizeof(k6_data));
539 /* only normal (i.e. non DCE style wrapping use padding ? */
540 if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
541 ret = gssapi_verify_pad(output_message_buffer,datalen,datalen, &padlen);
548 /* dont know what the checksum looks like for dce style gssapi */
549 if(pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_NORMAL){
550 ret = arcfour_mic_cksum(key_value, key_size,
553 tvb_get_ptr(pinfo->gssapi_wrap_tvb, 0, 8), 8,
554 Confounder, sizeof(Confounder),
555 output_message_buffer,
561 cmp = memcmp(cksum_data,
562 tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
574 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
577 decrypt_gssapi_krb_arcfour_wrap(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int keytype)
582 const guint8 *original_data;
584 static int omb_index=0;
585 static guint8 *omb_arr[4]={NULL,NULL,NULL,NULL};
586 static guint8 *cryptocopy=NULL; /* workaround for pre-0.6.1 heimdal bug */
587 guint8 *output_message_buffer;
593 output_message_buffer=omb_arr[omb_index];
596 length=tvb_length(pinfo->gssapi_encrypted_tvb);
597 original_data=tvb_get_ptr(pinfo->gssapi_encrypted_tvb, 0, length);
599 /* dont do anything if we are not attempting to decrypt data */
605 /* XXX we should only do this for first time, then store somewhere */
606 /* XXX We also need to re-read the keytab when the preference changes */
608 cryptocopy=ep_alloc(length);
609 if(output_message_buffer){
610 g_free(output_message_buffer);
611 output_message_buffer=NULL;
613 output_message_buffer=g_malloc(length);
615 for(ek=enc_key_list;ek;ek=ek->next){
616 /* shortcircuit and bail out if enctypes are not matching */
617 if(ek->keytype!=keytype){
621 /* pre-0.6.1 versions of Heimdal would sometimes change
622 the cryptotext data even when the decryption failed.
623 This would obviously not work since we iterate over the
624 keys. So just give it a copy of the crypto data instead.
625 This has been seen for RC4-HMAC blobs.
627 memcpy(cryptocopy, original_data, length);
628 ret=decrypt_arcfour(pinfo,
630 output_message_buffer,
636 proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
637 pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(tvb,
638 output_message_buffer,
640 add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
647 /* borrowed from heimdal */
649 rrc_rotate(void *data, int len, guint16 rrc, int unrotate)
651 unsigned char *tmp, buf[256];
664 if (rrc <= sizeof(buf)) {
673 memcpy(tmp, data, rrc);
674 memmove(data, (unsigned char *)data + rrc, left);
675 memcpy((unsigned char *)data + left, tmp, rrc);
677 memcpy(tmp, (unsigned char *)data + left, rrc);
678 memmove((unsigned char *)data + rrc, data, left);
679 memcpy(data, tmp, rrc);
682 if (rrc > sizeof(buf))
689 #define KRB5_KU_USAGE_ACCEPTOR_SEAL 22
690 #define KRB5_KU_USAGE_ACCEPTOR_SIGN 23
691 #define KRB5_KU_USAGE_INITIATOR_SEAL 24
692 #define KRB5_KU_USAGE_INITIATOR_SIGN 25
695 decrypt_gssapi_krb_cfx_wrap(proto_tree *tree _U_,
697 tvbuff_t *checksum_tvb,
698 tvbuff_t *encrypted_tvb,
710 /* dont do anything if we are not attempting to decrypt data */
715 datalen = tvb_length(checksum_tvb) + tvb_length(encrypted_tvb);
716 rotated = ep_alloc(datalen);
718 tvb_memcpy(checksum_tvb, rotated,
719 0, tvb_length(checksum_tvb));
720 tvb_memcpy(encrypted_tvb, rotated + tvb_length(checksum_tvb),
721 0, tvb_length(encrypted_tvb));
727 res = rrc_rotate(rotated, datalen, rrc, TRUE);
729 output = decrypt_krb5_data(tree, pinfo, usage, datalen,
730 rotated, keytype, &datalen);
735 outdata = ep_alloc(tvb_length(encrypted_tvb));
736 memcpy(outdata, output, tvb_length(encrypted_tvb));
739 pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(encrypted_tvb,
741 tvb_length(encrypted_tvb),
742 tvb_length(encrypted_tvb));
743 add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
749 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
755 * This is for GSSAPI Wrap tokens ...
758 dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
759 #ifndef HAVE_KERBEROS
762 , proto_tree *tree, guint16 token_id
763 #ifndef HAVE_KERBEROS
768 guint16 sgn_alg, seal_alg;
770 int start_offset=offset;
774 * The KRB5 blob conforms to RFC1964:
775 * USHORT (0x0102 == GSS_Wrap)
779 /* Now, the sign and seal algorithms ... */
781 sgn_alg = tvb_get_letohs(tvb, offset);
782 proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
787 seal_alg = tvb_get_letohs(tvb, offset);
788 proto_tree_add_uint(tree, hf_spnego_krb5_seal_alg, tvb, offset, 2,
793 /* Skip the filler */
797 /* Encrypted sequence number */
799 proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
804 /* Checksum of plaintext padded data */
806 proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
812 * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
813 * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
814 * extra 8 bytes of "Random confounder" after the checksum.
815 * It certainly confounds code expecting all Kerberos 5
816 * GSS_Wrap() tokens to look the same....
818 if ((sgn_alg == KRB_SGN_ALG_HMAC) ||
819 /* there also seems to be a confounder for DES MAC MD5 - certainly seen when using with
820 SASL with LDAP between a Java client and Active Directory. If this breaks other things
821 we may need to make this an option. gal 17/2/06 */
822 (sgn_alg == KRB_SGN_ALG_DES_MAC_MD5)) {
823 proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
828 /* Is the data encrypted? */
829 pinfo->gssapi_data_encrypted=(seal_alg!=KRB_SEAL_ALG_NONE);
832 #define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
833 if(pinfo->decrypt_gssapi_tvb){
834 /* if the caller did not provide a tvb, then we just use
835 whatever is left of our current tvb.
837 if(!pinfo->gssapi_encrypted_tvb){
839 len=tvb_reported_length_remaining(tvb,offset);
840 if(len>tvb_length_remaining(tvb, offset)){
841 /* no point in trying to decrypt,
842 we dont have the full pdu.
846 pinfo->gssapi_encrypted_tvb = tvb_new_subset(
847 tvb, offset, len, len);
850 /* if this is KRB5 wrapped rc4-hmac */
851 if((token_id==KRB_TOKEN_WRAP)
852 &&(sgn_alg==KRB_SGN_ALG_HMAC)
853 &&(seal_alg==KRB_SEAL_ALG_RC4)){
854 /* do we need to create a tvb for the wrapper
857 if(!pinfo->gssapi_wrap_tvb){
858 pinfo->gssapi_wrap_tvb = tvb_new_subset(
860 GSS_ARCFOUR_WRAP_TOKEN_SIZE,
861 GSS_ARCFOUR_WRAP_TOKEN_SIZE);
863 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
864 decrypt_gssapi_krb_arcfour_wrap(tree,
868 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
873 * Return the offset past the checksum, so that we know where
874 * the data we're wrapped around starts. Also, set the length
875 * of our top-level item to that offset, so it doesn't cover
876 * the data we're wrapped around.
878 * Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
885 * XXX - This is for GSSAPI GetMIC tokens ...
888 dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
893 * The KRB5 blob conforms to RFC1964:
894 * USHORT (0x0101 == GSS_GetMIC)
898 /* Now, the sign algorithm ... */
900 sgn_alg = tvb_get_letohs(tvb, offset);
901 proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
906 /* Skip the filler */
910 /* Encrypted sequence number */
912 proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
917 /* Checksum of plaintext padded data */
919 proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
925 * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
926 * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
927 * extra 8 bytes of "Random confounder" after the checksum.
928 * It certainly confounds code expecting all Kerberos 5
929 * GSS_Wrap() tokens to look the same....
931 * The exception is DNS/TSIG where there is no such confounder
932 * so we need to test here if there are more bytes in our tvb or not.
935 if (tvb_length_remaining(tvb, offset)) {
936 if (sgn_alg == KRB_SGN_ALG_HMAC) {
937 proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
945 * Return the offset past the checksum, so that we know where
946 * the data we're wrapped around starts. Also, set the length
947 * of our top-level item to that offset, so it doesn't cover
948 * the data we're wrapped around.
955 dissect_spnego_krb5_cfx_flags(tvbuff_t *tvb, int offset,
956 proto_tree *spnego_krb5_tree,
959 proto_tree *cfx_flags_tree = NULL;
960 proto_item *tf = NULL;
962 if (spnego_krb5_tree) {
963 tf = proto_tree_add_uint(spnego_krb5_tree,
964 hf_spnego_krb5_cfx_flags,
965 tvb, offset, 1, cfx_flags);
966 cfx_flags_tree = proto_item_add_subtree(tf, ett_spnego_krb5_cfx_flags);
969 proto_tree_add_boolean(cfx_flags_tree,
970 hf_spnego_krb5_cfx_flags_04,
971 tvb, offset, 1, cfx_flags);
972 proto_tree_add_boolean(cfx_flags_tree,
973 hf_spnego_krb5_cfx_flags_02,
974 tvb, offset, 1, cfx_flags);
975 proto_tree_add_boolean(cfx_flags_tree,
976 hf_spnego_krb5_cfx_flags_01,
977 tvb, offset, 1, cfx_flags);
983 * This is for GSSAPI CFX Wrap tokens ...
986 dissect_spnego_krb5_cfx_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
987 #ifndef HAVE_KERBEROS
990 , proto_tree *tree, guint16 token_id _U_
997 int start_offset=offset;
1000 * The KRB5 blob conforms to RFC4121:
1005 /* Now, the sign and seal algorithms ... */
1007 flags = tvb_get_guint8(tvb, offset);
1008 offset = dissect_spnego_krb5_cfx_flags(tvb, offset, tree, flags);
1010 pinfo->gssapi_data_encrypted=(flags & 2);
1012 /* Skip the filler */
1014 proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 1,
1019 ec = tvb_get_ntohs(tvb, offset);
1020 proto_tree_add_item(tree, hf_spnego_krb5_cfx_ec, tvb, offset, 2,
1025 rrc = tvb_get_ntohs(tvb, offset);
1026 proto_tree_add_item(tree, hf_spnego_krb5_cfx_rrc, tvb, offset, 2,
1030 /* sequence number */
1032 proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
1036 /* Checksum of plaintext padded data */
1038 if (pinfo->gssapi_data_encrypted) {
1039 checksum_size = 44 + ec;
1044 proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
1045 checksum_size, FALSE);
1046 offset += checksum_size;
1048 if(pinfo->decrypt_gssapi_tvb){
1049 /* if the caller did not provide a tvb, then we just use
1050 whatever is left of our current tvb.
1052 if(!pinfo->gssapi_encrypted_tvb){
1054 len=tvb_reported_length_remaining(tvb,offset);
1055 if(len>tvb_length_remaining(tvb, offset)){
1056 /* no point in trying to decrypt,
1057 we dont have the full pdu.
1061 pinfo->gssapi_encrypted_tvb = tvb_new_subset(
1062 tvb, offset, len, len);
1065 if (pinfo->gssapi_data_encrypted) {
1066 /* do we need to create a tvb for the wrapper
1069 if(!pinfo->gssapi_wrap_tvb){
1070 pinfo->gssapi_wrap_tvb = tvb_new_subset(
1071 tvb, start_offset-2,
1072 offset - (start_offset-2),
1073 offset - (start_offset-2));
1078 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
1080 tvbuff_t *checksum_tvb = tvb_new_subset(tvb, 16, checksum_size, checksum_size);
1082 if (pinfo->gssapi_data_encrypted) {
1083 if(pinfo->gssapi_encrypted_tvb){
1084 decrypt_gssapi_krb_cfx_wrap(tree,
1087 pinfo->gssapi_encrypted_tvb,
1090 (pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_DCE)?TRUE:FALSE,
1093 KRB5_KU_USAGE_ACCEPTOR_SEAL:
1094 KRB5_KU_USAGE_INITIATOR_SEAL);
1098 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1101 * Return the offset past the checksum, so that we know where
1102 * the data we're wrapped around starts. Also, set the length
1103 * of our top-level item to that offset, so it doesn't cover
1104 * the data we're wrapped around.
1106 * Note that for DCERPC the GSSAPI blobs comes after the data it wraps,
1113 * XXX - This is for GSSAPI CFX GetMIC tokens ...
1116 dissect_spnego_krb5_cfx_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
1122 * The KRB5 blob conforms to RFC4121:
1123 * USHORT (0x0404 == GSS_GetMIC)
1127 flags = tvb_get_guint8(tvb, offset);
1128 offset = dissect_spnego_krb5_cfx_flags(tvb, offset, tree, flags);
1130 /* Skip the filler */
1132 proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 5,
1136 /* sequence number */
1138 proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
1142 /* Checksum of plaintext padded data */
1144 checksum_size = tvb_length_remaining(tvb, offset);
1146 proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
1147 checksum_size, FALSE);
1148 offset += checksum_size;
1151 * Return the offset past the checksum, so that we know where
1152 * the data we're wrapped around starts. Also, set the length
1153 * of our top-level item to that offset, so it doesn't cover
1154 * the data we're wrapped around.
1161 * XXX - is this for SPNEGO or just GSS-API?
1162 * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
1163 * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
1164 * than designating SPNEGO as the mechanism, offering Kerberos V5, and
1165 * getting it accepted.
1168 dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1171 proto_tree *subtree;
1175 item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, 0, -1, FALSE);
1177 subtree = proto_item_add_subtree(item, ett_spnego_krb5);
1180 * The KRB5 blob conforms to RFC1964:
1181 * USHORT (0x0102 == GSS_Wrap)
1185 /* First, the token ID ... */
1187 token_id = tvb_get_letohs(tvb, offset);
1188 proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
1194 case KRB_TOKEN_GETMIC:
1195 offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
1198 case KRB_TOKEN_WRAP:
1199 offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree, token_id);
1202 case KRB_TOKEN_CFX_GETMIC:
1203 offset = dissect_spnego_krb5_cfx_getmic_base(tvb, offset, pinfo, subtree);
1206 case KRB_TOKEN_CFX_WRAP:
1207 offset = dissect_spnego_krb5_cfx_wrap_base(tvb, offset, pinfo, subtree, token_id);
1216 * Return the offset past the checksum, so that we know where
1217 * the data we're wrapped around starts. Also, set the length
1218 * of our top-level item to that offset, so it doesn't cover
1219 * the data we're wrapped around.
1221 proto_item_set_len(item, offset);
1225 /* Spnego stuff from here */
1228 dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1231 proto_tree *subtree;
1233 asn1_ctx_t asn1_ctx;
1234 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1239 * We need this later, so lets get it now ...
1240 * It has to be per-frame as there can be more than one GSS-API
1241 * negotiation in a conversation.
1245 item = proto_tree_add_item(tree, hf_spnego, tvb, offset,
1248 subtree = proto_item_add_subtree(item, ett_spnego);
1250 * The TVB contains a [0] header and a sequence that consists of an
1251 * object ID and a blob containing the data ...
1252 * XXX - is this RFC 2743's "Mechanism-Independent Token Format",
1253 * with the "optional" "use in non-initial tokens" being chosen.
1254 * ASN1 code addet to spnego.asn to handle this.
1257 offset = dissect_spnego_InitialContextToken(FALSE, tvb, offset, &asn1_ctx , subtree, -1);
1264 dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
1267 proto_tree *subtree;
1269 conversation_t *conversation;
1270 asn1_ctx_t asn1_ctx;
1271 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1274 * We need this later, so lets get it now ...
1275 * It has to be per-frame as there can be more than one GSS-API
1276 * negotiation in a conversation.
1278 next_level_value = p_get_proto_data(pinfo->fd, proto_spnego);
1279 if (!next_level_value && !pinfo->fd->flags.visited) {
1281 * No handle attached to this frame, but it's the first
1282 * pass, so it'd be attached to the conversation.
1283 * If we have a conversation, try to get the handle,
1284 * and if we get one, attach it to the frame.
1286 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1287 pinfo->ptype, pinfo->srcport,
1288 pinfo->destport, 0);
1291 next_level_value = conversation_get_proto_data(conversation,
1293 if (next_level_value)
1294 p_add_proto_data(pinfo->fd, proto_spnego, next_level_value);
1298 item = proto_tree_add_item(parent_tree, hf_spnego, tvb, offset,
1301 subtree = proto_item_add_subtree(item, ett_spnego);
1304 * The TVB contains a [0] header and a sequence that consists of an
1305 * object ID and a blob containing the data ...
1306 * Actually, it contains, according to RFC2478:
1307 * NegotiationToken ::= CHOICE {
1308 * negTokenInit [0] NegTokenInit,
1309 * negTokenTarg [1] NegTokenTarg }
1310 * NegTokenInit ::= SEQUENCE {
1311 * mechTypes [0] MechTypeList OPTIONAL,
1312 * reqFlags [1] ContextFlags OPTIONAL,
1313 * mechToken [2] OCTET STRING OPTIONAL,
1314 * mechListMIC [3] OCTET STRING OPTIONAL }
1315 * NegTokenTarg ::= SEQUENCE {
1316 * negResult [0] ENUMERATED {
1317 * accept_completed (0),
1318 * accept_incomplete (1),
1319 * reject (2) } OPTIONAL,
1320 * supportedMech [1] MechType OPTIONAL,
1321 * responseToken [2] OCTET STRING OPTIONAL,
1322 * mechListMIC [3] OCTET STRING OPTIONAL }
1324 * Windows typically includes mechTypes and mechListMic ('NONE'
1325 * in the case of NTLMSSP only).
1326 * It seems to duplicate the responseToken into the mechListMic field
1327 * as well. Naughty, naughty.
1330 offset = dissect_spnego_NegotiationToken(FALSE, tvb, offset, &asn1_ctx, subtree, -1);
1334 /*--- proto_register_spnego -------------------------------------------*/
1335 void proto_register_spnego(void) {
1337 /* List of fields */
1338 static hf_register_info hf[] = {
1340 { "SPNEGO", "spnego", FT_NONE, BASE_NONE, NULL, 0x0,
1342 { &hf_spnego_wraptoken,
1343 { "wrapToken", "spnego.wraptoken",
1344 FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO wrapToken",
1347 { "krb5_blob", "spnego.krb5.blob", FT_BYTES,
1348 BASE_NONE, NULL, 0, NULL, HFILL }},
1349 { &hf_spnego_krb5_oid,
1350 { "KRB5 OID", "spnego.krb5_oid", FT_STRING,
1351 BASE_NONE, NULL, 0, NULL, HFILL }},
1352 { &hf_spnego_krb5_tok_id,
1353 { "krb5_tok_id", "spnego.krb5.tok_id", FT_UINT16, BASE_HEX,
1354 VALS(spnego_krb5_tok_id_vals), 0, "KRB5 Token Id", HFILL}},
1355 { &hf_spnego_krb5_sgn_alg,
1356 { "krb5_sgn_alg", "spnego.krb5.sgn_alg", FT_UINT16, BASE_HEX,
1357 VALS(spnego_krb5_sgn_alg_vals), 0, "KRB5 Signing Algorithm", HFILL}},
1358 { &hf_spnego_krb5_seal_alg,
1359 { "krb5_seal_alg", "spnego.krb5.seal_alg", FT_UINT16, BASE_HEX,
1360 VALS(spnego_krb5_seal_alg_vals), 0, "KRB5 Sealing Algorithm", HFILL}},
1361 { &hf_spnego_krb5_snd_seq,
1362 { "krb5_snd_seq", "spnego.krb5.snd_seq", FT_BYTES, BASE_NONE,
1363 NULL, 0, "KRB5 Encrypted Sequence Number", HFILL}},
1364 { &hf_spnego_krb5_sgn_cksum,
1365 { "krb5_sgn_cksum", "spnego.krb5.sgn_cksum", FT_BYTES, BASE_NONE,
1366 NULL, 0, "KRB5 Data Checksum", HFILL}},
1367 { &hf_spnego_krb5_confounder,
1368 { "krb5_confounder", "spnego.krb5.confounder", FT_BYTES, BASE_NONE,
1369 NULL, 0, "KRB5 Confounder", HFILL}},
1370 { &hf_spnego_krb5_filler,
1371 { "krb5_filler", "spnego.krb5.filler", FT_BYTES, BASE_NONE,
1372 NULL, 0, "KRB5 Filler", HFILL}},
1373 { &hf_spnego_krb5_cfx_flags,
1374 { "krb5_cfx_flags", "spnego.krb5.cfx_flags", FT_UINT8, BASE_HEX,
1375 NULL, 0, "KRB5 CFX Flags", HFILL}},
1376 { &hf_spnego_krb5_cfx_flags_01,
1377 { "SendByAcceptor", "spnego.krb5.send_by_acceptor", FT_BOOLEAN, 8,
1378 TFS (&tfs_set_notset), 0x01, NULL, HFILL}},
1379 { &hf_spnego_krb5_cfx_flags_02,
1380 { "Sealed", "spnego.krb5.sealed", FT_BOOLEAN, 8,
1381 TFS (&tfs_set_notset), 0x02, NULL, HFILL}},
1382 { &hf_spnego_krb5_cfx_flags_04,
1383 { "AcceptorSubkey", "spnego.krb5.acceptor_subkey", FT_BOOLEAN, 8,
1384 TFS (&tfs_set_notset), 0x04, NULL, HFILL}},
1385 { &hf_spnego_krb5_cfx_ec,
1386 { "krb5_cfx_ec", "spnego.krb5.cfx_ec", FT_UINT16, BASE_DEC,
1387 NULL, 0, "KRB5 CFX Extra Count", HFILL}},
1388 { &hf_spnego_krb5_cfx_rrc,
1389 { "krb5_cfx_rrc", "spnego.krb5.cfx_rrc", FT_UINT16, BASE_DEC,
1390 NULL, 0, "KRB5 CFX Right Rotation Count", HFILL}},
1391 { &hf_spnego_krb5_cfx_seq,
1392 { "krb5_cfx_seq", "spnego.krb5.cfx_seq", FT_UINT64, BASE_DEC,
1393 NULL, 0, "KRB5 Sequence Number", HFILL}},
1395 #include "packet-spnego-hfarr.c"
1398 /* List of subtrees */
1399 static gint *ett[] = {
1401 &ett_spnego_wraptoken,
1403 &ett_spnego_krb5_cfx_flags,
1405 #include "packet-spnego-ettarr.c"
1408 /* Register protocol */
1409 proto_spnego = proto_register_protocol(PNAME, PSNAME, PFNAME);
1411 register_dissector("spnego", dissect_spnego, proto_spnego);
1413 proto_spnego_krb5 = proto_register_protocol("SPNEGO-KRB5",
1417 register_dissector("spnego-krb5", dissect_spnego_krb5, proto_spnego_krb5);
1418 new_register_dissector("spnego-krb5-wrap", dissect_spnego_krb5_wrap, proto_spnego_krb5);
1420 /* Register fields and subtrees */
1421 proto_register_field_array(proto_spnego, hf, array_length(hf));
1422 proto_register_subtree_array(ett, array_length(ett));
1426 /*--- proto_reg_handoff_spnego ---------------------------------------*/
1427 void proto_reg_handoff_spnego(void) {
1429 dissector_handle_t spnego_handle, spnego_wrap_handle;
1430 dissector_handle_t spnego_krb5_handle, spnego_krb5_wrap_handle;
1432 /* Register protocol with GSS-API module */
1434 spnego_handle = find_dissector("spnego");
1435 spnego_wrap_handle = new_create_dissector_handle(dissect_spnego_wrap, proto_spnego);
1436 gssapi_init_oid("1.3.6.1.5.5.2", proto_spnego, ett_spnego,
1437 spnego_handle, spnego_wrap_handle,
1438 "SPNEGO - Simple Protected Negotiation");
1440 /* Register both the one MS created and the real one */
1442 * Thanks to Jean-Baptiste Marchand and Richard B Ward, the
1443 * mystery of the MS KRB5 OID is cleared up. It was due to a library
1444 * that did not handle OID components greater than 16 bits, and was
1445 * fixed in Win2K SP2 as well as WinXP.
1446 * See the archive of <ietf-krb-wg@anl.gov> for the thread topic
1447 * SPNEGO implementation issues. 3-Dec-2002.
1449 spnego_krb5_handle = find_dissector("spnego-krb5");
1450 spnego_krb5_wrap_handle = find_dissector("spnego-krb5-wrap");
1451 gssapi_init_oid("1.2.840.48018.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
1452 spnego_krb5_handle, spnego_krb5_wrap_handle,
1453 "MS KRB5 - Microsoft Kerberos 5");
1454 gssapi_init_oid("1.2.840.113554.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
1455 spnego_krb5_handle, spnego_krb5_wrap_handle,
1456 "KRB5 - Kerberos 5");
1457 gssapi_init_oid("1.2.840.113554.1.2.2.3", proto_spnego_krb5, ett_spnego_krb5,
1458 spnego_krb5_handle, spnego_krb5_wrap_handle,
1459 "KRB5 - Kerberos 5 - User to User");