diff options
Diffstat (limited to 'src/lib/kdb')
| -rw-r--r-- | src/lib/kdb/kdb5.c | 111 | ||||
| -rw-r--r-- | src/lib/kdb/kdb5.h | 3 | ||||
| -rw-r--r-- | src/lib/kdb/keytab.c | 12 | ||||
| -rw-r--r-- | src/lib/kdb/libkdb5.exports | 2 |
4 files changed, 80 insertions, 48 deletions
diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c index 9786503005..c549689870 100644 --- a/src/lib/kdb/kdb5.c +++ b/src/lib/kdb/kdb5.c @@ -1,6 +1,6 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* - * Copyright 2006, 2009 by the Massachusetts Institute of Technology. + * Copyright 2006, 2009, 2010 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -549,17 +549,23 @@ static krb5_error_code kdb_free_lib_handle(krb5_context kcontext) { krb5_error_code status = 0; + krb5_keylist_node *old_keylist = kcontext->dal_handle->master_keylist; status = kdb_free_library(kcontext->dal_handle->lib_handle); if (status) return status; - + /* The dal_handle holds an alias to the most recent mkey_list*/ + if (kcontext->dal_handle->free_keylist) { + kcontext->dal_handle->master_keylist = NULL; /*force freeing*/ + krb5_db_free_mkey_list(kcontext, old_keylist); + } + krb5_free_principal(kcontext, kcontext->dal_handle->master_princ); free(kcontext->dal_handle); kcontext->dal_handle = NULL; return 0; } -static krb5_error_code +static krb5_error_code get_vftabl(krb5_context kcontext, kdb_vftabl **vftabl_ptr) { krb5_error_code status; @@ -989,35 +995,6 @@ krb5_db_iterate(krb5_context kcontext, } krb5_error_code -krb5_db_set_mkey_list(krb5_context kcontext, - krb5_keylist_node * keylist) -{ - krb5_error_code status = 0; - kdb_vftabl *v; - - status = get_vftabl(kcontext, &v); - if (status) - return status; - if (v->set_master_key_list == NULL) - return KRB5_PLUGIN_OP_NOTSUPP; - return v->set_master_key_list(kcontext, keylist); -} - -krb5_error_code -krb5_db_get_mkey_list(krb5_context kcontext, krb5_keylist_node ** keylist) -{ - krb5_error_code status = 0; - kdb_vftabl *v; - - status = get_vftabl(kcontext, &v); - if (status) - return status; - if (v->get_master_key_list == NULL) - return KRB5_PLUGIN_OP_NOTSUPP; - return v->get_master_key_list(kcontext, keylist); -} - -krb5_error_code krb5_db_fetch_mkey_list(krb5_context context, krb5_principal mname, const krb5_keyblock * mkey, @@ -1026,11 +1003,28 @@ krb5_db_fetch_mkey_list(krb5_context context, { kdb_vftabl *v; krb5_error_code status = 0; + krb5_keylist_node *local_keylist; status = get_vftabl(context, &v); if (status) return status; - return v->fetch_master_key_list(context, mname, mkey, mkvno, mkey_list); + if (!context->dal_handle->master_princ) { + status = krb5_copy_principal(context, mname, &context->dal_handle->master_princ); + if (status) + return status; + } + if (mkey_list == NULL) + mkey_list = &local_keylist; + status = v->fetch_master_key_list(context, mname, mkey, mkvno, mkey_list); + if (status == 0) { + /* The dal_handle holds an alias to the most recent master_keylist*/ + krb5_keylist_node *old_keylist = context->dal_handle->master_keylist; + context->dal_handle->master_keylist = *mkey_list; + if (context->dal_handle->free_keylist) + krb5_db_free_mkey_list(context, old_keylist); + context->dal_handle->free_keylist = (mkey_list == &local_keylist); + } + return status; } void @@ -1039,6 +1033,19 @@ krb5_db_free_mkey_list(krb5_context context, { krb5_keylist_node *cur, *prev; + /* + * The dal_handle holds onto the most recent master + * keylist that has been fetched throughout the lifetime of the context; if + * this function is called on that keylist, then the dal_handle is updated to + * indicate that the keylist should be freed on next call to + * krb5_db_fetch_mkey_list() or when the database is closed. Otherwise, the + * master_keylist is freed. Either way, the caller must not access this master + * keylist after calling this function. + */ + if (context&& context->dal_handle->master_keylist == mkey_list) { + context->dal_handle->free_keylist = 1; + return; + } for (cur = mkey_list; cur != NULL;) { prev = cur; cur = cur->next; @@ -2177,6 +2184,27 @@ krb5_db_promote(krb5_context kcontext, char **db_args) return status; } +static krb5_error_code +decrypt_iterator(krb5_context kcontext, + const krb5_key_data * key_data, + krb5_keyblock * dbkey, + krb5_keysalt * keysalt) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + krb5_keylist_node *n = kcontext->dal_handle->master_keylist; + status = get_vftabl(kcontext, &v); + if (status) + return status; + for (;n; n = n->next) { + krb5_clear_error_message(kcontext); + status= v->decrypt_key_data(kcontext, &n->keyblock, key_data, dbkey, keysalt); + if (status == 0) + return 0; + } + return status; +} + krb5_error_code krb5_dbe_decrypt_key_data( krb5_context kcontext, const krb5_keyblock * mkey, @@ -2186,11 +2214,24 @@ krb5_dbe_decrypt_key_data( krb5_context kcontext, { krb5_error_code status = 0; kdb_vftabl *v; - + krb5_keylist_node *n = kcontext->dal_handle->master_keylist; status = get_vftabl(kcontext, &v); if (status) return status; - return v->decrypt_key_data(kcontext, mkey, key_data, dbkey, keysalt); + if (mkey ||!n) + return v->decrypt_key_data(kcontext, mkey, key_data, dbkey, keysalt); + status = decrypt_iterator(kcontext, key_data, dbkey, keysalt); + if (status == 0) + return 0; + if (kcontext->dal_handle->master_keylist) { + /* Try reloading master keys*/ + krb5_keyblock *cur_mkey = &kcontext->dal_handle->master_keylist->keyblock; + if (krb5_db_fetch_mkey_list(kcontext, kcontext->dal_handle->master_princ, + cur_mkey, -1, NULL) == 0) { + return decrypt_iterator(kcontext, key_data, dbkey, keysalt); + } + } + return status; } krb5_error_code diff --git a/src/lib/kdb/kdb5.h b/src/lib/kdb/kdb5.h index c1265e704d..6d5c0a6cd9 100644 --- a/src/lib/kdb/kdb5.h +++ b/src/lib/kdb/kdb5.h @@ -30,6 +30,9 @@ struct _kdb5_dal_handle extent. */ void *db_context; db_library lib_handle; + krb5_keylist_node *master_keylist; + krb5_boolean free_keylist; + krb5_principal master_princ; }; /* typedef kdb5_dal_handle is in k5-int.h now */ diff --git a/src/lib/kdb/keytab.c b/src/lib/kdb/keytab.c index 4d56915b99..dbbbe75cdd 100644 --- a/src/lib/kdb/keytab.c +++ b/src/lib/kdb/keytab.c @@ -124,8 +124,6 @@ krb5_ktkdb_get_entry(in_context, id, principal, kvno, enctype, entry) krb5_keytab_entry * entry; { krb5_context context; - krb5_keylist_node * master_keylist; - krb5_keyblock * master_key; krb5_error_code kerror = 0; krb5_key_data * key_data; krb5_db_entry * db_entry; @@ -157,14 +155,6 @@ krb5_ktkdb_get_entry(in_context, id, principal, kvno, enctype, entry) } /* match key */ - kerror = krb5_db_get_mkey_list(context, &master_keylist); - if (kerror) - goto error; - - kerror = krb5_dbe_find_mkey(context, master_keylist, db_entry, &master_key); - if (kerror) - goto error; - /* For cross realm tgts, we match whatever enctype is provided; * for other principals, we only match the first enctype that is * found. Since the TGS and AS code do the same thing, then we @@ -178,7 +168,7 @@ krb5_ktkdb_get_entry(in_context, id, principal, kvno, enctype, entry) goto error; - kerror = krb5_dbe_decrypt_key_data(context, master_key, key_data, + kerror = krb5_dbe_decrypt_key_data(context, NULL, key_data, &entry->key, NULL); if (kerror) goto error; diff --git a/src/lib/kdb/libkdb5.exports b/src/lib/kdb/libkdb5.exports index 6e890478d4..f3f6a8021c 100644 --- a/src/lib/kdb/libkdb5.exports +++ b/src/lib/kdb/libkdb5.exports @@ -18,7 +18,6 @@ krb5_db_fini krb5_db_free_principal krb5_db_get_age krb5_db_get_key_data_kvno -krb5_db_get_mkey_list krb5_db_get_context krb5_db_get_principal krb5_db_iterate @@ -26,7 +25,6 @@ krb5_db_lock krb5_db_put_principal krb5_db_refresh_config krb5_db_set_context -krb5_db_set_mkey_list krb5_db_setup_mkey_name krb5_db_sign_authdata krb5_db_unlock |
