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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma weak _crypt = crypt 28 #pragma weak _encrypt = encrypt 29 #pragma weak _setkey = setkey 30 31 #include "lint.h" 32 #include "mtlib.h" 33 #include <synch.h> 34 #include <thread.h> 35 #include <ctype.h> 36 #include <dlfcn.h> 37 #include <errno.h> 38 #include <stdio.h> 39 #include <strings.h> 40 #include <stdlib.h> 41 #include <sys/time.h> 42 #include <limits.h> 43 #include <sys/types.h> 44 #include <sys/stat.h> 45 #include <fcntl.h> 46 #include <syslog.h> 47 #include <unistd.h> 48 #include <atomic.h> 49 50 #include <crypt.h> 51 #include <libc.h> 52 #include "tsd.h" 53 54 #define CRYPT_ALGORITHMS_ALLOW "CRYPT_ALGORITHMS_ALLOW" 55 #define CRYPT_ALGORITHMS_DEPRECATE "CRYPT_ALGORITHMS_DEPRECATE" 56 #define CRYPT_DEFAULT "CRYPT_DEFAULT" 57 #define CRYPT_UNIX "__unix__" 58 59 #define CRYPT_CONFFILE "/etc/security/crypt.conf" 60 #define POLICY_CONF_FILE "/etc/security/policy.conf" 61 62 #define CRYPT_CONFLINELENGTH 1024 63 64 #define CRYPT_MODULE_ISA "/$ISA/" 65 #ifdef _LP64 66 #define CRYPT_MODULE_DIR "/usr/lib/security/64/" 67 #define CRYPT_ISA_DIR "/64/" 68 #else /* !_LP64 */ 69 #define CRYPT_MODULE_DIR "/usr/lib/security/" 70 #define CRYPT_ISA_DIR "/" 71 #endif /* _LP64 */ 72 73 /* 74 * MAX_ALGNAME_LEN: 75 * 76 * In practical terms this is probably never any bigger than about 10, but... 77 * 78 * It has to fix the encrypted password filed of struct spwd it is 79 * theoretically the maximum length of the cipher minus the magic $ sign. 80 * Though that would be unexpected. 81 * Since it also has to fit in crypt.conf it is CRYPT_CONFLINELENGTH 82 * minus the path to the module and the minimum white space. 83 * 84 * CRYPT_MAXCIPHERTEXTLEN is defined in crypt.h and is smaller than 85 * CRYPT_CONFLINELENGTH, and probably always will be. 86 */ 87 #define MAX_ALGNAME_LEN (CRYPT_MAXCIPHERTEXTLEN - 1) 88 89 struct crypt_alg_s { 90 void *a_libhandle; 91 char *(*a_genhash)(char *, const size_t, const char *, 92 const char *, const char **); 93 char *(*a_gensalt)(char *, const size_t, 94 const char *, const struct passwd *, const char **); 95 char **a_params; 96 int a_nparams; 97 }; 98 99 struct crypt_policy_s { 100 char *cp_default; 101 char *cp_allow; 102 char *cp_deny; 103 }; 104 105 enum crypt_policy_error_e { 106 CPE_BOTH = 1, 107 CPE_MULTI 108 }; 109 110 static struct crypt_policy_s *getcryptpolicy(void); 111 static void free_crypt_policy(struct crypt_policy_s *policy); 112 static struct crypt_alg_s *getalgbyname(const char *algname, boolean_t *found); 113 static void free_crypt_alg(struct crypt_alg_s *alg); 114 static char *getalgfromsalt(const char *salt); 115 static boolean_t alg_valid(const char *algname, 116 const struct crypt_policy_s *policy); 117 static char *isa_path(const char *path); 118 119 static char *_unix_crypt(const char *pw, const char *salt, char *iobuf); 120 static char *_unix_crypt_gensalt(char *gsbuffer, size_t gsbufflen, 121 const char *oldpuresalt, const struct passwd *userinfo, 122 const char *params[]); 123 124 125 /* 126 * crypt - string encoding function 127 * 128 * This function encodes strings in a suitable for for secure storage 129 * as passwords. It generates the password hash given the plaintext and salt. 130 * 131 * If the first character of salt is "$" then we use crypt.conf(4) to 132 * determine which plugin to use and run the crypt_genhash_impl(3c) function 133 * from it. 134 * Otherwise we use the old unix algorithm. 135 * 136 * RETURN VALUES 137 * On Success we return a pointer to the encoded string. The 138 * return value points to thread specific static data and should NOT 139 * be passed free(3c). 140 * On failure we return NULL and set errno to one of: 141 * EINVAL, ELIBACC, ENOMEM, ENOSYS. 142 */ 143 char * 144 crypt(const char *plaintext, const char *salt) 145 { 146 struct crypt_alg_s *alg; 147 char *ctbuffer; 148 char *ciphertext; 149 char *algname; 150 boolean_t found; 151 152 ctbuffer = tsdalloc(_T_CRYPT, CRYPT_MAXCIPHERTEXTLEN, NULL); 153 if (ctbuffer == NULL) 154 return (NULL); 155 bzero(ctbuffer, CRYPT_MAXCIPHERTEXTLEN); 156 157 /* 158 * '$' is never a possible salt char with the traditional unix 159 * algorithm. If the salt passed in is NULL or the first char 160 * of the salt isn't a $ then do the traditional thing. 161 * We also do the traditional thing if the salt is only 1 char. 162 */ 163 if (salt == NULL || salt[0] != '$' || strlen(salt) == 1) { 164 return (_unix_crypt(plaintext, salt, ctbuffer)); 165 } 166 167 /* 168 * Find the algorithm name from the salt and look it up in 169 * crypt.conf(4) to find out what shared object to use. 170 * If we can't find it in crypt.conf then getalgbyname would 171 * have returned with found = B_FALSE so we use the unix algorithm. 172 * If alg is NULL but found = B_TRUE then there is a problem with 173 * the plugin so we fail leaving errno set to what getalgbyname() 174 * set it to or EINVAL it if wasn't set. 175 */ 176 if ((algname = getalgfromsalt(salt)) == NULL) { 177 return (NULL); 178 } 179 180 errno = 0; 181 alg = getalgbyname(algname, &found); 182 if ((alg == NULL) || !found) { 183 if (errno == 0) 184 errno = EINVAL; 185 ciphertext = NULL; 186 goto cleanup; 187 } else if (!found) { 188 ciphertext = _unix_crypt(plaintext, salt, ctbuffer); 189 } else { 190 ciphertext = alg->a_genhash(ctbuffer, CRYPT_MAXCIPHERTEXTLEN, 191 plaintext, salt, (const char **)alg->a_params); 192 } 193 194 cleanup: 195 free_crypt_alg(alg); 196 if (algname != NULL) 197 free(algname); 198 199 return (ciphertext); 200 } 201 202 /* 203 * crypt_gensalt - generate salt string for string encoding 204 * 205 * This function generates the salt string pased to crypt(3c). 206 * If oldsalt is NULL, the use the default algorithm. 207 * Other wise check the policy in policy.conf to ensure that it is 208 * either still allowed or not deprecated. 209 * 210 * RETURN VALUES 211 * Return a pointer to the new salt, the caller is responsible 212 * for using free(3c) on the return value. 213 * Returns NULL on error and sets errno to one of: 214 * EINVAL, ELIBACC, ENOMEM 215 */ 216 char * 217 crypt_gensalt(const char *oldsalt, const struct passwd *userinfo) 218 { 219 struct crypt_alg_s *alg = NULL; 220 struct crypt_policy_s *policy = NULL; 221 char *newsalt = NULL; 222 char *gsbuffer; 223 char *algname = NULL; 224 boolean_t found; 225 226 gsbuffer = calloc(CRYPT_MAXCIPHERTEXTLEN, sizeof (char *)); 227 if (gsbuffer == NULL) { 228 errno = ENOMEM; 229 goto cleanup; 230 } 231 232 policy = getcryptpolicy(); 233 if (policy == NULL) { 234 errno = EINVAL; 235 goto cleanup; 236 } 237 238 algname = getalgfromsalt(oldsalt); 239 if (!alg_valid(algname, policy)) { 240 free(algname); 241 algname = strdup(policy->cp_default); 242 } 243 244 if (strcmp(algname, CRYPT_UNIX) == 0) { 245 newsalt = _unix_crypt_gensalt(gsbuffer, CRYPT_MAXCIPHERTEXTLEN, 246 oldsalt, userinfo, NULL); 247 } else { 248 errno = 0; 249 alg = getalgbyname(algname, &found); 250 if (alg == NULL || !found) { 251 if (errno == 0) 252 errno = EINVAL; 253 goto cleanup; 254 } 255 newsalt = alg->a_gensalt(gsbuffer, CRYPT_MAXCIPHERTEXTLEN, 256 oldsalt, userinfo, (const char **)alg->a_params); 257 } 258 259 cleanup: 260 free_crypt_policy(policy); 261 free_crypt_alg(alg); 262 if (newsalt == NULL && gsbuffer != NULL) 263 free(gsbuffer); 264 if (algname != NULL) 265 free(algname); 266 267 return (newsalt); 268 } 269 270 /* 271 * =========================================================================== 272 * The remainder of this file contains internal interfaces for 273 * the implementation of crypt(3c) and crypt_gensalt(3c) 274 * =========================================================================== 275 */ 276 277 278 /* 279 * getalgfromsalt - extract the algorithm name from the salt string 280 */ 281 static char * 282 getalgfromsalt(const char *salt) 283 { 284 char algname[CRYPT_MAXCIPHERTEXTLEN]; 285 int i; 286 int j; 287 288 if (salt == NULL || strlen(salt) > CRYPT_MAXCIPHERTEXTLEN) 289 return (NULL); 290 /* 291 * Salts are in this format: 292 * $<algname>[,var=val,[var=val ...][$puresalt]$<ciphertext> 293 * 294 * The only bit we need to worry about here is extracting the 295 * name which is the string between the first "$" and the first 296 * of "," or second "$". 297 */ 298 if (salt[0] != '$') { 299 return (strdup(CRYPT_UNIX)); 300 } 301 302 i = 1; 303 j = 0; 304 while (salt[i] != '\0' && salt[i] != '$' && salt[i] != ',') { 305 algname[j] = salt[i]; 306 i++; 307 j++; 308 } 309 if (j == 0) 310 return (NULL); 311 312 algname[j] = '\0'; 313 314 return (strdup(algname)); 315 } 316 317 318 /* 319 * log_invalid_policy - syslog helper 320 */ 321 static void 322 log_invalid_policy(enum crypt_policy_error_e error, char *value) 323 { 324 switch (error) { 325 case CPE_BOTH: 326 syslog(LOG_AUTH | LOG_ERR, 327 "crypt(3c): %s contains both %s and %s; only one may be " 328 "specified, using first entry in file.", POLICY_CONF_FILE, 329 CRYPT_ALGORITHMS_ALLOW, CRYPT_ALGORITHMS_DEPRECATE); 330 break; 331 case CPE_MULTI: 332 syslog(LOG_AUTH | LOG_ERR, 333 "crypt(3c): %s contains multiple %s entries;" 334 "using first entry file.", POLICY_CONF_FILE, value); 335 break; 336 } 337 } 338 339 static char * 340 getval(const char *ival) 341 { 342 char *tmp; 343 char *oval; 344 int off; 345 346 if (ival == NULL) 347 return (NULL); 348 349 if ((tmp = strchr(ival, '=')) == NULL) 350 return (NULL); 351 352 oval = strdup(tmp + 1); /* everything after the "=" */ 353 if (oval == NULL) 354 return (NULL); 355 off = strlen(oval) - 1; 356 if (off < 0) { 357 free(oval); 358 return (NULL); 359 } 360 if (oval[off] == '\n') 361 oval[off] = '\0'; 362 363 return (oval); 364 } 365 366 /* 367 * getcryptpolicy - read /etc/security/policy.conf into a crypt_policy_s 368 */ 369 static struct crypt_policy_s * 370 getcryptpolicy(void) 371 { 372 FILE *pconf; 373 char line[BUFSIZ]; 374 struct crypt_policy_s *policy; 375 376 if ((pconf = fopen(POLICY_CONF_FILE, "rF")) == NULL) { 377 return (NULL); 378 } 379 380 policy = malloc(sizeof (struct crypt_policy_s)); 381 if (policy == NULL) { 382 return (NULL); 383 } 384 policy->cp_default = NULL; 385 policy->cp_allow = NULL; 386 policy->cp_deny = NULL; 387 388 while (!feof(pconf) && 389 (fgets(line, sizeof (line), pconf) != NULL)) { 390 if (strncasecmp(CRYPT_DEFAULT, line, 391 strlen(CRYPT_DEFAULT)) == 0) { 392 if (policy->cp_default != NULL) { 393 log_invalid_policy(CPE_MULTI, CRYPT_DEFAULT); 394 } else { 395 policy->cp_default = getval(line); 396 } 397 } 398 if (strncasecmp(CRYPT_ALGORITHMS_ALLOW, line, 399 strlen(CRYPT_ALGORITHMS_ALLOW)) == 0) { 400 if (policy->cp_deny != NULL) { 401 log_invalid_policy(CPE_BOTH, NULL); 402 } else if (policy->cp_allow != NULL) { 403 log_invalid_policy(CPE_MULTI, 404 CRYPT_ALGORITHMS_ALLOW); 405 } else { 406 policy->cp_allow = getval(line); 407 } 408 } 409 if (strncasecmp(CRYPT_ALGORITHMS_DEPRECATE, line, 410 strlen(CRYPT_ALGORITHMS_DEPRECATE)) == 0) { 411 if (policy->cp_allow != NULL) { 412 log_invalid_policy(CPE_BOTH, NULL); 413 } else if (policy->cp_deny != NULL) { 414 log_invalid_policy(CPE_MULTI, 415 CRYPT_ALGORITHMS_DEPRECATE); 416 } else { 417 policy->cp_deny = getval(line); 418 } 419 } 420 } 421 (void) fclose(pconf); 422 423 if (policy->cp_default == NULL) { 424 policy->cp_default = strdup(CRYPT_UNIX); 425 if (policy->cp_default == NULL) 426 free_crypt_policy(policy); 427 } 428 429 return (policy); 430 } 431 432 433 /* 434 * alg_valid - is this algorithm valid given the policy ? 435 */ 436 static boolean_t 437 alg_valid(const char *algname, const struct crypt_policy_s *policy) 438 { 439 char *lasts; 440 char *list; 441 char *entry; 442 boolean_t allowed = B_FALSE; 443 444 if ((algname == NULL) || (policy == NULL)) { 445 return (B_FALSE); 446 } 447 448 if (strcmp(algname, policy->cp_default) == 0) { 449 return (B_TRUE); 450 } 451 452 if (policy->cp_deny != NULL) { 453 list = policy->cp_deny; 454 allowed = B_FALSE; 455 } else if (policy->cp_allow != NULL) { 456 list = policy->cp_allow; 457 allowed = B_TRUE; 458 } else { 459 /* 460 * Neither of allow or deny policies are set so anything goes. 461 */ 462 return (B_TRUE); 463 } 464 lasts = list; 465 while ((entry = strtok_r(NULL, ",", &lasts)) != NULL) { 466 if (strcmp(entry, algname) == 0) { 467 return (allowed); 468 } 469 } 470 471 return (!allowed); 472 } 473 474 /* 475 * getalgbyname - read crypt.conf(4) looking for algname 476 * 477 * RETURN VALUES 478 * On error NULL and errno is set 479 * On success the alg details including an open handle to the lib 480 * If crypt.conf(4) is okay but algname doesn't exist in it then 481 * return NULL the caller should then use the default algorithm 482 * as per the policy. 483 */ 484 static struct crypt_alg_s * 485 getalgbyname(const char *algname, boolean_t *found) 486 { 487 struct stat stb; 488 int configfd; 489 FILE *fconf = NULL; 490 struct crypt_alg_s *alg = NULL; 491 char line[CRYPT_CONFLINELENGTH]; 492 int linelen = 0; 493 int lineno = 0; 494 char *pathname = NULL; 495 char *lasts = NULL; 496 char *token = NULL; 497 498 *found = B_FALSE; 499 if ((algname == NULL) || (strcmp(algname, CRYPT_UNIX) == 0)) { 500 return (NULL); 501 } 502 503 if ((configfd = open(CRYPT_CONFFILE, O_RDONLY)) == -1) { 504 syslog(LOG_ALERT, "crypt: open(%s) failed: %s", 505 CRYPT_CONFFILE, strerror(errno)); 506 return (NULL); 507 } 508 509 /* 510 * Stat the file so we can check modes and ownerships 511 */ 512 if (fstat(configfd, &stb) < 0) { 513 syslog(LOG_ALERT, "crypt: stat(%s) failed: %s", 514 CRYPT_CONFFILE, strerror(errno)); 515 goto cleanup; 516 } 517 518 /* 519 * Check the ownership of the file 520 */ 521 if (stb.st_uid != (uid_t)0) { 522 syslog(LOG_ALERT, 523 "crypt: Owner of %s is not root", CRYPT_CONFFILE); 524 goto cleanup; 525 } 526 527 /* 528 * Check the modes on the file 529 */ 530 if (stb.st_mode & S_IWGRP) { 531 syslog(LOG_ALERT, 532 "crypt: %s writable by group", CRYPT_CONFFILE); 533 goto cleanup; 534 } 535 if (stb.st_mode & S_IWOTH) { 536 syslog(LOG_ALERT, 537 "crypt: %s writable by world", CRYPT_CONFFILE); 538 goto cleanup; 539 } 540 541 if ((fconf = fdopen(configfd, "rF")) == NULL) { 542 syslog(LOG_ALERT, "crypt: fdopen(%d) failed: %s", 543 configfd, strerror(errno)); 544 goto cleanup; 545 } 546 547 /* 548 * /etc/security/crypt.conf has 3 fields: 549 * <algname> <pathname> [<name[=val]>[<name[=val]>]] 550 */ 551 errno = 0; 552 while (!(*found) && 553 ((fgets(line, sizeof (line), fconf) != NULL) && !feof(fconf))) { 554 lineno++; 555 /* 556 * Skip over comments 557 */ 558 if ((line[0] == '#') || (line[0] == '\n')) { 559 continue; 560 } 561 562 linelen = strlen(line); 563 line[--linelen] = '\0'; /* chop the trailing \n */ 564 565 token = strtok_r(line, " \t", &lasts); 566 if (token == NULL) { 567 continue; 568 } 569 if (strcmp(token, algname) == 0) { 570 *found = B_TRUE; 571 } 572 } 573 if (!found) { 574 errno = EINVAL; 575 goto cleanup; 576 } 577 578 token = strtok_r(NULL, " \t", &lasts); 579 if (token == NULL) { 580 /* 581 * Broken config file 582 */ 583 syslog(LOG_ALERT, "crypt(3c): %s may be corrupt at line %d", 584 CRYPT_CONFFILE, lineno); 585 *found = B_FALSE; 586 errno = EINVAL; 587 goto cleanup; 588 } 589 590 if ((pathname = isa_path(token)) == NULL) { 591 if (errno != ENOMEM) 592 errno = EINVAL; 593 *found = B_FALSE; 594 goto cleanup; 595 } 596 597 if ((alg = malloc(sizeof (struct crypt_alg_s))) == NULL) { 598 *found = B_FALSE; 599 goto cleanup; 600 } 601 alg->a_libhandle = NULL; 602 alg->a_genhash = NULL; 603 alg->a_gensalt = NULL; 604 alg->a_params = NULL; 605 alg->a_nparams = 0; 606 607 /* 608 * The rest of the line is module specific params, space 609 * seprated. We wait until after we have checked the module is 610 * valid before parsing them into a_params, this saves us 611 * having to free them later if there is a problem. 612 */ 613 if ((alg->a_libhandle = dlopen(pathname, RTLD_NOW)) == NULL) { 614 syslog(LOG_ERR, "crypt(3c) unable to dlopen %s: %s", 615 pathname, dlerror()); 616 errno = ELIBACC; 617 *found = B_FALSE; 618 goto cleanup; 619 } 620 621 alg->a_genhash = 622 (char *(*)())dlsym(alg->a_libhandle, "crypt_genhash_impl"); 623 if (alg->a_genhash == NULL) { 624 syslog(LOG_ERR, "crypt(3c) unable to find cryp_genhash_impl" 625 "symbol in %s: %s", pathname, dlerror()); 626 errno = ELIBACC; 627 *found = B_FALSE; 628 goto cleanup; 629 } 630 alg->a_gensalt = 631 (char *(*)())dlsym(alg->a_libhandle, "crypt_gensalt_impl"); 632 if (alg->a_gensalt == NULL) { 633 syslog(LOG_ERR, "crypt(3c) unable to find crypt_gensalt_impl" 634 "symbol in %s: %s", pathname, dlerror()); 635 errno = ELIBACC; 636 *found = B_FALSE; 637 goto cleanup; 638 } 639 640 /* 641 * We have a good module so build the a_params if we have any. 642 * Count how much space we need first and then allocate an array 643 * to hold that many module params. 644 */ 645 if (lasts != NULL) { 646 int nparams = 0; 647 char *tparams; 648 char *tplasts; 649 650 if ((tparams = strdup(lasts)) == NULL) { 651 *found = B_FALSE; 652 goto cleanup; 653 } 654 655 (void) strtok_r(tparams, " \t", &tplasts); 656 do { 657 nparams++; 658 } while (strtok_r(NULL, " \t", &tplasts) != NULL); 659 free(tparams); 660 661 alg->a_params = calloc(nparams + 1, sizeof (char *)); 662 if (alg->a_params == NULL) { 663 *found = B_FALSE; 664 goto cleanup; 665 } 666 667 while ((token = strtok_r(NULL, " \t", &lasts)) != NULL) { 668 alg->a_params[alg->a_nparams++] = token; 669 } 670 } 671 672 cleanup: 673 if (*found == B_FALSE) { 674 free_crypt_alg(alg); 675 alg = NULL; 676 } 677 678 if (pathname != NULL) { 679 free(pathname); 680 } 681 682 if (fconf != NULL) { 683 (void) fclose(fconf); 684 } else { 685 (void) close(configfd); 686 } 687 688 return (alg); 689 } 690 691 static void 692 free_crypt_alg(struct crypt_alg_s *alg) 693 { 694 if (alg == NULL) 695 return; 696 697 if (alg->a_libhandle != NULL) { 698 (void) dlclose(alg->a_libhandle); 699 } 700 free(alg->a_params); 701 free(alg); 702 } 703 704 static void 705 free_crypt_policy(struct crypt_policy_s *policy) 706 { 707 if (policy == NULL) 708 return; 709 710 if (policy->cp_default != NULL) { 711 bzero(policy->cp_default, strlen(policy->cp_default)); 712 free(policy->cp_default); 713 policy->cp_default = NULL; 714 } 715 716 if (policy->cp_allow != NULL) { 717 bzero(policy->cp_allow, strlen(policy->cp_allow)); 718 free(policy->cp_allow); 719 policy->cp_allow = NULL; 720 } 721 722 if (policy->cp_deny != NULL) { 723 bzero(policy->cp_deny, strlen(policy->cp_deny)); 724 free(policy->cp_deny); 725 policy->cp_deny = NULL; 726 } 727 728 free(policy); 729 } 730 731 732 /* 733 * isa_path - prepend the default dir or patch up the $ISA in path 734 * Caller is responsible for calling free(3c) on the result. 735 */ 736 static char * 737 isa_path(const char *path) 738 { 739 char *ret = NULL; 740 741 if ((path == NULL) || (strlen(path) > PATH_MAX)) { 742 return (NULL); 743 } 744 745 ret = calloc(PATH_MAX, sizeof (char)); 746 747 /* 748 * Module path doesn't start with "/" then prepend 749 * the default search path CRYPT_MODULE_DIR (/usr/lib/security/$ISA) 750 */ 751 if (path[0] != '/') { 752 if (snprintf(ret, PATH_MAX, "%s%s", CRYPT_MODULE_DIR, 753 path) > PATH_MAX) { 754 free(ret); 755 return (NULL); 756 } 757 } else { /* patch up $ISA */ 758 char *isa; 759 760 if ((isa = strstr(path, CRYPT_MODULE_ISA)) != NULL) { 761 *isa = '\0'; 762 isa += strlen(CRYPT_MODULE_ISA); 763 if (snprintf(ret, PATH_MAX, "%s%s%s", path, 764 CRYPT_ISA_DIR, isa) > PATH_MAX) { 765 free(ret); 766 return (NULL); 767 } 768 } else { 769 free(ret); 770 ret = strdup(path); 771 } 772 } 773 774 return (ret); 775 } 776 777 778 /*ARGSUSED*/ 779 static char * 780 _unix_crypt_gensalt(char *gsbuffer, 781 size_t gsbufflen, 782 const char *oldpuresalt, 783 const struct passwd *userinfo, 784 const char *argv[]) 785 { 786 static const char saltchars[] = 787 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 788 struct timeval tv; 789 790 (void) gettimeofday(&tv, (void *) 0); 791 srand48(tv.tv_sec ^ tv.tv_usec); 792 gsbuffer[0] = saltchars[lrand48() % 64]; /* lrand48() is MT-SAFE */ 793 gsbuffer[1] = saltchars[lrand48() % 64]; /* lrand48() is MT-SAFE */ 794 gsbuffer[2] = '\0'; 795 796 return (gsbuffer); 797 } 798 799 /* 800 * The rest of the code below comes from the old crypt.c and is the 801 * implementation of the hardwired/fallback traditional algorithm 802 * It has been otimized to take better advantage of MT features. 803 * 804 * It is included here to reduce the overhead of dlopen() 805 * for the common case. 806 */ 807 808 809 /* Copyright (c) 1988 AT&T */ 810 /* All Rights Reserved */ 811 812 813 814 /* 815 * This program implements a data encryption algorithm to encrypt passwords. 816 */ 817 818 static mutex_t crypt_lock = DEFAULTMUTEX; 819 #define TSDBUFSZ (66 + 16) 820 821 static const char IP[] = { 822 58, 50, 42, 34, 26, 18, 10, 2, 823 60, 52, 44, 36, 28, 20, 12, 4, 824 62, 54, 46, 38, 30, 22, 14, 6, 825 64, 56, 48, 40, 32, 24, 16, 8, 826 57, 49, 41, 33, 25, 17, 9, 1, 827 59, 51, 43, 35, 27, 19, 11, 3, 828 61, 53, 45, 37, 29, 21, 13, 5, 829 63, 55, 47, 39, 31, 23, 15, 7, 830 }; 831 832 static const char FP[] = { 833 40, 8, 48, 16, 56, 24, 64, 32, 834 39, 7, 47, 15, 55, 23, 63, 31, 835 38, 6, 46, 14, 54, 22, 62, 30, 836 37, 5, 45, 13, 53, 21, 61, 29, 837 36, 4, 44, 12, 52, 20, 60, 28, 838 35, 3, 43, 11, 51, 19, 59, 27, 839 34, 2, 42, 10, 50, 18, 58, 26, 840 33, 1, 41, 9, 49, 17, 57, 25, 841 }; 842 843 static const char PC1_C[] = { 844 57, 49, 41, 33, 25, 17, 9, 845 1, 58, 50, 42, 34, 26, 18, 846 10, 2, 59, 51, 43, 35, 27, 847 19, 11, 3, 60, 52, 44, 36, 848 }; 849 850 static const char PC1_D[] = { 851 63, 55, 47, 39, 31, 23, 15, 852 7, 62, 54, 46, 38, 30, 22, 853 14, 6, 61, 53, 45, 37, 29, 854 21, 13, 5, 28, 20, 12, 4, 855 }; 856 857 static const char shifts[] = { 858 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 859 }; 860 861 static const char PC2_C[] = { 862 14, 17, 11, 24, 1, 5, 863 3, 28, 15, 6, 21, 10, 864 23, 19, 12, 4, 26, 8, 865 16, 7, 27, 20, 13, 2, 866 }; 867 868 static const char PC2_D[] = { 869 41, 52, 31, 37, 47, 55, 870 30, 40, 51, 45, 33, 48, 871 44, 49, 39, 56, 34, 53, 872 46, 42, 50, 36, 29, 32, 873 }; 874 875 static char C[28]; 876 static char D[28]; 877 static char *KS; 878 879 static char E[48]; 880 static const char e2[] = { 881 32, 1, 2, 3, 4, 5, 882 4, 5, 6, 7, 8, 9, 883 8, 9, 10, 11, 12, 13, 884 12, 13, 14, 15, 16, 17, 885 16, 17, 18, 19, 20, 21, 886 20, 21, 22, 23, 24, 25, 887 24, 25, 26, 27, 28, 29, 888 28, 29, 30, 31, 32, 1, 889 }; 890 891 /* 892 * The KS array (768 bytes) is allocated once, and only if 893 * one of _unix_crypt(), encrypt() or setkey() is called. 894 * The complexity below is due to the fact that calloc() 895 * must not be called while holding any locks. 896 */ 897 static int 898 allocate_KS(void) 899 { 900 char *ks; 901 int failed; 902 int assigned; 903 904 if (KS != NULL) { /* already allocated */ 905 membar_consumer(); 906 return (0); 907 } 908 909 ks = calloc(16, 48 * sizeof (char)); 910 failed = 0; 911 lmutex_lock(&crypt_lock); 912 if (KS != NULL) { /* someone else got here first */ 913 assigned = 0; 914 } else { 915 assigned = 1; 916 membar_producer(); 917 if ((KS = ks) == NULL) /* calloc() failed */ 918 failed = 1; 919 } 920 lmutex_unlock(&crypt_lock); 921 if (!assigned) 922 free(ks); 923 return (failed); 924 } 925 926 static void 927 unlocked_setkey(const char *key) 928 { 929 int i, j, k; 930 char t; 931 932 for (i = 0; i < 28; i++) { 933 C[i] = key[PC1_C[i]-1]; 934 D[i] = key[PC1_D[i]-1]; 935 } 936 for (i = 0; i < 16; i++) { 937 for (k = 0; k < shifts[i]; k++) { 938 t = C[0]; 939 for (j = 0; j < 28-1; j++) 940 C[j] = C[j+1]; 941 C[27] = t; 942 t = D[0]; 943 for (j = 0; j < 28-1; j++) 944 D[j] = D[j+1]; 945 D[27] = t; 946 } 947 for (j = 0; j < 24; j++) { 948 int index = i * 48; 949 950 *(KS+index+j) = C[PC2_C[j]-1]; 951 *(KS+index+j+24) = D[PC2_D[j]-28-1]; 952 } 953 } 954 for (i = 0; i < 48; i++) 955 E[i] = e2[i]; 956 } 957 958 static const char S[8][64] = { 959 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 960 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 961 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 962 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, 963 964 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 965 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 966 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 967 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, 968 969 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 970 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 971 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 972 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, 973 974 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 975 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 976 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 977 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, 978 979 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 980 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 981 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 982 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, 983 984 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 985 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 986 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 987 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, 988 989 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 990 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 991 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 992 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, 993 994 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 995 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 996 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 997 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11, 998 }; 999 1000 static const char P[] = { 1001 16, 7, 20, 21, 1002 29, 12, 28, 17, 1003 1, 15, 23, 26, 1004 5, 18, 31, 10, 1005 2, 8, 24, 14, 1006 32, 27, 3, 9, 1007 19, 13, 30, 6, 1008 22, 11, 4, 25, 1009 }; 1010 1011 static char L[64]; 1012 static char tempL[32]; 1013 static char f[32]; 1014 1015 static char preS[48]; 1016 1017 /*ARGSUSED*/ 1018 static void 1019 unlocked_encrypt(char *block, int fake) 1020 { 1021 int i; 1022 int t, j, k; 1023 char *R = &L[32]; 1024 1025 for (j = 0; j < 64; j++) 1026 L[j] = block[IP[j]-1]; 1027 for (i = 0; i < 16; i++) { 1028 int index = i * 48; 1029 1030 for (j = 0; j < 32; j++) 1031 tempL[j] = R[j]; 1032 for (j = 0; j < 48; j++) 1033 preS[j] = R[E[j]-1] ^ *(KS+index+j); 1034 for (j = 0; j < 8; j++) { 1035 t = 6 * j; 1036 k = S[j][(preS[t+0]<<5) + 1037 (preS[t+1]<<3) + 1038 (preS[t+2]<<2) + 1039 (preS[t+3]<<1) + 1040 (preS[t+4]<<0) + 1041 (preS[t+5]<<4)]; 1042 t = 4*j; 1043 f[t+0] = (k>>3)&01; 1044 f[t+1] = (k>>2)&01; 1045 f[t+2] = (k>>1)&01; 1046 f[t+3] = (k>>0)&01; 1047 } 1048 for (j = 0; j < 32; j++) 1049 R[j] = L[j] ^ f[P[j]-1]; 1050 for (j = 0; j < 32; j++) 1051 L[j] = tempL[j]; 1052 } 1053 for (j = 0; j < 32; j++) { 1054 t = L[j]; 1055 L[j] = R[j]; 1056 R[j] = (char)t; 1057 } 1058 for (j = 0; j < 64; j++) 1059 block[j] = L[FP[j]-1]; 1060 } 1061 1062 char * 1063 _unix_crypt(const char *pw, const char *salt, char *iobuf) 1064 { 1065 int c, i, j; 1066 char temp; 1067 char *block; 1068 1069 block = iobuf + 16; 1070 1071 if (iobuf == 0) { 1072 errno = ENOMEM; 1073 return (NULL); 1074 } 1075 if (allocate_KS() != 0) 1076 return (NULL); 1077 lmutex_lock(&crypt_lock); 1078 for (i = 0; i < 66; i++) 1079 block[i] = 0; 1080 for (i = 0; (c = *pw) != '\0' && i < 64; pw++) { 1081 for (j = 0; j < 7; j++, i++) 1082 block[i] = (c>>(6-j)) & 01; 1083 i++; 1084 } 1085 1086 unlocked_setkey(block); 1087 1088 for (i = 0; i < 66; i++) 1089 block[i] = 0; 1090 1091 for (i = 0; i < 2; i++) { 1092 c = *salt++; 1093 iobuf[i] = (char)c; 1094 if (c > 'Z') 1095 c -= 6; 1096 if (c > '9') 1097 c -= 7; 1098 c -= '.'; 1099 for (j = 0; j < 6; j++) { 1100 if ((c>>j) & 01) { 1101 temp = E[6*i+j]; 1102 E[6*i+j] = E[6*i+j+24]; 1103 E[6*i+j+24] = temp; 1104 } 1105 } 1106 } 1107 1108 for (i = 0; i < 25; i++) 1109 unlocked_encrypt(block, 0); 1110 1111 lmutex_unlock(&crypt_lock); 1112 for (i = 0; i < 11; i++) { 1113 c = 0; 1114 for (j = 0; j < 6; j++) { 1115 c <<= 1; 1116 c |= block[6*i+j]; 1117 } 1118 c += '.'; 1119 if (c > '9') 1120 c += 7; 1121 if (c > 'Z') 1122 c += 6; 1123 iobuf[i+2] = (char)c; 1124 } 1125 iobuf[i+2] = 0; 1126 if (iobuf[1] == 0) 1127 iobuf[1] = iobuf[0]; 1128 return (iobuf); 1129 } 1130 1131 1132 /*ARGSUSED*/ 1133 void 1134 encrypt(char *block, int fake) 1135 { 1136 if (fake != 0) { 1137 errno = ENOSYS; 1138 return; 1139 } 1140 if (allocate_KS() != 0) 1141 return; 1142 lmutex_lock(&crypt_lock); 1143 unlocked_encrypt(block, fake); 1144 lmutex_unlock(&crypt_lock); 1145 } 1146 1147 1148 void 1149 setkey(const char *key) 1150 { 1151 if (allocate_KS() != 0) 1152 return; 1153 lmutex_lock(&crypt_lock); 1154 unlocked_setkey(key); 1155 lmutex_unlock(&crypt_lock); 1156 } 1157