From: Russ Allbery Date: Mon, 16 Apr 2007 21:35:01 +0000 (+0000) Subject: Add support for extracting existing keys from the KDC with kadmin.local. X-Git-Tag: krb5-1.7-alpha1~1138 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=4fc0ae1c5a5abdd76e1e75f96b81b37be5595a5e;p=krb5.git Add support for extracting existing keys from the KDC with kadmin.local. Adds a -norandkey option to the ktadd command only in kadmin.local, and adds a new function to the libkadm5srv library that kadmin.local can call. There is no protocol or network access to this function. Ticket: 914 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19474 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/kadmin/cli/kadmin.M b/src/kadmin/cli/kadmin.M index 20958e88e..7739bbbbe 100644 --- a/src/kadmin/cli/kadmin.M +++ b/src/kadmin/cli/kadmin.M @@ -749,11 +749,29 @@ kadmin: .TP \fBktadd\fP [\fB\-k\fP \fIkeytab\fP] [\fB\-q\fP] [\fB\-e\fP \fIkeysaltlist\fP] .br -[\fIprincipal\fP | \fB\-glob\fP \fIprinc-exp\fP] [\fI...\fP] +[\fB\-norandkey\fP] [[\fIprincipal\fP | \fB\-glob\fP \fIprinc-exp\fP] [\fI...\fP] .br Adds a principal or all principals matching .I princ-exp -to a keytab, randomizing each principal's key in the process. Requires the +to a keytab. +It randomizes each principal's key in the process, to prevent a +compromised admin account from reading out all of the keys from the +database. However, +.B kadmin.local +has the +.B \-norandkey +option, which leaves the keys and their version numbers unchanged, +similar to the Kerberos V4 +.B ext_srvtab +command. +That allows users to continue to use the passwords they know +to login normally, while simultaneously allowing scripts +to login to the same account using a keytab. +There is no significant security risk added since +.B kadmin.local +must be run by root on the KDC anyway. +.sp +Requires the .I inquire and .I changepw diff --git a/src/kadmin/cli/keytab.c b/src/kadmin/cli/keytab.c index d0fca77d5..297b7994e 100644 --- a/src/kadmin/cli/keytab.c +++ b/src/kadmin/cli/keytab.c @@ -55,9 +55,17 @@ static char *etype_string(krb5_enctype enctype); static int quiet; +#ifdef KADMIN_LOCAL +static int norandkey; +#endif + static void add_usage() { +#ifdef KADMIN_LOCAL + fprintf(stderr, "Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [-norandkey] [principal | -glob princ-exp] [...]\n"); +#else fprintf(stderr, "Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [principal | -glob princ-exp] [...]\n"); +#endif } static void rem_usage() @@ -126,6 +134,9 @@ void kadmin_keytab_add(int argc, char **argv) argc--; argv++; quiet = 0; +#ifdef KADMIN_LOCAL + norandkey = 0; +#endif while (argc) { if (strncmp(*argv, "-k", 2) == 0) { argc--; argv++; @@ -136,6 +147,10 @@ void kadmin_keytab_add(int argc, char **argv) keytab_str = *argv; } else if (strcmp(*argv, "-q") == 0) { quiet++; +#ifdef KADMIN_LOCAL + } else if (strcmp(*argv, "-norandkey") == 0) { + norandkey++; +#endif } else if (strcmp(*argv, "-e") == 0) { argc--; if (argc < 1) { @@ -160,6 +175,13 @@ void kadmin_keytab_add(int argc, char **argv) return; } +#ifdef KADMIN_LOCAL + if (norandkey && ks_tuple) { + fprintf(stderr, "cannot specify keysaltlist when not changing key\n"); + return; + } +#endif + if (process_keytab(context, &keytab_str, &keytab)) return; @@ -261,6 +283,11 @@ int add_principal(void *lhandle, char *keytab_str, krb5_keytab keytab, goto cleanup; } +#ifdef KADMIN_LOCAL + if (norandkey) + code = kadm5_get_principal_keys(handle, princ, &keys, &nkeys); + else +#endif if (keepold || ks_tuple != NULL) { code = kadm5_randkey_principal_3(lhandle, princ, keepold, n_ks_tuple, ks_tuple, diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h index 99d18d4e2..adbd6c8cd 100644 --- a/src/lib/kadm5/admin.h +++ b/src/lib/kadm5/admin.h @@ -494,6 +494,16 @@ kadm5_ret_t kadm5_free_name_list(void *server_handle, char **names, krb5_error_code kadm5_init_krb5_context (krb5_context *); +/* + * kadm5_get_principal_keys is used only by kadmin.local to extract existing + * keys from the database without changing them. It should never be exposed + * to the network protocol. + */ +kadm5_ret_t kadm5_get_principal_keys(void *server_handle, + krb5_principal principal, + krb5_keyblock **keyblocks, + int *n_keys); + #if USE_KADM5_API_VERSION == 1 /* * OVSEC_KADM_API_VERSION_1 should be, if possible, compile-time diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c index 0a66a0631..a7636e770 100644 --- a/src/lib/kadm5/srv/svr_principal.c +++ b/src/lib/kadm5/srv/svr_principal.c @@ -1995,6 +1995,61 @@ done: return ret; } +/* + * Return the list of keys like kadm5_randkey_principal, + * but don't modify the principal. + */ +kadm5_ret_t +kadm5_get_principal_keys(void *server_handle /* IN */, + krb5_principal principal /* IN */, + krb5_keyblock **keyblocks /* OUT */, + int *n_keys /* OUT */) +{ + krb5_db_entry kdb; + osa_princ_ent_rec adb; + krb5_key_data *key_data; + kadm5_ret_t ret; + kadm5_server_handle_t handle = server_handle; + + if (keyblocks) + *keyblocks = NULL; + + CHECK_HANDLE(server_handle); + + if (principal == NULL) + return EINVAL; + + if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) + return(ret); + + if (keyblocks) { + if (handle->api_version == KADM5_API_VERSION_1) { + /* Version 1 clients will expect to see a DES_CRC enctype. */ + if ((ret = krb5_dbe_find_enctype(handle->context, &kdb, + ENCTYPE_DES_CBC_CRC, + -1, -1, &key_data))) + goto done; + + if ((ret = decrypt_key_data(handle->context, 1, key_data, + keyblocks, NULL))) + goto done; + } else { + ret = decrypt_key_data(handle->context, + kdb.n_key_data, kdb.key_data, + keyblocks, n_keys); + if (ret) + goto done; + } + } + + ret = KADM5_OK; +done: + kdb_free_entry(handle, &kdb, &adb); + + return ret; +} + + /* * Allocate an array of n_key_data krb5_keyblocks, fill in each * element with the results of decrypting the nth key in key_data with