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