From c2ec368c36d96319aac5c3cbdfb5fde145fdc10d Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Sat, 16 Jul 2011 17:51:39 -0500 Subject: [PATCH] Add HDB extension for storing policy regarding what historic keys may be used for --- kadmin/get.c | 2 ++ kadmin/kadmin-commands.in | 24 +++++++++++++++ lib/hdb/ext.c | 64 +++++++++++++++++++++++++++++++++++++++ lib/hdb/hdb.asn1 | 4 ++- lib/hdb/mkey.c | 12 ++++++-- lib/kadm5/admin.h | 2 ++ 6 files changed, 105 insertions(+), 3 deletions(-) diff --git a/kadmin/get.c b/kadmin/get.c index 0895b53cc..98ace8927 100644 --- a/kadmin/get.c +++ b/kadmin/get.c @@ -64,6 +64,8 @@ static struct field_name { { "password", KADM5_TL_DATA, KRB5_TL_PASSWORD, KADM5_KEY_DATA, "Password", "Password", 0 }, { "pkinit-acl", KADM5_TL_DATA, KRB5_TL_PKINIT_ACL, 0, "PK-INIT ACL", "PK-INIT ACL", 0 }, { "aliases", KADM5_TL_DATA, KRB5_TL_ALIASES, 0, "Aliases", "Aliases", 0 }, + { "hist-kvno-diff-clnt", KADM5_TL_DATA, KRB5_TL_HIST_KVNO_DIFF_CLNT, 0, "Clnt hist keys", "Historic keys allowed for client", 0 }, + { "hist-kvno-diff-svc", KADM5_TL_DATA, KRB5_TL_HIST_KVNO_DIFF_SVC, 0, "Svc hist keys", "Historic keys allowed for service", 0 }, { NULL } }; diff --git a/kadmin/kadmin-commands.in b/kadmin/kadmin-commands.in index dece8ea35..8fc300825 100644 --- a/kadmin/kadmin-commands.in +++ b/kadmin/kadmin-commands.in @@ -174,6 +174,18 @@ command = { argument = "time" help = "password expiration time" } + option = { + long = "hist-kvno-diff-clnt" + type = "string" + argument = "kvno diff" + help = "historic keys allowed for client" + } + option = { + long = "hist-kvno-diff-svc" + type = "string" + argument = "kvno diff" + help = "historic keys allowed for service" + } option = { long = "use-defaults" type = "flag" @@ -365,6 +377,18 @@ command = { argument = "policy" help = "policy name" } + option = { + long = "hist-kvno-diff-clnt" + type = "string" + argument = "kvno diff" + help = "historic keys allowed for client" + } + option = { + long = "hist-kvno-diff-svc" + type = "string" + argument = "kvno diff" + help = "historic keys allowed for service" + } argument = "principal" min_args = "1" max_args = "1" diff --git a/lib/hdb/ext.c b/lib/hdb/ext.c index d2a4373b9..f4f171524 100644 --- a/lib/hdb/ext.c +++ b/lib/hdb/ext.c @@ -432,3 +432,67 @@ hdb_entry_get_aliases(const hdb_entry *entry, const HDB_Ext_Aliases **a) return 0; } + +unsigned int +hdb_entry_get_kvno_diff_clnt(const hdb_entry *entry) +{ + const HDB_extension *ext; + + ext = hdb_find_extension(entry, + choice_HDB_extension_data_hist_kvno_diff_clnt); + if (ext) + return ext->data.u.hist_kvno_diff_clnt; + return 1; +} + +krb5_error_code +hdb_entry_set_kvno_diff_clnt(krb5_context context, hdb_entry *entry, + unsigned int diff) +{ + HDB_extension ext; + + if (diff > 16384) + return EINVAL; + ext.data.element = choice_HDB_extension_data_hist_kvno_diff_clnt; + ext.data.u.hist_kvno_diff_clnt = diff; + return hdb_replace_extension(context, entry, &ext); +} + +krb5_error_code +hdb_entry_clear_kvno_diff_clnt(krb5_context context, hdb_entry *entry) +{ + return hdb_clear_extension(context, entry, + choice_HDB_extension_data_hist_kvno_diff_clnt); +} + +unsigned int +hdb_entry_get_kvno_diff_svc(const hdb_entry *entry) +{ + const HDB_extension *ext; + + ext = hdb_find_extension(entry, + choice_HDB_extension_data_hist_kvno_diff_svc); + if (ext) + return ext->data.u.hist_kvno_diff_svc; + return 1024; /* max_life effectively provides a better default */ +} + +krb5_error_code +hdb_entry_set_kvno_diff_svc(krb5_context context, hdb_entry *entry, + unsigned int diff) +{ + HDB_extension ext; + + if (diff > 16384) + return EINVAL; + ext.data.element = choice_HDB_extension_data_hist_kvno_diff_svc; + ext.data.u.hist_kvno_diff_svc = diff; + return hdb_replace_extension(context, entry, &ext); +} + +krb5_error_code +hdb_entry_clear_kvno_diff_svc(krb5_context context, hdb_entry *entry) +{ + return hdb_clear_extension(context, entry, + choice_HDB_extension_data_hist_kvno_diff_svc); +} diff --git a/lib/hdb/hdb.asn1 b/lib/hdb/hdb.asn1 index 8eb1f87bf..adba09c39 100644 --- a/lib/hdb/hdb.asn1 +++ b/lib/hdb/hdb.asn1 @@ -112,7 +112,9 @@ HDB-extension ::= SEQUENCE { last-pw-change[7] KerberosTime, pkinit-cert[8] HDB-Ext-PKINIT-cert, hist-keys[9] HDB-Ext-KeySet, - policy[10] UTF8String, + hist-kvno-diff-clnt[10] INTEGER (0..4294967295), + hist-kvno-diff-svc[11] INTEGER (0..4294967295), + policy[12] UTF8String, ... }, ... diff --git a/lib/hdb/mkey.c b/lib/hdb/mkey.c index 9ecdd58e4..e4c929c9f 100644 --- a/lib/hdb/mkey.c +++ b/lib/hdb/mkey.c @@ -490,6 +490,7 @@ hdb_unseal_keys_kvno(krb5_context context, HDB *db, krb5_kvno kvno, hdb_keyset *tmp_keys; Key *tmp_val; unsigned int tmp_len; + unsigned int kvno_diff = 0; krb5_kvno tmp_kvno; int i, k; int exclude_dead = 0; @@ -498,6 +499,10 @@ hdb_unseal_keys_kvno(krb5_context context, HDB *db, krb5_kvno kvno, if ((flags & HDB_F_LIVE_CLNT_KVNOS) || (flags & HDB_F_LIVE_SVC_KVNOS)) { exclude_dead = 1; now = time(NULL); + if (HDB_F_LIVE_CLNT_KVNOS) + kvno_diff = hdb_entry_get_kvno_diff_clnt(ent); + else + kvno_diff = hdb_entry_get_kvno_diff_svc(ent); } assert(kvno == 0 || kvno < ent->kvno); @@ -516,8 +521,11 @@ 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))) + if (exclude_dead && + ((ent->max_life != NULL && + hist_keys->val[i].set_time < (now - (*ent->max_life))) || + (hist_keys->val[i].kvno < kvno && + (kvno - hist_keys->val[i].kvno) > kvno_diff))) /* * 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 diff --git a/lib/kadm5/admin.h b/lib/kadm5/admin.h index c0e7a4fa3..1ddb4d41c 100644 --- a/lib/kadm5/admin.h +++ b/lib/kadm5/admin.h @@ -134,6 +134,8 @@ typedef struct _krb5_tl_data { #define KRB5_TL_EXTENSION 0x0008 #define KRB5_TL_PKINIT_ACL 0x0009 #define KRB5_TL_ALIASES 0x000a +#define KRB5_TL_HIST_KVNO_DIFF_CLNT 0x000b +#define KRB5_TL_HIST_KVNO_DIFF_SVC 0x000c typedef struct _kadm5_principal_ent_t { krb5_principal principal;