diff options
author | Stefan Metzmacher <metze@samba.org> | 2020-05-21 03:10:27 +0200 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2020-05-26 08:28:46 +0000 |
commit | 0b7dd5720d0554f5311b625f88d4d4ccbcc3d3d2 (patch) | |
tree | fbf831cab9f97a2553160206c513e2522bce3911 /epan/dissectors/asn1 | |
parent | 4caaba64b2d17162155b219cf860c2269850ce61 (diff) |
packet-kerberos: let verify_krb5_pac() use kerberos_longterm_keys
Here it's enough to try longterm keys from the keytab.
Change-Id: I4d98fd7aa456c5cf2ca175cdcefc0ad1a4a8be2d
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-on: https://code.wireshark.org/review/37286
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/asn1')
-rw-r--r-- | epan/dissectors/asn1/kerberos/packet-kerberos-template.c | 132 |
1 files changed, 83 insertions, 49 deletions
diff --git a/epan/dissectors/asn1/kerberos/packet-kerberos-template.c b/epan/dissectors/asn1/kerberos/packet-kerberos-template.c index 046f71d70f..515e397981 100644 --- a/epan/dissectors/asn1/kerberos/packet-kerberos-template.c +++ b/epan/dissectors/asn1/kerberos/packet-kerberos-template.c @@ -1082,17 +1082,80 @@ decrypt_krb5_krb_cfx_dce(proto_tree *tree, extern krb5_error_code krb5int_c_mandatory_cksumtype(krb5_context, krb5_enctype, krb5_cksumtype *); +struct verify_krb5_pac_state { + krb5_pac pac; + krb5_cksumtype server_checksum; + enc_key_t *server_ek; + krb5_cksumtype kdc_checksum; + enc_key_t *kdc_ek; +}; + +static void +verify_krb5_pac_try_key(gpointer __key _U_, gpointer value, gpointer userdata) +{ + struct verify_krb5_pac_state *state = + (struct verify_krb5_pac_state *)userdata; + enc_key_t *ek = (enc_key_t *)value; + krb5_keyblock keyblock; + krb5_cksumtype checksumtype = 0; + krb5_error_code ret; + + if (state->server_checksum == 0 && state->kdc_checksum == 0) { + /* + * nothing more todo, stop traversing. + */ + return; + } + + if (state->server_ek != NULL && state->kdc_ek != NULL) { + /* + * we're done. + */ + return; + } + + ret = krb5int_c_mandatory_cksumtype(krb5_ctx, ek->keytype, + &checksumtype); + if (ret != 0) { + /* + * the key is not usable, keep traversing. + * try the next key... + */ + return; + } + + keyblock.magic = KV5M_KEYBLOCK; + keyblock.enctype = ek->keytype; + keyblock.length = ek->keylength; + keyblock.contents = (guint8 *)ek->keyvalue; + + if (checksumtype == state->server_checksum && state->server_ek == NULL) { + ret = krb5_pac_verify(krb5_ctx, state->pac, 0, NULL, + &keyblock, NULL); + if (ret == 0) { + state->server_ek = ek; + } + } + + if (checksumtype == state->kdc_checksum && state->kdc_ek == NULL) { + ret = krb5_pac_verify(krb5_ctx, state->pac, 0, NULL, + NULL, &keyblock); + if (ret == 0) { + state->kdc_ek = ek; + } + } +} + 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; + struct verify_krb5_pac_state state = { + .kdc_checksum = 0, + }; /* don't do anything if we are not attempting to decrypt data */ if(!krb_decrypt || length < 1){ @@ -1106,7 +1169,7 @@ verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb) pacbuffer = tvb_get_ptr(pactvb, 0, length); - ret = krb5_pac_parse(krb5_ctx, pacbuffer, length, &pac); + ret = krb5_pac_parse(krb5_ctx, pacbuffer, length, &state.pac); if (ret != 0) { proto_tree_add_expert_format(tree, actx->pinfo, &ei_kerberos_decrypted_keytype, pactvb, 0, 0, @@ -1115,63 +1178,34 @@ verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb) return; } - ret = krb5_pac_get_buffer(krb5_ctx, pac, KRB5_PAC_SERVER_CHECKSUM, + ret = krb5_pac_get_buffer(krb5_ctx, state.pac, KRB5_PAC_SERVER_CHECKSUM, &checksum_data); if (ret == 0) { - server_checksum = pletoh32(checksum_data.data); + state.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, + ret = krb5_pac_get_buffer(krb5_ctx, state.pac, KRB5_PAC_PRIVSVR_CHECKSUM, &checksum_data); if (ret == 0) { - kdc_checksum = pletoh32(checksum_data.data); + state.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; - } - } - + wmem_map_foreach(kerberos_longterm_keys, + verify_krb5_pac_try_key, + &state); + if (state.server_ek != NULL) { + used_signing_key(tree, actx->pinfo, state.server_ek, pactvb, + state.server_checksum, "Verified Server"); + } + if (state.kdc_ek != NULL) { + used_signing_key(tree, actx->pinfo, state.kdc_ek, pactvb, + state.kdc_checksum, "Verified KDC"); } - krb5_pac_free(krb5_ctx, pac); + krb5_pac_free(krb5_ctx, state.pac); } #endif /* HAVE_KRB5_PAC_VERIFY */ |