From f07bca9fc94a5cf2e3c0f58226c7973a4b86b7a9 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Mon, 21 Sep 2009 18:40:02 +0000 Subject: [PATCH] Improve the mechanism used for addprinc -randkey. In the kadmin 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 | 104 ++++++++++-------- src/lib/kadm5/srv/svr_principal.c | 35 ++++-- .../kadm5/unit-test/api.2/crte-principal.exp | 2 +- 3 files changed, 85 insertions(+), 56 deletions(-) diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c index e57d497c8..d4bb2bfde 100644 --- a/src/kadmin/cli/kadmin.c +++ b/src/kadmin/cli/kadmin.c @@ -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 diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c index 5c5cdc8cc..1a60f52f4 100644 --- a/src/lib/kadm5/srv/svr_principal.c +++ b/src/lib/kadm5/srv/svr_principal.c @@ -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); diff --git a/src/lib/kadm5/unit-test/api.2/crte-principal.exp b/src/lib/kadm5/unit-test/api.2/crte-principal.exp index 8a84af271..bb7917b90 100644 --- a/src/lib/kadm5/unit-test/api.2/crte-principal.exp +++ b/src/lib/kadm5/unit-test/api.2/crte-principal.exp @@ -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" -- 2.26.2