summaryrefslogtreecommitdiffstats
path: root/src/lib/kadm5
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/kadm5')
-rw-r--r--src/lib/kadm5/srv/libkadm5srv.exports1
-rw-r--r--src/lib/kadm5/srv/server_kdb.c43
-rw-r--r--src/lib/kadm5/srv/svr_iters.c1
-rw-r--r--src/lib/kadm5/srv/svr_principal.c153
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;