xref: /illumos-gate/usr/src/lib/libc/port/gen/crypt.c (revision 4a38094c)
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(5) 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(5) 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(5) 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(5) 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 	free(alg->a_params);
701 	free(alg);
702 }
703 
704 static void
free_crypt_policy(struct crypt_policy_s * policy)705 free_crypt_policy(struct crypt_policy_s *policy)
706 {
707 	if (policy == NULL)
708 		return;
709 
710 	if (policy->cp_default != NULL) {
711 		bzero(policy->cp_default, strlen(policy->cp_default));
712 		free(policy->cp_default);
713 		policy->cp_default = NULL;
714 	}
715 
716 	if (policy->cp_allow != NULL) {
717 		bzero(policy->cp_allow, strlen(policy->cp_allow));
718 		free(policy->cp_allow);
719 		policy->cp_allow = NULL;
720 	}
721 
722 	if (policy->cp_deny != NULL) {
723 		bzero(policy->cp_deny, strlen(policy->cp_deny));
724 		free(policy->cp_deny);
725 		policy->cp_deny = NULL;
726 	}
727 
728 	free(policy);
729 }
730 
731 
732 /*
733  * isa_path - prepend the default dir or patch up the $ISA in path
734  *	Caller is responsible for calling free(3c) on the result.
735  */
736 static char *
isa_path(const char * path)737 isa_path(const char *path)
738 {
739 	char *ret = NULL;
740 
741 	if ((path == NULL) || (strlen(path) > PATH_MAX)) {
742 		return (NULL);
743 	}
744 
745 	ret = calloc(PATH_MAX, sizeof (char));
746 
747 	/*
748 	 * Module path doesn't start with "/" then prepend
749 	 * the default search path CRYPT_MODULE_DIR (/usr/lib/security/$ISA)
750 	 */
751 	if (path[0] != '/') {
752 		if (snprintf(ret, PATH_MAX, "%s%s", CRYPT_MODULE_DIR,
753 		    path) > PATH_MAX) {
754 			free(ret);
755 			return (NULL);
756 		}
757 	} else { /* patch up $ISA */
758 		char *isa;
759 
760 		if ((isa = strstr(path, CRYPT_MODULE_ISA)) != NULL) {
761 			*isa = '\0';
762 			isa += strlen(CRYPT_MODULE_ISA);
763 			if (snprintf(ret, PATH_MAX, "%s%s%s", path,
764 			    CRYPT_ISA_DIR, isa) > PATH_MAX) {
765 				free(ret);
766 				return (NULL);
767 			}
768 		} else {
769 			free(ret);
770 			ret = strdup(path);
771 		}
772 	}
773 
774 	return (ret);
775 }
776 
777 
778 static char *
_unix_crypt_gensalt(char * gsbuffer,size_t gsbufflen __unused,const char * oldpuresalt __unused,const struct passwd * userinfo __unused,const char * argv[]__unused)779 _unix_crypt_gensalt(char *gsbuffer,
780     size_t gsbufflen __unused,
781     const char *oldpuresalt __unused,
782     const struct passwd *userinfo __unused,
783     const char *argv[] __unused)
784 {
785 	static const char saltchars[] =
786 	    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
787 	struct timeval tv;
788 
789 	(void) gettimeofday(&tv, (void *) 0);
790 	srand48(tv.tv_sec ^ tv.tv_usec);
791 	gsbuffer[0] = saltchars[lrand48() % 64]; /* lrand48() is MT-SAFE */
792 	gsbuffer[1] = saltchars[lrand48() % 64]; /* lrand48() is MT-SAFE */
793 	gsbuffer[2] = '\0';
794 
795 	return (gsbuffer);
796 }
797 
798 /*
799  * The rest of the code below comes from the old crypt.c and is the
800  * implementation of the hardwired/fallback traditional algorithm
801  * It has been otimized to take better advantage of MT features.
802  *
803  * It is included here to reduce the overhead of dlopen()
804  * for the common case.
805  */
806 
807 
808 /*	Copyright (c) 1988 AT&T	*/
809 /*	  All Rights Reserved	*/
810 
811 
812 
813 /*
814  * This program implements a data encryption algorithm to encrypt passwords.
815  */
816 
817 static mutex_t crypt_lock = DEFAULTMUTEX;
818 #define	TSDBUFSZ	(66 + 16)
819 
820 static const char IP[] = {
821 	58, 50, 42, 34, 26, 18, 10, 2,
822 	60, 52, 44, 36, 28, 20, 12, 4,
823 	62, 54, 46, 38, 30, 22, 14, 6,
824 	64, 56, 48, 40, 32, 24, 16, 8,
825 	57, 49, 41, 33, 25, 17, 9, 1,
826 	59, 51, 43, 35, 27, 19, 11, 3,
827 	61, 53, 45, 37, 29, 21, 13, 5,
828 	63, 55, 47, 39, 31, 23, 15, 7,
829 };
830 
831 static const char FP[] = {
832 	40, 8, 48, 16, 56, 24, 64, 32,
833 	39, 7, 47, 15,  55, 23, 63, 31,
834 	38, 6, 46, 14, 54, 22, 62, 30,
835 	37, 5, 45, 13, 53, 21, 61, 29,
836 	36, 4, 44, 12, 52, 20, 60, 28,
837 	35, 3, 43, 11, 51, 19, 59, 27,
838 	34, 2, 42, 10, 50, 18, 58, 26,
839 	33, 1, 41, 9, 49, 17, 57, 25,
840 };
841 
842 static const char PC1_C[] = {
843 	57, 49, 41, 33, 25, 17, 9,
844 	1, 58, 50, 42, 34, 26, 18,
845 	10, 2, 59, 51, 43, 35, 27,
846 	19, 11, 3, 60, 52, 44, 36,
847 };
848 
849 static const char PC1_D[] = {
850 	63, 55, 47, 39, 31, 23, 15,
851 	7, 62, 54, 46, 38, 30, 22,
852 	14, 6, 61, 53, 45, 37, 29,
853 	21, 13, 5, 28, 20, 12, 4,
854 };
855 
856 static const char shifts[] = {
857 	1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,
858 };
859 
860 static const char PC2_C[] = {
861 	14, 17, 11, 24, 1, 5,
862 	3, 28, 15, 6, 21, 10,
863 	23, 19, 12, 4, 26, 8,
864 	16, 7, 27, 20, 13, 2,
865 };
866 
867 static const char PC2_D[] = {
868 	41, 52, 31, 37, 47, 55,
869 	30, 40, 51, 45, 33, 48,
870 	44, 49, 39, 56, 34, 53,
871 	46, 42, 50, 36, 29, 32,
872 };
873 
874 static char C[28];
875 static char D[28];
876 static char *KS;
877 
878 static char E[48];
879 static const char e2[] = {
880 	32, 1, 2, 3, 4, 5,
881 	4, 5, 6, 7, 8, 9,
882 	8, 9, 10, 11, 12, 13,
883 	12, 13, 14, 15, 16, 17,
884 	16, 17, 18, 19, 20, 21,
885 	20, 21, 22, 23, 24, 25,
886 	24, 25, 26, 27, 28, 29,
887 	28, 29, 30, 31, 32, 1,
888 };
889 
890 /*
891  * The KS array (768 bytes) is allocated once, and only if
892  * one of _unix_crypt(), encrypt() or setkey() is called.
893  * The complexity below is due to the fact that calloc()
894  * must not be called while holding any locks.
895  */
896 static int
allocate_KS(void)897 allocate_KS(void)
898 {
899 	char *ks;
900 	int failed;
901 	int assigned;
902 
903 	if (KS != NULL) {		/* already allocated */
904 		membar_consumer();
905 		return (0);
906 	}
907 
908 	ks = calloc(16, 48 * sizeof (char));
909 	failed = 0;
910 	lmutex_lock(&crypt_lock);
911 	if (KS != NULL) {	/* someone else got here first */
912 		assigned = 0;
913 	} else {
914 		assigned = 1;
915 		membar_producer();
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
unlocked_setkey(const char * key)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 static void
unlocked_encrypt(char * block,int fake __unused)1017 unlocked_encrypt(char *block, int fake __unused)
1018 {
1019 	int	i;
1020 	int t, j, k;
1021 	char *R = &L[32];
1022 
1023 	for (j = 0; j < 64; j++)
1024 		L[j] = block[IP[j]-1];
1025 	for (i = 0; i < 16; i++) {
1026 		int index = i * 48;
1027 
1028 		for (j = 0; j < 32; j++)
1029 			tempL[j] = R[j];
1030 		for (j = 0; j < 48; j++)
1031 			preS[j] = R[E[j]-1] ^ *(KS+index+j);
1032 		for (j = 0; j < 8; j++) {
1033 			t = 6 * j;
1034 			k = S[j][(preS[t+0]<<5) +
1035 			    (preS[t+1]<<3) +
1036 			    (preS[t+2]<<2) +
1037 			    (preS[t+3]<<1) +
1038 			    (preS[t+4]<<0) +
1039 			    (preS[t+5]<<4)];
1040 			t = 4*j;
1041 			f[t+0] = (k>>3)&01;
1042 			f[t+1] = (k>>2)&01;
1043 			f[t+2] = (k>>1)&01;
1044 			f[t+3] = (k>>0)&01;
1045 		}
1046 		for (j = 0; j < 32; j++)
1047 			R[j] = L[j] ^ f[P[j]-1];
1048 		for (j = 0; j < 32; j++)
1049 			L[j] = tempL[j];
1050 	}
1051 	for (j = 0; j < 32; j++) {
1052 		t = L[j];
1053 		L[j] = R[j];
1054 		R[j] = (char)t;
1055 	}
1056 	for (j = 0; j < 64; j++)
1057 		block[j] = L[FP[j]-1];
1058 }
1059 
1060 char *
_unix_crypt(const char * pw,const char * salt,char * iobuf)1061 _unix_crypt(const char *pw, const char *salt, char *iobuf)
1062 {
1063 	int c, i, j;
1064 	char temp;
1065 	char *block;
1066 
1067 	block = iobuf + 16;
1068 
1069 	if (iobuf == 0) {
1070 		errno = ENOMEM;
1071 		return (NULL);
1072 	}
1073 	if (allocate_KS() != 0)
1074 		return (NULL);
1075 	lmutex_lock(&crypt_lock);
1076 	for (i = 0; i < 66; i++)
1077 		block[i] = 0;
1078 	for (i = 0; (c = *pw) != '\0' && i < 64; pw++) {
1079 		for (j = 0; j < 7; j++, i++)
1080 			block[i] = (c>>(6-j)) & 01;
1081 		i++;
1082 	}
1083 
1084 	unlocked_setkey(block);
1085 
1086 	for (i = 0; i < 66; i++)
1087 		block[i] = 0;
1088 
1089 	for (i = 0; i < 2; i++) {
1090 		c = *salt++;
1091 		iobuf[i] = (char)c;
1092 		if (c > 'Z')
1093 			c -= 6;
1094 		if (c > '9')
1095 			c -= 7;
1096 		c -= '.';
1097 		for (j = 0; j < 6; j++) {
1098 			if ((c>>j) & 01) {
1099 				temp = E[6*i+j];
1100 				E[6*i+j] = E[6*i+j+24];
1101 				E[6*i+j+24] = temp;
1102 			}
1103 		}
1104 	}
1105 
1106 	for (i = 0; i < 25; i++)
1107 		unlocked_encrypt(block, 0);
1108 
1109 	lmutex_unlock(&crypt_lock);
1110 	for (i = 0; i < 11; i++) {
1111 		c = 0;
1112 		for (j = 0; j < 6; j++) {
1113 			c <<= 1;
1114 			c |= block[6*i+j];
1115 		}
1116 		c += '.';
1117 		if (c > '9')
1118 			c += 7;
1119 		if (c > 'Z')
1120 			c += 6;
1121 		iobuf[i+2] = (char)c;
1122 	}
1123 	iobuf[i+2] = 0;
1124 	if (iobuf[1] == 0)
1125 		iobuf[1] = iobuf[0];
1126 	return (iobuf);
1127 }
1128 
1129 
1130 /*ARGSUSED*/
1131 void
encrypt(char * block,int fake)1132 encrypt(char *block, int fake)
1133 {
1134 	if (fake != 0) {
1135 		errno = ENOSYS;
1136 		return;
1137 	}
1138 	if (allocate_KS() != 0)
1139 		return;
1140 	lmutex_lock(&crypt_lock);
1141 	unlocked_encrypt(block, fake);
1142 	lmutex_unlock(&crypt_lock);
1143 }
1144 
1145 
1146 void
setkey(const char * key)1147 setkey(const char *key)
1148 {
1149 	if (allocate_KS() != 0)
1150 		return;
1151 	lmutex_lock(&crypt_lock);
1152 	unlocked_setkey(key);
1153 	lmutex_unlock(&crypt_lock);
1154 }
1155