summaryrefslogtreecommitdiffstats
path: root/src/kadmin/create
diff options
context:
space:
mode:
Diffstat (limited to 'src/kadmin/create')
-rw-r--r--src/kadmin/create/ChangeLog9
-rw-r--r--src/kadmin/create/Makefile.in15
-rw-r--r--src/kadmin/create/Makefile.ov12
-rw-r--r--src/kadmin/create/attic/Makefile.in20
-rw-r--r--src/kadmin/create/attic/configure.in12
-rw-r--r--src/kadmin/create/attic/make_extern16
-rw-r--r--src/kadmin/create/attic/ovsec_adm_create.c663
-rw-r--r--src/kadmin/create/configure.in11
-rw-r--r--src/kadmin/create/kadm5_create.c241
-rw-r--r--src/kadmin/create/kdb5_create.c536
-rw-r--r--src/kadmin/create/string_table.c91
-rw-r--r--src/kadmin/create/string_table.h40
12 files changed, 1666 insertions, 0 deletions
diff --git a/src/kadmin/create/ChangeLog b/src/kadmin/create/ChangeLog
new file mode 100644
index 000000000..0c724422d
--- /dev/null
+++ b/src/kadmin/create/ChangeLog
@@ -0,0 +1,9 @@
+Fri Jul 12 14:43:56 1996 Marc Horowitz <marc@mit.edu>
+
+ * configure.in (USE_GSSAPI_LIBRARY): shared libraries require that
+ all symbols be resolved, even if they are not used by the
+ executeable. Thus, create needs to link against gssapi
+
+Wed Jul 10 01:24:29 1996 Marc Horowitz <marc@mit.edu>
+
+ * Makefile.in, configure.in: added autoconf support
diff --git a/src/kadmin/create/Makefile.in b/src/kadmin/create/Makefile.in
new file mode 100644
index 000000000..547bd39c6
--- /dev/null
+++ b/src/kadmin/create/Makefile.in
@@ -0,0 +1,15 @@
+CFLAGS = $(CCOPTS) $(DEFS) $(LOCALINCLUDE)
+
+PROG = kdb5_create
+OBJS = kdb5_create.o kadm5_create.o string_table.o
+
+all:: $(PROG)
+
+$(PROG): $(OBJS) $(DEPLIBS)
+ $(CC) $(LDFLAGS) $(LDARGS) -o $(PROG) $(OBJS) $(LIBS)
+
+install::
+ $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
+
+clean::
+ $(RM) $(PROG) $(OBJS)
diff --git a/src/kadmin/create/Makefile.ov b/src/kadmin/create/Makefile.ov
new file mode 100644
index 000000000..cdec414b7
--- /dev/null
+++ b/src/kadmin/create/Makefile.ov
@@ -0,0 +1,12 @@
+TOP = ..
+include $(TOP)/config.mk/template
+
+PROG = kadmin_create
+SRCS = kdb5_create.c kadm5_create.c string_table.c
+OBJS = kdb5_create.o kadm5_create.o string_table.o
+
+LIBS = $(LIBADMSRV) $(LIBRPCLIB) $(LIBKDB5) $(LIBKRB5_ALL) \
+ $(LIBDYN) $(NDBMLIB) $(LIBDB) $(BSDLIB) $(NETLIB)
+
+expand InstallAdmin
+expand Depend
diff --git a/src/kadmin/create/attic/Makefile.in b/src/kadmin/create/attic/Makefile.in
new file mode 100644
index 000000000..f7bd9ca38
--- /dev/null
+++ b/src/kadmin/create/attic/Makefile.in
@@ -0,0 +1,20 @@
+CFLAGS = $(CCOPTS) $(DEFS) $(LOCALINCLUDE)
+
+all::
+
+SRCS = $(srcdir)/ovsec_adm_create.c \
+ $(srcdir)/string_table.c
+
+OBJS = ovsec_adm_create.o \
+ string_table.o
+
+all:: ovsec_adm_create
+
+ovsec_adm_create: $(OBJS) $(DEPLIBS)
+ $(LD) $(LDFLAGS) $(LDARGS) -o ovsec_adm_create $(OBJS) $(LIBS)
+
+install::
+ $(INSTALL_PROGRAM) ./ovsec_adm_create ${DESTDIR}$(SERVER_BINDIR)/kadmind5
+
+clean::
+ $(RM) ovsec_adm_create
diff --git a/src/kadmin/create/attic/configure.in b/src/kadmin/create/attic/configure.in
new file mode 100644
index 000000000..67b8f7c52
--- /dev/null
+++ b/src/kadmin/create/attic/configure.in
@@ -0,0 +1,12 @@
+AC_INIT(ovsec_adm_create.c)
+CONFIG_RULES
+AC_PROG_INSTALL
+USE_KADMSRV_LIBRARY
+USE_GSSRPC_LIBRARY
+USE_GSSAPI_LIBRARY
+USE_KDB5_LIBRARY
+USE_DYN_LIBRARY
+USE_DB_LIBRARY
+KRB5_LIBRARIES
+V5_USE_SHARED_LIB
+V5_AC_OUTPUT_MAKEFILE
diff --git a/src/kadmin/create/attic/make_extern b/src/kadmin/create/attic/make_extern
new file mode 100644
index 000000000..5432edf66
--- /dev/null
+++ b/src/kadmin/create/attic/make_extern
@@ -0,0 +1,16 @@
+#!/bin/csh
+
+echo '/*'
+echo ' * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.'
+echo ' * '
+echo ' * $Header$'
+echo ' *'
+echo ' */'
+echo ' '
+echo '#ifndef _OVSEC_ADM_STRINGS_'
+echo ' '
+
+cat $1 | grep -v rcsid | grep ^char | awk '{printf "extern %s %s;\n",$1,$2}'
+
+echo ' '
+echo '#endif /* _OVSEC_ADM_STRINGS_ */'
diff --git a/src/kadmin/create/attic/ovsec_adm_create.c b/src/kadmin/create/attic/ovsec_adm_create.c
new file mode 100644
index 000000000..90be0c406
--- /dev/null
+++ b/src/kadmin/create/attic/ovsec_adm_create.c
@@ -0,0 +1,663 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.23 1996/07/22 20:24:35 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.22.4.1 1996/07/18 03:01:22 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.22.2.1 1996/06/20 21:44:55 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.22 1996/06/19 15:09:32 bjaspan
+ * changes to work in mit tree
+ *
+ * Revision 1.21 1995/11/07 23:27:28 grier
+ * Add stdlib.h
+ * Add string.h
+ *
+ * Revision 1.20 1995/08/13 16:41:11 jik
+ * Fix a nonsensical comment about the iterator() function. See PR
+ * secure-admin/470.
+ *
+ * Revision 1.19 1995/07/02 19:55:13 jik
+ * Key version numbers should start out at 1, not 0.
+ * Should get the master key version number from the master_db entry in
+ * server_kdb.c, rather than assuming that the master key version number
+ * is 0.
+ *
+ * Revision 1.18 1995/03/14 16:58:50 jik
+ * Use krb5_xfree instead of xfree if KRB5B4 is defined.
+ *
+ * Revision 1.17 1994/03/11 19:37:34 bjaspan
+ * [secure-admin/1593: ovsec_adm_create non-error messages go to stderr]
+ * [secure-releng/1608: audit secure-admin/1593: ovsec_adm_create non-error messages go to stderr]
+ *
+ * Sandbox:
+ *
+ * Normal messages should be printed to stdout rather than displayed
+ * using com_err, which will cause then to go to stderr.
+ *
+ * Revision 1.17 1994/03/09 22:21:33 jik
+ * Normal messages should be printed to stdout rather than displayed
+ * using com_err, which will cause then to go to stderr.
+ *
+ * Revision 1.16 1993/12/21 20:26:34 marc
+ * create new principals with policy NULL, not ""
+ *
+ * Revision 1.15 1993/12/14 22:51:35 marc
+ * missing * in call to krb5_random_key
+ *
+ * Revision 1.14 1993/11/27 20:42:32 bjaspan
+ * fix secure/621: coredumps with default realm
+ *
+ * Revision 1.13 1993/11/19 20:03:51 shanzer
+ * osa_adb_open_T takes a file name argument.
+ *
+ * Revision 1.12 1993/11/10 21:30:24 bjaspan
+ * move init code to main, accept -m
+ *
+ * Revision 1.11 1993/11/10 04:33:35 bjaspan
+ * rewrote adding principals to kdb, and set lifetimes
+ *
+ * Revision 1.10 1993/11/06 00:08:44 bjaspan
+ * use new OVSEC_KADM_* names, use correct realm
+ *
+ * Revision 1.9 1993/11/05 05:05:35 bjaspan
+ * added -r realm argument
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include "string_table.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ovsec_admin/adb.h>
+#include <ovsec_admin/admin.h>
+
+#include <krb5.h>
+#include <krb5/kdb.h>
+
+int add_admin_princ(void *handle, krb5_context context,
+ char *name, char *realm, int attrs, int lifetime);
+
+#define ERR 1
+#define OK 0
+
+#define ADMIN_LIFETIME 60*60*3 /* 3 hours */
+#define CHANGEPW_LIFETIME 60*5 /* 5 minutes */
+
+char *whoami;
+
+extern krb5_encrypt_block master_encblock;
+extern krb5_keyblock master_keyblock;
+extern krb5_db_entry master_db;
+
+/*
+ * Function: main
+ *
+ * Purpose: create admin principals, create and populate admin dbs
+ *
+ * Arguments:
+ *
+ * input none
+ * <return value> exit status 1 for error 0 for success
+ *
+ * Requires:
+ *
+ *
+ * Effects:
+ *
+ *
+ * Modifies:
+ *
+ */
+
+void usage()
+{
+ fprintf(stderr, "%s\n", str_PROG_CREATE_USAGE);
+ exit(1);
+}
+
+void main(int argc, char **argv)
+{
+ char *realm = NULL;
+ int freerealm = 0;
+ int retval, from_keyboard = 0;
+ krb5_principal creator = NULL;
+ void *handle;
+ krb5_context context;
+
+ whoami = str_PROG_NAME_CREATE;
+
+ argc--; argv++;
+ while (argc) {
+ if (strcmp(*argv, "-r") == 0) {
+ argc--; argv++;
+ if (!argc)
+ usage();
+ realm = *argv;
+ } else if (strcmp(*argv, "-m") == 0) {
+ from_keyboard = 1;
+ } else
+ break;
+ argc--; argv++;
+ }
+
+ if (argc != 0)
+ usage();
+
+ if (retval = krb5_init_context(&context))
+ exit(ERR);
+
+ if (realm == NULL) {
+ if ((retval = krb5_get_default_realm(context, &realm)) != 0)
+ exit(retval);
+ freerealm = 1;
+ }
+
+ if ((retval = ovsec_kadm_init(whoami, from_keyboard?"non-null":NULL,
+ NULL, realm,
+ OVSEC_KADM_STRUCT_VERSION,
+ OVSEC_KADM_API_VERSION_1,
+ &handle))) {
+ com_err(whoami, retval, str_INITING_KCONTEXT);
+
+ krb5_free_context(context);
+ exit(ERR);
+ }
+
+ retval = add_admin_princs(handle, context, realm);
+
+ ovsec_kadm_destroy(handle);
+ krb5_free_context(context);
+
+ if (retval)
+ exit(retval);
+
+ exit(0);
+}
+
+/*
+ * Function: build_name_with_realm
+ *
+ * Purpose: concatenate a name and a realm to form a krb5 name
+ *
+ * Arguments:
+ *
+ * name (input) the name
+ * realm (input) the realm
+ *
+ * Returns:
+ *
+ * pointer to name@realm, in allocated memory, or NULL if it
+ * cannot be allocated
+ *
+ * Requires: both strings are null-terminated
+ */
+char *build_name_with_realm(char *name, char *realm)
+{
+ char *n;
+
+ n = (char *) malloc(strlen(name) + strlen(realm) + 2);
+ sprintf(n, "%s@%s", name, realm);
+ return n;
+}
+
+/*
+ * Function: add_admin_princs
+ *
+ * Purpose: create admin principals
+ *
+ * Arguments:
+ *
+ * rseed (input) random seed
+ * realm (input) realm, or NULL for default realm
+ * <return value> (output) status, 0 for success, 1 for serious error
+ *
+ * Requires:
+ *
+ * Effects:
+ *
+ * add_admin_princs creates OVSEC_KADM_ADMIN_SERVICE,
+ * OVSEC_KADM_CHANGEPW_SERVICE, and OVSEC_KADM_HIST_PRINCIPAL. If any
+ * of these exist a message is printed. If any of these existing
+ * principal do not have the proper attributes, a warning message is
+ * printed.
+ */
+int add_admin_princs(void *handle, krb5_context context, char *realm)
+{
+ krb5_error_code ret = 0;
+
+ if ((ret = add_admin_princ(handle, context,
+ OVSEC_KADM_ADMIN_SERVICE, realm,
+ KRB5_KDB_DISALLOW_TGT_BASED,
+ ADMIN_LIFETIME)))
+ goto clean_and_exit;
+
+ if ((ret = add_admin_princ(handle, context,
+ OVSEC_KADM_CHANGEPW_SERVICE, realm,
+ KRB5_KDB_DISALLOW_TGT_BASED |
+ KRB5_KDB_PWCHANGE_SERVICE,
+ CHANGEPW_LIFETIME)))
+ goto clean_and_exit;
+
+#if 0
+ /* this is now done inside kdb_init_hist in the admin server */
+
+ if ((ret = add_admin_princ(handle, context,
+ OVSEC_KADM_HIST_PRINCIPAL, realm,
+ KRB5_KDB_DISALLOW_ALL_TIX,
+ 0)))
+ goto clean_and_exit;
+#endif
+
+clean_and_exit:
+
+ return ret;
+}
+
+/*
+ * Function: add_admin_princ
+ *
+ * Arguments:
+ *
+ * creator (r) principal to use as "mod_by"
+ * rseed (r) seed for random key generator
+ * name (r) principal name
+ * realm (r) realm name for principal
+ * attrs (r) principal's attributes
+ * lifetime (r) principal's max life, or 0
+ * not_unique (r) error message for multiple entries, never used
+ * exists (r) warning message for principal exists
+ * wrong_attrs (r) warning message for wrong attributes
+ *
+ * Returns:
+ *
+ * OK on success
+ * ERR on serious errors
+ *
+ * Effects:
+ *
+ * If the principal is not unique, not_unique is printed (but this
+ * never happens). If the principal exists, then exists is printed
+ * and if the principals attributes != attrs, wrong_attrs is printed.
+ * Otherwise, the principal is created with mod_by creator and
+ * attributes attrs and max life of lifetime (if not zero).
+ */
+
+int add_admin_princ(void *handle, krb5_context context,
+ char *name, char *realm, int attrs, int lifetime)
+{
+ char *fullname;
+ int nprincs;
+ krb5_error_code ret;
+ ovsec_kadm_principal_ent_rec ent;
+
+ memset(&ent, 0, sizeof(ent));
+
+ fullname = build_name_with_realm(name, realm);
+ if (ret = krb5_parse_name(context, fullname, &ent.principal)) {
+ com_err(whoami, ret, str_PARSE_NAME);
+ return(ERR);
+ }
+ ent.max_life = lifetime;
+ ent.attributes = attrs;
+
+ if (ret = ovsec_kadm_create_principal(handle, &ent,
+ (OVSEC_KADM_PRINCIPAL |
+ OVSEC_KADM_MAX_LIFE |
+ OVSEC_KADM_ATTRIBUTES),
+ "to-be-random")) {
+ if (ret == OVSEC_KADM_DUP)
+ ret = ovsec_kadm_modify_principal(handle, &ent,
+ (OVSEC_KADM_PRINCIPAL |
+ OVSEC_KADM_MAX_LIFE |
+ OVSEC_KADM_ATTRIBUTES));
+
+ if (ret) {
+ com_err(whoami, ret, str_PUT_PRINC, fullname);
+ krb5_free_principal(context, ent.principal);
+ free(fullname);
+ return ERR;
+ }
+ }
+
+ ret = ovsec_kadm_randkey_principal(handle, ent.principal, NULL);
+
+ krb5_free_principal(context, ent.principal);
+ free(fullname);
+
+ if (ret) {
+ com_err(whoami, ret, str_RANDOM_KEY, fullname);
+ return ERR;
+ }
+
+ return OK;
+}
+
+#if 0
+/*
+ * Function: main
+ *
+ * Purpose: Return "garbage" if the caller asks for it.
+ *
+ * Arguments:
+ *
+ * input (input) A null-terminated string,
+ * or NULL.
+ * delay (input/output) The number of seconds the
+ * function should delay before returning.
+ * <return value> (output) A string.
+ *
+ * Requires:
+ *
+ * "input" must either be NULL or point to an address in the
+ * program's address space. "delay" must point to an address in
+ * the program's address space.
+ *
+ * Effects:
+ *
+ * The function first sleeps for approximately the number of
+ * seconds specified in "delay".
+ *
+ * Then, if "input" is non-NULL and points to a null-terminated
+ * string which is equal to "garbage", the function sets "delay"
+ * to 42 and returns a string allocated with malloc(3) containing
+ * "more-garbage".
+ *
+ * If "input" is NULL or does not contain "garbage", the function
+ * returns NULL without modifying "delay".
+ *
+ * If "<return value>" is non-NULL, the caller should deallocate
+ * the string in it (with free(3)) when it is no longer needed.
+ *
+ * Modifies:
+ *
+ * May allocate a new block of memory in the malloc(3) arena.
+ * May change the value in the memory location pointed to by
+ * "delay".
+ */
+
+krb5_error_code add_random_princ(princ_str, princ, attrs, lifetime,
+ creator, rseed)
+ char *princ_str;
+ krb5_principal princ, creator;
+ krb5_flags attrs;
+ int lifetime;
+ krb5_pointer *rseed;
+{
+ krb5_db_entry entry;
+ krb5_error_code ret;
+ krb5_encrypted_keyblock ekey;
+ krb5_keyblock *rkey;
+ int nentries = 1;
+
+ memset((char *) &entry, 0, sizeof(entry));
+ entry.principal = princ;
+ entry.kvno = 1;
+ entry.max_life = KRB5_KDB_MAX_LIFE;
+ entry.max_renewable_life = 0;
+ entry.mkvno = master_db.mkvno;
+ entry.expiration = KRB5_KDB_EXPIRATION;
+ entry.mod_name = creator;
+ if (lifetime != 0)
+ entry.max_life = lifetime;
+
+ if (ret = krb5_timeofday(&entry.mod_date))
+ return(ret);
+
+ entry.attributes = attrs;
+
+ ret = krb5_random_key(&master_encblock, *rseed, &rkey);
+ if (ret != 0) {
+ com_err(whoami, ret, str_RANDOM_KEY, princ_str);
+ return (ERR);
+ }
+
+
+ ret = krb5_kdb_encrypt_key(&master_encblock, rkey, &ekey);
+ krb5_free_keyblock(rkey);
+ if (ret != 0) {
+ com_err(whoami, ret, str_ENCRYPT_KEY, princ_str);
+ return (ERR);
+ }
+
+ entry.key = ekey;
+ entry.salt_type = KRB5_KDB_SALTTYPE_NORMAL;
+ entry.salt_length = 0;
+ entry.salt = 0;
+
+ ret = krb5_db_put_principal(&entry, &nentries);
+ if (ret != 0)
+ com_err(whoami, ret, str_PUT_PRINC, princ_str);
+#ifdef KRB5B4
+ krb5_xfree(ekey.contents);
+#else
+ xfree(ekey.contents);
+#endif
+
+ if (ret) return(ERR);
+
+ printf(str_CREATED_PRINC, whoami, princ_str);
+
+ return(OK);
+}
+
+/*
+ * Function: create_admin_policy_db
+ *
+ * Purpose: Return "garbage" if the caller asks for it.
+ *
+ * Arguments:
+ *
+ * input (input) A null-terminated string,
+ * or NULL.
+ * delay (input/output) The number of seconds the
+ * function should delay before returning.
+ * <return value> (output) A string.
+ *
+ * Requires:
+ *
+ * "input" must either be NULL or point to an address in the
+ * program's address space. "delay" must point to an address in
+ * the program's address space.
+ *
+ * Effects:
+ *
+ * The function first sleeps for approximately the number of
+ * seconds specified in "delay".
+ *
+ * Then, if "input" is non-NULL and points to a null-terminated
+ * string which is equal to "garbage", the function sets "delay"
+ * to 42 and returns a string allocated with malloc(3) containing
+ * "more-garbage".
+ *
+ * If "input" is NULL or does not contain "garbage", the function
+ * returns NULL without modifying "delay".
+ *
+ * If "<return value>" is non-NULL, the caller should deallocate
+ * the string in it (with free(3)) when it is no longer needed.
+ *
+ * Modifies:
+ *
+ * May allocate a new block of memory in the malloc(3) arena.
+ * May change the value in the memory location pointed to by
+ * "delay".
+ */
+
+int create_admin_policy_db()
+{
+ /* We don't have a create/destroy routine, so opening the db and
+ closing it will have to do. */
+ osa_adb_policy_t policy_db = NULL;
+ osa_adb_ret_t ret;
+
+ ret = osa_adb_open_policy(&policy_db, POLICY_DB);
+ if (ret != OSA_ADB_OK) {
+ com_err (whoami, ret, str_CREATING_POLICY_DB);
+ return(-1);
+ }
+
+ /* Should create sample policies here */
+
+ ret = osa_adb_close_policy(policy_db);
+ if (ret != OSA_ADB_OK) {
+ com_err (whoami, ret, str_CLOSING_POLICY_DB);
+ return(-1);
+ }
+
+ printf(str_CREATED_POLICY_DB, whoami);
+
+ return(OK);
+}
+
+/*
+
+ * Function: iterator(ptr, entry)
+ *
+ * Purpose:
+ *
+ * Creates an entry in the Admin database corresponding to the
+ * specified entry in the Kerberos database.
+ *
+ * Arguments:
+ *
+ * ptr (input) Actually of type osa_adb_princ_t,
+ * represents the Admin database in which to
+ * create the principal.
+ * entry (input) The entry in the Kerberos database for
+ * which to create an entry in the Admin
+ * database.
+ *
+ * Requires:
+ *
+ * "ptr" represents a valid, open Admin principal database.
+ * "entry" represents a valid, decoded Kerberos database
+ * principal entry.
+ *
+ * Effects:
+ *
+ * Modifies the Admin principal database by creating a principal
+ * in the database with the same name as "entry" and no other
+ * information.
+ *
+ * Modifies:
+ *
+ * Does not modify any global memory. Modifies the Admin
+ * principal database whose handle is passed into it.
+ */
+
+krb5_error_code
+iterator(ptr, entry)
+krb5_pointer ptr;
+krb5_db_entry *entry;
+{
+ osa_adb_ret_t retval;
+ krb5_error_code retval2;
+ char *princ_str = NULL;
+ osa_princ_ent_rec osa_princ;
+
+ /* Zero the whole struct, and fill in the princ name */
+ memset(&osa_princ, 0, sizeof(osa_princ_ent_rec));
+
+ osa_princ.name = entry->principal;
+ osa_princ.policy = NULL;
+
+ retval = osa_adb_create_princ((osa_adb_princ_t) ptr, &osa_princ);
+ if (retval != OSA_ADB_OK) {
+ if (retval2 = krb5_unparse_name(entry->principal, &princ_str)) {
+ com_err(whoami, retval2, str_UNPARSE_PRINC);
+ }
+ com_err(whoami, retval, str_CREATING_PRINC_ENTRY,
+ (princ_str ? princ_str : str_A_PRINC));
+ if (princ_str) free(princ_str);
+ }
+ return (0);
+}
+
+/*
+ * Function: create_and_populate_admin_princ_db
+ *
+ * Purpose: Return "garbage" if the caller asks for it.
+ *
+ * Arguments:
+ *
+ * input (input) A null-terminated string,
+ * or NULL.
+ * delay (input/output) The number of seconds the
+ * function should delay before returning.
+ * <return value> (output) A string.
+ *
+ * Requires:
+ *
+ * "input" must either be NULL or point to an address in the
+ * program's address space. "delay" must point to an address in
+ * the program's address space.
+ *
+ * Effects:
+ *
+ * The function first sleeps for approximately the number of
+ * seconds specified in "delay".
+ *
+ * Then, if "input" is non-NULL and points to a null-terminated
+ * string which is equal to "garbage", the function sets "delay"
+ * to 42 and returns a string allocated with malloc(3) containing
+ * "more-garbage".
+ *
+ * If "input" is NULL or does not contain "garbage", the function
+ * returns NULL without modifying "delay".
+ *
+ * If "<return value>" is non-NULL, the caller should deallocate
+ * the string in it (with free(3)) when it is no longer needed.
+ *
+ * Modifies:
+ *
+ * May allocate a new block of memory in the malloc(3) arena.
+ * May change the value in the memory location pointed to by
+ * "delay".
+ */
+
+int create_and_populate_admin_princ_db()
+{
+ osa_adb_princ_t princ_db = NULL;
+ osa_adb_ret_t ret;
+
+ /* We don't have a create/destroy routine, so opening the db and
+ closing it will have to do. */
+
+ ret = osa_adb_open_princ(&princ_db, PRINCIPAL_DB);
+ if (ret != OSA_ADB_OK) {
+ com_err (whoami, ret, str_CREATING_PRINC_DB);
+ return(-1);
+ }
+
+ printf(str_CREATED_PRINC_DB, whoami);
+
+ (void) krb5_db_iterate(iterator, princ_db);
+
+ ret = osa_adb_close_princ(princ_db);
+ if (ret != OSA_ADB_OK) {
+ com_err (whoami, ret, str_CLOSING_PRINC_DB);
+ return(-1);
+ }
+
+
+ return(OK);
+}
+
+#endif
diff --git a/src/kadmin/create/configure.in b/src/kadmin/create/configure.in
new file mode 100644
index 000000000..403034263
--- /dev/null
+++ b/src/kadmin/create/configure.in
@@ -0,0 +1,11 @@
+AC_INIT(kdb5_create.c)
+CONFIG_RULES
+AC_PROG_INSTALL
+USE_KADMSRV_LIBRARY
+USE_GSSRPC_LIBRARY
+USE_GSSAPI_LIBRARY
+USE_DYN_LIBRARY
+USE_KDB5_LIBRARY
+KRB5_LIBRARIES
+V5_USE_SHARED_LIB
+V5_AC_OUTPUT_MAKEFILE
diff --git a/src/kadmin/create/kadm5_create.c b/src/kadmin/create/kadm5_create.c
new file mode 100644
index 000000000..33b30ec9c
--- /dev/null
+++ b/src/kadmin/create/kadm5_create.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include "string_table.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <kadm5/adb.h>
+#include <kadm5/admin.h>
+
+#include <krb5.h>
+#include <krb5/kdb.h>
+
+int add_admin_princ(void *handle, krb5_context context,
+ char *name, char *realm, int attrs, int lifetime);
+
+#define ERR 1
+#define OK 0
+
+#define ADMIN_LIFETIME 60*60*3 /* 3 hours */
+#define CHANGEPW_LIFETIME 60*5 /* 5 minutes */
+
+extern char *whoami;
+
+extern krb5_encrypt_block master_encblock;
+extern krb5_keyblock master_keyblock;
+extern krb5_db_entry master_db;
+
+/*
+ * Function: kadm5_create
+ *
+ * Purpose: create admin principals in KDC database
+ *
+ * Arguments: params (r) configuration parameters to use
+ *
+ * Effects: Creates KADM5_ADMIN_SERVICE and KADM5_CHANGEPW_SERVICE
+ * principals in the KDC database and sets their attributes
+ * appropriately.
+ */
+void kadm5_create(kadm5_config_params *params)
+{
+ int retval;
+ void *handle;
+ krb5_context context;
+ FILE *f;
+
+
+ if (retval = krb5_init_context(&context))
+ exit(ERR);
+
+ /*
+ * The lock file has to exist before calling kadm5_init, but
+ * params->admin_lockfile may not be set yet...
+ */
+ if (retval = kadm5_get_config_params(context, NULL, NULL,
+ params, params)) {
+ com_err(whoami, retval, str_INITING_KCONTEXT);
+ exit(1);
+ }
+
+ if (retval = osa_adb_create_policy_db(params)) {
+ com_err(whoami, retval, str_CREATING_POLICY_DB);
+ exit(1);
+ }
+
+ if ((retval = kadm5_init(whoami, NULL, NULL, params,
+ KADM5_STRUCT_VERSION,
+ KADM5_API_VERSION_2,
+ &handle))) {
+ com_err(whoami, retval, str_INITING_KCONTEXT);
+
+ krb5_free_context(context);
+ exit(ERR);
+ }
+
+ retval = add_admin_princs(handle, context, params->realm);
+
+ kadm5_destroy(handle);
+ krb5_free_context(context);
+
+ if (retval)
+ exit(retval);
+
+ exit(0);
+}
+
+/*
+ * Function: build_name_with_realm
+ *
+ * Purpose: concatenate a name and a realm to form a krb5 name
+ *
+ * Arguments:
+ *
+ * name (input) the name
+ * realm (input) the realm
+ *
+ * Returns:
+ *
+ * pointer to name@realm, in allocated memory, or NULL if it
+ * cannot be allocated
+ *
+ * Requires: both strings are null-terminated
+ */
+char *build_name_with_realm(char *name, char *realm)
+{
+ char *n;
+
+ n = (char *) malloc(strlen(name) + strlen(realm) + 2);
+ sprintf(n, "%s@%s", name, realm);
+ return n;
+}
+
+/*
+ * Function: add_admin_princs
+ *
+ * Purpose: create admin principals
+ *
+ * Arguments:
+ *
+ * rseed (input) random seed
+ * realm (input) realm, or NULL for default realm
+ * <return value> (output) status, 0 for success, 1 for serious error
+ *
+ * Requires:
+ *
+ * Effects:
+ *
+ * add_admin_princs creates KADM5_ADMIN_SERVICE,
+ * KADM5_CHANGEPW_SERVICE. If any of these exist a message is
+ * printed. If any of these existing principal do not have the proper
+ * attributes, a warning message is printed.
+ */
+int add_admin_princs(void *handle, krb5_context context, char *realm)
+{
+ krb5_error_code ret = 0;
+
+ if ((ret = add_admin_princ(handle, context,
+ KADM5_ADMIN_SERVICE, realm,
+ KRB5_KDB_DISALLOW_TGT_BASED,
+ ADMIN_LIFETIME)))
+ goto clean_and_exit;
+
+ if ((ret = add_admin_princ(handle, context,
+ KADM5_CHANGEPW_SERVICE, realm,
+ KRB5_KDB_DISALLOW_TGT_BASED |
+ KRB5_KDB_PWCHANGE_SERVICE,
+ CHANGEPW_LIFETIME)))
+ goto clean_and_exit;
+
+clean_and_exit:
+
+ return ret;
+}
+
+/*
+ * Function: add_admin_princ
+ *
+ * Arguments:
+ *
+ * creator (r) principal to use as "mod_by"
+ * rseed (r) seed for random key generator
+ * name (r) principal name
+ * realm (r) realm name for principal
+ * attrs (r) principal's attributes
+ * lifetime (r) principal's max life, or 0
+ * not_unique (r) error message for multiple entries, never used
+ * exists (r) warning message for principal exists
+ * wrong_attrs (r) warning message for wrong attributes
+ *
+ * Returns:
+ *
+ * OK on success
+ * ERR on serious errors
+ *
+ * Effects:
+ *
+ * If the principal is not unique, not_unique is printed (but this
+ * never happens). If the principal exists, then exists is printed
+ * and if the principals attributes != attrs, wrong_attrs is printed.
+ * Otherwise, the principal is created with mod_by creator and
+ * attributes attrs and max life of lifetime (if not zero).
+ */
+
+int add_admin_princ(void *handle, krb5_context context,
+ char *name, char *realm, int attrs, int lifetime)
+{
+ char *fullname;
+ int nprincs;
+ krb5_error_code ret;
+ kadm5_principal_ent_rec ent;
+
+ memset(&ent, 0, sizeof(ent));
+
+ fullname = build_name_with_realm(name, realm);
+ if (ret = krb5_parse_name(context, fullname, &ent.principal)) {
+ com_err(whoami, ret, str_PARSE_NAME);
+ return(ERR);
+ }
+ ent.max_life = lifetime;
+ ent.attributes = attrs;
+
+ if (ret = kadm5_create_principal(handle, &ent,
+ (KADM5_PRINCIPAL |
+ KADM5_MAX_LIFE |
+ KADM5_ATTRIBUTES),
+ "to-be-random")) {
+ if (ret == KADM5_DUP)
+ ret = kadm5_modify_principal(handle, &ent,
+ (KADM5_PRINCIPAL |
+ KADM5_MAX_LIFE |
+ KADM5_ATTRIBUTES));
+
+ if (ret) {
+ com_err(whoami, ret, str_PUT_PRINC, fullname);
+ krb5_free_principal(context, ent.principal);
+ free(fullname);
+ return ERR;
+ }
+ }
+
+ ret = kadm5_randkey_principal(handle, ent.principal, NULL, NULL);
+
+ krb5_free_principal(context, ent.principal);
+ free(fullname);
+
+ if (ret) {
+ com_err(whoami, ret, str_RANDOM_KEY, fullname);
+ return ERR;
+ }
+
+ return OK;
+}
diff --git a/src/kadmin/create/kdb5_create.c b/src/kadmin/create/kdb5_create.c
new file mode 100644
index 000000000..8b167b6b9
--- /dev/null
+++ b/src/kadmin/create/kdb5_create.c
@@ -0,0 +1,536 @@
+/*
+ * admin/create/kdb5_create.c
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * 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 KDC database.
+ */
+
+#include <stdio.h>
+#include <k5-int.h>
+#include <kadm5/admin.h>
+
+enum ap_op {
+ NULL_KEY, /* setup null keys */
+ MASTER_KEY, /* use master key as new key */
+ TGT_KEY /* special handling for tgt key */
+};
+
+krb5_key_salt_tuple def_kslist = { ENCTYPE_DES_CBC_CRC, KRB5_KDB_SALTTYPE_NORMAL };
+
+struct realm_info {
+ krb5_deltat max_life;
+ krb5_deltat max_rlife;
+ krb5_timestamp expiration;
+ krb5_flags flags;
+ krb5_encrypt_block *eblock;
+ krb5_pointer rseed;
+ krb5_int32 nkslist;
+ krb5_key_salt_tuple *kslist;
+} rblock = { /* XXX */
+ KRB5_KDB_MAX_LIFE,
+ KRB5_KDB_MAX_RLIFE,
+ KRB5_KDB_EXPIRATION,
+ KRB5_KDB_DEF_FLAGS,
+ (krb5_encrypt_block *) NULL,
+ (krb5_pointer) NULL,
+ 1,
+ &def_kslist
+};
+
+struct iterate_args {
+ krb5_context ctx;
+ struct realm_info *rblock;
+ krb5_db_entry *dbentp;
+};
+
+static krb5_error_code add_principal
+ PROTOTYPE((krb5_context,
+ krb5_principal,
+ enum ap_op,
+ struct realm_info *));
+
+/*
+ * 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 dbpathname] [-r realmname] [-k enctype]\n\
+\t[-M mkeyname]\n",
+ who);
+ exit(status);
+}
+
+krb5_keyblock master_keyblock;
+krb5_principal master_princ;
+krb5_encrypt_block master_encblock;
+krb5_data master_salt;
+
+krb5_data tgt_princ_entries[] = {
+ {0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME},
+ {0, 0, 0} };
+
+krb5_data db_creator_entries[] = {
+ {0, sizeof("db_creation")-1, "db_creation"} };
+
+/* XXX knows about contents of krb5_principal, and that tgt names
+ are of form TGT/REALM@REALM */
+krb5_principal_data tgt_princ = {
+ 0, /* magic number */
+ {0, 0, 0}, /* krb5_data realm */
+ tgt_princ_entries, /* krb5_data *data */
+ 2, /* int length */
+ KRB5_NT_SRV_INST /* int type */
+};
+
+krb5_principal_data db_create_princ = {
+ 0, /* magic number */
+ {0, 0, 0}, /* krb5_data realm */
+ db_creator_entries, /* krb5_data *data */
+ 1, /* int length */
+ KRB5_NT_SRV_INST /* int type */
+};
+
+char *mkey_password = 0;
+char *whoami;
+
+void
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ extern char *optarg;
+ int optchar;
+
+ krb5_error_code retval;
+ char *dbname = (char *) NULL;
+ char *realm = 0;
+ char *mkey_name = 0;
+ char *mkey_fullname;
+ char *defrealm;
+ char *pw_str = 0;
+ char *keyfile = 0;
+ int pw_size = 0;
+ int enctypedone = 0;
+ int do_stash = 0;
+ krb5_data pwd;
+ krb5_context context;
+ krb5_realm_params *rparams;
+ kadm5_config_params kadm5_params;
+
+ memset(&kadm5_params, 0, sizeof(kadm5_params));
+
+ krb5_init_context(&context);
+ krb5_init_ets(context);
+
+ if (strrchr(argv[0], '/'))
+ argv[0] = strrchr(argv[0], '/')+1;
+ whoami = argv[0];
+
+ kadm5_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
+ kadm5_params.mkey_from_kbd = 1;
+
+ while ((optchar = getopt(argc, argv, "d:r:k:M:e:P:sf:")) != EOF) {
+ switch(optchar) {
+ case 'd': /* set db name */
+ kadm5_params.dbname = dbname = optarg;
+ kadm5_params.mask |= KADM5_CONFIG_DBNAME;
+ break;
+ case 'r':
+ kadm5_params.realm = realm = optarg;
+ kadm5_params.mask |= KADM5_CONFIG_REALM;
+ break;
+ case 'k':
+ if (!krb5_string_to_enctype(optarg, &master_keyblock.enctype)){
+ enctypedone++;
+ kadm5_params.enctype = master_keyblock.enctype;
+ kadm5_params.mask |= KADM5_CONFIG_ENCTYPE;
+ }
+ else
+ com_err(argv[0], 0, "%s is an invalid enctype", optarg);
+ break;
+ case 's':
+ do_stash++;
+ kadm5_params.mkey_from_kbd = 0;
+ break;
+ case 'f':
+ kadm5_params.stash_file = keyfile = optarg;
+ kadm5_params.mask |= KADM5_CONFIG_STASH_FILE;
+ break;
+ case 'M': /* master key name in DB */
+ kadm5_params.mkey_name = mkey_name = optarg;
+ kadm5_params.mask |= KADM5_CONFIG_MKEY_NAME;
+ break;
+ case 'P': /* Only used for testing!!! */
+ mkey_password = optarg;
+ break;
+ case '?':
+ default:
+ usage(argv[0], 1);
+ /*NOTREACHED*/
+ }
+ }
+
+ /*
+ * Attempt to read the KDC profile. If we do, then read appropriate values
+ * from it and augment values supplied on the command line.
+ */
+ if (!(retval = krb5_read_realm_params(context,
+ realm,
+ (char *) NULL,
+ (char *) NULL,
+ &rparams))) {
+ /* Get the value for the database */
+ if (rparams->realm_dbname && !dbname)
+ dbname = strdup(rparams->realm_dbname);
+
+ /* Get the value for the master key name */
+ if (rparams->realm_mkey_name && !mkey_name)
+ mkey_name = strdup(rparams->realm_mkey_name);
+
+ /* Get the value for the master key type */
+ if (rparams->realm_enctype_valid && !enctypedone) {
+ master_keyblock.enctype = rparams->realm_enctype;
+ enctypedone++;
+ }
+
+ /* Get the value for maximum ticket lifetime. */
+ if (rparams->realm_max_life_valid)
+ rblock.max_life = rparams->realm_max_life;
+
+ /* Get the value for maximum renewable ticket lifetime. */
+ if (rparams->realm_max_rlife_valid)
+ rblock.max_rlife = rparams->realm_max_rlife;
+
+ /* Get the value for the default principal expiration */
+ if (rparams->realm_expiration_valid)
+ rblock.expiration = rparams->realm_expiration;
+
+ /* Get the value for the default principal flags */
+ if (rparams->realm_flags_valid)
+ rblock.flags = rparams->realm_flags;
+
+ /* Get the value of the supported key/salt pairs */
+ if (rparams->realm_num_keysalts) {
+ rblock.nkslist = rparams->realm_num_keysalts;
+ rblock.kslist = rparams->realm_keysalts;
+ rparams->realm_num_keysalts = 0;
+ rparams->realm_keysalts = (krb5_key_salt_tuple *) NULL;
+ }
+
+ /* Get the value for the stash file */
+ if (rparams->realm_stash_file && !keyfile)
+ keyfile = strdup(rparams->realm_stash_file);
+
+ krb5_free_realm_params(context, rparams);
+ }
+
+ if (!dbname)
+ dbname = DEFAULT_KDB_FILE;
+
+ if (!enctypedone)
+ master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
+
+ if (!valid_enctype(master_keyblock.enctype)) {
+ char tmp[32];
+ if (krb5_enctype_to_string(master_keyblock.enctype, tmp, sizeof(tmp)))
+ com_err(argv[0], KRB5_PROG_KEYTYPE_NOSUPP,
+ "while setting up enctype %d", master_keyblock.enctype);
+ else
+ com_err(argv[0], KRB5_PROG_KEYTYPE_NOSUPP, tmp);
+ exit(1);
+ }
+
+ krb5_use_enctype(context, &master_encblock, master_keyblock.enctype);
+
+ retval = krb5_db_set_name(context, dbname);
+ if (!retval) retval = EEXIST;
+
+ if (retval == EEXIST || retval == EACCES || retval == EPERM) {
+ /* it exists ! */
+ com_err(argv[0], 0, "The database '%s' appears to already exist",
+ dbname);
+ exit(1);
+ }
+ if (!realm) {
+ if ((retval = krb5_get_default_realm(context, &defrealm))) {
+ com_err(argv[0], retval, "while retrieving default realm name");
+ exit(1);
+ }
+ realm = defrealm;
+ }
+
+ /* assemble & parse the master key name */
+
+ if ((retval = krb5_db_setup_mkey_name(context, mkey_name, realm,
+ &mkey_fullname, &master_princ))) {
+ com_err(argv[0], retval, "while setting up master key name");
+ exit(1);
+ }
+
+ krb5_princ_set_realm_data(context, &db_create_princ, realm);
+ krb5_princ_set_realm_length(context, &db_create_princ, strlen(realm));
+ krb5_princ_set_realm_data(context, &tgt_princ, realm);
+ krb5_princ_set_realm_length(context, &tgt_princ, strlen(realm));
+ krb5_princ_component(context, &tgt_princ,1)->data = realm;
+ krb5_princ_component(context, &tgt_princ,1)->length = strlen(realm);
+
+ printf("Initializing database '%s' for realm '%s',\n\
+master key name '%s'\n",
+ dbname, realm, mkey_fullname);
+
+ if (!mkey_password) {
+ printf("You will be prompted for the database Master Password.\n");
+ printf("It is important that you NOT FORGET this password.\n");
+ fflush(stdout);
+
+ pw_size = 1024;
+ pw_str = malloc(pw_size);
+
+ retval = krb5_read_password(context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2,
+ pw_str, &pw_size);
+ if (retval) {
+ com_err(argv[0], retval, "while reading master key from keyboard");
+ exit(1);
+ }
+ mkey_password = pw_str;
+ }
+
+ pwd.data = mkey_password;
+ pwd.length = strlen(mkey_password);
+ retval = krb5_principal2salt(context, master_princ, &master_salt);
+ if (retval) {
+ com_err(argv[0], retval, "while calculated master key salt");
+ exit(1);
+ }
+ if (retval = krb5_string_to_key(context, &master_encblock,
+ &master_keyblock, &pwd, &master_salt)) {
+ com_err(argv[0], retval, "while transforming master key from password");
+ exit(1);
+ }
+
+ if ((retval = krb5_process_key(context, &master_encblock,
+ &master_keyblock))) {
+ com_err(argv[0], retval, "while processing master key");
+ exit(1);
+ }
+
+ rblock.eblock = &master_encblock;
+ if ((retval = krb5_init_random_key(context, &master_encblock,
+ &master_keyblock, &rblock.rseed))) {
+ com_err(argv[0], retval, "while initializing random key generator");
+ (void) krb5_finish_key(context, &master_encblock);
+ exit(1);
+ }
+ if ((retval = krb5_db_create(context, dbname))) {
+ (void) krb5_finish_key(context, &master_encblock);
+ (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
+ com_err(argv[0], retval, "while creating database '%s'",
+ dbname);
+ exit(1);
+ }
+ if ((retval = krb5_db_set_name(context, dbname))) {
+ (void) krb5_finish_key(context, &master_encblock);
+ (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
+ com_err(argv[0], retval, "while setting active database to '%s'",
+ dbname);
+ exit(1);
+ }
+ if ((retval = krb5_db_init(context))) {
+ (void) krb5_finish_key(context, &master_encblock);
+ (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
+ com_err(argv[0], retval, "while initializing the database '%s'",
+ dbname);
+ exit(1);
+ }
+
+ if ((retval = add_principal(context, master_princ, MASTER_KEY, &rblock)) ||
+ (retval = add_principal(context, &tgt_princ, TGT_KEY, &rblock))) {
+ (void) krb5_db_fini(context);
+ (void) krb5_finish_key(context, &master_encblock);
+ (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
+ com_err(argv[0], retval, "while adding entries to the database");
+ exit(1);
+ }
+ if (do_stash &&
+ ((retval = krb5_db_store_mkey(context, keyfile, master_princ,
+ &master_keyblock)))) {
+ com_err(argv[0], errno, "while storing key");
+ printf("Warning: couldn't stash master key.\n");
+ }
+ /* clean up */
+ (void) krb5_db_fini(context);
+ (void) krb5_finish_key(context, &master_encblock);
+ (void) krb5_finish_random_key(context, &master_encblock, &rblock.rseed);
+ memset((char *)master_keyblock.contents, 0, master_keyblock.length);
+ free(master_keyblock.contents);
+ if (pw_str) {
+ memset(pw_str, 0, pw_size);
+ free(pw_str);
+ }
+ free(master_salt.data);
+
+ kadm5_create(&kadm5_params);
+
+ exit(0);
+
+}
+
+static krb5_error_code
+tgt_keysalt_iterate(ksent, ptr)
+ krb5_key_salt_tuple *ksent;
+ krb5_pointer ptr;
+{
+ krb5_context context;
+ krb5_error_code kret;
+ struct iterate_args *iargs;
+ krb5_keyblock random_keyblock, *key;
+ krb5_int32 ind;
+ krb5_encrypt_block random_encblock;
+ krb5_pointer rseed;
+ krb5_data pwd;
+
+ iargs = (struct iterate_args *) ptr;
+ kret = 0;
+
+ context = iargs->ctx;
+
+ /*
+ * Convert the master key password into a key for this particular
+ * encryption system.
+ */
+ krb5_use_enctype(context, &random_encblock, ksent->ks_enctype);
+ pwd.data = mkey_password;
+ pwd.length = strlen(mkey_password);
+ if (kret = krb5_string_to_key(context, &random_encblock, &random_keyblock,
+ &pwd, &master_salt))
+ return kret;
+ if ((kret = krb5_init_random_key(context, &random_encblock,
+ &random_keyblock, &rseed)))
+ return kret;
+
+ if (!(kret = krb5_dbe_create_key_data(iargs->ctx, iargs->dbentp))) {
+ ind = iargs->dbentp->n_key_data-1;
+ if (!(kret = krb5_random_key(context,
+ &random_encblock, rseed,
+ &key))) {
+ kret = krb5_dbekd_encrypt_key_data(context,
+ iargs->rblock->eblock,
+ key,
+ NULL,
+ 1,
+ &iargs->dbentp->key_data[ind]);
+ krb5_free_keyblock(context, key);
+ }
+ }
+ memset((char *)random_keyblock.contents, 0, random_keyblock.length);
+ free(random_keyblock.contents);
+ (void) krb5_finish_random_key(context, &random_encblock, &rseed);
+ return(kret);
+}
+
+static krb5_error_code
+add_principal(context, princ, op, pblock)
+ krb5_context context;
+ krb5_principal princ;
+ enum ap_op op;
+ struct realm_info *pblock;
+{
+ krb5_error_code retval;
+ krb5_db_entry entry;
+
+ krb5_timestamp now;
+ struct iterate_args iargs;
+
+ int nentries = 1;
+
+ memset((char *) &entry, 0, sizeof(entry));
+
+ entry.len = KRB5_KDB_V1_BASE_LENGTH;
+ entry.attributes = pblock->flags;
+ entry.max_life = pblock->max_life;
+ entry.max_renewable_life = pblock->max_rlife;
+ entry.expiration = pblock->expiration;
+
+ if ((retval = krb5_copy_principal(context, princ, &entry.princ)))
+ goto error_out;
+
+ if ((retval = krb5_timeofday(context, &now)))
+ goto error_out;
+
+ if ((retval = krb5_dbe_update_mod_princ_data(context, &entry,
+ now, &db_create_princ)))
+ goto error_out;
+
+ switch (op) {
+ case MASTER_KEY:
+ if ((entry.key_data=(krb5_key_data*)malloc(sizeof(krb5_key_data)))
+ == NULL)
+ goto error_out;
+ memset((char *) entry.key_data, 0, sizeof(krb5_key_data));
+ entry.n_key_data = 1;
+
+ entry.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+ if ((retval = krb5_dbekd_encrypt_key_data(context, pblock->eblock,
+ &master_keyblock, NULL,
+ 1, entry.key_data)))
+ return retval;
+ break;
+ case TGT_KEY:
+ iargs.ctx = context;
+ iargs.rblock = pblock;
+ iargs.dbentp = &entry;
+ /*
+ * Iterate through the key/salt list, ignoring salt types.
+ */
+ if ((retval = krb5_keysalt_iterate(pblock->kslist,
+ pblock->nkslist,
+ 1,
+ tgt_keysalt_iterate,
+ (krb5_pointer) &iargs)))
+ return retval;
+ break;
+ case NULL_KEY:
+ return EOPNOTSUPP;
+ default:
+ break;
+ }
+
+ retval = krb5_db_put_principal(context, &entry, &nentries);
+
+error_out:;
+ krb5_dbe_free_contents(context, &entry);
+ return retval;
+}
diff --git a/src/kadmin/create/string_table.c b/src/kadmin/create/string_table.c
new file mode 100644
index 000000000..b9f86a363
--- /dev/null
+++ b/src/kadmin/create/string_table.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+/* String table of messages for kadm5_create */
+
+char *str_INITING_KCONTEXT = "while initializing the kerberos context";
+
+char *str_PARSE_NAME = "while parsing admin principal name.";
+
+char *str_HISTORY_PARSE_NAME = "while parsing admin history principal name.";
+
+char *str_ADMIN_PRINC_EXISTS = "Warning! Admin principal already exists.";
+
+char *str_CHANGEPW_PRINC_EXISTS = "Warning! Changepw principal already exists.";
+
+char *str_HISTORY_PRINC_EXISTS = "Warning! Admin history principal already exists.";
+
+char *str_ADMIN_PRINC_WRONG_ATTRS =
+ "Warning! Admin principal has incorrect attributes.\n"
+ "\tDISALLOW_TGT should be set, and max_life should be three hours.\n"
+ "\tThis program will leave them as-is, but beware!.";
+
+char *str_CHANGEPW_PRINC_WRONG_ATTRS =
+ "Warning! Changepw principal has incorrect attributes.\n"
+ "\tDISALLOW_TGT and PW_CHANGE_SERVICE should both be set, and "
+ "max_life should be five minutes.\n"
+ "\tThis program will leave them as-is, but beware!.";
+
+char *str_HISTORY_PRINC_WRONG_ATTRS =
+ "Warning! Admin history principal has incorrect attributes.\n"
+ "\tDISALLOW_ALL_TIX should be set.\n"
+ "\tThis program will leave it as-is, but beware!.";
+
+char *str_CREATED_PRINC_DB =
+ "%s: Admin principal database created (or it already existed).\n"; /* whoami */
+
+char *str_CREATED_POLICY_DB =
+ "%s: Admin policy database created (or it already existed).\n"; /* whoami */
+
+char *str_RANDOM_KEY =
+ "while calling random key for %s."; /* principal name */
+
+char *str_ENCRYPT_KEY =
+ "while calling encrypt key for %s."; /* principal name */
+
+char *str_PUT_PRINC =
+ "while calling storing %s in Kerberos database."; /* principal name */
+
+char *str_CREATING_POLICY_DB = "while creating/opening admin policy database.";
+
+char *str_CLOSING_POLICY_DB = "while closing admin policy database.";
+
+char *str_CREATING_PRINC_DB = "while creating/opening admin principal database.";
+
+char *str_CLOSING_PRINC_DB = "while closing admin principal database.";
+
+char *str_CREATING_PRINC_ENTRY =
+ "while creating admin principal database entry for %s."; /* princ_name */
+
+char *str_A_PRINC = "a principal";
+
+char *str_UNPARSE_PRINC = "while unparsing principal.";
+
+char *str_CREATED_PRINC = "%s: Created %s principal.\n"; /* whoami, princ_name */
+
+char *str_INIT_KDB = "while initializing kdb.";
+
+char *str_NO_KDB =
+"while initializing kdb.\nThe Kerberos KDC database needs to exist in /krb5.\n\
+If you haven't run kdb5_create you need to do so before running this command.";
+
+
+char *str_INIT_RANDOM_KEY = "while initializing random key generator.";
+
+char *str_TOO_MANY_ADMIN_PRINC =
+ "while fetching admin princ. Can only have one admin principal.";
+
+char *str_TOO_MANY_CHANGEPW_PRINC =
+ "while fetching changepw princ. Can only have one changepw principal.";
+
+char *str_TOO_MANY_HIST_PRINC =
+ "while fetching history princ. Can only have one history principal.";
+
+char *str_WHILE_DESTROYING_ADMIN_SESSION = "while closing session with admin server and destroying tickets.";
diff --git a/src/kadmin/create/string_table.h b/src/kadmin/create/string_table.h
new file mode 100644
index 000000000..e8cb45367
--- /dev/null
+++ b/src/kadmin/create/string_table.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef _OVSEC_ADM_STRINGS_
+
+extern char *str_INITING_KCONTEXT;
+extern char *str_PARSE_NAME;
+extern char *str_HISTORY_PARSE_NAME;
+extern char *str_ADMIN_PRINC_EXISTS;
+extern char *str_CHANGEPW_PRINC_EXISTS;
+extern char *str_HISTORY_PRINC_EXISTS;
+extern char *str_ADMIN_PRINC_WRONG_ATTRS;
+extern char *str_CHANGEPW_PRINC_WRONG_ATTRS;
+extern char *str_HISTORY_PRINC_WRONG_ATTRS;
+extern char *str_CREATED_PRINC_DB;
+extern char *str_CREATED_POLICY_DB;
+extern char *str_RANDOM_KEY;
+extern char *str_ENCRYPT_KEY;
+extern char *str_PUT_PRINC;
+extern char *str_CREATING_POLICY_DB;
+extern char *str_CLOSING_POLICY_DB;
+extern char *str_CREATING_PRINC_DB;
+extern char *str_CLOSING_PRINC_DB;
+extern char *str_CREATING_PRINC_ENTRY;
+extern char *str_A_PRINC;
+extern char *str_UNPARSE_PRINC;
+extern char *str_CREATED_PRINC;
+extern char *str_INIT_KDB;
+extern char *str_NO_KDB;
+extern char *str_INIT_RANDOM_KEY;
+extern char *str_TOO_MANY_ADMIN_PRINC;
+extern char *str_TOO_MANY_CHANGEPW_PRINC;
+extern char *str_TOO_MANY_HIST_PRINC;
+extern char *str_WHILE_DESTROYING_ADMIN_SESSION;
+
+#endif /* _OVSEC_ADM_STRINGS_ */