From 19b6c47f72c865471295d12e79b7fe703aa4a773 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Fri, 4 Nov 2011 15:34:00 -0500 Subject: [PATCH] Handle 1DES enctype similarity in MIT HDB We have some cross-realm principals in an MIT KDB with one kind of 1DES enctype, but the other realm's KDCs issue x-realm TGTs where the ticket encpart key enctype is a different 1DES enctype. We need this to work if we use Heimdal with the MIT HDB backend. An alternative would be to check for similar (or, rather, compatible) enctypes in the KDC (and elsewhere?). This patch avoids the need to make such ugly changes elsewhere. --- lib/hdb/hdb-mitdb.c | 98 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/lib/hdb/hdb-mitdb.c b/lib/hdb/hdb-mitdb.c index 4e8b4424b..533add07a 100644 --- a/lib/hdb/hdb-mitdb.c +++ b/lib/hdb/hdb-mitdb.c @@ -287,6 +287,102 @@ out: } +static krb5_error_code +add_1des_dup(krb5_context context, Keys *keys, Key *key, krb5_keytype keytype) +{ + key->key.keytype = keytype; + return add_Keys(keys, key); +} + +/* + * This monstrosity is here so we can avoid having to do enctype + * similarity checking in the KDC. This helper function dups 1DES keys + * in a keyset for all the similar 1DES enctypes for which keys are + * missing. And, of course, we do this only if there's any 1DES keys in + * the keyset to begin with. + */ +static krb5_error_code +dup_similar_keys_in_keyset(krb5_context context, Keys *keys) +{ + krb5_error_code ret; + size_t i, k; + Key key; + int keyset_has_1des = 0; + int keyset_has_1des_crc = 0; + int keyset_has_1des_md4 = 0; + int keyset_has_1des_md5 = 0; + + memset(&key, 0, sizeof (key)); + k = keys->len; + for (i = 0; i < keys->len; i++) { + if (keys->val[i].key.keytype == ETYPE_DES_CBC_CRC) { + keyset_has_1des_crc = 1; + if (k == keys->len) + k = i; + } else if (keys->val[i].key.keytype == ETYPE_DES_CBC_MD4) { + keyset_has_1des_crc = 1; + if (k == keys->len) + k = i; + } else if (keys->val[i].key.keytype == ETYPE_DES_CBC_MD5) { + keyset_has_1des_crc = 1; + if (k == keys->len) + k = i; + } + } + if (k == keys->len) + return 0; + + keyset_has_1des = 1; + ret = copy_Key(&keys->val[k], &key); + if (ret) + return ret; + if (!keyset_has_1des_crc) { + ret = add_1des_dup(context, keys, &key, ETYPE_DES_CBC_CRC); + if (ret) + goto out; + } + if (!keyset_has_1des_md4) { + ret = add_1des_dup(context, keys, &key, ETYPE_DES_CBC_MD4); + if (ret) + goto out; + } + if (!keyset_has_1des_md5) { + ret = add_1des_dup(context, keys, &key, ETYPE_DES_CBC_MD5); + if (ret) + goto out; + } + +out: + free_Key(&key); + return ret; +} + + +static krb5_error_code +dup_similar_keys(krb5_context context, hdb_entry *entry) +{ + krb5_error_code ret; + HDB_Ext_KeySet *hist_keys; + HDB_extension *extp; + size_t i; + + ret = dup_similar_keys_in_keyset(context, &entry->keys); + if (ret) + return ret; + extp = hdb_find_extension(entry, choice_HDB_extension_data_hist_keys); + if (extp == NULL) + return 0; + + hist_keys = &extp->data.u.hist_keys; + for (i = 0; i < hist_keys->len; i++) { + ret = dup_similar_keys_in_keyset(context, &hist_keys->val[i].keys); + if (ret) + return ret; + } + return 0; +} + + /** * This function parses an MIT krb5 encoded KDB entry and fills in the * given HDB entry with it. @@ -508,7 +604,7 @@ mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno target_kvno, krb5_storage_free(sp); - return 0; + return dup_similar_keys(context, entry); out: krb5_storage_free(sp);