xref: /onnv-gate/usr/src/cmd/krb5/kadmin/dbutil/kdb5_util.c (revision 8092:19771b16f0a8)
10Sstevel@tonic-gate /*
25867Smp153739  * 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/edit/kdb5_edit.c
260Sstevel@tonic-gate  *
270Sstevel@tonic-gate  * (C) Copyright 1990,1991, 1996 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  * Edit a KDC database.
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate 
530Sstevel@tonic-gate /*
542881Smp153739  * Copyright (C) 1998 by the FundsXpress, INC.
552881Smp153739  *
562881Smp153739  * All rights reserved.
572881Smp153739  *
582881Smp153739  * Export of this software from the United States of America may require
592881Smp153739  * a specific license from the United States Government.  It is the
602881Smp153739  * responsibility of any person or organization contemplating export to
612881Smp153739  * obtain such a license before exporting.
622881Smp153739  *
632881Smp153739  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
642881Smp153739  * distribute this software and its documentation for any purpose and
652881Smp153739  * without fee is hereby granted, provided that the above copyright
662881Smp153739  * notice appear in all copies and that both that copyright notice and
672881Smp153739  * this permission notice appear in supporting documentation, and that
682881Smp153739  * the name of FundsXpress. not be used in advertising or publicity pertaining
692881Smp153739  * to distribution of the software without specific, written prior
702881Smp153739  * permission.  FundsXpress makes no representations about the suitability of
712881Smp153739  * this software for any purpose.  It is provided "as is" without express
722881Smp153739  * or implied warranty.
732881Smp153739  *
742881Smp153739  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
752881Smp153739  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
762881Smp153739  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
772881Smp153739  */
782881Smp153739 
792881Smp153739 /*
800Sstevel@tonic-gate  *  Yes, I know this is a hack, but we need admin.h without including the
810Sstevel@tonic-gate  *  rpc.h header. Additionally, our rpc.h header brings in
820Sstevel@tonic-gate  *  a des.h header which causes other problems.
830Sstevel@tonic-gate  */
840Sstevel@tonic-gate #define	_RPC_RPC_H
850Sstevel@tonic-gate 
860Sstevel@tonic-gate #include <stdio.h>
870Sstevel@tonic-gate #include <k5-int.h>
880Sstevel@tonic-gate #include <kadm5/admin.h>
890Sstevel@tonic-gate #include <rpc/types.h>
904960Swillf #include <krb5/adm_proto.h>
910Sstevel@tonic-gate #include <rpc/xdr.h>
920Sstevel@tonic-gate #include <time.h>
930Sstevel@tonic-gate #include <libintl.h>
940Sstevel@tonic-gate #include <locale.h>
950Sstevel@tonic-gate #include "kdb5_util.h"
960Sstevel@tonic-gate 
970Sstevel@tonic-gate char	*Err_no_master_msg = "Master key not entered!\n";
980Sstevel@tonic-gate char	*Err_no_database = "Database not currently opened!\n";
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate /*
1010Sstevel@tonic-gate  * XXX Ick, ick, ick.  These global variables shouldn't be global....
1020Sstevel@tonic-gate  */
1030Sstevel@tonic-gate char *mkey_password = 0;
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate /*
1060Sstevel@tonic-gate  * I can't figure out any way for this not to be global, given how ss
1070Sstevel@tonic-gate  * works.
1080Sstevel@tonic-gate  */
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate int exit_status = 0;
1110Sstevel@tonic-gate krb5_context util_context;
1120Sstevel@tonic-gate kadm5_config_params global_params;
1130Sstevel@tonic-gate 
usage()1142881Smp153739 void usage()
1150Sstevel@tonic-gate {
1162881Smp153739      fprintf(stderr, "%s: "
1174960Swillf 	   "kdb5_util [-x db_args]* [-r realm] [-d dbname] [-k mkeytype] [-M mkeyname]\n"
1184960Swillf 	     "\t        [-sf stashfilename] [-P password] [-m] cmd [cmd_options]\n"
1192881Smp153739 	     "\tcreate	[-s]\n"
1202881Smp153739 	     "\tdestroy	[-f]\n"
1212881Smp153739 	     "\tstash	[-f keyfile]\n"
1222881Smp153739 	     "\tdump	[-old] [-ov] [-b6] [-verbose] [filename	[princs...]]\n"
1232881Smp153739 	     "\t	[-mkey_convert] [-new_mkey_file mkey_file]\n"
1242881Smp153739 	     "\t	[-rev] [-recurse] [filename [princs...]]\n"
1252881Smp153739 	     "\tload	[-old] [-ov] [-b6] [-verbose] [-update] filename\n"
1264960Swillf 	     "\tark	[-e etype_list] principal\n"
1274960Swillf 	     "\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n"
1284960Swillf 	     "\t\t\tLook at each database documentation for supported arguments\n",
1294960Swillf 		gettext("Usage"));
1302881Smp153739      exit(1);
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate krb5_keyblock master_key;
1340Sstevel@tonic-gate extern krb5_principal master_princ;
1350Sstevel@tonic-gate krb5_db_entry master_entry;
1360Sstevel@tonic-gate int	valid_master_key = 0;
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate char *progname;
1390Sstevel@tonic-gate krb5_boolean manual_mkey = FALSE;
1400Sstevel@tonic-gate krb5_boolean dbactive = FALSE;
1410Sstevel@tonic-gate 
1422881Smp153739 static int open_db_and_mkey(void);
1432881Smp153739 
1442881Smp153739 static void add_random_key(int, char **);
1450Sstevel@tonic-gate 
1462881Smp153739 typedef void (*cmd_func)(int, char **);
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate struct _cmd_table {
1490Sstevel@tonic-gate      char *name;
1500Sstevel@tonic-gate      cmd_func func;
1510Sstevel@tonic-gate      int opendb;
1520Sstevel@tonic-gate } cmd_table[] = {
1532881Smp153739      {"create", kdb5_create, 0},
1542881Smp153739      {"destroy", kdb5_destroy, 1},
1552881Smp153739      {"stash", kdb5_stash, 1},
1562881Smp153739      {"dump", dump_db, 1},
1572881Smp153739      {"load", load_db, 0},
1582881Smp153739      {"ark", add_random_key, 1},
1592881Smp153739      {NULL, NULL, 0},
1600Sstevel@tonic-gate };
1610Sstevel@tonic-gate 
cmd_lookup(name)1622881Smp153739 static struct _cmd_table *cmd_lookup(name)
1630Sstevel@tonic-gate    char *name;
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate      struct _cmd_table *cmd = cmd_table;
1660Sstevel@tonic-gate      while (cmd->name) {
1670Sstevel@tonic-gate 	  if (strcmp(cmd->name, name) == 0)
1682881Smp153739 	       return cmd;
1690Sstevel@tonic-gate 	  else
1700Sstevel@tonic-gate 	       cmd++;
1710Sstevel@tonic-gate      }
1720Sstevel@tonic-gate 
1732881Smp153739      return NULL;
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate 
1762881Smp153739 #define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(usage(), NULL))
1774960Swillf 
1784960Swillf char **db5util_db_args = NULL;
1794960Swillf int    db5util_db_args_size = 0;
1800Sstevel@tonic-gate 
extended_com_err_fn(const char * myprog,errcode_t code,const char * fmt,va_list args)1814960Swillf static void extended_com_err_fn (const char *myprog, errcode_t code,
1824960Swillf 				 const char *fmt, va_list args)
1834960Swillf {
1844960Swillf     const char *emsg;
1854960Swillf     if (code) {
1864960Swillf 	emsg = krb5_get_error_message (util_context, code);
1874960Swillf 	fprintf (stderr, "%s: %s ", myprog, emsg);
1884960Swillf 	krb5_free_error_message (util_context, emsg);
1894960Swillf     } else {
1904960Swillf 	fprintf (stderr, "%s: ", myprog);
1914960Swillf     }
1924960Swillf     vfprintf (stderr, fmt, args);
1934960Swillf     fprintf (stderr, "\n");
1944960Swillf }
1954960Swillf 
add_db_arg(char * arg)1964960Swillf int add_db_arg(char *arg)
1974960Swillf {
1984960Swillf     char **temp;
1994960Swillf     db5util_db_args_size++;
2004960Swillf     temp = realloc(db5util_db_args,
2014960Swillf 		   sizeof(char *) * (db5util_db_args_size + 1));
2024960Swillf     if (temp == NULL)
2034960Swillf 	return 0;
2044960Swillf     db5util_db_args = temp;
2054960Swillf     db5util_db_args[db5util_db_args_size-1] = arg;
2064960Swillf     db5util_db_args[db5util_db_args_size]   = NULL;
2074960Swillf     return 1;
2084960Swillf }
2094960Swillf 
main(argc,argv)2102881Smp153739 int main(argc, argv)
2110Sstevel@tonic-gate     int argc;
2120Sstevel@tonic-gate     char *argv[];
2130Sstevel@tonic-gate {
2140Sstevel@tonic-gate     struct _cmd_table *cmd = NULL;
2152881Smp153739     char *koptarg, **cmd_argv;
2164960Swillf     char *db_name_tmp = NULL;
2170Sstevel@tonic-gate     int cmd_argc;
2180Sstevel@tonic-gate     krb5_error_code retval;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2214960Swillf     set_com_err_hook(extended_com_err_fn);
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)  /* Should be defined by cc -D */
2240Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it weren't */
2250Sstevel@tonic-gate #endif
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	Err_no_master_msg = gettext("Master key not entered!\n");
2300Sstevel@tonic-gate 	Err_no_database = gettext("Database not currently opened!\n");
2310Sstevel@tonic-gate 
2325867Smp153739 	/*
2335867Smp153739 	 * Solaris Kerberos:
2345867Smp153739 	 * Ensure that "progname" is set before calling com_err.
2355867Smp153739 	 */
2365867Smp153739 	progname = (strrchr(argv[0], '/') ?
2375867Smp153739 		    strrchr(argv[0], '/') + 1 : argv[0]);
2385867Smp153739 
2394960Swillf     retval = kadm5_init_krb5_context(&util_context);
2400Sstevel@tonic-gate     if (retval) {
2410Sstevel@tonic-gate 	    com_err (progname, retval,
2420Sstevel@tonic-gate 		gettext("while initializing Kerberos code"));
2430Sstevel@tonic-gate 	    exit(1);
2440Sstevel@tonic-gate     }
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate     cmd_argv = (char **) malloc(sizeof(char *)*argc);
2470Sstevel@tonic-gate     if (cmd_argv == NULL) {
2480Sstevel@tonic-gate 		com_err(progname, ENOMEM,
2490Sstevel@tonic-gate 		    gettext("while creating sub-command arguments"));
2500Sstevel@tonic-gate 	 exit(1);
2510Sstevel@tonic-gate     }
2520Sstevel@tonic-gate     memset(cmd_argv, 0, sizeof(char *)*argc);
2530Sstevel@tonic-gate     cmd_argc = 1;
2540Sstevel@tonic-gate 
2552881Smp153739     argv++; argc--;
2560Sstevel@tonic-gate     while (*argv) {
2570Sstevel@tonic-gate        if (strcmp(*argv, "-P") == 0 && ARG_VAL) {
2582881Smp153739 	    mkey_password = koptarg;
2590Sstevel@tonic-gate 	    manual_mkey = TRUE;
2600Sstevel@tonic-gate        } else if (strcmp(*argv, "-d") == 0 && ARG_VAL) {
2612881Smp153739 	    global_params.dbname = koptarg;
2620Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_DBNAME;
2634960Swillf 
2644960Swillf 	    db_name_tmp = malloc( strlen(global_params.dbname) + sizeof("dbname="));
2654960Swillf 	    if( db_name_tmp == NULL )
2664960Swillf 	    {
2674960Swillf 		com_err(progname, ENOMEM, "while parsing command arguments");
2684960Swillf 		exit(1);
2694960Swillf 	    }
2704960Swillf 
2714960Swillf 	    strcpy( db_name_tmp, "dbname=");
2724960Swillf 	    strcat( db_name_tmp, global_params.dbname );
2734960Swillf 
2744960Swillf 	    if (!add_db_arg(db_name_tmp)) {
2754960Swillf 		com_err(progname, ENOMEM, "while parsing command arguments\n");
2764960Swillf 		exit(1);
2774960Swillf 	    }
2784960Swillf 
2794960Swillf        } else if (strcmp(*argv, "-x") == 0 && ARG_VAL) {
2804960Swillf 	   if (!add_db_arg(koptarg)) {
2814960Swillf 		com_err(progname, ENOMEM, "while parsing command arguments\n");
2824960Swillf 		exit(1);
2834960Swillf 	   }
2844960Swillf 
2850Sstevel@tonic-gate        } else if (strcmp(*argv, "-r") == 0 && ARG_VAL) {
2862881Smp153739 	    global_params.realm = koptarg;
2870Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_REALM;
2880Sstevel@tonic-gate 	    /* not sure this is really necessary */
2890Sstevel@tonic-gate 	    if ((retval = krb5_set_default_realm(util_context,
2900Sstevel@tonic-gate 						 global_params.realm))) {
2910Sstevel@tonic-gate 				com_err(progname, retval,
2920Sstevel@tonic-gate 					gettext("while setting default "
2930Sstevel@tonic-gate 						"realm name"));
2940Sstevel@tonic-gate 		 exit(1);
2950Sstevel@tonic-gate 	    }
2960Sstevel@tonic-gate        } else if (strcmp(*argv, "-k") == 0 && ARG_VAL) {
297*8092SMark.Phalan@Sun.COM 	    if (krb5_string_to_enctype(koptarg, &global_params.enctype)) {
298*8092SMark.Phalan@Sun.COM 		/* Solaris Kerberos */
299*8092SMark.Phalan@Sun.COM 		 com_err(progname, 0, gettext("%s is an invalid enctype"), koptarg);
300*8092SMark.Phalan@Sun.COM 	    }
3010Sstevel@tonic-gate 	    else
3020Sstevel@tonic-gate 		 global_params.mask |= KADM5_CONFIG_ENCTYPE;
3030Sstevel@tonic-gate        } else if (strcmp(*argv, "-M") == 0 && ARG_VAL) {
3042881Smp153739 	    global_params.mkey_name = koptarg;
3050Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_MKEY_NAME;
3060Sstevel@tonic-gate        } else if (((strcmp(*argv, "-sf") == 0)
3070Sstevel@tonic-gate 		/* SUNWresync121 - carry the old -f forward too */
3080Sstevel@tonic-gate 		|| (strcmp(*argv, "-f") == 0)) && ARG_VAL) {
3092881Smp153739 	    global_params.stash_file = koptarg;
3100Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_STASH_FILE;
3110Sstevel@tonic-gate        } else if (strcmp(*argv, "-m") == 0) {
3120Sstevel@tonic-gate 	    manual_mkey = TRUE;
3130Sstevel@tonic-gate 	    global_params.mkey_from_kbd = 1;
3140Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
3150Sstevel@tonic-gate        } else if (cmd_lookup(*argv) != NULL) {
3160Sstevel@tonic-gate 	    if (cmd_argv[0] == NULL)
3170Sstevel@tonic-gate 		 cmd_argv[0] = *argv;
3180Sstevel@tonic-gate 	    else
3190Sstevel@tonic-gate 		 usage();
3200Sstevel@tonic-gate        } else {
3210Sstevel@tonic-gate 	    cmd_argv[cmd_argc++] = *argv;
3220Sstevel@tonic-gate        }
3232881Smp153739        argv++; argc--;
3240Sstevel@tonic-gate     }
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate     if (cmd_argv[0] == NULL)
3270Sstevel@tonic-gate 	 usage();
3280Sstevel@tonic-gate 
3297934SMark.Phalan@Sun.COM     if( !util_context->default_realm )
3307934SMark.Phalan@Sun.COM     {
3317934SMark.Phalan@Sun.COM 	char *temp = NULL;
3327934SMark.Phalan@Sun.COM 	retval = krb5_get_default_realm(util_context, &temp);
3337934SMark.Phalan@Sun.COM 	if( retval )
3347934SMark.Phalan@Sun.COM 	{
3357934SMark.Phalan@Sun.COM 	    com_err (progname, retval, "while getting default realm");
3367934SMark.Phalan@Sun.COM 	    exit(1);
3377934SMark.Phalan@Sun.COM 	}
3387934SMark.Phalan@Sun.COM 	util_context->default_realm = temp;
3397934SMark.Phalan@Sun.COM     }
3407934SMark.Phalan@Sun.COM 
3417934SMark.Phalan@Sun.COM     retval = kadm5_get_config_params(util_context, 1,
3422881Smp153739 				     &global_params, &global_params);
3432881Smp153739     if (retval) {
344*8092SMark.Phalan@Sun.COM 		/* Solaris Kerberos */
345*8092SMark.Phalan@Sun.COM 		com_err(progname, retval,
3460Sstevel@tonic-gate 		    gettext("while retreiving configuration parameters"));
3470Sstevel@tonic-gate 	 exit(1);
3480Sstevel@tonic-gate     }
3492881Smp153739 
3500Sstevel@tonic-gate     /*
3510Sstevel@tonic-gate      * Dump creates files which should not be world-readable.  It is
3520Sstevel@tonic-gate      * easiest to do a single umask call here.
3530Sstevel@tonic-gate      */
3540Sstevel@tonic-gate     (void) umask(077);
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate     (void) memset(&master_key, 0, sizeof (krb5_keyblock));
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate     if ((global_params.enctype != ENCTYPE_UNKNOWN) &&
359781Sgtb 	(!krb5_c_valid_enctype(global_params.enctype))) {
360*8092SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
361*8092SMark.Phalan@Sun.COM 	com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
3620Sstevel@tonic-gate 	    gettext("while setting up enctype %d"), global_params.enctype);
363*8092SMark.Phalan@Sun.COM 	exit(1);
3640Sstevel@tonic-gate     }
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate     cmd = cmd_lookup(cmd_argv[0]);
3670Sstevel@tonic-gate     if (cmd->opendb && open_db_and_mkey())
3682881Smp153739 	 return exit_status;
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	if (global_params.iprop_enabled == TRUE)
3710Sstevel@tonic-gate 		ulog_set_role(util_context, IPROP_MASTER);
3720Sstevel@tonic-gate 	else
3730Sstevel@tonic-gate 		ulog_set_role(util_context, IPROP_NULL);
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate     (*cmd->func)(cmd_argc, cmd_argv);
3760Sstevel@tonic-gate 
3774960Swillf     if( db_name_tmp )
3784960Swillf 	free( db_name_tmp );
3794960Swillf 
3804960Swillf     if( db5util_db_args )
3814960Swillf 	free(db5util_db_args);
3824960Swillf 
3830Sstevel@tonic-gate     kadm5_free_config_params(util_context, &global_params);
3840Sstevel@tonic-gate     krb5_free_context(util_context);
3852881Smp153739     return exit_status;
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate #if 0
3890Sstevel@tonic-gate /*
3900Sstevel@tonic-gate  * This function is no longer used in kdb5_util (and it would no
3910Sstevel@tonic-gate  * longer work, anyway).
3920Sstevel@tonic-gate  */
3932881Smp153739 void set_dbname(argc, argv)
3940Sstevel@tonic-gate     int argc;
3950Sstevel@tonic-gate     char *argv[];
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate     krb5_error_code retval;
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate     if (argc < 3) {
400*8092SMark.Phalan@Sun.COM 		/* Solaris Kerberos */
401*8092SMark.Phalan@Sun.COM 		com_err(progname, 0, gettext("Too few arguments"));
402*8092SMark.Phalan@Sun.COM 		com_err(progname, 0, gettext("Usage: %s dbpathname realmname"),
403*8092SMark.Phalan@Sun.COM 			progname);
4040Sstevel@tonic-gate 	exit_status++;
4050Sstevel@tonic-gate 	return;
4060Sstevel@tonic-gate     }
4070Sstevel@tonic-gate     if (dbactive) {
4084960Swillf 	if ((retval = krb5_db_fini(util_context)) && retval!= KRB5_KDB_DBNOTINITED) {
409*8092SMark.Phalan@Sun.COM 	    /* Solaris Kerberos */
410*8092SMark.Phalan@Sun.COM 	    com_err(progname, retval, gettext("while closing previous database"));
4110Sstevel@tonic-gate 	    exit_status++;
4120Sstevel@tonic-gate 	    return;
4130Sstevel@tonic-gate 	}
4140Sstevel@tonic-gate 	if (valid_master_key) {
4150Sstevel@tonic-gate 	    krb5_free_keyblock_contents(util_context, &master_key);
4164960Swillf 	    master_key.contents = NULL;
4170Sstevel@tonic-gate 	    valid_master_key = 0;
4180Sstevel@tonic-gate 	}
4190Sstevel@tonic-gate 	krb5_free_principal(util_context, master_princ);
4200Sstevel@tonic-gate 	dbactive = FALSE;
4210Sstevel@tonic-gate     }
4220Sstevel@tonic-gate 
423*8092SMark.Phalan@Sun.COM     /* Solaris Kerberos */
424*8092SMark.Phalan@Sun.COM     (void) set_dbname_help(progname, argv[1]);
4252881Smp153739     return;
4260Sstevel@tonic-gate }
4270Sstevel@tonic-gate #endif
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate /*
4300Sstevel@tonic-gate  * open_db_and_mkey: Opens the KDC and policy database, and sets the
4310Sstevel@tonic-gate  * global master_* variables.  Sets dbactive to TRUE if the databases
4320Sstevel@tonic-gate  * are opened, and valid_master_key to 1 if the global master
4330Sstevel@tonic-gate  * variables are set properly.  Returns 0 on success, and 1 on
4340Sstevel@tonic-gate  * failure, but it is not considered a failure if the master key
4350Sstevel@tonic-gate  * cannot be fetched (the master key stash file may not exist when the
4360Sstevel@tonic-gate  * program is run).
4370Sstevel@tonic-gate  */
open_db_and_mkey()4382881Smp153739 static int open_db_and_mkey()
4390Sstevel@tonic-gate {
4400Sstevel@tonic-gate     krb5_error_code retval;
4410Sstevel@tonic-gate     int nentries;
4420Sstevel@tonic-gate     krb5_boolean more;
4430Sstevel@tonic-gate     krb5_data scratch, pwd, seed;
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate     dbactive = FALSE;
4460Sstevel@tonic-gate     valid_master_key = 0;
4470Sstevel@tonic-gate 
4484960Swillf     if ((retval = krb5_db_open(util_context, db5util_db_args,
4494960Swillf 			       KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) {
4504960Swillf 	com_err(progname, retval, "while initializing database");
4510Sstevel@tonic-gate 	exit_status++;
4520Sstevel@tonic-gate 	return(1);
4530Sstevel@tonic-gate     }
4542881Smp153739 
4550Sstevel@tonic-gate    /* assemble & parse the master key name */
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate     if ((retval = krb5_db_setup_mkey_name(util_context,
4580Sstevel@tonic-gate 					  global_params.mkey_name,
4590Sstevel@tonic-gate 					  global_params.realm,
4600Sstevel@tonic-gate 					  0, &master_princ))) {
4610Sstevel@tonic-gate 		com_err(progname, retval,
4620Sstevel@tonic-gate 		    gettext("while setting up master key name"));
4630Sstevel@tonic-gate 	exit_status++;
4640Sstevel@tonic-gate 	return(1);
4650Sstevel@tonic-gate     }
4660Sstevel@tonic-gate     nentries = 1;
4670Sstevel@tonic-gate     if ((retval = krb5_db_get_principal(util_context, master_princ,
4680Sstevel@tonic-gate 					&master_entry, &nentries, &more))) {
4690Sstevel@tonic-gate 		com_err(progname, retval,
4700Sstevel@tonic-gate 		    gettext("while retrieving master entry"));
4710Sstevel@tonic-gate 	exit_status++;
4720Sstevel@tonic-gate 	(void) krb5_db_fini(util_context);
4730Sstevel@tonic-gate 	return(1);
4740Sstevel@tonic-gate     } else if (more) {
4750Sstevel@tonic-gate 	com_err(progname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE,
4760Sstevel@tonic-gate 		    gettext("while retrieving master entry"));
4770Sstevel@tonic-gate 	exit_status++;
4780Sstevel@tonic-gate 	(void) krb5_db_fini(util_context);
4790Sstevel@tonic-gate 	return(1);
4800Sstevel@tonic-gate     } else if (!nentries) {
4810Sstevel@tonic-gate 		com_err(progname, KRB5_KDB_NOENTRY,
4820Sstevel@tonic-gate 		    gettext("while retrieving master entry"));
4830Sstevel@tonic-gate 	exit_status++;
4840Sstevel@tonic-gate 	(void) krb5_db_fini(util_context);
4850Sstevel@tonic-gate 	return(1);
4860Sstevel@tonic-gate     }
4872881Smp153739 
4880Sstevel@tonic-gate     krb5_db_free_principal(util_context, &master_entry, nentries);
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate     /* the databases are now open, and the master principal exists */
4910Sstevel@tonic-gate     dbactive = TRUE;
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate     if (mkey_password) {
4940Sstevel@tonic-gate 	pwd.data = mkey_password;
4950Sstevel@tonic-gate 	pwd.length = strlen(mkey_password);
4962881Smp153739 	retval = krb5_principal2salt(util_context, master_princ, &scratch);
4970Sstevel@tonic-gate 	if (retval) {
4980Sstevel@tonic-gate 		com_err(progname, retval,
4990Sstevel@tonic-gate 		    gettext("while calculated master key salt"));
500*8092SMark.Phalan@Sun.COM 	    /* Solaris Kerberos */
501*8092SMark.Phalan@Sun.COM 	    exit_status++;
5022881Smp153739 	    return(1);
5030Sstevel@tonic-gate 	}
5042881Smp153739 
5050Sstevel@tonic-gate 	/* If no encryption type is set, use the default */
5060Sstevel@tonic-gate 	if (global_params.enctype == ENCTYPE_UNKNOWN) {
5070Sstevel@tonic-gate 	    global_params.enctype = DEFAULT_KDC_ENCTYPE;
508781Sgtb 	    if (!krb5_c_valid_enctype(global_params.enctype))
5090Sstevel@tonic-gate 		com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
5100Sstevel@tonic-gate 			gettext("while setting up enctype %d"),
5110Sstevel@tonic-gate 			global_params.enctype);
5120Sstevel@tonic-gate 	}
5130Sstevel@tonic-gate 
5147934SMark.Phalan@Sun.COM 	retval = krb5_c_string_to_key(util_context, global_params.enctype,
5157934SMark.Phalan@Sun.COM 				      &pwd, &scratch, &master_key);
5160Sstevel@tonic-gate 	if (retval) {
5170Sstevel@tonic-gate 	    com_err(progname, retval,
5180Sstevel@tonic-gate 		gettext("while transforming master key from password"));
519*8092SMark.Phalan@Sun.COM 	    /* Solaris Kerberos */
520*8092SMark.Phalan@Sun.COM 	    exit_status++;
5210Sstevel@tonic-gate 	    return(1);
5220Sstevel@tonic-gate 	}
5230Sstevel@tonic-gate 	free(scratch.data);
5240Sstevel@tonic-gate 	mkey_password = 0;
5250Sstevel@tonic-gate     } else if ((retval = krb5_db_fetch_mkey(util_context, master_princ,
5260Sstevel@tonic-gate 					    global_params.enctype,
5270Sstevel@tonic-gate 					    manual_mkey, FALSE,
5280Sstevel@tonic-gate 					    global_params.stash_file,
5290Sstevel@tonic-gate 					    0, &master_key))) {
5300Sstevel@tonic-gate 	com_err(progname, retval,
5310Sstevel@tonic-gate 	    gettext("while reading master key"));
5320Sstevel@tonic-gate 	com_err(progname, 0,
5330Sstevel@tonic-gate 	    gettext("Warning: proceeding without master key"));
5344621Ssemery 	/*
5354621Ssemery 	 * Solaris Kerberos: We don't want to count as an error if for instance
5364621Ssemery 	 * the stash file is not present and we are trying to automate
5374621Ssemery 	 * propagation, which really doesn't need a master key to do so.
5384621Ssemery 	 */
5394621Ssemery 	if (retval != KRB5_KDB_CANTREAD_STORED)
5404621Ssemery 		exit_status++;
5410Sstevel@tonic-gate 	return(0);
5420Sstevel@tonic-gate     }
5430Sstevel@tonic-gate     if ((retval = krb5_db_verify_master_key(util_context, master_princ,
5440Sstevel@tonic-gate 		&master_key))) {
5450Sstevel@tonic-gate 	com_err(progname, retval,
5460Sstevel@tonic-gate 		gettext("while verifying master key"));
5470Sstevel@tonic-gate 	exit_status++;
5480Sstevel@tonic-gate 	krb5_free_keyblock_contents(util_context, &master_key);
5490Sstevel@tonic-gate 	return(1);
5500Sstevel@tonic-gate     }
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate     seed.length = master_key.length;
5530Sstevel@tonic-gate     seed.data = (char *)master_key.contents;
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate     if ((retval = krb5_c_random_seed(util_context, &seed))) {
5560Sstevel@tonic-gate 	com_err(progname, retval,
5570Sstevel@tonic-gate 		gettext("while initializing random key generator"));
5580Sstevel@tonic-gate 	exit_status++;
5590Sstevel@tonic-gate 	krb5_free_keyblock_contents(util_context, &master_key);
5600Sstevel@tonic-gate 	return(1);
5610Sstevel@tonic-gate     }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate     valid_master_key = 1;
5640Sstevel@tonic-gate     dbactive = TRUE;
5652881Smp153739     return 0;
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate #ifdef HAVE_GETCWD
5690Sstevel@tonic-gate #undef getwd
5700Sstevel@tonic-gate #endif
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate int
quit()5730Sstevel@tonic-gate quit()
5740Sstevel@tonic-gate {
5750Sstevel@tonic-gate     krb5_error_code retval;
5760Sstevel@tonic-gate     static krb5_boolean finished = 0;
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate     if (finished)
5792881Smp153739 	return 0;
5800Sstevel@tonic-gate     retval = krb5_db_fini(util_context);
5810Sstevel@tonic-gate     krb5_free_keyblock_contents(util_context, &master_key);
5820Sstevel@tonic-gate     finished = TRUE;
5830Sstevel@tonic-gate     krb5_free_context(util_context);
5840Sstevel@tonic-gate     if (retval && retval != KRB5_KDB_DBNOTINITED) {
5850Sstevel@tonic-gate 		com_err(progname, retval, gettext("while closing database"));
5860Sstevel@tonic-gate 	exit_status++;
5872881Smp153739 	return 1;
5880Sstevel@tonic-gate     }
5892881Smp153739     return 0;
5900Sstevel@tonic-gate }
5910Sstevel@tonic-gate 
5922881Smp153739 static void
add_random_key(argc,argv)5930Sstevel@tonic-gate add_random_key(argc, argv)
5940Sstevel@tonic-gate     int argc;
5950Sstevel@tonic-gate     char **argv;
5960Sstevel@tonic-gate {
5970Sstevel@tonic-gate     krb5_error_code ret;
5980Sstevel@tonic-gate     krb5_principal princ;
5990Sstevel@tonic-gate     krb5_db_entry dbent;
6002881Smp153739     int n;
6010Sstevel@tonic-gate     krb5_boolean more;
6020Sstevel@tonic-gate     krb5_timestamp now;
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate     krb5_key_salt_tuple *keysalts = NULL;
6050Sstevel@tonic-gate     krb5_int32 num_keysalts = 0;
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate     int free_keysalts;
608*8092SMark.Phalan@Sun.COM     /* Solaris Kerberos */
609*8092SMark.Phalan@Sun.COM     char *me = progname;
6100Sstevel@tonic-gate     char *ks_str = NULL;
6110Sstevel@tonic-gate     char *pr_str;
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate     if (argc < 2)
6140Sstevel@tonic-gate 	usage();
6150Sstevel@tonic-gate     for (argv++, argc--; *argv; argv++, argc--) {
6160Sstevel@tonic-gate 	if (!strcmp(*argv, "-e")) {
6170Sstevel@tonic-gate 	    argv++; argc--;
6180Sstevel@tonic-gate 	    ks_str = *argv;
6190Sstevel@tonic-gate 	    continue;
6200Sstevel@tonic-gate 	} else
6210Sstevel@tonic-gate 	    break;
6220Sstevel@tonic-gate     }
6230Sstevel@tonic-gate     if (argc < 1)
6240Sstevel@tonic-gate 	usage();
6250Sstevel@tonic-gate     pr_str = *argv;
6260Sstevel@tonic-gate     ret = krb5_parse_name(util_context, pr_str, &princ);
6270Sstevel@tonic-gate     if (ret) {
6280Sstevel@tonic-gate 	com_err(me, ret, gettext("while parsing principal name %s"), pr_str);
6292881Smp153739 	exit_status++;
6302881Smp153739 	return;
6310Sstevel@tonic-gate     }
6320Sstevel@tonic-gate     n = 1;
6330Sstevel@tonic-gate     ret = krb5_db_get_principal(util_context, princ, &dbent,
6340Sstevel@tonic-gate 				&n, &more);
6350Sstevel@tonic-gate     if (ret) {
6360Sstevel@tonic-gate 	com_err(me, ret, gettext("while fetching principal %s"), pr_str);
6372881Smp153739 	exit_status++;
6382881Smp153739 	return;
6390Sstevel@tonic-gate     }
6400Sstevel@tonic-gate     if (n != 1) {
6410Sstevel@tonic-gate 	fprintf(stderr, gettext("principal %s not found\n"), pr_str);
6422881Smp153739 	exit_status++;
6432881Smp153739 	return;
6440Sstevel@tonic-gate     }
6450Sstevel@tonic-gate     if (more) {
6460Sstevel@tonic-gate 	fprintf(stderr, gettext("principal %s not unique\n"), pr_str);
6474960Swillf 	krb5_db_free_principal(util_context, &dbent, 1);
6482881Smp153739 	exit_status++;
6492881Smp153739 	return;
6500Sstevel@tonic-gate     }
6510Sstevel@tonic-gate     ret = krb5_string_to_keysalts(ks_str,
6520Sstevel@tonic-gate 				  ", \t", ":.-", 0,
6530Sstevel@tonic-gate 				  &keysalts,
6540Sstevel@tonic-gate 				  &num_keysalts);
6550Sstevel@tonic-gate     if (ret) {
6560Sstevel@tonic-gate 	com_err(me, ret, gettext("while parsing keysalts %s"), ks_str);
6572881Smp153739 	exit_status++;
6582881Smp153739 	return;
6590Sstevel@tonic-gate     }
6600Sstevel@tonic-gate     if (!num_keysalts || keysalts == NULL) {
6610Sstevel@tonic-gate 	num_keysalts = global_params.num_keysalts;
6620Sstevel@tonic-gate 	keysalts = global_params.keysalts;
6630Sstevel@tonic-gate 	free_keysalts = 0;
6640Sstevel@tonic-gate     } else
6650Sstevel@tonic-gate 	free_keysalts = 1;
6660Sstevel@tonic-gate     ret = krb5_dbe_ark(util_context, &master_key,
6670Sstevel@tonic-gate 		       keysalts, num_keysalts,
6680Sstevel@tonic-gate 		       &dbent);
6690Sstevel@tonic-gate     if (free_keysalts)
6700Sstevel@tonic-gate 	free(keysalts);
6710Sstevel@tonic-gate     if (ret) {
6720Sstevel@tonic-gate 	com_err(me, ret, gettext("while randomizing principal %s"), pr_str);
6734960Swillf 	krb5_db_free_principal(util_context, &dbent, 1);
6742881Smp153739 	exit_status++;
6752881Smp153739 	return;
6760Sstevel@tonic-gate     }
6770Sstevel@tonic-gate     dbent.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
6780Sstevel@tonic-gate     ret = krb5_timeofday(util_context, &now);
6790Sstevel@tonic-gate     if (ret) {
6800Sstevel@tonic-gate 	com_err(me, ret, gettext("while getting time"));
6814960Swillf 	krb5_db_free_principal(util_context, &dbent, 1);
6822881Smp153739 	exit_status++;
6832881Smp153739 	return;
6840Sstevel@tonic-gate     }
6850Sstevel@tonic-gate     ret = krb5_dbe_update_last_pwd_change(util_context, &dbent, now);
6860Sstevel@tonic-gate     if (ret) {
6870Sstevel@tonic-gate 	com_err(me, ret, gettext("while setting changetime"));
6884960Swillf 	krb5_db_free_principal(util_context, &dbent, 1);
6892881Smp153739 	exit_status++;
6902881Smp153739 	return;
6910Sstevel@tonic-gate     }
6920Sstevel@tonic-gate     ret = krb5_db_put_principal(util_context, &dbent, &n);
6934960Swillf     krb5_db_free_principal(util_context, &dbent, 1);
6940Sstevel@tonic-gate     if (ret) {
6950Sstevel@tonic-gate 	com_err(me, ret, gettext("while saving principal %s"), pr_str);
6962881Smp153739 	exit_status++;
6972881Smp153739 	return;
6980Sstevel@tonic-gate     }
6990Sstevel@tonic-gate     printf("%s changed\n", pr_str);
7000Sstevel@tonic-gate }
701