From 308e53a4a88445973c14f788977883e421914691 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Fri, 15 Jul 2011 19:13:10 -0500 Subject: [PATCH] Initial support for filtering out "dead" historical keys. --- lib/hdb/common.c | 6 +++--- lib/hdb/hdb.h | 4 +++- lib/hdb/mkey.c | 29 ++++++++++++++++++++--------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/lib/hdb/common.c b/lib/hdb/common.c index 125ca997a..1ce470861 100644 --- a/lib/hdb/common.c +++ b/lib/hdb/common.c @@ -164,7 +164,7 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, return ret; } /* Decrypt the key history too */ - ret = hdb_unseal_keys_kvno(context, db, 0, &entry->entry); + ret = hdb_unseal_keys_kvno(context, db, 0, flags, &entry->entry); if (ret) { hdb_free_entry(context, entry); return ret; @@ -182,7 +182,7 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, * Find and decrypt the keys from the history that we want, * and swap them with the current keys */ - ret = hdb_unseal_keys_kvno(context, db, 0, &entry->entry); + ret = hdb_unseal_keys_kvno(context, db, 0, flags, &entry->entry); if (ret) { hdb_free_entry(context, entry); return ret; @@ -190,7 +190,7 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, } if ((flags & HDB_F_ALL_KVNOS)) { /* Decrypt the history, post current/requested switcheroo */ - ret = hdb_unseal_keys_kvno(context, db, 0, &entry->entry); + ret = hdb_unseal_keys_kvno(context, db, 0, flags, &entry->entry); if (ret) { hdb_free_entry(context, entry); return ret; diff --git a/lib/hdb/hdb.h b/lib/hdb/hdb.h index 61314153c..64b52a393 100644 --- a/lib/hdb/hdb.h +++ b/lib/hdb/hdb.h @@ -58,7 +58,9 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK }; #define HDB_F_ADMIN_DATA 64 /* want data that kdc don't use */ #define HDB_F_KVNO_SPECIFIED 128 /* we want a particular KVNO */ #define HDB_F_CURRENT_KVNO 256 /* we want the current KVNO */ -#define HDB_F_ALL_KVNOS 512 /* we want all the keys */ +#define HDB_F_LIVE_CLNT_KVNOS 512 /* we want all live keys for pre-auth */ +#define HDB_F_LIVE_SVC_KVNOS 1024 /* we want all live keys for tix */ +#define HDB_F_ALL_KVNOS 2048 /* we want all the keys, live or not */ /* hdb_capability_flags */ #define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1 diff --git a/lib/hdb/mkey.c b/lib/hdb/mkey.c index c2685e64b..9ecdd58e4 100644 --- a/lib/hdb/mkey.c +++ b/lib/hdb/mkey.c @@ -482,7 +482,7 @@ hdb_unseal_keys(krb5_context context, HDB *db, hdb_entry *ent) krb5_error_code hdb_unseal_keys_kvno(krb5_context context, HDB *db, krb5_kvno kvno, - hdb_entry *ent) + unsigned flags, hdb_entry *ent) { krb5_error_code ret = KRB5KRB_AP_ERR_NOKEY; /* XXX need a better code? */ HDB_extension *ext; @@ -492,6 +492,13 @@ hdb_unseal_keys_kvno(krb5_context context, HDB *db, krb5_kvno kvno, unsigned int tmp_len; krb5_kvno tmp_kvno; int i, k; + int exclude_dead = 0; + KerberosTime now = 0; + + if ((flags & HDB_F_LIVE_CLNT_KVNOS) || (flags & HDB_F_LIVE_SVC_KVNOS)) { + exclude_dead = 1; + now = time(NULL); + } assert(kvno == 0 || kvno < ent->kvno); @@ -509,6 +516,15 @@ hdb_unseal_keys_kvno(krb5_context context, HDB *db, krb5_kvno kvno, if (kvno != 0 && hist_keys->val[i].kvno != kvno) continue; + if (exclude_dead && ent->max_life != NULL && + hist_keys->val[i].set_time < (now - (*ent->max_life))) + /* + * The KDC may want to to check for this keyset's set_time + * is within the TGS principal's max_life, say. But we stop + * here. + */ + continue; + /* Either the keys we want, or all the keys */ for (k = 0; k < hist_keys->val[i].keys.len; k++) { ret = hdb_unseal_key_mkey(context, @@ -518,14 +534,9 @@ hdb_unseal_keys_kvno(krb5_context context, HDB *db, krb5_kvno kvno, * If kvno == 0 we might not want to bail here! E.g., if we * no longer have the right master key, so just ignore this. * - * Might we want to filter out keys that we can't decrypt - * because of HDB_ERR_NO_MKEY? Probably. If nothing else - * so we don't leave turds behind. But also in case of old - * master keys derived from passwords -- we don't want to - * help kadmin clients with fetch authorization be able to - * mount dictionary attacks on old master keys. Also, - * mayber we're misconfigured and simply can't find a live - * master key. + * We could filter out keys that we can't decrypt here + * because of HDB_ERR_NO_MKEY. However, it seems safest to + * filter them out only where necessary, say, in kadm5. */ if (ret != HDB_ERR_NO_MKEY) return (ret);