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