summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/kdb.h13
-rw-r--r--src/kadmin/server/ovsec_kadmd.c6
-rw-r--r--src/kdc/do_as_req.c44
-rw-r--r--src/kdc/do_tgs_req.c23
-rw-r--r--src/kdc/kdc_preauth.c65
-rw-r--r--src/kdc/kdc_util.c24
-rw-r--r--src/kdc/main.c6
-rw-r--r--src/lib/kadm5/srv/svr_principal.c53
-rw-r--r--src/lib/kdb/kdb5.c111
-rw-r--r--src/lib/kdb/kdb5.h3
-rw-r--r--src/lib/kdb/keytab.c12
-rw-r--r--src/lib/kdb/libkdb5.exports2
-rw-r--r--src/tests/verify/kdb5_verify.c2
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;