2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
9 * Openvision retains the copyright to derivative works of
10 * this source code. Do *NOT* create a derivative of this
11 * source code before consulting with your legal department.
12 * Do *NOT* integrate *ANY* of this source code into another
13 * product before consulting with your legal department.
15 * For further information, read the top-level Openvision
16 * copyright which is contained in the top-level MIT Kerberos
19 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
25 * admin/edit/kdb5_edit.c
27 * (C) Copyright 1990,1991, 1996 by the Massachusetts Institute of Technology.
28 * All Rights Reserved.
30 * Export of this software from the United States of America may
31 * require a specific license from the United States Government.
32 * It is the responsibility of any person or organization contemplating
33 * export to obtain such a license before exporting.
35 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
36 * distribute this software and its documentation for any purpose and
37 * without fee is hereby granted, provided that the above copyright
38 * notice appear in all copies and that both that copyright notice and
39 * this permission notice appear in supporting documentation, and that
40 * the name of M.I.T. not be used in advertising or publicity pertaining
41 * to distribution of the software without specific, written prior
42 * permission. Furthermore if you modify this software you must label
43 * your software as modified software and not distribute it in such a
44 * fashion that it might be confused with the original M.I.T. software.
45 * M.I.T. makes no representations about the suitability of
46 * this software for any purpose. It is provided "as is" without express
47 * or implied warranty.
50 * Edit a KDC database.
54 * Copyright (C) 1998 by the FundsXpress, INC.
56 * All rights reserved.
58 * Export of this software from the United States of America may require
59 * a specific license from the United States Government. It is the
60 * responsibility of any person or organization contemplating export to
61 * obtain such a license before exporting.
63 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
64 * distribute this software and its documentation for any purpose and
65 * without fee is hereby granted, provided that the above copyright
66 * notice appear in all copies and that both that copyright notice and
67 * this permission notice appear in supporting documentation, and that
68 * the name of FundsXpress. not be used in advertising or publicity pertaining
69 * to distribution of the software without specific, written prior
70 * permission. FundsXpress makes no representations about the suitability of
71 * this software for any purpose. It is provided "as is" without express
72 * or implied warranty.
74 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
75 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
76 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
80 * Yes, I know this is a hack, but we need admin.h without including the
81 * rpc.h header. Additionally, our rpc.h header brings in
82 * a des.h header which causes other problems.
88 #include <kadm5/admin.h>
89 #include <rpc/types.h>
90 #include <krb5/adm_proto.h>
95 #include "kdb5_util.h"
97 char *Err_no_master_msg
= "Master key not entered!\n";
98 char *Err_no_database
= "Database not currently opened!\n";
101 * XXX Ick, ick, ick. These global variables shouldn't be global....
103 char *mkey_password
= 0;
106 * I can't figure out any way for this not to be global, given how ss
111 krb5_context util_context
;
112 kadm5_config_params global_params
;
116 fprintf(stderr
, "%s: "
117 "kdb5_util [-x db_args]* [-r realm] [-d dbname] [-k mkeytype] [-M mkeyname]\n"
118 "\t [-sf stashfilename] [-P password] [-m] cmd [cmd_options]\n"
121 "\tstash [-f keyfile]\n"
122 "\tdump [-old] [-ov] [-b6] [-verbose] [filename [princs...]]\n"
123 "\t [-mkey_convert] [-new_mkey_file mkey_file]\n"
124 "\t [-rev] [-recurse] [filename [princs...]]\n"
125 "\tload [-old] [-ov] [-b6] [-verbose] [-update] filename\n"
126 "\tark [-e etype_list] principal\n"
127 "\nwhere,\n\t[-x db_args]* - any number of database specific arguments.\n"
128 "\t\t\tLook at each database documentation for supported arguments\n",
133 krb5_keyblock master_key
;
134 extern krb5_principal master_princ
;
135 krb5_db_entry master_entry
;
136 int valid_master_key
= 0;
139 krb5_boolean manual_mkey
= FALSE
;
140 krb5_boolean dbactive
= FALSE
;
142 static int open_db_and_mkey(void);
144 static void add_random_key(int, char **);
146 typedef void (*cmd_func
)(int, char **);
153 {"create", kdb5_create
, 0},
154 {"destroy", kdb5_destroy
, 1},
155 {"stash", kdb5_stash
, 1},
156 {"dump", dump_db
, 1},
157 {"load", load_db
, 0},
158 {"ark", add_random_key
, 1},
162 static struct _cmd_table
*cmd_lookup(name
)
165 struct _cmd_table
*cmd
= cmd_table
;
167 if (strcmp(cmd
->name
, name
) == 0)
176 #define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(usage(), NULL))
178 char **db5util_db_args
= NULL
;
179 int db5util_db_args_size
= 0;
181 static void extended_com_err_fn (const char *myprog
, errcode_t code
,
182 const char *fmt
, va_list args
)
186 emsg
= krb5_get_error_message (util_context
, code
);
187 fprintf (stderr
, "%s: %s ", myprog
, emsg
);
188 krb5_free_error_message (util_context
, emsg
);
190 fprintf (stderr
, "%s: ", myprog
);
192 vfprintf (stderr
, fmt
, args
);
193 fprintf (stderr
, "\n");
196 int add_db_arg(char *arg
)
199 db5util_db_args_size
++;
200 temp
= realloc(db5util_db_args
,
201 sizeof(char *) * (db5util_db_args_size
+ 1));
204 db5util_db_args
= temp
;
205 db5util_db_args
[db5util_db_args_size
-1] = arg
;
206 db5util_db_args
[db5util_db_args_size
] = NULL
;
214 struct _cmd_table
*cmd
= NULL
;
215 char *koptarg
, **cmd_argv
;
216 char *db_name_tmp
= NULL
;
218 krb5_error_code retval
;
220 (void) setlocale(LC_ALL
, "");
221 set_com_err_hook(extended_com_err_fn
);
223 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
224 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
227 (void) textdomain(TEXT_DOMAIN
);
229 Err_no_master_msg
= gettext("Master key not entered!\n");
230 Err_no_database
= gettext("Database not currently opened!\n");
234 * Ensure that "progname" is set before calling com_err.
236 progname
= (strrchr(argv
[0], '/') ?
237 strrchr(argv
[0], '/') + 1 : argv
[0]);
239 retval
= kadm5_init_krb5_context(&util_context
);
241 com_err (progname
, retval
,
242 gettext("while initializing Kerberos code"));
246 cmd_argv
= (char **) malloc(sizeof(char *)*argc
);
247 if (cmd_argv
== NULL
) {
248 com_err(progname
, ENOMEM
,
249 gettext("while creating sub-command arguments"));
252 memset(cmd_argv
, 0, sizeof(char *)*argc
);
257 if (strcmp(*argv
, "-P") == 0 && ARG_VAL
) {
258 mkey_password
= koptarg
;
260 } else if (strcmp(*argv
, "-d") == 0 && ARG_VAL
) {
261 global_params
.dbname
= koptarg
;
262 global_params
.mask
|= KADM5_CONFIG_DBNAME
;
264 db_name_tmp
= malloc( strlen(global_params
.dbname
) + sizeof("dbname="));
265 if( db_name_tmp
== NULL
)
267 com_err(progname
, ENOMEM
, "while parsing command arguments");
271 strcpy( db_name_tmp
, "dbname=");
272 strcat( db_name_tmp
, global_params
.dbname
);
274 if (!add_db_arg(db_name_tmp
)) {
275 com_err(progname
, ENOMEM
, "while parsing command arguments\n");
279 } else if (strcmp(*argv
, "-x") == 0 && ARG_VAL
) {
280 if (!add_db_arg(koptarg
)) {
281 com_err(progname
, ENOMEM
, "while parsing command arguments\n");
285 } else if (strcmp(*argv
, "-r") == 0 && ARG_VAL
) {
286 global_params
.realm
= koptarg
;
287 global_params
.mask
|= KADM5_CONFIG_REALM
;
288 /* not sure this is really necessary */
289 if ((retval
= krb5_set_default_realm(util_context
,
290 global_params
.realm
))) {
291 com_err(progname
, retval
,
292 gettext("while setting default "
296 } else if (strcmp(*argv
, "-k") == 0 && ARG_VAL
) {
297 if (krb5_string_to_enctype(koptarg
, &global_params
.enctype
)) {
298 /* Solaris Kerberos */
299 com_err(progname
, 0, gettext("%s is an invalid enctype"), koptarg
);
302 global_params
.mask
|= KADM5_CONFIG_ENCTYPE
;
303 } else if (strcmp(*argv
, "-M") == 0 && ARG_VAL
) {
304 global_params
.mkey_name
= koptarg
;
305 global_params
.mask
|= KADM5_CONFIG_MKEY_NAME
;
306 } else if (((strcmp(*argv
, "-sf") == 0)
307 /* SUNWresync121 - carry the old -f forward too */
308 || (strcmp(*argv
, "-f") == 0)) && ARG_VAL
) {
309 global_params
.stash_file
= koptarg
;
310 global_params
.mask
|= KADM5_CONFIG_STASH_FILE
;
311 } else if (strcmp(*argv
, "-m") == 0) {
313 global_params
.mkey_from_kbd
= 1;
314 global_params
.mask
|= KADM5_CONFIG_MKEY_FROM_KBD
;
315 } else if (cmd_lookup(*argv
) != NULL
) {
316 if (cmd_argv
[0] == NULL
)
321 cmd_argv
[cmd_argc
++] = *argv
;
326 if (cmd_argv
[0] == NULL
)
329 if( !util_context
->default_realm
)
332 retval
= krb5_get_default_realm(util_context
, &temp
);
335 com_err (progname
, retval
, "while getting default realm");
338 util_context
->default_realm
= temp
;
341 retval
= kadm5_get_config_params(util_context
, 1,
342 &global_params
, &global_params
);
344 /* Solaris Kerberos */
345 com_err(progname
, retval
,
346 gettext("while retreiving configuration parameters"));
351 * Dump creates files which should not be world-readable. It is
352 * easiest to do a single umask call here.
356 (void) memset(&master_key
, 0, sizeof (krb5_keyblock
));
358 if ((global_params
.enctype
!= ENCTYPE_UNKNOWN
) &&
359 (!krb5_c_valid_enctype(global_params
.enctype
))) {
360 /* Solaris Kerberos */
361 com_err(progname
, KRB5_PROG_KEYTYPE_NOSUPP
,
362 gettext("while setting up enctype %d"), global_params
.enctype
);
366 cmd
= cmd_lookup(cmd_argv
[0]);
367 if (cmd
->opendb
&& open_db_and_mkey())
370 if (global_params
.iprop_enabled
== TRUE
)
371 ulog_set_role(util_context
, IPROP_MASTER
);
373 ulog_set_role(util_context
, IPROP_NULL
);
375 (*cmd
->func
)(cmd_argc
, cmd_argv
);
380 if( db5util_db_args
)
381 free(db5util_db_args
);
383 kadm5_free_config_params(util_context
, &global_params
);
384 krb5_free_context(util_context
);
390 * This function is no longer used in kdb5_util (and it would no
391 * longer work, anyway).
393 void set_dbname(argc
, argv
)
397 krb5_error_code retval
;
400 /* Solaris Kerberos */
401 com_err(progname
, 0, gettext("Too few arguments"));
402 com_err(progname
, 0, gettext("Usage: %s dbpathname realmname"),
408 if ((retval
= krb5_db_fini(util_context
)) && retval
!= KRB5_KDB_DBNOTINITED
) {
409 /* Solaris Kerberos */
410 com_err(progname
, retval
, gettext("while closing previous database"));
414 if (valid_master_key
) {
415 krb5_free_keyblock_contents(util_context
, &master_key
);
416 master_key
.contents
= NULL
;
417 valid_master_key
= 0;
419 krb5_free_principal(util_context
, master_princ
);
423 /* Solaris Kerberos */
424 (void) set_dbname_help(progname
, argv
[1]);
430 * open_db_and_mkey: Opens the KDC and policy database, and sets the
431 * global master_* variables. Sets dbactive to TRUE if the databases
432 * are opened, and valid_master_key to 1 if the global master
433 * variables are set properly. Returns 0 on success, and 1 on
434 * failure, but it is not considered a failure if the master key
435 * cannot be fetched (the master key stash file may not exist when the
438 static int open_db_and_mkey()
440 krb5_error_code retval
;
443 krb5_data scratch
, pwd
, seed
;
446 valid_master_key
= 0;
448 if ((retval
= krb5_db_open(util_context
, db5util_db_args
,
449 KRB5_KDB_OPEN_RW
| KRB5_KDB_SRV_TYPE_ADMIN
))) {
450 com_err(progname
, retval
, "while initializing database");
455 /* assemble & parse the master key name */
457 if ((retval
= krb5_db_setup_mkey_name(util_context
,
458 global_params
.mkey_name
,
460 0, &master_princ
))) {
461 com_err(progname
, retval
,
462 gettext("while setting up master key name"));
467 if ((retval
= krb5_db_get_principal(util_context
, master_princ
,
468 &master_entry
, &nentries
, &more
))) {
469 com_err(progname
, retval
,
470 gettext("while retrieving master entry"));
472 (void) krb5_db_fini(util_context
);
475 com_err(progname
, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE
,
476 gettext("while retrieving master entry"));
478 (void) krb5_db_fini(util_context
);
480 } else if (!nentries
) {
481 com_err(progname
, KRB5_KDB_NOENTRY
,
482 gettext("while retrieving master entry"));
484 (void) krb5_db_fini(util_context
);
488 krb5_db_free_principal(util_context
, &master_entry
, nentries
);
490 /* the databases are now open, and the master principal exists */
494 pwd
.data
= mkey_password
;
495 pwd
.length
= strlen(mkey_password
);
496 retval
= krb5_principal2salt(util_context
, master_princ
, &scratch
);
498 com_err(progname
, retval
,
499 gettext("while calculated master key salt"));
500 /* Solaris Kerberos */
505 /* If no encryption type is set, use the default */
506 if (global_params
.enctype
== ENCTYPE_UNKNOWN
) {
507 global_params
.enctype
= DEFAULT_KDC_ENCTYPE
;
508 if (!krb5_c_valid_enctype(global_params
.enctype
))
509 com_err(progname
, KRB5_PROG_KEYTYPE_NOSUPP
,
510 gettext("while setting up enctype %d"),
511 global_params
.enctype
);
514 retval
= krb5_c_string_to_key(util_context
, global_params
.enctype
,
515 &pwd
, &scratch
, &master_key
);
517 com_err(progname
, retval
,
518 gettext("while transforming master key from password"));
519 /* Solaris Kerberos */
525 } else if ((retval
= krb5_db_fetch_mkey(util_context
, master_princ
,
526 global_params
.enctype
,
528 global_params
.stash_file
,
530 com_err(progname
, retval
,
531 gettext("while reading master key"));
533 gettext("Warning: proceeding without master key"));
535 * Solaris Kerberos: We don't want to count as an error if for instance
536 * the stash file is not present and we are trying to automate
537 * propagation, which really doesn't need a master key to do so.
539 if (retval
!= KRB5_KDB_CANTREAD_STORED
)
543 if ((retval
= krb5_db_verify_master_key(util_context
, master_princ
,
545 com_err(progname
, retval
,
546 gettext("while verifying master key"));
548 krb5_free_keyblock_contents(util_context
, &master_key
);
552 seed
.length
= master_key
.length
;
553 seed
.data
= (char *)master_key
.contents
;
555 if ((retval
= krb5_c_random_seed(util_context
, &seed
))) {
556 com_err(progname
, retval
,
557 gettext("while initializing random key generator"));
559 krb5_free_keyblock_contents(util_context
, &master_key
);
563 valid_master_key
= 1;
575 krb5_error_code retval
;
576 static krb5_boolean finished
= 0;
580 retval
= krb5_db_fini(util_context
);
581 krb5_free_keyblock_contents(util_context
, &master_key
);
583 krb5_free_context(util_context
);
584 if (retval
&& retval
!= KRB5_KDB_DBNOTINITED
) {
585 com_err(progname
, retval
, gettext("while closing database"));
593 add_random_key(argc
, argv
)
598 krb5_principal princ
;
604 krb5_key_salt_tuple
*keysalts
= NULL
;
605 krb5_int32 num_keysalts
= 0;
608 /* Solaris Kerberos */
615 for (argv
++, argc
--; *argv
; argv
++, argc
--) {
616 if (!strcmp(*argv
, "-e")) {
626 ret
= krb5_parse_name(util_context
, pr_str
, &princ
);
628 com_err(me
, ret
, gettext("while parsing principal name %s"), pr_str
);
633 ret
= krb5_db_get_principal(util_context
, princ
, &dbent
,
636 com_err(me
, ret
, gettext("while fetching principal %s"), pr_str
);
641 fprintf(stderr
, gettext("principal %s not found\n"), pr_str
);
646 fprintf(stderr
, gettext("principal %s not unique\n"), pr_str
);
647 krb5_db_free_principal(util_context
, &dbent
, 1);
651 ret
= krb5_string_to_keysalts(ks_str
,
656 com_err(me
, ret
, gettext("while parsing keysalts %s"), ks_str
);
660 if (!num_keysalts
|| keysalts
== NULL
) {
661 num_keysalts
= global_params
.num_keysalts
;
662 keysalts
= global_params
.keysalts
;
666 ret
= krb5_dbe_ark(util_context
, &master_key
,
667 keysalts
, num_keysalts
,
672 com_err(me
, ret
, gettext("while randomizing principal %s"), pr_str
);
673 krb5_db_free_principal(util_context
, &dbent
, 1);
677 dbent
.attributes
&= ~KRB5_KDB_REQUIRES_PWCHANGE
;
678 ret
= krb5_timeofday(util_context
, &now
);
680 com_err(me
, ret
, gettext("while getting time"));
681 krb5_db_free_principal(util_context
, &dbent
, 1);
685 ret
= krb5_dbe_update_last_pwd_change(util_context
, &dbent
, now
);
687 com_err(me
, ret
, gettext("while setting changetime"));
688 krb5_db_free_principal(util_context
, &dbent
, 1);
692 ret
= krb5_db_put_principal(util_context
, &dbent
, &n
);
693 krb5_db_free_principal(util_context
, &dbent
, 1);
695 com_err(me
, ret
, gettext("while saving principal %s"), pr_str
);
699 printf("%s changed\n", pr_str
);