X-Git-Url: http://git.samba.org/?p=metze%2Fwireshark%2Fwip.git;a=blobdiff_plain;f=epan%2Fdissectors%2Fasn1%2Fkerberos%2Fpacket-kerberos-template.c;h=87fbcbec236738ce3204c8c9c1d8615ddc8fd6d2;hp=3a51e59923da2534ad5f7399267c0ed30c90c32c;hb=eb864b3e37ae0b1e4a69bb45cd804063d5f6d95c;hpb=82d285ce117a4af3275e420f4d3f8097314049da;ds=sidebyside diff --git a/epan/dissectors/asn1/kerberos/packet-kerberos-template.c b/epan/dissectors/asn1/kerberos/packet-kerberos-template.c index 3a51e59923..87fbcbec23 100644 --- a/epan/dissectors/asn1/kerberos/packet-kerberos-template.c +++ b/epan/dissectors/asn1/kerberos/packet-kerberos-template.c @@ -59,6 +59,7 @@ #include #include #include +#include #include "packet-kerberos.h" #include "packet-netbios.h" #include "packet-tcp.h" @@ -356,6 +357,36 @@ add_encryption_key(packet_info *pinfo, int keytype, int keylength, const char *k new_key->keyvalue=(char *)g_memdup(keyvalue, keylength); } +static void used_encryption_key(proto_tree *tree, packet_info *pinfo, + enc_key_t *ek, int usage, tvbuff_t *cryptotvb) +{ + kerberos_private_data_t *private_data = kerberos_get_private_data_p(pinfo); + + proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_decrypted_keytype, + cryptotvb, 0, 0, + "Decrypted keytype %d usage %d in frame %u " + "using %s (%02x%02x%02x%02x...)", + ek->keytype, pinfo->fd->num, usage, ek->key_origin, + ek->keyvalue[0] & 0xFF, ek->keyvalue[1] & 0xFF, + ek->keyvalue[2] & 0xFF, ek->keyvalue[3] & 0xFF); + + private_data->last_decryption_key = ek; +} + +static void used_signing_key(proto_tree *tree, packet_info *pinfo, + enc_key_t *ek, tvbuff_t *tvb, + krb5_cksumtype checksum, + const char *reason) +{ + proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_decrypted_keytype, + tvb, 0, 0, + "%s checksum %d keytype %d in frame %u " + "using %s (%02x%02x%02x%02x...)", + reason, checksum, ek->keytype, pinfo->fd->num, ek->key_origin, + ek->keyvalue[0] & 0xFF, ek->keyvalue[1] & 0xFF, + ek->keyvalue[2] & 0xFF, ek->keyvalue[3] & 0xFF); +} + static void krb5_fast_key(packet_info *pinfo, const enc_key_t *ek1, const char *p1, @@ -601,11 +632,7 @@ decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo, p1); krb5_free_keyblock(krb5_ctx, k); ek = enc_key_list; - proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_decrypted_keytype, - cryptotvb, 0, 0, - "Decrypted keytype %d in frame %u using %s", - ek->keytype, pinfo->fd->num, ek->key_origin); - private_data->last_decryption_key = ek; + used_encryption_key(tree, pinfo, ek, usage, cryptotvb); /* return a private g_malloced blob to the caller */ user_data=data.data; @@ -650,11 +677,7 @@ decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo, "strengthenkey"); krb5_free_keyblock(krb5_ctx, k); ek = enc_key_list; - proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_decrypted_keytype, - cryptotvb, 0, 0, - "Decrypted keytype %d in frame %u using %s", - ek->keytype, pinfo->fd->num, ek->key_origin); - private_data->last_decryption_key = ek; + used_encryption_key(tree, pinfo, ek, usage, cryptotvb); /* return a private g_malloced blob to the caller */ user_data=data.data; @@ -675,11 +698,7 @@ decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo, if(ret == 0){ char *user_data; - proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_decrypted_keytype, - cryptotvb, 0, 0, - "Decrypted keytype %d in frame %u using %s", - ek->keytype, pinfo->num, ek->key_origin); - private_data->last_decryption_key = ek; + used_encryption_key(tree, pinfo, ek, usage, cryptotvb); user_data=data.data; if (datalen) { @@ -693,6 +712,101 @@ decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo, } USES_APPLE_RST +extern krb5_error_code +krb5int_c_mandatory_cksumtype(krb5_context, krb5_enctype, krb5_cksumtype *); + +static void +verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb) +{ + krb5_error_code ret; + enc_key_t *ek = NULL;; + krb5_data checksum_data = {0,0,NULL}; + krb5_cksumtype server_checksum = 0; + krb5_cksumtype kdc_checksum = 0; + int length = tvb_captured_length(pactvb); + const guint8 *pacbuffer = NULL; + krb5_pac pac; + + /* don't do anything if we are not attempting to decrypt data */ + if(!krb_decrypt || length < 1){ + return; + } + + /* make sure we have all the data we need */ + if (tvb_captured_length(pactvb) < tvb_reported_length(pactvb)) { + return; + } + + pacbuffer = tvb_get_ptr(pactvb, 0, length); + + ret = krb5_pac_parse(krb5_ctx, pacbuffer, length, &pac); + if (ret != 0) { + proto_tree_add_expert_format(tree, actx->pinfo, &ei_kerberos_decrypted_keytype, + pactvb, 0, 0, + "Failed to parse PAC buffer %d in frame %u", + ret, actx->pinfo->fd->num); + return; + } + + ret = krb5_pac_get_buffer(krb5_ctx, pac, KRB5_PAC_SERVER_CHECKSUM, + &checksum_data); + if (ret == 0) { + server_checksum = pletoh32(checksum_data.data); + krb5_free_data_contents(krb5_ctx, &checksum_data); + }; + ret = krb5_pac_get_buffer(krb5_ctx, pac, KRB5_PAC_PRIVSVR_CHECKSUM, + &checksum_data); + if (ret == 0) { + kdc_checksum = pletoh32(checksum_data.data); + krb5_free_data_contents(krb5_ctx, &checksum_data); + }; + + read_keytab_file_from_preferences(); + + for(ek=enc_key_list;ek;ek=ek->next){ + krb5_keyblock keyblock; + krb5_cksumtype checksumtype = 0; + + if (server_checksum == 0 && kdc_checksum == 0) { + break; + } + + ret = krb5int_c_mandatory_cksumtype(krb5_ctx, ek->keytype, + &checksumtype); + if (ret != 0) { + continue; + } + + keyblock.magic = KV5M_KEYBLOCK; + keyblock.enctype = ek->keytype; + keyblock.length = ek->keylength; + keyblock.contents = (guint8 *)ek->keyvalue; + + if (checksumtype == server_checksum) { + ret = krb5_pac_verify(krb5_ctx, pac, 0, NULL, + &keyblock, NULL); + if (ret == 0) { + used_signing_key(tree, actx->pinfo, ek, pactvb, + server_checksum, "Verified Server"); + server_checksum = 0; + } + } + + if (checksumtype == kdc_checksum) { + ret = krb5_pac_verify(krb5_ctx, pac, 0, NULL, + NULL, &keyblock); + if (ret == 0) { + used_signing_key(tree, actx->pinfo, ek, pactvb, + kdc_checksum, "Verified KDC"); + kdc_checksum = 0; + } + } + + } + + krb5_pac_free(krb5_ctx, pac); +} + #elif defined(HAVE_HEIMDAL_KERBEROS) static krb5_context krb5_ctx; @@ -2292,6 +2406,10 @@ dissect_krb5_AD_WIN2K_PAC(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, guint32 version; guint32 i; +#ifdef HAVE_KERBEROS + verify_krb5_pac(tree, actx, tvb); +#endif + /* first in the PAC structure comes the number of entries */ entries=tvb_get_letohl(tvb, offset); proto_tree_add_uint(tree, hf_krb_w2k_pac_entries, tvb, offset, 4, entries);