xref: /titanic_44/usr/src/lib/libc/port/gen/crypt.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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