xref: /illumos-gate/usr/src/cmd/krb5/kadmin/cli/kadmin.c (revision 55fea89d)
17c478bd9Sstevel@tonic-gate /*
208e8465eSPeter Shoults  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
37c478bd9Sstevel@tonic-gate  */
47c478bd9Sstevel@tonic-gate 
57c478bd9Sstevel@tonic-gate /*
67c478bd9Sstevel@tonic-gate  * Copyright 1994 by the Massachusetts Institute of Technology.
77c478bd9Sstevel@tonic-gate  * All Rights Reserved.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
107c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
117c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
127c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
1354925bf6Swillf  *
147c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
157c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
167c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
177c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
187c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
197c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
207c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
217c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
227c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
237c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
247c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
257c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
267c478bd9Sstevel@tonic-gate  * or implied warranty.
2754925bf6Swillf  *
287c478bd9Sstevel@tonic-gate  * kadmin.c: base functions for a kadmin command line interface using
297c478bd9Sstevel@tonic-gate  * the OVSecure library
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <kadm5/admin.h>
3356a424ccSmp #include <krb5/adm_proto.h>
347c478bd9Sstevel@tonic-gate #include <stdio.h>
357c478bd9Sstevel@tonic-gate #include <string.h>
367c478bd9Sstevel@tonic-gate #include <sys/types.h>
377c478bd9Sstevel@tonic-gate #include <math.h>
387c478bd9Sstevel@tonic-gate #include <unistd.h>
397c478bd9Sstevel@tonic-gate #include <pwd.h>
407c478bd9Sstevel@tonic-gate /* #include <sys/timeb.h> */
417c478bd9Sstevel@tonic-gate #include <time.h>
4254925bf6Swillf #include "kadmin.h"
437c478bd9Sstevel@tonic-gate #include <libintl.h>
44159d09a2SMark Phalan #include <krb5.h>
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate  * Solaris:  the following are needed for paging
487c478bd9Sstevel@tonic-gate  */
497c478bd9Sstevel@tonic-gate #include <signal.h>
507c478bd9Sstevel@tonic-gate #include <sys/wait.h>
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /* command name when called "locally" (i.e. non-networked client ) */
537c478bd9Sstevel@tonic-gate #define KADMIN_LOCAL_NAME "kadmin.local"
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /* functions defined in remote/local specific files */
567c478bd9Sstevel@tonic-gate extern void usage(const char *);
577c478bd9Sstevel@tonic-gate 
5856a424ccSmp /* special struct to convert flag names for principals
5956a424ccSmp    to actual krb5_flags for a principal */
607c478bd9Sstevel@tonic-gate struct pflag {
617c478bd9Sstevel@tonic-gate     char *flagname;		/* name of flag as typed to CLI */
627c478bd9Sstevel@tonic-gate     int flaglen;		/* length of string (not counting -,+) */
637c478bd9Sstevel@tonic-gate     krb5_flags theflag;		/* actual principal flag to set/clear */
647c478bd9Sstevel@tonic-gate     int set;			/* 0 means clear, 1 means set (on '-') */
657c478bd9Sstevel@tonic-gate };
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate static struct pflag flags[] = {
687c478bd9Sstevel@tonic-gate {"allow_postdated",	15,	KRB5_KDB_DISALLOW_POSTDATED,	1},
697c478bd9Sstevel@tonic-gate {"allow_forwardable",	17,	KRB5_KDB_DISALLOW_FORWARDABLE,	1},
707c478bd9Sstevel@tonic-gate {"allow_tgs_req",	13,	KRB5_KDB_DISALLOW_TGT_BASED,	1},
717c478bd9Sstevel@tonic-gate {"allow_renewable",	15,	KRB5_KDB_DISALLOW_RENEWABLE,	1},
727c478bd9Sstevel@tonic-gate {"allow_proxiable",	15,	KRB5_KDB_DISALLOW_PROXIABLE,	1},
737c478bd9Sstevel@tonic-gate {"allow_dup_skey",	14,	KRB5_KDB_DISALLOW_DUP_SKEY,	1},
747c478bd9Sstevel@tonic-gate {"allow_tix",		9,	KRB5_KDB_DISALLOW_ALL_TIX,	1},
757c478bd9Sstevel@tonic-gate {"requires_preauth",	16,	KRB5_KDB_REQUIRES_PRE_AUTH,	0},
767c478bd9Sstevel@tonic-gate {"requires_hwauth",	15,	KRB5_KDB_REQUIRES_HW_AUTH,	0},
7754925bf6Swillf {"needchange", 10,	KRB5_KDB_REQUIRES_PWCHANGE,	0},
7854925bf6Swillf {"allow_svr", 9,	KRB5_KDB_DISALLOW_SVR, 1},
797c478bd9Sstevel@tonic-gate {"password_changing_service",	25,	KRB5_KDB_PWCHANGE_SERVICE,	0 },
807c478bd9Sstevel@tonic-gate {"support_desmd5",	14,	KRB5_KDB_SUPPORT_DESMD5,	0 }
817c478bd9Sstevel@tonic-gate };
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate static char *prflags[] = {
847c478bd9Sstevel@tonic-gate     "DISALLOW_POSTDATED",	/* 0x00000001 */
857c478bd9Sstevel@tonic-gate     "DISALLOW_FORWARDABLE",	/* 0x00000002 */
867c478bd9Sstevel@tonic-gate     "DISALLOW_TGT_BASED",	/* 0x00000004 */
877c478bd9Sstevel@tonic-gate     "DISALLOW_RENEWABLE",	/* 0x00000008 */
887c478bd9Sstevel@tonic-gate     "DISALLOW_PROXIABLE",	/* 0x00000010 */
897c478bd9Sstevel@tonic-gate     "DISALLOW_DUP_SKEY",	/* 0x00000020 */
907c478bd9Sstevel@tonic-gate     "DISALLOW_ALL_TIX",		/* 0x00000040 */
917c478bd9Sstevel@tonic-gate     "REQUIRES_PRE_AUTH",	/* 0x00000080 */
927c478bd9Sstevel@tonic-gate     "REQUIRES_HW_AUTH",		/* 0x00000100 */
937c478bd9Sstevel@tonic-gate     "REQUIRES_PWCHANGE",	/* 0x00000200 */
947c478bd9Sstevel@tonic-gate     "UNKNOWN_0x00000400",	/* 0x00000400 */
957c478bd9Sstevel@tonic-gate     "UNKNOWN_0x00000800",	/* 0x00000800 */
967c478bd9Sstevel@tonic-gate     "DISALLOW_SVR",		/* 0x00001000 */
977c478bd9Sstevel@tonic-gate     "PWCHANGE_SERVICE",		/* 0x00002000 */
987c478bd9Sstevel@tonic-gate     "SUPPORT_DESMD5",		/* 0x00004000 */
997c478bd9Sstevel@tonic-gate     "NEW_PRINC",		/* 0x00008000 */
1007c478bd9Sstevel@tonic-gate };
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate char *getenv();
1037c478bd9Sstevel@tonic-gate int exit_status = 0;
1047c478bd9Sstevel@tonic-gate char *def_realm = NULL;
1057c478bd9Sstevel@tonic-gate char *whoami = NULL;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate void *handle = NULL;
1087c478bd9Sstevel@tonic-gate krb5_context context;
1097c478bd9Sstevel@tonic-gate char *ccache_name = NULL;
1107c478bd9Sstevel@tonic-gate 
11156a424ccSmp int locked = 0;
strdur(duration)11256a424ccSmp static char *strdur(duration)
1137c478bd9Sstevel@tonic-gate     time_t duration;
1147c478bd9Sstevel@tonic-gate {
11556a424ccSmp     static char out[50];
11656a424ccSmp     int neg, days, hours, minutes, seconds;
11756a424ccSmp 
11856a424ccSmp     if (duration < 0) {
11956a424ccSmp 	duration *= -1;
12056a424ccSmp 	neg = 1;
12156a424ccSmp     } else
12256a424ccSmp 	neg = 0;
1237c478bd9Sstevel@tonic-gate     days = duration / (24 * 3600);
1247c478bd9Sstevel@tonic-gate     duration %= 24 * 3600;
1257c478bd9Sstevel@tonic-gate     hours = duration / 3600;
1267c478bd9Sstevel@tonic-gate     duration %= 3600;
1277c478bd9Sstevel@tonic-gate     minutes = duration / 60;
1287c478bd9Sstevel@tonic-gate     duration %= 60;
1297c478bd9Sstevel@tonic-gate     seconds = duration;
13056a424ccSmp     snprintf(out, sizeof (out), "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
13156a424ccSmp 	    days, days == 1 ? gettext("day") : gettext("days"),
13256a424ccSmp 	    hours, minutes, seconds);
13356a424ccSmp     return out;
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate 
strdate(when)13656a424ccSmp static char *strdate(when)
1377c478bd9Sstevel@tonic-gate     krb5_timestamp when;
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate     struct tm *tm;
14056a424ccSmp     static char out[40];
14154925bf6Swillf 
1427c478bd9Sstevel@tonic-gate     time_t lcltim = when;
1437c478bd9Sstevel@tonic-gate     tm = localtime(&lcltim);
14456a424ccSmp     strftime(out, sizeof(out), gettext("%a %b %d %H:%M:%S %Z %Y"), tm);
14556a424ccSmp     return out;
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate 
14856a424ccSmp /* this is a wrapper to go around krb5_parse_principal so we can set
14956a424ccSmp    the default realm up properly */
15054925bf6Swillf static krb5_error_code
kadmin_parse_name(name,principal)1517c478bd9Sstevel@tonic-gate kadmin_parse_name(name, principal)
1527c478bd9Sstevel@tonic-gate     char *name;
1537c478bd9Sstevel@tonic-gate     krb5_principal *principal;
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate     char *cp, *fullname;
1567c478bd9Sstevel@tonic-gate     krb5_error_code retval;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate     if (name == NULL)
1597c478bd9Sstevel@tonic-gate 	return (EINVAL);
160*55fea89dSDan Cross 
1617c478bd9Sstevel@tonic-gate     /* assumes def_realm is initialized! */
1627c478bd9Sstevel@tonic-gate     fullname = (char *)malloc(strlen(name) + 1 + strlen(def_realm) + 1);
1637c478bd9Sstevel@tonic-gate     if (fullname == NULL)
16456a424ccSmp 	return ENOMEM;
1657c478bd9Sstevel@tonic-gate     strcpy(fullname, name);
1667c478bd9Sstevel@tonic-gate     cp = strchr(fullname, '@');
1677c478bd9Sstevel@tonic-gate     while (cp) {
1687c478bd9Sstevel@tonic-gate 	if (cp - fullname && *(cp - 1) != '\\')
1697c478bd9Sstevel@tonic-gate 	    break;
1707c478bd9Sstevel@tonic-gate 	else
17156a424ccSmp 	    cp = strchr(cp + 1, '@');
1727c478bd9Sstevel@tonic-gate     }
1737c478bd9Sstevel@tonic-gate     if (cp == NULL) {
1747c478bd9Sstevel@tonic-gate 	strcat(fullname, "@");
1757c478bd9Sstevel@tonic-gate 	strcat(fullname, def_realm);
1767c478bd9Sstevel@tonic-gate     }
1777c478bd9Sstevel@tonic-gate     retval = krb5_parse_name(context, fullname, principal);
1787c478bd9Sstevel@tonic-gate     free(fullname);
17956a424ccSmp     return retval;
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate 
extended_com_err_fn(const char * myprog,errcode_t code,const char * fmt,va_list args)18254925bf6Swillf static void extended_com_err_fn (const char *myprog, errcode_t code,
18354925bf6Swillf 				 const char *fmt, va_list args)
18454925bf6Swillf {
18554925bf6Swillf     if (code) {
18654925bf6Swillf 	const char *emsg;
18754925bf6Swillf 	emsg = krb5_get_error_message (context, code);
18854925bf6Swillf 	fprintf (stderr, "%s: %s ", myprog, emsg);
18954925bf6Swillf 	krb5_free_error_message (context, emsg);
19054925bf6Swillf     } else {
19154925bf6Swillf 	fprintf (stderr, "%s: ", myprog);
19254925bf6Swillf     }
19354925bf6Swillf     vfprintf (stderr, fmt, args);
19454925bf6Swillf     fprintf (stderr, "\n");
19554925bf6Swillf }
kadmin_startup(argc,argv)19656a424ccSmp char *kadmin_startup(argc, argv)
1977c478bd9Sstevel@tonic-gate     int argc;
1987c478bd9Sstevel@tonic-gate     char *argv[];
1997c478bd9Sstevel@tonic-gate {
2007c478bd9Sstevel@tonic-gate     extern char *optarg;
2017c478bd9Sstevel@tonic-gate     char *princstr = NULL, *keytab_name = NULL, *query = NULL;
2027c478bd9Sstevel@tonic-gate     char *password = NULL;
2037c478bd9Sstevel@tonic-gate     char *luser, *canon, *cp;
20456a424ccSmp     int optchar, freeprinc = 0, use_keytab = 0;
2057c478bd9Sstevel@tonic-gate     struct passwd *pw;
2067c478bd9Sstevel@tonic-gate     kadm5_ret_t retval;
2077c478bd9Sstevel@tonic-gate     krb5_ccache cc;
2087c478bd9Sstevel@tonic-gate     krb5_principal princ;
2097c478bd9Sstevel@tonic-gate     kadm5_config_params params;
21054925bf6Swillf     char **db_args = NULL;
21154925bf6Swillf     int db_args_size = 0;
21254925bf6Swillf     char *db_name = NULL;
21356a424ccSmp     char *svcname = NULL;
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate     memset((char *) &params, 0, sizeof(params));
21654925bf6Swillf 
21754925bf6Swillf     if (strcmp (whoami, "kadmin.local") == 0)
21854925bf6Swillf 	set_com_err_hook(extended_com_err_fn);
21954925bf6Swillf 
22054925bf6Swillf     retval = kadm5_init_krb5_context(&context);
22156a424ccSmp     if (retval) {
22254925bf6Swillf 	com_err(whoami, retval, gettext("while initializing krb5 library"));
22354925bf6Swillf 	exit(1);
2247c478bd9Sstevel@tonic-gate     }
22554925bf6Swillf 
22654925bf6Swillf     while ((optchar = getopt(argc, argv, "x:r:p:kq:w:d:s:mc:t:e:ON")) != EOF) {
2277c478bd9Sstevel@tonic-gate 	switch (optchar) {
22854925bf6Swillf 	case 'x':
22954925bf6Swillf 	    db_args_size++;
23054925bf6Swillf 	    {
23154925bf6Swillf 		char **temp = realloc(db_args, sizeof(char*) * (db_args_size+1));
23254925bf6Swillf 		if (temp == NULL) {
23354925bf6Swillf 		    fprintf(stderr, gettext("%s: Cannot initialize. Not enough memory\n"),
23454925bf6Swillf 			    argv[0]);
23554925bf6Swillf 		    exit(1);
23654925bf6Swillf 		}
23754925bf6Swillf 
23854925bf6Swillf 		db_args = temp;
23954925bf6Swillf 	    }
24054925bf6Swillf 	    db_args[db_args_size-1] = optarg;
24154925bf6Swillf 	    db_args[db_args_size]   = NULL;
24254925bf6Swillf 	    break;
24354925bf6Swillf 
2447c478bd9Sstevel@tonic-gate 	case 'r':
2457c478bd9Sstevel@tonic-gate 	    def_realm = optarg;
2467c478bd9Sstevel@tonic-gate 	    break;
2477c478bd9Sstevel@tonic-gate 	case 'p':
24856a424ccSmp 	    princstr = optarg;
24956a424ccSmp 	    break;
25054925bf6Swillf 	case 'c':
2517c478bd9Sstevel@tonic-gate 	    ccache_name = optarg;
2527c478bd9Sstevel@tonic-gate 	    break;
25354925bf6Swillf 	case 'k':
2547c478bd9Sstevel@tonic-gate 	    use_keytab++;
2557c478bd9Sstevel@tonic-gate 	    break;
25654925bf6Swillf 	case 't':
2577c478bd9Sstevel@tonic-gate 	    keytab_name = optarg;
2587c478bd9Sstevel@tonic-gate 	    break;
25954925bf6Swillf 	case 'w':
2607c478bd9Sstevel@tonic-gate 	    password = optarg;
2617c478bd9Sstevel@tonic-gate 	    break;
2627c478bd9Sstevel@tonic-gate 	case 'q':
2637c478bd9Sstevel@tonic-gate 	    query = optarg;
2647c478bd9Sstevel@tonic-gate 	    break;
26554925bf6Swillf 	case 'd':
26654925bf6Swillf 	    /* now db_name is not a seperate argument. It has to be passed as part of the db_args */
26754925bf6Swillf 	    if (!db_name) {
26854925bf6Swillf 		db_name = malloc(strlen(optarg) + sizeof("dbname="));
26954925bf6Swillf 	    } else {
27054925bf6Swillf 		db_name = realloc(db_name, strlen(optarg) + sizeof("dbname="));
27154925bf6Swillf 	    }
27254925bf6Swillf 
27354925bf6Swillf 	    strcpy(db_name, "dbname=");
27454925bf6Swillf 	    strcat(db_name, optarg);
27554925bf6Swillf 
27654925bf6Swillf 	    db_args_size++;
27754925bf6Swillf 	    {
27854925bf6Swillf 		char **temp = realloc(db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */
27954925bf6Swillf 		if (temp == NULL) {
28054925bf6Swillf 		    fprintf(stderr,
28154925bf6Swillf 			    gettext("%s: Cannot initialize. Not enough memory\n"),
28254925bf6Swillf 			    argv[0]);
28354925bf6Swillf 		    exit(1);
28454925bf6Swillf 		}
28554925bf6Swillf 
28654925bf6Swillf 		db_args = temp;
28754925bf6Swillf 	    }
28854925bf6Swillf 	    db_args[db_args_size-1] = db_name;
28954925bf6Swillf 	    db_args[db_args_size]   = NULL;
2907c478bd9Sstevel@tonic-gate 	    break;
29154925bf6Swillf 	case 's':
2927c478bd9Sstevel@tonic-gate 	    params.admin_server = optarg;
2937c478bd9Sstevel@tonic-gate 	    params.mask |= KADM5_CONFIG_ADMIN_SERVER;
2947c478bd9Sstevel@tonic-gate 	    break;
29554925bf6Swillf 	case 'm':
2967c478bd9Sstevel@tonic-gate 	    params.mkey_from_kbd = 1;
2977c478bd9Sstevel@tonic-gate 	    params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
2987c478bd9Sstevel@tonic-gate 	    break;
29954925bf6Swillf 	case 'e':
3007c478bd9Sstevel@tonic-gate 	    retval = krb5_string_to_keysalts(optarg,
30156a424ccSmp 					     ", \t",
30256a424ccSmp 					     ":.-",
30356a424ccSmp 					     0,
30456a424ccSmp 					     &params.keysalts,
30556a424ccSmp 					     &params.num_keysalts);
3067c478bd9Sstevel@tonic-gate 	    if (retval) {
30756a424ccSmp 		 com_err(whoami, retval,
3087c478bd9Sstevel@tonic-gate 			gettext("while parsing keysalts %s"), optarg);
30956a424ccSmp 		 exit(1);
3107c478bd9Sstevel@tonic-gate 	    }
3117c478bd9Sstevel@tonic-gate 	    params.mask |= KADM5_CONFIG_ENCTYPES;
3127c478bd9Sstevel@tonic-gate 	    break;
31356a424ccSmp 	case 'O':	/* Undocumented option for testing only */
31456a424ccSmp 		svcname = KADM5_ADMIN_SERVICE_P;
31556a424ccSmp 	    break;
3167c478bd9Sstevel@tonic-gate 	default:
3177c478bd9Sstevel@tonic-gate 	    usage(whoami);
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate     }
3207c478bd9Sstevel@tonic-gate     if ((ccache_name && use_keytab) ||
3217c478bd9Sstevel@tonic-gate 	(keytab_name && !use_keytab))
32256a424ccSmp 	 usage(whoami);
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate     if (def_realm == NULL && krb5_get_default_realm(context, &def_realm)) {
32556a424ccSmp 	if (freeprinc)
32656a424ccSmp 	    free(princstr);
3277c478bd9Sstevel@tonic-gate 	fprintf(stderr,
3287c478bd9Sstevel@tonic-gate 		gettext("%s: unable to get default realm\n"), whoami);
3297c478bd9Sstevel@tonic-gate 	exit(1);
3307c478bd9Sstevel@tonic-gate     }
33156a424ccSmp 
3327c478bd9Sstevel@tonic-gate     params.mask |= KADM5_CONFIG_REALM;
3337c478bd9Sstevel@tonic-gate     params.realm = def_realm;
3347c478bd9Sstevel@tonic-gate 
33556a424ccSmp     if (svcname == NULL) {
3367c478bd9Sstevel@tonic-gate 	if (kadm5_get_adm_host_srv_name(context,
33756a424ccSmp 			       def_realm, &svcname)) {
3387c478bd9Sstevel@tonic-gate 		fprintf(stderr,
3397c478bd9Sstevel@tonic-gate 			gettext("%s: unable to get host based "
3407c478bd9Sstevel@tonic-gate 				"service name for realm %s\n"),
3417c478bd9Sstevel@tonic-gate 			whoami, def_realm);
34256a424ccSmp 		if (freeprinc)
34356a424ccSmp 			free(princstr);
3447c478bd9Sstevel@tonic-gate 		exit(1);
3457c478bd9Sstevel@tonic-gate 	}
3467c478bd9Sstevel@tonic-gate     }
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate     /*
3497c478bd9Sstevel@tonic-gate      * Set cc to an open credentials cache, either specified by the -c
3507c478bd9Sstevel@tonic-gate      * argument or the default.
3517c478bd9Sstevel@tonic-gate      */
3527c478bd9Sstevel@tonic-gate     if (ccache_name == NULL) {
35356a424ccSmp 	 if ((retval = krb5_cc_default(context, &cc))) {
3547c478bd9Sstevel@tonic-gate 	      com_err(whoami, retval,
3557c478bd9Sstevel@tonic-gate 				gettext("while opening default "
3567c478bd9Sstevel@tonic-gate 					"credentials cache"));
3577c478bd9Sstevel@tonic-gate 	      exit(1);
3587c478bd9Sstevel@tonic-gate 	 }
3597c478bd9Sstevel@tonic-gate     } else {
36056a424ccSmp 	 if ((retval = krb5_cc_resolve(context, ccache_name, &cc))) {
3617c478bd9Sstevel@tonic-gate 	      com_err(whoami, retval,
3627c478bd9Sstevel@tonic-gate 			gettext("while opening credentials cache %s"),
3637c478bd9Sstevel@tonic-gate 			ccache_name);
3647c478bd9Sstevel@tonic-gate 	      exit(1);
3657c478bd9Sstevel@tonic-gate 	 }
3667c478bd9Sstevel@tonic-gate     }
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate     /*
36956a424ccSmp      * If no principal name is specified: If a ccache was specified
37056a424ccSmp      * and its primary principal name can be read, it is used, else if
37156a424ccSmp      * a keytab was specified, the principal name is host/hostname,
3727c478bd9Sstevel@tonic-gate      * otherwise append "/admin" to the primary name of the default
3737c478bd9Sstevel@tonic-gate      * ccache, $USER, or pw_name.
3747c478bd9Sstevel@tonic-gate      *
3757c478bd9Sstevel@tonic-gate      * Gee, 100+ lines to figure out the client principal name.  This
3767c478bd9Sstevel@tonic-gate      * should be compressed...
3777c478bd9Sstevel@tonic-gate      */
37854925bf6Swillf 
3797c478bd9Sstevel@tonic-gate     if (princstr == NULL) {
3807c478bd9Sstevel@tonic-gate 	if (ccache_name != NULL &&
3817c478bd9Sstevel@tonic-gate 	    !krb5_cc_get_principal(context, cc, &princ)) {
38256a424ccSmp 	     if ((retval = krb5_unparse_name(context, princ, &princstr))) {
3837c478bd9Sstevel@tonic-gate 		  com_err(whoami, retval,
3847c478bd9Sstevel@tonic-gate 			gettext("while canonicalizing principal name"));
38556a424ccSmp 		  krb5_free_principal(context, princ);
3867c478bd9Sstevel@tonic-gate 		  exit(1);
38756a424ccSmp 	     }
38856a424ccSmp 	     krb5_free_principal(context, princ);
38956a424ccSmp 	     freeprinc++;
39056a424ccSmp 	} else if (use_keytab != 0) {
39154925bf6Swillf 	    if ((retval = krb5_sname_to_principal(context, NULL,
39254925bf6Swillf 						  "host",
39354925bf6Swillf 						  KRB5_NT_SRV_HST,
39454925bf6Swillf 						  &princ))) {
39554925bf6Swillf 		com_err(whoami, retval,
39656a424ccSmp 			gettext("creating host service principal"));
39754925bf6Swillf 		exit(1);
39854925bf6Swillf 	    }
39954925bf6Swillf 	    if ((retval = krb5_unparse_name(context, princ, &princstr))) {
40054925bf6Swillf 		com_err(whoami, retval,
40154925bf6Swillf 			gettext("while canonicalizing principal name"));
40254925bf6Swillf 		krb5_free_principal(context, princ);
40354925bf6Swillf 		exit(1);
40454925bf6Swillf 	    }
40554925bf6Swillf 	    krb5_free_principal(context, princ);
40654925bf6Swillf 	    freeprinc++;
4077c478bd9Sstevel@tonic-gate 	} else if (!krb5_cc_get_principal(context, cc, &princ)) {
4087c478bd9Sstevel@tonic-gate 	    char *realm = NULL;
4097c478bd9Sstevel@tonic-gate 	    if (krb5_unparse_name(context, princ, &canon)) {
4107c478bd9Sstevel@tonic-gate 		fprintf(stderr,
4117c478bd9Sstevel@tonic-gate 			gettext("%s: unable to canonicalize "
4127c478bd9Sstevel@tonic-gate 				"principal\n"), whoami);
4137c478bd9Sstevel@tonic-gate 		krb5_free_principal(context, princ);
4147c478bd9Sstevel@tonic-gate 		exit(1);
4157c478bd9Sstevel@tonic-gate 	    }
41656a424ccSmp 	    /* strip out realm of principal if it's there */
41756a424ccSmp 	    realm = strchr(canon, '@');
41856a424ccSmp 	    while (realm) {
41956a424ccSmp 		if (realm - canon && *(realm - 1) != '\\')
42056a424ccSmp 		    break;
42156a424ccSmp 		else
42254925bf6Swillf 		    realm = strchr(realm+1, '@');
42356a424ccSmp 	    }
42456a424ccSmp 	    if (realm)
42556a424ccSmp 		*realm++ = '\0';
42656a424ccSmp 	    cp = strchr(canon, '/');
42756a424ccSmp 	    while (cp) {
42856a424ccSmp 		if (cp - canon && *(cp - 1) != '\\')
42956a424ccSmp 		    break;
43056a424ccSmp 		else
43154925bf6Swillf 		    cp = strchr(cp+1, '/');
43256a424ccSmp 	    }
43356a424ccSmp 	    if (cp != NULL)
43456a424ccSmp 		*cp = '\0';
43556a424ccSmp 	    princstr = (char*)malloc(strlen(canon) + 6 /* "/admin" */ +
43656a424ccSmp 				     (realm ? 1 + strlen(realm) : 0) + 1);
43756a424ccSmp 	    if (princstr == NULL) {
43856a424ccSmp 		fprintf(stderr,
43956a424ccSmp 			gettext("%s: out of memory\n"),
44056a424ccSmp 			whoami);
44156a424ccSmp 		exit(1);
44256a424ccSmp 	    }
44356a424ccSmp 	    strcpy(princstr, canon);
44456a424ccSmp 	    strcat(princstr, "/admin");
44556a424ccSmp 	    if (realm) {
44656a424ccSmp 		strcat(princstr, "@");
44756a424ccSmp 		strcat(princstr, realm);
44856a424ccSmp 	    }
4497c478bd9Sstevel@tonic-gate 	    free(canon);
45056a424ccSmp 	    krb5_free_principal(context, princ);
45156a424ccSmp 	    freeprinc++;
45256a424ccSmp 	} else if ((luser = getenv("USER"))) {
45356a424ccSmp 	    princstr = (char *) malloc(strlen(luser) + 7 /* "/admin@" */
45454925bf6Swillf 				       + strlen(def_realm) + 1);
45556a424ccSmp 	    if (princstr == NULL) {
45656a424ccSmp 		fprintf(stderr,
45756a424ccSmp 			gettext("%s: out of memory\n"),
45856a424ccSmp 			whoami);
45956a424ccSmp 		exit(1);
46056a424ccSmp 	    }
46156a424ccSmp 	    strcpy(princstr, luser);
46256a424ccSmp 	    strcat(princstr, "/admin");
46356a424ccSmp 	    strcat(princstr, "@");
46456a424ccSmp 	    strcat(princstr, def_realm);
46556a424ccSmp 	    freeprinc++;
46656a424ccSmp 	} else if ((pw = getpwuid(getuid()))) {
46756a424ccSmp 	    princstr = (char *) malloc(strlen(pw->pw_name) + 7 /* "/admin@" */
46854925bf6Swillf 				       + strlen(def_realm) + 1);
46956a424ccSmp 	    if (princstr == NULL) {
4707c478bd9Sstevel@tonic-gate 		fprintf(stderr,
47156a424ccSmp 			gettext("%s: out of memory\n"),
47256a424ccSmp 			whoami);
47356a424ccSmp 		exit(1);
47456a424ccSmp 	    }
47556a424ccSmp 	    strcpy(princstr, pw->pw_name);
47656a424ccSmp 	    strcat(princstr, "/admin@");
47756a424ccSmp 	    strcat(princstr, def_realm);
47856a424ccSmp 	    freeprinc++;
47956a424ccSmp 	} else {
48056a424ccSmp 	    fprintf(stderr,
4817c478bd9Sstevel@tonic-gate 			gettext("%s: unable to figure out "
4827c478bd9Sstevel@tonic-gate 				"a principal name\n"),
48356a424ccSmp 		    whoami);
48456a424ccSmp 	    exit(1);
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate     }
4877c478bd9Sstevel@tonic-gate 
48856a424ccSmp     retval = krb5_klog_init(context, "admin_server", whoami, 0);
48956a424ccSmp     if (retval) {
49056a424ccSmp 	com_err(whoami, retval, "while setting up logging");
49156a424ccSmp 	exit(1);
49256a424ccSmp     }
49356a424ccSmp 
4947c478bd9Sstevel@tonic-gate     /*
49556a424ccSmp      * Initialize the kadm5 connection.  If we were given a ccache,
49656a424ccSmp      * use it.  Otherwise, use/prompt for the password.
4977c478bd9Sstevel@tonic-gate      */
498d51f1d33Smp 
499d51f1d33Smp     /* Solaris Kerberos:
500d51f1d33Smp      * Send warnings to stderr
501d51f1d33Smp      */
5027c478bd9Sstevel@tonic-gate     if (ccache_name) {
50354925bf6Swillf 	fprintf(stderr, gettext("Authenticating as principal %s with existing credentials.\n"),
50454925bf6Swillf 	       princstr);
50554925bf6Swillf 	retval = kadm5_init_with_creds(princstr, cc,
50654925bf6Swillf 				       svcname,
50756a424ccSmp 				       &params,
50856a424ccSmp 				       KADM5_STRUCT_VERSION,
50956a424ccSmp 				       KADM5_API_VERSION_2,
51054925bf6Swillf 				       db_args,
51156a424ccSmp 				       &handle);
51254925bf6Swillf     } else if (use_keytab) {
51354925bf6Swillf 	if (keytab_name)
51454925bf6Swillf 	    fprintf(stderr, gettext("Authenticating as principal %s with keytab %s.\n"),
51554925bf6Swillf 		   princstr, keytab_name);
51654925bf6Swillf 	else
51754925bf6Swillf 	    fprintf(stderr, gettext("Authenticating as principal %s with default keytab.\n"),
51854925bf6Swillf 		   princstr);
51954925bf6Swillf 	retval = kadm5_init_with_skey(princstr, keytab_name,
52054925bf6Swillf 				      svcname,
52154925bf6Swillf 				      &params,
52254925bf6Swillf 				      KADM5_STRUCT_VERSION,
52354925bf6Swillf 				      KADM5_API_VERSION_2,
52454925bf6Swillf 				      db_args,
52554925bf6Swillf 				      &handle);
5267c478bd9Sstevel@tonic-gate     } else {
527d51f1d33Smp 	 fprintf(stderr, gettext("Authenticating as principal %s with password.\n"),
52854925bf6Swillf 	       princstr);
52954925bf6Swillf 	retval = kadm5_init_with_password(princstr, password,
53054925bf6Swillf 					  svcname,
53154925bf6Swillf 					  &params,
53254925bf6Swillf 					  KADM5_STRUCT_VERSION,
53354925bf6Swillf 					  KADM5_API_VERSION_2,
53454925bf6Swillf 					  db_args,
53554925bf6Swillf 					  &handle);
5367c478bd9Sstevel@tonic-gate     }
5377c478bd9Sstevel@tonic-gate     if (retval) {
5387c478bd9Sstevel@tonic-gate 	    if (retval == KADM5_RPC_ERROR_CANTENCODEARGS ||
5397c478bd9Sstevel@tonic-gate 		retval == KADM5_RPC_ERROR_CANTDECODEARGS) {
5407c478bd9Sstevel@tonic-gate 		    com_err(whoami, KADM5_RPC_ERROR,
5417c478bd9Sstevel@tonic-gate 			gettext("while initializing %s interface"), whoami);
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 		    /* privacy-enabled mech probably not installed/configed */
5447c478bd9Sstevel@tonic-gate 		    com_err(whoami, retval, gettext("."), whoami);
5457c478bd9Sstevel@tonic-gate 	    } else {
5467c478bd9Sstevel@tonic-gate 		    com_err(whoami, retval,
5477c478bd9Sstevel@tonic-gate 			gettext("while initializing %s interface"), whoami);
5487c478bd9Sstevel@tonic-gate 	if (retval == KADM5_BAD_CLIENT_PARAMS ||
5497c478bd9Sstevel@tonic-gate 	    retval == KADM5_BAD_SERVER_PARAMS)
5507c478bd9Sstevel@tonic-gate 		usage(whoami);
5517c478bd9Sstevel@tonic-gate 	}
5527c478bd9Sstevel@tonic-gate 	exit(1);
5537c478bd9Sstevel@tonic-gate     }
55456a424ccSmp     if (freeprinc)
55556a424ccSmp 	free(princstr);
5567c478bd9Sstevel@tonic-gate 
55754925bf6Swillf     if (db_name)
55854925bf6Swillf 	free(db_name), db_name=NULL;
55954925bf6Swillf 
56054925bf6Swillf     if (db_args)
56154925bf6Swillf 	free(db_args), db_args=NULL;
56254925bf6Swillf 
56356a424ccSmp     if ((retval = krb5_cc_close(context, cc))) {
56456a424ccSmp 	 com_err(whoami, retval, gettext("while closing ccache %s"),
56556a424ccSmp 		 ccache_name);
5667c478bd9Sstevel@tonic-gate 	 exit(1);
5677c478bd9Sstevel@tonic-gate     }
56856a424ccSmp 
56956a424ccSmp     /* register the WRFILE keytab type and set it as the default */
5707c478bd9Sstevel@tonic-gate     {
571159d09a2SMark Phalan #define DEFAULT_KEYTAB "WRFILE:/etc/krb5/krb5.keytab"
572159d09a2SMark Phalan 	/* XXX krb5_defkeyname is an internal library global and
573159d09a2SMark Phalan 	   should go away */
574159d09a2SMark Phalan 	extern char *krb5_defkeyname;
575159d09a2SMark Phalan 	krb5_defkeyname = DEFAULT_KEYTAB;
5767c478bd9Sstevel@tonic-gate     }
577*55fea89dSDan Cross 
5787c478bd9Sstevel@tonic-gate     if ((retval = kadm5_init_iprop(handle)) != 0) {
5797c478bd9Sstevel@tonic-gate 	com_err(whoami, retval, gettext("while mapping update log"));
5807c478bd9Sstevel@tonic-gate 	exit(1);
5817c478bd9Sstevel@tonic-gate     }
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate     /* Solaris kerberos: fix memory leak */
58456a424ccSmp     if (svcname)
58556a424ccSmp 	free(svcname);
5867c478bd9Sstevel@tonic-gate 
58756a424ccSmp     return query;
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate 
quit()59056a424ccSmp int quit()
5917c478bd9Sstevel@tonic-gate {
59256a424ccSmp     kadm5_ret_t retval;
5937c478bd9Sstevel@tonic-gate 
59456a424ccSmp     if (locked) {
59556a424ccSmp 	retval = kadm5_unlock(handle);
59656a424ccSmp 	if (retval) {
59756a424ccSmp 	    com_err("quit", retval, gettext("while unlocking locked database"));
59856a424ccSmp 	    return 1;
5997c478bd9Sstevel@tonic-gate 	}
60056a424ccSmp 	locked = 0;
60156a424ccSmp     }
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate      kadm5_destroy(handle);
6047c478bd9Sstevel@tonic-gate      if (ccache_name != NULL) {
6057c478bd9Sstevel@tonic-gate 	  fprintf(stderr,
6067c478bd9Sstevel@tonic-gate 			gettext("\n\a\a\aAdministration credentials "
6077c478bd9Sstevel@tonic-gate 				"NOT DESTROYED.\n"));
6087c478bd9Sstevel@tonic-gate      }
60956a424ccSmp 
6107c478bd9Sstevel@tonic-gate      /* insert more random cleanup here */
61156a424ccSmp      krb5_klog_close(context);
6127c478bd9Sstevel@tonic-gate      krb5_free_context(context);
6137c478bd9Sstevel@tonic-gate      context = NULL;
61456a424ccSmp      return 0;
61556a424ccSmp }
61656a424ccSmp 
kadmin_lock(argc,argv)61756a424ccSmp void kadmin_lock(argc, argv)
61856a424ccSmp     int argc;
61956a424ccSmp     char *argv[];
62056a424ccSmp {
62156a424ccSmp     kadm5_ret_t retval;
62256a424ccSmp 
62356a424ccSmp     if (locked)
62456a424ccSmp 	return;
62556a424ccSmp     retval = kadm5_lock(handle);
62656a424ccSmp     if (retval) {
62756a424ccSmp 	com_err("lock", retval, "");
62856a424ccSmp 	return;
62956a424ccSmp     }
63056a424ccSmp     locked = 1;
63156a424ccSmp }
63256a424ccSmp 
kadmin_unlock(argc,argv)63356a424ccSmp void kadmin_unlock(argc, argv)
63456a424ccSmp     int argc;
63556a424ccSmp     char *argv[];
63656a424ccSmp {
63756a424ccSmp     kadm5_ret_t retval;
63856a424ccSmp 
63956a424ccSmp     if (!locked)
64056a424ccSmp 	return;
64156a424ccSmp     retval = kadm5_unlock(handle);
64256a424ccSmp     if (retval) {
64356a424ccSmp 	com_err("unlock", retval, "");
64456a424ccSmp 	return;
64556a424ccSmp     }
64656a424ccSmp     locked = 0;
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate 
kadmin_delprinc(argc,argv)64956a424ccSmp void kadmin_delprinc(argc, argv)
6507c478bd9Sstevel@tonic-gate     int argc;
6517c478bd9Sstevel@tonic-gate     char *argv[];
6527c478bd9Sstevel@tonic-gate {
6537c478bd9Sstevel@tonic-gate     kadm5_ret_t retval;
6547c478bd9Sstevel@tonic-gate     krb5_principal princ;
6557c478bd9Sstevel@tonic-gate     char *canon;
65656a424ccSmp     char reply[32];
65754925bf6Swillf 
6587c478bd9Sstevel@tonic-gate     if (! (argc == 2 ||
65956a424ccSmp 	   (argc == 3 && !strcmp("-force", argv[1])))) {
66056a424ccSmp 	fprintf(stderr, "%s: delete_principal [-force] %s\n",
6617c478bd9Sstevel@tonic-gate 			gettext("usage"), gettext("principal"));
6627c478bd9Sstevel@tonic-gate 	return;
6637c478bd9Sstevel@tonic-gate     }
6647c478bd9Sstevel@tonic-gate     retval = kadmin_parse_name(argv[argc - 1], &princ);
6657c478bd9Sstevel@tonic-gate     if (retval) {
66656a424ccSmp 	com_err("delete_principal", retval,
6677c478bd9Sstevel@tonic-gate 			gettext("while parsing principal name"));
6687c478bd9Sstevel@tonic-gate 	return;
6697c478bd9Sstevel@tonic-gate     }
6707c478bd9Sstevel@tonic-gate     retval = krb5_unparse_name(context, princ, &canon);
6717c478bd9Sstevel@tonic-gate     if (retval) {
6727c478bd9Sstevel@tonic-gate 	com_err("delete_principal", retval,
6737c478bd9Sstevel@tonic-gate 			gettext("while canonicalizing principal"));
6747c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, princ);
6757c478bd9Sstevel@tonic-gate 	return;
6767c478bd9Sstevel@tonic-gate     }
6777c478bd9Sstevel@tonic-gate     if (argc == 2) {
67856a424ccSmp 	printf(gettext("Are you sure you want to delete "
6797c478bd9Sstevel@tonic-gate 			    "the principal \"%s\"? (yes/no): "), canon);
6807c478bd9Sstevel@tonic-gate 	fgets(reply, sizeof (reply), stdin);
6817c478bd9Sstevel@tonic-gate 		if (strncmp(gettext("yes\n"), reply, sizeof (reply)) &&
6827c478bd9Sstevel@tonic-gate 			strncmp(gettext("y\n"), reply, sizeof (reply)) &&
6837c478bd9Sstevel@tonic-gate 			strncmp(gettext("Y\n"), reply, sizeof (reply))) {
6847c478bd9Sstevel@tonic-gate 			fprintf(stderr,
6857c478bd9Sstevel@tonic-gate 				gettext("Principal \"%s\" not deleted\n"),
6867c478bd9Sstevel@tonic-gate 				canon);
6877c478bd9Sstevel@tonic-gate 	    free(canon);
6887c478bd9Sstevel@tonic-gate 	    krb5_free_principal(context, princ);
6897c478bd9Sstevel@tonic-gate 	    return;
6907c478bd9Sstevel@tonic-gate 	}
6917c478bd9Sstevel@tonic-gate     }
6927c478bd9Sstevel@tonic-gate     retval = kadm5_delete_principal(handle, princ);
6937c478bd9Sstevel@tonic-gate     krb5_free_principal(context, princ);
6947c478bd9Sstevel@tonic-gate     if (retval) {
6957c478bd9Sstevel@tonic-gate 	com_err("delete_principal", retval,
6967c478bd9Sstevel@tonic-gate 			gettext("while deleting principal \"%s\""), canon);
6977c478bd9Sstevel@tonic-gate 	free(canon);
6987c478bd9Sstevel@tonic-gate 	return;
6997c478bd9Sstevel@tonic-gate     }
70056a424ccSmp     printf(gettext("Principal \"%s\" deleted.\n"), canon);
7017c478bd9Sstevel@tonic-gate 	printf(gettext("Make sure that you have removed this principal "
7027c478bd9Sstevel@tonic-gate 			"from all ACLs before reusing.\n"));
7037c478bd9Sstevel@tonic-gate     free(canon);
70456a424ccSmp     return;
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate 
kadmin_cpw(argc,argv)70756a424ccSmp void kadmin_cpw(argc, argv)
7087c478bd9Sstevel@tonic-gate     int argc;
7097c478bd9Sstevel@tonic-gate     char *argv[];
7107c478bd9Sstevel@tonic-gate {
7117c478bd9Sstevel@tonic-gate     kadm5_ret_t retval;
7127c478bd9Sstevel@tonic-gate     static char newpw[1024];
7137c478bd9Sstevel@tonic-gate     static char prompt1[1024], prompt2[1024];
7147c478bd9Sstevel@tonic-gate     char *canon;
7157c478bd9Sstevel@tonic-gate     char *pwarg = NULL;
71656a424ccSmp     int n_ks_tuple = 0, randkey = 0;
71756a424ccSmp     krb5_boolean keepold = FALSE;
7187c478bd9Sstevel@tonic-gate     krb5_key_salt_tuple *ks_tuple = NULL;
7197c478bd9Sstevel@tonic-gate     krb5_principal princ;
72054925bf6Swillf     char **db_args = NULL;
72154925bf6Swillf     int db_args_size = 0;
722bcfd778bSwillf     int local_kadmin = 0;
723bcfd778bSwillf 
724bcfd778bSwillf     local_kadmin = (strcmp(whoami, KADMIN_LOCAL_NAME) == 0);
725*55fea89dSDan Cross 
7267c478bd9Sstevel@tonic-gate     if (argc < 2) {
72754925bf6Swillf 	goto usage;
7287c478bd9Sstevel@tonic-gate     }
7297c478bd9Sstevel@tonic-gate     for (argv++, argc--; argc > 1; argc--, argv++) {
73054925bf6Swillf 	if (!strcmp("-x", *argv)) {
73154925bf6Swillf 	    argc--;
73254925bf6Swillf 	    if (argc < 1) {
73354925bf6Swillf 		fprintf(stderr, gettext("change_password: missing db argument\n"));
73454925bf6Swillf 		goto usage;
73554925bf6Swillf 	    }
73654925bf6Swillf 	    db_args_size++;
73754925bf6Swillf 	    {
73854925bf6Swillf 		char **temp = realloc(db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */
73954925bf6Swillf 		if (temp == NULL) {
74054925bf6Swillf 		    fprintf(stderr, gettext("change_password: Not enough memory\n"));
74154925bf6Swillf 		    free(db_args), db_args = NULL;
74254925bf6Swillf 		    exit(1);
74354925bf6Swillf 		}
74454925bf6Swillf 
74554925bf6Swillf 		db_args = temp;
74654925bf6Swillf 	    }
74754925bf6Swillf 	    db_args[db_args_size-1] = *++argv;
74854925bf6Swillf 	    db_args[db_args_size]   = NULL;
74954925bf6Swillf 	    continue;
75054925bf6Swillf 	}
7517c478bd9Sstevel@tonic-gate 	if (!strcmp("-pw", *argv)) {
7527c478bd9Sstevel@tonic-gate 	    argc--;
7537c478bd9Sstevel@tonic-gate 	    if (argc < 1) {
7547c478bd9Sstevel@tonic-gate 		fprintf(stderr, "change_password: %s",
7557c478bd9Sstevel@tonic-gate 			gettext("missing password arg\n"));
7567c478bd9Sstevel@tonic-gate 		goto usage;
7577c478bd9Sstevel@tonic-gate 	    }
7587c478bd9Sstevel@tonic-gate 	    pwarg = *++argv;
7597c478bd9Sstevel@tonic-gate 	    continue;
7607c478bd9Sstevel@tonic-gate 	}
7617c478bd9Sstevel@tonic-gate 	if (!strcmp("-randkey", *argv)) {
7627c478bd9Sstevel@tonic-gate 	    randkey++;
7637c478bd9Sstevel@tonic-gate 	    continue;
7647c478bd9Sstevel@tonic-gate 	}
7657c478bd9Sstevel@tonic-gate 	if (!strcmp("-keepold", *argv)) {
76656a424ccSmp 	    keepold = TRUE;
7677c478bd9Sstevel@tonic-gate 	    continue;
7687c478bd9Sstevel@tonic-gate 	}
7697c478bd9Sstevel@tonic-gate 	if (!strcmp("-e", *argv)) {
7707c478bd9Sstevel@tonic-gate 	    argc--;
7717c478bd9Sstevel@tonic-gate 	    if (argc < 1) {
7727c478bd9Sstevel@tonic-gate 		fprintf(stderr, "change_password: %s",
7737c478bd9Sstevel@tonic-gate 			gettext("missing keysaltlist arg\n"));
7747c478bd9Sstevel@tonic-gate 		goto usage;
7757c478bd9Sstevel@tonic-gate 	    }
7767c478bd9Sstevel@tonic-gate 	    retval = krb5_string_to_keysalts(*++argv, ", \t", ":.-", 0,
7777c478bd9Sstevel@tonic-gate 					     &ks_tuple, &n_ks_tuple);
7787c478bd9Sstevel@tonic-gate 	    if (retval) {
7797c478bd9Sstevel@tonic-gate 		com_err("change_password", retval,
7807c478bd9Sstevel@tonic-gate 			gettext("while parsing keysalts %s"), *argv);
7817c478bd9Sstevel@tonic-gate 		return;
7827c478bd9Sstevel@tonic-gate 	    }
7837c478bd9Sstevel@tonic-gate 	    continue;
7847c478bd9Sstevel@tonic-gate 	}
7857c478bd9Sstevel@tonic-gate 	goto usage;
7867c478bd9Sstevel@tonic-gate     }
78754925bf6Swillf     if (*argv == NULL) {
78854925bf6Swillf 	com_err("change_password", 0, "missing principal name");
78954925bf6Swillf 	goto usage;
79054925bf6Swillf     }
7917c478bd9Sstevel@tonic-gate     retval = kadmin_parse_name(*argv, &princ);
7927c478bd9Sstevel@tonic-gate     if (retval) {
793*55fea89dSDan Cross 	com_err("change_password", retval,
7947c478bd9Sstevel@tonic-gate 		gettext("while parsing principal name"));
7957c478bd9Sstevel@tonic-gate 	if (ks_tuple != NULL)
7967c478bd9Sstevel@tonic-gate 	    free(ks_tuple);
79754925bf6Swillf 	if (db_args) free(db_args);
7987c478bd9Sstevel@tonic-gate 	goto usage;
7997c478bd9Sstevel@tonic-gate     }
8007c478bd9Sstevel@tonic-gate     retval = krb5_unparse_name(context, princ, &canon);
8017c478bd9Sstevel@tonic-gate     if (retval) {
8027c478bd9Sstevel@tonic-gate 		com_err("change_password", retval,
8037c478bd9Sstevel@tonic-gate 			gettext("while canonicalizing principal"));
8047c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, princ);
8057c478bd9Sstevel@tonic-gate 	if (ks_tuple != NULL)
8067c478bd9Sstevel@tonic-gate 	    free(ks_tuple);
80754925bf6Swillf 	if (db_args) free(db_args);
8087c478bd9Sstevel@tonic-gate 	return;
8097c478bd9Sstevel@tonic-gate     }
8107c478bd9Sstevel@tonic-gate     if (pwarg != NULL) {
8117c478bd9Sstevel@tonic-gate 	if (keepold || ks_tuple != NULL) {
8127c478bd9Sstevel@tonic-gate 	    retval = kadm5_chpass_principal_3(handle, princ, keepold,
8137c478bd9Sstevel@tonic-gate 					      n_ks_tuple, ks_tuple, pwarg);
8147c478bd9Sstevel@tonic-gate 	    if (ks_tuple != NULL)
8157c478bd9Sstevel@tonic-gate 		free(ks_tuple);
8167c478bd9Sstevel@tonic-gate 	} else {
8177c478bd9Sstevel@tonic-gate 	    retval = kadm5_chpass_principal(handle, princ, pwarg);
8187c478bd9Sstevel@tonic-gate 	}
8197c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, princ);
8207c478bd9Sstevel@tonic-gate 	if (retval) {
8217c478bd9Sstevel@tonic-gate 	    com_err("change_password", retval,
8227c478bd9Sstevel@tonic-gate 				gettext("while changing password for \"%s\"."),
8237c478bd9Sstevel@tonic-gate 				canon);
8247c478bd9Sstevel@tonic-gate 	    free(canon);
82554925bf6Swillf 	    if (db_args) free(db_args);
8267c478bd9Sstevel@tonic-gate 	    return;
8277c478bd9Sstevel@tonic-gate 	}
8287c478bd9Sstevel@tonic-gate 		printf(gettext("Password for \"%s\" changed.\n"), canon);
8297c478bd9Sstevel@tonic-gate 	free(canon);
83054925bf6Swillf 	if (db_args) free(db_args);
8317c478bd9Sstevel@tonic-gate 	return;
8327c478bd9Sstevel@tonic-gate     } else if (randkey) {
833bcfd778bSwillf 	if (keepold || ks_tuple != NULL || local_kadmin) {
8347c478bd9Sstevel@tonic-gate 	    retval = kadm5_randkey_principal_3(handle, princ, keepold,
8357c478bd9Sstevel@tonic-gate 					       n_ks_tuple, ks_tuple,
8367c478bd9Sstevel@tonic-gate 					       NULL, NULL);
8377c478bd9Sstevel@tonic-gate 	    if (ks_tuple != NULL)
8387c478bd9Sstevel@tonic-gate 		free(ks_tuple);
8397c478bd9Sstevel@tonic-gate 	} else {
8407c478bd9Sstevel@tonic-gate 	    retval = kadm5_randkey_principal(handle, princ, NULL, NULL);
8417c478bd9Sstevel@tonic-gate 	}
8427c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, princ);
8437c478bd9Sstevel@tonic-gate 	if (retval) {
8447c478bd9Sstevel@tonic-gate 	    com_err("change_password", retval,
8457c478bd9Sstevel@tonic-gate 				gettext("while randomizing key for \"%s\"."),
8467c478bd9Sstevel@tonic-gate 				canon);
8477c478bd9Sstevel@tonic-gate 	    free(canon);
84854925bf6Swillf 	    if (db_args) free(db_args);
8497c478bd9Sstevel@tonic-gate 	    return;
8507c478bd9Sstevel@tonic-gate 	}
8517c478bd9Sstevel@tonic-gate 	printf(gettext("Key for \"%s\" randomized.\n"), canon);
8527c478bd9Sstevel@tonic-gate 	free(canon);
85354925bf6Swillf 	if (db_args) free(db_args);
8547c478bd9Sstevel@tonic-gate 	return;
8557c478bd9Sstevel@tonic-gate     } else if (argc == 1) {
8567c478bd9Sstevel@tonic-gate 	unsigned int i = sizeof (newpw) - 1;
857*55fea89dSDan Cross 
8587c478bd9Sstevel@tonic-gate 		snprintf(prompt1, sizeof (prompt1),
859e49962a0Ssemery 			gettext("Enter password for principal \"%.900s\""),
8607c478bd9Sstevel@tonic-gate 			*argv);
8617c478bd9Sstevel@tonic-gate 		snprintf(prompt2, sizeof (prompt2),
862e49962a0Ssemery 			gettext("Re-enter password for principal \"%.900s\""),
8637c478bd9Sstevel@tonic-gate 			*argv);
8647c478bd9Sstevel@tonic-gate 	retval = krb5_read_password(context, prompt1, prompt2,
8657c478bd9Sstevel@tonic-gate 				    newpw, &i);
8667c478bd9Sstevel@tonic-gate 	if (retval) {
8677c478bd9Sstevel@tonic-gate 	    com_err("change_password", retval,
8687c478bd9Sstevel@tonic-gate 				gettext("while reading password for \"%s\"."),
8697c478bd9Sstevel@tonic-gate 				canon);
8707c478bd9Sstevel@tonic-gate 	    free(canon);
8717c478bd9Sstevel@tonic-gate 	    if (ks_tuple != NULL)
8727c478bd9Sstevel@tonic-gate 		free(ks_tuple);
8737c478bd9Sstevel@tonic-gate 	    krb5_free_principal(context, princ);
87454925bf6Swillf 	    if (db_args) free(db_args);
8757c478bd9Sstevel@tonic-gate 	    return;
8767c478bd9Sstevel@tonic-gate 	}
8777c478bd9Sstevel@tonic-gate 	if (keepold || ks_tuple != NULL) {
8787c478bd9Sstevel@tonic-gate 	    retval = kadm5_chpass_principal_3(handle, princ, keepold,
8797c478bd9Sstevel@tonic-gate 					      n_ks_tuple, ks_tuple,
8807c478bd9Sstevel@tonic-gate 					      newpw);
8817c478bd9Sstevel@tonic-gate 	    if (ks_tuple != NULL)
8827c478bd9Sstevel@tonic-gate 		free(ks_tuple);
8837c478bd9Sstevel@tonic-gate 	} else {
8847c478bd9Sstevel@tonic-gate 	    retval = kadm5_chpass_principal(handle, princ, newpw);
8857c478bd9Sstevel@tonic-gate 	}
8867c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, princ);
8877c478bd9Sstevel@tonic-gate 	memset(newpw, 0, sizeof (newpw));
8887c478bd9Sstevel@tonic-gate 	if (retval) {
8897c478bd9Sstevel@tonic-gate 	    com_err("change_password", retval,
8907c478bd9Sstevel@tonic-gate 				gettext("while changing password for \"%s\"."),
8917c478bd9Sstevel@tonic-gate 				canon);
8927c478bd9Sstevel@tonic-gate 	    free(canon);
89354925bf6Swillf 	    if (db_args) free(db_args);
8947c478bd9Sstevel@tonic-gate 	    return;
8957c478bd9Sstevel@tonic-gate 	}
8967c478bd9Sstevel@tonic-gate 		printf(gettext("Password for \"%s\" changed.\n"), canon);
8977c478bd9Sstevel@tonic-gate 	free(canon);
89854925bf6Swillf 	if (db_args) free(db_args);
8997c478bd9Sstevel@tonic-gate 	return;
90054925bf6Swillf     } else {
9017c478bd9Sstevel@tonic-gate 	free(canon);
9027c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, princ);
90354925bf6Swillf     usage:
90456a424ccSmp 	if (ks_tuple != NULL)
90556a424ccSmp 	    free(ks_tuple);
9067c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: change_password [-randkey] [-keepold] "
9077c478bd9Sstevel@tonic-gate 			"[-e keysaltlist] [-pw password] %s\n",
9087c478bd9Sstevel@tonic-gate 			gettext("usage"), gettext("principal"));
9097c478bd9Sstevel@tonic-gate 	return;
91054925bf6Swillf     }
9117c478bd9Sstevel@tonic-gate }
9127c478bd9Sstevel@tonic-gate 
91354925bf6Swillf static void
kadmin_free_tl_data(kadm5_principal_ent_t princ)91454925bf6Swillf kadmin_free_tl_data(kadm5_principal_ent_t princ)
91554925bf6Swillf {
91654925bf6Swillf     krb5_tl_data *tl_data = princ->tl_data;
91754925bf6Swillf     int n_tl_data         = princ->n_tl_data;
91854925bf6Swillf     int i;
91954925bf6Swillf 
92054925bf6Swillf     princ->n_tl_data = 0;
92154925bf6Swillf     princ->tl_data   = NULL;
92254925bf6Swillf 
92354925bf6Swillf     for (i = 0; tl_data && (i < n_tl_data); i++) {
92454925bf6Swillf 	krb5_tl_data *next = tl_data->tl_data_next;
92554925bf6Swillf 	if (tl_data->tl_data_contents)
92654925bf6Swillf 	    free(tl_data->tl_data_contents);
92754925bf6Swillf 	free(tl_data);
92854925bf6Swillf 	tl_data = next;
92954925bf6Swillf     }
93054925bf6Swillf }
93154925bf6Swillf 
93254925bf6Swillf #define KRB5_TL_DB_ARGS 0x7fff
93354925bf6Swillf static int
kadmin_parse_princ_args(argc,argv,oprinc,mask,pass,randkey,ks_tuple,n_ks_tuple,caller)93456a424ccSmp kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, randkey,
93556a424ccSmp 			ks_tuple, n_ks_tuple, caller)
9367c478bd9Sstevel@tonic-gate     int argc;
9377c478bd9Sstevel@tonic-gate     char *argv[];
9387c478bd9Sstevel@tonic-gate     kadm5_principal_ent_t oprinc;
9397c478bd9Sstevel@tonic-gate     long *mask;
9407c478bd9Sstevel@tonic-gate     char **pass;
9417c478bd9Sstevel@tonic-gate     int *randkey;
9427c478bd9Sstevel@tonic-gate     krb5_key_salt_tuple **ks_tuple;
9437c478bd9Sstevel@tonic-gate     int *n_ks_tuple;
9447c478bd9Sstevel@tonic-gate     char *caller;
9457c478bd9Sstevel@tonic-gate {
9467c478bd9Sstevel@tonic-gate     int i, j, attrib_set;
9477c478bd9Sstevel@tonic-gate     time_t date;
9487c478bd9Sstevel@tonic-gate     time_t now;
9497c478bd9Sstevel@tonic-gate     krb5_error_code retval;
95054925bf6Swillf     krb5_tl_data *tl_data, *tail = NULL;
95154925bf6Swillf 
9527c478bd9Sstevel@tonic-gate     *mask = 0;
9537c478bd9Sstevel@tonic-gate     *pass = NULL;
9547c478bd9Sstevel@tonic-gate     *n_ks_tuple = 0;
9557c478bd9Sstevel@tonic-gate     *ks_tuple = NULL;
9567c478bd9Sstevel@tonic-gate     time(&now);
9577c478bd9Sstevel@tonic-gate     *randkey = 0;
9587c478bd9Sstevel@tonic-gate     for (i = 1; i < argc - 1; i++) {
9597c478bd9Sstevel@tonic-gate 	attrib_set = 0;
96054925bf6Swillf 	if (strlen(argv[i]) == 2 &&
96154925bf6Swillf 	    !strcmp("-x",argv[i])) {
96254925bf6Swillf 	    if (++i > argc - 2)
96354925bf6Swillf 		return -1;
96454925bf6Swillf 
96554925bf6Swillf 	    tl_data = malloc(sizeof(krb5_tl_data));
96654925bf6Swillf 	    if (tl_data == NULL) {
96754925bf6Swillf 		fprintf(stderr, gettext("Not enough memory\n"));
96854925bf6Swillf 		return ENOMEM;
96954925bf6Swillf 	    }
97054925bf6Swillf 
97154925bf6Swillf 	    memset(tl_data, 0, sizeof(krb5_tl_data));
97254925bf6Swillf 	    tl_data->tl_data_type = KRB5_TL_DB_ARGS;
97354925bf6Swillf 	    tl_data->tl_data_length  = strlen(argv[i])+1;
97454925bf6Swillf 	    tl_data->tl_data_contents = (unsigned char*)strdup(argv[i]);
97554925bf6Swillf 
97654925bf6Swillf 	    if (tail) {
97754925bf6Swillf 		tail->tl_data_next = tl_data;
97854925bf6Swillf 	    } else {
97954925bf6Swillf 		oprinc->tl_data = tl_data;
98054925bf6Swillf 	    }
98154925bf6Swillf 	    tail = tl_data;
98254925bf6Swillf 	    oprinc->n_tl_data++;
98354925bf6Swillf 
98454925bf6Swillf 	    if (tl_data->tl_data_contents == NULL) {
98554925bf6Swillf 		fprintf(stderr, gettext("Not enough memory\n"));
98654925bf6Swillf 		return ENOMEM;
98754925bf6Swillf 	    }
98854925bf6Swillf 	    *mask |= KADM5_TL_DATA;
98954925bf6Swillf 	    continue;
99054925bf6Swillf 	}
9917c478bd9Sstevel@tonic-gate 	if (strlen(argv[i]) == 7 &&
99254925bf6Swillf 	    !strcmp("-expire", argv[i])) {
9937c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
99456a424ccSmp 		return -1;
9957c478bd9Sstevel@tonic-gate 	    else {
99656a424ccSmp 		date = get_date(argv[i]);
9977c478bd9Sstevel@tonic-gate  		if (date == (time_t)-1) {
99856a424ccSmp 		     fprintf(stderr,
9997c478bd9Sstevel@tonic-gate 						gettext("Invalid date "
10007c478bd9Sstevel@tonic-gate 							"specification "
10017c478bd9Sstevel@tonic-gate 							"\"%s\".\n"),
10027c478bd9Sstevel@tonic-gate 			     argv[i]);
100356a424ccSmp 		     return -1;
10047c478bd9Sstevel@tonic-gate  		}
10057c478bd9Sstevel@tonic-gate 		oprinc->princ_expire_time = date;
10067c478bd9Sstevel@tonic-gate 		*mask |= KADM5_PRINC_EXPIRE_TIME;
10077c478bd9Sstevel@tonic-gate 		continue;
10087c478bd9Sstevel@tonic-gate 	    }
10097c478bd9Sstevel@tonic-gate 	}
10107c478bd9Sstevel@tonic-gate 	if (strlen(argv[i]) == 9 &&
101156a424ccSmp 	    !strcmp("-pwexpire", argv[i])) {
10127c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
101356a424ccSmp 		return -1;
10147c478bd9Sstevel@tonic-gate 	    else {
101556a424ccSmp 		date = get_date(argv[i]);
10167c478bd9Sstevel@tonic-gate  		if (date == (time_t)-1) {
101756a424ccSmp 		     fprintf(stderr,
10187c478bd9Sstevel@tonic-gate 						gettext("Invalid date "
10197c478bd9Sstevel@tonic-gate 							"specification "
10207c478bd9Sstevel@tonic-gate 							"\"%s\".\n"),
10217c478bd9Sstevel@tonic-gate 			     argv[i]);
102256a424ccSmp 		     return -1;
10237c478bd9Sstevel@tonic-gate  		}
10247c478bd9Sstevel@tonic-gate 		oprinc->pw_expiration = date;
10257c478bd9Sstevel@tonic-gate 		*mask |= KADM5_PW_EXPIRATION;
10267c478bd9Sstevel@tonic-gate 		continue;
10277c478bd9Sstevel@tonic-gate 	    }
10287c478bd9Sstevel@tonic-gate 	}
10297c478bd9Sstevel@tonic-gate 	if (strlen(argv[i]) == 8 &&
103056a424ccSmp 	    !strcmp("-maxlife", argv[i])) {
10317c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
103256a424ccSmp 		return -1;
10337c478bd9Sstevel@tonic-gate 	    else {
103456a424ccSmp 		date = get_date(argv[i]);
10357c478bd9Sstevel@tonic-gate  		if (date == (time_t)-1) {
10367c478bd9Sstevel@tonic-gate 					fprintf(stderr,
10377c478bd9Sstevel@tonic-gate 						gettext("Invalid date "
10387c478bd9Sstevel@tonic-gate 							"specification "
10397c478bd9Sstevel@tonic-gate 							"\"%s\".\n"),
10407c478bd9Sstevel@tonic-gate 			     argv[i]);
104156a424ccSmp 		     return -1;
10427c478bd9Sstevel@tonic-gate  		}
10437c478bd9Sstevel@tonic-gate 		oprinc->max_life = date - now;
10447c478bd9Sstevel@tonic-gate 		*mask |= KADM5_MAX_LIFE;
10457c478bd9Sstevel@tonic-gate 		continue;
10467c478bd9Sstevel@tonic-gate 	    }
10477c478bd9Sstevel@tonic-gate 	}
10487c478bd9Sstevel@tonic-gate 	if (strlen(argv[i]) == 13 &&
104956a424ccSmp 	    !strcmp("-maxrenewlife", argv[i])) {
10507c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
105156a424ccSmp 		return -1;
10527c478bd9Sstevel@tonic-gate 	    else {
105356a424ccSmp 		date = get_date(argv[i]);
10547c478bd9Sstevel@tonic-gate  		if (date == (time_t)-1) {
10557c478bd9Sstevel@tonic-gate 					fprintf(stderr,
10567c478bd9Sstevel@tonic-gate 						gettext("Invalid date "
10577c478bd9Sstevel@tonic-gate 							"specification "
10587c478bd9Sstevel@tonic-gate 							"\"%s\".\n"),
10597c478bd9Sstevel@tonic-gate 			     argv[i]);
106056a424ccSmp 		     return -1;
10617c478bd9Sstevel@tonic-gate  		}
10627c478bd9Sstevel@tonic-gate 		oprinc->max_renewable_life = date - now;
10637c478bd9Sstevel@tonic-gate 		*mask |= KADM5_MAX_RLIFE;
10647c478bd9Sstevel@tonic-gate 		continue;
10657c478bd9Sstevel@tonic-gate 	    }
10667c478bd9Sstevel@tonic-gate 	}
10677c478bd9Sstevel@tonic-gate 	if (strlen(argv[i]) == 5 &&
106856a424ccSmp 	    !strcmp("-kvno", argv[i])) {
10697c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
107056a424ccSmp 		return -1;
10717c478bd9Sstevel@tonic-gate 	    else {
10727c478bd9Sstevel@tonic-gate 		oprinc->kvno = atoi(argv[i]);
10737c478bd9Sstevel@tonic-gate 		*mask |= KADM5_KVNO;
10747c478bd9Sstevel@tonic-gate 		continue;
10757c478bd9Sstevel@tonic-gate 	    }
10767c478bd9Sstevel@tonic-gate 	}
10777c478bd9Sstevel@tonic-gate 	if (strlen(argv[i]) == 7 &&
107856a424ccSmp 	    !strcmp("-policy", argv[i])) {
10797c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
108056a424ccSmp 		return -1;
10817c478bd9Sstevel@tonic-gate 	    else {
10827c478bd9Sstevel@tonic-gate 		oprinc->policy = argv[i];
10837c478bd9Sstevel@tonic-gate 		*mask |= KADM5_POLICY;
10847c478bd9Sstevel@tonic-gate 		continue;
10857c478bd9Sstevel@tonic-gate 	    }
10867c478bd9Sstevel@tonic-gate 	}
10877c478bd9Sstevel@tonic-gate 	if (strlen(argv[i]) == 12 &&
108856a424ccSmp 	    !strcmp("-clearpolicy", argv[i])) {
10897c478bd9Sstevel@tonic-gate 	    oprinc->policy = NULL;
10907c478bd9Sstevel@tonic-gate 	    *mask |= KADM5_POLICY_CLR;
10917c478bd9Sstevel@tonic-gate 	    continue;
10927c478bd9Sstevel@tonic-gate 	}
10937c478bd9Sstevel@tonic-gate 	if (strlen(argv[i]) == 3 &&
109456a424ccSmp 	    !strcmp("-pw", argv[i])) {
10957c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
109656a424ccSmp 		return -1;
10977c478bd9Sstevel@tonic-gate 	    else {
10987c478bd9Sstevel@tonic-gate 		*pass = argv[i];
10997c478bd9Sstevel@tonic-gate 		continue;
11007c478bd9Sstevel@tonic-gate 	    }
11017c478bd9Sstevel@tonic-gate 	}
11027c478bd9Sstevel@tonic-gate 	if (strlen(argv[i]) == 8 &&
110356a424ccSmp 	    !strcmp("-randkey", argv[i])) {
11047c478bd9Sstevel@tonic-gate 	    ++*randkey;
11057c478bd9Sstevel@tonic-gate 	    continue;
11067c478bd9Sstevel@tonic-gate 	}
11077c478bd9Sstevel@tonic-gate 	if (!strcmp("-e", argv[i])) {
11087c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
11097c478bd9Sstevel@tonic-gate 		return -1;
11107c478bd9Sstevel@tonic-gate 	    else {
11117c478bd9Sstevel@tonic-gate 		retval = krb5_string_to_keysalts(argv[i], ", \t", ":.-", 0,
11127c478bd9Sstevel@tonic-gate 						 ks_tuple, n_ks_tuple);
11137c478bd9Sstevel@tonic-gate 		if (retval) {
11147c478bd9Sstevel@tonic-gate 		    com_err(caller, retval,
11157c478bd9Sstevel@tonic-gate 			    gettext("while parsing keysalts %s"), argv[i]);
11167c478bd9Sstevel@tonic-gate 		    return -1;
11177c478bd9Sstevel@tonic-gate 		}
11187c478bd9Sstevel@tonic-gate 	    }
11197c478bd9Sstevel@tonic-gate 	    continue;
11207c478bd9Sstevel@tonic-gate 	}
11217c478bd9Sstevel@tonic-gate 	for (j = 0; j < sizeof (flags) / sizeof (struct pflag); j++) {
11227c478bd9Sstevel@tonic-gate 	    if (strlen(argv[i]) == flags[j].flaglen + 1 &&
112356a424ccSmp 		!strcmp(flags[j].flagname,
112456a424ccSmp 			&argv[i][1] /* strip off leading + or - */)) {
112556a424ccSmp 		if ((flags[j].set && argv[i][0] == '-') ||
112656a424ccSmp 		    (!flags[j].set && argv[i][0] == '+')) {
11277c478bd9Sstevel@tonic-gate 		    oprinc->attributes |= flags[j].theflag;
11287c478bd9Sstevel@tonic-gate 		    *mask |= KADM5_ATTRIBUTES;
11297c478bd9Sstevel@tonic-gate 		    attrib_set++;
11307c478bd9Sstevel@tonic-gate 		    break;
113156a424ccSmp 		} else if ((flags[j].set && argv[i][0] == '+') ||
113256a424ccSmp 			   (!flags[j].set && argv[i][0] == '-')) {
11337c478bd9Sstevel@tonic-gate 		    oprinc->attributes &= ~flags[j].theflag;
11347c478bd9Sstevel@tonic-gate 		    *mask |= KADM5_ATTRIBUTES;
11357c478bd9Sstevel@tonic-gate 		    attrib_set++;
11367c478bd9Sstevel@tonic-gate 		    break;
11377c478bd9Sstevel@tonic-gate 		} else {
113856a424ccSmp 		    return -1;
11397c478bd9Sstevel@tonic-gate 		}
11407c478bd9Sstevel@tonic-gate 	    }
11417c478bd9Sstevel@tonic-gate 	}
11427c478bd9Sstevel@tonic-gate 	if (!attrib_set)
114356a424ccSmp 	    return -1;		/* nothing was parsed */
11447c478bd9Sstevel@tonic-gate     }
11457c478bd9Sstevel@tonic-gate     if (i != argc - 1) {
114656a424ccSmp 	return -1;
11477c478bd9Sstevel@tonic-gate     }
11487c478bd9Sstevel@tonic-gate     retval = kadmin_parse_name(argv[i], &oprinc->principal);
11497c478bd9Sstevel@tonic-gate     if (retval) {
115056a424ccSmp 	com_err(caller, retval, gettext("while parsing principal"));
115156a424ccSmp 	return -1;
11527c478bd9Sstevel@tonic-gate     }
115356a424ccSmp     return 0;
11547c478bd9Sstevel@tonic-gate }
11557c478bd9Sstevel@tonic-gate 
115654925bf6Swillf static void
kadmin_addprinc_usage(func)11577c478bd9Sstevel@tonic-gate kadmin_addprinc_usage(func)
115854925bf6Swillf     char *func;
11597c478bd9Sstevel@tonic-gate {
11607c478bd9Sstevel@tonic-gate 	fprintf(stderr, "%s: %s %s\n", gettext("usage"), func,
11617c478bd9Sstevel@tonic-gate 		gettext("[options] principal"));
11627c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("\toptions are:\n"));
11637c478bd9Sstevel@tonic-gate 	fprintf(stderr, "\t\t[-expire expdate] [-pwexpire pwexpdate] "
11647c478bd9Sstevel@tonic-gate 		"[-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] "
11657c478bd9Sstevel@tonic-gate 		"[-randkey] [-pw password]\n\t\t[-maxrenewlife maxrenewlife] "
11667c478bd9Sstevel@tonic-gate 		"[-e keysaltlist] [{+|-}attribute]\n");
11677c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("\tattributes are:\n"));
11687c478bd9Sstevel@tonic-gate      fprintf(stderr, "%s%s%s",
11697c478bd9Sstevel@tonic-gate 		"\t\tallow_postdated allow_forwardable allow_tgs_req "
11707c478bd9Sstevel@tonic-gate 		"allow_renewable\n",
11717c478bd9Sstevel@tonic-gate 		"\t\tallow_proxiable allow_dup_skey allow_tix "
11727c478bd9Sstevel@tonic-gate 		"requires_preauth\n",
11737c478bd9Sstevel@tonic-gate 		"\t\trequires_hwauth needchange allow_svr "
11747c478bd9Sstevel@tonic-gate 		"password_changing_service\n");
11757c478bd9Sstevel@tonic-gate }
11767c478bd9Sstevel@tonic-gate 
117754925bf6Swillf static void
kadmin_modprinc_usage(func)11787c478bd9Sstevel@tonic-gate kadmin_modprinc_usage(func)
117954925bf6Swillf     char *func;
11807c478bd9Sstevel@tonic-gate {
11817c478bd9Sstevel@tonic-gate 	fprintf(stderr, "%s: %s %s\n", gettext("usage"), func,
11827c478bd9Sstevel@tonic-gate 		gettext("[options] principal"));
11837c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("\toptions are:\n"));
11847c478bd9Sstevel@tonic-gate 	fprintf(stderr, "\t\t[-expire expdate] [-pwexpire pwexpdate] "
11857c478bd9Sstevel@tonic-gate 		"[-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] "
11867c478bd9Sstevel@tonic-gate 		"[-clearpolicy]\n\t\t[-maxrenewlife maxrenewlife] "
11877c478bd9Sstevel@tonic-gate 		"[{+|-}attribute]\n");
11887c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("\tattributes are:\n"));
11897c478bd9Sstevel@tonic-gate      fprintf(stderr, "%s%s%s",
11907c478bd9Sstevel@tonic-gate 		"\t\tallow_postdated allow_forwardable allow_tgs_req "
11917c478bd9Sstevel@tonic-gate 		"allow_renewable\n",
11927c478bd9Sstevel@tonic-gate 		"\t\tallow_proxiable allow_dup_skey allow_tix "
11937c478bd9Sstevel@tonic-gate 		"requires_preauth\n",
11947c478bd9Sstevel@tonic-gate 		"\t\trequires_hwauth needchange allow_svr "
11957c478bd9Sstevel@tonic-gate 		"password_changing_service\n");
11967c478bd9Sstevel@tonic-gate }
11977c478bd9Sstevel@tonic-gate 
kadmin_addprinc(argc,argv)119856a424ccSmp void kadmin_addprinc(argc, argv)
11997c478bd9Sstevel@tonic-gate     int argc;
12007c478bd9Sstevel@tonic-gate     char *argv[];
12017c478bd9Sstevel@tonic-gate {
12027c478bd9Sstevel@tonic-gate     kadm5_principal_ent_rec princ, dprinc;
12037c478bd9Sstevel@tonic-gate     kadm5_policy_ent_rec defpol;
12047c478bd9Sstevel@tonic-gate     long mask;
12057c478bd9Sstevel@tonic-gate     int randkey = 0, i;
12067c478bd9Sstevel@tonic-gate     int n_ks_tuple;
12077c478bd9Sstevel@tonic-gate     krb5_key_salt_tuple *ks_tuple;
12087c478bd9Sstevel@tonic-gate     char *pass, *canon;
12097c478bd9Sstevel@tonic-gate     krb5_error_code retval;
12107c478bd9Sstevel@tonic-gate     static char newpw[1024], dummybuf[256];
12117c478bd9Sstevel@tonic-gate     static char prompt1[1024], prompt2[1024];
12127c478bd9Sstevel@tonic-gate     int local_kadmin = 0;
12137c478bd9Sstevel@tonic-gate 
12147c478bd9Sstevel@tonic-gate     local_kadmin = (strcmp(whoami, KADMIN_LOCAL_NAME) == 0);
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate     if (dummybuf[0] == 0) {
121754925bf6Swillf 	for (i = 0; i < 256; i++)
121854925bf6Swillf 	    dummybuf[i] = (i+1) % 256;
12197c478bd9Sstevel@tonic-gate     }
122054925bf6Swillf 
12217c478bd9Sstevel@tonic-gate     /* Zero all fields in request structure */
12227c478bd9Sstevel@tonic-gate     memset(&princ, 0, sizeof(princ));
12237c478bd9Sstevel@tonic-gate     memset(&dprinc, 0, sizeof(dprinc));
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate     princ.attributes = dprinc.attributes = 0;
12267c478bd9Sstevel@tonic-gate     if (kadmin_parse_princ_args(argc, argv,
12277c478bd9Sstevel@tonic-gate 				&princ, &mask, &pass, &randkey,
12287c478bd9Sstevel@tonic-gate 				&ks_tuple, &n_ks_tuple,
12297c478bd9Sstevel@tonic-gate 				"add_principal")) {
123054925bf6Swillf 	kadmin_addprinc_usage("add_principal");
123154925bf6Swillf 	kadmin_free_tl_data(&princ); /* need to free ks_tuple also??? */
123254925bf6Swillf 	return;
12337c478bd9Sstevel@tonic-gate     }
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate     retval = krb5_unparse_name(context, princ.principal, &canon);
12367c478bd9Sstevel@tonic-gate     if (retval) {
123754925bf6Swillf 	com_err("add_principal",
123854925bf6Swillf 		retval, gettext("while canonicalizing principal"));
12397c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, princ.principal);
12407c478bd9Sstevel@tonic-gate 	if (ks_tuple != NULL)
12417c478bd9Sstevel@tonic-gate 	    free(ks_tuple);
124254925bf6Swillf 	kadmin_free_tl_data(&princ);
12437c478bd9Sstevel@tonic-gate 	return;
12447c478bd9Sstevel@tonic-gate     }
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate     /*
12477c478bd9Sstevel@tonic-gate      * If -policy was not specified, and -clearpolicy was not
12487c478bd9Sstevel@tonic-gate      * specified, and the policy "default" exists, assign it.  If
12497c478bd9Sstevel@tonic-gate      * -clearpolicy was specified, then KADM5_POLICY_CLR should be
12507c478bd9Sstevel@tonic-gate      * unset, since it is never valid for kadm5_create_principal.
12517c478bd9Sstevel@tonic-gate      */
12527c478bd9Sstevel@tonic-gate     if ((! (mask & KADM5_POLICY)) &&
12537c478bd9Sstevel@tonic-gate 	(! (mask & KADM5_POLICY_CLR))) {
125454925bf6Swillf 	if (! kadm5_get_policy(handle, "default", &defpol)) {
125554925bf6Swillf 	    fprintf(stderr,
125654925bf6Swillf 		    gettext("NOTICE: no policy specified for %s; assigning \"default\"\n"),
125754925bf6Swillf 		    canon);
125854925bf6Swillf 	    princ.policy = "default";
125954925bf6Swillf 	    mask |= KADM5_POLICY;
126054925bf6Swillf 	    (void) kadm5_free_policy_ent(handle, &defpol);
126154925bf6Swillf 	} else
126254925bf6Swillf 	    fprintf(stderr,
126354925bf6Swillf 		    gettext("WARNING: no policy specified for %s; defaulting to no policy\n"),
12647c478bd9Sstevel@tonic-gate 		    canon);
12657c478bd9Sstevel@tonic-gate     }
12667c478bd9Sstevel@tonic-gate     mask &= ~KADM5_POLICY_CLR;
1267*55fea89dSDan Cross 
12687c478bd9Sstevel@tonic-gate     /*
12697c478bd9Sstevel@tonic-gate      * Set 'notix' for randkey principals and also for principals which have
12707c478bd9Sstevel@tonic-gate      * specified flag options on the cmdline. This is because we want to apply
12717c478bd9Sstevel@tonic-gate      * generic flag settings from 'default_principal_flags' first (during
12727c478bd9Sstevel@tonic-gate      * principal creation), followed by a kadm5_modify_principal() which
12737c478bd9Sstevel@tonic-gate      * correctly applies the cli flag options. So, we do *not* want any tix
12747c478bd9Sstevel@tonic-gate      * issued in the interim.
12757c478bd9Sstevel@tonic-gate      */
12767c478bd9Sstevel@tonic-gate     if (randkey || (mask & KADM5_ATTRIBUTES))
12777c478bd9Sstevel@tonic-gate 	princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
12787c478bd9Sstevel@tonic-gate 
1279*55fea89dSDan Cross     if (randkey) {
12807c478bd9Sstevel@tonic-gate 	mask |= KADM5_ATTRIBUTES;
128156a424ccSmp 	pass = dummybuf;
12827c478bd9Sstevel@tonic-gate     } else if (pass == NULL) {
128356a424ccSmp 	unsigned int sz = sizeof (newpw) - 1;
12847c478bd9Sstevel@tonic-gate 	snprintf(prompt1, sizeof (prompt1),
1285e49962a0Ssemery 		gettext("Enter password for principal \"%.900s\""),
12867c478bd9Sstevel@tonic-gate 		canon);
12877c478bd9Sstevel@tonic-gate 	snprintf(prompt2, sizeof (prompt1),
1288e49962a0Ssemery 		gettext("Re-enter password for principal \"%.900s\""),
12897c478bd9Sstevel@tonic-gate 		canon);
12907c478bd9Sstevel@tonic-gate 	retval = krb5_read_password(context, prompt1, prompt2,
129156a424ccSmp 				    newpw, &sz);
12927c478bd9Sstevel@tonic-gate 	if (retval) {
12937c478bd9Sstevel@tonic-gate 	    com_err("add_principal", retval,
12947c478bd9Sstevel@tonic-gate 		gettext("while reading password for \"%s\"."), canon);
12957c478bd9Sstevel@tonic-gate 	    free(canon);
12967c478bd9Sstevel@tonic-gate 	    krb5_free_principal(context, princ.principal);
129754925bf6Swillf 	    kadmin_free_tl_data(&princ);
12987c478bd9Sstevel@tonic-gate 	    return;
12997c478bd9Sstevel@tonic-gate 	}
13007c478bd9Sstevel@tonic-gate 	pass = newpw;
13017c478bd9Sstevel@tonic-gate     }
13027c478bd9Sstevel@tonic-gate     mask |= KADM5_PRINCIPAL;
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate     /*
13057c478bd9Sstevel@tonic-gate      * If the client being used is local, always use the new
13067c478bd9Sstevel@tonic-gate      * API so we get the full set of enctype support.
13077c478bd9Sstevel@tonic-gate      */
13087c478bd9Sstevel@tonic-gate     if (ks_tuple != NULL || local_kadmin) {
13097c478bd9Sstevel@tonic-gate 	retval = kadm5_create_principal_3(handle, &princ, mask,
13107c478bd9Sstevel@tonic-gate 					  n_ks_tuple, ks_tuple, pass);
13117c478bd9Sstevel@tonic-gate     } else {
13127c478bd9Sstevel@tonic-gate 	retval = kadm5_create_principal(handle, &princ, mask, pass);
13137c478bd9Sstevel@tonic-gate     }
13147c478bd9Sstevel@tonic-gate     if (retval) {
13157c478bd9Sstevel@tonic-gate 	com_err("add_principal", retval,
13167c478bd9Sstevel@tonic-gate 		gettext("while creating \"%s\"."), canon);
13177c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, princ.principal);
13187c478bd9Sstevel@tonic-gate 	free(canon);
13197c478bd9Sstevel@tonic-gate 	if (ks_tuple != NULL)
13207c478bd9Sstevel@tonic-gate 	    free(ks_tuple);
132154925bf6Swillf 	kadmin_free_tl_data(&princ);
13227c478bd9Sstevel@tonic-gate 	return;
13237c478bd9Sstevel@tonic-gate     }
132456a424ccSmp     if (randkey) {		/* more special stuff for -randkey */
13257c478bd9Sstevel@tonic-gate 	if (ks_tuple != NULL || local_kadmin) {
13267c478bd9Sstevel@tonic-gate 	    retval = kadm5_randkey_principal_3(handle, princ.principal,
13277c478bd9Sstevel@tonic-gate 					       FALSE,
13287c478bd9Sstevel@tonic-gate 					       n_ks_tuple, ks_tuple,
13297c478bd9Sstevel@tonic-gate 					       NULL, NULL);
13307c478bd9Sstevel@tonic-gate 	} else {
13317c478bd9Sstevel@tonic-gate 	    retval = kadm5_randkey_principal(handle, princ.principal,
13327c478bd9Sstevel@tonic-gate 					     NULL, NULL);
13337c478bd9Sstevel@tonic-gate 	}
13347c478bd9Sstevel@tonic-gate 	if (retval) {
13357c478bd9Sstevel@tonic-gate 	    com_err("add_principal", retval,
13367c478bd9Sstevel@tonic-gate 		gettext("while randomizing key for \"%s\"."), canon);
13377c478bd9Sstevel@tonic-gate 	    krb5_free_principal(context, princ.principal);
13387c478bd9Sstevel@tonic-gate 	    free(canon);
13397c478bd9Sstevel@tonic-gate 	    if (ks_tuple != NULL)
13407c478bd9Sstevel@tonic-gate 		free(ks_tuple);
134154925bf6Swillf 	    kadmin_free_tl_data(&princ);
13427c478bd9Sstevel@tonic-gate 	    return;
13437c478bd9Sstevel@tonic-gate 	}
13447c478bd9Sstevel@tonic-gate     }
13457c478bd9Sstevel@tonic-gate 
13467c478bd9Sstevel@tonic-gate     /*
13477c478bd9Sstevel@tonic-gate      * We now retrieve the intersection set of the generic flag settings and
13487c478bd9Sstevel@tonic-gate      * the ones specified on the cli & re-parse the princ args, just to make
13497c478bd9Sstevel@tonic-gate      * sure we account for conflicts between 'default_principal_flags' and
13507c478bd9Sstevel@tonic-gate      * the cmdline flag args. While we are here, also clear 'notix'.
13517c478bd9Sstevel@tonic-gate      */
13527c478bd9Sstevel@tonic-gate     if (randkey || (mask & KADM5_ATTRIBUTES)) {
13537c478bd9Sstevel@tonic-gate 	retval = kadm5_get_principal(handle, princ.principal, &dprinc,
13547c478bd9Sstevel@tonic-gate 			KADM5_PRINCIPAL_NORMAL_MASK);
13557c478bd9Sstevel@tonic-gate         if (retval == 0) {
13567c478bd9Sstevel@tonic-gate 	    if (dprinc.attributes != 0)
13577c478bd9Sstevel@tonic-gate 		princ.attributes = dprinc.attributes;
13587c478bd9Sstevel@tonic-gate 	} else {
13597c478bd9Sstevel@tonic-gate 	    com_err("add_principal", retval,
13607c478bd9Sstevel@tonic-gate 		gettext("while doing a get_principal on \"%s\"."), canon);
13617c478bd9Sstevel@tonic-gate 	    printf(gettext("\nWarning: Principal \"%s\" could have incomplete "
13627c478bd9Sstevel@tonic-gate 		"flag settings, as a result of a failed get_principal.\n"
1363bbf21555SRichard Lowe 		"Check the 'default_principal_flags' setting in kdc.conf(5).\n"
1364bbf21555SRichard Lowe 		"If there is a mismatch, use modprinc in kadmin(8) to rectify "
13657c478bd9Sstevel@tonic-gate 		"the same.\n\n"), canon);
13667c478bd9Sstevel@tonic-gate 	}
13677c478bd9Sstevel@tonic-gate 
13681fceb383Ssemery 	/*
13691fceb383Ssemery 	 * Solaris Kerberos: We unset KRB5_KDB_DISALLOW_ALL_TIX before
13701fceb383Ssemery 	 * kadmin_parse_princ_args is called, because -allow_tix may
13711fceb383Ssemery 	 * have been an argument.  We still have to unset here because
13721fceb383Ssemery 	 * kadmin_parse_princ_args will not reset the attribute unless
13731fceb383Ssemery 	 * it is was explicity defined.
13741fceb383Ssemery 	 */
13751fceb383Ssemery 	princ.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX;
13767c478bd9Sstevel@tonic-gate 	(void) kadmin_parse_princ_args(argc, argv, &princ, &mask, &pass,
13777c478bd9Sstevel@tonic-gate 			&randkey, &ks_tuple, &n_ks_tuple, "add_principal");
13787c478bd9Sstevel@tonic-gate 	mask = KADM5_ATTRIBUTES;
13797c478bd9Sstevel@tonic-gate 	retval = kadm5_modify_principal(handle, &princ, mask);
13807c478bd9Sstevel@tonic-gate 	if (retval) {
13817c478bd9Sstevel@tonic-gate 	    com_err("add_principal", retval,
13827c478bd9Sstevel@tonic-gate 		gettext("while doing a modify_principal to restore flag "
13837c478bd9Sstevel@tonic-gate 			"settings for \"%s\"."), canon);
13847c478bd9Sstevel@tonic-gate 	    krb5_free_principal(context, princ.principal);
13857c478bd9Sstevel@tonic-gate 	    free(canon);
13867c478bd9Sstevel@tonic-gate 	    if (ks_tuple != NULL)
13877c478bd9Sstevel@tonic-gate 		free(ks_tuple);
138854925bf6Swillf 	    kadmin_free_tl_data(&princ);
13897c478bd9Sstevel@tonic-gate 	    return;
13907c478bd9Sstevel@tonic-gate 	}
13917c478bd9Sstevel@tonic-gate     }
13927c478bd9Sstevel@tonic-gate     krb5_free_principal(context, princ.principal);
13937c478bd9Sstevel@tonic-gate 	printf(gettext("Principal \"%s\" created.\n"), canon);
13947c478bd9Sstevel@tonic-gate     if (ks_tuple != NULL)
13957c478bd9Sstevel@tonic-gate 	free(ks_tuple);
13967c478bd9Sstevel@tonic-gate     free(canon);
139754925bf6Swillf     kadmin_free_tl_data(&princ);
139854925bf6Swillf 
13997c478bd9Sstevel@tonic-gate }
14007c478bd9Sstevel@tonic-gate 
kadmin_modprinc(argc,argv)140156a424ccSmp void kadmin_modprinc(argc, argv)
14027c478bd9Sstevel@tonic-gate     int argc;
14037c478bd9Sstevel@tonic-gate     char *argv[];
14047c478bd9Sstevel@tonic-gate {
14057c478bd9Sstevel@tonic-gate     kadm5_principal_ent_rec princ, oldprinc;
14067c478bd9Sstevel@tonic-gate     krb5_principal kprinc;
14077c478bd9Sstevel@tonic-gate     long mask;
14087c478bd9Sstevel@tonic-gate     krb5_error_code retval;
14097c478bd9Sstevel@tonic-gate     char *pass, *canon;
14107c478bd9Sstevel@tonic-gate     int randkey = 0;
14117c478bd9Sstevel@tonic-gate     int n_ks_tuple = 0;
14127c478bd9Sstevel@tonic-gate     krb5_key_salt_tuple *ks_tuple;
14137c478bd9Sstevel@tonic-gate 
14147c478bd9Sstevel@tonic-gate     if (argc < 2) {
141554925bf6Swillf 	kadmin_modprinc_usage("modify_principal");
141654925bf6Swillf 	return;
14177c478bd9Sstevel@tonic-gate     }
14187c478bd9Sstevel@tonic-gate 
14197c478bd9Sstevel@tonic-gate     memset(&oldprinc, 0, sizeof(oldprinc));
14207c478bd9Sstevel@tonic-gate     memset(&princ, 0, sizeof(princ));
14217c478bd9Sstevel@tonic-gate 
14227c478bd9Sstevel@tonic-gate     retval = kadmin_parse_name(argv[argc - 1], &kprinc);
14237c478bd9Sstevel@tonic-gate     if (retval) {
142456a424ccSmp 	com_err("modify_principal", retval,
14257c478bd9Sstevel@tonic-gate 			gettext("while parsing principal"));
14267c478bd9Sstevel@tonic-gate 	return;
14277c478bd9Sstevel@tonic-gate     }
14287c478bd9Sstevel@tonic-gate     retval = krb5_unparse_name(context, kprinc, &canon);
14297c478bd9Sstevel@tonic-gate     if (retval) {
14307c478bd9Sstevel@tonic-gate 	com_err("modify_principal", retval,
14317c478bd9Sstevel@tonic-gate 			gettext("while canonicalizing principal"));
14327c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, kprinc);
14337c478bd9Sstevel@tonic-gate 	return;
14347c478bd9Sstevel@tonic-gate     }
14357c478bd9Sstevel@tonic-gate     retval = kadm5_get_principal(handle, kprinc, &oldprinc,
14367c478bd9Sstevel@tonic-gate 				 KADM5_PRINCIPAL_NORMAL_MASK);
14377c478bd9Sstevel@tonic-gate     krb5_free_principal(context, kprinc);
14387c478bd9Sstevel@tonic-gate     if (retval) {
143956a424ccSmp 	com_err("modify_principal", retval,
14407c478bd9Sstevel@tonic-gate 			gettext("while getting \"%s\"."), canon);
14417c478bd9Sstevel@tonic-gate 	free(canon);
14427c478bd9Sstevel@tonic-gate 	return;
14437c478bd9Sstevel@tonic-gate     }
14447c478bd9Sstevel@tonic-gate     princ.attributes = oldprinc.attributes;
14457c478bd9Sstevel@tonic-gate     kadm5_free_principal_ent(handle, &oldprinc);
14467c478bd9Sstevel@tonic-gate     retval = kadmin_parse_princ_args(argc, argv,
14477c478bd9Sstevel@tonic-gate 				     &princ, &mask,
14487c478bd9Sstevel@tonic-gate 				     &pass, &randkey,
14497c478bd9Sstevel@tonic-gate 				     &ks_tuple, &n_ks_tuple,
14507c478bd9Sstevel@tonic-gate 				     "modify_principal");
14517c478bd9Sstevel@tonic-gate     if (ks_tuple != NULL) {
14527c478bd9Sstevel@tonic-gate 	free(ks_tuple);
14537c478bd9Sstevel@tonic-gate 	kadmin_modprinc_usage("modify_principal");
14547c478bd9Sstevel@tonic-gate 	free(canon);
145554925bf6Swillf 	kadmin_free_tl_data(&princ);
14567c478bd9Sstevel@tonic-gate 	return;
14577c478bd9Sstevel@tonic-gate     }
14587c478bd9Sstevel@tonic-gate     if (retval) {
14597c478bd9Sstevel@tonic-gate 	kadmin_modprinc_usage("modify_principal");
14607c478bd9Sstevel@tonic-gate 	free(canon);
146154925bf6Swillf 	kadmin_free_tl_data(&princ);
14627c478bd9Sstevel@tonic-gate 	return;
14637c478bd9Sstevel@tonic-gate     }
14647c478bd9Sstevel@tonic-gate     if (randkey) {
14657c478bd9Sstevel@tonic-gate 		fprintf(stderr, "modify_principal: -randkey %s ",
14667c478bd9Sstevel@tonic-gate 			gettext("not allowed\n"));
14677c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, princ.principal);
14687c478bd9Sstevel@tonic-gate 	free(canon);
146954925bf6Swillf 	kadmin_free_tl_data(&princ);
14707c478bd9Sstevel@tonic-gate 	return;
14717c478bd9Sstevel@tonic-gate     }
14727c478bd9Sstevel@tonic-gate     if (pass) {
14737c478bd9Sstevel@tonic-gate 	fprintf(stderr,
14747c478bd9Sstevel@tonic-gate 		"modify_principal: -pw %s change_password\n",
14757c478bd9Sstevel@tonic-gate 		gettext("not allowed; use"));
14767c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, princ.principal);
14777c478bd9Sstevel@tonic-gate 	free(canon);
147854925bf6Swillf 	kadmin_free_tl_data(&princ);
14797c478bd9Sstevel@tonic-gate 	return;
14807c478bd9Sstevel@tonic-gate     }
14817c478bd9Sstevel@tonic-gate     retval = kadm5_modify_principal(handle, &princ, mask);
14827c478bd9Sstevel@tonic-gate     krb5_free_principal(context, princ.principal);
14837c478bd9Sstevel@tonic-gate     if (retval) {
14847c478bd9Sstevel@tonic-gate 	com_err("modify_principal", retval,
14857c478bd9Sstevel@tonic-gate 			gettext("while modifying \"%s\"."), canon);
14867c478bd9Sstevel@tonic-gate 	free(canon);
148754925bf6Swillf 	kadmin_free_tl_data(&princ);
14887c478bd9Sstevel@tonic-gate 	return;
14897c478bd9Sstevel@tonic-gate     }
14907c478bd9Sstevel@tonic-gate 	printf(gettext("Principal \"%s\" modified.\n"), canon);
149154925bf6Swillf     kadmin_free_tl_data(&princ);
14927c478bd9Sstevel@tonic-gate     free(canon);
14937c478bd9Sstevel@tonic-gate }
14947c478bd9Sstevel@tonic-gate 
kadmin_getprinc(argc,argv)149556a424ccSmp void kadmin_getprinc(argc, argv)
14967c478bd9Sstevel@tonic-gate     int argc;
14977c478bd9Sstevel@tonic-gate     char *argv[];
14987c478bd9Sstevel@tonic-gate {
14997c478bd9Sstevel@tonic-gate     kadm5_principal_ent_rec dprinc;
15007c478bd9Sstevel@tonic-gate     krb5_principal princ;
15017c478bd9Sstevel@tonic-gate     krb5_error_code retval;
15027c478bd9Sstevel@tonic-gate     char *canon, *modcanon;
15037c478bd9Sstevel@tonic-gate     int i;
150454925bf6Swillf 
15057c478bd9Sstevel@tonic-gate     if (! (argc == 2 ||
150656a424ccSmp 	   (argc == 3 && !strcmp("-terse", argv[1])))) {
15077c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: get_principal [-terse] %s\n",
15087c478bd9Sstevel@tonic-gate 			gettext("usage"), gettext("principal"));
15097c478bd9Sstevel@tonic-gate 	return;
15107c478bd9Sstevel@tonic-gate     }
151156a424ccSmp 
151256a424ccSmp 
15137c478bd9Sstevel@tonic-gate     memset(&dprinc, 0, sizeof(dprinc));
15147c478bd9Sstevel@tonic-gate     memset(&princ, 0, sizeof(princ));
15157c478bd9Sstevel@tonic-gate 
15167c478bd9Sstevel@tonic-gate     retval = kadmin_parse_name(argv[argc - 1], &princ);
15177c478bd9Sstevel@tonic-gate     if (retval) {
151856a424ccSmp 	com_err("get_principal", retval,
15197c478bd9Sstevel@tonic-gate 			gettext("while parsing principal"));
15207c478bd9Sstevel@tonic-gate 	return;
15217c478bd9Sstevel@tonic-gate     }
15227c478bd9Sstevel@tonic-gate     retval = krb5_unparse_name(context, princ, &canon);
15237c478bd9Sstevel@tonic-gate     if (retval) {
152456a424ccSmp 	com_err("get_principal", retval,
15257c478bd9Sstevel@tonic-gate 			gettext("while canonicalizing principal"));
15267c478bd9Sstevel@tonic-gate 	krb5_free_principal(context, princ);
15277c478bd9Sstevel@tonic-gate 	return;
15287c478bd9Sstevel@tonic-gate     }
15297c478bd9Sstevel@tonic-gate     retval = kadm5_get_principal(handle, princ, &dprinc,
15307c478bd9Sstevel@tonic-gate 				 KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA);
15317c478bd9Sstevel@tonic-gate     krb5_free_principal(context, princ);
15327c478bd9Sstevel@tonic-gate     if (retval) {
153356a424ccSmp 	com_err("get_principal", retval,
15347c478bd9Sstevel@tonic-gate 			gettext("while retrieving \"%s\"."), canon);
15357c478bd9Sstevel@tonic-gate 	free(canon);
15367c478bd9Sstevel@tonic-gate 	return;
15377c478bd9Sstevel@tonic-gate     }
15387c478bd9Sstevel@tonic-gate     retval = krb5_unparse_name(context, dprinc.mod_name, &modcanon);
15397c478bd9Sstevel@tonic-gate     if (retval) {
154056a424ccSmp 	com_err("get_principal", retval,
15417c478bd9Sstevel@tonic-gate 			gettext("while unparsing modname"));
15427c478bd9Sstevel@tonic-gate 	kadm5_free_principal_ent(handle, &dprinc);
15437c478bd9Sstevel@tonic-gate 	free(canon);
15447c478bd9Sstevel@tonic-gate 	return;
15457c478bd9Sstevel@tonic-gate     }
15467c478bd9Sstevel@tonic-gate     if (argc == 2) {
15477c478bd9Sstevel@tonic-gate 		printf(gettext("Principal: %s\n"), canon);
15487c478bd9Sstevel@tonic-gate 		printf(gettext("Expiration date: %s\n"),
15497c478bd9Sstevel@tonic-gate 		    dprinc.princ_expire_time ?
15507c478bd9Sstevel@tonic-gate 		    strdate(dprinc.princ_expire_time) :
15517c478bd9Sstevel@tonic-gate 		    gettext("[never]"));
15527c478bd9Sstevel@tonic-gate 		printf(gettext("Last password change: %s\n"),
15537c478bd9Sstevel@tonic-gate 		    dprinc.last_pwd_change ?
15547c478bd9Sstevel@tonic-gate 		    strdate(dprinc.last_pwd_change) :
15557c478bd9Sstevel@tonic-gate 		    gettext("[never]"));
15567c478bd9Sstevel@tonic-gate 		printf(gettext("Password expiration date: %s\n"),
15577c478bd9Sstevel@tonic-gate 	       dprinc.pw_expiration ?
15587c478bd9Sstevel@tonic-gate 		    strdate(dprinc.pw_expiration) : gettext("[none]"));
15597c478bd9Sstevel@tonic-gate 		printf(gettext("Maximum ticket life: %s\n"),
15607c478bd9Sstevel@tonic-gate 		    strdur(dprinc.max_life));
15617c478bd9Sstevel@tonic-gate 		printf(gettext("Maximum renewable life: %s\n"),
15627c478bd9Sstevel@tonic-gate 		    strdur(dprinc.max_renewable_life));
15637c478bd9Sstevel@tonic-gate 		printf(gettext("Last modified: %s (%s)\n"),
15647c478bd9Sstevel@tonic-gate 		    strdate(dprinc.mod_date), modcanon);
15657c478bd9Sstevel@tonic-gate 		printf(gettext("Last successful authentication: %s\n"),
15667c478bd9Sstevel@tonic-gate 	       dprinc.last_success ? strdate(dprinc.last_success) :
15677c478bd9Sstevel@tonic-gate 		    gettext("[never]"));
15687c478bd9Sstevel@tonic-gate 		printf(gettext("Last failed authentication: %s\n"),
15697c478bd9Sstevel@tonic-gate 	       dprinc.last_failed ? strdate(dprinc.last_failed) :
15707c478bd9Sstevel@tonic-gate 		    gettext("[never]"));
15717c478bd9Sstevel@tonic-gate 		printf(gettext("Failed password attempts: %d\n"),
15727c478bd9Sstevel@tonic-gate 	       dprinc.fail_auth_count);
15737c478bd9Sstevel@tonic-gate 		printf(gettext("Number of keys: %d\n"), dprinc.n_key_data);
15747c478bd9Sstevel@tonic-gate 	for (i = 0; i < dprinc.n_key_data; i++) {
157554925bf6Swillf 	    krb5_key_data *key_data = &dprinc.key_data[i];
157654925bf6Swillf 	    char enctype[BUFSIZ], salttype[BUFSIZ];
157754925bf6Swillf 
157854925bf6Swillf 	    if (krb5_enctype_to_string(key_data->key_data_type[0],
157954925bf6Swillf 				       enctype, sizeof(enctype)))
158054925bf6Swillf 		snprintf(enctype, sizeof (enctype), gettext("<Encryption type 0x%x>"),
158154925bf6Swillf 			key_data->key_data_type[0]);
158254925bf6Swillf 	    printf("Key: vno %d, %s, ", key_data->key_data_kvno, enctype);
158354925bf6Swillf 	    if (key_data->key_data_ver > 1) {
158454925bf6Swillf 		if (krb5_salttype_to_string(key_data->key_data_type[1],
158554925bf6Swillf 					    salttype, sizeof(salttype)))
158654925bf6Swillf 		    snprintf(salttype, sizeof(salttype), gettext("<Salt type 0x%x>"),
158754925bf6Swillf 			    key_data->key_data_type[1]);
158854925bf6Swillf 		printf("%s\n", salttype);
158954925bf6Swillf 	    } else
159054925bf6Swillf 		printf(gettext("no salt\n"));
15917c478bd9Sstevel@tonic-gate 	}
159254925bf6Swillf 
159354925bf6Swillf 	printf(gettext("Attributes:"));
15947c478bd9Sstevel@tonic-gate 	for (i = 0; i < sizeof (prflags) / sizeof (char *); i++) {
15957c478bd9Sstevel@tonic-gate 	    if (dprinc.attributes & (krb5_flags) 1 << i)
15967c478bd9Sstevel@tonic-gate 		printf(" %s", prflags[i]);
15977c478bd9Sstevel@tonic-gate 	}
15987c478bd9Sstevel@tonic-gate 	printf("\n");
15997c478bd9Sstevel@tonic-gate 		printf(gettext("Policy: %s\n"),
16007c478bd9Sstevel@tonic-gate 		    dprinc.policy ? dprinc.policy : gettext("[none]"));
16017c478bd9Sstevel@tonic-gate     } else {
16027c478bd9Sstevel@tonic-gate 	printf("\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\t%d\t%d\t%d\t%d\t\"%s\""
16037c478bd9Sstevel@tonic-gate 	       "\t%d\t%d\t%d\t%d\t%d",
16047c478bd9Sstevel@tonic-gate 	       canon, dprinc.princ_expire_time, dprinc.last_pwd_change,
16057c478bd9Sstevel@tonic-gate 	       dprinc.pw_expiration, dprinc.max_life, modcanon,
16067c478bd9Sstevel@tonic-gate 	       dprinc.mod_date, dprinc.attributes, dprinc.kvno,
160754925bf6Swillf 	       dprinc.mkvno, dprinc.policy ? dprinc.policy : gettext("[none]"),
16087c478bd9Sstevel@tonic-gate 	       dprinc.max_renewable_life, dprinc.last_success,
16097c478bd9Sstevel@tonic-gate 	       dprinc.last_failed, dprinc.fail_auth_count,
16107c478bd9Sstevel@tonic-gate 	       dprinc.n_key_data);
16117c478bd9Sstevel@tonic-gate 	for (i = 0; i < dprinc.n_key_data; i++)
161254925bf6Swillf 	    printf("\t%d\t%d\t%d\t%d",
161354925bf6Swillf 		   dprinc.key_data[i].key_data_ver,
161454925bf6Swillf 		   dprinc.key_data[i].key_data_kvno,
161554925bf6Swillf 		   dprinc.key_data[i].key_data_type[0],
161654925bf6Swillf 		   dprinc.key_data[i].key_data_type[1]);
16177c478bd9Sstevel@tonic-gate 	printf("\n");
161854925bf6Swillf     }
16197c478bd9Sstevel@tonic-gate     free(modcanon);
16207c478bd9Sstevel@tonic-gate     kadm5_free_principal_ent(handle, &dprinc);
16217c478bd9Sstevel@tonic-gate     free(canon);
16227c478bd9Sstevel@tonic-gate }
16237c478bd9Sstevel@tonic-gate 
kadmin_getprincs(argc,argv)162456a424ccSmp void kadmin_getprincs(argc, argv)
16257c478bd9Sstevel@tonic-gate     int argc;
16267c478bd9Sstevel@tonic-gate     char *argv[];
16277c478bd9Sstevel@tonic-gate {
16287c478bd9Sstevel@tonic-gate     krb5_error_code retval;
162956a424ccSmp     char *expr, **names;
16307c478bd9Sstevel@tonic-gate     int i, count;
16317c478bd9Sstevel@tonic-gate 
16327c478bd9Sstevel@tonic-gate 	FILE *output;
16337c478bd9Sstevel@tonic-gate 	int fd;
16347c478bd9Sstevel@tonic-gate 	struct sigaction nsig, osig;
16357c478bd9Sstevel@tonic-gate 	sigset_t nmask, omask;
16367c478bd9Sstevel@tonic-gate 	int waitb;
16377c478bd9Sstevel@tonic-gate 
163856a424ccSmp     expr = NULL;
163956a424ccSmp     if (! (argc == 1 || (argc == 2 && (expr = argv[1])))) {
16407c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: get_principals %s\n",
16417c478bd9Sstevel@tonic-gate 			gettext("usage"), gettext("[expression]"));
16427c478bd9Sstevel@tonic-gate 	return;
16437c478bd9Sstevel@tonic-gate     }
164456a424ccSmp     retval = kadm5_get_principals(handle, expr, &names, &count);
16457c478bd9Sstevel@tonic-gate     if (retval) {
164656a424ccSmp 	com_err("get_principals", retval,
16477c478bd9Sstevel@tonic-gate 			gettext("while retrieving list."));
16487c478bd9Sstevel@tonic-gate 	return;
16497c478bd9Sstevel@tonic-gate     }
16507c478bd9Sstevel@tonic-gate 
16517c478bd9Sstevel@tonic-gate 	/*
16527c478bd9Sstevel@tonic-gate 	 * Solaris:  the following code is used for paging
16537c478bd9Sstevel@tonic-gate 	 */
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 	sigemptyset(&nmask);
16567c478bd9Sstevel@tonic-gate 	sigaddset(&nmask, SIGINT);
16577c478bd9Sstevel@tonic-gate 	sigprocmask(SIG_BLOCK, &nmask, &omask);
16587c478bd9Sstevel@tonic-gate 
16597c478bd9Sstevel@tonic-gate 	nsig.sa_handler = SIG_IGN;
16607c478bd9Sstevel@tonic-gate 	sigemptyset(&nsig.sa_mask);
16617c478bd9Sstevel@tonic-gate 	nsig.sa_flags = 0;
16627c478bd9Sstevel@tonic-gate 	sigaction(SIGINT, &nsig, &osig);
16637c478bd9Sstevel@tonic-gate 
16647c478bd9Sstevel@tonic-gate 	fd = ss_pager_create();
16657c478bd9Sstevel@tonic-gate 	output = fdopen(fd, "w");
16667c478bd9Sstevel@tonic-gate 
16677c478bd9Sstevel@tonic-gate 	sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
16687c478bd9Sstevel@tonic-gate 
16697c478bd9Sstevel@tonic-gate     for (i = 0; i < count; i++)
167056a424ccSmp 	 fprintf(output, "%s\n", names[i]);
16717c478bd9Sstevel@tonic-gate 
16727c478bd9Sstevel@tonic-gate 	fclose(output);
16737c478bd9Sstevel@tonic-gate 
16747c478bd9Sstevel@tonic-gate 	wait(&waitb);
16757c478bd9Sstevel@tonic-gate 
1676d51f1d33Smp 	/* Solaris Kerberos:
1677d51f1d33Smp 	 * Restore the original handler for SIGINT
1678d51f1d33Smp 	 */
1679d51f1d33Smp 	if (sigaction(SIGINT, &osig, (struct sigaction *)0) == -1) {
1680d51f1d33Smp 		perror("sigaction");
1681d51f1d33Smp 	}
1682d51f1d33Smp 
16837c478bd9Sstevel@tonic-gate     kadm5_free_name_list(handle, names, count);
16847c478bd9Sstevel@tonic-gate }
16857c478bd9Sstevel@tonic-gate 
168654925bf6Swillf static int
kadmin_parse_policy_args(argc,argv,policy,mask,caller)16877c478bd9Sstevel@tonic-gate kadmin_parse_policy_args(argc, argv, policy, mask, caller)
16887c478bd9Sstevel@tonic-gate     int argc;
16897c478bd9Sstevel@tonic-gate     char *argv[];
16907c478bd9Sstevel@tonic-gate     kadm5_policy_ent_t policy;
16917c478bd9Sstevel@tonic-gate     long *mask;
16927c478bd9Sstevel@tonic-gate     char *caller;
16937c478bd9Sstevel@tonic-gate {
16947c478bd9Sstevel@tonic-gate     int i;
16957c478bd9Sstevel@tonic-gate     time_t now;
16967c478bd9Sstevel@tonic-gate     time_t date;
16977c478bd9Sstevel@tonic-gate 
16987c478bd9Sstevel@tonic-gate     time(&now);
16997c478bd9Sstevel@tonic-gate     *mask = 0;
17007c478bd9Sstevel@tonic-gate     for (i = 1; i < argc - 1; i++) {
17017c478bd9Sstevel@tonic-gate 	if (strlen(argv[i]) == 8 &&
170256a424ccSmp 	    !strcmp(argv[i], "-maxlife")) {
17037c478bd9Sstevel@tonic-gate 	    if (++i > argc -2)
170456a424ccSmp 		return -1;
17057c478bd9Sstevel@tonic-gate 	    else {
170656a424ccSmp 		date = get_date(argv[i]);
170754925bf6Swillf 		if (date == (time_t)-1) {
170854925bf6Swillf 		    fprintf(stderr, gettext("Invalid date specification \"%s\".\n"),
170954925bf6Swillf 			    argv[i]);
171054925bf6Swillf 		    return -1;
171154925bf6Swillf 		}
17127c478bd9Sstevel@tonic-gate 		policy->pw_max_life = date - now;
17137c478bd9Sstevel@tonic-gate 		*mask |= KADM5_PW_MAX_LIFE;
17147c478bd9Sstevel@tonic-gate 		continue;
17157c478bd9Sstevel@tonic-gate 	    }
17167c478bd9Sstevel@tonic-gate 	} else if (strlen(argv[i]) == 8 &&
171756a424ccSmp 		   !strcmp(argv[i], "-minlife")) {
17187c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
171956a424ccSmp 		return -1;
17207c478bd9Sstevel@tonic-gate 	    else {
172156a424ccSmp 		date = get_date(argv[i]);
172254925bf6Swillf 		if (date == (time_t)-1) {
172354925bf6Swillf 		    fprintf(stderr, gettext("Invalid date specification \"%s\".\n"),
172454925bf6Swillf 			    argv[i]);
172554925bf6Swillf 		    return -1;
172654925bf6Swillf 		}
17277c478bd9Sstevel@tonic-gate 		policy->pw_min_life = date - now;
17287c478bd9Sstevel@tonic-gate 		*mask |= KADM5_PW_MIN_LIFE;
17297c478bd9Sstevel@tonic-gate 		continue;
17307c478bd9Sstevel@tonic-gate 	    }
17317c478bd9Sstevel@tonic-gate 	} else if (strlen(argv[i]) == 10 &&
173254925bf6Swillf 		   !strcmp(argv[i], "-minlength")) {
17337c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
173456a424ccSmp 		return -1;
17357c478bd9Sstevel@tonic-gate 	    else {
17367c478bd9Sstevel@tonic-gate 		policy->pw_min_length = atoi(argv[i]);
17377c478bd9Sstevel@tonic-gate 		*mask |= KADM5_PW_MIN_LENGTH;
17387c478bd9Sstevel@tonic-gate 		continue;
17397c478bd9Sstevel@tonic-gate 	    }
17407c478bd9Sstevel@tonic-gate 	} else if (strlen(argv[i]) == 11 &&
174156a424ccSmp 		   !strcmp(argv[i], "-minclasses")) {
17427c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
174356a424ccSmp 		return -1;
17447c478bd9Sstevel@tonic-gate 	    else {
17457c478bd9Sstevel@tonic-gate 		policy->pw_min_classes = atoi(argv[i]);
17467c478bd9Sstevel@tonic-gate 		*mask |= KADM5_PW_MIN_CLASSES;
17477c478bd9Sstevel@tonic-gate 		continue;
17487c478bd9Sstevel@tonic-gate 	    }
17497c478bd9Sstevel@tonic-gate 	} else if (strlen(argv[i]) == 8 &&
175056a424ccSmp 		   !strcmp(argv[i], "-history")) {
17517c478bd9Sstevel@tonic-gate 	    if (++i > argc - 2)
175256a424ccSmp 		return -1;
17537c478bd9Sstevel@tonic-gate 	    else {
17547c478bd9Sstevel@tonic-gate 		policy->pw_history_num = atoi(argv[i]);
17557c478bd9Sstevel@tonic-gate 		*mask |= KADM5_PW_HISTORY_NUM;
17567c478bd9Sstevel@tonic-gate 		continue;
17577c478bd9Sstevel@tonic-gate 	    }
17587c478bd9Sstevel@tonic-gate 	} else
175956a424ccSmp 	    return -1;
17607c478bd9Sstevel@tonic-gate     }
17617c478bd9Sstevel@tonic-gate     if (i != argc -1) {
176256a424ccSmp 	fprintf(stderr, gettext("%s: parser lost count!\n"), caller);
176356a424ccSmp 	return -1;
17647c478bd9Sstevel@tonic-gate     } else
176556a424ccSmp 	return 0;
17667c478bd9Sstevel@tonic-gate }
17677c478bd9Sstevel@tonic-gate 
176854925bf6Swillf static void
kadmin_addmodpol_usage(func)17697c478bd9Sstevel@tonic-gate kadmin_addmodpol_usage(func)
177054925bf6Swillf     char *func;
17717c478bd9Sstevel@tonic-gate {
17727c478bd9Sstevel@tonic-gate 	fprintf(stderr, "%s: %s %s\n", gettext("usage"), func,
17737c478bd9Sstevel@tonic-gate 		gettext("[options] policy"));
17747c478bd9Sstevel@tonic-gate 	fprintf(stderr, gettext("\toptions are:\n"));
17757c478bd9Sstevel@tonic-gate 	fprintf(stderr, "\t\t[-maxlife time] [-minlife time] "
17767c478bd9Sstevel@tonic-gate 		"[-minlength length]\n\t\t[-minclasses number] "
17777c478bd9Sstevel@tonic-gate 		"[-history number]\n");
17787c478bd9Sstevel@tonic-gate }
17797c478bd9Sstevel@tonic-gate 
kadmin_addpol(argc,argv)178056a424ccSmp void kadmin_addpol(argc, argv)
17817c478bd9Sstevel@tonic-gate     int argc;
17827c478bd9Sstevel@tonic-gate     char *argv[];
17837c478bd9Sstevel@tonic-gate {
17847c478bd9Sstevel@tonic-gate     krb5_error_code retval;
17857c478bd9Sstevel@tonic-gate     long mask;
17867c478bd9Sstevel@tonic-gate     kadm5_policy_ent_rec policy;
17877c478bd9Sstevel@tonic-gate 
17887c478bd9Sstevel@tonic-gate     memset(&policy, 0, sizeof(policy));
178956a424ccSmp     if (kadmin_parse_policy_args(argc, argv, &policy, &mask, "add_policy")) {
179054925bf6Swillf 	kadmin_addmodpol_usage("add_policy");
179154925bf6Swillf 	return;
17927c478bd9Sstevel@tonic-gate     } else {
17937c478bd9Sstevel@tonic-gate 	policy.policy = argv[argc - 1];
17947c478bd9Sstevel@tonic-gate 	mask |= KADM5_POLICY;
17957c478bd9Sstevel@tonic-gate 	retval = kadm5_create_policy(handle, &policy, mask);
17967c478bd9Sstevel@tonic-gate 	if (retval) {
17977c478bd9Sstevel@tonic-gate 			com_err("add_policy", retval,
17987c478bd9Sstevel@tonic-gate 				gettext("while creating policy \"%s\"."),
17997c478bd9Sstevel@tonic-gate 		    policy.policy);
18007c478bd9Sstevel@tonic-gate 	    return;
18017c478bd9Sstevel@tonic-gate 	}
18027c478bd9Sstevel@tonic-gate     }
180356a424ccSmp     return;
18047c478bd9Sstevel@tonic-gate }
18057c478bd9Sstevel@tonic-gate 
kadmin_modpol(argc,argv)180656a424ccSmp void kadmin_modpol(argc, argv)
18077c478bd9Sstevel@tonic-gate     int argc;
18087c478bd9Sstevel@tonic-gate     char *argv[];
18097c478bd9Sstevel@tonic-gate {
18107c478bd9Sstevel@tonic-gate     krb5_error_code retval;
18117c478bd9Sstevel@tonic-gate     long mask;
18127c478bd9Sstevel@tonic-gate     kadm5_policy_ent_rec policy;
18137c478bd9Sstevel@tonic-gate 
18147c478bd9Sstevel@tonic-gate     memset(&policy, 0, sizeof(policy));
18157c478bd9Sstevel@tonic-gate     if (kadmin_parse_policy_args(argc, argv, &policy, &mask,
18167c478bd9Sstevel@tonic-gate 				 "modify_policy")) {
18177c478bd9Sstevel@tonic-gate 	kadmin_addmodpol_usage("modify_policy");
18187c478bd9Sstevel@tonic-gate 	return;
18197c478bd9Sstevel@tonic-gate     } else {
18207c478bd9Sstevel@tonic-gate 	policy.policy = argv[argc - 1];
18217c478bd9Sstevel@tonic-gate 	retval = kadm5_modify_policy(handle, &policy, mask);
18227c478bd9Sstevel@tonic-gate 	if (retval) {
182354925bf6Swillf 	    com_err("modify_policy", retval, gettext("while modifying policy \"%s\"."),
18247c478bd9Sstevel@tonic-gate 		    policy.policy);
18257c478bd9Sstevel@tonic-gate 	    return;
18267c478bd9Sstevel@tonic-gate 	}
18277c478bd9Sstevel@tonic-gate     }
182856a424ccSmp     return;
18297c478bd9Sstevel@tonic-gate }
18307c478bd9Sstevel@tonic-gate 
kadmin_delpol(argc,argv)183156a424ccSmp void kadmin_delpol(argc, argv)
18327c478bd9Sstevel@tonic-gate     int argc;
18337c478bd9Sstevel@tonic-gate     char *argv[];
18347c478bd9Sstevel@tonic-gate {
18357c478bd9Sstevel@tonic-gate     krb5_error_code retval;
183656a424ccSmp     char reply[32];
183754925bf6Swillf 
18387c478bd9Sstevel@tonic-gate     if (! (argc == 2 ||
183956a424ccSmp 	   (argc == 3 && !strcmp("-force", argv[1])))) {
184056a424ccSmp 	fprintf(stderr, "%s: delete_policy [-force] %s\n",
18417c478bd9Sstevel@tonic-gate 			gettext("usage"), gettext("policy"));
18427c478bd9Sstevel@tonic-gate 	return;
18437c478bd9Sstevel@tonic-gate     }
18447c478bd9Sstevel@tonic-gate     if (argc == 2) {
18457c478bd9Sstevel@tonic-gate 		printf(gettext("Are you sure you want to delete the policy "
18467c478bd9Sstevel@tonic-gate 			    "\"%s\"? (yes/no): "), argv[1]);
18477c478bd9Sstevel@tonic-gate 	fgets(reply, sizeof (reply), stdin);
18487c478bd9Sstevel@tonic-gate 		if (strncmp(gettext("yes\n"), reply, sizeof (reply)) &&
18497c478bd9Sstevel@tonic-gate 			strncmp(gettext("y\n"), reply, sizeof (reply)) &&
18507c478bd9Sstevel@tonic-gate 			strncmp(gettext("Y\n"), reply, sizeof (reply))
18517c478bd9Sstevel@tonic-gate 			) {
18527c478bd9Sstevel@tonic-gate 			fprintf(stderr,
18537c478bd9Sstevel@tonic-gate 				gettext("Policy \"%s\" not deleted.\n"),
18547c478bd9Sstevel@tonic-gate 				argv[1]);
18557c478bd9Sstevel@tonic-gate 	    return;
18567c478bd9Sstevel@tonic-gate 	}
18577c478bd9Sstevel@tonic-gate     }
18587c478bd9Sstevel@tonic-gate     retval = kadm5_delete_policy(handle, argv[argc - 1]);
18597c478bd9Sstevel@tonic-gate     if (retval) {
18607c478bd9Sstevel@tonic-gate 		com_err("delete_policy:", retval,
18617c478bd9Sstevel@tonic-gate 			gettext("while deleting policy \"%s\""),
18627c478bd9Sstevel@tonic-gate 		argv[argc - 1]);
18637c478bd9Sstevel@tonic-gate 	return;
18647c478bd9Sstevel@tonic-gate     }
186556a424ccSmp     return;
18667c478bd9Sstevel@tonic-gate }
18677c478bd9Sstevel@tonic-gate 
kadmin_getpol(argc,argv)186856a424ccSmp void kadmin_getpol(argc, argv)
18697c478bd9Sstevel@tonic-gate     int argc;
18707c478bd9Sstevel@tonic-gate     char *argv[];
18717c478bd9Sstevel@tonic-gate {
18727c478bd9Sstevel@tonic-gate     krb5_error_code retval;
18737c478bd9Sstevel@tonic-gate     kadm5_policy_ent_rec policy;
187454925bf6Swillf 
18757c478bd9Sstevel@tonic-gate     if (! (argc == 2 ||
187656a424ccSmp 	   (argc == 3 && !strcmp("-terse", argv[1])))) {
18777c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: get_policy [-terse] %s\n",
18787c478bd9Sstevel@tonic-gate 			gettext("usage"), gettext("policy"));
18797c478bd9Sstevel@tonic-gate 	return;
18807c478bd9Sstevel@tonic-gate     }
18817c478bd9Sstevel@tonic-gate     retval = kadm5_get_policy(handle, argv[argc - 1], &policy);
18827c478bd9Sstevel@tonic-gate     if (retval) {
18837c478bd9Sstevel@tonic-gate 		com_err("get_policy", retval,
18847c478bd9Sstevel@tonic-gate 			gettext("while retrieving policy \"%s\"."),
18857c478bd9Sstevel@tonic-gate 		argv[argc - 1]);
18867c478bd9Sstevel@tonic-gate 	return;
18877c478bd9Sstevel@tonic-gate     }
18887c478bd9Sstevel@tonic-gate     if (argc == 2) {
18897c478bd9Sstevel@tonic-gate 		printf(gettext("Policy: %s\n"), policy.policy);
189056a424ccSmp 		printf(gettext("Maximum password life: %ld\n"),
18917c478bd9Sstevel@tonic-gate 		    policy.pw_max_life);
189256a424ccSmp 		printf(gettext("Minimum password life: %ld\n"),
18937c478bd9Sstevel@tonic-gate 		    policy.pw_min_life);
189456a424ccSmp 		printf(gettext("Minimum password length: %ld\n"),
18957c478bd9Sstevel@tonic-gate 		    policy.pw_min_length);
18967c478bd9Sstevel@tonic-gate 		printf(gettext("Minimum number of password "
189756a424ccSmp 			    "character classes: %ld\n"),
18987c478bd9Sstevel@tonic-gate 	       policy.pw_min_classes);
189956a424ccSmp 		printf(gettext("Number of old keys kept: %ld\n"),
19007c478bd9Sstevel@tonic-gate 		    policy.pw_history_num);
190156a424ccSmp 		printf(gettext("Reference count: %ld\n"), policy.policy_refcnt);
19027c478bd9Sstevel@tonic-gate     } else {
190356a424ccSmp 	printf("\"%s\"\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\n",
19047c478bd9Sstevel@tonic-gate 	       policy.policy, policy.pw_max_life, policy.pw_min_life,
19057c478bd9Sstevel@tonic-gate 	       policy.pw_min_length, policy.pw_min_classes,
19067c478bd9Sstevel@tonic-gate 	       policy.pw_history_num, policy.policy_refcnt);
19077c478bd9Sstevel@tonic-gate     }
19087c478bd9Sstevel@tonic-gate     kadm5_free_policy_ent(handle, &policy);
190956a424ccSmp     return;
19107c478bd9Sstevel@tonic-gate }
19117c478bd9Sstevel@tonic-gate 
kadmin_getpols(argc,argv)191256a424ccSmp void kadmin_getpols(argc, argv)
19137c478bd9Sstevel@tonic-gate     int argc;
19147c478bd9Sstevel@tonic-gate     char *argv[];
19157c478bd9Sstevel@tonic-gate {
19167c478bd9Sstevel@tonic-gate     krb5_error_code retval;
191756a424ccSmp     char *expr, **names;
19187c478bd9Sstevel@tonic-gate     int i, count;
19197c478bd9Sstevel@tonic-gate 
1920d51f1d33Smp     /* Solaris Kerberos:
1921d51f1d33Smp      * Use a pager for listing policies (similar to listing princs)
1922d51f1d33Smp      */
1923d51f1d33Smp     FILE *output = NULL;
1924d51f1d33Smp     int fd;
1925d51f1d33Smp     struct sigaction nsig, osig;
1926d51f1d33Smp     sigset_t nmask, omask;
1927d51f1d33Smp     int waitb;
1928d51f1d33Smp 
192956a424ccSmp     expr = NULL;
193056a424ccSmp     if (! (argc == 1 || (argc == 2 && (expr = argv[1])))) {
193156a424ccSmp 	fprintf(stderr, "%s: get_policies %s\n",
19327c478bd9Sstevel@tonic-gate 			gettext("usage"), gettext("[expression]\n"));
19337c478bd9Sstevel@tonic-gate 	return;
19347c478bd9Sstevel@tonic-gate     }
193556a424ccSmp     retval = kadm5_get_policies(handle, expr, &names, &count);
19367c478bd9Sstevel@tonic-gate     if (retval) {
193756a424ccSmp 	com_err("get_policies", retval,
19387c478bd9Sstevel@tonic-gate 			gettext("while retrieving list."));
19397c478bd9Sstevel@tonic-gate 	return;
19407c478bd9Sstevel@tonic-gate     }
1941d51f1d33Smp 
1942d51f1d33Smp     if (sigemptyset(&nmask) == -1) {
1943d51f1d33Smp         perror("sigemptyset");
1944d51f1d33Smp         kadm5_free_name_list(handle, names, count);
1945d51f1d33Smp         return;
1946d51f1d33Smp     }
1947d51f1d33Smp 
1948d51f1d33Smp     if (sigaddset(&nmask, SIGINT) == -1) {
1949d51f1d33Smp         perror("sigaddset");
1950d51f1d33Smp         kadm5_free_name_list(handle, names, count);
1951d51f1d33Smp         return;
1952d51f1d33Smp     }
1953d51f1d33Smp 
1954d51f1d33Smp     if (sigemptyset(&nsig.sa_mask) == -1) {
1955d51f1d33Smp         perror("sigemptyset");
1956d51f1d33Smp         kadm5_free_name_list(handle, names, count);
1957d51f1d33Smp         return;
1958d51f1d33Smp     }
1959d51f1d33Smp 
1960d51f1d33Smp     if (sigprocmask(SIG_BLOCK, &nmask, &omask) == -1) {
1961d51f1d33Smp         perror("sigprocmask");
1962d51f1d33Smp         kadm5_free_name_list(handle, names, count);
1963d51f1d33Smp         return;
1964d51f1d33Smp     }
1965d51f1d33Smp 
1966d51f1d33Smp     nsig.sa_handler = SIG_IGN;
1967d51f1d33Smp     nsig.sa_flags = 0;
1968d51f1d33Smp     if (sigaction(SIGINT, &nsig, &osig) == -1) {
1969d51f1d33Smp         perror("sigaction");
1970d51f1d33Smp         if (sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0) == -1) {
1971d51f1d33Smp             perror("sigprocmask");
1972d51f1d33Smp         }
1973d51f1d33Smp         kadm5_free_name_list(handle, names, count);
1974d51f1d33Smp         return;
1975d51f1d33Smp     }
1976d51f1d33Smp 
1977d51f1d33Smp     fd = ss_pager_create();
1978d51f1d33Smp     if (fd == -1) {
1979d51f1d33Smp         fprintf(stderr, "%s: failed to create pager\n", whoami);
1980d51f1d33Smp         if (sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0) == -1) {
1981d51f1d33Smp             perror("sigprocmask");
1982d51f1d33Smp         }
1983d51f1d33Smp 
1984d51f1d33Smp         if (sigaction(SIGINT, &osig, (struct sigaction *)0) == -1) {
1985d51f1d33Smp             perror("sigaction");
1986d51f1d33Smp         }
1987d51f1d33Smp 
1988d51f1d33Smp         kadm5_free_name_list(handle, names, count);
1989d51f1d33Smp         return;
1990d51f1d33Smp     }
1991d51f1d33Smp 
1992d51f1d33Smp     output = fdopen(fd, "w");
1993d51f1d33Smp     if (output == NULL) {
1994d51f1d33Smp         perror("fdopen");
1995d51f1d33Smp     }
1996d51f1d33Smp 
1997d51f1d33Smp     if (sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0) == -1) {
1998d51f1d33Smp         perror("sigprocmask");
1999d51f1d33Smp     }
2000d51f1d33Smp 
2001d51f1d33Smp     if (output != NULL) {
2002d51f1d33Smp         for (i = 0; i < count; i++)
2003d51f1d33Smp         fprintf(output, "%s\n", names[i]);
2004d51f1d33Smp     }
2005d51f1d33Smp 
2006d51f1d33Smp     if (output != NULL && fclose(output) != 0) {
2007d51f1d33Smp         perror("fclose");
2008d51f1d33Smp     }
2009d51f1d33Smp 
2010d51f1d33Smp     if (wait(&waitb) == -1) {
2011d51f1d33Smp         perror("wait");
2012d51f1d33Smp     }
2013d51f1d33Smp 
2014d51f1d33Smp     if (sigaction(SIGINT, &osig, (struct sigaction *)0) == -1) {
2015d51f1d33Smp         perror("sigaction");
2016d51f1d33Smp     }
20177c478bd9Sstevel@tonic-gate     kadm5_free_name_list(handle, names, count);
20187c478bd9Sstevel@tonic-gate }
2019