xref: /freebsd/lib/libpam/modules/pam_unix/pam_unix.c (revision a8b1e59eb28a533a62c0ff287f0d8d8cc18ebbfc)
19a10bb17SJohn Polstra /*-
29a10bb17SJohn Polstra  * Copyright 1998 Juniper Networks, Inc.
39a10bb17SJohn Polstra  * All rights reserved.
4f03a4b81SDag-Erling Smørgrav  * Copyright (c) 2002 Networks Associates Technology, Inc.
5e9cc7b1dSDag-Erling Smørgrav  * All rights reserved.
6e9cc7b1dSDag-Erling Smørgrav  *
7e9cc7b1dSDag-Erling Smørgrav  * Portions of this software was developed for the FreeBSD Project by
8e9cc7b1dSDag-Erling Smørgrav  * ThinkSec AS and NAI Labs, the Security Research Division of Network
9e9cc7b1dSDag-Erling Smørgrav  * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
10e9cc7b1dSDag-Erling Smørgrav  * ("CBOSS"), as part of the DARPA CHATS research program.
119a10bb17SJohn Polstra  *
129a10bb17SJohn Polstra  * Redistribution and use in source and binary forms, with or without
139a10bb17SJohn Polstra  * modification, are permitted provided that the following conditions
149a10bb17SJohn Polstra  * are met:
159a10bb17SJohn Polstra  * 1. Redistributions of source code must retain the above copyright
169a10bb17SJohn Polstra  *    notice, this list of conditions and the following disclaimer.
179a10bb17SJohn Polstra  * 2. Redistributions in binary form must reproduce the above copyright
189a10bb17SJohn Polstra  *    notice, this list of conditions and the following disclaimer in the
199a10bb17SJohn Polstra  *    documentation and/or other materials provided with the distribution.
20e9cc7b1dSDag-Erling Smørgrav  * 3. The name of the author may not be used to endorse or promote
21e9cc7b1dSDag-Erling Smørgrav  *    products derived from this software without specific prior written
22e9cc7b1dSDag-Erling Smørgrav  *    permission.
239a10bb17SJohn Polstra  *
249a10bb17SJohn Polstra  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
259a10bb17SJohn Polstra  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
269a10bb17SJohn Polstra  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
279a10bb17SJohn Polstra  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
289a10bb17SJohn Polstra  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
299a10bb17SJohn Polstra  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
309a10bb17SJohn Polstra  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
319a10bb17SJohn Polstra  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
329a10bb17SJohn Polstra  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
339a10bb17SJohn Polstra  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
349a10bb17SJohn Polstra  * SUCH DAMAGE.
359a10bb17SJohn Polstra  */
369a10bb17SJohn Polstra 
37ceaf33f5SMatthew Dillon #include <sys/cdefs.h>
38ceaf33f5SMatthew Dillon __FBSDID("$FreeBSD$");
39ceaf33f5SMatthew Dillon 
40e9cc7b1dSDag-Erling Smørgrav #include <sys/param.h>
41e9cc7b1dSDag-Erling Smørgrav #include <sys/socket.h>
42d65b34dbSJohn Polstra #include <sys/time.h>
43e9cc7b1dSDag-Erling Smørgrav #include <netinet/in.h>
44e9cc7b1dSDag-Erling Smørgrav #include <arpa/inet.h>
45e9cc7b1dSDag-Erling Smørgrav 
463d55a6c0SMark Murray #ifdef YP
473d55a6c0SMark Murray #include <rpc/rpc.h>
483d55a6c0SMark Murray #include <rpcsvc/yp_prot.h>
493d55a6c0SMark Murray #include <rpcsvc/ypclnt.h>
503d55a6c0SMark Murray #include <rpcsvc/yppasswd.h>
513d55a6c0SMark Murray #endif
52e9cc7b1dSDag-Erling Smørgrav 
53d65b34dbSJohn Polstra #include <login_cap.h>
54e9cc7b1dSDag-Erling Smørgrav #include <netdb.h>
559a10bb17SJohn Polstra #include <pwd.h>
569a10bb17SJohn Polstra #include <stdlib.h>
579a10bb17SJohn Polstra #include <string.h>
58d65b34dbSJohn Polstra #include <stdio.h>
597f28386aSDag-Erling Smørgrav #include <syslog.h>
609a10bb17SJohn Polstra #include <unistd.h>
619a10bb17SJohn Polstra 
623d55a6c0SMark Murray #include <pw_copy.h>
633d55a6c0SMark Murray #include <pw_util.h>
643d55a6c0SMark Murray 
653d55a6c0SMark Murray #ifdef YP
663d55a6c0SMark Murray #include <pw_yp.h>
673d55a6c0SMark Murray #include "yppasswd_private.h"
683d55a6c0SMark Murray #endif
693d55a6c0SMark Murray 
709a10bb17SJohn Polstra #define PAM_SM_AUTH
71d65b34dbSJohn Polstra #define PAM_SM_ACCOUNT
723d55a6c0SMark Murray #define	PAM_SM_SESSION
733d55a6c0SMark Murray #define	PAM_SM_PASSWORD
743d55a6c0SMark Murray 
758c66575dSDag-Erling Smørgrav #include <security/pam_appl.h>
769a10bb17SJohn Polstra #include <security/pam_modules.h>
778c66575dSDag-Erling Smørgrav #include <security/pam_mod_misc.h>
789a10bb17SJohn Polstra 
793d55a6c0SMark Murray #define PASSWORD_HASH		"md5"
801642eb1aSMark Murray #define DEFAULT_WARN		(2L * 7L * 86400L)  /* Two weeks */
818c3ea588SMark Murray #define	SALTSIZE		32
828c3ea588SMark Murray 
838c3ea588SMark Murray static void makesalt(char []);
841642eb1aSMark Murray 
85ac569969SMark Murray static char password_hash[] =		PASSWORD_HASH;
868c3ea588SMark Murray static char colon[] =			":";
87ac569969SMark Murray 
88e9cc7b1dSDag-Erling Smørgrav enum {
89e9cc7b1dSDag-Erling Smørgrav 	PAM_OPT_AUTH_AS_SELF	= PAM_OPT_STD_MAX,
90e9cc7b1dSDag-Erling Smørgrav 	PAM_OPT_NULLOK,
91e9cc7b1dSDag-Erling Smørgrav 	PAM_OPT_LOCAL_PASS,
92e9cc7b1dSDag-Erling Smørgrav 	PAM_OPT_NIS_PASS
93e9cc7b1dSDag-Erling Smørgrav };
941642eb1aSMark Murray 
951642eb1aSMark Murray static struct opttab other_options[] = {
961642eb1aSMark Murray 	{ "auth_as_self",	PAM_OPT_AUTH_AS_SELF },
971642eb1aSMark Murray 	{ "nullok",		PAM_OPT_NULLOK },
983d55a6c0SMark Murray 	{ "local_pass",		PAM_OPT_LOCAL_PASS },
993d55a6c0SMark Murray 	{ "nis_pass",		PAM_OPT_NIS_PASS },
1001642eb1aSMark Murray 	{ NULL, 0 }
1011642eb1aSMark Murray };
1029a10bb17SJohn Polstra 
1033d55a6c0SMark Murray #ifdef YP
1043d55a6c0SMark Murray int pam_use_yp = 0;
1053d55a6c0SMark Murray int yp_errno = YP_TRUE;
1063d55a6c0SMark Murray #endif
1073d55a6c0SMark Murray 
1083d55a6c0SMark Murray char *tempname = NULL;
1093d55a6c0SMark Murray static int local_passwd(const char *user, const char *pass);
1103d55a6c0SMark Murray #ifdef YP
1113d55a6c0SMark Murray static int yp_passwd(const char *user, const char *pass);
1123d55a6c0SMark Murray #endif
1133d55a6c0SMark Murray 
114d65b34dbSJohn Polstra /*
115d65b34dbSJohn Polstra  * authentication management
116d65b34dbSJohn Polstra  */
1179a10bb17SJohn Polstra PAM_EXTERN int
118ac569969SMark Murray pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, int argc, const char **argv)
1199a10bb17SJohn Polstra {
1203d55a6c0SMark Murray 	login_cap_t *lc;
1211642eb1aSMark Murray 	struct options options;
1229a10bb17SJohn Polstra 	struct passwd *pwd;
1231642eb1aSMark Murray 	int retval;
1243d55a6c0SMark Murray 	const char *pass, *user;
1253d55a6c0SMark Murray 	char *encrypted, *password_prompt;
1269a10bb17SJohn Polstra 
1271642eb1aSMark Murray 	pam_std_option(&options, other_options, argc, argv);
1281642eb1aSMark Murray 
1291642eb1aSMark Murray 	PAM_LOG("Options processed");
1301642eb1aSMark Murray 
1311642eb1aSMark Murray 	if (pam_test_option(&options, PAM_OPT_AUTH_AS_SELF, NULL))
1323d55a6c0SMark Murray 		pwd = getpwnam(getlogin());
1334448b21cSMark Murray 	else {
1341642eb1aSMark Murray 		retval = pam_get_user(pamh, &user, NULL);
1351642eb1aSMark Murray 		if (retval != PAM_SUCCESS)
1361642eb1aSMark Murray 			PAM_RETURN(retval);
1374448b21cSMark Murray 		pwd = getpwnam(user);
1384448b21cSMark Murray 	}
1391642eb1aSMark Murray 
1401642eb1aSMark Murray 	PAM_LOG("Got user: %s", user);
1411642eb1aSMark Murray 
1424448b21cSMark Murray 	if (pwd != NULL) {
1431642eb1aSMark Murray 
1441642eb1aSMark Murray 		PAM_LOG("Doing real authentication");
1451642eb1aSMark Murray 
1461642eb1aSMark Murray 		if (pwd->pw_passwd[0] == '\0'
1471642eb1aSMark Murray 		    && pam_test_option(&options, PAM_OPT_NULLOK, NULL)) {
14846efbac2SMark Murray 			/*
14946efbac2SMark Murray 			 * No password case. XXX Are we giving too much away
15046efbac2SMark Murray 			 * by not prompting for a password?
15146efbac2SMark Murray 			 */
1521642eb1aSMark Murray 			PAM_LOG("No password, and null password OK");
1531642eb1aSMark Murray 			PAM_RETURN(PAM_SUCCESS);
1541642eb1aSMark Murray 		}
15546efbac2SMark Murray 		else {
156a8b1e59eSDag-Erling Smørgrav 			lc = login_getpwclass(pwd);
157a8b1e59eSDag-Erling Smørgrav 			password_prompt = login_getcapstr(lc, "passwd_prompt",
158a8b1e59eSDag-Erling Smørgrav 			    NULL, NULL);
159111ccd25SDag-Erling Smørgrav 			retval = pam_get_authtok(pamh, PAM_AUTHTOK,
160111ccd25SDag-Erling Smørgrav 			    &pass, password_prompt);
161a8b1e59eSDag-Erling Smørgrav 			login_close(lc);
1621642eb1aSMark Murray 			if (retval != PAM_SUCCESS)
1631642eb1aSMark Murray 				PAM_RETURN(retval);
1641642eb1aSMark Murray 			PAM_LOG("Got password");
16546efbac2SMark Murray 		}
1663d55a6c0SMark Murray 		encrypted = crypt(pass, pwd->pw_passwd);
1673d55a6c0SMark Murray 		if (pass[0] == '\0' && pwd->pw_passwd[0] != '\0')
1688c3ea588SMark Murray 			encrypted = colon;
1699a10bb17SJohn Polstra 
1703d55a6c0SMark Murray 		PAM_LOG("Encrypted password 1 is: %s", encrypted);
1713d55a6c0SMark Murray 		PAM_LOG("Encrypted password 2 is: %s", pwd->pw_passwd);
1721642eb1aSMark Murray 
1739a10bb17SJohn Polstra 		retval = strcmp(encrypted, pwd->pw_passwd) == 0 ?
1749a10bb17SJohn Polstra 		    PAM_SUCCESS : PAM_AUTH_ERR;
1751642eb1aSMark Murray 	}
1761642eb1aSMark Murray 	else {
1771642eb1aSMark Murray 
1781642eb1aSMark Murray 		PAM_LOG("Doing dummy authentication");
1791642eb1aSMark Murray 
1809a10bb17SJohn Polstra 		/*
1811642eb1aSMark Murray 		 * User unknown.
1821642eb1aSMark Murray 		 * Encrypt a dummy password so as to not give away too much.
1839a10bb17SJohn Polstra 		 */
184a8b1e59eSDag-Erling Smørgrav 		lc = login_getclass(NULL);
185a8b1e59eSDag-Erling Smørgrav 		password_prompt = login_getcapstr(lc, "passwd_prompt",
186a8b1e59eSDag-Erling Smørgrav 		    NULL, NULL);
187111ccd25SDag-Erling Smørgrav 		retval = pam_get_authtok(pamh,
188111ccd25SDag-Erling Smørgrav 		    PAM_AUTHTOK, &pass, password_prompt);
189a8b1e59eSDag-Erling Smørgrav 		login_close(lc);
1901642eb1aSMark Murray 		if (retval != PAM_SUCCESS)
1911642eb1aSMark Murray 			PAM_RETURN(retval);
1921642eb1aSMark Murray 		PAM_LOG("Got password");
1933d55a6c0SMark Murray 		crypt(pass, "xx");
1949a10bb17SJohn Polstra 		retval = PAM_AUTH_ERR;
1959a10bb17SJohn Polstra 	}
1961642eb1aSMark Murray 
1979a10bb17SJohn Polstra 	/*
1989a10bb17SJohn Polstra 	 * The PAM infrastructure will obliterate the cleartext
1999a10bb17SJohn Polstra 	 * password before returning to the application.
2009a10bb17SJohn Polstra 	 */
2013d55a6c0SMark Murray 	if (retval != PAM_SUCCESS)
2023d55a6c0SMark Murray 		PAM_VERBOSE_ERROR("UNIX authentication refused");
2033d55a6c0SMark Murray 
2041642eb1aSMark Murray 	PAM_RETURN(retval);
2059a10bb17SJohn Polstra }
2069a10bb17SJohn Polstra 
2079a10bb17SJohn Polstra PAM_EXTERN int
208ac569969SMark Murray pam_sm_setcred(pam_handle_t *pamh __unused, int flags __unused, int argc, const char **argv)
2099a10bb17SJohn Polstra {
2103d55a6c0SMark Murray 	struct options options;
2113d55a6c0SMark Murray 
2123d55a6c0SMark Murray 	pam_std_option(&options, other_options, argc, argv);
2133d55a6c0SMark Murray 
2143d55a6c0SMark Murray 	PAM_LOG("Options processed");
2153d55a6c0SMark Murray 
2163d55a6c0SMark Murray 	PAM_RETURN(PAM_SUCCESS);
2179a10bb17SJohn Polstra }
2189294327dSJohn Polstra 
219d65b34dbSJohn Polstra /*
220d65b34dbSJohn Polstra  * account management
221d65b34dbSJohn Polstra  */
2223d55a6c0SMark Murray PAM_EXTERN int
223ac569969SMark Murray pam_sm_acct_mgmt(pam_handle_t *pamh, int flags __unused, int argc, const char **argv)
224d65b34dbSJohn Polstra {
225e9cc7b1dSDag-Erling Smørgrav 	struct addrinfo hints, *res;
2261642eb1aSMark Murray 	struct options options;
227e9cc7b1dSDag-Erling Smørgrav 	struct passwd *pwd;
228d65b34dbSJohn Polstra 	struct timeval tp;
2291642eb1aSMark Murray 	login_cap_t *lc;
230d65b34dbSJohn Polstra 	time_t warntime;
231d65b34dbSJohn Polstra 	int retval;
232e9cc7b1dSDag-Erling Smørgrav 	const char *rhost, *tty, *user;
233e9cc7b1dSDag-Erling Smørgrav 	char rhostip[MAXHOSTNAMELEN];
2341642eb1aSMark Murray 
2351642eb1aSMark Murray 	pam_std_option(&options, other_options, argc, argv);
2361642eb1aSMark Murray 
2371642eb1aSMark Murray 	PAM_LOG("Options processed");
238d65b34dbSJohn Polstra 
239111ccd25SDag-Erling Smørgrav 	retval = pam_get_user(pamh, &user, NULL);
240e9cc7b1dSDag-Erling Smørgrav 	if (retval != PAM_SUCCESS)
241e9cc7b1dSDag-Erling Smørgrav 		PAM_RETURN(retval);
242d65b34dbSJohn Polstra 
243e9cc7b1dSDag-Erling Smørgrav 	if (user == NULL || (pwd = getpwnam(user)) == NULL)
244e9cc7b1dSDag-Erling Smørgrav 		PAM_RETURN(PAM_SERVICE_ERR);
2451642eb1aSMark Murray 
2461642eb1aSMark Murray 	PAM_LOG("Got user: %s", user);
247d65b34dbSJohn Polstra 
248e9cc7b1dSDag-Erling Smørgrav 	retval = pam_get_item(pamh, PAM_RHOST, (const void **)&rhost);
249e9cc7b1dSDag-Erling Smørgrav 	if (retval != PAM_SUCCESS)
250e9cc7b1dSDag-Erling Smørgrav 		PAM_RETURN(retval);
251d65b34dbSJohn Polstra 
252e9cc7b1dSDag-Erling Smørgrav 	retval = pam_get_item(pamh, PAM_TTY, (const void **)&tty);
253e9cc7b1dSDag-Erling Smørgrav 	if (retval != PAM_SUCCESS)
254e9cc7b1dSDag-Erling Smørgrav 		PAM_RETURN(retval);
255d65b34dbSJohn Polstra 
256e9cc7b1dSDag-Erling Smørgrav 	if (*pwd->pw_passwd == '\0' &&
257e9cc7b1dSDag-Erling Smørgrav 	    (flags & PAM_DISALLOW_NULL_AUTHTOK) != 0)
258e9cc7b1dSDag-Erling Smørgrav 		return (PAM_NEW_AUTHTOK_REQD);
259e9cc7b1dSDag-Erling Smørgrav 
260e9cc7b1dSDag-Erling Smørgrav 	lc = login_getpwclass(pwd);
261e9cc7b1dSDag-Erling Smørgrav 	if (lc == NULL) {
262e9cc7b1dSDag-Erling Smørgrav 		PAM_LOG("Unable to get login class for user %s", user);
263e9cc7b1dSDag-Erling Smørgrav 		return (PAM_SERVICE_ERR);
264e9cc7b1dSDag-Erling Smørgrav 	}
265d65b34dbSJohn Polstra 
2661642eb1aSMark Murray 	PAM_LOG("Got login_cap");
2671642eb1aSMark Murray 
268e9cc7b1dSDag-Erling Smørgrav 	if (pwd->pw_change || pwd->pw_expire)
269e9cc7b1dSDag-Erling Smørgrav 		gettimeofday(&tp, NULL);
270d65b34dbSJohn Polstra 
271e9cc7b1dSDag-Erling Smørgrav 	/*
272e9cc7b1dSDag-Erling Smørgrav 	 * Check pw_expire before pw_change - no point in letting the
273e9cc7b1dSDag-Erling Smørgrav 	 * user change the password on an expired account.
274e9cc7b1dSDag-Erling Smørgrav 	 */
275d65b34dbSJohn Polstra 
276e9cc7b1dSDag-Erling Smørgrav 	if (pwd->pw_expire) {
277e9cc7b1dSDag-Erling Smørgrav 		warntime = login_getcaptime(lc, "warnexpire",
278e9cc7b1dSDag-Erling Smørgrav 		    DEFAULT_WARN, DEFAULT_WARN);
279e9cc7b1dSDag-Erling Smørgrav 		if (tp.tv_sec >= pwd->pw_expire) {
280e9cc7b1dSDag-Erling Smørgrav 			login_close(lc);
281e9cc7b1dSDag-Erling Smørgrav 			PAM_RETURN(PAM_ACCT_EXPIRED);
282e9cc7b1dSDag-Erling Smørgrav 		} else if (pwd->pw_expire - tp.tv_sec < warntime &&
283e9cc7b1dSDag-Erling Smørgrav 		    (flags & PAM_SILENT) == 0) {
284519b6a4cSDag-Erling Smørgrav 			pam_error(pamh, "Warning: your account expires on %s",
285e9cc7b1dSDag-Erling Smørgrav 			    ctime(&pwd->pw_expire));
286d65b34dbSJohn Polstra 		}
287d65b34dbSJohn Polstra 	}
288d65b34dbSJohn Polstra 
289e9cc7b1dSDag-Erling Smørgrav 	retval = PAM_SUCCESS;
290e9cc7b1dSDag-Erling Smørgrav 	if (pwd->pw_change) {
291e9cc7b1dSDag-Erling Smørgrav 		warntime = login_getcaptime(lc, "warnpassword",
292e9cc7b1dSDag-Erling Smørgrav 		    DEFAULT_WARN, DEFAULT_WARN);
293e9cc7b1dSDag-Erling Smørgrav 		if (tp.tv_sec >= pwd->pw_change) {
294e9cc7b1dSDag-Erling Smørgrav 			retval = PAM_NEW_AUTHTOK_REQD;
295e9cc7b1dSDag-Erling Smørgrav 		} else if (pwd->pw_change - tp.tv_sec < warntime &&
296e9cc7b1dSDag-Erling Smørgrav 		    (flags & PAM_SILENT) == 0) {
297519b6a4cSDag-Erling Smørgrav 			pam_error(pamh, "Warning: your password expires on %s",
298e9cc7b1dSDag-Erling Smørgrav 			    ctime(&pwd->pw_change));
299e9cc7b1dSDag-Erling Smørgrav 		}
300e9cc7b1dSDag-Erling Smørgrav 	}
301e9cc7b1dSDag-Erling Smørgrav 
302e9cc7b1dSDag-Erling Smørgrav 	/*
303e9cc7b1dSDag-Erling Smørgrav 	 * From here on, we must leave retval untouched (unless we
304e9cc7b1dSDag-Erling Smørgrav 	 * know we're going to fail), because we need to remember
305e9cc7b1dSDag-Erling Smørgrav 	 * whether we're supposed to return PAM_SUCCESS or
306e9cc7b1dSDag-Erling Smørgrav 	 * PAM_NEW_AUTHTOK_REQD.
307e9cc7b1dSDag-Erling Smørgrav 	 */
308e9cc7b1dSDag-Erling Smørgrav 
309e9cc7b1dSDag-Erling Smørgrav 	if (rhost) {
310e9cc7b1dSDag-Erling Smørgrav 		memset(&hints, 0, sizeof(hints));
311e9cc7b1dSDag-Erling Smørgrav 		hints.ai_family = AF_UNSPEC;
312e9cc7b1dSDag-Erling Smørgrav 		if (getaddrinfo(rhost, NULL, &hints, &res) == 0) {
313e9cc7b1dSDag-Erling Smørgrav 			getnameinfo(res->ai_addr, res->ai_addrlen,
314e9cc7b1dSDag-Erling Smørgrav 			    rhostip, sizeof(rhostip), NULL, 0,
315e9cc7b1dSDag-Erling Smørgrav 			    NI_NUMERICHOST|NI_WITHSCOPEID);
316e9cc7b1dSDag-Erling Smørgrav 		}
317e9cc7b1dSDag-Erling Smørgrav 		if (res != NULL)
318e9cc7b1dSDag-Erling Smørgrav 			freeaddrinfo(res);
319e9cc7b1dSDag-Erling Smørgrav 	}
320e9cc7b1dSDag-Erling Smørgrav 
321e9cc7b1dSDag-Erling Smørgrav 	/*
322e9cc7b1dSDag-Erling Smørgrav 	 * Check host / tty / time-of-day restrictions
323e9cc7b1dSDag-Erling Smørgrav 	 */
324e9cc7b1dSDag-Erling Smørgrav 
325e9cc7b1dSDag-Erling Smørgrav 	if (!auth_hostok(lc, rhost, rhostip) ||
326e9cc7b1dSDag-Erling Smørgrav 	    !auth_ttyok(lc, tty) ||
327e9cc7b1dSDag-Erling Smørgrav 	    !auth_timeok(lc, time(NULL)))
328e9cc7b1dSDag-Erling Smørgrav 		retval = PAM_AUTH_ERR;
329e9cc7b1dSDag-Erling Smørgrav 
330d65b34dbSJohn Polstra 	login_close(lc);
3311642eb1aSMark Murray 
3321642eb1aSMark Murray 	PAM_RETURN(retval);
333d65b34dbSJohn Polstra }
334d65b34dbSJohn Polstra 
3353d55a6c0SMark Murray /*
3363d55a6c0SMark Murray  * session management
3373d55a6c0SMark Murray  *
3383d55a6c0SMark Murray  * logging only
3393d55a6c0SMark Murray  */
3403d55a6c0SMark Murray PAM_EXTERN int
341ac569969SMark Murray pam_sm_open_session(pam_handle_t *pamh __unused, int flags __unused, int argc, const char **argv)
3423d55a6c0SMark Murray {
3433d55a6c0SMark Murray 	struct options options;
3443d55a6c0SMark Murray 
3453d55a6c0SMark Murray 	pam_std_option(&options, other_options, argc, argv);
3463d55a6c0SMark Murray 
3473d55a6c0SMark Murray 	PAM_LOG("Options processed");
3483d55a6c0SMark Murray 
3493d55a6c0SMark Murray 	PAM_RETURN(PAM_SUCCESS);
3503d55a6c0SMark Murray }
3513d55a6c0SMark Murray 
3523d55a6c0SMark Murray PAM_EXTERN int
353ac569969SMark Murray pam_sm_close_session(pam_handle_t *pamh __unused, int flags __unused, int argc, const char **argv)
3543d55a6c0SMark Murray {
3553d55a6c0SMark Murray 	struct options options;
3563d55a6c0SMark Murray 
3573d55a6c0SMark Murray 	pam_std_option(&options, other_options, argc, argv);
3583d55a6c0SMark Murray 
3593d55a6c0SMark Murray 	PAM_LOG("Options processed");
3603d55a6c0SMark Murray 
3613d55a6c0SMark Murray 	PAM_RETURN(PAM_SUCCESS);
3623d55a6c0SMark Murray }
3633d55a6c0SMark Murray 
3643d55a6c0SMark Murray /*
3653d55a6c0SMark Murray  * password management
3663d55a6c0SMark Murray  *
3673d55a6c0SMark Murray  * standard Unix and NIS password changing
3683d55a6c0SMark Murray  */
3693d55a6c0SMark Murray PAM_EXTERN int
3703d55a6c0SMark Murray pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
3713d55a6c0SMark Murray {
3723d55a6c0SMark Murray 	struct options options;
3733d55a6c0SMark Murray 	struct passwd *pwd;
374111ccd25SDag-Erling Smørgrav 	const char *user, *pass, *new_pass;
375111ccd25SDag-Erling Smørgrav 	char *encrypted, *usrdup;
376111ccd25SDag-Erling Smørgrav 	int retval, res;
3773d55a6c0SMark Murray 
3783d55a6c0SMark Murray 	pam_std_option(&options, other_options, argc, argv);
3793d55a6c0SMark Murray 
3803d55a6c0SMark Murray 	PAM_LOG("Options processed");
3813d55a6c0SMark Murray 
3823d55a6c0SMark Murray 	if (pam_test_option(&options, PAM_OPT_AUTH_AS_SELF, NULL))
3833d55a6c0SMark Murray 		pwd = getpwnam(getlogin());
3843d55a6c0SMark Murray 	else {
3853d55a6c0SMark Murray 		retval = pam_get_user(pamh, &user, NULL);
3863d55a6c0SMark Murray 		if (retval != PAM_SUCCESS)
3873d55a6c0SMark Murray 			PAM_RETURN(retval);
3883d55a6c0SMark Murray 		pwd = getpwnam(user);
3893d55a6c0SMark Murray 	}
3903d55a6c0SMark Murray 
3913d55a6c0SMark Murray 	PAM_LOG("Got user: %s", user);
3923d55a6c0SMark Murray 
3933d55a6c0SMark Murray 	if (flags & PAM_PRELIM_CHECK) {
3943d55a6c0SMark Murray 
3953d55a6c0SMark Murray 		PAM_LOG("PRELIM round; checking user password");
3963d55a6c0SMark Murray 
3973d55a6c0SMark Murray 		if (pwd->pw_passwd[0] == '\0'
3983d55a6c0SMark Murray 		    && pam_test_option(&options, PAM_OPT_NULLOK, NULL)) {
3993d55a6c0SMark Murray 			/*
4003d55a6c0SMark Murray 			 * No password case. XXX Are we giving too much away
4013d55a6c0SMark Murray 			 * by not prompting for a password?
402111ccd25SDag-Erling Smørgrav 			 * XXX check PAM_DISALLOW_NULL_AUTHTOK
4033d55a6c0SMark Murray 			 */
404111ccd25SDag-Erling Smørgrav 			PAM_LOG("Got password");
4053d55a6c0SMark Murray 			PAM_RETURN(PAM_SUCCESS);
4063d55a6c0SMark Murray 		}
4073d55a6c0SMark Murray 		else {
408111ccd25SDag-Erling Smørgrav 			retval = pam_get_authtok(pamh,
409111ccd25SDag-Erling Smørgrav 			    PAM_OLDAUTHTOK, &pass, NULL);
4103d55a6c0SMark Murray 			if (retval != PAM_SUCCESS)
4113d55a6c0SMark Murray 				PAM_RETURN(retval);
412111ccd25SDag-Erling Smørgrav 			PAM_LOG("Got password");
4133d55a6c0SMark Murray 		}
4143d55a6c0SMark Murray 		encrypted = crypt(pass, pwd->pw_passwd);
4153d55a6c0SMark Murray 		if (pass[0] == '\0' && pwd->pw_passwd[0] != '\0')
4168c3ea588SMark Murray 			encrypted = colon;
4173d55a6c0SMark Murray 
418111ccd25SDag-Erling Smørgrav 		if (strcmp(encrypted, pwd->pw_passwd) != 0) {
419111ccd25SDag-Erling Smørgrav 			pam_set_item(pamh, PAM_OLDAUTHTOK, NULL);
4203d55a6c0SMark Murray 			PAM_RETURN(PAM_AUTH_ERR);
421111ccd25SDag-Erling Smørgrav 		}
4223d55a6c0SMark Murray 
4233d55a6c0SMark Murray 		PAM_RETURN(PAM_SUCCESS);
4243d55a6c0SMark Murray 	}
4253d55a6c0SMark Murray 	else if (flags & PAM_UPDATE_AUTHTOK) {
4263d55a6c0SMark Murray 		PAM_LOG("UPDATE round; checking user password");
4273d55a6c0SMark Murray 
428111ccd25SDag-Erling Smørgrav 		retval = pam_get_authtok(pamh, PAM_OLDAUTHTOK, &pass, NULL);
4293d55a6c0SMark Murray 		if (retval != PAM_SUCCESS)
4303d55a6c0SMark Murray 			PAM_RETURN(retval);
4313d55a6c0SMark Murray 
432111ccd25SDag-Erling Smørgrav 		PAM_LOG("Got old password");
4333d55a6c0SMark Murray 
434111ccd25SDag-Erling Smørgrav 		for (;;) {
435111ccd25SDag-Erling Smørgrav 			retval = pam_get_authtok(pamh,
436111ccd25SDag-Erling Smørgrav 			    PAM_AUTHTOK, &new_pass, NULL);
437111ccd25SDag-Erling Smørgrav 			if (retval != PAM_TRY_AGAIN)
4383d55a6c0SMark Murray 				break;
439111ccd25SDag-Erling Smørgrav 			pam_error(pamh, "Mismatch; try again, EOF to quit.");
4403d55a6c0SMark Murray 		}
4413d55a6c0SMark Murray 
442111ccd25SDag-Erling Smørgrav 		if (retval != PAM_SUCCESS) {
443111ccd25SDag-Erling Smørgrav 			PAM_VERBOSE_ERROR("Unable to get new password");
4443d55a6c0SMark Murray 			PAM_RETURN(PAM_PERM_DENIED);
4453d55a6c0SMark Murray 		}
4463d55a6c0SMark Murray 
4473d55a6c0SMark Murray 		PAM_LOG("Got new password: %s", new_pass);
4483d55a6c0SMark Murray 
4493d55a6c0SMark Murray #ifdef YP
4503d55a6c0SMark Murray 		/* If NIS is set in the passwd database, use it */
4514004c08eSDag-Erling Smørgrav 		if ((usrdup = strdup(user)) == NULL)
4524004c08eSDag-Erling Smørgrav 			PAM_RETURN(PAM_BUF_ERR);
4534004c08eSDag-Erling Smørgrav 		res = use_yp(usrdup, 0, 0);
4544004c08eSDag-Erling Smørgrav 		free(usrdup);
4553d55a6c0SMark Murray 		if (res == USER_YP_ONLY) {
4563d55a6c0SMark Murray 			if (!pam_test_option(&options, PAM_OPT_LOCAL_PASS,
4573d55a6c0SMark Murray 			    NULL))
4583d55a6c0SMark Murray 				retval = yp_passwd(user, new_pass);
4593d55a6c0SMark Murray 			else {
4603d55a6c0SMark Murray 				/* Reject 'local' flag if NIS is on and the user
4613d55a6c0SMark Murray 				 * is not local
4623d55a6c0SMark Murray 				 */
4633d55a6c0SMark Murray 				retval = PAM_PERM_DENIED;
4643d55a6c0SMark Murray 				PAM_LOG("Unknown local user: %s", user);
4653d55a6c0SMark Murray 			}
4663d55a6c0SMark Murray 		}
4673d55a6c0SMark Murray 		else if (res == USER_LOCAL_ONLY) {
4683d55a6c0SMark Murray 			if (!pam_test_option(&options, PAM_OPT_NIS_PASS, NULL))
4693d55a6c0SMark Murray 				retval = local_passwd(user, new_pass);
4703d55a6c0SMark Murray 			else {
4713d55a6c0SMark Murray 				/* Reject 'nis' flag if user is only local */
4723d55a6c0SMark Murray 				retval = PAM_PERM_DENIED;
4733d55a6c0SMark Murray 				PAM_LOG("Unknown NIS user: %s", user);
4743d55a6c0SMark Murray 			}
4753d55a6c0SMark Murray 		}
4763d55a6c0SMark Murray 		else if (res == USER_YP_AND_LOCAL) {
4773d55a6c0SMark Murray 			if (pam_test_option(&options, PAM_OPT_NIS_PASS, NULL))
4783d55a6c0SMark Murray 				retval = yp_passwd(user, new_pass);
4793d55a6c0SMark Murray 			else
4803d55a6c0SMark Murray 				retval = local_passwd(user, new_pass);
4813d55a6c0SMark Murray 		}
4823d55a6c0SMark Murray 		else
4834004c08eSDag-Erling Smørgrav 			retval = PAM_SERVICE_ERR; /* Bad juju */
4843d55a6c0SMark Murray #else
4853d55a6c0SMark Murray 		retval = local_passwd(user, new_pass);
4863d55a6c0SMark Murray #endif
4873d55a6c0SMark Murray 	}
4883d55a6c0SMark Murray 	else {
4893d55a6c0SMark Murray 		/* Very bad juju */
4903d55a6c0SMark Murray 		retval = PAM_ABORT;
4913d55a6c0SMark Murray 		PAM_LOG("Illegal 'flags'");
4923d55a6c0SMark Murray 	}
4933d55a6c0SMark Murray 
4943d55a6c0SMark Murray 	PAM_RETURN(retval);
4953d55a6c0SMark Murray }
4963d55a6c0SMark Murray 
4973d55a6c0SMark Murray /* Mostly stolen from passwd(1)'s local_passwd.c - markm */
4983d55a6c0SMark Murray 
4993d55a6c0SMark Murray static unsigned char itoa64[] =		/* 0 ... 63 => ascii - 64 */
5003d55a6c0SMark Murray 	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
5013d55a6c0SMark Murray 
5023d55a6c0SMark Murray static void
5033d55a6c0SMark Murray to64(char *s, long v, int n)
5043d55a6c0SMark Murray {
5053d55a6c0SMark Murray 	while (--n >= 0) {
5063d55a6c0SMark Murray 		*s++ = itoa64[v&0x3f];
5073d55a6c0SMark Murray 		v >>= 6;
5083d55a6c0SMark Murray 	}
5093d55a6c0SMark Murray }
5103d55a6c0SMark Murray 
5113d55a6c0SMark Murray static int
5123d55a6c0SMark Murray local_passwd(const char *user, const char *pass)
5133d55a6c0SMark Murray {
5143d55a6c0SMark Murray 	login_cap_t * lc;
5153d55a6c0SMark Murray 	struct passwd *pwd;
5163d55a6c0SMark Murray 	int pfd, tfd;
5178c3ea588SMark Murray 	char *crypt_type, salt[SALTSIZE + 1];
5183d55a6c0SMark Murray 
5193d55a6c0SMark Murray 	pwd = getpwnam(user);
5203d55a6c0SMark Murray 	if (pwd == NULL)
5214004c08eSDag-Erling Smørgrav 		return(PAM_SERVICE_ERR); /* Really bad things */
5223d55a6c0SMark Murray 
5233d55a6c0SMark Murray #ifdef YP
5243d55a6c0SMark Murray 	pwd = (struct passwd *)&local_password;
5253d55a6c0SMark Murray #endif
5263d55a6c0SMark Murray 	pw_init();
5273d55a6c0SMark Murray 
5283d55a6c0SMark Murray 	pwd->pw_change = 0;
5293d55a6c0SMark Murray 	lc = login_getclass(NULL);
5303d55a6c0SMark Murray 	crypt_type = login_getcapstr(lc, "passwd_format",
531ac569969SMark Murray 		password_hash, password_hash);
5323d55a6c0SMark Murray 	if (login_setcryptfmt(lc, crypt_type, NULL) == NULL)
5333d55a6c0SMark Murray 		syslog(LOG_ERR, "cannot set password cipher");
5343d55a6c0SMark Murray 	login_close(lc);
5358c3ea588SMark Murray 	makesalt(salt);
5363d55a6c0SMark Murray 	pwd->pw_passwd = crypt(pass, salt);
5373d55a6c0SMark Murray 
5383d55a6c0SMark Murray 	pfd = pw_lock();
5393d55a6c0SMark Murray 	tfd = pw_tmp();
54051906f45SCrist J. Clark 	pw_copy(pfd, tfd, pwd, NULL);
5413d55a6c0SMark Murray 
542ac569969SMark Murray 	if (!pw_mkdb(user))
5433d55a6c0SMark Murray 		pw_error((char *)NULL, 0, 1);
5443d55a6c0SMark Murray 
5454004c08eSDag-Erling Smørgrav 	return (PAM_SUCCESS);
5463d55a6c0SMark Murray }
5473d55a6c0SMark Murray 
5483d55a6c0SMark Murray #ifdef YP
5493d55a6c0SMark Murray /* Stolen from src/usr.bin/passwd/yp_passwd.c, carrying copyrights of:
5503d55a6c0SMark Murray  * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
5513d55a6c0SMark Murray  * Copyright (c) 1994 Olaf Kirch <okir@monad.swb.de>
5523d55a6c0SMark Murray  * Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>
5533d55a6c0SMark Murray  */
5543d55a6c0SMark Murray int
555519b6a4cSDag-Erling Smørgrav yp_passwd(const char *user __unused, const char *pass)
5563d55a6c0SMark Murray {
557111ccd25SDag-Erling Smørgrav 	struct yppasswd yppwd;
558519b6a4cSDag-Erling Smørgrav 	struct master_yppasswd master_yppwd;
5593d55a6c0SMark Murray 	struct passwd *pwd;
5603d55a6c0SMark Murray 	struct rpc_err err;
5613d55a6c0SMark Murray 	CLIENT *clnt;
5623d55a6c0SMark Murray 	login_cap_t *lc;
5633d55a6c0SMark Murray 	int    *status;
5643d55a6c0SMark Murray 	uid_t uid;
5658c3ea588SMark Murray 	char   *master, sockname[] = YP_SOCKNAME, salt[SALTSIZE + 1];
5663d55a6c0SMark Murray 
5673d55a6c0SMark Murray 	_use_yp = 1;
5683d55a6c0SMark Murray 
5693d55a6c0SMark Murray 	uid = getuid();
5703d55a6c0SMark Murray 
5713d55a6c0SMark Murray 	master = get_yp_master(1);
5723d55a6c0SMark Murray 	if (master == NULL)
5734004c08eSDag-Erling Smørgrav 		return (PAM_SERVICE_ERR); /* Major disaster */
5743d55a6c0SMark Murray 
5753d55a6c0SMark Murray 	/*
5763d55a6c0SMark Murray 	 * It is presumed that by the time we get here, use_yp()
5773d55a6c0SMark Murray 	 * has been called and that we have verified that the user
5783d55a6c0SMark Murray 	 * actually exists. This being the case, the yp_password
5793d55a6c0SMark Murray 	 * stucture has already been filled in for us.
5803d55a6c0SMark Murray 	 */
5813d55a6c0SMark Murray 
5823d55a6c0SMark Murray 	/* Use the correct password */
5833d55a6c0SMark Murray 	pwd = (struct passwd *)&yp_password;
5843d55a6c0SMark Murray 
5853d55a6c0SMark Murray 	pwd->pw_change = 0;
5863d55a6c0SMark Murray 
5873d55a6c0SMark Murray 	/* Initialize password information */
5883d55a6c0SMark Murray 	if (suser_override) {
589519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_passwd = strdup(pwd->pw_passwd);
590519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_name = strdup(pwd->pw_name);
591519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_uid = pwd->pw_uid;
592519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_gid = pwd->pw_gid;
593519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_expire = pwd->pw_expire;
594519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_change = pwd->pw_change;
595519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_fields = pwd->pw_fields;
596519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_gecos = strdup(pwd->pw_gecos);
597519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_dir = strdup(pwd->pw_dir);
598519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_shell = strdup(pwd->pw_shell);
599519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_class = pwd->pw_class != NULL ?
600ac569969SMark Murray 					strdup(pwd->pw_class) : strdup("");
601519b6a4cSDag-Erling Smørgrav 		master_yppwd.oldpass = strdup("");
602519b6a4cSDag-Erling Smørgrav 		master_yppwd.domain = yp_domain;
6033d55a6c0SMark Murray 	} else {
604519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_passwd = strdup(pwd->pw_passwd);
605519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_name = strdup(pwd->pw_name);
606519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_uid = pwd->pw_uid;
607519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_gid = pwd->pw_gid;
608519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_gecos = strdup(pwd->pw_gecos);
609519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_dir = strdup(pwd->pw_dir);
610519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_shell = strdup(pwd->pw_shell);
611519b6a4cSDag-Erling Smørgrav 		yppwd.oldpass = strdup("");
6123d55a6c0SMark Murray 	}
6133d55a6c0SMark Murray 
6143d55a6c0SMark Murray 	if (login_setcryptfmt(lc, "md5", NULL) == NULL)
6153d55a6c0SMark Murray 		syslog(LOG_ERR, "cannot set password cipher");
6163d55a6c0SMark Murray 	login_close(lc);
6173d55a6c0SMark Murray 
6188c3ea588SMark Murray 	makesalt(salt);
6193d55a6c0SMark Murray 	if (suser_override)
620519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_passwd = crypt(pass, salt);
6213d55a6c0SMark Murray 	else
622519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_passwd = crypt(pass, salt);
6233d55a6c0SMark Murray 
6243d55a6c0SMark Murray 	if (suser_override) {
6253d55a6c0SMark Murray 		if ((clnt = clnt_create(sockname, MASTER_YPPASSWDPROG,
6263d55a6c0SMark Murray 		    MASTER_YPPASSWDVERS, "unix")) == NULL) {
6273d55a6c0SMark Murray 			syslog(LOG_ERR,
6283d55a6c0SMark Murray 			    "Cannot contact rpc.yppasswdd on host %s: %s",
6293d55a6c0SMark Murray 			    master, clnt_spcreateerror(""));
6304004c08eSDag-Erling Smørgrav 			return (PAM_SERVICE_ERR);
6313d55a6c0SMark Murray 		}
6323d55a6c0SMark Murray 	}
6333d55a6c0SMark Murray 	else {
6343d55a6c0SMark Murray 		if ((clnt = clnt_create(master, YPPASSWDPROG,
6353d55a6c0SMark Murray 		    YPPASSWDVERS, "udp")) == NULL) {
6363d55a6c0SMark Murray 			syslog(LOG_ERR,
6373d55a6c0SMark Murray 			    "Cannot contact rpc.yppasswdd on host %s: %s",
6383d55a6c0SMark Murray 			    master, clnt_spcreateerror(""));
6394004c08eSDag-Erling Smørgrav 			return (PAM_SERVICE_ERR);
6403d55a6c0SMark Murray 		}
6413d55a6c0SMark Murray 	}
6423d55a6c0SMark Murray 	/*
6433d55a6c0SMark Murray 	 * The yppasswd.x file said `unix authentication required',
6443d55a6c0SMark Murray 	 * so I added it. This is the only reason it is in here.
6453d55a6c0SMark Murray 	 * My yppasswdd doesn't use it, but maybe some others out there
6463d55a6c0SMark Murray 	 * do. 					--okir
6473d55a6c0SMark Murray 	 */
6483d55a6c0SMark Murray 	clnt->cl_auth = authunix_create_default();
6493d55a6c0SMark Murray 
6503d55a6c0SMark Murray 	if (suser_override)
651519b6a4cSDag-Erling Smørgrav 		status = yppasswdproc_update_master_1(&master_yppwd, clnt);
6523d55a6c0SMark Murray 	else
653519b6a4cSDag-Erling Smørgrav 		status = yppasswdproc_update_1(&yppwd, clnt);
6543d55a6c0SMark Murray 
6553d55a6c0SMark Murray 	clnt_geterr(clnt, &err);
6563d55a6c0SMark Murray 
6573d55a6c0SMark Murray 	auth_destroy(clnt->cl_auth);
6583d55a6c0SMark Murray 	clnt_destroy(clnt);
6593d55a6c0SMark Murray 
6603d55a6c0SMark Murray 	if (err.re_status != RPC_SUCCESS || status == NULL || *status)
6614004c08eSDag-Erling Smørgrav 		return (PAM_SERVICE_ERR);
6623d55a6c0SMark Murray 
6634004c08eSDag-Erling Smørgrav 	if (err.re_status || status == NULL || *status)
6644004c08eSDag-Erling Smørgrav 		return (PAM_SERVICE_ERR);
6654004c08eSDag-Erling Smørgrav 	return (PAM_SUCCESS);
6663d55a6c0SMark Murray }
6673d55a6c0SMark Murray #endif /* YP */
6683d55a6c0SMark Murray 
6698c3ea588SMark Murray /* Salt suitable for traditional DES and MD5 */
6708c3ea588SMark Murray void
6718c3ea588SMark Murray makesalt(char salt[SALTSIZE])
6728c3ea588SMark Murray {
6738c3ea588SMark Murray 	int i;
6748c3ea588SMark Murray 
6758c3ea588SMark Murray 	/* These are not really random numbers, they are just
6768c3ea588SMark Murray 	 * numbers that change to thwart construction of a
6778c3ea588SMark Murray 	 * dictionary. This is exposed to the public.
6788c3ea588SMark Murray 	 */
6798c3ea588SMark Murray 	for (i = 0; i < SALTSIZE; i += 4)
6808c3ea588SMark Murray 		to64(&salt[i], arc4random(), 4);
6818c3ea588SMark Murray 	salt[SALTSIZE] = '\0';
6828c3ea588SMark Murray }
6838c3ea588SMark Murray 
6849294327dSJohn Polstra PAM_MODULE_ENTRY("pam_unix");
685