]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
first commit to backup my changes
authorWill Fiveash <will.fiveash@oracle.com>
Fri, 6 Jun 2008 23:15:02 +0000 (23:15 +0000)
committerWill Fiveash <will.fiveash@oracle.com>
Fri, 6 Jun 2008 23:15:02 +0000 (23:15 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/mkey_keytab@20369 dc483132-0cff-0310-8789-dd5450dbe970

22 files changed:
src/include/k5-int.h
src/include/kdb.h
src/kadmin/dbutil/dump.c
src/kadmin/dbutil/kdb5_create.c
src/kadmin/dbutil/kdb5_stash.c
src/kadmin/dbutil/kdb5_util.M
src/kadmin/dbutil/kdb5_util.c
src/kdc/main.c
src/lib/kadm5/admin.h
src/lib/kadm5/alt_prof.c
src/lib/kadm5/srv/server_kdb.c
src/lib/kdb/kdb5.c
src/lib/kdb/kdb5.h
src/lib/kdb/kdb_default.c
src/lib/krb5/keytab/kt_file.c
src/lib/krb5/keytab/kt_memory.c
src/lib/krb5/keytab/kt_srvtab.c
src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c
src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M
src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c
src/tests/create/kdb5_mkdums.c
src/tests/verify/kdb5_verify.c

index 5e1fd113a3f1f13e024a355d43d3d3ca1eb4633c..8341af365ac0bcf447beb1cb96021d8ca21d276e 100644 (file)
@@ -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
  */
index 66e8d0698bf73deb7ad8b32cc1ffa8d57d78856e..b510404d31d8c5b59bd3fe0cce7fa651e664f303 100644 (file)
@@ -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,
index 44675a6b2cac6712ab9a4e83a635df3649c2aa3e..66fedf0aa6c2c3aa8aa8cc41c3a2d3c8339ad554 100644 (file)
@@ -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,
index da192256ea612e5eb62bd2b93ab5787dada6c175..f8c59c880c62d9fa0647f9a31815df752b668ec0 100644 (file)
@@ -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:
index 7e8fd3e8b04285a27fb6d08e023a8f8eb08300ed..5ae482a05037e7d0dd72238acc5490c4dc807077 100644 (file)
@@ -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);
index 0c7cac4004c6f6536ce8d11f616901f8f0b484f4..6e0fd4736939d8b4eca0fcb5fb24f56e1cb268c3 100644 (file)
@@ -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
index 1807d1ad00fcfe164e659b9ad9697f557673b23d..c986405942e3ced3d94ff3b1b453565a348923fc 100644 (file)
@@ -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);
index 5540c18a3bdea14ee1a00ad71e836901d315baa1..1827649e4dddfe4d82745a72e834c99f086bdb01 100644 (file)
@@ -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);
index adbd6c8cd02e445b5dedb704c149f9cd8faad0ca..e52d995e9a49ccdeb2dbaa681376f7970889a4bb 100644 (file)
@@ -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;
 
 /***********************************************************************
index 5724c14031544decf531747caadd72b63c45dbbb..5a55e22b73c26f16d16f3b108e74a23e59658458 100644 (file)
@@ -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
index 700b53a66a04bda2b721055e712218abe70263b3..a08a2a5354fcdb6df8f44086b4f5a616bead8a84 100644 (file)
@@ -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;
     }
index bdade990477141e153b1dbdddb99dfe43d277aa9..37f1cdb2bd02cba2cd73a0d12dc0bf26b858ee53 100644 (file)
@@ -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);
 
index 328ce251998d5cb6b36c4bacf0b2279d6e830e73..3893ba63982fdfa22e7e00f913a2a7dc0e314ccc 100644 (file)
@@ -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,
index fd95c83793d981973a8ab809a2f101d48561d44b..5b34632f790edfd5ba3a789912f5e2214871e748 100644 (file)
@@ -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);
index 1baa80096cc1019e55c38f827f46758627a65e23..81f8a9b0410cadee5d6040ab8bee93ecde94477f 100644 (file)
@@ -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)  */
index ae232801acbaa4a1c99e7f7e594161e0ea210843..092212146f08fa7a9edec94b27d3b4960b312fba 100644 (file)
@@ -39,8 +39,6 @@
 /*
  * Constants
  */
-#define IGNORE_VNO 0
-#define IGNORE_ENCTYPE 0
 
 /* 
  * Types
index e3dd00926bf12ab873e7d2f364248208664db984..77546446e0925fe44e3e1dc55629bde120cd770a 100644 (file)
@@ -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)  */
index 4a64143de240a4b123cdb5fab3fe07e4b3811cf8..dcc702abb5b122e88c672a3841c97bba7fdcf12f 100644 (file)
@@ -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");
index 08463b7f87b0d18c33bfa568b8e83874512d8b81..75afded0f8aea7e580a807f1808482acd30ac705 100644 (file)
@@ -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.
index 34a2fc8087973e909d01d03e5d5772e6556eb18d..54272b4586403ac3bc621de13fdb11d7cc41951b 100644 (file)
@@ -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;
index 79112e7c2f75c6ff001f4122cb74c4b6fd9f7bb5..2af219b999f2bba5a10cf3a7711d5d6227a512f8 100644 (file)
@@ -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);
index 2dd19ba44033149b0ae018f92a885f67999f97e1..2fb0ac2fd6ec733d59d7911313237be63864f6f8 100644 (file)
@@ -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);