In addition to the PAM environment, export a handful of useful PAM items.
Suggested by: Ed Maste <emaste@phaedrus.sandvine.ca>
This commit is contained in:
parent
ff18d74b6c
commit
837425d0f3
@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 6, 2003
|
||||
.Dd February 1, 2005
|
||||
.Dt PAM_EXEC 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -51,8 +51,17 @@ arguments.
|
||||
The child's environment is set to the current PAM environment list,
|
||||
as returned by
|
||||
.Xr pam_getenvlist 3 .
|
||||
In addition, the following PAM items are exported as environment
|
||||
variables:
|
||||
.Ev PAM_RHOST ,
|
||||
.Ev PAM_RUSER ,
|
||||
.Ev PAM_SERVICE ,
|
||||
.Ev PAM_TTY ,
|
||||
and
|
||||
.Ev PAM_USER .
|
||||
.Sh SEE ALSO
|
||||
.Xr pam.conf 5 ,
|
||||
.Xr pam_get_item 3 ,
|
||||
.Xr pam 8
|
||||
.Sh AUTHORS
|
||||
The
|
||||
|
@ -47,12 +47,24 @@ __FBSDID("$FreeBSD$");
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/openpam.h>
|
||||
|
||||
#define ENV_ITEM(n) { (n), #n }
|
||||
static struct {
|
||||
int item;
|
||||
const char *name;
|
||||
} env_items[] = {
|
||||
ENV_ITEM(PAM_SERVICE),
|
||||
ENV_ITEM(PAM_USER),
|
||||
ENV_ITEM(PAM_TTY),
|
||||
ENV_ITEM(PAM_RHOST),
|
||||
ENV_ITEM(PAM_RUSER),
|
||||
};
|
||||
|
||||
static int
|
||||
_pam_exec(pam_handle_t *pamh __unused, int flags __unused,
|
||||
int argc, const char *argv[])
|
||||
{
|
||||
int childerr, status;
|
||||
char **env, **envlist;
|
||||
int childerr, envlen, i, nitems, pam_err, status;
|
||||
char *env, **envlist, **tmp;
|
||||
pid_t pid;
|
||||
|
||||
if (argc < 1)
|
||||
@ -62,16 +74,49 @@ _pam_exec(pam_handle_t *pamh __unused, int flags __unused,
|
||||
* XXX For additional credit, divert child's stdin/stdout/stderr
|
||||
* to the conversation function.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set up the child's environment list. It consists of the PAM
|
||||
* environment, plus a few hand-picked PAM items.
|
||||
*/
|
||||
envlist = pam_getenvlist(pamh);
|
||||
for (envlen = 0; envlist[envlen] != NULL; ++envlen)
|
||||
/* nothing */ ;
|
||||
nitems = sizeof(env_items) / sizeof(*env_items);
|
||||
tmp = realloc(envlist, (envlen + nitems + 1) * sizeof **envlist);
|
||||
if (tmp == NULL) {
|
||||
openpam_free_envlist(envlist);
|
||||
return (PAM_BUF_ERR);
|
||||
}
|
||||
envlist = tmp;
|
||||
for (i = 0; i < nitems; ++i) {
|
||||
const void *item;
|
||||
char *envstr;
|
||||
|
||||
pam_err = pam_get_item(pamh, env_items[i].item, &item);
|
||||
if (pam_err != PAM_SUCCESS || item == NULL)
|
||||
continue;
|
||||
asprintf(&envstr, "%s=%s", env_items[i].name, item);
|
||||
if (envstr == NULL) {
|
||||
openpam_free_envlist(envlist);
|
||||
return (PAM_BUF_ERR);
|
||||
}
|
||||
envlist[envlen++] = envstr;
|
||||
envlist[envlen] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fork and run the command. By using vfork() instead of fork(),
|
||||
* we can distinguish between an execve() failure and a non-zero
|
||||
* exit code from the command.
|
||||
*/
|
||||
childerr = 0;
|
||||
if ((pid = vfork()) == 0) {
|
||||
execve(argv[0], argv, envlist);
|
||||
execve(argv[0], (char * const *)argv, (char * const *)envlist);
|
||||
childerr = errno;
|
||||
_exit(1);
|
||||
}
|
||||
for (env = envlist; *env != NULL; ++env)
|
||||
free(*env);
|
||||
free(envlist);
|
||||
openpam_free_envlist(envlist);
|
||||
if (pid == -1) {
|
||||
openpam_log(PAM_LOG_ERROR, "vfork(): %m");
|
||||
return (PAM_SYSTEM_ERR);
|
||||
@ -81,7 +126,7 @@ _pam_exec(pam_handle_t *pamh __unused, int flags __unused,
|
||||
return (PAM_SYSTEM_ERR);
|
||||
}
|
||||
if (childerr != 0) {
|
||||
openpam_log(PAM_LOG_ERROR, "execv(): %m");
|
||||
openpam_log(PAM_LOG_ERROR, "execve(): %m");
|
||||
return (PAM_SYSTEM_ERR);
|
||||
}
|
||||
if (WIFSIGNALED(status)) {
|
||||
|
Loading…
Reference in New Issue
Block a user