summaryrefslogtreecommitdiffstats
path: root/src/lib/kdb/kdb_default.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/kdb/kdb_default.c')
-rw-r--r--src/lib/kdb/kdb_default.c220
1 files changed, 204 insertions, 16 deletions
diff --git a/src/lib/kdb/kdb_default.c b/src/lib/kdb/kdb_default.c
index f173e127df..df87916242 100644
--- a/src/lib/kdb/kdb_default.c
+++ b/src/lib/kdb/kdb_default.c
@@ -1,7 +1,7 @@
/*
* lib/kdb/kdb_helper.c
*
- * Copyright 1995, 2008 by the Massachusetts Institute of Technology.
+ * Copyright 1995, 2009 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -25,6 +25,11 @@
*
*/
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
#include "k5-int.h"
#include "kdb.h"
#include <string.h>
@@ -133,12 +138,11 @@ krb5_dbe_def_search_enctype(kcontext, dbentp, start, ktype, stype, kvno, kdatap)
#endif
krb5_error_code
-krb5_def_store_mkey(krb5_context context,
- char *keyfile,
- krb5_principal mname,
- krb5_kvno kvno,
- krb5_keyblock *key,
- char *master_pwd)
+krb5_def_store_mkey_list(krb5_context context,
+ char *keyfile,
+ krb5_principal mname,
+ krb5_keylist_node *keylist,
+ char *master_pwd)
{
krb5_error_code retval = 0;
char defkeyfile[MAXPATHLEN+1];
@@ -199,12 +203,17 @@ krb5_def_store_mkey(krb5_context context,
if (retval != 0)
goto out;
- memset((char *) &new_entry, 0, sizeof(new_entry));
- new_entry.principal = mname;
- new_entry.key = *key;
- new_entry.vno = kvno;
+ while (keylist && !retval) {
+ memset((char *) &new_entry, 0, sizeof(new_entry));
+ new_entry.principal = mname;
+ new_entry.key = keylist->keyblock;
+ new_entry.vno = keylist->kvno;
+
+ retval = krb5_kt_add_entry(context, kt, &new_entry);
+ keylist = keylist->next;
+ }
+ krb5_kt_close(context, kt);
- retval = krb5_kt_add_entry(context, kt, &new_entry);
if (retval != 0) {
/* delete tmp keyfile if it exists and an error occurrs */
if (stat(keyfile, &stb) >= 0)
@@ -222,12 +231,27 @@ krb5_def_store_mkey(krb5_context context,
out:
if (tmp_ktname != NULL)
free(tmp_ktname);
- if (kt)
- krb5_kt_close(context, kt);
return retval;
}
+krb5_error_code
+krb5_def_store_mkey(krb5_context context,
+ char *keyfile,
+ krb5_principal mname,
+ krb5_kvno kvno,
+ krb5_keyblock *key,
+ char *master_pwd)
+{
+ krb5_keylist_node list;
+
+ list.kvno = kvno;
+ list.keyblock = *key;
+ list.next = NULL;
+ return krb5_def_store_mkey_list(context, keyfile, mname, &list,
+ master_pwd);
+}
+
static krb5_error_code
krb5_db_def_fetch_mkey_stash(krb5_context context,
const char *keyfile,
@@ -288,7 +312,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
@@ -421,6 +445,9 @@ krb5_db_def_fetch_mkey(krb5_context context,
}
}
+/*
+ * Note, this verifies that the input mkey is currently protecting all the mkeys
+ */
krb5_error_code
krb5_def_verify_master_key(krb5_context context,
krb5_principal mprinc,
@@ -468,13 +495,160 @@ 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);
free(tempkey.contents);
krb5_db_free_principal(context, &master_entry, nprinc);
return retval;
}
+krb5_error_code
+krb5_def_fetch_mkey_list(krb5_context context,
+ krb5_principal mprinc,
+ const krb5_keyblock *mkey,
+ krb5_kvno mkvno,
+ krb5_keylist_node **mkeys_list)
+{
+ krb5_error_code retval;
+ krb5_db_entry master_entry;
+ int nprinc;
+ krb5_boolean more, found_key = FALSE;
+ 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;
+ int i;
+
+ if (mkeys_list == NULL)
+ return (EINVAL);
+
+ memset(&cur_mkey, 0, sizeof(cur_mkey));
+
+ nprinc = 1;
+ if ((retval = krb5_db_get_principal(context, mprinc,
+ &master_entry, &nprinc, &more)))
+ return (retval);
+
+ if (nprinc != 1) {
+ if (nprinc)
+ krb5_db_free_principal(context, &master_entry, nprinc);
+ return(KRB5_KDB_NOMASTERKEY);
+ } else if (more) {
+ krb5_db_free_principal(context, &master_entry, nprinc);
+ return (KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
+ }
+
+ /*
+ * Check if the input mkey is the latest key and if it isn't then find the
+ * latest mkey.
+ */
+
+ 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],
+ &cur_mkey, NULL) == 0) {
+ found_key = TRUE;
+ }
+ }
+
+ if (!found_key) {
+ /*
+ * Note the mkvno may provide a hint as to which mkey_aux tuple to
+ * decrypt.
+ */
+ if ((retval = krb5_dbe_lookup_mkey_aux(context, &master_entry,
+ &mkey_aux_data_list)))
+ goto clean_n_exit;
+
+ /* mkvno may be 0 in some cases like keyboard and should be ignored */
+ if (mkvno != 0) {
+ /* for performance sake, try decrypting with matching kvno */
+ for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL;
+ aux_data_entry = aux_data_entry->next) {
+
+ if (aux_data_entry->mkey_kvno == mkvno) {
+ if (krb5_dbekd_decrypt_key_data(context, mkey,
+ &aux_data_entry->latest_mkey,
+ &cur_mkey, NULL) == 0) {
+ found_key = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ if (!found_key) {
+ /* given the importance of acquiring the latest mkey, try brute force */
+ for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL;
+ aux_data_entry = aux_data_entry->next) {
+
+ if (mkey->enctype == aux_data_entry->latest_mkey.key_data_type[0] &&
+ (krb5_dbekd_decrypt_key_data(context, mkey,
+ &aux_data_entry->latest_mkey,
+ &cur_mkey, NULL) == 0)) {
+ found_key = TRUE;
+ break;
+ }
+ }
+ if (found_key != TRUE) {
+ krb5_set_error_message (context, KRB5_KDB_BADMASTERKEY,
+ "Unable to decrypt latest master key with the provided master key\n");
+ retval = KRB5_KDB_BADMASTERKEY;
+ goto clean_n_exit;
+ }
+ }
+ }
+
+ /*
+ * Extract all the mkeys from master_entry using the most current mkey and
+ * create a mkey list for the mkeys field in kdc_realm_t.
+ */
+
+ mkey_list_head = (krb5_keylist_node *) malloc(sizeof(krb5_keylist_node));
+ if (mkey_list_head == NULL) {
+ retval = ENOMEM;
+ goto clean_n_exit;
+ }
+
+ memset(mkey_list_head, 0, sizeof(krb5_keylist_node));
+
+ /* 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;
+
+ /* 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));
+ if (*mkey_list_node == NULL) {
+ retval = ENOMEM;
+ goto clean_n_exit;
+ }
+ memset(*mkey_list_node, 0, sizeof(krb5_keylist_node));
+ }
+ key_data = &master_entry.key_data[i];
+ retval = krb5_dbekd_decrypt_key_data(context, &cur_mkey,
+ key_data,
+ &((*mkey_list_node)->keyblock),
+ NULL);
+ if (retval)
+ goto clean_n_exit;
+
+ (*mkey_list_node)->kvno = key_data->key_data_kvno;
+ mkey_list_node = &((*mkey_list_node)->next);
+ }
+
+ *mkeys_list = mkey_list_head;
+
+clean_n_exit:
+ krb5_db_free_principal(context, &master_entry, nprinc);
+ if (retval != 0)
+ krb5_dbe_free_key_list(context, mkey_list_head);
+ return retval;
+}
krb5_error_code kdb_def_set_mkey ( krb5_context kcontext,
char *pwd,
@@ -491,6 +665,20 @@ krb5_error_code kdb_def_get_mkey ( krb5_context kcontext,
return 0;
}
+krb5_error_code kdb_def_set_mkey_list ( krb5_context kcontext,
+ krb5_keylist_node *keylist )
+{
+ /* printf("default set master key\n"); */
+ return 0;
+}
+
+krb5_error_code kdb_def_get_mkey_list ( krb5_context kcontext,
+ krb5_keylist_node **keylist )
+{
+ /* printf("default get master key\n"); */
+ return 0;
+}
+
krb5_error_code krb5_def_promote_db (krb5_context kcontext,
char *s, char **args)
{