xref: /onnv-gate/usr/src/cmd/krb5/kadmin/dbutil/kdb5_create.c (revision 8092:19771b16f0a8)
10Sstevel@tonic-gate /*
2*8092SMark.Phalan@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate /*
70Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  *	Openvision retains the copyright to derivative works of
100Sstevel@tonic-gate  *	this source code.  Do *NOT* create a derivative of this
110Sstevel@tonic-gate  *	source code before consulting with your legal department.
120Sstevel@tonic-gate  *	Do *NOT* integrate *ANY* of this source code into another
130Sstevel@tonic-gate  *	product before consulting with your legal department.
140Sstevel@tonic-gate  *
150Sstevel@tonic-gate  *	For further information, read the top-level Openvision
160Sstevel@tonic-gate  *	copyright which is contained in the top-level MIT Kerberos
170Sstevel@tonic-gate  *	copyright.
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
200Sstevel@tonic-gate  *
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate 
230Sstevel@tonic-gate 
240Sstevel@tonic-gate /*
250Sstevel@tonic-gate  * admin/create/kdb5_create.c
260Sstevel@tonic-gate  *
270Sstevel@tonic-gate  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
280Sstevel@tonic-gate  * All Rights Reserved.
290Sstevel@tonic-gate  *
300Sstevel@tonic-gate  * Export of this software from the United States of America may
310Sstevel@tonic-gate  *   require a specific license from the United States Government.
320Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
330Sstevel@tonic-gate  *   export to obtain such a license before exporting.
340Sstevel@tonic-gate  *
350Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
360Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
370Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
380Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
390Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
400Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
410Sstevel@tonic-gate  * to distribution of the software without specific, written prior
420Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
430Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
440Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
450Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
460Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
470Sstevel@tonic-gate  * or implied warranty.
480Sstevel@tonic-gate  *
490Sstevel@tonic-gate  *
500Sstevel@tonic-gate  * Generate (from scratch) a Kerberos KDC database.
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate 
530Sstevel@tonic-gate /*
540Sstevel@tonic-gate  *  Yes, I know this is a hack, but we need admin.h without including the
550Sstevel@tonic-gate  *  rpc.h header. Additionally, our rpc.h header brings in
560Sstevel@tonic-gate  *  a des.h header which causes other problems.
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate #define	_RPC_RPC_H
590Sstevel@tonic-gate 
600Sstevel@tonic-gate #include <stdio.h>
610Sstevel@tonic-gate #include <k5-int.h>
624960Swillf #include <krb5/kdb.h>
634960Swillf #include <kadm5/server_internal.h>
640Sstevel@tonic-gate #include <kadm5/admin.h>
650Sstevel@tonic-gate #include <rpc/types.h>
660Sstevel@tonic-gate #include <rpc/xdr.h>
670Sstevel@tonic-gate #include <libintl.h>
680Sstevel@tonic-gate #include "kdb5_util.h"
690Sstevel@tonic-gate 
700Sstevel@tonic-gate enum ap_op {
710Sstevel@tonic-gate     NULL_KEY,				/* setup null keys */
720Sstevel@tonic-gate     MASTER_KEY,				/* use master key as new key */
730Sstevel@tonic-gate     TGT_KEY				/* special handling for tgt key */
740Sstevel@tonic-gate };
750Sstevel@tonic-gate 
762881Smp153739 krb5_key_salt_tuple def_kslist = { ENCTYPE_DES_CBC_CRC, KRB5_KDB_SALTTYPE_NORMAL };
770Sstevel@tonic-gate 
780Sstevel@tonic-gate struct realm_info {
790Sstevel@tonic-gate     krb5_deltat max_life;
800Sstevel@tonic-gate     krb5_deltat max_rlife;
810Sstevel@tonic-gate     krb5_timestamp expiration;
820Sstevel@tonic-gate     krb5_flags flags;
830Sstevel@tonic-gate     krb5_keyblock *key;
840Sstevel@tonic-gate     krb5_int32 nkslist;
850Sstevel@tonic-gate     krb5_key_salt_tuple *kslist;
860Sstevel@tonic-gate } rblock = { /* XXX */
870Sstevel@tonic-gate     KRB5_KDB_MAX_LIFE,
880Sstevel@tonic-gate     KRB5_KDB_MAX_RLIFE,
890Sstevel@tonic-gate     KRB5_KDB_EXPIRATION,
900Sstevel@tonic-gate     KRB5_KDB_DEF_FLAGS,
910Sstevel@tonic-gate     (krb5_keyblock *) NULL,
920Sstevel@tonic-gate     1,
930Sstevel@tonic-gate     &def_kslist
940Sstevel@tonic-gate };
950Sstevel@tonic-gate 
960Sstevel@tonic-gate struct iterate_args {
970Sstevel@tonic-gate     krb5_context	ctx;
980Sstevel@tonic-gate     struct realm_info	*rblock;
990Sstevel@tonic-gate     krb5_db_entry	*dbentp;
1000Sstevel@tonic-gate };
1010Sstevel@tonic-gate 
1022881Smp153739 static krb5_error_code add_principal
1032881Smp153739 	(krb5_context,
1042881Smp153739 	 krb5_principal,
1052881Smp153739 	 enum ap_op,
1062881Smp153739 	 struct realm_info *,
1070Sstevel@tonic-gate 		krb5_keyblock *);
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate /*
1100Sstevel@tonic-gate  * Steps in creating a database:
1110Sstevel@tonic-gate  *
1120Sstevel@tonic-gate  * 1) use the db calls to open/create a new database
1130Sstevel@tonic-gate  *
1140Sstevel@tonic-gate  * 2) get a realm name for the new db
1150Sstevel@tonic-gate  *
1160Sstevel@tonic-gate  * 3) get a master password for the new db; convert to an encryption key.
1170Sstevel@tonic-gate  *
1180Sstevel@tonic-gate  * 4) create various required entries in the database
1190Sstevel@tonic-gate  *
1200Sstevel@tonic-gate  * 5) close & exit
1210Sstevel@tonic-gate  */
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate extern krb5_principal master_princ;
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate krb5_data tgt_princ_entries[] = {
1260Sstevel@tonic-gate 	{0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME},
1270Sstevel@tonic-gate 	{0, 0, 0} };
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate krb5_data db_creator_entries[] = {
1300Sstevel@tonic-gate 	{0, sizeof("db_creation")-1, "db_creation"} };
1310Sstevel@tonic-gate 
1322881Smp153739 /* XXX knows about contents of krb5_principal, and that tgt names
1332881Smp153739  are of form TGT/REALM@REALM */
1340Sstevel@tonic-gate krb5_principal_data tgt_princ = {
1350Sstevel@tonic-gate         0,					/* magic number */
1360Sstevel@tonic-gate 	{0, 0, 0},				/* krb5_data realm */
1370Sstevel@tonic-gate 	tgt_princ_entries,			/* krb5_data *data */
1380Sstevel@tonic-gate 	2,					/* int length */
1390Sstevel@tonic-gate 	KRB5_NT_SRV_INST			/* int type */
1400Sstevel@tonic-gate };
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate krb5_principal_data db_create_princ = {
1430Sstevel@tonic-gate         0,					/* magic number */
1440Sstevel@tonic-gate 	{0, 0, 0},				/* krb5_data realm */
1450Sstevel@tonic-gate 	db_creator_entries,			/* krb5_data *data */
1460Sstevel@tonic-gate 	1,					/* int length */
1470Sstevel@tonic-gate 	KRB5_NT_SRV_INST			/* int type */
1480Sstevel@tonic-gate };
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate extern char *mkey_password;
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate extern char *progname;
1530Sstevel@tonic-gate extern int exit_status;
1540Sstevel@tonic-gate extern kadm5_config_params global_params;
1550Sstevel@tonic-gate extern krb5_context util_context;
1560Sstevel@tonic-gate 
kdb5_create(argc,argv)1572881Smp153739 void kdb5_create(argc, argv)
1580Sstevel@tonic-gate    int argc;
1590Sstevel@tonic-gate    char *argv[];
1600Sstevel@tonic-gate {
1610Sstevel@tonic-gate     int optchar;
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate     krb5_error_code retval;
1640Sstevel@tonic-gate     char *mkey_fullname;
1650Sstevel@tonic-gate     char *pw_str = 0;
1660Sstevel@tonic-gate     unsigned int pw_size = 0;
1670Sstevel@tonic-gate     int do_stash = 0;
1680Sstevel@tonic-gate     krb5_data pwd, seed;
1690Sstevel@tonic-gate     kdb_log_context *log_ctx;
1700Sstevel@tonic-gate     krb5_keyblock mkey;
1710Sstevel@tonic-gate     krb5_data master_salt = { 0, NULL };
172*8092SMark.Phalan@Sun.COM 
173*8092SMark.Phalan@Sun.COM     /* Solaris Kerberos */
174*8092SMark.Phalan@Sun.COM     (void) memset(&mkey, 0, sizeof (mkey));
175*8092SMark.Phalan@Sun.COM 
176*8092SMark.Phalan@Sun.COM /* Solaris Kerberos */
177*8092SMark.Phalan@Sun.COM #if 0
1780Sstevel@tonic-gate     if (strrchr(argv[0], '/'))
1790Sstevel@tonic-gate 	argv[0] = strrchr(argv[0], '/')+1;
180*8092SMark.Phalan@Sun.COM #endif
1810Sstevel@tonic-gate     while ((optchar = getopt(argc, argv, "s")) != -1) {
1820Sstevel@tonic-gate 	switch(optchar) {
1830Sstevel@tonic-gate 	case 's':
1840Sstevel@tonic-gate 	    do_stash++;
1850Sstevel@tonic-gate 	    break;
1860Sstevel@tonic-gate 	case 'h':
1874960Swillf 	    if (!add_db_arg("hash=true")) {
1884960Swillf 		com_err(progname, ENOMEM, "while parsing command arguments\n");
1894960Swillf 		exit(1);
1904960Swillf 	    }
1914960Swillf 	    break;
1920Sstevel@tonic-gate 	case '?':
1930Sstevel@tonic-gate 	default:
1940Sstevel@tonic-gate 	    usage();
1950Sstevel@tonic-gate 	    return;
1960Sstevel@tonic-gate 	}
1970Sstevel@tonic-gate     }
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate     rblock.max_life = global_params.max_life;
2000Sstevel@tonic-gate     rblock.max_rlife = global_params.max_rlife;
2010Sstevel@tonic-gate     rblock.expiration = global_params.expiration;
2020Sstevel@tonic-gate     rblock.flags = global_params.flags;
2030Sstevel@tonic-gate     rblock.nkslist = global_params.num_keysalts;
2040Sstevel@tonic-gate     rblock.kslist = global_params.keysalts;
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate     log_ctx = util_context->kdblog_context;
2070Sstevel@tonic-gate 
2082881Smp153739 /* SUNW14resync XXX */
2092881Smp153739 #if 0
2102881Smp153739     printf ("Loading random data\n");
2112881Smp153739     retval = krb5_c_random_os_entropy (util_context, 1, NULL);
2122881Smp153739     if (retval) {
213*8092SMark.Phalan@Sun.COM       /* Solaris Kerberos */
214*8092SMark.Phalan@Sun.COM       com_err (progname, retval, "Loading random data");
2152881Smp153739       exit_status++; return;
2162881Smp153739     }
2172881Smp153739 #endif
2180Sstevel@tonic-gate     /* assemble & parse the master key name */
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate     if ((retval = krb5_db_setup_mkey_name(util_context,
2210Sstevel@tonic-gate 					  global_params.mkey_name,
2220Sstevel@tonic-gate 					  global_params.realm,
2230Sstevel@tonic-gate 					  &mkey_fullname, &master_princ))) {
224*8092SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
225*8092SMark.Phalan@Sun.COM 	com_err(progname, retval,
2260Sstevel@tonic-gate 			gettext("while setting up master key name"));
2272881Smp153739 	exit_status++; return;
2280Sstevel@tonic-gate     }
2292881Smp153739 
2302881Smp153739     krb5_princ_set_realm_data(util_context, &db_create_princ, global_params.realm);
2312881Smp153739     krb5_princ_set_realm_length(util_context, &db_create_princ, strlen(global_params.realm));
2322881Smp153739     krb5_princ_set_realm_data(util_context, &tgt_princ, global_params.realm);
2332881Smp153739     krb5_princ_set_realm_length(util_context, &tgt_princ, strlen(global_params.realm));
2342881Smp153739     krb5_princ_component(util_context, &tgt_princ,1)->data = global_params.realm;
2352881Smp153739     krb5_princ_component(util_context, &tgt_princ,1)->length = strlen(global_params.realm);
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	printf(gettext("Initializing database '%s' for realm '%s',\n"
2380Sstevel@tonic-gate 			"master key name '%s'\n"),
2390Sstevel@tonic-gate 	   global_params.dbname, global_params.realm, mkey_fullname);
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate     if (!mkey_password) {
2420Sstevel@tonic-gate 	printf(gettext("You will be prompted for the "
2430Sstevel@tonic-gate 			"database Master Password.\n"));
2440Sstevel@tonic-gate 	printf(gettext("It is important that you NOT FORGET this password.\n"));
2450Sstevel@tonic-gate 	fflush(stdout);
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	pw_size = 1024;
2480Sstevel@tonic-gate 	pw_str = malloc(pw_size);
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	retval = krb5_read_password(util_context,
2511692Ssemery 			    gettext("Enter KDC database master key"),
2520Sstevel@tonic-gate 			    gettext("Re-enter KDC database "
2531692Ssemery 				    "master key to verify"),
2540Sstevel@tonic-gate 			    pw_str, &pw_size);
2550Sstevel@tonic-gate 	if (retval) {
256*8092SMark.Phalan@Sun.COM 	    /* Solaris Kerberos */
257*8092SMark.Phalan@Sun.COM 	    com_err(progname, retval,
2580Sstevel@tonic-gate 		    gettext("while reading master key from keyboard"));
2592881Smp153739 	    exit_status++; return;
2600Sstevel@tonic-gate 	}
2610Sstevel@tonic-gate 	mkey_password = pw_str;
2620Sstevel@tonic-gate     }
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate     pwd.data = mkey_password;
2650Sstevel@tonic-gate     pwd.length = strlen(mkey_password);
2660Sstevel@tonic-gate     retval = krb5_principal2salt(util_context, master_princ, &master_salt);
2670Sstevel@tonic-gate     if (retval) {
268*8092SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
269*8092SMark.Phalan@Sun.COM 	com_err(progname, retval,
2700Sstevel@tonic-gate 		gettext("while calculated master key salt"));
2710Sstevel@tonic-gate 	exit_status++;
2720Sstevel@tonic-gate 	goto cleanup;
2730Sstevel@tonic-gate     }
2740Sstevel@tonic-gate 
2752881Smp153739     retval = krb5_c_string_to_key(util_context, global_params.enctype,
2762881Smp153739 				  &pwd, &master_salt, &mkey);
2772881Smp153739     if (retval) {
278*8092SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
279*8092SMark.Phalan@Sun.COM 	com_err(progname, retval,
2800Sstevel@tonic-gate 	    gettext("while transforming master key from password"));
2810Sstevel@tonic-gate 	exit_status++;
2820Sstevel@tonic-gate 	goto cleanup;
2830Sstevel@tonic-gate     }
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate     retval = krb5_copy_keyblock(util_context, &mkey, &rblock.key);
2860Sstevel@tonic-gate     if (retval) {
287*8092SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
288*8092SMark.Phalan@Sun.COM 	com_err(progname, retval, gettext("while copying master key"));
2890Sstevel@tonic-gate 	exit_status++;
2900Sstevel@tonic-gate 	goto cleanup;
2910Sstevel@tonic-gate     }
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate     seed.length = mkey.length;
2940Sstevel@tonic-gate     seed.data = (char *)mkey.contents;
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate     if ((retval = krb5_c_random_seed(util_context, &seed))) {
297*8092SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
298*8092SMark.Phalan@Sun.COM 	com_err(progname, retval,
2990Sstevel@tonic-gate 		gettext("while initializing random key generator"));
3000Sstevel@tonic-gate 	exit_status++;
3010Sstevel@tonic-gate 	goto cleanup;
3020Sstevel@tonic-gate     }
3034960Swillf     if ((retval = krb5_db_create(util_context, db5util_db_args))) {
304*8092SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
305*8092SMark.Phalan@Sun.COM 	com_err(progname, retval,
3060Sstevel@tonic-gate 		gettext("while creating database '%s'"),
3070Sstevel@tonic-gate 		global_params.dbname);
3080Sstevel@tonic-gate 	exit_status++;
3090Sstevel@tonic-gate 	goto cleanup;
3100Sstevel@tonic-gate     }
3114960Swillf #if 0 /************** Begin IFDEF'ed OUT *******************************/
3120Sstevel@tonic-gate     if (retval = krb5_db_fini(util_context)) {
313*8092SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
314*8092SMark.Phalan@Sun.COM 	com_err(progname, retval,
3150Sstevel@tonic-gate 		gettext("while closing current database"));
3160Sstevel@tonic-gate 	exit_status++;
3170Sstevel@tonic-gate 	goto cleanup;
3180Sstevel@tonic-gate     }
3190Sstevel@tonic-gate     if ((retval = krb5_db_set_name(util_context, global_params.dbname))) {
320*8092SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
321*8092SMark.Phalan@Sun.COM 	com_err(progname, retval,
3220Sstevel@tonic-gate 		gettext("while setting active database to '%s'"),
3230Sstevel@tonic-gate                global_params.dbname);
3240Sstevel@tonic-gate 	exit_status++;
3250Sstevel@tonic-gate 	goto cleanup;
3260Sstevel@tonic-gate     }
3270Sstevel@tonic-gate     if ((retval = krb5_db_init(util_context))) {
328*8092SMark.Phalan@Sun.COM 	com_err(progname, retval,
3290Sstevel@tonic-gate 		gettext("while initializing the database '%s'"),
3300Sstevel@tonic-gate 	global_params.dbname);
3310Sstevel@tonic-gate 	exit_status++;
3320Sstevel@tonic-gate 	goto cleanup;
3330Sstevel@tonic-gate     }
3344960Swillf #endif /**************** END IFDEF'ed OUT *******************************/
3350Sstevel@tonic-gate 
3364960Swillf     /* Solaris Kerberos: for iprop */
3370Sstevel@tonic-gate     if (log_ctx && log_ctx->iproprole) {
3380Sstevel@tonic-gate 	if (retval = ulog_map(util_context, &global_params, FKCOMMAND)) {
339*8092SMark.Phalan@Sun.COM 		/* Solaris Kerberos */
340*8092SMark.Phalan@Sun.COM 		com_err(progname, retval,
3410Sstevel@tonic-gate 			gettext("while creating update log"));
3420Sstevel@tonic-gate 		exit_status++;
3430Sstevel@tonic-gate 		goto cleanup;
3440Sstevel@tonic-gate 	}
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	/*
3470Sstevel@tonic-gate 	 * We're reinitializing the update log in case one already
3480Sstevel@tonic-gate 	 * existed, but this should never happen.
3490Sstevel@tonic-gate 	 */
3500Sstevel@tonic-gate 	(void) memset(log_ctx->ulog, 0, sizeof (kdb_hlog_t));
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	log_ctx->ulog->kdb_hmagic = KDB_HMAGIC;
3530Sstevel@tonic-gate 	log_ctx->ulog->db_version_num = KDB_VERSION;
3540Sstevel@tonic-gate 	log_ctx->ulog->kdb_state = KDB_STABLE;
3550Sstevel@tonic-gate 	log_ctx->ulog->kdb_block = ULOG_BLOCK;
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	/*
3580Sstevel@tonic-gate 	 * Since we're creating a new db we shouldn't worry about
3590Sstevel@tonic-gate 	 * adding the initial principals since any slave might as well
3600Sstevel@tonic-gate 	 * do full resyncs from this newly created db.
3610Sstevel@tonic-gate 	 */
3620Sstevel@tonic-gate 	log_ctx->iproprole = IPROP_NULL;
3630Sstevel@tonic-gate     }
3640Sstevel@tonic-gate 
3654960Swillf     if ((retval = add_principal(util_context, master_princ, MASTER_KEY, &rblock, &mkey)) ||
3664960Swillf 	(retval = add_principal(util_context, &tgt_princ, TGT_KEY, &rblock, &mkey))) {
3670Sstevel@tonic-gate 	(void) krb5_db_fini(util_context);
368*8092SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
369*8092SMark.Phalan@Sun.COM 	com_err(progname, retval, gettext("while adding entries to the database"));
3700Sstevel@tonic-gate 	exit_status++;
3710Sstevel@tonic-gate 	goto cleanup;
3720Sstevel@tonic-gate     }
3730Sstevel@tonic-gate     /*
3740Sstevel@tonic-gate      * Always stash the master key so kadm5_create does not prompt for
3750Sstevel@tonic-gate      * it; delete the file below if it was not requested.  DO NOT EXIT
3760Sstevel@tonic-gate      * BEFORE DELETING THE KEYFILE if do_stash is not set.
3770Sstevel@tonic-gate      */
3784960Swillf     retval = krb5_db_store_master_key(util_context,
3794960Swillf 				      global_params.stash_file,
3804960Swillf 				      master_princ,
3814960Swillf 				      &mkey,
3824960Swillf 				      mkey_password);
3834960Swillf 
3842881Smp153739     if (retval) {
385*8092SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
386*8092SMark.Phalan@Sun.COM 	com_err(progname, errno, gettext("while storing key"));
3870Sstevel@tonic-gate 	printf(gettext("Warning: couldn't stash master key.\n"));
3880Sstevel@tonic-gate     }
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate     if (pw_str)
3910Sstevel@tonic-gate 	memset(pw_str, 0, pw_size);
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate     if (kadm5_create(&global_params)) {
3942881Smp153739 	 if (!do_stash) unlink(global_params.stash_file);
3952881Smp153739 	 exit_status++;
3962881Smp153739 	 goto cleanup;
3970Sstevel@tonic-gate     }
3982881Smp153739     if (!do_stash) unlink(global_params.stash_file);
3990Sstevel@tonic-gate 
4004960Swillf /* Solaris Kerberos: deal with master_keyblock in better way */
4010Sstevel@tonic-gate cleanup:
4020Sstevel@tonic-gate     if (pw_str) {
4030Sstevel@tonic-gate 	if (mkey_password == pw_str)
4040Sstevel@tonic-gate 		mkey_password = NULL;
4050Sstevel@tonic-gate 	free(pw_str);
4060Sstevel@tonic-gate     }
4070Sstevel@tonic-gate     if (master_salt.data)
4080Sstevel@tonic-gate 	free(master_salt.data);
4094621Ssemery     krb5_free_keyblock(util_context, rblock.key);
4100Sstevel@tonic-gate     krb5_free_keyblock_contents(util_context, &mkey);
4110Sstevel@tonic-gate     (void) krb5_db_fini(util_context);
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate     return;
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate static krb5_error_code
tgt_keysalt_iterate(ksent,ptr)4170Sstevel@tonic-gate tgt_keysalt_iterate(ksent, ptr)
4180Sstevel@tonic-gate     krb5_key_salt_tuple	*ksent;
4190Sstevel@tonic-gate     krb5_pointer	ptr;
4200Sstevel@tonic-gate {
4210Sstevel@tonic-gate     krb5_context	context;
4220Sstevel@tonic-gate     krb5_error_code	kret;
4230Sstevel@tonic-gate     struct iterate_args	*iargs;
4240Sstevel@tonic-gate     krb5_keyblock	key;
4250Sstevel@tonic-gate     krb5_int32		ind;
4260Sstevel@tonic-gate     krb5_data	pwd;
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate     iargs = (struct iterate_args *) ptr;
4290Sstevel@tonic-gate     kret = 0;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate     context = iargs->ctx;
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate     /*
4340Sstevel@tonic-gate      * Convert the master key password into a key for this particular
4350Sstevel@tonic-gate      * encryption system.
4360Sstevel@tonic-gate      */
4370Sstevel@tonic-gate     pwd.data = mkey_password;
4380Sstevel@tonic-gate     pwd.length = strlen(mkey_password);
4392881Smp153739     kret = krb5_c_random_seed(context, &pwd);
4402881Smp153739     if (kret)
4410Sstevel@tonic-gate 	return kret;
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate     if (!(kret = krb5_dbe_create_key_data(iargs->ctx, iargs->dbentp))) {
4440Sstevel@tonic-gate 	ind = iargs->dbentp->n_key_data-1;
4450Sstevel@tonic-gate 	if (!(kret = krb5_c_make_random_key(context, ksent->ks_enctype,
4460Sstevel@tonic-gate 					    &key))) {
4470Sstevel@tonic-gate 	    kret = krb5_dbekd_encrypt_key_data(context,
4480Sstevel@tonic-gate 					       iargs->rblock->key,
4490Sstevel@tonic-gate 					       &key,
4500Sstevel@tonic-gate 					       NULL,
4510Sstevel@tonic-gate 					       1,
4520Sstevel@tonic-gate 					       &iargs->dbentp->key_data[ind]);
4530Sstevel@tonic-gate 	    krb5_free_keyblock_contents(context, &key);
4540Sstevel@tonic-gate 	}
4550Sstevel@tonic-gate     }
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate     return(kret);
4580Sstevel@tonic-gate }
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate static krb5_error_code
add_principal(context,princ,op,pblock,mkey)4612881Smp153739 add_principal(context, princ, op, pblock, mkey)
4622881Smp153739     krb5_context context;
4632881Smp153739     krb5_principal princ;
4642881Smp153739     enum ap_op op;
4652881Smp153739     struct realm_info *pblock;
4662881Smp153739     krb5_keyblock *mkey;
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate     krb5_error_code 	  retval;
4690Sstevel@tonic-gate     krb5_db_entry 	  entry;
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate     krb5_timestamp	  now;
4720Sstevel@tonic-gate     struct iterate_args	  iargs;
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate     int			  nentries = 1;
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate     memset((char *) &entry, 0, sizeof(entry));
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate     entry.len = KRB5_KDB_V1_BASE_LENGTH;
4790Sstevel@tonic-gate     entry.attributes = pblock->flags;
4800Sstevel@tonic-gate     entry.max_life = pblock->max_life;
4810Sstevel@tonic-gate     entry.max_renewable_life = pblock->max_rlife;
4820Sstevel@tonic-gate     entry.expiration = pblock->expiration;
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate     if ((retval = krb5_copy_principal(context, princ, &entry.princ)))
4850Sstevel@tonic-gate 	goto error_out;
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate     if ((retval = krb5_timeofday(context, &now)))
4880Sstevel@tonic-gate 	goto error_out;
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate     if ((retval = krb5_dbe_update_mod_princ_data(context, &entry,
4910Sstevel@tonic-gate 						 now, &db_create_princ)))
4920Sstevel@tonic-gate 	goto error_out;
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate     switch (op) {
4950Sstevel@tonic-gate     case MASTER_KEY:
4962881Smp153739 	if ((entry.key_data=(krb5_key_data*)malloc(sizeof(krb5_key_data)))
4972881Smp153739 	    == NULL)
4980Sstevel@tonic-gate 	    goto error_out;
4990Sstevel@tonic-gate 	memset((char *) entry.key_data, 0, sizeof(krb5_key_data));
5000Sstevel@tonic-gate 	entry.n_key_data = 1;
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	entry.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
5030Sstevel@tonic-gate 	if ((retval = krb5_dbekd_encrypt_key_data(context, pblock->key,
5042881Smp153739 						  mkey, NULL,
5052881Smp153739 						  1, entry.key_data)))
5062881Smp153739 	    goto error_out;
5070Sstevel@tonic-gate 	break;
5080Sstevel@tonic-gate     case TGT_KEY:
5090Sstevel@tonic-gate 	iargs.ctx = context;
5100Sstevel@tonic-gate 	iargs.rblock = pblock;
5110Sstevel@tonic-gate 	iargs.dbentp = &entry;
5120Sstevel@tonic-gate 	/*
5130Sstevel@tonic-gate 	 * Iterate through the key/salt list, ignoring salt types.
5140Sstevel@tonic-gate 	 */
5150Sstevel@tonic-gate 	if ((retval = krb5_keysalt_iterate(pblock->kslist,
5160Sstevel@tonic-gate 					   pblock->nkslist,
5170Sstevel@tonic-gate 					   1,
5180Sstevel@tonic-gate 					   tgt_keysalt_iterate,
5190Sstevel@tonic-gate 					   (krb5_pointer) &iargs)))
5202881Smp153739 	    return retval;
5210Sstevel@tonic-gate 	break;
5220Sstevel@tonic-gate     case NULL_KEY:
5232881Smp153739 	return EOPNOTSUPP;
5240Sstevel@tonic-gate     default:
5250Sstevel@tonic-gate 	break;
5260Sstevel@tonic-gate     }
5270Sstevel@tonic-gate 
5284960Swillf     entry.mask = (KADM5_KEY_DATA | KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
5294960Swillf 	KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_TL_DATA |
5304960Swillf 	KADM5_PRINC_EXPIRE_TIME);
5314960Swillf 
5320Sstevel@tonic-gate     retval = krb5_db_put_principal(context, &entry, &nentries);
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate error_out:;
5354960Swillf     krb5_db_free_principal(context, &entry, 1);
5362881Smp153739     return retval;
5370Sstevel@tonic-gate }
538