xref: /freebsd/lib/libpam/modules/pam_exec/pam_exec.c (revision 7e3d5c1fca5f9648f1b47dc0e1499f32029c73ca)
1f65b2180SDag-Erling Smørgrav /*-
237def36fSDag-Erling Smørgrav  * Copyright (c) 2001,2003 Networks Associates Technology, Inc.
3f65b2180SDag-Erling Smørgrav  * All rights reserved.
4f65b2180SDag-Erling Smørgrav  *
5f65b2180SDag-Erling Smørgrav  * This software was developed for the FreeBSD Project by ThinkSec AS and
6f65b2180SDag-Erling Smørgrav  * NAI Labs, the Security Research Division of Network Associates, Inc.
7f65b2180SDag-Erling Smørgrav  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
8f65b2180SDag-Erling Smørgrav  * DARPA CHATS research program.
9f65b2180SDag-Erling Smørgrav  *
10f65b2180SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
11f65b2180SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
12f65b2180SDag-Erling Smørgrav  * are met:
13f65b2180SDag-Erling Smørgrav  * 1. Redistributions of source code must retain the above copyright
14f65b2180SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer.
15f65b2180SDag-Erling Smørgrav  * 2. Redistributions in binary form must reproduce the above copyright
16f65b2180SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer in the
17f65b2180SDag-Erling Smørgrav  *    documentation and/or other materials provided with the distribution.
18f65b2180SDag-Erling Smørgrav  * 3. The name of the author may not be used to endorse or promote
19f65b2180SDag-Erling Smørgrav  *    products derived from this software without specific prior written
20f65b2180SDag-Erling Smørgrav  *    permission.
21f65b2180SDag-Erling Smørgrav  *
22f65b2180SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23f65b2180SDag-Erling Smørgrav  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24f65b2180SDag-Erling Smørgrav  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25f65b2180SDag-Erling Smørgrav  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26f65b2180SDag-Erling Smørgrav  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27f65b2180SDag-Erling Smørgrav  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28f65b2180SDag-Erling Smørgrav  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29f65b2180SDag-Erling Smørgrav  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30f65b2180SDag-Erling Smørgrav  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31f65b2180SDag-Erling Smørgrav  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32f65b2180SDag-Erling Smørgrav  * SUCH DAMAGE.
33f65b2180SDag-Erling Smørgrav  */
34f65b2180SDag-Erling Smørgrav 
35f65b2180SDag-Erling Smørgrav #include <sys/cdefs.h>
36f65b2180SDag-Erling Smørgrav __FBSDID("$FreeBSD$");
37f65b2180SDag-Erling Smørgrav 
38f65b2180SDag-Erling Smørgrav #include <sys/types.h>
39f65b2180SDag-Erling Smørgrav #include <sys/wait.h>
40f65b2180SDag-Erling Smørgrav 
41f65b2180SDag-Erling Smørgrav #include <errno.h>
428bdb099aSEd Schouten #include <stdio.h>
43f65b2180SDag-Erling Smørgrav #include <stdlib.h>
44f65b2180SDag-Erling Smørgrav #include <string.h>
45f65b2180SDag-Erling Smørgrav #include <unistd.h>
46f65b2180SDag-Erling Smørgrav 
47f65b2180SDag-Erling Smørgrav #include <security/pam_appl.h>
48f65b2180SDag-Erling Smørgrav #include <security/pam_modules.h>
49f65b2180SDag-Erling Smørgrav #include <security/openpam.h>
50f65b2180SDag-Erling Smørgrav 
519d97c7eeSDag-Erling Smørgrav #define ENV_ITEM(n) { (n), #n }
529d97c7eeSDag-Erling Smørgrav static struct {
539d97c7eeSDag-Erling Smørgrav 	int item;
549d97c7eeSDag-Erling Smørgrav 	const char *name;
559d97c7eeSDag-Erling Smørgrav } env_items[] = {
569d97c7eeSDag-Erling Smørgrav 	ENV_ITEM(PAM_SERVICE),
579d97c7eeSDag-Erling Smørgrav 	ENV_ITEM(PAM_USER),
589d97c7eeSDag-Erling Smørgrav 	ENV_ITEM(PAM_TTY),
599d97c7eeSDag-Erling Smørgrav 	ENV_ITEM(PAM_RHOST),
609d97c7eeSDag-Erling Smørgrav 	ENV_ITEM(PAM_RUSER),
619d97c7eeSDag-Erling Smørgrav };
629d97c7eeSDag-Erling Smørgrav 
63*7e3d5c1fSJean-Sébastien Pédron #define	PAM_RV_COUNT 24
64*7e3d5c1fSJean-Sébastien Pédron 
65f65b2180SDag-Erling Smørgrav static int
66*7e3d5c1fSJean-Sébastien Pédron _pam_exec(pam_handle_t *pamh __unused,
67*7e3d5c1fSJean-Sébastien Pédron     const char *func, int flags __unused, int argc, const char *argv[])
68f65b2180SDag-Erling Smørgrav {
69*7e3d5c1fSJean-Sébastien Pédron 	int envlen, i, nitems, pam_err, status, return_prog_exit_status;
70*7e3d5c1fSJean-Sébastien Pédron 	int nitems_rv;
71*7e3d5c1fSJean-Sébastien Pédron 	char *env, **envlist, **tmp, *envstr;
721cede0c9SDag-Erling Smørgrav 	volatile int childerr;
73f65b2180SDag-Erling Smørgrav 	pid_t pid;
74f65b2180SDag-Erling Smørgrav 
75f65b2180SDag-Erling Smørgrav 	/*
76f65b2180SDag-Erling Smørgrav 	 * XXX For additional credit, divert child's stdin/stdout/stderr
77f65b2180SDag-Erling Smørgrav 	 * to the conversation function.
78f65b2180SDag-Erling Smørgrav 	 */
799d97c7eeSDag-Erling Smørgrav 
809d97c7eeSDag-Erling Smørgrav 	/*
81*7e3d5c1fSJean-Sébastien Pédron 	 * Parse options:
82*7e3d5c1fSJean-Sébastien Pédron 	 *   return_prog_exit_status:
83*7e3d5c1fSJean-Sébastien Pédron 	 *     use the program exit status as the return code of pam_exec
84*7e3d5c1fSJean-Sébastien Pédron 	 *   --:
85*7e3d5c1fSJean-Sébastien Pédron 	 *     stop options parsing; what follows is the command to execute
86*7e3d5c1fSJean-Sébastien Pédron 	 */
87*7e3d5c1fSJean-Sébastien Pédron 	return_prog_exit_status = 0;
88*7e3d5c1fSJean-Sébastien Pédron 	for (i = 0; i < argc; ++i) {
89*7e3d5c1fSJean-Sébastien Pédron 		if (strcmp(argv[i], "return_prog_exit_status") == 0) {
90*7e3d5c1fSJean-Sébastien Pédron 			openpam_log(PAM_LOG_DEBUG,
91*7e3d5c1fSJean-Sébastien Pédron 			    "%s: Option \"return_prog_exit_status\" enabled",
92*7e3d5c1fSJean-Sébastien Pédron 			    func);
93*7e3d5c1fSJean-Sébastien Pédron 			return_prog_exit_status = 1;
94*7e3d5c1fSJean-Sébastien Pédron 		} else {
95*7e3d5c1fSJean-Sébastien Pédron 			if (strcmp(argv[i], "--") == 0) {
96*7e3d5c1fSJean-Sébastien Pédron 				argc--;
97*7e3d5c1fSJean-Sébastien Pédron 				argv++;
98*7e3d5c1fSJean-Sébastien Pédron 			}
99*7e3d5c1fSJean-Sébastien Pédron 
100*7e3d5c1fSJean-Sébastien Pédron 			break;
101*7e3d5c1fSJean-Sébastien Pédron 		}
102*7e3d5c1fSJean-Sébastien Pédron 	}
103*7e3d5c1fSJean-Sébastien Pédron 
104*7e3d5c1fSJean-Sébastien Pédron 	argc -= i;
105*7e3d5c1fSJean-Sébastien Pédron 	argv += i;
106*7e3d5c1fSJean-Sébastien Pédron 
107*7e3d5c1fSJean-Sébastien Pédron 	/* Check there's a program name left after parsing options. */
108*7e3d5c1fSJean-Sébastien Pédron 	if (argc < 1) {
109*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s: No program specified: aborting",
110*7e3d5c1fSJean-Sébastien Pédron 		    func);
111*7e3d5c1fSJean-Sébastien Pédron 		return (PAM_SERVICE_ERR);
112*7e3d5c1fSJean-Sébastien Pédron 	}
113*7e3d5c1fSJean-Sébastien Pédron 
114*7e3d5c1fSJean-Sébastien Pédron 	/*
1159d97c7eeSDag-Erling Smørgrav 	 * Set up the child's environment list. It consists of the PAM
116*7e3d5c1fSJean-Sébastien Pédron 	 * environment, plus a few hand-picked PAM items, the pam_sm_*
117*7e3d5c1fSJean-Sébastien Pédron 	 * function name calling it and, if return_prog_exit_status is
118*7e3d5c1fSJean-Sébastien Pédron 	 * set, the valid return codes numerical values.
1199d97c7eeSDag-Erling Smørgrav 	 */
120a76a4d44SDag-Erling Smørgrav 	envlist = pam_getenvlist(pamh);
1219d97c7eeSDag-Erling Smørgrav 	for (envlen = 0; envlist[envlen] != NULL; ++envlen)
1229d97c7eeSDag-Erling Smørgrav 		/* nothing */ ;
1239d97c7eeSDag-Erling Smørgrav 	nitems = sizeof(env_items) / sizeof(*env_items);
124*7e3d5c1fSJean-Sébastien Pédron 	/* Count PAM return values put in the environment. */
125*7e3d5c1fSJean-Sébastien Pédron 	nitems_rv = return_prog_exit_status ? PAM_RV_COUNT : 0;
126*7e3d5c1fSJean-Sébastien Pédron 	tmp = realloc(envlist, (envlen + nitems + 1 + nitems_rv + 1) *
127*7e3d5c1fSJean-Sébastien Pédron 	    sizeof(*envlist));
1289d97c7eeSDag-Erling Smørgrav 	if (tmp == NULL) {
1299d97c7eeSDag-Erling Smørgrav 		openpam_free_envlist(envlist);
1309d97c7eeSDag-Erling Smørgrav 		return (PAM_BUF_ERR);
1319d97c7eeSDag-Erling Smørgrav 	}
1329d97c7eeSDag-Erling Smørgrav 	envlist = tmp;
1339d97c7eeSDag-Erling Smørgrav 	for (i = 0; i < nitems; ++i) {
1349d97c7eeSDag-Erling Smørgrav 		const void *item;
1359d97c7eeSDag-Erling Smørgrav 
1369d97c7eeSDag-Erling Smørgrav 		pam_err = pam_get_item(pamh, env_items[i].item, &item);
1379d97c7eeSDag-Erling Smørgrav 		if (pam_err != PAM_SUCCESS || item == NULL)
1389d97c7eeSDag-Erling Smørgrav 			continue;
1399d97c7eeSDag-Erling Smørgrav 		asprintf(&envstr, "%s=%s", env_items[i].name, item);
1409d97c7eeSDag-Erling Smørgrav 		if (envstr == NULL) {
1419d97c7eeSDag-Erling Smørgrav 			openpam_free_envlist(envlist);
1429d97c7eeSDag-Erling Smørgrav 			return (PAM_BUF_ERR);
1439d97c7eeSDag-Erling Smørgrav 		}
1449d97c7eeSDag-Erling Smørgrav 		envlist[envlen++] = envstr;
1459d97c7eeSDag-Erling Smørgrav 		envlist[envlen] = NULL;
1469d97c7eeSDag-Erling Smørgrav 	}
1479d97c7eeSDag-Erling Smørgrav 
148*7e3d5c1fSJean-Sébastien Pédron 	/* Add the pam_sm_* function name to the environment. */
149*7e3d5c1fSJean-Sébastien Pédron 	asprintf(&envstr, "PAM_SM_FUNC=%s", func);
150*7e3d5c1fSJean-Sébastien Pédron 	if (envstr == NULL) {
151*7e3d5c1fSJean-Sébastien Pédron 		openpam_free_envlist(envlist);
152*7e3d5c1fSJean-Sébastien Pédron 		return (PAM_BUF_ERR);
153*7e3d5c1fSJean-Sébastien Pédron 	}
154*7e3d5c1fSJean-Sébastien Pédron 	envlist[envlen++] = envstr;
155*7e3d5c1fSJean-Sébastien Pédron 
156*7e3d5c1fSJean-Sébastien Pédron 	/* Add the PAM return values to the environment. */
157*7e3d5c1fSJean-Sébastien Pédron 	if (return_prog_exit_status) {
158*7e3d5c1fSJean-Sébastien Pédron #define	ADD_PAM_RV_TO_ENV(name)						\
159*7e3d5c1fSJean-Sébastien Pédron 		asprintf(&envstr, #name "=%d", name);			\
160*7e3d5c1fSJean-Sébastien Pédron 		if (envstr == NULL) {					\
161*7e3d5c1fSJean-Sébastien Pédron 			openpam_free_envlist(envlist);			\
162*7e3d5c1fSJean-Sébastien Pédron 			return (PAM_BUF_ERR);				\
163*7e3d5c1fSJean-Sébastien Pédron 		}							\
164*7e3d5c1fSJean-Sébastien Pédron 		envlist[envlen++] = envstr
165*7e3d5c1fSJean-Sébastien Pédron 		/*
166*7e3d5c1fSJean-Sébastien Pédron 		 * CAUTION: When adding/removing an item in the list
167*7e3d5c1fSJean-Sébastien Pédron 		 * below, be sure to update the value of PAM_RV_COUNT.
168*7e3d5c1fSJean-Sébastien Pédron 		 */
169*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_ABORT);
170*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_ACCT_EXPIRED);
171*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_AUTHINFO_UNAVAIL);
172*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_AUTHTOK_DISABLE_AGING);
173*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_AUTHTOK_ERR);
174*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_AUTHTOK_LOCK_BUSY);
175*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_AUTHTOK_RECOVERY_ERR);
176*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_AUTH_ERR);
177*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_BUF_ERR);
178*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_CONV_ERR);
179*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_CRED_ERR);
180*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_CRED_EXPIRED);
181*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_CRED_INSUFFICIENT);
182*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_CRED_UNAVAIL);
183*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_IGNORE);
184*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_MAXTRIES);
185*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_NEW_AUTHTOK_REQD);
186*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_PERM_DENIED);
187*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_SERVICE_ERR);
188*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_SESSION_ERR);
189*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_SUCCESS);
190*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_SYSTEM_ERR);
191*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_TRY_AGAIN);
192*7e3d5c1fSJean-Sébastien Pédron 		ADD_PAM_RV_TO_ENV(PAM_USER_UNKNOWN);
193*7e3d5c1fSJean-Sébastien Pédron 	}
194*7e3d5c1fSJean-Sébastien Pédron 
195*7e3d5c1fSJean-Sébastien Pédron 	envlist[envlen] = NULL;
196*7e3d5c1fSJean-Sébastien Pédron 
1979d97c7eeSDag-Erling Smørgrav 	/*
1989d97c7eeSDag-Erling Smørgrav 	 * Fork and run the command.  By using vfork() instead of fork(),
1999d97c7eeSDag-Erling Smørgrav 	 * we can distinguish between an execve() failure and a non-zero
200*7e3d5c1fSJean-Sébastien Pédron 	 * exit status from the command.
2019d97c7eeSDag-Erling Smørgrav 	 */
202f65b2180SDag-Erling Smørgrav 	childerr = 0;
203f65b2180SDag-Erling Smørgrav 	if ((pid = vfork()) == 0) {
2049d97c7eeSDag-Erling Smørgrav 		execve(argv[0], (char * const *)argv, (char * const *)envlist);
205f65b2180SDag-Erling Smørgrav 		childerr = errno;
206f65b2180SDag-Erling Smørgrav 		_exit(1);
207a76a4d44SDag-Erling Smørgrav 	}
2089d97c7eeSDag-Erling Smørgrav 	openpam_free_envlist(envlist);
209a76a4d44SDag-Erling Smørgrav 	if (pid == -1) {
210*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s: vfork(): %m", func);
211f65b2180SDag-Erling Smørgrav 		return (PAM_SYSTEM_ERR);
212f65b2180SDag-Erling Smørgrav 	}
213*7e3d5c1fSJean-Sébastien Pédron 	while (waitpid(pid, &status, 0) == -1) {
214*7e3d5c1fSJean-Sébastien Pédron 		if (errno == EINTR)
215*7e3d5c1fSJean-Sébastien Pédron 			continue;
216*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s: waitpid(): %m", func);
217f65b2180SDag-Erling Smørgrav 		return (PAM_SYSTEM_ERR);
218f65b2180SDag-Erling Smørgrav 	}
219f65b2180SDag-Erling Smørgrav 	if (childerr != 0) {
220*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s: execve(): %m", func);
221f65b2180SDag-Erling Smørgrav 		return (PAM_SYSTEM_ERR);
222f65b2180SDag-Erling Smørgrav 	}
223f65b2180SDag-Erling Smørgrav 	if (WIFSIGNALED(status)) {
224*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s: %s caught signal %d%s",
225*7e3d5c1fSJean-Sébastien Pédron 		    func, argv[0], WTERMSIG(status),
226f65b2180SDag-Erling Smørgrav 		    WCOREDUMP(status) ? " (core dumped)" : "");
227*7e3d5c1fSJean-Sébastien Pédron 		return (PAM_SERVICE_ERR);
228f65b2180SDag-Erling Smørgrav 	}
229f65b2180SDag-Erling Smørgrav 	if (!WIFEXITED(status)) {
230*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s: unknown status 0x%x",
231*7e3d5c1fSJean-Sébastien Pédron 		    func, status);
232*7e3d5c1fSJean-Sébastien Pédron 		return (PAM_SERVICE_ERR);
233f65b2180SDag-Erling Smørgrav 	}
234*7e3d5c1fSJean-Sébastien Pédron 
235*7e3d5c1fSJean-Sébastien Pédron 	if (return_prog_exit_status) {
236*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_DEBUG,
237*7e3d5c1fSJean-Sébastien Pédron 		    "%s: Use program exit status as return value: %d",
238*7e3d5c1fSJean-Sébastien Pédron 		    func, WEXITSTATUS(status));
239*7e3d5c1fSJean-Sébastien Pédron 		return (WEXITSTATUS(status));
240*7e3d5c1fSJean-Sébastien Pédron 	} else {
241*7e3d5c1fSJean-Sébastien Pédron 		return (WEXITSTATUS(status) == 0 ?
242*7e3d5c1fSJean-Sébastien Pédron 		    PAM_SUCCESS : PAM_PERM_DENIED);
243f65b2180SDag-Erling Smørgrav 	}
244f65b2180SDag-Erling Smørgrav }
245f65b2180SDag-Erling Smørgrav 
246f65b2180SDag-Erling Smørgrav PAM_EXTERN int
247f65b2180SDag-Erling Smørgrav pam_sm_authenticate(pam_handle_t *pamh, int flags,
248f65b2180SDag-Erling Smørgrav     int argc, const char *argv[])
249f65b2180SDag-Erling Smørgrav {
250*7e3d5c1fSJean-Sébastien Pédron 	int ret;
251f65b2180SDag-Erling Smørgrav 
252*7e3d5c1fSJean-Sébastien Pédron 	ret = _pam_exec(pamh, __func__, flags, argc, argv);
253*7e3d5c1fSJean-Sébastien Pédron 
254*7e3d5c1fSJean-Sébastien Pédron 	/*
255*7e3d5c1fSJean-Sébastien Pédron 	 * We must check that the program returned a valid code for this
256*7e3d5c1fSJean-Sébastien Pédron 	 * function.
257*7e3d5c1fSJean-Sébastien Pédron 	 */
258*7e3d5c1fSJean-Sébastien Pédron 	switch (ret) {
259*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SUCCESS:
260*7e3d5c1fSJean-Sébastien Pédron 	case PAM_ABORT:
261*7e3d5c1fSJean-Sébastien Pédron 	case PAM_AUTHINFO_UNAVAIL:
262*7e3d5c1fSJean-Sébastien Pédron 	case PAM_AUTH_ERR:
263*7e3d5c1fSJean-Sébastien Pédron 	case PAM_BUF_ERR:
264*7e3d5c1fSJean-Sébastien Pédron 	case PAM_CONV_ERR:
265*7e3d5c1fSJean-Sébastien Pédron 	case PAM_CRED_INSUFFICIENT:
266*7e3d5c1fSJean-Sébastien Pédron 	case PAM_IGNORE:
267*7e3d5c1fSJean-Sébastien Pédron 	case PAM_MAXTRIES:
268*7e3d5c1fSJean-Sébastien Pédron 	case PAM_PERM_DENIED:
269*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SERVICE_ERR:
270*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SYSTEM_ERR:
271*7e3d5c1fSJean-Sébastien Pédron 	case PAM_USER_UNKNOWN:
272*7e3d5c1fSJean-Sébastien Pédron 		break;
273*7e3d5c1fSJean-Sébastien Pédron 	default:
274*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
275*7e3d5c1fSJean-Sébastien Pédron 		    argv[0], ret);
276*7e3d5c1fSJean-Sébastien Pédron 		ret = PAM_SERVICE_ERR;
277*7e3d5c1fSJean-Sébastien Pédron 	}
278*7e3d5c1fSJean-Sébastien Pédron 
279*7e3d5c1fSJean-Sébastien Pédron 	return (ret);
280f65b2180SDag-Erling Smørgrav }
281f65b2180SDag-Erling Smørgrav 
282f65b2180SDag-Erling Smørgrav PAM_EXTERN int
283f65b2180SDag-Erling Smørgrav pam_sm_setcred(pam_handle_t *pamh, int flags,
284f65b2180SDag-Erling Smørgrav     int argc, const char *argv[])
285f65b2180SDag-Erling Smørgrav {
286*7e3d5c1fSJean-Sébastien Pédron 	int ret;
287f65b2180SDag-Erling Smørgrav 
288*7e3d5c1fSJean-Sébastien Pédron 	ret = _pam_exec(pamh, __func__, flags, argc, argv);
289*7e3d5c1fSJean-Sébastien Pédron 
290*7e3d5c1fSJean-Sébastien Pédron 	/*
291*7e3d5c1fSJean-Sébastien Pédron 	 * We must check that the program returned a valid code for this
292*7e3d5c1fSJean-Sébastien Pédron 	 * function.
293*7e3d5c1fSJean-Sébastien Pédron 	 */
294*7e3d5c1fSJean-Sébastien Pédron 	switch (ret) {
295*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SUCCESS:
296*7e3d5c1fSJean-Sébastien Pédron 	case PAM_ABORT:
297*7e3d5c1fSJean-Sébastien Pédron 	case PAM_BUF_ERR:
298*7e3d5c1fSJean-Sébastien Pédron 	case PAM_CONV_ERR:
299*7e3d5c1fSJean-Sébastien Pédron 	case PAM_CRED_ERR:
300*7e3d5c1fSJean-Sébastien Pédron 	case PAM_CRED_EXPIRED:
301*7e3d5c1fSJean-Sébastien Pédron 	case PAM_CRED_UNAVAIL:
302*7e3d5c1fSJean-Sébastien Pédron 	case PAM_IGNORE:
303*7e3d5c1fSJean-Sébastien Pédron 	case PAM_PERM_DENIED:
304*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SERVICE_ERR:
305*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SYSTEM_ERR:
306*7e3d5c1fSJean-Sébastien Pédron 	case PAM_USER_UNKNOWN:
307*7e3d5c1fSJean-Sébastien Pédron 		break;
308*7e3d5c1fSJean-Sébastien Pédron 	default:
309*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
310*7e3d5c1fSJean-Sébastien Pédron 		    argv[0], ret);
311*7e3d5c1fSJean-Sébastien Pédron 		ret = PAM_SERVICE_ERR;
312*7e3d5c1fSJean-Sébastien Pédron 	}
313*7e3d5c1fSJean-Sébastien Pédron 
314*7e3d5c1fSJean-Sébastien Pédron 	return (ret);
315f65b2180SDag-Erling Smørgrav }
316f65b2180SDag-Erling Smørgrav 
317f65b2180SDag-Erling Smørgrav PAM_EXTERN int
318f65b2180SDag-Erling Smørgrav pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
319f65b2180SDag-Erling Smørgrav     int argc, const char *argv[])
320f65b2180SDag-Erling Smørgrav {
321*7e3d5c1fSJean-Sébastien Pédron 	int ret;
322f65b2180SDag-Erling Smørgrav 
323*7e3d5c1fSJean-Sébastien Pédron 	ret = _pam_exec(pamh, __func__, flags, argc, argv);
324*7e3d5c1fSJean-Sébastien Pédron 
325*7e3d5c1fSJean-Sébastien Pédron 	/*
326*7e3d5c1fSJean-Sébastien Pédron 	 * We must check that the program returned a valid code for this
327*7e3d5c1fSJean-Sébastien Pédron 	 * function.
328*7e3d5c1fSJean-Sébastien Pédron 	 */
329*7e3d5c1fSJean-Sébastien Pédron 	switch (ret) {
330*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SUCCESS:
331*7e3d5c1fSJean-Sébastien Pédron 	case PAM_ABORT:
332*7e3d5c1fSJean-Sébastien Pédron 	case PAM_ACCT_EXPIRED:
333*7e3d5c1fSJean-Sébastien Pédron 	case PAM_AUTH_ERR:
334*7e3d5c1fSJean-Sébastien Pédron 	case PAM_BUF_ERR:
335*7e3d5c1fSJean-Sébastien Pédron 	case PAM_CONV_ERR:
336*7e3d5c1fSJean-Sébastien Pédron 	case PAM_IGNORE:
337*7e3d5c1fSJean-Sébastien Pédron 	case PAM_NEW_AUTHTOK_REQD:
338*7e3d5c1fSJean-Sébastien Pédron 	case PAM_PERM_DENIED:
339*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SERVICE_ERR:
340*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SYSTEM_ERR:
341*7e3d5c1fSJean-Sébastien Pédron 	case PAM_USER_UNKNOWN:
342*7e3d5c1fSJean-Sébastien Pédron 		break;
343*7e3d5c1fSJean-Sébastien Pédron 	default:
344*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
345*7e3d5c1fSJean-Sébastien Pédron 		    argv[0], ret);
346*7e3d5c1fSJean-Sébastien Pédron 		ret = PAM_SERVICE_ERR;
347*7e3d5c1fSJean-Sébastien Pédron 	}
348*7e3d5c1fSJean-Sébastien Pédron 
349*7e3d5c1fSJean-Sébastien Pédron 	return (ret);
350f65b2180SDag-Erling Smørgrav }
351f65b2180SDag-Erling Smørgrav 
352f65b2180SDag-Erling Smørgrav PAM_EXTERN int
353f65b2180SDag-Erling Smørgrav pam_sm_open_session(pam_handle_t *pamh, int flags,
354f65b2180SDag-Erling Smørgrav     int argc, const char *argv[])
355f65b2180SDag-Erling Smørgrav {
356*7e3d5c1fSJean-Sébastien Pédron 	int ret;
357f65b2180SDag-Erling Smørgrav 
358*7e3d5c1fSJean-Sébastien Pédron 	ret = _pam_exec(pamh, __func__, flags, argc, argv);
359*7e3d5c1fSJean-Sébastien Pédron 
360*7e3d5c1fSJean-Sébastien Pédron 	/*
361*7e3d5c1fSJean-Sébastien Pédron 	 * We must check that the program returned a valid code for this
362*7e3d5c1fSJean-Sébastien Pédron 	 * function.
363*7e3d5c1fSJean-Sébastien Pédron 	 */
364*7e3d5c1fSJean-Sébastien Pédron 	switch (ret) {
365*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SUCCESS:
366*7e3d5c1fSJean-Sébastien Pédron 	case PAM_ABORT:
367*7e3d5c1fSJean-Sébastien Pédron 	case PAM_BUF_ERR:
368*7e3d5c1fSJean-Sébastien Pédron 	case PAM_CONV_ERR:
369*7e3d5c1fSJean-Sébastien Pédron 	case PAM_IGNORE:
370*7e3d5c1fSJean-Sébastien Pédron 	case PAM_PERM_DENIED:
371*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SERVICE_ERR:
372*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SESSION_ERR:
373*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SYSTEM_ERR:
374*7e3d5c1fSJean-Sébastien Pédron 		break;
375*7e3d5c1fSJean-Sébastien Pédron 	default:
376*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
377*7e3d5c1fSJean-Sébastien Pédron 		    argv[0], ret);
378*7e3d5c1fSJean-Sébastien Pédron 		ret = PAM_SERVICE_ERR;
379*7e3d5c1fSJean-Sébastien Pédron 	}
380*7e3d5c1fSJean-Sébastien Pédron 
381*7e3d5c1fSJean-Sébastien Pédron 	return (ret);
382f65b2180SDag-Erling Smørgrav }
383f65b2180SDag-Erling Smørgrav 
384f65b2180SDag-Erling Smørgrav PAM_EXTERN int
385f65b2180SDag-Erling Smørgrav pam_sm_close_session(pam_handle_t *pamh, int flags,
386f65b2180SDag-Erling Smørgrav     int argc, const char *argv[])
387f65b2180SDag-Erling Smørgrav {
388*7e3d5c1fSJean-Sébastien Pédron 	int ret;
389f65b2180SDag-Erling Smørgrav 
390*7e3d5c1fSJean-Sébastien Pédron 	ret = _pam_exec(pamh, __func__, flags, argc, argv);
391*7e3d5c1fSJean-Sébastien Pédron 
392*7e3d5c1fSJean-Sébastien Pédron 	/*
393*7e3d5c1fSJean-Sébastien Pédron 	 * We must check that the program returned a valid code for this
394*7e3d5c1fSJean-Sébastien Pédron 	 * function.
395*7e3d5c1fSJean-Sébastien Pédron 	 */
396*7e3d5c1fSJean-Sébastien Pédron 	switch (ret) {
397*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SUCCESS:
398*7e3d5c1fSJean-Sébastien Pédron 	case PAM_ABORT:
399*7e3d5c1fSJean-Sébastien Pédron 	case PAM_BUF_ERR:
400*7e3d5c1fSJean-Sébastien Pédron 	case PAM_CONV_ERR:
401*7e3d5c1fSJean-Sébastien Pédron 	case PAM_IGNORE:
402*7e3d5c1fSJean-Sébastien Pédron 	case PAM_PERM_DENIED:
403*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SERVICE_ERR:
404*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SESSION_ERR:
405*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SYSTEM_ERR:
406*7e3d5c1fSJean-Sébastien Pédron 		break;
407*7e3d5c1fSJean-Sébastien Pédron 	default:
408*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
409*7e3d5c1fSJean-Sébastien Pédron 		    argv[0], ret);
410*7e3d5c1fSJean-Sébastien Pédron 		ret = PAM_SERVICE_ERR;
411*7e3d5c1fSJean-Sébastien Pédron 	}
412*7e3d5c1fSJean-Sébastien Pédron 
413*7e3d5c1fSJean-Sébastien Pédron 	return (ret);
414f65b2180SDag-Erling Smørgrav }
415f65b2180SDag-Erling Smørgrav 
416f65b2180SDag-Erling Smørgrav PAM_EXTERN int
417f65b2180SDag-Erling Smørgrav pam_sm_chauthtok(pam_handle_t *pamh, int flags,
418f65b2180SDag-Erling Smørgrav     int argc, const char *argv[])
419f65b2180SDag-Erling Smørgrav {
420*7e3d5c1fSJean-Sébastien Pédron 	int ret;
421f65b2180SDag-Erling Smørgrav 
422*7e3d5c1fSJean-Sébastien Pédron 	ret = _pam_exec(pamh, __func__, flags, argc, argv);
423*7e3d5c1fSJean-Sébastien Pédron 
424*7e3d5c1fSJean-Sébastien Pédron 	/*
425*7e3d5c1fSJean-Sébastien Pédron 	 * We must check that the program returned a valid code for this
426*7e3d5c1fSJean-Sébastien Pédron 	 * function.
427*7e3d5c1fSJean-Sébastien Pédron 	 */
428*7e3d5c1fSJean-Sébastien Pédron 	switch (ret) {
429*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SUCCESS:
430*7e3d5c1fSJean-Sébastien Pédron 	case PAM_ABORT:
431*7e3d5c1fSJean-Sébastien Pédron 	case PAM_AUTHTOK_DISABLE_AGING:
432*7e3d5c1fSJean-Sébastien Pédron 	case PAM_AUTHTOK_ERR:
433*7e3d5c1fSJean-Sébastien Pédron 	case PAM_AUTHTOK_LOCK_BUSY:
434*7e3d5c1fSJean-Sébastien Pédron 	case PAM_AUTHTOK_RECOVERY_ERR:
435*7e3d5c1fSJean-Sébastien Pédron 	case PAM_BUF_ERR:
436*7e3d5c1fSJean-Sébastien Pédron 	case PAM_CONV_ERR:
437*7e3d5c1fSJean-Sébastien Pédron 	case PAM_IGNORE:
438*7e3d5c1fSJean-Sébastien Pédron 	case PAM_PERM_DENIED:
439*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SERVICE_ERR:
440*7e3d5c1fSJean-Sébastien Pédron 	case PAM_SYSTEM_ERR:
441*7e3d5c1fSJean-Sébastien Pédron 	case PAM_TRY_AGAIN:
442*7e3d5c1fSJean-Sébastien Pédron 		break;
443*7e3d5c1fSJean-Sébastien Pédron 	default:
444*7e3d5c1fSJean-Sébastien Pédron 		openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
445*7e3d5c1fSJean-Sébastien Pédron 		    argv[0], ret);
446*7e3d5c1fSJean-Sébastien Pédron 		ret = PAM_SERVICE_ERR;
447*7e3d5c1fSJean-Sébastien Pédron 	}
448*7e3d5c1fSJean-Sébastien Pédron 
449*7e3d5c1fSJean-Sébastien Pédron 	return (ret);
450f65b2180SDag-Erling Smørgrav }
451f65b2180SDag-Erling Smørgrav 
452f65b2180SDag-Erling Smørgrav PAM_MODULE_ENTRY("pam_exec");
453