From 6962e7e541546253d6d8d4d8e4bc5ca5290b8e5a Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Mon, 4 Feb 2008 15:27:31 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-02-04 Thorsten Kukuk * modules/pam_exec/pam_exec.c: Set PAM environment variables and add 'quiet' option. * modules/pam_exec/pam_exec.8.xml: Document new behavior. Patch from Julien Lecomte . --- ChangeLog | 5 ++++ modules/pam_exec/pam_exec.8.xml | 28 ++++++++++++++++++ modules/pam_exec/pam_exec.c | 63 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2ae0d805..fbe3a36b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,11 @@ * po/POTFILES.in: Add pam_sepermit.c. + * modules/pam_exec/pam_exec.c: Set PAM environment variables and + add 'quiet' option. + * modules/pam_exec/pam_exec.8.xml: Document new behavior. + Patch from Julien Lecomte . + 2008-02-01 Tomas Mraz * modules/pam_namespace/namespace.conf.5.xml: Add documentation for diff --git a/modules/pam_exec/pam_exec.8.xml b/modules/pam_exec/pam_exec.8.xml index 1e8bb0ba..f4dc1e15 100644 --- a/modules/pam_exec/pam_exec.8.xml +++ b/modules/pam_exec/pam_exec.8.xml @@ -24,6 +24,9 @@ seteuid + + quiet + log=file @@ -45,6 +48,18 @@ an external command. + + The child's environment is set to the current PAM environment list, as + returned by + + pam_getenvlist3 + + In addition, the following PAM items are + exported as environment variables: PAM_RHOST, + PAM_RUSER, PAM_SERVICE, + PAM_TTY, and PAM_USER. + + @@ -76,6 +91,19 @@ + + + + + + + Per default pam_exec.so will echo the exit status of the + external command if it fails. + Specifying this option will suppress the message. + + + + diff --git a/modules/pam_exec/pam_exec.c b/modules/pam_exec/pam_exec.c index 49790d80..766c0a06 100644 --- a/modules/pam_exec/pam_exec.c +++ b/modules/pam_exec/pam_exec.c @@ -59,11 +59,24 @@ #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 call_exec (pam_handle_t *pamh, int argc, const char **argv) { int debug = 0; int call_setuid = 0; + int quiet = 0; int optargc; const char *logfile = NULL; pid_t pid; @@ -85,6 +98,8 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) logfile = &argv[optargc][4]; else if (strcasecmp (argv[optargc], "seteuid") == 0) call_setuid = 1; + else if (strcasecmp (argv[optargc], "quiet") == 0) + quiet = 1; else break; /* Unknown option, assume program to execute. */ } @@ -115,6 +130,7 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) { pam_syslog (pamh, LOG_ERR, "%s failed: exit code %d", argv[optargc], WEXITSTATUS(status)); + if (!quiet) pam_error (pamh, _("%s failed: exit code %d"), argv[optargc], WEXITSTATUS(status)); } @@ -123,6 +139,7 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) pam_syslog (pamh, LOG_ERR, "%s failed: caught signal %d%s", argv[optargc], WTERMSIG(status), WCOREDUMP(status) ? " (core dumped)" : ""); + if (!quiet) pam_error (pamh, _("%s failed: caught signal %d%s"), argv[optargc], WTERMSIG(status), WCOREDUMP(status) ? " (core dumped)" : ""); @@ -131,6 +148,7 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) { pam_syslog (pamh, LOG_ERR, "%s failed: unknown status 0x%x", argv[optargc], status); + if (!quiet) pam_error (pamh, _("%s failed: unknown status 0x%x"), argv[optargc], status); } @@ -211,19 +229,58 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) arggv[i] = strdup(argv[i+optargc]); arggv[i] = NULL; + char **envlist, **tmp; + int envlen, nitems; + + /* + * 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) + { + free(envlist); + pam_syslog (pamh, LOG_ERR, "realloc environment failed : %m"); + exit (ENOMEM); + } + envlist = tmp; + for (i = 0; i < nitems; ++i) + { + const void *item; + char *envstr; + + if (pam_get_item(pamh, env_items[i].item, &item) != PAM_SUCCESS || item == NULL) + continue; + asprintf(&envstr, "%s=%s", env_items[i].name, (const char *)item); + if (envstr == NULL) + { + free(envlist); + pam_syslog (pamh, LOG_ERR, "prepare environment failed : %m"); + exit (ENOMEM); + } + envlist[envlen++] = envstr; + envlist[envlen] = NULL; + } + if (debug) pam_syslog (pamh, LOG_DEBUG, "Calling %s ...", arggv[0]); - if (execv (arggv[0], arggv) == -1) + if (execve (arggv[0], arggv, envlist) == -1) { int err = errno; - pam_syslog (pamh, LOG_ERR, "execv(%s,...) failed: %m", + pam_syslog (pamh, LOG_ERR, "execve(%s,...) failed: %m", arggv[0]); + free(envlist); exit (err); } + free(envlist); exit (1); /* should never be reached. */ } - return PAM_SYSTEM_ERR; + return PAM_SYSTEM_ERR; /* will never be reached. */ } PAM_EXTERN int -- cgit v1.2.3