From b0d098fb3c0b0335d47a860cc6fb174948400795 Mon Sep 17 00:00:00 2001 From: des Date: Tue, 1 Feb 2005 10:37:07 +0000 Subject: In addition to the PAM environment, export a handful of useful PAM items. Suggested by: Ed Maste --- lib/libpam/modules/pam_exec/pam_exec.8 | 11 ++++++- lib/libpam/modules/pam_exec/pam_exec.c | 59 ++++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 8 deletions(-) (limited to 'lib/libpam/modules') diff --git a/lib/libpam/modules/pam_exec/pam_exec.8 b/lib/libpam/modules/pam_exec/pam_exec.8 index c07ff26..d7e5308 100644 --- a/lib/libpam/modules/pam_exec/pam_exec.8 +++ b/lib/libpam/modules/pam_exec/pam_exec.8 @@ -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 diff --git a/lib/libpam/modules/pam_exec/pam_exec.c b/lib/libpam/modules/pam_exec/pam_exec.c index b59a9d3..620dc0d 100644 --- a/lib/libpam/modules/pam_exec/pam_exec.c +++ b/lib/libpam/modules/pam_exec/pam_exec.c @@ -47,12 +47,24 @@ __FBSDID("$FreeBSD$"); #include #include +#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)) { -- cgit v1.1