diff options
Diffstat (limited to 'src/lib/kadm5')
| -rw-r--r-- | src/lib/kadm5/srv/libkadm5srv.exports | 1 | ||||
| -rw-r--r-- | src/lib/kadm5/srv/server_kdb.c | 43 | ||||
| -rw-r--r-- | src/lib/kadm5/srv/svr_iters.c | 1 | ||||
| -rw-r--r-- | src/lib/kadm5/srv/svr_principal.c | 153 |
4 files changed, 172 insertions, 26 deletions
diff --git a/src/lib/kadm5/srv/libkadm5srv.exports b/src/lib/kadm5/srv/libkadm5srv.exports index a02577667..545d43b70 100644 --- a/src/lib/kadm5/srv/libkadm5srv.exports +++ b/src/lib/kadm5/srv/libkadm5srv.exports @@ -87,6 +87,7 @@ krb5_string_to_keysalts krb5_match_config_pattern master_db master_keyblock +master_keylist master_princ osa_free_princ_ent ovsec_kadm_chpass_principal diff --git a/src/lib/kadm5/srv/server_kdb.c b/src/lib/kadm5/srv/server_kdb.c index 836cd00b7..47f00c071 100644 --- a/src/lib/kadm5/srv/server_kdb.c +++ b/src/lib/kadm5/srv/server_kdb.c @@ -4,6 +4,11 @@ * $Header$ */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + #if !defined(lint) && !defined(__CODECENTER__) static char *rcsid = "$Header$"; #endif @@ -15,7 +20,9 @@ static char *rcsid = "$Header$"; #include "server_internal.h" krb5_principal master_princ; -krb5_keyblock master_keyblock; +krb5_keyblock master_keyblock; /* local mkey */ +krb5_keylist_node *master_keylist = NULL; +krb5_actkvno_node *active_mkey_list = NULL; krb5_db_entry master_db; krb5_principal hist_princ; @@ -32,6 +39,7 @@ krb5_error_code kdb_init_master(kadm5_server_handle_t handle, int ret = 0; char *realm; krb5_boolean from_kbd = FALSE; + krb5_kvno mkvno = IGNORE_VNO; if (from_keyboard) from_kbd = TRUE; @@ -50,22 +58,45 @@ krb5_error_code kdb_init_master(kadm5_server_handle_t handle, master_keyblock.enctype = handle->params.enctype; + /* + * Fetch the local mkey, may not be the latest but that's okay because we + * really want the list of all mkeys and those can be retrieved with any + * valid mkey. + */ ret = krb5_db_fetch_mkey(handle->context, master_princ, master_keyblock.enctype, from_kbd, FALSE /* only prompt once */, handle->params.stash_file, - NULL /* don't care about kvno */, + &mkvno /* get the kvno of the returned mkey */, NULL /* I'm not sure about this, but it's what the kdc does --marc */, &master_keyblock); if (ret) goto done; +#if 0 /************** Begin IFDEF'ed OUT *******************************/ + /* + * krb5_db_fetch_mkey_list will verify mkey so don't call + * krb5_db_verify_master_key() + */ if ((ret = krb5_db_verify_master_key(handle->context, master_princ, IGNORE_VNO, &master_keyblock))) { krb5_db_fini(handle->context); return ret; } +#endif /**************** END IFDEF'ed OUT *******************************/ + + if ((ret = krb5_db_fetch_mkey_list(handle->context, master_princ, + &master_keyblock, mkvno, &master_keylist))) { + krb5_db_fini(handle->context); + return (ret); + } + + if ((ret = krb5_dbe_fetch_act_key_list(handle->context, master_princ, + &active_mkey_list))) { + krb5_db_fini(handle->context); + return (ret); + } done: if (r == NULL) @@ -106,6 +137,7 @@ krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, char *r) char *realm, *hist_name; krb5_key_data *key_data; krb5_key_salt_tuple ks[1]; + krb5_keyblock *tmp_mkey; if (r == NULL) { if ((ret = krb5_get_default_realm(handle->context, &realm))) @@ -177,7 +209,12 @@ krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, char *r) if (ret) goto done; - ret = krb5_dbekd_decrypt_key_data(handle->context, &master_keyblock, + ret = krb5_dbe_find_mkey(handle->context, master_keylist, &hist_db, + &tmp_mkey); + if (ret) + goto done; + + ret = krb5_dbekd_decrypt_key_data(handle->context, tmp_mkey, key_data, &hist_key, NULL); if (ret) goto done; diff --git a/src/lib/kadm5/srv/svr_iters.c b/src/lib/kadm5/srv/svr_iters.c index cd3fb4177..757d3ab0e 100644 --- a/src/lib/kadm5/srv/svr_iters.c +++ b/src/lib/kadm5/srv/svr_iters.c @@ -46,6 +46,7 @@ struct iter_data { #endif }; +/* XXX Duplicated in kdb5_util! */ /* * Function: glob_to_regexp * diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c index 2bdc1f5b2..207143710 100644 --- a/src/lib/kadm5/srv/svr_principal.c +++ b/src/lib/kadm5/srv/svr_principal.c @@ -32,13 +32,15 @@ static char *rcsid = "$Header$"; extern krb5_principal master_princ; extern krb5_principal hist_princ; -extern krb5_keyblock master_keyblock; +extern krb5_keyblock master_keyblock; +extern krb5_keylist_node *master_keylist; +extern krb5_actkvno_node *active_mkey_list; extern krb5_keyblock hist_key; extern krb5_db_entry master_db; extern krb5_db_entry hist_db; extern krb5_kvno hist_kvno; -static int decrypt_key_data(krb5_context context, +static int decrypt_key_data(krb5_context context, krb5_keyblock *mkey, int n_key_data, krb5_key_data *key_data, krb5_keyblock **keyblocks, int *n_keys); @@ -205,6 +207,8 @@ kadm5_create_principal_3(void *server_handle, krb5_tl_data *tl_data_orig, *tl_data_tail; unsigned int ret; kadm5_server_handle_t handle = server_handle; + krb5_keyblock *act_mkey; + krb5_kvno act_kvno; CHECK_HANDLE(server_handle); @@ -347,7 +351,16 @@ kadm5_create_principal_3(void *server_handle, /* initialize the keys */ - if ((ret = krb5_dbe_cpw(handle->context, &master_keyblock, + ret = krb5_dbe_find_act_mkey(handle->context, master_keylist, + active_mkey_list, &act_kvno, &act_mkey); + if (ret) { + krb5_db_free_principal(handle->context, &kdb, 1); + if (mask & KADM5_POLICY) + (void) kadm5_free_policy_ent(handle->lhandle, &polent); + return (ret); + } + + if ((ret = krb5_dbe_cpw(handle->context, act_mkey, n_ks_tuple?ks_tuple:handle->params.keysalts, n_ks_tuple?n_ks_tuple:handle->params.num_keysalts, password, @@ -359,6 +372,16 @@ kadm5_create_principal_3(void *server_handle, return(ret); } + /* Record the master key VNO used to encrypt this entry's keys */ + ret = krb5_dbe_update_mkvno(handle->context, &kdb, act_kvno); + if (ret) + { + krb5_db_free_principal(handle->context, &kdb, 1); + if (mask & KADM5_POLICY) + (void) kadm5_free_policy_ent(handle->lhandle, &polent); + return ret; + } + /* populate the admin-server-specific fields. In the OV server, this used to be in a separate database. Since there's already marshalling code for the admin fields, to keep things simple, @@ -806,12 +829,24 @@ kadm5_get_principal(void *server_handle, krb5_principal principal, if (kdb.key_data[i].key_data_kvno > entry->kvno) entry->kvno = kdb.key_data[i].key_data_kvno; + ret = krb5_dbe_lookup_mkvno(handle->context, &kdb, &entry->mkvno); + if (ret) + goto done; + + /* + * It's my understanding that KADM5_API_VERSION_1 is for OpenVision admin + * system compatiblity and is not required to maintain at this point so I'm + * commenting out this code. + * -- Will Fiveash + */ +#if 0 /************** Begin IFDEF'ed OUT *******************************/ if (handle->api_version == KADM5_API_VERSION_2) entry->mkvno = 0; else { /* XXX I'll be damned if I know how to deal with this one --marc */ entry->mkvno = 1; } +#endif /**************** END IFDEF'ed OUT *******************************/ /* * The new fields that only exist in version 2 start here @@ -936,6 +971,7 @@ 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) @@ -946,7 +982,7 @@ check_pw_reuse(krb5_context context, for (x = 0; x < n_new_key_data; x++) { ret = krb5_dbekd_decrypt_key_data(context, - &master_keyblock, + mkey, &(new_key_data[x]), &newkey, NULL); if (ret) @@ -999,7 +1035,7 @@ check_pw_reuse(krb5_context context, * set to n_key_data. */ static -int create_history_entry(krb5_context context, int n_key_data, +int create_history_entry(krb5_context context, krb5_keyblock *mkey, int n_key_data, krb5_key_data *key_data, osa_pw_hist_ent *hist) { int i, ret; @@ -1013,7 +1049,7 @@ int create_history_entry(krb5_context context, int n_key_data, for (i = 0; i < n_key_data; i++) { ret = krb5_dbekd_decrypt_key_data(context, - &master_keyblock, + mkey, &key_data[i], &key, &salt); if (ret) @@ -1302,6 +1338,8 @@ kadm5_chpass_principal_3(void *server_handle, int have_pol = 0; kadm5_server_handle_t handle = server_handle; osa_pw_hist_ent hist; + krb5_keyblock *act_mkey; + krb5_kvno act_kvno; CHECK_HANDLE(server_handle); @@ -1335,7 +1373,12 @@ kadm5_chpass_principal_3(void *server_handle, KADM5_POLICY, &pol, principal))) goto done; - ret = krb5_dbe_cpw(handle->context, &master_keyblock, + ret = krb5_dbe_find_act_mkey(handle->context, master_keylist, + active_mkey_list, &act_kvno, &act_mkey); + if (ret) + goto done; + + ret = krb5_dbe_cpw(handle->context, act_mkey, n_ks_tuple?ks_tuple:handle->params.keysalts, n_ks_tuple?n_ks_tuple:handle->params.num_keysalts, password, 0 /* increment kvno */, @@ -1343,6 +1386,10 @@ kadm5_chpass_principal_3(void *server_handle, if (ret) goto done; + ret = krb5_dbe_update_mkvno(handle->context, &kdb, act_kvno); + if (ret) + goto done; + kdb.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE; ret = krb5_timeofday(handle->context, &now); @@ -1372,12 +1419,13 @@ kadm5_chpass_principal_3(void *server_handle, #endif ret = create_history_entry(handle->context, + act_mkey, kdb_save.n_key_data, kdb_save.key_data, &hist); if (ret) goto done; - ret = check_pw_reuse(handle->context, &hist_key, + ret = check_pw_reuse(handle->context, act_mkey, &hist_key, kdb.n_key_data, kdb.key_data, 1, &hist); if (ret) @@ -1389,7 +1437,7 @@ kadm5_chpass_principal_3(void *server_handle, goto done; } - ret = check_pw_reuse(handle->context, &hist_key, + ret = check_pw_reuse(handle->context, act_mkey, &hist_key, kdb.n_key_data, kdb.key_data, adb.old_key_len, adb.old_keys); if (ret) @@ -1489,6 +1537,7 @@ kadm5_randkey_principal_3(void *server_handle, krb5_key_data *key_data; int ret, last_pwd, have_pol = 0; kadm5_server_handle_t handle = server_handle; + krb5_keyblock *act_mkey; if (keyblocks) *keyblocks = NULL; @@ -1507,7 +1556,12 @@ kadm5_randkey_principal_3(void *server_handle, if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) return(ret); - ret = krb5_dbe_crk(handle->context, &master_keyblock, + ret = krb5_dbe_find_act_mkey(handle->context, master_keylist, + active_mkey_list, NULL, &act_mkey); + if (ret) + goto done; + + ret = krb5_dbe_crk(handle->context, act_mkey, n_ks_tuple?ks_tuple:handle->params.keysalts, n_ks_tuple?n_ks_tuple:handle->params.num_keysalts, keepold, @@ -1552,7 +1606,7 @@ kadm5_randkey_principal_3(void *server_handle, goto done; } - ret = check_pw_reuse(handle->context, &hist_key, + ret = check_pw_reuse(handle->context, act_mkey, &hist_key, kdb.n_key_data, kdb.key_data, adb.old_key_len, adb.old_keys); if (ret) @@ -1579,12 +1633,12 @@ kadm5_randkey_principal_3(void *server_handle, if (ret) goto done; - ret = decrypt_key_data(handle->context, 1, key_data, + ret = decrypt_key_data(handle->context, act_mkey, 1, key_data, keyblocks, NULL); if (ret) goto done; } else { - ret = decrypt_key_data(handle->context, + ret = decrypt_key_data(handle->context, act_mkey, kdb.n_key_data, kdb.key_data, keyblocks, n_keys); if (ret) @@ -1630,6 +1684,7 @@ kadm5_setv4key_principal(void *server_handle, #endif kadm5_server_handle_t handle = server_handle; krb5_key_data tmp_key_data; + krb5_keyblock *act_mkey; memset( &tmp_key_data, 0, sizeof(tmp_key_data)); @@ -1667,8 +1722,13 @@ kadm5_setv4key_principal(void *server_handle, keysalt.data.length = 0; keysalt.data.data = NULL; + ret = krb5_dbe_find_act_mkey(handle->context, master_keylist, + active_mkey_list, NULL, &act_mkey); + if (ret) + goto done; + /* use tmp_key_data as temporary location and reallocate later */ - ret = krb5_dbekd_encrypt_key_data(handle->context, &master_keyblock, + ret = krb5_dbekd_encrypt_key_data(handle->context, act_mkey, keyblock, &keysalt, kvno + 1, &tmp_key_data); if (ret) { @@ -1809,6 +1869,7 @@ kadm5_setkey_principal_3(void *server_handle, krb5_keysalt keysalt; krb5_key_data tmp_key_data; krb5_key_data *tptr; + krb5_keyblock *act_mkey; CHECK_HANDLE(server_handle); @@ -1880,15 +1941,20 @@ kadm5_setkey_principal_3(void *server_handle, } memset (&tmp_key_data, 0, sizeof(tmp_key_data)); + ret = krb5_dbe_find_act_mkey(handle->context, master_keylist, + active_mkey_list, NULL, &act_mkey); + if (ret) + goto done; + ret = krb5_dbekd_encrypt_key_data(handle->context, - &master_keyblock, + act_mkey, &keyblocks[i], n_ks_tuple ? &keysalt : NULL, kvno + 1, &tmp_key_data); - if (ret) { + if (ret) goto done; - } + tptr = &kdb.key_data[i]; tptr->key_data_ver = tmp_key_data.key_data_ver; tptr->key_data_kvno = tmp_key_data.key_data_kvno; @@ -2013,6 +2079,7 @@ kadm5_get_principal_keys(void *server_handle /* IN */, krb5_key_data *key_data; kadm5_ret_t ret; kadm5_server_handle_t handle = server_handle; + krb5_keyblock *mkey_ptr; if (keyblocks) *keyblocks = NULL; @@ -2026,6 +2093,25 @@ 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; + } + } + if (handle->api_version == KADM5_API_VERSION_1) { /* Version 1 clients will expect to see a DES_CRC enctype. */ if ((ret = krb5_dbe_find_enctype(handle->context, &kdb, @@ -2033,11 +2119,11 @@ kadm5_get_principal_keys(void *server_handle /* IN */, -1, -1, &key_data))) goto done; - if ((ret = decrypt_key_data(handle->context, 1, key_data, + if ((ret = decrypt_key_data(handle->context, mkey_ptr, 1, key_data, keyblocks, NULL))) goto done; } else { - ret = decrypt_key_data(handle->context, + ret = decrypt_key_data(handle->context, mkey_ptr, kdb.n_key_data, kdb.key_data, keyblocks, n_keys); if (ret) @@ -2056,10 +2142,10 @@ 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 - * master_keyblock, and if n_keys is not NULL fill it in with the + * mkey, and if n_keys is not NULL fill it in with the * number of keys decrypted. */ -static int decrypt_key_data(krb5_context context, +static int decrypt_key_data(krb5_context context, krb5_keyblock *mkey, int n_key_data, krb5_key_data *key_data, krb5_keyblock **keyblocks, int *n_keys) { @@ -2072,7 +2158,7 @@ static int decrypt_key_data(krb5_context context, memset((char *) keys, 0, n_key_data*sizeof(krb5_keyblock)); for (i = 0; i < n_key_data; i++) { - ret = krb5_dbekd_decrypt_key_data(context, &master_keyblock, + ret = krb5_dbekd_decrypt_key_data(context, mkey, &key_data[i], &keys[i], NULL); if (ret) { @@ -2135,6 +2221,7 @@ kadm5_ret_t kadm5_decrypt_key(void *server_handle, kadm5_server_handle_t handle = server_handle; krb5_db_entry dbent; krb5_key_data *key_data; + krb5_keyblock *mkey_ptr; int ret; CHECK_HANDLE(server_handle); @@ -2149,8 +2236,28 @@ kadm5_ret_t kadm5_decrypt_key(void *server_handle, stype, kvno, &key_data))) return ret; + /* find_mkey only uses this field */ + dbent.tl_data = entry->tl_data; + if ((ret = krb5_dbe_find_mkey(handle->context, master_keylist, &dbent, + &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, + &dbent, &mkey_ptr))) { + return ret; + } + } else { + return ret; + } + } + if ((ret = krb5_dbekd_decrypt_key_data(handle->context, - &master_keyblock, key_data, + mkey_ptr, key_data, keyblock, keysalt))) return ret; |
