1f65b2180SDag-Erling Smørgrav /*- 2*5e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*5e53a4f9SPedro F. Giffuni * 437def36fSDag-Erling Smørgrav * Copyright (c) 2001,2003 Networks Associates Technology, Inc. 53869fb78SDag-Erling Smørgrav * Copyright (c) 2017 Dag-Erling Smørgrav 6f65b2180SDag-Erling Smørgrav * All rights reserved. 7f65b2180SDag-Erling Smørgrav * 8f65b2180SDag-Erling Smørgrav * This software was developed for the FreeBSD Project by ThinkSec AS and 9f65b2180SDag-Erling Smørgrav * NAI Labs, the Security Research Division of Network Associates, Inc. 10f65b2180SDag-Erling Smørgrav * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 11f65b2180SDag-Erling Smørgrav * DARPA CHATS research program. 12f65b2180SDag-Erling Smørgrav * 13f65b2180SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 14f65b2180SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 15f65b2180SDag-Erling Smørgrav * are met: 16f65b2180SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 17f65b2180SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 18f65b2180SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 19f65b2180SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 20f65b2180SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 21f65b2180SDag-Erling Smørgrav * 3. The name of the author may not be used to endorse or promote 22f65b2180SDag-Erling Smørgrav * products derived from this software without specific prior written 23f65b2180SDag-Erling Smørgrav * permission. 24f65b2180SDag-Erling Smørgrav * 25f65b2180SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 26f65b2180SDag-Erling Smørgrav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27f65b2180SDag-Erling Smørgrav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28f65b2180SDag-Erling Smørgrav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 29f65b2180SDag-Erling Smørgrav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30f65b2180SDag-Erling Smørgrav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31f65b2180SDag-Erling Smørgrav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32f65b2180SDag-Erling Smørgrav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33f65b2180SDag-Erling Smørgrav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34f65b2180SDag-Erling Smørgrav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35f65b2180SDag-Erling Smørgrav * SUCH DAMAGE. 36f65b2180SDag-Erling Smørgrav */ 37f65b2180SDag-Erling Smørgrav 38f65b2180SDag-Erling Smørgrav #include <sys/cdefs.h> 39f65b2180SDag-Erling Smørgrav __FBSDID("$FreeBSD$"); 40f65b2180SDag-Erling Smørgrav 41f65b2180SDag-Erling Smørgrav #include <sys/types.h> 423869fb78SDag-Erling Smørgrav #include <sys/poll.h> 433869fb78SDag-Erling Smørgrav #include <sys/procdesc.h> 44f65b2180SDag-Erling Smørgrav #include <sys/wait.h> 45f65b2180SDag-Erling Smørgrav 46f65b2180SDag-Erling Smørgrav #include <errno.h> 473869fb78SDag-Erling Smørgrav #include <fcntl.h> 488bdb099aSEd Schouten #include <stdio.h> 49f65b2180SDag-Erling Smørgrav #include <stdlib.h> 50f65b2180SDag-Erling Smørgrav #include <string.h> 51f65b2180SDag-Erling Smørgrav #include <unistd.h> 52f65b2180SDag-Erling Smørgrav 53f65b2180SDag-Erling Smørgrav #include <security/pam_appl.h> 54f65b2180SDag-Erling Smørgrav #include <security/pam_modules.h> 55f65b2180SDag-Erling Smørgrav #include <security/openpam.h> 56f65b2180SDag-Erling Smørgrav 573869fb78SDag-Erling Smørgrav #define PAM_ITEM_ENV(n) { (n), #n } 589d97c7eeSDag-Erling Smørgrav static struct { 599d97c7eeSDag-Erling Smørgrav int item; 609d97c7eeSDag-Erling Smørgrav const char *name; 613869fb78SDag-Erling Smørgrav } pam_item_env[] = { 623869fb78SDag-Erling Smørgrav PAM_ITEM_ENV(PAM_SERVICE), 633869fb78SDag-Erling Smørgrav PAM_ITEM_ENV(PAM_USER), 643869fb78SDag-Erling Smørgrav PAM_ITEM_ENV(PAM_TTY), 653869fb78SDag-Erling Smørgrav PAM_ITEM_ENV(PAM_RHOST), 663869fb78SDag-Erling Smørgrav PAM_ITEM_ENV(PAM_RUSER), 679d97c7eeSDag-Erling Smørgrav }; 683869fb78SDag-Erling Smørgrav #define NUM_PAM_ITEM_ENV (sizeof(pam_item_env) / sizeof(pam_item_env[0])) 693869fb78SDag-Erling Smørgrav 703869fb78SDag-Erling Smørgrav #define PAM_ERR_ENV_X(str, num) str "=" #num 713869fb78SDag-Erling Smørgrav #define PAM_ERR_ENV(pam_err) PAM_ERR_ENV_X(#pam_err, pam_err) 723869fb78SDag-Erling Smørgrav static const char *pam_err_env[] = { 733869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_SUCCESS), 743869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_OPEN_ERR), 753869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_SYMBOL_ERR), 763869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_SERVICE_ERR), 773869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_SYSTEM_ERR), 783869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_BUF_ERR), 793869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_CONV_ERR), 803869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_PERM_DENIED), 813869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_MAXTRIES), 823869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTH_ERR), 833869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_NEW_AUTHTOK_REQD), 843869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_CRED_INSUFFICIENT), 853869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHINFO_UNAVAIL), 863869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_USER_UNKNOWN), 873869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_CRED_UNAVAIL), 883869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_CRED_EXPIRED), 893869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_CRED_ERR), 903869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_ACCT_EXPIRED), 913869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHTOK_EXPIRED), 923869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_SESSION_ERR), 933869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHTOK_ERR), 943869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHTOK_RECOVERY_ERR), 953869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHTOK_LOCK_BUSY), 963869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHTOK_DISABLE_AGING), 973869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_NO_MODULE_DATA), 983869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_IGNORE), 993869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_ABORT), 1003869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_TRY_AGAIN), 1013869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_MODULE_UNKNOWN), 1023869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_DOMAIN_UNKNOWN), 1033869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_NUM_ERR), 1043869fb78SDag-Erling Smørgrav }; 1053869fb78SDag-Erling Smørgrav #define NUM_PAM_ERR_ENV (sizeof(pam_err_env) / sizeof(pam_err_env[0])) 1069d97c7eeSDag-Erling Smørgrav 1073902d8a9SJean-Sébastien Pédron struct pe_opts { 1083902d8a9SJean-Sébastien Pédron int return_prog_exit_status; 1093869fb78SDag-Erling Smørgrav int capture_stdout; 1103869fb78SDag-Erling Smørgrav int capture_stderr; 1113902d8a9SJean-Sébastien Pédron }; 1123902d8a9SJean-Sébastien Pédron 113f65b2180SDag-Erling Smørgrav static int 1143902d8a9SJean-Sébastien Pédron parse_options(const char *func, int *argc, const char **argv[], 1153902d8a9SJean-Sébastien Pédron struct pe_opts *options) 116f65b2180SDag-Erling Smørgrav { 1173902d8a9SJean-Sébastien Pédron int i; 1189d97c7eeSDag-Erling Smørgrav 1199d97c7eeSDag-Erling Smørgrav /* 1207e3d5c1fSJean-Sébastien Pédron * Parse options: 1217e3d5c1fSJean-Sébastien Pédron * return_prog_exit_status: 1227e3d5c1fSJean-Sébastien Pédron * use the program exit status as the return code of pam_exec 1237e3d5c1fSJean-Sébastien Pédron * --: 1247e3d5c1fSJean-Sébastien Pédron * stop options parsing; what follows is the command to execute 1257e3d5c1fSJean-Sébastien Pédron */ 1263869fb78SDag-Erling Smørgrav memset(options, 0, sizeof(*options)); 1273902d8a9SJean-Sébastien Pédron 1283902d8a9SJean-Sébastien Pédron for (i = 0; i < *argc; ++i) { 1293869fb78SDag-Erling Smørgrav if (strcmp((*argv)[i], "debug") == 0 || 1303869fb78SDag-Erling Smørgrav strcmp((*argv)[i], "no_warn") == 0) { 1313869fb78SDag-Erling Smørgrav /* ignore */ 1323869fb78SDag-Erling Smørgrav } else if (strcmp((*argv)[i], "capture_stdout") == 0) { 1333869fb78SDag-Erling Smørgrav options->capture_stdout = 1; 1343869fb78SDag-Erling Smørgrav } else if (strcmp((*argv)[i], "capture_stderr") == 0) { 1353869fb78SDag-Erling Smørgrav options->capture_stderr = 1; 1363869fb78SDag-Erling Smørgrav } else if (strcmp((*argv)[i], "return_prog_exit_status") == 0) { 1373902d8a9SJean-Sébastien Pédron options->return_prog_exit_status = 1; 1387e3d5c1fSJean-Sébastien Pédron } else { 1393902d8a9SJean-Sébastien Pédron if (strcmp((*argv)[i], "--") == 0) { 1403902d8a9SJean-Sébastien Pédron (*argc)--; 1413902d8a9SJean-Sébastien Pédron (*argv)++; 1427e3d5c1fSJean-Sébastien Pédron } 1437e3d5c1fSJean-Sébastien Pédron break; 1447e3d5c1fSJean-Sébastien Pédron } 1453869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_DEBUG, "%s: option \"%s\" enabled", 1463869fb78SDag-Erling Smørgrav func, (*argv)[i]); 1477e3d5c1fSJean-Sébastien Pédron } 1487e3d5c1fSJean-Sébastien Pédron 1493902d8a9SJean-Sébastien Pédron (*argc) -= i; 1503902d8a9SJean-Sébastien Pédron (*argv) += i; 1513902d8a9SJean-Sébastien Pédron 1523902d8a9SJean-Sébastien Pédron return (0); 1533902d8a9SJean-Sébastien Pédron } 1543902d8a9SJean-Sébastien Pédron 1553902d8a9SJean-Sébastien Pédron static int 1563869fb78SDag-Erling Smørgrav _pam_exec(pam_handle_t *pamh, 1573902d8a9SJean-Sébastien Pédron const char *func, int flags __unused, int argc, const char *argv[], 1583902d8a9SJean-Sébastien Pédron struct pe_opts *options) 1593902d8a9SJean-Sébastien Pédron { 1603869fb78SDag-Erling Smørgrav char buf[PAM_MAX_MSG_SIZE]; 1613869fb78SDag-Erling Smørgrav struct pollfd pfd[3]; 1623869fb78SDag-Erling Smørgrav const void *item; 1633869fb78SDag-Erling Smørgrav char **envlist, *envstr, *resp, **tmp; 1643869fb78SDag-Erling Smørgrav ssize_t rlen; 1653869fb78SDag-Erling Smørgrav int envlen, extralen, i; 1663869fb78SDag-Erling Smørgrav int pam_err, serrno, status; 1673869fb78SDag-Erling Smørgrav int chout[2], cherr[2], pd; 1683869fb78SDag-Erling Smørgrav nfds_t nfds; 1693902d8a9SJean-Sébastien Pédron pid_t pid; 1703902d8a9SJean-Sébastien Pédron 1713869fb78SDag-Erling Smørgrav pd = -1; 1723869fb78SDag-Erling Smørgrav pid = 0; 1733869fb78SDag-Erling Smørgrav chout[0] = chout[1] = cherr[0] = cherr[1] = -1; 1743869fb78SDag-Erling Smørgrav envlist = NULL; 1753869fb78SDag-Erling Smørgrav 1763869fb78SDag-Erling Smørgrav #define OUT(ret) do { pam_err = (ret); goto out; } while (0) 1777e3d5c1fSJean-Sébastien Pédron 1787e3d5c1fSJean-Sébastien Pédron /* Check there's a program name left after parsing options. */ 1797e3d5c1fSJean-Sébastien Pédron if (argc < 1) { 1807e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s: No program specified: aborting", 1817e3d5c1fSJean-Sébastien Pédron func); 1823869fb78SDag-Erling Smørgrav OUT(PAM_SERVICE_ERR); 1837e3d5c1fSJean-Sébastien Pédron } 1847e3d5c1fSJean-Sébastien Pédron 1857e3d5c1fSJean-Sébastien Pédron /* 1869d97c7eeSDag-Erling Smørgrav * Set up the child's environment list. It consists of the PAM 1873869fb78SDag-Erling Smørgrav * environment, a few hand-picked PAM items, the name of the 1883869fb78SDag-Erling Smørgrav * service function, and if return_prog_exit_status is set, the 1893869fb78SDag-Erling Smørgrav * numerical values of all PAM error codes. 1909d97c7eeSDag-Erling Smørgrav */ 1913869fb78SDag-Erling Smørgrav 1923869fb78SDag-Erling Smørgrav /* compute the final size of the environment. */ 193a76a4d44SDag-Erling Smørgrav envlist = pam_getenvlist(pamh); 1949d97c7eeSDag-Erling Smørgrav for (envlen = 0; envlist[envlen] != NULL; ++envlen) 1959d97c7eeSDag-Erling Smørgrav /* nothing */ ; 1963869fb78SDag-Erling Smørgrav extralen = NUM_PAM_ITEM_ENV + 1; 1973869fb78SDag-Erling Smørgrav if (options->return_prog_exit_status) 1983869fb78SDag-Erling Smørgrav extralen += NUM_PAM_ERR_ENV; 1993869fb78SDag-Erling Smørgrav tmp = reallocarray(envlist, envlen + extralen + 1, sizeof(*envlist)); 2003869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_DEBUG, "envlen = %d extralen = %d tmp = %p", 2013869fb78SDag-Erling Smørgrav envlen, extralen, tmp); 2023869fb78SDag-Erling Smørgrav if (tmp == NULL) 2033869fb78SDag-Erling Smørgrav OUT(PAM_BUF_ERR); 2049d97c7eeSDag-Erling Smørgrav envlist = tmp; 2053869fb78SDag-Erling Smørgrav extralen += envlen; 2069d97c7eeSDag-Erling Smørgrav 2073869fb78SDag-Erling Smørgrav /* copy selected PAM items to the environment */ 2083869fb78SDag-Erling Smørgrav for (i = 0; i < NUM_PAM_ITEM_ENV; ++i) { 2093869fb78SDag-Erling Smørgrav pam_err = pam_get_item(pamh, pam_item_env[i].item, &item); 2109d97c7eeSDag-Erling Smørgrav if (pam_err != PAM_SUCCESS || item == NULL) 2119d97c7eeSDag-Erling Smørgrav continue; 2123869fb78SDag-Erling Smørgrav if (asprintf(&envstr, "%s=%s", pam_item_env[i].name, item) < 0) 2133869fb78SDag-Erling Smørgrav OUT(PAM_BUF_ERR); 2149d97c7eeSDag-Erling Smørgrav envlist[envlen++] = envstr; 2159d97c7eeSDag-Erling Smørgrav envlist[envlen] = NULL; 2163869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_DEBUG, "setenv %s", envstr); 2179d97c7eeSDag-Erling Smørgrav } 2189d97c7eeSDag-Erling Smørgrav 2193869fb78SDag-Erling Smørgrav /* add the name of the service function to the environment */ 2203869fb78SDag-Erling Smørgrav if (asprintf(&envstr, "PAM_SM_FUNC=%s", func) < 0) 2213869fb78SDag-Erling Smørgrav OUT(PAM_BUF_ERR); 2227e3d5c1fSJean-Sébastien Pédron envlist[envlen++] = envstr; 2233869fb78SDag-Erling Smørgrav envlist[envlen] = NULL; 2247e3d5c1fSJean-Sébastien Pédron 2253869fb78SDag-Erling Smørgrav /* add the PAM error codes to the environment. */ 2263902d8a9SJean-Sébastien Pédron if (options->return_prog_exit_status) { 2273869fb78SDag-Erling Smørgrav for (i = 0; i < (int)NUM_PAM_ERR_ENV; ++i) { 2283869fb78SDag-Erling Smørgrav if ((envstr = strdup(pam_err_env[i])) == NULL) 2293869fb78SDag-Erling Smørgrav OUT(PAM_BUF_ERR); 2303869fb78SDag-Erling Smørgrav envlist[envlen++] = envstr; 2313869fb78SDag-Erling Smørgrav envlist[envlen] = NULL; 2323869fb78SDag-Erling Smørgrav } 2337e3d5c1fSJean-Sébastien Pédron } 2347e3d5c1fSJean-Sébastien Pédron 2353869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_DEBUG, "envlen = %d extralen = %d envlist = %p", 2363869fb78SDag-Erling Smørgrav envlen, extralen, envlist); 2377e3d5c1fSJean-Sébastien Pédron 2383869fb78SDag-Erling Smørgrav /* set up pipes if capture was requested */ 2393869fb78SDag-Erling Smørgrav if (options->capture_stdout) { 2403869fb78SDag-Erling Smørgrav if (pipe(chout) != 0) { 2413869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: pipe(): %m", func); 2423869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2433869fb78SDag-Erling Smørgrav } 2443869fb78SDag-Erling Smørgrav if (fcntl(chout[0], F_SETFL, O_NONBLOCK) != 0) { 2453869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: fcntl(): %m", func); 2463869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2473869fb78SDag-Erling Smørgrav } 2483869fb78SDag-Erling Smørgrav } else { 2493869fb78SDag-Erling Smørgrav if ((chout[1] = open("/dev/null", O_RDWR)) < 0) { 2503869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: /dev/null: %m", func); 2513869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2523869fb78SDag-Erling Smørgrav } 2533869fb78SDag-Erling Smørgrav } 2543869fb78SDag-Erling Smørgrav if (options->capture_stderr) { 2553869fb78SDag-Erling Smørgrav if (pipe(cherr) != 0) { 2563869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: pipe(): %m", func); 2573869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2583869fb78SDag-Erling Smørgrav } 2593869fb78SDag-Erling Smørgrav if (fcntl(cherr[0], F_SETFL, O_NONBLOCK) != 0) { 2603869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: fcntl(): %m", func); 2613869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2623869fb78SDag-Erling Smørgrav } 2633869fb78SDag-Erling Smørgrav } else { 2643869fb78SDag-Erling Smørgrav if ((cherr[1] = open("/dev/null", O_RDWR)) < 0) { 2653869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: /dev/null: %m", func); 2663869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2673869fb78SDag-Erling Smørgrav } 2683869fb78SDag-Erling Smørgrav } 2693869fb78SDag-Erling Smørgrav 2703869fb78SDag-Erling Smørgrav if ((pid = pdfork(&pd, 0)) == 0) { 2713869fb78SDag-Erling Smørgrav /* child */ 2723869fb78SDag-Erling Smørgrav if ((chout[0] >= 0 && close(chout[0]) != 0) || 2733869fb78SDag-Erling Smørgrav (cherr[0] >= 0 && close(cherr[0]) != 0)) { 2743869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: close(): %m", func); 2753869fb78SDag-Erling Smørgrav } else if (dup2(chout[1], STDOUT_FILENO) != STDOUT_FILENO || 2763869fb78SDag-Erling Smørgrav dup2(cherr[1], STDERR_FILENO) != STDERR_FILENO) { 2773869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: dup2(): %m", func); 2783869fb78SDag-Erling Smørgrav } else { 2793869fb78SDag-Erling Smørgrav execve(argv[0], (char * const *)argv, 2803869fb78SDag-Erling Smørgrav (char * const *)envlist); 2813869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: execve(%s): %m", 2823869fb78SDag-Erling Smørgrav func, argv[0]); 2833869fb78SDag-Erling Smørgrav } 284f65b2180SDag-Erling Smørgrav _exit(1); 285a76a4d44SDag-Erling Smørgrav } 2863869fb78SDag-Erling Smørgrav /* parent */ 287a76a4d44SDag-Erling Smørgrav if (pid == -1) { 2883869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: pdfork(): %m", func); 2893869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 290f65b2180SDag-Erling Smørgrav } 2913869fb78SDag-Erling Smørgrav /* use poll() to watch the process and stdout / stderr */ 2923869fb78SDag-Erling Smørgrav if (chout[1] >= 0) 2933869fb78SDag-Erling Smørgrav close(chout[1]); 2943869fb78SDag-Erling Smørgrav if (cherr[1] >= 0) 2953869fb78SDag-Erling Smørgrav close(cherr[1]); 2963869fb78SDag-Erling Smørgrav memset(pfd, 0, sizeof pfd); 2973869fb78SDag-Erling Smørgrav pfd[0].fd = pd; 2983869fb78SDag-Erling Smørgrav pfd[0].events = POLLHUP; 2993869fb78SDag-Erling Smørgrav nfds = 1; 3003869fb78SDag-Erling Smørgrav if (options->capture_stdout) { 3013869fb78SDag-Erling Smørgrav pfd[nfds].fd = chout[0]; 3023869fb78SDag-Erling Smørgrav pfd[nfds].events = POLLIN|POLLERR|POLLHUP; 3033869fb78SDag-Erling Smørgrav nfds++; 3043869fb78SDag-Erling Smørgrav } 3053869fb78SDag-Erling Smørgrav if (options->capture_stderr) { 3063869fb78SDag-Erling Smørgrav pfd[nfds].fd = cherr[0]; 3073869fb78SDag-Erling Smørgrav pfd[nfds].events = POLLIN|POLLERR|POLLHUP; 3083869fb78SDag-Erling Smørgrav nfds++; 3093869fb78SDag-Erling Smørgrav } 3103869fb78SDag-Erling Smørgrav 3113869fb78SDag-Erling Smørgrav /* loop until the process exits */ 3123869fb78SDag-Erling Smørgrav do { 3133869fb78SDag-Erling Smørgrav if (poll(pfd, nfds, INFTIM) < 0) { 3143869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: poll(): %m", func); 3153869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 3163869fb78SDag-Erling Smørgrav } 3173869fb78SDag-Erling Smørgrav for (i = 1; i < nfds; ++i) { 3183869fb78SDag-Erling Smørgrav if ((pfd[i].revents & POLLIN) == 0) 3193869fb78SDag-Erling Smørgrav continue; 3203869fb78SDag-Erling Smørgrav if ((rlen = read(pfd[i].fd, buf, sizeof(buf) - 1)) < 0) { 3213869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: read(): %m", 3223869fb78SDag-Erling Smørgrav func); 3233869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 3243869fb78SDag-Erling Smørgrav } else if (rlen == 0) { 3253869fb78SDag-Erling Smørgrav continue; 3263869fb78SDag-Erling Smørgrav } 3273869fb78SDag-Erling Smørgrav buf[rlen] = '\0'; 3283869fb78SDag-Erling Smørgrav (void)pam_prompt(pamh, pfd[i].fd == chout[0] ? 3293869fb78SDag-Erling Smørgrav PAM_TEXT_INFO : PAM_ERROR_MSG, &resp, "%s", buf); 3303869fb78SDag-Erling Smørgrav } 3313869fb78SDag-Erling Smørgrav } while (pfd[0].revents == 0); 3323869fb78SDag-Erling Smørgrav 3333869fb78SDag-Erling Smørgrav /* the child process has exited */ 3347e3d5c1fSJean-Sébastien Pédron while (waitpid(pid, &status, 0) == -1) { 3357e3d5c1fSJean-Sébastien Pédron if (errno == EINTR) 3367e3d5c1fSJean-Sébastien Pédron continue; 3377e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s: waitpid(): %m", func); 3383869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 339f65b2180SDag-Erling Smørgrav } 3403869fb78SDag-Erling Smørgrav 3413869fb78SDag-Erling Smørgrav /* check exit code */ 342f65b2180SDag-Erling Smørgrav if (WIFSIGNALED(status)) { 3437e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s: %s caught signal %d%s", 3447e3d5c1fSJean-Sébastien Pédron func, argv[0], WTERMSIG(status), 345f65b2180SDag-Erling Smørgrav WCOREDUMP(status) ? " (core dumped)" : ""); 3463869fb78SDag-Erling Smørgrav OUT(PAM_SERVICE_ERR); 347f65b2180SDag-Erling Smørgrav } 348f65b2180SDag-Erling Smørgrav if (!WIFEXITED(status)) { 3497e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s: unknown status 0x%x", 3507e3d5c1fSJean-Sébastien Pédron func, status); 3513869fb78SDag-Erling Smørgrav OUT(PAM_SERVICE_ERR); 352f65b2180SDag-Erling Smørgrav } 3537e3d5c1fSJean-Sébastien Pédron 3543902d8a9SJean-Sébastien Pédron if (options->return_prog_exit_status) { 3557e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_DEBUG, 3567e3d5c1fSJean-Sébastien Pédron "%s: Use program exit status as return value: %d", 3577e3d5c1fSJean-Sébastien Pédron func, WEXITSTATUS(status)); 3583869fb78SDag-Erling Smørgrav OUT(WEXITSTATUS(status)); 3597e3d5c1fSJean-Sébastien Pédron } else { 3603869fb78SDag-Erling Smørgrav OUT(WEXITSTATUS(status) == 0 ? PAM_SUCCESS : PAM_PERM_DENIED); 361f65b2180SDag-Erling Smørgrav } 3623869fb78SDag-Erling Smørgrav /* unreachable */ 3633869fb78SDag-Erling Smørgrav out: 3643869fb78SDag-Erling Smørgrav serrno = errno; 3653869fb78SDag-Erling Smørgrav if (pd >= 0) 3663869fb78SDag-Erling Smørgrav close(pd); 3673869fb78SDag-Erling Smørgrav if (chout[0] >= 0) 3683869fb78SDag-Erling Smørgrav close(chout[0]); 3693869fb78SDag-Erling Smørgrav if (chout[1] >= 0) 3703869fb78SDag-Erling Smørgrav close(chout[1]); 3713869fb78SDag-Erling Smørgrav if (cherr[0] >= 0) 3723869fb78SDag-Erling Smørgrav close(cherr[0]); 3733869fb78SDag-Erling Smørgrav if (cherr[0] >= 0) 3743869fb78SDag-Erling Smørgrav close(cherr[1]); 3753869fb78SDag-Erling Smørgrav if (envlist != NULL) 3763869fb78SDag-Erling Smørgrav openpam_free_envlist(envlist); 3773869fb78SDag-Erling Smørgrav errno = serrno; 3783869fb78SDag-Erling Smørgrav return (pam_err); 379f65b2180SDag-Erling Smørgrav } 380f65b2180SDag-Erling Smørgrav 381f65b2180SDag-Erling Smørgrav PAM_EXTERN int 382f65b2180SDag-Erling Smørgrav pam_sm_authenticate(pam_handle_t *pamh, int flags, 383f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 384f65b2180SDag-Erling Smørgrav { 3857e3d5c1fSJean-Sébastien Pédron int ret; 3863902d8a9SJean-Sébastien Pédron struct pe_opts options; 387f65b2180SDag-Erling Smørgrav 3883902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 3893902d8a9SJean-Sébastien Pédron if (ret != 0) 3903902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 3913902d8a9SJean-Sébastien Pédron 3923902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 3937e3d5c1fSJean-Sébastien Pédron 3947e3d5c1fSJean-Sébastien Pédron /* 3957e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 3967e3d5c1fSJean-Sébastien Pédron * function. 3977e3d5c1fSJean-Sébastien Pédron */ 3987e3d5c1fSJean-Sébastien Pédron switch (ret) { 3997e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 4007e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 4017e3d5c1fSJean-Sébastien Pédron case PAM_AUTHINFO_UNAVAIL: 4027e3d5c1fSJean-Sébastien Pédron case PAM_AUTH_ERR: 4037e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 4047e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 4057e3d5c1fSJean-Sébastien Pédron case PAM_CRED_INSUFFICIENT: 4067e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 4077e3d5c1fSJean-Sébastien Pédron case PAM_MAXTRIES: 4087e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 4097e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 4107e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 4117e3d5c1fSJean-Sébastien Pédron case PAM_USER_UNKNOWN: 4127e3d5c1fSJean-Sébastien Pédron break; 4137e3d5c1fSJean-Sébastien Pédron default: 4147e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 4157e3d5c1fSJean-Sébastien Pédron argv[0], ret); 4167e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 4177e3d5c1fSJean-Sébastien Pédron } 4187e3d5c1fSJean-Sébastien Pédron 4197e3d5c1fSJean-Sébastien Pédron return (ret); 420f65b2180SDag-Erling Smørgrav } 421f65b2180SDag-Erling Smørgrav 422f65b2180SDag-Erling Smørgrav PAM_EXTERN int 423f65b2180SDag-Erling Smørgrav pam_sm_setcred(pam_handle_t *pamh, int flags, 424f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 425f65b2180SDag-Erling Smørgrav { 4267e3d5c1fSJean-Sébastien Pédron int ret; 4273902d8a9SJean-Sébastien Pédron struct pe_opts options; 428f65b2180SDag-Erling Smørgrav 4293902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 4303902d8a9SJean-Sébastien Pédron if (ret != 0) 4313902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 4323902d8a9SJean-Sébastien Pédron 4333902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 4347e3d5c1fSJean-Sébastien Pédron 4357e3d5c1fSJean-Sébastien Pédron /* 4367e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 4377e3d5c1fSJean-Sébastien Pédron * function. 4387e3d5c1fSJean-Sébastien Pédron */ 4397e3d5c1fSJean-Sébastien Pédron switch (ret) { 4407e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 4417e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 4427e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 4437e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 4447e3d5c1fSJean-Sébastien Pédron case PAM_CRED_ERR: 4457e3d5c1fSJean-Sébastien Pédron case PAM_CRED_EXPIRED: 4467e3d5c1fSJean-Sébastien Pédron case PAM_CRED_UNAVAIL: 4477e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 4487e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 4497e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 4507e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 4517e3d5c1fSJean-Sébastien Pédron case PAM_USER_UNKNOWN: 4527e3d5c1fSJean-Sébastien Pédron break; 4537e3d5c1fSJean-Sébastien Pédron default: 4547e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 4557e3d5c1fSJean-Sébastien Pédron argv[0], ret); 4567e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 4577e3d5c1fSJean-Sébastien Pédron } 4587e3d5c1fSJean-Sébastien Pédron 4597e3d5c1fSJean-Sébastien Pédron return (ret); 460f65b2180SDag-Erling Smørgrav } 461f65b2180SDag-Erling Smørgrav 462f65b2180SDag-Erling Smørgrav PAM_EXTERN int 463f65b2180SDag-Erling Smørgrav pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, 464f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 465f65b2180SDag-Erling Smørgrav { 4667e3d5c1fSJean-Sébastien Pédron int ret; 4673902d8a9SJean-Sébastien Pédron struct pe_opts options; 468f65b2180SDag-Erling Smørgrav 4693902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 4703902d8a9SJean-Sébastien Pédron if (ret != 0) 4713902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 4723902d8a9SJean-Sébastien Pédron 4733902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 4747e3d5c1fSJean-Sébastien Pédron 4757e3d5c1fSJean-Sébastien Pédron /* 4767e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 4777e3d5c1fSJean-Sébastien Pédron * function. 4787e3d5c1fSJean-Sébastien Pédron */ 4797e3d5c1fSJean-Sébastien Pédron switch (ret) { 4807e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 4817e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 4827e3d5c1fSJean-Sébastien Pédron case PAM_ACCT_EXPIRED: 4837e3d5c1fSJean-Sébastien Pédron case PAM_AUTH_ERR: 4847e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 4857e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 4867e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 4877e3d5c1fSJean-Sébastien Pédron case PAM_NEW_AUTHTOK_REQD: 4887e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 4897e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 4907e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 4917e3d5c1fSJean-Sébastien Pédron case PAM_USER_UNKNOWN: 4927e3d5c1fSJean-Sébastien Pédron break; 4937e3d5c1fSJean-Sébastien Pédron default: 4947e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 4957e3d5c1fSJean-Sébastien Pédron argv[0], ret); 4967e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 4977e3d5c1fSJean-Sébastien Pédron } 4987e3d5c1fSJean-Sébastien Pédron 4997e3d5c1fSJean-Sébastien Pédron return (ret); 500f65b2180SDag-Erling Smørgrav } 501f65b2180SDag-Erling Smørgrav 502f65b2180SDag-Erling Smørgrav PAM_EXTERN int 503f65b2180SDag-Erling Smørgrav pam_sm_open_session(pam_handle_t *pamh, int flags, 504f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 505f65b2180SDag-Erling Smørgrav { 5067e3d5c1fSJean-Sébastien Pédron int ret; 5073902d8a9SJean-Sébastien Pédron struct pe_opts options; 508f65b2180SDag-Erling Smørgrav 5093902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 5103902d8a9SJean-Sébastien Pédron if (ret != 0) 5113902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 5123902d8a9SJean-Sébastien Pédron 5133902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 5147e3d5c1fSJean-Sébastien Pédron 5157e3d5c1fSJean-Sébastien Pédron /* 5167e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 5177e3d5c1fSJean-Sébastien Pédron * function. 5187e3d5c1fSJean-Sébastien Pédron */ 5197e3d5c1fSJean-Sébastien Pédron switch (ret) { 5207e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 5217e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 5227e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 5237e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 5247e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 5257e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 5267e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 5277e3d5c1fSJean-Sébastien Pédron case PAM_SESSION_ERR: 5287e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 5297e3d5c1fSJean-Sébastien Pédron break; 5307e3d5c1fSJean-Sébastien Pédron default: 5317e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 5327e3d5c1fSJean-Sébastien Pédron argv[0], ret); 5337e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 5347e3d5c1fSJean-Sébastien Pédron } 5357e3d5c1fSJean-Sébastien Pédron 5367e3d5c1fSJean-Sébastien Pédron return (ret); 537f65b2180SDag-Erling Smørgrav } 538f65b2180SDag-Erling Smørgrav 539f65b2180SDag-Erling Smørgrav PAM_EXTERN int 540f65b2180SDag-Erling Smørgrav pam_sm_close_session(pam_handle_t *pamh, int flags, 541f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 542f65b2180SDag-Erling Smørgrav { 5437e3d5c1fSJean-Sébastien Pédron int ret; 5443902d8a9SJean-Sébastien Pédron struct pe_opts options; 545f65b2180SDag-Erling Smørgrav 5463902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 5473902d8a9SJean-Sébastien Pédron if (ret != 0) 5483902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 5493902d8a9SJean-Sébastien Pédron 5503902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 5517e3d5c1fSJean-Sébastien Pédron 5527e3d5c1fSJean-Sébastien Pédron /* 5537e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 5547e3d5c1fSJean-Sébastien Pédron * function. 5557e3d5c1fSJean-Sébastien Pédron */ 5567e3d5c1fSJean-Sébastien Pédron switch (ret) { 5577e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 5587e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 5597e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 5607e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 5617e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 5627e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 5637e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 5647e3d5c1fSJean-Sébastien Pédron case PAM_SESSION_ERR: 5657e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 5667e3d5c1fSJean-Sébastien Pédron break; 5677e3d5c1fSJean-Sébastien Pédron default: 5687e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 5697e3d5c1fSJean-Sébastien Pédron argv[0], ret); 5707e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 5717e3d5c1fSJean-Sébastien Pédron } 5727e3d5c1fSJean-Sébastien Pédron 5737e3d5c1fSJean-Sébastien Pédron return (ret); 574f65b2180SDag-Erling Smørgrav } 575f65b2180SDag-Erling Smørgrav 576f65b2180SDag-Erling Smørgrav PAM_EXTERN int 577f65b2180SDag-Erling Smørgrav pam_sm_chauthtok(pam_handle_t *pamh, int flags, 578f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 579f65b2180SDag-Erling Smørgrav { 5807e3d5c1fSJean-Sébastien Pédron int ret; 5813902d8a9SJean-Sébastien Pédron struct pe_opts options; 582f65b2180SDag-Erling Smørgrav 5833902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 5843902d8a9SJean-Sébastien Pédron if (ret != 0) 5853902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 5863902d8a9SJean-Sébastien Pédron 5873902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 5887e3d5c1fSJean-Sébastien Pédron 5897e3d5c1fSJean-Sébastien Pédron /* 5907e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 5917e3d5c1fSJean-Sébastien Pédron * function. 5927e3d5c1fSJean-Sébastien Pédron */ 5937e3d5c1fSJean-Sébastien Pédron switch (ret) { 5947e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 5957e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 5967e3d5c1fSJean-Sébastien Pédron case PAM_AUTHTOK_DISABLE_AGING: 5977e3d5c1fSJean-Sébastien Pédron case PAM_AUTHTOK_ERR: 5987e3d5c1fSJean-Sébastien Pédron case PAM_AUTHTOK_LOCK_BUSY: 5997e3d5c1fSJean-Sébastien Pédron case PAM_AUTHTOK_RECOVERY_ERR: 6007e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 6017e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 6027e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 6037e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 6047e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 6057e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 6067e3d5c1fSJean-Sébastien Pédron case PAM_TRY_AGAIN: 6077e3d5c1fSJean-Sébastien Pédron break; 6087e3d5c1fSJean-Sébastien Pédron default: 6097e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 6107e3d5c1fSJean-Sébastien Pédron argv[0], ret); 6117e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 6127e3d5c1fSJean-Sébastien Pédron } 6137e3d5c1fSJean-Sébastien Pédron 6147e3d5c1fSJean-Sébastien Pédron return (ret); 615f65b2180SDag-Erling Smørgrav } 616f65b2180SDag-Erling Smørgrav 617f65b2180SDag-Erling Smørgrav PAM_MODULE_ENTRY("pam_exec"); 618