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