xref: /freebsd/crypto/krb5/src/kadmin/dbutil/kdb5_util.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* kadmin/dbutil/kdb5_util.c - Administer a KDC database */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert  * (C) Copyright 1990,1991, 1996, 2008, 2009 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert  * All Rights Reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert  *   require a specific license from the United States Government.
9*7f2fe78bSCy Schubert  *   It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert  *   export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert  *
12*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert  * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert  * permission.  Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert  * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert  * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert  * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
24*7f2fe78bSCy Schubert  * or implied warranty.
25*7f2fe78bSCy Schubert  */
26*7f2fe78bSCy Schubert /*
27*7f2fe78bSCy Schubert  * Copyright (C) 1998 by the FundsXpress, INC.
28*7f2fe78bSCy Schubert  *
29*7f2fe78bSCy Schubert  * All rights reserved.
30*7f2fe78bSCy Schubert  *
31*7f2fe78bSCy Schubert  * Export of this software from the United States of America may require
32*7f2fe78bSCy Schubert  * a specific license from the United States Government.  It is the
33*7f2fe78bSCy Schubert  * responsibility of any person or organization contemplating export to
34*7f2fe78bSCy Schubert  * obtain such a license before exporting.
35*7f2fe78bSCy Schubert  *
36*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
37*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
38*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
39*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
40*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
41*7f2fe78bSCy Schubert  * the name of FundsXpress. not be used in advertising or publicity pertaining
42*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
43*7f2fe78bSCy Schubert  * permission.  FundsXpress makes no representations about the suitability of
44*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
45*7f2fe78bSCy Schubert  * or implied warranty.
46*7f2fe78bSCy Schubert  *
47*7f2fe78bSCy Schubert  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
48*7f2fe78bSCy Schubert  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
49*7f2fe78bSCy Schubert  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
50*7f2fe78bSCy Schubert  */
51*7f2fe78bSCy Schubert /*
52*7f2fe78bSCy Schubert  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
53*7f2fe78bSCy Schubert  * Use is subject to license terms.
54*7f2fe78bSCy Schubert  */
55*7f2fe78bSCy Schubert 
56*7f2fe78bSCy Schubert #include <k5-int.h>
57*7f2fe78bSCy Schubert #include <kadm5/admin.h>
58*7f2fe78bSCy Schubert #include <locale.h>
59*7f2fe78bSCy Schubert #include <adm_proto.h>
60*7f2fe78bSCy Schubert #include <time.h>
61*7f2fe78bSCy Schubert #include "kdb5_util.h"
62*7f2fe78bSCy Schubert 
63*7f2fe78bSCy Schubert /*
64*7f2fe78bSCy Schubert  * XXX Ick, ick, ick.  These global variables shouldn't be global....
65*7f2fe78bSCy Schubert  */
66*7f2fe78bSCy Schubert char *mkey_password = 0;
67*7f2fe78bSCy Schubert 
68*7f2fe78bSCy Schubert /*
69*7f2fe78bSCy Schubert  * I can't figure out any way for this not to be global, given how ss
70*7f2fe78bSCy Schubert  * works.
71*7f2fe78bSCy Schubert  */
72*7f2fe78bSCy Schubert 
73*7f2fe78bSCy Schubert int exit_status = 0;
74*7f2fe78bSCy Schubert krb5_context util_context;
75*7f2fe78bSCy Schubert kadm5_config_params global_params;
76*7f2fe78bSCy Schubert 
usage()77*7f2fe78bSCy Schubert void usage()
78*7f2fe78bSCy Schubert {
79*7f2fe78bSCy Schubert     fprintf(stderr,
80*7f2fe78bSCy Schubert             _("Usage: kdb5_util [-r realm] [-d dbname] "
81*7f2fe78bSCy Schubert               "[-k mkeytype] [-kv mkeyVNO]\n"
82*7f2fe78bSCy Schubert               "\t        [-M mkeyname] [-m] [-sf stashfilename] "
83*7f2fe78bSCy Schubert               "[-P password]\n"
84*7f2fe78bSCy Schubert               "\t        [-x db_args]* cmd [cmd_options]\n"
85*7f2fe78bSCy Schubert               "\tcreate  [-s]\n"
86*7f2fe78bSCy Schubert               "\tdestroy [-f]\n"
87*7f2fe78bSCy Schubert               "\tstash   [-f keyfile]\n"
88*7f2fe78bSCy Schubert               "\tdump    [-b7|-r13|-r18] [-verbose]\n"
89*7f2fe78bSCy Schubert               "\t        [-mkey_convert] [-new_mkey_file mkey_file]\n"
90*7f2fe78bSCy Schubert               "\t        [-rev] [-recurse] [filename [princs...]]\n"
91*7f2fe78bSCy Schubert               "\tload    [-b7|-r13|-r18] [-hash] [-verbose] [-update] "
92*7f2fe78bSCy Schubert               "filename\n"
93*7f2fe78bSCy Schubert               "\tark     [-e etype_list] principal\n"
94*7f2fe78bSCy Schubert               "\tadd_mkey [-e etype] [-s]\n"
95*7f2fe78bSCy Schubert               "\tuse_mkey kvno [time]\n"
96*7f2fe78bSCy Schubert               "\tlist_mkeys\n"));
97*7f2fe78bSCy Schubert     /* avoid a string length compiler warning */
98*7f2fe78bSCy Schubert     fprintf(stderr,
99*7f2fe78bSCy Schubert             _("\tupdate_princ_encryption [-f] [-n] [-v] [princ-pattern]\n"
100*7f2fe78bSCy Schubert               "\tpurge_mkeys [-f] [-n] [-v]\n"
101*7f2fe78bSCy Schubert               "\ttabdump [-H] [-c] [-e] [-n] [-o outfile] dumptype\n"
102*7f2fe78bSCy Schubert               "\nwhere,\n\t[-x db_args]* - any number of database specific "
103*7f2fe78bSCy Schubert               "arguments.\n"
104*7f2fe78bSCy Schubert               "\t\t\tLook at each database documentation for supported "
105*7f2fe78bSCy Schubert               "arguments\n"));
106*7f2fe78bSCy Schubert     exit(1);
107*7f2fe78bSCy Schubert }
108*7f2fe78bSCy Schubert 
109*7f2fe78bSCy Schubert krb5_keyblock master_keyblock;
110*7f2fe78bSCy Schubert krb5_kvno   master_kvno; /* fetched */
111*7f2fe78bSCy Schubert extern krb5_principal master_princ;
112*7f2fe78bSCy Schubert char *mkey_fullname;
113*7f2fe78bSCy Schubert krb5_db_entry *master_entry = NULL;
114*7f2fe78bSCy Schubert int     valid_master_key = 0;
115*7f2fe78bSCy Schubert 
116*7f2fe78bSCy Schubert char *progname;
117*7f2fe78bSCy Schubert krb5_boolean manual_mkey = FALSE;
118*7f2fe78bSCy Schubert krb5_boolean dbactive = FALSE;
119*7f2fe78bSCy Schubert 
120*7f2fe78bSCy Schubert static int open_db_and_mkey(void);
121*7f2fe78bSCy Schubert 
122*7f2fe78bSCy Schubert static void add_random_key(int, char **);
123*7f2fe78bSCy Schubert 
124*7f2fe78bSCy Schubert typedef void (*cmd_func)(int, char **);
125*7f2fe78bSCy Schubert 
126*7f2fe78bSCy Schubert struct _cmd_table {
127*7f2fe78bSCy Schubert     char *name;
128*7f2fe78bSCy Schubert     cmd_func func;
129*7f2fe78bSCy Schubert     int opendb;
130*7f2fe78bSCy Schubert } cmd_table[] = {
131*7f2fe78bSCy Schubert     {"create", kdb5_create, 0},
132*7f2fe78bSCy Schubert     {"destroy", kdb5_destroy, 1}, /* 1 opens the kdb */
133*7f2fe78bSCy Schubert     {"stash", kdb5_stash, 1},
134*7f2fe78bSCy Schubert     {"dump", dump_db, 1},
135*7f2fe78bSCy Schubert     {"load", load_db, 0},
136*7f2fe78bSCy Schubert     {"ark", add_random_key, 1},
137*7f2fe78bSCy Schubert     {"add_mkey", kdb5_add_mkey, 1},
138*7f2fe78bSCy Schubert     {"use_mkey", kdb5_use_mkey, 1},
139*7f2fe78bSCy Schubert     {"list_mkeys", kdb5_list_mkeys, 1},
140*7f2fe78bSCy Schubert     {"update_princ_encryption", kdb5_update_princ_encryption, 1},
141*7f2fe78bSCy Schubert     {"purge_mkeys", kdb5_purge_mkeys, 1},
142*7f2fe78bSCy Schubert     {"tabdump", tabdump, 1},
143*7f2fe78bSCy Schubert     {NULL, NULL, 0},
144*7f2fe78bSCy Schubert };
145*7f2fe78bSCy Schubert 
cmd_lookup(name)146*7f2fe78bSCy Schubert static struct _cmd_table *cmd_lookup(name)
147*7f2fe78bSCy Schubert     char *name;
148*7f2fe78bSCy Schubert {
149*7f2fe78bSCy Schubert     struct _cmd_table *cmd = cmd_table;
150*7f2fe78bSCy Schubert     while (cmd->name) {
151*7f2fe78bSCy Schubert         if (strcmp(cmd->name, name) == 0)
152*7f2fe78bSCy Schubert             return cmd;
153*7f2fe78bSCy Schubert         else
154*7f2fe78bSCy Schubert             cmd++;
155*7f2fe78bSCy Schubert     }
156*7f2fe78bSCy Schubert 
157*7f2fe78bSCy Schubert     return NULL;
158*7f2fe78bSCy Schubert }
159*7f2fe78bSCy Schubert 
160*7f2fe78bSCy Schubert #define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(usage(), NULL))
161*7f2fe78bSCy Schubert 
162*7f2fe78bSCy Schubert char **db5util_db_args = NULL;
163*7f2fe78bSCy Schubert int    db5util_db_args_size = 0;
164*7f2fe78bSCy Schubert 
extended_com_err_fn(const char * myprog,errcode_t code,const char * fmt,va_list args)165*7f2fe78bSCy Schubert static void extended_com_err_fn (const char *myprog, errcode_t code,
166*7f2fe78bSCy Schubert                                  const char *fmt, va_list args)
167*7f2fe78bSCy Schubert {
168*7f2fe78bSCy Schubert     const char *emsg;
169*7f2fe78bSCy Schubert     if (code) {
170*7f2fe78bSCy Schubert         emsg = krb5_get_error_message (util_context, code);
171*7f2fe78bSCy Schubert         fprintf (stderr, "%s: %s ", myprog, emsg);
172*7f2fe78bSCy Schubert         krb5_free_error_message (util_context, emsg);
173*7f2fe78bSCy Schubert     } else {
174*7f2fe78bSCy Schubert         fprintf (stderr, "%s: ", myprog);
175*7f2fe78bSCy Schubert     }
176*7f2fe78bSCy Schubert     vfprintf (stderr, fmt, args);
177*7f2fe78bSCy Schubert     fprintf (stderr, "\n");
178*7f2fe78bSCy Schubert }
179*7f2fe78bSCy Schubert 
add_db_arg(char * arg)180*7f2fe78bSCy Schubert int add_db_arg(char *arg)
181*7f2fe78bSCy Schubert {
182*7f2fe78bSCy Schubert     char **temp;
183*7f2fe78bSCy Schubert     db5util_db_args_size++;
184*7f2fe78bSCy Schubert     temp = realloc(db5util_db_args,
185*7f2fe78bSCy Schubert                    sizeof(char *) * (db5util_db_args_size + 1));
186*7f2fe78bSCy Schubert     if (temp == NULL)
187*7f2fe78bSCy Schubert         return 0;
188*7f2fe78bSCy Schubert     db5util_db_args = temp;
189*7f2fe78bSCy Schubert     db5util_db_args[db5util_db_args_size-1] = arg;
190*7f2fe78bSCy Schubert     db5util_db_args[db5util_db_args_size]   = NULL;
191*7f2fe78bSCy Schubert     return 1;
192*7f2fe78bSCy Schubert }
193*7f2fe78bSCy Schubert 
main(argc,argv)194*7f2fe78bSCy Schubert int main(argc, argv)
195*7f2fe78bSCy Schubert     int argc;
196*7f2fe78bSCy Schubert     char *argv[];
197*7f2fe78bSCy Schubert {
198*7f2fe78bSCy Schubert     struct _cmd_table *cmd = NULL;
199*7f2fe78bSCy Schubert     char *koptarg, **cmd_argv;
200*7f2fe78bSCy Schubert     char *db_name_tmp = NULL;
201*7f2fe78bSCy Schubert     int cmd_argc;
202*7f2fe78bSCy Schubert     krb5_error_code retval;
203*7f2fe78bSCy Schubert 
204*7f2fe78bSCy Schubert     setlocale(LC_ALL, "");
205*7f2fe78bSCy Schubert     set_com_err_hook(extended_com_err_fn);
206*7f2fe78bSCy Schubert 
207*7f2fe78bSCy Schubert     /*
208*7f2fe78bSCy Schubert      * Ensure that "progname" is set before calling com_err.
209*7f2fe78bSCy Schubert      */
210*7f2fe78bSCy Schubert     progname = (strrchr(argv[0], '/') ?
211*7f2fe78bSCy Schubert                 strrchr(argv[0], '/') + 1 : argv[0]);
212*7f2fe78bSCy Schubert 
213*7f2fe78bSCy Schubert     retval = kadm5_init_krb5_context(&util_context);
214*7f2fe78bSCy Schubert     if (retval) {
215*7f2fe78bSCy Schubert         com_err (progname, retval, _("while initializing Kerberos code"));
216*7f2fe78bSCy Schubert         exit(1);
217*7f2fe78bSCy Schubert     }
218*7f2fe78bSCy Schubert 
219*7f2fe78bSCy Schubert     cmd_argv = (char **) malloc(sizeof(char *)*argc);
220*7f2fe78bSCy Schubert     if (cmd_argv == NULL) {
221*7f2fe78bSCy Schubert         com_err(progname, ENOMEM, _("while creating sub-command arguments"));
222*7f2fe78bSCy Schubert         exit(1);
223*7f2fe78bSCy Schubert     }
224*7f2fe78bSCy Schubert     memset(cmd_argv, 0, sizeof(char *)*argc);
225*7f2fe78bSCy Schubert     cmd_argc = 0;
226*7f2fe78bSCy Schubert 
227*7f2fe78bSCy Schubert     argv++; argc--;
228*7f2fe78bSCy Schubert     while (*argv) {
229*7f2fe78bSCy Schubert         if (strcmp(*argv, "-P") == 0 && ARG_VAL) {
230*7f2fe78bSCy Schubert             mkey_password = koptarg;
231*7f2fe78bSCy Schubert             manual_mkey = TRUE;
232*7f2fe78bSCy Schubert         } else if (strcmp(*argv, "-d") == 0 && ARG_VAL) {
233*7f2fe78bSCy Schubert             global_params.dbname = koptarg;
234*7f2fe78bSCy Schubert             global_params.mask |= KADM5_CONFIG_DBNAME;
235*7f2fe78bSCy Schubert 
236*7f2fe78bSCy Schubert             if (asprintf(&db_name_tmp, "dbname=%s", global_params.dbname) < 0)
237*7f2fe78bSCy Schubert             {
238*7f2fe78bSCy Schubert                 com_err(progname, ENOMEM,
239*7f2fe78bSCy Schubert                         _("while parsing command arguments"));
240*7f2fe78bSCy Schubert                 exit(1);
241*7f2fe78bSCy Schubert             }
242*7f2fe78bSCy Schubert 
243*7f2fe78bSCy Schubert             if (!add_db_arg(db_name_tmp)) {
244*7f2fe78bSCy Schubert                 com_err(progname, ENOMEM,
245*7f2fe78bSCy Schubert                         _("while parsing command arguments\n"));
246*7f2fe78bSCy Schubert                 exit(1);
247*7f2fe78bSCy Schubert             }
248*7f2fe78bSCy Schubert 
249*7f2fe78bSCy Schubert         } else if (strcmp(*argv, "-x") == 0 && ARG_VAL) {
250*7f2fe78bSCy Schubert             if (!add_db_arg(koptarg)) {
251*7f2fe78bSCy Schubert                 com_err(progname, ENOMEM,
252*7f2fe78bSCy Schubert                         _("while parsing command arguments\n"));
253*7f2fe78bSCy Schubert                 exit(1);
254*7f2fe78bSCy Schubert             }
255*7f2fe78bSCy Schubert 
256*7f2fe78bSCy Schubert         } else if (strcmp(*argv, "-r") == 0 && ARG_VAL) {
257*7f2fe78bSCy Schubert             global_params.realm = koptarg;
258*7f2fe78bSCy Schubert             global_params.mask |= KADM5_CONFIG_REALM;
259*7f2fe78bSCy Schubert             /* not sure this is really necessary */
260*7f2fe78bSCy Schubert             if ((retval = krb5_set_default_realm(util_context,
261*7f2fe78bSCy Schubert                                                  global_params.realm))) {
262*7f2fe78bSCy Schubert                 com_err(progname, retval,
263*7f2fe78bSCy Schubert                         _("while setting default realm name"));
264*7f2fe78bSCy Schubert                 exit(1);
265*7f2fe78bSCy Schubert             }
266*7f2fe78bSCy Schubert         } else if (strcmp(*argv, "-k") == 0 && ARG_VAL) {
267*7f2fe78bSCy Schubert             if (krb5_string_to_enctype(koptarg, &global_params.enctype)) {
268*7f2fe78bSCy Schubert                 com_err(progname, EINVAL, _(": %s is an invalid enctype"),
269*7f2fe78bSCy Schubert                         koptarg);
270*7f2fe78bSCy Schubert                 exit(1);
271*7f2fe78bSCy Schubert             } else
272*7f2fe78bSCy Schubert                 global_params.mask |= KADM5_CONFIG_ENCTYPE;
273*7f2fe78bSCy Schubert         } else if (strcmp(*argv, "-kv") == 0 && ARG_VAL) {
274*7f2fe78bSCy Schubert             global_params.kvno = (krb5_kvno) atoi(koptarg);
275*7f2fe78bSCy Schubert             if (global_params.kvno == IGNORE_VNO) {
276*7f2fe78bSCy Schubert                 com_err(progname, EINVAL, _(": %s is an invalid mkeyVNO"),
277*7f2fe78bSCy Schubert                         koptarg);
278*7f2fe78bSCy Schubert                 exit(1);
279*7f2fe78bSCy Schubert             } else
280*7f2fe78bSCy Schubert                 global_params.mask |= KADM5_CONFIG_KVNO;
281*7f2fe78bSCy Schubert         } else if (strcmp(*argv, "-M") == 0 && ARG_VAL) {
282*7f2fe78bSCy Schubert             global_params.mkey_name = koptarg;
283*7f2fe78bSCy Schubert             global_params.mask |= KADM5_CONFIG_MKEY_NAME;
284*7f2fe78bSCy Schubert         } else if (strcmp(*argv, "-sf") == 0 && ARG_VAL) {
285*7f2fe78bSCy Schubert             global_params.stash_file = koptarg;
286*7f2fe78bSCy Schubert             global_params.mask |= KADM5_CONFIG_STASH_FILE;
287*7f2fe78bSCy Schubert         } else if (strcmp(*argv, "-m") == 0) {
288*7f2fe78bSCy Schubert             manual_mkey = TRUE;
289*7f2fe78bSCy Schubert             global_params.mkey_from_kbd = 1;
290*7f2fe78bSCy Schubert             global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
291*7f2fe78bSCy Schubert         } else {
292*7f2fe78bSCy Schubert             cmd_argv[cmd_argc++] = *argv;
293*7f2fe78bSCy Schubert         }
294*7f2fe78bSCy Schubert         argv++; argc--;
295*7f2fe78bSCy Schubert     }
296*7f2fe78bSCy Schubert 
297*7f2fe78bSCy Schubert     if (cmd_argv[0] == NULL)
298*7f2fe78bSCy Schubert         usage();
299*7f2fe78bSCy Schubert     cmd = cmd_lookup(cmd_argv[0]);
300*7f2fe78bSCy Schubert     if (cmd == NULL)
301*7f2fe78bSCy Schubert         usage();
302*7f2fe78bSCy Schubert 
303*7f2fe78bSCy Schubert     if( !util_context->default_realm )
304*7f2fe78bSCy Schubert     {
305*7f2fe78bSCy Schubert         char *temp = NULL;
306*7f2fe78bSCy Schubert         retval = krb5_get_default_realm(util_context, &temp);
307*7f2fe78bSCy Schubert         if( retval )
308*7f2fe78bSCy Schubert         {
309*7f2fe78bSCy Schubert             com_err(progname, retval, _("while getting default realm"));
310*7f2fe78bSCy Schubert             exit(1);
311*7f2fe78bSCy Schubert         }
312*7f2fe78bSCy Schubert         krb5_free_default_realm(util_context, temp);
313*7f2fe78bSCy Schubert     }
314*7f2fe78bSCy Schubert 
315*7f2fe78bSCy Schubert     retval = kadm5_get_config_params(util_context, 1,
316*7f2fe78bSCy Schubert                                      &global_params, &global_params);
317*7f2fe78bSCy Schubert     if (retval) {
318*7f2fe78bSCy Schubert         com_err(progname, retval,
319*7f2fe78bSCy Schubert                 _("while retrieving configuration parameters"));
320*7f2fe78bSCy Schubert         exit(1);
321*7f2fe78bSCy Schubert     }
322*7f2fe78bSCy Schubert 
323*7f2fe78bSCy Schubert     /*
324*7f2fe78bSCy Schubert      * Dump creates files which should not be world-readable.  It is
325*7f2fe78bSCy Schubert      * easiest to do a single umask call here.
326*7f2fe78bSCy Schubert      */
327*7f2fe78bSCy Schubert     (void) umask(077);
328*7f2fe78bSCy Schubert 
329*7f2fe78bSCy Schubert     master_keyblock.enctype = global_params.enctype;
330*7f2fe78bSCy Schubert     if ((master_keyblock.enctype != ENCTYPE_UNKNOWN) &&
331*7f2fe78bSCy Schubert         (!krb5_c_valid_enctype(master_keyblock.enctype))) {
332*7f2fe78bSCy Schubert         com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
333*7f2fe78bSCy Schubert                 "while setting up enctype %d", master_keyblock.enctype);
334*7f2fe78bSCy Schubert     }
335*7f2fe78bSCy Schubert 
336*7f2fe78bSCy Schubert     if (cmd->opendb && open_db_and_mkey())
337*7f2fe78bSCy Schubert         return exit_status;
338*7f2fe78bSCy Schubert 
339*7f2fe78bSCy Schubert     if (global_params.iprop_enabled == TRUE)
340*7f2fe78bSCy Schubert         ulog_set_role(util_context, IPROP_PRIMARY);
341*7f2fe78bSCy Schubert     else
342*7f2fe78bSCy Schubert         ulog_set_role(util_context, IPROP_NULL);
343*7f2fe78bSCy Schubert 
344*7f2fe78bSCy Schubert     (*cmd->func)(cmd_argc, cmd_argv);
345*7f2fe78bSCy Schubert 
346*7f2fe78bSCy Schubert     if( db_name_tmp )
347*7f2fe78bSCy Schubert         free( db_name_tmp );
348*7f2fe78bSCy Schubert 
349*7f2fe78bSCy Schubert     if( db5util_db_args )
350*7f2fe78bSCy Schubert         free(db5util_db_args);
351*7f2fe78bSCy Schubert 
352*7f2fe78bSCy Schubert     quit();
353*7f2fe78bSCy Schubert     kadm5_free_config_params(util_context, &global_params);
354*7f2fe78bSCy Schubert     krb5_free_context(util_context);
355*7f2fe78bSCy Schubert     free(cmd_argv);
356*7f2fe78bSCy Schubert     return exit_status;
357*7f2fe78bSCy Schubert }
358*7f2fe78bSCy Schubert 
359*7f2fe78bSCy Schubert /*
360*7f2fe78bSCy Schubert  * open_db_and_mkey: Opens the KDC and policy database, and sets the
361*7f2fe78bSCy Schubert  * global master_* variables.  Sets dbactive to TRUE if the databases
362*7f2fe78bSCy Schubert  * are opened, and valid_master_key to 1 if the global master
363*7f2fe78bSCy Schubert  * variables are set properly.  Returns 0 on success, and 1 on
364*7f2fe78bSCy Schubert  * failure, but it is not considered a failure if the master key
365*7f2fe78bSCy Schubert  * cannot be fetched (the master key stash file may not exist when the
366*7f2fe78bSCy Schubert  * program is run).
367*7f2fe78bSCy Schubert  */
open_db_and_mkey()368*7f2fe78bSCy Schubert static int open_db_and_mkey()
369*7f2fe78bSCy Schubert {
370*7f2fe78bSCy Schubert     krb5_error_code retval;
371*7f2fe78bSCy Schubert     krb5_data scratch, pwd, seed;
372*7f2fe78bSCy Schubert 
373*7f2fe78bSCy Schubert     dbactive = FALSE;
374*7f2fe78bSCy Schubert     valid_master_key = 0;
375*7f2fe78bSCy Schubert 
376*7f2fe78bSCy Schubert     if ((retval = krb5_db_open(util_context, db5util_db_args,
377*7f2fe78bSCy Schubert                                KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) {
378*7f2fe78bSCy Schubert         com_err(progname, retval, _("while initializing database"));
379*7f2fe78bSCy Schubert         exit_status++;
380*7f2fe78bSCy Schubert         return(1);
381*7f2fe78bSCy Schubert     }
382*7f2fe78bSCy Schubert 
383*7f2fe78bSCy Schubert     /* assemble & parse the master key name */
384*7f2fe78bSCy Schubert 
385*7f2fe78bSCy Schubert     if ((retval = krb5_db_setup_mkey_name(util_context,
386*7f2fe78bSCy Schubert                                           global_params.mkey_name,
387*7f2fe78bSCy Schubert                                           global_params.realm,
388*7f2fe78bSCy Schubert                                           &mkey_fullname, &master_princ))) {
389*7f2fe78bSCy Schubert         com_err(progname, retval, _("while setting up master key name"));
390*7f2fe78bSCy Schubert         exit_status++;
391*7f2fe78bSCy Schubert         return(1);
392*7f2fe78bSCy Schubert     }
393*7f2fe78bSCy Schubert     if ((retval = krb5_db_get_principal(util_context, master_princ, 0,
394*7f2fe78bSCy Schubert                                         &master_entry))) {
395*7f2fe78bSCy Schubert         com_err(progname, retval, _("while retrieving master entry"));
396*7f2fe78bSCy Schubert         exit_status++;
397*7f2fe78bSCy Schubert         (void) krb5_db_fini(util_context);
398*7f2fe78bSCy Schubert         return(1);
399*7f2fe78bSCy Schubert     }
400*7f2fe78bSCy Schubert 
401*7f2fe78bSCy Schubert     if (global_params.mask & KADM5_CONFIG_KVNO)
402*7f2fe78bSCy Schubert         master_kvno = global_params.kvno; /* user specified */
403*7f2fe78bSCy Schubert     else
404*7f2fe78bSCy Schubert         master_kvno = IGNORE_VNO;
405*7f2fe78bSCy Schubert 
406*7f2fe78bSCy Schubert     /* the databases are now open, and the master principal exists */
407*7f2fe78bSCy Schubert     dbactive = TRUE;
408*7f2fe78bSCy Schubert 
409*7f2fe78bSCy Schubert     if (mkey_password) {
410*7f2fe78bSCy Schubert         pwd.data = mkey_password;
411*7f2fe78bSCy Schubert         pwd.length = strlen(mkey_password);
412*7f2fe78bSCy Schubert         retval = krb5_principal2salt(util_context, master_princ, &scratch);
413*7f2fe78bSCy Schubert         if (retval) {
414*7f2fe78bSCy Schubert             com_err(progname, retval, _("while calculated master key salt"));
415*7f2fe78bSCy Schubert             exit_status++;
416*7f2fe78bSCy Schubert             return(1);
417*7f2fe78bSCy Schubert         }
418*7f2fe78bSCy Schubert 
419*7f2fe78bSCy Schubert         /* If no encryption type is set, use the default */
420*7f2fe78bSCy Schubert         if (master_keyblock.enctype == ENCTYPE_UNKNOWN)
421*7f2fe78bSCy Schubert             master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
422*7f2fe78bSCy Schubert         if (!krb5_c_valid_enctype(master_keyblock.enctype))
423*7f2fe78bSCy Schubert             com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
424*7f2fe78bSCy Schubert                     "while setting up enctype %d",
425*7f2fe78bSCy Schubert                     master_keyblock.enctype);
426*7f2fe78bSCy Schubert 
427*7f2fe78bSCy Schubert         retval = krb5_c_string_to_key(util_context, master_keyblock.enctype,
428*7f2fe78bSCy Schubert                                       &pwd, &scratch, &master_keyblock);
429*7f2fe78bSCy Schubert         if (retval) {
430*7f2fe78bSCy Schubert             com_err(progname, retval,
431*7f2fe78bSCy Schubert                     _("while transforming master key from password"));
432*7f2fe78bSCy Schubert             exit_status++;
433*7f2fe78bSCy Schubert             return(1);
434*7f2fe78bSCy Schubert         }
435*7f2fe78bSCy Schubert         free(scratch.data);
436*7f2fe78bSCy Schubert         mkey_password = 0;
437*7f2fe78bSCy Schubert 
438*7f2fe78bSCy Schubert     } else {
439*7f2fe78bSCy Schubert         if ((retval = krb5_db_fetch_mkey(util_context, master_princ,
440*7f2fe78bSCy Schubert                                          master_keyblock.enctype,
441*7f2fe78bSCy Schubert                                          manual_mkey, FALSE,
442*7f2fe78bSCy Schubert                                          global_params.stash_file,
443*7f2fe78bSCy Schubert                                          &master_kvno,
444*7f2fe78bSCy Schubert                                          0, &master_keyblock))) {
445*7f2fe78bSCy Schubert             com_err(progname, retval, _("while reading master key"));
446*7f2fe78bSCy Schubert             com_err(progname, 0, _("Warning: proceeding without master key"));
447*7f2fe78bSCy Schubert             exit_status++;
448*7f2fe78bSCy Schubert             return(0);
449*7f2fe78bSCy Schubert         }
450*7f2fe78bSCy Schubert     }
451*7f2fe78bSCy Schubert 
452*7f2fe78bSCy Schubert     if ((retval = krb5_db_fetch_mkey_list(util_context, master_princ,
453*7f2fe78bSCy Schubert                                           &master_keyblock))) {
454*7f2fe78bSCy Schubert         com_err(progname, retval, "while getting master key list");
455*7f2fe78bSCy Schubert         com_err(progname, 0, "Warning: proceeding without master key list");
456*7f2fe78bSCy Schubert         exit_status++;
457*7f2fe78bSCy Schubert         return(0);
458*7f2fe78bSCy Schubert     }
459*7f2fe78bSCy Schubert 
460*7f2fe78bSCy Schubert     seed.length = master_keyblock.length;
461*7f2fe78bSCy Schubert     seed.data = (char *) master_keyblock.contents;
462*7f2fe78bSCy Schubert 
463*7f2fe78bSCy Schubert     if ((retval = krb5_c_random_seed(util_context, &seed))) {
464*7f2fe78bSCy Schubert         com_err(progname, retval, _("while seeding random number generator"));
465*7f2fe78bSCy Schubert         exit_status++;
466*7f2fe78bSCy Schubert         memset(master_keyblock.contents, 0, master_keyblock.length);
467*7f2fe78bSCy Schubert         krb5_free_keyblock_contents(util_context, &master_keyblock);
468*7f2fe78bSCy Schubert         return(1);
469*7f2fe78bSCy Schubert     }
470*7f2fe78bSCy Schubert 
471*7f2fe78bSCy Schubert     if (global_params.iprop_enabled) {
472*7f2fe78bSCy Schubert         if (ulog_map(util_context, global_params.iprop_logfile,
473*7f2fe78bSCy Schubert                      global_params.iprop_ulogsize)) {
474*7f2fe78bSCy Schubert             fprintf(stderr, _("%s: Could not map log\n"), progname);
475*7f2fe78bSCy Schubert             exit_status++;
476*7f2fe78bSCy Schubert             return(1);
477*7f2fe78bSCy Schubert         }
478*7f2fe78bSCy Schubert     }
479*7f2fe78bSCy Schubert 
480*7f2fe78bSCy Schubert     valid_master_key = 1;
481*7f2fe78bSCy Schubert     dbactive = TRUE;
482*7f2fe78bSCy Schubert     return 0;
483*7f2fe78bSCy Schubert }
484*7f2fe78bSCy Schubert 
485*7f2fe78bSCy Schubert #ifdef HAVE_GETCWD
486*7f2fe78bSCy Schubert #undef getwd
487*7f2fe78bSCy Schubert #endif
488*7f2fe78bSCy Schubert 
489*7f2fe78bSCy Schubert int
quit()490*7f2fe78bSCy Schubert quit()
491*7f2fe78bSCy Schubert {
492*7f2fe78bSCy Schubert     krb5_error_code retval;
493*7f2fe78bSCy Schubert     static krb5_boolean finished = 0;
494*7f2fe78bSCy Schubert 
495*7f2fe78bSCy Schubert     if (finished)
496*7f2fe78bSCy Schubert         return 0;
497*7f2fe78bSCy Schubert     ulog_fini(util_context);
498*7f2fe78bSCy Schubert     retval = krb5_db_fini(util_context);
499*7f2fe78bSCy Schubert     zapfree(master_keyblock.contents, master_keyblock.length);
500*7f2fe78bSCy Schubert     krb5_free_principal(util_context, master_princ);
501*7f2fe78bSCy Schubert     finished = TRUE;
502*7f2fe78bSCy Schubert     if (retval && retval != KRB5_KDB_DBNOTINITED) {
503*7f2fe78bSCy Schubert         com_err(progname, retval, _("while closing database"));
504*7f2fe78bSCy Schubert         exit_status++;
505*7f2fe78bSCy Schubert         return 1;
506*7f2fe78bSCy Schubert     }
507*7f2fe78bSCy Schubert     return 0;
508*7f2fe78bSCy Schubert }
509*7f2fe78bSCy Schubert 
510*7f2fe78bSCy Schubert static void
add_random_key(argc,argv)511*7f2fe78bSCy Schubert add_random_key(argc, argv)
512*7f2fe78bSCy Schubert     int argc;
513*7f2fe78bSCy Schubert     char **argv;
514*7f2fe78bSCy Schubert {
515*7f2fe78bSCy Schubert     krb5_error_code ret;
516*7f2fe78bSCy Schubert     krb5_principal princ;
517*7f2fe78bSCy Schubert     krb5_db_entry *dbent;
518*7f2fe78bSCy Schubert     krb5_timestamp now;
519*7f2fe78bSCy Schubert 
520*7f2fe78bSCy Schubert     krb5_key_salt_tuple *keysalts = NULL;
521*7f2fe78bSCy Schubert     krb5_int32 num_keysalts = 0;
522*7f2fe78bSCy Schubert 
523*7f2fe78bSCy Schubert     int free_keysalts;
524*7f2fe78bSCy Schubert     char *me = progname;
525*7f2fe78bSCy Schubert     char *ks_str = NULL;
526*7f2fe78bSCy Schubert     char *pr_str;
527*7f2fe78bSCy Schubert     krb5_keyblock *tmp_mkey;
528*7f2fe78bSCy Schubert 
529*7f2fe78bSCy Schubert     if (argc < 2)
530*7f2fe78bSCy Schubert         usage();
531*7f2fe78bSCy Schubert     for (argv++, argc--; *argv; argv++, argc--) {
532*7f2fe78bSCy Schubert         if (!strcmp(*argv, "-e")) {
533*7f2fe78bSCy Schubert             argv++; argc--;
534*7f2fe78bSCy Schubert             ks_str = *argv;
535*7f2fe78bSCy Schubert             continue;
536*7f2fe78bSCy Schubert         } else
537*7f2fe78bSCy Schubert             break;
538*7f2fe78bSCy Schubert     }
539*7f2fe78bSCy Schubert     if (argc < 1)
540*7f2fe78bSCy Schubert         usage();
541*7f2fe78bSCy Schubert     pr_str = *argv;
542*7f2fe78bSCy Schubert     ret = krb5_parse_name(util_context, pr_str, &princ);
543*7f2fe78bSCy Schubert     if (ret) {
544*7f2fe78bSCy Schubert         com_err(me, ret, _("while parsing principal name %s"), pr_str);
545*7f2fe78bSCy Schubert         exit_status++;
546*7f2fe78bSCy Schubert         return;
547*7f2fe78bSCy Schubert     }
548*7f2fe78bSCy Schubert     ret = krb5_db_get_principal(util_context, princ, 0, &dbent);
549*7f2fe78bSCy Schubert     if (ret) {
550*7f2fe78bSCy Schubert         com_err(me, ret, _("while fetching principal %s"), pr_str);
551*7f2fe78bSCy Schubert         exit_status++;
552*7f2fe78bSCy Schubert         return;
553*7f2fe78bSCy Schubert     }
554*7f2fe78bSCy Schubert     ret = krb5_string_to_keysalts(ks_str,
555*7f2fe78bSCy Schubert                                   NULL, NULL, 0,
556*7f2fe78bSCy Schubert                                   &keysalts,
557*7f2fe78bSCy Schubert                                   &num_keysalts);
558*7f2fe78bSCy Schubert     if (ret) {
559*7f2fe78bSCy Schubert         com_err(me, ret, _("while parsing keysalts %s"), ks_str);
560*7f2fe78bSCy Schubert         exit_status++;
561*7f2fe78bSCy Schubert         return;
562*7f2fe78bSCy Schubert     }
563*7f2fe78bSCy Schubert     if (!num_keysalts || keysalts == NULL) {
564*7f2fe78bSCy Schubert         num_keysalts = global_params.num_keysalts;
565*7f2fe78bSCy Schubert         keysalts = global_params.keysalts;
566*7f2fe78bSCy Schubert         free_keysalts = 0;
567*7f2fe78bSCy Schubert     } else
568*7f2fe78bSCy Schubert         free_keysalts = 1;
569*7f2fe78bSCy Schubert 
570*7f2fe78bSCy Schubert     /* Find the mkey used to protect the existing keys */
571*7f2fe78bSCy Schubert     ret = krb5_dbe_find_mkey(util_context, dbent, &tmp_mkey);
572*7f2fe78bSCy Schubert     if (ret) {
573*7f2fe78bSCy Schubert         com_err(me, ret, _("while finding mkey"));
574*7f2fe78bSCy Schubert         krb5_db_free_principal(util_context, dbent);
575*7f2fe78bSCy Schubert         exit_status++;
576*7f2fe78bSCy Schubert         return;
577*7f2fe78bSCy Schubert     }
578*7f2fe78bSCy Schubert 
579*7f2fe78bSCy Schubert     ret = krb5_dbe_ark(util_context, tmp_mkey, keysalts, num_keysalts, dbent);
580*7f2fe78bSCy Schubert     if (free_keysalts)
581*7f2fe78bSCy Schubert         free(keysalts);
582*7f2fe78bSCy Schubert     if (ret) {
583*7f2fe78bSCy Schubert         com_err(me, ret, "while randomizing principal %s", pr_str);
584*7f2fe78bSCy Schubert         krb5_db_free_principal(util_context, dbent);
585*7f2fe78bSCy Schubert         exit_status++;
586*7f2fe78bSCy Schubert         return;
587*7f2fe78bSCy Schubert     }
588*7f2fe78bSCy Schubert     dbent->attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
589*7f2fe78bSCy Schubert     ret = krb5_timeofday(util_context, &now);
590*7f2fe78bSCy Schubert     if (ret) {
591*7f2fe78bSCy Schubert         com_err(me, ret, _("while getting time"));
592*7f2fe78bSCy Schubert         krb5_db_free_principal(util_context, dbent);
593*7f2fe78bSCy Schubert         exit_status++;
594*7f2fe78bSCy Schubert         return;
595*7f2fe78bSCy Schubert     }
596*7f2fe78bSCy Schubert     ret = krb5_dbe_update_last_pwd_change(util_context, dbent, now);
597*7f2fe78bSCy Schubert     if (ret) {
598*7f2fe78bSCy Schubert         com_err(me, ret, _("while setting changetime"));
599*7f2fe78bSCy Schubert         krb5_db_free_principal(util_context, dbent);
600*7f2fe78bSCy Schubert         exit_status++;
601*7f2fe78bSCy Schubert         return;
602*7f2fe78bSCy Schubert     }
603*7f2fe78bSCy Schubert     ret = krb5_db_put_principal(util_context, dbent);
604*7f2fe78bSCy Schubert     krb5_db_free_principal(util_context, dbent);
605*7f2fe78bSCy Schubert     if (ret) {
606*7f2fe78bSCy Schubert         com_err(me, ret, _("while saving principal %s"), pr_str);
607*7f2fe78bSCy Schubert         exit_status++;
608*7f2fe78bSCy Schubert         return;
609*7f2fe78bSCy Schubert     }
610*7f2fe78bSCy Schubert     printf(_("%s changed\n"), pr_str);
611*7f2fe78bSCy Schubert }
612