]> granicus.if.org Git - linux-pam/commitdiff
Relevant BUGIDs:
authorThorsten Kukuk <kukuk@thkukuk.de>
Mon, 4 Feb 2008 15:27:31 +0000 (15:27 +0000)
committerThorsten Kukuk <kukuk@thkukuk.de>
Mon, 4 Feb 2008 15:27:31 +0000 (15:27 +0000)
Purpose of commit: new feature

Commit summary:
---------------

2008-02-04  Thorsten Kukuk  <kukuk@thkukuk.de>

        * 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 <julien@lecomte.at>.

ChangeLog
modules/pam_exec/pam_exec.8.xml
modules/pam_exec/pam_exec.c

index 2ae0d8051ccbbff3f7c052e16c7d52e2178f6a43..fbe3a36b483850eb17e964e2573978bae04c51b4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
        * 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 <julien@lecomte.at>.
+
 2008-02-01  Tomas Mraz  <t8m@centrum.cz>
 
        * modules/pam_namespace/namespace.conf.5.xml: Add documentation for
index 1e8bb0baaaf5d811caf157b6819b26de347f18d7..f4dc1e1542c114b84797927cae9b5953a431d33b 100644 (file)
@@ -24,6 +24,9 @@
       <arg choice="opt">
         seteuid
       </arg>
+      <arg choice="opt">
+        quiet
+      </arg>
       <arg choice="opt">
         log=<replaceable>file</replaceable>
       </arg>
       an external command.
     </para>
 
+    <para>
+     The child's environment is set to the current PAM environment list, as
+     returned by
+     <citerefentry>
+        <refentrytitle>pam_getenvlist</refentrytitle><manvolnum>3</manvolnum>
+     </citerefentry>
+     In addition, the following PAM items are
+     exported as environment variables: <emphasis>PAM_RHOST</emphasis>,
+     <emphasis>PAM_RUSER</emphasis>, <emphasis>PAM_SERVICE</emphasis>,
+     <emphasis>PAM_TTY</emphasis>, and <emphasis>PAM_USER</emphasis>.
+    </para>
+
   </refsect1>
 
   <refsect1 id="pam_exec-options">
           </listitem>
        </varlistentry>
 
+        <varlistentry>
+          <term>
+            <option>quiet</option>
+          </term>
+          <listitem>
+            <para>
+             Per default pam_exec.so will echo the exit status of the
+             external command if it fails.
+              Specifying this option will suppress the message.
+            </para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term>
             <option>seteuid</option>
index 49790d80323d0265d9d589c7b2faf59d3c15406b..766c0a06b115446f3e35b9698dee333042dda478 100644 (file)
 #include <security/pam_modutil.h>
 #include <security/pam_ext.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
 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