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