1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* 9 * Copyright 1994 by the Massachusetts Institute of Technology. 10 * All Rights Reserved. 11 * 12 * Export of this software from the United States of America may 13 * require a specific license from the United States Government. 14 * It is the responsibility of any person or organization contemplating 15 * export to obtain such a license before exporting. 16 * 17 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 18 * distribute this software and its documentation for any purpose and 19 * without fee is hereby granted, provided that the above copyright 20 * notice appear in all copies and that both that copyright notice and 21 * this permission notice appear in supporting documentation, and that 22 * the name of M.I.T. not be used in advertising or publicity pertaining 23 * to distribution of the software without specific, written prior 24 * permission. Furthermore if you modify this software you must label 25 * your software as modified software and not distribute it in such a 26 * fashion that it might be confused with the original M.I.T. software. 27 * M.I.T. makes no representations about the suitability of 28 * this software for any purpose. It is provided "as is" without express 29 * or implied warranty. 30 * 31 * kadmin.c: base functions for a kadmin command line interface using 32 * the OVSecure library 33 */ 34 35 #include <krb5.h> 36 #include <k5-int.h> 37 #include <kadm5/admin.h> 38 #include <stdio.h> 39 #include <string.h> 40 #include <sys/types.h> 41 #include <math.h> 42 #include <unistd.h> 43 #include <pwd.h> 44 /* #include <sys/timeb.h> */ 45 #include <time.h> 46 #include <libintl.h> 47 48 /* 49 * Solaris: the following are needed for paging 50 */ 51 #include <signal.h> 52 #include <sys/wait.h> 53 54 /* command name when called "locally" (i.e. non-networked client ) */ 55 #define KADMIN_LOCAL_NAME "kadmin.local" 56 57 /* functions defined in remote/local specific files */ 58 extern void usage(const char *); 59 extern void debugEnable(int); 60 61 /* local principal helpers */ 62 static char *find_component(const char *, char); 63 static char *trim_principal(char *); 64 static char *build_admin_princ(const char *, const char *); 65 66 /* 67 * special struct to convert flag names for principals 68 * to actual krb5_flags for a principal 69 */ 70 struct pflag { 71 char *flagname; /* name of flag as typed to CLI */ 72 int flaglen; /* length of string (not counting -,+) */ 73 krb5_flags theflag; /* actual principal flag to set/clear */ 74 int set; /* 0 means clear, 1 means set (on '-') */ 75 }; 76 77 static struct pflag flags[] = { 78 {"allow_postdated", 15, KRB5_KDB_DISALLOW_POSTDATED, 1}, 79 {"allow_forwardable", 17, KRB5_KDB_DISALLOW_FORWARDABLE, 1}, 80 {"allow_tgs_req", 13, KRB5_KDB_DISALLOW_TGT_BASED, 1}, 81 {"allow_renewable", 15, KRB5_KDB_DISALLOW_RENEWABLE, 1}, 82 {"allow_proxiable", 15, KRB5_KDB_DISALLOW_PROXIABLE, 1}, 83 {"allow_dup_skey", 14, KRB5_KDB_DISALLOW_DUP_SKEY, 1}, 84 {"allow_tix", 9, KRB5_KDB_DISALLOW_ALL_TIX, 1}, 85 {"requires_preauth", 16, KRB5_KDB_REQUIRES_PRE_AUTH, 0}, 86 {"requires_hwauth", 15, KRB5_KDB_REQUIRES_HW_AUTH, 0}, 87 {"needchange", 10, KRB5_KDB_REQUIRES_PWCHANGE, 0}, 88 {"allow_svr", 9, KRB5_KDB_DISALLOW_SVR, 1}, 89 {"password_changing_service", 25, KRB5_KDB_PWCHANGE_SERVICE, 0 }, 90 {"support_desmd5", 14, KRB5_KDB_SUPPORT_DESMD5, 0 } 91 }; 92 93 static char *prflags[] = { 94 "DISALLOW_POSTDATED", /* 0x00000001 */ 95 "DISALLOW_FORWARDABLE", /* 0x00000002 */ 96 "DISALLOW_TGT_BASED", /* 0x00000004 */ 97 "DISALLOW_RENEWABLE", /* 0x00000008 */ 98 "DISALLOW_PROXIABLE", /* 0x00000010 */ 99 "DISALLOW_DUP_SKEY", /* 0x00000020 */ 100 "DISALLOW_ALL_TIX", /* 0x00000040 */ 101 "REQUIRES_PRE_AUTH", /* 0x00000080 */ 102 "REQUIRES_HW_AUTH", /* 0x00000100 */ 103 "REQUIRES_PWCHANGE", /* 0x00000200 */ 104 "UNKNOWN_0x00000400", /* 0x00000400 */ 105 "UNKNOWN_0x00000800", /* 0x00000800 */ 106 "DISALLOW_SVR", /* 0x00001000 */ 107 "PWCHANGE_SERVICE", /* 0x00002000 */ 108 "SUPPORT_DESMD5", /* 0x00004000 */ 109 "NEW_PRINC", /* 0x00008000 */ 110 }; 111 112 char *getenv(); 113 int exit_status = 0; 114 char *def_realm = NULL; 115 char *whoami = NULL; 116 time_t get_date(); 117 118 void *handle = NULL; 119 krb5_context context; 120 char *ccache_name = NULL; 121 122 char * 123 strdur(duration) 124 time_t duration; 125 { 126 static char out[100]; 127 int days, hours, minutes, seconds; 128 129 days = duration / (24 * 3600); 130 duration %= 24 * 3600; 131 hours = duration / 3600; 132 duration %= 3600; 133 minutes = duration / 60; 134 duration %= 60; 135 seconds = duration; 136 if (days == 1) { 137 snprintf(out, sizeof (out), gettext("%d day %02d:%02d:%02d"), 138 days, hours, minutes, seconds); 139 } else { 140 snprintf(out, sizeof (out), gettext("%d days %02d:%02d:%02d"), 141 days, hours, minutes, seconds); 142 } 143 return (out); 144 } 145 146 char * 147 strdate(when) 148 krb5_timestamp when; 149 { 150 struct tm *tm; 151 static char out[30]; 152 153 time_t lcltim = when; 154 155 tm = localtime(&lcltim); 156 strftime(out, 30, gettext("%a %b %d %H:%M:%S %Z %Y"), tm); 157 return (out); 158 } 159 160 /* 161 * this is a wrapper to go around krb5_parse_principal so we can set 162 * the default realm up properly 163 */ 164 krb5_error_code 165 kadmin_parse_name(name, principal) 166 char *name; 167 krb5_principal *principal; 168 { 169 char *cp, *fullname; 170 krb5_error_code retval; 171 172 if (name == NULL) 173 return (EINVAL); 174 175 /* assumes def_realm is initialized! */ 176 fullname = (char *)malloc(strlen(name) + 1 + strlen(def_realm) + 1); 177 if (fullname == NULL) 178 return (ENOMEM); 179 strcpy(fullname, name); 180 cp = strchr(fullname, '@'); 181 while (cp) { 182 if (cp - fullname && *(cp - 1) != '\\') 183 break; 184 else 185 cp = strchr((cp + 1), '@'); 186 } 187 if (cp == NULL) { 188 strcat(fullname, "@"); 189 strcat(fullname, def_realm); 190 } 191 retval = krb5_parse_name(context, fullname, principal); 192 free(fullname); 193 return (retval); 194 } 195 196 char * 197 kadmin_startup(argc, argv) 198 int argc; 199 char *argv[]; 200 { 201 extern krb5_kt_ops krb5_ktf_writable_ops; 202 extern char *optarg; 203 char *princstr = NULL, *keytab_name = NULL, *query = NULL; 204 char *password = NULL; 205 char *kadmin_princ = NULL; 206 char *luser, *canon, *cp; 207 int optchar, use_keytab = 0, debug = 0; 208 struct passwd *pw; 209 kadm5_ret_t retval; 210 krb5_ccache cc; 211 krb5_principal princ; 212 kadm5_config_params params; 213 214 memset((char *) ¶ms, 0, sizeof(params)); 215 216 if (retval = krb5_init_context(&context)) { 217 com_err(whoami, retval, 218 gettext("while initializing krb5 library")); 219 exit(1); 220 } 221 while ((optchar = getopt(argc, argv, "Dr:p:kq:w:d:s:mc:t:e:O")) != EOF) { 222 switch (optchar) { 223 case 'O': /* Undocumented option for testing only */ 224 kadmin_princ = KADM5_ADMIN_SERVICE_P; 225 break; 226 case 'D': 227 debug++; 228 break; 229 case 'r': 230 def_realm = optarg; 231 break; 232 case 'p': 233 princstr = strdup(optarg); 234 if (princstr == NULL) { 235 fprintf(stderr, gettext("Out of memory in %s\n"), 236 whoami); 237 exit(1); 238 } 239 break; 240 case 'c': 241 ccache_name = optarg; 242 break; 243 case 'k': 244 use_keytab++; 245 break; 246 case 't': 247 keytab_name = optarg; 248 break; 249 case 'w': 250 password = optarg; 251 break; 252 case 'q': 253 query = optarg; 254 break; 255 case 'd': 256 params.dbname = optarg; 257 params.mask |= KADM5_CONFIG_DBNAME; 258 break; 259 case 's': 260 params.admin_server = optarg; 261 params.mask |= KADM5_CONFIG_ADMIN_SERVER; 262 break; 263 case 'm': 264 params.mkey_from_kbd = 1; 265 params.mask |= KADM5_CONFIG_MKEY_FROM_KBD; 266 break; 267 case 'e': 268 retval = krb5_string_to_keysalts(optarg, 269 ", \t", ":.-", 0, 270 ¶ms.keysalts, 271 ¶ms.num_keysalts); 272 if (retval) { 273 com_err(whoami, retval, 274 gettext("while parsing keysalts %s"), optarg); 275 exit(1); 276 } 277 params.mask |= KADM5_CONFIG_ENCTYPES; 278 break; 279 default: 280 usage(whoami); 281 } 282 } 283 284 debugEnable(debug); 285 286 if ((ccache_name && use_keytab) || 287 (keytab_name && !use_keytab)) 288 usage(whoami); 289 290 if (def_realm == NULL && krb5_get_default_realm(context, &def_realm)) { 291 free(princstr); 292 fprintf(stderr, 293 gettext("%s: unable to get default realm\n"), whoami); 294 exit(1); 295 } 296 params.mask |= KADM5_CONFIG_REALM; 297 params.realm = def_realm; 298 299 if (kadmin_princ == NULL) { 300 if (kadm5_get_adm_host_srv_name(context, 301 def_realm, &kadmin_princ)) { 302 fprintf(stderr, 303 gettext("%s: unable to get host based " 304 "service name for realm %s\n"), 305 whoami, def_realm); 306 free(princstr); 307 exit(1); 308 } 309 } 310 311 /* 312 * Set cc to an open credentials cache, either specified by the -c 313 * argument or the default. 314 */ 315 if (ccache_name == NULL) { 316 if (retval = krb5_cc_default(context, &cc)) { 317 com_err(whoami, retval, 318 gettext("while opening default " 319 "credentials cache")); 320 exit(1); 321 } 322 } else { 323 if (retval = krb5_cc_resolve(context, ccache_name, &cc)) { 324 com_err(whoami, retval, 325 gettext("while opening credentials cache %s"), 326 ccache_name); 327 exit(1); 328 } 329 } 330 331 /* 332 * If no principal name is specified: If a ccache was specified and 333 * its primary principal name can be read, it is used, else if a 334 * keytab was specified, the principal name is host/hostname, 335 * otherwise append "/admin" to the primary name of the default 336 * ccache, $USER, or pw_name. 337 * 338 * Gee, 100+ lines to figure out the client principal name. This 339 * should be compressed... 340 */ 341 342 if (princstr == NULL) { 343 if (ccache_name != NULL && 344 !krb5_cc_get_principal(context, cc, &princ)) { 345 if (retval = krb5_unparse_name(context, princ, 346 &princstr)) { 347 com_err(whoami, retval, 348 gettext("while canonicalizing principal name")); 349 krb5_free_principal(context, princ); 350 exit(1); 351 } 352 krb5_free_principal(context, princ); 353 } else if (use_keytab != 0) { 354 if (retval = krb5_sname_to_principal(context, NULL, 355 "host", KRB5_NT_SRV_HST, 356 &princ)) { 357 com_err(whoami, retval, 358 gettext("creating host service principal")); 359 exit(1); 360 } 361 if (retval = krb5_unparse_name(context, princ, 362 &princstr)) { 363 com_err(whoami, retval, 364 gettext("while canonicalizing " 365 "principal name")); 366 krb5_free_principal(context, princ); 367 exit(1); 368 } 369 krb5_free_principal(context, princ); 370 } else if (!krb5_cc_get_principal(context, cc, &princ)) { 371 char *realm = NULL; 372 373 if (krb5_unparse_name(context, princ, &canon)) { 374 fprintf(stderr, 375 gettext("%s: unable to canonicalize " 376 "principal\n"), whoami); 377 krb5_free_principal(context, princ); 378 exit(1); 379 } 380 krb5_free_principal(context, princ); 381 (void) trim_principal(canon); 382 princstr = build_admin_princ(canon, def_realm); 383 free(canon); 384 } else if (luser = getenv("USER")) { 385 princstr = build_admin_princ(luser, def_realm); 386 } else if (pw = getpwuid(getuid())) { 387 princstr = build_admin_princ(pw->pw_name, def_realm); 388 } else { 389 fprintf(stderr, 390 gettext("%s: unable to figure out " 391 "a principal name\n"), 392 whoami); 393 exit(1); 394 } 395 } else { /* (princstr != NULL) */ 396 /* See if we need to add the default realm */ 397 if (find_component(princstr, '@') == NULL) { 398 size_t len; 399 400 /* principal @ realm NULL */ 401 len = strlen(princstr) + 1 + strlen(def_realm) + 1; 402 princstr = realloc(princstr, len); 403 if (princstr == NULL) { 404 fprintf(stderr, 405 gettext("%s: out of memory\n"), whoami); 406 exit(1); 407 } 408 strcat(princstr, "@"); 409 strcat(princstr, def_realm); 410 } 411 } 412 413 /* 414 * Initialize the kadm5 connection. If we were given a ccache, use 415 * it. Otherwise, use/prompt for the password. 416 */ 417 if (ccache_name) { 418 printf(gettext( 419 "Authenticating as principal %s with existing credentials.\n"), 420 princstr); 421 retval = kadm5_init_with_creds(princstr, cc, 422 kadmin_princ, 423 ¶ms, 424 KADM5_STRUCT_VERSION, 425 KADM5_API_VERSION_2, 426 &handle); 427 } else if (use_keytab) { 428 if (keytab_name) 429 printf(gettext("Authenticating as principal %s with keytab %s.\n"), 430 princstr, keytab_name); 431 else 432 printf(gettext( 433 "Authenticating as principal %s with default keytab.\n"), 434 princstr); 435 retval = kadm5_init_with_skey(princstr, keytab_name, 436 kadmin_princ, 437 ¶ms, 438 KADM5_STRUCT_VERSION, 439 KADM5_API_VERSION_2, 440 &handle); 441 } else { 442 printf(gettext("Authenticating as principal %s with password.\n"), 443 princstr); 444 retval = kadm5_init_with_password(princstr, password, 445 kadmin_princ, ¶ms, 446 KADM5_STRUCT_VERSION, 447 KADM5_API_VERSION_2, 448 &handle); 449 } 450 if (retval) { 451 if (retval == KADM5_RPC_ERROR_CANTENCODEARGS || 452 retval == KADM5_RPC_ERROR_CANTDECODEARGS) { 453 com_err(whoami, KADM5_RPC_ERROR, 454 gettext("while initializing %s interface"), whoami); 455 456 /* privacy-enabled mech probably not installed/configed */ 457 com_err(whoami, retval, gettext("."), whoami); 458 } else { 459 com_err(whoami, retval, 460 gettext("while initializing %s interface"), whoami); 461 if (retval == KADM5_BAD_CLIENT_PARAMS || 462 retval == KADM5_BAD_SERVER_PARAMS) 463 usage(whoami); 464 } 465 exit(1); 466 } 467 free(princstr); 468 469 if (retval = krb5_cc_close(context, cc)) { 470 com_err(whoami, retval, gettext("while closing ccache %s"), 471 ccache_name); 472 exit(1); 473 } 474 /* register the WRFILE keytab type and set it as the default */ 475 if (retval = krb5_kt_register(context, &krb5_ktf_writable_ops)) { 476 com_err(whoami, retval, 477 gettext("while registering writable key table functions")); 478 exit(1); 479 } 480 { 481 /* 482 * XXX krb5_defkeyname is an internal library global and 483 * should go away 484 */ 485 extern char *krb5_defkeyname; 486 487 krb5_defkeyname = DEFAULT_KEYTAB; 488 } 489 490 if ((retval = kadm5_init_iprop(handle)) != 0) { 491 com_err(whoami, retval, gettext("while mapping update log")); 492 exit(1); 493 } 494 495 /* Solaris kerberos: fix memory leak */ 496 if (kadmin_princ) 497 free(kadmin_princ); 498 499 return (query); 500 } 501 502 static char * 503 find_component(const char *principal, char sep) 504 { 505 char *p = strchr(principal, sep); 506 507 for(p = strchr(principal, sep); p; p = strchr(p, sep)) 508 if (p != principal && *(p - 1) != '\\') 509 break; 510 return (p); 511 } 512 513 static char * 514 trim_principal(char *principal) 515 { 516 char *p = find_component(principal, '/'); 517 518 if (p == NULL) 519 p = find_component(principal, '@'); 520 521 if (p) 522 *p = '\0'; 523 524 return (principal); 525 } 526 527 static char * 528 build_admin_princ(const char *user, const char *realm) 529 { 530 char *princstr; 531 532 /* Add 7 to the length for "/admin@" */ 533 princstr = (char *) malloc(strlen(user) + 7 + strlen(realm) + 1); 534 if (princstr == NULL) { 535 fprintf(stderr, 536 gettext("%s: out of memory\n"), 537 whoami); 538 exit(1); 539 } 540 sprintf(princstr, "%s/admin@%s", user, realm); 541 542 return (princstr); 543 } 544 545 int 546 quit() 547 { 548 krb5_ccache cc; 549 int retval; 550 551 kadm5_destroy(handle); 552 if (ccache_name != NULL) { 553 fprintf(stderr, 554 gettext("\n\a\a\aAdministration credentials " 555 "NOT DESTROYED.\n")); 556 } 557 /* insert more random cleanup here */ 558 krb5_free_context(context); 559 context = NULL; 560 return (0); 561 } 562 563 void 564 kadmin_delprinc(argc, argv) 565 int argc; 566 char *argv[]; 567 { 568 kadm5_ret_t retval; 569 krb5_principal princ; 570 char *canon; 571 char reply[32]; 572 573 if (! (argc == 2 || 574 (argc == 3 && strcmp("-force", argv[1]) == 0))) { 575 fprintf(stderr, "%s: delete_principal [-force] %s\n", 576 gettext("usage"), gettext("principal")); 577 return; 578 } 579 retval = kadmin_parse_name(argv[argc - 1], &princ); 580 if (retval) { 581 com_err("delete_principal", retval, 582 gettext("while parsing principal name")); 583 return; 584 } 585 retval = krb5_unparse_name(context, princ, &canon); 586 if (retval) { 587 com_err("delete_principal", retval, 588 gettext("while canonicalizing principal")); 589 krb5_free_principal(context, princ); 590 return; 591 } 592 if (argc == 2) { 593 printf(gettext("Are you sure you want to delete " 594 "the principal \"%s\"? (yes/no): "), canon); 595 fgets(reply, sizeof (reply), stdin); 596 if (strncmp(gettext("yes\n"), reply, sizeof (reply)) && 597 strncmp(gettext("y\n"), reply, sizeof (reply)) && 598 strncmp(gettext("Y\n"), reply, sizeof (reply))) { 599 fprintf(stderr, 600 gettext("Principal \"%s\" not deleted\n"), 601 canon); 602 free(canon); 603 krb5_free_principal(context, princ); 604 return; 605 } 606 } 607 retval = kadm5_delete_principal(handle, princ); 608 krb5_free_principal(context, princ); 609 if (retval) { 610 com_err("delete_principal", retval, 611 gettext("while deleting principal \"%s\""), canon); 612 free(canon); 613 return; 614 } 615 printf(gettext("Principal \"%s\" deleted.\n"), canon); 616 printf(gettext("Make sure that you have removed this principal " 617 "from all ACLs before reusing.\n")); 618 free(canon); 619 } 620 621 void 622 kadmin_cpw(argc, argv) 623 int argc; 624 char *argv[]; 625 { 626 kadm5_ret_t retval; 627 static char newpw[1024]; 628 static char prompt1[1024], prompt2[1024]; 629 char *canon; 630 char *pwarg = NULL; 631 int n_ks_tuple = 0, keepold = 0, randkey = 0; 632 krb5_key_salt_tuple *ks_tuple = NULL; 633 krb5_principal princ; 634 635 if (argc < 2) { 636 goto usage; 637 } 638 for (argv++, argc--; argc > 1; argc--, argv++) { 639 if (!strcmp("-pw", *argv)) { 640 argc--; 641 if (argc < 1) { 642 fprintf(stderr, "change_password: %s", 643 gettext("missing password arg\n")); 644 goto usage; 645 } 646 pwarg = *++argv; 647 continue; 648 } 649 if (!strcmp("-randkey", *argv)) { 650 randkey++; 651 continue; 652 } 653 if (!strcmp("-keepold", *argv)) { 654 keepold++; 655 continue; 656 } 657 if (!strcmp("-e", *argv)) { 658 argc--; 659 if (argc < 1) { 660 fprintf(stderr, "change_password: %s", 661 gettext("missing keysaltlist arg\n")); 662 goto usage; 663 } 664 retval = krb5_string_to_keysalts(*++argv, ", \t", ":.-", 0, 665 &ks_tuple, &n_ks_tuple); 666 if (retval) { 667 com_err("change_password", retval, 668 gettext("while parsing keysalts %s"), *argv); 669 return; 670 } 671 continue; 672 } 673 goto usage; 674 } 675 retval = kadmin_parse_name(*argv, &princ); 676 if (retval) { 677 com_err("change_password", retval, 678 gettext("while parsing principal name")); 679 if (ks_tuple != NULL) 680 free(ks_tuple); 681 goto usage; 682 } 683 retval = krb5_unparse_name(context, princ, &canon); 684 if (retval) { 685 com_err("change_password", retval, 686 gettext("while canonicalizing principal")); 687 krb5_free_principal(context, princ); 688 if (ks_tuple != NULL) 689 free(ks_tuple); 690 return; 691 } 692 if (pwarg != NULL) { 693 if (keepold || ks_tuple != NULL) { 694 retval = kadm5_chpass_principal_3(handle, princ, keepold, 695 n_ks_tuple, ks_tuple, pwarg); 696 if (ks_tuple != NULL) 697 free(ks_tuple); 698 } else { 699 retval = kadm5_chpass_principal(handle, princ, pwarg); 700 } 701 krb5_free_principal(context, princ); 702 if (retval) { 703 com_err("change_password", retval, 704 gettext("while changing password for \"%s\"."), 705 canon); 706 free(canon); 707 return; 708 } 709 printf(gettext("Password for \"%s\" changed.\n"), canon); 710 free(canon); 711 return; 712 } else if (randkey) { 713 if (keepold || ks_tuple != NULL) { 714 retval = kadm5_randkey_principal_3(handle, princ, keepold, 715 n_ks_tuple, ks_tuple, 716 NULL, NULL); 717 if (ks_tuple != NULL) 718 free(ks_tuple); 719 } else { 720 retval = kadm5_randkey_principal(handle, princ, NULL, NULL); 721 } 722 krb5_free_principal(context, princ); 723 if (retval) { 724 com_err("change_password", retval, 725 gettext("while randomizing key for \"%s\"."), 726 canon); 727 free(canon); 728 return; 729 } 730 printf(gettext("Key for \"%s\" randomized.\n"), canon); 731 free(canon); 732 return; 733 } else if (argc == 1) { 734 unsigned int i = sizeof (newpw) - 1; 735 736 snprintf(prompt1, sizeof (prompt1), 737 gettext("Enter password for principal \"%.900s\": "), 738 *argv); 739 snprintf(prompt2, sizeof (prompt2), 740 gettext("Re-enter password for principal \"%.900s\": "), 741 *argv); 742 retval = krb5_read_password(context, prompt1, prompt2, 743 newpw, &i); 744 if (retval) { 745 com_err("change_password", retval, 746 gettext("while reading password for \"%s\"."), 747 canon); 748 free(canon); 749 if (ks_tuple != NULL) 750 free(ks_tuple); 751 krb5_free_principal(context, princ); 752 return; 753 } 754 if (keepold || ks_tuple != NULL) { 755 retval = kadm5_chpass_principal_3(handle, princ, keepold, 756 n_ks_tuple, ks_tuple, 757 newpw); 758 if (ks_tuple != NULL) 759 free(ks_tuple); 760 } else { 761 retval = kadm5_chpass_principal(handle, princ, newpw); 762 } 763 krb5_free_principal(context, princ); 764 memset(newpw, 0, sizeof (newpw)); 765 if (retval) { 766 com_err("change_password", retval, 767 gettext("while changing password for \"%s\"."), 768 canon); 769 free(canon); 770 return; 771 } 772 printf(gettext("Password for \"%s\" changed.\n"), canon); 773 free(canon); 774 return; 775 } else { 776 free(canon); 777 krb5_free_principal(context, princ); 778 usage: 779 fprintf(stderr, "%s: change_password [-randkey] [-keepold] " 780 "[-e keysaltlist] [-pw password] %s\n", 781 gettext("usage"), gettext("principal")); 782 return; 783 } 784 } 785 786 int kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, randkey, 787 ks_tuple, n_ks_tuple, caller) 788 int argc; 789 char *argv[]; 790 kadm5_principal_ent_t oprinc; 791 long *mask; 792 char **pass; 793 int *randkey; 794 krb5_key_salt_tuple **ks_tuple; 795 int *n_ks_tuple; 796 char *caller; 797 { 798 int i, j, attrib_set; 799 time_t date; 800 time_t now; 801 krb5_error_code retval; 802 803 *mask = 0; 804 *pass = NULL; 805 *n_ks_tuple = 0; 806 *ks_tuple = NULL; 807 time(&now); 808 *randkey = 0; 809 for (i = 1; i < argc - 1; i++) { 810 attrib_set = 0; 811 if (strlen(argv[i]) == 7 && 812 strcmp("-expire", argv[i]) == 0) { 813 if (++i > argc - 2) 814 return (-1); 815 else { 816 date = get_date(argv[i], NULL); 817 if (date == (time_t)-1) { 818 fprintf(stderr, 819 gettext("Invalid date " 820 "specification " 821 "\"%s\".\n"), 822 argv[i]); 823 return (-1); 824 } 825 oprinc->princ_expire_time = date; 826 *mask |= KADM5_PRINC_EXPIRE_TIME; 827 continue; 828 } 829 } 830 if (strlen(argv[i]) == 9 && 831 strcmp("-pwexpire", argv[i]) == 0) { 832 if (++i > argc - 2) 833 return (-1); 834 else { 835 date = get_date(argv[i], NULL); 836 if (date == (time_t)-1) { 837 fprintf(stderr, 838 gettext("Invalid date " 839 "specification " 840 "\"%s\".\n"), 841 argv[i]); 842 return (-1); 843 } 844 oprinc->pw_expiration = date; 845 *mask |= KADM5_PW_EXPIRATION; 846 continue; 847 } 848 } 849 if (strlen(argv[i]) == 8 && 850 strcmp("-maxlife", argv[i]) == 0) { 851 if (++i > argc - 2) 852 return (-1); 853 else { 854 date = get_date(argv[i], NULL); 855 if (date == (time_t)-1) { 856 fprintf(stderr, 857 gettext("Invalid date " 858 "specification " 859 "\"%s\".\n"), 860 argv[i]); 861 return (-1); 862 } 863 if (date <= now) { 864 fprintf(stderr, 865 gettext("Date specified is " 866 "in the past " 867 "\"%s\".\n"), 868 argv[i]); 869 return (-1); 870 } 871 oprinc->max_life = date - now; 872 *mask |= KADM5_MAX_LIFE; 873 continue; 874 } 875 } 876 if (strlen(argv[i]) == 13 && 877 strcmp("-maxrenewlife", argv[i]) == 0) { 878 if (++i > argc - 2) 879 return (-1); 880 else { 881 date = get_date(argv[i], NULL); 882 if (date == (time_t)-1) { 883 fprintf(stderr, 884 gettext("Invalid date " 885 "specification " 886 "\"%s\".\n"), 887 argv[i]); 888 return (-1); 889 } 890 if (date <= now) { 891 fprintf(stderr, 892 gettext("Date specified is " 893 "in the past " 894 "\"%s\".\n"), 895 argv[i]); 896 return (-1); 897 } 898 oprinc->max_renewable_life = date - now; 899 *mask |= KADM5_MAX_RLIFE; 900 continue; 901 } 902 } 903 if (strlen(argv[i]) == 5 && 904 strcmp("-kvno", argv[i]) == 0) { 905 if (++i > argc - 2) 906 return (-1); 907 else { 908 oprinc->kvno = atoi(argv[i]); 909 *mask |= KADM5_KVNO; 910 continue; 911 } 912 } 913 if (strlen(argv[i]) == 7 && 914 strcmp("-policy", argv[i]) == 0) { 915 if (++i > argc - 2) 916 return (-1); 917 else { 918 oprinc->policy = argv[i]; 919 *mask |= KADM5_POLICY; 920 continue; 921 } 922 } 923 if (strlen(argv[i]) == 12 && 924 strcmp("-clearpolicy", argv[i]) == 0) { 925 oprinc->policy = NULL; 926 *mask |= KADM5_POLICY_CLR; 927 continue; 928 } 929 if (strlen(argv[i]) == 3 && 930 strcmp("-pw", argv[i]) == 0) { 931 if (++i > argc - 2) 932 return (-1); 933 else { 934 *pass = argv[i]; 935 continue; 936 } 937 } 938 if (strlen(argv[i]) == 8 && 939 strcmp("-randkey", argv[i]) == 0) { 940 ++*randkey; 941 continue; 942 } 943 if (!strcmp("-e", argv[i])) { 944 if (++i > argc - 2) 945 return -1; 946 else { 947 retval = krb5_string_to_keysalts(argv[i], ", \t", ":.-", 0, 948 ks_tuple, n_ks_tuple); 949 if (retval) { 950 com_err(caller, retval, 951 gettext("while parsing keysalts %s"), argv[i]); 952 return -1; 953 } 954 } 955 continue; 956 } 957 for (j = 0; j < sizeof (flags) / sizeof (struct pflag); j++) { 958 if (strlen(argv[i]) == flags[j].flaglen + 1 && 959 strcmp(flags[j].flagname, 960 /* strip off leading + or - */ 961 &argv[i][1]) == 0) { 962 if (flags[j].set && argv[i][0] == '-' || 963 !flags[j].set && argv[i][0] == '+') { 964 oprinc->attributes |= flags[j].theflag; 965 *mask |= KADM5_ATTRIBUTES; 966 attrib_set++; 967 break; 968 } else if (flags[j].set && argv[i][0] == '+' || 969 !flags[j].set && argv[i][0] == '-') { 970 oprinc->attributes &= ~flags[j].theflag; 971 *mask |= KADM5_ATTRIBUTES; 972 attrib_set++; 973 break; 974 } else { 975 return (-1); 976 } 977 } 978 } 979 if (!attrib_set) 980 return (-1); /* nothing was parsed */ 981 } 982 if (i != argc - 1) { 983 return (-1); 984 } 985 retval = kadmin_parse_name(argv[i], &oprinc->principal); 986 if (retval) { 987 com_err(caller, retval, gettext("while parsing principal")); 988 return (-1); 989 } 990 return (0); 991 } 992 993 void 994 kadmin_addprinc_usage(func) 995 char *func; 996 { 997 fprintf(stderr, "%s: %s %s\n", gettext("usage"), func, 998 gettext("[options] principal")); 999 fprintf(stderr, gettext("\toptions are:\n")); 1000 fprintf(stderr, "\t\t[-expire expdate] [-pwexpire pwexpdate] " 1001 "[-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] " 1002 "[-randkey] [-pw password]\n\t\t[-maxrenewlife maxrenewlife] " 1003 "[-e keysaltlist] [{+|-}attribute]\n"); 1004 fprintf(stderr, gettext("\tattributes are:\n")); 1005 fprintf(stderr, "%s%s%s", 1006 "\t\tallow_postdated allow_forwardable allow_tgs_req " 1007 "allow_renewable\n", 1008 "\t\tallow_proxiable allow_dup_skey allow_tix " 1009 "requires_preauth\n", 1010 "\t\trequires_hwauth needchange allow_svr " 1011 "password_changing_service\n"); 1012 } 1013 1014 void 1015 kadmin_modprinc_usage(func) 1016 char *func; 1017 { 1018 fprintf(stderr, "%s: %s %s\n", gettext("usage"), func, 1019 gettext("[options] principal")); 1020 fprintf(stderr, gettext("\toptions are:\n")); 1021 fprintf(stderr, "\t\t[-expire expdate] [-pwexpire pwexpdate] " 1022 "[-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] " 1023 "[-clearpolicy]\n\t\t[-maxrenewlife maxrenewlife] " 1024 "[{+|-}attribute]\n"); 1025 fprintf(stderr, gettext("\tattributes are:\n")); 1026 fprintf(stderr, "%s%s%s", 1027 "\t\tallow_postdated allow_forwardable allow_tgs_req " 1028 "allow_renewable\n", 1029 "\t\tallow_proxiable allow_dup_skey allow_tix " 1030 "requires_preauth\n", 1031 "\t\trequires_hwauth needchange allow_svr " 1032 "password_changing_service\n"); 1033 } 1034 1035 void 1036 kadmin_addprinc(argc, argv) 1037 int argc; 1038 char *argv[]; 1039 { 1040 kadm5_principal_ent_rec princ, dprinc; 1041 kadm5_policy_ent_rec defpol; 1042 long mask; 1043 int randkey = 0, i; 1044 int n_ks_tuple; 1045 krb5_key_salt_tuple *ks_tuple; 1046 char *pass, *canon; 1047 krb5_error_code retval; 1048 static char newpw[1024], dummybuf[256]; 1049 static char prompt1[1024], prompt2[1024]; 1050 int local_kadmin = 0; 1051 1052 local_kadmin = (strcmp(whoami, KADMIN_LOCAL_NAME) == 0); 1053 1054 if (dummybuf[0] == 0) { 1055 for (i = 0; i < 256; i++) 1056 dummybuf[i] = (i+1) % 256; 1057 } 1058 1059 /* Zero all fields in request structure */ 1060 memset(&princ, 0, sizeof(princ)); 1061 memset(&dprinc, 0, sizeof(dprinc)); 1062 1063 princ.attributes = dprinc.attributes = 0; 1064 if (kadmin_parse_princ_args(argc, argv, 1065 &princ, &mask, &pass, &randkey, 1066 &ks_tuple, &n_ks_tuple, 1067 "add_principal")) { 1068 kadmin_addprinc_usage("add_principal"); 1069 return; 1070 } 1071 1072 retval = krb5_unparse_name(context, princ.principal, &canon); 1073 if (retval) { 1074 com_err("add_principal", retval, 1075 gettext("while canonicalizing principal")); 1076 krb5_free_principal(context, princ.principal); 1077 if (ks_tuple != NULL) 1078 free(ks_tuple); 1079 return; 1080 } 1081 1082 /* 1083 * If -policy was not specified, and -clearpolicy was not 1084 * specified, and the policy "default" exists, assign it. If 1085 * -clearpolicy was specified, then KADM5_POLICY_CLR should be 1086 * unset, since it is never valid for kadm5_create_principal. 1087 */ 1088 if ((! (mask & KADM5_POLICY)) && 1089 (! (mask & KADM5_POLICY_CLR))) { 1090 if (! kadm5_get_policy(handle, "default", &defpol)) { 1091 fprintf(stderr, 1092 gettext( 1093 "NOTICE: no policy specified for %s; assigning \"default\"\n"), 1094 canon); 1095 princ.policy = "default"; 1096 mask |= KADM5_POLICY; 1097 (void) kadm5_free_policy_ent(handle, &defpol); 1098 } else 1099 fprintf(stderr, gettext("WARNING: no policy specified " 1100 "for %s; defaulting to no policy\n"), canon); 1101 } 1102 mask &= ~KADM5_POLICY_CLR; 1103 1104 /* 1105 * Set 'notix' for randkey principals and also for principals which have 1106 * specified flag options on the cmdline. This is because we want to apply 1107 * generic flag settings from 'default_principal_flags' first (during 1108 * principal creation), followed by a kadm5_modify_principal() which 1109 * correctly applies the cli flag options. So, we do *not* want any tix 1110 * issued in the interim. 1111 */ 1112 if (randkey || (mask & KADM5_ATTRIBUTES)) 1113 princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; 1114 1115 if (randkey) { 1116 pass = dummybuf; 1117 mask |= KADM5_ATTRIBUTES; 1118 } else if (pass == NULL) { 1119 unsigned int i = sizeof (newpw) - 1; 1120 snprintf(prompt1, sizeof (prompt1), 1121 gettext("Enter password for principal \"%.900s\": "), 1122 canon); 1123 snprintf(prompt2, sizeof (prompt1), 1124 gettext("Re-enter password for principal \"%.900s\": "), 1125 canon); 1126 retval = krb5_read_password(context, prompt1, prompt2, 1127 newpw, &i); 1128 if (retval) { 1129 com_err("add_principal", retval, 1130 gettext("while reading password for \"%s\"."), canon); 1131 free(canon); 1132 krb5_free_principal(context, princ.principal); 1133 return; 1134 } 1135 pass = newpw; 1136 } 1137 mask |= KADM5_PRINCIPAL; 1138 1139 /* 1140 * If the client being used is local, always use the new 1141 * API so we get the full set of enctype support. 1142 */ 1143 if (ks_tuple != NULL || local_kadmin) { 1144 retval = kadm5_create_principal_3(handle, &princ, mask, 1145 n_ks_tuple, ks_tuple, pass); 1146 } else { 1147 retval = kadm5_create_principal(handle, &princ, mask, pass); 1148 } 1149 if (retval) { 1150 com_err("add_principal", retval, 1151 gettext("while creating \"%s\"."), canon); 1152 krb5_free_principal(context, princ.principal); 1153 free(canon); 1154 if (ks_tuple != NULL) 1155 free(ks_tuple); 1156 return; 1157 } 1158 1159 if (randkey) { /* more special stuff for -randkey */ 1160 if (ks_tuple != NULL || local_kadmin) { 1161 retval = kadm5_randkey_principal_3(handle, princ.principal, 1162 FALSE, 1163 n_ks_tuple, ks_tuple, 1164 NULL, NULL); 1165 } else { 1166 retval = kadm5_randkey_principal(handle, princ.principal, 1167 NULL, NULL); 1168 } 1169 if (retval) { 1170 com_err("add_principal", retval, 1171 gettext("while randomizing key for \"%s\"."), canon); 1172 krb5_free_principal(context, princ.principal); 1173 free(canon); 1174 if (ks_tuple != NULL) 1175 free(ks_tuple); 1176 return; 1177 } 1178 } 1179 1180 /* 1181 * We now retrieve the intersection set of the generic flag settings and 1182 * the ones specified on the cli & re-parse the princ args, just to make 1183 * sure we account for conflicts between 'default_principal_flags' and 1184 * the cmdline flag args. While we are here, also clear 'notix'. 1185 */ 1186 if (randkey || (mask & KADM5_ATTRIBUTES)) { 1187 retval = kadm5_get_principal(handle, princ.principal, &dprinc, 1188 KADM5_PRINCIPAL_NORMAL_MASK); 1189 if (retval == 0) { 1190 if (dprinc.attributes != 0) 1191 princ.attributes = dprinc.attributes; 1192 } else { 1193 com_err("add_principal", retval, 1194 gettext("while doing a get_principal on \"%s\"."), canon); 1195 printf(gettext("\nWarning: Principal \"%s\" could have incomplete " 1196 "flag settings, as a result of a failed get_principal.\n" 1197 "Check the 'default_principal_flags' setting in kdc.conf(4).\n" 1198 "If there is a mismatch, use modprinc in kadmin(1M) to rectify " 1199 "the same.\n\n"), canon); 1200 } 1201 1202 (void) kadmin_parse_princ_args(argc, argv, &princ, &mask, &pass, 1203 &randkey, &ks_tuple, &n_ks_tuple, "add_principal"); 1204 1205 princ.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; 1206 mask = KADM5_ATTRIBUTES; 1207 retval = kadm5_modify_principal(handle, &princ, mask); 1208 if (retval) { 1209 com_err("add_principal", retval, 1210 gettext("while doing a modify_principal to restore flag " 1211 "settings for \"%s\"."), canon); 1212 krb5_free_principal(context, princ.principal); 1213 free(canon); 1214 if (ks_tuple != NULL) 1215 free(ks_tuple); 1216 return; 1217 } 1218 } 1219 1220 krb5_free_principal(context, princ.principal); 1221 printf(gettext("Principal \"%s\" created.\n"), canon); 1222 if (ks_tuple != NULL) 1223 free(ks_tuple); 1224 free(canon); 1225 } 1226 1227 void 1228 kadmin_modprinc(argc, argv) 1229 int argc; 1230 char *argv[]; 1231 { 1232 kadm5_principal_ent_rec princ, oldprinc; 1233 krb5_principal kprinc; 1234 long mask; 1235 krb5_error_code retval; 1236 char *pass, *canon; 1237 int randkey = 0; 1238 int n_ks_tuple = 0; 1239 krb5_key_salt_tuple *ks_tuple; 1240 1241 if (argc < 2) { 1242 kadmin_modprinc_usage("modify_principal"); 1243 return; 1244 } 1245 1246 memset(&oldprinc, 0, sizeof(oldprinc)); 1247 memset(&princ, 0, sizeof(princ)); 1248 1249 retval = kadmin_parse_name(argv[argc - 1], &kprinc); 1250 if (retval) { 1251 com_err("modify_principal", retval, 1252 gettext("while parsing principal")); 1253 return; 1254 } 1255 retval = krb5_unparse_name(context, kprinc, &canon); 1256 if (retval) { 1257 com_err("modify_principal", retval, 1258 gettext("while canonicalizing principal")); 1259 krb5_free_principal(context, kprinc); 1260 return; 1261 } 1262 retval = kadm5_get_principal(handle, kprinc, &oldprinc, 1263 KADM5_PRINCIPAL_NORMAL_MASK); 1264 krb5_free_principal(context, kprinc); 1265 if (retval) { 1266 com_err("modify_principal", retval, 1267 gettext("while getting \"%s\"."), canon); 1268 free(canon); 1269 return; 1270 } 1271 princ.attributes = oldprinc.attributes; 1272 kadm5_free_principal_ent(handle, &oldprinc); 1273 retval = kadmin_parse_princ_args(argc, argv, 1274 &princ, &mask, 1275 &pass, &randkey, 1276 &ks_tuple, &n_ks_tuple, 1277 "modify_principal"); 1278 if (ks_tuple != NULL) { 1279 free(ks_tuple); 1280 kadmin_modprinc_usage("modify_principal"); 1281 free(canon); 1282 return; 1283 } 1284 if (retval) { 1285 kadmin_modprinc_usage("modify_principal"); 1286 free(canon); 1287 return; 1288 } 1289 if (randkey) { 1290 fprintf(stderr, "modify_principal: -randkey %s ", 1291 gettext("not allowed\n")); 1292 krb5_free_principal(context, princ.principal); 1293 free(canon); 1294 return; 1295 } 1296 if (pass) { 1297 fprintf(stderr, 1298 "modify_principal: -pw %s change_password\n", 1299 gettext("not allowed; use")); 1300 krb5_free_principal(context, princ.principal); 1301 free(canon); 1302 return; 1303 } 1304 retval = kadm5_modify_principal(handle, &princ, mask); 1305 krb5_free_principal(context, princ.principal); 1306 if (retval) { 1307 com_err("modify_principal", retval, 1308 gettext("while modifying \"%s\"."), canon); 1309 free(canon); 1310 return; 1311 } 1312 printf(gettext("Principal \"%s\" modified.\n"), canon); 1313 free(canon); 1314 } 1315 1316 void 1317 kadmin_getprinc(argc, argv) 1318 int argc; 1319 char *argv[]; 1320 { 1321 kadm5_principal_ent_rec dprinc; 1322 krb5_principal princ; 1323 krb5_error_code retval; 1324 char *canon, *modcanon; 1325 int i; 1326 1327 if (! (argc == 2 || 1328 (argc == 3 && strcmp("-terse", argv[1]) == 0))) { 1329 fprintf(stderr, "%s: get_principal [-terse] %s\n", 1330 gettext("usage"), gettext("principal")); 1331 return; 1332 } 1333 memset(&dprinc, 0, sizeof(dprinc)); 1334 memset(&princ, 0, sizeof(princ)); 1335 1336 retval = kadmin_parse_name(argv[argc - 1], &princ); 1337 if (retval) { 1338 com_err("get_principal", retval, 1339 gettext("while parsing principal")); 1340 return; 1341 } 1342 retval = krb5_unparse_name(context, princ, &canon); 1343 if (retval) { 1344 com_err("get_principal", retval, 1345 gettext("while canonicalizing principal")); 1346 krb5_free_principal(context, princ); 1347 return; 1348 } 1349 retval = kadm5_get_principal(handle, princ, &dprinc, 1350 KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA); 1351 krb5_free_principal(context, princ); 1352 if (retval) { 1353 com_err("get_principal", retval, 1354 gettext("while retrieving \"%s\"."), canon); 1355 free(canon); 1356 return; 1357 } 1358 retval = krb5_unparse_name(context, dprinc.mod_name, &modcanon); 1359 if (retval) { 1360 com_err("get_principal", retval, 1361 gettext("while unparsing modname")); 1362 kadm5_free_principal_ent(handle, &dprinc); 1363 free(canon); 1364 return; 1365 } 1366 if (argc == 2) { 1367 printf(gettext("Principal: %s\n"), canon); 1368 printf(gettext("Expiration date: %s\n"), 1369 dprinc.princ_expire_time ? 1370 strdate(dprinc.princ_expire_time) : 1371 gettext("[never]")); 1372 printf(gettext("Last password change: %s\n"), 1373 dprinc.last_pwd_change ? 1374 strdate(dprinc.last_pwd_change) : 1375 gettext("[never]")); 1376 printf(gettext("Password expiration date: %s\n"), 1377 dprinc.pw_expiration ? 1378 strdate(dprinc.pw_expiration) : gettext("[none]")); 1379 printf(gettext("Maximum ticket life: %s\n"), 1380 strdur(dprinc.max_life)); 1381 printf(gettext("Maximum renewable life: %s\n"), 1382 strdur(dprinc.max_renewable_life)); 1383 printf(gettext("Last modified: %s (%s)\n"), 1384 strdate(dprinc.mod_date), modcanon); 1385 printf(gettext("Last successful authentication: %s\n"), 1386 dprinc.last_success ? strdate(dprinc.last_success) : 1387 gettext("[never]")); 1388 printf(gettext("Last failed authentication: %s\n"), 1389 dprinc.last_failed ? strdate(dprinc.last_failed) : 1390 gettext("[never]")); 1391 printf(gettext("Failed password attempts: %d\n"), 1392 dprinc.fail_auth_count); 1393 printf(gettext("Number of keys: %d\n"), dprinc.n_key_data); 1394 for (i = 0; i < dprinc.n_key_data; i++) { 1395 krb5_key_data *key_data = &dprinc.key_data[i]; 1396 char enctype[BUFSIZ], salttype[BUFSIZ]; 1397 1398 if (krb5_enctype_to_string(key_data->key_data_type[0], 1399 enctype, sizeof(enctype))) 1400 snprintf(enctype, sizeof (enctype), 1401 gettext("<Encryption type 0x%x>"), 1402 key_data->key_data_type[0]); 1403 printf(gettext("Key: vno %d, %s, "), 1404 key_data->key_data_kvno, enctype); 1405 if (key_data->key_data_ver > 1) { 1406 if (krb5_salttype_to_string( 1407 key_data->key_data_type[1], 1408 salttype, sizeof(salttype))) 1409 snprintf(salttype, sizeof (salttype), 1410 gettext("<Salt type 0x%x>"), 1411 key_data->key_data_type[1]); 1412 printf("%s\n", salttype); 1413 } else 1414 printf(gettext("no salt\n")); 1415 } 1416 1417 printf(gettext("Attributes:")); 1418 for (i = 0; i < sizeof (prflags) / sizeof (char *); i++) { 1419 if (dprinc.attributes & (krb5_flags) 1 << i) 1420 printf(" %s", prflags[i]); 1421 } 1422 printf("\n"); 1423 printf(gettext("Policy: %s\n"), 1424 dprinc.policy ? dprinc.policy : gettext("[none]")); 1425 } else { 1426 printf("\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"" 1427 "\t%d\t%d\t%d\t%d\t%d", 1428 canon, dprinc.princ_expire_time, dprinc.last_pwd_change, 1429 dprinc.pw_expiration, dprinc.max_life, modcanon, 1430 dprinc.mod_date, dprinc.attributes, dprinc.kvno, 1431 dprinc.mkvno, dprinc.policy ? 1432 dprinc.policy : gettext("[none]"), 1433 dprinc.max_renewable_life, dprinc.last_success, 1434 dprinc.last_failed, dprinc.fail_auth_count, 1435 dprinc.n_key_data); 1436 for (i = 0; i < dprinc.n_key_data; i++) 1437 printf("\t%d\t%d\t%d\t%d", 1438 dprinc.key_data[i].key_data_ver, 1439 dprinc.key_data[i].key_data_kvno, 1440 dprinc.key_data[i].key_data_type[0], 1441 dprinc.key_data[i].key_data_type[1]); 1442 printf("\n"); 1443 } 1444 free(modcanon); 1445 kadm5_free_principal_ent(handle, &dprinc); 1446 free(canon); 1447 } 1448 1449 void 1450 kadmin_getprincs(argc, argv) 1451 int argc; 1452 char *argv[]; 1453 { 1454 krb5_error_code retval; 1455 char *exp, **names; 1456 int i, count; 1457 1458 FILE *output; 1459 int fd; 1460 struct sigaction nsig, osig; 1461 sigset_t nmask, omask; 1462 int waitb; 1463 1464 exp = NULL; 1465 if (! (argc == 1 || (argc == 2 && (exp = argv[1])))) { 1466 fprintf(stderr, "%s: get_principals %s\n", 1467 gettext("usage"), gettext("[expression]")); 1468 return; 1469 } 1470 retval = kadm5_get_principals(handle, exp, &names, &count); 1471 if (retval) { 1472 com_err("get_principals", retval, 1473 gettext("while retrieving list.")); 1474 return; 1475 } 1476 1477 /* 1478 * Solaris: the following code is used for paging 1479 */ 1480 1481 sigemptyset(&nmask); 1482 sigaddset(&nmask, SIGINT); 1483 sigprocmask(SIG_BLOCK, &nmask, &omask); 1484 1485 nsig.sa_handler = SIG_IGN; 1486 sigemptyset(&nsig.sa_mask); 1487 nsig.sa_flags = 0; 1488 sigaction(SIGINT, &nsig, &osig); 1489 1490 fd = ss_pager_create(); 1491 output = fdopen(fd, "w"); 1492 1493 sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0); 1494 1495 for (i = 0; i < count; i++) 1496 fprintf(output, "%s\n", names[i]); 1497 1498 fclose(output); 1499 1500 wait(&waitb); 1501 1502 kadm5_free_name_list(handle, names, count); 1503 } 1504 1505 int 1506 kadmin_parse_policy_args(argc, argv, policy, mask, caller) 1507 int argc; 1508 char *argv[]; 1509 kadm5_policy_ent_t policy; 1510 long *mask; 1511 char *caller; 1512 { 1513 int i; 1514 time_t now; 1515 time_t date; 1516 krb5_error_code retval; 1517 1518 time(&now); 1519 *mask = 0; 1520 for (i = 1; i < argc - 1; i++) { 1521 if (strlen(argv[i]) == 8 && 1522 strcmp(argv[i], "-maxlife") == 0) { 1523 if (++i > argc -2) 1524 return (-1); 1525 else { 1526 date = get_date(argv[i], NULL); 1527 if (date == (time_t)-1) { 1528 fprintf(stderr, 1529 gettext("Invalid date " 1530 "specification " 1531 "\"%s\".\n"), 1532 argv[i]); 1533 return (-1); 1534 } 1535 if (date <= now) { 1536 fprintf(stderr, 1537 gettext("Date specified is " 1538 "in the past " 1539 "\"%s\".\n"), 1540 argv[i]); 1541 return (-1); 1542 } 1543 policy->pw_max_life = date - now; 1544 *mask |= KADM5_PW_MAX_LIFE; 1545 continue; 1546 } 1547 } else if (strlen(argv[i]) == 8 && 1548 strcmp(argv[i], "-minlife") == 0) { 1549 if (++i > argc - 2) 1550 return (-1); 1551 else { 1552 date = get_date(argv[i], NULL); 1553 if (date == (time_t)-1) { 1554 fprintf(stderr, 1555 gettext("Invalid date " 1556 "specification " 1557 "\"%s\".\n"), 1558 argv[i]); 1559 return (-1); 1560 } 1561 if (date <= now) { 1562 fprintf(stderr, 1563 gettext("Date specified is " 1564 "in the past " 1565 "\"%s\".\n"), 1566 argv[i]); 1567 return (-1); 1568 } 1569 policy->pw_min_life = date - now; 1570 *mask |= KADM5_PW_MIN_LIFE; 1571 continue; 1572 } 1573 } else if (strlen(argv[i]) == 10 && 1574 strcmp(argv[i], "-minlength") == 0) { 1575 if (++i > argc - 2) 1576 return (-1); 1577 else { 1578 policy->pw_min_length = atoi(argv[i]); 1579 *mask |= KADM5_PW_MIN_LENGTH; 1580 continue; 1581 } 1582 } else if (strlen(argv[i]) == 11 && 1583 strcmp(argv[i], "-minclasses") == 0) { 1584 if (++i > argc - 2) 1585 return (-1); 1586 else { 1587 policy->pw_min_classes = atoi(argv[i]); 1588 *mask |= KADM5_PW_MIN_CLASSES; 1589 continue; 1590 } 1591 } else if (strlen(argv[i]) == 8 && 1592 strcmp(argv[i], "-history") == 0) { 1593 if (++i > argc - 2) 1594 return (-1); 1595 else { 1596 policy->pw_history_num = atoi(argv[i]); 1597 *mask |= KADM5_PW_HISTORY_NUM; 1598 continue; 1599 } 1600 } else 1601 return (-1); 1602 } 1603 if (i != argc -1) { 1604 fprintf(stderr, gettext("%s: parser lost count!\n"), caller); 1605 return (-1); 1606 } else 1607 return (0); 1608 } 1609 1610 void 1611 kadmin_addmodpol_usage(func) 1612 char *func; 1613 { 1614 fprintf(stderr, "%s: %s %s\n", gettext("usage"), func, 1615 gettext("[options] policy")); 1616 fprintf(stderr, gettext("\toptions are:\n")); 1617 fprintf(stderr, "\t\t[-maxlife time] [-minlife time] " 1618 "[-minlength length]\n\t\t[-minclasses number] " 1619 "[-history number]\n"); 1620 } 1621 1622 void 1623 kadmin_addpol(argc, argv) 1624 int argc; 1625 char *argv[]; 1626 { 1627 krb5_error_code retval; 1628 long mask; 1629 kadm5_policy_ent_rec policy; 1630 1631 memset(&policy, 0, sizeof(policy)); 1632 if (kadmin_parse_policy_args(argc, argv, 1633 &policy, &mask, "add_policy")) { 1634 kadmin_addmodpol_usage("add_policy"); 1635 return; 1636 } else { 1637 policy.policy = argv[argc - 1]; 1638 mask |= KADM5_POLICY; 1639 retval = kadm5_create_policy(handle, &policy, mask); 1640 if (retval) { 1641 com_err("add_policy", retval, 1642 gettext("while creating policy \"%s\"."), 1643 policy.policy); 1644 return; 1645 } 1646 } 1647 } 1648 1649 void 1650 kadmin_modpol(argc, argv) 1651 int argc; 1652 char *argv[]; 1653 { 1654 krb5_error_code retval; 1655 long mask; 1656 kadm5_policy_ent_rec policy; 1657 1658 memset(&policy, 0, sizeof(policy)); 1659 if (kadmin_parse_policy_args(argc, argv, &policy, &mask, 1660 "modify_policy")) { 1661 kadmin_addmodpol_usage("modify_policy"); 1662 return; 1663 } else { 1664 policy.policy = argv[argc - 1]; 1665 retval = kadm5_modify_policy(handle, &policy, mask); 1666 if (retval) { 1667 com_err("modify_policy", retval, 1668 gettext("while modifying policy \"%s\"."), 1669 policy.policy); 1670 return; 1671 } 1672 } 1673 } 1674 1675 void 1676 kadmin_delpol(argc, argv) 1677 int argc; 1678 char *argv[]; 1679 { 1680 krb5_error_code retval; 1681 char reply[32]; 1682 1683 if (! (argc == 2 || 1684 (argc == 3 && strcmp("-force", argv[1]) == 0))) { 1685 fprintf(stderr, "%s: delete_policy [-force] %s\n", 1686 gettext("usage"), gettext("policy")); 1687 return; 1688 } 1689 if (argc == 2) { 1690 printf(gettext("Are you sure you want to delete the policy " 1691 "\"%s\"? (yes/no): "), argv[1]); 1692 fgets(reply, sizeof (reply), stdin); 1693 if (strncmp(gettext("yes\n"), reply, sizeof (reply)) && 1694 strncmp(gettext("y\n"), reply, sizeof (reply)) && 1695 strncmp(gettext("Y\n"), reply, sizeof (reply)) 1696 ) { 1697 fprintf(stderr, 1698 gettext("Policy \"%s\" not deleted.\n"), 1699 argv[1]); 1700 return; 1701 } 1702 } 1703 retval = kadm5_delete_policy(handle, argv[argc - 1]); 1704 if (retval) { 1705 com_err("delete_policy:", retval, 1706 gettext("while deleting policy \"%s\""), 1707 argv[argc - 1]); 1708 return; 1709 } 1710 } 1711 1712 void 1713 kadmin_getpol(argc, argv) 1714 int argc; 1715 char *argv[]; 1716 { 1717 krb5_error_code retval; 1718 kadm5_policy_ent_rec policy; 1719 1720 if (! (argc == 2 || 1721 (argc == 3 && strcmp("-terse", argv[1]) == 0))) { 1722 fprintf(stderr, "%s: get_policy [-terse] %s\n", 1723 gettext("usage"), gettext("policy")); 1724 return; 1725 } 1726 retval = kadm5_get_policy(handle, argv[argc - 1], &policy); 1727 if (retval) { 1728 com_err("get_policy", retval, 1729 gettext("while retrieving policy \"%s\"."), 1730 argv[argc - 1]); 1731 return; 1732 } 1733 if (argc == 2) { 1734 printf(gettext("Policy: %s\n"), policy.policy); 1735 printf(gettext("Maximum password life: %d\n"), 1736 policy.pw_max_life); 1737 printf(gettext("Minimum password life: %d\n"), 1738 policy.pw_min_life); 1739 printf(gettext("Minimum password length: %d\n"), 1740 policy.pw_min_length); 1741 printf(gettext("Minimum number of password " 1742 "character classes: %d\n"), 1743 policy.pw_min_classes); 1744 printf(gettext("Number of old keys kept: %d\n"), 1745 policy.pw_history_num); 1746 printf(gettext("Reference count: %d\n"), policy.policy_refcnt); 1747 } else { 1748 printf("\"%s\"\t%d\t%d\t%d\t%d\t%d\t%d\n", 1749 policy.policy, policy.pw_max_life, policy.pw_min_life, 1750 policy.pw_min_length, policy.pw_min_classes, 1751 policy.pw_history_num, policy.policy_refcnt); 1752 } 1753 kadm5_free_policy_ent(handle, &policy); 1754 } 1755 1756 void 1757 kadmin_getpols(argc, argv) 1758 int argc; 1759 char *argv[]; 1760 { 1761 krb5_error_code retval; 1762 char *exp, **names; 1763 int i, count; 1764 1765 exp = NULL; 1766 if (! (argc == 1 || (argc == 2 && (exp = argv[1])))) { 1767 fprintf(stderr, "%s: get_policies %s\n", 1768 gettext("usage"), gettext("[expression]\n")); 1769 return; 1770 } 1771 retval = kadm5_get_policies(handle, exp, &names, &count); 1772 if (retval) { 1773 com_err("get_policies", retval, 1774 gettext("while retrieving list.")); 1775 return; 1776 } 1777 for (i = 0; i < count; i++) 1778 printf("%s\n", names[i]); 1779 kadm5_free_name_list(handle, names, count); 1780 } 1781