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