*** empty log message ***
authorJohn Kohl <jtkohl@mit.edu>
Fri, 14 Jun 1991 11:28:58 +0000 (11:28 +0000)
committerJohn Kohl <jtkohl@mit.edu>
Fri, 14 Jun 1991 11:28:58 +0000 (11:28 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@2176 dc483132-0cff-0310-8789-dd5450dbe970

src/admin/convert/Imakefile [new file with mode: 0644]
src/admin/convert/kdb5_convert.c [new file with mode: 0644]

diff --git a/src/admin/convert/Imakefile b/src/admin/convert/Imakefile
new file mode 100644 (file)
index 0000000..5cb3afc
--- /dev/null
@@ -0,0 +1,29 @@
+#      $Source$
+#      $Author$
+#      $Id$
+#
+#  Copyright 1991 by the Massachusetts Institute of Technology.
+#  All Rights Reserved.
+# 
+# Export of this software from the United States of America is assumed
+#   to require a specific license from the United States Government.
+#   It is the responsibility of any person or organization contemplating
+#   export to obtain such a license before exporting.
+# 
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+# 
+# 
+DEPLIBS = $(DEPKDBLIB) $(DEPKLIB)
+LOCAL_LIBRARIES = $(KDBLIB) $(KLIB) -lkdb -lkrb -ldes425
+INCLUDES=-I$(TOP)/include/kerberosIV
+
+Krb5AdminProgramTarget(kdb5_convert)
diff --git a/src/admin/convert/kdb5_convert.c b/src/admin/convert/kdb5_convert.c
new file mode 100644 (file)
index 0000000..da7c6f6
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America is assumed
+ *   to require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * Generate (from scratch) a Kerberos V5 KDC database, filling it in with the
+ * entries from a V4 database.
+ * You'd better have NDBM if you're doing this!
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcsid_kdb_create_c[] =
+"$Id$";
+#endif /* !lint & !SABER */
+
+#include <des.h>
+#include <krb.h>
+#include <krb_db.h>
+/* MKEYFILE is now defined in kdc.h */
+#include <kdc.h>
+
+static C_Block master_key;
+static Key_schedule master_key_schedule;
+static long master_key_version;
+
+#include <krb5/krb5.h>
+#include <krb5/kdb.h>
+#include <krb5/kdb_dbm.h>
+#include <krb5/los-proto.h>
+#include <krb5/asn1.h>
+#include <krb5/osconf.h>
+
+#include <com_err.h>
+#include <stdio.h>
+
+#include <krb5/ext-proto.h>
+
+#ifdef ODBM
+#error:  This program cannot work properly with a DBM database unless it has the NDBM package
+/* This is because the program opens both databases simultaneously,
+   and the old DBM does not support multiple simultaneous databases. */
+#endif
+
+#define PROGNAME argv[0]
+
+enum ap_op {
+    NULL_KEY,                          /* setup null keys */
+    MASTER_KEY,                                /* use master key as new key */
+    RANDOM_KEY                         /* choose a random key */
+};
+
+struct realm_info {
+    krb5_deltat max_life;
+    krb5_deltat max_rlife;
+    krb5_timestamp expiration;
+    krb5_flags flags;
+    krb5_encrypt_block *eblock;
+    krb5_pointer rseed;
+} rblock = { /* XXX */
+    KRB5_KDB_MAX_LIFE,
+    KRB5_KDB_MAX_RLIFE,
+    KRB5_KDB_EXPIRATION,
+    KRB5_KDB_DEF_FLAGS,
+    0
+};
+
+
+static krb5_error_code add_principal PROTOTYPE((krb5_principal, enum ap_op,
+                                               struct realm_info *));
+void v4cleanup PROTOTYPE((void));
+int v4init PROTOTYPE((char *, char *, int));
+krb5_error_code enter_in_v5_db PROTOTYPE((char *, Principal *));
+
+/*
+ * Steps in creating a database:
+ *
+ * 1) use the db calls to open/create a new database
+ *
+ * 2) get a realm name for the new db
+ *
+ * 3) get a master password for the new db; convert to an encryption key.
+ *
+ * 4) create various required entries in the database
+ *
+ * 5) close & exit
+ */
+
+static void
+usage(who, status)
+char *who;
+int status;
+{
+    fprintf(stderr, "usage: %s [-d v5dbpathname] [-D v4dbpathname] [-n] [-r realmname] [-k keytype]\n\
+\t[-e etype] [-M mkeyname]\n",
+           who);
+    exit(status);
+}
+
+krb5_keyblock master_keyblock;
+krb5_principal master_princ;
+krb5_encrypt_block master_encblock;
+
+krb5_data tgt_princ_entries[] = {
+       {0, 0},
+       {sizeof(TGTNAME)-1, TGTNAME} };
+
+krb5_data db_creator_entries[] = {
+       {sizeof("db_creation")-1, "db_creation"} };
+
+/* XXX knows about contents of krb5_principal, and that tgt names
+ are of form TGT/REALM@REALM */
+krb5_data *tgt_princ[] = {
+       &tgt_princ_entries[0],
+       &tgt_princ_entries[1],
+       &tgt_princ_entries[0],
+       0 };
+
+krb5_data *db_create_princ[] = {
+       &tgt_princ_entries[0],
+       &db_creator_entries[0],
+       0 };
+
+void
+main(argc, argv)
+int argc;
+char *argv[];
+{
+    extern char *optarg;       
+    int optchar;
+    
+    krb5_error_code retval;
+    char *dbname = 0;
+    char *v4dbname = 0;
+    char *realm = 0;
+    char *mkey_name = 0;
+    char *mkey_fullname;
+    char *defrealm;
+    int keytypedone = 0;
+    int v4manual = 0;
+    krb5_enctype etype = 0xffff;
+
+    initialize_krb5_error_table();
+    initialize_kdb5_error_table();
+    initialize_isod_error_table();
+
+    if (strrchr(argv[0], '/'))
+       argv[0] = strrchr(argv[0], '/')+1;
+
+    while ((optchar = getopt(argc, argv, "d:D:r:k:M:e:n")) != EOF) {
+       switch(optchar) {
+       case 'd':                       /* set db name */
+           dbname = optarg;
+           break;
+       case 'D':                       /* set db name */
+           v4dbname = optarg;
+           break;
+       case 'r':
+           realm = optarg;
+           break;
+       case 'k':
+           master_keyblock.keytype = atoi(optarg);
+           keytypedone++;
+           break;
+       case 'M':                       /* master key name in DB */
+           mkey_name = optarg;
+           break;
+       case 'e':
+           etype = atoi(optarg);
+           break;
+       case 'n':
+           v4manual++;
+           break;
+       case '?':
+       default:
+           usage(PROGNAME, 1);
+           /*NOTREACHED*/
+       }
+    }
+
+    if (!keytypedone)
+       master_keyblock.keytype = DEFAULT_KDC_KEYTYPE;
+
+    if (!valid_keytype(master_keyblock.keytype)) {
+       com_err(PROGNAME, KRB5_PROG_KEYTYPE_NOSUPP,
+               "while setting up keytype %d", master_keyblock.keytype);
+       exit(1);
+    }
+
+    if (etype == 0xffff)
+       etype = DEFAULT_KDC_ETYPE;
+
+    if (!valid_etype(etype)) {
+       com_err(PROGNAME, KRB5_PROG_ETYPE_NOSUPP,
+               "while setting up etype %d", etype);
+       exit(1);
+    }
+    krb5_use_cstype(&master_encblock, etype);
+
+    if (!dbname)
+       dbname = DEFAULT_DBM_FILE;      /* XXX? */
+
+    retval = krb5_db_set_name(dbname);
+    if (!retval) retval = EEXIST;
+
+    if (retval == EEXIST || retval == EACCES || retval == EPERM) {
+       /* it exists ! */
+       com_err(PROGNAME, 0, "The database '%s' appears to already exist",
+               dbname);
+       exit(1);
+    }
+    if (!realm) {
+       if (retval = krb5_get_default_realm(&defrealm)) {
+           com_err(PROGNAME, retval, "while retrieving default realm name");
+           exit(1);
+       }           
+       realm = defrealm;
+    }
+
+    /* assemble & parse the master key name */
+
+    if (retval = krb5_db_setup_mkey_name(mkey_name, realm, &mkey_fullname,
+                                &master_princ)) {
+       com_err(PROGNAME, retval, "while setting up master key name");
+       exit(1);
+    }
+
+    tgt_princ[0]->data = realm;
+    tgt_princ[0]->length = strlen(realm);
+
+    printf("Initializing database '%s' for realm '%s',\n\
+master key name '%s'\n",
+          dbname, realm, mkey_fullname);
+
+    printf("You will be prompted for the database Master Password.\n");
+    printf("It is important that you NOT FORGET this password.\n");
+    fflush(stdout);
+
+    /* TRUE here means read the keyboard, and do it twice */
+    if (retval = krb5_db_fetch_mkey(master_princ, &master_encblock, TRUE, TRUE,
+                                   &master_keyblock)) {
+       com_err(PROGNAME, retval, "while reading master key");
+       exit(1);
+    }
+    if (retval = krb5_process_key(&master_encblock, &master_keyblock)) {
+       com_err(PROGNAME, retval, "while processing master key");
+       exit(1);
+    }
+
+    rblock.eblock = &master_encblock;
+    if (retval = krb5_init_random_key(&master_encblock, &master_keyblock,
+                                     &rblock.rseed)) {
+       com_err(PROGNAME, retval, "while initializing random key generator");
+       (void) krb5_finish_key(&master_encblock);
+       exit(1);
+    }
+    if (retval = krb5_db_create(dbname)) {
+       (void) krb5_finish_key(&master_encblock);
+       (void) krb5_finish_random_key(&master_encblock, &rblock.rseed);
+       com_err(PROGNAME, retval, "while creating database '%s'",
+               dbname);
+       exit(1);
+    }
+    if (retval = krb5_db_set_name(dbname)) {
+       (void) krb5_finish_key(&master_encblock);
+       (void) krb5_finish_random_key(&master_encblock, &rblock.rseed);
+        com_err(PROGNAME, retval, "while setting active database to '%s'",
+                dbname);
+        exit(1);
+    }
+    if (v4init(PROGNAME, v4dbname, v4manual)) {
+       (void) krb5_finish_key(&master_encblock);
+       (void) krb5_finish_random_key(&master_encblock, &rblock.rseed);
+       exit(1);
+    }
+    if (retval = krb5_db_init()) {
+       (void) krb5_finish_key(&master_encblock);
+       (void) krb5_finish_random_key(&master_encblock, &rblock.rseed);
+       com_err(PROGNAME, retval, "while initializing the database '%s'",
+               dbname);
+       exit(1);
+    }
+
+    if ((retval = add_principal(master_princ, MASTER_KEY, &rblock)) ||
+       (retval = add_principal(tgt_princ, RANDOM_KEY, &rblock))) {
+       (void) krb5_db_fini();
+       (void) krb5_finish_key(&master_encblock);
+       (void) krb5_finish_random_key(&master_encblock, &rblock.rseed);
+       com_err(PROGNAME, retval, "while adding entries to the database");
+       exit(1);
+    }
+    if (retval = kerb_db_iterate(enter_in_v5_db, realm)) {
+       com_err(PROGNAME, retval, "while translating entries to the database");
+    }
+    putchar('\n');
+    /* clean up */
+    (void) krb5_db_fini();
+    (void) krb5_finish_key(&master_encblock);
+    (void) krb5_finish_random_key(&master_encblock, &rblock.rseed);
+    memset((char *)master_keyblock.contents, 0, master_keyblock.length);
+    exit(retval ? 1 : 0);
+}
+
+void
+v4cleanup()
+{
+    return;
+}
+
+int
+v4init(pname, name, manual)
+char *pname, *name;
+int manual;
+{
+    kerb_init();
+    if (name) {
+       if (kerb_db_set_name(name) != 0) {
+           com_err(pname, 0,
+                   "Could not open alternate v4 database name %s\n",
+                   name);
+           return 1;
+       }
+    }
+    if (kdb_get_master_key ((manual == 0), 
+                           master_key, master_key_schedule) != 0) {
+       com_err(pname, 0, "Couldn't read v4 master key.");
+       return 1;
+    }
+    if ((master_key_version = kdb_verify_master_key(master_key,
+                                                   master_key_schedule,
+                                                   stdout)) < 0) {
+       com_err(pname, 0, "Couldn't verify v4 master key.");
+       return 1;
+    }
+    return 0;
+}
+
+krb5_error_code
+enter_in_v5_db(realm, princ)
+char *realm;
+Principal *princ;
+{
+    krb5_db_entry entry;
+    krb5_error_code retval;
+    krb5_encrypted_keyblock ekey;
+    krb5_keyblock v4v5key;
+    int nentries = 1;
+    des_cblock v4key;
+    char *name;
+
+    /* don't convert certain principals... */
+    if (!strcmp(princ->name, "krbtgt") ||
+       (!strcmp(princ->name, KERB_M_NAME) &&
+        !strcmp(princ->instance, KERB_M_INST))) {
+       printf("\nignoring '%s.%s' ...", princ->name, princ->instance);
+       return 0;
+    }
+    if (retval = krb5_build_principal(&entry.principal, strlen(realm),
+                                     realm, princ->name,
+                                     princ->instance[0] ? princ->instance : 0,
+                                     0))
+       return retval;
+    if (retval = krb5_unparse_name(entry.principal, &name))
+       name = strdup("<not unparsable name!>");
+    printf("\ntranslating %s...", name);
+    free(name);
+
+    if (retval = krb5_build_principal(&entry.mod_name, strlen(realm),
+                                     realm, princ->mod_name,
+                                     princ->mod_instance[0] ? princ->instance : 0,
+                                     0)) {
+       krb5_free_principal(entry.principal);
+       return retval;
+    }
+
+    entry.kvno = princ->key_version;
+    entry.max_life = princ->max_life * 60 * 5;
+    entry.max_renewable_life = rblock.max_rlife;
+    entry.mkvno = 0;
+    entry.expiration = princ->exp_date;
+    entry.mod_date = princ->mod_date;
+    entry.attributes = rblock.flags;   /* XXX is there a way to convert
+                                          the old attrs? */
+
+    bcopy((char *)&(princ->key_low), (char *)v4key, 4);
+    bcopy((char *)&(princ->key_high), (char *) (((long *) v4key) + 1), 4);
+    kdb_encrypt_key (v4key, v4key, master_key, master_key_schedule, DECRYPT);
+
+    v4v5key.contents = (krb5_octet *)v4key;
+    v4v5key.keytype = KEYTYPE_DES;
+    v4v5key.length = sizeof(v4key);
+
+    retval = krb5_kdb_encrypt_key(rblock.eblock, &v4v5key, &ekey);
+    if (retval) {
+       krb5_free_principal(entry.principal);
+       krb5_free_principal(entry.mod_name);
+       return retval;
+    }
+    memset((char *)v4key, 0, sizeof(v4key));
+    entry.key = ekey;
+    entry.salt_type = KRB5_KDB_SALTTYPE_V4;
+    entry.salt_length = 0;
+    entry.salt = 0;
+
+    if (retval = krb5_db_put_principal(&entry, &nentries)) {
+       krb5_free_principal(entry.principal);
+       krb5_free_principal(entry.mod_name);
+       return retval;
+    }
+    xfree(ekey.contents);
+    return 0;
+}
+
+static krb5_error_code
+add_principal(princ, op, pblock)
+krb5_principal princ;
+enum ap_op op;
+struct realm_info *pblock;
+{
+    krb5_db_entry entry;
+    krb5_error_code retval;
+    krb5_encrypted_keyblock ekey;
+    krb5_keyblock *rkey;
+    int nentries = 1;
+
+    entry.principal = princ;
+    entry.kvno = 0;
+    entry.max_life = pblock->max_life;
+    entry.max_renewable_life = pblock->max_rlife;
+    entry.mkvno = 0;
+    entry.expiration = pblock->expiration;
+    entry.mod_name = db_create_princ;
+
+    if (retval = krb5_timeofday(&entry.mod_date))
+       return retval;
+    entry.attributes = pblock->flags;
+
+    switch (op) {
+    case MASTER_KEY:
+       entry.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+       if (retval = krb5_kdb_encrypt_key(pblock->eblock,
+                                         &master_keyblock,
+                                         &ekey))
+           return retval;
+       break;
+    case RANDOM_KEY:
+       if (retval = krb5_random_key(pblock->eblock, pblock->rseed, &rkey))
+           return retval;
+       retval = krb5_kdb_encrypt_key(pblock->eblock, rkey, &ekey);
+       krb5_free_keyblock(rkey);
+       if (retval)
+           return retval;
+       break;
+    case NULL_KEY:
+       return EOPNOTSUPP;
+    default:
+       break;
+    }
+    entry.key = ekey;
+    entry.salt_type = KRB5_KDB_SALTTYPE_NORMAL;
+    entry.salt_length = 0;
+    entry.salt = 0;
+
+    if (retval = krb5_db_put_principal(&entry, &nentries))
+       return retval;
+
+    xfree(ekey.contents);
+    return 0;
+}