xref: /freebsd/crypto/krb5/src/kadmin/cli/kadmin.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert  * Copyright 1994, 2008 by the Massachusetts Institute of Technology.
4*7f2fe78bSCy Schubert  * All Rights Reserved.
5*7f2fe78bSCy Schubert  *
6*7f2fe78bSCy Schubert  * Export of this software from the United States of America may
7*7f2fe78bSCy Schubert  *   require a specific license from the United States Government.
8*7f2fe78bSCy Schubert  *   It is the responsibility of any person or organization contemplating
9*7f2fe78bSCy Schubert  *   export to obtain such a license before exporting.
10*7f2fe78bSCy Schubert  *
11*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
13*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
14*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
15*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
16*7f2fe78bSCy Schubert  * the name of M.I.T. not be used in advertising or publicity pertaining
17*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
18*7f2fe78bSCy Schubert  * permission.  Furthermore if you modify this software you must label
19*7f2fe78bSCy Schubert  * your software as modified software and not distribute it in such a
20*7f2fe78bSCy Schubert  * fashion that it might be confused with the original M.I.T. software.
21*7f2fe78bSCy Schubert  * M.I.T. makes no representations about the suitability of
22*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
23*7f2fe78bSCy Schubert  * or implied warranty.
24*7f2fe78bSCy Schubert  */
25*7f2fe78bSCy Schubert /*
26*7f2fe78bSCy Schubert  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
27*7f2fe78bSCy Schubert  * Use is subject to license terms.
28*7f2fe78bSCy Schubert  */
29*7f2fe78bSCy Schubert 
30*7f2fe78bSCy Schubert /* Base functions for a kadmin command line interface using the OVSecure
31*7f2fe78bSCy Schubert  * library */
32*7f2fe78bSCy Schubert 
33*7f2fe78bSCy Schubert /* for "_" macro */
34*7f2fe78bSCy Schubert #include "k5-int.h"
35*7f2fe78bSCy Schubert #include <kadm5/admin.h>
36*7f2fe78bSCy Schubert #include <adm_proto.h>
37*7f2fe78bSCy Schubert #include <errno.h>
38*7f2fe78bSCy Schubert #include <stdio.h>
39*7f2fe78bSCy Schubert #include <string.h>
40*7f2fe78bSCy Schubert #include <ctype.h>
41*7f2fe78bSCy Schubert #include <sys/types.h>
42*7f2fe78bSCy Schubert #include <math.h>
43*7f2fe78bSCy Schubert #include <unistd.h>
44*7f2fe78bSCy Schubert #include <pwd.h>
45*7f2fe78bSCy Schubert /* #include <sys/timeb.h> */
46*7f2fe78bSCy Schubert #include <time.h>
47*7f2fe78bSCy Schubert #include "kadmin.h"
48*7f2fe78bSCy Schubert 
49*7f2fe78bSCy Schubert static krb5_boolean script_mode = FALSE;
50*7f2fe78bSCy Schubert int exit_status = 0;
51*7f2fe78bSCy Schubert char *def_realm = NULL;
52*7f2fe78bSCy Schubert char *whoami = NULL;
53*7f2fe78bSCy Schubert 
54*7f2fe78bSCy Schubert void *handle = NULL;
55*7f2fe78bSCy Schubert krb5_context context;
56*7f2fe78bSCy Schubert char *ccache_name = NULL;
57*7f2fe78bSCy Schubert 
58*7f2fe78bSCy Schubert int locked = 0;
59*7f2fe78bSCy Schubert 
60*7f2fe78bSCy Schubert static void
61*7f2fe78bSCy Schubert info(const char *fmt, ...)
62*7f2fe78bSCy Schubert #if !defined(__cplusplus) && (__GNUC__ > 2)
63*7f2fe78bSCy Schubert     __attribute__((__format__(__printf__, 1, 2)))
64*7f2fe78bSCy Schubert #endif
65*7f2fe78bSCy Schubert     ;
66*7f2fe78bSCy Schubert 
67*7f2fe78bSCy Schubert static void
68*7f2fe78bSCy Schubert error(const char *fmt, ...)
69*7f2fe78bSCy Schubert #if !defined(__cplusplus) && (__GNUC__ > 2)
70*7f2fe78bSCy Schubert     __attribute__((__format__(__printf__, 1, 2)))
71*7f2fe78bSCy Schubert #endif
72*7f2fe78bSCy Schubert     ;
73*7f2fe78bSCy Schubert 
74*7f2fe78bSCy Schubert /* Like printf, but suppressed if script_mode is set. */
75*7f2fe78bSCy Schubert static void
info(const char * fmt,...)76*7f2fe78bSCy Schubert info(const char *fmt, ...)
77*7f2fe78bSCy Schubert {
78*7f2fe78bSCy Schubert     va_list ap;
79*7f2fe78bSCy Schubert 
80*7f2fe78bSCy Schubert     if (script_mode)
81*7f2fe78bSCy Schubert         return;
82*7f2fe78bSCy Schubert     va_start(ap, fmt);
83*7f2fe78bSCy Schubert     vprintf(fmt, ap);
84*7f2fe78bSCy Schubert     va_end(ap);
85*7f2fe78bSCy Schubert }
86*7f2fe78bSCy Schubert 
87*7f2fe78bSCy Schubert /* Like fprintf to stderr; also set exit_status if script_mode is set. */
88*7f2fe78bSCy Schubert static void
error(const char * fmt,...)89*7f2fe78bSCy Schubert error(const char *fmt, ...)
90*7f2fe78bSCy Schubert {
91*7f2fe78bSCy Schubert     va_list ap;
92*7f2fe78bSCy Schubert 
93*7f2fe78bSCy Schubert     if (script_mode)
94*7f2fe78bSCy Schubert         exit_status = 1;
95*7f2fe78bSCy Schubert     va_start(ap, fmt);
96*7f2fe78bSCy Schubert     vfprintf(stderr, fmt, ap);
97*7f2fe78bSCy Schubert     va_end(ap);
98*7f2fe78bSCy Schubert }
99*7f2fe78bSCy Schubert 
100*7f2fe78bSCy Schubert static void
usage()101*7f2fe78bSCy Schubert usage()
102*7f2fe78bSCy Schubert {
103*7f2fe78bSCy Schubert     error(_("Usage: %s [-r realm] [-p principal] [-q query] "
104*7f2fe78bSCy Schubert             "[clnt|local args]\n"
105*7f2fe78bSCy Schubert             "              [command args...]\n"
106*7f2fe78bSCy Schubert             "\tclnt args: [-s admin_server[:port]] "
107*7f2fe78bSCy Schubert             "[[-c ccache]|[-k [-t keytab]]]|[-n] [-O | -N]\n"
108*7f2fe78bSCy Schubert             "\tlocal args: [-x db_args]* [-d dbname] "
109*7f2fe78bSCy Schubert             "[-e \"enc:salt ...\"] [-m] [-w password] "
110*7f2fe78bSCy Schubert             "where,\n\t[-x db_args]* - any number of database specific "
111*7f2fe78bSCy Schubert             "arguments.\n"
112*7f2fe78bSCy Schubert             "\t\t\tLook at each database documentation for supported "
113*7f2fe78bSCy Schubert             "arguments\n"), whoami);
114*7f2fe78bSCy Schubert     exit(1);
115*7f2fe78bSCy Schubert }
116*7f2fe78bSCy Schubert 
117*7f2fe78bSCy Schubert static char *
strdur(time_t duration)118*7f2fe78bSCy Schubert strdur(time_t duration)
119*7f2fe78bSCy Schubert {
120*7f2fe78bSCy Schubert     static char out[50];
121*7f2fe78bSCy Schubert     int neg, days, hours, minutes, seconds;
122*7f2fe78bSCy Schubert 
123*7f2fe78bSCy Schubert     if (duration < 0) {
124*7f2fe78bSCy Schubert         duration *= -1;
125*7f2fe78bSCy Schubert         neg = 1;
126*7f2fe78bSCy Schubert     } else
127*7f2fe78bSCy Schubert         neg = 0;
128*7f2fe78bSCy Schubert     days = duration / (24 * 3600);
129*7f2fe78bSCy Schubert     duration %= 24 * 3600;
130*7f2fe78bSCy Schubert     hours = duration / 3600;
131*7f2fe78bSCy Schubert     duration %= 3600;
132*7f2fe78bSCy Schubert     minutes = duration / 60;
133*7f2fe78bSCy Schubert     duration %= 60;
134*7f2fe78bSCy Schubert     seconds = duration;
135*7f2fe78bSCy Schubert     snprintf(out, sizeof(out), "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
136*7f2fe78bSCy Schubert              days, days == 1 ? "day" : "days",
137*7f2fe78bSCy Schubert              hours, minutes, seconds);
138*7f2fe78bSCy Schubert     return out;
139*7f2fe78bSCy Schubert }
140*7f2fe78bSCy Schubert 
141*7f2fe78bSCy Schubert static const char *
strdate(krb5_timestamp when)142*7f2fe78bSCy Schubert strdate(krb5_timestamp when)
143*7f2fe78bSCy Schubert {
144*7f2fe78bSCy Schubert     struct tm *tm;
145*7f2fe78bSCy Schubert     static char out[40];
146*7f2fe78bSCy Schubert     time_t lcltim = ts2tt(when);
147*7f2fe78bSCy Schubert 
148*7f2fe78bSCy Schubert     tm = localtime(&lcltim);
149*7f2fe78bSCy Schubert     if (tm == NULL ||
150*7f2fe78bSCy Schubert         strftime(out, sizeof(out), "%a %b %d %H:%M:%S %Z %Y", tm) == 0)
151*7f2fe78bSCy Schubert         strlcpy(out, "(error)", sizeof(out));
152*7f2fe78bSCy Schubert     return out;
153*7f2fe78bSCy Schubert }
154*7f2fe78bSCy Schubert 
155*7f2fe78bSCy Schubert /* Parse a date string using getdate.y.  On failure, output an error message
156*7f2fe78bSCy Schubert  * and return (time_t)-1. */
157*7f2fe78bSCy Schubert static time_t
parse_date(char * str,time_t now)158*7f2fe78bSCy Schubert parse_date(char *str, time_t now)
159*7f2fe78bSCy Schubert {
160*7f2fe78bSCy Schubert     time_t date;
161*7f2fe78bSCy Schubert 
162*7f2fe78bSCy Schubert     date = get_date_rel(str, now);
163*7f2fe78bSCy Schubert     if (date == (time_t)-1)
164*7f2fe78bSCy Schubert         error(_("Invalid date specification \"%s\".\n"), str);
165*7f2fe78bSCy Schubert     return date;
166*7f2fe78bSCy Schubert }
167*7f2fe78bSCy Schubert 
168*7f2fe78bSCy Schubert /*
169*7f2fe78bSCy Schubert  * Parse a time interval.  Use krb5_string_to_deltat() if it works; otherwise
170*7f2fe78bSCy Schubert  * use getdate.y and subtract now, with sanity checks.  On failure, output an
171*7f2fe78bSCy Schubert  * error message and return (time_t)-1.
172*7f2fe78bSCy Schubert  */
173*7f2fe78bSCy Schubert static time_t
parse_interval(char * str,time_t now)174*7f2fe78bSCy Schubert parse_interval(char *str, time_t now)
175*7f2fe78bSCy Schubert {
176*7f2fe78bSCy Schubert     time_t date;
177*7f2fe78bSCy Schubert     krb5_deltat delta;
178*7f2fe78bSCy Schubert 
179*7f2fe78bSCy Schubert     if (krb5_string_to_deltat(str, &delta) == 0)
180*7f2fe78bSCy Schubert         return delta;
181*7f2fe78bSCy Schubert 
182*7f2fe78bSCy Schubert     date = parse_date(str, now);
183*7f2fe78bSCy Schubert     if (date == (time_t)-1)
184*7f2fe78bSCy Schubert         return date;
185*7f2fe78bSCy Schubert 
186*7f2fe78bSCy Schubert     /* Interpret an absolute time of 0 (e.g. "never") as an interval of 0. */
187*7f2fe78bSCy Schubert     if (date == 0)
188*7f2fe78bSCy Schubert         return 0;
189*7f2fe78bSCy Schubert 
190*7f2fe78bSCy Schubert     /* Don't return a negative interval if the date is in the past. */
191*7f2fe78bSCy Schubert     if (date < now) {
192*7f2fe78bSCy Schubert         error(_("Interval specification \"%s\" is in the past.\n"), str);
193*7f2fe78bSCy Schubert         return (time_t)-1;
194*7f2fe78bSCy Schubert     }
195*7f2fe78bSCy Schubert 
196*7f2fe78bSCy Schubert     return date - now;
197*7f2fe78bSCy Schubert }
198*7f2fe78bSCy Schubert 
199*7f2fe78bSCy Schubert /* this is a wrapper to go around krb5_parse_principal so we can set
200*7f2fe78bSCy Schubert    the default realm up properly */
201*7f2fe78bSCy Schubert static krb5_error_code
kadmin_parse_name(char * name,krb5_principal * principal)202*7f2fe78bSCy Schubert kadmin_parse_name(char *name, krb5_principal *principal)
203*7f2fe78bSCy Schubert {
204*7f2fe78bSCy Schubert     char *cp, *fullname;
205*7f2fe78bSCy Schubert     krb5_error_code retval;
206*7f2fe78bSCy Schubert     int result;
207*7f2fe78bSCy Schubert 
208*7f2fe78bSCy Schubert     /* assumes def_realm is initialized! */
209*7f2fe78bSCy Schubert     cp = strchr(name, '@');
210*7f2fe78bSCy Schubert     while (cp) {
211*7f2fe78bSCy Schubert         if (cp - name && *(cp - 1) != '\\')
212*7f2fe78bSCy Schubert             break;
213*7f2fe78bSCy Schubert         else
214*7f2fe78bSCy Schubert             cp = strchr(cp + 1, '@');
215*7f2fe78bSCy Schubert     }
216*7f2fe78bSCy Schubert     if (cp == NULL)
217*7f2fe78bSCy Schubert         result = asprintf(&fullname, "%s@%s", name, def_realm);
218*7f2fe78bSCy Schubert     else
219*7f2fe78bSCy Schubert         result = asprintf(&fullname, "%s", name);
220*7f2fe78bSCy Schubert     if (result < 0)
221*7f2fe78bSCy Schubert         return ENOMEM;
222*7f2fe78bSCy Schubert     retval = krb5_parse_name(context, fullname, principal);
223*7f2fe78bSCy Schubert     free(fullname);
224*7f2fe78bSCy Schubert     return retval;
225*7f2fe78bSCy Schubert }
226*7f2fe78bSCy Schubert 
227*7f2fe78bSCy Schubert static void
extended_com_err_fn(const char * myprog,errcode_t code,const char * fmt,va_list args)228*7f2fe78bSCy Schubert extended_com_err_fn(const char *myprog, errcode_t code,
229*7f2fe78bSCy Schubert                     const char *fmt, va_list args)
230*7f2fe78bSCy Schubert {
231*7f2fe78bSCy Schubert     const char *emsg;
232*7f2fe78bSCy Schubert 
233*7f2fe78bSCy Schubert     if (code) {
234*7f2fe78bSCy Schubert         emsg = krb5_get_error_message(context, code);
235*7f2fe78bSCy Schubert         error("%s: %s ", myprog, emsg);
236*7f2fe78bSCy Schubert         krb5_free_error_message(context, emsg);
237*7f2fe78bSCy Schubert     } else {
238*7f2fe78bSCy Schubert         error("%s: ", myprog);
239*7f2fe78bSCy Schubert     }
240*7f2fe78bSCy Schubert     vfprintf(stderr, fmt, args);
241*7f2fe78bSCy Schubert     error("\n");
242*7f2fe78bSCy Schubert }
243*7f2fe78bSCy Schubert 
244*7f2fe78bSCy Schubert /* Create a principal using the oldest appropriate kadm5 API. */
245*7f2fe78bSCy Schubert static krb5_error_code
create_princ(kadm5_principal_ent_rec * princ,long mask,int n_ks,krb5_key_salt_tuple * ks,char * pass)246*7f2fe78bSCy Schubert create_princ(kadm5_principal_ent_rec *princ, long mask, int n_ks,
247*7f2fe78bSCy Schubert              krb5_key_salt_tuple *ks, char *pass)
248*7f2fe78bSCy Schubert {
249*7f2fe78bSCy Schubert     if (ks)
250*7f2fe78bSCy Schubert         return kadm5_create_principal_3(handle, princ, mask, n_ks, ks, pass);
251*7f2fe78bSCy Schubert     else
252*7f2fe78bSCy Schubert         return kadm5_create_principal(handle, princ, mask, pass);
253*7f2fe78bSCy Schubert }
254*7f2fe78bSCy Schubert 
255*7f2fe78bSCy Schubert /* Randomize a principal's password using the appropriate kadm5 API. */
256*7f2fe78bSCy Schubert krb5_error_code
randkey_princ(void * lhandle,krb5_principal princ,krb5_boolean keepold,int n_ks,krb5_key_salt_tuple * ks,krb5_keyblock ** key,int * n_keys)257*7f2fe78bSCy Schubert randkey_princ(void *lhandle, krb5_principal princ, krb5_boolean keepold,
258*7f2fe78bSCy Schubert               int n_ks, krb5_key_salt_tuple *ks, krb5_keyblock **key,
259*7f2fe78bSCy Schubert               int *n_keys)
260*7f2fe78bSCy Schubert {
261*7f2fe78bSCy Schubert     krb5_error_code ret;
262*7f2fe78bSCy Schubert 
263*7f2fe78bSCy Schubert     /* Try the newer API first, because the Solaris kadmind only creates DES
264*7f2fe78bSCy Schubert      * keys when the old API is used. */
265*7f2fe78bSCy Schubert     ret = kadm5_randkey_principal_3(lhandle, princ, keepold, n_ks, ks, key,
266*7f2fe78bSCy Schubert                                     n_keys);
267*7f2fe78bSCy Schubert 
268*7f2fe78bSCy Schubert     /* Fall back to the old version if we get an error and aren't using any new
269*7f2fe78bSCy Schubert      * parameters. */
270*7f2fe78bSCy Schubert     if (ret == KADM5_RPC_ERROR && !keepold && ks == NULL)
271*7f2fe78bSCy Schubert         ret = kadm5_randkey_principal(lhandle, princ, key, n_keys);
272*7f2fe78bSCy Schubert 
273*7f2fe78bSCy Schubert     return ret;
274*7f2fe78bSCy Schubert }
275*7f2fe78bSCy Schubert 
276*7f2fe78bSCy Schubert static krb5_boolean
policy_exists(const char * name)277*7f2fe78bSCy Schubert policy_exists(const char *name)
278*7f2fe78bSCy Schubert {
279*7f2fe78bSCy Schubert     kadm5_policy_ent_rec pol;
280*7f2fe78bSCy Schubert 
281*7f2fe78bSCy Schubert     if (kadm5_get_policy(handle, (char *)name, &pol) != 0)
282*7f2fe78bSCy Schubert         return FALSE;
283*7f2fe78bSCy Schubert     kadm5_free_policy_ent(handle, &pol);
284*7f2fe78bSCy Schubert     return TRUE;
285*7f2fe78bSCy Schubert }
286*7f2fe78bSCy Schubert 
287*7f2fe78bSCy Schubert void
kadmin_startup(int argc,char * argv[],char ** request_out,char *** args_out)288*7f2fe78bSCy Schubert kadmin_startup(int argc, char *argv[], char **request_out, char ***args_out)
289*7f2fe78bSCy Schubert {
290*7f2fe78bSCy Schubert     extern char *optarg;
291*7f2fe78bSCy Schubert     char *princstr = NULL, *keytab_name = NULL, *query = NULL;
292*7f2fe78bSCy Schubert     char *password = NULL;
293*7f2fe78bSCy Schubert     char *luser, *canon, *cp;
294*7f2fe78bSCy Schubert     int optchar, freeprinc = 0, use_keytab = 0, use_anonymous = 0;
295*7f2fe78bSCy Schubert     struct passwd *pw;
296*7f2fe78bSCy Schubert     kadm5_ret_t retval;
297*7f2fe78bSCy Schubert     krb5_ccache cc;
298*7f2fe78bSCy Schubert     krb5_principal princ;
299*7f2fe78bSCy Schubert     kadm5_config_params params;
300*7f2fe78bSCy Schubert     char **db_args = NULL;
301*7f2fe78bSCy Schubert     int db_args_size = 0;
302*7f2fe78bSCy Schubert     char *db_name = NULL;
303*7f2fe78bSCy Schubert     char *svcname, *realm;
304*7f2fe78bSCy Schubert 
305*7f2fe78bSCy Schubert     memset(&params, 0, sizeof(params));
306*7f2fe78bSCy Schubert 
307*7f2fe78bSCy Schubert     set_com_err_hook(extended_com_err_fn);
308*7f2fe78bSCy Schubert 
309*7f2fe78bSCy Schubert     retval = kadm5_init_krb5_context(&context);
310*7f2fe78bSCy Schubert     if (retval) {
311*7f2fe78bSCy Schubert         com_err(whoami, retval, _("while initializing krb5 library"));
312*7f2fe78bSCy Schubert         exit(1);
313*7f2fe78bSCy Schubert     }
314*7f2fe78bSCy Schubert 
315*7f2fe78bSCy Schubert     while ((optchar = getopt(argc, argv,
316*7f2fe78bSCy Schubert                              "+x:r:p:knq:w:d:s:mc:t:e:ON")) != EOF) {
317*7f2fe78bSCy Schubert         switch (optchar) {
318*7f2fe78bSCy Schubert         case 'x':
319*7f2fe78bSCy Schubert             db_args_size++;
320*7f2fe78bSCy Schubert             db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1));
321*7f2fe78bSCy Schubert             if (db_args == NULL) {
322*7f2fe78bSCy Schubert                 error(_("%s: Cannot initialize. Not enough memory\n"), whoami);
323*7f2fe78bSCy Schubert                 exit(1);
324*7f2fe78bSCy Schubert             }
325*7f2fe78bSCy Schubert             db_args[db_args_size - 1] = optarg;
326*7f2fe78bSCy Schubert             db_args[db_args_size] = NULL;
327*7f2fe78bSCy Schubert             break;
328*7f2fe78bSCy Schubert 
329*7f2fe78bSCy Schubert         case 'r':
330*7f2fe78bSCy Schubert             def_realm = optarg;
331*7f2fe78bSCy Schubert             break;
332*7f2fe78bSCy Schubert         case 'p':
333*7f2fe78bSCy Schubert             princstr = optarg;
334*7f2fe78bSCy Schubert             break;
335*7f2fe78bSCy Schubert         case 'c':
336*7f2fe78bSCy Schubert             ccache_name = optarg;
337*7f2fe78bSCy Schubert             break;
338*7f2fe78bSCy Schubert         case 'k':
339*7f2fe78bSCy Schubert             use_keytab++;
340*7f2fe78bSCy Schubert             break;
341*7f2fe78bSCy Schubert         case 'n':
342*7f2fe78bSCy Schubert             use_anonymous++;
343*7f2fe78bSCy Schubert             break;
344*7f2fe78bSCy Schubert         case 't':
345*7f2fe78bSCy Schubert             keytab_name = optarg;
346*7f2fe78bSCy Schubert             break;
347*7f2fe78bSCy Schubert         case 'w':
348*7f2fe78bSCy Schubert             password = optarg;
349*7f2fe78bSCy Schubert             break;
350*7f2fe78bSCy Schubert         case 'q':
351*7f2fe78bSCy Schubert             query = optarg;
352*7f2fe78bSCy Schubert             break;
353*7f2fe78bSCy Schubert         case 'd':
354*7f2fe78bSCy Schubert             /* db_name has to be passed as part of the db_args. */
355*7f2fe78bSCy Schubert             free(db_name);
356*7f2fe78bSCy Schubert             asprintf(&db_name, "dbname=%s", optarg);
357*7f2fe78bSCy Schubert 
358*7f2fe78bSCy Schubert             db_args_size++;
359*7f2fe78bSCy Schubert             db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1));
360*7f2fe78bSCy Schubert             if (db_args == NULL) {
361*7f2fe78bSCy Schubert                 error(_("%s: Cannot initialize. Not enough memory\n"), whoami);
362*7f2fe78bSCy Schubert                 exit(1);
363*7f2fe78bSCy Schubert             }
364*7f2fe78bSCy Schubert             db_args[db_args_size - 1] = db_name;
365*7f2fe78bSCy Schubert             db_args[db_args_size] = NULL;
366*7f2fe78bSCy Schubert             break;
367*7f2fe78bSCy Schubert         case 's':
368*7f2fe78bSCy Schubert             params.admin_server = optarg;
369*7f2fe78bSCy Schubert             params.mask |= KADM5_CONFIG_ADMIN_SERVER;
370*7f2fe78bSCy Schubert             break;
371*7f2fe78bSCy Schubert         case 'm':
372*7f2fe78bSCy Schubert             params.mkey_from_kbd = 1;
373*7f2fe78bSCy Schubert             params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
374*7f2fe78bSCy Schubert             break;
375*7f2fe78bSCy Schubert         case 'e':
376*7f2fe78bSCy Schubert             retval = krb5_string_to_keysalts(optarg, NULL, NULL, 0,
377*7f2fe78bSCy Schubert                                              &params.keysalts,
378*7f2fe78bSCy Schubert                                              &params.num_keysalts);
379*7f2fe78bSCy Schubert             if (retval) {
380*7f2fe78bSCy Schubert                 com_err(whoami, retval, _("while parsing keysalts %s"),
381*7f2fe78bSCy Schubert                         optarg);
382*7f2fe78bSCy Schubert                 exit(1);
383*7f2fe78bSCy Schubert             }
384*7f2fe78bSCy Schubert             params.mask |= KADM5_CONFIG_ENCTYPES;
385*7f2fe78bSCy Schubert             break;
386*7f2fe78bSCy Schubert         case 'O':
387*7f2fe78bSCy Schubert             params.mask |= KADM5_CONFIG_OLD_AUTH_GSSAPI;
388*7f2fe78bSCy Schubert             break;
389*7f2fe78bSCy Schubert         case 'N':
390*7f2fe78bSCy Schubert             params.mask |= KADM5_CONFIG_AUTH_NOFALLBACK;
391*7f2fe78bSCy Schubert             break;
392*7f2fe78bSCy Schubert         default:
393*7f2fe78bSCy Schubert             usage();
394*7f2fe78bSCy Schubert         }
395*7f2fe78bSCy Schubert     }
396*7f2fe78bSCy Schubert     if ((ccache_name && use_keytab) ||
397*7f2fe78bSCy Schubert         (keytab_name && !use_keytab) ||
398*7f2fe78bSCy Schubert         (ccache_name && use_anonymous) ||
399*7f2fe78bSCy Schubert         (use_anonymous && use_keytab))
400*7f2fe78bSCy Schubert         usage();
401*7f2fe78bSCy Schubert 
402*7f2fe78bSCy Schubert     if (query != NULL && argv[optind] != NULL) {
403*7f2fe78bSCy Schubert         error(_("%s: -q is exclusive with command-line query"), whoami);
404*7f2fe78bSCy Schubert         usage();
405*7f2fe78bSCy Schubert     }
406*7f2fe78bSCy Schubert 
407*7f2fe78bSCy Schubert     if (argv[optind] != NULL)
408*7f2fe78bSCy Schubert         script_mode = TRUE;
409*7f2fe78bSCy Schubert 
410*7f2fe78bSCy Schubert     if (def_realm == NULL && krb5_get_default_realm(context, &def_realm)) {
411*7f2fe78bSCy Schubert         error(_("%s: unable to get default realm\n"), whoami);
412*7f2fe78bSCy Schubert         exit(1);
413*7f2fe78bSCy Schubert     }
414*7f2fe78bSCy Schubert 
415*7f2fe78bSCy Schubert     params.mask |= KADM5_CONFIG_REALM;
416*7f2fe78bSCy Schubert     params.realm = def_realm;
417*7f2fe78bSCy Schubert 
418*7f2fe78bSCy Schubert     if (params.mask & KADM5_CONFIG_OLD_AUTH_GSSAPI)
419*7f2fe78bSCy Schubert         svcname = KADM5_ADMIN_SERVICE;
420*7f2fe78bSCy Schubert     else
421*7f2fe78bSCy Schubert         svcname = NULL;
422*7f2fe78bSCy Schubert 
423*7f2fe78bSCy Schubert     /*
424*7f2fe78bSCy Schubert      * Set cc to an open credentials cache, either specified by the -c
425*7f2fe78bSCy Schubert      * argument or the default.
426*7f2fe78bSCy Schubert      */
427*7f2fe78bSCy Schubert     if (ccache_name == NULL) {
428*7f2fe78bSCy Schubert         retval = krb5_cc_default(context, &cc);
429*7f2fe78bSCy Schubert         if (retval) {
430*7f2fe78bSCy Schubert             com_err(whoami, retval,
431*7f2fe78bSCy Schubert                     _("while opening default credentials cache"));
432*7f2fe78bSCy Schubert             exit(1);
433*7f2fe78bSCy Schubert         }
434*7f2fe78bSCy Schubert     } else {
435*7f2fe78bSCy Schubert         retval = krb5_cc_resolve(context, ccache_name, &cc);
436*7f2fe78bSCy Schubert         if (retval) {
437*7f2fe78bSCy Schubert             com_err(whoami, retval, _("while opening credentials cache %s"),
438*7f2fe78bSCy Schubert                     ccache_name);
439*7f2fe78bSCy Schubert             exit(1);
440*7f2fe78bSCy Schubert         }
441*7f2fe78bSCy Schubert     }
442*7f2fe78bSCy Schubert 
443*7f2fe78bSCy Schubert     /*
444*7f2fe78bSCy Schubert      * If no principal name is specified: If authenticating anonymously, use
445*7f2fe78bSCy Schubert      * the anonymous principal for the local realm, else if a ccache was
446*7f2fe78bSCy Schubert      * specified and its primary principal name can be read, it is used, else
447*7f2fe78bSCy Schubert      * if a keytab was specified, the principal name is host/hostname,
448*7f2fe78bSCy Schubert      * otherwise append "/admin" to the primary name of the default ccache,
449*7f2fe78bSCy Schubert      * $USER, or pw_name.
450*7f2fe78bSCy Schubert      *
451*7f2fe78bSCy Schubert      * Gee, 100+ lines to figure out the client principal name.  This
452*7f2fe78bSCy Schubert      * should be compressed...
453*7f2fe78bSCy Schubert      */
454*7f2fe78bSCy Schubert 
455*7f2fe78bSCy Schubert     if (princstr == NULL) {
456*7f2fe78bSCy Schubert         if (use_anonymous) {
457*7f2fe78bSCy Schubert             if (asprintf(&princstr, "%s/%s@%s", KRB5_WELLKNOWN_NAMESTR,
458*7f2fe78bSCy Schubert                          KRB5_ANONYMOUS_PRINCSTR, def_realm) < 0) {
459*7f2fe78bSCy Schubert                 error(_("%s: out of memory\n"), whoami);
460*7f2fe78bSCy Schubert                 exit(1);
461*7f2fe78bSCy Schubert             }
462*7f2fe78bSCy Schubert             freeprinc++;
463*7f2fe78bSCy Schubert         } else if (ccache_name != NULL &&
464*7f2fe78bSCy Schubert             !krb5_cc_get_principal(context, cc, &princ)) {
465*7f2fe78bSCy Schubert             retval = krb5_unparse_name(context, princ, &princstr);
466*7f2fe78bSCy Schubert             if (retval) {
467*7f2fe78bSCy Schubert                 com_err(whoami, retval,
468*7f2fe78bSCy Schubert                         _("while canonicalizing principal name"));
469*7f2fe78bSCy Schubert                 exit(1);
470*7f2fe78bSCy Schubert             }
471*7f2fe78bSCy Schubert             krb5_free_principal(context, princ);
472*7f2fe78bSCy Schubert             freeprinc++;
473*7f2fe78bSCy Schubert         } else if (use_keytab != 0) {
474*7f2fe78bSCy Schubert             retval = krb5_sname_to_principal(context, NULL, "host",
475*7f2fe78bSCy Schubert                                              KRB5_NT_SRV_HST, &princ);
476*7f2fe78bSCy Schubert             if (retval) {
477*7f2fe78bSCy Schubert                 com_err(whoami, retval, _("creating host service principal"));
478*7f2fe78bSCy Schubert                 exit(1);
479*7f2fe78bSCy Schubert             }
480*7f2fe78bSCy Schubert             retval = krb5_unparse_name(context, princ, &princstr);
481*7f2fe78bSCy Schubert             if (retval) {
482*7f2fe78bSCy Schubert                 com_err(whoami, retval,
483*7f2fe78bSCy Schubert                         _("while canonicalizing principal name"));
484*7f2fe78bSCy Schubert                 exit(1);
485*7f2fe78bSCy Schubert             }
486*7f2fe78bSCy Schubert             krb5_free_principal(context, princ);
487*7f2fe78bSCy Schubert             freeprinc++;
488*7f2fe78bSCy Schubert         } else if (!krb5_cc_get_principal(context, cc, &princ)) {
489*7f2fe78bSCy Schubert             if (krb5_unparse_name(context, princ, &canon)) {
490*7f2fe78bSCy Schubert                 error(_("%s: unable to canonicalize principal\n"), whoami);
491*7f2fe78bSCy Schubert                 exit(1);
492*7f2fe78bSCy Schubert             }
493*7f2fe78bSCy Schubert             /* Strip out realm of principal if it's there. */
494*7f2fe78bSCy Schubert             realm = strchr(canon, '@');
495*7f2fe78bSCy Schubert             while (realm) {
496*7f2fe78bSCy Schubert                 if (realm > canon && *(realm - 1) != '\\')
497*7f2fe78bSCy Schubert                     break;
498*7f2fe78bSCy Schubert                 realm = strchr(realm + 1, '@');
499*7f2fe78bSCy Schubert             }
500*7f2fe78bSCy Schubert             if (realm)
501*7f2fe78bSCy Schubert                 *realm++ = '\0';
502*7f2fe78bSCy Schubert             cp = strchr(canon, '/');
503*7f2fe78bSCy Schubert             while (cp) {
504*7f2fe78bSCy Schubert                 if (cp > canon && *(cp - 1) != '\\')
505*7f2fe78bSCy Schubert                     break;
506*7f2fe78bSCy Schubert                 cp = strchr(cp + 1, '/');
507*7f2fe78bSCy Schubert             }
508*7f2fe78bSCy Schubert             if (cp != NULL)
509*7f2fe78bSCy Schubert                 *cp = '\0';
510*7f2fe78bSCy Schubert             if (asprintf(&princstr, "%s/admin%s%s", canon,
511*7f2fe78bSCy Schubert                          (realm) ? "@" : "",
512*7f2fe78bSCy Schubert                          (realm) ? realm : "") < 0) {
513*7f2fe78bSCy Schubert                 error(_("%s: out of memory\n"), whoami);
514*7f2fe78bSCy Schubert                 exit(1);
515*7f2fe78bSCy Schubert             }
516*7f2fe78bSCy Schubert             free(canon);
517*7f2fe78bSCy Schubert             krb5_free_principal(context, princ);
518*7f2fe78bSCy Schubert             freeprinc++;
519*7f2fe78bSCy Schubert         } else if ((luser = getenv("USER"))) {
520*7f2fe78bSCy Schubert             if (asprintf(&princstr, "%s/admin@%s", luser, def_realm) < 0) {
521*7f2fe78bSCy Schubert                 error(_("%s: out of memory\n"), whoami);
522*7f2fe78bSCy Schubert                 exit(1);
523*7f2fe78bSCy Schubert             }
524*7f2fe78bSCy Schubert             freeprinc++;
525*7f2fe78bSCy Schubert         } else if ((pw = getpwuid(getuid()))) {
526*7f2fe78bSCy Schubert             if (asprintf(&princstr, "%s/admin@%s", pw->pw_name,
527*7f2fe78bSCy Schubert                          def_realm) < 0) {
528*7f2fe78bSCy Schubert                 error(_("%s: out of memory\n"), whoami);
529*7f2fe78bSCy Schubert                 exit(1);
530*7f2fe78bSCy Schubert             }
531*7f2fe78bSCy Schubert             freeprinc++;
532*7f2fe78bSCy Schubert         } else {
533*7f2fe78bSCy Schubert             error(_("%s: unable to figure out a principal name\n"), whoami);
534*7f2fe78bSCy Schubert             exit(1);
535*7f2fe78bSCy Schubert         }
536*7f2fe78bSCy Schubert     }
537*7f2fe78bSCy Schubert 
538*7f2fe78bSCy Schubert     retval = krb5_klog_init(context, "admin_server", whoami, 0);
539*7f2fe78bSCy Schubert     if (retval) {
540*7f2fe78bSCy Schubert         com_err(whoami, retval, _("while setting up logging"));
541*7f2fe78bSCy Schubert         exit(1);
542*7f2fe78bSCy Schubert     }
543*7f2fe78bSCy Schubert 
544*7f2fe78bSCy Schubert     /*
545*7f2fe78bSCy Schubert      * Initialize the kadm5 connection.  If we were given a ccache,
546*7f2fe78bSCy Schubert      * use it.  Otherwise, use/prompt for the password.
547*7f2fe78bSCy Schubert      */
548*7f2fe78bSCy Schubert     if (ccache_name) {
549*7f2fe78bSCy Schubert         info(_("Authenticating as principal %s with existing "
550*7f2fe78bSCy Schubert                "credentials.\n"), princstr);
551*7f2fe78bSCy Schubert         retval = kadm5_init_with_creds(context, princstr, cc, svcname, &params,
552*7f2fe78bSCy Schubert                                        KADM5_STRUCT_VERSION,
553*7f2fe78bSCy Schubert                                        KADM5_API_VERSION_4, db_args, &handle);
554*7f2fe78bSCy Schubert     } else if (use_anonymous) {
555*7f2fe78bSCy Schubert         info(_("Authenticating as principal %s with password; "
556*7f2fe78bSCy Schubert                "anonymous requested.\n"), princstr);
557*7f2fe78bSCy Schubert         retval = kadm5_init_anonymous(context, princstr, svcname, &params,
558*7f2fe78bSCy Schubert                                       KADM5_STRUCT_VERSION,
559*7f2fe78bSCy Schubert                                       KADM5_API_VERSION_4, db_args, &handle);
560*7f2fe78bSCy Schubert     } else if (use_keytab) {
561*7f2fe78bSCy Schubert         if (keytab_name != NULL) {
562*7f2fe78bSCy Schubert             info(_("Authenticating as principal %s with keytab %s.\n"),
563*7f2fe78bSCy Schubert                  princstr, keytab_name);
564*7f2fe78bSCy Schubert         } else {
565*7f2fe78bSCy Schubert             info(_("Authenticating as principal %s with default keytab.\n"),
566*7f2fe78bSCy Schubert                  princstr);
567*7f2fe78bSCy Schubert         }
568*7f2fe78bSCy Schubert         retval = kadm5_init_with_skey(context, princstr, keytab_name, svcname,
569*7f2fe78bSCy Schubert                                       &params, KADM5_STRUCT_VERSION,
570*7f2fe78bSCy Schubert                                       KADM5_API_VERSION_4, db_args, &handle);
571*7f2fe78bSCy Schubert     } else {
572*7f2fe78bSCy Schubert         info(_("Authenticating as principal %s with password.\n"),
573*7f2fe78bSCy Schubert              princstr);
574*7f2fe78bSCy Schubert         retval = kadm5_init_with_password(context, princstr, password, svcname,
575*7f2fe78bSCy Schubert                                           &params, KADM5_STRUCT_VERSION,
576*7f2fe78bSCy Schubert                                           KADM5_API_VERSION_4, db_args,
577*7f2fe78bSCy Schubert                                           &handle);
578*7f2fe78bSCy Schubert     }
579*7f2fe78bSCy Schubert     if (retval) {
580*7f2fe78bSCy Schubert         com_err(whoami, retval, _("while initializing %s interface"), whoami);
581*7f2fe78bSCy Schubert         if (retval == KADM5_BAD_CLIENT_PARAMS ||
582*7f2fe78bSCy Schubert             retval == KADM5_BAD_SERVER_PARAMS)
583*7f2fe78bSCy Schubert             usage();
584*7f2fe78bSCy Schubert         exit(1);
585*7f2fe78bSCy Schubert     }
586*7f2fe78bSCy Schubert     if (freeprinc)
587*7f2fe78bSCy Schubert         free(princstr);
588*7f2fe78bSCy Schubert 
589*7f2fe78bSCy Schubert     free(params.keysalts);
590*7f2fe78bSCy Schubert     free(db_name);
591*7f2fe78bSCy Schubert     free(db_args);
592*7f2fe78bSCy Schubert 
593*7f2fe78bSCy Schubert     retval = krb5_cc_close(context, cc);
594*7f2fe78bSCy Schubert     if (retval) {
595*7f2fe78bSCy Schubert         com_err(whoami, retval, _("while closing ccache %s"), ccache_name);
596*7f2fe78bSCy Schubert         exit(1);
597*7f2fe78bSCy Schubert     }
598*7f2fe78bSCy Schubert 
599*7f2fe78bSCy Schubert     retval = kadm5_init_iprop(handle, 0);
600*7f2fe78bSCy Schubert     if (retval) {
601*7f2fe78bSCy Schubert         com_err(whoami, retval, _("while mapping update log"));
602*7f2fe78bSCy Schubert         exit(1);
603*7f2fe78bSCy Schubert     }
604*7f2fe78bSCy Schubert 
605*7f2fe78bSCy Schubert     *request_out = query;
606*7f2fe78bSCy Schubert     *args_out = argv + optind;
607*7f2fe78bSCy Schubert }
608*7f2fe78bSCy Schubert 
609*7f2fe78bSCy Schubert int
quit()610*7f2fe78bSCy Schubert quit()
611*7f2fe78bSCy Schubert {
612*7f2fe78bSCy Schubert     kadm5_ret_t retval;
613*7f2fe78bSCy Schubert 
614*7f2fe78bSCy Schubert     if (locked) {
615*7f2fe78bSCy Schubert         retval = kadm5_unlock(handle);
616*7f2fe78bSCy Schubert         if (retval) {
617*7f2fe78bSCy Schubert             com_err("quit", retval, _("while unlocking locked database"));
618*7f2fe78bSCy Schubert             return 1;
619*7f2fe78bSCy Schubert         }
620*7f2fe78bSCy Schubert         locked = 0;
621*7f2fe78bSCy Schubert     }
622*7f2fe78bSCy Schubert 
623*7f2fe78bSCy Schubert     kadm5_destroy(handle);
624*7f2fe78bSCy Schubert     if (ccache_name != NULL && !script_mode) {
625*7f2fe78bSCy Schubert         fprintf(stderr, "\n\a\a\a%s",
626*7f2fe78bSCy Schubert                 _("Administration credentials NOT DESTROYED.\n"));
627*7f2fe78bSCy Schubert     }
628*7f2fe78bSCy Schubert 
629*7f2fe78bSCy Schubert     /* insert more random cleanup here */
630*7f2fe78bSCy Schubert     krb5_klog_close(context);
631*7f2fe78bSCy Schubert     krb5_free_context(context);
632*7f2fe78bSCy Schubert     return 0;
633*7f2fe78bSCy Schubert }
634*7f2fe78bSCy Schubert 
635*7f2fe78bSCy Schubert void
kadmin_lock(int argc,char * argv[])636*7f2fe78bSCy Schubert kadmin_lock(int argc, char *argv[])
637*7f2fe78bSCy Schubert {
638*7f2fe78bSCy Schubert     kadm5_ret_t retval;
639*7f2fe78bSCy Schubert 
640*7f2fe78bSCy Schubert     if (locked)
641*7f2fe78bSCy Schubert         return;
642*7f2fe78bSCy Schubert     retval = kadm5_lock(handle);
643*7f2fe78bSCy Schubert     if (retval) {
644*7f2fe78bSCy Schubert         com_err("lock", retval, "");
645*7f2fe78bSCy Schubert         return;
646*7f2fe78bSCy Schubert     }
647*7f2fe78bSCy Schubert     locked = 1;
648*7f2fe78bSCy Schubert }
649*7f2fe78bSCy Schubert 
650*7f2fe78bSCy Schubert void
kadmin_unlock(int argc,char * argv[])651*7f2fe78bSCy Schubert kadmin_unlock(int argc, char *argv[])
652*7f2fe78bSCy Schubert {
653*7f2fe78bSCy Schubert     kadm5_ret_t retval;
654*7f2fe78bSCy Schubert 
655*7f2fe78bSCy Schubert     if (!locked)
656*7f2fe78bSCy Schubert         return;
657*7f2fe78bSCy Schubert     retval = kadm5_unlock(handle);
658*7f2fe78bSCy Schubert     if (retval) {
659*7f2fe78bSCy Schubert         com_err("unlock", retval, "");
660*7f2fe78bSCy Schubert         return;
661*7f2fe78bSCy Schubert     }
662*7f2fe78bSCy Schubert     locked = 0;
663*7f2fe78bSCy Schubert }
664*7f2fe78bSCy Schubert 
665*7f2fe78bSCy Schubert void
kadmin_delprinc(int argc,char * argv[])666*7f2fe78bSCy Schubert kadmin_delprinc(int argc, char *argv[])
667*7f2fe78bSCy Schubert {
668*7f2fe78bSCy Schubert     kadm5_ret_t retval;
669*7f2fe78bSCy Schubert     krb5_principal princ = NULL;
670*7f2fe78bSCy Schubert     char *canon = NULL;
671*7f2fe78bSCy Schubert     char reply[5];
672*7f2fe78bSCy Schubert 
673*7f2fe78bSCy Schubert     if (! (argc == 2 ||
674*7f2fe78bSCy Schubert            (argc == 3 && !strcmp("-force", argv[1])))) {
675*7f2fe78bSCy Schubert         error(_("usage: delete_principal [-force] principal\n"));
676*7f2fe78bSCy Schubert         return;
677*7f2fe78bSCy Schubert     }
678*7f2fe78bSCy Schubert     retval = kadmin_parse_name(argv[argc - 1], &princ);
679*7f2fe78bSCy Schubert     if (retval) {
680*7f2fe78bSCy Schubert         com_err("delete_principal", retval, _("while parsing principal name"));
681*7f2fe78bSCy Schubert         return;
682*7f2fe78bSCy Schubert     }
683*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, princ, &canon);
684*7f2fe78bSCy Schubert     if (retval) {
685*7f2fe78bSCy Schubert         com_err("delete_principal", retval,
686*7f2fe78bSCy Schubert                 _("while canonicalizing principal"));
687*7f2fe78bSCy Schubert         goto cleanup;
688*7f2fe78bSCy Schubert     }
689*7f2fe78bSCy Schubert     if (argc == 2 && !script_mode) {
690*7f2fe78bSCy Schubert         printf(_("Are you sure you want to delete the principal \"%s\"? "
691*7f2fe78bSCy Schubert                  "(yes/no): "), canon);
692*7f2fe78bSCy Schubert         fgets(reply, sizeof (reply), stdin);
693*7f2fe78bSCy Schubert         if (strcmp("yes\n", reply)) {
694*7f2fe78bSCy Schubert             fprintf(stderr, _("Principal \"%s\" not deleted\n"), canon);
695*7f2fe78bSCy Schubert             goto cleanup;
696*7f2fe78bSCy Schubert         }
697*7f2fe78bSCy Schubert     }
698*7f2fe78bSCy Schubert     retval = kadm5_delete_principal(handle, princ);
699*7f2fe78bSCy Schubert     if (retval) {
700*7f2fe78bSCy Schubert         com_err("delete_principal", retval,
701*7f2fe78bSCy Schubert                 _("while deleting principal \"%s\""), canon);
702*7f2fe78bSCy Schubert         goto cleanup;
703*7f2fe78bSCy Schubert     }
704*7f2fe78bSCy Schubert     info(_("Principal \"%s\" deleted.\n"), canon);
705*7f2fe78bSCy Schubert     info(_("Make sure that you have removed this principal from all ACLs "
706*7f2fe78bSCy Schubert            "before reusing.\n"));
707*7f2fe78bSCy Schubert 
708*7f2fe78bSCy Schubert cleanup:
709*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
710*7f2fe78bSCy Schubert     free(canon);
711*7f2fe78bSCy Schubert }
712*7f2fe78bSCy Schubert 
713*7f2fe78bSCy Schubert void
kadmin_renameprinc(int argc,char * argv[])714*7f2fe78bSCy Schubert kadmin_renameprinc(int argc, char *argv[])
715*7f2fe78bSCy Schubert {
716*7f2fe78bSCy Schubert     kadm5_ret_t retval;
717*7f2fe78bSCy Schubert     krb5_principal oprinc = NULL, nprinc = NULL;
718*7f2fe78bSCy Schubert     char *ocanon = NULL, *ncanon = NULL;
719*7f2fe78bSCy Schubert     char reply[5];
720*7f2fe78bSCy Schubert 
721*7f2fe78bSCy Schubert     if (!(argc == 3 || (argc == 4 && !strcmp("-force", argv[1])))) {
722*7f2fe78bSCy Schubert         error(_("usage: rename_principal [-force] old_principal "
723*7f2fe78bSCy Schubert                 "new_principal\n"));
724*7f2fe78bSCy Schubert         return;
725*7f2fe78bSCy Schubert     }
726*7f2fe78bSCy Schubert     retval = kadmin_parse_name(argv[argc - 2], &oprinc);
727*7f2fe78bSCy Schubert     if (retval) {
728*7f2fe78bSCy Schubert         com_err("rename_principal", retval,
729*7f2fe78bSCy Schubert                 _("while parsing old principal name"));
730*7f2fe78bSCy Schubert         goto cleanup;
731*7f2fe78bSCy Schubert     }
732*7f2fe78bSCy Schubert     retval = kadmin_parse_name(argv[argc - 1], &nprinc);
733*7f2fe78bSCy Schubert     if (retval) {
734*7f2fe78bSCy Schubert         com_err("rename_principal", retval,
735*7f2fe78bSCy Schubert                 _("while parsing new principal name"));
736*7f2fe78bSCy Schubert         goto cleanup;
737*7f2fe78bSCy Schubert     }
738*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, oprinc, &ocanon);
739*7f2fe78bSCy Schubert     if (retval) {
740*7f2fe78bSCy Schubert         com_err("rename_principal", retval,
741*7f2fe78bSCy Schubert                 _("while canonicalizing old principal"));
742*7f2fe78bSCy Schubert         goto cleanup;
743*7f2fe78bSCy Schubert     }
744*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, nprinc, &ncanon);
745*7f2fe78bSCy Schubert     if (retval) {
746*7f2fe78bSCy Schubert         com_err("rename_principal", retval,
747*7f2fe78bSCy Schubert                 _("while canonicalizing new principal"));
748*7f2fe78bSCy Schubert         goto cleanup;
749*7f2fe78bSCy Schubert     }
750*7f2fe78bSCy Schubert     if (argc == 3 && !script_mode) {
751*7f2fe78bSCy Schubert         printf(_("Are you sure you want to rename the principal \"%s\" "
752*7f2fe78bSCy Schubert                  "to \"%s\"? (yes/no): "), ocanon, ncanon);
753*7f2fe78bSCy Schubert         fgets(reply, sizeof(reply), stdin);
754*7f2fe78bSCy Schubert         if (strcmp("yes\n", reply)) {
755*7f2fe78bSCy Schubert             fprintf(stderr, _("Principal \"%s\" not renamed\n"), ocanon);
756*7f2fe78bSCy Schubert             goto cleanup;
757*7f2fe78bSCy Schubert         }
758*7f2fe78bSCy Schubert     }
759*7f2fe78bSCy Schubert     retval = kadm5_rename_principal(handle, oprinc, nprinc);
760*7f2fe78bSCy Schubert     if (retval) {
761*7f2fe78bSCy Schubert         com_err("rename_principal", retval,
762*7f2fe78bSCy Schubert                 _("while renaming principal \"%s\" to \"%s\""),
763*7f2fe78bSCy Schubert                 ocanon, ncanon);
764*7f2fe78bSCy Schubert         goto cleanup;
765*7f2fe78bSCy Schubert     }
766*7f2fe78bSCy Schubert     info(_("Principal \"%s\" renamed to \"%s\".\n"), ocanon, ncanon);
767*7f2fe78bSCy Schubert     info(_("Make sure that you have removed the old principal from all ACLs "
768*7f2fe78bSCy Schubert            "before reusing.\n"));
769*7f2fe78bSCy Schubert 
770*7f2fe78bSCy Schubert cleanup:
771*7f2fe78bSCy Schubert     krb5_free_principal(context, nprinc);
772*7f2fe78bSCy Schubert     krb5_free_principal(context, oprinc);
773*7f2fe78bSCy Schubert     free(ncanon);
774*7f2fe78bSCy Schubert     free(ocanon);
775*7f2fe78bSCy Schubert }
776*7f2fe78bSCy Schubert 
777*7f2fe78bSCy Schubert static void
cpw_usage(const char * str)778*7f2fe78bSCy Schubert cpw_usage(const char *str)
779*7f2fe78bSCy Schubert {
780*7f2fe78bSCy Schubert     if (str)
781*7f2fe78bSCy Schubert         error("%s\n", str);
782*7f2fe78bSCy Schubert     error(_("usage: change_password [-randkey] [-keepold] "
783*7f2fe78bSCy Schubert             "[-e keysaltlist] [-pw password] principal\n"));
784*7f2fe78bSCy Schubert }
785*7f2fe78bSCy Schubert 
786*7f2fe78bSCy Schubert void
kadmin_cpw(int argc,char * argv[])787*7f2fe78bSCy Schubert kadmin_cpw(int argc, char *argv[])
788*7f2fe78bSCy Schubert {
789*7f2fe78bSCy Schubert     kadm5_ret_t retval;
790*7f2fe78bSCy Schubert     static char newpw[1024];
791*7f2fe78bSCy Schubert     static char prompt1[1024], prompt2[1024];
792*7f2fe78bSCy Schubert     char *canon = NULL, *pwarg = NULL;
793*7f2fe78bSCy Schubert     int n_ks_tuple = 0, randkey = 0;
794*7f2fe78bSCy Schubert     krb5_boolean keepold = FALSE;
795*7f2fe78bSCy Schubert     krb5_key_salt_tuple *ks_tuple = NULL;
796*7f2fe78bSCy Schubert     krb5_principal princ = NULL;
797*7f2fe78bSCy Schubert     char **db_args = NULL;
798*7f2fe78bSCy Schubert     int db_args_size = 0;
799*7f2fe78bSCy Schubert 
800*7f2fe78bSCy Schubert     if (argc < 1) {
801*7f2fe78bSCy Schubert         cpw_usage(NULL);
802*7f2fe78bSCy Schubert         return;
803*7f2fe78bSCy Schubert     }
804*7f2fe78bSCy Schubert     for (argv++, argc--; argc > 0 && **argv == '-'; argc--, argv++) {
805*7f2fe78bSCy Schubert         if (!strcmp("-x", *argv)) {
806*7f2fe78bSCy Schubert             argc--;
807*7f2fe78bSCy Schubert             if (argc < 1) {
808*7f2fe78bSCy Schubert                 cpw_usage(_("change_password: missing db argument"));
809*7f2fe78bSCy Schubert                 goto cleanup;
810*7f2fe78bSCy Schubert             }
811*7f2fe78bSCy Schubert             db_args_size++;
812*7f2fe78bSCy Schubert             db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1));
813*7f2fe78bSCy Schubert             if (db_args == NULL) {
814*7f2fe78bSCy Schubert                 error(_("change_password: Not enough memory\n"));
815*7f2fe78bSCy Schubert                 exit(1);
816*7f2fe78bSCy Schubert             }
817*7f2fe78bSCy Schubert             db_args[db_args_size - 1] = *++argv;
818*7f2fe78bSCy Schubert             db_args[db_args_size] = NULL;
819*7f2fe78bSCy Schubert         } else if (!strcmp("-pw", *argv)) {
820*7f2fe78bSCy Schubert             argc--;
821*7f2fe78bSCy Schubert             if (argc < 1) {
822*7f2fe78bSCy Schubert                 cpw_usage(_("change_password: missing password arg"));
823*7f2fe78bSCy Schubert                 goto cleanup;
824*7f2fe78bSCy Schubert             }
825*7f2fe78bSCy Schubert             pwarg = *++argv;
826*7f2fe78bSCy Schubert         } else if (!strcmp("-randkey", *argv)) {
827*7f2fe78bSCy Schubert             randkey++;
828*7f2fe78bSCy Schubert         } else if (!strcmp("-keepold", *argv)) {
829*7f2fe78bSCy Schubert             keepold = TRUE;
830*7f2fe78bSCy Schubert         } else if (!strcmp("-e", *argv)) {
831*7f2fe78bSCy Schubert             argc--;
832*7f2fe78bSCy Schubert             if (argc < 1) {
833*7f2fe78bSCy Schubert                 cpw_usage(_("change_password: missing keysaltlist arg"));
834*7f2fe78bSCy Schubert                 goto cleanup;
835*7f2fe78bSCy Schubert             }
836*7f2fe78bSCy Schubert             retval = krb5_string_to_keysalts(*++argv, NULL, NULL, 0,
837*7f2fe78bSCy Schubert                                              &ks_tuple, &n_ks_tuple);
838*7f2fe78bSCy Schubert             if (retval) {
839*7f2fe78bSCy Schubert                 com_err("change_password", retval,
840*7f2fe78bSCy Schubert                         _("while parsing keysalts %s"), *argv);
841*7f2fe78bSCy Schubert                 goto cleanup;
842*7f2fe78bSCy Schubert             }
843*7f2fe78bSCy Schubert         } else {
844*7f2fe78bSCy Schubert             com_err("change_password", 0, _("unrecognized option %s"), *argv);
845*7f2fe78bSCy Schubert             cpw_usage(NULL);
846*7f2fe78bSCy Schubert             goto cleanup;
847*7f2fe78bSCy Schubert         }
848*7f2fe78bSCy Schubert     }
849*7f2fe78bSCy Schubert     if (argc != 1) {
850*7f2fe78bSCy Schubert         if (argc < 1)
851*7f2fe78bSCy Schubert             com_err("change_password", 0, _("missing principal name"));
852*7f2fe78bSCy Schubert         else
853*7f2fe78bSCy Schubert             com_err("change_password", 0, _("too many arguments"));
854*7f2fe78bSCy Schubert         cpw_usage(NULL);
855*7f2fe78bSCy Schubert         goto cleanup;
856*7f2fe78bSCy Schubert     }
857*7f2fe78bSCy Schubert     retval = kadmin_parse_name(*argv, &princ);
858*7f2fe78bSCy Schubert     if (retval) {
859*7f2fe78bSCy Schubert         com_err("change_password", retval, _("while parsing principal name"));
860*7f2fe78bSCy Schubert         goto cleanup;
861*7f2fe78bSCy Schubert     }
862*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, princ, &canon);
863*7f2fe78bSCy Schubert     if (retval) {
864*7f2fe78bSCy Schubert         com_err("change_password", retval,
865*7f2fe78bSCy Schubert                 _("while canonicalizing principal"));
866*7f2fe78bSCy Schubert         goto cleanup;
867*7f2fe78bSCy Schubert     }
868*7f2fe78bSCy Schubert     if (pwarg != NULL) {
869*7f2fe78bSCy Schubert         if (keepold || ks_tuple != NULL) {
870*7f2fe78bSCy Schubert             retval = kadm5_chpass_principal_3(handle, princ, keepold,
871*7f2fe78bSCy Schubert                                               n_ks_tuple, ks_tuple, pwarg);
872*7f2fe78bSCy Schubert         } else {
873*7f2fe78bSCy Schubert             retval = kadm5_chpass_principal(handle, princ, pwarg);
874*7f2fe78bSCy Schubert         }
875*7f2fe78bSCy Schubert         if (retval) {
876*7f2fe78bSCy Schubert             com_err("change_password", retval,
877*7f2fe78bSCy Schubert                     _("while changing password for \"%s\"."), canon);
878*7f2fe78bSCy Schubert             goto cleanup;
879*7f2fe78bSCy Schubert         }
880*7f2fe78bSCy Schubert         info(_("Password for \"%s\" changed.\n"), canon);
881*7f2fe78bSCy Schubert     } else if (randkey) {
882*7f2fe78bSCy Schubert         retval = randkey_princ(handle, princ, keepold, n_ks_tuple, ks_tuple,
883*7f2fe78bSCy Schubert                                NULL, NULL);
884*7f2fe78bSCy Schubert         if (retval) {
885*7f2fe78bSCy Schubert             com_err("change_password", retval,
886*7f2fe78bSCy Schubert                     _("while randomizing key for \"%s\"."), canon);
887*7f2fe78bSCy Schubert             goto cleanup;
888*7f2fe78bSCy Schubert         }
889*7f2fe78bSCy Schubert         info(_("Key for \"%s\" randomized.\n"), canon);
890*7f2fe78bSCy Schubert     } else {
891*7f2fe78bSCy Schubert         unsigned int i = sizeof (newpw) - 1;
892*7f2fe78bSCy Schubert 
893*7f2fe78bSCy Schubert         snprintf(prompt1, sizeof(prompt1),
894*7f2fe78bSCy Schubert                  _("Enter password for principal \"%s\""), canon);
895*7f2fe78bSCy Schubert         snprintf(prompt2, sizeof(prompt2),
896*7f2fe78bSCy Schubert                  _("Re-enter password for principal \"%s\""), canon);
897*7f2fe78bSCy Schubert         retval = krb5_read_password(context, prompt1, prompt2,
898*7f2fe78bSCy Schubert                                     newpw, &i);
899*7f2fe78bSCy Schubert         if (retval) {
900*7f2fe78bSCy Schubert             com_err("change_password", retval,
901*7f2fe78bSCy Schubert                     _("while reading password for \"%s\"."), canon);
902*7f2fe78bSCy Schubert             goto cleanup;
903*7f2fe78bSCy Schubert         }
904*7f2fe78bSCy Schubert         if (keepold || ks_tuple != NULL) {
905*7f2fe78bSCy Schubert             retval = kadm5_chpass_principal_3(handle, princ, keepold,
906*7f2fe78bSCy Schubert                                               n_ks_tuple, ks_tuple,
907*7f2fe78bSCy Schubert                                               newpw);
908*7f2fe78bSCy Schubert         } else {
909*7f2fe78bSCy Schubert             retval = kadm5_chpass_principal(handle, princ, newpw);
910*7f2fe78bSCy Schubert         }
911*7f2fe78bSCy Schubert         memset(newpw, 0, sizeof (newpw));
912*7f2fe78bSCy Schubert         if (retval) {
913*7f2fe78bSCy Schubert             com_err("change_password", retval,
914*7f2fe78bSCy Schubert                     _("while changing password for \"%s\"."), canon);
915*7f2fe78bSCy Schubert             goto cleanup;
916*7f2fe78bSCy Schubert         }
917*7f2fe78bSCy Schubert         info(_("Password for \"%s\" changed.\n"), canon);
918*7f2fe78bSCy Schubert     }
919*7f2fe78bSCy Schubert cleanup:
920*7f2fe78bSCy Schubert     free(canon);
921*7f2fe78bSCy Schubert     free(db_args);
922*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
923*7f2fe78bSCy Schubert     free(ks_tuple);
924*7f2fe78bSCy Schubert }
925*7f2fe78bSCy Schubert 
926*7f2fe78bSCy Schubert static void
kadmin_free_tl_data(krb5_int16 * n_tl_datap,krb5_tl_data ** tl_datap)927*7f2fe78bSCy Schubert kadmin_free_tl_data(krb5_int16 *n_tl_datap, krb5_tl_data **tl_datap)
928*7f2fe78bSCy Schubert {
929*7f2fe78bSCy Schubert     krb5_tl_data *tl_data = *tl_datap, *next;
930*7f2fe78bSCy Schubert     int n_tl_data = *n_tl_datap;
931*7f2fe78bSCy Schubert     int i;
932*7f2fe78bSCy Schubert 
933*7f2fe78bSCy Schubert     *n_tl_datap = 0;
934*7f2fe78bSCy Schubert     *tl_datap = NULL;
935*7f2fe78bSCy Schubert 
936*7f2fe78bSCy Schubert     for (i = 0; tl_data && (i < n_tl_data); i++) {
937*7f2fe78bSCy Schubert         next = tl_data->tl_data_next;
938*7f2fe78bSCy Schubert         free(tl_data->tl_data_contents);
939*7f2fe78bSCy Schubert         free(tl_data);
940*7f2fe78bSCy Schubert         tl_data = next;
941*7f2fe78bSCy Schubert     }
942*7f2fe78bSCy Schubert }
943*7f2fe78bSCy Schubert 
944*7f2fe78bSCy Schubert /* Construct a tl_data element and add it to the tail of *tl_datap. */
945*7f2fe78bSCy Schubert static void
add_tl_data(krb5_int16 * n_tl_datap,krb5_tl_data ** tl_datap,krb5_int16 tl_type,krb5_ui_2 len,krb5_octet * contents)946*7f2fe78bSCy Schubert add_tl_data(krb5_int16 *n_tl_datap, krb5_tl_data **tl_datap,
947*7f2fe78bSCy Schubert             krb5_int16 tl_type, krb5_ui_2 len, krb5_octet *contents)
948*7f2fe78bSCy Schubert {
949*7f2fe78bSCy Schubert     krb5_tl_data *tl_data;
950*7f2fe78bSCy Schubert     krb5_octet *copy;
951*7f2fe78bSCy Schubert 
952*7f2fe78bSCy Schubert     copy = malloc(len);
953*7f2fe78bSCy Schubert     tl_data = calloc(1, sizeof(*tl_data));
954*7f2fe78bSCy Schubert     if (copy == NULL || tl_data == NULL) {
955*7f2fe78bSCy Schubert         error(_("Not enough memory\n"));
956*7f2fe78bSCy Schubert         exit(1);
957*7f2fe78bSCy Schubert     }
958*7f2fe78bSCy Schubert     memcpy(copy, contents, len);
959*7f2fe78bSCy Schubert 
960*7f2fe78bSCy Schubert     tl_data->tl_data_type = tl_type;
961*7f2fe78bSCy Schubert     tl_data->tl_data_length = len;
962*7f2fe78bSCy Schubert     tl_data->tl_data_contents = copy;
963*7f2fe78bSCy Schubert     tl_data->tl_data_next = NULL;
964*7f2fe78bSCy Schubert 
965*7f2fe78bSCy Schubert     for (; *tl_datap != NULL; tl_datap = &(*tl_datap)->tl_data_next);
966*7f2fe78bSCy Schubert     *tl_datap = tl_data;
967*7f2fe78bSCy Schubert     (*n_tl_datap)++;
968*7f2fe78bSCy Schubert }
969*7f2fe78bSCy Schubert 
970*7f2fe78bSCy Schubert static void
unlock_princ(kadm5_principal_ent_t princ,long * mask,const char * caller)971*7f2fe78bSCy Schubert unlock_princ(kadm5_principal_ent_t princ, long *mask, const char *caller)
972*7f2fe78bSCy Schubert {
973*7f2fe78bSCy Schubert     krb5_error_code retval;
974*7f2fe78bSCy Schubert     krb5_timestamp now;
975*7f2fe78bSCy Schubert     krb5_octet timebuf[4];
976*7f2fe78bSCy Schubert 
977*7f2fe78bSCy Schubert     /* Zero out the failed auth count. */
978*7f2fe78bSCy Schubert     princ->fail_auth_count = 0;
979*7f2fe78bSCy Schubert     *mask |= KADM5_FAIL_AUTH_COUNT;
980*7f2fe78bSCy Schubert 
981*7f2fe78bSCy Schubert     /* Record the timestamp of this unlock operation so that replica KDCs will
982*7f2fe78bSCy Schubert      * see it, since fail_auth_count is unreplicated. */
983*7f2fe78bSCy Schubert     retval = krb5_timeofday(context, &now);
984*7f2fe78bSCy Schubert     if (retval) {
985*7f2fe78bSCy Schubert         com_err(caller, retval, _("while getting time"));
986*7f2fe78bSCy Schubert         exit(1);
987*7f2fe78bSCy Schubert     }
988*7f2fe78bSCy Schubert     store_32_le((krb5_int32)now, timebuf);
989*7f2fe78bSCy Schubert     add_tl_data(&princ->n_tl_data, &princ->tl_data,
990*7f2fe78bSCy Schubert                 KRB5_TL_LAST_ADMIN_UNLOCK, 4, timebuf);
991*7f2fe78bSCy Schubert     *mask |= KADM5_TL_DATA;
992*7f2fe78bSCy Schubert }
993*7f2fe78bSCy Schubert 
994*7f2fe78bSCy Schubert /*
995*7f2fe78bSCy Schubert  * Parse addprinc or modprinc arguments.  Some output fields may be
996*7f2fe78bSCy Schubert  * filled in on error.
997*7f2fe78bSCy Schubert  */
998*7f2fe78bSCy Schubert static int
kadmin_parse_princ_args(int argc,char * argv[],kadm5_principal_ent_t oprinc,long * mask,char ** pass,krb5_boolean * randkey,krb5_boolean * nokey,krb5_key_salt_tuple ** ks_tuple,int * n_ks_tuple,char * caller)999*7f2fe78bSCy Schubert kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc,
1000*7f2fe78bSCy Schubert                         long *mask, char **pass, krb5_boolean *randkey,
1001*7f2fe78bSCy Schubert                         krb5_boolean *nokey, krb5_key_salt_tuple **ks_tuple,
1002*7f2fe78bSCy Schubert                         int *n_ks_tuple, char *caller)
1003*7f2fe78bSCy Schubert {
1004*7f2fe78bSCy Schubert     int i;
1005*7f2fe78bSCy Schubert     time_t now, date, interval;
1006*7f2fe78bSCy Schubert     krb5_error_code retval;
1007*7f2fe78bSCy Schubert 
1008*7f2fe78bSCy Schubert     *mask = 0;
1009*7f2fe78bSCy Schubert     *pass = NULL;
1010*7f2fe78bSCy Schubert     *n_ks_tuple = 0;
1011*7f2fe78bSCy Schubert     *ks_tuple = NULL;
1012*7f2fe78bSCy Schubert     time(&now);
1013*7f2fe78bSCy Schubert     *randkey = FALSE;
1014*7f2fe78bSCy Schubert     *nokey = FALSE;
1015*7f2fe78bSCy Schubert     for (i = 1; i < argc - 1; i++) {
1016*7f2fe78bSCy Schubert         if (!strcmp("-x",argv[i])) {
1017*7f2fe78bSCy Schubert             if (++i > argc - 2)
1018*7f2fe78bSCy Schubert                 return -1;
1019*7f2fe78bSCy Schubert 
1020*7f2fe78bSCy Schubert             add_tl_data(&oprinc->n_tl_data, &oprinc->tl_data,
1021*7f2fe78bSCy Schubert                         KRB5_TL_DB_ARGS, strlen(argv[i]) + 1,
1022*7f2fe78bSCy Schubert                         (krb5_octet *)argv[i]);
1023*7f2fe78bSCy Schubert             *mask |= KADM5_TL_DATA;
1024*7f2fe78bSCy Schubert             continue;
1025*7f2fe78bSCy Schubert         }
1026*7f2fe78bSCy Schubert         if (!strcmp("-expire", argv[i])) {
1027*7f2fe78bSCy Schubert             if (++i > argc - 2)
1028*7f2fe78bSCy Schubert                 return -1;
1029*7f2fe78bSCy Schubert             date = parse_date(argv[i], now);
1030*7f2fe78bSCy Schubert             if (date == (time_t)-1)
1031*7f2fe78bSCy Schubert                 return -1;
1032*7f2fe78bSCy Schubert             oprinc->princ_expire_time = date;
1033*7f2fe78bSCy Schubert             *mask |= KADM5_PRINC_EXPIRE_TIME;
1034*7f2fe78bSCy Schubert             continue;
1035*7f2fe78bSCy Schubert         }
1036*7f2fe78bSCy Schubert         if (!strcmp("-pwexpire", argv[i])) {
1037*7f2fe78bSCy Schubert             if (++i > argc - 2)
1038*7f2fe78bSCy Schubert                 return -1;
1039*7f2fe78bSCy Schubert             date = parse_date(argv[i], now);
1040*7f2fe78bSCy Schubert             if (date == (time_t)-1)
1041*7f2fe78bSCy Schubert                 return -1;
1042*7f2fe78bSCy Schubert             oprinc->pw_expiration = date;
1043*7f2fe78bSCy Schubert             *mask |= KADM5_PW_EXPIRATION;
1044*7f2fe78bSCy Schubert             continue;
1045*7f2fe78bSCy Schubert         }
1046*7f2fe78bSCy Schubert         if (!strcmp("-maxlife", argv[i])) {
1047*7f2fe78bSCy Schubert             if (++i > argc - 2)
1048*7f2fe78bSCy Schubert                 return -1;
1049*7f2fe78bSCy Schubert             interval = parse_interval(argv[i], now);
1050*7f2fe78bSCy Schubert             if (interval == (time_t)-1)
1051*7f2fe78bSCy Schubert                 return -1;
1052*7f2fe78bSCy Schubert             oprinc->max_life = interval;
1053*7f2fe78bSCy Schubert             *mask |= KADM5_MAX_LIFE;
1054*7f2fe78bSCy Schubert             continue;
1055*7f2fe78bSCy Schubert         }
1056*7f2fe78bSCy Schubert         if (!strcmp("-maxrenewlife", argv[i])) {
1057*7f2fe78bSCy Schubert             if (++i > argc - 2)
1058*7f2fe78bSCy Schubert                 return -1;
1059*7f2fe78bSCy Schubert             interval = parse_interval(argv[i], now);
1060*7f2fe78bSCy Schubert             if (interval == (time_t)-1)
1061*7f2fe78bSCy Schubert                 return -1;
1062*7f2fe78bSCy Schubert             oprinc->max_renewable_life = interval;
1063*7f2fe78bSCy Schubert             *mask |= KADM5_MAX_RLIFE;
1064*7f2fe78bSCy Schubert             continue;
1065*7f2fe78bSCy Schubert         }
1066*7f2fe78bSCy Schubert         if (!strcmp("-kvno", argv[i])) {
1067*7f2fe78bSCy Schubert             if (++i > argc - 2)
1068*7f2fe78bSCy Schubert                 return -1;
1069*7f2fe78bSCy Schubert             oprinc->kvno = atoi(argv[i]);
1070*7f2fe78bSCy Schubert             *mask |= KADM5_KVNO;
1071*7f2fe78bSCy Schubert             continue;
1072*7f2fe78bSCy Schubert         }
1073*7f2fe78bSCy Schubert         if (!strcmp("-policy", argv[i])) {
1074*7f2fe78bSCy Schubert             if (++i > argc - 2)
1075*7f2fe78bSCy Schubert                 return -1;
1076*7f2fe78bSCy Schubert             oprinc->policy = argv[i];
1077*7f2fe78bSCy Schubert             *mask |= KADM5_POLICY;
1078*7f2fe78bSCy Schubert             continue;
1079*7f2fe78bSCy Schubert         }
1080*7f2fe78bSCy Schubert         if (!strcmp("-clearpolicy", argv[i])) {
1081*7f2fe78bSCy Schubert             oprinc->policy = NULL;
1082*7f2fe78bSCy Schubert             *mask |= KADM5_POLICY_CLR;
1083*7f2fe78bSCy Schubert             continue;
1084*7f2fe78bSCy Schubert         }
1085*7f2fe78bSCy Schubert         if (!strcmp("-pw", argv[i])) {
1086*7f2fe78bSCy Schubert             if (++i > argc - 2)
1087*7f2fe78bSCy Schubert                 return -1;
1088*7f2fe78bSCy Schubert             *pass = argv[i];
1089*7f2fe78bSCy Schubert             continue;
1090*7f2fe78bSCy Schubert         }
1091*7f2fe78bSCy Schubert         if (!strcmp("-randkey", argv[i])) {
1092*7f2fe78bSCy Schubert             *randkey = TRUE;
1093*7f2fe78bSCy Schubert             continue;
1094*7f2fe78bSCy Schubert         }
1095*7f2fe78bSCy Schubert         if (!strcmp("-nokey", argv[i])) {
1096*7f2fe78bSCy Schubert             *nokey = TRUE;
1097*7f2fe78bSCy Schubert             continue;
1098*7f2fe78bSCy Schubert         }
1099*7f2fe78bSCy Schubert         if (!strcmp("-unlock", argv[i])) {
1100*7f2fe78bSCy Schubert             unlock_princ(oprinc, mask, caller);
1101*7f2fe78bSCy Schubert             continue;
1102*7f2fe78bSCy Schubert         }
1103*7f2fe78bSCy Schubert         if (!strcmp("-e", argv[i])) {
1104*7f2fe78bSCy Schubert             if (++i > argc - 2)
1105*7f2fe78bSCy Schubert                 return -1;
1106*7f2fe78bSCy Schubert             retval = krb5_string_to_keysalts(argv[i], NULL, NULL, 0,
1107*7f2fe78bSCy Schubert                                              ks_tuple, n_ks_tuple);
1108*7f2fe78bSCy Schubert             if (retval) {
1109*7f2fe78bSCy Schubert                 com_err(caller, retval, _("while parsing keysalts %s"),
1110*7f2fe78bSCy Schubert                         argv[i]);
1111*7f2fe78bSCy Schubert                 return -1;
1112*7f2fe78bSCy Schubert             }
1113*7f2fe78bSCy Schubert             continue;
1114*7f2fe78bSCy Schubert         }
1115*7f2fe78bSCy Schubert         retval = krb5_flagspec_to_mask(argv[i], &oprinc->attributes,
1116*7f2fe78bSCy Schubert                                        &oprinc->attributes);
1117*7f2fe78bSCy Schubert         if (retval)
1118*7f2fe78bSCy Schubert             return -1;
1119*7f2fe78bSCy Schubert         else
1120*7f2fe78bSCy Schubert             *mask |= KADM5_ATTRIBUTES;
1121*7f2fe78bSCy Schubert     }
1122*7f2fe78bSCy Schubert     if (i != argc - 1)
1123*7f2fe78bSCy Schubert         return -1;
1124*7f2fe78bSCy Schubert     retval = kadmin_parse_name(argv[i], &oprinc->principal);
1125*7f2fe78bSCy Schubert     if (retval) {
1126*7f2fe78bSCy Schubert         com_err(caller, retval, _("while parsing principal"));
1127*7f2fe78bSCy Schubert         return -1;
1128*7f2fe78bSCy Schubert     }
1129*7f2fe78bSCy Schubert     return 0;
1130*7f2fe78bSCy Schubert }
1131*7f2fe78bSCy Schubert 
1132*7f2fe78bSCy Schubert static void
kadmin_addprinc_usage()1133*7f2fe78bSCy Schubert kadmin_addprinc_usage()
1134*7f2fe78bSCy Schubert {
1135*7f2fe78bSCy Schubert     error(_("usage: add_principal [options] principal\n"));
1136*7f2fe78bSCy Schubert     error(_("\toptions are:\n"));
1137*7f2fe78bSCy Schubert     error(_("\t\t[-randkey|-nokey] [-x db_princ_args]* [-expire expdate] "
1138*7f2fe78bSCy Schubert             "[-pwexpire pwexpdate] [-maxlife maxtixlife]\n"
1139*7f2fe78bSCy Schubert             "\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n"
1140*7f2fe78bSCy Schubert             "\t\t[-pw password] [-maxrenewlife maxrenewlife]\n"
1141*7f2fe78bSCy Schubert             "\t\t[-e keysaltlist]\n\t\t[{+|-}attribute]\n"));
1142*7f2fe78bSCy Schubert     error(_("\tattributes are:\n"));
1143*7f2fe78bSCy Schubert     error(_("\t\tallow_postdated allow_forwardable allow_tgs_req "
1144*7f2fe78bSCy Schubert             "allow_renewable\n"
1145*7f2fe78bSCy Schubert             "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n"
1146*7f2fe78bSCy Schubert             "\t\trequires_hwauth needchange allow_svr "
1147*7f2fe78bSCy Schubert             "password_changing_service\n"
1148*7f2fe78bSCy Schubert             "\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n"
1149*7f2fe78bSCy Schubert             "\t\tlockdown_keys\n"
1150*7f2fe78bSCy Schubert             "\nwhere,\n\t[-x db_princ_args]* - any number of database "
1151*7f2fe78bSCy Schubert             "specific arguments.\n"
1152*7f2fe78bSCy Schubert             "\t\t\tLook at each database documentation for supported "
1153*7f2fe78bSCy Schubert             "arguments\n"));
1154*7f2fe78bSCy Schubert }
1155*7f2fe78bSCy Schubert 
1156*7f2fe78bSCy Schubert static void
kadmin_modprinc_usage()1157*7f2fe78bSCy Schubert kadmin_modprinc_usage()
1158*7f2fe78bSCy Schubert {
1159*7f2fe78bSCy Schubert     error(_("usage: modify_principal [options] principal\n"));
1160*7f2fe78bSCy Schubert     error(_("\toptions are:\n"));
1161*7f2fe78bSCy Schubert     error(_("\t\t[-x db_princ_args]* [-expire expdate] "
1162*7f2fe78bSCy Schubert             "[-pwexpire pwexpdate] [-maxlife maxtixlife]\n"
1163*7f2fe78bSCy Schubert             "\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n"
1164*7f2fe78bSCy Schubert             "\t\t[-maxrenewlife maxrenewlife] [-unlock] [{+|-}attribute]\n"));
1165*7f2fe78bSCy Schubert     error(_("\tattributes are:\n"));
1166*7f2fe78bSCy Schubert     error(_("\t\tallow_postdated allow_forwardable allow_tgs_req "
1167*7f2fe78bSCy Schubert             "allow_renewable\n"
1168*7f2fe78bSCy Schubert             "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n"
1169*7f2fe78bSCy Schubert             "\t\trequires_hwauth needchange allow_svr "
1170*7f2fe78bSCy Schubert             "password_changing_service\n"
1171*7f2fe78bSCy Schubert             "\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n"
1172*7f2fe78bSCy Schubert             "\t\tlockdown_keys\n"
1173*7f2fe78bSCy Schubert             "\nwhere,\n\t[-x db_princ_args]* - any number of database "
1174*7f2fe78bSCy Schubert             "specific arguments.\n"
1175*7f2fe78bSCy Schubert             "\t\t\tLook at each database documentation for supported "
1176*7f2fe78bSCy Schubert             "arguments\n"));
1177*7f2fe78bSCy Schubert }
1178*7f2fe78bSCy Schubert 
1179*7f2fe78bSCy Schubert /* Create a dummy password for old-style (pre-1.8) randkey creation. */
1180*7f2fe78bSCy Schubert static void
prepare_dummy_password(char * buf,size_t sz)1181*7f2fe78bSCy Schubert prepare_dummy_password(char *buf, size_t sz)
1182*7f2fe78bSCy Schubert {
1183*7f2fe78bSCy Schubert     size_t i;
1184*7f2fe78bSCy Schubert 
1185*7f2fe78bSCy Schubert     /* Must try to pass any password policy in place, and be valid UTF-8. */
1186*7f2fe78bSCy Schubert     strlcpy(buf, "6F a[", sz);
1187*7f2fe78bSCy Schubert     for (i = strlen(buf); i < sz - 1; i++)
1188*7f2fe78bSCy Schubert         buf[i] = 'a' + (i % 26);
1189*7f2fe78bSCy Schubert     buf[sz - 1] = '\0';
1190*7f2fe78bSCy Schubert }
1191*7f2fe78bSCy Schubert 
1192*7f2fe78bSCy Schubert void
kadmin_addprinc(int argc,char * argv[])1193*7f2fe78bSCy Schubert kadmin_addprinc(int argc, char *argv[])
1194*7f2fe78bSCy Schubert {
1195*7f2fe78bSCy Schubert     kadm5_principal_ent_rec princ;
1196*7f2fe78bSCy Schubert     long mask;
1197*7f2fe78bSCy Schubert     krb5_boolean randkey = FALSE, nokey = FALSE, old_style_randkey = FALSE;
1198*7f2fe78bSCy Schubert     int n_ks_tuple;
1199*7f2fe78bSCy Schubert     krb5_key_salt_tuple *ks_tuple = NULL;
1200*7f2fe78bSCy Schubert     char *pass, *canon = NULL;
1201*7f2fe78bSCy Schubert     krb5_error_code retval;
1202*7f2fe78bSCy Schubert     char newpw[1024], dummybuf[256];
1203*7f2fe78bSCy Schubert     static char prompt1[1024], prompt2[1024];
1204*7f2fe78bSCy Schubert 
1205*7f2fe78bSCy Schubert     /* Zero all fields in request structure */
1206*7f2fe78bSCy Schubert     memset(&princ, 0, sizeof(princ));
1207*7f2fe78bSCy Schubert 
1208*7f2fe78bSCy Schubert     princ.attributes = 0;
1209*7f2fe78bSCy Schubert     if (kadmin_parse_princ_args(argc, argv, &princ, &mask, &pass, &randkey,
1210*7f2fe78bSCy Schubert                                 &nokey, &ks_tuple, &n_ks_tuple,
1211*7f2fe78bSCy Schubert                                 "add_principal")) {
1212*7f2fe78bSCy Schubert         kadmin_addprinc_usage();
1213*7f2fe78bSCy Schubert         goto cleanup;
1214*7f2fe78bSCy Schubert     }
1215*7f2fe78bSCy Schubert 
1216*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, princ.principal, &canon);
1217*7f2fe78bSCy Schubert     if (retval) {
1218*7f2fe78bSCy Schubert         com_err("add_principal", retval, _("while canonicalizing principal"));
1219*7f2fe78bSCy Schubert         goto cleanup;
1220*7f2fe78bSCy Schubert     }
1221*7f2fe78bSCy Schubert 
1222*7f2fe78bSCy Schubert     if (mask & KADM5_POLICY) {
1223*7f2fe78bSCy Schubert         /* Warn if the specified policy does not exist. */
1224*7f2fe78bSCy Schubert         if (!script_mode && !policy_exists(princ.policy)) {
1225*7f2fe78bSCy Schubert             fprintf(stderr, _("WARNING: policy \"%s\" does not exist\n"),
1226*7f2fe78bSCy Schubert                     princ.policy);
1227*7f2fe78bSCy Schubert         }
1228*7f2fe78bSCy Schubert     } else if (!(mask & KADM5_POLICY_CLR)) {
1229*7f2fe78bSCy Schubert         /* If the policy "default" exists, assign it. */
1230*7f2fe78bSCy Schubert         if (policy_exists("default")) {
1231*7f2fe78bSCy Schubert             if (!script_mode) {
1232*7f2fe78bSCy Schubert                 fprintf(stderr, _("No policy specified for %s; "
1233*7f2fe78bSCy Schubert                                   "assigning \"default\"\n"), canon);
1234*7f2fe78bSCy Schubert             }
1235*7f2fe78bSCy Schubert             princ.policy = "default";
1236*7f2fe78bSCy Schubert             mask |= KADM5_POLICY;
1237*7f2fe78bSCy Schubert         } else if (!script_mode) {
1238*7f2fe78bSCy Schubert             fprintf(stderr, _("No policy specified for %s; "
1239*7f2fe78bSCy Schubert                               "defaulting to no policy\n"), canon);
1240*7f2fe78bSCy Schubert         }
1241*7f2fe78bSCy Schubert     }
1242*7f2fe78bSCy Schubert     /* Don't send KADM5_POLICY_CLR to the server. */
1243*7f2fe78bSCy Schubert     mask &= ~KADM5_POLICY_CLR;
1244*7f2fe78bSCy Schubert 
1245*7f2fe78bSCy Schubert     if (nokey) {
1246*7f2fe78bSCy Schubert         pass = NULL;
1247*7f2fe78bSCy Schubert         mask |= KADM5_KEY_DATA;
1248*7f2fe78bSCy Schubert     } else if (randkey) {
1249*7f2fe78bSCy Schubert         pass = NULL;
1250*7f2fe78bSCy Schubert     } else if (pass == NULL) {
1251*7f2fe78bSCy Schubert         unsigned int sz = sizeof(newpw) - 1;
1252*7f2fe78bSCy Schubert 
1253*7f2fe78bSCy Schubert         snprintf(prompt1, sizeof(prompt1),
1254*7f2fe78bSCy Schubert                  _("Enter password for principal \"%s\""), canon);
1255*7f2fe78bSCy Schubert         snprintf(prompt2, sizeof(prompt2),
1256*7f2fe78bSCy Schubert                  _("Re-enter password for principal \"%s\""), canon);
1257*7f2fe78bSCy Schubert         retval = krb5_read_password(context, prompt1, prompt2, newpw, &sz);
1258*7f2fe78bSCy Schubert         if (retval) {
1259*7f2fe78bSCy Schubert             com_err("add_principal", retval,
1260*7f2fe78bSCy Schubert                     _("while reading password for \"%s\"."), canon);
1261*7f2fe78bSCy Schubert             goto cleanup;
1262*7f2fe78bSCy Schubert         }
1263*7f2fe78bSCy Schubert         pass = newpw;
1264*7f2fe78bSCy Schubert     }
1265*7f2fe78bSCy Schubert     mask |= KADM5_PRINCIPAL;
1266*7f2fe78bSCy Schubert     retval = create_princ(&princ, mask, n_ks_tuple, ks_tuple, pass);
1267*7f2fe78bSCy Schubert     if (retval == EINVAL && randkey) {
1268*7f2fe78bSCy Schubert         /*
1269*7f2fe78bSCy Schubert          * The server doesn't support randkey creation.  Create the principal
1270*7f2fe78bSCy Schubert          * with a dummy password and disallow tickets.
1271*7f2fe78bSCy Schubert          */
1272*7f2fe78bSCy Schubert         prepare_dummy_password(dummybuf, sizeof(dummybuf));
1273*7f2fe78bSCy Schubert         princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
1274*7f2fe78bSCy Schubert         mask |= KADM5_ATTRIBUTES;
1275*7f2fe78bSCy Schubert         pass = dummybuf;
1276*7f2fe78bSCy Schubert         retval = create_princ(&princ, mask, n_ks_tuple, ks_tuple, pass);
1277*7f2fe78bSCy Schubert         old_style_randkey = 1;
1278*7f2fe78bSCy Schubert     }
1279*7f2fe78bSCy Schubert     if (retval == KADM5_BAD_MASK && nokey) {
1280*7f2fe78bSCy Schubert         error(_("Admin server does not support -nokey while creating "
1281*7f2fe78bSCy Schubert                 "\"%s\"\n"), canon);
1282*7f2fe78bSCy Schubert         goto cleanup;
1283*7f2fe78bSCy Schubert     }
1284*7f2fe78bSCy Schubert     if (retval) {
1285*7f2fe78bSCy Schubert         com_err("add_principal", retval, "while creating \"%s\".", canon);
1286*7f2fe78bSCy Schubert         goto cleanup;
1287*7f2fe78bSCy Schubert     }
1288*7f2fe78bSCy Schubert     if (old_style_randkey) {
1289*7f2fe78bSCy Schubert         /* Randomize the password and re-enable tickets. */
1290*7f2fe78bSCy Schubert         retval = randkey_princ(handle, princ.principal, FALSE, n_ks_tuple,
1291*7f2fe78bSCy Schubert                                ks_tuple, NULL, NULL);
1292*7f2fe78bSCy Schubert         if (retval) {
1293*7f2fe78bSCy Schubert             com_err("add_principal", retval,
1294*7f2fe78bSCy Schubert                     _("while randomizing key for \"%s\"."), canon);
1295*7f2fe78bSCy Schubert             goto cleanup;
1296*7f2fe78bSCy Schubert         }
1297*7f2fe78bSCy Schubert         princ.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; /* clear notix */
1298*7f2fe78bSCy Schubert         mask = KADM5_ATTRIBUTES;
1299*7f2fe78bSCy Schubert         retval = kadm5_modify_principal(handle, &princ, mask);
1300*7f2fe78bSCy Schubert         if (retval) {
1301*7f2fe78bSCy Schubert             com_err("add_principal", retval,
1302*7f2fe78bSCy Schubert                     _("while clearing DISALLOW_ALL_TIX for \"%s\"."), canon);
1303*7f2fe78bSCy Schubert             goto cleanup;
1304*7f2fe78bSCy Schubert         }
1305*7f2fe78bSCy Schubert     }
1306*7f2fe78bSCy Schubert     info("Principal \"%s\" created.\n", canon);
1307*7f2fe78bSCy Schubert 
1308*7f2fe78bSCy Schubert cleanup:
1309*7f2fe78bSCy Schubert     krb5_free_principal(context, princ.principal);
1310*7f2fe78bSCy Schubert     free(ks_tuple);
1311*7f2fe78bSCy Schubert     free(canon);
1312*7f2fe78bSCy Schubert     kadmin_free_tl_data(&princ.n_tl_data, &princ.tl_data);
1313*7f2fe78bSCy Schubert }
1314*7f2fe78bSCy Schubert 
1315*7f2fe78bSCy Schubert void
kadmin_modprinc(int argc,char * argv[])1316*7f2fe78bSCy Schubert kadmin_modprinc(int argc, char *argv[])
1317*7f2fe78bSCy Schubert {
1318*7f2fe78bSCy Schubert     kadm5_principal_ent_rec princ, oldprinc;
1319*7f2fe78bSCy Schubert     krb5_principal kprinc = NULL;
1320*7f2fe78bSCy Schubert     long mask;
1321*7f2fe78bSCy Schubert     krb5_error_code retval;
1322*7f2fe78bSCy Schubert     char *pass, *canon = NULL;
1323*7f2fe78bSCy Schubert     krb5_boolean randkey = FALSE, nokey = FALSE;
1324*7f2fe78bSCy Schubert     int n_ks_tuple = 0;
1325*7f2fe78bSCy Schubert     krb5_key_salt_tuple *ks_tuple = NULL;
1326*7f2fe78bSCy Schubert 
1327*7f2fe78bSCy Schubert     if (argc < 2) {
1328*7f2fe78bSCy Schubert         kadmin_modprinc_usage();
1329*7f2fe78bSCy Schubert         return;
1330*7f2fe78bSCy Schubert     }
1331*7f2fe78bSCy Schubert 
1332*7f2fe78bSCy Schubert     memset(&oldprinc, 0, sizeof(oldprinc));
1333*7f2fe78bSCy Schubert     memset(&princ, 0, sizeof(princ));
1334*7f2fe78bSCy Schubert 
1335*7f2fe78bSCy Schubert     retval = kadmin_parse_name(argv[argc - 1], &kprinc);
1336*7f2fe78bSCy Schubert     if (retval) {
1337*7f2fe78bSCy Schubert         com_err("modify_principal", retval, _("while parsing principal"));
1338*7f2fe78bSCy Schubert         return;
1339*7f2fe78bSCy Schubert     }
1340*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, kprinc, &canon);
1341*7f2fe78bSCy Schubert     if (retval) {
1342*7f2fe78bSCy Schubert         com_err("modify_principal", retval,
1343*7f2fe78bSCy Schubert                 _("while canonicalizing principal"));
1344*7f2fe78bSCy Schubert         goto cleanup;
1345*7f2fe78bSCy Schubert     }
1346*7f2fe78bSCy Schubert     retval = kadm5_get_principal(handle, kprinc, &oldprinc,
1347*7f2fe78bSCy Schubert                                  KADM5_PRINCIPAL_NORMAL_MASK);
1348*7f2fe78bSCy Schubert     if (retval) {
1349*7f2fe78bSCy Schubert         com_err("modify_principal", retval, _("while getting \"%s\"."), canon);
1350*7f2fe78bSCy Schubert         goto cleanup;
1351*7f2fe78bSCy Schubert     }
1352*7f2fe78bSCy Schubert     princ.attributes = oldprinc.attributes;
1353*7f2fe78bSCy Schubert     kadm5_free_principal_ent(handle, &oldprinc);
1354*7f2fe78bSCy Schubert     retval = kadmin_parse_princ_args(argc, argv,
1355*7f2fe78bSCy Schubert                                      &princ, &mask,
1356*7f2fe78bSCy Schubert                                      &pass, &randkey, &nokey,
1357*7f2fe78bSCy Schubert                                      &ks_tuple, &n_ks_tuple,
1358*7f2fe78bSCy Schubert                                      "modify_principal");
1359*7f2fe78bSCy Schubert     if (retval || ks_tuple != NULL || randkey || nokey || pass) {
1360*7f2fe78bSCy Schubert         kadmin_modprinc_usage();
1361*7f2fe78bSCy Schubert         goto cleanup;
1362*7f2fe78bSCy Schubert     }
1363*7f2fe78bSCy Schubert     if (mask & KADM5_POLICY) {
1364*7f2fe78bSCy Schubert         /* Warn if the specified policy does not exist. */
1365*7f2fe78bSCy Schubert         if (!script_mode && !policy_exists(princ.policy)) {
1366*7f2fe78bSCy Schubert             fprintf(stderr, _("WARNING: policy \"%s\" does not exist\n"),
1367*7f2fe78bSCy Schubert                     princ.policy);
1368*7f2fe78bSCy Schubert         }
1369*7f2fe78bSCy Schubert     }
1370*7f2fe78bSCy Schubert     if (mask) {
1371*7f2fe78bSCy Schubert         /* Skip this if all we're doing is setting certhash. */
1372*7f2fe78bSCy Schubert         retval = kadm5_modify_principal(handle, &princ, mask);
1373*7f2fe78bSCy Schubert     }
1374*7f2fe78bSCy Schubert     if (retval) {
1375*7f2fe78bSCy Schubert         com_err("modify_principal", retval, _("while modifying \"%s\"."),
1376*7f2fe78bSCy Schubert                 canon);
1377*7f2fe78bSCy Schubert         goto cleanup;
1378*7f2fe78bSCy Schubert     }
1379*7f2fe78bSCy Schubert     info(_("Principal \"%s\" modified.\n"), canon);
1380*7f2fe78bSCy Schubert cleanup:
1381*7f2fe78bSCy Schubert     krb5_free_principal(context, kprinc);
1382*7f2fe78bSCy Schubert     krb5_free_principal(context, princ.principal);
1383*7f2fe78bSCy Schubert     kadmin_free_tl_data(&princ.n_tl_data, &princ.tl_data);
1384*7f2fe78bSCy Schubert     free(canon);
1385*7f2fe78bSCy Schubert     free(ks_tuple);
1386*7f2fe78bSCy Schubert }
1387*7f2fe78bSCy Schubert 
1388*7f2fe78bSCy Schubert void
kadmin_getprinc(int argc,char * argv[])1389*7f2fe78bSCy Schubert kadmin_getprinc(int argc, char *argv[])
1390*7f2fe78bSCy Schubert {
1391*7f2fe78bSCy Schubert     kadm5_principal_ent_rec dprinc;
1392*7f2fe78bSCy Schubert     krb5_principal princ = NULL;
1393*7f2fe78bSCy Schubert     krb5_error_code retval;
1394*7f2fe78bSCy Schubert     const char *polname, *noexist;
1395*7f2fe78bSCy Schubert     char *canon = NULL, *princstr = NULL, *modprincstr = NULL;
1396*7f2fe78bSCy Schubert     char **sp = NULL, **attrstrs = NULL;
1397*7f2fe78bSCy Schubert     int i;
1398*7f2fe78bSCy Schubert 
1399*7f2fe78bSCy Schubert     if (!(argc == 2 || (argc == 3 && !strcmp("-terse", argv[1])))) {
1400*7f2fe78bSCy Schubert         error(_("usage: get_principal [-terse] principal\n"));
1401*7f2fe78bSCy Schubert         return;
1402*7f2fe78bSCy Schubert     }
1403*7f2fe78bSCy Schubert 
1404*7f2fe78bSCy Schubert     memset(&dprinc, 0, sizeof(dprinc));
1405*7f2fe78bSCy Schubert 
1406*7f2fe78bSCy Schubert     retval = kadmin_parse_name(argv[argc - 1], &princ);
1407*7f2fe78bSCy Schubert     if (retval) {
1408*7f2fe78bSCy Schubert         com_err("get_principal", retval, _("while parsing principal"));
1409*7f2fe78bSCy Schubert         return;
1410*7f2fe78bSCy Schubert     }
1411*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, princ, &canon);
1412*7f2fe78bSCy Schubert     if (retval) {
1413*7f2fe78bSCy Schubert         com_err("get_principal", retval, _("while canonicalizing principal"));
1414*7f2fe78bSCy Schubert         goto cleanup;
1415*7f2fe78bSCy Schubert     }
1416*7f2fe78bSCy Schubert     retval = kadm5_get_principal(handle, princ, &dprinc,
1417*7f2fe78bSCy Schubert                                  KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA);
1418*7f2fe78bSCy Schubert     if (retval) {
1419*7f2fe78bSCy Schubert         com_err("get_principal", retval, _("while retrieving \"%s\"."), canon);
1420*7f2fe78bSCy Schubert         goto cleanup;
1421*7f2fe78bSCy Schubert     }
1422*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, dprinc.principal, &princstr);
1423*7f2fe78bSCy Schubert     if (retval) {
1424*7f2fe78bSCy Schubert         com_err("get_principal", retval, _("while unparsing principal"));
1425*7f2fe78bSCy Schubert         goto cleanup;
1426*7f2fe78bSCy Schubert     }
1427*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, dprinc.mod_name, &modprincstr);
1428*7f2fe78bSCy Schubert     if (retval) {
1429*7f2fe78bSCy Schubert         com_err("get_principal", retval, _("while unparsing principal"));
1430*7f2fe78bSCy Schubert         goto cleanup;
1431*7f2fe78bSCy Schubert     }
1432*7f2fe78bSCy Schubert     if (argc == 2) {
1433*7f2fe78bSCy Schubert         printf(_("Principal: %s\n"), princstr);
1434*7f2fe78bSCy Schubert         printf(_("Expiration date: %s\n"), dprinc.princ_expire_time ?
1435*7f2fe78bSCy Schubert                strdate(dprinc.princ_expire_time) : _("[never]"));
1436*7f2fe78bSCy Schubert         printf(_("Last password change: %s\n"), dprinc.last_pwd_change ?
1437*7f2fe78bSCy Schubert                strdate(dprinc.last_pwd_change) : _("[never]"));
1438*7f2fe78bSCy Schubert         printf(_("Password expiration date: %s\n"),
1439*7f2fe78bSCy Schubert                dprinc.pw_expiration ?
1440*7f2fe78bSCy Schubert                strdate(dprinc.pw_expiration) : _("[never]"));
1441*7f2fe78bSCy Schubert         printf(_("Maximum ticket life: %s\n"), strdur(dprinc.max_life));
1442*7f2fe78bSCy Schubert         printf(_("Maximum renewable life: %s\n"),
1443*7f2fe78bSCy Schubert                strdur(dprinc.max_renewable_life));
1444*7f2fe78bSCy Schubert         printf(_("Last modified: %s (%s)\n"), strdate(dprinc.mod_date),
1445*7f2fe78bSCy Schubert                modprincstr);
1446*7f2fe78bSCy Schubert         printf(_("Last successful authentication: %s\n"),
1447*7f2fe78bSCy Schubert                dprinc.last_success ? strdate(dprinc.last_success) :
1448*7f2fe78bSCy Schubert                _("[never]"));
1449*7f2fe78bSCy Schubert         printf("Last failed authentication: %s\n",
1450*7f2fe78bSCy Schubert                dprinc.last_failed ? strdate(dprinc.last_failed) :
1451*7f2fe78bSCy Schubert                "[never]");
1452*7f2fe78bSCy Schubert         printf(_("Failed password attempts: %d\n"),
1453*7f2fe78bSCy Schubert                dprinc.fail_auth_count);
1454*7f2fe78bSCy Schubert         printf(_("Number of keys: %d\n"), dprinc.n_key_data);
1455*7f2fe78bSCy Schubert         for (i = 0; i < dprinc.n_key_data; i++) {
1456*7f2fe78bSCy Schubert             krb5_key_data *key_data = &dprinc.key_data[i];
1457*7f2fe78bSCy Schubert             char enctype[BUFSIZ], salttype[BUFSIZ];
1458*7f2fe78bSCy Schubert             char *deprecated = "";
1459*7f2fe78bSCy Schubert 
1460*7f2fe78bSCy Schubert             if (krb5_enctype_to_name(key_data->key_data_type[0], FALSE,
1461*7f2fe78bSCy Schubert                                      enctype, sizeof(enctype)))
1462*7f2fe78bSCy Schubert                 snprintf(enctype, sizeof(enctype), _("<Encryption type 0x%x>"),
1463*7f2fe78bSCy Schubert                          key_data->key_data_type[0]);
1464*7f2fe78bSCy Schubert             if (!krb5_c_valid_enctype(key_data->key_data_type[0]))
1465*7f2fe78bSCy Schubert                 deprecated = "UNSUPPORTED:";
1466*7f2fe78bSCy Schubert             else if (krb5int_c_deprecated_enctype(key_data->key_data_type[0]))
1467*7f2fe78bSCy Schubert                 deprecated = "DEPRECATED:";
1468*7f2fe78bSCy Schubert             printf("Key: vno %d, %s%s", key_data->key_data_kvno, deprecated,
1469*7f2fe78bSCy Schubert                    enctype);
1470*7f2fe78bSCy Schubert             if (key_data->key_data_ver > 1 &&
1471*7f2fe78bSCy Schubert                 key_data->key_data_type[1] != KRB5_KDB_SALTTYPE_NORMAL) {
1472*7f2fe78bSCy Schubert                 if (krb5_salttype_to_string(key_data->key_data_type[1],
1473*7f2fe78bSCy Schubert                                             salttype, sizeof(salttype)))
1474*7f2fe78bSCy Schubert                     snprintf(salttype, sizeof(salttype), _("<Salt type 0x%x>"),
1475*7f2fe78bSCy Schubert                              key_data->key_data_type[1]);
1476*7f2fe78bSCy Schubert                 printf(":%s", salttype);
1477*7f2fe78bSCy Schubert             }
1478*7f2fe78bSCy Schubert             printf("\n");
1479*7f2fe78bSCy Schubert         }
1480*7f2fe78bSCy Schubert         printf(_("MKey: vno %d\n"), dprinc.mkvno);
1481*7f2fe78bSCy Schubert 
1482*7f2fe78bSCy Schubert         printf(_("Attributes:"));
1483*7f2fe78bSCy Schubert         retval = krb5_flags_to_strings(dprinc.attributes, &attrstrs);
1484*7f2fe78bSCy Schubert         if (retval) {
1485*7f2fe78bSCy Schubert             com_err("get_principal", retval, _("while printing flags"));
1486*7f2fe78bSCy Schubert             return;
1487*7f2fe78bSCy Schubert         }
1488*7f2fe78bSCy Schubert         for (sp = attrstrs; sp != NULL && *sp != NULL; sp++) {
1489*7f2fe78bSCy Schubert             printf(" %s", *sp);
1490*7f2fe78bSCy Schubert             free(*sp);
1491*7f2fe78bSCy Schubert         }
1492*7f2fe78bSCy Schubert         free(attrstrs);
1493*7f2fe78bSCy Schubert         printf("\n");
1494*7f2fe78bSCy Schubert         polname = (dprinc.policy != NULL) ? dprinc.policy : _("[none]");
1495*7f2fe78bSCy Schubert         noexist = (dprinc.policy != NULL && !policy_exists(dprinc.policy)) ?
1496*7f2fe78bSCy Schubert             _(" [does not exist]") : "";
1497*7f2fe78bSCy Schubert         printf(_("Policy: %s%s\n"), polname, noexist);
1498*7f2fe78bSCy Schubert     } else {
1499*7f2fe78bSCy Schubert         printf("\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\t%d\t%d\t%d\t%d\t\"%s\""
1500*7f2fe78bSCy Schubert                "\t%d\t%d\t%d\t%d\t%d",
1501*7f2fe78bSCy Schubert                princstr, dprinc.princ_expire_time, dprinc.last_pwd_change,
1502*7f2fe78bSCy Schubert                dprinc.pw_expiration, dprinc.max_life, modprincstr,
1503*7f2fe78bSCy Schubert                dprinc.mod_date, dprinc.attributes, dprinc.kvno,
1504*7f2fe78bSCy Schubert                dprinc.mkvno, dprinc.policy ? dprinc.policy : "[none]",
1505*7f2fe78bSCy Schubert                dprinc.max_renewable_life, dprinc.last_success,
1506*7f2fe78bSCy Schubert                dprinc.last_failed, dprinc.fail_auth_count,
1507*7f2fe78bSCy Schubert                dprinc.n_key_data);
1508*7f2fe78bSCy Schubert         for (i = 0; i < dprinc.n_key_data; i++)
1509*7f2fe78bSCy Schubert             printf("\t%d\t%d\t%d\t%d",
1510*7f2fe78bSCy Schubert                    dprinc.key_data[i].key_data_ver,
1511*7f2fe78bSCy Schubert                    dprinc.key_data[i].key_data_kvno,
1512*7f2fe78bSCy Schubert                    dprinc.key_data[i].key_data_type[0],
1513*7f2fe78bSCy Schubert                    dprinc.key_data[i].key_data_type[1]);
1514*7f2fe78bSCy Schubert         printf("\n");
1515*7f2fe78bSCy Schubert     }
1516*7f2fe78bSCy Schubert cleanup:
1517*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
1518*7f2fe78bSCy Schubert     kadm5_free_principal_ent(handle, &dprinc);
1519*7f2fe78bSCy Schubert     free(canon);
1520*7f2fe78bSCy Schubert     free(princstr);
1521*7f2fe78bSCy Schubert     free(modprincstr);
1522*7f2fe78bSCy Schubert }
1523*7f2fe78bSCy Schubert 
1524*7f2fe78bSCy Schubert void
kadmin_getprincs(int argc,char * argv[])1525*7f2fe78bSCy Schubert kadmin_getprincs(int argc, char *argv[])
1526*7f2fe78bSCy Schubert {
1527*7f2fe78bSCy Schubert     krb5_error_code retval;
1528*7f2fe78bSCy Schubert     char *expr, **names;
1529*7f2fe78bSCy Schubert     int i, count;
1530*7f2fe78bSCy Schubert 
1531*7f2fe78bSCy Schubert     expr = NULL;
1532*7f2fe78bSCy Schubert     if (!(argc == 1 || (argc == 2 && (expr = argv[1])))) {
1533*7f2fe78bSCy Schubert         error(_("usage: get_principals [expression]\n"));
1534*7f2fe78bSCy Schubert         return;
1535*7f2fe78bSCy Schubert     }
1536*7f2fe78bSCy Schubert     retval = kadm5_get_principals(handle, expr, &names, &count);
1537*7f2fe78bSCy Schubert     if (retval) {
1538*7f2fe78bSCy Schubert         com_err("get_principals", retval, _("while retrieving list."));
1539*7f2fe78bSCy Schubert         return;
1540*7f2fe78bSCy Schubert     }
1541*7f2fe78bSCy Schubert     for (i = 0; i < count; i++)
1542*7f2fe78bSCy Schubert         printf("%s\n", names[i]);
1543*7f2fe78bSCy Schubert     kadm5_free_name_list(handle, names, count);
1544*7f2fe78bSCy Schubert }
1545*7f2fe78bSCy Schubert 
1546*7f2fe78bSCy Schubert static int
kadmin_parse_policy_args(int argc,char * argv[],kadm5_policy_ent_t policy,long * mask,char * caller)1547*7f2fe78bSCy Schubert kadmin_parse_policy_args(int argc, char *argv[], kadm5_policy_ent_t policy,
1548*7f2fe78bSCy Schubert                          long *mask, char *caller)
1549*7f2fe78bSCy Schubert {
1550*7f2fe78bSCy Schubert     krb5_error_code retval;
1551*7f2fe78bSCy Schubert     int i;
1552*7f2fe78bSCy Schubert     time_t now, interval;
1553*7f2fe78bSCy Schubert 
1554*7f2fe78bSCy Schubert     time(&now);
1555*7f2fe78bSCy Schubert     *mask = 0;
1556*7f2fe78bSCy Schubert     for (i = 1; i < argc - 1; i++) {
1557*7f2fe78bSCy Schubert         if (!strcmp(argv[i], "-maxlife")) {
1558*7f2fe78bSCy Schubert             if (++i > argc -2)
1559*7f2fe78bSCy Schubert                 return -1;
1560*7f2fe78bSCy Schubert             interval = parse_interval(argv[i], now);
1561*7f2fe78bSCy Schubert             if (interval == (time_t)-1)
1562*7f2fe78bSCy Schubert                 return -1;
1563*7f2fe78bSCy Schubert             policy->pw_max_life = interval;
1564*7f2fe78bSCy Schubert             *mask |= KADM5_PW_MAX_LIFE;
1565*7f2fe78bSCy Schubert             continue;
1566*7f2fe78bSCy Schubert         } else if (!strcmp(argv[i], "-minlife")) {
1567*7f2fe78bSCy Schubert             if (++i > argc - 2)
1568*7f2fe78bSCy Schubert                 return -1;
1569*7f2fe78bSCy Schubert             interval = parse_interval(argv[i], now);
1570*7f2fe78bSCy Schubert             if (interval == (time_t)-1)
1571*7f2fe78bSCy Schubert                 return -1;
1572*7f2fe78bSCy Schubert             policy->pw_min_life = interval;
1573*7f2fe78bSCy Schubert             *mask |= KADM5_PW_MIN_LIFE;
1574*7f2fe78bSCy Schubert             continue;
1575*7f2fe78bSCy Schubert         } else if (!strcmp(argv[i], "-minlength")) {
1576*7f2fe78bSCy Schubert             if (++i > argc - 2)
1577*7f2fe78bSCy Schubert                 return -1;
1578*7f2fe78bSCy Schubert             policy->pw_min_length = atoi(argv[i]);
1579*7f2fe78bSCy Schubert             *mask |= KADM5_PW_MIN_LENGTH;
1580*7f2fe78bSCy Schubert             continue;
1581*7f2fe78bSCy Schubert         } else if (!strcmp(argv[i], "-minclasses")) {
1582*7f2fe78bSCy Schubert             if (++i > argc - 2)
1583*7f2fe78bSCy Schubert                 return -1;
1584*7f2fe78bSCy Schubert             policy->pw_min_classes = atoi(argv[i]);
1585*7f2fe78bSCy Schubert             *mask |= KADM5_PW_MIN_CLASSES;
1586*7f2fe78bSCy Schubert             continue;
1587*7f2fe78bSCy Schubert         } else if (!strcmp(argv[i], "-history")) {
1588*7f2fe78bSCy Schubert             if (++i > argc - 2)
1589*7f2fe78bSCy Schubert                 return -1;
1590*7f2fe78bSCy Schubert             policy->pw_history_num = atoi(argv[i]);
1591*7f2fe78bSCy Schubert             *mask |= KADM5_PW_HISTORY_NUM;
1592*7f2fe78bSCy Schubert             continue;
1593*7f2fe78bSCy Schubert         } else if (strlen(argv[i]) == 11 &&
1594*7f2fe78bSCy Schubert                    !strcmp(argv[i], "-maxfailure")) {
1595*7f2fe78bSCy Schubert             if (++i > argc - 2)
1596*7f2fe78bSCy Schubert                 return -1;
1597*7f2fe78bSCy Schubert             policy->pw_max_fail = atoi(argv[i]);
1598*7f2fe78bSCy Schubert             *mask |= KADM5_PW_MAX_FAILURE;
1599*7f2fe78bSCy Schubert             continue;
1600*7f2fe78bSCy Schubert         } else if (strlen(argv[i]) == 21 &&
1601*7f2fe78bSCy Schubert                    !strcmp(argv[i], "-failurecountinterval")) {
1602*7f2fe78bSCy Schubert             if (++i > argc - 2)
1603*7f2fe78bSCy Schubert                 return -1;
1604*7f2fe78bSCy Schubert             interval = parse_interval(argv[i], now);
1605*7f2fe78bSCy Schubert             if (interval == (time_t)-1)
1606*7f2fe78bSCy Schubert                 return -1;
1607*7f2fe78bSCy Schubert             policy->pw_failcnt_interval = interval;
1608*7f2fe78bSCy Schubert             *mask |= KADM5_PW_FAILURE_COUNT_INTERVAL;
1609*7f2fe78bSCy Schubert             continue;
1610*7f2fe78bSCy Schubert         } else if (strlen(argv[i]) == 16 &&
1611*7f2fe78bSCy Schubert                    !strcmp(argv[i], "-lockoutduration")) {
1612*7f2fe78bSCy Schubert             if (++i > argc - 2)
1613*7f2fe78bSCy Schubert                 return -1;
1614*7f2fe78bSCy Schubert             interval = parse_interval(argv[i], now);
1615*7f2fe78bSCy Schubert             if (interval == (time_t)-1)
1616*7f2fe78bSCy Schubert                 return -1;
1617*7f2fe78bSCy Schubert             policy->pw_lockout_duration = interval;
1618*7f2fe78bSCy Schubert             *mask |= KADM5_PW_LOCKOUT_DURATION;
1619*7f2fe78bSCy Schubert             continue;
1620*7f2fe78bSCy Schubert         } else if (!strcmp(argv[i], "-allowedkeysalts")) {
1621*7f2fe78bSCy Schubert             krb5_key_salt_tuple *ks_tuple = NULL;
1622*7f2fe78bSCy Schubert             int n_ks_tuple = 0;
1623*7f2fe78bSCy Schubert 
1624*7f2fe78bSCy Schubert             if (++i > argc - 2)
1625*7f2fe78bSCy Schubert                 return -1;
1626*7f2fe78bSCy Schubert             if (strcmp(argv[i], "-")) {
1627*7f2fe78bSCy Schubert                 retval = krb5_string_to_keysalts(argv[i], ",", NULL, 0,
1628*7f2fe78bSCy Schubert                                                  &ks_tuple, &n_ks_tuple);
1629*7f2fe78bSCy Schubert                 if (retval) {
1630*7f2fe78bSCy Schubert                     com_err(caller, retval, _("while parsing keysalts %s"),
1631*7f2fe78bSCy Schubert                             argv[i]);
1632*7f2fe78bSCy Schubert                     return -1;
1633*7f2fe78bSCy Schubert                 }
1634*7f2fe78bSCy Schubert                 free(ks_tuple);
1635*7f2fe78bSCy Schubert                 policy->allowed_keysalts = argv[i];
1636*7f2fe78bSCy Schubert             }
1637*7f2fe78bSCy Schubert             *mask |= KADM5_POLICY_ALLOWED_KEYSALTS;
1638*7f2fe78bSCy Schubert             continue;
1639*7f2fe78bSCy Schubert         } else
1640*7f2fe78bSCy Schubert             return -1;
1641*7f2fe78bSCy Schubert     }
1642*7f2fe78bSCy Schubert     if (i != argc -1) {
1643*7f2fe78bSCy Schubert         error(_("%s: parser lost count!\n"), caller);
1644*7f2fe78bSCy Schubert         return -1;
1645*7f2fe78bSCy Schubert     } else
1646*7f2fe78bSCy Schubert         return 0;
1647*7f2fe78bSCy Schubert }
1648*7f2fe78bSCy Schubert 
1649*7f2fe78bSCy Schubert static void
kadmin_addmodpol_usage(char * func)1650*7f2fe78bSCy Schubert kadmin_addmodpol_usage(char *func)
1651*7f2fe78bSCy Schubert {
1652*7f2fe78bSCy Schubert     error(_("usage; %s [options] policy\n"), func);
1653*7f2fe78bSCy Schubert     error(_("\toptions are:\n"));
1654*7f2fe78bSCy Schubert     error(_("\t\t[-maxlife time] [-minlife time] [-minlength length]\n"
1655*7f2fe78bSCy Schubert             "\t\t[-minclasses number] [-history number]\n"
1656*7f2fe78bSCy Schubert             "\t\t[-maxfailure number] [-failurecountinterval time]\n"
1657*7f2fe78bSCy Schubert             "\t\t[-allowedkeysalts keysalts]\n"));
1658*7f2fe78bSCy Schubert     error(_("\t\t[-lockoutduration time]\n"));
1659*7f2fe78bSCy Schubert }
1660*7f2fe78bSCy Schubert 
1661*7f2fe78bSCy Schubert void
kadmin_addpol(int argc,char * argv[])1662*7f2fe78bSCy Schubert kadmin_addpol(int argc, char *argv[])
1663*7f2fe78bSCy Schubert {
1664*7f2fe78bSCy Schubert     krb5_error_code retval;
1665*7f2fe78bSCy Schubert     long mask;
1666*7f2fe78bSCy Schubert     kadm5_policy_ent_rec policy;
1667*7f2fe78bSCy Schubert 
1668*7f2fe78bSCy Schubert     memset(&policy, 0, sizeof(policy));
1669*7f2fe78bSCy Schubert     if (kadmin_parse_policy_args(argc, argv, &policy, &mask, "add_policy")) {
1670*7f2fe78bSCy Schubert         kadmin_addmodpol_usage("add_policy");
1671*7f2fe78bSCy Schubert         return;
1672*7f2fe78bSCy Schubert     }
1673*7f2fe78bSCy Schubert     policy.policy = argv[argc - 1];
1674*7f2fe78bSCy Schubert     mask |= KADM5_POLICY;
1675*7f2fe78bSCy Schubert     retval = kadm5_create_policy(handle, &policy, mask);
1676*7f2fe78bSCy Schubert     if (retval) {
1677*7f2fe78bSCy Schubert         com_err("add_policy", retval, _("while creating policy \"%s\"."),
1678*7f2fe78bSCy Schubert                 policy.policy);
1679*7f2fe78bSCy Schubert     }
1680*7f2fe78bSCy Schubert }
1681*7f2fe78bSCy Schubert 
1682*7f2fe78bSCy Schubert void
kadmin_modpol(int argc,char * argv[])1683*7f2fe78bSCy Schubert kadmin_modpol(int argc, char *argv[])
1684*7f2fe78bSCy Schubert {
1685*7f2fe78bSCy Schubert     krb5_error_code retval;
1686*7f2fe78bSCy Schubert     long mask;
1687*7f2fe78bSCy Schubert     kadm5_policy_ent_rec policy;
1688*7f2fe78bSCy Schubert 
1689*7f2fe78bSCy Schubert     memset(&policy, 0, sizeof(policy));
1690*7f2fe78bSCy Schubert     if (kadmin_parse_policy_args(argc, argv, &policy, &mask,
1691*7f2fe78bSCy Schubert                                  "modify_policy")) {
1692*7f2fe78bSCy Schubert         kadmin_addmodpol_usage("modify_policy");
1693*7f2fe78bSCy Schubert         return;
1694*7f2fe78bSCy Schubert     }
1695*7f2fe78bSCy Schubert     policy.policy = argv[argc - 1];
1696*7f2fe78bSCy Schubert     retval = kadm5_modify_policy(handle, &policy, mask);
1697*7f2fe78bSCy Schubert     if (retval) {
1698*7f2fe78bSCy Schubert         com_err("modify_policy", retval, _("while modifying policy \"%s\"."),
1699*7f2fe78bSCy Schubert                 policy.policy);
1700*7f2fe78bSCy Schubert     }
1701*7f2fe78bSCy Schubert }
1702*7f2fe78bSCy Schubert 
1703*7f2fe78bSCy Schubert void
kadmin_delpol(int argc,char * argv[])1704*7f2fe78bSCy Schubert kadmin_delpol(int argc, char *argv[])
1705*7f2fe78bSCy Schubert {
1706*7f2fe78bSCy Schubert     krb5_error_code retval;
1707*7f2fe78bSCy Schubert     char reply[5];
1708*7f2fe78bSCy Schubert 
1709*7f2fe78bSCy Schubert     if (!(argc == 2 || (argc == 3 && !strcmp("-force", argv[1])))) {
1710*7f2fe78bSCy Schubert         error(_("usage: delete_policy [-force] policy\n"));
1711*7f2fe78bSCy Schubert         return;
1712*7f2fe78bSCy Schubert     }
1713*7f2fe78bSCy Schubert     if (argc == 2 && !script_mode) {
1714*7f2fe78bSCy Schubert         printf(_("Are you sure you want to delete the policy \"%s\"? "
1715*7f2fe78bSCy Schubert                  "(yes/no): "), argv[1]);
1716*7f2fe78bSCy Schubert         fgets(reply, sizeof(reply), stdin);
1717*7f2fe78bSCy Schubert         if (strcmp("yes\n", reply)) {
1718*7f2fe78bSCy Schubert             fprintf(stderr, _("Policy \"%s\" not deleted.\n"), argv[1]);
1719*7f2fe78bSCy Schubert             return;
1720*7f2fe78bSCy Schubert         }
1721*7f2fe78bSCy Schubert     }
1722*7f2fe78bSCy Schubert     retval = kadm5_delete_policy(handle, argv[argc - 1]);
1723*7f2fe78bSCy Schubert     if (retval) {
1724*7f2fe78bSCy Schubert         com_err("delete_policy:", retval, _("while deleting policy \"%s\""),
1725*7f2fe78bSCy Schubert                 argv[argc - 1]);
1726*7f2fe78bSCy Schubert     }
1727*7f2fe78bSCy Schubert }
1728*7f2fe78bSCy Schubert 
1729*7f2fe78bSCy Schubert void
kadmin_getpol(int argc,char * argv[])1730*7f2fe78bSCy Schubert kadmin_getpol(int argc, char *argv[])
1731*7f2fe78bSCy Schubert {
1732*7f2fe78bSCy Schubert     krb5_error_code retval;
1733*7f2fe78bSCy Schubert     kadm5_policy_ent_rec policy;
1734*7f2fe78bSCy Schubert 
1735*7f2fe78bSCy Schubert     if (!(argc == 2 || (argc == 3 && !strcmp("-terse", argv[1])))) {
1736*7f2fe78bSCy Schubert         error(_("usage: get_policy [-terse] policy\n"));
1737*7f2fe78bSCy Schubert         return;
1738*7f2fe78bSCy Schubert     }
1739*7f2fe78bSCy Schubert     retval = kadm5_get_policy(handle, argv[argc - 1], &policy);
1740*7f2fe78bSCy Schubert     if (retval) {
1741*7f2fe78bSCy Schubert         com_err("get_policy", retval, _("while retrieving policy \"%s\"."),
1742*7f2fe78bSCy Schubert                 argv[argc - 1]);
1743*7f2fe78bSCy Schubert         return;
1744*7f2fe78bSCy Schubert     }
1745*7f2fe78bSCy Schubert     if (argc == 2) {
1746*7f2fe78bSCy Schubert         printf(_("Policy: %s\n"), policy.policy);
1747*7f2fe78bSCy Schubert         printf(_("Maximum password life: %s\n"), strdur(policy.pw_max_life));
1748*7f2fe78bSCy Schubert         printf(_("Minimum password life: %s\n"), strdur(policy.pw_min_life));
1749*7f2fe78bSCy Schubert         printf(_("Minimum password length: %ld\n"), policy.pw_min_length);
1750*7f2fe78bSCy Schubert         printf(_("Minimum number of password character classes: %ld\n"),
1751*7f2fe78bSCy Schubert                policy.pw_min_classes);
1752*7f2fe78bSCy Schubert         printf(_("Number of old keys kept: %ld\n"), policy.pw_history_num);
1753*7f2fe78bSCy Schubert         printf(_("Maximum password failures before lockout: %lu\n"),
1754*7f2fe78bSCy Schubert                (unsigned long)policy.pw_max_fail);
1755*7f2fe78bSCy Schubert         printf(_("Password failure count reset interval: %s\n"),
1756*7f2fe78bSCy Schubert                strdur(policy.pw_failcnt_interval));
1757*7f2fe78bSCy Schubert         printf(_("Password lockout duration: %s\n"),
1758*7f2fe78bSCy Schubert                strdur(policy.pw_lockout_duration));
1759*7f2fe78bSCy Schubert         if (policy.allowed_keysalts != NULL)
1760*7f2fe78bSCy Schubert             printf(_("Allowed key/salt types: %s\n"), policy.allowed_keysalts);
1761*7f2fe78bSCy Schubert     } else {
1762*7f2fe78bSCy Schubert         /* Output 0 where we used to output policy_refcnt. */
1763*7f2fe78bSCy Schubert         printf("\"%s\"\t%ld\t%ld\t%ld\t%ld\t%ld\t0\t%lu\t%ld\t%ld\t%s\n",
1764*7f2fe78bSCy Schubert                policy.policy, policy.pw_max_life, policy.pw_min_life,
1765*7f2fe78bSCy Schubert                policy.pw_min_length, policy.pw_min_classes,
1766*7f2fe78bSCy Schubert                policy.pw_history_num, (unsigned long)policy.pw_max_fail,
1767*7f2fe78bSCy Schubert                (long)policy.pw_failcnt_interval,
1768*7f2fe78bSCy Schubert                (long)policy.pw_lockout_duration,
1769*7f2fe78bSCy Schubert                (policy.allowed_keysalts == NULL) ? "-" :
1770*7f2fe78bSCy Schubert                policy.allowed_keysalts);
1771*7f2fe78bSCy Schubert     }
1772*7f2fe78bSCy Schubert     kadm5_free_policy_ent(handle, &policy);
1773*7f2fe78bSCy Schubert }
1774*7f2fe78bSCy Schubert 
1775*7f2fe78bSCy Schubert void
kadmin_getpols(int argc,char * argv[])1776*7f2fe78bSCy Schubert kadmin_getpols(int argc, char *argv[])
1777*7f2fe78bSCy Schubert {
1778*7f2fe78bSCy Schubert     krb5_error_code retval;
1779*7f2fe78bSCy Schubert     char *expr, **names;
1780*7f2fe78bSCy Schubert     int i, count;
1781*7f2fe78bSCy Schubert 
1782*7f2fe78bSCy Schubert     expr = NULL;
1783*7f2fe78bSCy Schubert     if (!(argc == 1 || (argc == 2 && (expr = argv[1])))) {
1784*7f2fe78bSCy Schubert         error(_("usage: get_policies [expression]\n"));
1785*7f2fe78bSCy Schubert         return;
1786*7f2fe78bSCy Schubert     }
1787*7f2fe78bSCy Schubert     retval = kadm5_get_policies(handle, expr, &names, &count);
1788*7f2fe78bSCy Schubert     if (retval) {
1789*7f2fe78bSCy Schubert         com_err("get_policies", retval, _("while retrieving list."));
1790*7f2fe78bSCy Schubert         return;
1791*7f2fe78bSCy Schubert     }
1792*7f2fe78bSCy Schubert     for (i = 0; i < count; i++)
1793*7f2fe78bSCy Schubert         printf("%s\n", names[i]);
1794*7f2fe78bSCy Schubert     kadm5_free_name_list(handle, names, count);
1795*7f2fe78bSCy Schubert }
1796*7f2fe78bSCy Schubert 
1797*7f2fe78bSCy Schubert void
kadmin_getprivs(int argc,char * argv[])1798*7f2fe78bSCy Schubert kadmin_getprivs(int argc, char *argv[])
1799*7f2fe78bSCy Schubert {
1800*7f2fe78bSCy Schubert     static char *privs[] = {"INQUIRE", "ADD", "MODIFY", "DELETE"};
1801*7f2fe78bSCy Schubert     krb5_error_code retval;
1802*7f2fe78bSCy Schubert     size_t i;
1803*7f2fe78bSCy Schubert     long plist;
1804*7f2fe78bSCy Schubert 
1805*7f2fe78bSCy Schubert     if (argc != 1) {
1806*7f2fe78bSCy Schubert         error(_("usage: get_privs\n"));
1807*7f2fe78bSCy Schubert         return;
1808*7f2fe78bSCy Schubert     }
1809*7f2fe78bSCy Schubert     retval = kadm5_get_privs(handle, &plist);
1810*7f2fe78bSCy Schubert     if (retval) {
1811*7f2fe78bSCy Schubert         com_err("get_privs", retval, _("while retrieving privileges"));
1812*7f2fe78bSCy Schubert         return;
1813*7f2fe78bSCy Schubert     }
1814*7f2fe78bSCy Schubert     printf(_("current privileges:"));
1815*7f2fe78bSCy Schubert     for (i = 0; i < sizeof (privs) / sizeof (char *); i++) {
1816*7f2fe78bSCy Schubert         if (plist & 1 << i)
1817*7f2fe78bSCy Schubert             printf(" %s", privs[i]);
1818*7f2fe78bSCy Schubert     }
1819*7f2fe78bSCy Schubert     printf("\n");
1820*7f2fe78bSCy Schubert }
1821*7f2fe78bSCy Schubert 
1822*7f2fe78bSCy Schubert void
kadmin_purgekeys(int argc,char * argv[])1823*7f2fe78bSCy Schubert kadmin_purgekeys(int argc, char *argv[])
1824*7f2fe78bSCy Schubert {
1825*7f2fe78bSCy Schubert     kadm5_ret_t retval;
1826*7f2fe78bSCy Schubert     int keepkvno = -1;
1827*7f2fe78bSCy Schubert     char *pname = NULL, *canon = NULL;
1828*7f2fe78bSCy Schubert     krb5_principal princ;
1829*7f2fe78bSCy Schubert 
1830*7f2fe78bSCy Schubert     if (argc == 4 && strcmp(argv[1], "-keepkvno") == 0) {
1831*7f2fe78bSCy Schubert         keepkvno = atoi(argv[2]);
1832*7f2fe78bSCy Schubert         pname = argv[3];
1833*7f2fe78bSCy Schubert     } else if (argc == 3 && strcmp(argv[1], "-all") == 0) {
1834*7f2fe78bSCy Schubert         keepkvno = KRB5_INT32_MAX;
1835*7f2fe78bSCy Schubert         pname = argv[2];
1836*7f2fe78bSCy Schubert     } else if (argc == 2) {
1837*7f2fe78bSCy Schubert         pname = argv[1];
1838*7f2fe78bSCy Schubert     }
1839*7f2fe78bSCy Schubert     if (pname == NULL) {
1840*7f2fe78bSCy Schubert         error(_("usage: purgekeys [-all|-keepkvno oldest_kvno_to_keep] "
1841*7f2fe78bSCy Schubert                 "principal\n"));
1842*7f2fe78bSCy Schubert         return;
1843*7f2fe78bSCy Schubert     }
1844*7f2fe78bSCy Schubert 
1845*7f2fe78bSCy Schubert     retval = kadmin_parse_name(pname, &princ);
1846*7f2fe78bSCy Schubert     if (retval) {
1847*7f2fe78bSCy Schubert         com_err("purgekeys", retval, _("while parsing principal"));
1848*7f2fe78bSCy Schubert         return;
1849*7f2fe78bSCy Schubert     }
1850*7f2fe78bSCy Schubert 
1851*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, princ, &canon);
1852*7f2fe78bSCy Schubert     if (retval) {
1853*7f2fe78bSCy Schubert         com_err("purgekeys", retval, _("while canonicalizing principal"));
1854*7f2fe78bSCy Schubert         goto cleanup;
1855*7f2fe78bSCy Schubert     }
1856*7f2fe78bSCy Schubert 
1857*7f2fe78bSCy Schubert     retval = kadm5_purgekeys(handle, princ, keepkvno);
1858*7f2fe78bSCy Schubert     if (retval) {
1859*7f2fe78bSCy Schubert         com_err("purgekeys", retval,
1860*7f2fe78bSCy Schubert                 _("while purging keys for principal \"%s\""), canon);
1861*7f2fe78bSCy Schubert         goto cleanup;
1862*7f2fe78bSCy Schubert     }
1863*7f2fe78bSCy Schubert 
1864*7f2fe78bSCy Schubert     if (keepkvno == KRB5_INT32_MAX)
1865*7f2fe78bSCy Schubert         info(_("All keys for principal \"%s\" removed.\n"), canon);
1866*7f2fe78bSCy Schubert     else
1867*7f2fe78bSCy Schubert         info(_("Old keys for principal \"%s\" purged.\n"), canon);
1868*7f2fe78bSCy Schubert cleanup:
1869*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
1870*7f2fe78bSCy Schubert     free(canon);
1871*7f2fe78bSCy Schubert     return;
1872*7f2fe78bSCy Schubert }
1873*7f2fe78bSCy Schubert 
1874*7f2fe78bSCy Schubert void
kadmin_getstrings(int argc,char * argv[])1875*7f2fe78bSCy Schubert kadmin_getstrings(int argc, char *argv[])
1876*7f2fe78bSCy Schubert {
1877*7f2fe78bSCy Schubert     kadm5_ret_t retval;
1878*7f2fe78bSCy Schubert     char *pname, *canon = NULL;
1879*7f2fe78bSCy Schubert     krb5_principal princ = NULL;
1880*7f2fe78bSCy Schubert     krb5_string_attr *strings = NULL;
1881*7f2fe78bSCy Schubert     int count, i;
1882*7f2fe78bSCy Schubert 
1883*7f2fe78bSCy Schubert     if (argc != 2) {
1884*7f2fe78bSCy Schubert         error(_("usage: get_strings principal\n"));
1885*7f2fe78bSCy Schubert         return;
1886*7f2fe78bSCy Schubert     }
1887*7f2fe78bSCy Schubert     pname = argv[1];
1888*7f2fe78bSCy Schubert 
1889*7f2fe78bSCy Schubert     retval = kadmin_parse_name(pname, &princ);
1890*7f2fe78bSCy Schubert     if (retval) {
1891*7f2fe78bSCy Schubert         com_err("get_strings", retval, _("while parsing principal"));
1892*7f2fe78bSCy Schubert         return;
1893*7f2fe78bSCy Schubert     }
1894*7f2fe78bSCy Schubert 
1895*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, princ, &canon);
1896*7f2fe78bSCy Schubert     if (retval) {
1897*7f2fe78bSCy Schubert         com_err("get_strings", retval, _("while canonicalizing principal"));
1898*7f2fe78bSCy Schubert         goto cleanup;
1899*7f2fe78bSCy Schubert     }
1900*7f2fe78bSCy Schubert 
1901*7f2fe78bSCy Schubert     retval = kadm5_get_strings(handle, princ, &strings, &count);
1902*7f2fe78bSCy Schubert     if (retval) {
1903*7f2fe78bSCy Schubert         com_err("get_strings", retval,
1904*7f2fe78bSCy Schubert                 _("while getting attributes for principal \"%s\""), canon);
1905*7f2fe78bSCy Schubert         goto cleanup;
1906*7f2fe78bSCy Schubert     }
1907*7f2fe78bSCy Schubert 
1908*7f2fe78bSCy Schubert     if (count == 0)
1909*7f2fe78bSCy Schubert         printf(_("(No string attributes.)\n"));
1910*7f2fe78bSCy Schubert     for (i = 0; i < count; i++)
1911*7f2fe78bSCy Schubert         printf("%s: %s\n", strings[i].key, strings[i].value);
1912*7f2fe78bSCy Schubert     kadm5_free_strings(handle, strings, count);
1913*7f2fe78bSCy Schubert 
1914*7f2fe78bSCy Schubert cleanup:
1915*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
1916*7f2fe78bSCy Schubert     free(canon);
1917*7f2fe78bSCy Schubert     return;
1918*7f2fe78bSCy Schubert }
1919*7f2fe78bSCy Schubert 
1920*7f2fe78bSCy Schubert void
kadmin_setstring(int argc,char * argv[])1921*7f2fe78bSCy Schubert kadmin_setstring(int argc, char *argv[])
1922*7f2fe78bSCy Schubert {
1923*7f2fe78bSCy Schubert     kadm5_ret_t retval;
1924*7f2fe78bSCy Schubert     char *pname, *canon = NULL, *key, *value;
1925*7f2fe78bSCy Schubert     krb5_principal princ = NULL;
1926*7f2fe78bSCy Schubert 
1927*7f2fe78bSCy Schubert     if (argc != 4) {
1928*7f2fe78bSCy Schubert         error(_("usage: set_string principal key value\n"));
1929*7f2fe78bSCy Schubert         return;
1930*7f2fe78bSCy Schubert     }
1931*7f2fe78bSCy Schubert     pname = argv[1];
1932*7f2fe78bSCy Schubert     key = argv[2];
1933*7f2fe78bSCy Schubert     value = argv[3];
1934*7f2fe78bSCy Schubert 
1935*7f2fe78bSCy Schubert     retval = kadmin_parse_name(pname, &princ);
1936*7f2fe78bSCy Schubert     if (retval) {
1937*7f2fe78bSCy Schubert         com_err("set_string", retval, _("while parsing principal"));
1938*7f2fe78bSCy Schubert         return;
1939*7f2fe78bSCy Schubert     }
1940*7f2fe78bSCy Schubert 
1941*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, princ, &canon);
1942*7f2fe78bSCy Schubert     if (retval) {
1943*7f2fe78bSCy Schubert         com_err("set_string", retval, _("while canonicalizing principal"));
1944*7f2fe78bSCy Schubert         goto cleanup;
1945*7f2fe78bSCy Schubert     }
1946*7f2fe78bSCy Schubert 
1947*7f2fe78bSCy Schubert     retval = kadm5_set_string(handle, princ, key, value);
1948*7f2fe78bSCy Schubert     if (retval) {
1949*7f2fe78bSCy Schubert         com_err("set_string", retval,
1950*7f2fe78bSCy Schubert                 _("while setting attribute on principal \"%s\""), canon);
1951*7f2fe78bSCy Schubert         goto cleanup;
1952*7f2fe78bSCy Schubert     }
1953*7f2fe78bSCy Schubert 
1954*7f2fe78bSCy Schubert     info(_("Attribute set for principal \"%s\".\n"), canon);
1955*7f2fe78bSCy Schubert cleanup:
1956*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
1957*7f2fe78bSCy Schubert     free(canon);
1958*7f2fe78bSCy Schubert     return;
1959*7f2fe78bSCy Schubert }
1960*7f2fe78bSCy Schubert 
1961*7f2fe78bSCy Schubert void
kadmin_delstring(int argc,char * argv[])1962*7f2fe78bSCy Schubert kadmin_delstring(int argc, char *argv[])
1963*7f2fe78bSCy Schubert {
1964*7f2fe78bSCy Schubert     kadm5_ret_t retval;
1965*7f2fe78bSCy Schubert     char *pname, *canon = NULL, *key;
1966*7f2fe78bSCy Schubert     krb5_principal princ = NULL;
1967*7f2fe78bSCy Schubert 
1968*7f2fe78bSCy Schubert     if (argc != 3) {
1969*7f2fe78bSCy Schubert         error(_("usage: del_string principal key\n"));
1970*7f2fe78bSCy Schubert         return;
1971*7f2fe78bSCy Schubert     }
1972*7f2fe78bSCy Schubert     pname = argv[1];
1973*7f2fe78bSCy Schubert     key = argv[2];
1974*7f2fe78bSCy Schubert 
1975*7f2fe78bSCy Schubert     retval = kadmin_parse_name(pname, &princ);
1976*7f2fe78bSCy Schubert     if (retval) {
1977*7f2fe78bSCy Schubert         com_err("delstring", retval, _("while parsing principal"));
1978*7f2fe78bSCy Schubert         return;
1979*7f2fe78bSCy Schubert     }
1980*7f2fe78bSCy Schubert 
1981*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, princ, &canon);
1982*7f2fe78bSCy Schubert     if (retval) {
1983*7f2fe78bSCy Schubert         com_err("del_string", retval, _("while canonicalizing principal"));
1984*7f2fe78bSCy Schubert         goto cleanup;
1985*7f2fe78bSCy Schubert     }
1986*7f2fe78bSCy Schubert 
1987*7f2fe78bSCy Schubert     retval = kadm5_set_string(handle, princ, key, NULL);
1988*7f2fe78bSCy Schubert     if (retval) {
1989*7f2fe78bSCy Schubert         com_err("del_string", retval,
1990*7f2fe78bSCy Schubert                 _("while deleting attribute from principal \"%s\""), canon);
1991*7f2fe78bSCy Schubert         goto cleanup;
1992*7f2fe78bSCy Schubert     }
1993*7f2fe78bSCy Schubert 
1994*7f2fe78bSCy Schubert     info(_("Attribute removed from principal \"%s\".\n"), canon);
1995*7f2fe78bSCy Schubert cleanup:
1996*7f2fe78bSCy Schubert     krb5_free_principal(context, princ);
1997*7f2fe78bSCy Schubert     free(canon);
1998*7f2fe78bSCy Schubert     return;
1999*7f2fe78bSCy Schubert }
2000