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 cmpdomain[MAXHOSTNAMELEN + 1]; 1274 char *userdomain, *domain; 1275 1276 if (!(userdomain = strchr(netname, '@'))) { 1277 fprintf(stderr, "%s: invalid netname: '%s'.\n", 1278 program_name, netname); 1279 exit(1); 1280 } 1281 userdomain++; 1282 1283 if (strlcpy(cmpdomain, userdomain, sizeof (cmpdomain)) >= 1284 sizeof (cmpdomain)) { 1285 (void) fprintf(stderr, 1286 "%s: net domain name %s is too long\n", 1287 program_name, cmpdomain); 1288 exit(1); 1289 } 1290 1291 if (cmpdomain[strlen(cmpdomain) - 1] != '.') { 1292 if (strlcat(cmpdomain, ".", sizeof (cmpdomain)) >= 1293 sizeof (cmpdomain)) { 1294 (void) fprintf(stderr, 1295 "%s: net domain name %s is too long\n", 1296 program_name, cmpdomain); 1297 exit(1); 1298 } 1299 } 1300 1301 domain = nis_domain_of(nis_princ); 1302 if (strcasecmp(domain, cmpdomain) != 0) 1303 domain = nis_local_directory(); 1304 1305 if (!sanity_checks(nis_princ, domain, authtype)) 1306 exit(1); 1307 1308 addition = (cred_exists(nis_princ, authtype, domain) == NIS_NOTFOUND); 1309 1310 ENTRY_VAL(obj, 0) = nis_princ; 1311 ENTRY_LEN(obj, 0) = strlen(nis_princ) + 1; 1312 1313 ENTRY_VAL(obj, 1) = authtype; 1314 ENTRY_LEN(obj, 1) = strlen(authtype) + 1; 1315 1316 ENTRY_VAL(obj, 2) = netname; 1317 ENTRY_LEN(obj, 2) = strlen(netname) + 1; 1318 1319 ENTRY_VAL(obj, 3) = public; 1320 ENTRY_LEN(obj, 3) = strlen(public) + 1; 1321 1322 ENTRY_VAL(obj, 4) = crypt; 1323 ENTRY_LEN(obj, 4) = strlen(crypt) + 1; 1324 1325 if (addition) { 1326 obj->zo_owner = nis_princ; 1327 obj->zo_group = nis_local_group(); 1328 obj->zo_domain = domain; 1329 /* owner: r, group: rmcd */ 1330 obj->zo_access = ((NIS_READ_ACC<<16)| 1331 (NIS_READ_ACC|NIS_MODIFY_ACC|NIS_CREATE_ACC| 1332 NIS_DESTROY_ACC)<<8); 1333 status = add_cred_obj(obj, domain); 1334 } else { 1335 obj->EN_data.en_cols.en_cols_val[3].ec_flags |= EN_MODIFIED; 1336 obj->EN_data.en_cols.en_cols_val[4].ec_flags |= EN_MODIFIED; 1337 status = modify_cred_obj(obj, domain); 1338 } 1339 return (status == 1 ? 0 : 1); 1340 } 1341 1342 1343 void 1344 addmechtolist(char *mechtype) 1345 { 1346 mechanism_t **realmechlist; 1347 int i; 1348 1349 if (realmechlist = __nis_get_mechanisms(FALSE)) { 1350 /* Match requested mech with list */ 1351 for (i = 0; realmechlist[i]; i++) { 1352 if (realmechlist[i]->alias) 1353 if (strcmp(realmechlist[i]->alias, mechtype) 1354 == 0) { 1355 /* 1356 * Match, add it to the mechs. 1357 * Don't worry about qop or 1358 * secserv since they are not 1359 * used by chkey. 1360 */ 1361 numspecmech++; 1362 if ((mechs = 1363 (mechanism_t **)realloc(mechs, 1364 sizeof (mechanism_t *) * (numspecmech + 1))) == 1365 NULL) { 1366 perror("Can not change keys"); 1367 exit(1); 1368 } 1369 1370 if ((mechs[numspecmech - 1] = 1371 (mechanism_t *)malloc(sizeof (mechanism_t))) == NULL) { 1372 perror("Can not change keys"); 1373 exit(1); 1374 } 1375 if (realmechlist[i]->mechname) 1376 mechs[numspecmech - 1]->mechname = 1377 strdup(realmechlist[i]->mechname); 1378 if (realmechlist[i]->alias) 1379 mechs[numspecmech - 1]->alias = 1380 strdup(realmechlist[i]->alias); 1381 mechs[numspecmech - 1]->keylen = 1382 realmechlist[i]->keylen; 1383 mechs[numspecmech - 1]->algtype = 1384 realmechlist[i]->algtype; 1385 mechs[numspecmech] = NULL; 1386 __nis_release_mechanisms(realmechlist); 1387 return; 1388 } 1389 } 1390 1391 fprintf(stderr, 1392 "WARNING: Mechanism '%s' not configured, skipping...\n", 1393 mechtype); 1394 __nis_release_mechanisms(realmechlist); 1395 return; 1396 } 1397 fprintf(stderr, 1398 "WARNING: Mechanism '%s' not configured, skipping...\n", 1399 mechtype); 1400 } 1401 1402 1403 int 1404 main(int argc, char **argv) 1405 { 1406 int c, mcount; 1407 uid_t uid; 1408 uid_t orig_euid; 1409 char *service = NULL; 1410 program_name = argv[0]; 1411 1412 mechs = __nis_get_mechanisms(FALSE); 1413 1414 while ((c = getopt(argc, argv, "fps:m:")) != -1) { 1415 switch (c) { 1416 case 'f': 1417 /* 1418 * Not documented as of on1093. 1419 * Temporarily supported 1420 */ 1421 force++; 1422 break; 1423 case 'p': 1424 makenew = FALSE; 1425 break; 1426 case 's': 1427 if (!service) 1428 service = strdup(optarg); 1429 else 1430 usage(); 1431 break; 1432 case 'm': 1433 if (mechs && specmech == FALSE) { 1434 __nis_release_mechanisms(mechs); 1435 mechs = NULL; 1436 } 1437 specmech = TRUE; 1438 addmechtolist(optarg); 1439 break; 1440 default: 1441 usage(); 1442 } 1443 } 1444 1445 if (optind < argc) 1446 usage(); 1447 1448 dest_service = get_pk_source(service); 1449 1450 if (!(netname = malloc(MAXNETNAMELEN + 1))) { 1451 fprintf(stderr, "%s: Malloc failure.\n", program_name); 1452 exit(1); 1453 } 1454 if (!__getnetnamebyuid(netname, uid = getuid())) { 1455 fprintf(stderr, "%s: cannot generate netname for uid %d\n", 1456 program_name, uid); 1457 exit(1); 1458 } 1459 sec_domain = strdup(strchr(netname, '@') + 1); 1460 getdomainname(local_domain, MAXNETNAMELEN); 1461 1462 if (makenew) 1463 fprintf(stdout, "Generating new key for '%s'.\n", netname); 1464 else 1465 fprintf(stdout, "Reencrypting key for '%s'.\n", netname); 1466 1467 if (mechs) { 1468 if (dest_service == PK_YP || dest_service == PK_FILES) { 1469 fprintf(stderr, 1470 "%s: can not add non-DES public keys to %s, skipping.\n", 1471 program_name, service); 1472 __nis_release_mechanisms(mechs); 1473 mechs = NULL; 1474 initkeylist(TRUE); 1475 } else 1476 initkeylist(FALSE); 1477 } else 1478 initkeylist(TRUE); 1479 1480 uid = getuid(); 1481 orig_euid = geteuid(); 1482 1483 /* Get password information */ 1484 if ((pw = getpwuid(uid)) == NULL) { 1485 fprintf(stderr, 1486 "%s: Can not find passwd information for %d.\n", 1487 program_name, uid); 1488 exit(1); 1489 } 1490 1491 /* Set eUID to user */ 1492 seteuid(uid); 1493 1494 /* Obtain a list of decrypted secret keys */ 1495 getsecrets(); 1496 1497 /* Keylogin user if not already done */ 1498 if (mechs) { 1499 int mcount; 1500 1501 for (mcount = 0; CURMECH; mcount++) { 1502 keylen_t keylen = CURMECH->keylen; 1503 algtype_t algtype = CURMECH->algtype; 1504 1505 if (!key_secretkey_is_set_g(keylen, algtype) && 1506 slist[mcount]) { 1507 keylogin(CURMECH->keylen, CURMECH->algtype); 1508 if ((uid == 0) && (makenew == FALSE)) 1509 write_rootkey(slist[mcount], 1510 VALID_ALIAS(CURMECH->alias) ? 1511 CURMECH->alias : 1512 "", 1513 keylen, algtype); 1514 } 1515 } 1516 } else { 1517 assert(slist[0]); 1518 if (!key_secretkey_is_set()) { 1519 keylogin_des(); 1520 if ((uid == 0) && (makenew == FALSE)) 1521 write_rootkey(slist[0], "des", 192, 0); 1522 } 1523 } 1524 1525 /* Set eUID back to root */ 1526 (void) seteuid(orig_euid); 1527 1528 /* 1529 * Call getspnam() after the keylogin has been done so we have 1530 * the best chance of having read access to the encrypted pw. 1531 * 1532 * The eUID must be 0 for the getspnam() so the name service 1533 * switch can handle the following eUID sensitive cases: 1534 * 1535 * files/compat: read /etc/shadow 1536 * 1537 * nisplus: try to read the encrypted pw as the root 1538 * principal and if that fails, and if the 1539 * user's secret key is set, seteuid(user) 1540 * and retry the read. 1541 */ 1542 if ((spw = getspnam(pw->pw_name)) == 0) { 1543 1544 /* Set eUID back to user */ 1545 (void) seteuid(uid); 1546 1547 (void) fprintf(stderr, 1548 "%s: cannot find shadow entry for %s.\n", 1549 program_name, pw->pw_name); 1550 exit(1); 1551 } 1552 1553 /* Set eUID back to user */ 1554 (void) seteuid(uid); 1555 1556 if (strcmp(spw->sp_pwdp, "*NP*") == 0) { 1557 (void) fprintf(stderr, 1558 "%s: do not have read access to the passwd field for %s\n", 1559 program_name, pw->pw_name); 1560 exit(1); 1561 } 1562 1563 /* 1564 * force will be only supported for a while 1565 * -- it is NOT documented as of s1093 1566 */ 1567 if (force) { 1568 char *prompt = "Please enter New password:"; 1569 1570 login_pw = getpass(prompt); 1571 if (!login_pw || !(strlen(login_pw))) { 1572 fprintf(stderr, "%s: key-pair(s) unchanged for %s.\n", 1573 program_name, pw->pw_name); 1574 exit(1); 1575 } 1576 } else { 1577 /* 1578 * Reconsile rpc_pws and login_pw. 1579 * 1580 * This function will either return with login_pw == rpc_pw 1581 * (and thus, the new pw to encrypt keys) or it will exit. 1582 */ 1583 cmp_passwd(); 1584 } 1585 1586 if (makenew) 1587 makenewkeys(); 1588 else 1589 getpublics(); 1590 1591 encryptkeys(); 1592 1593 storekeys(); 1594 1595 if (makenew) { 1596 if (uid == 0) { 1597 if (mechs) { 1598 for (mcount = 0; CURMECH; mcount++) { 1599 if (!slist[mcount]) 1600 continue; 1601 write_rootkey(slist[mcount], 1602 CURMECH->alias, 1603 CURMECH->keylen, 1604 CURMECH->algtype); 1605 } 1606 } else { 1607 assert(slist[0]); 1608 write_rootkey(slist[0], "des", 192, 0); 1609 } 1610 } 1611 if (mechs) { 1612 for (mcount = 0; CURMECH; mcount++) 1613 keylogin(CURMECH->keylen, 1614 CURMECH->algtype); 1615 } else 1616 keylogin_des(); 1617 } 1618 return (0); 1619 } 1620