Improve the mechanism used for addprinc -randkey. In the kadmin
authorGreg Hudson <ghudson@mit.edu>
Mon, 21 Sep 2009 18:40:02 +0000 (18:40 +0000)
committerGreg Hudson <ghudson@mit.edu>
Mon, 21 Sep 2009 18:40:02 +0000 (18:40 +0000)
server, if the password is null when creating a principal, treat that
as a request for a random key.  In the kadmin client, try using the
new method for random key creation and then fall back to the old one.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22782 dc483132-0cff-0310-8789-dd5450dbe970

src/kadmin/cli/kadmin.c
src/lib/kadm5/srv/svr_principal.c
src/lib/kadm5/unit-test/api.2/crte-principal.exp

index e57d497c813842898b4c9ee80e7fa305c2091dff..d4bb2bfdefce59a16f415f8db73dd6f9d1600223 100644 (file)
@@ -207,6 +207,29 @@ static void extended_com_err_fn (const char *myprog, errcode_t code,
     fprintf (stderr, "\n");
 }
 
+/* Create a principal using the oldest appropriate kadm5 API. */
+static krb5_error_code
+create_princ(kadm5_principal_ent_rec *princ, long mask, int n_ks,
+            krb5_key_salt_tuple *ks, char *pass)
+{
+    if (ks)
+       return kadm5_create_principal_3(handle, princ, mask, n_ks, ks, pass);
+    else
+       return kadm5_create_principal(handle, princ, mask, pass);
+}
+
+/* Randomize a principal's password using the oldest appropriate kadm5 API. */
+static krb5_error_code
+randkey_princ(krb5_principal princ, krb5_boolean keepold, int n_ks,
+             krb5_key_salt_tuple *ks)
+{
+    if (keepold || ks) {
+       return kadm5_randkey_principal_3(handle, princ, keepold, n_ks, ks,
+                                        NULL, NULL);
+    } else
+       return kadm5_randkey_principal(handle, princ, NULL, NULL);
+}
+
 char *kadmin_startup(argc, argv)
     int argc;
     char *argv[];
@@ -780,15 +803,9 @@ void kadmin_cpw(argc, argv)
        if (db_args) free(db_args);
        return;
     } else if (randkey) {
-       if (keepold || ks_tuple != NULL) {
-           retval = kadm5_randkey_principal_3(handle, princ, keepold,
-                                              n_ks_tuple, ks_tuple,
-                                              NULL, NULL);
-           if (ks_tuple != NULL)
-               free(ks_tuple);
-       } else {
-           retval = kadm5_randkey_principal(handle, princ, NULL, NULL);
-       }
+       retval = randkey_princ(princ, keepold, n_ks_tuple, ks_tuple);
+       if (ks_tuple != NULL)
+           free(ks_tuple);
        krb5_free_principal(context, princ);
        if (retval) {
            com_err("change_password", retval,
@@ -891,7 +908,7 @@ kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, randkey,
     kadm5_principal_ent_t oprinc;
     long *mask;
     char **pass;
-    int *randkey;
+    krb5_boolean *randkey;
     krb5_key_salt_tuple **ks_tuple;
     int *n_ks_tuple;
 #if APPLE_PKINIT
@@ -913,7 +930,7 @@ kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, randkey,
     *cert_hash = NULL;
 #endif /* APPLE_PKINIT */
     time(&now);
-    *randkey = 0;
+    *randkey = FALSE;
     for (i = 1; i < argc - 1; i++) {
        attrib_set = 0;
        if (strlen(argv[i]) == 2 &&
@@ -1048,7 +1065,7 @@ kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, randkey,
        }
        if (strlen(argv[i]) == 8 &&
            !strcmp("-randkey", argv[i])) {
-           ++*randkey;
+           *randkey = TRUE;
            continue;
        }
 #if APPLE_PKINIT
@@ -1150,6 +1167,19 @@ kadmin_modprinc_usage(func)
        );
 }
 
+/* Create a dummy password for old-style (pre-1.8) randkey creation. */
+static void
+prepare_dummy_password(char *buf, size_t sz)
+{
+    size_t i;
+
+    /* Must try to pass any password policy in place, and be valid UTF-8. */
+    strcpy(buf, "6F a[");
+    for (i = strlen(buf); i < sz - 1; i++)
+       buf[i] = 'a' + (i % 26);
+    buf[sz - 1] = '\0';
+}
+
 void kadmin_addprinc(argc, argv)
     int argc;
     char *argv[];
@@ -1157,7 +1187,7 @@ void kadmin_addprinc(argc, argv)
     kadm5_principal_ent_rec princ;
     kadm5_policy_ent_rec defpol;
     long mask;
-    int randkey = 0, i;
+    krb5_boolean randkey = FALSE, old_style_randkey = FALSE;
     int n_ks_tuple;
     krb5_key_salt_tuple *ks_tuple;
     char *pass, *canon;
@@ -1168,16 +1198,6 @@ void kadmin_addprinc(argc, argv)
     char *cert_hash = NULL;
 #endif /* APPLE_PKINIT */
 
-    /*
-     * We begin with a bad password and DISALLOW_ALL_TIX.  The bad
-     * password must try to pass any password policy in place, and
-     * must be valid UTF-8 for the arcfour string-to-key).
-     */
-    strcpy(dummybuf, "6F a[");
-    for (i = strlen(dummybuf); i < sizeof(dummybuf) - 1; i++)
-       dummybuf[i] = 'a' + (random() % 25);
-    dummybuf[sizeof(dummybuf) - 1] = '\0';
-
     /* Zero all fields in request structure */
     memset(&princ, 0, sizeof(princ));
 
@@ -1235,10 +1255,8 @@ void kadmin_addprinc(argc, argv)
     }
     mask &= ~KADM5_POLICY_CLR;
 
-    if (randkey) {             /* do special stuff if -randkey specified */
-       princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; /* set notix */
-       mask |= KADM5_ATTRIBUTES;
-       pass = dummybuf;
+    if (randkey) {
+       pass = NULL;
     } else if (pass == NULL) {
        unsigned int sz = sizeof (newpw) - 1;
 
@@ -1261,11 +1279,18 @@ void kadmin_addprinc(argc, argv)
        pass = newpw;
     }
     mask |= KADM5_PRINCIPAL;
-    if (ks_tuple != NULL) {
-       retval = kadm5_create_principal_3(handle, &princ, mask,
-                                         n_ks_tuple, ks_tuple, pass);
-    } else {
-       retval = kadm5_create_principal(handle, &princ, mask, pass);
+    retval = create_princ(&princ, mask, n_ks_tuple, ks_tuple, pass);
+    if (retval == EINVAL && randkey) {
+       /*
+        * The server doesn't support randkey creation.  Create the principal
+        * with a dummy password and disallow tickets.
+        */
+       prepare_dummy_password(dummybuf, sizeof(dummybuf));
+       princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+       mask |= KADM5_ATTRIBUTES;
+       pass = dummybuf;
+       retval = create_princ(&princ, mask, n_ks_tuple, ks_tuple, pass);
+       old_style_randkey = 1;
     }
     if (retval) {
        com_err("add_principal", retval, "while creating \"%s\".",
@@ -1277,16 +1302,9 @@ void kadmin_addprinc(argc, argv)
        kadmin_free_tl_data(&princ);
        return;
     }
-    if (randkey) {             /* more special stuff for -randkey */
-       if (ks_tuple != NULL) {
-           retval = kadm5_randkey_principal_3(handle, princ.principal,
-                                              FALSE,
-                                              n_ks_tuple, ks_tuple,
-                                              NULL, NULL);
-       } else {
-           retval = kadm5_randkey_principal(handle, princ.principal,
-                                            NULL, NULL);
-       }
+    if (old_style_randkey) {
+       /* Randomize the password and re-enable tickets. */
+       retval = randkey_princ(princ.principal, FALSE, n_ks_tuple, ks_tuple);
        if (retval) {
            com_err("add_principal", retval,
                    "while randomizing key for \"%s\".", canon);
@@ -1329,7 +1347,7 @@ void kadmin_modprinc(argc, argv)
     long mask;
     krb5_error_code retval;
     char *pass, *canon;
-    int randkey = 0;
+    krb5_boolean randkey = FALSE;
     int n_ks_tuple = 0;
     krb5_key_salt_tuple *ks_tuple;
 #if APPLE_PKINIT
index 5c5cdc8cc96ddc76a02f08bbbee3e3ceddf4d0e4..1a60f52f4a00ef75f8a0965896aa2b99c882b0a1 100644 (file)
@@ -226,7 +226,7 @@ kadm5_create_principal_3(void *server_handle,
        return KADM5_BAD_MASK;
     if((mask & ~ALL_PRINC_MASK))
        return KADM5_BAD_MASK;
-    if (entry == (kadm5_principal_ent_t) NULL || password == NULL)
+    if (entry == NULL)
        return EINVAL;
 
     /*
@@ -260,11 +260,14 @@ kadm5_create_principal_3(void *server_handle,
                return ret;
        }
     }
-    if ((ret = passwd_check(handle, password, (mask & KADM5_POLICY),
-                           &polent, entry->principal))) {
-       if (mask & KADM5_POLICY)
-            (void) kadm5_free_policy_ent(handle->lhandle, &polent);
-       return ret;
+    if (password) {
+       ret = passwd_check(handle, password, (mask & KADM5_POLICY),
+                          &polent, entry->principal);
+       if (ret) {
+           if (mask & KADM5_POLICY)
+               (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+           return ret;
+       }
     }
     /*
      * Start populating the various DB fields, using the
@@ -360,12 +363,20 @@ kadm5_create_principal_3(void *server_handle,
         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,
-                           (mask & KADM5_KVNO)?entry->kvno:1,
-                           FALSE, &kdb))) {
+    if (password) {
+       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, (mask & KADM5_KVNO)?entry->kvno:1,
+                          FALSE, &kdb);
+    } else {
+       /* Null password means create with random key (new in 1.8). */
+       ret = krb5_dbe_crk(handle->context, &master_keyblock,
+                          n_ks_tuple?ks_tuple:handle->params.keysalts,
+                          n_ks_tuple?n_ks_tuple:handle->params.num_keysalts,
+                          FALSE, &kdb);
+    }
+    if (ret) {
        krb5_db_free_principal(handle->context, &kdb, 1);
        if (mask & KADM5_POLICY)
             (void) kadm5_free_policy_ent(handle->lhandle, &polent);
index 8a84af271082af446b8aa930dbc3e74e04cfdf1f..bb7917b90eea6b016bc91570207b9dd32b2d7bbd 100644 (file)
@@ -54,7 +54,7 @@ proc test3 {} {
        perror "$test: unexpected failure in init"
        return
     }
-    one_line_fail_test [format {
+    one_line_succeed_test [format {
        kadm5_create_principal $server_handle [simple_principal "%s/a"] \
                {KADM5_PRINCIPAL} null
     } $test] "EINVAL"