xref: /freebsd/lib/libpam/modules/pam_unix/pam_unix.c (revision 111ccd256cfcfe84d7e294090ce08febf8f1441a)
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 
1423d55a6c0SMark Murray 	lc = login_getclass(NULL);
1433d55a6c0SMark Murray 	password_prompt = login_getcapstr(lc, "passwd_prompt",
144111ccd25SDag-Erling Smørgrav 	    password_prompt, NULL);
1453d55a6c0SMark Murray 	login_close(lc);
1463d55a6c0SMark Murray 	lc = NULL;
1473d55a6c0SMark Murray 
1484448b21cSMark Murray 	if (pwd != NULL) {
1491642eb1aSMark Murray 
1501642eb1aSMark Murray 		PAM_LOG("Doing real authentication");
1511642eb1aSMark Murray 
1521642eb1aSMark Murray 		if (pwd->pw_passwd[0] == '\0'
1531642eb1aSMark Murray 		    && pam_test_option(&options, PAM_OPT_NULLOK, NULL)) {
15446efbac2SMark Murray 			/*
15546efbac2SMark Murray 			 * No password case. XXX Are we giving too much away
15646efbac2SMark Murray 			 * by not prompting for a password?
15746efbac2SMark Murray 			 */
1581642eb1aSMark Murray 			PAM_LOG("No password, and null password OK");
1591642eb1aSMark Murray 			PAM_RETURN(PAM_SUCCESS);
1601642eb1aSMark Murray 		}
16146efbac2SMark Murray 		else {
162111ccd25SDag-Erling Smørgrav 			retval = pam_get_authtok(pamh, PAM_AUTHTOK,
163111ccd25SDag-Erling Smørgrav 			    &pass, password_prompt);
1641642eb1aSMark Murray 			if (retval != PAM_SUCCESS)
1651642eb1aSMark Murray 				PAM_RETURN(retval);
1661642eb1aSMark Murray 			PAM_LOG("Got password");
16746efbac2SMark Murray 		}
1683d55a6c0SMark Murray 		encrypted = crypt(pass, pwd->pw_passwd);
1693d55a6c0SMark Murray 		if (pass[0] == '\0' && pwd->pw_passwd[0] != '\0')
1708c3ea588SMark Murray 			encrypted = colon;
1719a10bb17SJohn Polstra 
1723d55a6c0SMark Murray 		PAM_LOG("Encrypted password 1 is: %s", encrypted);
1733d55a6c0SMark Murray 		PAM_LOG("Encrypted password 2 is: %s", pwd->pw_passwd);
1741642eb1aSMark Murray 
1759a10bb17SJohn Polstra 		retval = strcmp(encrypted, pwd->pw_passwd) == 0 ?
1769a10bb17SJohn Polstra 		    PAM_SUCCESS : PAM_AUTH_ERR;
1771642eb1aSMark Murray 	}
1781642eb1aSMark Murray 	else {
1791642eb1aSMark Murray 
1801642eb1aSMark Murray 		PAM_LOG("Doing dummy authentication");
1811642eb1aSMark Murray 
1829a10bb17SJohn Polstra 		/*
1831642eb1aSMark Murray 		 * User unknown.
1841642eb1aSMark Murray 		 * Encrypt a dummy password so as to not give away too much.
1859a10bb17SJohn Polstra 		 */
186111ccd25SDag-Erling Smørgrav 		retval = pam_get_authtok(pamh,
187111ccd25SDag-Erling Smørgrav 		    PAM_AUTHTOK, &pass, password_prompt);
1881642eb1aSMark Murray 		if (retval != PAM_SUCCESS)
1891642eb1aSMark Murray 			PAM_RETURN(retval);
1901642eb1aSMark Murray 		PAM_LOG("Got password");
1913d55a6c0SMark Murray 		crypt(pass, "xx");
1929a10bb17SJohn Polstra 		retval = PAM_AUTH_ERR;
1939a10bb17SJohn Polstra 	}
1941642eb1aSMark Murray 
1959a10bb17SJohn Polstra 	/*
1969a10bb17SJohn Polstra 	 * The PAM infrastructure will obliterate the cleartext
1979a10bb17SJohn Polstra 	 * password before returning to the application.
1989a10bb17SJohn Polstra 	 */
1993d55a6c0SMark Murray 	if (retval != PAM_SUCCESS)
2003d55a6c0SMark Murray 		PAM_VERBOSE_ERROR("UNIX authentication refused");
2013d55a6c0SMark Murray 
2021642eb1aSMark Murray 	PAM_RETURN(retval);
2039a10bb17SJohn Polstra }
2049a10bb17SJohn Polstra 
2059a10bb17SJohn Polstra PAM_EXTERN int
206ac569969SMark Murray pam_sm_setcred(pam_handle_t *pamh __unused, int flags __unused, int argc, const char **argv)
2079a10bb17SJohn Polstra {
2083d55a6c0SMark Murray 	struct options options;
2093d55a6c0SMark Murray 
2103d55a6c0SMark Murray 	pam_std_option(&options, other_options, argc, argv);
2113d55a6c0SMark Murray 
2123d55a6c0SMark Murray 	PAM_LOG("Options processed");
2133d55a6c0SMark Murray 
2143d55a6c0SMark Murray 	PAM_RETURN(PAM_SUCCESS);
2159a10bb17SJohn Polstra }
2169294327dSJohn Polstra 
217d65b34dbSJohn Polstra /*
218d65b34dbSJohn Polstra  * account management
219d65b34dbSJohn Polstra  */
2203d55a6c0SMark Murray PAM_EXTERN int
221ac569969SMark Murray pam_sm_acct_mgmt(pam_handle_t *pamh, int flags __unused, int argc, const char **argv)
222d65b34dbSJohn Polstra {
223e9cc7b1dSDag-Erling Smørgrav 	struct addrinfo hints, *res;
2241642eb1aSMark Murray 	struct options options;
225e9cc7b1dSDag-Erling Smørgrav 	struct passwd *pwd;
226d65b34dbSJohn Polstra 	struct timeval tp;
2271642eb1aSMark Murray 	login_cap_t *lc;
228d65b34dbSJohn Polstra 	time_t warntime;
229d65b34dbSJohn Polstra 	int retval;
230e9cc7b1dSDag-Erling Smørgrav 	const char *rhost, *tty, *user;
231e9cc7b1dSDag-Erling Smørgrav 	char rhostip[MAXHOSTNAMELEN];
2321642eb1aSMark Murray 
2331642eb1aSMark Murray 	pam_std_option(&options, other_options, argc, argv);
2341642eb1aSMark Murray 
2351642eb1aSMark Murray 	PAM_LOG("Options processed");
236d65b34dbSJohn Polstra 
237111ccd25SDag-Erling Smørgrav 	retval = pam_get_user(pamh, &user, NULL);
238e9cc7b1dSDag-Erling Smørgrav 	if (retval != PAM_SUCCESS)
239e9cc7b1dSDag-Erling Smørgrav 		PAM_RETURN(retval);
240d65b34dbSJohn Polstra 
241e9cc7b1dSDag-Erling Smørgrav 	if (user == NULL || (pwd = getpwnam(user)) == NULL)
242e9cc7b1dSDag-Erling Smørgrav 		PAM_RETURN(PAM_SERVICE_ERR);
2431642eb1aSMark Murray 
2441642eb1aSMark Murray 	PAM_LOG("Got user: %s", user);
245d65b34dbSJohn Polstra 
246e9cc7b1dSDag-Erling Smørgrav 	retval = pam_get_item(pamh, PAM_RHOST, (const void **)&rhost);
247e9cc7b1dSDag-Erling Smørgrav 	if (retval != PAM_SUCCESS)
248e9cc7b1dSDag-Erling Smørgrav 		PAM_RETURN(retval);
249d65b34dbSJohn Polstra 
250e9cc7b1dSDag-Erling Smørgrav 	retval = pam_get_item(pamh, PAM_TTY, (const void **)&tty);
251e9cc7b1dSDag-Erling Smørgrav 	if (retval != PAM_SUCCESS)
252e9cc7b1dSDag-Erling Smørgrav 		PAM_RETURN(retval);
253d65b34dbSJohn Polstra 
254e9cc7b1dSDag-Erling Smørgrav 	if (*pwd->pw_passwd == '\0' &&
255e9cc7b1dSDag-Erling Smørgrav 	    (flags & PAM_DISALLOW_NULL_AUTHTOK) != 0)
256e9cc7b1dSDag-Erling Smørgrav 		return (PAM_NEW_AUTHTOK_REQD);
257e9cc7b1dSDag-Erling Smørgrav 
258e9cc7b1dSDag-Erling Smørgrav 	lc = login_getpwclass(pwd);
259e9cc7b1dSDag-Erling Smørgrav 	if (lc == NULL) {
260e9cc7b1dSDag-Erling Smørgrav 		PAM_LOG("Unable to get login class for user %s", user);
261e9cc7b1dSDag-Erling Smørgrav 		return (PAM_SERVICE_ERR);
262e9cc7b1dSDag-Erling Smørgrav 	}
263d65b34dbSJohn Polstra 
2641642eb1aSMark Murray 	PAM_LOG("Got login_cap");
2651642eb1aSMark Murray 
266e9cc7b1dSDag-Erling Smørgrav 	if (pwd->pw_change || pwd->pw_expire)
267e9cc7b1dSDag-Erling Smørgrav 		gettimeofday(&tp, NULL);
268d65b34dbSJohn Polstra 
269e9cc7b1dSDag-Erling Smørgrav 	/*
270e9cc7b1dSDag-Erling Smørgrav 	 * Check pw_expire before pw_change - no point in letting the
271e9cc7b1dSDag-Erling Smørgrav 	 * user change the password on an expired account.
272e9cc7b1dSDag-Erling Smørgrav 	 */
273d65b34dbSJohn Polstra 
274e9cc7b1dSDag-Erling Smørgrav 	if (pwd->pw_expire) {
275e9cc7b1dSDag-Erling Smørgrav 		warntime = login_getcaptime(lc, "warnexpire",
276e9cc7b1dSDag-Erling Smørgrav 		    DEFAULT_WARN, DEFAULT_WARN);
277e9cc7b1dSDag-Erling Smørgrav 		if (tp.tv_sec >= pwd->pw_expire) {
278e9cc7b1dSDag-Erling Smørgrav 			login_close(lc);
279e9cc7b1dSDag-Erling Smørgrav 			PAM_RETURN(PAM_ACCT_EXPIRED);
280e9cc7b1dSDag-Erling Smørgrav 		} else if (pwd->pw_expire - tp.tv_sec < warntime &&
281e9cc7b1dSDag-Erling Smørgrav 		    (flags & PAM_SILENT) == 0) {
282519b6a4cSDag-Erling Smørgrav 			pam_error(pamh, "Warning: your account expires on %s",
283e9cc7b1dSDag-Erling Smørgrav 			    ctime(&pwd->pw_expire));
284d65b34dbSJohn Polstra 		}
285d65b34dbSJohn Polstra 	}
286d65b34dbSJohn Polstra 
287e9cc7b1dSDag-Erling Smørgrav 	retval = PAM_SUCCESS;
288e9cc7b1dSDag-Erling Smørgrav 	if (pwd->pw_change) {
289e9cc7b1dSDag-Erling Smørgrav 		warntime = login_getcaptime(lc, "warnpassword",
290e9cc7b1dSDag-Erling Smørgrav 		    DEFAULT_WARN, DEFAULT_WARN);
291e9cc7b1dSDag-Erling Smørgrav 		if (tp.tv_sec >= pwd->pw_change) {
292e9cc7b1dSDag-Erling Smørgrav 			retval = PAM_NEW_AUTHTOK_REQD;
293e9cc7b1dSDag-Erling Smørgrav 		} else if (pwd->pw_change - tp.tv_sec < warntime &&
294e9cc7b1dSDag-Erling Smørgrav 		    (flags & PAM_SILENT) == 0) {
295519b6a4cSDag-Erling Smørgrav 			pam_error(pamh, "Warning: your password expires on %s",
296e9cc7b1dSDag-Erling Smørgrav 			    ctime(&pwd->pw_change));
297e9cc7b1dSDag-Erling Smørgrav 		}
298e9cc7b1dSDag-Erling Smørgrav 	}
299e9cc7b1dSDag-Erling Smørgrav 
300e9cc7b1dSDag-Erling Smørgrav 	/*
301e9cc7b1dSDag-Erling Smørgrav 	 * From here on, we must leave retval untouched (unless we
302e9cc7b1dSDag-Erling Smørgrav 	 * know we're going to fail), because we need to remember
303e9cc7b1dSDag-Erling Smørgrav 	 * whether we're supposed to return PAM_SUCCESS or
304e9cc7b1dSDag-Erling Smørgrav 	 * PAM_NEW_AUTHTOK_REQD.
305e9cc7b1dSDag-Erling Smørgrav 	 */
306e9cc7b1dSDag-Erling Smørgrav 
307e9cc7b1dSDag-Erling Smørgrav 	if (rhost) {
308e9cc7b1dSDag-Erling Smørgrav 		memset(&hints, 0, sizeof(hints));
309e9cc7b1dSDag-Erling Smørgrav 		hints.ai_family = AF_UNSPEC;
310e9cc7b1dSDag-Erling Smørgrav 		if (getaddrinfo(rhost, NULL, &hints, &res) == 0) {
311e9cc7b1dSDag-Erling Smørgrav 			getnameinfo(res->ai_addr, res->ai_addrlen,
312e9cc7b1dSDag-Erling Smørgrav 			    rhostip, sizeof(rhostip), NULL, 0,
313e9cc7b1dSDag-Erling Smørgrav 			    NI_NUMERICHOST|NI_WITHSCOPEID);
314e9cc7b1dSDag-Erling Smørgrav 		}
315e9cc7b1dSDag-Erling Smørgrav 		if (res != NULL)
316e9cc7b1dSDag-Erling Smørgrav 			freeaddrinfo(res);
317e9cc7b1dSDag-Erling Smørgrav 	}
318e9cc7b1dSDag-Erling Smørgrav 
319e9cc7b1dSDag-Erling Smørgrav 	/*
320e9cc7b1dSDag-Erling Smørgrav 	 * Check host / tty / time-of-day restrictions
321e9cc7b1dSDag-Erling Smørgrav 	 */
322e9cc7b1dSDag-Erling Smørgrav 
323e9cc7b1dSDag-Erling Smørgrav 	if (!auth_hostok(lc, rhost, rhostip) ||
324e9cc7b1dSDag-Erling Smørgrav 	    !auth_ttyok(lc, tty) ||
325e9cc7b1dSDag-Erling Smørgrav 	    !auth_timeok(lc, time(NULL)))
326e9cc7b1dSDag-Erling Smørgrav 		retval = PAM_AUTH_ERR;
327e9cc7b1dSDag-Erling Smørgrav 
328d65b34dbSJohn Polstra 	login_close(lc);
3291642eb1aSMark Murray 
3301642eb1aSMark Murray 	PAM_RETURN(retval);
331d65b34dbSJohn Polstra }
332d65b34dbSJohn Polstra 
3333d55a6c0SMark Murray /*
3343d55a6c0SMark Murray  * session management
3353d55a6c0SMark Murray  *
3363d55a6c0SMark Murray  * logging only
3373d55a6c0SMark Murray  */
3383d55a6c0SMark Murray PAM_EXTERN int
339ac569969SMark Murray pam_sm_open_session(pam_handle_t *pamh __unused, int flags __unused, int argc, const char **argv)
3403d55a6c0SMark Murray {
3413d55a6c0SMark Murray 	struct options options;
3423d55a6c0SMark Murray 
3433d55a6c0SMark Murray 	pam_std_option(&options, other_options, argc, argv);
3443d55a6c0SMark Murray 
3453d55a6c0SMark Murray 	PAM_LOG("Options processed");
3463d55a6c0SMark Murray 
3473d55a6c0SMark Murray 	PAM_RETURN(PAM_SUCCESS);
3483d55a6c0SMark Murray }
3493d55a6c0SMark Murray 
3503d55a6c0SMark Murray PAM_EXTERN int
351ac569969SMark Murray pam_sm_close_session(pam_handle_t *pamh __unused, int flags __unused, int argc, const char **argv)
3523d55a6c0SMark Murray {
3533d55a6c0SMark Murray 	struct options options;
3543d55a6c0SMark Murray 
3553d55a6c0SMark Murray 	pam_std_option(&options, other_options, argc, argv);
3563d55a6c0SMark Murray 
3573d55a6c0SMark Murray 	PAM_LOG("Options processed");
3583d55a6c0SMark Murray 
3593d55a6c0SMark Murray 	PAM_RETURN(PAM_SUCCESS);
3603d55a6c0SMark Murray }
3613d55a6c0SMark Murray 
3623d55a6c0SMark Murray /*
3633d55a6c0SMark Murray  * password management
3643d55a6c0SMark Murray  *
3653d55a6c0SMark Murray  * standard Unix and NIS password changing
3663d55a6c0SMark Murray  */
3673d55a6c0SMark Murray PAM_EXTERN int
3683d55a6c0SMark Murray pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
3693d55a6c0SMark Murray {
3703d55a6c0SMark Murray 	struct options options;
3713d55a6c0SMark Murray 	struct passwd *pwd;
372111ccd25SDag-Erling Smørgrav 	const char *user, *pass, *new_pass;
373111ccd25SDag-Erling Smørgrav 	char *encrypted, *usrdup;
374111ccd25SDag-Erling Smørgrav 	int retval, res;
3753d55a6c0SMark Murray 
3763d55a6c0SMark Murray 	pam_std_option(&options, other_options, argc, argv);
3773d55a6c0SMark Murray 
3783d55a6c0SMark Murray 	PAM_LOG("Options processed");
3793d55a6c0SMark Murray 
3803d55a6c0SMark Murray 	if (pam_test_option(&options, PAM_OPT_AUTH_AS_SELF, NULL))
3813d55a6c0SMark Murray 		pwd = getpwnam(getlogin());
3823d55a6c0SMark Murray 	else {
3833d55a6c0SMark Murray 		retval = pam_get_user(pamh, &user, NULL);
3843d55a6c0SMark Murray 		if (retval != PAM_SUCCESS)
3853d55a6c0SMark Murray 			PAM_RETURN(retval);
3863d55a6c0SMark Murray 		pwd = getpwnam(user);
3873d55a6c0SMark Murray 	}
3883d55a6c0SMark Murray 
3893d55a6c0SMark Murray 	PAM_LOG("Got user: %s", user);
3903d55a6c0SMark Murray 
3913d55a6c0SMark Murray 	if (flags & PAM_PRELIM_CHECK) {
3923d55a6c0SMark Murray 
3933d55a6c0SMark Murray 		PAM_LOG("PRELIM round; checking user password");
3943d55a6c0SMark Murray 
3953d55a6c0SMark Murray 		if (pwd->pw_passwd[0] == '\0'
3963d55a6c0SMark Murray 		    && pam_test_option(&options, PAM_OPT_NULLOK, NULL)) {
3973d55a6c0SMark Murray 			/*
3983d55a6c0SMark Murray 			 * No password case. XXX Are we giving too much away
3993d55a6c0SMark Murray 			 * by not prompting for a password?
400111ccd25SDag-Erling Smørgrav 			 * XXX check PAM_DISALLOW_NULL_AUTHTOK
4013d55a6c0SMark Murray 			 */
402111ccd25SDag-Erling Smørgrav 			PAM_LOG("Got password");
4033d55a6c0SMark Murray 			PAM_RETURN(PAM_SUCCESS);
4043d55a6c0SMark Murray 		}
4053d55a6c0SMark Murray 		else {
406111ccd25SDag-Erling Smørgrav 			retval = pam_get_authtok(pamh,
407111ccd25SDag-Erling Smørgrav 			    PAM_OLDAUTHTOK, &pass, NULL);
4083d55a6c0SMark Murray 			if (retval != PAM_SUCCESS)
4093d55a6c0SMark Murray 				PAM_RETURN(retval);
410111ccd25SDag-Erling Smørgrav 			PAM_LOG("Got password");
4113d55a6c0SMark Murray 		}
4123d55a6c0SMark Murray 		encrypted = crypt(pass, pwd->pw_passwd);
4133d55a6c0SMark Murray 		if (pass[0] == '\0' && pwd->pw_passwd[0] != '\0')
4148c3ea588SMark Murray 			encrypted = colon;
4153d55a6c0SMark Murray 
416111ccd25SDag-Erling Smørgrav 		if (strcmp(encrypted, pwd->pw_passwd) != 0) {
417111ccd25SDag-Erling Smørgrav 			pam_set_item(pamh, PAM_OLDAUTHTOK, NULL);
4183d55a6c0SMark Murray 			PAM_RETURN(PAM_AUTH_ERR);
419111ccd25SDag-Erling Smørgrav 		}
4203d55a6c0SMark Murray 
4213d55a6c0SMark Murray 		PAM_RETURN(PAM_SUCCESS);
4223d55a6c0SMark Murray 	}
4233d55a6c0SMark Murray 	else if (flags & PAM_UPDATE_AUTHTOK) {
4243d55a6c0SMark Murray 		PAM_LOG("UPDATE round; checking user password");
4253d55a6c0SMark Murray 
426111ccd25SDag-Erling Smørgrav 		retval = pam_get_authtok(pamh, PAM_OLDAUTHTOK, &pass, NULL);
4273d55a6c0SMark Murray 		if (retval != PAM_SUCCESS)
4283d55a6c0SMark Murray 			PAM_RETURN(retval);
4293d55a6c0SMark Murray 
430111ccd25SDag-Erling Smørgrav 		PAM_LOG("Got old password");
4313d55a6c0SMark Murray 
432111ccd25SDag-Erling Smørgrav 		for (;;) {
433111ccd25SDag-Erling Smørgrav 			retval = pam_get_authtok(pamh,
434111ccd25SDag-Erling Smørgrav 			    PAM_AUTHTOK, &new_pass, NULL);
435111ccd25SDag-Erling Smørgrav 			if (retval != PAM_TRY_AGAIN)
4363d55a6c0SMark Murray 				break;
437111ccd25SDag-Erling Smørgrav 			pam_error(pamh, "Mismatch; try again, EOF to quit.");
4383d55a6c0SMark Murray 		}
4393d55a6c0SMark Murray 
440111ccd25SDag-Erling Smørgrav 		if (retval != PAM_SUCCESS) {
441111ccd25SDag-Erling Smørgrav 			PAM_VERBOSE_ERROR("Unable to get new password");
4423d55a6c0SMark Murray 			PAM_RETURN(PAM_PERM_DENIED);
4433d55a6c0SMark Murray 		}
4443d55a6c0SMark Murray 
4453d55a6c0SMark Murray 		PAM_LOG("Got new password: %s", new_pass);
4463d55a6c0SMark Murray 
4473d55a6c0SMark Murray #ifdef YP
4483d55a6c0SMark Murray 		/* If NIS is set in the passwd database, use it */
4494004c08eSDag-Erling Smørgrav 		if ((usrdup = strdup(user)) == NULL)
4504004c08eSDag-Erling Smørgrav 			PAM_RETURN(PAM_BUF_ERR);
4514004c08eSDag-Erling Smørgrav 		res = use_yp(usrdup, 0, 0);
4524004c08eSDag-Erling Smørgrav 		free(usrdup);
4533d55a6c0SMark Murray 		if (res == USER_YP_ONLY) {
4543d55a6c0SMark Murray 			if (!pam_test_option(&options, PAM_OPT_LOCAL_PASS,
4553d55a6c0SMark Murray 			    NULL))
4563d55a6c0SMark Murray 				retval = yp_passwd(user, new_pass);
4573d55a6c0SMark Murray 			else {
4583d55a6c0SMark Murray 				/* Reject 'local' flag if NIS is on and the user
4593d55a6c0SMark Murray 				 * is not local
4603d55a6c0SMark Murray 				 */
4613d55a6c0SMark Murray 				retval = PAM_PERM_DENIED;
4623d55a6c0SMark Murray 				PAM_LOG("Unknown local user: %s", user);
4633d55a6c0SMark Murray 			}
4643d55a6c0SMark Murray 		}
4653d55a6c0SMark Murray 		else if (res == USER_LOCAL_ONLY) {
4663d55a6c0SMark Murray 			if (!pam_test_option(&options, PAM_OPT_NIS_PASS, NULL))
4673d55a6c0SMark Murray 				retval = local_passwd(user, new_pass);
4683d55a6c0SMark Murray 			else {
4693d55a6c0SMark Murray 				/* Reject 'nis' flag if user is only local */
4703d55a6c0SMark Murray 				retval = PAM_PERM_DENIED;
4713d55a6c0SMark Murray 				PAM_LOG("Unknown NIS user: %s", user);
4723d55a6c0SMark Murray 			}
4733d55a6c0SMark Murray 		}
4743d55a6c0SMark Murray 		else if (res == USER_YP_AND_LOCAL) {
4753d55a6c0SMark Murray 			if (pam_test_option(&options, PAM_OPT_NIS_PASS, NULL))
4763d55a6c0SMark Murray 				retval = yp_passwd(user, new_pass);
4773d55a6c0SMark Murray 			else
4783d55a6c0SMark Murray 				retval = local_passwd(user, new_pass);
4793d55a6c0SMark Murray 		}
4803d55a6c0SMark Murray 		else
4814004c08eSDag-Erling Smørgrav 			retval = PAM_SERVICE_ERR; /* Bad juju */
4823d55a6c0SMark Murray #else
4833d55a6c0SMark Murray 		retval = local_passwd(user, new_pass);
4843d55a6c0SMark Murray #endif
4853d55a6c0SMark Murray 	}
4863d55a6c0SMark Murray 	else {
4873d55a6c0SMark Murray 		/* Very bad juju */
4883d55a6c0SMark Murray 		retval = PAM_ABORT;
4893d55a6c0SMark Murray 		PAM_LOG("Illegal 'flags'");
4903d55a6c0SMark Murray 	}
4913d55a6c0SMark Murray 
4923d55a6c0SMark Murray 	PAM_RETURN(retval);
4933d55a6c0SMark Murray }
4943d55a6c0SMark Murray 
4953d55a6c0SMark Murray /* Mostly stolen from passwd(1)'s local_passwd.c - markm */
4963d55a6c0SMark Murray 
4973d55a6c0SMark Murray static unsigned char itoa64[] =		/* 0 ... 63 => ascii - 64 */
4983d55a6c0SMark Murray 	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
4993d55a6c0SMark Murray 
5003d55a6c0SMark Murray static void
5013d55a6c0SMark Murray to64(char *s, long v, int n)
5023d55a6c0SMark Murray {
5033d55a6c0SMark Murray 	while (--n >= 0) {
5043d55a6c0SMark Murray 		*s++ = itoa64[v&0x3f];
5053d55a6c0SMark Murray 		v >>= 6;
5063d55a6c0SMark Murray 	}
5073d55a6c0SMark Murray }
5083d55a6c0SMark Murray 
5093d55a6c0SMark Murray static int
5103d55a6c0SMark Murray local_passwd(const char *user, const char *pass)
5113d55a6c0SMark Murray {
5123d55a6c0SMark Murray 	login_cap_t * lc;
5133d55a6c0SMark Murray 	struct passwd *pwd;
5143d55a6c0SMark Murray 	int pfd, tfd;
5158c3ea588SMark Murray 	char *crypt_type, salt[SALTSIZE + 1];
5163d55a6c0SMark Murray 
5173d55a6c0SMark Murray 	pwd = getpwnam(user);
5183d55a6c0SMark Murray 	if (pwd == NULL)
5194004c08eSDag-Erling Smørgrav 		return(PAM_SERVICE_ERR); /* Really bad things */
5203d55a6c0SMark Murray 
5213d55a6c0SMark Murray #ifdef YP
5223d55a6c0SMark Murray 	pwd = (struct passwd *)&local_password;
5233d55a6c0SMark Murray #endif
5243d55a6c0SMark Murray 	pw_init();
5253d55a6c0SMark Murray 
5263d55a6c0SMark Murray 	pwd->pw_change = 0;
5273d55a6c0SMark Murray 	lc = login_getclass(NULL);
5283d55a6c0SMark Murray 	crypt_type = login_getcapstr(lc, "passwd_format",
529ac569969SMark Murray 		password_hash, password_hash);
5303d55a6c0SMark Murray 	if (login_setcryptfmt(lc, crypt_type, NULL) == NULL)
5313d55a6c0SMark Murray 		syslog(LOG_ERR, "cannot set password cipher");
5323d55a6c0SMark Murray 	login_close(lc);
5338c3ea588SMark Murray 	makesalt(salt);
5343d55a6c0SMark Murray 	pwd->pw_passwd = crypt(pass, salt);
5353d55a6c0SMark Murray 
5363d55a6c0SMark Murray 	pfd = pw_lock();
5373d55a6c0SMark Murray 	tfd = pw_tmp();
53851906f45SCrist J. Clark 	pw_copy(pfd, tfd, pwd, NULL);
5393d55a6c0SMark Murray 
540ac569969SMark Murray 	if (!pw_mkdb(user))
5413d55a6c0SMark Murray 		pw_error((char *)NULL, 0, 1);
5423d55a6c0SMark Murray 
5434004c08eSDag-Erling Smørgrav 	return (PAM_SUCCESS);
5443d55a6c0SMark Murray }
5453d55a6c0SMark Murray 
5463d55a6c0SMark Murray #ifdef YP
5473d55a6c0SMark Murray /* Stolen from src/usr.bin/passwd/yp_passwd.c, carrying copyrights of:
5483d55a6c0SMark Murray  * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
5493d55a6c0SMark Murray  * Copyright (c) 1994 Olaf Kirch <okir@monad.swb.de>
5503d55a6c0SMark Murray  * Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>
5513d55a6c0SMark Murray  */
5523d55a6c0SMark Murray int
553519b6a4cSDag-Erling Smørgrav yp_passwd(const char *user __unused, const char *pass)
5543d55a6c0SMark Murray {
555111ccd25SDag-Erling Smørgrav 	struct yppasswd yppwd;
556519b6a4cSDag-Erling Smørgrav 	struct master_yppasswd master_yppwd;
5573d55a6c0SMark Murray 	struct passwd *pwd;
5583d55a6c0SMark Murray 	struct rpc_err err;
5593d55a6c0SMark Murray 	CLIENT *clnt;
5603d55a6c0SMark Murray 	login_cap_t *lc;
5613d55a6c0SMark Murray 	int    *status;
5623d55a6c0SMark Murray 	uid_t uid;
5638c3ea588SMark Murray 	char   *master, sockname[] = YP_SOCKNAME, salt[SALTSIZE + 1];
5643d55a6c0SMark Murray 
5653d55a6c0SMark Murray 	_use_yp = 1;
5663d55a6c0SMark Murray 
5673d55a6c0SMark Murray 	uid = getuid();
5683d55a6c0SMark Murray 
5693d55a6c0SMark Murray 	master = get_yp_master(1);
5703d55a6c0SMark Murray 	if (master == NULL)
5714004c08eSDag-Erling Smørgrav 		return (PAM_SERVICE_ERR); /* Major disaster */
5723d55a6c0SMark Murray 
5733d55a6c0SMark Murray 	/*
5743d55a6c0SMark Murray 	 * It is presumed that by the time we get here, use_yp()
5753d55a6c0SMark Murray 	 * has been called and that we have verified that the user
5763d55a6c0SMark Murray 	 * actually exists. This being the case, the yp_password
5773d55a6c0SMark Murray 	 * stucture has already been filled in for us.
5783d55a6c0SMark Murray 	 */
5793d55a6c0SMark Murray 
5803d55a6c0SMark Murray 	/* Use the correct password */
5813d55a6c0SMark Murray 	pwd = (struct passwd *)&yp_password;
5823d55a6c0SMark Murray 
5833d55a6c0SMark Murray 	pwd->pw_change = 0;
5843d55a6c0SMark Murray 
5853d55a6c0SMark Murray 	/* Initialize password information */
5863d55a6c0SMark Murray 	if (suser_override) {
587519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_passwd = strdup(pwd->pw_passwd);
588519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_name = strdup(pwd->pw_name);
589519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_uid = pwd->pw_uid;
590519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_gid = pwd->pw_gid;
591519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_expire = pwd->pw_expire;
592519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_change = pwd->pw_change;
593519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_fields = pwd->pw_fields;
594519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_gecos = strdup(pwd->pw_gecos);
595519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_dir = strdup(pwd->pw_dir);
596519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_shell = strdup(pwd->pw_shell);
597519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_class = pwd->pw_class != NULL ?
598ac569969SMark Murray 					strdup(pwd->pw_class) : strdup("");
599519b6a4cSDag-Erling Smørgrav 		master_yppwd.oldpass = strdup("");
600519b6a4cSDag-Erling Smørgrav 		master_yppwd.domain = yp_domain;
6013d55a6c0SMark Murray 	} else {
602519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_passwd = strdup(pwd->pw_passwd);
603519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_name = strdup(pwd->pw_name);
604519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_uid = pwd->pw_uid;
605519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_gid = pwd->pw_gid;
606519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_gecos = strdup(pwd->pw_gecos);
607519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_dir = strdup(pwd->pw_dir);
608519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_shell = strdup(pwd->pw_shell);
609519b6a4cSDag-Erling Smørgrav 		yppwd.oldpass = strdup("");
6103d55a6c0SMark Murray 	}
6113d55a6c0SMark Murray 
6123d55a6c0SMark Murray 	if (login_setcryptfmt(lc, "md5", NULL) == NULL)
6133d55a6c0SMark Murray 		syslog(LOG_ERR, "cannot set password cipher");
6143d55a6c0SMark Murray 	login_close(lc);
6153d55a6c0SMark Murray 
6168c3ea588SMark Murray 	makesalt(salt);
6173d55a6c0SMark Murray 	if (suser_override)
618519b6a4cSDag-Erling Smørgrav 		master_yppwd.newpw.pw_passwd = crypt(pass, salt);
6193d55a6c0SMark Murray 	else
620519b6a4cSDag-Erling Smørgrav 		yppwd.newpw.pw_passwd = crypt(pass, salt);
6213d55a6c0SMark Murray 
6223d55a6c0SMark Murray 	if (suser_override) {
6233d55a6c0SMark Murray 		if ((clnt = clnt_create(sockname, MASTER_YPPASSWDPROG,
6243d55a6c0SMark Murray 		    MASTER_YPPASSWDVERS, "unix")) == NULL) {
6253d55a6c0SMark Murray 			syslog(LOG_ERR,
6263d55a6c0SMark Murray 			    "Cannot contact rpc.yppasswdd on host %s: %s",
6273d55a6c0SMark Murray 			    master, clnt_spcreateerror(""));
6284004c08eSDag-Erling Smørgrav 			return (PAM_SERVICE_ERR);
6293d55a6c0SMark Murray 		}
6303d55a6c0SMark Murray 	}
6313d55a6c0SMark Murray 	else {
6323d55a6c0SMark Murray 		if ((clnt = clnt_create(master, YPPASSWDPROG,
6333d55a6c0SMark Murray 		    YPPASSWDVERS, "udp")) == NULL) {
6343d55a6c0SMark Murray 			syslog(LOG_ERR,
6353d55a6c0SMark Murray 			    "Cannot contact rpc.yppasswdd on host %s: %s",
6363d55a6c0SMark Murray 			    master, clnt_spcreateerror(""));
6374004c08eSDag-Erling Smørgrav 			return (PAM_SERVICE_ERR);
6383d55a6c0SMark Murray 		}
6393d55a6c0SMark Murray 	}
6403d55a6c0SMark Murray 	/*
6413d55a6c0SMark Murray 	 * The yppasswd.x file said `unix authentication required',
6423d55a6c0SMark Murray 	 * so I added it. This is the only reason it is in here.
6433d55a6c0SMark Murray 	 * My yppasswdd doesn't use it, but maybe some others out there
6443d55a6c0SMark Murray 	 * do. 					--okir
6453d55a6c0SMark Murray 	 */
6463d55a6c0SMark Murray 	clnt->cl_auth = authunix_create_default();
6473d55a6c0SMark Murray 
6483d55a6c0SMark Murray 	if (suser_override)
649519b6a4cSDag-Erling Smørgrav 		status = yppasswdproc_update_master_1(&master_yppwd, clnt);
6503d55a6c0SMark Murray 	else
651519b6a4cSDag-Erling Smørgrav 		status = yppasswdproc_update_1(&yppwd, clnt);
6523d55a6c0SMark Murray 
6533d55a6c0SMark Murray 	clnt_geterr(clnt, &err);
6543d55a6c0SMark Murray 
6553d55a6c0SMark Murray 	auth_destroy(clnt->cl_auth);
6563d55a6c0SMark Murray 	clnt_destroy(clnt);
6573d55a6c0SMark Murray 
6583d55a6c0SMark Murray 	if (err.re_status != RPC_SUCCESS || status == NULL || *status)
6594004c08eSDag-Erling Smørgrav 		return (PAM_SERVICE_ERR);
6603d55a6c0SMark Murray 
6614004c08eSDag-Erling Smørgrav 	if (err.re_status || status == NULL || *status)
6624004c08eSDag-Erling Smørgrav 		return (PAM_SERVICE_ERR);
6634004c08eSDag-Erling Smørgrav 	return (PAM_SUCCESS);
6643d55a6c0SMark Murray }
6653d55a6c0SMark Murray #endif /* YP */
6663d55a6c0SMark Murray 
6678c3ea588SMark Murray /* Salt suitable for traditional DES and MD5 */
6688c3ea588SMark Murray void
6698c3ea588SMark Murray makesalt(char salt[SALTSIZE])
6708c3ea588SMark Murray {
6718c3ea588SMark Murray 	int i;
6728c3ea588SMark Murray 
6738c3ea588SMark Murray 	/* These are not really random numbers, they are just
6748c3ea588SMark Murray 	 * numbers that change to thwart construction of a
6758c3ea588SMark Murray 	 * dictionary. This is exposed to the public.
6768c3ea588SMark Murray 	 */
6778c3ea588SMark Murray 	for (i = 0; i < SALTSIZE; i += 4)
6788c3ea588SMark Murray 		to64(&salt[i], arc4random(), 4);
6798c3ea588SMark Murray 	salt[SALTSIZE] = '\0';
6808c3ea588SMark Murray }
6818c3ea588SMark Murray 
6829294327dSJohn Polstra PAM_MODULE_ENTRY("pam_unix");
683