1242be47eSzrj /*-
2*c98db407SSascha Wildner * SPDX-License-Identifier: BSD-3-Clause
3*c98db407SSascha Wildner *
4242be47eSzrj * Copyright (c) 2001,2003 Networks Associates Technology, Inc.
5242be47eSzrj * All rights reserved.
6242be47eSzrj *
7242be47eSzrj * This software was developed for the FreeBSD Project by ThinkSec AS and
8242be47eSzrj * NAI Labs, the Security Research Division of Network Associates, Inc.
9242be47eSzrj * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
10242be47eSzrj * DARPA CHATS research program.
11242be47eSzrj *
12242be47eSzrj * Redistribution and use in source and binary forms, with or without
13242be47eSzrj * modification, are permitted provided that the following conditions
14242be47eSzrj * are met:
15242be47eSzrj * 1. Redistributions of source code must retain the above copyright
16242be47eSzrj * notice, this list of conditions and the following disclaimer.
17242be47eSzrj * 2. Redistributions in binary form must reproduce the above copyright
18242be47eSzrj * notice, this list of conditions and the following disclaimer in the
19242be47eSzrj * documentation and/or other materials provided with the distribution.
20242be47eSzrj * 3. The name of the author may not be used to endorse or promote
21242be47eSzrj * products derived from this software without specific prior written
22242be47eSzrj * permission.
23242be47eSzrj *
24242be47eSzrj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25242be47eSzrj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26242be47eSzrj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27242be47eSzrj * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28242be47eSzrj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29242be47eSzrj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30242be47eSzrj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31242be47eSzrj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32242be47eSzrj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33242be47eSzrj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34242be47eSzrj * SUCH DAMAGE.
35242be47eSzrj *
36*c98db407SSascha Wildner * $FreeBSD: head/lib/libpam/modules/pam_exec/pam_exec.c 315164 2017-03-12 17:41:51Z pfg $
37242be47eSzrj */
38242be47eSzrj
39242be47eSzrj #include <sys/types.h>
40242be47eSzrj #include <sys/wait.h>
41242be47eSzrj
42242be47eSzrj #include <errno.h>
43242be47eSzrj #include <stdio.h>
44242be47eSzrj #include <stdlib.h>
45242be47eSzrj #include <string.h>
46242be47eSzrj #include <unistd.h>
47242be47eSzrj
48242be47eSzrj #include <security/pam_appl.h>
49242be47eSzrj #include <security/pam_modules.h>
50242be47eSzrj #include <security/openpam.h>
51242be47eSzrj
52242be47eSzrj #define ENV_ITEM(n) { (n), #n }
53242be47eSzrj static struct {
54242be47eSzrj int item;
55242be47eSzrj const char *name;
56242be47eSzrj } env_items[] = {
57242be47eSzrj ENV_ITEM(PAM_SERVICE),
58242be47eSzrj ENV_ITEM(PAM_USER),
59242be47eSzrj ENV_ITEM(PAM_TTY),
60242be47eSzrj ENV_ITEM(PAM_RHOST),
61242be47eSzrj ENV_ITEM(PAM_RUSER),
62242be47eSzrj };
63242be47eSzrj
64242be47eSzrj struct pe_opts {
65242be47eSzrj int return_prog_exit_status;
66242be47eSzrj };
67242be47eSzrj
68242be47eSzrj #define PAM_RV_COUNT 24
69242be47eSzrj
70242be47eSzrj static int
parse_options(const char * func,int * argc,const char ** argv[],struct pe_opts * options)71242be47eSzrj parse_options(const char *func, int *argc, const char **argv[],
72242be47eSzrj struct pe_opts *options)
73242be47eSzrj {
74242be47eSzrj int i;
75242be47eSzrj
76242be47eSzrj /*
77242be47eSzrj * Parse options:
78242be47eSzrj * return_prog_exit_status:
79242be47eSzrj * use the program exit status as the return code of pam_exec
80242be47eSzrj * --:
81242be47eSzrj * stop options parsing; what follows is the command to execute
82242be47eSzrj */
83242be47eSzrj options->return_prog_exit_status = 0;
84242be47eSzrj
85242be47eSzrj for (i = 0; i < *argc; ++i) {
86242be47eSzrj if (strcmp((*argv)[i], "return_prog_exit_status") == 0) {
87242be47eSzrj openpam_log(PAM_LOG_DEBUG,
88242be47eSzrj "%s: Option \"return_prog_exit_status\" enabled",
89242be47eSzrj func);
90242be47eSzrj options->return_prog_exit_status = 1;
91242be47eSzrj } else {
92242be47eSzrj if (strcmp((*argv)[i], "--") == 0) {
93242be47eSzrj (*argc)--;
94242be47eSzrj (*argv)++;
95242be47eSzrj }
96242be47eSzrj
97242be47eSzrj break;
98242be47eSzrj }
99242be47eSzrj }
100242be47eSzrj
101242be47eSzrj (*argc) -= i;
102242be47eSzrj (*argv) += i;
103242be47eSzrj
104242be47eSzrj return (0);
105242be47eSzrj }
106242be47eSzrj
107242be47eSzrj static int
_pam_exec(pam_handle_t * pamh __unused,const char * func,int flags __unused,int argc,const char * argv[],struct pe_opts * options)108242be47eSzrj _pam_exec(pam_handle_t *pamh __unused,
109242be47eSzrj const char *func, int flags __unused, int argc, const char *argv[],
110242be47eSzrj struct pe_opts *options)
111242be47eSzrj {
112242be47eSzrj int envlen, i, nitems, pam_err, status;
113242be47eSzrj int nitems_rv;
114242be47eSzrj char **envlist, **tmp, *envstr;
115242be47eSzrj volatile int childerr;
116242be47eSzrj pid_t pid;
117242be47eSzrj
118242be47eSzrj /*
119242be47eSzrj * XXX For additional credit, divert child's stdin/stdout/stderr
120242be47eSzrj * to the conversation function.
121242be47eSzrj */
122242be47eSzrj
123242be47eSzrj /* Check there's a program name left after parsing options. */
124242be47eSzrj if (argc < 1) {
125242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s: No program specified: aborting",
126242be47eSzrj func);
127242be47eSzrj return (PAM_SERVICE_ERR);
128242be47eSzrj }
129242be47eSzrj
130242be47eSzrj /*
131242be47eSzrj * Set up the child's environment list. It consists of the PAM
132242be47eSzrj * environment, plus a few hand-picked PAM items, the pam_sm_*
133242be47eSzrj * function name calling it and, if return_prog_exit_status is
134242be47eSzrj * set, the valid return codes numerical values.
135242be47eSzrj */
136242be47eSzrj envlist = pam_getenvlist(pamh);
137242be47eSzrj for (envlen = 0; envlist[envlen] != NULL; ++envlen)
138242be47eSzrj /* nothing */ ;
139242be47eSzrj nitems = sizeof(env_items) / sizeof(*env_items);
140242be47eSzrj /* Count PAM return values put in the environment. */
141242be47eSzrj nitems_rv = options->return_prog_exit_status ? PAM_RV_COUNT : 0;
142242be47eSzrj tmp = realloc(envlist, (envlen + nitems + 1 + nitems_rv + 1) *
143242be47eSzrj sizeof(*envlist));
144242be47eSzrj if (tmp == NULL) {
145242be47eSzrj openpam_free_envlist(envlist);
146242be47eSzrj return (PAM_BUF_ERR);
147242be47eSzrj }
148242be47eSzrj envlist = tmp;
149242be47eSzrj for (i = 0; i < nitems; ++i) {
150242be47eSzrj const void *item;
151242be47eSzrj
152242be47eSzrj pam_err = pam_get_item(pamh, env_items[i].item, &item);
153242be47eSzrj if (pam_err != PAM_SUCCESS || item == NULL)
154242be47eSzrj continue;
155242be47eSzrj asprintf(&envstr, "%s=%s", env_items[i].name,
156242be47eSzrj (const char *)item);
157242be47eSzrj if (envstr == NULL) {
158242be47eSzrj openpam_free_envlist(envlist);
159242be47eSzrj return (PAM_BUF_ERR);
160242be47eSzrj }
161242be47eSzrj envlist[envlen++] = envstr;
162242be47eSzrj envlist[envlen] = NULL;
163242be47eSzrj }
164242be47eSzrj
165242be47eSzrj /* Add the pam_sm_* function name to the environment. */
166242be47eSzrj asprintf(&envstr, "PAM_SM_FUNC=%s", func);
167242be47eSzrj if (envstr == NULL) {
168242be47eSzrj openpam_free_envlist(envlist);
169242be47eSzrj return (PAM_BUF_ERR);
170242be47eSzrj }
171242be47eSzrj envlist[envlen++] = envstr;
172242be47eSzrj
173242be47eSzrj /* Add the PAM return values to the environment. */
174242be47eSzrj if (options->return_prog_exit_status) {
175242be47eSzrj #define ADD_PAM_RV_TO_ENV(name) \
176242be47eSzrj asprintf(&envstr, #name "=%d", name); \
177242be47eSzrj if (envstr == NULL) { \
178242be47eSzrj openpam_free_envlist(envlist); \
179242be47eSzrj return (PAM_BUF_ERR); \
180242be47eSzrj } \
181242be47eSzrj envlist[envlen++] = envstr
182242be47eSzrj /*
183242be47eSzrj * CAUTION: When adding/removing an item in the list
184242be47eSzrj * below, be sure to update the value of PAM_RV_COUNT.
185242be47eSzrj */
186242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_ABORT);
187242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_ACCT_EXPIRED);
188242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_AUTHINFO_UNAVAIL);
189242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_AUTHTOK_DISABLE_AGING);
190242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_AUTHTOK_ERR);
191242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_AUTHTOK_LOCK_BUSY);
192242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_AUTHTOK_RECOVERY_ERR);
193242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_AUTH_ERR);
194242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_BUF_ERR);
195242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_CONV_ERR);
196242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_CRED_ERR);
197242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_CRED_EXPIRED);
198242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_CRED_INSUFFICIENT);
199242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_CRED_UNAVAIL);
200242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_IGNORE);
201242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_MAXTRIES);
202242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_NEW_AUTHTOK_REQD);
203242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_PERM_DENIED);
204242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_SERVICE_ERR);
205242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_SESSION_ERR);
206242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_SUCCESS);
207242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_SYSTEM_ERR);
208242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_TRY_AGAIN);
209242be47eSzrj ADD_PAM_RV_TO_ENV(PAM_USER_UNKNOWN);
210242be47eSzrj }
211242be47eSzrj
212242be47eSzrj envlist[envlen] = NULL;
213242be47eSzrj
214242be47eSzrj /*
215242be47eSzrj * Fork and run the command. By using vfork() instead of fork(),
216242be47eSzrj * we can distinguish between an execve() failure and a non-zero
217242be47eSzrj * exit status from the command.
218242be47eSzrj */
219242be47eSzrj childerr = 0;
220242be47eSzrj if ((pid = vfork()) == 0) {
221242be47eSzrj execve(argv[0], (char * const *)argv, (char * const *)envlist);
222242be47eSzrj childerr = errno;
223242be47eSzrj _exit(1);
224242be47eSzrj }
225242be47eSzrj openpam_free_envlist(envlist);
226242be47eSzrj if (pid == -1) {
227242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s: vfork(): %m", func);
228242be47eSzrj return (PAM_SYSTEM_ERR);
229242be47eSzrj }
230242be47eSzrj while (waitpid(pid, &status, 0) == -1) {
231242be47eSzrj if (errno == EINTR)
232242be47eSzrj continue;
233242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s: waitpid(): %m", func);
234242be47eSzrj return (PAM_SYSTEM_ERR);
235242be47eSzrj }
236242be47eSzrj if (childerr != 0) {
237242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s: execve(): %m", func);
238242be47eSzrj return (PAM_SYSTEM_ERR);
239242be47eSzrj }
240242be47eSzrj if (WIFSIGNALED(status)) {
241242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s: %s caught signal %d%s",
242242be47eSzrj func, argv[0], WTERMSIG(status),
243242be47eSzrj WCOREDUMP(status) ? " (core dumped)" : "");
244242be47eSzrj return (PAM_SERVICE_ERR);
245242be47eSzrj }
246242be47eSzrj if (!WIFEXITED(status)) {
247242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s: unknown status 0x%x",
248242be47eSzrj func, status);
249242be47eSzrj return (PAM_SERVICE_ERR);
250242be47eSzrj }
251242be47eSzrj
252242be47eSzrj if (options->return_prog_exit_status) {
253242be47eSzrj openpam_log(PAM_LOG_DEBUG,
254242be47eSzrj "%s: Use program exit status as return value: %d",
255242be47eSzrj func, WEXITSTATUS(status));
256242be47eSzrj return (WEXITSTATUS(status));
257242be47eSzrj } else {
258242be47eSzrj return (WEXITSTATUS(status) == 0 ?
259242be47eSzrj PAM_SUCCESS : PAM_PERM_DENIED);
260242be47eSzrj }
261242be47eSzrj }
262242be47eSzrj
263242be47eSzrj PAM_EXTERN int
pam_sm_authenticate(pam_handle_t * pamh,int flags,int argc,const char * argv[])264*c98db407SSascha Wildner pam_sm_authenticate(pam_handle_t *pamh, int flags,
265*c98db407SSascha Wildner int argc, const char *argv[])
266242be47eSzrj {
267242be47eSzrj int ret;
268242be47eSzrj struct pe_opts options;
269242be47eSzrj
270242be47eSzrj ret = parse_options(__func__, &argc, &argv, &options);
271242be47eSzrj if (ret != 0)
272242be47eSzrj return (PAM_SERVICE_ERR);
273242be47eSzrj
274242be47eSzrj ret = _pam_exec(pamh, __func__, flags, argc, argv, &options);
275242be47eSzrj
276242be47eSzrj /*
277242be47eSzrj * We must check that the program returned a valid code for this
278242be47eSzrj * function.
279242be47eSzrj */
280242be47eSzrj switch (ret) {
281242be47eSzrj case PAM_SUCCESS:
282242be47eSzrj case PAM_ABORT:
283242be47eSzrj case PAM_AUTHINFO_UNAVAIL:
284242be47eSzrj case PAM_AUTH_ERR:
285242be47eSzrj case PAM_BUF_ERR:
286242be47eSzrj case PAM_CONV_ERR:
287242be47eSzrj case PAM_CRED_INSUFFICIENT:
288242be47eSzrj case PAM_IGNORE:
289242be47eSzrj case PAM_MAXTRIES:
290242be47eSzrj case PAM_PERM_DENIED:
291242be47eSzrj case PAM_SERVICE_ERR:
292242be47eSzrj case PAM_SYSTEM_ERR:
293242be47eSzrj case PAM_USER_UNKNOWN:
294242be47eSzrj break;
295242be47eSzrj default:
296242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
297242be47eSzrj argv[0], ret);
298242be47eSzrj ret = PAM_SERVICE_ERR;
299242be47eSzrj }
300242be47eSzrj
301242be47eSzrj return (ret);
302242be47eSzrj }
303242be47eSzrj
304242be47eSzrj PAM_EXTERN int
pam_sm_setcred(pam_handle_t * pamh,int flags,int argc,const char * argv[])305*c98db407SSascha Wildner pam_sm_setcred(pam_handle_t *pamh, int flags,
306*c98db407SSascha Wildner int argc, const char *argv[])
307242be47eSzrj {
308242be47eSzrj int ret;
309242be47eSzrj struct pe_opts options;
310242be47eSzrj
311242be47eSzrj ret = parse_options(__func__, &argc, &argv, &options);
312242be47eSzrj if (ret != 0)
313242be47eSzrj return (PAM_SERVICE_ERR);
314242be47eSzrj
315242be47eSzrj ret = _pam_exec(pamh, __func__, flags, argc, argv, &options);
316242be47eSzrj
317242be47eSzrj /*
318242be47eSzrj * We must check that the program returned a valid code for this
319242be47eSzrj * function.
320242be47eSzrj */
321242be47eSzrj switch (ret) {
322242be47eSzrj case PAM_SUCCESS:
323242be47eSzrj case PAM_ABORT:
324242be47eSzrj case PAM_BUF_ERR:
325242be47eSzrj case PAM_CONV_ERR:
326242be47eSzrj case PAM_CRED_ERR:
327242be47eSzrj case PAM_CRED_EXPIRED:
328242be47eSzrj case PAM_CRED_UNAVAIL:
329242be47eSzrj case PAM_IGNORE:
330242be47eSzrj case PAM_PERM_DENIED:
331242be47eSzrj case PAM_SERVICE_ERR:
332242be47eSzrj case PAM_SYSTEM_ERR:
333242be47eSzrj case PAM_USER_UNKNOWN:
334242be47eSzrj break;
335242be47eSzrj default:
336242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
337242be47eSzrj argv[0], ret);
338242be47eSzrj ret = PAM_SERVICE_ERR;
339242be47eSzrj }
340242be47eSzrj
341242be47eSzrj return (ret);
342242be47eSzrj }
343242be47eSzrj
344242be47eSzrj PAM_EXTERN int
pam_sm_acct_mgmt(pam_handle_t * pamh,int flags,int argc,const char * argv[])345*c98db407SSascha Wildner pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
346*c98db407SSascha Wildner int argc, const char *argv[])
347242be47eSzrj {
348242be47eSzrj int ret;
349242be47eSzrj struct pe_opts options;
350242be47eSzrj
351242be47eSzrj ret = parse_options(__func__, &argc, &argv, &options);
352242be47eSzrj if (ret != 0)
353242be47eSzrj return (PAM_SERVICE_ERR);
354242be47eSzrj
355242be47eSzrj ret = _pam_exec(pamh, __func__, flags, argc, argv, &options);
356242be47eSzrj
357242be47eSzrj /*
358242be47eSzrj * We must check that the program returned a valid code for this
359242be47eSzrj * function.
360242be47eSzrj */
361242be47eSzrj switch (ret) {
362242be47eSzrj case PAM_SUCCESS:
363242be47eSzrj case PAM_ABORT:
364242be47eSzrj case PAM_ACCT_EXPIRED:
365242be47eSzrj case PAM_AUTH_ERR:
366242be47eSzrj case PAM_BUF_ERR:
367242be47eSzrj case PAM_CONV_ERR:
368242be47eSzrj case PAM_IGNORE:
369242be47eSzrj case PAM_NEW_AUTHTOK_REQD:
370242be47eSzrj case PAM_PERM_DENIED:
371242be47eSzrj case PAM_SERVICE_ERR:
372242be47eSzrj case PAM_SYSTEM_ERR:
373242be47eSzrj case PAM_USER_UNKNOWN:
374242be47eSzrj break;
375242be47eSzrj default:
376242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
377242be47eSzrj argv[0], ret);
378242be47eSzrj ret = PAM_SERVICE_ERR;
379242be47eSzrj }
380242be47eSzrj
381242be47eSzrj return (ret);
382242be47eSzrj }
383242be47eSzrj
384242be47eSzrj PAM_EXTERN int
pam_sm_open_session(pam_handle_t * pamh,int flags,int argc,const char * argv[])385*c98db407SSascha Wildner pam_sm_open_session(pam_handle_t *pamh, int flags,
386*c98db407SSascha Wildner int argc, const char *argv[])
387242be47eSzrj {
388242be47eSzrj int ret;
389242be47eSzrj struct pe_opts options;
390242be47eSzrj
391242be47eSzrj ret = parse_options(__func__, &argc, &argv, &options);
392242be47eSzrj if (ret != 0)
393242be47eSzrj return (PAM_SERVICE_ERR);
394242be47eSzrj
395242be47eSzrj ret = _pam_exec(pamh, __func__, flags, argc, argv, &options);
396242be47eSzrj
397242be47eSzrj /*
398242be47eSzrj * We must check that the program returned a valid code for this
399242be47eSzrj * function.
400242be47eSzrj */
401242be47eSzrj switch (ret) {
402242be47eSzrj case PAM_SUCCESS:
403242be47eSzrj case PAM_ABORT:
404242be47eSzrj case PAM_BUF_ERR:
405242be47eSzrj case PAM_CONV_ERR:
406242be47eSzrj case PAM_IGNORE:
407242be47eSzrj case PAM_PERM_DENIED:
408242be47eSzrj case PAM_SERVICE_ERR:
409242be47eSzrj case PAM_SESSION_ERR:
410242be47eSzrj case PAM_SYSTEM_ERR:
411242be47eSzrj break;
412242be47eSzrj default:
413242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
414242be47eSzrj argv[0], ret);
415242be47eSzrj ret = PAM_SERVICE_ERR;
416242be47eSzrj }
417242be47eSzrj
418242be47eSzrj return (ret);
419242be47eSzrj }
420242be47eSzrj
421242be47eSzrj PAM_EXTERN int
pam_sm_close_session(pam_handle_t * pamh,int flags,int argc,const char * argv[])422242be47eSzrj pam_sm_close_session(pam_handle_t *pamh, int flags,
423242be47eSzrj int argc, const char *argv[])
424242be47eSzrj {
425242be47eSzrj int ret;
426242be47eSzrj struct pe_opts options;
427242be47eSzrj
428242be47eSzrj ret = parse_options(__func__, &argc, &argv, &options);
429242be47eSzrj if (ret != 0)
430242be47eSzrj return (PAM_SERVICE_ERR);
431242be47eSzrj
432242be47eSzrj ret = _pam_exec(pamh, __func__, flags, argc, argv, &options);
433242be47eSzrj
434242be47eSzrj /*
435242be47eSzrj * We must check that the program returned a valid code for this
436242be47eSzrj * function.
437242be47eSzrj */
438242be47eSzrj switch (ret) {
439242be47eSzrj case PAM_SUCCESS:
440242be47eSzrj case PAM_ABORT:
441242be47eSzrj case PAM_BUF_ERR:
442242be47eSzrj case PAM_CONV_ERR:
443242be47eSzrj case PAM_IGNORE:
444242be47eSzrj case PAM_PERM_DENIED:
445242be47eSzrj case PAM_SERVICE_ERR:
446242be47eSzrj case PAM_SESSION_ERR:
447242be47eSzrj case PAM_SYSTEM_ERR:
448242be47eSzrj break;
449242be47eSzrj default:
450242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
451242be47eSzrj argv[0], ret);
452242be47eSzrj ret = PAM_SERVICE_ERR;
453242be47eSzrj }
454242be47eSzrj
455242be47eSzrj return (ret);
456242be47eSzrj }
457242be47eSzrj
458242be47eSzrj PAM_EXTERN int
pam_sm_chauthtok(pam_handle_t * pamh,int flags,int argc,const char * argv[])459*c98db407SSascha Wildner pam_sm_chauthtok(pam_handle_t *pamh, int flags,
460*c98db407SSascha Wildner int argc, const char *argv[])
461242be47eSzrj {
462242be47eSzrj int ret;
463242be47eSzrj struct pe_opts options;
464242be47eSzrj
465242be47eSzrj ret = parse_options(__func__, &argc, &argv, &options);
466242be47eSzrj if (ret != 0)
467242be47eSzrj return (PAM_SERVICE_ERR);
468242be47eSzrj
469242be47eSzrj ret = _pam_exec(pamh, __func__, flags, argc, argv, &options);
470242be47eSzrj
471242be47eSzrj /*
472242be47eSzrj * We must check that the program returned a valid code for this
473242be47eSzrj * function.
474242be47eSzrj */
475242be47eSzrj switch (ret) {
476242be47eSzrj case PAM_SUCCESS:
477242be47eSzrj case PAM_ABORT:
478242be47eSzrj case PAM_AUTHTOK_DISABLE_AGING:
479242be47eSzrj case PAM_AUTHTOK_ERR:
480242be47eSzrj case PAM_AUTHTOK_LOCK_BUSY:
481242be47eSzrj case PAM_AUTHTOK_RECOVERY_ERR:
482242be47eSzrj case PAM_BUF_ERR:
483242be47eSzrj case PAM_CONV_ERR:
484242be47eSzrj case PAM_IGNORE:
485242be47eSzrj case PAM_PERM_DENIED:
486242be47eSzrj case PAM_SERVICE_ERR:
487242be47eSzrj case PAM_SYSTEM_ERR:
488242be47eSzrj case PAM_TRY_AGAIN:
489242be47eSzrj break;
490242be47eSzrj default:
491242be47eSzrj openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d",
492242be47eSzrj argv[0], ret);
493242be47eSzrj ret = PAM_SERVICE_ERR;
494242be47eSzrj }
495242be47eSzrj
496242be47eSzrj return (ret);
497242be47eSzrj }
498242be47eSzrj
499242be47eSzrj PAM_MODULE_ENTRY("pam_exec");
500