From f5858299a92520163ca5598e1caca4f68179b349 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 27 May 2020 09:59:45 +0200 Subject: [PATCH] packet-kerberos: maintain EncAPRepPart_subkey in a kerberos_app_session_keys map This improves the performance a lot if you have a keytab with a lot of entries (e.g. for a whole domain). GSSKRB5 decryption should only try the subkey of the AP-Rep. We could further optimize this and remember the key on the cenversation after the first success, but that's for another day. Change-Id: I405e41e7d90073d569fcbeec4b4188453a251000 Signed-off-by: Stefan Metzmacher Reviewed-on: https://code.wireshark.org/review/37323 Petri-Dish: Anders Broman Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- .../asn1/kerberos/packet-kerberos-template.c | 41 ++++++++++++++-- epan/dissectors/packet-kerberos.c | 47 ++++++++++++++++--- 2 files changed, 79 insertions(+), 9 deletions(-) diff --git a/epan/dissectors/asn1/kerberos/packet-kerberos-template.c b/epan/dissectors/asn1/kerberos/packet-kerberos-template.c index 3a4e0b50fc..0ae06b23db 100644 --- a/epan/dissectors/asn1/kerberos/packet-kerberos-template.c +++ b/epan/dissectors/asn1/kerberos/packet-kerberos-template.c @@ -380,6 +380,7 @@ enc_key_t *enc_key_list=NULL; static guint kerberos_longterm_ids = 0; wmem_map_t *kerberos_longterm_keys = NULL; static wmem_map_t *kerberos_all_keys = NULL; +static wmem_map_t *kerberos_app_session_keys = NULL; static gboolean enc_key_list_cb(wmem_allocator_t* allocator _U_, wmem_cb_event_t event _U_, void *user_data _U_) @@ -464,6 +465,13 @@ kerberos_key_map_insert(wmem_map_t *key_map, enc_key_t *new_key) return; } + if (key_map != kerberos_all_keys) { + /* + * It should already be linked to the existing key... + */ + return; + } + if (existing->fd_num == -1 && new_key->fd_num != -1) { /* * We can't reference a learnt key @@ -740,7 +748,19 @@ save_EncAPRepPart_subkey(tvbuff_t *tvb, int offset, int length, int parent_hf_index, int hf_index) { + kerberos_private_data_t *private_data = kerberos_get_private_data(actx); + save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index); + + if (actx->pinfo->fd->visited) { + return; + } + + if (private_data->last_added_key == NULL) { + return; + } + + kerberos_key_map_insert(kerberos_app_session_keys, private_data->last_added_key); } static void @@ -1350,8 +1370,8 @@ decrypt_krb5_with_cb(proto_tree *tree, void *decrypt_cb_data), void *decrypt_cb_data) { - const char *key_map_name = "all_keys"; - wmem_map_t *key_map = kerberos_all_keys; + const char *key_map_name = NULL; + wmem_map_t *key_map = NULL; struct decrypt_krb5_with_cb_state state = { .tree = tree, .pinfo = pinfo, @@ -1365,7 +1385,18 @@ decrypt_krb5_with_cb(proto_tree *tree, read_keytab_file_from_preferences(); - insert_longterm_keys_into_key_map(key_map); + switch (usage) { + case KRB5_KU_USAGE_INITIATOR_SEAL: + case KRB5_KU_USAGE_ACCEPTOR_SEAL: + key_map_name = "app_session_keys"; + key_map = kerberos_app_session_keys; + break; + default: + key_map_name = "all_keys"; + key_map = kerberos_all_keys; + insert_longterm_keys_into_key_map(key_map); + break; + } wmem_map_foreach(key_map, decrypt_krb5_with_cb_try_key, &state); if (state.ek != NULL) { @@ -4405,6 +4436,10 @@ void proto_register_kerberos(void) { wmem_file_scope(), enc_key_content_hash, enc_key_content_equal); + kerberos_app_session_keys = wmem_map_new_autoreset(wmem_epan_scope(), + wmem_file_scope(), + enc_key_content_hash, + enc_key_content_equal); #endif /* defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS) */ #endif diff --git a/epan/dissectors/packet-kerberos.c b/epan/dissectors/packet-kerberos.c index 7d58fdd41f..73fdd64500 100644 --- a/epan/dissectors/packet-kerberos.c +++ b/epan/dissectors/packet-kerberos.c @@ -821,6 +821,7 @@ enc_key_t *enc_key_list=NULL; static guint kerberos_longterm_ids = 0; wmem_map_t *kerberos_longterm_keys = NULL; static wmem_map_t *kerberos_all_keys = NULL; +static wmem_map_t *kerberos_app_session_keys = NULL; static gboolean enc_key_list_cb(wmem_allocator_t* allocator _U_, wmem_cb_event_t event _U_, void *user_data _U_) @@ -905,6 +906,13 @@ kerberos_key_map_insert(wmem_map_t *key_map, enc_key_t *new_key) return; } + if (key_map != kerberos_all_keys) { + /* + * It should already be linked to the existing key... + */ + return; + } + if (existing->fd_num == -1 && new_key->fd_num != -1) { /* * We can't reference a learnt key @@ -1181,7 +1189,19 @@ save_EncAPRepPart_subkey(tvbuff_t *tvb, int offset, int length, int parent_hf_index, int hf_index) { + kerberos_private_data_t *private_data = kerberos_get_private_data(actx); + save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index); + + if (actx->pinfo->fd->visited) { + return; + } + + if (private_data->last_added_key == NULL) { + return; + } + + kerberos_key_map_insert(kerberos_app_session_keys, private_data->last_added_key); } static void @@ -1791,8 +1811,8 @@ decrypt_krb5_with_cb(proto_tree *tree, void *decrypt_cb_data), void *decrypt_cb_data) { - const char *key_map_name = "all_keys"; - wmem_map_t *key_map = kerberos_all_keys; + const char *key_map_name = NULL; + wmem_map_t *key_map = NULL; struct decrypt_krb5_with_cb_state state = { .tree = tree, .pinfo = pinfo, @@ -1806,7 +1826,18 @@ decrypt_krb5_with_cb(proto_tree *tree, read_keytab_file_from_preferences(); - insert_longterm_keys_into_key_map(key_map); + switch (usage) { + case KRB5_KU_USAGE_INITIATOR_SEAL: + case KRB5_KU_USAGE_ACCEPTOR_SEAL: + key_map_name = "app_session_keys"; + key_map = kerberos_app_session_keys; + break; + default: + key_map_name = "all_keys"; + key_map = kerberos_all_keys; + insert_longterm_keys_into_key_map(key_map); + break; + } wmem_map_foreach(key_map, decrypt_krb5_with_cb_try_key, &state); if (state.ek != NULL) { @@ -7069,7 +7100,7 @@ dissect_kerberos_EncryptedChallenge(gboolean implicit_tag _U_, tvbuff_t *tvb _U_ /*--- End of included file: packet-kerberos-fn.c ---*/ -#line 3753 "./asn1/kerberos/packet-kerberos-template.c" +#line 3784 "./asn1/kerberos/packet-kerberos-template.c" #ifdef HAVE_KERBEROS static const ber_sequence_t PA_ENC_TS_ENC_sequence[] = { @@ -8587,7 +8618,7 @@ void proto_register_kerberos(void) { NULL, HFILL }}, /*--- End of included file: packet-kerberos-hfarr.c ---*/ -#line 4338 "./asn1/kerberos/packet-kerberos-template.c" +#line 4369 "./asn1/kerberos/packet-kerberos-template.c" }; /* List of subtrees */ @@ -8691,7 +8722,7 @@ void proto_register_kerberos(void) { &ett_kerberos_EncryptedChallenge, /*--- End of included file: packet-kerberos-ettarr.c ---*/ -#line 4361 "./asn1/kerberos/packet-kerberos-template.c" +#line 4392 "./asn1/kerberos/packet-kerberos-template.c" }; static ei_register_info ei[] = { @@ -8739,6 +8770,10 @@ void proto_register_kerberos(void) { wmem_file_scope(), enc_key_content_hash, enc_key_content_equal); + kerberos_app_session_keys = wmem_map_new_autoreset(wmem_epan_scope(), + wmem_file_scope(), + enc_key_content_hash, + enc_key_content_equal); #endif /* defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS) */ #endif