2 * Copyright 1994 by the Massachusetts Institute of Technology.
5 * Export of this software from the United States of America may
6 * require a specific license from the United States Government.
7 * It is the responsibility of any person or organization contemplating
8 * export to obtain such a license before exporting.
10 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
11 * distribute this software and its documentation for any purpose and
12 * without fee is hereby granted, provided that the above copyright
13 * notice appear in all copies and that both that copyright notice and
14 * this permission notice appear in supporting documentation, and that
15 * the name of M.I.T. not be used in advertising or publicity pertaining
16 * to distribution of the software without specific, written prior
17 * permission. M.I.T. makes no representations about the suitability of
18 * this software for any purpose. It is provided "as is" without express
19 * or implied warranty.
21 * kadmin.c: base functions for a kadmin command line interface using
22 * the OVSecure library
27 #include <kadm5/admin.h>
30 #include <sys/types.h>
34 /* #include <sys/timeb.h> */
37 /* special struct to convert flag names for principals
38 to actual krb5_flags for a principal */
40 char *flagname; /* name of flag as typed to CLI */
41 int flaglen; /* length of string (not counting -,+) */
42 krb5_flags theflag; /* actual principal flag to set/clear */
43 int set; /* 0 means clear, 1 means set (on '-') */
46 static struct pflag flags[] = {
47 {"allow_postdated", 15, KRB5_KDB_DISALLOW_POSTDATED, 1},
48 {"allow_forwardable", 17, KRB5_KDB_DISALLOW_FORWARDABLE, 1},
49 {"allow_tgs_req", 13, KRB5_KDB_DISALLOW_TGT_BASED, 1},
50 {"allow_renewable", 15, KRB5_KDB_DISALLOW_RENEWABLE, 1},
51 {"allow_proxiable", 15, KRB5_KDB_DISALLOW_PROXIABLE, 1},
52 {"allow_dup_skey", 14, KRB5_KDB_DISALLOW_DUP_SKEY, 1},
53 {"allow_tix", 9, KRB5_KDB_DISALLOW_ALL_TIX, 1},
54 {"requires_preauth", 16, KRB5_KDB_REQUIRES_PRE_AUTH, 0},
55 {"requires_hwauth", 15, KRB5_KDB_REQUIRES_HW_AUTH, 0},
56 {"needchange", 10, KRB5_KDB_REQUIRES_PWCHANGE, 0},
57 {"allow_svr", 9, KRB5_KDB_DISALLOW_SVR, 1},
58 {"password_changing_service", 25, KRB5_KDB_PWCHANGE_SERVICE, 0 },
59 {"support_desmd5", 14, KRB5_KDB_SUPPORT_DESMD5, 0 }
62 static char *prflags[] = {
63 "DISALLOW_POSTDATED", /* 0x00000001 */
64 "DISALLOW_FORWARDABLE", /* 0x00000002 */
65 "DISALLOW_TGT_BASED", /* 0x00000004 */
66 "DISALLOW_RENEWABLE", /* 0x00000008 */
67 "DISALLOW_PROXIABLE", /* 0x00000010 */
68 "DISALLOW_DUP_SKEY", /* 0x00000020 */
69 "DISALLOW_ALL_TIX", /* 0x00000040 */
70 "REQUIRES_PRE_AUTH", /* 0x00000080 */
71 "REQUIRES_HW_AUTH", /* 0x00000100 */
72 "REQUIRES_PWCHANGE", /* 0x00000200 */
73 "UNKNOWN_0x00000400", /* 0x00000400 */
74 "UNKNOWN_0x00000800", /* 0x00000800 */
75 "DISALLOW_SVR", /* 0x00001000 */
76 "PWCHANGE_SERVICE", /* 0x00002000 */
77 "SUPPORT_DESMD5", /* 0x00004000 */
78 "NEW_PRINC", /* 0x00008000 */
83 char *def_realm = NULL;
89 char *ccache_name = NULL;
94 "Usage: %s [-r realm] [-p principal] [-q query] [clnt|local args]\n"
95 "\tclnt args: [-s admin_server[:port]] [[-c ccache]|[-k [-t keytab]]]\n"
96 "\tlocal args: [-d dbname] [-e \"enc:salt ...\"] [-m]\n", whoami);
100 char *strdur(duration)
104 int days, hours, minutes, seconds;
106 days = duration / (24 * 3600);
107 duration %= 24 * 3600;
108 hours = duration / 3600;
110 minutes = duration / 60;
113 sprintf(out, "%d %s %02d:%02d:%02d", days, days == 1 ? "day" : "days",
114 hours, minutes, seconds);
124 time_t lcltim = when;
125 tm = localtime(&lcltim);
126 strftime(out, 30, "%a %b %d %H:%M:%S %Z %Y", tm);
130 /* this is a wrapper to go around krb5_parse_principal so we can set
131 the default realm up properly */
132 krb5_error_code kadmin_parse_name(name, principal)
134 krb5_principal *principal;
137 krb5_error_code retval;
139 /* assumes def_realm is initialized! */
140 fullname = (char *)malloc(strlen(name) + 1 + strlen(def_realm) + 1);
141 if (fullname == NULL)
143 strcpy(fullname, name);
144 cp = strchr(fullname, '@');
146 if (cp - fullname && *(cp - 1) != '\\')
149 cp = strchr(cp, '@');
152 strcat(fullname, "@");
153 strcat(fullname, def_realm);
155 retval = krb5_parse_name(context, fullname, principal);
160 char *kadmin_startup(argc, argv)
164 extern krb5_kt_ops krb5_ktf_writable_ops;
166 char *princstr = NULL, *keytab_name = NULL, *query = NULL;
167 char *password = NULL;
168 char *luser, *canon, *cp;
169 int optchar, freeprinc = 0, use_keytab = 0;
173 krb5_principal princ;
174 kadm5_config_params params;
176 memset((char *) ¶ms, 0, sizeof(params));
178 if (retval = krb5_init_context(&context)) {
179 com_err(whoami, retval, "while initializing krb5 library");
183 while ((optchar = getopt(argc, argv, "r:p:kq:w:d:s:mc:t:e:")) != EOF) {
192 ccache_name = optarg;
198 keytab_name = optarg;
207 params.dbname = optarg;
208 params.mask |= KADM5_CONFIG_DBNAME;
211 params.admin_server = optarg;
212 params.mask |= KADM5_CONFIG_ADMIN_SERVER;
215 params.mkey_from_kbd = 1;
216 params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
219 retval = krb5_string_to_keysalts(optarg,
224 ¶ms.num_keysalts);
226 com_err(whoami, retval, "while parsing keysalts %s", optarg);
229 params.mask |= KADM5_CONFIG_ENCTYPES;
235 if ((ccache_name && use_keytab) ||
236 (keytab_name && !use_keytab))
239 if (def_realm == NULL && krb5_get_default_realm(context, &def_realm)) {
242 fprintf(stderr, "%s: unable to get default realm\n", whoami);
246 params.mask |= KADM5_CONFIG_REALM;
247 params.realm = def_realm;
250 * Set cc to an open credentials cache, either specified by the -c
251 * argument or the default.
253 if (ccache_name == NULL) {
254 if (retval = krb5_cc_default(context, &cc)) {
255 com_err(whoami, retval,
256 "while opening default credentials cache");
260 if (retval = krb5_cc_resolve(context, ccache_name, &cc)) {
261 com_err(whoami, retval,
262 "while opening credentials cache %s", ccache_name);
268 * If no principal name is specified: If a ccache was specified
269 * and its primary principal name can be read, it is used, else if
270 * a keytab was specified, the principal name is host/hostname,
271 * otherwise append "/admin" to the primary name of the default
272 * ccache, $USER, or pw_name.
274 * Gee, 100+ lines to figure out the client principal name. This
275 * should be compressed...
278 if (princstr == NULL) {
279 if (ccache_name != NULL &&
280 !krb5_cc_get_principal(context, cc, &princ)) {
281 if (retval = krb5_unparse_name(context, princ, &princstr)) {
282 com_err(whoami, retval,
283 "while canonicalizing principal name");
284 krb5_free_principal(context, princ);
287 krb5_free_principal(context, princ);
289 } else if (use_keytab != 0) {
290 if (retval = krb5_sname_to_principal(context, NULL,
294 com_err(whoami, retval,
295 "creating host service principal");
298 if (retval = krb5_unparse_name(context, princ, &princstr)) {
299 com_err(whoami, retval,
300 "while canonicalizing principal name");
301 krb5_free_principal(context, princ);
304 krb5_free_principal(context, princ);
306 } else if (!krb5_cc_get_principal(context, cc, &princ)) {
308 if (krb5_unparse_name(context, princ, &canon)) {
310 "%s: unable to canonicalize principal\n", whoami);
311 krb5_free_principal(context, princ);
314 /* strip out realm of principal if it's there */
315 realm = strchr(canon, '@');
317 if (realm - canon && *(realm - 1) != '\\')
320 realm = strchr(realm, '@');
324 cp = strchr(canon, '/');
326 if (cp - canon && *(cp - 1) != '\\')
329 cp = strchr(cp, '/');
333 princstr = (char*)malloc(strlen(canon) + 6 /* "/admin" */ +
334 (realm ? 1 + strlen(realm) : 0) + 1);
335 if (princstr == NULL) {
336 fprintf(stderr, "%s: out of memory\n", whoami);
339 strcpy(princstr, canon);
340 strcat(princstr, "/admin");
342 strcat(princstr, "@");
343 strcat(princstr, realm);
346 krb5_free_principal(context, princ);
348 } else if (luser = getenv("USER")) {
349 princstr = (char *) malloc(strlen(luser) + 7 /* "/admin@" */
350 + strlen(def_realm) + 1);
351 if (princstr == NULL) {
352 fprintf(stderr, "%s: out of memory\n", whoami);
355 strcpy(princstr, luser);
356 strcat(princstr, "/admin");
357 strcat(princstr, "@");
358 strcat(princstr, def_realm);
360 } else if (pw = getpwuid(getuid())) {
361 princstr = (char *) malloc(strlen(pw->pw_name) + 7 /* "/admin@" */
362 + strlen(def_realm) + 1);
363 if (princstr == NULL) {
364 fprintf(stderr, "%s: out of memory\n", whoami);
367 strcpy(princstr, pw->pw_name);
368 strcat(princstr, "/admin@");
369 strcat(princstr, def_realm);
372 fprintf(stderr, "%s: unable to figure out a principal name\n",
379 * Initialize the kadm5 connection. If we were given a ccache,
380 * use it. Otherwise, use/prompt for the password.
383 printf("Authenticating as principal %s with existing credentials.\n",
385 retval = kadm5_init_with_creds(princstr, cc,
388 KADM5_STRUCT_VERSION,
391 } else if (use_keytab) {
392 printf("Authenticating as principal %s with keytab %s.\n",
393 princstr, keytab_name);
394 retval = kadm5_init_with_skey(princstr, keytab_name,
397 KADM5_STRUCT_VERSION,
401 printf("Authenticating as principal %s with password.\n",
403 retval = kadm5_init_with_password(princstr, password,
406 KADM5_STRUCT_VERSION,
411 com_err(whoami, retval, "while initializing %s interface", whoami);
412 if (retval == KADM5_BAD_CLIENT_PARAMS ||
413 retval == KADM5_BAD_SERVER_PARAMS)
420 if (retval = krb5_cc_close(context, cc)) {
421 com_err(whoami, retval, "while closing ccache %s",
426 /* register the WRFILE keytab type and set it as the default */
427 if (retval = krb5_kt_register(context, &krb5_ktf_writable_ops)) {
428 com_err(whoami, retval,
429 "while registering writable key table functions");
433 #define DEFAULT_KEYTAB "WRFILE:/etc/krb5.keytab"
434 /* XXX krb5_defkeyname is an internal library global and
436 extern char *krb5_defkeyname;
437 krb5_defkeyname = DEFAULT_KEYTAB;
448 kadm5_destroy(handle);
449 if (ccache_name != NULL) {
451 "\n\a\a\aAdministration credentials NOT DESTROYED.\n");
454 /* insert more random cleanup here */
458 void kadmin_delprinc(argc, argv)
463 krb5_principal princ;
468 (argc == 3 && !strcmp("-force", argv[1])))) {
469 fprintf(stderr, "usage: delete_principal [-force] principal\n");
472 retval = kadmin_parse_name(argv[argc - 1], &princ);
474 com_err("delete_principal", retval, "while parsing principal name");
477 retval = krb5_unparse_name(context, princ, &canon);
479 com_err("delete_principal", retval,
480 "while canonicalizing principal");
481 krb5_free_principal(context, princ);
485 printf("Are you sure you want to delete the principal \"%s\"? (yes/no): ", canon);
486 fgets(reply, sizeof (reply), stdin);
487 if (strcmp("yes\n", reply)) {
488 fprintf(stderr, "Principal \"%s\" not deleted\n", canon);
490 krb5_free_principal(context, princ);
494 retval = kadm5_delete_principal(handle, princ);
495 krb5_free_principal(context, princ);
497 com_err("delete_principal", retval,
498 "while deleteing principal \"%s\"", canon);
502 printf("Principal \"%s\" deleted.\nMake sure that you have removed this principal from all ACLs before reusing.\n", canon);
507 void kadmin_cpw(argc, argv)
512 static char newpw[1024];
513 static char prompt1[1024], prompt2[1024];
515 krb5_principal princ;
521 retval = kadmin_parse_name(argv[argc - 1], &princ);
523 com_err("change_password", retval, "while parsing principal name");
526 retval = krb5_unparse_name(context, princ, &canon);
528 com_err("change_password", retval, "while canonicalizing principal");
529 krb5_free_principal(context, princ);
532 if ((argc == 4) && (strlen(argv[1]) == 3) && !strcmp("-pw", argv[1])) {
533 retval = kadm5_chpass_principal(handle, princ, argv[2]);
534 krb5_free_principal(context, princ);
536 com_err("change_password", retval,
537 "while changing password for \"%s\".", canon);
541 printf("Password for \"%s\" changed.\n", canon);
544 } else if ((argc == 3) && (strlen(argv[1]) == 8) &&
545 !strcmp("-randkey", argv[1])) {
546 retval = kadm5_randkey_principal(handle, princ, NULL, NULL);
547 krb5_free_principal(context, princ);
549 com_err("change_password", retval,
550 "while randomizing key for \"%s\".", canon);
554 printf("Key for \"%s\" randomized.\n", canon);
557 } else if (argc == 2) {
558 int i = sizeof (newpw) - 1;
560 sprintf(prompt1, "Enter password for principal \"%.900s\": ",
563 "Re-enter password for principal \"%.900s\": ",
565 retval = krb5_read_password(context, prompt1, prompt2,
568 com_err("change_password", retval,
569 "while reading password for \"%s\".", canon);
571 krb5_free_principal(context, princ);
574 retval = kadm5_chpass_principal(handle, princ, newpw);
575 krb5_free_principal(context, princ);
576 memset(newpw, 0, sizeof (newpw));
578 com_err("change_password", retval,
579 "while changing password for \"%s\".", canon);
583 printf("Password for \"%s\" changed.\n", canon);
588 krb5_free_principal(context, princ);
591 "usage: change_password [-randkey] [-pw password] "
597 int kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, randkey, caller)
600 kadm5_principal_ent_t oprinc;
606 int i, j, attrib_set;
609 krb5_error_code retval;
615 for (i = 1; i < argc - 1; i++) {
617 if (strlen(argv[i]) == 7 &&
618 !strcmp("-expire", argv[i])) {
622 date = get_date(argv[i], NULL);
623 if (date == (time_t)-1) {
624 fprintf(stderr, "Invalid date specification \"%s\".\n",
628 oprinc->princ_expire_time = date;
629 *mask |= KADM5_PRINC_EXPIRE_TIME;
633 if (strlen(argv[i]) == 9 &&
634 !strcmp("-pwexpire", argv[i])) {
638 date = get_date(argv[i], NULL);
639 if (date == (time_t)-1) {
640 fprintf(stderr, "Invalid date specification \"%s\".\n",
644 oprinc->pw_expiration = date;
645 *mask |= KADM5_PW_EXPIRATION;
649 if (strlen(argv[i]) == 8 &&
650 !strcmp("-maxlife", argv[i])) {
654 date = get_date(argv[i], NULL);
655 if (date == (time_t)-1) {
656 fprintf(stderr, "Invalid date specification \"%s\".\n",
660 oprinc->max_life = date - now;
661 *mask |= KADM5_MAX_LIFE;
665 if (strlen(argv[i]) == 13 &&
666 !strcmp("-maxrenewlife", argv[i])) {
670 date = get_date(argv[i], NULL);
671 if (date == (time_t)-1) {
672 fprintf(stderr, "Invalid date specification \"%s\".\n",
676 oprinc->max_renewable_life = date - now;
677 *mask |= KADM5_MAX_RLIFE;
681 if (strlen(argv[i]) == 5 &&
682 !strcmp("-kvno", argv[i])) {
686 oprinc->kvno = atoi(argv[i]);
691 if (strlen(argv[i]) == 7 &&
692 !strcmp("-policy", argv[i])) {
696 oprinc->policy = argv[i];
697 *mask |= KADM5_POLICY;
701 if (strlen(argv[i]) == 12 &&
702 !strcmp("-clearpolicy", argv[i])) {
703 oprinc->policy = NULL;
704 *mask |= KADM5_POLICY_CLR;
707 if (strlen(argv[i]) == 3 &&
708 !strcmp("-pw", argv[i])) {
716 if (strlen(argv[i]) == 8 &&
717 !strcmp("-randkey", argv[i])) {
721 for (j = 0; j < sizeof (flags) / sizeof (struct pflag); j++) {
722 if (strlen(argv[i]) == flags[j].flaglen + 1 &&
723 !strcmp(flags[j].flagname,
724 &argv[i][1] /* strip off leading + or - */)) {
725 if (flags[j].set && argv[i][0] == '-' ||
726 !flags[j].set && argv[i][0] == '+') {
727 oprinc->attributes |= flags[j].theflag;
728 *mask |= KADM5_ATTRIBUTES;
731 } else if (flags[j].set && argv[i][0] == '+' ||
732 !flags[j].set && argv[i][0] == '-') {
733 oprinc->attributes &= ~flags[j].theflag;
734 *mask |= KADM5_ATTRIBUTES;
743 return -1; /* nothing was parsed */
748 retval = kadmin_parse_name(argv[i], &oprinc->principal);
750 com_err(caller, retval, "while parsing principal");
756 void kadmin_addprinc_usage(func)
759 fprintf(stderr, "usage: %s [options] principal\n", func);
760 fprintf(stderr, "\toptions are:\n");
761 fprintf(stderr, "\t\t[-expire expdate] [-pwexpire pwexpdate] [-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] [-randkey] [-pw password]\n\t\t[-maxrenewlife maxrenewlife] [{+|-}attribute]\n");
762 fprintf(stderr, "\tattributes are:\n");
763 fprintf(stderr, "%s%s%s",
764 "\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n",
765 "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n",
766 "\t\trequires_hwauth needchange allow_svr password_changing_service\n");
769 void kadmin_modprinc_usage(func)
772 fprintf(stderr, "usage: %s [options] principal\n", func);
773 fprintf(stderr, "\toptions are:\n");
774 fprintf(stderr, "\t\t[-expire expdate] [-pwexpire pwexpdate] [-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n\t\t[-maxrenewlife maxrenewlife] [{+|-}attribute]\n");
775 fprintf(stderr, "\tattributes are:\n");
776 fprintf(stderr, "%s%s%s",
777 "\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n",
778 "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n",
779 "\t\trequires_hwauth needchange allow_svr password_changing_service\n");
782 void kadmin_addprinc(argc, argv)
786 kadm5_principal_ent_rec princ;
787 kadm5_policy_ent_rec defpol;
791 krb5_error_code retval;
792 static char newpw[1024], dummybuf[256];
793 static char prompt1[1024], prompt2[1024];
795 if (dummybuf[0] == 0) {
796 for (i = 0; i < 256; i++)
797 dummybuf[i] = (i+1) % 256;
800 /* Zero all fields in request structure */
801 memset(&princ, 0, sizeof(princ));
803 princ.attributes = 0;
804 if (kadmin_parse_princ_args(argc, argv,
805 &princ, &mask, &pass, &randkey,
807 kadmin_addprinc_usage("add_principal");
811 retval = krb5_unparse_name(context, princ.principal, &canon);
813 com_err("add_principal",
814 retval, "while canonicalizing principal");
815 krb5_free_principal(context, princ.principal);
820 * If -policy was not specified, and -clearpolicy was not
821 * specified, and the policy "default" exists, assign it. If
822 * -clearpolicy was specified, then KADM5_POLICY_CLR should be
823 * unset, since it is never valid for kadm5_create_principal.
825 if ((! (mask & KADM5_POLICY)) &&
826 (! (mask & KADM5_POLICY_CLR))) {
827 if (! kadm5_get_policy(handle, "default", &defpol)) {
829 "NOTICE: no policy specified for %s; assigning \"default\"\n",
831 princ.policy = "default";
832 mask |= KADM5_POLICY;
833 (void) kadm5_free_policy_ent(handle, &defpol);
836 "WARNING: no policy specified for %s; defaulting to no policy\n",
839 mask &= ~KADM5_POLICY_CLR;
841 if (randkey) { /* do special stuff if -randkey specified */
842 princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; /* set notix */
843 mask |= KADM5_ATTRIBUTES;
845 } else if (pass == NULL) {
846 int i = sizeof (newpw) - 1;
848 sprintf(prompt1, "Enter password for principal \"%.900s\": ",
851 "Re-enter password for principal \"%.900s\": ",
853 retval = krb5_read_password(context, prompt1, prompt2,
856 com_err("add_principal", retval,
857 "while reading password for \"%s\".", canon);
859 krb5_free_principal(context, princ.principal);
864 mask |= KADM5_PRINCIPAL;
865 retval = kadm5_create_principal(handle, &princ, mask, pass);
867 com_err("add_principal", retval, "while creating \"%s\".",
869 krb5_free_principal(context, princ.principal);
873 if (randkey) { /* more special stuff for -randkey */
874 retval = kadm5_randkey_principal(handle, princ.principal,
877 com_err("add_principal", retval,
878 "while randomizing key for \"%s\".", canon);
879 krb5_free_principal(context, princ.principal);
883 princ.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; /* clear notix */
884 mask = KADM5_ATTRIBUTES;
885 retval = kadm5_modify_principal(handle, &princ, mask);
887 com_err("add_principal", retval,
888 "while clearing DISALLOW_ALL_TIX for \"%s\".", canon);
889 krb5_free_principal(context, princ.principal);
894 krb5_free_principal(context, princ.principal);
895 printf("Principal \"%s\" created.\n", canon);
899 void kadmin_modprinc(argc, argv)
903 kadm5_principal_ent_rec princ, oldprinc;
904 krb5_principal kprinc;
906 krb5_error_code retval;
911 kadmin_modprinc_usage("modify_principal");
915 memset(&oldprinc, 0, sizeof(oldprinc));
916 memset(&princ, 0, sizeof(princ));
918 retval = kadmin_parse_name(argv[argc - 1], &kprinc);
920 com_err("modify_principal", retval, "while parsing principal");
923 retval = krb5_unparse_name(context, kprinc, &canon);
925 com_err("modify_principal", retval,
926 "while canonicalizing principal");
927 krb5_free_principal(context, kprinc);
930 retval = kadm5_get_principal(handle, kprinc, &oldprinc,
931 KADM5_PRINCIPAL_NORMAL_MASK);
932 krb5_free_principal(context, kprinc);
934 com_err("modify_principal", retval, "while getting \"%s\".",
939 princ.attributes = oldprinc.attributes;
940 kadm5_free_principal_ent(handle, &oldprinc);
941 retval = kadmin_parse_princ_args(argc, argv,
946 kadmin_modprinc_usage("modify_principal");
951 fprintf(stderr, "modify_principal: -randkey not allowed\n");
952 krb5_free_principal(context, princ.principal);
956 retval = kadm5_modify_principal(handle, &princ, mask);
957 krb5_free_principal(context, princ.principal);
959 com_err("modify_principal", retval,
960 "while modifying \"%s\".", canon);
964 printf("Principal \"%s\" modified.\n", canon);
968 void kadmin_getprinc(argc, argv)
972 kadm5_principal_ent_rec dprinc;
973 krb5_principal princ;
974 krb5_error_code retval;
975 char *canon, *modcanon;
979 (argc == 3 && !strcmp("-terse", argv[1])))) {
980 fprintf(stderr, "usage: get_principal [-terse] principal\n");
985 memset(&dprinc, 0, sizeof(dprinc));
986 memset(&princ, 0, sizeof(princ));
988 retval = kadmin_parse_name(argv[argc - 1], &princ);
990 com_err("get_principal", retval, "while parsing principal");
993 retval = krb5_unparse_name(context, princ, &canon);
995 com_err("get_principal", retval, "while canonicalizing principal");
996 krb5_free_principal(context, princ);
999 retval = kadm5_get_principal(handle, princ, &dprinc,
1000 KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA);
1001 krb5_free_principal(context, princ);
1003 com_err("get_principal", retval, "while retrieving \"%s\".", canon);
1007 retval = krb5_unparse_name(context, dprinc.mod_name, &modcanon);
1009 com_err("get_principal", retval, "while unparsing modname");
1010 kadm5_free_principal_ent(handle, &dprinc);
1015 printf("Principal: %s\n", canon);
1016 printf("Expiration date: %s\n", dprinc.princ_expire_time ?
1017 strdate(dprinc.princ_expire_time) : "[never]");
1018 printf("Last password change: %s\n", dprinc.last_pwd_change ?
1019 strdate(dprinc.last_pwd_change) : "[never]");
1020 printf("Password expiration date: %s\n",
1021 dprinc.pw_expiration ?
1022 strdate(dprinc.pw_expiration) : "[none]");
1023 printf("Maximum ticket life: %s\n", strdur(dprinc.max_life));
1024 printf("Maximum renewable life: %s\n", strdur(dprinc.max_renewable_life));
1025 printf("Last modified: %s (%s)\n", strdate(dprinc.mod_date), modcanon);
1026 printf("Last successful authentication: %s\n",
1027 dprinc.last_success ? strdate(dprinc.last_success) :
1029 printf("Last failed authentication: %s\n",
1030 dprinc.last_failed ? strdate(dprinc.last_failed) :
1032 printf("Failed password attempts: %d\n",
1033 dprinc.fail_auth_count);
1034 printf("Number of keys: %d\n", dprinc.n_key_data);
1035 for (i = 0; i < dprinc.n_key_data; i++) {
1036 krb5_key_data *key_data = &dprinc.key_data[i];
1037 char enctype[BUFSIZ], salttype[BUFSIZ];
1039 if (krb5_enctype_to_string(key_data->key_data_type[0],
1040 enctype, sizeof(enctype)))
1041 sprintf(enctype, "<Encryption type 0x%x>",
1042 key_data->key_data_type[0]);
1043 printf("Key: vno %d, %s, ", key_data->key_data_kvno, enctype);
1044 if (key_data->key_data_ver > 1) {
1045 if (krb5_salttype_to_string(key_data->key_data_type[1],
1046 salttype, sizeof(salttype)))
1047 sprintf(salttype, "<Salt type 0x%x>",
1048 key_data->key_data_type[1]);
1049 printf("%s\n", salttype);
1051 printf("no salt\n");
1054 printf("Attributes:");
1055 for (i = 0; i < sizeof (prflags) / sizeof (char *); i++) {
1056 if (dprinc.attributes & (krb5_flags) 1 << i)
1057 printf(" %s", prflags[i]);
1060 printf("Policy: %s\n", dprinc.policy ? dprinc.policy : "[none]");
1062 printf("\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\t%d\t%d\t%d\t%d\t\"%s\""
1063 "\t%d\t%d\t%d\t%d\t%d",
1064 canon, dprinc.princ_expire_time, dprinc.last_pwd_change,
1065 dprinc.pw_expiration, dprinc.max_life, modcanon,
1066 dprinc.mod_date, dprinc.attributes, dprinc.kvno,
1067 dprinc.mkvno, dprinc.policy ? dprinc.policy : "[none]",
1068 dprinc.max_renewable_life, dprinc.last_success,
1069 dprinc.last_failed, dprinc.fail_auth_count,
1071 for (i = 0; i < dprinc.n_key_data; i++)
1072 printf("\t%d\t%d\t%d\t%d",
1073 dprinc.key_data[i].key_data_ver,
1074 dprinc.key_data[i].key_data_kvno,
1075 dprinc.key_data[i].key_data_type[0],
1076 dprinc.key_data[i].key_data_type[1]);
1080 kadm5_free_principal_ent(handle, &dprinc);
1084 void kadmin_getprincs(argc, argv)
1088 krb5_error_code retval;
1093 if (! (argc == 1 || (argc == 2 && (exp = argv[1])))) {
1094 fprintf(stderr, "usage: get_principals [expression]\n");
1097 retval = kadm5_get_principals(handle, exp, &names, &count);
1099 com_err("get_principals", retval, "while retrieving list.");
1102 for (i = 0; i < count; i++)
1103 printf("%s\n", names[i]);
1104 kadm5_free_name_list(handle, names, count);
1107 int kadmin_parse_policy_args(argc, argv, policy, mask, caller)
1110 kadm5_policy_ent_t policy;
1117 krb5_error_code retval;
1121 for (i = 1; i < argc - 1; i++) {
1122 if (strlen(argv[i]) == 8 &&
1123 !strcmp(argv[i], "-maxlife")) {
1127 date = get_date(argv[i], NULL);
1128 if (date == (time_t)-1) {
1129 fprintf(stderr, "Invalid date specification \"%s\".\n",
1133 policy->pw_max_life = date - now;
1134 *mask |= KADM5_PW_MAX_LIFE;
1137 } else if (strlen(argv[i]) == 8 &&
1138 !strcmp(argv[i], "-minlife")) {
1142 date = get_date(argv[i], NULL);
1143 if (date == (time_t)-1) {
1144 fprintf(stderr, "Invalid date specification \"%s\".\n",
1148 policy->pw_min_life = date - now;
1149 *mask |= KADM5_PW_MIN_LIFE;
1152 } else if (strlen(argv[i]) == 10 &&
1153 !strcmp(argv[i], "-minlength")) {
1157 policy->pw_min_length = atoi(argv[i]);
1158 *mask |= KADM5_PW_MIN_LENGTH;
1161 } else if (strlen(argv[i]) == 11 &&
1162 !strcmp(argv[i], "-minclasses")) {
1166 policy->pw_min_classes = atoi(argv[i]);
1167 *mask |= KADM5_PW_MIN_CLASSES;
1170 } else if (strlen(argv[i]) == 8 &&
1171 !strcmp(argv[i], "-history")) {
1175 policy->pw_history_num = atoi(argv[i]);
1176 *mask |= KADM5_PW_HISTORY_NUM;
1183 fprintf(stderr, "%s: parser lost count!\n", caller);
1189 void kadmin_addmodpol_usage(func)
1192 fprintf(stderr, "usage; %s [options] policy\n", func);
1193 fprintf(stderr, "\toptions are:\n");
1194 fprintf(stderr, "\t\t[-maxlife time] [-minlife time] [-minlength length]\n\t\t[-minclasses number] [-history number]\n");
1197 void kadmin_addpol(argc, argv)
1201 krb5_error_code retval;
1203 kadm5_policy_ent_rec policy;
1205 memset(&policy, 0, sizeof(policy));
1206 if (kadmin_parse_policy_args(argc, argv, &policy, &mask, "add_policy")) {
1207 kadmin_addmodpol_usage("add_policy");
1210 policy.policy = argv[argc - 1];
1211 mask |= KADM5_POLICY;
1212 retval = kadm5_create_policy(handle, &policy, mask);
1214 com_err("add_policy", retval, "while creating policy \"%s\".",
1222 void kadmin_modpol(argc, argv)
1226 krb5_error_code retval;
1228 kadm5_policy_ent_rec policy;
1230 memset(&policy, 0, sizeof(policy));
1231 if (kadmin_parse_policy_args(argc, argv, &policy, &mask,
1233 kadmin_addmodpol_usage("modify_policy");
1236 policy.policy = argv[argc - 1];
1237 retval = kadm5_modify_policy(handle, &policy, mask);
1239 com_err("modify_policy", retval, "while modifying policy \"%s\".",
1247 void kadmin_delpol(argc, argv)
1251 krb5_error_code retval;
1255 (argc == 3 && !strcmp("-force", argv[1])))) {
1256 fprintf(stderr, "usage: delete_policy [-force] policy\n");
1260 printf("Are you sure you want to delete the policy \"%s\"? (yes/no): ", argv[1]);
1261 fgets(reply, sizeof (reply), stdin);
1262 if (strcmp("yes\n", reply)) {
1263 fprintf(stderr, "Policy \"%s\" not deleted.\n", argv[1]);
1267 retval = kadm5_delete_policy(handle, argv[argc - 1]);
1269 com_err("delete_policy:", retval, "while deleting policy \"%s\"",
1276 void kadmin_getpol(argc, argv)
1280 krb5_error_code retval;
1281 kadm5_policy_ent_rec policy;
1284 (argc == 3 && !strcmp("-terse", argv[1])))) {
1285 fprintf(stderr, "usage: get_policy [-terse] policy\n");
1288 retval = kadm5_get_policy(handle, argv[argc - 1], &policy);
1290 com_err("get_policy", retval, "while retrieving policy \"%s\".",
1295 printf("Policy: %s\n", policy.policy);
1296 printf("Maximum password life: %d\n", policy.pw_max_life);
1297 printf("Minimum password life: %d\n", policy.pw_min_life);
1298 printf("Minimum password length: %d\n", policy.pw_min_length);
1299 printf("Minimum number of password character classes: %d\n",
1300 policy.pw_min_classes);
1301 printf("Number of old keys kept: %d\n", policy.pw_history_num);
1302 printf("Reference count: %d\n", policy.policy_refcnt);
1304 printf("\"%s\"\t%d\t%d\t%d\t%d\t%d\t%d\n",
1305 policy.policy, policy.pw_max_life, policy.pw_min_life,
1306 policy.pw_min_length, policy.pw_min_classes,
1307 policy.pw_history_num, policy.policy_refcnt);
1309 kadm5_free_policy_ent(handle, &policy);
1313 void kadmin_getpols(argc, argv)
1317 krb5_error_code retval;
1322 if (! (argc == 1 || (argc == 2 && (exp = argv[1])))) {
1323 fprintf(stderr, "usage: get_policies [expression]\n");
1326 retval = kadm5_get_policies(handle, exp, &names, &count);
1328 com_err("get_policies", retval, "while retrieving list.");
1331 for (i = 0; i < count; i++)
1332 printf("%s\n", names[i]);
1333 kadm5_free_name_list(handle, names, count);
1336 void kadmin_getprivs(argc, argv)
1340 static char *privs[] = {"GET", "ADD", "MODIFY", "DELETE"};
1341 krb5_error_code retval;
1346 fprintf(stderr, "usage: get_privs\n");
1349 retval = kadm5_get_privs(handle, &plist);
1351 com_err("get_privs", retval, "while retrieving privileges");
1354 printf("current privileges:");
1355 for (i = 0; i < sizeof (privs) / sizeof (char *); i++) {
1357 printf(" %s", privs[i]);