pam_exec.c revision 110446
197182Sdes/*- 297182Sdes * Copyright (c) 2001 Networks Associates Technology, Inc. 397182Sdes * All rights reserved. 497182Sdes * 597182Sdes * This software was developed for the FreeBSD Project by ThinkSec AS and 697182Sdes * NAI Labs, the Security Research Division of Network Associates, Inc. 797182Sdes * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 897182Sdes * DARPA CHATS research program. 997182Sdes * 1097182Sdes * Redistribution and use in source and binary forms, with or without 1197182Sdes * modification, are permitted provided that the following conditions 1297182Sdes * are met: 1397182Sdes * 1. Redistributions of source code must retain the above copyright 1497182Sdes * notice, this list of conditions and the following disclaimer. 1597182Sdes * 2. Redistributions in binary form must reproduce the above copyright 1697182Sdes * notice, this list of conditions and the following disclaimer in the 1797182Sdes * documentation and/or other materials provided with the distribution. 1897182Sdes * 3. The name of the author may not be used to endorse or promote 1997182Sdes * products derived from this software without specific prior written 2097182Sdes * permission. 2197182Sdes * 2297182Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2397182Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2497182Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2597182Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2697182Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2797182Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2897182Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2997182Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3097182Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3197182Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3297182Sdes * SUCH DAMAGE. 3397182Sdes */ 3497182Sdes 3597182Sdes#include <sys/cdefs.h> 3697182Sdes__FBSDID("$FreeBSD: head/lib/libpam/modules/pam_exec/pam_exec.c 110446 2003-02-06 12:40:58Z des $"); 3797182Sdes 3897182Sdes#include <sys/types.h> 3997182Sdes#include <sys/wait.h> 4097182Sdes 4197182Sdes#include <errno.h> 4297182Sdes#include <stdlib.h> 4397182Sdes#include <string.h> 4497182Sdes#include <unistd.h> 4597182Sdes 4697182Sdes#include <security/pam_appl.h> 4797182Sdes#include <security/pam_modules.h> 4897182Sdes#include <security/openpam.h> 4997182Sdes 5097182Sdesstatic int 5197182Sdes_pam_exec(pam_handle_t *pamh __unused, int flags __unused, 5297182Sdes int argc, const char *argv[]) 5397182Sdes{ 5497182Sdes int childerr, status; 55110446Sdes char **env, **envlist; 5697182Sdes pid_t pid; 5797182Sdes 5897182Sdes if (argc < 1) 5997182Sdes return (PAM_SERVICE_ERR); 6097182Sdes 6197182Sdes /* 6297182Sdes * XXX For additional credit, divert child's stdin/stdout/stderr 6397182Sdes * to the conversation function. 6497182Sdes */ 65110446Sdes envlist = pam_getenvlist(pamh); 6697182Sdes childerr = 0; 6797182Sdes if ((pid = vfork()) == 0) { 68110446Sdes execve(argv[0], argv, envlist); 6997182Sdes childerr = errno; 7097182Sdes _exit(1); 71110446Sdes } 72110446Sdes for (env = envlist; *env != NULL; ++env) 73110446Sdes free(*env); 74110446Sdes free(envlist); 75110446Sdes if (pid == -1) { 7697182Sdes openpam_log(PAM_LOG_ERROR, "vfork(): %m"); 7797182Sdes return (PAM_SYSTEM_ERR); 7897182Sdes } 7997182Sdes if (waitpid(pid, &status, 0) == -1) { 8097182Sdes openpam_log(PAM_LOG_ERROR, "waitpid(): %m"); 8197182Sdes return (PAM_SYSTEM_ERR); 8297182Sdes } 8397182Sdes if (childerr != 0) { 8497182Sdes openpam_log(PAM_LOG_ERROR, "execv(): %m"); 8597182Sdes return (PAM_SYSTEM_ERR); 8697182Sdes } 8797182Sdes if (WIFSIGNALED(status)) { 8897182Sdes openpam_log(PAM_LOG_ERROR, "%s caught signal %d%s", 8997182Sdes argv[0], WTERMSIG(status), 9097182Sdes WCOREDUMP(status) ? " (core dumped)" : ""); 9197182Sdes return (PAM_SYSTEM_ERR); 9297182Sdes } 9397182Sdes if (!WIFEXITED(status)) { 9497182Sdes openpam_log(PAM_LOG_ERROR, "unknown status 0x%x", status); 9597182Sdes return (PAM_SYSTEM_ERR); 9697182Sdes } 9797182Sdes if (WEXITSTATUS(status) != 0) { 9897182Sdes openpam_log(PAM_LOG_ERROR, "%s returned code %d", 9997182Sdes argv[0], WEXITSTATUS(status)); 10097182Sdes return (PAM_SYSTEM_ERR); 10197182Sdes } 10297182Sdes return (PAM_SUCCESS); 10397182Sdes} 10497182Sdes 10597182SdesPAM_EXTERN int 10697182Sdespam_sm_authenticate(pam_handle_t *pamh, int flags, 10797182Sdes int argc, const char *argv[]) 10897182Sdes{ 10997182Sdes 11097182Sdes return (_pam_exec(pamh, flags, argc, argv)); 11197182Sdes} 11297182Sdes 11397182SdesPAM_EXTERN int 11497182Sdespam_sm_setcred(pam_handle_t *pamh, int flags, 11597182Sdes int argc, const char *argv[]) 11697182Sdes{ 11797182Sdes 11897182Sdes return (_pam_exec(pamh, flags, argc, argv)); 11997182Sdes} 12097182Sdes 12197182SdesPAM_EXTERN int 12297182Sdespam_sm_acct_mgmt(pam_handle_t *pamh, int flags, 12397182Sdes int argc, const char *argv[]) 12497182Sdes{ 12597182Sdes 12697182Sdes return (_pam_exec(pamh, flags, argc, argv)); 12797182Sdes} 12897182Sdes 12997182SdesPAM_EXTERN int 13097182Sdespam_sm_open_session(pam_handle_t *pamh, int flags, 13197182Sdes int argc, const char *argv[]) 13297182Sdes{ 13397182Sdes 13497182Sdes return (_pam_exec(pamh, flags, argc, argv)); 13597182Sdes} 13697182Sdes 13797182SdesPAM_EXTERN int 13897182Sdespam_sm_close_session(pam_handle_t *pamh, int flags, 13997182Sdes int argc, const char *argv[]) 14097182Sdes{ 14197182Sdes 14297182Sdes return (_pam_exec(pamh, flags, argc, argv)); 14397182Sdes} 14497182Sdes 14597182SdesPAM_EXTERN int 14697182Sdespam_sm_chauthtok(pam_handle_t *pamh, int flags, 14797182Sdes int argc, const char *argv[]) 14897182Sdes{ 14997182Sdes 15097182Sdes return (_pam_exec(pamh, flags, argc, argv)); 15197182Sdes} 15297182Sdes 15397182SdesPAM_MODULE_ENTRY("pam_exec"); 154