xref: /onnv-gate/usr/src/cmd/krb5/kadmin/dbutil/kdb5_util.c (revision 781:57319a72b15f)
10Sstevel@tonic-gate /*
2358Sgtb  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
70Sstevel@tonic-gate 
80Sstevel@tonic-gate /*
90Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
100Sstevel@tonic-gate  *
110Sstevel@tonic-gate  *	Openvision retains the copyright to derivative works of
120Sstevel@tonic-gate  *	this source code.  Do *NOT* create a derivative of this
130Sstevel@tonic-gate  *	source code before consulting with your legal department.
140Sstevel@tonic-gate  *	Do *NOT* integrate *ANY* of this source code into another
150Sstevel@tonic-gate  *	product before consulting with your legal department.
160Sstevel@tonic-gate  *
170Sstevel@tonic-gate  *	For further information, read the top-level Openvision
180Sstevel@tonic-gate  *	copyright which is contained in the top-level MIT Kerberos
190Sstevel@tonic-gate  *	copyright.
200Sstevel@tonic-gate  *
210Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * admin/edit/kdb5_edit.c
280Sstevel@tonic-gate  *
290Sstevel@tonic-gate  * (C) Copyright 1990,1991, 1996 by the Massachusetts Institute of Technology.
300Sstevel@tonic-gate  * All Rights Reserved.
310Sstevel@tonic-gate  *
320Sstevel@tonic-gate  * Export of this software from the United States of America may
330Sstevel@tonic-gate  *   require a specific license from the United States Government.
340Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
350Sstevel@tonic-gate  *   export to obtain such a license before exporting.
360Sstevel@tonic-gate  *
370Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
380Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
390Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
400Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
410Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
420Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
430Sstevel@tonic-gate  * to distribution of the software without specific, written prior
440Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
450Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
460Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
470Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
480Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
490Sstevel@tonic-gate  * or implied warranty.
500Sstevel@tonic-gate  *
510Sstevel@tonic-gate  *
520Sstevel@tonic-gate  * Edit a KDC database.
530Sstevel@tonic-gate  */
540Sstevel@tonic-gate 
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate  *  Yes, I know this is a hack, but we need admin.h without including the
570Sstevel@tonic-gate  *  rpc.h header. Additionally, our rpc.h header brings in
580Sstevel@tonic-gate  *  a des.h header which causes other problems.
590Sstevel@tonic-gate  */
600Sstevel@tonic-gate #define	_RPC_RPC_H
610Sstevel@tonic-gate 
620Sstevel@tonic-gate #include <stdio.h>
630Sstevel@tonic-gate #define KDB5_DISPATCH
640Sstevel@tonic-gate #define KRB5_KDB5_DBM__
650Sstevel@tonic-gate #include <k5-int.h>
660Sstevel@tonic-gate /* #define these to avoid an indirection function; for future implementations,
670Sstevel@tonic-gate    these may be redirected from a dispatch table/routine */
680Sstevel@tonic-gate #define krb5_dbm_db_set_name krb5_db_set_name
690Sstevel@tonic-gate #define krb5_dbm_db_set_nonblocking krb5_db_set_nonblocking
700Sstevel@tonic-gate #define krb5_dbm_db_init krb5_db_init
710Sstevel@tonic-gate #define krb5_dbm_db_get_age krb5_db_get_age
720Sstevel@tonic-gate #define krb5_dbm_db_create krb5_db_create
730Sstevel@tonic-gate #define krb5_dbm_db_rename krb5_db_rename
740Sstevel@tonic-gate #define krb5_dbm_db_get_principal krb5_db_get_principal
750Sstevel@tonic-gate #define krb5_dbm_db_free_principal krb5_db_free_principal
760Sstevel@tonic-gate #define krb5_dbm_db_put_principal krb5_db_put_principal
770Sstevel@tonic-gate #define krb5_dbm_db_delete_principal krb5_db_delete_principal
780Sstevel@tonic-gate #define krb5_dbm_db_lock krb5_db_lock
790Sstevel@tonic-gate #define krb5_dbm_db_unlock krb5_db_unlock
800Sstevel@tonic-gate #define krb5_dbm_db_set_lockmode krb5_db_set_lockmode
810Sstevel@tonic-gate #define krb5_dbm_db_close_database krb5_db_close_database
820Sstevel@tonic-gate #define krb5_dbm_db_open_database krb5_db_open_database
830Sstevel@tonic-gate 
840Sstevel@tonic-gate #include <kadm5/admin.h>
850Sstevel@tonic-gate #include <rpc/types.h>
860Sstevel@tonic-gate #include <rpc/xdr.h>
870Sstevel@tonic-gate #include <kadm5/adb.h>
880Sstevel@tonic-gate #include <time.h>
890Sstevel@tonic-gate #include <libintl.h>
900Sstevel@tonic-gate #include <locale.h>
910Sstevel@tonic-gate #include "kdb5_util.h"
920Sstevel@tonic-gate 
930Sstevel@tonic-gate char	*Err_no_master_msg = "Master key not entered!\n";
940Sstevel@tonic-gate char	*Err_no_database = "Database not currently opened!\n";
950Sstevel@tonic-gate 
960Sstevel@tonic-gate /*
970Sstevel@tonic-gate  * XXX Ick, ick, ick.  These global variables shouldn't be global....
980Sstevel@tonic-gate  */
990Sstevel@tonic-gate char *mkey_password = 0;
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate /*
1020Sstevel@tonic-gate  * I can't figure out any way for this not to be global, given how ss
1030Sstevel@tonic-gate  * works.
1040Sstevel@tonic-gate  */
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate int exit_status = 0;
1070Sstevel@tonic-gate krb5_context util_context;
1080Sstevel@tonic-gate osa_adb_policy_t policy_db;
1090Sstevel@tonic-gate kadm5_config_params global_params;
1100Sstevel@tonic-gate 
111358Sgtb void
1120Sstevel@tonic-gate usage()
1130Sstevel@tonic-gate {
1140Sstevel@tonic-gate 	fprintf(stderr, "%s: "
1150Sstevel@tonic-gate 	   "kdb5_util cmd [-r realm] [-d dbname] [-k mkeytype] [-M mkeyname]\n"
1160Sstevel@tonic-gate 	    "\t         [-f] [stashfile] [-P password] [-m ] [cmd options]\n"
1170Sstevel@tonic-gate 	    "\tcreate	[-s]\n"
1180Sstevel@tonic-gate 	    "\tdestroy	\n"
1190Sstevel@tonic-gate 	    "\tstash	\n"
1200Sstevel@tonic-gate 	    "\tdump	[-old] [-ov] [-b6] [-verbose] [filename	[princs...]]\n"
1210Sstevel@tonic-gate 	    "\tload	[-old] [-ov] [-b6] [-verbose] [-update] filename\n"
1220Sstevel@tonic-gate #ifdef SUNWOFF
1230Sstevel@tonic-gate 	    "\tload_v4	[-t] [-n] [-v] [-K] [-s stashfile] inputfile\n"
1240Sstevel@tonic-gate #endif
1250Sstevel@tonic-gate 	    "\tark	[-e etype_list] principal\n",
1260Sstevel@tonic-gate 	    gettext("Usage"));
1270Sstevel@tonic-gate      exit(1);
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate krb5_keyblock master_key;
1310Sstevel@tonic-gate extern krb5_principal master_princ;
1320Sstevel@tonic-gate krb5_db_entry master_entry;
1330Sstevel@tonic-gate int	valid_master_key = 0;
1340Sstevel@tonic-gate int     close_policy_db = 0;
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate char *progname;
1370Sstevel@tonic-gate krb5_boolean manual_mkey = FALSE;
1380Sstevel@tonic-gate krb5_boolean dbactive = FALSE;
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate int kdb5_create(int, char **);
1410Sstevel@tonic-gate int kdb5_destroy(int, char **);
1420Sstevel@tonic-gate int kdb5_stash(int, char **);
1430Sstevel@tonic-gate int dump_db(int, char **);
1440Sstevel@tonic-gate int load_db(int, char **);
1450Sstevel@tonic-gate int open_db_and_mkey();
1460Sstevel@tonic-gate int add_random_key(int, char **);
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate typedef int (*cmd_func)(int, char **);
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate struct _cmd_table {
1510Sstevel@tonic-gate      char *name;
1520Sstevel@tonic-gate      cmd_func func;
1530Sstevel@tonic-gate      int opendb;
1540Sstevel@tonic-gate } cmd_table[] = {
1550Sstevel@tonic-gate      "create", kdb5_create, 0,
1560Sstevel@tonic-gate      "destroy", kdb5_destroy, 1,
1570Sstevel@tonic-gate      "stash", kdb5_stash, 1,
1580Sstevel@tonic-gate      "dump", dump_db, 1,
1590Sstevel@tonic-gate      "load", load_db, 0,
1600Sstevel@tonic-gate      "ark", add_random_key, 1,
1610Sstevel@tonic-gate      NULL, NULL, 0,
1620Sstevel@tonic-gate };
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate struct _cmd_table *
1650Sstevel@tonic-gate cmd_lookup(name)
1660Sstevel@tonic-gate    char *name;
1670Sstevel@tonic-gate {
1680Sstevel@tonic-gate      struct _cmd_table *cmd = cmd_table;
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate      while (cmd->name) {
1710Sstevel@tonic-gate 	  if (strcmp(cmd->name, name) == 0)
1720Sstevel@tonic-gate 			return (cmd);
1730Sstevel@tonic-gate 	  else
1740Sstevel@tonic-gate 	       cmd++;
1750Sstevel@tonic-gate      }
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	return (NULL);
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate #define ARG_VAL (--argc > 0 ? (optarg = *(++argv)) : (char *)(usage(), NULL))
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate int
1830Sstevel@tonic-gate main(argc, argv)
1840Sstevel@tonic-gate     int argc;
1850Sstevel@tonic-gate     char *argv[];
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate     struct _cmd_table *cmd = NULL;
1880Sstevel@tonic-gate     char *optarg, **cmd_argv;
1890Sstevel@tonic-gate     int cmd_argc;
1900Sstevel@tonic-gate     krb5_error_code retval;
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)  /* Should be defined by cc -D */
1950Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it weren't */
1960Sstevel@tonic-gate #endif
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	Err_no_master_msg = gettext("Master key not entered!\n");
2010Sstevel@tonic-gate 	Err_no_database = gettext("Database not currently opened!\n");
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate     retval = krb5_init_context(&util_context);
2040Sstevel@tonic-gate     if (retval) {
2050Sstevel@tonic-gate 	    com_err (progname, retval,
2060Sstevel@tonic-gate 		gettext("while initializing Kerberos code"));
2070Sstevel@tonic-gate 	    exit(1);
2080Sstevel@tonic-gate     }
2090Sstevel@tonic-gate 	progname = (strrchr(argv[0], '/') ?
2100Sstevel@tonic-gate 		    strrchr(argv[0], '/') + 1 : argv[0]);
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate     cmd_argv = (char **) malloc(sizeof(char *)*argc);
2130Sstevel@tonic-gate     if (cmd_argv == NULL) {
2140Sstevel@tonic-gate 		com_err(progname, ENOMEM,
2150Sstevel@tonic-gate 		    gettext("while creating sub-command arguments"));
2160Sstevel@tonic-gate 	 exit(1);
2170Sstevel@tonic-gate     }
2180Sstevel@tonic-gate     memset(cmd_argv, 0, sizeof(char *)*argc);
2190Sstevel@tonic-gate     cmd_argc = 1;
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 	argv++;
2220Sstevel@tonic-gate 	argc--;
2230Sstevel@tonic-gate     while (*argv) {
2240Sstevel@tonic-gate        if (strcmp(*argv, "-P") == 0 && ARG_VAL) {
2250Sstevel@tonic-gate 	    mkey_password = optarg;
2260Sstevel@tonic-gate 	    manual_mkey = TRUE;
2270Sstevel@tonic-gate        } else if (strcmp(*argv, "-d") == 0 && ARG_VAL) {
2280Sstevel@tonic-gate 	    global_params.dbname = optarg;
2290Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_DBNAME;
2300Sstevel@tonic-gate        } else if (strcmp(*argv, "-r") == 0 && ARG_VAL) {
2310Sstevel@tonic-gate 	    global_params.realm = optarg;
2320Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_REALM;
2330Sstevel@tonic-gate 	    /* not sure this is really necessary */
2340Sstevel@tonic-gate 	    if ((retval = krb5_set_default_realm(util_context,
2350Sstevel@tonic-gate 						 global_params.realm))) {
2360Sstevel@tonic-gate 				com_err(progname, retval,
2370Sstevel@tonic-gate 					gettext("while setting default "
2380Sstevel@tonic-gate 						"realm name"));
2390Sstevel@tonic-gate 		 exit(1);
2400Sstevel@tonic-gate 	    }
2410Sstevel@tonic-gate        } else if (strcmp(*argv, "-k") == 0 && ARG_VAL) {
2420Sstevel@tonic-gate 			if (krb5_string_to_enctype(optarg,
2430Sstevel@tonic-gate 						    &global_params.enctype))
2440Sstevel@tonic-gate 				com_err(argv[0], 0,
2450Sstevel@tonic-gate 					gettext("%s is an invalid enctype"),
2460Sstevel@tonic-gate 					optarg);
2470Sstevel@tonic-gate 	    else
2480Sstevel@tonic-gate 		 global_params.mask |= KADM5_CONFIG_ENCTYPE;
2490Sstevel@tonic-gate        } else if (strcmp(*argv, "-M") == 0 && ARG_VAL) {
2500Sstevel@tonic-gate 	    global_params.mkey_name = optarg;
2510Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_MKEY_NAME;
2520Sstevel@tonic-gate        } else if (((strcmp(*argv, "-sf") == 0)
2530Sstevel@tonic-gate 		/* SUNWresync121 - carry the old -f forward too */
2540Sstevel@tonic-gate 		|| (strcmp(*argv, "-f") == 0)) && ARG_VAL) {
2550Sstevel@tonic-gate 	    global_params.stash_file = optarg;
2560Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_STASH_FILE;
2570Sstevel@tonic-gate        } else if (strcmp(*argv, "-m") == 0) {
2580Sstevel@tonic-gate 	    manual_mkey = TRUE;
2590Sstevel@tonic-gate 	    global_params.mkey_from_kbd = 1;
2600Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
2610Sstevel@tonic-gate        } else if (cmd_lookup(*argv) != NULL) {
2620Sstevel@tonic-gate 	    if (cmd_argv[0] == NULL)
2630Sstevel@tonic-gate 		 cmd_argv[0] = *argv;
2640Sstevel@tonic-gate 	    else
2650Sstevel@tonic-gate 		 usage();
2660Sstevel@tonic-gate        } else {
2670Sstevel@tonic-gate 	    cmd_argv[cmd_argc++] = *argv;
2680Sstevel@tonic-gate        }
2690Sstevel@tonic-gate 		argv++;
2700Sstevel@tonic-gate 		argc--;
2710Sstevel@tonic-gate     }
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate     if (cmd_argv[0] == NULL)
2740Sstevel@tonic-gate 	 usage();
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate     if (retval = kadm5_get_config_params(util_context, NULL, NULL,
2770Sstevel@tonic-gate 					 &global_params, &global_params)) {
2780Sstevel@tonic-gate 		com_err(argv[0], retval,
2790Sstevel@tonic-gate 		    gettext("while retreiving configuration parameters"));
2800Sstevel@tonic-gate 	 exit(1);
2810Sstevel@tonic-gate     }
2820Sstevel@tonic-gate     /*
2830Sstevel@tonic-gate      * Dump creates files which should not be world-readable.  It is
2840Sstevel@tonic-gate      * easiest to do a single umask call here.
2850Sstevel@tonic-gate      */
2860Sstevel@tonic-gate     (void) umask(077);
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate     (void) memset(&master_key, 0, sizeof (krb5_keyblock));
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate     if ((global_params.enctype != ENCTYPE_UNKNOWN) &&
291*781Sgtb 	(!krb5_c_valid_enctype(global_params.enctype))) {
2920Sstevel@tonic-gate 	com_err(argv[0], KRB5_PROG_KEYTYPE_NOSUPP,
2930Sstevel@tonic-gate 	    gettext("while setting up enctype %d"), global_params.enctype);
2940Sstevel@tonic-gate     }
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate     cmd = cmd_lookup(cmd_argv[0]);
2970Sstevel@tonic-gate     if (cmd->opendb && open_db_and_mkey())
2980Sstevel@tonic-gate 		return (exit_status);
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	if (global_params.iprop_enabled == TRUE)
3010Sstevel@tonic-gate 		ulog_set_role(util_context, IPROP_MASTER);
3020Sstevel@tonic-gate 	else
3030Sstevel@tonic-gate 		ulog_set_role(util_context, IPROP_NULL);
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate     (*cmd->func)(cmd_argc, cmd_argv);
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate     if(close_policy_db) {
3080Sstevel@tonic-gate          (void) osa_adb_close_policy(policy_db);
3090Sstevel@tonic-gate     }
3100Sstevel@tonic-gate     kadm5_free_config_params(util_context, &global_params);
3110Sstevel@tonic-gate     krb5_free_context(util_context);
3120Sstevel@tonic-gate     return (exit_status);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate #if 0
3160Sstevel@tonic-gate /*
3170Sstevel@tonic-gate  * This function is no longer used in kdb5_util (and it would no
3180Sstevel@tonic-gate  * longer work, anyway).
3190Sstevel@tonic-gate  */
3200Sstevel@tonic-gate void
3210Sstevel@tonic-gate set_dbname(argc, argv)
3220Sstevel@tonic-gate     int argc;
3230Sstevel@tonic-gate     char *argv[];
3240Sstevel@tonic-gate {
3250Sstevel@tonic-gate     krb5_error_code retval;
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate     if (argc < 3) {
3280Sstevel@tonic-gate 		com_err(argv[0], 0, gettext("Too few arguments"));
3290Sstevel@tonic-gate 		com_err(argv[0], 0, gettext("Usage: %s dbpathname realmname"),
3300Sstevel@tonic-gate 			argv[0]);
3310Sstevel@tonic-gate 	exit_status++;
3320Sstevel@tonic-gate 	return;
3330Sstevel@tonic-gate     }
3340Sstevel@tonic-gate     if (dbactive) {
3350Sstevel@tonic-gate 		if ((retval = krb5_db_fini(util_context)) &&
3360Sstevel@tonic-gate 				retval != KRB5_KDB_DBNOTINITED) {
3370Sstevel@tonic-gate 			com_err(argv[0], retval,
3380Sstevel@tonic-gate 				gettext("while closing previous database"));
3390Sstevel@tonic-gate 	    exit_status++;
3400Sstevel@tonic-gate 	    return;
3410Sstevel@tonic-gate 	}
3420Sstevel@tonic-gate 	if (valid_master_key) {
3430Sstevel@tonic-gate 	    krb5_free_keyblock_contents(util_context, &master_key);
3440Sstevel@tonic-gate 	    valid_master_key = 0;
3450Sstevel@tonic-gate 	}
3460Sstevel@tonic-gate 	krb5_free_principal(util_context, master_princ);
3470Sstevel@tonic-gate 	dbactive = FALSE;
3480Sstevel@tonic-gate     }
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate     (void) set_dbname_help(argv[0], argv[1]);
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate #endif
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate /*
3560Sstevel@tonic-gate  * open_db_and_mkey: Opens the KDC and policy database, and sets the
3570Sstevel@tonic-gate  * global master_* variables.  Sets dbactive to TRUE if the databases
3580Sstevel@tonic-gate  * are opened, and valid_master_key to 1 if the global master
3590Sstevel@tonic-gate  * variables are set properly.  Returns 0 on success, and 1 on
3600Sstevel@tonic-gate  * failure, but it is not considered a failure if the master key
3610Sstevel@tonic-gate  * cannot be fetched (the master key stash file may not exist when the
3620Sstevel@tonic-gate  * program is run).
3630Sstevel@tonic-gate  */
3640Sstevel@tonic-gate int
3650Sstevel@tonic-gate open_db_and_mkey()
3660Sstevel@tonic-gate {
3670Sstevel@tonic-gate     krb5_error_code retval;
3680Sstevel@tonic-gate     int nentries;
3690Sstevel@tonic-gate     krb5_boolean more;
3700Sstevel@tonic-gate     krb5_data scratch, pwd, seed;
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate     dbactive = FALSE;
3730Sstevel@tonic-gate     valid_master_key = 0;
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate     if ((retval = krb5_db_set_name(util_context, global_params.dbname))) {
3760Sstevel@tonic-gate 		com_err(progname, retval,
3770Sstevel@tonic-gate 		    gettext("while setting active database to '%s'"),
3780Sstevel@tonic-gate 		global_params.dbname);
3790Sstevel@tonic-gate 	exit_status++;
3800Sstevel@tonic-gate 	return(1);
3810Sstevel@tonic-gate     }
3820Sstevel@tonic-gate     if ((retval = krb5_db_init(util_context))) {
3830Sstevel@tonic-gate 		com_err(progname, retval,
3840Sstevel@tonic-gate 		    gettext("while initializing database"));
3850Sstevel@tonic-gate 	exit_status++;
3860Sstevel@tonic-gate 	return(1);
3870Sstevel@tonic-gate     }
3880Sstevel@tonic-gate     if (retval = osa_adb_open_policy(&policy_db, &global_params)) {
3890Sstevel@tonic-gate 		com_err(progname, retval,
3900Sstevel@tonic-gate 		    gettext("opening policy database"));
3910Sstevel@tonic-gate 	 exit_status++;
3920Sstevel@tonic-gate 	 return (1);
3930Sstevel@tonic-gate     }
3940Sstevel@tonic-gate    /* assemble & parse the master key name */
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate     if ((retval = krb5_db_setup_mkey_name(util_context,
3970Sstevel@tonic-gate 					  global_params.mkey_name,
3980Sstevel@tonic-gate 					  global_params.realm,
3990Sstevel@tonic-gate 					  0, &master_princ))) {
4000Sstevel@tonic-gate 		com_err(progname, retval,
4010Sstevel@tonic-gate 		    gettext("while setting up master key name"));
4020Sstevel@tonic-gate 	exit_status++;
4030Sstevel@tonic-gate 	return(1);
4040Sstevel@tonic-gate     }
4050Sstevel@tonic-gate     nentries = 1;
4060Sstevel@tonic-gate     if ((retval = krb5_db_get_principal(util_context, master_princ,
4070Sstevel@tonic-gate 					&master_entry, &nentries, &more))) {
4080Sstevel@tonic-gate 		com_err(progname, retval,
4090Sstevel@tonic-gate 		    gettext("while retrieving master entry"));
4100Sstevel@tonic-gate 	exit_status++;
4110Sstevel@tonic-gate 	(void) krb5_db_fini(util_context);
4120Sstevel@tonic-gate 	return(1);
4130Sstevel@tonic-gate     } else if (more) {
4140Sstevel@tonic-gate 	com_err(progname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE,
4150Sstevel@tonic-gate 		    gettext("while retrieving master entry"));
4160Sstevel@tonic-gate 	exit_status++;
4170Sstevel@tonic-gate 	(void) krb5_db_fini(util_context);
4180Sstevel@tonic-gate 	return(1);
4190Sstevel@tonic-gate     } else if (!nentries) {
4200Sstevel@tonic-gate 		com_err(progname, KRB5_KDB_NOENTRY,
4210Sstevel@tonic-gate 		    gettext("while retrieving master entry"));
4220Sstevel@tonic-gate 	exit_status++;
4230Sstevel@tonic-gate 	(void) krb5_db_fini(util_context);
4240Sstevel@tonic-gate 	return(1);
4250Sstevel@tonic-gate     }
4260Sstevel@tonic-gate     krb5_db_free_principal(util_context, &master_entry, nentries);
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate     /* the databases are now open, and the master principal exists */
4290Sstevel@tonic-gate     dbactive = TRUE;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate     if (mkey_password) {
4320Sstevel@tonic-gate 	pwd.data = mkey_password;
4330Sstevel@tonic-gate 	pwd.length = strlen(mkey_password);
4340Sstevel@tonic-gate 	retval = krb5_principal2salt(util_context,
4350Sstevel@tonic-gate 			    master_princ, &scratch);
4360Sstevel@tonic-gate 	if (retval) {
4370Sstevel@tonic-gate 		com_err(progname, retval,
4380Sstevel@tonic-gate 		    gettext("while calculated master key salt"));
4390Sstevel@tonic-gate 		return(1);
4400Sstevel@tonic-gate 	}
4410Sstevel@tonic-gate 	/* If no encryption type is set, use the default */
4420Sstevel@tonic-gate 	if (global_params.enctype == ENCTYPE_UNKNOWN) {
4430Sstevel@tonic-gate 	    global_params.enctype = DEFAULT_KDC_ENCTYPE;
444*781Sgtb 	    if (!krb5_c_valid_enctype(global_params.enctype))
4450Sstevel@tonic-gate 		com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
4460Sstevel@tonic-gate 			gettext("while setting up enctype %d"),
4470Sstevel@tonic-gate 			global_params.enctype);
4480Sstevel@tonic-gate 	}
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	retval = krb5_c_string_to_key(util_context,
4510Sstevel@tonic-gate 				global_params.enctype,
4520Sstevel@tonic-gate 				&pwd, &scratch, &master_key);
4530Sstevel@tonic-gate 	if (retval) {
4540Sstevel@tonic-gate 	    com_err(progname, retval,
4550Sstevel@tonic-gate 		gettext("while transforming master key from password"));
4560Sstevel@tonic-gate 	    return(1);
4570Sstevel@tonic-gate 	}
4580Sstevel@tonic-gate 	free(scratch.data);
4590Sstevel@tonic-gate 	mkey_password = 0;
4600Sstevel@tonic-gate     } else if ((retval = krb5_db_fetch_mkey(util_context, master_princ,
4610Sstevel@tonic-gate 					    global_params.enctype,
4620Sstevel@tonic-gate 					    manual_mkey, FALSE,
4630Sstevel@tonic-gate 					    global_params.stash_file,
4640Sstevel@tonic-gate 					    0, &master_key))) {
4650Sstevel@tonic-gate 	com_err(progname, retval,
4660Sstevel@tonic-gate 	    gettext("while reading master key"));
4670Sstevel@tonic-gate 	com_err(progname, 0,
4680Sstevel@tonic-gate 	    gettext("Warning: proceeding without master key"));
4690Sstevel@tonic-gate 	exit_status++;
4700Sstevel@tonic-gate 	return(0);
4710Sstevel@tonic-gate     }
4720Sstevel@tonic-gate     if ((retval = krb5_db_verify_master_key(util_context, master_princ,
4730Sstevel@tonic-gate 		&master_key))) {
4740Sstevel@tonic-gate 	com_err(progname, retval,
4750Sstevel@tonic-gate 		gettext("while verifying master key"));
4760Sstevel@tonic-gate 	exit_status++;
4770Sstevel@tonic-gate 	krb5_free_keyblock_contents(util_context, &master_key);
4780Sstevel@tonic-gate 	return(1);
4790Sstevel@tonic-gate     }
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate     seed.length = master_key.length;
4820Sstevel@tonic-gate     seed.data = (char *)master_key.contents;
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate     if ((retval = krb5_c_random_seed(util_context, &seed))) {
4850Sstevel@tonic-gate 	com_err(progname, retval,
4860Sstevel@tonic-gate 		gettext("while initializing random key generator"));
4870Sstevel@tonic-gate 	exit_status++;
4880Sstevel@tonic-gate 	krb5_free_keyblock_contents(util_context, &master_key);
4890Sstevel@tonic-gate 	return(1);
4900Sstevel@tonic-gate     }
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate     valid_master_key = 1;
4930Sstevel@tonic-gate     dbactive = TRUE;
4940Sstevel@tonic-gate 	return (0);
4950Sstevel@tonic-gate }
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate #ifdef HAVE_GETCWD
4980Sstevel@tonic-gate #undef getwd
4990Sstevel@tonic-gate #endif
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate int
5020Sstevel@tonic-gate quit()
5030Sstevel@tonic-gate {
5040Sstevel@tonic-gate     krb5_error_code retval;
5050Sstevel@tonic-gate     static krb5_boolean finished = 0;
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate     if (finished)
5080Sstevel@tonic-gate 		return (0);
5090Sstevel@tonic-gate     retval = krb5_db_fini(util_context);
5100Sstevel@tonic-gate     krb5_free_keyblock_contents(util_context, &master_key);
5110Sstevel@tonic-gate     finished = TRUE;
5120Sstevel@tonic-gate     krb5_free_context(util_context);
5130Sstevel@tonic-gate     if (retval && retval != KRB5_KDB_DBNOTINITED) {
5140Sstevel@tonic-gate 		com_err(progname, retval, gettext("while closing database"));
5150Sstevel@tonic-gate 	exit_status++;
5160Sstevel@tonic-gate 	return (1);
5170Sstevel@tonic-gate     }
5180Sstevel@tonic-gate     return (0);
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate int
5220Sstevel@tonic-gate add_random_key(argc, argv)
5230Sstevel@tonic-gate     int argc;
5240Sstevel@tonic-gate     char **argv;
5250Sstevel@tonic-gate {
5260Sstevel@tonic-gate     krb5_error_code ret;
5270Sstevel@tonic-gate     krb5_principal princ;
5280Sstevel@tonic-gate     krb5_db_entry dbent;
5290Sstevel@tonic-gate     int n, i;
5300Sstevel@tonic-gate     krb5_boolean more;
5310Sstevel@tonic-gate     krb5_timestamp now;
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate     krb5_key_salt_tuple *keysalts = NULL;
5340Sstevel@tonic-gate     krb5_int32 num_keysalts = 0;
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate     int free_keysalts;
5370Sstevel@tonic-gate     char *me = argv[0];
5380Sstevel@tonic-gate     char *ks_str = NULL;
5390Sstevel@tonic-gate     char *pr_str;
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate     if (argc < 2)
5420Sstevel@tonic-gate 	usage();
5430Sstevel@tonic-gate     for (argv++, argc--; *argv; argv++, argc--) {
5440Sstevel@tonic-gate 	if (!strcmp(*argv, "-e")) {
5450Sstevel@tonic-gate 	    argv++; argc--;
5460Sstevel@tonic-gate 	    ks_str = *argv;
5470Sstevel@tonic-gate 	    continue;
5480Sstevel@tonic-gate 	} else
5490Sstevel@tonic-gate 	    break;
5500Sstevel@tonic-gate     }
5510Sstevel@tonic-gate     if (argc < 1)
5520Sstevel@tonic-gate 	usage();
5530Sstevel@tonic-gate     pr_str = *argv;
5540Sstevel@tonic-gate     ret = krb5_parse_name(util_context, pr_str, &princ);
5550Sstevel@tonic-gate     if (ret) {
5560Sstevel@tonic-gate 	com_err(me, ret, gettext("while parsing principal name %s"), pr_str);
5570Sstevel@tonic-gate 	return 1;
5580Sstevel@tonic-gate     }
5590Sstevel@tonic-gate     n = 1;
5600Sstevel@tonic-gate     ret = krb5_db_get_principal(util_context, princ, &dbent,
5610Sstevel@tonic-gate 				&n, &more);
5620Sstevel@tonic-gate     if (ret) {
5630Sstevel@tonic-gate 	com_err(me, ret, gettext("while fetching principal %s"), pr_str);
5640Sstevel@tonic-gate 	return 1;
5650Sstevel@tonic-gate     }
5660Sstevel@tonic-gate     if (n != 1) {
5670Sstevel@tonic-gate 	fprintf(stderr, gettext("principal %s not found\n"), pr_str);
5680Sstevel@tonic-gate 	return 1;
5690Sstevel@tonic-gate     }
5700Sstevel@tonic-gate     if (more) {
5710Sstevel@tonic-gate 	fprintf(stderr, gettext("principal %s not unique\n"), pr_str);
5720Sstevel@tonic-gate 	krb5_dbe_free_contents(util_context, &dbent);
5730Sstevel@tonic-gate 	return 1;
5740Sstevel@tonic-gate     }
5750Sstevel@tonic-gate     ret = krb5_string_to_keysalts(ks_str,
5760Sstevel@tonic-gate 				  ", \t", ":.-", 0,
5770Sstevel@tonic-gate 				  &keysalts,
5780Sstevel@tonic-gate 				  &num_keysalts);
5790Sstevel@tonic-gate     if (ret) {
5800Sstevel@tonic-gate 	com_err(me, ret, gettext("while parsing keysalts %s"), ks_str);
5810Sstevel@tonic-gate 	return 1;
5820Sstevel@tonic-gate     }
5830Sstevel@tonic-gate     if (!num_keysalts || keysalts == NULL) {
5840Sstevel@tonic-gate 	num_keysalts = global_params.num_keysalts;
5850Sstevel@tonic-gate 	keysalts = global_params.keysalts;
5860Sstevel@tonic-gate 	free_keysalts = 0;
5870Sstevel@tonic-gate     } else
5880Sstevel@tonic-gate 	free_keysalts = 1;
5890Sstevel@tonic-gate     ret = krb5_dbe_ark(util_context, &master_key,
5900Sstevel@tonic-gate 		       keysalts, num_keysalts,
5910Sstevel@tonic-gate 		       &dbent);
5920Sstevel@tonic-gate     if (free_keysalts)
5930Sstevel@tonic-gate 	free(keysalts);
5940Sstevel@tonic-gate     if (ret) {
5950Sstevel@tonic-gate 	com_err(me, ret, gettext("while randomizing principal %s"), pr_str);
5960Sstevel@tonic-gate 	krb5_dbe_free_contents(util_context, &dbent);
5970Sstevel@tonic-gate 	return 1;
5980Sstevel@tonic-gate     }
5990Sstevel@tonic-gate     dbent.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
6000Sstevel@tonic-gate     ret = krb5_timeofday(util_context, &now);
6010Sstevel@tonic-gate     if (ret) {
6020Sstevel@tonic-gate 	com_err(me, ret, gettext("while getting time"));
6030Sstevel@tonic-gate 	krb5_dbe_free_contents(util_context, &dbent);
6040Sstevel@tonic-gate 	return 1;
6050Sstevel@tonic-gate     }
6060Sstevel@tonic-gate     ret = krb5_dbe_update_last_pwd_change(util_context, &dbent, now);
6070Sstevel@tonic-gate     if (ret) {
6080Sstevel@tonic-gate 	com_err(me, ret, gettext("while setting changetime"));
6090Sstevel@tonic-gate 	krb5_dbe_free_contents(util_context, &dbent);
6100Sstevel@tonic-gate 	return 1;
6110Sstevel@tonic-gate     }
6120Sstevel@tonic-gate     ret = krb5_db_put_principal(util_context, &dbent, &n);
6130Sstevel@tonic-gate     krb5_dbe_free_contents(util_context, &dbent);
6140Sstevel@tonic-gate     if (ret) {
6150Sstevel@tonic-gate 	com_err(me, ret, gettext("while saving principal %s"), pr_str);
6160Sstevel@tonic-gate 	return 1;
6170Sstevel@tonic-gate     }
6180Sstevel@tonic-gate     printf("%s changed\n", pr_str);
6190Sstevel@tonic-gate     return 0;
6200Sstevel@tonic-gate }
621