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