pam_exec

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Hello all,

I've ported the BSD style PAM environment variables to pam_exec. Below is a patch for pam_exec.c and the documentation. I've taken the code from FreeBSD's 6.2 openpam.

I've also added a documented 'quiet' option so that users don't necessarily get an error message when script returns a (probably expected) failure. This is mostly useful if pam_exec is used for auth service.

Julien






--- Linux-PAM-0.99.9.0-pristine/modules/pam_exec/pam_exec.c	2006-08-29 16:43:25.000000000 +0200
+++ Linux-PAM-0.99.9.0/modules/pam_exec/pam_exec.c	2007-12-07 19:18:56.000000000 +0100
@@ -59,11 +59,24 @@
 #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 @@
 	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 @@
 	    {
 	      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 @@
 	      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 @@
 	    {
 	      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 @@
 	arggv[i] = 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
--- Linux-PAM-0.99.9.0-pristine/modules/pam_exec/pam_exec.8.xml	2006-06-09 18:44:06.000000000 +0200
+++ Linux-PAM-0.99.9.0/modules/pam_exec/pam_exec.8.xml	2007-12-04 17:21:53.000000000 +0100
@@ -25,6 +25,9 @@
         seteuid
       </arg>
       <arg choice="opt">
+        quiet
+      </arg>
+      <arg choice="opt">
         log=<replaceable>file</replaceable>
       </arg>
       <arg choice="plain">
@@ -45,6 +48,18 @@
       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">
@@ -78,6 +93,19 @@
 
         <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>
           </term>
           <listitem>
_______________________________________________
Pam-list mailing list
Pam-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/pam-list

[Index of Archives]     [Fedora Users]     [Kernel]     [Red Hat Install]     [Linux for the blind]     [Gimp]

  Powered by Linux