svn rev #21806: branches/mkey_migrate/src/ include/ kadmin/dbutil/ kdc/ lib/kadm5/ ...

wfiveash@MIT.EDU wfiveash at MIT.EDU
Mon Jan 26 23:16:32 EST 2009


http://src.mit.edu/fisheye/changelog/krb5/?cs=21806
Commit By: wfiveash
Log Message:
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).



Changed Files:
U   branches/mkey_migrate/src/include/kdb.h
U   branches/mkey_migrate/src/kadmin/dbutil/dump.c
U   branches/mkey_migrate/src/kadmin/dbutil/kdb5_mkey.c
U   branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.h
U   branches/mkey_migrate/src/kdc/extern.h
U   branches/mkey_migrate/src/kdc/main.c
U   branches/mkey_migrate/src/lib/kadm5/admin.h
U   branches/mkey_migrate/src/lib/kadm5/srv/server_kdb.c
U   branches/mkey_migrate/src/lib/kdb/kdb5.c
U   branches/mkey_migrate/src/lib/kdb/kdb_default.c
U   branches/mkey_migrate/src/lib/kdb/libkdb5.exports
U   branches/mkey_migrate/src/plugins/kdb/ldap/ldap_exp.c
U   branches/mkey_migrate/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c
U   branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
U   branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c
U   branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h
Modified: branches/mkey_migrate/src/include/kdb.h
===================================================================
--- branches/mkey_migrate/src/include/kdb.h	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/include/kdb.h	2009-01-27 04:16:26 UTC (rev 21806)
@@ -183,10 +183,10 @@
 #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 @@
 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

Modified: branches/mkey_migrate/src/kadmin/dbutil/dump.c
===================================================================
--- branches/mkey_migrate/src/kadmin/dbutil/dump.c	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/kadmin/dbutil/dump.c	2009-01-27 04:16:26 UTC (rev 21806)
@@ -178,6 +178,7 @@
 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 @@
 
     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;
+    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));
+            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;
-	}
+            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;
+            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;
 }

Modified: branches/mkey_migrate/src/kadmin/dbutil/kdb5_mkey.c
===================================================================
--- branches/mkey_migrate/src/kadmin/dbutil/kdb5_mkey.c	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/kadmin/dbutil/kdb5_mkey.c	2009-01-27 04:16:26 UTC (rev 21806)
@@ -34,6 +34,130 @@
     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 @@
     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 @@
     }
 
     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,133 +260,20 @@
     }
 
     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");
+    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;
     }
-    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");
-        exit_status++;
-        return;
-    }
-
     if ((retval = krb5_timeofday(util_context, &now))) {
         com_err(progname, retval, "while getting current time");
         exit_status++;
@@ -286,11 +296,11 @@
 
     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 @@
     (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 @@
     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 @@
                       *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 @@
      * 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 @@
         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 @@
     /* 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;
 }
 

Modified: branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.h
===================================================================
--- branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.h	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/kadmin/dbutil/kdb5_util.h	2009-01-27 04:16:26 UTC (rev 21806)
@@ -88,5 +88,7 @@
 
 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);
 

Modified: branches/mkey_migrate/src/kdc/extern.h
===================================================================
--- branches/mkey_migrate/src/kdc/extern.h	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/kdc/extern.h	2009-01-27 04:16:26 UTC (rev 21806)
@@ -41,7 +41,6 @@
     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 @@
     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.
      */

Modified: branches/mkey_migrate/src/kdc/main.c
===================================================================
--- branches/mkey_migrate/src/kdc/main.c	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/kdc/main.c	2009-01-27 04:16:26 UTC (rev 21806)
@@ -150,9 +150,12 @@
 	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);

Modified: branches/mkey_migrate/src/lib/kadm5/admin.h
===================================================================
--- branches/mkey_migrate/src/lib/kadm5/admin.h	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/lib/kadm5/admin.h	2009-01-27 04:16:26 UTC (rev 21806)
@@ -184,7 +184,6 @@
 	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 {

Modified: branches/mkey_migrate/src/lib/kadm5/srv/server_kdb.c
===================================================================
--- branches/mkey_migrate/src/lib/kadm5/srv/server_kdb.c	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/lib/kadm5/srv/server_kdb.c	2009-01-27 04:16:26 UTC (rev 21806)
@@ -76,8 +76,8 @@
 				 
 #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))) {

Modified: branches/mkey_migrate/src/lib/kdb/kdb5.c
===================================================================
--- branches/mkey_migrate/src/lib/kdb/kdb5.c	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/lib/kdb/kdb5.c	2009-01-27 04:16:26 UTC (rev 21806)
@@ -111,8 +111,7 @@
  * 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,9 +125,22 @@
     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;
 
     for (temp = val; temp != NULL;) {
@@ -138,8 +150,8 @@
     }
 }
 
-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 @@
     } 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 @@
 
                 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 @@
                     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 @@
     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 @@
     }
 
     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 @@
 
     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 @@
     } 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 @@
             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 @@
 /*
  * 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 @@
         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 @@
 
     return (retval);
 }
+#endif /* KRB5_TL_ACTKVNO_VER == 1 */
 
 krb5_error_code
 krb5_dbe_update_last_pwd_change(context, entry, stamp)

Modified: branches/mkey_migrate/src/lib/kdb/kdb_default.c
===================================================================
--- branches/mkey_migrate/src/lib/kdb/kdb_default.c	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/lib/kdb/kdb_default.c	2009-01-27 04:16:26 UTC (rev 21806)
@@ -288,7 +288,7 @@
     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 @@
             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_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 @@
     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 @@
     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 @@
 
                 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 @@
 
                 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 @@
                 goto clean_n_exit;
             }
         }
-        current_mkey = &tmp_clearkey;
     }
 
     /*
@@ -587,12 +583,16 @@
     }
 
     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 @@
             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 @@
 
 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;
 }

Modified: branches/mkey_migrate/src/lib/kdb/libkdb5.exports
===================================================================
--- branches/mkey_migrate/src/lib/kdb/libkdb5.exports	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/lib/kdb/libkdb5.exports	2009-01-27 04:16:26 UTC (rev 21806)
@@ -37,7 +37,10 @@
 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

Modified: branches/mkey_migrate/src/plugins/kdb/ldap/ldap_exp.c
===================================================================
--- branches/mkey_migrate/src/plugins/kdb/ldap/ldap_exp.c	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/plugins/kdb/ldap/ldap_exp.c	2009-01-27 04:16:26 UTC (rev 21806)
@@ -78,8 +78,8 @@
             /* 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 */,

Modified: branches/mkey_migrate/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c
===================================================================
--- branches/mkey_migrate/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c	2009-01-27 04:16:26 UTC (rev 21806)
@@ -2379,6 +2379,8 @@
     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 @@
     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 @@
 	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:

Modified: branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
===================================================================
--- branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h	2009-01-27 04:16:26 UTC (rev 21806)
@@ -267,6 +267,12 @@
 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 

Modified: branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c
===================================================================
--- branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c	2009-01-27 04:16:26 UTC (rev 21806)
@@ -98,3 +98,45 @@
     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;
+}
+

Modified: branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h
===================================================================
--- branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h	2009-01-26 22:50:02 UTC (rev 21805)
+++ branches/mkey_migrate/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h	2009-01-27 04:16:26 UTC (rev 21806)
@@ -68,6 +68,7 @@
   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;
 




More information about the cvs-krb5 mailing list