aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/asn1
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2020-05-21 03:10:27 +0200
committerAnders Broman <a.broman58@gmail.com>2020-05-26 08:28:46 +0000
commit0b7dd5720d0554f5311b625f88d4d4ccbcc3d3d2 (patch)
treefbf831cab9f97a2553160206c513e2522bce3911 /epan/dissectors/asn1
parent4caaba64b2d17162155b219cf860c2269850ce61 (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.c132
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 */