diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/kdb.h | 13 | ||||
-rw-r--r-- | src/kadmin/server/ovsec_kadmd.c | 6 | ||||
-rw-r--r-- | src/kdc/do_as_req.c | 44 | ||||
-rw-r--r-- | src/kdc/do_tgs_req.c | 23 | ||||
-rw-r--r-- | src/kdc/kdc_preauth.c | 65 | ||||
-rw-r--r-- | src/kdc/kdc_util.c | 24 | ||||
-rw-r--r-- | src/kdc/main.c | 6 | ||||
-rw-r--r-- | src/lib/kadm5/srv/svr_principal.c | 53 | ||||
-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 | ||||
-rw-r--r-- | src/tests/verify/kdb5_verify.c | 2 |
13 files changed, 114 insertions, 250 deletions
diff --git a/src/include/kdb.h b/src/include/kdb.h index d401fd544..8b03398e5 100644 --- a/src/include/kdb.h +++ b/src/include/kdb.h @@ -350,11 +350,6 @@ krb5_error_code krb5_db_iterate ( krb5_context kcontext, int (*func) (krb5_pointer, krb5_db_entry *), krb5_pointer func_arg ); -krb5_error_code krb5_db_set_mkey_list( krb5_context context, - krb5_keylist_node * keylist); - -krb5_error_code krb5_db_get_mkey_list( krb5_context kcontext, - krb5_keylist_node ** keylist); krb5_error_code krb5_db_store_master_key ( krb5_context kcontext, char *keyfile, @@ -382,7 +377,9 @@ krb5_db_fetch_mkey_list( krb5_context context, const krb5_keyblock * mkey, krb5_kvno mkvno, krb5_keylist_node **mkeys_list ); - +/** + * Free a master keylist. + */ void krb5_db_free_mkey_list( krb5_context context, krb5_keylist_node *mkey_list ); @@ -411,6 +408,10 @@ krb5_db_setup_mkey_name ( krb5_context context, char **fullname, krb5_principal *principal); +/** + * Decrypts the key given in @@a key_data. If @a mkey is specified, that + * master key is used. If @a mkey is NULL, then all master keys are tried. + */ krb5_error_code krb5_dbe_decrypt_key_data( krb5_context context, const krb5_keyblock * mkey, diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c index 6d25a0fab..6b55273de 100644 --- a/src/kadmin/server/ovsec_kadmd.c +++ b/src/kadmin/server/ovsec_kadmd.c @@ -430,12 +430,6 @@ int main(int argc, char *argv[]) krb5_klog_syslog(LOG_ERR, "Can't set kdb keytab's internal context."); goto kterr; } - /* XXX master_keylist is in guts of lib/kadm5/server_kdb.c */ - ret = krb5_db_set_mkey_list(hctx, master_keylist); - if (ret) { - krb5_klog_syslog(LOG_ERR, "Can't set master key list for kdb keytab."); - goto kterr; - } ret = krb5_kt_register(context, &krb5_kt_kdb_ops); if (ret) { krb5_klog_syslog(LOG_ERR, "Can't register kdb keytab."); diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index fa98ae3a0..557ae3dea 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -115,7 +115,6 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, const char *status; krb5_key_data *server_key, *client_key; krb5_keyblock server_keyblock, client_keyblock; - krb5_keyblock *mkey_ptr; krb5_enctype useenctype; krb5_data e_data; register int i; @@ -126,7 +125,6 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, void *pa_context = NULL; int did_log = 0; const char *emsg = 0; - krb5_keylist_node *tmp_mkey_list; struct kdc_request_state *state = NULL; krb5_data encoded_req_body; krb5_keyblock *as_encrypting_key = NULL; @@ -461,32 +459,13 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, goto errout; } - if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, server, - &mkey_ptr))) { - /* try refreshing master key list */ - /* XXX it would nice if we had the mkvno here for optimization */ - if (krb5_db_fetch_mkey_list(kdc_context, master_princ, - &master_keyblock, 0, &tmp_mkey_list) == 0) { - krb5_dbe_free_key_list(kdc_context, master_keylist); - master_keylist = tmp_mkey_list; - if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, - server, &mkey_ptr))) { - status = "FINDING_MASTER_KEY"; - goto errout; - } - } else { - status = "FINDING_MASTER_KEY"; - goto errout; - } - } - /* * Convert server->key into a real key * (it may be encrypted in the database) * * server_keyblock is later used to generate auth data signatures */ - if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, mkey_ptr, + if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL, server_key, &server_keyblock, NULL))) { status = "DECRYPT_SERVER_KEY"; @@ -514,27 +493,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, goto errout; } - if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, client, - &mkey_ptr))) { - /* try refreshing master key list */ - /* XXX it would nice if we had the mkvno here for optimization */ - if (krb5_db_fetch_mkey_list(kdc_context, master_princ, - &master_keyblock, 0, &tmp_mkey_list) == 0) { - krb5_dbe_free_key_list(kdc_context, master_keylist); - master_keylist = tmp_mkey_list; - if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, - client, &mkey_ptr))) { - status = "FINDING_MASTER_KEY"; - goto errout; - } - } else { - status = "FINDING_MASTER_KEY"; - goto errout; - } - } - /* convert client.key_data into a real key */ - if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, mkey_ptr, + if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL, client_key, &client_keyblock, NULL))) { status = "DECRYPT_CLIENT_KEY"; diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 2c4514ca2..b424b3edd 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -104,7 +104,6 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, krb5_keyblock session_key; krb5_timestamp rtime; krb5_keyblock *reply_key = NULL; - krb5_keyblock *mkey_ptr; krb5_key_data *server_key; char *cname = 0, *sname = 0, *altcname = 0; krb5_last_req_entry *nolrarray[2], nolrentry; @@ -625,31 +624,11 @@ tgt_again: goto cleanup; } - if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, server, - &mkey_ptr))) { - krb5_keylist_node *tmp_mkey_list; - /* try refreshing master key list */ - /* XXX it would nice if we had the mkvno here for optimization */ - if (krb5_db_fetch_mkey_list(kdc_context, master_princ, - &master_keyblock, 0, &tmp_mkey_list) == 0) { - krb5_dbe_free_key_list(kdc_context, master_keylist); - master_keylist = tmp_mkey_list; - if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, - server, &mkey_ptr))) { - status = "FINDING_MASTER_KEY"; - goto cleanup; - } - } else { - status = "FINDING_MASTER_KEY"; - goto cleanup; - } - } - /* * Convert server.key into a real key * (it may be encrypted in the database) */ - if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, mkey_ptr, + if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL, server_key, &encrypting_key, NULL))) { status = "DECRYPT_SERVER_KEY"; diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index 4c413d07e..503c2313b 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -711,7 +711,7 @@ get_entry_data(krb5_context context, int i, k; krb5_data *ret; krb5_deltat *delta; - krb5_keyblock *keys, *mkey_ptr; + krb5_keyblock *keys; krb5_key_data *entry_key; krb5_error_code error; struct kdc_request_state *state = request->kdc_state; @@ -748,32 +748,13 @@ get_entry_data(krb5_context context, ret->data = (char *) keys; ret->length = sizeof(krb5_keyblock) * (request->nktypes + 1); memset(ret->data, 0, ret->length); - if ((error = krb5_dbe_find_mkey(context, master_keylist, entry, - &mkey_ptr))) { - krb5_keylist_node *tmp_mkey_list; - /* try refreshing the mkey list in case it's been updated */ - if (krb5_db_fetch_mkey_list(context, master_princ, - &master_keyblock, 0, - &tmp_mkey_list) == 0) { - krb5_dbe_free_key_list(context, master_keylist); - master_keylist = tmp_mkey_list; - if ((error = krb5_dbe_find_mkey(context, master_keylist, entry, - &mkey_ptr))) { - free(ret); - return (error); - } - } else { - free(ret); - return (error); - } - } k = 0; for (i = 0; i < request->nktypes; i++) { entry_key = NULL; if (krb5_dbe_find_enctype(context, entry, request->ktype[i], -1, 0, &entry_key) != 0) continue; - if (krb5_dbe_decrypt_key_data(context, mkey_ptr, entry_key, + if (krb5_dbe_decrypt_key_data(context, NULL, entry_key, &keys[k], NULL) != 0) { if (keys[k].contents != NULL) krb5_free_keyblock_contents(context, &keys[k]); @@ -1328,7 +1309,7 @@ return_padata(krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, } key_modified = FALSE; null_item.contents = NULL; - null_item.length = NULL; + null_item.length = 0; send_pa = send_pa_list; *send_pa = 0; @@ -1430,7 +1411,7 @@ verify_enc_timestamp(krb5_context context, krb5_db_entry *client, krb5_data scratch; krb5_data enc_ts_data; krb5_enc_data *enc_data = 0; - krb5_keyblock key, *mkey_ptr; + krb5_keyblock key; krb5_key_data * client_key; krb5_int32 start; krb5_timestamp timenow; @@ -1448,24 +1429,6 @@ verify_enc_timestamp(krb5_context context, krb5_db_entry *client, if ((enc_ts_data.data = (char *) malloc(enc_ts_data.length)) == NULL) goto cleanup; - if ((retval = krb5_dbe_find_mkey(context, master_keylist, client, - &mkey_ptr))) { - krb5_keylist_node *tmp_mkey_list; - /* try refreshing the mkey list in case it's been updated */ - if (krb5_db_fetch_mkey_list(context, master_princ, - &master_keyblock, 0, - &tmp_mkey_list) == 0) { - krb5_dbe_free_key_list(context, master_keylist); - master_keylist = tmp_mkey_list; - if ((retval = krb5_dbe_find_mkey(context, master_keylist, client, - &mkey_ptr))) { - goto cleanup; - } - } else { - goto cleanup; - } - } - start = 0; decrypt_err = 0; while (1) { @@ -1474,7 +1437,7 @@ verify_enc_timestamp(krb5_context context, krb5_db_entry *client, -1, 0, &client_key))) goto cleanup; - if ((retval = krb5_dbe_decrypt_key_data(context, mkey_ptr, client_key, + if ((retval = krb5_dbe_decrypt_key_data(context, NULL, client_key, &key, NULL))) goto cleanup; @@ -2785,22 +2748,6 @@ static krb5_error_code verify_pkinit_request( goto cleanup; } cert_hash_len = strlen(cert_hash); - if ((krtn = krb5_dbe_find_mkey(context, master_keylist, &entry, &mkey_ptr))) { - krb5_keylist_node *tmp_mkey_list; - /* try refreshing the mkey list in case it's been updated */ - if (krb5_db_fetch_mkey_list(context, master_princ, - &master_keyblock, 0, - &tmp_mkey_list) == 0) { - krb5_dbe_free_key_list(context, master_keylist); - master_keylist = tmp_mkey_list; - if ((krtn = krb5_dbe_find_mkey(context, master_keylist, &entry, - &mkey_ptr))) { - goto cleanup; - } - } else { - goto cleanup; - } - } for(key_dex=0; key_dex<client->n_key_data; key_dex++) { krb5_key_data *key_data = &client->key_data[key_dex]; kdcPkinitDebug("--- key %u type[0] %u length[0] %u type[1] %u length[1] %u\n", @@ -2815,7 +2762,7 @@ static krb5_error_code verify_pkinit_request( * Unfortunately this key is stored encrypted even though it's * not sensitive... */ - krtn = krb5_dbe_decrypt_key_data(context, mkey_ptr, key_data, + krtn = krb5_dbe_decrypt_key_data(context, NULL, key_data, &decrypted_key, NULL); if(krtn) { kdcPkinitDebug("verify_pkinit_request: error decrypting cert hash block\n"); diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index 61bd7fdd4..7b62b53df 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -454,7 +454,6 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags, krb5_error_code retval; krb5_boolean similar; krb5_key_data * server_key; - krb5_keyblock * mkey_ptr; krb5_db_entry * server = NULL; *server_ptr = NULL; @@ -478,27 +477,6 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags, goto errout; } - if ((retval = krb5_dbe_find_mkey(kdc_context, master_keylist, server, - &mkey_ptr))) { - krb5_keylist_node *tmp_mkey_list; - /* try refreshing master key list */ - /* XXX it would nice if we had the mkvno here for optimization */ - if (krb5_db_fetch_mkey_list(kdc_context, master_princ, - &master_keyblock, 0, &tmp_mkey_list) == 0) { - krb5_dbe_free_key_list(kdc_context, master_keylist); - master_keylist = tmp_mkey_list; - retval = krb5_db_set_mkey_list(kdc_context, master_keylist); - if (retval) - goto errout; - if ((retval = krb5_dbe_find_mkey(kdc_context, master_keylist, - server, &mkey_ptr))) { - goto errout; - } - } else { - goto errout; - } - } - retval = krb5_dbe_find_enctype(kdc_context, server, match_enctype ? ticket->enc_part.enctype : -1, -1, (krb5_int32)ticket->enc_part.kvno, @@ -510,7 +488,7 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags, goto errout; } if ((*key = (krb5_keyblock *)malloc(sizeof **key))) { - retval = krb5_dbe_decrypt_key_data(kdc_context, mkey_ptr, server_key, + retval = krb5_dbe_decrypt_key_data(kdc_context, NULL, server_key, *key, NULL); } else retval = ENOMEM; diff --git a/src/kdc/main.c b/src/kdc/main.c index 60a3dc02e..21c67f8b2 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -431,12 +431,6 @@ init_realm(kdc_realm_t *rdp, char *realm, char *def_mpname, goto whoops; } - kret = krb5_db_set_mkey_list(rdp->realm_context, rdp->mkey_list); - if (kret) { - kdc_err(rdp->realm_context, kret, - "while setting master key list for realm %s", realm); - goto whoops; - } /* Set up the keytab */ if ((kret = krb5_ktkdb_resolve(rdp->realm_context, NULL, diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c index dc1640643..c1a955aea 100644 --- a/src/lib/kadm5/srv/svr_principal.c +++ b/src/lib/kadm5/srv/svr_principal.c @@ -38,7 +38,7 @@ extern krb5_keylist_node *master_keylist; extern krb5_actkvno_node *active_mkey_list; extern krb5_db_entry master_db; -static int decrypt_key_data(krb5_context context, krb5_keyblock *mkey, +static int decrypt_key_data(krb5_context context, int n_key_data, krb5_key_data *key_data, krb5_keyblock **keyblocks, int *n_keys); @@ -933,17 +933,16 @@ done: */ static kadm5_ret_t check_pw_reuse(krb5_context context, - krb5_keyblock *mkey, krb5_keyblock *hist_keyblock, int n_new_key_data, krb5_key_data *new_key_data, unsigned int n_pw_hist_data, osa_pw_hist_ent *pw_hist_data) { - int x, y, z; + unsigned int x, y, z; krb5_keyblock newkey, histkey; krb5_error_code ret; for (x = 0; x < n_new_key_data; x++) { - ret = krb5_dbe_decrypt_key_data(context, mkey, &(new_key_data[x]), + ret = krb5_dbe_decrypt_key_data(context, NULL, &(new_key_data[x]), &newkey, NULL); if (ret) return(ret); @@ -996,7 +995,7 @@ check_pw_reuse(krb5_context context, * set to n_key_data. */ static -int create_history_entry(krb5_context context, krb5_keyblock *mkey, +int create_history_entry(krb5_context context, krb5_keyblock *hist_key, int n_key_data, krb5_key_data *key_data, osa_pw_hist_ent *hist) { @@ -1010,7 +1009,7 @@ int create_history_entry(krb5_context context, krb5_keyblock *mkey, memset(hist->key_data, 0, n_key_data*sizeof(krb5_key_data)); for (i = 0; i < n_key_data; i++) { - ret = krb5_dbe_decrypt_key_data(context, mkey, &key_data[i], &key, + ret = krb5_dbe_decrypt_key_data(context, NULL, &key_data[i], &key, &salt); if (ret) return ret; @@ -1394,13 +1393,13 @@ kadm5_chpass_principal_3(void *server_handle, goto done; ret = create_history_entry(handle->context, - act_mkey, &hist_keyblock, + &hist_keyblock, kdb_save->n_key_data, kdb_save->key_data, &hist); if (ret) goto done; - ret = check_pw_reuse(handle->context, act_mkey, &hist_keyblock, + ret = check_pw_reuse(handle->context, &hist_keyblock, kdb->n_key_data, kdb->key_data, 1, &hist); if (ret) @@ -1410,7 +1409,7 @@ kadm5_chpass_principal_3(void *server_handle, /* If hist_kvno has changed since the last password change, we * can't check the history. */ if (adb.admin_history_kvno == hist_kvno) { - ret = check_pw_reuse(handle->context, act_mkey, &hist_keyblock, + ret = check_pw_reuse(handle->context, &hist_keyblock, kdb->n_key_data, kdb->key_data, adb.old_key_len, adb.old_keys); if (ret) @@ -1533,7 +1532,7 @@ kadm5_randkey_principal_3(void *server_handle, if (keepold) return KADM5_PROTECT_PRINCIPAL; ks_tuple = n_ks_tuple ? ks_tuple : handle->params.keysalts, - n_ks_tuple = 1; + n_ks_tuple = 1; } if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) @@ -1598,7 +1597,7 @@ kadm5_randkey_principal_3(void *server_handle, kdb->fail_auth_count = 0; if (keyblocks) { - ret = decrypt_key_data(handle->context, act_mkey, + ret = decrypt_key_data(handle->context, kdb->n_key_data, kdb->key_data, keyblocks, n_keys); if (ret) @@ -2007,7 +2006,6 @@ kadm5_get_principal_keys(void *server_handle /* IN */, osa_princ_ent_rec adb; kadm5_ret_t ret; kadm5_server_handle_t handle = server_handle; - krb5_keyblock *mkey_ptr; if (keyblocks) *keyblocks = NULL; @@ -2021,26 +2019,7 @@ kadm5_get_principal_keys(void *server_handle /* IN */, return(ret); if (keyblocks) { - if ((ret = krb5_dbe_find_mkey(handle->context, master_keylist, kdb, - &mkey_ptr))) { - krb5_keylist_node *tmp_mkey_list; - /* try refreshing master key list */ - /* XXX it would nice if we had the mkvno here for optimization */ - if (krb5_db_fetch_mkey_list(handle->context, master_princ, - &master_keyblock, 0, - &tmp_mkey_list) == 0) { - krb5_dbe_free_key_list(handle->context, master_keylist); - master_keylist = tmp_mkey_list; - if ((ret = krb5_dbe_find_mkey(handle->context, master_keylist, - kdb, &mkey_ptr))) { - goto done; - } - } else { - goto done; - } - } - - ret = decrypt_key_data(handle->context, mkey_ptr, + ret = decrypt_key_data(handle->context, kdb->n_key_data, kdb->key_data, keyblocks, n_keys); if (ret) @@ -2057,11 +2036,11 @@ done: /* * Allocate an array of n_key_data krb5_keyblocks, fill in each - * element with the results of decrypting the nth key in key_data with - * mkey, and if n_keys is not NULL fill it in with the + * element with the results of decrypting the nth key in key_data, + * and if n_keys is not NULL fill it in with the * number of keys decrypted. */ -static int decrypt_key_data(krb5_context context, krb5_keyblock *mkey, +static int decrypt_key_data(krb5_context context, int n_key_data, krb5_key_data *key_data, krb5_keyblock **keyblocks, int *n_keys) { @@ -2074,7 +2053,7 @@ static int decrypt_key_data(krb5_context context, krb5_keyblock *mkey, memset(keys, 0, n_key_data*sizeof(krb5_keyblock)); for (i = 0; i < n_key_data; i++) { - ret = krb5_dbe_decrypt_key_data(context, mkey, &key_data[i], &keys[i], + ret = krb5_dbe_decrypt_key_data(context, NULL, &key_data[i], &keys[i], NULL); if (ret) { for (; i >= 0; i--) { @@ -2171,7 +2150,7 @@ kadm5_ret_t kadm5_decrypt_key(void *server_handle, } } - if ((ret = krb5_dbe_decrypt_key_data(handle->context, mkey_ptr, key_data, + if ((ret = krb5_dbe_decrypt_key_data(handle->context, NULL, key_data, keyblock, keysalt))) return ret; diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c index 978650300..c54968987 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 c1265e704..6d5c0a6cd 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 4d56915b9..dbbbe75cd 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 6e890478d..f3f6a8021 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 diff --git a/src/tests/verify/kdb5_verify.c b/src/tests/verify/kdb5_verify.c index 4f77b19c9..a19a5aa9f 100644 --- a/src/tests/verify/kdb5_verify.c +++ b/src/tests/verify/kdb5_verify.c @@ -272,7 +272,7 @@ check_princ(context, str_princ) } krb5_free_principal(context, princ); - if ((retval = krb5_dbe_decrypt_key_data(context, &master_keyblock, + if ((retval = krb5_dbe_decrypt_key_data(context, NULL, kdbe->key_data, &db_key, NULL))) { com_err(progname, retval, "while decrypting key for '%s'", princ_name); goto errout; |