1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * Copyright 1994, 2008 by the Massachusetts Institute of Technology.
6 * Export of this software from the United States of America may
7 * require a specific license from the United States Government.
8 * It is the responsibility of any person or organization contemplating
9 * export to obtain such a license before exporting.
11 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12 * distribute this software and its documentation for any purpose and
13 * without fee is hereby granted, provided that the above copyright
14 * notice appear in all copies and that both that copyright notice and
15 * this permission notice appear in supporting documentation, and that
16 * the name of M.I.T. not be used in advertising or publicity pertaining
17 * to distribution of the software without specific, written prior
18 * permission. Furthermore if you modify this software you must label
19 * your software as modified software and not distribute it in such a
20 * fashion that it might be confused with the original M.I.T. software.
21 * M.I.T. makes no representations about the suitability of
22 * this software for any purpose. It is provided "as is" without express
23 * or implied warranty.
26 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
30 /* Base functions for a kadmin command line interface using the OVSecure
35 #include <kadm5/admin.h>
36 #include <adm_proto.h>
41 #include <sys/types.h>
45 /* #include <sys/timeb.h> */
49 static krb5_boolean script_mode = FALSE;
51 char *def_realm = NULL;
56 char *ccache_name = NULL;
61 info(const char *fmt, ...)
62 #if !defined(__cplusplus) && (__GNUC__ > 2)
63 __attribute__((__format__(__printf__, 1, 2)))
68 error(const char *fmt, ...)
69 #if !defined(__cplusplus) && (__GNUC__ > 2)
70 __attribute__((__format__(__printf__, 1, 2)))
74 /* Like printf, but suppressed if script_mode is set. */
76 info(const char *fmt, ...)
87 /* Like fprintf to stderr; also set exit_status if script_mode is set. */
89 error(const char *fmt, ...)
96 vfprintf(stderr, fmt, ap);
103 error(_("Usage: %s [-r realm] [-p principal] [-q query] "
104 "[clnt|local args]\n"
105 " [command args...]\n"
106 "\tclnt args: [-s admin_server[:port]] "
107 "[[-c ccache]|[-k [-t keytab]]]|[-n]\n"
108 "\tlocal args: [-x db_args]* [-d dbname] "
109 "[-e \"enc:salt ...\"] [-m]"
110 "where,\n\t[-x db_args]* - any number of database specific "
112 "\t\t\tLook at each database documentation for supported "
113 "arguments\n"), whoami);
118 strdur(time_t duration)
121 int neg, days, hours, minutes, seconds;
128 days = duration / (24 * 3600);
129 duration %= 24 * 3600;
130 hours = duration / 3600;
132 minutes = duration / 60;
135 snprintf(out, sizeof(out), "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
136 days, days == 1 ? "day" : "days",
137 hours, minutes, seconds);
142 strdate(krb5_timestamp when)
146 time_t lcltim = ts2tt(when);
148 tm = localtime(&lcltim);
150 strftime(out, sizeof(out), "%a %b %d %H:%M:%S %Z %Y", tm) == 0)
151 strlcpy(out, "(error)", sizeof(out));
155 /* Parse a date string using getdate.y. On failure, output an error message
156 * and return (time_t)-1. */
158 parse_date(char *str, time_t now)
162 date = get_date_rel(str, now);
163 if (date == (time_t)-1)
164 error(_("Invalid date specification \"%s\".\n"), str);
169 * Parse a time interval. Use krb5_string_to_deltat() if it works; otherwise
170 * use getdate.y and subtract now, with sanity checks. On failure, output an
171 * error message and return (time_t)-1.
174 parse_interval(char *str, time_t now)
179 if (krb5_string_to_deltat(str, &delta) == 0)
182 date = parse_date(str, now);
183 if (date == (time_t)-1)
186 /* Interpret an absolute time of 0 (e.g. "never") as an interval of 0. */
190 /* Don't return a negative interval if the date is in the past. */
192 error(_("Interval specification \"%s\" is in the past.\n"), str);
199 /* this is a wrapper to go around krb5_parse_principal so we can set
200 the default realm up properly */
201 static krb5_error_code
202 kadmin_parse_name(char *name, krb5_principal *principal)
205 krb5_error_code retval;
208 /* assumes def_realm is initialized! */
209 cp = strchr(name, '@');
211 if (cp - name && *(cp - 1) != '\\')
214 cp = strchr(cp + 1, '@');
217 result = asprintf(&fullname, "%s@%s", name, def_realm);
219 result = asprintf(&fullname, "%s", name);
222 retval = krb5_parse_name(context, fullname, principal);
228 extended_com_err_fn(const char *myprog, errcode_t code,
229 const char *fmt, va_list args)
234 emsg = krb5_get_error_message(context, code);
235 error("%s: %s ", myprog, emsg);
236 krb5_free_error_message(context, emsg);
238 error("%s: ", myprog);
240 vfprintf(stderr, fmt, args);
244 /* Create a principal using the oldest appropriate kadm5 API. */
245 static krb5_error_code
246 create_princ(kadm5_principal_ent_rec *princ, long mask, int n_ks,
247 krb5_key_salt_tuple *ks, char *pass)
250 return kadm5_create_principal_3(handle, princ, mask, n_ks, ks, pass);
252 return kadm5_create_principal(handle, princ, mask, pass);
255 /* Randomize a principal's password using the appropriate kadm5 API. */
257 randkey_princ(void *lhandle, krb5_principal princ, krb5_boolean keepold,
258 int n_ks, krb5_key_salt_tuple *ks, krb5_keyblock **key,
263 /* Try the newer API first, because the Solaris kadmind only creates DES
264 * keys when the old API is used. */
265 ret = kadm5_randkey_principal_3(lhandle, princ, keepold, n_ks, ks, key,
268 /* Fall back to the old version if we get an error and aren't using any new
270 if (ret == KADM5_RPC_ERROR && !keepold && ks == NULL)
271 ret = kadm5_randkey_principal(lhandle, princ, key, n_keys);
277 policy_exists(const char *name)
279 kadm5_policy_ent_rec pol;
281 if (kadm5_get_policy(handle, (char *)name, &pol) != 0)
283 kadm5_free_policy_ent(handle, &pol);
288 kadmin_startup(int argc, char *argv[], char **request_out, char ***args_out)
291 char *princstr = NULL, *keytab_name = NULL, *query = NULL;
292 char *password = NULL;
293 char *luser, *canon, *cp;
294 int optchar, freeprinc = 0, use_keytab = 0, use_anonymous = 0;
298 krb5_principal princ;
299 kadm5_config_params params;
300 char **db_args = NULL;
301 int db_args_size = 0;
302 char *db_name = NULL;
303 char *svcname, *realm;
305 memset(¶ms, 0, sizeof(params));
307 set_com_err_hook(extended_com_err_fn);
309 retval = kadm5_init_krb5_context(&context);
311 com_err(whoami, retval, _("while initializing krb5 library"));
315 while ((optchar = getopt(argc, argv,
316 "+x:r:p:knq:w:d:s:mc:t:e:ON")) != EOF) {
320 db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1));
321 if (db_args == NULL) {
322 error(_("%s: Cannot initialize. Not enough memory\n"), whoami);
325 db_args[db_args_size - 1] = optarg;
326 db_args[db_args_size] = NULL;
336 ccache_name = optarg;
345 keytab_name = optarg;
354 /* db_name has to be passed as part of the db_args. */
356 asprintf(&db_name, "dbname=%s", optarg);
359 db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1));
360 if (db_args == NULL) {
361 error(_("%s: Cannot initialize. Not enough memory\n"), whoami);
364 db_args[db_args_size - 1] = db_name;
365 db_args[db_args_size] = NULL;
368 params.admin_server = optarg;
369 params.mask |= KADM5_CONFIG_ADMIN_SERVER;
372 params.mkey_from_kbd = 1;
373 params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
376 retval = krb5_string_to_keysalts(optarg, NULL, NULL, 0,
378 ¶ms.num_keysalts);
380 com_err(whoami, retval, _("while parsing keysalts %s"),
384 params.mask |= KADM5_CONFIG_ENCTYPES;
387 params.mask |= KADM5_CONFIG_OLD_AUTH_GSSAPI;
390 params.mask |= KADM5_CONFIG_AUTH_NOFALLBACK;
396 if ((ccache_name && use_keytab) ||
397 (keytab_name && !use_keytab) ||
398 (ccache_name && use_anonymous) ||
399 (use_anonymous && use_keytab))
402 if (query != NULL && argv[optind] != NULL) {
403 error(_("%s: -q is exclusive with command-line query"), whoami);
407 if (argv[optind] != NULL)
410 if (def_realm == NULL && krb5_get_default_realm(context, &def_realm)) {
411 error(_("%s: unable to get default realm\n"), whoami);
415 params.mask |= KADM5_CONFIG_REALM;
416 params.realm = def_realm;
418 if (params.mask & KADM5_CONFIG_OLD_AUTH_GSSAPI)
419 svcname = KADM5_ADMIN_SERVICE;
424 * Set cc to an open credentials cache, either specified by the -c
425 * argument or the default.
427 if (ccache_name == NULL) {
428 retval = krb5_cc_default(context, &cc);
430 com_err(whoami, retval,
431 _("while opening default credentials cache"));
435 retval = krb5_cc_resolve(context, ccache_name, &cc);
437 com_err(whoami, retval, _("while opening credentials cache %s"),
444 * If no principal name is specified: If authenticating anonymously, use
445 * the anonymouse principal for the local realm, else if a ccache was
446 * specified and its primary principal name can be read, it is used, else
447 * if a keytab was specified, the principal name is host/hostname,
448 * otherwise append "/admin" to the primary name of the default ccache,
451 * Gee, 100+ lines to figure out the client principal name. This
452 * should be compressed...
455 if (princstr == NULL) {
457 if (asprintf(&princstr, "%s/%s@%s", KRB5_WELLKNOWN_NAMESTR,
458 KRB5_ANONYMOUS_PRINCSTR, def_realm) < 0) {
459 error(_("%s: out of memory\n"), whoami);
463 } else if (ccache_name != NULL &&
464 !krb5_cc_get_principal(context, cc, &princ)) {
465 retval = krb5_unparse_name(context, princ, &princstr);
467 com_err(whoami, retval,
468 _("while canonicalizing principal name"));
471 krb5_free_principal(context, princ);
473 } else if (use_keytab != 0) {
474 retval = krb5_sname_to_principal(context, NULL, "host",
475 KRB5_NT_SRV_HST, &princ);
477 com_err(whoami, retval, _("creating host service principal"));
480 retval = krb5_unparse_name(context, princ, &princstr);
482 com_err(whoami, retval,
483 _("while canonicalizing principal name"));
486 krb5_free_principal(context, princ);
488 } else if (!krb5_cc_get_principal(context, cc, &princ)) {
489 if (krb5_unparse_name(context, princ, &canon)) {
490 error(_("%s: unable to canonicalize principal\n"), whoami);
493 /* Strip out realm of principal if it's there. */
494 realm = strchr(canon, '@');
496 if (realm > canon && *(realm - 1) != '\\')
498 realm = strchr(realm + 1, '@');
502 cp = strchr(canon, '/');
504 if (cp > canon && *(cp - 1) != '\\')
506 cp = strchr(cp + 1, '/');
510 if (asprintf(&princstr, "%s/admin%s%s", canon,
512 (realm) ? realm : "") < 0) {
513 error(_("%s: out of memory\n"), whoami);
517 krb5_free_principal(context, princ);
519 } else if ((luser = getenv("USER"))) {
520 if (asprintf(&princstr, "%s/admin@%s", luser, def_realm) < 0) {
521 error(_("%s: out of memory\n"), whoami);
525 } else if ((pw = getpwuid(getuid()))) {
526 if (asprintf(&princstr, "%s/admin@%s", pw->pw_name,
528 error(_("%s: out of memory\n"), whoami);
533 error(_("%s: unable to figure out a principal name\n"), whoami);
538 retval = krb5_klog_init(context, "admin_server", whoami, 0);
540 com_err(whoami, retval, _("while setting up logging"));
545 * Initialize the kadm5 connection. If we were given a ccache,
546 * use it. Otherwise, use/prompt for the password.
549 info(_("Authenticating as principal %s with existing "
550 "credentials.\n"), princstr);
551 retval = kadm5_init_with_creds(context, princstr, cc, svcname, ¶ms,
552 KADM5_STRUCT_VERSION,
553 KADM5_API_VERSION_4, db_args, &handle);
554 } else if (use_anonymous) {
555 info(_("Authenticating as principal %s with password; "
556 "anonymous requested.\n"), princstr);
557 retval = kadm5_init_anonymous(context, princstr, svcname, ¶ms,
558 KADM5_STRUCT_VERSION,
559 KADM5_API_VERSION_4, db_args, &handle);
560 } else if (use_keytab) {
561 if (keytab_name != NULL) {
562 info(_("Authenticating as principal %s with keytab %s.\n"),
563 princstr, keytab_name);
565 info(_("Authenticating as principal %s with default keytab.\n"),
568 retval = kadm5_init_with_skey(context, princstr, keytab_name, svcname,
569 ¶ms, KADM5_STRUCT_VERSION,
570 KADM5_API_VERSION_4, db_args, &handle);
572 info(_("Authenticating as principal %s with password.\n"),
574 retval = kadm5_init_with_password(context, princstr, password, svcname,
575 ¶ms, KADM5_STRUCT_VERSION,
576 KADM5_API_VERSION_4, db_args,
580 com_err(whoami, retval, _("while initializing %s interface"), whoami);
581 if (retval == KADM5_BAD_CLIENT_PARAMS ||
582 retval == KADM5_BAD_SERVER_PARAMS)
589 free(params.keysalts);
593 retval = krb5_cc_close(context, cc);
595 com_err(whoami, retval, _("while closing ccache %s"), ccache_name);
599 retval = kadm5_init_iprop(handle, 0);
601 com_err(whoami, retval, _("while mapping update log"));
605 *request_out = query;
606 *args_out = argv + optind;
615 retval = kadm5_unlock(handle);
617 com_err("quit", retval, _("while unlocking locked database"));
623 kadm5_destroy(handle);
624 if (ccache_name != NULL && !script_mode) {
625 fprintf(stderr, "\n\a\a\a%s",
626 _("Administration credentials NOT DESTROYED.\n"));
629 /* insert more random cleanup here */
630 krb5_klog_close(context);
631 krb5_free_context(context);
636 kadmin_lock(int argc, char *argv[])
642 retval = kadm5_lock(handle);
644 com_err("lock", retval, "");
651 kadmin_unlock(int argc, char *argv[])
657 retval = kadm5_unlock(handle);
659 com_err("unlock", retval, "");
666 kadmin_delprinc(int argc, char *argv[])
669 krb5_principal princ = NULL;
674 (argc == 3 && !strcmp("-force", argv[1])))) {
675 error(_("usage: delete_principal [-force] principal\n"));
678 retval = kadmin_parse_name(argv[argc - 1], &princ);
680 com_err("delete_principal", retval, _("while parsing principal name"));
683 retval = krb5_unparse_name(context, princ, &canon);
685 com_err("delete_principal", retval,
686 _("while canonicalizing principal"));
689 if (argc == 2 && !script_mode) {
690 printf(_("Are you sure you want to delete the principal \"%s\"? "
691 "(yes/no): "), canon);
692 fgets(reply, sizeof (reply), stdin);
693 if (strcmp("yes\n", reply)) {
694 fprintf(stderr, _("Principal \"%s\" not deleted\n"), canon);
698 retval = kadm5_delete_principal(handle, princ);
700 com_err("delete_principal", retval,
701 _("while deleting principal \"%s\""), canon);
704 info(_("Principal \"%s\" deleted.\n"), canon);
705 info(_("Make sure that you have removed this principal from all ACLs "
706 "before reusing.\n"));
709 krb5_free_principal(context, princ);
714 kadmin_renameprinc(int argc, char *argv[])
717 krb5_principal oprinc = NULL, nprinc = NULL;
718 char *ocanon = NULL, *ncanon = NULL;
721 if (!(argc == 3 || (argc == 4 && !strcmp("-force", argv[1])))) {
722 error(_("usage: rename_principal [-force] old_principal "
726 retval = kadmin_parse_name(argv[argc - 2], &oprinc);
728 com_err("rename_principal", retval,
729 _("while parsing old principal name"));
732 retval = kadmin_parse_name(argv[argc - 1], &nprinc);
734 com_err("rename_principal", retval,
735 _("while parsing new principal name"));
738 retval = krb5_unparse_name(context, oprinc, &ocanon);
740 com_err("rename_principal", retval,
741 _("while canonicalizing old principal"));
744 retval = krb5_unparse_name(context, nprinc, &ncanon);
746 com_err("rename_principal", retval,
747 _("while canonicalizing new principal"));
750 if (argc == 3 && !script_mode) {
751 printf(_("Are you sure you want to rename the principal \"%s\" "
752 "to \"%s\"? (yes/no): "), ocanon, ncanon);
753 fgets(reply, sizeof(reply), stdin);
754 if (strcmp("yes\n", reply)) {
755 fprintf(stderr, _("Principal \"%s\" not renamed\n"), ocanon);
759 retval = kadm5_rename_principal(handle, oprinc, nprinc);
761 com_err("rename_principal", retval,
762 _("while renaming principal \"%s\" to \"%s\""),
766 info(_("Principal \"%s\" renamed to \"%s\".\n"), ocanon, ncanon);
767 info(_("Make sure that you have removed the old principal from all ACLs "
768 "before reusing.\n"));
771 krb5_free_principal(context, nprinc);
772 krb5_free_principal(context, oprinc);
778 cpw_usage(const char *str)
782 error(_("usage: change_password [-randkey] [-keepold] "
783 "[-e keysaltlist] [-pw password] principal\n"));
787 kadmin_cpw(int argc, char *argv[])
790 static char newpw[1024];
791 static char prompt1[1024], prompt2[1024];
792 char *canon = NULL, *pwarg = NULL;
793 int n_ks_tuple = 0, randkey = 0;
794 krb5_boolean keepold = FALSE;
795 krb5_key_salt_tuple *ks_tuple = NULL;
796 krb5_principal princ = NULL;
797 char **db_args = NULL;
798 int db_args_size = 0;
804 for (argv++, argc--; argc > 1; argc--, argv++) {
805 if (!strcmp("-x", *argv)) {
808 cpw_usage(_("change_password: missing db argument"));
812 db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1));
813 if (db_args == NULL) {
814 error(_("change_password: Not enough memory\n"));
817 db_args[db_args_size - 1] = *++argv;
818 db_args[db_args_size] = NULL;
819 } else if (!strcmp("-pw", *argv)) {
822 cpw_usage(_("change_password: missing password arg"));
826 } else if (!strcmp("-randkey", *argv)) {
828 } else if (!strcmp("-keepold", *argv)) {
830 } else if (!strcmp("-e", *argv)) {
833 cpw_usage(_("change_password: missing keysaltlist arg"));
836 retval = krb5_string_to_keysalts(*++argv, NULL, NULL, 0,
837 &ks_tuple, &n_ks_tuple);
839 com_err("change_password", retval,
840 _("while parsing keysalts %s"), *argv);
849 com_err("change_password", 0, _("missing principal name"));
853 retval = kadmin_parse_name(*argv, &princ);
855 com_err("change_password", retval, _("while parsing principal name"));
858 retval = krb5_unparse_name(context, princ, &canon);
860 com_err("change_password", retval,
861 _("while canonicalizing principal"));
865 if (keepold || ks_tuple != NULL) {
866 retval = kadm5_chpass_principal_3(handle, princ, keepold,
867 n_ks_tuple, ks_tuple, pwarg);
869 retval = kadm5_chpass_principal(handle, princ, pwarg);
872 com_err("change_password", retval,
873 _("while changing password for \"%s\"."), canon);
876 info(_("Password for \"%s\" changed.\n"), canon);
877 } else if (randkey) {
878 retval = randkey_princ(handle, princ, keepold, n_ks_tuple, ks_tuple,
881 com_err("change_password", retval,
882 _("while randomizing key for \"%s\"."), canon);
885 info(_("Key for \"%s\" randomized.\n"), canon);
887 unsigned int i = sizeof (newpw) - 1;
889 snprintf(prompt1, sizeof(prompt1),
890 _("Enter password for principal \"%s\""), canon);
891 snprintf(prompt2, sizeof(prompt2),
892 _("Re-enter password for principal \"%s\""), canon);
893 retval = krb5_read_password(context, prompt1, prompt2,
896 com_err("change_password", retval,
897 _("while reading password for \"%s\"."), canon);
900 if (keepold || ks_tuple != NULL) {
901 retval = kadm5_chpass_principal_3(handle, princ, keepold,
902 n_ks_tuple, ks_tuple,
905 retval = kadm5_chpass_principal(handle, princ, newpw);
907 memset(newpw, 0, sizeof (newpw));
909 com_err("change_password", retval,
910 _("while changing password for \"%s\"."), canon);
913 info(_("Password for \"%s\" changed.\n"), canon);
918 krb5_free_principal(context, princ);
923 kadmin_free_tl_data(krb5_int16 *n_tl_datap, krb5_tl_data **tl_datap)
925 krb5_tl_data *tl_data = *tl_datap, *next;
926 int n_tl_data = *n_tl_datap;
932 for (i = 0; tl_data && (i < n_tl_data); i++) {
933 next = tl_data->tl_data_next;
934 free(tl_data->tl_data_contents);
940 /* Construct a tl_data element and add it to the tail of *tl_datap. */
942 add_tl_data(krb5_int16 *n_tl_datap, krb5_tl_data **tl_datap,
943 krb5_int16 tl_type, krb5_ui_2 len, krb5_octet *contents)
945 krb5_tl_data *tl_data;
949 tl_data = calloc(1, sizeof(*tl_data));
950 if (copy == NULL || tl_data == NULL) {
951 error(_("Not enough memory\n"));
954 memcpy(copy, contents, len);
956 tl_data->tl_data_type = tl_type;
957 tl_data->tl_data_length = len;
958 tl_data->tl_data_contents = copy;
959 tl_data->tl_data_next = NULL;
961 for (; *tl_datap != NULL; tl_datap = &(*tl_datap)->tl_data_next);
967 unlock_princ(kadm5_principal_ent_t princ, long *mask, const char *caller)
969 krb5_error_code retval;
971 krb5_octet timebuf[4];
973 /* Zero out the failed auth count. */
974 princ->fail_auth_count = 0;
975 *mask |= KADM5_FAIL_AUTH_COUNT;
977 /* Record the timestamp of this unlock operation so that replica KDCs will
978 * see it, since fail_auth_count is unreplicated. */
979 retval = krb5_timeofday(context, &now);
981 com_err(caller, retval, _("while getting time"));
984 store_32_le((krb5_int32)now, timebuf);
985 add_tl_data(&princ->n_tl_data, &princ->tl_data,
986 KRB5_TL_LAST_ADMIN_UNLOCK, 4, timebuf);
987 *mask |= KADM5_TL_DATA;
991 * Parse addprinc or modprinc arguments. Some output fields may be
992 * filled in on error.
995 kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc,
996 long *mask, char **pass, krb5_boolean *randkey,
997 krb5_boolean *nokey, krb5_key_salt_tuple **ks_tuple,
998 int *n_ks_tuple, char *caller)
1001 time_t now, date, interval;
1002 krb5_error_code retval;
1011 for (i = 1; i < argc - 1; i++) {
1012 if (!strcmp("-x",argv[i])) {
1016 add_tl_data(&oprinc->n_tl_data, &oprinc->tl_data,
1017 KRB5_TL_DB_ARGS, strlen(argv[i]) + 1,
1018 (krb5_octet *)argv[i]);
1019 *mask |= KADM5_TL_DATA;
1022 if (!strcmp("-expire", argv[i])) {
1025 date = parse_date(argv[i], now);
1026 if (date == (time_t)-1)
1028 oprinc->princ_expire_time = date;
1029 *mask |= KADM5_PRINC_EXPIRE_TIME;
1032 if (!strcmp("-pwexpire", argv[i])) {
1035 date = parse_date(argv[i], now);
1036 if (date == (time_t)-1)
1038 oprinc->pw_expiration = date;
1039 *mask |= KADM5_PW_EXPIRATION;
1042 if (!strcmp("-maxlife", argv[i])) {
1045 interval = parse_interval(argv[i], now);
1046 if (interval == (time_t)-1)
1048 oprinc->max_life = interval;
1049 *mask |= KADM5_MAX_LIFE;
1052 if (!strcmp("-maxrenewlife", argv[i])) {
1055 interval = parse_interval(argv[i], now);
1056 if (interval == (time_t)-1)
1058 oprinc->max_renewable_life = interval;
1059 *mask |= KADM5_MAX_RLIFE;
1062 if (!strcmp("-kvno", argv[i])) {
1065 oprinc->kvno = atoi(argv[i]);
1066 *mask |= KADM5_KVNO;
1069 if (!strcmp("-policy", argv[i])) {
1072 oprinc->policy = argv[i];
1073 *mask |= KADM5_POLICY;
1076 if (!strcmp("-clearpolicy", argv[i])) {
1077 oprinc->policy = NULL;
1078 *mask |= KADM5_POLICY_CLR;
1081 if (!strcmp("-pw", argv[i])) {
1087 if (!strcmp("-randkey", argv[i])) {
1091 if (!strcmp("-nokey", argv[i])) {
1095 if (!strcmp("-unlock", argv[i])) {
1096 unlock_princ(oprinc, mask, caller);
1099 if (!strcmp("-e", argv[i])) {
1102 retval = krb5_string_to_keysalts(argv[i], NULL, NULL, 0,
1103 ks_tuple, n_ks_tuple);
1105 com_err(caller, retval, _("while parsing keysalts %s"),
1111 retval = krb5_flagspec_to_mask(argv[i], &oprinc->attributes,
1112 &oprinc->attributes);
1116 *mask |= KADM5_ATTRIBUTES;
1120 retval = kadmin_parse_name(argv[i], &oprinc->principal);
1122 com_err(caller, retval, _("while parsing principal"));
1129 kadmin_addprinc_usage()
1131 error(_("usage: add_principal [options] principal\n"));
1132 error(_("\toptions are:\n"));
1133 error(_("\t\t[-randkey|-nokey] [-x db_princ_args]* [-expire expdate] "
1134 "[-pwexpire pwexpdate] [-maxlife maxtixlife]\n"
1135 "\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n"
1136 "\t\t[-pw password] [-maxrenewlife maxrenewlife]\n"
1137 "\t\t[-e keysaltlist]\n\t\t[{+|-}attribute]\n"));
1138 error(_("\tattributes are:\n"));
1139 error(_("\t\tallow_postdated allow_forwardable allow_tgs_req "
1141 "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n"
1142 "\t\trequires_hwauth needchange allow_svr "
1143 "password_changing_service\n"
1144 "\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n"
1145 "\t\tlockdown_keys\n"
1146 "\nwhere,\n\t[-x db_princ_args]* - any number of database "
1147 "specific arguments.\n"
1148 "\t\t\tLook at each database documentation for supported "
1153 kadmin_modprinc_usage()
1155 error(_("usage: modify_principal [options] principal\n"));
1156 error(_("\toptions are:\n"));
1157 error(_("\t\t[-x db_princ_args]* [-expire expdate] "
1158 "[-pwexpire pwexpdate] [-maxlife maxtixlife]\n"
1159 "\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n"
1160 "\t\t[-maxrenewlife maxrenewlife] [-unlock] [{+|-}attribute]\n"));
1161 error(_("\tattributes are:\n"));
1162 error(_("\t\tallow_postdated allow_forwardable allow_tgs_req "
1164 "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n"
1165 "\t\trequires_hwauth needchange allow_svr "
1166 "password_changing_service\n"
1167 "\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n"
1168 "\t\tlockdown_keys\n"
1169 "\nwhere,\n\t[-x db_princ_args]* - any number of database "
1170 "specific arguments.\n"
1171 "\t\t\tLook at each database documentation for supported "
1175 /* Create a dummy password for old-style (pre-1.8) randkey creation. */
1177 prepare_dummy_password(char *buf, size_t sz)
1181 /* Must try to pass any password policy in place, and be valid UTF-8. */
1182 strlcpy(buf, "6F a[", sz);
1183 for (i = strlen(buf); i < sz - 1; i++)
1184 buf[i] = 'a' + (i % 26);
1189 kadmin_addprinc(int argc, char *argv[])
1191 kadm5_principal_ent_rec princ;
1193 krb5_boolean randkey = FALSE, nokey = FALSE, old_style_randkey = FALSE;
1195 krb5_key_salt_tuple *ks_tuple = NULL;
1196 char *pass, *canon = NULL;
1197 krb5_error_code retval;
1198 char newpw[1024], dummybuf[256];
1199 static char prompt1[1024], prompt2[1024];
1201 /* Zero all fields in request structure */
1202 memset(&princ, 0, sizeof(princ));
1204 princ.attributes = 0;
1205 if (kadmin_parse_princ_args(argc, argv, &princ, &mask, &pass, &randkey,
1206 &nokey, &ks_tuple, &n_ks_tuple,
1208 kadmin_addprinc_usage();
1212 retval = krb5_unparse_name(context, princ.principal, &canon);
1214 com_err("add_principal", retval, _("while canonicalizing principal"));
1218 if (mask & KADM5_POLICY) {
1219 /* Warn if the specified policy does not exist. */
1220 if (!script_mode && !policy_exists(princ.policy)) {
1221 fprintf(stderr, _("WARNING: policy \"%s\" does not exist\n"),
1224 } else if (!(mask & KADM5_POLICY_CLR)) {
1225 /* If the policy "default" exists, assign it. */
1226 if (policy_exists("default")) {
1228 fprintf(stderr, _("NOTICE: no policy specified for %s; "
1229 "assigning \"default\"\n"), canon);
1231 princ.policy = "default";
1232 mask |= KADM5_POLICY;
1233 } else if (!script_mode) {
1234 fprintf(stderr, _("WARNING: no policy specified for %s; "
1235 "defaulting to no policy\n"), canon);
1238 /* Don't send KADM5_POLICY_CLR to the server. */
1239 mask &= ~KADM5_POLICY_CLR;
1243 mask |= KADM5_KEY_DATA;
1244 } else if (randkey) {
1246 } else if (pass == NULL) {
1247 unsigned int sz = sizeof(newpw) - 1;
1249 snprintf(prompt1, sizeof(prompt1),
1250 _("Enter password for principal \"%s\""), canon);
1251 snprintf(prompt2, sizeof(prompt2),
1252 _("Re-enter password for principal \"%s\""), canon);
1253 retval = krb5_read_password(context, prompt1, prompt2, newpw, &sz);
1255 com_err("add_principal", retval,
1256 _("while reading password for \"%s\"."), canon);
1261 mask |= KADM5_PRINCIPAL;
1262 retval = create_princ(&princ, mask, n_ks_tuple, ks_tuple, pass);
1263 if (retval == EINVAL && randkey) {
1265 * The server doesn't support randkey creation. Create the principal
1266 * with a dummy password and disallow tickets.
1268 prepare_dummy_password(dummybuf, sizeof(dummybuf));
1269 princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
1270 mask |= KADM5_ATTRIBUTES;
1272 retval = create_princ(&princ, mask, n_ks_tuple, ks_tuple, pass);
1273 old_style_randkey = 1;
1275 if (retval == KADM5_BAD_MASK && nokey) {
1276 error(_("Admin server does not support -nokey while creating "
1277 "\"%s\"\n"), canon);
1281 com_err("add_principal", retval, "while creating \"%s\".", canon);
1284 if (old_style_randkey) {
1285 /* Randomize the password and re-enable tickets. */
1286 retval = randkey_princ(handle, princ.principal, FALSE, n_ks_tuple,
1287 ks_tuple, NULL, NULL);
1289 com_err("add_principal", retval,
1290 _("while randomizing key for \"%s\"."), canon);
1293 princ.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; /* clear notix */
1294 mask = KADM5_ATTRIBUTES;
1295 retval = kadm5_modify_principal(handle, &princ, mask);
1297 com_err("add_principal", retval,
1298 _("while clearing DISALLOW_ALL_TIX for \"%s\"."), canon);
1302 info("Principal \"%s\" created.\n", canon);
1305 krb5_free_principal(context, princ.principal);
1308 kadmin_free_tl_data(&princ.n_tl_data, &princ.tl_data);
1312 kadmin_modprinc(int argc, char *argv[])
1314 kadm5_principal_ent_rec princ, oldprinc;
1315 krb5_principal kprinc = NULL;
1317 krb5_error_code retval;
1318 char *pass, *canon = NULL;
1319 krb5_boolean randkey = FALSE, nokey = FALSE;
1321 krb5_key_salt_tuple *ks_tuple = NULL;
1324 kadmin_modprinc_usage();
1328 memset(&oldprinc, 0, sizeof(oldprinc));
1329 memset(&princ, 0, sizeof(princ));
1331 retval = kadmin_parse_name(argv[argc - 1], &kprinc);
1333 com_err("modify_principal", retval, _("while parsing principal"));
1336 retval = krb5_unparse_name(context, kprinc, &canon);
1338 com_err("modify_principal", retval,
1339 _("while canonicalizing principal"));
1342 retval = kadm5_get_principal(handle, kprinc, &oldprinc,
1343 KADM5_PRINCIPAL_NORMAL_MASK);
1345 com_err("modify_principal", retval, _("while getting \"%s\"."), canon);
1348 princ.attributes = oldprinc.attributes;
1349 kadm5_free_principal_ent(handle, &oldprinc);
1350 retval = kadmin_parse_princ_args(argc, argv,
1352 &pass, &randkey, &nokey,
1353 &ks_tuple, &n_ks_tuple,
1354 "modify_principal");
1355 if (retval || ks_tuple != NULL || randkey || nokey || pass) {
1356 kadmin_modprinc_usage();
1359 if (mask & KADM5_POLICY) {
1360 /* Warn if the specified policy does not exist. */
1361 if (!script_mode && !policy_exists(princ.policy)) {
1362 fprintf(stderr, _("WARNING: policy \"%s\" does not exist\n"),
1367 /* Skip this if all we're doing is setting certhash. */
1368 retval = kadm5_modify_principal(handle, &princ, mask);
1371 com_err("modify_principal", retval, _("while modifying \"%s\"."),
1375 info(_("Principal \"%s\" modified.\n"), canon);
1377 krb5_free_principal(context, kprinc);
1378 krb5_free_principal(context, princ.principal);
1379 kadmin_free_tl_data(&princ.n_tl_data, &princ.tl_data);
1385 kadmin_getprinc(int argc, char *argv[])
1387 kadm5_principal_ent_rec dprinc;
1388 krb5_principal princ = NULL;
1389 krb5_error_code retval;
1390 const char *polname, *noexist;
1391 char *canon = NULL, *princstr = NULL, *modprincstr = NULL;
1392 char **sp = NULL, **attrstrs = NULL;
1395 if (!(argc == 2 || (argc == 3 && !strcmp("-terse", argv[1])))) {
1396 error(_("usage: get_principal [-terse] principal\n"));
1400 memset(&dprinc, 0, sizeof(dprinc));
1402 retval = kadmin_parse_name(argv[argc - 1], &princ);
1404 com_err("get_principal", retval, _("while parsing principal"));
1407 retval = krb5_unparse_name(context, princ, &canon);
1409 com_err("get_principal", retval, _("while canonicalizing principal"));
1412 retval = kadm5_get_principal(handle, princ, &dprinc,
1413 KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA);
1415 com_err("get_principal", retval, _("while retrieving \"%s\"."), canon);
1418 retval = krb5_unparse_name(context, dprinc.principal, &princstr);
1420 com_err("get_principal", retval, _("while unparsing principal"));
1423 retval = krb5_unparse_name(context, dprinc.mod_name, &modprincstr);
1425 com_err("get_principal", retval, _("while unparsing principal"));
1429 printf(_("Principal: %s\n"), princstr);
1430 printf(_("Expiration date: %s\n"), dprinc.princ_expire_time ?
1431 strdate(dprinc.princ_expire_time) : _("[never]"));
1432 printf(_("Last password change: %s\n"), dprinc.last_pwd_change ?
1433 strdate(dprinc.last_pwd_change) : _("[never]"));
1434 printf(_("Password expiration date: %s\n"),
1435 dprinc.pw_expiration ?
1436 strdate(dprinc.pw_expiration) : _("[never]"));
1437 printf(_("Maximum ticket life: %s\n"), strdur(dprinc.max_life));
1438 printf(_("Maximum renewable life: %s\n"),
1439 strdur(dprinc.max_renewable_life));
1440 printf(_("Last modified: %s (%s)\n"), strdate(dprinc.mod_date),
1442 printf(_("Last successful authentication: %s\n"),
1443 dprinc.last_success ? strdate(dprinc.last_success) :
1445 printf("Last failed authentication: %s\n",
1446 dprinc.last_failed ? strdate(dprinc.last_failed) :
1448 printf(_("Failed password attempts: %d\n"),
1449 dprinc.fail_auth_count);
1450 printf(_("Number of keys: %d\n"), dprinc.n_key_data);
1451 for (i = 0; i < dprinc.n_key_data; i++) {
1452 krb5_key_data *key_data = &dprinc.key_data[i];
1453 char enctype[BUFSIZ], salttype[BUFSIZ];
1455 if (krb5_enctype_to_name(key_data->key_data_type[0], FALSE,
1456 enctype, sizeof(enctype)))
1457 snprintf(enctype, sizeof(enctype), _("<Encryption type 0x%x>"),
1458 key_data->key_data_type[0]);
1459 printf("Key: vno %d, %s", key_data->key_data_kvno, enctype);
1460 if (key_data->key_data_ver > 1 &&
1461 key_data->key_data_type[1] != KRB5_KDB_SALTTYPE_NORMAL) {
1462 if (krb5_salttype_to_string(key_data->key_data_type[1],
1463 salttype, sizeof(salttype)))
1464 snprintf(salttype, sizeof(salttype), _("<Salt type 0x%x>"),
1465 key_data->key_data_type[1]);
1466 printf(":%s", salttype);
1470 printf(_("MKey: vno %d\n"), dprinc.mkvno);
1472 printf(_("Attributes:"));
1473 retval = krb5_flags_to_strings(dprinc.attributes, &attrstrs);
1475 com_err("get_principal", retval, _("while printing flags"));
1478 for (sp = attrstrs; sp != NULL && *sp != NULL; sp++) {
1484 polname = (dprinc.policy != NULL) ? dprinc.policy : _("[none]");
1485 noexist = (dprinc.policy != NULL && !policy_exists(dprinc.policy)) ?
1486 _(" [does not exist]") : "";
1487 printf(_("Policy: %s%s\n"), polname, noexist);
1489 printf("\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\t%d\t%d\t%d\t%d\t\"%s\""
1490 "\t%d\t%d\t%d\t%d\t%d",
1491 princstr, dprinc.princ_expire_time, dprinc.last_pwd_change,
1492 dprinc.pw_expiration, dprinc.max_life, modprincstr,
1493 dprinc.mod_date, dprinc.attributes, dprinc.kvno,
1494 dprinc.mkvno, dprinc.policy ? dprinc.policy : "[none]",
1495 dprinc.max_renewable_life, dprinc.last_success,
1496 dprinc.last_failed, dprinc.fail_auth_count,
1498 for (i = 0; i < dprinc.n_key_data; i++)
1499 printf("\t%d\t%d\t%d\t%d",
1500 dprinc.key_data[i].key_data_ver,
1501 dprinc.key_data[i].key_data_kvno,
1502 dprinc.key_data[i].key_data_type[0],
1503 dprinc.key_data[i].key_data_type[1]);
1507 krb5_free_principal(context, princ);
1508 kadm5_free_principal_ent(handle, &dprinc);
1515 kadmin_getprincs(int argc, char *argv[])
1517 krb5_error_code retval;
1518 char *expr, **names;
1522 if (!(argc == 1 || (argc == 2 && (expr = argv[1])))) {
1523 error(_("usage: get_principals [expression]\n"));
1526 retval = kadm5_get_principals(handle, expr, &names, &count);
1528 com_err("get_principals", retval, _("while retrieving list."));
1531 for (i = 0; i < count; i++)
1532 printf("%s\n", names[i]);
1533 kadm5_free_name_list(handle, names, count);
1537 kadmin_parse_policy_args(int argc, char *argv[], kadm5_policy_ent_t policy,
1538 long *mask, char *caller)
1540 krb5_error_code retval;
1542 time_t now, interval;
1546 for (i = 1; i < argc - 1; i++) {
1547 if (!strcmp(argv[i], "-maxlife")) {
1550 interval = parse_interval(argv[i], now);
1551 if (interval == (time_t)-1)
1553 policy->pw_max_life = interval;
1554 *mask |= KADM5_PW_MAX_LIFE;
1556 } else if (!strcmp(argv[i], "-minlife")) {
1559 interval = parse_interval(argv[i], now);
1560 if (interval == (time_t)-1)
1562 policy->pw_min_life = interval;
1563 *mask |= KADM5_PW_MIN_LIFE;
1565 } else if (!strcmp(argv[i], "-minlength")) {
1568 policy->pw_min_length = atoi(argv[i]);
1569 *mask |= KADM5_PW_MIN_LENGTH;
1571 } else if (!strcmp(argv[i], "-minclasses")) {
1574 policy->pw_min_classes = atoi(argv[i]);
1575 *mask |= KADM5_PW_MIN_CLASSES;
1577 } else if (!strcmp(argv[i], "-history")) {
1580 policy->pw_history_num = atoi(argv[i]);
1581 *mask |= KADM5_PW_HISTORY_NUM;
1583 } else if (strlen(argv[i]) == 11 &&
1584 !strcmp(argv[i], "-maxfailure")) {
1587 policy->pw_max_fail = atoi(argv[i]);
1588 *mask |= KADM5_PW_MAX_FAILURE;
1590 } else if (strlen(argv[i]) == 21 &&
1591 !strcmp(argv[i], "-failurecountinterval")) {
1594 interval = parse_interval(argv[i], now);
1595 if (interval == (time_t)-1)
1597 policy->pw_failcnt_interval = interval;
1598 *mask |= KADM5_PW_FAILURE_COUNT_INTERVAL;
1600 } else if (strlen(argv[i]) == 16 &&
1601 !strcmp(argv[i], "-lockoutduration")) {
1604 interval = parse_interval(argv[i], now);
1605 if (interval == (time_t)-1)
1607 policy->pw_lockout_duration = interval;
1608 *mask |= KADM5_PW_LOCKOUT_DURATION;
1610 } else if (!strcmp(argv[i], "-allowedkeysalts")) {
1611 krb5_key_salt_tuple *ks_tuple = NULL;
1616 if (strcmp(argv[i], "-")) {
1617 retval = krb5_string_to_keysalts(argv[i], ",", NULL, 0,
1618 &ks_tuple, &n_ks_tuple);
1620 com_err(caller, retval, _("while parsing keysalts %s"),
1625 policy->allowed_keysalts = argv[i];
1627 *mask |= KADM5_POLICY_ALLOWED_KEYSALTS;
1633 error(_("%s: parser lost count!\n"), caller);
1640 kadmin_addmodpol_usage(char *func)
1642 error(_("usage; %s [options] policy\n"), func);
1643 error(_("\toptions are:\n"));
1644 error(_("\t\t[-maxlife time] [-minlife time] [-minlength length]\n"
1645 "\t\t[-minclasses number] [-history number]\n"
1646 "\t\t[-maxfailure number] [-failurecountinterval time]\n"
1647 "\t\t[-allowedkeysalts keysalts]\n"));
1648 error(_("\t\t[-lockoutduration time]\n"));
1652 kadmin_addpol(int argc, char *argv[])
1654 krb5_error_code retval;
1656 kadm5_policy_ent_rec policy;
1658 memset(&policy, 0, sizeof(policy));
1659 if (kadmin_parse_policy_args(argc, argv, &policy, &mask, "add_policy")) {
1660 kadmin_addmodpol_usage("add_policy");
1663 policy.policy = argv[argc - 1];
1664 mask |= KADM5_POLICY;
1665 retval = kadm5_create_policy(handle, &policy, mask);
1667 com_err("add_policy", retval, _("while creating policy \"%s\"."),
1673 kadmin_modpol(int argc, char *argv[])
1675 krb5_error_code retval;
1677 kadm5_policy_ent_rec policy;
1679 memset(&policy, 0, sizeof(policy));
1680 if (kadmin_parse_policy_args(argc, argv, &policy, &mask,
1682 kadmin_addmodpol_usage("modify_policy");
1685 policy.policy = argv[argc - 1];
1686 retval = kadm5_modify_policy(handle, &policy, mask);
1688 com_err("modify_policy", retval, _("while modifying policy \"%s\"."),
1694 kadmin_delpol(int argc, char *argv[])
1696 krb5_error_code retval;
1699 if (!(argc == 2 || (argc == 3 && !strcmp("-force", argv[1])))) {
1700 error(_("usage: delete_policy [-force] policy\n"));
1703 if (argc == 2 && !script_mode) {
1704 printf(_("Are you sure you want to delete the policy \"%s\"? "
1705 "(yes/no): "), argv[1]);
1706 fgets(reply, sizeof(reply), stdin);
1707 if (strcmp("yes\n", reply)) {
1708 fprintf(stderr, _("Policy \"%s\" not deleted.\n"), argv[1]);
1712 retval = kadm5_delete_policy(handle, argv[argc - 1]);
1714 com_err("delete_policy:", retval, _("while deleting policy \"%s\""),
1720 kadmin_getpol(int argc, char *argv[])
1722 krb5_error_code retval;
1723 kadm5_policy_ent_rec policy;
1725 if (!(argc == 2 || (argc == 3 && !strcmp("-terse", argv[1])))) {
1726 error(_("usage: get_policy [-terse] policy\n"));
1729 retval = kadm5_get_policy(handle, argv[argc - 1], &policy);
1731 com_err("get_policy", retval, _("while retrieving policy \"%s\"."),
1736 printf(_("Policy: %s\n"), policy.policy);
1737 printf(_("Maximum password life: %s\n"), strdur(policy.pw_max_life));
1738 printf(_("Minimum password life: %s\n"), strdur(policy.pw_min_life));
1739 printf(_("Minimum password length: %ld\n"), policy.pw_min_length);
1740 printf(_("Minimum number of password character classes: %ld\n"),
1741 policy.pw_min_classes);
1742 printf(_("Number of old keys kept: %ld\n"), policy.pw_history_num);
1743 printf(_("Maximum password failures before lockout: %lu\n"),
1744 (unsigned long)policy.pw_max_fail);
1745 printf(_("Password failure count reset interval: %s\n"),
1746 strdur(policy.pw_failcnt_interval));
1747 printf(_("Password lockout duration: %s\n"),
1748 strdur(policy.pw_lockout_duration));
1749 if (policy.allowed_keysalts != NULL)
1750 printf(_("Allowed key/salt types: %s\n"), policy.allowed_keysalts);
1752 /* Output 0 where we used to output policy_refcnt. */
1753 printf("\"%s\"\t%ld\t%ld\t%ld\t%ld\t%ld\t0\t%lu\t%ld\t%ld\t%s\n",
1754 policy.policy, policy.pw_max_life, policy.pw_min_life,
1755 policy.pw_min_length, policy.pw_min_classes,
1756 policy.pw_history_num, (unsigned long)policy.pw_max_fail,
1757 (long)policy.pw_failcnt_interval,
1758 (long)policy.pw_lockout_duration,
1759 (policy.allowed_keysalts == NULL) ? "-" :
1760 policy.allowed_keysalts);
1762 kadm5_free_policy_ent(handle, &policy);
1766 kadmin_getpols(int argc, char *argv[])
1768 krb5_error_code retval;
1769 char *expr, **names;
1773 if (!(argc == 1 || (argc == 2 && (expr = argv[1])))) {
1774 error(_("usage: get_policies [expression]\n"));
1777 retval = kadm5_get_policies(handle, expr, &names, &count);
1779 com_err("get_policies", retval, _("while retrieving list."));
1782 for (i = 0; i < count; i++)
1783 printf("%s\n", names[i]);
1784 kadm5_free_name_list(handle, names, count);
1788 kadmin_getprivs(int argc, char *argv[])
1790 static char *privs[] = {"INQUIRE", "ADD", "MODIFY", "DELETE"};
1791 krb5_error_code retval;
1796 error(_("usage: get_privs\n"));
1799 retval = kadm5_get_privs(handle, &plist);
1801 com_err("get_privs", retval, _("while retrieving privileges"));
1804 printf(_("current privileges:"));
1805 for (i = 0; i < sizeof (privs) / sizeof (char *); i++) {
1807 printf(" %s", privs[i]);
1813 kadmin_purgekeys(int argc, char *argv[])
1817 char *pname = NULL, *canon = NULL;
1818 krb5_principal princ;
1820 if (argc == 4 && strcmp(argv[1], "-keepkvno") == 0) {
1821 keepkvno = atoi(argv[2]);
1823 } else if (argc == 3 && strcmp(argv[1], "-all") == 0) {
1824 keepkvno = KRB5_INT32_MAX;
1826 } else if (argc == 2) {
1829 if (pname == NULL) {
1830 error(_("usage: purgekeys [-all|-keepkvno oldest_kvno_to_keep] "
1835 retval = kadmin_parse_name(pname, &princ);
1837 com_err("purgekeys", retval, _("while parsing principal"));
1841 retval = krb5_unparse_name(context, princ, &canon);
1843 com_err("purgekeys", retval, _("while canonicalizing principal"));
1847 retval = kadm5_purgekeys(handle, princ, keepkvno);
1849 com_err("purgekeys", retval,
1850 _("while purging keys for principal \"%s\""), canon);
1854 if (keepkvno == KRB5_INT32_MAX)
1855 info(_("All keys for principal \"%s\" removed.\n"), canon);
1857 info(_("Old keys for principal \"%s\" purged.\n"), canon);
1859 krb5_free_principal(context, princ);
1865 kadmin_getstrings(int argc, char *argv[])
1868 char *pname, *canon = NULL;
1869 krb5_principal princ = NULL;
1870 krb5_string_attr *strings = NULL;
1874 error(_("usage: get_strings principal\n"));
1879 retval = kadmin_parse_name(pname, &princ);
1881 com_err("get_strings", retval, _("while parsing principal"));
1885 retval = krb5_unparse_name(context, princ, &canon);
1887 com_err("get_strings", retval, _("while canonicalizing principal"));
1891 retval = kadm5_get_strings(handle, princ, &strings, &count);
1893 com_err("get_strings", retval,
1894 _("while getting attributes for principal \"%s\""), canon);
1899 printf(_("(No string attributes.)\n"));
1900 for (i = 0; i < count; i++)
1901 printf("%s: %s\n", strings[i].key, strings[i].value);
1902 kadm5_free_strings(handle, strings, count);
1905 krb5_free_principal(context, princ);
1911 kadmin_setstring(int argc, char *argv[])
1914 char *pname, *canon = NULL, *key, *value;
1915 krb5_principal princ = NULL;
1918 error(_("usage: set_string principal key value\n"));
1925 retval = kadmin_parse_name(pname, &princ);
1927 com_err("set_string", retval, _("while parsing principal"));
1931 retval = krb5_unparse_name(context, princ, &canon);
1933 com_err("set_string", retval, _("while canonicalizing principal"));
1937 retval = kadm5_set_string(handle, princ, key, value);
1939 com_err("set_string", retval,
1940 _("while setting attribute on principal \"%s\""), canon);
1944 info(_("Attribute set for principal \"%s\".\n"), canon);
1946 krb5_free_principal(context, princ);
1952 kadmin_delstring(int argc, char *argv[])
1955 char *pname, *canon = NULL, *key;
1956 krb5_principal princ = NULL;
1959 error(_("usage: del_string principal key\n"));
1965 retval = kadmin_parse_name(pname, &princ);
1967 com_err("delstring", retval, _("while parsing principal"));
1971 retval = krb5_unparse_name(context, princ, &canon);
1973 com_err("del_string", retval, _("while canonicalizing principal"));
1977 retval = kadm5_set_string(handle, princ, key, NULL);
1979 com_err("del_string", retval,
1980 _("while deleting attribute from principal \"%s\""), canon);
1984 info(_("Attribute removed from principal \"%s\".\n"), canon);
1986 krb5_free_principal(context, princ);