17c478bd9Sstevel@tonic-gate /*
278894ffcSmp  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  *	Openvision retains the copyright to derivative works of
107c478bd9Sstevel@tonic-gate  *	this source code.  Do *NOT* create a derivative of this
117c478bd9Sstevel@tonic-gate  *	source code before consulting with your legal department.
127c478bd9Sstevel@tonic-gate  *	Do *NOT* integrate *ANY* of this source code into another
137c478bd9Sstevel@tonic-gate  *	product before consulting with your legal department.
147c478bd9Sstevel@tonic-gate  *
157c478bd9Sstevel@tonic-gate  *	For further information, read the top-level Openvision
167c478bd9Sstevel@tonic-gate  *	copyright which is contained in the top-level MIT Kerberos
177c478bd9Sstevel@tonic-gate  *	copyright.
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
207c478bd9Sstevel@tonic-gate  *
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate 
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate /*
257c478bd9Sstevel@tonic-gate  * admin/edit/kdb5_edit.c
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  * (C) Copyright 1990,1991, 1996 by the Massachusetts Institute of Technology.
287c478bd9Sstevel@tonic-gate  * All Rights Reserved.
297c478bd9Sstevel@tonic-gate  *
307c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
317c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
327c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
337c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
34*55fea89dSDan Cross  *
357c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
367c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
377c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
387c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
397c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
407c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
417c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
427c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
437c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
447c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
457c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
467c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
477c478bd9Sstevel@tonic-gate  * or implied warranty.
48*55fea89dSDan Cross  *
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  * Edit a KDC database.
517c478bd9Sstevel@tonic-gate  */
527c478bd9Sstevel@tonic-gate 
5356a424ccSmp /*
5456a424ccSmp  * Copyright (C) 1998 by the FundsXpress, INC.
55*55fea89dSDan Cross  *
5656a424ccSmp  * All rights reserved.
57*55fea89dSDan Cross  *
5856a424ccSmp  * Export of this software from the United States of America may require
5956a424ccSmp  * a specific license from the United States Government.  It is the
6056a424ccSmp  * responsibility of any person or organization contemplating export to
6156a424ccSmp  * obtain such a license before exporting.
62*55fea89dSDan Cross  *
6356a424ccSmp  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
6456a424ccSmp  * distribute this software and its documentation for any purpose and
6556a424ccSmp  * without fee is hereby granted, provided that the above copyright
6656a424ccSmp  * notice appear in all copies and that both that copyright notice and
6756a424ccSmp  * this permission notice appear in supporting documentation, and that
6856a424ccSmp  * the name of FundsXpress. not be used in advertising or publicity pertaining
6956a424ccSmp  * to distribution of the software without specific, written prior
7056a424ccSmp  * permission.  FundsXpress makes no representations about the suitability of
7156a424ccSmp  * this software for any purpose.  It is provided "as is" without express
7256a424ccSmp  * or implied warranty.
73*55fea89dSDan Cross  *
7456a424ccSmp  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
7556a424ccSmp  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
7656a424ccSmp  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
7756a424ccSmp  */
7856a424ccSmp 
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate  *  Yes, I know this is a hack, but we need admin.h without including the
817c478bd9Sstevel@tonic-gate  *  rpc.h header. Additionally, our rpc.h header brings in
827c478bd9Sstevel@tonic-gate  *  a des.h header which causes other problems.
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate #define	_RPC_RPC_H
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate #include <stdio.h>
877c478bd9Sstevel@tonic-gate #include <k5-int.h>
887c478bd9Sstevel@tonic-gate #include <kadm5/admin.h>
897c478bd9Sstevel@tonic-gate #include <rpc/types.h>
9054925bf6Swillf #include <krb5/adm_proto.h>
917c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
927c478bd9Sstevel@tonic-gate #include <time.h>
937c478bd9Sstevel@tonic-gate #include <libintl.h>
947c478bd9Sstevel@tonic-gate #include <locale.h>
957c478bd9Sstevel@tonic-gate #include "kdb5_util.h"
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate char	*Err_no_master_msg = "Master key not entered!\n";
987c478bd9Sstevel@tonic-gate char	*Err_no_database = "Database not currently opened!\n";
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate  * XXX Ick, ick, ick.  These global variables shouldn't be global....
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate char *mkey_password = 0;
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate  * I can't figure out any way for this not to be global, given how ss
1077c478bd9Sstevel@tonic-gate  * works.
1087c478bd9Sstevel@tonic-gate  */
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate int exit_status = 0;
1117c478bd9Sstevel@tonic-gate krb5_context util_context;
1127c478bd9Sstevel@tonic-gate kadm5_config_params global_params;
1137c478bd9Sstevel@tonic-gate 
usage()11456a424ccSmp void usage()
1157c478bd9Sstevel@tonic-gate {
11656a424ccSmp      fprintf(stderr, "%s: "
11754925bf6Swillf 	   "kdb5_util [-x db_args]* [-r realm] [-d dbname] [-k mkeytype] [-M mkeyname]\n"
11854925bf6Swillf 	     "\t        [-sf stashfilename] [-P password] [-m] cmd [cmd_options]\n"
11956a424ccSmp 	     "\tcreate	[-s]\n"
12056a424ccSmp 	     "\tdestroy	[-f]\n"
12156a424ccSmp 	     "\tstash	[-f keyfile]\n"
12256a424ccSmp 	     "\tdump	[-old] [-ov] [-b6] [-verbose] [filename	[princs...]]\n"
12356a424ccSmp 	     "\t	[-mkey_convert] [-new_mkey_file mkey_file]\n"
12456a424ccSmp 	     "\t	[-rev] [-recurse] [filename [princs...]]\n"
12556a424ccSmp 	     "\tload	[-old] [-ov] [-b6] [-verbose] [-update] filename\n"
12654925bf6Swillf 	     "\tark	[-e etype_list] principal\n"
12754925bf6Swillf 	     "\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n"
12854925bf6Swillf 	     "\t\t\tLook at each database documentation for supported arguments\n",
12954925bf6Swillf 		gettext("Usage"));
13056a424ccSmp      exit(1);
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate krb5_keyblock master_key;
1347c478bd9Sstevel@tonic-gate extern krb5_principal master_princ;
1357c478bd9Sstevel@tonic-gate krb5_db_entry master_entry;
1367c478bd9Sstevel@tonic-gate int	valid_master_key = 0;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate char *progname;
1397c478bd9Sstevel@tonic-gate krb5_boolean manual_mkey = FALSE;
1407c478bd9Sstevel@tonic-gate krb5_boolean dbactive = FALSE;
1417c478bd9Sstevel@tonic-gate 
14256a424ccSmp static int open_db_and_mkey(void);
14356a424ccSmp 
14456a424ccSmp static void add_random_key(int, char **);
145*55fea89dSDan Cross 
14656a424ccSmp typedef void (*cmd_func)(int, char **);
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate struct _cmd_table {
1497c478bd9Sstevel@tonic-gate      char *name;
1507c478bd9Sstevel@tonic-gate      cmd_func func;
1517c478bd9Sstevel@tonic-gate      int opendb;
1527c478bd9Sstevel@tonic-gate } cmd_table[] = {
15356a424ccSmp      {"create", kdb5_create, 0},
15456a424ccSmp      {"destroy", kdb5_destroy, 1},
15556a424ccSmp      {"stash", kdb5_stash, 1},
15656a424ccSmp      {"dump", dump_db, 1},
15756a424ccSmp      {"load", load_db, 0},
15856a424ccSmp      {"ark", add_random_key, 1},
15956a424ccSmp      {NULL, NULL, 0},
1607c478bd9Sstevel@tonic-gate };
1617c478bd9Sstevel@tonic-gate 
cmd_lookup(name)16256a424ccSmp static struct _cmd_table *cmd_lookup(name)
1637c478bd9Sstevel@tonic-gate    char *name;
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate      struct _cmd_table *cmd = cmd_table;
1667c478bd9Sstevel@tonic-gate      while (cmd->name) {
1677c478bd9Sstevel@tonic-gate 	  if (strcmp(cmd->name, name) == 0)
16856a424ccSmp 	       return cmd;
1697c478bd9Sstevel@tonic-gate 	  else
1707c478bd9Sstevel@tonic-gate 	       cmd++;
1717c478bd9Sstevel@tonic-gate      }
172*55fea89dSDan Cross 
17356a424ccSmp      return NULL;
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate 
17656a424ccSmp #define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(usage(), NULL))
17754925bf6Swillf 
17854925bf6Swillf char **db5util_db_args = NULL;
17954925bf6Swillf int    db5util_db_args_size = 0;
180*55fea89dSDan Cross 
extended_com_err_fn(const char * myprog,errcode_t code,const char * fmt,va_list args)18154925bf6Swillf static void extended_com_err_fn (const char *myprog, errcode_t code,
18254925bf6Swillf 				 const char *fmt, va_list args)
18354925bf6Swillf {
18454925bf6Swillf     const char *emsg;
18554925bf6Swillf     if (code) {
18654925bf6Swillf 	emsg = krb5_get_error_message (util_context, code);
18754925bf6Swillf 	fprintf (stderr, "%s: %s ", myprog, emsg);
18854925bf6Swillf 	krb5_free_error_message (util_context, emsg);
18954925bf6Swillf     } else {
19054925bf6Swillf 	fprintf (stderr, "%s: ", myprog);
19154925bf6Swillf     }
19254925bf6Swillf     vfprintf (stderr, fmt, args);
19354925bf6Swillf     fprintf (stderr, "\n");
19454925bf6Swillf }
19554925bf6Swillf 
add_db_arg(char * arg)19654925bf6Swillf int add_db_arg(char *arg)
19754925bf6Swillf {
19854925bf6Swillf     char **temp;
19954925bf6Swillf     db5util_db_args_size++;
20054925bf6Swillf     temp = realloc(db5util_db_args,
20154925bf6Swillf 		   sizeof(char *) * (db5util_db_args_size + 1));
20254925bf6Swillf     if (temp == NULL)
20354925bf6Swillf 	return 0;
20454925bf6Swillf     db5util_db_args = temp;
20554925bf6Swillf     db5util_db_args[db5util_db_args_size-1] = arg;
20654925bf6Swillf     db5util_db_args[db5util_db_args_size]   = NULL;
20754925bf6Swillf     return 1;
20854925bf6Swillf }
20954925bf6Swillf 
main(argc,argv)21056a424ccSmp int main(argc, argv)
2117c478bd9Sstevel@tonic-gate     int argc;
2127c478bd9Sstevel@tonic-gate     char *argv[];
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate     struct _cmd_table *cmd = NULL;
215*55fea89dSDan Cross     char *koptarg, **cmd_argv;
21654925bf6Swillf     char *db_name_tmp = NULL;
2177c478bd9Sstevel@tonic-gate     int cmd_argc;
2187c478bd9Sstevel@tonic-gate     krb5_error_code retval;
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
22154925bf6Swillf     set_com_err_hook(extended_com_err_fn);
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)  /* Should be defined by cc -D */
2247c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it weren't */
2257c478bd9Sstevel@tonic-gate #endif
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	Err_no_master_msg = gettext("Master key not entered!\n");
2307c478bd9Sstevel@tonic-gate 	Err_no_database = gettext("Database not currently opened!\n");
2317c478bd9Sstevel@tonic-gate 
23278894ffcSmp 	/*
23378894ffcSmp 	 * Solaris Kerberos:
23478894ffcSmp 	 * Ensure that "progname" is set before calling com_err.
23578894ffcSmp 	 */
23678894ffcSmp 	progname = (strrchr(argv[0], '/') ?
23778894ffcSmp 		    strrchr(argv[0], '/') + 1 : argv[0]);
23878894ffcSmp 
23954925bf6Swillf     retval = kadm5_init_krb5_context(&util_context);
2407c478bd9Sstevel@tonic-gate     if (retval) {
241*55fea89dSDan Cross 	    com_err (progname, retval,
2427c478bd9Sstevel@tonic-gate 		gettext("while initializing Kerberos code"));
2437c478bd9Sstevel@tonic-gate 	    exit(1);
2447c478bd9Sstevel@tonic-gate     }
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate     cmd_argv = (char **) malloc(sizeof(char *)*argc);
2477c478bd9Sstevel@tonic-gate     if (cmd_argv == NULL) {
2487c478bd9Sstevel@tonic-gate 		com_err(progname, ENOMEM,
2497c478bd9Sstevel@tonic-gate 		    gettext("while creating sub-command arguments"));
2507c478bd9Sstevel@tonic-gate 	 exit(1);
2517c478bd9Sstevel@tonic-gate     }
2527c478bd9Sstevel@tonic-gate     memset(cmd_argv, 0, sizeof(char *)*argc);
2537c478bd9Sstevel@tonic-gate     cmd_argc = 1;
254*55fea89dSDan Cross 
25556a424ccSmp     argv++; argc--;
2567c478bd9Sstevel@tonic-gate     while (*argv) {
2577c478bd9Sstevel@tonic-gate        if (strcmp(*argv, "-P") == 0 && ARG_VAL) {
25856a424ccSmp 	    mkey_password = koptarg;
2597c478bd9Sstevel@tonic-gate 	    manual_mkey = TRUE;
2607c478bd9Sstevel@tonic-gate        } else if (strcmp(*argv, "-d") == 0 && ARG_VAL) {
26156a424ccSmp 	    global_params.dbname = koptarg;
2627c478bd9Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_DBNAME;
26354925bf6Swillf 
26454925bf6Swillf 	    db_name_tmp = malloc( strlen(global_params.dbname) + sizeof("dbname="));
26554925bf6Swillf 	    if( db_name_tmp == NULL )
26654925bf6Swillf 	    {
26754925bf6Swillf 		com_err(progname, ENOMEM, "while parsing command arguments");
26854925bf6Swillf 		exit(1);
26954925bf6Swillf 	    }
27054925bf6Swillf 
27154925bf6Swillf 	    strcpy( db_name_tmp, "dbname=");
27254925bf6Swillf 	    strcat( db_name_tmp, global_params.dbname );
27354925bf6Swillf 
27454925bf6Swillf 	    if (!add_db_arg(db_name_tmp)) {
27554925bf6Swillf 		com_err(progname, ENOMEM, "while parsing command arguments\n");
27654925bf6Swillf 		exit(1);
27754925bf6Swillf 	    }
27854925bf6Swillf 
27954925bf6Swillf        } else if (strcmp(*argv, "-x") == 0 && ARG_VAL) {
28054925bf6Swillf 	   if (!add_db_arg(koptarg)) {
28154925bf6Swillf 		com_err(progname, ENOMEM, "while parsing command arguments\n");
28254925bf6Swillf 		exit(1);
28354925bf6Swillf 	   }
28454925bf6Swillf 
2857c478bd9Sstevel@tonic-gate        } else if (strcmp(*argv, "-r") == 0 && ARG_VAL) {
28656a424ccSmp 	    global_params.realm = koptarg;
2877c478bd9Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_REALM;
2887c478bd9Sstevel@tonic-gate 	    /* not sure this is really necessary */
2897c478bd9Sstevel@tonic-gate 	    if ((retval = krb5_set_default_realm(util_context,
2907c478bd9Sstevel@tonic-gate 						 global_params.realm))) {
2917c478bd9Sstevel@tonic-gate 				com_err(progname, retval,
2927c478bd9Sstevel@tonic-gate 					gettext("while setting default "
2937c478bd9Sstevel@tonic-gate 						"realm name"));
2947c478bd9Sstevel@tonic-gate 		 exit(1);
2957c478bd9Sstevel@tonic-gate 	    }
2967c478bd9Sstevel@tonic-gate        } else if (strcmp(*argv, "-k") == 0 && ARG_VAL) {
297dd9ccd46S 	    if (krb5_string_to_enctype(koptarg, &global_params.enctype)) {
298dd9ccd46S 		/* Solaris Kerberos */
299dd9ccd46S 		 com_err(progname, 0, gettext("%s is an invalid enctype"), koptarg);
300dd9ccd46S 	    }
3017c478bd9Sstevel@tonic-gate 	    else
3027c478bd9Sstevel@tonic-gate 		 global_params.mask |= KADM5_CONFIG_ENCTYPE;
3037c478bd9Sstevel@tonic-gate        } else if (strcmp(*argv, "-M") == 0 && ARG_VAL) {
30456a424ccSmp 	    global_params.mkey_name = koptarg;
3057c478bd9Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_MKEY_NAME;
3067c478bd9Sstevel@tonic-gate        } else if (((strcmp(*argv, "-sf") == 0)
3077c478bd9Sstevel@tonic-gate 		/* SUNWresync121 - carry the old -f forward too */
3087c478bd9Sstevel@tonic-gate 		|| (strcmp(*argv, "-f") == 0)) && ARG_VAL) {
30956a424ccSmp 	    global_params.stash_file = koptarg;
3107c478bd9Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_STASH_FILE;
3117c478bd9Sstevel@tonic-gate        } else if (strcmp(*argv, "-m") == 0) {
3127c478bd9Sstevel@tonic-gate 	    manual_mkey = TRUE;
3137c478bd9Sstevel@tonic-gate 	    global_params.mkey_from_kbd = 1;
3147c478bd9Sstevel@tonic-gate 	    global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
3157c478bd9Sstevel@tonic-gate        } else if (cmd_lookup(*argv) != NULL) {
3167c478bd9Sstevel@tonic-gate 	    if (cmd_argv[0] == NULL)
3177c478bd9Sstevel@tonic-gate 		 cmd_argv[0] = *argv;
3187c478bd9Sstevel@tonic-gate 	    else
3197c478bd9Sstevel@tonic-gate 		 usage();
3207c478bd9Sstevel@tonic-gate        } else {
3217c478bd9Sstevel@tonic-gate 	    cmd_argv[cmd_argc++] = *argv;
3227c478bd9Sstevel@tonic-gate        }
32356a424ccSmp        argv++; argc--;
3247c478bd9Sstevel@tonic-gate     }
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate     if (cmd_argv[0] == NULL)
3277c478bd9Sstevel@tonic-gate 	 usage();
328*55fea89dSDan Cross 
329159d09a2SMark Phalan     if( !util_context->default_realm )
330159d09a2SMark Phalan     {
331159d09a2SMark Phalan 	char *temp = NULL;
332159d09a2SMark Phalan 	retval = krb5_get_default_realm(util_context, &temp);
333159d09a2SMark Phalan 	if( retval )
334159d09a2SMark Phalan 	{
335159d09a2SMark Phalan 	    com_err (progname, retval, "while getting default realm");
336159d09a2SMark Phalan 	    exit(1);
337159d09a2SMark Phalan 	}
338159d09a2SMark Phalan 	util_context->default_realm = temp;
339159d09a2SMark Phalan     }
340159d09a2SMark Phalan 
341159d09a2SMark Phalan     retval = kadm5_get_config_params(util_context, 1,
34256a424ccSmp 				     &global_params, &global_params);
34356a424ccSmp     if (retval) {
344dd9ccd46S 		/* Solaris Kerberos */
345dd9ccd46S 		com_err(progname, retval,
3467c478bd9Sstevel@tonic-gate 		    gettext("while retreiving configuration parameters"));
3477c478bd9Sstevel@tonic-gate 	 exit(1);
3487c478bd9Sstevel@tonic-gate     }
34956a424ccSmp 
3507c478bd9Sstevel@tonic-gate     /*
3517c478bd9Sstevel@tonic-gate      * Dump creates files which should not be world-readable.  It is
3527c478bd9Sstevel@tonic-gate      * easiest to do a single umask call here.
3537c478bd9Sstevel@tonic-gate      */
3547c478bd9Sstevel@tonic-gate     (void) umask(077);
3557c478bd9Sstevel@tonic-gate 
356*55fea89dSDan Cross     (void) memset(&master_key, 0, sizeof (krb5_keyblock));
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate     if ((global_params.enctype != ENCTYPE_UNKNOWN) &&
359505d05c7Sgtb 	(!krb5_c_valid_enctype(global_params.enctype))) {
360dd9ccd46S 	/* Solaris Kerberos */
361dd9ccd46S 	com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
3627c478bd9Sstevel@tonic-gate 	    gettext("while setting up enctype %d"), global_params.enctype);
363dd9ccd46S 	exit(1);
3647c478bd9Sstevel@tonic-gate     }
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate     cmd = cmd_lookup(cmd_argv[0]);
3677c478bd9Sstevel@tonic-gate     if (cmd->opendb && open_db_and_mkey())
36856a424ccSmp 	 return exit_status;
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	if (global_params.iprop_enabled == TRUE)
3717c478bd9Sstevel@tonic-gate 		ulog_set_role(util_context, IPROP_MASTER);
3727c478bd9Sstevel@tonic-gate 	else
3737c478bd9Sstevel@tonic-gate 		ulog_set_role(util_context, IPROP_NULL);
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate     (*cmd->func)(cmd_argc, cmd_argv);
3767c478bd9Sstevel@tonic-gate 
37754925bf6Swillf     if( db_name_tmp )
37854925bf6Swillf 	free( db_name_tmp );
37954925bf6Swillf 
38054925bf6Swillf     if( db5util_db_args )
38154925bf6Swillf 	free(db5util_db_args);
38254925bf6Swillf 
3837c478bd9Sstevel@tonic-gate     kadm5_free_config_params(util_context, &global_params);
3847c478bd9Sstevel@tonic-gate     krb5_free_context(util_context);
38556a424ccSmp     return exit_status;
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate #if 0
3897c478bd9Sstevel@tonic-gate /*
3907c478bd9Sstevel@tonic-gate  * This function is no longer used in kdb5_util (and it would no
3917c478bd9Sstevel@tonic-gate  * longer work, anyway).
3927c478bd9Sstevel@tonic-gate  */
39356a424ccSmp void set_dbname(argc, argv)
3947c478bd9Sstevel@tonic-gate     int argc;
3957c478bd9Sstevel@tonic-gate     char *argv[];
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate     krb5_error_code retval;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate     if (argc < 3) {
400dd9ccd46S 		/* Solaris Kerberos */
401dd9ccd46S 		com_err(progname, 0, gettext("Too few arguments"));
402dd9ccd46S 		com_err(progname, 0, gettext("Usage: %s dbpathname realmname"),
403dd9ccd46S 			progname);
4047c478bd9Sstevel@tonic-gate 	exit_status++;
4057c478bd9Sstevel@tonic-gate 	return;
4067c478bd9Sstevel@tonic-gate     }
4077c478bd9Sstevel@tonic-gate     if (dbactive) {
40854925bf6Swillf 	if ((retval = krb5_db_fini(util_context)) && retval!= KRB5_KDB_DBNOTINITED) {
409dd9ccd46S 	    /* Solaris Kerberos */
410dd9ccd46S 	    com_err(progname, retval, gettext("while closing previous database"));
4117c478bd9Sstevel@tonic-gate 	    exit_status++;
4127c478bd9Sstevel@tonic-gate 	    return;
4137c478bd9Sstevel@tonic-gate 	}
4147c478bd9Sstevel@tonic-gate 	if (valid_master_key) {
4157c478bd9Sstevel@tonic-gate 	    krb5_free_keyblock_contents(util_context, &master_key);
41654925bf6Swillf 	    master_key.contents = NULL;
4177c478bd9Sstevel@tonic-gate 	    valid_master_key = 0;
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate 	krb5_free_principal(util_context, master_princ);
4207c478bd9Sstevel@tonic-gate 	dbactive = FALSE;
4217c478bd9Sstevel@tonic-gate     }
4227c478bd9Sstevel@tonic-gate 
423dd9ccd46S     /* Solaris Kerberos */
424dd9ccd46S     (void) set_dbname_help(progname, argv[1]);
42556a424ccSmp     return;
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate #endif
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate  * open_db_and_mkey: Opens the KDC and policy database, and sets the
4317c478bd9Sstevel@tonic-gate  * global master_* variables.  Sets dbactive to TRUE if the databases
4327c478bd9Sstevel@tonic-gate  * are opened, and valid_master_key to 1 if the global master
4337c478bd9Sstevel@tonic-gate  * variables are set properly.  Returns 0 on success, and 1 on
4347c478bd9Sstevel@tonic-gate  * failure, but it is not considered a failure if the master key
4357c478bd9Sstevel@tonic-gate  * cannot be fetched (the master key stash file may not exist when the
4367c478bd9Sstevel@tonic-gate  * program is run).
4377c478bd9Sstevel@tonic-gate  */
open_db_and_mkey()43856a424ccSmp static int open_db_and_mkey()
4397c478bd9Sstevel@tonic-gate {
4407c478bd9Sstevel@tonic-gate     krb5_error_code retval;
4417c478bd9Sstevel@tonic-gate     int nentries;
4427c478bd9Sstevel@tonic-gate     krb5_boolean more;
4437c478bd9Sstevel@tonic-gate     krb5_data scratch, pwd, seed;
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate     dbactive = FALSE;
4467c478bd9Sstevel@tonic-gate     valid_master_key = 0;
4477c478bd9Sstevel@tonic-gate 
448*55fea89dSDan Cross     if ((retval = krb5_db_open(util_context, db5util_db_args,
44954925bf6Swillf 			       KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) {
45054925bf6Swillf 	com_err(progname, retval, "while initializing database");
4517c478bd9Sstevel@tonic-gate 	exit_status++;
4527c478bd9Sstevel@tonic-gate 	return(1);
4537c478bd9Sstevel@tonic-gate     }
45456a424ccSmp 
4557c478bd9Sstevel@tonic-gate    /* assemble & parse the master key name */
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate     if ((retval = krb5_db_setup_mkey_name(util_context,
4587c478bd9Sstevel@tonic-gate 					  global_params.mkey_name,
459*55fea89dSDan Cross 					  global_params.realm,
4607c478bd9Sstevel@tonic-gate 					  0, &master_princ))) {
4617c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
4627c478bd9Sstevel@tonic-gate 		    gettext("while setting up master key name"));
4637c478bd9Sstevel@tonic-gate 	exit_status++;
4647c478bd9Sstevel@tonic-gate 	return(1);
4657c478bd9Sstevel@tonic-gate     }
4667c478bd9Sstevel@tonic-gate     nentries = 1;
467*55fea89dSDan Cross     if ((retval = krb5_db_get_principal(util_context, master_princ,
4687c478bd9Sstevel@tonic-gate 					&master_entry, &nentries, &more))) {
4697c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
4707c478bd9Sstevel@tonic-gate 		    gettext("while retrieving master entry"));
4717c478bd9Sstevel@tonic-gate 	exit_status++;
4727c478bd9Sstevel@tonic-gate 	(void) krb5_db_fini(util_context);
4737c478bd9Sstevel@tonic-gate 	return(1);
4747c478bd9Sstevel@tonic-gate     } else if (more) {
4757c478bd9Sstevel@tonic-gate 	com_err(progname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE,
4767c478bd9Sstevel@tonic-gate 		    gettext("while retrieving master entry"));
4777c478bd9Sstevel@tonic-gate 	exit_status++;
4787c478bd9Sstevel@tonic-gate 	(void) krb5_db_fini(util_context);
4797c478bd9Sstevel@tonic-gate 	return(1);
4807c478bd9Sstevel@tonic-gate     } else if (!nentries) {
4817c478bd9Sstevel@tonic-gate 		com_err(progname, KRB5_KDB_NOENTRY,
4827c478bd9Sstevel@tonic-gate 		    gettext("while retrieving master entry"));
4837c478bd9Sstevel@tonic-gate 	exit_status++;
4847c478bd9Sstevel@tonic-gate 	(void) krb5_db_fini(util_context);
4857c478bd9Sstevel@tonic-gate 	return(1);
4867c478bd9Sstevel@tonic-gate     }
48756a424ccSmp 
4887c478bd9Sstevel@tonic-gate     krb5_db_free_principal(util_context, &master_entry, nentries);
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate     /* the databases are now open, and the master principal exists */
4917c478bd9Sstevel@tonic-gate     dbactive = TRUE;
492*55fea89dSDan Cross 
4937c478bd9Sstevel@tonic-gate     if (mkey_password) {
4947c478bd9Sstevel@tonic-gate 	pwd.data = mkey_password;
4957c478bd9Sstevel@tonic-gate 	pwd.length = strlen(mkey_password);
49656a424ccSmp 	retval = krb5_principal2salt(util_context, master_princ, &scratch);
4977c478bd9Sstevel@tonic-gate 	if (retval) {
4987c478bd9Sstevel@tonic-gate 		com_err(progname, retval,
4997c478bd9Sstevel@tonic-gate 		    gettext("while calculated master key salt"));
500dd9ccd46S 	    /* Solaris Kerberos */
501dd9ccd46S 	    exit_status++;
50256a424ccSmp 	    return(1);
5037c478bd9Sstevel@tonic-gate 	}
50456a424ccSmp 
5057c478bd9Sstevel@tonic-gate 	/* If no encryption type is set, use the default */
5067c478bd9Sstevel@tonic-gate 	if (global_params.enctype == ENCTYPE_UNKNOWN) {
5077c478bd9Sstevel@tonic-gate 	    global_params.enctype = DEFAULT_KDC_ENCTYPE;
508505d05c7Sgtb 	    if (!krb5_c_valid_enctype(global_params.enctype))
5097c478bd9Sstevel@tonic-gate 		com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
5107c478bd9Sstevel@tonic-gate 			gettext("while setting up enctype %d"),
5117c478bd9Sstevel@tonic-gate 			global_params.enctype);
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate 
514*55fea89dSDan Cross 	retval = krb5_c_string_to_key(util_context, global_params.enctype,
515159d09a2SMark Phalan 				      &pwd, &scratch, &master_key);
5167c478bd9Sstevel@tonic-gate 	if (retval) {
5177c478bd9Sstevel@tonic-gate 	    com_err(progname, retval,
5187c478bd9Sstevel@tonic-gate 		gettext("while transforming master key from password"));
519dd9ccd46S 	    /* Solaris Kerberos */
520dd9ccd46S 	    exit_status++;
5217c478bd9Sstevel@tonic-gate 	    return(1);
5227c478bd9Sstevel@tonic-gate 	}
5237c478bd9Sstevel@tonic-gate 	free(scratch.data);
5247c478bd9Sstevel@tonic-gate 	mkey_password = 0;
525*55fea89dSDan Cross     } else if ((retval = krb5_db_fetch_mkey(util_context, master_princ,
5267c478bd9Sstevel@tonic-gate 					    global_params.enctype,
5277c478bd9Sstevel@tonic-gate 					    manual_mkey, FALSE,
5287c478bd9Sstevel@tonic-gate 					    global_params.stash_file,
5297c478bd9Sstevel@tonic-gate 					    0, &master_key))) {
5307c478bd9Sstevel@tonic-gate 	com_err(progname, retval,
5317c478bd9Sstevel@tonic-gate 	    gettext("while reading master key"));
5327c478bd9Sstevel@tonic-gate 	com_err(progname, 0,
5337c478bd9Sstevel@tonic-gate 	    gettext("Warning: proceeding without master key"));
5343441f6a1Ssemery 	/*
5353441f6a1Ssemery 	 * Solaris Kerberos: We don't want to count as an error if for instance
5363441f6a1Ssemery 	 * the stash file is not present and we are trying to automate
5373441f6a1Ssemery 	 * propagation, which really doesn't need a master key to do so.
5383441f6a1Ssemery 	 */
5393441f6a1Ssemery 	if (retval != KRB5_KDB_CANTREAD_STORED)
5403441f6a1Ssemery 		exit_status++;
5417c478bd9Sstevel@tonic-gate 	return(0);
5427c478bd9Sstevel@tonic-gate     }
543*55fea89dSDan Cross     if ((retval = krb5_db_verify_master_key(util_context, master_princ,
5447c478bd9Sstevel@tonic-gate 		&master_key))) {
5457c478bd9Sstevel@tonic-gate 	com_err(progname, retval,
5467c478bd9Sstevel@tonic-gate 		gettext("while verifying master key"));
5477c478bd9Sstevel@tonic-gate 	exit_status++;
5487c478bd9Sstevel@tonic-gate 	krb5_free_keyblock_contents(util_context, &master_key);
5497c478bd9Sstevel@tonic-gate 	return(1);
5507c478bd9Sstevel@tonic-gate     }
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate     seed.length = master_key.length;
5537c478bd9Sstevel@tonic-gate     seed.data = (char *)master_key.contents;
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate     if ((retval = krb5_c_random_seed(util_context, &seed))) {
556*55fea89dSDan Cross 	com_err(progname, retval,
5577c478bd9Sstevel@tonic-gate 		gettext("while initializing random key generator"));
5587c478bd9Sstevel@tonic-gate 	exit_status++;
5597c478bd9Sstevel@tonic-gate 	krb5_free_keyblock_contents(util_context, &master_key);
5607c478bd9Sstevel@tonic-gate 	return(1);
5617c478bd9Sstevel@tonic-gate     }
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate     valid_master_key = 1;
5647c478bd9Sstevel@tonic-gate     dbactive = TRUE;
56556a424ccSmp     return 0;
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate #ifdef HAVE_GETCWD
5697c478bd9Sstevel@tonic-gate #undef getwd
5707c478bd9Sstevel@tonic-gate #endif
5717c478bd9Sstevel@tonic-gate 
572*55fea89dSDan Cross int
quit()5737c478bd9Sstevel@tonic-gate quit()
5747c478bd9Sstevel@tonic-gate {
5757c478bd9Sstevel@tonic-gate     krb5_error_code retval;
5767c478bd9Sstevel@tonic-gate     static krb5_boolean finished = 0;
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate     if (finished)
57956a424ccSmp 	return 0;
5807c478bd9Sstevel@tonic-gate     retval = krb5_db_fini(util_context);
5817c478bd9Sstevel@tonic-gate     krb5_free_keyblock_contents(util_context, &master_key);
5827c478bd9Sstevel@tonic-gate     finished = TRUE;
5837c478bd9Sstevel@tonic-gate     krb5_free_context(util_context);
5847c478bd9Sstevel@tonic-gate     if (retval && retval != KRB5_KDB_DBNOTINITED) {
5857c478bd9Sstevel@tonic-gate 		com_err(progname, retval, gettext("while closing database"));
5867c478bd9Sstevel@tonic-gate 	exit_status++;
58756a424ccSmp 	return 1;
5887c478bd9Sstevel@tonic-gate     }
58956a424ccSmp     return 0;
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate 
59256a424ccSmp static void
add_random_key(argc,argv)5937c478bd9Sstevel@tonic-gate add_random_key(argc, argv)
5947c478bd9Sstevel@tonic-gate     int argc;
5957c478bd9Sstevel@tonic-gate     char **argv;
5967c478bd9Sstevel@tonic-gate {
5977c478bd9Sstevel@tonic-gate     krb5_error_code ret;
5987c478bd9Sstevel@tonic-gate     krb5_principal princ;
5997c478bd9Sstevel@tonic-gate     krb5_db_entry dbent;
60056a424ccSmp     int n;
6017c478bd9Sstevel@tonic-gate     krb5_boolean more;
6027c478bd9Sstevel@tonic-gate     krb5_timestamp now;
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate     krb5_key_salt_tuple *keysalts = NULL;
6057c478bd9Sstevel@tonic-gate     krb5_int32 num_keysalts = 0;
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate     int free_keysalts;
608dd9ccd46S     /* Solaris Kerberos */
609dd9ccd46S     char *me = progname;
6107c478bd9Sstevel@tonic-gate     char *ks_str = NULL;
6117c478bd9Sstevel@tonic-gate     char *pr_str;
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate     if (argc < 2)
6147c478bd9Sstevel@tonic-gate 	usage();
6157c478bd9Sstevel@tonic-gate     for (argv++, argc--; *argv; argv++, argc--) {
6167c478bd9Sstevel@tonic-gate 	if (!strcmp(*argv, "-e")) {
6177c478bd9Sstevel@tonic-gate 	    argv++; argc--;
6187c478bd9Sstevel@tonic-gate 	    ks_str = *argv;
6197c478bd9Sstevel@tonic-gate 	    continue;
6207c478bd9Sstevel@tonic-gate 	} else
6217c478bd9Sstevel@tonic-gate 	    break;
6227c478bd9Sstevel@tonic-gate     }
6237c478bd9Sstevel@tonic-gate     if (argc < 1)
6247c478bd9Sstevel@tonic-gate 	usage();
6257c478bd9Sstevel@tonic-gate     pr_str = *argv;
6267c478bd9Sstevel@tonic-gate     ret = krb5_parse_name(util_context, pr_str, &princ);
6277c478bd9Sstevel@tonic-gate     if (ret) {
6287c478bd9Sstevel@tonic-gate 	com_err(me, ret, gettext("while parsing principal name %s"), pr_str);
62956a424ccSmp 	exit_status++;
63056a424ccSmp 	return;
6317c478bd9Sstevel@tonic-gate     }
6327c478bd9Sstevel@tonic-gate     n = 1;
6337c478bd9Sstevel@tonic-gate     ret = krb5_db_get_principal(util_context, princ, &dbent,
6347c478bd9Sstevel@tonic-gate 				&n, &more);
6357c478bd9Sstevel@tonic-gate     if (ret) {
6367c478bd9Sstevel@tonic-gate 	com_err(me, ret, gettext("while fetching principal %s"), pr_str);
63756a424ccSmp 	exit_status++;
63856a424ccSmp 	return;
6397c478bd9Sstevel@tonic-gate     }
6407c478bd9Sstevel@tonic-gate     if (n != 1) {
6417c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("principal %s not found\n"), pr_str);
64256a424ccSmp 	exit_status++;
64356a424ccSmp 	return;
6447c478bd9Sstevel@tonic-gate     }
6457c478bd9Sstevel@tonic-gate     if (more) {
6467c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("principal %s not unique\n"), pr_str);
64754925bf6Swillf 	krb5_db_free_principal(util_context, &dbent, 1);
64856a424ccSmp 	exit_status++;
64956a424ccSmp 	return;
6507c478bd9Sstevel@tonic-gate     }
6517c478bd9Sstevel@tonic-gate     ret = krb5_string_to_keysalts(ks_str,
6527c478bd9Sstevel@tonic-gate 				  ", \t", ":.-", 0,
6537c478bd9Sstevel@tonic-gate 				  &keysalts,
6547c478bd9Sstevel@tonic-gate 				  &num_keysalts);
6557c478bd9Sstevel@tonic-gate     if (ret) {
6567c478bd9Sstevel@tonic-gate 	com_err(me, ret, gettext("while parsing keysalts %s"), ks_str);
65756a424ccSmp 	exit_status++;
65856a424ccSmp 	return;
6597c478bd9Sstevel@tonic-gate     }
6607c478bd9Sstevel@tonic-gate     if (!num_keysalts || keysalts == NULL) {
6617c478bd9Sstevel@tonic-gate 	num_keysalts = global_params.num_keysalts;
6627c478bd9Sstevel@tonic-gate 	keysalts = global_params.keysalts;
6637c478bd9Sstevel@tonic-gate 	free_keysalts = 0;
6647c478bd9Sstevel@tonic-gate     } else
6657c478bd9Sstevel@tonic-gate 	free_keysalts = 1;
6667c478bd9Sstevel@tonic-gate     ret = krb5_dbe_ark(util_context, &master_key,
6677c478bd9Sstevel@tonic-gate 		       keysalts, num_keysalts,
6687c478bd9Sstevel@tonic-gate 		       &dbent);
6697c478bd9Sstevel@tonic-gate     if (free_keysalts)
6707c478bd9Sstevel@tonic-gate 	free(keysalts);
6717c478bd9Sstevel@tonic-gate     if (ret) {
6727c478bd9Sstevel@tonic-gate 	com_err(me, ret, gettext("while randomizing principal %s"), pr_str);
67354925bf6Swillf 	krb5_db_free_principal(util_context, &dbent, 1);
67456a424ccSmp 	exit_status++;
67556a424ccSmp 	return;
6767c478bd9Sstevel@tonic-gate     }
6777c478bd9Sstevel@tonic-gate     dbent.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
6787c478bd9Sstevel@tonic-gate     ret = krb5_timeofday(util_context, &now);
6797c478bd9Sstevel@tonic-gate     if (ret) {
6807c478bd9Sstevel@tonic-gate 	com_err(me, ret, gettext("while getting time"));
68154925bf6Swillf 	krb5_db_free_principal(util_context, &dbent, 1);
68256a424ccSmp 	exit_status++;
68356a424ccSmp 	return;
6847c478bd9Sstevel@tonic-gate     }
6857c478bd9Sstevel@tonic-gate     ret = krb5_dbe_update_last_pwd_change(util_context, &dbent, now);
6867c478bd9Sstevel@tonic-gate     if (ret) {
6877c478bd9Sstevel@tonic-gate 	com_err(me, ret, gettext("while setting changetime"));
68854925bf6Swillf 	krb5_db_free_principal(util_context, &dbent, 1);
68956a424ccSmp 	exit_status++;
69056a424ccSmp 	return;
6917c478bd9Sstevel@tonic-gate     }
6927c478bd9Sstevel@tonic-gate     ret = krb5_db_put_principal(util_context, &dbent, &n);
69354925bf6Swillf     krb5_db_free_principal(util_context, &dbent, 1);
6947c478bd9Sstevel@tonic-gate     if (ret) {
6957c478bd9Sstevel@tonic-gate 	com_err(me, ret, gettext("while saving principal %s"), pr_str);
69656a424ccSmp 	exit_status++;
69756a424ccSmp 	return;
6987c478bd9Sstevel@tonic-gate     }
6997c478bd9Sstevel@tonic-gate     printf("%s changed\n", pr_str);
7007c478bd9Sstevel@tonic-gate }
701