aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWill Fiveash <will.fiveash@oracle.com>2009-01-27 04:16:26 +0000
committerWill Fiveash <will.fiveash@oracle.com>2009-01-27 04:16:26 +0000
commitc1e6bdf4eba202ad43fb416c884a66a8af24ab5f (patch)
tree6942d0fe6dcfc18a28e6f7220da980eb33fa4011 /src
parent45dc001ab167b4c49c2f7e07dc55a28f14305265 (diff)
downloadkrb5-c1e6bdf4eba202ad43fb416c884a66a8af24ab5f.zip
krb5-c1e6bdf4eba202ad43fb416c884a66a8af24ab5f.tar.gz
krb5-c1e6bdf4eba202ad43fb416c884a66a8af24ab5f.tar.bz2
More review changes:
Have both LDAP and DB2 back ends been tried with Will's new code? Looks like some default routines like kdb_def_get_mkey_list won't do anything; is that okay? Done but not tested. "XXX" comments in kdc/extern.h and elsewhere need to be looked into, obviously. Almost done (working on the mkey_convert issue). git-svn-id: svn://anonsvn.mit.edu/krb5/branches/mkey_migrate@21806 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/include/kdb.h13
-rw-r--r--src/kadmin/dbutil/dump.c86
-rw-r--r--src/kadmin/dbutil/kdb5_mkey.c298
-rw-r--r--src/kadmin/dbutil/kdb5_util.h2
-rw-r--r--src/kdc/extern.h10
-rw-r--r--src/kdc/main.c3
-rw-r--r--src/lib/kadm5/admin.h1
-rw-r--r--src/lib/kadm5/srv/server_kdb.c4
-rw-r--r--src/lib/kdb/kdb5.c48
-rw-r--r--src/lib/kdb/kdb_default.c47
-rw-r--r--src/lib/kdb/libkdb5.exports3
-rw-r--r--src/plugins/kdb/ldap/ldap_exp.c4
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c27
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h6
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c42
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h1
16 files changed, 343 insertions, 252 deletions
diff --git a/src/include/kdb.h b/src/include/kdb.h
index ae56568..d60a5c5 100644
--- a/src/include/kdb.h
+++ b/src/include/kdb.h
@@ -183,10 +183,10 @@ typedef struct __krb5_key_salt_tuple {
#define KRB5_TL_MKEY_AUX 0x000a
/* version number for KRB5_TL_ACTKVNO data */
-#define KRB5_TL_ACTKVNO_VER_1 1
+#define KRB5_TL_ACTKVNO_VER 1
/* version number for KRB5_TL_MKEY_AUX data */
-#define KRB5_TL_MKEY_AUX_VER_1 1
+#define KRB5_TL_MKEY_AUX_VER 1
typedef struct _krb5_actkvno_node {
struct _krb5_actkvno_node *next;
@@ -662,6 +662,15 @@ krb5_db_get_context
void
krb5_dbe_free_key_data_contents(krb5_context, krb5_key_data *);
+void
+krb5_dbe_free_key_list(krb5_context, krb5_keylist_node *);
+
+void
+krb5_dbe_free_actkvno_list(krb5_context, krb5_actkvno_node *);
+
+void
+krb5_dbe_free_mkey_aux_list(krb5_context, krb5_mkey_aux_node *);
+
#define KRB5_KDB_DEF_FLAGS 0
#define KDB_MAX_DB_NAME 128
diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
index 68a8270..f5b6cd6 100644
--- a/src/kadmin/dbutil/dump.c
+++ b/src/kadmin/dbutil/dump.c
@@ -178,6 +178,7 @@ extern krb5_boolean dbactive;
extern int exit_status;
extern krb5_context util_context;
extern kadm5_config_params global_params;
+extern krb5_keylist_node *master_keylist;
/* Strings */
@@ -274,48 +275,49 @@ static krb5_error_code master_key_convert(context, db_entry)
is_mkey = krb5_principal_compare(context, master_princ, db_entry->princ);
- /* XXX WAF: need to fix this! */
- if (is_mkey && db_entry->n_key_data != 1)
- fprintf(stderr,
- "Master key db entry has %d keys, expecting only 1!\n",
- db_entry->n_key_data);
- for (i=0; i < db_entry->n_key_data; i++) {
- key_data = &db_entry->key_data[i];
- if (key_data->key_data_length == 0)
- continue;
- retval = krb5_dbekd_decrypt_key_data(context, &master_keyblock,
- key_data, &v5plainkey,
- &keysalt);
- if (retval)
- return retval;
-
- memset(&new_key_data, 0, sizeof(new_key_data));
-
- if (is_mkey) {
- key_ptr = &new_master_keyblock;
- /* override mkey princ's kvno */
- if (global_params.mask & KADM5_CONFIG_KVNO)
- kvno = global_params.kvno;
- else
- kvno = (krb5_kvno) key_data->key_data_kvno;
- } else {
- key_ptr = &v5plainkey;
- kvno = (krb5_kvno) key_data->key_data_kvno;
- }
-
- retval = krb5_dbekd_encrypt_key_data(context, &new_master_keyblock,
- key_ptr, &keysalt,
- (int) kvno,
- &new_key_data);
- if (retval)
- return retval;
- krb5_free_keyblock_contents(context, &v5plainkey);
- for (j = 0; j < key_data->key_data_ver; j++) {
- if (key_data->key_data_length[j]) {
- free(key_data->key_data_contents[j]);
- }
- }
- *key_data = new_key_data;
+ if (is_mkey) {
+ retval = add_new_mkey(context, db_entry, &new_master_keyblock);
+ if (retval)
+ return retval;
+ } else {
+ for (i=0; i < db_entry->n_key_data; i++) {
+ key_data = &db_entry->key_data[i];
+ if (key_data->key_data_length == 0)
+ continue;
+ retval = krb5_dbekd_decrypt_key_data(context, &master_keyblock,
+ key_data, &v5plainkey,
+ &keysalt);
+ if (retval)
+ return retval;
+
+ memset(&new_key_data, 0, sizeof(new_key_data));
+
+ if (is_mkey) {
+ key_ptr = &new_master_keyblock;
+ /* override mkey princ's kvno */
+ if (global_params.mask & KADM5_CONFIG_KVNO)
+ kvno = global_params.kvno;
+ else
+ kvno = (krb5_kvno) key_data->key_data_kvno;
+ } else {
+ key_ptr = &v5plainkey;
+ kvno = (krb5_kvno) key_data->key_data_kvno;
+ }
+
+ retval = krb5_dbekd_encrypt_key_data(context, &new_master_keyblock,
+ key_ptr, &keysalt,
+ (int) kvno,
+ &new_key_data);
+ if (retval)
+ return retval;
+ krb5_free_keyblock_contents(context, &v5plainkey);
+ for (j = 0; j < key_data->key_data_ver; j++) {
+ if (key_data->key_data_length[j]) {
+ free(key_data->key_data_contents[j]);
+ }
+ }
+ *key_data = new_key_data;
+ }
}
return 0;
}
diff --git a/src/kadmin/dbutil/kdb5_mkey.c b/src/kadmin/dbutil/kdb5_mkey.c
index 57d469b..d127b41 100644
--- a/src/kadmin/dbutil/kdb5_mkey.c
+++ b/src/kadmin/dbutil/kdb5_mkey.c
@@ -34,6 +34,130 @@ static char *strdate(krb5_timestamp when)
return out;
}
+krb5_error_code
+add_new_mkey(krb5_context context, krb5_db_entry *master_entry, krb5_keyblock *new_mkey)
+{
+ krb5_error_code retval = 0;
+ int old_key_data_count, i;
+ krb5_kvno old_kvno, new_mkey_kvno;
+ krb5_keyblock new_mkeyblock;
+ krb5_key_data tmp_key_data, *old_key_data;
+ krb5_enctype new_master_enctype = ENCTYPE_UNKNOWN;
+ krb5_mkey_aux_node *mkey_aux_data_head = NULL, **mkey_aux_data,
+ *cur_mkey_aux_data, *next_mkey_aux_data;
+ krb5_keylist_node *keylist_node;
+
+ /* First save the old keydata */
+ old_kvno = krb5_db_get_key_data_kvno(context, master_entry->n_key_data,
+ master_entry->key_data);
+ old_key_data_count = master_entry->n_key_data;
+ old_key_data = master_entry->key_data;
+
+ /* alloc enough space to hold new and existing key_data */
+ /*
+ * The encrypted key is malloc'ed by krb5_dbekd_encrypt_key_data and
+ * krb5_key_data key_data_contents is a pointer to this key. Using some
+ * logic from master_key_convert().
+ */
+ master_entry->key_data = (krb5_key_data *) malloc(sizeof(krb5_key_data) *
+ (old_key_data_count + 1));
+ if (master_entry->key_data == NULL)
+ return (ENOMEM);
+
+ memset((char *) master_entry->key_data, 0,
+ sizeof(krb5_key_data) * (old_key_data_count + 1));
+ master_entry->n_key_data = old_key_data_count + 1;
+
+ new_mkey_kvno = old_kvno + 1;
+ /* deal with wrapping? */
+ if (new_mkey_kvno == 0)
+ new_mkey_kvno = 1; /* knvo must not be 0 as this is special value (IGNORE_VNO) */
+
+ /* Note, mkey does not have salt */
+ /* add new mkey encrypted with itself to mkey princ entry */
+ if ((retval = krb5_dbekd_encrypt_key_data(context, new_mkey,
+ new_mkey, NULL,
+ (int) new_mkey_kvno,
+ &master_entry->key_data[0]))) {
+ return (retval);
+ }
+
+ /*
+ * Need to decrypt old keys with the current mkey which is in the global
+ * master_keyblock and encrypt those keys with the latest mkey. And while
+ * the old keys are being decrypted, use those to create the
+ * KRB5_TL_MKEY_AUX entries which store the latest mkey encrypted by one of
+ * the older mkeys.
+ *
+ * The new mkey is followed by existing keys.
+ *
+ * First, set up for creating a krb5_mkey_aux_node list which will be used
+ * to update the mkey aux data for the mkey princ entry.
+ */
+ mkey_aux_data_head = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node));
+ if (mkey_aux_data_head == NULL) {
+ retval = ENOMEM;
+ goto clean_n_exit;
+ }
+ memset(mkey_aux_data_head, 0, sizeof(krb5_mkey_aux_node));
+ mkey_aux_data = &mkey_aux_data_head;
+
+ for (keylist_node = master_keylist, i = 1; keylist_node != NULL;
+ keylist_node = keylist_node->next, i++) {
+
+ /*
+ * Create a list of krb5_mkey_aux_node nodes. One node contains the new
+ * mkey encrypted by an old mkey and the old mkey's kvno (one node per
+ * old mkey).
+ */
+ if (*mkey_aux_data == NULL) {
+ /* *mkey_aux_data points to next field of previous node */
+ *mkey_aux_data = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node));
+ if (*mkey_aux_data == NULL) {
+ retval = ENOMEM;
+ goto clean_n_exit;
+ }
+ memset(*mkey_aux_data, 0, sizeof(krb5_mkey_aux_node));
+ }
+
+ memset(&tmp_key_data, 0, sizeof(tmp_key_data));
+ /* encrypt the new mkey with the older mkey */
+ retval = krb5_dbekd_encrypt_key_data(context, &keylist_node->keyblock,
+ new_mkey,
+ NULL, /* no keysalt */
+ (int) new_mkey_kvno,
+ &tmp_key_data);
+ if (retval)
+ goto clean_n_exit;
+
+ (*mkey_aux_data)->latest_mkey = tmp_key_data;
+ (*mkey_aux_data)->mkey_kvno = keylist_node->kvno;
+ mkey_aux_data = &((*mkey_aux_data)->next);
+
+ /*
+ * Store old key in master_entry keydata past the new mkey
+ */
+ retval = krb5_dbekd_encrypt_key_data(context, new_mkey,
+ &keylist_node->keyblock,
+ NULL, /* no keysalt */
+ (int) keylist_node->kvno,
+ &master_entry->key_data[i]);
+ if (retval)
+ goto clean_n_exit;
+ }
+ assert(i == old_key_data_count + 1);
+
+ if ((retval = krb5_dbe_update_mkey_aux(context, master_entry,
+ mkey_aux_data_head))) {
+ goto clean_n_exit;
+ }
+
+clean_n_exit:
+ if (mkey_aux_data_head)
+ krb5_dbe_free_mkey_aux_list(context, mkey_aux_data_head);
+ return (retval);
+}
+
void
kdb5_add_mkey(int argc, char *argv[])
{
@@ -47,7 +171,7 @@ kdb5_add_mkey(int argc, char *argv[])
krb5_boolean more = 0;
krb5_data pwd;
krb5_kvno old_kvno, new_mkey_kvno;
- krb5_keyblock new_master_keyblock;
+ krb5_keyblock new_mkeyblock;
krb5_key_data tmp_key_data, *old_key_data;
krb5_enctype new_master_enctype = ENCTYPE_UNKNOWN;
char *new_mkey_password;
@@ -95,8 +219,7 @@ kdb5_add_mkey(int argc, char *argv[])
}
retval = krb5_db_get_principal(util_context, master_princ, &master_entry,
- &nentries,
- &more);
+ &nentries, &more);
if (retval != 0) {
com_err(progname, retval, "while setting up master key name");
exit_status++;
@@ -137,129 +260,16 @@ kdb5_add_mkey(int argc, char *argv[])
}
retval = krb5_c_string_to_key(util_context, new_master_enctype,
- &pwd, &master_salt, &new_master_keyblock);
+ &pwd, &master_salt, &new_mkeyblock);
if (retval) {
com_err(progname, retval, "while transforming master key from password");
exit_status++;
return;
}
- /* First save the old keydata */
- old_kvno = krb5_db_get_key_data_kvno(util_context, master_entry.n_key_data,
- master_entry.key_data);
- old_key_data_count = master_entry.n_key_data;
- old_key_data = master_entry.key_data;
-
- /* alloc enough space to hold new and existing key_data */
- /*
- * The encrypted key is malloc'ed by krb5_dbekd_encrypt_key_data and
- * krb5_key_data key_data_contents is a pointer to this key. Using some
- * logic from master_key_convert().
- */
- master_entry.key_data = (krb5_key_data *) malloc(sizeof(krb5_key_data) *
- (old_key_data_count + 1));
- if (master_entry.key_data == NULL) {
- com_err(progname, ENOMEM, "while adding new master key");
- exit_status++;
- return;
- }
- memset((char *) master_entry.key_data, 0,
- sizeof(krb5_key_data) * (old_key_data_count + 1));
- master_entry.n_key_data = old_key_data_count + 1;
-
- new_mkey_kvno = old_kvno + 1;
- /* deal with wrapping? */
- if (new_mkey_kvno == 0)
- new_mkey_kvno = 1; /* knvo must not be 0 as this is special value (IGNORE_VNO) */
-
- /* Note, mkey does not have salt */
- /* add new mkey encrypted with itself to mkey princ entry */
- if ((retval = krb5_dbekd_encrypt_key_data(util_context, &new_master_keyblock,
- &new_master_keyblock, NULL,
- (int) new_mkey_kvno,
- master_entry.key_data))) {
- com_err(progname, retval, "while creating new master key");
- exit_status++;
- return;
- }
-
- /*
- * Need to decrypt old keys with the current mkey which is in the global
- * master_keyblock and encrypt those keys with the latest mkey. And while
- * the old keys are being decrypted, use those to create the
- * KRB5_TL_MKEY_AUX entries which store the latest mkey encrypted by one of
- * the older mkeys.
- *
- * The new mkey is followed by existing keys.
- *
- * First, set up for creating a krb5_mkey_aux_node list which will be used
- * to update the mkey aux data for the mkey princ entry.
- */
- mkey_aux_data_head = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node));
- if (mkey_aux_data_head == NULL) {
- com_err(progname, ENOMEM, "while creating mkey_aux_data");
- exit_status++;
- return;
- }
- memset(mkey_aux_data_head, 0, sizeof(krb5_mkey_aux_node));
- mkey_aux_data = &mkey_aux_data_head;
-
- for (keylist_node = master_keylist, i = 1; keylist_node != NULL;
- keylist_node = keylist_node->next, i++) {
-
- /*
- * Create a list of krb5_mkey_aux_node nodes. One node contains the new
- * mkey encrypted by an old mkey and the old mkey's kvno (one node per
- * old mkey).
- */
- if (*mkey_aux_data == NULL) {
- /* *mkey_aux_data points to next field of previous node */
- *mkey_aux_data = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node));
- if (*mkey_aux_data == NULL) {
- com_err(progname, ENOMEM, "while creating mkey_aux_data");
- exit_status++;
- return;
- }
- memset(*mkey_aux_data, 0, sizeof(krb5_mkey_aux_node));
- }
-
- memset(&tmp_key_data, 0, sizeof(tmp_key_data));
- /* encrypt the new mkey with the older mkey */
- retval = krb5_dbekd_encrypt_key_data(util_context, &keylist_node->keyblock,
- &new_master_keyblock,
- NULL, /* no keysalt */
- (int) new_mkey_kvno,
- &tmp_key_data);
- if (retval) {
- com_err(progname, retval, "while encrypting master keys");
- exit_status++;
- return;
- }
-
- (*mkey_aux_data)->latest_mkey = tmp_key_data;
- (*mkey_aux_data)->mkey_kvno = keylist_node->kvno;
- mkey_aux_data = &((*mkey_aux_data)->next);
-
- /*
- * Store old key in master_entry keydata past the new mkey
- */
- retval = krb5_dbekd_encrypt_key_data(util_context, &new_master_keyblock,
- &keylist_node->keyblock,
- NULL, /* no keysalt */
- (int) keylist_node->kvno,
- &master_entry.key_data[i]);
- if (retval) {
- com_err(progname, retval, "while encrypting master keys");
- exit_status++;
- return;
- }
- }
-
- assert(i == old_key_data_count + 1);
-
- if ((retval = krb5_dbe_update_mkey_aux(util_context, &master_entry,
- mkey_aux_data_head))) {
- com_err(progname, retval, "while updating mkey aux data");
+ retval = add_new_mkey(util_context, &master_entry, &new_mkeyblock);
+ if (retval) {
+ com_err(progname, retval, "adding new master key to master principal");
exit_status++;
return;
}
@@ -286,11 +296,11 @@ kdb5_add_mkey(int argc, char *argv[])
if (do_stash) {
retval = krb5_db_store_master_key(util_context,
- global_params.stash_file,
- master_princ,
- new_mkey_kvno,
- &new_master_keyblock,
- mkey_password);
+ global_params.stash_file,
+ master_princ,
+ new_mkey_kvno,
+ &new_mkeyblock,
+ mkey_password);
if (retval) {
com_err(progname, errno, "while storing key");
printf("Warning: couldn't stash master key.\n");
@@ -300,8 +310,8 @@ kdb5_add_mkey(int argc, char *argv[])
(void) krb5_db_fini(util_context);
zap((char *)master_keyblock.contents, master_keyblock.length);
free(master_keyblock.contents);
- zap((char *)new_master_keyblock.contents, new_master_keyblock.length);
- free(new_master_keyblock.contents);
+ zap((char *)new_mkeyblock.contents, new_mkeyblock.length);
+ free(new_mkeyblock.contents);
if (pw_str) {
zap(pw_str, pw_size);
free(pw_str);
@@ -309,12 +319,6 @@ kdb5_add_mkey(int argc, char *argv[])
free(master_salt.data);
free(mkey_fullname);
- for (cur_mkey_aux_data = mkey_aux_data_head; cur_mkey_aux_data != NULL;
- cur_mkey_aux_data = next_mkey_aux_data) {
- next_mkey_aux_data = cur_mkey_aux_data->next;
- krb5_dbe_free_key_data_contents(util_context, &(cur_mkey_aux_data->latest_mkey));
- free(cur_mkey_aux_data);
- }
return;
}
@@ -329,19 +333,33 @@ kdb5_use_mkey(int argc, char *argv[])
*prev_actkvno, *cur_actkvno;
krb5_db_entry master_entry;
int nentries = 0;
- krb5_boolean more = 0;
+ krb5_boolean more = 0, found;
+ krb5_keylist_node *keylist_node;
if (argc < 2 || argc > 3) {
/* usage calls exit */
usage();
}
- /* use_kvno = (int) strtol(argv[0], (char **)NULL, 10); */
use_kvno = atoi(argv[1]);
if (use_kvno == 0) {
com_err(progname, EINVAL, ": 0 is an invalid KVNO value.");
exit_status++;
return;
+ } else {
+ /* verify use_kvno is valid */
+ for (keylist_node = master_keylist, found = FALSE; keylist_node != NULL;
+ keylist_node = keylist_node->next) {
+ if (use_kvno == keylist_node->kvno) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found) {
+ com_err(progname, EINVAL, ": %d is an invalid KVNO value.", use_kvno);
+ exit_status++;
+ return;
+ }
}
if ((retval = krb5_timeofday(util_context, &now))) {
@@ -360,7 +378,6 @@ kdb5_use_mkey(int argc, char *argv[])
* Need to:
*
* 1. get mkey princ
- * 2. verify that mprinc actually has a mkey with the new actkvno
* 2. get krb5_actkvno_node list
* 3. add use_kvno to actkvno list (sorted in right spot)
* 4. update mkey princ's tl data
@@ -385,8 +402,6 @@ kdb5_use_mkey(int argc, char *argv[])
return;
}
- /* XXX WAF: verify that the provided kvno is valid */
-
retval = krb5_dbe_lookup_actkvno(util_context, &master_entry, &actkvno_list);
if (retval != 0) {
com_err(progname, retval, "while setting up master key name");
@@ -478,12 +493,7 @@ kdb5_use_mkey(int argc, char *argv[])
/* clean up */
(void) krb5_db_fini(util_context);
free(mkey_fullname);
- for (cur_actkvno = actkvno_list; cur_actkvno != NULL;) {
-
- prev_actkvno = cur_actkvno;
- cur_actkvno = cur_actkvno->next;
- free(prev_actkvno);
- }
+ krb5_dbe_free_actkvno_list(util_context, actkvno_list);
return;
}
diff --git a/src/kadmin/dbutil/kdb5_util.h b/src/kadmin/dbutil/kdb5_util.h
index cc69c90..dd74654 100644
--- a/src/kadmin/dbutil/kdb5_util.h
+++ b/src/kadmin/dbutil/kdb5_util.h
@@ -88,5 +88,7 @@ extern void update_ok_file (char *file_name);
extern int kadm5_create (kadm5_config_params *params);
+extern krb5_error_code add_new_mkey(krb5_context, krb5_db_entry *, krb5_keyblock *);
+
void usage (void);
diff --git a/src/kdc/extern.h b/src/kdc/extern.h
index d79e1aa..3b67eb8 100644
--- a/src/kdc/extern.h
+++ b/src/kdc/extern.h
@@ -41,7 +41,6 @@ typedef struct __kdc_realm_data {
krb5_context realm_context; /* Context to be used for realm */
krb5_keytab realm_keytab; /* keytab to be used for this realm */
char * realm_profile; /* Profile file for this realm */
- krb5_keylist_node * mkey_list; /* list of mkeys in use for this realm */
/*
* Database per-realm data.
*/
@@ -49,13 +48,12 @@ typedef struct __kdc_realm_data {
char * realm_stash; /* Stash file name for realm */
char * realm_mpname; /* Master principal name for realm */
krb5_principal realm_mprinc; /* Master principal for realm */
- /* XXX WAF: is realm_mkey the most current key in the keytab (or from
- * command line)? Or should this be the active key? I need to make sure
- * this is handled properly. what about the kvno of this key?
- * or maybe this should go away and be replaced with a function that
- * returns the proper mkey given a princ.
+ /*
+ * Note realm_mkey is mkey read from stash or keyboard and may not be the
+ * latest. The mkey_list will have all the mkeys in use.
*/
krb5_keyblock realm_mkey; /* Master key for this realm */
+ krb5_keylist_node * mkey_list; /* list of mkeys in use for this realm */
/*
* TGS per-realm data.
*/
diff --git a/src/kdc/main.c b/src/kdc/main.c
index 7a74139..4394b6d 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -150,9 +150,12 @@ finish_realm(kdc_realm_t *rdp)
if (rdp->realm_mprinc)
krb5_free_principal(rdp->realm_context, rdp->realm_mprinc);
if (rdp->realm_mkey.length && rdp->realm_mkey.contents) {
+ /* XXX shouldn't memset be zap for safety? */
memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length);
free(rdp->realm_mkey.contents);
}
+ if (rdp->mkey_list)
+ krb5_dbe_free_key_list(rdp->realm_context, rdp->mkey_list);
krb5_db_fini(rdp->realm_context);
if (rdp->realm_tgsprinc)
krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc);
diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h
index c861772..b2d05ad 100644
--- a/src/lib/kadm5/admin.h
+++ b/src/lib/kadm5/admin.h
@@ -184,7 +184,6 @@ typedef struct _kadm5_principal_ent_t_v2 {
krb5_int16 n_tl_data;
krb5_tl_data *tl_data;
krb5_key_data *key_data;
- int foo; /* XXX WAF: just to see if it breaks the build */
} kadm5_principal_ent_rec_v2, *kadm5_principal_ent_t_v2;
typedef struct _kadm5_principal_ent_t_v1 {
diff --git a/src/lib/kadm5/srv/server_kdb.c b/src/lib/kadm5/srv/server_kdb.c
index 31f793a..b73444c 100644
--- a/src/lib/kadm5/srv/server_kdb.c
+++ b/src/lib/kadm5/srv/server_kdb.c
@@ -76,8 +76,8 @@ krb5_error_code kdb_init_master(kadm5_server_handle_t handle,
#if 0 /************** Begin IFDEF'ed OUT *******************************/
/*
- * XXX WAF: since the local mkey may not be latest, hold off on verifying it
- * since krb5_db_fetch_mkey_list will do this work.
+ * 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))) {
diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c
index 40de458..d68bf60 100644
--- a/src/lib/kdb/kdb5.c
+++ b/src/lib/kdb/kdb5.c
@@ -111,8 +111,7 @@ kdb_unlock_list()
* so there is only a single version.
*/
void
-krb5_dbe_free_key_data_contents(krb5_context context,
- krb5_key_data *key)
+krb5_dbe_free_key_data_contents(krb5_context context, krb5_key_data *key)
{
int i, idx;
@@ -126,8 +125,21 @@ krb5_dbe_free_key_data_contents(krb5_context context,
return;
}
-static void
-krb5_free_actkvno_list(krb5_context context, krb5_actkvno_node *val)
+void
+krb5_dbe_free_key_list(krb5_context context, krb5_keylist_node *mkey_list)
+{
+ krb5_keylist_node *cur_node, *next_node;
+
+ for (cur_node = mkey_list; cur_node != NULL; cur_node = next_node) {
+ next_node = cur_node->next;
+ krb5_free_keyblock(context, &(cur_node->keyblock));
+ krb5_xfree(cur_node);
+ }
+ return;
+}
+
+void
+krb5_dbe_free_actkvno_list(krb5_context context, krb5_actkvno_node *val)
{
krb5_actkvno_node *temp, *prev;
@@ -138,8 +150,8 @@ krb5_free_actkvno_list(krb5_context context, krb5_actkvno_node *val)
}
}
-static void
-krb5_free_mkey_aux_list(krb5_context context, krb5_mkey_aux_node *val)
+void
+krb5_dbe_free_mkey_aux_list(krb5_context context, krb5_mkey_aux_node *val)
{
krb5_mkey_aux_node *temp, *prev;
@@ -2284,8 +2296,7 @@ krb5_dbe_lookup_mkey_aux(krb5_context context,
} else {
/* get version to determine how to parse the data */
krb5_kdb_decode_int16(tl_data.tl_data_contents, version);
- if (version == KRB5_TL_MKEY_AUX_VER_1) {
-
+ if (version == 1) {
/* variable size, must be at least 10 bytes */
if (tl_data.tl_data_length < 10)
return (KRB5_KDB_TRUNCATED_RECORD);
@@ -2297,7 +2308,7 @@ krb5_dbe_lookup_mkey_aux(krb5_context context,
new_data = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node));
if (new_data == NULL) {
- krb5_free_mkey_aux_list(context, head_data);
+ krb5_dbe_free_mkey_aux_list(context, head_data);
return (ENOMEM);
}
memset(new_data, 0, sizeof(krb5_mkey_aux_node));
@@ -2315,7 +2326,7 @@ krb5_dbe_lookup_mkey_aux(krb5_context context,
malloc(new_data->latest_mkey.key_data_length[0]);
if (new_data->latest_mkey.key_data_contents[0] == NULL) {
- krb5_free_mkey_aux_list(context, head_data);
+ krb5_dbe_free_mkey_aux_list(context, head_data);
return (ENOMEM);
}
memcpy(new_data->latest_mkey.key_data_contents[0], curloc,
@@ -2343,6 +2354,7 @@ krb5_dbe_lookup_mkey_aux(krb5_context context,
return (0);
}
+#if KRB5_TL_MKEY_AUX_VER == 1
krb5_error_code
krb5_dbe_update_mkey_aux(krb5_context context,
krb5_db_entry * entry,
@@ -2377,7 +2389,7 @@ krb5_dbe_update_mkey_aux(krb5_context context,
}
nextloc = tl_data.tl_data_contents;
- version = KRB5_TL_MKEY_AUX_VER_1;
+ version = KRB5_TL_MKEY_AUX_VER;
krb5_kdb_encode_int16(version, nextloc);
nextloc += sizeof(krb5_ui_2);
@@ -2409,15 +2421,17 @@ krb5_dbe_update_mkey_aux(krb5_context context,
return (krb5_dbe_update_tl_data(context, entry, &tl_data));
}
+#endif /* KRB5_TL_MKEY_AUX_VER == 1 */
-/* XXX WAF: should probably #ifdef this to be defined if version 1 is in use */
+#if KRB5_TL_ACTKVNO_VER == 1
/*
- * If version of the KRB5_TL_ACTKVNO data is KRB5_TL_ACTKVNO_VER_1 then size of
+ * If version of the KRB5_TL_ACTKVNO data is KRB5_TL_ACTKVNO_VER == 1 then size of
* a actkvno tuple {act_kvno, act_time} entry is:
*/
#define ACTKVNO_TUPLE_SIZE (sizeof(krb5_int16) + sizeof(krb5_int32))
#define act_kvno(cp) (cp) /* return pointer to start of act_kvno data */
#define act_time(cp) ((cp) + sizeof(krb5_int16)) /* return pointer to start of act_time data */
+#endif
krb5_error_code
krb5_dbe_lookup_actkvno(krb5_context context,
@@ -2443,7 +2457,7 @@ krb5_dbe_lookup_actkvno(krb5_context context,
} else {
/* get version to determine how to parse the data */
krb5_kdb_decode_int16(tl_data.tl_data_contents, version);
- if (version == KRB5_TL_ACTKVNO_VER_1) {
+ if (version == 1) {
/* variable size, must be at least 8 bytes */
if (tl_data.tl_data_length < 8)
@@ -2461,7 +2475,7 @@ krb5_dbe_lookup_actkvno(krb5_context context,
for (i = 0; i < num_actkvno; i++) {
new_data = (krb5_actkvno_node *) malloc(sizeof(krb5_actkvno_node));
if (new_data == NULL) {
- krb5_free_actkvno_list(context, head_data);
+ krb5_dbe_free_actkvno_list(context, head_data);
return (ENOMEM);
}
memset(new_data, 0, sizeof(krb5_actkvno_node));
@@ -2492,6 +2506,7 @@ krb5_dbe_lookup_actkvno(krb5_context context,
/*
* Add KRB5_TL_ACTKVNO TL data entries to krb5_db_entry *entry
*/
+#if KRB5_TL_ACTKVNO_VER == 1
krb5_error_code
krb5_dbe_update_actkvno(krb5_context context,
krb5_db_entry *entry,
@@ -2516,7 +2531,7 @@ krb5_dbe_update_actkvno(krb5_context context,
return (ENOMEM);
/* add the current version # for the data format used for KRB5_TL_ACTKVNO */
- version = KRB5_TL_ACTKVNO_VER_1;
+ version = KRB5_TL_ACTKVNO_VER;
krb5_kdb_encode_int16(version, (unsigned char *) new_tl_data.tl_data_contents);
for (cur_actkvno = actkvno_list; cur_actkvno != NULL;
@@ -2549,6 +2564,7 @@ krb5_dbe_update_actkvno(krb5_context context,
return (retval);
}
+#endif /* KRB5_TL_ACTKVNO_VER == 1 */
krb5_error_code
krb5_dbe_update_last_pwd_change(context, entry, stamp)
diff --git a/src/lib/kdb/kdb_default.c b/src/lib/kdb/kdb_default.c
index c290655..82b2ced 100644
--- a/src/lib/kdb/kdb_default.c
+++ b/src/lib/kdb/kdb_default.c
@@ -288,7 +288,7 @@ krb5_db_def_fetch_mkey_stash(krb5_context context,
if (fread((krb5_pointer) key->contents, sizeof(key->contents[0]),
key->length, kf) != key->length) {
retval = KRB5_KDB_CANTREAD_STORED;
- memset(key->contents, 0, key->length);
+ zap(key->contents, key->length);
free(key->contents);
key->contents = 0;
} else
@@ -471,7 +471,7 @@ krb5_def_verify_master_key(krb5_context context,
kvno, master_entry.key_data->key_data_kvno);
}
- memset((char *)tempkey.contents, 0, tempkey.length);
+ zap((char *)tempkey.contents, tempkey.length);
krb5_xfree(tempkey.contents);
krb5_db_free_principal(context, &master_entry, nprinc);
@@ -489,8 +489,7 @@ krb5_def_fetch_mkey_list(krb5_context context,
krb5_db_entry master_entry;
int nprinc;
krb5_boolean more, found_key = FALSE;
- krb5_keyblock tmp_clearkey;
- const krb5_keyblock *current_mkey;
+ krb5_keyblock cur_mkey;
krb5_keylist_node *mkey_list_head = NULL, **mkey_list_node;
krb5_key_data *key_data;
krb5_mkey_aux_node *mkey_aux_data_list, *aux_data_entry;
@@ -499,7 +498,7 @@ krb5_def_fetch_mkey_list(krb5_context context,
if (mkeys_list == NULL)
return (EINVAL);
- memset(&tmp_clearkey, 0, sizeof(tmp_clearkey));
+ memset(&cur_mkey, 0, sizeof(cur_mkey));
nprinc = 1;
if ((retval = krb5_db_get_principal(context, mprinc,
@@ -523,8 +522,7 @@ krb5_def_fetch_mkey_list(krb5_context context,
if (mkey->enctype == master_entry.key_data[0].key_data_type[0]) {
if (krb5_dbekd_decrypt_key_data(context, mkey,
&master_entry.key_data[0],
- &tmp_clearkey, NULL) == 0) {
- current_mkey = mkey;
+ &cur_mkey, NULL) == 0) {
found_key = TRUE;
}
}
@@ -545,7 +543,7 @@ krb5_def_fetch_mkey_list(krb5_context context,
if (aux_data_entry->mkey_kvno == mkvno) {
if (krb5_dbekd_decrypt_key_data(context, mkey, &aux_data_entry->latest_mkey,
- &tmp_clearkey, NULL) == 0) {
+ &cur_mkey, NULL) == 0) {
found_key = TRUE;
break;
}
@@ -559,9 +557,8 @@ krb5_def_fetch_mkey_list(krb5_context context,
if (mkey->enctype == aux_data_entry->latest_mkey.key_data_type[0] &&
(krb5_dbekd_decrypt_key_data(context, mkey, &aux_data_entry->latest_mkey,
- &tmp_clearkey, NULL) == 0)) {
+ &cur_mkey, NULL) == 0)) {
found_key = TRUE;
- /* XXX WAF: should I issue warning about kvno not matching? */
break;
}
}
@@ -572,7 +569,6 @@ krb5_def_fetch_mkey_list(krb5_context context,
goto clean_n_exit;
}
}
- current_mkey = &tmp_clearkey;
}
/*
@@ -587,12 +583,16 @@ krb5_def_fetch_mkey_list(krb5_context context,
}
memset(mkey_list_head, 0, sizeof(krb5_keylist_node));
- mkey_list_node = &mkey_list_head;
- /* XXX WAF: optimize by setting the first mkey_list_node to current mkey and
- * if there are any others then do for loop below. */
+ /* Set mkey_list_head to the current mkey as an optimization. */
+ /* mkvno may not be latest so ... */
+ mkey_list_head->kvno = master_entry.key_data[0].key_data_kvno;
+ /* this is the latest clear mkey (avoids a redundant decrypt) */
+ mkey_list_head->keyblock = cur_mkey;
- for (i = 0; i < master_entry.n_key_data; i++) {
+ /* loop through any other master keys creating a list of krb5_keylist_nodes */
+ mkey_list_node = &mkey_list_head->next;
+ for (i = 1; i < master_entry.n_key_data; i++) {
if (*mkey_list_node == NULL) {
/* *mkey_list_node points to next field of previous node */
*mkey_list_node = (krb5_keylist_node *) malloc(sizeof(krb5_keylist_node));
@@ -603,7 +603,7 @@ krb5_def_fetch_mkey_list(krb5_context context,
memset(*mkey_list_node, 0, sizeof(krb5_keylist_node));
}
key_data = &master_entry.key_data[i];
- retval = krb5_dbekd_decrypt_key_data(context, current_mkey,
+ retval = krb5_dbekd_decrypt_key_data(context, &cur_mkey,
key_data,
&((*mkey_list_node)->keyblock),
NULL);
@@ -618,21 +618,10 @@ krb5_def_fetch_mkey_list(krb5_context context,
clean_n_exit:
- if (tmp_clearkey.contents) {
- memset(tmp_clearkey.contents, 0, tmp_clearkey.length);
- krb5_db_free(context, tmp_clearkey.contents);
- }
-
krb5_db_free_principal(context, &master_entry, nprinc);
- if (retval != 0) {
- krb5_keylist_node *cur_node, *next_node;
- for (cur_node = mkey_list_head; cur_node != NULL; cur_node = next_node) {
- next_node = cur_node->next;
- krb5_free_keyblock(context, &(cur_node->keyblock));
- krb5_xfree(cur_node);
- }
- }
+ if (retval != 0)
+ krb5_dbe_free_key_list(context, mkey_list_head);
return retval;
}
diff --git a/src/lib/kdb/libkdb5.exports b/src/lib/kdb/libkdb5.exports
index c202f98..3cc0816 100644
--- a/src/lib/kdb/libkdb5.exports
+++ b/src/lib/kdb/libkdb5.exports
@@ -37,7 +37,10 @@ krb5_dbe_find_act_mkey
krb5_dbe_fetch_act_key_list
krb5_dbe_find_enctype
krb5_dbe_find_mkey
+krb5_dbe_free_actkvno_list
krb5_dbe_free_key_data_contents
+krb5_dbe_free_mkey_aux_list
+krb5_dbe_free_key_list
krb5_dbe_lookup_last_pwd_change
krb5_dbe_lookup_actkvno
krb5_dbe_lookup_mkvno
diff --git a/src/plugins/kdb/ldap/ldap_exp.c b/src/plugins/kdb/ldap/ldap_exp.c
index 2b3da30..2292f55 100644
--- a/src/plugins/kdb/ldap/ldap_exp.c
+++ b/src/plugins/kdb/ldap/ldap_exp.c
@@ -78,8 +78,8 @@ kdb_vftabl kdb_function_table = {
/* optional functions */
/* set_master_key */ krb5_ldap_set_mkey,
/* get_master_key */ krb5_ldap_get_mkey,
- /* set_master_key_list */ NULL,
- /* get_master_key_list */ NULL,
+ /* set_master_key_list */ krb5_ldap_set_mkey_list,
+ /* get_master_key_list */ krb5_ldap_get_mkey_list,
/* setup_master_key_name */ NULL,
/* store_master_key */ NULL,
/* fetch_master_key */ NULL /* krb5_ldap_fetch_mkey */,
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c
index c13d967..60d9e25 100644
--- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c
@@ -2379,6 +2379,8 @@ kdb_ldap_create_principal (context, princ, op, pblock)
krb5_ldap_context *ldap_context=NULL;
struct iterate_args iargs;
krb5_data *pdata;
+ krb5_timestamp now;
+ krb5_actkvno_node actkvno;
if ((pblock == NULL) || (context == NULL)) {
retval = EINVAL;
@@ -2425,14 +2427,12 @@ kdb_ldap_create_principal (context, princ, op, pblock)
entry.tl_data = tl_data;
entry.n_tl_data += 1;
/* Set the creator's name */
- {
- krb5_timestamp now;
- if ((retval = krb5_timeofday(context, &now)))
- goto cleanup;
- if ((retval = krb5_dbe_update_mod_princ_data_new(context, &entry,
- now, &db_create_princ)))
- goto cleanup;
- }
+ if ((retval = krb5_timeofday(context, &now)))
+ goto cleanup;
+ if ((retval = krb5_dbe_update_mod_princ_data_new(context, &entry,
+ now, &db_create_princ)))
+ goto cleanup;
+
entry.attributes = pblock->flags;
entry.max_life = pblock->max_life;
entry.max_renewable_life = pblock->max_rlife;
@@ -2507,6 +2507,17 @@ kdb_ldap_create_principal (context, princ, op, pblock)
if (retval) {
goto cleanup;
}
+ /*
+ * There should always be at least one "active" mkey so creating the
+ * KRB5_TL_ACTKVNO entry now so the initial mkey is active.
+ */
+ actkvno.next = NULL;
+ actkvno.act_kvno = kvno;
+ actkvno.act_time = now;
+ retval = krb5_dbe_update_actkvno(context, &entry, &actkvno);
+ if (retval)
+ goto cleanup;
+
break;
case NULL_KEY:
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
index 74bf4b1..802ab0f 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
+++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
@@ -267,6 +267,12 @@ krb5_error_code
krb5_ldap_set_mkey(krb5_context, char *, krb5_keyblock *);
krb5_error_code
+krb5_ldap_get_mkey_list (krb5_context context, krb5_keylist_node **key_list);
+
+krb5_error_code
+krb5_ldap_set_mkey_list(krb5_context, krb5_keylist_node *);
+
+krb5_error_code
krb5_ldap_create(krb5_context , char *, char **);
krb5_error_code
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c
index 9a36419..6da0806 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c
@@ -98,3 +98,45 @@ krb5_ldap_set_mkey (context, pwd, key)
memcpy(r_params->mkey.contents, key->contents, key->length);
return 0;
}
+
+krb5_error_code
+krb5_ldap_get_mkey_list (krb5_context context, krb5_keylist_node **key_list)
+
+{
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ dal_handle = context->dal_handle;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+ if (ldap_context == NULL || ldap_context->lrparams == NULL)
+ return KRB5_KDB_DBNOTINITED;
+
+ *key_list = ldap_context->lrparams->mkey_list;
+ return 0;
+}
+
+krb5_error_code
+krb5_ldap_set_mkey_list(krb5_context context, krb5_keylist_node *key_list)
+{
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_realm_params *r_params = NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ dal_handle = context->dal_handle;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+ if (ldap_context == NULL || ldap_context->lrparams == NULL)
+ return KRB5_KDB_DBNOTINITED;
+
+ r_params = ldap_context->lrparams;
+ r_params->mkey_list = key_list;
+ return 0;
+}
+
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h
index ffe6c36..db17509 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h
@@ -68,6 +68,7 @@ typedef struct _krb5_ldap_realm_params {
char **passwdservers;
krb5_tl_data *tl_data;
krb5_keyblock mkey;
+ krb5_keylist_node *mkey_list; /* all master keys in use for the realm */
long mask;
} krb5_ldap_realm_params;