1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #pragma weak crypt = _crypt 29 #pragma weak encrypt = _encrypt 30 #pragma weak setkey = _setkey 31 32 #include "synonyms.h" 33 #include "mtlib.h" 34 #include <synch.h> 35 #include <thread.h> 36 #include <ctype.h> 37 #include <dlfcn.h> 38 #include <errno.h> 39 #include <stdio.h> 40 #include <strings.h> 41 #include <stdlib.h> 42 #include <sys/time.h> 43 #include <limits.h> 44 #include <sys/types.h> 45 #include <sys/stat.h> 46 #include <fcntl.h> 47 #include <syslog.h> 48 #include <unistd.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 if (alg->a_nparams != NULL) { 701 free(alg->a_params); 702 } 703 free(alg); 704 } 705 706 static void 707 free_crypt_policy(struct crypt_policy_s *policy) 708 { 709 if (policy == NULL) 710 return; 711 712 if (policy->cp_default != NULL) { 713 bzero(policy->cp_default, strlen(policy->cp_default)); 714 free(policy->cp_default); 715 policy->cp_default = NULL; 716 } 717 718 if (policy->cp_allow != NULL) { 719 bzero(policy->cp_allow, strlen(policy->cp_allow)); 720 free(policy->cp_allow); 721 policy->cp_allow = NULL; 722 } 723 724 if (policy->cp_deny != NULL) { 725 bzero(policy->cp_deny, strlen(policy->cp_deny)); 726 free(policy->cp_deny); 727 policy->cp_deny = NULL; 728 } 729 730 free(policy); 731 } 732 733 734 /* 735 * isa_path - prepend the default dir or patch up the $ISA in path 736 * Caller is responsible for calling free(3c) on the result. 737 */ 738 static char * 739 isa_path(const char *path) 740 { 741 char *ret = NULL; 742 743 if ((path == NULL) || (strlen(path) > PATH_MAX)) { 744 return (NULL); 745 } 746 747 ret = calloc(PATH_MAX, sizeof (char)); 748 749 /* 750 * Module path doesn't start with "/" then prepend 751 * the default search path CRYPT_MODULE_DIR (/usr/lib/security/$ISA) 752 */ 753 if (path[0] != '/') { 754 if (snprintf(ret, PATH_MAX, "%s%s", CRYPT_MODULE_DIR, 755 path) > PATH_MAX) { 756 free(ret); 757 return (NULL); 758 } 759 } else { /* patch up $ISA */ 760 char *isa; 761 762 if ((isa = strstr(path, CRYPT_MODULE_ISA)) != NULL) { 763 *isa = '\0'; 764 isa += strlen(CRYPT_MODULE_ISA); 765 if (snprintf(ret, PATH_MAX, "%s%s%s", path, 766 CRYPT_ISA_DIR, isa) > PATH_MAX) { 767 free(ret); 768 return (NULL); 769 } 770 } else { 771 free(ret); 772 ret = strdup(path); 773 } 774 } 775 776 return (ret); 777 } 778 779 780 /*ARGSUSED*/ 781 static char * 782 _unix_crypt_gensalt(char *gsbuffer, 783 size_t gsbufflen, 784 const char *oldpuresalt, 785 const struct passwd *userinfo, 786 const char *argv[]) 787 { 788 static const char saltchars[] = 789 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 790 struct timeval tv; 791 792 gettimeofday(&tv, (void *) 0); 793 srand48(tv.tv_sec ^ tv.tv_usec); 794 gsbuffer[0] = saltchars[lrand48() % 64]; /* lrand48() is MT-SAFE */ 795 gsbuffer[1] = saltchars[lrand48() % 64]; /* lrand48() is MT-SAFE */ 796 gsbuffer[2] = '\0'; 797 798 return (gsbuffer); 799 } 800 801 /* 802 * The rest of the code below comes from the old crypt.c and is the 803 * implementation of the hardwired/fallback traditional algorithm 804 * It has been otimized to take better advantage of MT features. 805 * 806 * It is included here to reduce the overhead of dlopen() 807 * for the common case. 808 */ 809 810 811 /* Copyright (c) 1988 AT&T */ 812 /* All Rights Reserved */ 813 814 815 816 /* 817 * This program implements a data encryption algorithm to encrypt passwords. 818 */ 819 820 static mutex_t crypt_lock = DEFAULTMUTEX; 821 #define TSDBUFSZ (66 + 16) 822 823 static const char IP[] = { 824 58, 50, 42, 34, 26, 18, 10, 2, 825 60, 52, 44, 36, 28, 20, 12, 4, 826 62, 54, 46, 38, 30, 22, 14, 6, 827 64, 56, 48, 40, 32, 24, 16, 8, 828 57, 49, 41, 33, 25, 17, 9, 1, 829 59, 51, 43, 35, 27, 19, 11, 3, 830 61, 53, 45, 37, 29, 21, 13, 5, 831 63, 55, 47, 39, 31, 23, 15, 7, 832 }; 833 834 static const char FP[] = { 835 40, 8, 48, 16, 56, 24, 64, 32, 836 39, 7, 47, 15, 55, 23, 63, 31, 837 38, 6, 46, 14, 54, 22, 62, 30, 838 37, 5, 45, 13, 53, 21, 61, 29, 839 36, 4, 44, 12, 52, 20, 60, 28, 840 35, 3, 43, 11, 51, 19, 59, 27, 841 34, 2, 42, 10, 50, 18, 58, 26, 842 33, 1, 41, 9, 49, 17, 57, 25, 843 }; 844 845 static const char PC1_C[] = { 846 57, 49, 41, 33, 25, 17, 9, 847 1, 58, 50, 42, 34, 26, 18, 848 10, 2, 59, 51, 43, 35, 27, 849 19, 11, 3, 60, 52, 44, 36, 850 }; 851 852 static const char PC1_D[] = { 853 63, 55, 47, 39, 31, 23, 15, 854 7, 62, 54, 46, 38, 30, 22, 855 14, 6, 61, 53, 45, 37, 29, 856 21, 13, 5, 28, 20, 12, 4, 857 }; 858 859 static const char shifts[] = { 860 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 861 }; 862 863 static const char PC2_C[] = { 864 14, 17, 11, 24, 1, 5, 865 3, 28, 15, 6, 21, 10, 866 23, 19, 12, 4, 26, 8, 867 16, 7, 27, 20, 13, 2, 868 }; 869 870 static const char PC2_D[] = { 871 41, 52, 31, 37, 47, 55, 872 30, 40, 51, 45, 33, 48, 873 44, 49, 39, 56, 34, 53, 874 46, 42, 50, 36, 29, 32, 875 }; 876 877 static char C[28]; 878 static char D[28]; 879 static char *KS; 880 881 static char E[48]; 882 static const char e2[] = { 883 32, 1, 2, 3, 4, 5, 884 4, 5, 6, 7, 8, 9, 885 8, 9, 10, 11, 12, 13, 886 12, 13, 14, 15, 16, 17, 887 16, 17, 18, 19, 20, 21, 888 20, 21, 22, 23, 24, 25, 889 24, 25, 26, 27, 28, 29, 890 28, 29, 30, 31, 32, 1, 891 }; 892 893 /* 894 * The KS array (768 bytes) is allocated once, and only if 895 * one of _unix_crypt(), encrypt() or setkey() is called. 896 * The complexity below is due to the fact that calloc() 897 * must not be called while holding any locks. 898 */ 899 static int 900 allocate_KS(void) 901 { 902 char *ks; 903 int failed; 904 int assigned; 905 906 if (KS != NULL) /* already allocated */ 907 return (0); 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 if ((KS = ks) == NULL) /* calloc() failed */ 917 failed = 1; 918 } 919 lmutex_unlock(&crypt_lock); 920 if (!assigned) 921 free(ks); 922 return (failed); 923 } 924 925 static void 926 unlocked_setkey(const char *key) 927 { 928 int i, j, k; 929 char t; 930 931 for (i = 0; i < 28; i++) { 932 C[i] = key[PC1_C[i]-1]; 933 D[i] = key[PC1_D[i]-1]; 934 } 935 for (i = 0; i < 16; i++) { 936 for (k = 0; k < shifts[i]; k++) { 937 t = C[0]; 938 for (j = 0; j < 28-1; j++) 939 C[j] = C[j+1]; 940 C[27] = t; 941 t = D[0]; 942 for (j = 0; j < 28-1; j++) 943 D[j] = D[j+1]; 944 D[27] = t; 945 } 946 for (j = 0; j < 24; j++) { 947 int index = i * 48; 948 949 *(KS+index+j) = C[PC2_C[j]-1]; 950 *(KS+index+j+24) = D[PC2_D[j]-28-1]; 951 } 952 } 953 for (i = 0; i < 48; i++) 954 E[i] = e2[i]; 955 } 956 957 static const char S[8][64] = { 958 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 959 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 960 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 961 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, 962 963 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 964 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 965 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 966 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, 967 968 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 969 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 970 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 971 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, 972 973 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 974 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 975 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 976 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, 977 978 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 979 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 980 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 981 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, 982 983 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 984 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 985 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 986 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, 987 988 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 989 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 990 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 991 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, 992 993 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 994 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 995 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 996 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11, 997 }; 998 999 static const char P[] = { 1000 16, 7, 20, 21, 1001 29, 12, 28, 17, 1002 1, 15, 23, 26, 1003 5, 18, 31, 10, 1004 2, 8, 24, 14, 1005 32, 27, 3, 9, 1006 19, 13, 30, 6, 1007 22, 11, 4, 25, 1008 }; 1009 1010 static char L[64]; 1011 static char tempL[32]; 1012 static char f[32]; 1013 1014 static char preS[48]; 1015 1016 /*ARGSUSED*/ 1017 static void 1018 unlocked_encrypt(char *block, int fake) 1019 { 1020 int i; 1021 int t, j, k; 1022 char *R = &L[32]; 1023 1024 for (j = 0; j < 64; j++) 1025 L[j] = block[IP[j]-1]; 1026 for (i = 0; i < 16; i++) { 1027 int index = i * 48; 1028 1029 for (j = 0; j < 32; j++) 1030 tempL[j] = R[j]; 1031 for (j = 0; j < 48; j++) 1032 preS[j] = R[E[j]-1] ^ *(KS+index+j); 1033 for (j = 0; j < 8; j++) { 1034 t = 6 * j; 1035 k = S[j][(preS[t+0]<<5)+ 1036 (preS[t+1]<<3)+ 1037 (preS[t+2]<<2)+ 1038 (preS[t+3]<<1)+ 1039 (preS[t+4]<<0)+ 1040 (preS[t+5]<<4)]; 1041 t = 4*j; 1042 f[t+0] = (k>>3)&01; 1043 f[t+1] = (k>>2)&01; 1044 f[t+2] = (k>>1)&01; 1045 f[t+3] = (k>>0)&01; 1046 } 1047 for (j = 0; j < 32; j++) 1048 R[j] = L[j] ^ f[P[j]-1]; 1049 for (j = 0; j < 32; j++) 1050 L[j] = tempL[j]; 1051 } 1052 for (j = 0; j < 32; j++) { 1053 t = L[j]; 1054 L[j] = R[j]; 1055 R[j] = (char)t; 1056 } 1057 for (j = 0; j < 64; j++) 1058 block[j] = L[FP[j]-1]; 1059 } 1060 1061 char * 1062 _unix_crypt(const char *pw, const char *salt, char *iobuf) 1063 { 1064 int c, i, j; 1065 char temp; 1066 char *block; 1067 1068 block = iobuf + 16; 1069 1070 if (iobuf == 0) { 1071 errno = ENOMEM; 1072 return (NULL); 1073 } 1074 if (allocate_KS() != 0) 1075 return (NULL); 1076 lmutex_lock(&crypt_lock); 1077 for (i = 0; i < 66; i++) 1078 block[i] = 0; 1079 for (i = 0; (c = *pw) != '\0' && i < 64; pw++) { 1080 for (j = 0; j < 7; j++, i++) 1081 block[i] = (c>>(6-j)) & 01; 1082 i++; 1083 } 1084 1085 unlocked_setkey(block); 1086 1087 for (i = 0; i < 66; i++) 1088 block[i] = 0; 1089 1090 for (i = 0; i < 2; i++) { 1091 c = *salt++; 1092 iobuf[i] = (char)c; 1093 if (c > 'Z') 1094 c -= 6; 1095 if (c > '9') 1096 c -= 7; 1097 c -= '.'; 1098 for (j = 0; j < 6; j++) { 1099 if ((c>>j) & 01) { 1100 temp = E[6*i+j]; 1101 E[6*i+j] = E[6*i+j+24]; 1102 E[6*i+j+24] = temp; 1103 } 1104 } 1105 } 1106 1107 for (i = 0; i < 25; i++) 1108 unlocked_encrypt(block, 0); 1109 1110 lmutex_unlock(&crypt_lock); 1111 for (i = 0; i < 11; i++) { 1112 c = 0; 1113 for (j = 0; j < 6; j++) { 1114 c <<= 1; 1115 c |= block[6*i+j]; 1116 } 1117 c += '.'; 1118 if (c > '9') 1119 c += 7; 1120 if (c > 'Z') 1121 c += 6; 1122 iobuf[i+2] = (char)c; 1123 } 1124 iobuf[i+2] = 0; 1125 if (iobuf[1] == 0) 1126 iobuf[1] = iobuf[0]; 1127 return (iobuf); 1128 } 1129 1130 1131 /*ARGSUSED*/ 1132 void 1133 encrypt(char *block, int fake) 1134 { 1135 if (fake != 0) { 1136 errno = ENOSYS; 1137 return; 1138 } 1139 if (allocate_KS() != 0) 1140 return; 1141 lmutex_lock(&crypt_lock); 1142 unlocked_encrypt(block, fake); 1143 lmutex_unlock(&crypt_lock); 1144 } 1145 1146 1147 void 1148 setkey(const char *key) 1149 { 1150 if (allocate_KS() != 0) 1151 return; 1152 lmutex_lock(&crypt_lock); 1153 unlocked_setkey(key); 1154 lmutex_unlock(&crypt_lock); 1155 } 1156