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