a stash file is not a keytab
authorWill Fiveash <will.fiveash@oracle.com>
Fri, 15 Aug 2008 00:38:41 +0000 (00:38 +0000)
committerWill Fiveash <will.fiveash@oracle.com>
Fri, 15 Aug 2008 00:38:41 +0000 (00:38 +0000)
Note, this is the commit for the associated Krb Consortium project:
Projects/Masterkey Keytab Stash

ticket: 194

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

29 files changed:
src/configure.in
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/kadm5/unit-test/api.2/init-v2.exp
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/Makefile.in
src/tests/create/kdb5_mkdums.c
src/tests/mkeystash_compat/Makefile.in [new file with mode: 0644]
src/tests/mkeystash_compat/bigendian.c [new file with mode: 0644]
src/tests/mkeystash_compat/old_stash_bendian [new file with mode: 0644]
src/tests/mkeystash_compat/old_stash_lendian [new file with mode: 0644]
src/tests/verify/kdb5_verify.c

index ffec8b0af6939def44ee4772157e7b19bbadd195..0e9bd3ab5ae5ce8b4f95a401adb650ae82debf96 100644 (file)
@@ -1141,6 +1141,6 @@ V5_AC_OUTPUT_MAKEFILE(.
 
        tests tests/resolve tests/asn.1 tests/create tests/hammer
        tests/verify tests/gssapi tests/dejagnu tests/threads tests/shlib
-       tests/gss-threads tests/misc
+       tests/gss-threads tests/misc tests/mkeystash_compat
        util/collected-client-lib
 )
index 4b0a0937e9590698e57dcb8e30403acaf295557c..b9abd8a34b92e7a3e6e8f8d4ccc8e8ad1143b066 100644 (file)
@@ -1803,6 +1803,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..cc5951d4644af7b4e716581dc941822577358030 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,
@@ -285,11 +286,13 @@ krb5_error_code krb5_db_fetch_mkey  ( krb5_context   context,
                                      krb5_boolean   fromkeyboard,
                                      krb5_boolean   twice,
                                      char          *db_args,
+                                      krb5_kvno     *kvno,
                                      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 +435,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 +444,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_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 0cc227d30b9d1bc4434ee11d2dd9a96277df3979..fbb8fd21e23f92a8be26643bd37162de6ca65c8e 100644 (file)
@@ -270,6 +270,7 @@ static krb5_error_code master_key_convert(context, db_entry)
     int              i, j;
     krb5_key_data      new_key_data, *key_data;
     krb5_boolean       is_mkey;
+    krb5_kvno           kvno;
 
     is_mkey = krb5_principal_compare(context, master_princ, db_entry->princ);
 
@@ -288,10 +289,22 @@ static krb5_error_code master_key_convert(context, db_entry)
                return retval;
 
        memset(&new_key_data, 0, sizeof(new_key_data));
-       key_ptr = is_mkey ? &new_master_keyblock : &v5plainkey;
+
+       if (is_mkey) {
+               key_ptr = &new_master_keyblock;
+               /* override mkey princ's kvno */
+               if (global_params.mask & KADM5_CONFIG_KVNO)
+                       kvno = global_params.kvno;
+               else
+                       kvno = (krb5_kvno) key_data->key_data_kvno;
+       } else {
+               key_ptr = &v5plainkey;
+               kvno = (krb5_kvno) key_data->key_data_kvno;
+       }
+
        retval = krb5_dbekd_encrypt_key_data(context, &new_master_keyblock,
                                             key_ptr, &keysalt,
-                                            key_data->key_data_kvno,
+                                            (int) kvno,
                                             &new_key_data);
        if (retval)
                return retval;
@@ -1126,7 +1139,8 @@ dump_db(argc, argv)
                                                master_princ,
                                                master_keyblock.enctype,
                                                TRUE, FALSE,
-                                               (char *) NULL, 0,
+                                               (char *) NULL,
+                                               NULL, NULL,
                                                &master_keyblock);
                    if (retval) {
                            com_err(progname, retval,
@@ -1135,6 +1149,7 @@ dump_db(argc, argv)
                    }
                    retval = krb5_db_verify_master_key(util_context,
                                                       master_princ,
+                                                      IGNORE_VNO,
                                                       &master_keyblock);
                    if (retval) {
                            com_err(progname, retval,
@@ -1145,17 +1160,37 @@ dump_db(argc, argv)
            new_master_keyblock.enctype = global_params.enctype;
            if (new_master_keyblock.enctype == ENCTYPE_UNKNOWN)
                    new_master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
-           if (!new_mkey_file)
+
+           if (new_mkey_file) {
+                   krb5_kvno kt_kvno;
+
+                   if (global_params.mask & KADM5_CONFIG_KVNO)
+                           kt_kvno = global_params.kvno;
+                   else
+                           kt_kvno = IGNORE_VNO;
+
+                   if ((retval = krb5_db_fetch_mkey(util_context, master_princ, 
+                                                    new_master_keyblock.enctype,
+                                                    FALSE, 
+                                                    FALSE, 
+                                                    new_mkey_file,
+                                                    &kt_kvno,
+                                                    NULL,
+                                                    &new_master_keyblock))) { 
+                           com_err(progname, retval, "while reading new master key");
+                           exit(1);
+                   }
+           } else {
                    printf("Please enter new master key....\n");
-           if ((retval = krb5_db_fetch_mkey(util_context, master_princ, 
-                                            new_master_keyblock.enctype,
-                                            (new_mkey_file == 0) ? 
-                                               (krb5_boolean) 1 : 0
-                                            TRUE, 
-                                            new_mkey_file, 0,
-                                            &new_master_keyblock))) { 
-                   com_err(progname, retval, "while reading new master key");
-                   exit(1);
+                   if ((retval = krb5_db_fetch_mkey(util_context, master_princ, 
+                                                    new_master_keyblock.enctype,
+                                                    TRUE,
+                                                    TRUE
+                                                    NULL, NULL, NULL,
+                                                    &new_master_keyblock))) { 
+                           com_err(progname, retval, "while reading new master key");
+                           exit(1);
+                   }
            }
     }
 
index eaeade1630956878afb3c6e5b75bfbeae0053491..c996dad25fb928759b7a1c5597a168eab4441026 100644 (file)
@@ -166,6 +166,7 @@ void kdb5_create(argc, argv)
     int do_stash = 0;
     krb5_data pwd, seed;
     kdb_log_context *log_ctx;
+    krb5_kvno mkey_kvno;
           
     while ((optchar = getopt(argc, argv, "s")) != -1) {
        switch(optchar) {
@@ -319,9 +320,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) {
@@ -401,6 +413,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;
@@ -433,10 +446,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 a34aa132a21bcce1ccba76958b25187b606534d6..3583a3285f0b1ee4c3abb4671fa9e2aa009159f1 100644 (file)
@@ -81,6 +81,7 @@ kdb5_stash(argc, argv)
     char *mkey_fullname;
     char *keyfile = 0;
     krb5_context context;
+    krb5_kvno mkey_kvno;
 
     retval = kadm5_init_krb5_context(&context);
     if( retval )
@@ -139,11 +140,17 @@ 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_fetch_mkey finds */
+
     /* TRUE here means read the keyboard, but only once */
     retval = krb5_db_fetch_mkey(context, master_princ,
                                master_keyblock.enctype,
                                TRUE, FALSE, (char *) NULL,
-                               0, &master_keyblock);
+                                &mkey_kvno,
+                               NULL, &master_keyblock);
     if (retval) {
        com_err(progname, retval, "while reading master key");
        (void) krb5_db_fini(context);
@@ -151,6 +158,7 @@ kdb5_stash(argc, argv)
     }
 
     retval = krb5_db_verify_master_key(context, master_princ, 
+                                       mkey_kvno,
                                       &master_keyblock);
     if (retval) {
        com_err(progname, retval, "while verifying master key");
@@ -159,7 +167,7 @@ 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(progname, errno, "while storing key");
        memset((char *)master_keyblock.contents, 0, master_keyblock.length);
index 11ef7ca18c03504e55d503819e0569211fd40b21..d58c972aff8f40bd8caa5ac13641872e024b8dcb 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
+1.  Note that 0 is not allowed.
+.TP
 \fB\-M\fP\ \fImkeyname\fP
 principal name for the master key in the database; the default is
 that given in
index cfc3d08218d84855b79a71beea3a5aeacc3b70a1..ff6bcc99573de601048447e1170ed670df4b8ee9 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"
@@ -205,7 +205,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) {
@@ -246,10 +246,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(progname, 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;
@@ -380,6 +388,7 @@ static int open_db_and_mkey()
     int nentries;
     krb5_boolean more;
     krb5_data scratch, pwd, seed;
+    krb5_kvno kvno;
 
     dbactive = FALSE;
     valid_master_key = 0;
@@ -421,6 +430,11 @@ static int open_db_and_mkey()
        return(1);
     }
 
+    if (global_params.mask & KADM5_CONFIG_KVNO)
+        kvno = global_params.kvno; /* user specified */
+    else
+        kvno = (krb5_kvno) master_entry.key_data->key_data_kvno;
+
     krb5_db_free_principal(util_context, &master_entry, nentries);
 
     /* the databases are now open, and the master principal exists */
@@ -437,13 +451,12 @@ static int open_db_and_mkey()
        }
 
        /* If no encryption type is set, use the default */
-       if (master_keyblock.enctype == ENCTYPE_UNKNOWN) {
+       if (master_keyblock.enctype == ENCTYPE_UNKNOWN)
            master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
-           if (!krb5_c_valid_enctype(master_keyblock.enctype))
-               com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
-                       "while setting up enctype %d",
-                       master_keyblock.enctype);
-       }
+        if (!krb5_c_valid_enctype(master_keyblock.enctype))
+            com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
+                    "while setting up enctype %d",
+                    master_keyblock.enctype);
 
        retval = krb5_c_string_to_key(util_context, master_keyblock.enctype, 
                                      &pwd, &scratch, &master_keyblock);
@@ -455,10 +468,12 @@ static int open_db_and_mkey()
        }
        free(scratch.data);
        mkey_password = 0;
+
     } else if ((retval = krb5_db_fetch_mkey(util_context, master_princ, 
                                            master_keyblock.enctype,
                                            manual_mkey, FALSE,
                                            global_params.stash_file,
+                                           &kvno,
                                            0, &master_keyblock))) {
        com_err(progname, retval, "while reading master key");
        com_err(progname, 0, "Warning: proceeding without master key");
@@ -466,7 +481,7 @@ static int open_db_and_mkey()
        return(0);
     }
     if ((retval = krb5_db_verify_master_key(util_context, master_princ, 
-                                           &master_keyblock))) {
+                                           kvno, &master_keyblock))) {
        com_err(progname, retval, "while verifying master key");
        exit_status++;
        krb5_free_keyblock_contents(util_context, &master_keyblock);
index ff675dcae9af32ced70d8166ca3bd4c7ce0bda06..ff47c008802254227b843d8854c152fb836e4d05 100644 (file)
@@ -267,7 +267,7 @@ init_realm(char *progname, kdc_realm_t *rdp, char *realm,
     if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc,
                                   rdp->realm_mkey.enctype, manual,
                                   FALSE, rdp->realm_stash,
-                                  0, &rdp->realm_mkey))) {
+                                  NULL, NULL, &rdp->realm_mkey))) {
        com_err(progname, kret,
                "while fetching master key %s for realm %s",
                rdp->realm_mpname, realm);
@@ -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,
+                                          IGNORE_VNO,
                                          &rdp->realm_mkey))) {
        com_err(progname, kret,
                "while verifying master key for realm %s", realm);
index 9013305b6934d15c9d32320ce5164a4cf7d500b6..281719561d34da00bb39b8300dad3354abdf7b7c 100644 (file)
@@ -139,6 +139,7 @@ typedef long                kadm5_ret_t;
 #define KADM5_CONFIG_POLL_TIME         0x04000000
 #define KADM5_CONFIG_IPROP_LOGFILE     0x08000000
 #define KADM5_CONFIG_IPROP_PORT                0x10000000
+#define KADM5_CONFIG_KVNO           0x20000000
 /*
  * permission bits
  */
@@ -256,7 +257,7 @@ typedef struct _kadm5_config_params {
      krb5_flags                flags;
      krb5_key_salt_tuple *keysalts;
      krb5_int32                num_keysalts;
-
+     krb5_kvno          kvno;
     bool_t             iprop_enabled;
     uint32_t           iprop_ulogsize;
     krb5_deltat                iprop_poll_time;
index c8bc6b052d565ca7f2d78eccd962741681574b46..cfcbd79aa6bbe8b986618770e7b7b6f874c3a008 100644 (file)
@@ -501,6 +501,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..836cd00b768b942f4bf1a1c3208aefb54a570b73 100644 (file)
@@ -54,6 +54,7 @@ krb5_error_code kdb_init_master(kadm5_server_handle_t handle,
                             master_keyblock.enctype, from_kbd,
                             FALSE /* only prompt once */,
                             handle->params.stash_file,
+                            NULL /* don't care about kvno */,
                             NULL /* I'm not sure about this,
                                     but it's what the kdc does --marc */,
                             &master_keyblock);
@@ -61,7 +62,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))) {
+                                        IGNORE_VNO, &master_keyblock))) {
          krb5_db_fini(handle->context);
          return ret;
     }
index 21f6260a4e1ecd774285ceffe31797f10e8304c6..24bfb09b022e99bd339a6e8d4f5197b4bb1e2e30 100644 (file)
@@ -147,7 +147,7 @@ proc test108 {} {
                [config_params {KADM5_CONFIG_MKEY_NAME} does/not/exist] \
                $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
                server_handle
-    } "KDB_NOMASTERKEY"
+    } "KRB5_KDB_CANTREAD_STORED"
 }
 if {! $RPC} test108
 
index f25864dc71aaf3176cd370d36c5eca1c4ea328ed..67ceacb9944412d7c7ba2cff4679596c8ddd6d24 100644 (file)
@@ -1390,8 +1390,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;
@@ -1411,8 +1412,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);
@@ -1425,18 +1427,20 @@ char   *krb5_mkey_pwd_prompt1 = KRB5_KDC_MKEY_1;
 char   *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2;
 
 krb5_error_code
-krb5_db_fetch_mkey(krb5_context context,
-                  krb5_principal mname,
-                  krb5_enctype etype,
-                  krb5_boolean fromkeyboard,
-                  krb5_boolean twice,
-                  char *db_args, krb5_data * salt, krb5_keyblock * key)
+krb5_db_fetch_mkey(krb5_context    context,
+                   krb5_principal  mname,
+                   krb5_enctype    etype,
+                   krb5_boolean    fromkeyboard,
+                   krb5_boolean    twice,
+                   char          * db_args,
+                   krb5_kvno     * kvno,
+                   krb5_data     * salt,
+                   krb5_keyblock * key)
 {
     krb5_error_code retval;
     char    password[BUFSIZ];
     krb5_data pwd;
     unsigned int size = sizeof(password);
-    int     kvno;
     krb5_keyblock tmp_key;
 
     memset(&tmp_key, 0, sizeof(tmp_key));
@@ -1460,6 +1464,30 @@ krb5_db_fetch_mkey(krb5_context context,
        retval =
            krb5_c_string_to_key(context, etype, &pwd, salt ? salt : &scratch,
                                 key);
+        /*
+         * If a kvno pointer was passed in and it dereferences the IGNORE_VNO
+         * value then it should be assigned the value of the kvno associated
+         * with the current mkey princ key if that princ entry is available
+         * otherwise assign 1 which is the default kvno value for the mkey
+         * princ.
+         */
+        if (kvno != NULL && *kvno == IGNORE_VNO) {
+            int nentries = 1;
+            krb5_boolean more;
+            krb5_error_code rc;
+            krb5_db_entry master_entry;
+
+            rc = krb5_db_get_principal(context, mname,
+                &master_entry, &nentries, &more);
+
+            if (rc == 0 && nentries == 1 && more == FALSE) 
+                *kvno = (krb5_kvno) master_entry.key_data->key_data_kvno;
+            else
+                *kvno = 1;
+
+            if (rc == 0 && nentries)
+                krb5_db_free_principal(context, &master_entry, nentries);
+        }
 
        if (!salt)
            krb5_xfree(scratch.data);
@@ -1485,7 +1513,7 @@ krb5_db_fetch_mkey(krb5_context context,
        retval = dal_handle->lib_handle->vftabl.fetch_master_key(context,
                                                                 mname,
                                                                 &tmp_key,
-                                                                &kvno,
+                                                                kvno,
                                                                 db_args);
        get_errmsg(context, retval);
        kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE);
@@ -1515,8 +1543,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;
@@ -1535,7 +1565,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..f9f44944228868930ae33748d52c01add066b1c7 100644 (file)
@@ -139,17 +139,19 @@ 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);
 
     krb5_error_code (*fetch_master_key) (krb5_context kcontext,
                                         krb5_principal mname,
                                         krb5_keyblock *key,
-                                        int *kvno,
+                                        krb5_kvno *kvno,
                                         char *db_args);
 
     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 22d3af24249c40aa0ce74d30ec89fd21c87ba11b..bf4ba358499f00b69d3717f6fb21cd3ce35a209b 100644 (file)
@@ -133,102 +133,117 @@ 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;
-    krb5_ui_4 keylength;
     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);
-#if BIG_ENDIAN_MASTER_KEY
-    enctype = htons((uint16_t) key->enctype);
-    keylength = htonl((uint32_t) key->length);
-#else
-    enctype = key->enctype;
-    keylength = key->length;
-#endif
-    if ((fwrite((krb5_pointer) &enctype,
-               2, 1, kf) != 1) ||
-       (fwrite((krb5_pointer) &keylength,
-               sizeof(keylength), 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_XXXXXX", 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,
-                       krb5_principal mname,
-                       krb5_keyblock *key,
-                       int           *kvno,
-                       char          *db_args)
+static krb5_error_code
+krb5_db_def_fetch_mkey_stash(krb5_context   context,
+                            const char *keyfile,
+                            krb5_keyblock *key,
+                            krb5_kvno     *kvno)
 {
-    krb5_error_code retval;
+    krb5_error_code retval = 0;
     krb5_ui_2 enctype;
     krb5_ui_4 keylength;
-    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);
@@ -260,7 +275,7 @@ krb5_db_def_fetch_mkey( krb5_context   context,
 #else
     key->length = keylength;
 #endif
-    
+
     if (!key->length || ((int) key->length) < 0) {
        retval = KRB5_KDB_BADSTORED_MKEY;
        goto errout;
@@ -271,9 +286,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);
@@ -281,20 +295,137 @@ krb5_db_def_fetch_mkey( krb5_context   context,
     } else
        retval = 0;
 
-    *kvno = 0;
+    /*
+     * Note, the old stash format did not store the kvno and at this point it
+     * can be assumed to be 1 as is the case for the mkey princ.  If the kvno is
+     * passed in and isn't ignore_vno just leave it alone as this could cause
+     * verifcation trouble if the mkey princ is using a kvno other than 1.
+     */
+    if (kvno && *kvno == IGNORE_VNO)
+       *kvno = 1;
 
  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;
+    krb5_keytab kt;
+    krb5_keytab_entry kt_ent;
+    krb5_enctype enctype = IGNORE_ENCTYPE;
+
+    if ((retval = krb5_kt_resolve(context, keyfile, &kt)) != 0)
+        goto errout;
+
+    /* override default */
+    if (key->enctype != ENCTYPE_UNKNOWN)
+        enctype = key->enctype;
+
+    if ((retval = krb5_kt_get_entry(context, kt, mname,
+                                    kvno ? *kvno : IGNORE_VNO,
+                                    enctype,
+                                    &kt_ent)) == 0) {
+
+        if (key->enctype == ENCTYPE_UNKNOWN)
+            key->enctype = kt_ent.key.enctype;
+
+        if (((int) kt_ent.key.length) < 0) {
+            retval = KRB5_KDB_BADSTORED_MKEY;
+            krb5_kt_free_entry(context, &kt_ent);
+            goto errout;
+        }
+
+        key->length = kt_ent.key.length;
+
+        /*
+         * If a kvno pointer was passed in and it dereferences the
+         * IGNORE_VNO value 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 != NULL && *kvno == IGNORE_VNO)
+            *kvno = kt_ent.vno;
+
+        /*
+         * kt_ent will be free'd so need to allocate and copy key contents for
+         * output to caller.
+         */
+        if (!(key->contents = (krb5_octet *)malloc(key->length))) {
+            retval = ENOMEM;
+            krb5_kt_free_entry(context, &kt_ent);
+            goto errout;
+        }
+        memcpy(key->contents, kt_ent.key.contents, kt_ent.key.length);
+        krb5_kt_free_entry(context, &kt_ent);
+    }
+
+errout:
+    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 keyfile[MAXPATHLEN+1];
+    krb5_data *realm = krb5_princ_realm(context, mname);
+
+    key->magic = KV5M_KEYBLOCK;
+
+    if (db_args != NULL) {
+        (void) strncpy(keyfile, db_args, sizeof(keyfile));
+    } else {
+        (void) strcpy(keyfile, DEFAULT_KEYFILE_STUB);
+        (void) strncat(keyfile, realm->data,
+            min(sizeof(keyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
+                realm->length));
+    }
+    /* null terminate no matter what */
+    keyfile[sizeof(keyfile) - 1] = '\0';
+
+    /* assume the master key is in a keytab */
+    retval_kt = krb5_db_def_fetch_mkey_keytab(context, keyfile, 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, keyfile, key, kvno);
+    }
+
+    if (retval_kt != 0 && retval_ofs != 0) {
+        /*
+         * Error, not able to get mkey from either file format.  Note, in order
+         * to try to return a more correct error, the logic below is assuming
+         * that if either of the stash reading functions returned
+         * KRB5_KDB_BADSTORED_MKEY then this is probably the real error.
+         */
+        krb5_set_error_message (context, KRB5_KDB_CANTREAD_STORED,
+            "Can not fetch master key either from keytab (error: %s) or old "
+            "format (error %s).", error_message(retval_kt),
+            error_message(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;
@@ -329,6 +460,14 @@ krb5_def_verify_master_key(context, mprinc, mkey)
        retval = KRB5_KDB_BADMASTERKEY;
     }
 
+    if (kvno != IGNORE_VNO &&
+        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 cc254dd4b4e4598abe1a304afbce5b5c0f9f95c4..357bb124650b8cf299e9502eceb8c10e6c8d1fa8 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 db392e6d59a7b5505e064307cf5ecb212754cfd9..bf9634e53a90770fd507572308579d44482f3dd9 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 eb20a28ed6ab860a8b0906aa05bcc8d5c7b53c71..288a5a0c6b35fe4103db13a792731e7dba816fe6 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(progname, errno, "while storing key");
index 08463b7f87b0d18c33bfa568b8e83874512d8b81..484c4ce886bae0f8ad35e00038154de080fa18a7 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
+1. Note that 0 is not allowed.
+.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 704bb163e8766f7f3b346412bdfdf829fc0fe773..1f900e67af04da3136d816439d4b006ba8ca4019 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"
 
@@ -346,10 +346,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(progname, 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 1329e8063b8afc27b949feb1dca7a38490afec93..09bc0442465c0c20fc983dda7eb5205278e1a2af 100644 (file)
@@ -3,7 +3,7 @@ mydir=tests
 myfulldir=tests
 BUILDTOP=$(REL)..
 SUBDIRS = resolve asn.1 create hammer verify gssapi dejagnu shlib \
-       gss-threads misc
+       gss-threads misc mkeystash_compat
 
 RUN_SETUP = @KRB5_RUN_ENV@ KRB5_KDC_PROFILE=kdc.conf KRB5_CONFIG=krb5.conf
 KRB5_RUN_ENV= @KRB5_RUN_ENV@
index 79112e7c2f75c6ff001f4122cb74c4b6fd9f7bb5..3abef65dbafd0c0cdb3f37ac1a1d3a40214836b6 100644 (file)
@@ -360,7 +360,8 @@ char *dbname;
     } else {
        if ((retval = krb5_db_fetch_mkey(test_context, master_princ, 
                                        master_keyblock.enctype, manual_mkey, 
-                                       FALSE, 0, NULL, &master_keyblock))) {
+                                       FALSE, 0, NULL, NULL,
+                                        &master_keyblock))) {
            com_err(pname, retval, "while reading master key");
            return(1);
        }
@@ -389,7 +390,7 @@ char *dbname;
     free(args[0]);
 
     if ((retval = krb5_db_verify_master_key(test_context, master_princ, 
-                                          &master_keyblock))){
+                                          IGNORE_VNO, &master_keyblock))){
        com_err(pname, retval, "while verifying master key");
        (void) krb5_db_fini(test_context);
        return(1);
diff --git a/src/tests/mkeystash_compat/Makefile.in b/src/tests/mkeystash_compat/Makefile.in
new file mode 100644 (file)
index 0000000..7b8956e
--- /dev/null
@@ -0,0 +1,49 @@
+thisconfigdir=../..
+mydir=tests/mkeystash_compat
+myfulldir=tests/mkeystash_compat
+BUILDTOP=$(REL)..$(S)..
+
+RUN_SETUP = @KRB5_RUN_ENV@ KRB5_KDC_PROFILE=kdc.conf KRB5_CONFIG=krb5.conf
+KRB5_RUN_ENV= @KRB5_RUN_ENV@
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+OBJS = bigendian.o
+SRCS = $(srcdir)/bigendian.c
+
+TEST_DB = ./testdb
+TEST_REALM = FOO.TEST.REALM
+TEST_MKEY = footes
+
+KADMIN_OPTS= -d $(TEST_DB) -r $(TEST_REALM)
+KDB_OPTS= $(KADMIN_OPTS) -P $(TEST_MKEY)
+
+check-unix:: mkeystash_check
+
+bigendian: $(OUTPRE)bigendian.$(OBJEXT) $(SUPPORT_DEPLIB)
+       $(CC_LINK) $(ALL_CFLAGS) -o bigendian $(OUTPRE)bigendian.$(OBJEXT)
+
+kdc.conf: Makefile
+       rm -rf kdc.conf
+       @echo "[realms]" > kdc.conf
+       @echo "$(TEST_REALM) = {" >> kdc.conf
+       @echo "  key_stash_file = `pwd`/stash_file" >> kdc.conf
+       @echo "}" >> kdc.conf
+
+krb5.conf: Makefile
+       cat $(SRCTOP)/config-files/krb5.conf > krb5.new
+
+# Verify that the mkey stash code is backward compat with old/non-keytab stashfile format
+mkeystash_check: kdc.conf krb5.conf bigendian
+       $(RM) $(TEST_DB)* stash_file
+       $(RUN_SETUP) $(VALGRIND) ../../kadmin/dbutil/kdb5_util $(KDB_OPTS) create -s
+       # overwrite keytab stash file with old format stash, depends on endianness of current test system
+       ./bigendian && cp $(srcdir)/old_stash_bendian stash_file || cp $(srcdir)/old_stash_lendian stash_file
+       # getprinc will fail if old stash file can not be read
+       $(RUN_SETUP) $(VALGRIND) ../../kadmin/cli/kadmin.local $(KADMIN_OPTS) -q 'getprinc K/M'
+       $(RUN_SETUP) $(VALGRIND) ../../kadmin/dbutil/kdb5_util $(KDB_OPTS) destroy -f
+       $(RM) $(TEST_DB)* stash_file
+
+clean::
+       $(RM) kdc.conf
+
diff --git a/src/tests/mkeystash_compat/bigendian.c b/src/tests/mkeystash_compat/bigendian.c
new file mode 100644 (file)
index 0000000..bcdeeb5
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+/*
+ * Test to see if system is bigendian
+ * Returns 0 if it is big endian
+ *         1 if it is little endian
+ */
+int main()
+{
+    int int_var = 1;
+    unsigned char *char_array = (unsigned char*)&int_var;
+
+    if (char_array[0] == 0)
+       return 0; /* big endian */
+    else
+       return 1; /* little endian */
+}
diff --git a/src/tests/mkeystash_compat/old_stash_bendian b/src/tests/mkeystash_compat/old_stash_bendian
new file mode 100644 (file)
index 0000000..7d3761f
Binary files /dev/null and b/src/tests/mkeystash_compat/old_stash_bendian differ
diff --git a/src/tests/mkeystash_compat/old_stash_lendian b/src/tests/mkeystash_compat/old_stash_lendian
new file mode 100644 (file)
index 0000000..754c320
Binary files /dev/null and b/src/tests/mkeystash_compat/old_stash_lendian differ
index 2dd19ba44033149b0ae018f92a885f67999f97e1..b6d7b23325e5641f63b37a783526397b4a9351ff 100644 (file)
@@ -389,8 +389,9 @@ set_dbname_help(context, pname, dbname)
     } else {
        if ((retval = krb5_db_fetch_mkey(context, master_princ,
                                         master_keyblock.enctype,
-                                       manual_mkey, FALSE, (char *) NULL, 0,
-                                       &master_keyblock))) {
+                                        manual_mkey, FALSE, (char *) NULL,
+                                         NULL, NULL,
+                                        &master_keyblock))) {
            com_err(pname, retval, "while reading master key");
            return(1);
        }
@@ -416,7 +417,7 @@ set_dbname_help(context, pname, dbname)
        return(1);
     }
     if ((retval = krb5_db_verify_master_key(context, master_princ, 
-                                           &master_keyblock))) {
+                                           IGNORE_VNO, &master_keyblock))) {
        com_err(pname, retval, "while verifying master key");
        (void) krb5_db_fini(context);
        return(1);