1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * University Copyright- Copyright (c) 1982, 1986, 1988 31 * The Regents of the University of California 32 * All Rights Reserved 33 * 34 * University Acknowledgment- Portions of this document are derived from 35 * software developed by the University of California, Berkeley, and its 36 * contributors. 37 */ 38 39 #pragma ident "%Z%%M% %I% %E% SMI" 40 41 #include <assert.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <pwd.h> 46 #include <shadow.h> 47 #include <crypt.h> 48 #include <sys/types.h> 49 #include <unistd.h> 50 #include <rpc/rpc.h> 51 #include <rpc/key_prot.h> 52 #include <rpcsvc/nis.h> 53 #include <rpcsvc/nis_dhext.h> 54 #include <rpcsvc/ypclnt.h> 55 #include <nsswitch.h> 56 57 #define PK_FILES 1 58 #define PK_YP 2 59 #define PK_NISPLUS 3 60 #define PK_LDAP 4 61 62 #define CURMECH mechs[mcount] 63 64 static char CRED_TABLE[] = "cred.org_dir"; 65 static char PKMAP[] = "publickey.byname"; 66 static char PKFILE[] = "/etc/publickey"; 67 #define MAXHOSTNAMELEN 256 68 69 #define ROOTKEY_FILE "/etc/.rootkey" 70 #define ROOTKEY_FILE_BACKUP "/etc/.rootkey.bak" 71 #define MAXROOTKEY_LINE_LEN 4224 /* Good upto 16384-bit keys */ 72 #define MAXROOTKEY_LEN 4096 73 74 /* Should last up to 16384-bit keys */ 75 #define MAXPKENTLEN 8500 76 77 bool_t makenew = TRUE; /* Make new keys or reencrypt existing */ 78 bool_t specmech = FALSE; /* Specific mechs requested */ 79 bool_t force = FALSE; 80 int dest_service = 0; /* To which nameservice do we store key(s) */ 81 82 char *program_name; 83 84 mechanism_t **mechs = NULL; /* List of DH mechanisms */ 85 char **plist = NULL; /* List of public key(s) */ 86 char **slist = NULL; /* List of secret key(s) */ 87 char **clist = NULL; /* List of encrypted secret key(s) */ 88 int numspecmech = 0; /* Number of mechanisms specified */ 89 90 struct passwd *pw = NULL; /* passwd entry of user */ 91 struct spwd *spw = NULL; /* shadow entry of user */ 92 93 char *netname = NULL; /* RPC netname of user */ 94 char local_domain[MAXNETNAMELEN + 1]; 95 char *sec_domain = NULL; 96 97 char **rpc_pws = NULL; /* List of S-RPC passwords */ 98 int rpc_pw_count = 0; /* Number of passwords entered by user */ 99 char *login_pw = NULL; /* Unencrypted login password */ 100 101 static int add_cred_obj(nis_object *, char *); 102 static nis_error auth_exists(char *, char *, char *, char *); 103 static void cmp_passwd(); 104 static nis_error cred_exists(const char *, const char *, const char *); 105 static void encryptkeys(); 106 static void error_msg(); 107 static char *fgets_ignorenul(); 108 static void getpublics(); 109 static void getrpcpws(); 110 static void getsecrets(); 111 static void initkeylist(bool_t); 112 static void keylogin(keylen_t, algtype_t); 113 static void keylogin_des(); 114 static void makenewkeys(); 115 static int modify_cred_obj(nis_object *, char *); 116 static int nisplus_update(nis_name, char *, char *, char *); 117 static int sanity_checks(char *, char *, char *); 118 static void storekeys(); 119 static void usage(); 120 static void write_rootkey(); 121 122 extern char *get_nisplus_principal(char *, uid_t); 123 extern nis_object *init_entry(); 124 extern int get_pk_source(char *); 125 extern int localupdate(char *, char *, uint_t, char *); 126 extern int xencrypt(); 127 extern int xencrypt_g(); 128 extern int __gen_dhkeys(); 129 extern int key_setnet(); 130 extern int key_setnet_g(); 131 extern int key_secretkey_is_set_g(); 132 extern int __getnetnamebyuid(); 133 extern int getdomainname(); 134 extern int ldap_update(char *, char *, char *, char *, char *); 135 136 137 static void 138 error_msg() 139 { 140 if (sec_domain && *sec_domain && 141 strcasecmp(sec_domain, local_domain)) { 142 fprintf(stderr, 143 "The system default domain '%s' is different from the Secure RPC\n\ 144 domain %s where the key is stored. The Secure RPC domainname is\n\ 145 defined by the directory object stored in the /var/nis/NIS_COLD_START file.\n\ 146 If you need to change this Secure RPC domainname, please use the nisinit(1M)\n\ 147 command with the `-k` option.\n", local_domain, sec_domain); 148 exit(1); 149 } 150 } 151 152 153 static void 154 usage() 155 { 156 fprintf(stderr, "usage: %s [-p] [-s ldap | nisplus | nis | files] \n", 157 program_name); 158 exit(1); 159 } 160 161 162 /* Encrypt secret key(s) with login_pw */ 163 static void 164 encryptkeys() 165 { 166 int mcount, ccount = 0; 167 168 if (mechs) { 169 for (mcount = 0; CURMECH; mcount++) { 170 char *crypt = NULL; 171 172 if (!xencrypt_g(slist[mcount], CURMECH->keylen, 173 CURMECH->algtype, login_pw, netname, 174 &crypt, TRUE)) { 175 /* Could not crypt key */ 176 crypt = NULL; 177 } else 178 ccount++; 179 clist[mcount] = crypt; 180 } 181 } else { 182 char *crypt = NULL; 183 184 if (!(crypt = 185 (char *)malloc(HEXKEYBYTES + KEYCHECKSUMSIZE + 1))) { 186 fprintf(stderr, "%s: Malloc failure.\n", program_name); 187 exit(1); 188 } 189 190 memcpy(crypt, slist[0], HEXKEYBYTES); 191 memcpy(crypt + HEXKEYBYTES, slist[0], KEYCHECKSUMSIZE); 192 crypt[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0; 193 xencrypt(crypt, login_pw); 194 195 clist[0] = crypt; 196 ccount++; 197 } 198 199 if (!ccount) { 200 fprintf(stderr, "%s: Could not encrypt any secret keys.\n", 201 program_name); 202 exit(1); 203 } 204 } 205 206 207 /* Initialize the array of public, secret, and encrypted secret keys */ 208 static void 209 initkeylist(bool_t nomech) 210 { 211 int mcount; 212 213 if (!nomech) { 214 assert(mechs && mechs[0]); 215 for (mcount = 0; CURMECH; mcount++); 216 } else 217 mcount = 1; 218 219 if (!(plist = (char **)malloc(sizeof (char *) * mcount))) { 220 fprintf(stderr, "%s: Malloc failure.\n", program_name); 221 exit(1); 222 } 223 if (!(slist = (char **)malloc(sizeof (char *) * mcount))) { 224 fprintf(stderr, "%s: Malloc failure.\n", program_name); 225 exit(1); 226 } 227 if (!(clist = (char **)malloc(sizeof (char *) * mcount))) { 228 fprintf(stderr, "%s: Malloc failure.\n", program_name); 229 exit(1); 230 } 231 } 232 233 234 /* Retrieve public key(s) */ 235 static void 236 getpublics() 237 { 238 int mcount; 239 int pcount = 0; 240 241 if (mechs) { 242 for (mcount = 0; CURMECH; mcount++) { 243 char *public; 244 size_t hexkeylen; 245 246 hexkeylen = ((CURMECH->keylen / 8) * 2) + 1; 247 if (!(public = (char *)malloc(hexkeylen))) { 248 fprintf(stderr, "%s: Malloc failure.\n", 249 program_name); 250 exit(1); 251 } 252 if (!getpublickey_g(netname, CURMECH->keylen, 253 CURMECH->algtype, public, 254 hexkeylen)) { 255 /* Could not get public key */ 256 fprintf(stderr, 257 "Could not get %s public key.\n", 258 VALID_ALIAS(CURMECH->alias) ? 259 CURMECH->alias : ""); 260 free(public); 261 public = NULL; 262 } else 263 pcount++; 264 265 plist[mcount] = public; 266 } 267 } else { 268 char *public; 269 270 if (!(public = (char *)malloc(HEXKEYBYTES + 1))) { 271 fprintf(stderr, "%s: Malloc failure.\n", program_name); 272 exit(1); 273 } 274 if (!getpublickey(netname, public)) { 275 free(public); 276 public = NULL; 277 } else 278 pcount++; 279 280 plist[0] = public; 281 } 282 283 if (!pcount) { 284 fprintf(stderr, "%s: cannot get any public keys for %s.\n", 285 program_name, pw->pw_name); 286 error_msg(); 287 fprintf(stderr, 288 "Make sure that the public keys are stored in the domain %s.\n", 289 local_domain); 290 exit(1); 291 } 292 } 293 294 295 /* Generate a new set of public/secret key pair(s) */ 296 static void 297 makenewkeys() 298 { 299 int mcount; 300 301 if (mechs) { 302 for (mcount = 0; CURMECH; mcount++) { 303 char *public, *secret; 304 size_t hexkeylen; 305 306 if (slist[mcount]) 307 free(slist[mcount]); 308 309 hexkeylen = ((CURMECH->keylen / 8) * 2) + 1; 310 311 if (!(public = malloc(hexkeylen))) { 312 fprintf(stderr, "%s: Malloc failure.\n", 313 program_name); 314 exit(1); 315 } 316 if (!(secret = malloc(hexkeylen))) { 317 fprintf(stderr, "%s: Malloc failure.\n", 318 program_name); 319 exit(1); 320 } 321 322 if (!(__gen_dhkeys_g(public, secret, CURMECH->keylen, 323 CURMECH->algtype, login_pw))) { 324 /* Could not generate key pair */ 325 fprintf(stderr, 326 "WARNING Could not generate key pair %s\n", 327 VALID_ALIAS(CURMECH->alias) ? 328 CURMECH->alias : ""); 329 free(public); 330 free(secret); 331 public = NULL; 332 secret = NULL; 333 } 334 335 plist[mcount] = public; 336 slist[mcount] = secret; 337 } 338 } else { 339 char *public, *secret; 340 if (slist[0]) 341 free(slist[0]); 342 343 if (!(public = malloc(HEXKEYBYTES + 1))) { 344 fprintf(stderr, "%s: Malloc failure.\n", program_name); 345 exit(1); 346 } 347 if (!(secret = malloc(HEXKEYBYTES + 1))) { 348 fprintf(stderr, "%s: Malloc failure.\n", program_name); 349 exit(1); 350 } 351 352 __gen_dhkeys(public, secret, login_pw); 353 354 plist[0] = public; 355 slist[0] = secret; 356 } 357 } 358 359 360 /* 361 * Make sure that the entered Secure-RPC password(s) match the login 362 * password 363 */ 364 static void 365 cmp_passwd() 366 { 367 char baseprompt[] = "Please enter the login password for"; 368 char prompt[BUFSIZ]; 369 char *en_login_pw = spw->sp_pwdp; 370 char *try_en_login_pw; 371 bool_t pwmatch = FALSE; 372 int done = 0, tries = 0, pcount; 373 374 snprintf(prompt, BUFSIZ, "%s %s:", baseprompt, pw->pw_name); 375 376 if (en_login_pw && (strlen(en_login_pw) != 0)) { 377 for (pcount = 0; pcount < rpc_pw_count; pcount++) { 378 char *try_en_rpc_pw; 379 380 try_en_rpc_pw = crypt(rpc_pws[pcount], en_login_pw); 381 if (strcmp(try_en_rpc_pw, en_login_pw) == 0) { 382 login_pw = rpc_pws[pcount]; 383 pwmatch = TRUE; 384 break; 385 } 386 } 387 if (!pwmatch) { 388 /* pw don't match */ 389 while (!done) { 390 /* ask for the pw */ 391 login_pw = getpass(prompt); 392 if (login_pw && strlen(login_pw)) { 393 /* pw was not empty */ 394 try_en_login_pw = crypt(login_pw, 395 en_login_pw); 396 /* compare the pw's */ 397 if (!(strcmp(try_en_login_pw, 398 en_login_pw))) { 399 /* pw was correct */ 400 return; 401 } else { 402 /* pw was wrong */ 403 if (tries++) { 404 /* Sorry */ 405 fprintf(stderr, 406 "Sorry.\n"); 407 exit(1); 408 } else { 409 /* Try again */ 410 snprintf(prompt, 411 BUFSIZ, 412 "Try again. %s %s:", 413 baseprompt, 414 pw->pw_name); 415 } 416 } 417 } else { 418 /* pw was empty */ 419 if (tries++) { 420 /* Unchanged */ 421 fprintf(stderr, 422 "%s: key-pair(s) unchanged for %s.\n", 423 program_name, 424 pw->pw_name); 425 exit(1); 426 } else { 427 /* Need a password */ 428 snprintf(prompt, BUFSIZ, 429 "Need a password. %s %s:", 430 baseprompt, 431 pw->pw_name); 432 } 433 } 434 } 435 } 436 /* pw match */ 437 return; 438 } else { 439 /* no pw found */ 440 fprintf(stderr, 441 "%s: no passwd found for %s in the shadow passwd entry.\n", 442 program_name, pw->pw_name); 443 exit(1); 444 } 445 } 446 447 448 /* Prompt the user for a Secure-RPC password and store it in a cache. */ 449 static void 450 getrpcpws(char *flavor) 451 { 452 char *cur_pw = NULL; 453 char prompt[BUFSIZ + 1]; 454 455 if (flavor) 456 snprintf(prompt, BUFSIZ, 457 "Please enter the %s Secure-RPC password for %s:", 458 flavor, pw->pw_name); 459 else 460 snprintf(prompt, BUFSIZ, 461 "Please enter the Secure-RPC password for %s:", 462 pw->pw_name); 463 464 cur_pw = getpass(prompt); 465 if (!cur_pw) { 466 /* No changes */ 467 fprintf(stderr, "%s: key-pair(s) unchanged for %s.\n", 468 program_name, pw->pw_name); 469 exit(1); 470 } 471 472 rpc_pw_count++; 473 if (!(rpc_pws = 474 (char **)realloc(rpc_pws, sizeof (char *) * rpc_pw_count))) { 475 fprintf(stderr, "%s: Realloc failure.\n", program_name); 476 exit(1); 477 } 478 rpc_pws[rpc_pw_count - 1] = cur_pw; 479 } 480 481 482 /* Retrieve the secret key(s) for the user and attempt to decrypt them */ 483 static void 484 getsecrets() 485 { 486 int mcount, scount = 0; 487 int tries = 0; 488 489 getrpcpws(NULL); 490 491 if (mechs) { 492 for (mcount = 0; CURMECH; mcount++) { 493 char *secret; 494 int pcount; 495 size_t hexkeylen; 496 497 hexkeylen = ((CURMECH->keylen / 8) * 2) + 1; 498 if (!(secret = (char *)calloc(hexkeylen, 499 sizeof (char)))) { 500 fprintf(stderr, "%s: Malloc failure.\n", 501 program_name); 502 exit(1); 503 } 504 505 for (pcount = 0; pcount < rpc_pw_count; pcount++) { 506 if (!getsecretkey_g(netname, CURMECH->keylen, 507 CURMECH->algtype, secret, 508 hexkeylen, 509 rpc_pws[pcount])) 510 continue; 511 512 if (secret[0] == 0) 513 continue; 514 else 515 break; 516 } 517 518 tries = 0; 519 getsecrets_tryagain_g: 520 if (secret[0] == 0) { 521 if (!tries) { 522 /* 523 * No existing pw can decrypt 524 * secret key 525 */ 526 getrpcpws(CURMECH->alias); 527 if (!getsecretkey_g(netname, 528 CURMECH->keylen, 529 CURMECH->algtype, 530 secret, 531 hexkeylen, 532 rpc_pws[pcount])) { 533 /* 534 * Could not retreive 535 * secret key, abort 536 */ 537 free(secret); 538 secret = NULL; 539 goto getsecrets_abort; 540 } 541 542 if (secret[0] == 0) { 543 /* Still no go, ask again */ 544 free(rpc_pws[pcount]); 545 rpc_pw_count--; 546 tries++; 547 printf("Try again. "); 548 fflush(stdout); 549 goto getsecrets_tryagain_g; 550 } else 551 scount++; 552 } else { 553 fprintf(stderr, 554 "%s: key-pair unchanged for %s.\n", 555 program_name, pw->pw_name); 556 exit(1); 557 } 558 } else 559 scount++; 560 561 getsecrets_abort: 562 slist[mcount] = secret; 563 } 564 } else { 565 char *secret = NULL; 566 567 if (!(secret = (char *)malloc(HEXKEYBYTES + 1))) { 568 fprintf(stderr, "%s: Malloc failure.\n", program_name); 569 exit(1); 570 } 571 getsecrets_tryagain: 572 if (!getsecretkey(netname, secret, rpc_pws[0])) { 573 fprintf(stderr, 574 "%s: could not get secret key for '%s'\n", 575 program_name, netname); 576 exit(1); 577 } 578 579 if (secret[0] == 0) { 580 if (!tries) { 581 free(rpc_pws[0]); 582 rpc_pw_count = 0; 583 tries++; 584 printf("Try again. "); 585 fflush(stdout); 586 getrpcpws(NULL); 587 goto getsecrets_tryagain; 588 } else { 589 fprintf(stderr, 590 "%s: key-pair unchanged for %s.\n", 591 program_name, pw->pw_name); 592 exit(1); 593 } 594 } 595 596 slist[0] = secret; 597 return; 598 } 599 600 if (!scount) { 601 (void) fprintf(stderr, 602 "%s: could not get nor decrypt any secret keys for '%s'\n", 603 program_name, netname); 604 error_msg(); 605 exit(1); 606 } 607 } 608 609 610 /* Register AUTH_DES secret key with keyserv */ 611 static void 612 keylogin_des() 613 { 614 char *secret = slist[0]; 615 struct key_netstarg netst; 616 617 /* 618 * try to revoke the existing key/credentials, assuming 619 * one exists. this will effectively mark "stale" any 620 * cached credientials... 621 */ 622 if (key_setsecret(secret) < 0) { 623 return; 624 } 625 626 #ifdef NFS_AUTH 627 /* 628 * it looks like a credential already existed, so try and 629 * revoke any lingering Secure-NFS privledges. 630 */ 631 632 nra.authtype = AUTH_DES; 633 nra.uid = getuid(); 634 635 if (_nfssys(NFS_REVAUTH, &nra) < 0) 636 perror("Warning: NFS credentials not destroyed"); 637 #endif /* NFS_AUTH */ 638 639 memcpy(netst.st_priv_key, secret, HEXKEYBYTES); 640 641 netst.st_pub_key[0] = '\0'; 642 netst.st_netname = strdup(netname); 643 644 /* do actual key login */ 645 if (key_setnet(&netst) < 0) { 646 fprintf(stderr, "Could not set %s's secret key\n", netname); 647 fprintf(stderr, "May be the keyserv is down?\n"); 648 } 649 } 650 651 652 /* Register a secret key with the keyserv */ 653 static void 654 keylogin(keylen_t keylen, algtype_t algtype) 655 { 656 int mcount; 657 658 if (mechs) { 659 for (mcount = 0; CURMECH; mcount++) { 660 if (keylen == CURMECH->keylen && 661 algtype == CURMECH->algtype) { 662 if (key_setnet_g(netname, slist[mcount], 663 CURMECH->keylen, 664 NULL, 0, 665 CURMECH->algtype) 666 < 0) 667 fprintf(stderr, 668 "Could not set %s's %s secret key\n", 669 netname, 670 VALID_ALIAS(CURMECH->alias) ? 671 CURMECH->alias : ""); 672 } 673 } 674 } else { 675 if (keylen == 192 && algtype == 0) 676 keylogin_des(); 677 } 678 } 679 680 681 /* 682 * fgets is "broken" in that if it reads a NUL character it will 683 * always return EOF for all reads, even when there is data left in 684 * the file. This replacement can deal with NUL's in a calm, rational 685 * manner. 686 */ 687 static char * 688 fgets_ignorenul(char *s, int n, FILE *stream) 689 { 690 int fildes = fileno(stream); 691 int i = 0; 692 int rs = 0; 693 char c; 694 695 if (fildes < 0) 696 return (NULL); 697 698 while (i < n - 1) { 699 rs = read(fildes, &c, 1); 700 switch (rs) { 701 case 1: 702 break; 703 case 0: 704 /* EOF */ 705 if (i > 0) 706 s[i] = '\0'; 707 return (NULL); 708 break; 709 default: 710 return (NULL); 711 } 712 switch (c) { 713 case '\0': 714 break; 715 case '\n': 716 s[i] = c; 717 s[++i] = '\0'; 718 return (s); 719 default: 720 if (c != '\0') 721 s[i++] = c; 722 } 723 } 724 s[i] = '\0'; 725 return (s); 726 } 727 728 729 /* Write unencrypted secret key into root key file */ 730 static void 731 write_rootkey(char *secret, char *flavor, keylen_t keylen, algtype_t algtype) 732 { 733 char line[MAXROOTKEY_LINE_LEN]; 734 char keyent[MAXROOTKEY_LEN]; 735 algtype_t atent; 736 int rootfd, bakfd, hexkeybytes; 737 bool_t lineone = TRUE; 738 bool_t gotit = FALSE; 739 FILE *rootfile, *bakfile; 740 741 unlink(ROOTKEY_FILE_BACKUP); 742 if ((rename(ROOTKEY_FILE, ROOTKEY_FILE_BACKUP)) < 0) { 743 if ((bakfd = creat(ROOTKEY_FILE_BACKUP, 0600)) < 0) { 744 perror("Could not create /etc/.rootkey.bak"); 745 goto rootkey_err; 746 } 747 close(bakfd); 748 } 749 750 if ((rootfd = open(ROOTKEY_FILE, O_WRONLY+O_CREAT, 0600)) < 0) { 751 perror("Could not open /etc/.rootkey for writing"); 752 fprintf(stderr, 753 "Attempting to restore original /etc/.rootkey\n"); 754 rename(ROOTKEY_FILE_BACKUP, ROOTKEY_FILE); 755 goto rootkey_err; 756 } 757 if (!(rootfile = fdopen(rootfd, "w"))) { 758 perror("Could not open /etc/.rootkey for writing"); 759 fprintf(stderr, 760 "Attempting to restore original /etc/.rootkey\n"); 761 close(rootfd); 762 unlink(ROOTKEY_FILE); 763 rename(ROOTKEY_FILE_BACKUP, ROOTKEY_FILE); 764 goto rootkey_err; 765 } 766 if (!(bakfile = fopen(ROOTKEY_FILE_BACKUP, "r"))) { 767 perror("Could not open /etc/.rootkey.bak for reading"); 768 fprintf(stderr, 769 "Attempting to restore original /etc/.rootkey\n"); 770 fclose(rootfile); 771 unlink(ROOTKEY_FILE); 772 rename(ROOTKEY_FILE_BACKUP, ROOTKEY_FILE); 773 goto rootkey_err; 774 } 775 776 hexkeybytes = ((keylen + 7) / 8) * 2; 777 778 while (fgets_ignorenul(line, MAXROOTKEY_LINE_LEN, bakfile)) { 779 if (sscanf(line, "%s %d", keyent, &atent) < 2) { 780 /* 781 * No encryption algorithm found in the file 782 * (atent) so default to DES. 783 */ 784 atent = AUTH_DES_ALGTYPE; 785 } 786 /* 787 * 192-bit keys always go on the first line 788 */ 789 if (lineone) { 790 lineone = FALSE; 791 if (keylen == 192) { 792 gotit = TRUE; 793 fprintf(rootfile, "%s\n", secret); 794 } else 795 fprintf(rootfile, "%s", line); 796 fflush(rootfile); 797 } else { 798 if ((strlen(keyent) == hexkeybytes) && 799 (atent == algtype)) { 800 /* 801 * Silently remove lines with the same 802 * keylen/algtype 803 */ 804 if (gotit) 805 continue; 806 else 807 gotit = TRUE; 808 809 fprintf(rootfile, "%s %d\n", secret, algtype); 810 } else 811 fprintf(rootfile, "%s", line); 812 fflush(rootfile); 813 } 814 } 815 816 /* Append key to rootkey file */ 817 if (!gotit) { 818 if (keylen == 192) 819 fprintf(rootfile, "%s\n", secret); 820 else { 821 if (lineone) 822 fprintf(rootfile, "\n"); 823 fprintf(rootfile, "%s %d\n", secret, algtype); 824 } 825 } 826 fflush(rootfile); 827 fclose(rootfile); 828 fclose(bakfile); 829 unlink(ROOTKEY_FILE_BACKUP); 830 return; 831 832 rootkey_err: 833 fprintf(stderr, "WARNING: Could not write %s key to /etc/.rootkey\n", 834 flavor); 835 } 836 837 838 /* Returns 0 if check fails; 1 if successful. */ 839 static int 840 sanity_checks(char *nis_princ, char *domain, char *authtype) 841 { 842 char netdomainaux[MAXHOSTNAMELEN+1]; 843 char *princdomain, *netdomain; 844 int len; 845 846 /* Sanity check 0. Do we have a nis+ principal name to work with? */ 847 if (nis_princ == NULL) { 848 (void) fprintf(stderr, 849 "%s: you must create a \"LOCAL\" credential for '%s' first.\n", 850 program_name, netname); 851 (void) fprintf(stderr, "\tSee nisaddcred(1).\n"); 852 return (0); 853 } 854 855 /* Sanity check 0.5. NIS+ principal names must be dotted. */ 856 len = strlen(nis_princ); 857 if (nis_princ[len-1] != '.') { 858 (void) fprintf(stderr, 859 "%s: invalid principal name: '%s' (forgot ending dot?).\n", 860 program_name, nis_princ); 861 return (0); 862 } 863 864 /* Sanity check 1. We only deal with one type of netnames. */ 865 if (strncmp(netname, "unix", 4) != 0) { 866 (void) fprintf(stderr, 867 "%s: unrecognized netname type: '%s'.\n", 868 program_name, netname); 869 return (0); 870 } 871 872 /* Sanity check 2. Should only add DES cred in home domain. */ 873 princdomain = nis_domain_of(nis_princ); 874 if (strcasecmp(princdomain, domain) != 0) { 875 (void) fprintf(stderr, 876 "%s: domain of principal '%s' does not match destination domain '%s'.\n", 877 program_name, nis_princ, domain); 878 (void) fprintf(stderr, 879 "Should only add DES credential of principal in its home domain\n"); 880 return (0); 881 } 882 883 /* 884 * Sanity check 3: Make sure netname's domain same as principal's 885 * and don't have extraneous dot at the end. 886 */ 887 netdomain = (char *)strchr(netname, '@'); 888 if (! netdomain || netname[strlen(netname)-1] == '.') { 889 (void) fprintf(stderr, "%s: invalid netname: '%s'. \n", 890 program_name, netname); 891 return (0); 892 } 893 netdomain++; /* skip '@' */ 894 895 if (strlcpy(netdomainaux, netdomain, sizeof (netdomainaux)) >= 896 sizeof (netdomainaux)) { 897 (void) fprintf(stderr, "%s: net domain name %s is too long\n", 898 program_name, netdomain); 899 return (0); 900 } 901 902 if (netdomainaux[strlen(netdomainaux) - 1] != '.') { 903 if (strlcat(netdomainaux, ".", sizeof (netdomainaux)) >= 904 sizeof (netdomainaux)) { 905 (void) fprintf(stderr, 906 "%s: net domain name %s is too long\n", 907 program_name, netdomainaux); 908 return (0); 909 } 910 } 911 912 if (strcasecmp(princdomain, netdomainaux) != 0) { 913 (void) fprintf(stderr, 914 "%s: domain of netname %s should be same as that of principal %s\n", 915 program_name, netname, nis_princ); 916 return (0); 917 } 918 919 /* Another principal owns same credentials? (exits if that happens) */ 920 (void) auth_exists(nis_princ, netname, authtype, domain); 921 922 return (1); /* all passed */ 923 } 924 925 926 /* Store new key information in the specified name service */ 927 static void 928 storekeys() 929 { 930 int mcount, ucount = 0; 931 char *ypmaster, *ypdomain = NULL, pkent[MAXPKENTLEN]; 932 nis_name nis_princ; 933 934 935 /* Setup */ 936 switch (dest_service) { 937 case PK_LDAP: 938 break; 939 case PK_NISPLUS: 940 nis_princ = get_nisplus_principal(nis_local_directory(), 941 geteuid()); 942 break; 943 case PK_YP: 944 yp_get_default_domain(&ypdomain); 945 if (yp_master(ypdomain, PKMAP, &ypmaster) != 0) { 946 fprintf(stderr, 947 "%s: cannot find master of NIS publickey database\n", 948 program_name); 949 exit(1); 950 } 951 fprintf(stdout, 952 "Sending key change request to %s ...\n", ypmaster); 953 break; 954 case PK_FILES: 955 if (geteuid() != 0) { 956 fprintf(stderr, 957 "%s: non-root users cannot change their key-pair in %s\n", 958 program_name, PKFILE); 959 exit(1); 960 } 961 break; 962 default: 963 fprintf(stderr, 964 "could not update; database %d unknown\n", 965 dest_service); 966 exit(1); 967 } 968 969 if (mechs) { 970 for (mcount = 0; CURMECH; mcount++) { 971 char authtype[MECH_MAXATNAME]; 972 973 if (!plist[mcount] && !clist[mcount]) 974 continue; 975 976 __nis_mechalias2authtype(CURMECH->alias, authtype, 977 MECH_MAXATNAME); 978 if (!authtype) { 979 fprintf(stderr, 980 "Could not generate auth_type for %s.\n", 981 CURMECH->alias); 982 continue; 983 } 984 985 snprintf(pkent, MAXPKENTLEN, "%s:%s:%d", 986 plist[mcount], clist[mcount], 987 CURMECH->algtype); 988 989 switch (dest_service) { 990 case PK_LDAP: 991 if (ldap_update(CURMECH->alias, netname, 992 plist[mcount], clist[mcount], 993 login_pw)) 994 fprintf(stderr, 995 "%s: unable to update %s key in LDAP database\n", 996 program_name, authtype); 997 else 998 ucount++; 999 break; 1000 1001 case PK_NISPLUS: 1002 if (nisplus_update(nis_princ, 1003 authtype, 1004 plist[mcount], 1005 clist[mcount])) 1006 fprintf(stderr, 1007 "%s: unable to update %s key in nisplus database\n", 1008 program_name, authtype); 1009 else 1010 ucount++; 1011 break; 1012 1013 case PK_YP: 1014 /* Should never get here. */ 1015 break; 1016 1017 case PK_FILES: 1018 /* Should never get here. */ 1019 break; 1020 } 1021 } 1022 } else { 1023 int status = 0; 1024 1025 assert(plist[0] && clist[0]); 1026 snprintf(pkent, MAXPKENTLEN, "%s:%s", plist[0], clist[0]); 1027 1028 switch (dest_service) { 1029 case PK_LDAP: 1030 if (ldap_update("dh192-0", netname, 1031 plist[0], clist[0], 1032 login_pw)) { 1033 fprintf(stderr, 1034 "%s: unable to update %s key in LDAP database\n", 1035 program_name); 1036 exit(1); 1037 } 1038 break; 1039 1040 case PK_NISPLUS: 1041 assert(plist[0] && clist[0]); 1042 if (nisplus_update(nis_princ, 1043 AUTH_DES_AUTH_TYPE, 1044 plist[0], 1045 clist[0])) { 1046 fprintf(stderr, 1047 "%s: unable to update nisplus database\n", 1048 program_name); 1049 exit(1); 1050 } 1051 break; 1052 1053 case PK_YP: 1054 if (status = yp_update(ypdomain, PKMAP, 1055 YPOP_STORE, netname, 1056 strlen(netname), pkent, 1057 strlen(pkent))) { 1058 fprintf(stderr, 1059 "%s: unable to update NIS database (%u): %s\n", 1060 program_name, status, 1061 yperr_string(status)); 1062 exit(1); 1063 } 1064 break; 1065 1066 case PK_FILES: 1067 if (localupdate(netname, PKFILE, YPOP_STORE, pkent)) { 1068 fprintf(stderr, 1069 "%s: hence, unable to update publickey database\n", 1070 program_name); 1071 exit(1); 1072 } 1073 break; 1074 1075 default: 1076 /* Should never get here */ 1077 assert(0); 1078 } 1079 return; 1080 } 1081 if (!ucount) { 1082 fprintf(stderr, "%s: unable to update any key-pairs for %s.\n", 1083 program_name, pw->pw_name); 1084 exit(1); 1085 } 1086 } 1087 1088 /* Check that someone else don't have the same auth information already */ 1089 static 1090 nis_error 1091 auth_exists(char *princname, char *auth_name, char *auth_type, char *domain) 1092 { 1093 char sname[NIS_MAXNAMELEN+1]; 1094 nis_result *res; 1095 nis_error status; 1096 char *foundprinc; 1097 1098 (void) sprintf(sname, "[auth_name=%s,auth_type=%s],%s.%s", 1099 auth_name, auth_type, CRED_TABLE, domain); 1100 if (sname[strlen(sname)-1] != '.') 1101 strcat(sname, "."); 1102 /* Don't want FOLLOW_PATH here */ 1103 res = nis_list(sname, 1104 MASTER_ONLY+USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS, 1105 NULL, NULL); 1106 1107 status = res->status; 1108 switch (res->status) { 1109 case NIS_NOTFOUND: 1110 break; 1111 case NIS_TRYAGAIN: 1112 (void) fprintf(stderr, 1113 "%s: NIS+ server busy, try again later.\n", 1114 program_name); 1115 exit(1); 1116 break; 1117 case NIS_PERMISSION: 1118 (void) fprintf(stderr, 1119 "%s: insufficient permission to look up old credentials.\n", 1120 program_name); 1121 exit(1); 1122 break; 1123 case NIS_SUCCESS: 1124 foundprinc = ENTRY_VAL(res->objects.objects_val, 0); 1125 if (nis_dir_cmp(foundprinc, princname) != SAME_NAME) { 1126 (void) fprintf(stderr, 1127 "%s: %s credentials with auth_name '%s' already belong to '%s'.\n", 1128 program_name, auth_type, auth_name, foundprinc); 1129 exit(1); 1130 } 1131 break; 1132 default: 1133 (void) fprintf(stderr, 1134 "%s: error looking at cred table, NIS+ error: %s\n", 1135 program_name, nis_sperrno(res->status)); 1136 exit(1); 1137 } 1138 nis_freeresult(res); 1139 return (status); 1140 } 1141 1142 1143 /* Check whether this principal already has this type of credentials */ 1144 static nis_error 1145 cred_exists(const char *nisprinc, const char *flavor, const char *domain) 1146 { 1147 char sname[NIS_MAXNAMELEN+1]; 1148 nis_result *res; 1149 nis_error status; 1150 1151 snprintf(sname, NIS_MAXNAMELEN, 1152 "[cname=\"%s\",auth_type=%s],%s.%s", 1153 nisprinc, flavor, CRED_TABLE, domain); 1154 if (sname[strlen(sname)-1] != '.') 1155 strcat(sname, "."); 1156 1157 /* Don't want FOLLOW_PATH here */ 1158 res = nis_list(sname, 1159 MASTER_ONLY+USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS, 1160 NULL, NULL); 1161 1162 status = res->status; 1163 switch (status) { 1164 case NIS_NOTFOUND: 1165 break; 1166 case NIS_TRYAGAIN: 1167 fprintf(stderr, 1168 "%s: NIS+ server busy, try again later.\n", 1169 program_name); 1170 exit(1); 1171 break; 1172 case NIS_PERMISSION: 1173 (void) fprintf(stderr, 1174 "%s: insufficient permission to look at credentials table\n", 1175 program_name); 1176 exit(1); 1177 break; 1178 case NIS_SUCCESS: 1179 case NIS_S_SUCCESS: 1180 break; 1181 default: 1182 (void) fprintf(stderr, 1183 "%s: error looking at cred table, NIS+ error: %s\n", 1184 program_name, nis_sperrno(res->status)); 1185 exit(1); 1186 } 1187 nis_freeresult(res); 1188 return (status); 1189 } 1190 1191 1192 static int 1193 modify_cred_obj(nis_object *obj, char *domain) 1194 { 1195 int status = 0; 1196 char sname[NIS_MAXNAMELEN+1]; 1197 nis_result *res; 1198 1199 (void) sprintf(sname, "%s.%s", CRED_TABLE, domain); 1200 res = nis_modify_entry(sname, obj, 0); 1201 switch (res->status) { 1202 case NIS_TRYAGAIN: 1203 (void) fprintf(stderr, 1204 "%s: NIS+ server busy, try again later.\n", 1205 program_name); 1206 exit(1); 1207 break; 1208 case NIS_PERMISSION: 1209 (void) fprintf(stderr, 1210 "%s: insufficient permission to update credentials.\n", 1211 program_name); 1212 exit(1); 1213 break; 1214 case NIS_SUCCESS: 1215 status = 1; 1216 break; 1217 default: 1218 (void) fprintf(stderr, 1219 "%s: error modifying credential, NIS+ error: %s.\n", 1220 program_name, nis_sperrno(res->status)); 1221 exit(1); 1222 } 1223 nis_freeresult(res); 1224 return (status); 1225 } 1226 1227 1228 static int 1229 add_cred_obj(nis_object *obj, char *domain) 1230 { 1231 int status = 0; 1232 char sname[NIS_MAXNAMELEN+1]; 1233 nis_result *res; 1234 1235 /* Assume check for cred_exists performed already */ 1236 1237 (void) sprintf(sname, "%s.%s", CRED_TABLE, domain); 1238 res = nis_add_entry(sname, obj, 0); 1239 switch (res->status) { 1240 case NIS_TRYAGAIN: 1241 (void) fprintf(stderr, 1242 "%s: NIS+ server busy, try again later.\n", 1243 program_name); 1244 exit(1); 1245 break; 1246 case NIS_PERMISSION: 1247 (void) fprintf(stderr, 1248 "%s: insufficient permission to update credentials.\n", 1249 program_name); 1250 exit(1); 1251 break; 1252 case NIS_SUCCESS: 1253 status = 1; 1254 break; 1255 default: 1256 (void) fprintf(stderr, 1257 "%s: error creating credential, NIS+ error: %s.\n", 1258 program_name, nis_sperrno(res->status)); 1259 exit(1); 1260 } 1261 nis_freeresult(res); 1262 return (status); 1263 } 1264 1265 1266 /* Update NIS+ table with new key information */ 1267 static int 1268 nisplus_update(nis_name nis_princ, char *authtype, char *public, char *crypt) 1269 { 1270 nis_object *obj = init_entry(); 1271 int status; 1272 bool_t addition; 1273 char *userdomain, *cmpdomain, *domain; 1274 1275 if (!(userdomain = strchr(netname, '@'))) { 1276 fprintf(stderr, "%s: invalid netname: '%s'.\n", 1277 program_name, netname); 1278 exit(1); 1279 } 1280 userdomain++; 1281 1282 cmpdomain = strdup(userdomain); 1283 if (cmpdomain[strlen(cmpdomain) - 1] != '.') 1284 strcat(cmpdomain, "."); 1285 1286 domain = nis_domain_of(nis_princ); 1287 if (strcasecmp(domain, cmpdomain) != 0) 1288 domain = nis_local_directory(); 1289 1290 if (!sanity_checks(nis_princ, domain, authtype)) 1291 exit(1); 1292 1293 addition = (cred_exists(nis_princ, authtype, domain) == NIS_NOTFOUND); 1294 1295 ENTRY_VAL(obj, 0) = nis_princ; 1296 ENTRY_LEN(obj, 0) = strlen(nis_princ) + 1; 1297 1298 ENTRY_VAL(obj, 1) = authtype; 1299 ENTRY_LEN(obj, 1) = strlen(authtype) + 1; 1300 1301 ENTRY_VAL(obj, 2) = netname; 1302 ENTRY_LEN(obj, 2) = strlen(netname) + 1; 1303 1304 ENTRY_VAL(obj, 3) = public; 1305 ENTRY_LEN(obj, 3) = strlen(public) + 1; 1306 1307 ENTRY_VAL(obj, 4) = crypt; 1308 ENTRY_LEN(obj, 4) = strlen(crypt) + 1; 1309 1310 if (addition) { 1311 obj->zo_owner = nis_princ; 1312 obj->zo_group = nis_local_group(); 1313 obj->zo_domain = domain; 1314 /* owner: r, group: rmcd */ 1315 obj->zo_access = ((NIS_READ_ACC<<16)| 1316 (NIS_READ_ACC|NIS_MODIFY_ACC|NIS_CREATE_ACC| 1317 NIS_DESTROY_ACC)<<8); 1318 status = add_cred_obj(obj, domain); 1319 } else { 1320 obj->EN_data.en_cols.en_cols_val[3].ec_flags |= EN_MODIFIED; 1321 obj->EN_data.en_cols.en_cols_val[4].ec_flags |= EN_MODIFIED; 1322 status = modify_cred_obj(obj, domain); 1323 } 1324 return (status == 1 ? 0 : 1); 1325 } 1326 1327 1328 void 1329 addmechtolist(char *mechtype) 1330 { 1331 mechanism_t **realmechlist; 1332 int i; 1333 1334 if (realmechlist = __nis_get_mechanisms(FALSE)) { 1335 /* Match requested mech with list */ 1336 for (i = 0; realmechlist[i]; i++) { 1337 if (realmechlist[i]->alias) 1338 if (strcmp(realmechlist[i]->alias, mechtype) 1339 == 0) { 1340 /* 1341 * Match, add it to the mechs. 1342 * Don't worry about qop or 1343 * secserv since they are not 1344 * used by chkey. 1345 */ 1346 numspecmech++; 1347 if ((mechs = 1348 (mechanism_t **)realloc(mechs, 1349 sizeof (mechanism_t *) * (numspecmech + 1))) == 1350 NULL) { 1351 perror("Can not change keys"); 1352 exit(1); 1353 } 1354 1355 if ((mechs[numspecmech - 1] = 1356 (mechanism_t *)malloc(sizeof (mechanism_t))) == NULL) { 1357 perror("Can not change keys"); 1358 exit(1); 1359 } 1360 if (realmechlist[i]->mechname) 1361 mechs[numspecmech - 1]->mechname = 1362 strdup(realmechlist[i]->mechname); 1363 if (realmechlist[i]->alias) 1364 mechs[numspecmech - 1]->alias = 1365 strdup(realmechlist[i]->alias); 1366 mechs[numspecmech - 1]->keylen = 1367 realmechlist[i]->keylen; 1368 mechs[numspecmech - 1]->algtype = 1369 realmechlist[i]->algtype; 1370 mechs[numspecmech] = NULL; 1371 __nis_release_mechanisms(realmechlist); 1372 return; 1373 } 1374 } 1375 1376 fprintf(stderr, 1377 "WARNING: Mechanism '%s' not configured, skipping...\n", 1378 mechtype); 1379 __nis_release_mechanisms(realmechlist); 1380 return; 1381 } 1382 fprintf(stderr, 1383 "WARNING: Mechanism '%s' not configured, skipping...\n", 1384 mechtype); 1385 } 1386 1387 1388 int 1389 main(int argc, char **argv) 1390 { 1391 int c, mcount; 1392 uid_t uid; 1393 uid_t orig_euid; 1394 char *service = NULL; 1395 program_name = argv[0]; 1396 1397 mechs = __nis_get_mechanisms(FALSE); 1398 1399 while ((c = getopt(argc, argv, "fps:m:")) != -1) { 1400 switch (c) { 1401 case 'f': 1402 /* 1403 * Not documented as of on1093. 1404 * Temporarily supported 1405 */ 1406 force++; 1407 break; 1408 case 'p': 1409 makenew = FALSE; 1410 break; 1411 case 's': 1412 if (!service) 1413 service = strdup(optarg); 1414 else 1415 usage(); 1416 break; 1417 case 'm': 1418 if (mechs && specmech == FALSE) { 1419 __nis_release_mechanisms(mechs); 1420 mechs = NULL; 1421 } 1422 specmech = TRUE; 1423 addmechtolist(optarg); 1424 break; 1425 default: 1426 usage(); 1427 } 1428 } 1429 1430 if (optind < argc) 1431 usage(); 1432 1433 dest_service = get_pk_source(service); 1434 1435 if (!(netname = malloc(MAXNETNAMELEN + 1))) { 1436 fprintf(stderr, "%s: Malloc failure.\n", program_name); 1437 exit(1); 1438 } 1439 if (!__getnetnamebyuid(netname, uid = getuid())) { 1440 fprintf(stderr, "%s: cannot generate netname for uid %d\n", 1441 program_name, uid); 1442 exit(1); 1443 } 1444 sec_domain = strdup(strchr(netname, '@') + 1); 1445 getdomainname(local_domain, MAXNETNAMELEN); 1446 1447 if (makenew) 1448 fprintf(stdout, "Generating new key for '%s'.\n", netname); 1449 else 1450 fprintf(stdout, "Reencrypting key for '%s'.\n", netname); 1451 1452 if (mechs) { 1453 if (dest_service == PK_YP || dest_service == PK_FILES) { 1454 fprintf(stderr, 1455 "%s: can not add non-DES public keys to %s, skipping.\n", 1456 program_name, service); 1457 __nis_release_mechanisms(mechs); 1458 mechs = NULL; 1459 initkeylist(TRUE); 1460 } else 1461 initkeylist(FALSE); 1462 } else 1463 initkeylist(TRUE); 1464 1465 uid = getuid(); 1466 orig_euid = geteuid(); 1467 1468 /* Get password information */ 1469 if ((pw = getpwuid(uid)) == NULL) { 1470 fprintf(stderr, 1471 "%s: Can not find passwd information for %d.\n", 1472 program_name, uid); 1473 exit(1); 1474 } 1475 1476 /* Set eUID to user */ 1477 seteuid(uid); 1478 1479 /* Obtain a list of decrypted secret keys */ 1480 getsecrets(); 1481 1482 /* Keylogin user if not already done */ 1483 if (mechs) { 1484 int mcount; 1485 1486 for (mcount = 0; CURMECH; mcount++) { 1487 keylen_t keylen = CURMECH->keylen; 1488 algtype_t algtype = CURMECH->algtype; 1489 1490 if (!key_secretkey_is_set_g(keylen, algtype) && 1491 slist[mcount]) { 1492 keylogin(CURMECH->keylen, CURMECH->algtype); 1493 if ((uid == 0) && (makenew == FALSE)) 1494 write_rootkey(slist[mcount], 1495 VALID_ALIAS(CURMECH->alias) ? 1496 CURMECH->alias : 1497 "", 1498 keylen, algtype); 1499 } 1500 } 1501 } else { 1502 assert(slist[0]); 1503 if (!key_secretkey_is_set()) { 1504 keylogin_des(); 1505 if ((uid == 0) && (makenew == FALSE)) 1506 write_rootkey(slist[0], "des", 192, 0); 1507 } 1508 } 1509 1510 /* Set eUID back to root */ 1511 (void) seteuid(orig_euid); 1512 1513 /* 1514 * Call getspnam() after the keylogin has been done so we have 1515 * the best chance of having read access to the encrypted pw. 1516 * 1517 * The eUID must be 0 for the getspnam() so the name service 1518 * switch can handle the following eUID sensitive cases: 1519 * 1520 * files/compat: read /etc/shadow 1521 * 1522 * nisplus: try to read the encrypted pw as the root 1523 * principal and if that fails, and if the 1524 * user's secret key is set, seteuid(user) 1525 * and retry the read. 1526 */ 1527 if ((spw = getspnam(pw->pw_name)) == 0) { 1528 1529 /* Set eUID back to user */ 1530 (void) seteuid(uid); 1531 1532 (void) fprintf(stderr, 1533 "%s: cannot find shadow entry for %s.\n", 1534 program_name, pw->pw_name); 1535 exit(1); 1536 } 1537 1538 /* Set eUID back to user */ 1539 (void) seteuid(uid); 1540 1541 if (strcmp(spw->sp_pwdp, "*NP*") == 0) { 1542 (void) fprintf(stderr, 1543 "%s: do not have read access to the passwd field for %s\n", 1544 program_name, pw->pw_name); 1545 exit(1); 1546 } 1547 1548 /* 1549 * force will be only supported for a while 1550 * -- it is NOT documented as of s1093 1551 */ 1552 if (force) { 1553 char *prompt = "Please enter New password:"; 1554 1555 login_pw = getpass(prompt); 1556 if (!login_pw || !(strlen(login_pw))) { 1557 fprintf(stderr, "%s: key-pair(s) unchanged for %s.\n", 1558 program_name, pw->pw_name); 1559 exit(1); 1560 } 1561 } else { 1562 /* 1563 * Reconsile rpc_pws and login_pw. 1564 * 1565 * This function will either return with login_pw == rpc_pw 1566 * (and thus, the new pw to encrypt keys) or it will exit. 1567 */ 1568 cmp_passwd(); 1569 } 1570 1571 if (makenew) 1572 makenewkeys(); 1573 else 1574 getpublics(); 1575 1576 encryptkeys(); 1577 1578 storekeys(); 1579 1580 if (makenew) { 1581 if (uid == 0) { 1582 if (mechs) { 1583 for (mcount = 0; CURMECH; mcount++) { 1584 if (!slist[mcount]) 1585 continue; 1586 write_rootkey(slist[mcount], 1587 CURMECH->alias, 1588 CURMECH->keylen, 1589 CURMECH->algtype); 1590 } 1591 } else { 1592 assert(slist[0]); 1593 write_rootkey(slist[0], "des", 192, 0); 1594 } 1595 } 1596 if (mechs) { 1597 for (mcount = 0; CURMECH; mcount++) 1598 keylogin(CURMECH->keylen, 1599 CURMECH->algtype); 1600 } else 1601 keylogin_des(); 1602 } 1603 return (0); 1604 } 1605