2 * Copyright (c) 2001,2003 Networks Associates Technology, Inc.
5 * This software was developed for the FreeBSD Project by ThinkSec AS and
6 * NAI Labs, the Security Research Division of Network Associates, Inc.
7 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
8 * DARPA CHATS research program.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote
19 * products derived from this software without specific prior written
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $FreeBSD: src/lib/libpam/modules/pam_exec/pam_exec.c,v 1.6 2006/11/10 23:33:25 des Exp $
37 #include <sys/types.h>
46 #include <security/pam_appl.h>
47 #include <security/pam_modules.h>
48 #include <security/openpam.h>
50 #define ENV_ITEM(n) { (n), #n }
55 ENV_ITEM(PAM_SERVICE
),
63 _pam_exec(pam_handle_t
*pamh __unused
, int flags __unused
,
64 int argc
, const char *argv
[])
66 int envlen
, i
, nitems
, pam_err
, status
;
67 char **envlist
, **tmp
;
68 volatile int childerr
;
72 return (PAM_SERVICE_ERR
);
75 * XXX For additional credit, divert child's stdin/stdout/stderr
76 * to the conversation function.
80 * Set up the child's environment list. It consists of the PAM
81 * environment, plus a few hand-picked PAM items.
83 envlist
= pam_getenvlist(pamh
);
84 for (envlen
= 0; envlist
[envlen
] != NULL
; ++envlen
)
86 nitems
= sizeof(env_items
) / sizeof(*env_items
);
87 tmp
= realloc(envlist
, (envlen
+ nitems
+ 1) * sizeof(*envlist
));
89 openpam_free_envlist(envlist
);
93 for (i
= 0; i
< nitems
; ++i
) {
97 pam_err
= pam_get_item(pamh
, env_items
[i
].item
, &item
);
98 if (pam_err
!= PAM_SUCCESS
|| item
== NULL
)
100 asprintf(&envstr
, "%s=%s", env_items
[i
].name
, item
);
101 if (envstr
== NULL
) {
102 openpam_free_envlist(envlist
);
103 return (PAM_BUF_ERR
);
105 envlist
[envlen
++] = envstr
;
106 envlist
[envlen
] = NULL
;
110 * Fork and run the command. By using vfork() instead of fork(),
111 * we can distinguish between an execve() failure and a non-zero
112 * exit code from the command.
115 if ((pid
= vfork()) == 0) {
116 execve(argv
[0], (char * const *)argv
, (char * const *)envlist
);
120 openpam_free_envlist(envlist
);
122 openpam_log(PAM_LOG_ERROR
, "vfork(): %m");
123 return (PAM_SYSTEM_ERR
);
125 if (waitpid(pid
, &status
, 0) == -1) {
126 openpam_log(PAM_LOG_ERROR
, "waitpid(): %m");
127 return (PAM_SYSTEM_ERR
);
130 openpam_log(PAM_LOG_ERROR
, "execve(): %m");
131 return (PAM_SYSTEM_ERR
);
133 if (WIFSIGNALED(status
)) {
134 openpam_log(PAM_LOG_ERROR
, "%s caught signal %d%s",
135 argv
[0], WTERMSIG(status
),
136 WCOREDUMP(status
) ? " (core dumped)" : "");
137 return (PAM_SYSTEM_ERR
);
139 if (!WIFEXITED(status
)) {
140 openpam_log(PAM_LOG_ERROR
, "unknown status 0x%x", status
);
141 return (PAM_SYSTEM_ERR
);
143 if (WEXITSTATUS(status
) != 0) {
144 openpam_log(PAM_LOG_ERROR
, "%s returned code %d",
145 argv
[0], WEXITSTATUS(status
));
146 return (PAM_SYSTEM_ERR
);
148 return (PAM_SUCCESS
);
152 pam_sm_authenticate(pam_handle_t
*pamh
, int flags
, int argc
, const char *argv
[])
155 return (_pam_exec(pamh
, flags
, argc
, argv
));
159 pam_sm_setcred(pam_handle_t
*pamh
, int flags
, int argc
, const char *argv
[])
162 return (_pam_exec(pamh
, flags
, argc
, argv
));
166 pam_sm_acct_mgmt(pam_handle_t
*pamh
, int flags
, int argc
, const char *argv
[])
169 return (_pam_exec(pamh
, flags
, argc
, argv
));
173 pam_sm_open_session(pam_handle_t
*pamh
, int flags
, int argc
, const char *argv
[])
176 return (_pam_exec(pamh
, flags
, argc
, argv
));
180 pam_sm_close_session(pam_handle_t
*pamh
, int flags
,
181 int argc
, const char *argv
[])
184 return (_pam_exec(pamh
, flags
, argc
, argv
));
188 pam_sm_chauthtok(pam_handle_t
*pamh
, int flags
, int argc
, const char *argv
[])
191 return (_pam_exec(pamh
, flags
, argc
, argv
));
194 PAM_MODULE_ENTRY("pam_exec");