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 *
crypt(const char * plaintext,const char * salt)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 *
crypt_gensalt(const char * oldsalt,const struct passwd * userinfo)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 *
getalgfromsalt(const char * salt)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
log_invalid_policy(enum crypt_policy_error_e error,char * value)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 *
getval(const char * ival)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 *
getcryptpolicy(void)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
alg_valid(const char * algname,const struct crypt_policy_s * policy)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 *
getalgbyname(const char * algname,boolean_t * found)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
free_crypt_alg(struct crypt_alg_s * alg)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
free_crypt_policy(struct crypt_policy_s * policy)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 *
isa_path(const char * path)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 *
_unix_crypt_gensalt(char * gsbuffer,size_t gsbufflen,const char * oldpuresalt,const struct passwd * userinfo,const char * argv[])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 (void) 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
allocate_KS(void)900 allocate_KS(void)
901 {
902 char *ks;
903 int failed;
904 int assigned;
905
906 if (KS != NULL) { /* already allocated */
907 membar_consumer();
908 return (0);
909 }
910
911 ks = calloc(16, 48 * sizeof (char));
912 failed = 0;
913 lmutex_lock(&crypt_lock);
914 if (KS != NULL) { /* someone else got here first */
915 assigned = 0;
916 } else {
917 assigned = 1;
918 membar_producer();
919 if ((KS = ks) == NULL) /* calloc() failed */
920 failed = 1;
921 }
922 lmutex_unlock(&crypt_lock);
923 if (!assigned)
924 free(ks);
925 return (failed);
926 }
927
928 static void
unlocked_setkey(const char * key)929 unlocked_setkey(const char *key)
930 {
931 int i, j, k;
932 char t;
933
934 for (i = 0; i < 28; i++) {
935 C[i] = key[PC1_C[i]-1];
936 D[i] = key[PC1_D[i]-1];
937 }
938 for (i = 0; i < 16; i++) {
939 for (k = 0; k < shifts[i]; k++) {
940 t = C[0];
941 for (j = 0; j < 28-1; j++)
942 C[j] = C[j+1];
943 C[27] = t;
944 t = D[0];
945 for (j = 0; j < 28-1; j++)
946 D[j] = D[j+1];
947 D[27] = t;
948 }
949 for (j = 0; j < 24; j++) {
950 int index = i * 48;
951
952 *(KS+index+j) = C[PC2_C[j]-1];
953 *(KS+index+j+24) = D[PC2_D[j]-28-1];
954 }
955 }
956 for (i = 0; i < 48; i++)
957 E[i] = e2[i];
958 }
959
960 static const char S[8][64] = {
961 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
962 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
963 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
964 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
965
966 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
967 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
968 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
969 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
970
971 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
972 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
973 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
974 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
975
976 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
977 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
978 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
979 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
980
981 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
982 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
983 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
984 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
985
986 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
987 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
988 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
989 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
990
991 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
992 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
993 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
994 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
995
996 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
997 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
998 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
999 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,
1000 };
1001
1002 static const char P[] = {
1003 16, 7, 20, 21,
1004 29, 12, 28, 17,
1005 1, 15, 23, 26,
1006 5, 18, 31, 10,
1007 2, 8, 24, 14,
1008 32, 27, 3, 9,
1009 19, 13, 30, 6,
1010 22, 11, 4, 25,
1011 };
1012
1013 static char L[64];
1014 static char tempL[32];
1015 static char f[32];
1016
1017 static char preS[48];
1018
1019 /*ARGSUSED*/
1020 static void
unlocked_encrypt(char * block,int fake)1021 unlocked_encrypt(char *block, int fake)
1022 {
1023 int i;
1024 int t, j, k;
1025 char *R = &L[32];
1026
1027 for (j = 0; j < 64; j++)
1028 L[j] = block[IP[j]-1];
1029 for (i = 0; i < 16; i++) {
1030 int index = i * 48;
1031
1032 for (j = 0; j < 32; j++)
1033 tempL[j] = R[j];
1034 for (j = 0; j < 48; j++)
1035 preS[j] = R[E[j]-1] ^ *(KS+index+j);
1036 for (j = 0; j < 8; j++) {
1037 t = 6 * j;
1038 k = S[j][(preS[t+0]<<5) +
1039 (preS[t+1]<<3) +
1040 (preS[t+2]<<2) +
1041 (preS[t+3]<<1) +
1042 (preS[t+4]<<0) +
1043 (preS[t+5]<<4)];
1044 t = 4*j;
1045 f[t+0] = (k>>3)&01;
1046 f[t+1] = (k>>2)&01;
1047 f[t+2] = (k>>1)&01;
1048 f[t+3] = (k>>0)&01;
1049 }
1050 for (j = 0; j < 32; j++)
1051 R[j] = L[j] ^ f[P[j]-1];
1052 for (j = 0; j < 32; j++)
1053 L[j] = tempL[j];
1054 }
1055 for (j = 0; j < 32; j++) {
1056 t = L[j];
1057 L[j] = R[j];
1058 R[j] = (char)t;
1059 }
1060 for (j = 0; j < 64; j++)
1061 block[j] = L[FP[j]-1];
1062 }
1063
1064 char *
_unix_crypt(const char * pw,const char * salt,char * iobuf)1065 _unix_crypt(const char *pw, const char *salt, char *iobuf)
1066 {
1067 int c, i, j;
1068 char temp;
1069 char *block;
1070
1071 block = iobuf + 16;
1072
1073 if (iobuf == 0) {
1074 errno = ENOMEM;
1075 return (NULL);
1076 }
1077 if (allocate_KS() != 0)
1078 return (NULL);
1079 lmutex_lock(&crypt_lock);
1080 for (i = 0; i < 66; i++)
1081 block[i] = 0;
1082 for (i = 0; (c = *pw) != '\0' && i < 64; pw++) {
1083 for (j = 0; j < 7; j++, i++)
1084 block[i] = (c>>(6-j)) & 01;
1085 i++;
1086 }
1087
1088 unlocked_setkey(block);
1089
1090 for (i = 0; i < 66; i++)
1091 block[i] = 0;
1092
1093 for (i = 0; i < 2; i++) {
1094 c = *salt++;
1095 iobuf[i] = (char)c;
1096 if (c > 'Z')
1097 c -= 6;
1098 if (c > '9')
1099 c -= 7;
1100 c -= '.';
1101 for (j = 0; j < 6; j++) {
1102 if ((c>>j) & 01) {
1103 temp = E[6*i+j];
1104 E[6*i+j] = E[6*i+j+24];
1105 E[6*i+j+24] = temp;
1106 }
1107 }
1108 }
1109
1110 for (i = 0; i < 25; i++)
1111 unlocked_encrypt(block, 0);
1112
1113 lmutex_unlock(&crypt_lock);
1114 for (i = 0; i < 11; i++) {
1115 c = 0;
1116 for (j = 0; j < 6; j++) {
1117 c <<= 1;
1118 c |= block[6*i+j];
1119 }
1120 c += '.';
1121 if (c > '9')
1122 c += 7;
1123 if (c > 'Z')
1124 c += 6;
1125 iobuf[i+2] = (char)c;
1126 }
1127 iobuf[i+2] = 0;
1128 if (iobuf[1] == 0)
1129 iobuf[1] = iobuf[0];
1130 return (iobuf);
1131 }
1132
1133
1134 /*ARGSUSED*/
1135 void
encrypt(char * block,int fake)1136 encrypt(char *block, int fake)
1137 {
1138 if (fake != 0) {
1139 errno = ENOSYS;
1140 return;
1141 }
1142 if (allocate_KS() != 0)
1143 return;
1144 lmutex_lock(&crypt_lock);
1145 unlocked_encrypt(block, fake);
1146 lmutex_unlock(&crypt_lock);
1147 }
1148
1149
1150 void
setkey(const char * key)1151 setkey(const char *key)
1152 {
1153 if (allocate_KS() != 0)
1154 return;
1155 lmutex_lock(&crypt_lock);
1156 unlocked_setkey(key);
1157 lmutex_unlock(&crypt_lock);
1158 }
1159