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