diff options
author | Will Fiveash <will.fiveash@oracle.com> | 2008-06-06 23:15:02 +0000 |
---|---|---|
committer | Will Fiveash <will.fiveash@oracle.com> | 2008-06-06 23:15:02 +0000 |
commit | 933b0cfc7a09b177df883f259ad2733ae1680085 (patch) | |
tree | 4094a092c9034f67ba05ab65a98ae95776cbc34e | |
parent | 0d828c454a65a690009eb2c0f93d918edb9d175f (diff) | |
download | krb5-933b0cfc7a09b177df883f259ad2733ae1680085.zip krb5-933b0cfc7a09b177df883f259ad2733ae1680085.tar.gz krb5-933b0cfc7a09b177df883f259ad2733ae1680085.tar.bz2 |
first commit to backup my changes
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/mkey_keytab@20369 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r-- | src/include/k5-int.h | 5 | ||||
-rw-r--r-- | src/include/kdb.h | 12 | ||||
-rw-r--r-- | src/kadmin/dbutil/dump.c | 1 | ||||
-rw-r--r-- | src/kadmin/dbutil/kdb5_create.c | 19 | ||||
-rw-r--r-- | src/kadmin/dbutil/kdb5_stash.c | 11 | ||||
-rw-r--r-- | src/kadmin/dbutil/kdb5_util.M | 5 | ||||
-rw-r--r-- | src/kadmin/dbutil/kdb5_util.c | 20 | ||||
-rw-r--r-- | src/kdc/main.c | 1 | ||||
-rw-r--r-- | src/lib/kadm5/admin.h | 2 | ||||
-rw-r--r-- | src/lib/kadm5/alt_prof.c | 5 | ||||
-rw-r--r-- | src/lib/kadm5/srv/server_kdb.c | 2 | ||||
-rw-r--r-- | src/lib/kdb/kdb5.c | 18 | ||||
-rw-r--r-- | src/lib/kdb/kdb5.h | 2 | ||||
-rw-r--r-- | src/lib/kdb/kdb_default.c | 309 | ||||
-rw-r--r-- | src/lib/krb5/keytab/kt_file.c | 2 | ||||
-rw-r--r-- | src/lib/krb5/keytab/kt_memory.c | 2 | ||||
-rw-r--r-- | src/lib/krb5/keytab/kt_srvtab.c | 2 | ||||
-rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c | 11 | ||||
-rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M | 6 | ||||
-rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c | 18 | ||||
-rw-r--r-- | src/tests/create/kdb5_mkdums.c | 2 | ||||
-rw-r--r-- | src/tests/verify/kdb5_verify.c | 2 |
22 files changed, 349 insertions, 108 deletions
diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 5e1fd11..8341af3 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -1778,6 +1778,11 @@ krb5int_make_srv_query_realm(const krb5_data *realm, void krb5int_free_srv_dns_data(struct srv_dns_entry *); #endif +/* value to use when requesting a keytab entry and KVNO doesn't matter */ +#define IGNORE_VNO 0 +/* value to use when requesting a keytab entry and enctype doesn't matter */ +#define IGNORE_ENCTYPE 0 + /* * Convenience function for structure magic number */ diff --git a/src/include/kdb.h b/src/include/kdb.h index 66e8d06..b510404 100644 --- a/src/include/kdb.h +++ b/src/include/kdb.h @@ -275,8 +275,9 @@ krb5_error_code krb5_db_get_mkey ( krb5_context kcontext, krb5_error_code krb5_db_free_master_key ( krb5_context kcontext, krb5_keyblock *key ); krb5_error_code krb5_db_store_master_key ( krb5_context kcontext, - char *db_arg, + char *keyfile, krb5_principal mname, + krb5_kvno kvno, krb5_keyblock *key, char *master_pwd); krb5_error_code krb5_db_fetch_mkey ( krb5_context context, @@ -287,9 +288,10 @@ krb5_error_code krb5_db_fetch_mkey ( krb5_context context, char *db_args, krb5_data *salt, krb5_keyblock *key); -krb5_error_code krb5_db_verify_master_key ( krb5_context kcontext, +krb5_error_code krb5_db_verify_master_key ( krb5_context kcontext, krb5_principal mprinc, - krb5_keyblock *mkey ); + krb5_kvno *kvno, + krb5_keyblock *mkey ); krb5_error_code krb5_dbe_find_enctype( krb5_context kcontext, krb5_db_entry *dbentp, @@ -432,6 +434,7 @@ krb5_error_code krb5_def_store_mkey( krb5_context context, char *keyfile, krb5_principal mname, + krb5_kvno kvno, krb5_keyblock *key, char *master_pwd); @@ -440,12 +443,13 @@ krb5_error_code krb5_db_def_fetch_mkey( krb5_context context, krb5_principal mname, krb5_keyblock *key, - int *kvno, + krb5_kvno *kvno, char *db_args); krb5_error_code krb5_def_verify_master_key( krb5_context context, krb5_principal mprinc, + krb5_kvno *kvno, krb5_keyblock *mkey); krb5_error_code kdb_def_set_mkey ( krb5_context kcontext, diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c index 44675a6..66fedf0 100644 --- a/src/kadmin/dbutil/dump.c +++ b/src/kadmin/dbutil/dump.c @@ -1106,6 +1106,7 @@ dump_db(argc, argv) } retval = krb5_db_verify_master_key(util_context, master_princ, + NULL, &master_keyblock); if (retval) { com_err(argv[0], retval, diff --git a/src/kadmin/dbutil/kdb5_create.c b/src/kadmin/dbutil/kdb5_create.c index da19225..f8c59c8 100644 --- a/src/kadmin/dbutil/kdb5_create.c +++ b/src/kadmin/dbutil/kdb5_create.c @@ -161,6 +161,7 @@ void kdb5_create(argc, argv) unsigned int pw_size = 0; int do_stash = 0; krb5_data pwd, seed; + krb5_kvno mkey_kvno; if (strrchr(argv[0], '/')) argv[0] = strrchr(argv[0], '/')+1; @@ -285,9 +286,20 @@ master key name '%s'\n", * it; delete the file below if it was not requested. DO NOT EXIT * BEFORE DELETING THE KEYFILE if do_stash is not set. */ + + /* + * Determine the kvno to use, it must be that used to create the master key + * princ. + */ + if (global_params.mask & KADM5_CONFIG_KVNO) + mkey_kvno = global_params.kvno; /* user specified */ + else + mkey_kvno = 1; /* Default */ + retval = krb5_db_store_master_key(util_context, global_params.stash_file, master_princ, + mkey_kvno, &master_keyblock, mkey_password); if (retval) { @@ -367,6 +379,7 @@ add_principal(context, princ, op, pblock) { krb5_error_code retval; krb5_db_entry entry; + krb5_kvno mkey_kvno; krb5_timestamp now; struct iterate_args iargs; @@ -399,10 +412,14 @@ add_principal(context, princ, op, pblock) memset((char *) entry.key_data, 0, sizeof(krb5_key_data)); entry.n_key_data = 1; + if (global_params.mask & KADM5_CONFIG_KVNO) + mkey_kvno = global_params.kvno; /* user specified */ + else + mkey_kvno = 1; /* Default */ entry.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; if ((retval = krb5_dbekd_encrypt_key_data(context, pblock->key, &master_keyblock, NULL, - 1, entry.key_data))) + mkey_kvno, entry.key_data))) return retval; break; case TGT_KEY: diff --git a/src/kadmin/dbutil/kdb5_stash.c b/src/kadmin/dbutil/kdb5_stash.c index 7e8fd3e..5ae482a 100644 --- a/src/kadmin/dbutil/kdb5_stash.c +++ b/src/kadmin/dbutil/kdb5_stash.c @@ -81,6 +81,7 @@ kdb5_stash(argc, argv) char *mkey_fullname; char *keyfile = 0; krb5_context context; + krb5_kvno mkey_kvno; if (strrchr(argv[0], '/')) argv[0] = strrchr(argv[0], '/')+1; @@ -153,7 +154,14 @@ kdb5_stash(argc, argv) exit_status++; return; } + if (global_params.mask & KADM5_CONFIG_KVNO) + mkey_kvno = global_params.kvno; /* user specified */ + else + mkey_kvno = IGNORE_VNO; /* use whatever krb5_db_verify_master_key finds */ + + /* verify will set mkey_kvno to mkey princ's kvno mkey_kvno if it's IGNORE_VNO */ retval = krb5_db_verify_master_key(context, master_princ, + &mkey_kvno, &master_keyblock); if (retval) { com_err(argv[0], retval, "while verifying master key"); @@ -162,7 +170,8 @@ kdb5_stash(argc, argv) } retval = krb5_db_store_master_key(context, keyfile, master_princ, - &master_keyblock, NULL); + mkey_kvno, &master_keyblock, + NULL); if (retval) { com_err(argv[0], errno, "while storing key"); memset((char *)master_keyblock.contents, 0, master_keyblock.length); diff --git a/src/kadmin/dbutil/kdb5_util.M b/src/kadmin/dbutil/kdb5_util.M index 0c7cac4..6e0fd47 100644 --- a/src/kadmin/dbutil/kdb5_util.M +++ b/src/kadmin/dbutil/kdb5_util.M @@ -5,6 +5,7 @@ kdb5_util \- Kerberos database maintainance utility .B kdb5_util [\fB\-r\fP\ \fIrealm\fP] [\fB\-d\fP\ \fIdbname\fP] [\fB\-k\fP\ \fImkeytype\fP] [\fB\-M\fP\ \fImkeyname\fP] +[\fB\-kv\fP\ \fImkeyVNO\fP] [\fB\-sf\fP\ \fIstashfilename\fP] [\fB\-m\fP] .I command @@ -58,6 +59,10 @@ specifies the key type of the master key in the database; the default is that given in .IR kdc.conf . .TP +\fB\-kv\fP\ \fImkeyVNO\fP +Specifies the version number of the master key in the database; the default is +0. +.TP \fB\-M\fP\ \fImkeyname\fP principal name for the master key in the database; the default is that given in diff --git a/src/kadmin/dbutil/kdb5_util.c b/src/kadmin/dbutil/kdb5_util.c index 1807d1a..c986405 100644 --- a/src/kadmin/dbutil/kdb5_util.c +++ b/src/kadmin/dbutil/kdb5_util.c @@ -81,7 +81,7 @@ void usage() { fprintf(stderr, "Usage: " "kdb5_util [-x db_args]* [-r realm] [-d dbname] [-k mkeytype] [-M mkeyname]\n" - "\t [-sf stashfilename] [-m] cmd [cmd_options]\n" + "\t [-kv mkeyVNO] [-sf stashfilename] [-m] cmd [cmd_options]\n" "\tcreate [-s]\n" "\tdestroy [-f]\n" "\tstash [-f keyfile]\n" @@ -203,7 +203,7 @@ int main(argc, argv) } memset(cmd_argv, 0, sizeof(char *)*argc); cmd_argc = 1; - + argv++; argc--; while (*argv) { if (strcmp(*argv, "-P") == 0 && ARG_VAL) { @@ -244,10 +244,18 @@ int main(argc, argv) exit(1); } } else if (strcmp(*argv, "-k") == 0 && ARG_VAL) { - if (krb5_string_to_enctype(koptarg, &global_params.enctype)) - com_err(argv[0], 0, "%s is an invalid enctype", koptarg); - else + if (krb5_string_to_enctype(koptarg, &global_params.enctype)) { + com_err(progname, EINVAL, ": %s is an invalid enctype", koptarg); + exit(1); + } else global_params.mask |= KADM5_CONFIG_ENCTYPE; + } else if (strcmp(*argv, "-kv") == 0 && ARG_VAL) { + global_params.kvno = (krb5_kvno) atoi(koptarg); + if (global_params.kvno == IGNORE_VNO) { + com_err(progname, EINVAL, ": %s is an invalid mkeyVNO", koptarg); + exit(1); + } else + global_params.mask |= KADM5_CONFIG_KVNO; } else if (strcmp(*argv, "-M") == 0 && ARG_VAL) { global_params.mkey_name = koptarg; global_params.mask |= KADM5_CONFIG_MKEY_NAME; @@ -457,7 +465,7 @@ static int open_db_and_mkey() return(0); } if ((retval = krb5_db_verify_master_key(util_context, master_princ, - &master_keyblock))) { + NULL, &master_keyblock))) { com_err(progname, retval, "while verifying master key"); exit_status++; krb5_free_keyblock_contents(util_context, &master_keyblock); diff --git a/src/kdc/main.c b/src/kdc/main.c index 5540c18..1827649 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -277,6 +277,7 @@ init_realm(char *progname, kdc_realm_t *rdp, char *realm, /* Verify the master key */ if ((kret = krb5_db_verify_master_key(rdp->realm_context, rdp->realm_mprinc, + NULL, &rdp->realm_mkey))) { com_err(progname, kret, "while verifying master key for realm %s", realm); diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h index adbd6c8..e52d995 100644 --- a/src/lib/kadm5/admin.h +++ b/src/lib/kadm5/admin.h @@ -133,6 +133,7 @@ typedef long kadm5_ret_t; #ifdef notyet /* Novell */ #define KADM5_CONFIG_KPASSWD_SERVER 0x800000 #endif +#define KADM5_CONFIG_KVNO 0x1000000 /* * permission bits */ @@ -243,6 +244,7 @@ typedef struct _kadm5_config_params { krb5_flags flags; krb5_key_salt_tuple *keysalts; krb5_int32 num_keysalts; + krb5_kvno kvno; } kadm5_config_params; /*********************************************************************** diff --git a/src/lib/kadm5/alt_prof.c b/src/lib/kadm5/alt_prof.c index 5724c14..5a55e22 100644 --- a/src/lib/kadm5/alt_prof.c +++ b/src/lib/kadm5/alt_prof.c @@ -403,6 +403,11 @@ krb5_error_code kadm5_get_config_params(context, use_kdc_config, params.realm = lrealm; params.mask |= KADM5_CONFIG_REALM; } + + if (params_in->mask & KADM5_CONFIG_KVNO) { + params.kvno = params_in->kvno; + params.mask |= KADM5_CONFIG_KVNO; + } /* * XXX These defaults should to work on both client and * server. kadm5_get_config_params can be implemented as a diff --git a/src/lib/kadm5/srv/server_kdb.c b/src/lib/kadm5/srv/server_kdb.c index 700b53a..a08a2a5 100644 --- a/src/lib/kadm5/srv/server_kdb.c +++ b/src/lib/kadm5/srv/server_kdb.c @@ -61,7 +61,7 @@ krb5_error_code kdb_init_master(kadm5_server_handle_t handle, goto done; if ((ret = krb5_db_verify_master_key(handle->context, master_princ, - &master_keyblock))) { + NULL, &master_keyblock))) { krb5_db_fini(handle->context); return ret; } diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c index bdade99..37f1cdb 100644 --- a/src/lib/kdb/kdb5.c +++ b/src/lib/kdb/kdb5.c @@ -1212,8 +1212,9 @@ krb5_db_get_mkey(krb5_context kcontext, krb5_keyblock ** key) krb5_error_code krb5_db_store_master_key(krb5_context kcontext, - char *db_arg, + char *keyfile, krb5_principal mname, + krb5_kvno kvno, krb5_keyblock * key, char *master_pwd) { krb5_error_code status = 0; @@ -1233,8 +1234,9 @@ krb5_db_store_master_key(krb5_context kcontext, } status = dal_handle->lib_handle->vftabl.store_master_key(kcontext, - db_arg, + keyfile, mname, + kvno, key, master_pwd); get_errmsg(kcontext, status); kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); @@ -1258,7 +1260,7 @@ krb5_db_fetch_mkey(krb5_context context, char password[BUFSIZ]; krb5_data pwd; unsigned int size = sizeof(password); - int kvno; + int kvno = IGNORE_VNO; krb5_keyblock tmp_key; memset(&tmp_key, 0, sizeof(tmp_key)); @@ -1337,8 +1339,10 @@ krb5_db_fetch_mkey(krb5_context context, } krb5_error_code -krb5_db_verify_master_key(krb5_context kcontext, - krb5_principal mprinc, krb5_keyblock * mkey) +krb5_db_verify_master_key(krb5_context kcontext, + krb5_principal mprinc, + krb5_kvno *kvno, + krb5_keyblock *mkey) { krb5_error_code status = 0; kdb5_dal_handle *dal_handle; @@ -1357,7 +1361,9 @@ krb5_db_verify_master_key(krb5_context kcontext, } status = dal_handle->lib_handle->vftabl.verify_master_key(kcontext, - mprinc, mkey); + mprinc, + kvno, + mkey); get_errmsg(kcontext, status); kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); diff --git a/src/lib/kdb/kdb5.h b/src/lib/kdb/kdb5.h index 328ce25..3893ba6 100644 --- a/src/lib/kdb/kdb5.h +++ b/src/lib/kdb/kdb5.h @@ -139,6 +139,7 @@ typedef struct _kdb_vftabl{ krb5_error_code (*store_master_key) (krb5_context kcontext, char *db_arg, krb5_principal mname, + krb5_kvno kvno, krb5_keyblock *key, char *master_pwd); @@ -150,6 +151,7 @@ typedef struct _kdb_vftabl{ krb5_error_code (*verify_master_key) (krb5_context kcontext, krb5_principal mprinc, + krb5_kvno *kvno, krb5_keyblock *mkey); krb5_error_code (*dbe_search_enctype) (krb5_context kcontext, diff --git a/src/lib/kdb/kdb_default.c b/src/lib/kdb/kdb_default.c index fd95c83..5b34632 100644 --- a/src/lib/kdb/kdb_default.c +++ b/src/lib/kdb/kdb_default.c @@ -132,94 +132,116 @@ krb5_dbe_def_search_enctype(kcontext, dbentp, start, ktype, stype, kvno, kdatap) #endif krb5_error_code -krb5_def_store_mkey(context, keyfile, mname, key, master_pwd) - krb5_context context; - char *keyfile; - krb5_principal mname; - krb5_keyblock *key; - char *master_pwd; +krb5_def_store_mkey(krb5_context context, + char *keyfile, + krb5_principal mname, + krb5_kvno kvno, + krb5_keyblock *key, + char *master_pwd) { - FILE *kf; krb5_error_code retval = 0; - krb5_ui_2 enctype; char defkeyfile[MAXPATHLEN+1]; + char *tmp_ktname = NULL, *tmp_ktpath; krb5_data *realm = krb5_princ_realm(context, mname); -#if HAVE_UMASK - mode_t oumask; -#endif + krb5_keytab kt; + krb5_keytab_entry new_entry; + struct stat stb; + int statrc; if (!keyfile) { - (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB); - (void) strncat(defkeyfile, realm->data, - min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1, - realm->length)); - defkeyfile[sizeof(defkeyfile) - 1] = '\0'; - keyfile = defkeyfile; + (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB); + (void) strncat(defkeyfile, realm->data, + min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1, + realm->length)); + defkeyfile[sizeof(defkeyfile) - 1] = '\0'; + keyfile = defkeyfile; } -#if HAVE_UMASK - oumask = umask(077); -#endif -#ifdef ANSI_STDIO - if (!(kf = fopen(keyfile, "wb"))) -#else - if (!(kf = fopen(keyfile, "w"))) -#endif - { - int e = errno; -#if HAVE_UMASK - (void) umask(oumask); -#endif - krb5_set_error_message (context, e, - "%s accessing file '%s'", - error_message (e), keyfile); - return e; + /* + * XXX making the assumption that the keyfile is in a dir that requires root + * privilege to write to thus making timing attacks unlikely. + */ + if ((statrc = stat(keyfile, &stb)) >= 0) { + /* if keyfile exists it better be a regular file */ + if (!S_ISREG(stb.st_mode)) { + retval = EINVAL; + krb5_set_error_message (context, retval, + "keyfile (%s) is not a regular file: %s", + keyfile, error_message(retval)); + goto out; + } } - set_cloexec_file(kf); - enctype = key->enctype; - if ((fwrite((krb5_pointer) &enctype, - 2, 1, kf) != 1) || - (fwrite((krb5_pointer) &key->length, - sizeof(key->length), 1, kf) != 1) || - (fwrite((krb5_pointer) key->contents, - sizeof(key->contents[0]), (unsigned) key->length, - kf) != key->length)) { - retval = errno; - (void) fclose(kf); - } else if (fclose(kf) == EOF) - retval = errno; -#if HAVE_UMASK - (void) umask(oumask); -#endif + + /* Use temp keytab file name in case creation of keytab fails */ + + /* create temp file template for use by mktemp() */ + if ((retval = asprintf(&tmp_ktname, "WRFILE:%s_XXXXX", keyfile)) < 0) { + krb5_set_error_message (context, retval, + "Could not create temp keytab file name."); + goto out; + } + if (mktemp(tmp_ktname) == NULL) { + retval = errno; + krb5_set_error_message (context, retval, + "Could not create temp stash file: %s", + error_message(errno)); + goto out; + } + + /* create new stash keytab using temp file name */ + retval = krb5_kt_resolve(context, tmp_ktname, &kt); + 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; + + /* + * Set tmp_ktpath to point to the keyfile path (skip WRFILE:). Subtracting + * 1 to account for NULL terminator in sizeof calculation of a string + * constant. Used further down. + */ + tmp_ktpath = tmp_ktname + (sizeof("WRFILE:") - 1); + + 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) + (void) unlink(tmp_ktpath); + } else { + /* rename original keyfile to original filename */ + if (rename(tmp_ktpath, keyfile) < 0) { + retval = errno; + krb5_set_error_message (context, retval, + "rename of temporary keyfile (%s) to (%s) failed: %s", + tmp_ktpath, keyfile, error_message(errno)); + } + } + +out: + if (tmp_ktname != NULL) + free(tmp_ktname); + return retval; } - -krb5_error_code -krb5_db_def_fetch_mkey( krb5_context context, +static krb5_error_code +krb5_db_def_fetch_mkey_stash( krb5_context context, + const char *keyfile, krb5_principal mname, krb5_keyblock *key, - int *kvno, - char *db_args) + krb5_kvno *kvno) { - krb5_error_code retval; + krb5_error_code retval = 0; krb5_ui_2 enctype; - char defkeyfile[MAXPATHLEN+1]; - krb5_data *realm = krb5_princ_realm(context, mname); FILE *kf = NULL; - retval = 0; - key->magic = KV5M_KEYBLOCK; - (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB); - (void) strncat(defkeyfile, realm->data, - min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1, - realm->length)); - defkeyfile[sizeof(defkeyfile) - 1] = '\0'; - #ifdef ANSI_STDIO - if (!(kf = fopen((db_args) ? db_args : defkeyfile, "rb"))) + if (!(kf = fopen(keyfile, "rb"))) #else - if (!(kf = fopen((db_args) ? db_args : defkeyfile, "r"))) + if (!(kf = fopen(keyfile, "r"))) #endif return KRB5_KDB_CANTREAD_STORED; set_cloexec_file(kf); @@ -252,9 +274,8 @@ krb5_db_def_fetch_mkey( krb5_context context, goto errout; } - if (fread((krb5_pointer) key->contents, - sizeof(key->contents[0]), key->length, kf) - != key->length) { + 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); free(key->contents); @@ -262,20 +283,144 @@ krb5_db_def_fetch_mkey( krb5_context context, } else retval = 0; - *kvno = 0; + /* + * Note, the old stash format did not store the kvno so it was always hard + * coded to be 0. + */ + if (kvno) + *kvno = 0; errout: (void) fclose(kf); return retval; +} + +static krb5_error_code +krb5_db_def_fetch_mkey_keytab( krb5_context context, + const char *keyfile, + krb5_principal mname, + krb5_keyblock *key, + krb5_kvno *kvno) +{ + krb5_error_code retval = 0; + char *ktname = NULL; + krb5_keytab kt; + krb5_keytab_entry kt_ent; + + /* memset krb5_kt_free_entry so can be called safely later */ + memset(&kt_ent, 0, sizeof(kt_ent)); + + /* create keytab name string to feed to krb5_kt_resolve */ + if ((retval = asprintf(&ktname, "FILE:%s", keyfile)) < 0) { + krb5_set_error_message (context, retval, + "Could not create keytab name string."); + goto errout; + } + if ((retval = krb5_kt_resolve(context, ktname, &kt)) != 0) + goto errout; + + if ((retval = krb5_kt_get_entry(context, kt, mname, + kvno ? *kvno : IGNORE_VNO, + IGNORE_ENCTYPE, + &kt_ent)) == 0) { + + if (key->enctype == ENCTYPE_UNKNOWN) + key->enctype = kt_ent.key.enctype; + else if (kt_ent.key.enctype != key->enctype) { + retval = KRB5_KDB_BADSTORED_MKEY; + goto errout; + } + + if (((int) kt_ent.key.length) < 0) { + retval = KRB5_KDB_BADSTORED_MKEY; + goto errout; + } + + key->length = kt_ent.key.length; + + if (kvno != NULL) { + /* + * if a kvno pointer was passed in and it dereferences to + * IGNORE_VNO then it should be assigned the value of the + * kvno found in the keytab otherwise the KNVO specified + * should be the same as the one returned from the keytab. + */ + if (*kvno == IGNORE_VNO) { + *kvno = kt_ent.vno; + } else if (*kvno != kt_ent.vno) { + retval = KRB5_KDB_BADSTORED_MKEY; + goto errout; + } + } + + /* + * kt_ent will be free'd later so need to allocate and copy key + * contents for output to caller. + */ + if (!(key->contents = (krb5_octet *)malloc(key->length))) { + retval = ENOMEM; + goto errout; + } + memcpy(key->contents, kt_ent.key.contents, kt_ent.key.length); + } + +errout: + krb5_kt_free_entry(context, &kt_ent); + return retval; } +krb5_error_code +krb5_db_def_fetch_mkey( krb5_context context, + krb5_principal mname, + krb5_keyblock *key, + krb5_kvno *kvno, + char *db_args) +{ + krb5_error_code retval_ofs = 0, retval_kt = 0; + char defkeyfile[MAXPATHLEN+1]; + krb5_data *realm = krb5_princ_realm(context, mname); + + key->magic = KV5M_KEYBLOCK; + (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB); + (void) strncat(defkeyfile, realm->data, + min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1, + realm->length)); + defkeyfile[sizeof(defkeyfile) - 1] = '\0'; + + /* assume the master key is in a keytab */ + retval_kt = krb5_db_def_fetch_mkey_keytab(context, defkeyfile, mname, key, + kvno); + if (retval_kt != 0) { + /* + * If it's not in a keytab, fall back and try getting the mkey from the + * older stash file format. + */ + retval_ofs = krb5_db_def_fetch_mkey_stash(context, defkeyfile, mname, + key, kvno); + } + + if (retval_kt != 0 && retval_ofs != 0) { + /* + * Error, not able to get mkey from either file format. + * + * XXX note this masks the underlying error, wonder if there is a better + * way to deal with this. + */ + krb5_set_error_message (context, KRB5_KDB_CANTREAD_STORED, + "Can not get master key either from keytab (error: %d) or old " + "format (error %d).", retval_kt, retval_ofs); + return KRB5_KDB_CANTREAD_STORED; + } else { + return 0; + } +} krb5_error_code -krb5_def_verify_master_key(context, mprinc, mkey) - krb5_context context; - krb5_principal mprinc; - krb5_keyblock *mkey; +krb5_def_verify_master_key( krb5_context context, + krb5_principal mprinc, + krb5_kvno *kvno, + krb5_keyblock *mkey) { krb5_error_code retval; krb5_db_entry master_entry; @@ -310,6 +455,18 @@ krb5_def_verify_master_key(context, mprinc, mkey) retval = KRB5_KDB_BADMASTERKEY; } + if (kvno != NULL) { + if (*kvno == IGNORE_VNO) { + /* return value of mkey princs kvno */ + *kvno = master_entry.key_data->key_data_kvno; + } else if (*kvno != (krb5_kvno) master_entry.key_data->key_data_kvno) { + retval = KRB5_KDB_BADMASTERKEY; + krb5_set_error_message (context, retval, + "User specified mkeyVNO (%u) does not match master key princ's KVNO (%u)", + *kvno, master_entry.key_data->key_data_kvno); + } + } + memset((char *)tempkey.contents, 0, tempkey.length); krb5_xfree(tempkey.contents); krb5_db_free_principal(context, &master_entry, nprinc); diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c index 1baa800..81f8a9b 100644 --- a/src/lib/krb5/keytab/kt_file.c +++ b/src/lib/krb5/keytab/kt_file.c @@ -37,8 +37,6 @@ /* * Constants */ -#define IGNORE_VNO 0 -#define IGNORE_ENCTYPE 0 #define KRB5_KT_VNO_1 0x0501 /* krb v5, keytab version 1 (DCE compat) */ #define KRB5_KT_VNO 0x0502 /* krb v5, keytab version 2 (standard) */ diff --git a/src/lib/krb5/keytab/kt_memory.c b/src/lib/krb5/keytab/kt_memory.c index ae23280..0922121 100644 --- a/src/lib/krb5/keytab/kt_memory.c +++ b/src/lib/krb5/keytab/kt_memory.c @@ -39,8 +39,6 @@ /* * Constants */ -#define IGNORE_VNO 0 -#define IGNORE_ENCTYPE 0 /* * Types diff --git a/src/lib/krb5/keytab/kt_srvtab.c b/src/lib/krb5/keytab/kt_srvtab.c index e3dd009..7754644 100644 --- a/src/lib/krb5/keytab/kt_srvtab.c +++ b/src/lib/krb5/keytab/kt_srvtab.c @@ -30,8 +30,6 @@ /* * Constants */ -#define IGNORE_VNO 0 -#define IGNORE_ENCTYPE 0 #define KRB5_KT_VNO_1 0x0501 /* krb v5, keytab version 1 (DCE compat) */ #define KRB5_KT_VNO 0x0502 /* krb v5, keytab version 2 (standard) */ diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c index 4a64143..dcc702a 100644 --- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c +++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c @@ -845,9 +845,20 @@ void kdb5_ldap_create(argc, argv) /* Stash the master key only if '-s' option is specified */ if (do_stash || global_params.mask & KADM5_CONFIG_STASH_FILE) { + krb5_kvno mkey_kvno; + /* + * Determine the kvno to use, it must be that used to create the master + * key princ. + */ + if (global_params.mask & KADM5_CONFIG_KVNO) + mkey_kvno = global_params.kvno; /* user specified */ + else + mkey_kvno = 1; /* Default */ + retval = krb5_def_store_mkey(util_context, global_params.stash_file, master_princ, + mkey_kvno, &master_keyblock, NULL); if (retval) { com_err(argv[0], errno, "while storing key"); diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M index 08463b7..75afded 100644 --- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M +++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M @@ -25,7 +25,7 @@ This option is not recommended. Specifies the URI of the LDAP server. .SH COMMANDS .TP -\fBcreate\fP [\fB\-subtrees\fP\ \fIsubtree_dn_list\fP] [\fB\-sscope\fP\ \fIsearch_scope\fP] [\fB\-containerref\fP\ \fIcontainer_reference_dn\fP] [\fB\-k\fP\ \fImkeytype\fP] [\fB\-m\fP|\fB\-P\fP\ \fIpassword\fP|\fB\-sf\fP\ \fIstashfilename\fP] [\fB\-s\fP] [\fB\-r\fP\ \fIrealm\fP] [\fB\-kdcdn\fP\ \fIkdc_service_list\fP] [\fB\-admindn\fP\ \fIadmin_service_list\fP] [\fB\-maxtktlife\fP\ \fImax_ticket_life\fP] [\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP] [\fIticket_flags\fP] +\fBcreate\fP [\fB\-subtrees\fP\ \fIsubtree_dn_list\fP] [\fB\-sscope\fP\ \fIsearch_scope\fP] [\fB\-containerref\fP\ \fIcontainer_reference_dn\fP] [\fB\-k\fP\ \fImkeytype\fP] [\fB\-kv\fP\ \fImkeyVNO\fP] [\fB\-m\fP|\fB\-P\fP\ \fIpassword\fP|\fB\-sf\fP\ \fIstashfilename\fP] [\fB\-s\fP] [\fB\-r\fP\ \fIrealm\fP] [\fB\-kdcdn\fP\ \fIkdc_service_list\fP] [\fB\-admindn\fP\ \fIadmin_service_list\fP] [\fB\-maxtktlife\fP\ \fImax_ticket_life\fP] [\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP] [\fIticket_flags\fP] Creates realm in directory. Options: .RS .TP @@ -47,6 +47,10 @@ Specifies the key type of the master key in the database; the default is that given in .IR kdc.conf . .TP +\fB\-kv\fP\ \fImkeyVNO\fP +Specifies the version number of the master key in the database; the default is +0. +.TP \fB\-m\fP Specifies that the master database password should be read from the TTY rather than fetched from a file on the disk. diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c index 34a2fc8..54272b4 100644 --- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c +++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c @@ -116,7 +116,7 @@ void usage() "\t\t[-kdcdn kdc_service_list] [-admindn admin_service_list]\n" "\t\t[-pwddn passwd_service_list]\n" #endif -"\t\t[-m|-P password|-sf stashfilename] [-k mkeytype] [-s]\n" +"\t\t[-m|-P password|-sf stashfilename] [-k mkeytype] [-kv mkeyVNO] [-s]\n" "\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n" "\t\t[ticket_flags] [-r realm]\n" @@ -343,10 +343,20 @@ int main(argc, argv) goto cleanup; } } else if (strcmp(*argv, "-k") == 0 && ARG_VAL) { - if (krb5_string_to_enctype(koptarg, &global_params.enctype)) - com_err(argv[0], 0, "%s is an invalid enctype", koptarg); - else + if (krb5_string_to_enctype(koptarg, &global_params.enctype)) { + com_err(progname, EINVAL, ": %s is an invalid enctype", koptarg); + exit_status++; + goto cleanup; + } else global_params.mask |= KADM5_CONFIG_ENCTYPE; + } else if (strcmp(*argv, "-kv") == 0 && ARG_VAL) { + global_params.kvno = (krb5_kvno) atoi(koptarg); + if (global_params.kvno == IGNORE_VNO) { + com_err(progname, EINVAL, ": %s is an invalid mkeyVNO", koptarg); + exit_status++; + goto cleanup; + } else + global_params.mask |= KADM5_CONFIG_KVNO; } else if (strcmp(*argv, "-M") == 0 && ARG_VAL) { global_params.mkey_name = koptarg; global_params.mask |= KADM5_CONFIG_MKEY_NAME; diff --git a/src/tests/create/kdb5_mkdums.c b/src/tests/create/kdb5_mkdums.c index 79112e7..2af219b 100644 --- a/src/tests/create/kdb5_mkdums.c +++ b/src/tests/create/kdb5_mkdums.c @@ -389,7 +389,7 @@ char *dbname; free(args[0]); if ((retval = krb5_db_verify_master_key(test_context, master_princ, - &master_keyblock))){ + NULL, &master_keyblock))){ com_err(pname, retval, "while verifying master key"); (void) krb5_db_fini(test_context); return(1); diff --git a/src/tests/verify/kdb5_verify.c b/src/tests/verify/kdb5_verify.c index 2dd19ba..2fb0ac2 100644 --- a/src/tests/verify/kdb5_verify.c +++ b/src/tests/verify/kdb5_verify.c @@ -416,7 +416,7 @@ set_dbname_help(context, pname, dbname) return(1); } if ((retval = krb5_db_verify_master_key(context, master_princ, - &master_keyblock))) { + NULL, &master_keyblock))) { com_err(pname, retval, "while verifying master key"); (void) krb5_db_fini(context); return(1); |