1 /* 2 * Copyright 2006 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 int local_kadmin = 0; 635 636 local_kadmin = (strcmp(whoami, KADMIN_LOCAL_NAME) == 0); 637 638 if (argc < 2) { 639 goto usage; 640 } 641 for (argv++, argc--; argc > 1; argc--, argv++) { 642 if (!strcmp("-pw", *argv)) { 643 argc--; 644 if (argc < 1) { 645 fprintf(stderr, "change_password: %s", 646 gettext("missing password arg\n")); 647 goto usage; 648 } 649 pwarg = *++argv; 650 continue; 651 } 652 if (!strcmp("-randkey", *argv)) { 653 randkey++; 654 continue; 655 } 656 if (!strcmp("-keepold", *argv)) { 657 keepold++; 658 continue; 659 } 660 if (!strcmp("-e", *argv)) { 661 argc--; 662 if (argc < 1) { 663 fprintf(stderr, "change_password: %s", 664 gettext("missing keysaltlist arg\n")); 665 goto usage; 666 } 667 retval = krb5_string_to_keysalts(*++argv, ", \t", ":.-", 0, 668 &ks_tuple, &n_ks_tuple); 669 if (retval) { 670 com_err("change_password", retval, 671 gettext("while parsing keysalts %s"), *argv); 672 return; 673 } 674 continue; 675 } 676 goto usage; 677 } 678 retval = kadmin_parse_name(*argv, &princ); 679 if (retval) { 680 com_err("change_password", retval, 681 gettext("while parsing principal name")); 682 if (ks_tuple != NULL) 683 free(ks_tuple); 684 goto usage; 685 } 686 retval = krb5_unparse_name(context, princ, &canon); 687 if (retval) { 688 com_err("change_password", retval, 689 gettext("while canonicalizing principal")); 690 krb5_free_principal(context, princ); 691 if (ks_tuple != NULL) 692 free(ks_tuple); 693 return; 694 } 695 if (pwarg != NULL) { 696 if (keepold || ks_tuple != NULL) { 697 retval = kadm5_chpass_principal_3(handle, princ, keepold, 698 n_ks_tuple, ks_tuple, pwarg); 699 if (ks_tuple != NULL) 700 free(ks_tuple); 701 } else { 702 retval = kadm5_chpass_principal(handle, princ, pwarg); 703 } 704 krb5_free_principal(context, princ); 705 if (retval) { 706 com_err("change_password", retval, 707 gettext("while changing password for \"%s\"."), 708 canon); 709 free(canon); 710 return; 711 } 712 printf(gettext("Password for \"%s\" changed.\n"), canon); 713 free(canon); 714 return; 715 } else if (randkey) { 716 if (keepold || ks_tuple != NULL || local_kadmin) { 717 retval = kadm5_randkey_principal_3(handle, princ, keepold, 718 n_ks_tuple, ks_tuple, 719 NULL, NULL); 720 if (ks_tuple != NULL) 721 free(ks_tuple); 722 } else { 723 retval = kadm5_randkey_principal(handle, princ, NULL, NULL); 724 } 725 krb5_free_principal(context, princ); 726 if (retval) { 727 com_err("change_password", retval, 728 gettext("while randomizing key for \"%s\"."), 729 canon); 730 free(canon); 731 return; 732 } 733 printf(gettext("Key for \"%s\" randomized.\n"), canon); 734 free(canon); 735 return; 736 } else if (argc == 1) { 737 unsigned int i = sizeof (newpw) - 1; 738 739 snprintf(prompt1, sizeof (prompt1), 740 gettext("Enter password for principal \"%.900s\""), 741 *argv); 742 snprintf(prompt2, sizeof (prompt2), 743 gettext("Re-enter password for principal \"%.900s\""), 744 *argv); 745 retval = krb5_read_password(context, prompt1, prompt2, 746 newpw, &i); 747 if (retval) { 748 com_err("change_password", retval, 749 gettext("while reading password for \"%s\"."), 750 canon); 751 free(canon); 752 if (ks_tuple != NULL) 753 free(ks_tuple); 754 krb5_free_principal(context, princ); 755 return; 756 } 757 if (keepold || ks_tuple != NULL) { 758 retval = kadm5_chpass_principal_3(handle, princ, keepold, 759 n_ks_tuple, ks_tuple, 760 newpw); 761 if (ks_tuple != NULL) 762 free(ks_tuple); 763 } else { 764 retval = kadm5_chpass_principal(handle, princ, newpw); 765 } 766 krb5_free_principal(context, princ); 767 memset(newpw, 0, sizeof (newpw)); 768 if (retval) { 769 com_err("change_password", retval, 770 gettext("while changing password for \"%s\"."), 771 canon); 772 free(canon); 773 return; 774 } 775 printf(gettext("Password for \"%s\" changed.\n"), canon); 776 free(canon); 777 return; 778 } else { 779 free(canon); 780 krb5_free_principal(context, princ); 781 usage: 782 fprintf(stderr, "%s: change_password [-randkey] [-keepold] " 783 "[-e keysaltlist] [-pw password] %s\n", 784 gettext("usage"), gettext("principal")); 785 return; 786 } 787 } 788 789 int kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, randkey, 790 ks_tuple, n_ks_tuple, caller) 791 int argc; 792 char *argv[]; 793 kadm5_principal_ent_t oprinc; 794 long *mask; 795 char **pass; 796 int *randkey; 797 krb5_key_salt_tuple **ks_tuple; 798 int *n_ks_tuple; 799 char *caller; 800 { 801 int i, j, attrib_set; 802 time_t date; 803 time_t now; 804 krb5_error_code retval; 805 806 *mask = 0; 807 *pass = NULL; 808 *n_ks_tuple = 0; 809 *ks_tuple = NULL; 810 time(&now); 811 *randkey = 0; 812 for (i = 1; i < argc - 1; i++) { 813 attrib_set = 0; 814 if (strlen(argv[i]) == 7 && 815 strcmp("-expire", argv[i]) == 0) { 816 if (++i > argc - 2) 817 return (-1); 818 else { 819 date = get_date(argv[i], NULL); 820 if (date == (time_t)-1) { 821 fprintf(stderr, 822 gettext("Invalid date " 823 "specification " 824 "\"%s\".\n"), 825 argv[i]); 826 return (-1); 827 } 828 oprinc->princ_expire_time = date; 829 *mask |= KADM5_PRINC_EXPIRE_TIME; 830 continue; 831 } 832 } 833 if (strlen(argv[i]) == 9 && 834 strcmp("-pwexpire", argv[i]) == 0) { 835 if (++i > argc - 2) 836 return (-1); 837 else { 838 date = get_date(argv[i], NULL); 839 if (date == (time_t)-1) { 840 fprintf(stderr, 841 gettext("Invalid date " 842 "specification " 843 "\"%s\".\n"), 844 argv[i]); 845 return (-1); 846 } 847 oprinc->pw_expiration = date; 848 *mask |= KADM5_PW_EXPIRATION; 849 continue; 850 } 851 } 852 if (strlen(argv[i]) == 8 && 853 strcmp("-maxlife", argv[i]) == 0) { 854 if (++i > argc - 2) 855 return (-1); 856 else { 857 date = get_date(argv[i], NULL); 858 if (date == (time_t)-1) { 859 fprintf(stderr, 860 gettext("Invalid date " 861 "specification " 862 "\"%s\".\n"), 863 argv[i]); 864 return (-1); 865 } 866 if (date <= now) { 867 fprintf(stderr, 868 gettext("Date specified is " 869 "in the past " 870 "\"%s\".\n"), 871 argv[i]); 872 return (-1); 873 } 874 oprinc->max_life = date - now; 875 *mask |= KADM5_MAX_LIFE; 876 continue; 877 } 878 } 879 if (strlen(argv[i]) == 13 && 880 strcmp("-maxrenewlife", argv[i]) == 0) { 881 if (++i > argc - 2) 882 return (-1); 883 else { 884 date = get_date(argv[i], NULL); 885 if (date == (time_t)-1) { 886 fprintf(stderr, 887 gettext("Invalid date " 888 "specification " 889 "\"%s\".\n"), 890 argv[i]); 891 return (-1); 892 } 893 if (date <= now) { 894 fprintf(stderr, 895 gettext("Date specified is " 896 "in the past " 897 "\"%s\".\n"), 898 argv[i]); 899 return (-1); 900 } 901 oprinc->max_renewable_life = date - now; 902 *mask |= KADM5_MAX_RLIFE; 903 continue; 904 } 905 } 906 if (strlen(argv[i]) == 5 && 907 strcmp("-kvno", argv[i]) == 0) { 908 if (++i > argc - 2) 909 return (-1); 910 else { 911 oprinc->kvno = atoi(argv[i]); 912 *mask |= KADM5_KVNO; 913 continue; 914 } 915 } 916 if (strlen(argv[i]) == 7 && 917 strcmp("-policy", argv[i]) == 0) { 918 if (++i > argc - 2) 919 return (-1); 920 else { 921 oprinc->policy = argv[i]; 922 *mask |= KADM5_POLICY; 923 continue; 924 } 925 } 926 if (strlen(argv[i]) == 12 && 927 strcmp("-clearpolicy", argv[i]) == 0) { 928 oprinc->policy = NULL; 929 *mask |= KADM5_POLICY_CLR; 930 continue; 931 } 932 if (strlen(argv[i]) == 3 && 933 strcmp("-pw", argv[i]) == 0) { 934 if (++i > argc - 2) 935 return (-1); 936 else { 937 *pass = argv[i]; 938 continue; 939 } 940 } 941 if (strlen(argv[i]) == 8 && 942 strcmp("-randkey", argv[i]) == 0) { 943 ++*randkey; 944 continue; 945 } 946 if (!strcmp("-e", argv[i])) { 947 if (++i > argc - 2) 948 return -1; 949 else { 950 retval = krb5_string_to_keysalts(argv[i], ", \t", ":.-", 0, 951 ks_tuple, n_ks_tuple); 952 if (retval) { 953 com_err(caller, retval, 954 gettext("while parsing keysalts %s"), argv[i]); 955 return -1; 956 } 957 } 958 continue; 959 } 960 for (j = 0; j < sizeof (flags) / sizeof (struct pflag); j++) { 961 if (strlen(argv[i]) == flags[j].flaglen + 1 && 962 strcmp(flags[j].flagname, 963 /* strip off leading + or - */ 964 &argv[i][1]) == 0) { 965 if (flags[j].set && argv[i][0] == '-' || 966 !flags[j].set && argv[i][0] == '+') { 967 oprinc->attributes |= flags[j].theflag; 968 *mask |= KADM5_ATTRIBUTES; 969 attrib_set++; 970 break; 971 } else if (flags[j].set && argv[i][0] == '+' || 972 !flags[j].set && argv[i][0] == '-') { 973 oprinc->attributes &= ~flags[j].theflag; 974 *mask |= KADM5_ATTRIBUTES; 975 attrib_set++; 976 break; 977 } else { 978 return (-1); 979 } 980 } 981 } 982 if (!attrib_set) 983 return (-1); /* nothing was parsed */ 984 } 985 if (i != argc - 1) { 986 return (-1); 987 } 988 retval = kadmin_parse_name(argv[i], &oprinc->principal); 989 if (retval) { 990 com_err(caller, retval, gettext("while parsing principal")); 991 return (-1); 992 } 993 return (0); 994 } 995 996 void 997 kadmin_addprinc_usage(func) 998 char *func; 999 { 1000 fprintf(stderr, "%s: %s %s\n", gettext("usage"), func, 1001 gettext("[options] principal")); 1002 fprintf(stderr, gettext("\toptions are:\n")); 1003 fprintf(stderr, "\t\t[-expire expdate] [-pwexpire pwexpdate] " 1004 "[-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] " 1005 "[-randkey] [-pw password]\n\t\t[-maxrenewlife maxrenewlife] " 1006 "[-e keysaltlist] [{+|-}attribute]\n"); 1007 fprintf(stderr, gettext("\tattributes are:\n")); 1008 fprintf(stderr, "%s%s%s", 1009 "\t\tallow_postdated allow_forwardable allow_tgs_req " 1010 "allow_renewable\n", 1011 "\t\tallow_proxiable allow_dup_skey allow_tix " 1012 "requires_preauth\n", 1013 "\t\trequires_hwauth needchange allow_svr " 1014 "password_changing_service\n"); 1015 } 1016 1017 void 1018 kadmin_modprinc_usage(func) 1019 char *func; 1020 { 1021 fprintf(stderr, "%s: %s %s\n", gettext("usage"), func, 1022 gettext("[options] principal")); 1023 fprintf(stderr, gettext("\toptions are:\n")); 1024 fprintf(stderr, "\t\t[-expire expdate] [-pwexpire pwexpdate] " 1025 "[-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] " 1026 "[-clearpolicy]\n\t\t[-maxrenewlife maxrenewlife] " 1027 "[{+|-}attribute]\n"); 1028 fprintf(stderr, gettext("\tattributes are:\n")); 1029 fprintf(stderr, "%s%s%s", 1030 "\t\tallow_postdated allow_forwardable allow_tgs_req " 1031 "allow_renewable\n", 1032 "\t\tallow_proxiable allow_dup_skey allow_tix " 1033 "requires_preauth\n", 1034 "\t\trequires_hwauth needchange allow_svr " 1035 "password_changing_service\n"); 1036 } 1037 1038 void 1039 kadmin_addprinc(argc, argv) 1040 int argc; 1041 char *argv[]; 1042 { 1043 kadm5_principal_ent_rec princ, dprinc; 1044 kadm5_policy_ent_rec defpol; 1045 long mask; 1046 int randkey = 0, i; 1047 int n_ks_tuple; 1048 krb5_key_salt_tuple *ks_tuple; 1049 char *pass, *canon; 1050 krb5_error_code retval; 1051 static char newpw[1024], dummybuf[256]; 1052 static char prompt1[1024], prompt2[1024]; 1053 int local_kadmin = 0; 1054 1055 local_kadmin = (strcmp(whoami, KADMIN_LOCAL_NAME) == 0); 1056 1057 if (dummybuf[0] == 0) { 1058 for (i = 0; i < 256; i++) 1059 dummybuf[i] = (i+1) % 256; 1060 } 1061 1062 /* Zero all fields in request structure */ 1063 memset(&princ, 0, sizeof(princ)); 1064 memset(&dprinc, 0, sizeof(dprinc)); 1065 1066 princ.attributes = dprinc.attributes = 0; 1067 if (kadmin_parse_princ_args(argc, argv, 1068 &princ, &mask, &pass, &randkey, 1069 &ks_tuple, &n_ks_tuple, 1070 "add_principal")) { 1071 kadmin_addprinc_usage("add_principal"); 1072 return; 1073 } 1074 1075 retval = krb5_unparse_name(context, princ.principal, &canon); 1076 if (retval) { 1077 com_err("add_principal", retval, 1078 gettext("while canonicalizing principal")); 1079 krb5_free_principal(context, princ.principal); 1080 if (ks_tuple != NULL) 1081 free(ks_tuple); 1082 return; 1083 } 1084 1085 /* 1086 * If -policy was not specified, and -clearpolicy was not 1087 * specified, and the policy "default" exists, assign it. If 1088 * -clearpolicy was specified, then KADM5_POLICY_CLR should be 1089 * unset, since it is never valid for kadm5_create_principal. 1090 */ 1091 if ((! (mask & KADM5_POLICY)) && 1092 (! (mask & KADM5_POLICY_CLR))) { 1093 if (! kadm5_get_policy(handle, "default", &defpol)) { 1094 fprintf(stderr, 1095 gettext( 1096 "NOTICE: no policy specified for %s; assigning \"default\"\n"), 1097 canon); 1098 princ.policy = "default"; 1099 mask |= KADM5_POLICY; 1100 (void) kadm5_free_policy_ent(handle, &defpol); 1101 } else 1102 fprintf(stderr, gettext("WARNING: no policy specified " 1103 "for %s; defaulting to no policy\n"), canon); 1104 } 1105 mask &= ~KADM5_POLICY_CLR; 1106 1107 /* 1108 * Set 'notix' for randkey principals and also for principals which have 1109 * specified flag options on the cmdline. This is because we want to apply 1110 * generic flag settings from 'default_principal_flags' first (during 1111 * principal creation), followed by a kadm5_modify_principal() which 1112 * correctly applies the cli flag options. So, we do *not* want any tix 1113 * issued in the interim. 1114 */ 1115 if (randkey || (mask & KADM5_ATTRIBUTES)) 1116 princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; 1117 1118 if (randkey) { 1119 pass = dummybuf; 1120 mask |= KADM5_ATTRIBUTES; 1121 } else if (pass == NULL) { 1122 unsigned int i = sizeof (newpw) - 1; 1123 snprintf(prompt1, sizeof (prompt1), 1124 gettext("Enter password for principal \"%.900s\""), 1125 canon); 1126 snprintf(prompt2, sizeof (prompt1), 1127 gettext("Re-enter password for principal \"%.900s\""), 1128 canon); 1129 retval = krb5_read_password(context, prompt1, prompt2, 1130 newpw, &i); 1131 if (retval) { 1132 com_err("add_principal", retval, 1133 gettext("while reading password for \"%s\"."), canon); 1134 free(canon); 1135 krb5_free_principal(context, princ.principal); 1136 return; 1137 } 1138 pass = newpw; 1139 } 1140 mask |= KADM5_PRINCIPAL; 1141 1142 /* 1143 * If the client being used is local, always use the new 1144 * API so we get the full set of enctype support. 1145 */ 1146 if (ks_tuple != NULL || local_kadmin) { 1147 retval = kadm5_create_principal_3(handle, &princ, mask, 1148 n_ks_tuple, ks_tuple, pass); 1149 } else { 1150 retval = kadm5_create_principal(handle, &princ, mask, pass); 1151 } 1152 if (retval) { 1153 com_err("add_principal", retval, 1154 gettext("while creating \"%s\"."), canon); 1155 krb5_free_principal(context, princ.principal); 1156 free(canon); 1157 if (ks_tuple != NULL) 1158 free(ks_tuple); 1159 return; 1160 } 1161 1162 if (randkey) { /* more special stuff for -randkey */ 1163 if (ks_tuple != NULL || local_kadmin) { 1164 retval = kadm5_randkey_principal_3(handle, princ.principal, 1165 FALSE, 1166 n_ks_tuple, ks_tuple, 1167 NULL, NULL); 1168 } else { 1169 retval = kadm5_randkey_principal(handle, princ.principal, 1170 NULL, NULL); 1171 } 1172 if (retval) { 1173 com_err("add_principal", retval, 1174 gettext("while randomizing key for \"%s\"."), canon); 1175 krb5_free_principal(context, princ.principal); 1176 free(canon); 1177 if (ks_tuple != NULL) 1178 free(ks_tuple); 1179 return; 1180 } 1181 } 1182 1183 /* 1184 * We now retrieve the intersection set of the generic flag settings and 1185 * the ones specified on the cli & re-parse the princ args, just to make 1186 * sure we account for conflicts between 'default_principal_flags' and 1187 * the cmdline flag args. While we are here, also clear 'notix'. 1188 */ 1189 if (randkey || (mask & KADM5_ATTRIBUTES)) { 1190 retval = kadm5_get_principal(handle, princ.principal, &dprinc, 1191 KADM5_PRINCIPAL_NORMAL_MASK); 1192 if (retval == 0) { 1193 if (dprinc.attributes != 0) 1194 princ.attributes = dprinc.attributes; 1195 } else { 1196 com_err("add_principal", retval, 1197 gettext("while doing a get_principal on \"%s\"."), canon); 1198 printf(gettext("\nWarning: Principal \"%s\" could have incomplete " 1199 "flag settings, as a result of a failed get_principal.\n" 1200 "Check the 'default_principal_flags' setting in kdc.conf(4).\n" 1201 "If there is a mismatch, use modprinc in kadmin(1M) to rectify " 1202 "the same.\n\n"), canon); 1203 } 1204 1205 (void) kadmin_parse_princ_args(argc, argv, &princ, &mask, &pass, 1206 &randkey, &ks_tuple, &n_ks_tuple, "add_principal"); 1207 1208 princ.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; 1209 mask = KADM5_ATTRIBUTES; 1210 retval = kadm5_modify_principal(handle, &princ, mask); 1211 if (retval) { 1212 com_err("add_principal", retval, 1213 gettext("while doing a modify_principal to restore flag " 1214 "settings for \"%s\"."), canon); 1215 krb5_free_principal(context, princ.principal); 1216 free(canon); 1217 if (ks_tuple != NULL) 1218 free(ks_tuple); 1219 return; 1220 } 1221 } 1222 1223 krb5_free_principal(context, princ.principal); 1224 printf(gettext("Principal \"%s\" created.\n"), canon); 1225 if (ks_tuple != NULL) 1226 free(ks_tuple); 1227 free(canon); 1228 } 1229 1230 void 1231 kadmin_modprinc(argc, argv) 1232 int argc; 1233 char *argv[]; 1234 { 1235 kadm5_principal_ent_rec princ, oldprinc; 1236 krb5_principal kprinc; 1237 long mask; 1238 krb5_error_code retval; 1239 char *pass, *canon; 1240 int randkey = 0; 1241 int n_ks_tuple = 0; 1242 krb5_key_salt_tuple *ks_tuple; 1243 1244 if (argc < 2) { 1245 kadmin_modprinc_usage("modify_principal"); 1246 return; 1247 } 1248 1249 memset(&oldprinc, 0, sizeof(oldprinc)); 1250 memset(&princ, 0, sizeof(princ)); 1251 1252 retval = kadmin_parse_name(argv[argc - 1], &kprinc); 1253 if (retval) { 1254 com_err("modify_principal", retval, 1255 gettext("while parsing principal")); 1256 return; 1257 } 1258 retval = krb5_unparse_name(context, kprinc, &canon); 1259 if (retval) { 1260 com_err("modify_principal", retval, 1261 gettext("while canonicalizing principal")); 1262 krb5_free_principal(context, kprinc); 1263 return; 1264 } 1265 retval = kadm5_get_principal(handle, kprinc, &oldprinc, 1266 KADM5_PRINCIPAL_NORMAL_MASK); 1267 krb5_free_principal(context, kprinc); 1268 if (retval) { 1269 com_err("modify_principal", retval, 1270 gettext("while getting \"%s\"."), canon); 1271 free(canon); 1272 return; 1273 } 1274 princ.attributes = oldprinc.attributes; 1275 kadm5_free_principal_ent(handle, &oldprinc); 1276 retval = kadmin_parse_princ_args(argc, argv, 1277 &princ, &mask, 1278 &pass, &randkey, 1279 &ks_tuple, &n_ks_tuple, 1280 "modify_principal"); 1281 if (ks_tuple != NULL) { 1282 free(ks_tuple); 1283 kadmin_modprinc_usage("modify_principal"); 1284 free(canon); 1285 return; 1286 } 1287 if (retval) { 1288 kadmin_modprinc_usage("modify_principal"); 1289 free(canon); 1290 return; 1291 } 1292 if (randkey) { 1293 fprintf(stderr, "modify_principal: -randkey %s ", 1294 gettext("not allowed\n")); 1295 krb5_free_principal(context, princ.principal); 1296 free(canon); 1297 return; 1298 } 1299 if (pass) { 1300 fprintf(stderr, 1301 "modify_principal: -pw %s change_password\n", 1302 gettext("not allowed; use")); 1303 krb5_free_principal(context, princ.principal); 1304 free(canon); 1305 return; 1306 } 1307 retval = kadm5_modify_principal(handle, &princ, mask); 1308 krb5_free_principal(context, princ.principal); 1309 if (retval) { 1310 com_err("modify_principal", retval, 1311 gettext("while modifying \"%s\"."), canon); 1312 free(canon); 1313 return; 1314 } 1315 printf(gettext("Principal \"%s\" modified.\n"), canon); 1316 free(canon); 1317 } 1318 1319 void 1320 kadmin_getprinc(argc, argv) 1321 int argc; 1322 char *argv[]; 1323 { 1324 kadm5_principal_ent_rec dprinc; 1325 krb5_principal princ; 1326 krb5_error_code retval; 1327 char *canon, *modcanon; 1328 int i; 1329 1330 if (! (argc == 2 || 1331 (argc == 3 && strcmp("-terse", argv[1]) == 0))) { 1332 fprintf(stderr, "%s: get_principal [-terse] %s\n", 1333 gettext("usage"), gettext("principal")); 1334 return; 1335 } 1336 memset(&dprinc, 0, sizeof(dprinc)); 1337 memset(&princ, 0, sizeof(princ)); 1338 1339 retval = kadmin_parse_name(argv[argc - 1], &princ); 1340 if (retval) { 1341 com_err("get_principal", retval, 1342 gettext("while parsing principal")); 1343 return; 1344 } 1345 retval = krb5_unparse_name(context, princ, &canon); 1346 if (retval) { 1347 com_err("get_principal", retval, 1348 gettext("while canonicalizing principal")); 1349 krb5_free_principal(context, princ); 1350 return; 1351 } 1352 retval = kadm5_get_principal(handle, princ, &dprinc, 1353 KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA); 1354 krb5_free_principal(context, princ); 1355 if (retval) { 1356 com_err("get_principal", retval, 1357 gettext("while retrieving \"%s\"."), canon); 1358 free(canon); 1359 return; 1360 } 1361 retval = krb5_unparse_name(context, dprinc.mod_name, &modcanon); 1362 if (retval) { 1363 com_err("get_principal", retval, 1364 gettext("while unparsing modname")); 1365 kadm5_free_principal_ent(handle, &dprinc); 1366 free(canon); 1367 return; 1368 } 1369 if (argc == 2) { 1370 printf(gettext("Principal: %s\n"), canon); 1371 printf(gettext("Expiration date: %s\n"), 1372 dprinc.princ_expire_time ? 1373 strdate(dprinc.princ_expire_time) : 1374 gettext("[never]")); 1375 printf(gettext("Last password change: %s\n"), 1376 dprinc.last_pwd_change ? 1377 strdate(dprinc.last_pwd_change) : 1378 gettext("[never]")); 1379 printf(gettext("Password expiration date: %s\n"), 1380 dprinc.pw_expiration ? 1381 strdate(dprinc.pw_expiration) : gettext("[none]")); 1382 printf(gettext("Maximum ticket life: %s\n"), 1383 strdur(dprinc.max_life)); 1384 printf(gettext("Maximum renewable life: %s\n"), 1385 strdur(dprinc.max_renewable_life)); 1386 printf(gettext("Last modified: %s (%s)\n"), 1387 strdate(dprinc.mod_date), modcanon); 1388 printf(gettext("Last successful authentication: %s\n"), 1389 dprinc.last_success ? strdate(dprinc.last_success) : 1390 gettext("[never]")); 1391 printf(gettext("Last failed authentication: %s\n"), 1392 dprinc.last_failed ? strdate(dprinc.last_failed) : 1393 gettext("[never]")); 1394 printf(gettext("Failed password attempts: %d\n"), 1395 dprinc.fail_auth_count); 1396 printf(gettext("Number of keys: %d\n"), dprinc.n_key_data); 1397 for (i = 0; i < dprinc.n_key_data; i++) { 1398 krb5_key_data *key_data = &dprinc.key_data[i]; 1399 char enctype[BUFSIZ], salttype[BUFSIZ]; 1400 1401 if (krb5_enctype_to_string(key_data->key_data_type[0], 1402 enctype, sizeof(enctype))) 1403 snprintf(enctype, sizeof (enctype), 1404 gettext("<Encryption type 0x%x>"), 1405 key_data->key_data_type[0]); 1406 printf(gettext("Key: vno %d, %s, "), 1407 key_data->key_data_kvno, enctype); 1408 if (key_data->key_data_ver > 1) { 1409 if (krb5_salttype_to_string( 1410 key_data->key_data_type[1], 1411 salttype, sizeof(salttype))) 1412 snprintf(salttype, sizeof (salttype), 1413 gettext("<Salt type 0x%x>"), 1414 key_data->key_data_type[1]); 1415 printf("%s\n", salttype); 1416 } else 1417 printf(gettext("no salt\n")); 1418 } 1419 1420 printf(gettext("Attributes:")); 1421 for (i = 0; i < sizeof (prflags) / sizeof (char *); i++) { 1422 if (dprinc.attributes & (krb5_flags) 1 << i) 1423 printf(" %s", prflags[i]); 1424 } 1425 printf("\n"); 1426 printf(gettext("Policy: %s\n"), 1427 dprinc.policy ? dprinc.policy : gettext("[none]")); 1428 } else { 1429 printf("\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"" 1430 "\t%d\t%d\t%d\t%d\t%d", 1431 canon, dprinc.princ_expire_time, dprinc.last_pwd_change, 1432 dprinc.pw_expiration, dprinc.max_life, modcanon, 1433 dprinc.mod_date, dprinc.attributes, dprinc.kvno, 1434 dprinc.mkvno, dprinc.policy ? 1435 dprinc.policy : gettext("[none]"), 1436 dprinc.max_renewable_life, dprinc.last_success, 1437 dprinc.last_failed, dprinc.fail_auth_count, 1438 dprinc.n_key_data); 1439 for (i = 0; i < dprinc.n_key_data; i++) 1440 printf("\t%d\t%d\t%d\t%d", 1441 dprinc.key_data[i].key_data_ver, 1442 dprinc.key_data[i].key_data_kvno, 1443 dprinc.key_data[i].key_data_type[0], 1444 dprinc.key_data[i].key_data_type[1]); 1445 printf("\n"); 1446 } 1447 free(modcanon); 1448 kadm5_free_principal_ent(handle, &dprinc); 1449 free(canon); 1450 } 1451 1452 void 1453 kadmin_getprincs(argc, argv) 1454 int argc; 1455 char *argv[]; 1456 { 1457 krb5_error_code retval; 1458 char *exp, **names; 1459 int i, count; 1460 1461 FILE *output; 1462 int fd; 1463 struct sigaction nsig, osig; 1464 sigset_t nmask, omask; 1465 int waitb; 1466 1467 exp = NULL; 1468 if (! (argc == 1 || (argc == 2 && (exp = argv[1])))) { 1469 fprintf(stderr, "%s: get_principals %s\n", 1470 gettext("usage"), gettext("[expression]")); 1471 return; 1472 } 1473 retval = kadm5_get_principals(handle, exp, &names, &count); 1474 if (retval) { 1475 com_err("get_principals", retval, 1476 gettext("while retrieving list.")); 1477 return; 1478 } 1479 1480 /* 1481 * Solaris: the following code is used for paging 1482 */ 1483 1484 sigemptyset(&nmask); 1485 sigaddset(&nmask, SIGINT); 1486 sigprocmask(SIG_BLOCK, &nmask, &omask); 1487 1488 nsig.sa_handler = SIG_IGN; 1489 sigemptyset(&nsig.sa_mask); 1490 nsig.sa_flags = 0; 1491 sigaction(SIGINT, &nsig, &osig); 1492 1493 fd = ss_pager_create(); 1494 output = fdopen(fd, "w"); 1495 1496 sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0); 1497 1498 for (i = 0; i < count; i++) 1499 fprintf(output, "%s\n", names[i]); 1500 1501 fclose(output); 1502 1503 wait(&waitb); 1504 1505 kadm5_free_name_list(handle, names, count); 1506 } 1507 1508 int 1509 kadmin_parse_policy_args(argc, argv, policy, mask, caller) 1510 int argc; 1511 char *argv[]; 1512 kadm5_policy_ent_t policy; 1513 long *mask; 1514 char *caller; 1515 { 1516 int i; 1517 time_t now; 1518 time_t date; 1519 krb5_error_code retval; 1520 1521 time(&now); 1522 *mask = 0; 1523 for (i = 1; i < argc - 1; i++) { 1524 if (strlen(argv[i]) == 8 && 1525 strcmp(argv[i], "-maxlife") == 0) { 1526 if (++i > argc -2) 1527 return (-1); 1528 else { 1529 date = get_date(argv[i], NULL); 1530 if (date == (time_t)-1) { 1531 fprintf(stderr, 1532 gettext("Invalid date " 1533 "specification " 1534 "\"%s\".\n"), 1535 argv[i]); 1536 return (-1); 1537 } 1538 if (date <= now) { 1539 fprintf(stderr, 1540 gettext("Date specified is " 1541 "in the past " 1542 "\"%s\".\n"), 1543 argv[i]); 1544 return (-1); 1545 } 1546 policy->pw_max_life = date - now; 1547 *mask |= KADM5_PW_MAX_LIFE; 1548 continue; 1549 } 1550 } else if (strlen(argv[i]) == 8 && 1551 strcmp(argv[i], "-minlife") == 0) { 1552 if (++i > argc - 2) 1553 return (-1); 1554 else { 1555 date = get_date(argv[i], NULL); 1556 if (date == (time_t)-1) { 1557 fprintf(stderr, 1558 gettext("Invalid date " 1559 "specification " 1560 "\"%s\".\n"), 1561 argv[i]); 1562 return (-1); 1563 } 1564 if (date <= now) { 1565 fprintf(stderr, 1566 gettext("Date specified is " 1567 "in the past " 1568 "\"%s\".\n"), 1569 argv[i]); 1570 return (-1); 1571 } 1572 policy->pw_min_life = date - now; 1573 *mask |= KADM5_PW_MIN_LIFE; 1574 continue; 1575 } 1576 } else if (strlen(argv[i]) == 10 && 1577 strcmp(argv[i], "-minlength") == 0) { 1578 if (++i > argc - 2) 1579 return (-1); 1580 else { 1581 policy->pw_min_length = atoi(argv[i]); 1582 *mask |= KADM5_PW_MIN_LENGTH; 1583 continue; 1584 } 1585 } else if (strlen(argv[i]) == 11 && 1586 strcmp(argv[i], "-minclasses") == 0) { 1587 if (++i > argc - 2) 1588 return (-1); 1589 else { 1590 policy->pw_min_classes = atoi(argv[i]); 1591 *mask |= KADM5_PW_MIN_CLASSES; 1592 continue; 1593 } 1594 } else if (strlen(argv[i]) == 8 && 1595 strcmp(argv[i], "-history") == 0) { 1596 if (++i > argc - 2) 1597 return (-1); 1598 else { 1599 policy->pw_history_num = atoi(argv[i]); 1600 *mask |= KADM5_PW_HISTORY_NUM; 1601 continue; 1602 } 1603 } else 1604 return (-1); 1605 } 1606 if (i != argc -1) { 1607 fprintf(stderr, gettext("%s: parser lost count!\n"), caller); 1608 return (-1); 1609 } else 1610 return (0); 1611 } 1612 1613 void 1614 kadmin_addmodpol_usage(func) 1615 char *func; 1616 { 1617 fprintf(stderr, "%s: %s %s\n", gettext("usage"), func, 1618 gettext("[options] policy")); 1619 fprintf(stderr, gettext("\toptions are:\n")); 1620 fprintf(stderr, "\t\t[-maxlife time] [-minlife time] " 1621 "[-minlength length]\n\t\t[-minclasses number] " 1622 "[-history number]\n"); 1623 } 1624 1625 void 1626 kadmin_addpol(argc, argv) 1627 int argc; 1628 char *argv[]; 1629 { 1630 krb5_error_code retval; 1631 long mask; 1632 kadm5_policy_ent_rec policy; 1633 1634 memset(&policy, 0, sizeof(policy)); 1635 if (kadmin_parse_policy_args(argc, argv, 1636 &policy, &mask, "add_policy")) { 1637 kadmin_addmodpol_usage("add_policy"); 1638 return; 1639 } else { 1640 policy.policy = argv[argc - 1]; 1641 mask |= KADM5_POLICY; 1642 retval = kadm5_create_policy(handle, &policy, mask); 1643 if (retval) { 1644 com_err("add_policy", retval, 1645 gettext("while creating policy \"%s\"."), 1646 policy.policy); 1647 return; 1648 } 1649 } 1650 } 1651 1652 void 1653 kadmin_modpol(argc, argv) 1654 int argc; 1655 char *argv[]; 1656 { 1657 krb5_error_code retval; 1658 long mask; 1659 kadm5_policy_ent_rec policy; 1660 1661 memset(&policy, 0, sizeof(policy)); 1662 if (kadmin_parse_policy_args(argc, argv, &policy, &mask, 1663 "modify_policy")) { 1664 kadmin_addmodpol_usage("modify_policy"); 1665 return; 1666 } else { 1667 policy.policy = argv[argc - 1]; 1668 retval = kadm5_modify_policy(handle, &policy, mask); 1669 if (retval) { 1670 com_err("modify_policy", retval, 1671 gettext("while modifying policy \"%s\"."), 1672 policy.policy); 1673 return; 1674 } 1675 } 1676 } 1677 1678 void 1679 kadmin_delpol(argc, argv) 1680 int argc; 1681 char *argv[]; 1682 { 1683 krb5_error_code retval; 1684 char reply[32]; 1685 1686 if (! (argc == 2 || 1687 (argc == 3 && strcmp("-force", argv[1]) == 0))) { 1688 fprintf(stderr, "%s: delete_policy [-force] %s\n", 1689 gettext("usage"), gettext("policy")); 1690 return; 1691 } 1692 if (argc == 2) { 1693 printf(gettext("Are you sure you want to delete the policy " 1694 "\"%s\"? (yes/no): "), argv[1]); 1695 fgets(reply, sizeof (reply), stdin); 1696 if (strncmp(gettext("yes\n"), reply, sizeof (reply)) && 1697 strncmp(gettext("y\n"), reply, sizeof (reply)) && 1698 strncmp(gettext("Y\n"), reply, sizeof (reply)) 1699 ) { 1700 fprintf(stderr, 1701 gettext("Policy \"%s\" not deleted.\n"), 1702 argv[1]); 1703 return; 1704 } 1705 } 1706 retval = kadm5_delete_policy(handle, argv[argc - 1]); 1707 if (retval) { 1708 com_err("delete_policy:", retval, 1709 gettext("while deleting policy \"%s\""), 1710 argv[argc - 1]); 1711 return; 1712 } 1713 } 1714 1715 void 1716 kadmin_getpol(argc, argv) 1717 int argc; 1718 char *argv[]; 1719 { 1720 krb5_error_code retval; 1721 kadm5_policy_ent_rec policy; 1722 1723 if (! (argc == 2 || 1724 (argc == 3 && strcmp("-terse", argv[1]) == 0))) { 1725 fprintf(stderr, "%s: get_policy [-terse] %s\n", 1726 gettext("usage"), gettext("policy")); 1727 return; 1728 } 1729 retval = kadm5_get_policy(handle, argv[argc - 1], &policy); 1730 if (retval) { 1731 com_err("get_policy", retval, 1732 gettext("while retrieving policy \"%s\"."), 1733 argv[argc - 1]); 1734 return; 1735 } 1736 if (argc == 2) { 1737 printf(gettext("Policy: %s\n"), policy.policy); 1738 printf(gettext("Maximum password life: %d\n"), 1739 policy.pw_max_life); 1740 printf(gettext("Minimum password life: %d\n"), 1741 policy.pw_min_life); 1742 printf(gettext("Minimum password length: %d\n"), 1743 policy.pw_min_length); 1744 printf(gettext("Minimum number of password " 1745 "character classes: %d\n"), 1746 policy.pw_min_classes); 1747 printf(gettext("Number of old keys kept: %d\n"), 1748 policy.pw_history_num); 1749 printf(gettext("Reference count: %d\n"), policy.policy_refcnt); 1750 } else { 1751 printf("\"%s\"\t%d\t%d\t%d\t%d\t%d\t%d\n", 1752 policy.policy, policy.pw_max_life, policy.pw_min_life, 1753 policy.pw_min_length, policy.pw_min_classes, 1754 policy.pw_history_num, policy.policy_refcnt); 1755 } 1756 kadm5_free_policy_ent(handle, &policy); 1757 } 1758 1759 void 1760 kadmin_getpols(argc, argv) 1761 int argc; 1762 char *argv[]; 1763 { 1764 krb5_error_code retval; 1765 char *exp, **names; 1766 int i, count; 1767 1768 exp = NULL; 1769 if (! (argc == 1 || (argc == 2 && (exp = argv[1])))) { 1770 fprintf(stderr, "%s: get_policies %s\n", 1771 gettext("usage"), gettext("[expression]\n")); 1772 return; 1773 } 1774 retval = kadm5_get_policies(handle, exp, &names, &count); 1775 if (retval) { 1776 com_err("get_policies", retval, 1777 gettext("while retrieving list.")); 1778 return; 1779 } 1780 for (i = 0; i < count; i++) 1781 printf("%s\n", names[i]); 1782 kadm5_free_name_list(handle, names, count); 1783 } 1784