1f65b2180SDag-Erling Smørgrav /*- 25e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 35e53a4f9SPedro 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 6bb3ba83eSDag-Erling Smørgrav * Copyright (c) 2018 Thomas Munro 7f65b2180SDag-Erling Smørgrav * All rights reserved. 8f65b2180SDag-Erling Smørgrav * 9f65b2180SDag-Erling Smørgrav * This software was developed for the FreeBSD Project by ThinkSec AS and 10f65b2180SDag-Erling Smørgrav * NAI Labs, the Security Research Division of Network Associates, Inc. 11f65b2180SDag-Erling Smørgrav * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 12f65b2180SDag-Erling Smørgrav * DARPA CHATS research program. 13f65b2180SDag-Erling Smørgrav * 14f65b2180SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 15f65b2180SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 16f65b2180SDag-Erling Smørgrav * are met: 17f65b2180SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 18f65b2180SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 19f65b2180SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 20f65b2180SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 21f65b2180SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 22f65b2180SDag-Erling Smørgrav * 3. The name of the author may not be used to endorse or promote 23f65b2180SDag-Erling Smørgrav * products derived from this software without specific prior written 24f65b2180SDag-Erling Smørgrav * permission. 25f65b2180SDag-Erling Smørgrav * 26f65b2180SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 27f65b2180SDag-Erling Smørgrav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28f65b2180SDag-Erling Smørgrav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29f65b2180SDag-Erling Smørgrav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 30f65b2180SDag-Erling Smørgrav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31f65b2180SDag-Erling Smørgrav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32f65b2180SDag-Erling Smørgrav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33f65b2180SDag-Erling Smørgrav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34f65b2180SDag-Erling Smørgrav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35f65b2180SDag-Erling Smørgrav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36f65b2180SDag-Erling Smørgrav * SUCH DAMAGE. 37f65b2180SDag-Erling Smørgrav */ 38f65b2180SDag-Erling Smørgrav 39f65b2180SDag-Erling Smørgrav #include <sys/cdefs.h> 40f65b2180SDag-Erling Smørgrav __FBSDID("$FreeBSD$"); 41f65b2180SDag-Erling Smørgrav 42f65b2180SDag-Erling Smørgrav #include <sys/types.h> 433869fb78SDag-Erling Smørgrav #include <sys/poll.h> 443869fb78SDag-Erling Smørgrav #include <sys/procdesc.h> 45f65b2180SDag-Erling Smørgrav #include <sys/wait.h> 46f65b2180SDag-Erling Smørgrav 47f65b2180SDag-Erling Smørgrav #include <errno.h> 483869fb78SDag-Erling Smørgrav #include <fcntl.h> 498bdb099aSEd Schouten #include <stdio.h> 50f65b2180SDag-Erling Smørgrav #include <stdlib.h> 51f65b2180SDag-Erling Smørgrav #include <string.h> 52f65b2180SDag-Erling Smørgrav #include <unistd.h> 53f65b2180SDag-Erling Smørgrav 54f65b2180SDag-Erling Smørgrav #include <security/pam_appl.h> 55f65b2180SDag-Erling Smørgrav #include <security/pam_modules.h> 56f65b2180SDag-Erling Smørgrav #include <security/openpam.h> 57f65b2180SDag-Erling Smørgrav 583869fb78SDag-Erling Smørgrav #define PAM_ITEM_ENV(n) { (n), #n } 599d97c7eeSDag-Erling Smørgrav static struct { 609d97c7eeSDag-Erling Smørgrav int item; 619d97c7eeSDag-Erling Smørgrav const char *name; 623869fb78SDag-Erling Smørgrav } pam_item_env[] = { 633869fb78SDag-Erling Smørgrav PAM_ITEM_ENV(PAM_SERVICE), 643869fb78SDag-Erling Smørgrav PAM_ITEM_ENV(PAM_USER), 653869fb78SDag-Erling Smørgrav PAM_ITEM_ENV(PAM_TTY), 663869fb78SDag-Erling Smørgrav PAM_ITEM_ENV(PAM_RHOST), 673869fb78SDag-Erling Smørgrav PAM_ITEM_ENV(PAM_RUSER), 689d97c7eeSDag-Erling Smørgrav }; 693869fb78SDag-Erling Smørgrav #define NUM_PAM_ITEM_ENV (sizeof(pam_item_env) / sizeof(pam_item_env[0])) 703869fb78SDag-Erling Smørgrav 713869fb78SDag-Erling Smørgrav #define PAM_ERR_ENV_X(str, num) str "=" #num 723869fb78SDag-Erling Smørgrav #define PAM_ERR_ENV(pam_err) PAM_ERR_ENV_X(#pam_err, pam_err) 733869fb78SDag-Erling Smørgrav static const char *pam_err_env[] = { 743869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_SUCCESS), 753869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_OPEN_ERR), 763869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_SYMBOL_ERR), 773869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_SERVICE_ERR), 783869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_SYSTEM_ERR), 793869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_BUF_ERR), 803869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_CONV_ERR), 813869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_PERM_DENIED), 823869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_MAXTRIES), 833869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTH_ERR), 843869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_NEW_AUTHTOK_REQD), 853869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_CRED_INSUFFICIENT), 863869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHINFO_UNAVAIL), 873869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_USER_UNKNOWN), 883869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_CRED_UNAVAIL), 893869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_CRED_EXPIRED), 903869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_CRED_ERR), 913869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_ACCT_EXPIRED), 923869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHTOK_EXPIRED), 933869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_SESSION_ERR), 943869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHTOK_ERR), 953869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHTOK_RECOVERY_ERR), 963869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHTOK_LOCK_BUSY), 973869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_AUTHTOK_DISABLE_AGING), 983869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_NO_MODULE_DATA), 993869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_IGNORE), 1003869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_ABORT), 1013869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_TRY_AGAIN), 1023869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_MODULE_UNKNOWN), 1033869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_DOMAIN_UNKNOWN), 1043869fb78SDag-Erling Smørgrav PAM_ERR_ENV(PAM_NUM_ERR), 1053869fb78SDag-Erling Smørgrav }; 1063869fb78SDag-Erling Smørgrav #define NUM_PAM_ERR_ENV (sizeof(pam_err_env) / sizeof(pam_err_env[0])) 1079d97c7eeSDag-Erling Smørgrav 1083902d8a9SJean-Sébastien Pédron struct pe_opts { 1093902d8a9SJean-Sébastien Pédron int return_prog_exit_status; 1103869fb78SDag-Erling Smørgrav int capture_stdout; 1113869fb78SDag-Erling Smørgrav int capture_stderr; 112bb3ba83eSDag-Erling Smørgrav int expose_authtok; 1133902d8a9SJean-Sébastien Pédron }; 1143902d8a9SJean-Sébastien Pédron 115f65b2180SDag-Erling Smørgrav static int 1163902d8a9SJean-Sébastien Pédron parse_options(const char *func, int *argc, const char **argv[], 1173902d8a9SJean-Sébastien Pédron struct pe_opts *options) 118f65b2180SDag-Erling Smørgrav { 1193902d8a9SJean-Sébastien Pédron int i; 1209d97c7eeSDag-Erling Smørgrav 1219d97c7eeSDag-Erling Smørgrav /* 1227e3d5c1fSJean-Sébastien Pédron * Parse options: 1237e3d5c1fSJean-Sébastien Pédron * return_prog_exit_status: 1247e3d5c1fSJean-Sébastien Pédron * use the program exit status as the return code of pam_exec 1257e3d5c1fSJean-Sébastien Pédron * --: 1267e3d5c1fSJean-Sébastien Pédron * stop options parsing; what follows is the command to execute 1277e3d5c1fSJean-Sébastien Pédron */ 1283869fb78SDag-Erling Smørgrav memset(options, 0, sizeof(*options)); 1293902d8a9SJean-Sébastien Pédron 1303902d8a9SJean-Sébastien Pédron for (i = 0; i < *argc; ++i) { 1313869fb78SDag-Erling Smørgrav if (strcmp((*argv)[i], "debug") == 0 || 1323869fb78SDag-Erling Smørgrav strcmp((*argv)[i], "no_warn") == 0) { 1333869fb78SDag-Erling Smørgrav /* ignore */ 1343869fb78SDag-Erling Smørgrav } else if (strcmp((*argv)[i], "capture_stdout") == 0) { 1353869fb78SDag-Erling Smørgrav options->capture_stdout = 1; 1363869fb78SDag-Erling Smørgrav } else if (strcmp((*argv)[i], "capture_stderr") == 0) { 1373869fb78SDag-Erling Smørgrav options->capture_stderr = 1; 1383869fb78SDag-Erling Smørgrav } else if (strcmp((*argv)[i], "return_prog_exit_status") == 0) { 1393902d8a9SJean-Sébastien Pédron options->return_prog_exit_status = 1; 140bb3ba83eSDag-Erling Smørgrav } else if (strcmp((*argv)[i], "expose_authtok") == 0) { 141bb3ba83eSDag-Erling Smørgrav options->expose_authtok = 1; 1427e3d5c1fSJean-Sébastien Pédron } else { 1433902d8a9SJean-Sébastien Pédron if (strcmp((*argv)[i], "--") == 0) { 1443902d8a9SJean-Sébastien Pédron (*argc)--; 1453902d8a9SJean-Sébastien Pédron (*argv)++; 1467e3d5c1fSJean-Sébastien Pédron } 1477e3d5c1fSJean-Sébastien Pédron break; 1487e3d5c1fSJean-Sébastien Pédron } 1493869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_DEBUG, "%s: option \"%s\" enabled", 1503869fb78SDag-Erling Smørgrav func, (*argv)[i]); 1517e3d5c1fSJean-Sébastien Pédron } 1527e3d5c1fSJean-Sébastien Pédron 1533902d8a9SJean-Sébastien Pédron (*argc) -= i; 1543902d8a9SJean-Sébastien Pédron (*argv) += i; 1553902d8a9SJean-Sébastien Pédron 1563902d8a9SJean-Sébastien Pédron return (0); 1573902d8a9SJean-Sébastien Pédron } 1583902d8a9SJean-Sébastien Pédron 1593902d8a9SJean-Sébastien Pédron static int 1603869fb78SDag-Erling Smørgrav _pam_exec(pam_handle_t *pamh, 1613902d8a9SJean-Sébastien Pédron const char *func, int flags __unused, int argc, const char *argv[], 1623902d8a9SJean-Sébastien Pédron struct pe_opts *options) 1633902d8a9SJean-Sébastien Pédron { 1643869fb78SDag-Erling Smørgrav char buf[PAM_MAX_MSG_SIZE]; 165bb3ba83eSDag-Erling Smørgrav struct pollfd pfd[4]; 1663869fb78SDag-Erling Smørgrav const void *item; 1673869fb78SDag-Erling Smørgrav char **envlist, *envstr, *resp, **tmp; 168bb3ba83eSDag-Erling Smørgrav ssize_t rlen, wlen; 1693869fb78SDag-Erling Smørgrav int envlen, extralen, i; 1703869fb78SDag-Erling Smørgrav int pam_err, serrno, status; 171bb3ba83eSDag-Erling Smørgrav int chin[2], chout[2], cherr[2], pd; 172bb3ba83eSDag-Erling Smørgrav nfds_t nfds, nreadfds; 1733902d8a9SJean-Sébastien Pédron pid_t pid; 174bb3ba83eSDag-Erling Smørgrav const char *authtok; 175bb3ba83eSDag-Erling Smørgrav size_t authtok_size; 176bb3ba83eSDag-Erling Smørgrav int rc; 1773902d8a9SJean-Sébastien Pédron 1783869fb78SDag-Erling Smørgrav pd = -1; 1793869fb78SDag-Erling Smørgrav pid = 0; 180bb3ba83eSDag-Erling Smørgrav chin[0] = chin[1] = chout[0] = chout[1] = cherr[0] = cherr[1] = -1; 1813869fb78SDag-Erling Smørgrav envlist = NULL; 1823869fb78SDag-Erling Smørgrav 1833869fb78SDag-Erling Smørgrav #define OUT(ret) do { pam_err = (ret); goto out; } while (0) 1847e3d5c1fSJean-Sébastien Pédron 1857e3d5c1fSJean-Sébastien Pédron /* Check there's a program name left after parsing options. */ 1867e3d5c1fSJean-Sébastien Pédron if (argc < 1) { 1877e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s: No program specified: aborting", 1887e3d5c1fSJean-Sébastien Pédron func); 1893869fb78SDag-Erling Smørgrav OUT(PAM_SERVICE_ERR); 1907e3d5c1fSJean-Sébastien Pédron } 1917e3d5c1fSJean-Sébastien Pédron 1927e3d5c1fSJean-Sébastien Pédron /* 1939d97c7eeSDag-Erling Smørgrav * Set up the child's environment list. It consists of the PAM 1943869fb78SDag-Erling Smørgrav * environment, a few hand-picked PAM items, the name of the 1953869fb78SDag-Erling Smørgrav * service function, and if return_prog_exit_status is set, the 1963869fb78SDag-Erling Smørgrav * numerical values of all PAM error codes. 1979d97c7eeSDag-Erling Smørgrav */ 1983869fb78SDag-Erling Smørgrav 1993869fb78SDag-Erling Smørgrav /* compute the final size of the environment. */ 200a76a4d44SDag-Erling Smørgrav envlist = pam_getenvlist(pamh); 2019d97c7eeSDag-Erling Smørgrav for (envlen = 0; envlist[envlen] != NULL; ++envlen) 2029d97c7eeSDag-Erling Smørgrav /* nothing */ ; 2033869fb78SDag-Erling Smørgrav extralen = NUM_PAM_ITEM_ENV + 1; 2043869fb78SDag-Erling Smørgrav if (options->return_prog_exit_status) 2053869fb78SDag-Erling Smørgrav extralen += NUM_PAM_ERR_ENV; 2063869fb78SDag-Erling Smørgrav tmp = reallocarray(envlist, envlen + extralen + 1, sizeof(*envlist)); 2073869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_DEBUG, "envlen = %d extralen = %d tmp = %p", 2083869fb78SDag-Erling Smørgrav envlen, extralen, tmp); 2093869fb78SDag-Erling Smørgrav if (tmp == NULL) 2103869fb78SDag-Erling Smørgrav OUT(PAM_BUF_ERR); 2119d97c7eeSDag-Erling Smørgrav envlist = tmp; 2123869fb78SDag-Erling Smørgrav extralen += envlen; 2139d97c7eeSDag-Erling Smørgrav 2143869fb78SDag-Erling Smørgrav /* copy selected PAM items to the environment */ 2153869fb78SDag-Erling Smørgrav for (i = 0; i < NUM_PAM_ITEM_ENV; ++i) { 2163869fb78SDag-Erling Smørgrav pam_err = pam_get_item(pamh, pam_item_env[i].item, &item); 2179d97c7eeSDag-Erling Smørgrav if (pam_err != PAM_SUCCESS || item == NULL) 2189d97c7eeSDag-Erling Smørgrav continue; 2193869fb78SDag-Erling Smørgrav if (asprintf(&envstr, "%s=%s", pam_item_env[i].name, item) < 0) 2203869fb78SDag-Erling Smørgrav OUT(PAM_BUF_ERR); 2219d97c7eeSDag-Erling Smørgrav envlist[envlen++] = envstr; 2229d97c7eeSDag-Erling Smørgrav envlist[envlen] = NULL; 2233869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_DEBUG, "setenv %s", envstr); 2249d97c7eeSDag-Erling Smørgrav } 2259d97c7eeSDag-Erling Smørgrav 2263869fb78SDag-Erling Smørgrav /* add the name of the service function to the environment */ 2273869fb78SDag-Erling Smørgrav if (asprintf(&envstr, "PAM_SM_FUNC=%s", func) < 0) 2283869fb78SDag-Erling Smørgrav OUT(PAM_BUF_ERR); 2297e3d5c1fSJean-Sébastien Pédron envlist[envlen++] = envstr; 2303869fb78SDag-Erling Smørgrav envlist[envlen] = NULL; 2317e3d5c1fSJean-Sébastien Pédron 2323869fb78SDag-Erling Smørgrav /* add the PAM error codes to the environment. */ 2333902d8a9SJean-Sébastien Pédron if (options->return_prog_exit_status) { 2343869fb78SDag-Erling Smørgrav for (i = 0; i < (int)NUM_PAM_ERR_ENV; ++i) { 2353869fb78SDag-Erling Smørgrav if ((envstr = strdup(pam_err_env[i])) == NULL) 2363869fb78SDag-Erling Smørgrav OUT(PAM_BUF_ERR); 2373869fb78SDag-Erling Smørgrav envlist[envlen++] = envstr; 2383869fb78SDag-Erling Smørgrav envlist[envlen] = NULL; 2393869fb78SDag-Erling Smørgrav } 2407e3d5c1fSJean-Sébastien Pédron } 2417e3d5c1fSJean-Sébastien Pédron 2423869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_DEBUG, "envlen = %d extralen = %d envlist = %p", 2433869fb78SDag-Erling Smørgrav envlen, extralen, envlist); 2447e3d5c1fSJean-Sébastien Pédron 245bb3ba83eSDag-Erling Smørgrav /* set up pipe and get authtok if requested */ 246bb3ba83eSDag-Erling Smørgrav if (options->expose_authtok) { 247bb3ba83eSDag-Erling Smørgrav if (pipe(chin) != 0) { 248bb3ba83eSDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: pipe(): %m", func); 249bb3ba83eSDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 250bb3ba83eSDag-Erling Smørgrav } 251bb3ba83eSDag-Erling Smørgrav if (fcntl(chin[1], F_SETFL, O_NONBLOCK)) { 252bb3ba83eSDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: fcntl(): %m", func); 253bb3ba83eSDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 254bb3ba83eSDag-Erling Smørgrav } 255bb3ba83eSDag-Erling Smørgrav rc = pam_get_authtok(pamh, PAM_AUTHTOK, &authtok, NULL); 256bb3ba83eSDag-Erling Smørgrav if (rc == PAM_SUCCESS) { 257*e165d7bcSDag-Erling Smørgrav /* We include the trailing NUL-terminator. */ 258*e165d7bcSDag-Erling Smørgrav authtok_size = strlen(authtok) + 1; 259bb3ba83eSDag-Erling Smørgrav } else { 260bb3ba83eSDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: pam_get_authtok(): %s", func, 261bb3ba83eSDag-Erling Smørgrav pam_strerror(pamh, rc)); 262bb3ba83eSDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 263bb3ba83eSDag-Erling Smørgrav } 264bb3ba83eSDag-Erling Smørgrav } 2653869fb78SDag-Erling Smørgrav /* set up pipes if capture was requested */ 2663869fb78SDag-Erling Smørgrav if (options->capture_stdout) { 2673869fb78SDag-Erling Smørgrav if (pipe(chout) != 0) { 2683869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: pipe(): %m", func); 2693869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2703869fb78SDag-Erling Smørgrav } 2713869fb78SDag-Erling Smørgrav if (fcntl(chout[0], F_SETFL, O_NONBLOCK) != 0) { 2723869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: fcntl(): %m", func); 2733869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2743869fb78SDag-Erling Smørgrav } 2753869fb78SDag-Erling Smørgrav } else { 2763869fb78SDag-Erling Smørgrav if ((chout[1] = open("/dev/null", O_RDWR)) < 0) { 2773869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: /dev/null: %m", func); 2783869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2793869fb78SDag-Erling Smørgrav } 2803869fb78SDag-Erling Smørgrav } 2813869fb78SDag-Erling Smørgrav if (options->capture_stderr) { 2823869fb78SDag-Erling Smørgrav if (pipe(cherr) != 0) { 2833869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: pipe(): %m", func); 2843869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2853869fb78SDag-Erling Smørgrav } 2863869fb78SDag-Erling Smørgrav if (fcntl(cherr[0], F_SETFL, O_NONBLOCK) != 0) { 2873869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: fcntl(): %m", func); 2883869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2893869fb78SDag-Erling Smørgrav } 2903869fb78SDag-Erling Smørgrav } else { 2913869fb78SDag-Erling Smørgrav if ((cherr[1] = open("/dev/null", O_RDWR)) < 0) { 2923869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: /dev/null: %m", func); 2933869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 2943869fb78SDag-Erling Smørgrav } 2953869fb78SDag-Erling Smørgrav } 2963869fb78SDag-Erling Smørgrav 2973869fb78SDag-Erling Smørgrav if ((pid = pdfork(&pd, 0)) == 0) { 2983869fb78SDag-Erling Smørgrav /* child */ 299bb3ba83eSDag-Erling Smørgrav if ((chin[1] >= 0 && close(chin[1]) != 0) || 300bb3ba83eSDag-Erling Smørgrav (chout[0] >= 0 && close(chout[0]) != 0) || 3013869fb78SDag-Erling Smørgrav (cherr[0] >= 0 && close(cherr[0]) != 0)) { 3023869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: close(): %m", func); 303bb3ba83eSDag-Erling Smørgrav } else if (chin[0] >= 0 && 304bb3ba83eSDag-Erling Smørgrav dup2(chin[0], STDIN_FILENO) != STDIN_FILENO) { 305bb3ba83eSDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: dup2(): %m", func); 3063869fb78SDag-Erling Smørgrav } else if (dup2(chout[1], STDOUT_FILENO) != STDOUT_FILENO || 3073869fb78SDag-Erling Smørgrav dup2(cherr[1], STDERR_FILENO) != STDERR_FILENO) { 3083869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: dup2(): %m", func); 3093869fb78SDag-Erling Smørgrav } else { 3103869fb78SDag-Erling Smørgrav execve(argv[0], (char * const *)argv, 3113869fb78SDag-Erling Smørgrav (char * const *)envlist); 3123869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: execve(%s): %m", 3133869fb78SDag-Erling Smørgrav func, argv[0]); 3143869fb78SDag-Erling Smørgrav } 315f65b2180SDag-Erling Smørgrav _exit(1); 316a76a4d44SDag-Erling Smørgrav } 3173869fb78SDag-Erling Smørgrav /* parent */ 318a76a4d44SDag-Erling Smørgrav if (pid == -1) { 3193869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: pdfork(): %m", func); 3203869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 321f65b2180SDag-Erling Smørgrav } 322bb3ba83eSDag-Erling Smørgrav /* use poll() to watch the process and stdin / stdout / stderr */ 323bb3ba83eSDag-Erling Smørgrav if (chin[0] >= 0) 324bb3ba83eSDag-Erling Smørgrav close(chin[0]); 3253869fb78SDag-Erling Smørgrav if (chout[1] >= 0) 3263869fb78SDag-Erling Smørgrav close(chout[1]); 3273869fb78SDag-Erling Smørgrav if (cherr[1] >= 0) 3283869fb78SDag-Erling Smørgrav close(cherr[1]); 3293869fb78SDag-Erling Smørgrav memset(pfd, 0, sizeof pfd); 3303869fb78SDag-Erling Smørgrav pfd[0].fd = pd; 3313869fb78SDag-Erling Smørgrav pfd[0].events = POLLHUP; 3323869fb78SDag-Erling Smørgrav nfds = 1; 333bb3ba83eSDag-Erling Smørgrav nreadfds = 0; 3343869fb78SDag-Erling Smørgrav if (options->capture_stdout) { 3353869fb78SDag-Erling Smørgrav pfd[nfds].fd = chout[0]; 3363869fb78SDag-Erling Smørgrav pfd[nfds].events = POLLIN|POLLERR|POLLHUP; 3373869fb78SDag-Erling Smørgrav nfds++; 338bb3ba83eSDag-Erling Smørgrav nreadfds++; 3393869fb78SDag-Erling Smørgrav } 3403869fb78SDag-Erling Smørgrav if (options->capture_stderr) { 3413869fb78SDag-Erling Smørgrav pfd[nfds].fd = cherr[0]; 3423869fb78SDag-Erling Smørgrav pfd[nfds].events = POLLIN|POLLERR|POLLHUP; 3433869fb78SDag-Erling Smørgrav nfds++; 344bb3ba83eSDag-Erling Smørgrav nreadfds++; 345bb3ba83eSDag-Erling Smørgrav } 346bb3ba83eSDag-Erling Smørgrav if (options->expose_authtok) { 347bb3ba83eSDag-Erling Smørgrav pfd[nfds].fd = chin[1]; 348bb3ba83eSDag-Erling Smørgrav pfd[nfds].events = POLLOUT|POLLERR|POLLHUP; 349bb3ba83eSDag-Erling Smørgrav nfds++; 3503869fb78SDag-Erling Smørgrav } 3513869fb78SDag-Erling Smørgrav 3523869fb78SDag-Erling Smørgrav /* loop until the process exits */ 3533869fb78SDag-Erling Smørgrav do { 3543869fb78SDag-Erling Smørgrav if (poll(pfd, nfds, INFTIM) < 0) { 3553869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: poll(): %m", func); 3563869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 3573869fb78SDag-Erling Smørgrav } 358bb3ba83eSDag-Erling Smørgrav /* are the stderr / stdout pipes ready for reading? */ 359bb3ba83eSDag-Erling Smørgrav for (i = 1; i < 1 + nreadfds; ++i) { 3603869fb78SDag-Erling Smørgrav if ((pfd[i].revents & POLLIN) == 0) 3613869fb78SDag-Erling Smørgrav continue; 3623869fb78SDag-Erling Smørgrav if ((rlen = read(pfd[i].fd, buf, sizeof(buf) - 1)) < 0) { 3633869fb78SDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: read(): %m", 3643869fb78SDag-Erling Smørgrav func); 3653869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 3663869fb78SDag-Erling Smørgrav } else if (rlen == 0) { 3673869fb78SDag-Erling Smørgrav continue; 3683869fb78SDag-Erling Smørgrav } 3693869fb78SDag-Erling Smørgrav buf[rlen] = '\0'; 3703869fb78SDag-Erling Smørgrav (void)pam_prompt(pamh, pfd[i].fd == chout[0] ? 3713869fb78SDag-Erling Smørgrav PAM_TEXT_INFO : PAM_ERROR_MSG, &resp, "%s", buf); 3723869fb78SDag-Erling Smørgrav } 373bb3ba83eSDag-Erling Smørgrav /* is the stdin pipe ready for writing? */ 374bb3ba83eSDag-Erling Smørgrav if (options->expose_authtok && authtok_size > 0 && 375bb3ba83eSDag-Erling Smørgrav (pfd[nfds - 1].revents & POLLOUT) != 0) { 376bb3ba83eSDag-Erling Smørgrav if ((wlen = write(chin[1], authtok, authtok_size)) < 0) { 377bb3ba83eSDag-Erling Smørgrav if (errno == EAGAIN) 378bb3ba83eSDag-Erling Smørgrav continue; 379bb3ba83eSDag-Erling Smørgrav openpam_log(PAM_LOG_ERROR, "%s: write(): %m", 380bb3ba83eSDag-Erling Smørgrav func); 381bb3ba83eSDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 382bb3ba83eSDag-Erling Smørgrav } else { 383bb3ba83eSDag-Erling Smørgrav authtok += wlen; 384bb3ba83eSDag-Erling Smørgrav authtok_size -= wlen; 385bb3ba83eSDag-Erling Smørgrav if (authtok_size == 0) { 386bb3ba83eSDag-Erling Smørgrav /* finished writing; close and forget the pipe */ 387bb3ba83eSDag-Erling Smørgrav close(chin[1]); 388bb3ba83eSDag-Erling Smørgrav chin[1] = -1; 389bb3ba83eSDag-Erling Smørgrav nfds--; 390bb3ba83eSDag-Erling Smørgrav } 391bb3ba83eSDag-Erling Smørgrav } 392bb3ba83eSDag-Erling Smørgrav } 3933869fb78SDag-Erling Smørgrav } while (pfd[0].revents == 0); 3943869fb78SDag-Erling Smørgrav 3953869fb78SDag-Erling Smørgrav /* the child process has exited */ 3967e3d5c1fSJean-Sébastien Pédron while (waitpid(pid, &status, 0) == -1) { 3977e3d5c1fSJean-Sébastien Pédron if (errno == EINTR) 3987e3d5c1fSJean-Sébastien Pédron continue; 3997e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s: waitpid(): %m", func); 4003869fb78SDag-Erling Smørgrav OUT(PAM_SYSTEM_ERR); 401f65b2180SDag-Erling Smørgrav } 4023869fb78SDag-Erling Smørgrav 4033869fb78SDag-Erling Smørgrav /* check exit code */ 404f65b2180SDag-Erling Smørgrav if (WIFSIGNALED(status)) { 4057e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s: %s caught signal %d%s", 4067e3d5c1fSJean-Sébastien Pédron func, argv[0], WTERMSIG(status), 407f65b2180SDag-Erling Smørgrav WCOREDUMP(status) ? " (core dumped)" : ""); 4083869fb78SDag-Erling Smørgrav OUT(PAM_SERVICE_ERR); 409f65b2180SDag-Erling Smørgrav } 410f65b2180SDag-Erling Smørgrav if (!WIFEXITED(status)) { 4117e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s: unknown status 0x%x", 4127e3d5c1fSJean-Sébastien Pédron func, status); 4133869fb78SDag-Erling Smørgrav OUT(PAM_SERVICE_ERR); 414f65b2180SDag-Erling Smørgrav } 4157e3d5c1fSJean-Sébastien Pédron 4163902d8a9SJean-Sébastien Pédron if (options->return_prog_exit_status) { 4177e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_DEBUG, 4187e3d5c1fSJean-Sébastien Pédron "%s: Use program exit status as return value: %d", 4197e3d5c1fSJean-Sébastien Pédron func, WEXITSTATUS(status)); 4203869fb78SDag-Erling Smørgrav OUT(WEXITSTATUS(status)); 4217e3d5c1fSJean-Sébastien Pédron } else { 4223869fb78SDag-Erling Smørgrav OUT(WEXITSTATUS(status) == 0 ? PAM_SUCCESS : PAM_PERM_DENIED); 423f65b2180SDag-Erling Smørgrav } 4243869fb78SDag-Erling Smørgrav /* unreachable */ 4253869fb78SDag-Erling Smørgrav out: 4263869fb78SDag-Erling Smørgrav serrno = errno; 4273869fb78SDag-Erling Smørgrav if (pd >= 0) 4283869fb78SDag-Erling Smørgrav close(pd); 429bb3ba83eSDag-Erling Smørgrav if (chin[0] >= 0) 430bb3ba83eSDag-Erling Smørgrav close(chin[0]); 431bb3ba83eSDag-Erling Smørgrav if (chin[1] >= 0) 432bb3ba83eSDag-Erling Smørgrav close(chin[1]); 4333869fb78SDag-Erling Smørgrav if (chout[0] >= 0) 4343869fb78SDag-Erling Smørgrav close(chout[0]); 4353869fb78SDag-Erling Smørgrav if (chout[1] >= 0) 4363869fb78SDag-Erling Smørgrav close(chout[1]); 4373869fb78SDag-Erling Smørgrav if (cherr[0] >= 0) 4383869fb78SDag-Erling Smørgrav close(cherr[0]); 4393869fb78SDag-Erling Smørgrav if (cherr[0] >= 0) 4403869fb78SDag-Erling Smørgrav close(cherr[1]); 4413869fb78SDag-Erling Smørgrav if (envlist != NULL) 4423869fb78SDag-Erling Smørgrav openpam_free_envlist(envlist); 4433869fb78SDag-Erling Smørgrav errno = serrno; 4443869fb78SDag-Erling Smørgrav return (pam_err); 445f65b2180SDag-Erling Smørgrav } 446f65b2180SDag-Erling Smørgrav 447f65b2180SDag-Erling Smørgrav PAM_EXTERN int 448f65b2180SDag-Erling Smørgrav pam_sm_authenticate(pam_handle_t *pamh, int flags, 449f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 450f65b2180SDag-Erling Smørgrav { 4517e3d5c1fSJean-Sébastien Pédron int ret; 4523902d8a9SJean-Sébastien Pédron struct pe_opts options; 453f65b2180SDag-Erling Smørgrav 4543902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 4553902d8a9SJean-Sébastien Pédron if (ret != 0) 4563902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 4573902d8a9SJean-Sébastien Pédron 4583902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 4597e3d5c1fSJean-Sébastien Pédron 4607e3d5c1fSJean-Sébastien Pédron /* 4617e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 4627e3d5c1fSJean-Sébastien Pédron * function. 4637e3d5c1fSJean-Sébastien Pédron */ 4647e3d5c1fSJean-Sébastien Pédron switch (ret) { 4657e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 4667e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 4677e3d5c1fSJean-Sébastien Pédron case PAM_AUTHINFO_UNAVAIL: 4687e3d5c1fSJean-Sébastien Pédron case PAM_AUTH_ERR: 4697e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 4707e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 4717e3d5c1fSJean-Sébastien Pédron case PAM_CRED_INSUFFICIENT: 4727e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 4737e3d5c1fSJean-Sébastien Pédron case PAM_MAXTRIES: 4747e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 4757e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 4767e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 4777e3d5c1fSJean-Sébastien Pédron case PAM_USER_UNKNOWN: 4787e3d5c1fSJean-Sébastien Pédron break; 4797e3d5c1fSJean-Sébastien Pédron default: 4807e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 4817e3d5c1fSJean-Sébastien Pédron argv[0], ret); 4827e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 4837e3d5c1fSJean-Sébastien Pédron } 4847e3d5c1fSJean-Sébastien Pédron 4857e3d5c1fSJean-Sébastien Pédron return (ret); 486f65b2180SDag-Erling Smørgrav } 487f65b2180SDag-Erling Smørgrav 488f65b2180SDag-Erling Smørgrav PAM_EXTERN int 489f65b2180SDag-Erling Smørgrav pam_sm_setcred(pam_handle_t *pamh, int flags, 490f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 491f65b2180SDag-Erling Smørgrav { 4927e3d5c1fSJean-Sébastien Pédron int ret; 4933902d8a9SJean-Sébastien Pédron struct pe_opts options; 494f65b2180SDag-Erling Smørgrav 4953902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 4963902d8a9SJean-Sébastien Pédron if (ret != 0) 4973902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 4983902d8a9SJean-Sébastien Pédron 4993902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 5007e3d5c1fSJean-Sébastien Pédron 5017e3d5c1fSJean-Sébastien Pédron /* 5027e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 5037e3d5c1fSJean-Sébastien Pédron * function. 5047e3d5c1fSJean-Sébastien Pédron */ 5057e3d5c1fSJean-Sébastien Pédron switch (ret) { 5067e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 5077e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 5087e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 5097e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 5107e3d5c1fSJean-Sébastien Pédron case PAM_CRED_ERR: 5117e3d5c1fSJean-Sébastien Pédron case PAM_CRED_EXPIRED: 5127e3d5c1fSJean-Sébastien Pédron case PAM_CRED_UNAVAIL: 5137e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 5147e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 5157e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 5167e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 5177e3d5c1fSJean-Sébastien Pédron case PAM_USER_UNKNOWN: 5187e3d5c1fSJean-Sébastien Pédron break; 5197e3d5c1fSJean-Sébastien Pédron default: 5207e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 5217e3d5c1fSJean-Sébastien Pédron argv[0], ret); 5227e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 5237e3d5c1fSJean-Sébastien Pédron } 5247e3d5c1fSJean-Sébastien Pédron 5257e3d5c1fSJean-Sébastien Pédron return (ret); 526f65b2180SDag-Erling Smørgrav } 527f65b2180SDag-Erling Smørgrav 528f65b2180SDag-Erling Smørgrav PAM_EXTERN int 529f65b2180SDag-Erling Smørgrav pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, 530f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 531f65b2180SDag-Erling Smørgrav { 5327e3d5c1fSJean-Sébastien Pédron int ret; 5333902d8a9SJean-Sébastien Pédron struct pe_opts options; 534f65b2180SDag-Erling Smørgrav 5353902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 5363902d8a9SJean-Sébastien Pédron if (ret != 0) 5373902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 5383902d8a9SJean-Sébastien Pédron 5393902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 5407e3d5c1fSJean-Sébastien Pédron 5417e3d5c1fSJean-Sébastien Pédron /* 5427e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 5437e3d5c1fSJean-Sébastien Pédron * function. 5447e3d5c1fSJean-Sébastien Pédron */ 5457e3d5c1fSJean-Sébastien Pédron switch (ret) { 5467e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 5477e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 5487e3d5c1fSJean-Sébastien Pédron case PAM_ACCT_EXPIRED: 5497e3d5c1fSJean-Sébastien Pédron case PAM_AUTH_ERR: 5507e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 5517e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 5527e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 5537e3d5c1fSJean-Sébastien Pédron case PAM_NEW_AUTHTOK_REQD: 5547e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 5557e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 5567e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 5577e3d5c1fSJean-Sébastien Pédron case PAM_USER_UNKNOWN: 5587e3d5c1fSJean-Sébastien Pédron break; 5597e3d5c1fSJean-Sébastien Pédron default: 5607e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 5617e3d5c1fSJean-Sébastien Pédron argv[0], ret); 5627e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 5637e3d5c1fSJean-Sébastien Pédron } 5647e3d5c1fSJean-Sébastien Pédron 5657e3d5c1fSJean-Sébastien Pédron return (ret); 566f65b2180SDag-Erling Smørgrav } 567f65b2180SDag-Erling Smørgrav 568f65b2180SDag-Erling Smørgrav PAM_EXTERN int 569f65b2180SDag-Erling Smørgrav pam_sm_open_session(pam_handle_t *pamh, int flags, 570f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 571f65b2180SDag-Erling Smørgrav { 5727e3d5c1fSJean-Sébastien Pédron int ret; 5733902d8a9SJean-Sébastien Pédron struct pe_opts options; 574f65b2180SDag-Erling Smørgrav 5753902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 5763902d8a9SJean-Sébastien Pédron if (ret != 0) 5773902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 5783902d8a9SJean-Sébastien Pédron 5793902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 5807e3d5c1fSJean-Sébastien Pédron 5817e3d5c1fSJean-Sébastien Pédron /* 5827e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 5837e3d5c1fSJean-Sébastien Pédron * function. 5847e3d5c1fSJean-Sébastien Pédron */ 5857e3d5c1fSJean-Sébastien Pédron switch (ret) { 5867e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 5877e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 5887e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 5897e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 5907e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 5917e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 5927e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 5937e3d5c1fSJean-Sébastien Pédron case PAM_SESSION_ERR: 5947e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 5957e3d5c1fSJean-Sébastien Pédron break; 5967e3d5c1fSJean-Sébastien Pédron default: 5977e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 5987e3d5c1fSJean-Sébastien Pédron argv[0], ret); 5997e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 6007e3d5c1fSJean-Sébastien Pédron } 6017e3d5c1fSJean-Sébastien Pédron 6027e3d5c1fSJean-Sébastien Pédron return (ret); 603f65b2180SDag-Erling Smørgrav } 604f65b2180SDag-Erling Smørgrav 605f65b2180SDag-Erling Smørgrav PAM_EXTERN int 606f65b2180SDag-Erling Smørgrav pam_sm_close_session(pam_handle_t *pamh, int flags, 607f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 608f65b2180SDag-Erling Smørgrav { 6097e3d5c1fSJean-Sébastien Pédron int ret; 6103902d8a9SJean-Sébastien Pédron struct pe_opts options; 611f65b2180SDag-Erling Smørgrav 6123902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 6133902d8a9SJean-Sébastien Pédron if (ret != 0) 6143902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 6153902d8a9SJean-Sébastien Pédron 6163902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 6177e3d5c1fSJean-Sébastien Pédron 6187e3d5c1fSJean-Sébastien Pédron /* 6197e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 6207e3d5c1fSJean-Sébastien Pédron * function. 6217e3d5c1fSJean-Sébastien Pédron */ 6227e3d5c1fSJean-Sébastien Pédron switch (ret) { 6237e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 6247e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 6257e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 6267e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 6277e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 6287e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 6297e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 6307e3d5c1fSJean-Sébastien Pédron case PAM_SESSION_ERR: 6317e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 6327e3d5c1fSJean-Sébastien Pédron break; 6337e3d5c1fSJean-Sébastien Pédron default: 6347e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 6357e3d5c1fSJean-Sébastien Pédron argv[0], ret); 6367e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 6377e3d5c1fSJean-Sébastien Pédron } 6387e3d5c1fSJean-Sébastien Pédron 6397e3d5c1fSJean-Sébastien Pédron return (ret); 640f65b2180SDag-Erling Smørgrav } 641f65b2180SDag-Erling Smørgrav 642f65b2180SDag-Erling Smørgrav PAM_EXTERN int 643f65b2180SDag-Erling Smørgrav pam_sm_chauthtok(pam_handle_t *pamh, int flags, 644f65b2180SDag-Erling Smørgrav int argc, const char *argv[]) 645f65b2180SDag-Erling Smørgrav { 6467e3d5c1fSJean-Sébastien Pédron int ret; 6473902d8a9SJean-Sébastien Pédron struct pe_opts options; 648f65b2180SDag-Erling Smørgrav 6493902d8a9SJean-Sébastien Pédron ret = parse_options(__func__, &argc, &argv, &options); 6503902d8a9SJean-Sébastien Pédron if (ret != 0) 6513902d8a9SJean-Sébastien Pédron return (PAM_SERVICE_ERR); 6523902d8a9SJean-Sébastien Pédron 6533902d8a9SJean-Sébastien Pédron ret = _pam_exec(pamh, __func__, flags, argc, argv, &options); 6547e3d5c1fSJean-Sébastien Pédron 6557e3d5c1fSJean-Sébastien Pédron /* 6567e3d5c1fSJean-Sébastien Pédron * We must check that the program returned a valid code for this 6577e3d5c1fSJean-Sébastien Pédron * function. 6587e3d5c1fSJean-Sébastien Pédron */ 6597e3d5c1fSJean-Sébastien Pédron switch (ret) { 6607e3d5c1fSJean-Sébastien Pédron case PAM_SUCCESS: 6617e3d5c1fSJean-Sébastien Pédron case PAM_ABORT: 6627e3d5c1fSJean-Sébastien Pédron case PAM_AUTHTOK_DISABLE_AGING: 6637e3d5c1fSJean-Sébastien Pédron case PAM_AUTHTOK_ERR: 6647e3d5c1fSJean-Sébastien Pédron case PAM_AUTHTOK_LOCK_BUSY: 6657e3d5c1fSJean-Sébastien Pédron case PAM_AUTHTOK_RECOVERY_ERR: 6667e3d5c1fSJean-Sébastien Pédron case PAM_BUF_ERR: 6677e3d5c1fSJean-Sébastien Pédron case PAM_CONV_ERR: 6687e3d5c1fSJean-Sébastien Pédron case PAM_IGNORE: 6697e3d5c1fSJean-Sébastien Pédron case PAM_PERM_DENIED: 6707e3d5c1fSJean-Sébastien Pédron case PAM_SERVICE_ERR: 6717e3d5c1fSJean-Sébastien Pédron case PAM_SYSTEM_ERR: 6727e3d5c1fSJean-Sébastien Pédron case PAM_TRY_AGAIN: 6737e3d5c1fSJean-Sébastien Pédron break; 6747e3d5c1fSJean-Sébastien Pédron default: 6757e3d5c1fSJean-Sébastien Pédron openpam_log(PAM_LOG_ERROR, "%s returned invalid code %d", 6767e3d5c1fSJean-Sébastien Pédron argv[0], ret); 6777e3d5c1fSJean-Sébastien Pédron ret = PAM_SERVICE_ERR; 6787e3d5c1fSJean-Sébastien Pédron } 6797e3d5c1fSJean-Sébastien Pédron 6807e3d5c1fSJean-Sébastien Pédron return (ret); 681f65b2180SDag-Erling Smørgrav } 682f65b2180SDag-Erling Smørgrav 683f65b2180SDag-Erling Smørgrav PAM_MODULE_ENTRY("pam_exec"); 684