Hello,

> - The patch needs to be updated to apply against the current package in
> unstable.

Done. I have attached a patch for unix_auth.c

> and, importantly:
>
> - we need some some code review/feedback/ignoff from the Debian folks
> maintaining PAM and other related components.  I am *NOT* going to be
> the guy who uploads a new setuid binary without adequate review.

Will you contact them?

> > unix2_chkpwd.c is available for example in the file
> > pam-modules-10.3-47.src.rpm of OpenSuSE 10.3. Installing that file on a
> > Debian system (with rpm -i) unpacks  unix2_chkpwd.c
> > into /usr/src/rpm/SOURCES/.
>
> This is interesting new information.  You're saying "unix2_chkpwd.c" has
> an upstream somewhere (separate from pam_unix2)?

Well, not completely separate, because pam-unix2 is also part of 
pam-modules-10.3-47.src.rpm

>
> Is there somewhere where one can download the current "unix2_chkpwd"
> source, on its own and not as part of the SuSE PAM source RPM?

Though I searched for a while, I could not find it elsewhere.

Regards
  Christoph
diff -Naurp libpam-unix2-2.1.orig/src/unix_auth.c libpam-unix2-2.1/src/unix_auth.c
--- libpam-unix2-2.1.orig/src/unix_auth.c	2006-11-06 14:57:01.000000000 +0100
+++ libpam-unix2-2.1/src/unix_auth.c	2008-05-13 10:05:44.361127527 +0200
@@ -57,6 +57,7 @@
 
 #define PAM_SM_AUTH
 #include <security/pam_modules.h>
+#include <security/_pam_macros.h>
 #if defined (HAVE_SECURITY_PAM_EXT_H)
 #include <security/pam_ext.h>
 #endif
@@ -69,6 +70,7 @@
 
 #include "public.h"
 
+#define CHKPWD_HELPER "/sbin/unix2_chkpwd"
 
 /* This module actually performs UNIX/shadow authentication.  */
 
@@ -121,6 +123,76 @@ need_password (pam_handle_t *pamh, const
   return 0;
 }
 
+static int _unix2_run_helper_binary(pam_handle_t *pamh, const char *passwd,
+				    const char *user, const options_t *options)
+{
+    int retval, child, fds[2];
+    sigset_t sigset;
+    char *service;
+
+    pam_get_item (pamh, PAM_SERVICE, (void *) &service);
+
+    if (options->debug)
+      pam_syslog (pamh, LOG_DEBUG, "_unix2_run_helper_binary called.");
+    /* create a pipe for the password */
+    if (pipe(fds) != 0) {
+	if (options->debug)
+	  pam_syslog (pamh, LOG_DEBUG, "could not make pipe");
+	return PAM_AUTH_ERR;
+    }
+
+    /* Block SIGCHLD */
+    sigemptyset(&sigset);
+    sigaddset(&sigset, SIGCHLD);
+    sigprocmask(SIG_BLOCK, &sigset, 0);
+
+    /* fork */
+    child = fork();
+    if (child == 0) {
+	char *args[] = { NULL, NULL, NULL, NULL };
+	static char *envp[] = { NULL };
+
+	/* XXX - should really tidy up PAM here too */
+
+	/* reopen stdin as pipe */
+	close(fds[1]);
+	dup2(fds[0], STDIN_FILENO);
+
+	/* exec binary helper */
+	args[0] = x_strdup(CHKPWD_HELPER);
+	args[1] = x_strdup(service);
+	args[2] = x_strdup(user);
+	
+	execve(CHKPWD_HELPER, args, envp);
+
+	/* should not get here: exit with error */
+	if (options->debug)
+	  pam_syslog (pamh, LOG_DEBUG, "helper binary is not available");
+	exit(PAM_AUTHINFO_UNAVAIL);
+    } else if (child > 0) {
+	if (passwd != NULL) {            /* send the password to the child */
+	    write(fds[1], passwd, strlen(passwd)+1);
+	    passwd = NULL;
+	} else {
+	    write(fds[1], "", 1);                        /* blank password */
+	}
+	close(fds[0]);       /* close here to avoid possible SIGPIPE above */
+	close(fds[1]);
+	(void) waitpid(child, &retval, 0);  /* wait for helper to complete */
+	retval = (retval == 0) ? PAM_SUCCESS:PAM_AUTH_ERR;
+    } else {
+	if (options->debug)
+	  pam_syslog (pamh, LOG_DEBUG, "fork failed");
+	retval = PAM_AUTH_ERR;
+    }
+
+    /* Unblock SIGCHLD */
+    sigprocmask(SIG_BLOCK, &sigset, 0);
+
+    if (options->debug)
+      pam_syslog (pamh, LOG_DEBUG, "returning %d", retval);
+    return retval;
+}
 
 int
 pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc,
@@ -303,7 +375,7 @@ pam_sm_authenticate (pam_handle_t *pamh,
 	salt = strdupa (sp->sp_pwdp);
       else
 	{
-	  if (strcmp (pw->pw_passwd, "x") == 0)
+	  if ((strcmp (pw->pw_passwd, "x") == 0) && ((geteuid() == 0)))
 	    __write_message (pamh, flags, PAM_TEXT_INFO,
 			     _("Permissions on the password database may be too restrictive."));
 	  salt = strdupa (pw->pw_passwd);
@@ -325,10 +397,21 @@ pam_sm_authenticate (pam_handle_t *pamh,
 
   if (strcmp (crypt_r (password, salt, &output), salt) != 0)
     {
+      if (geteuid())
+	{
+	  /* we are not root, perhaps this is the reason?  Run helper */
+	  if (options.debug)
+	    pam_syslog (pamh, LOG_DEBUG, "running helper binary");
+
+	  retval = _unix2_run_helper_binary(pamh, password, name, &options);
+	  return retval;
+	}
+      
       if (options.debug)
 	pam_syslog (pamh, LOG_DEBUG, "wrong password, return PAM_AUTH_ERR");
       return PAM_AUTH_ERR;
     }
+  
   if (options.debug)
     pam_syslog (pamh, LOG_DEBUG, "pam_sm_authenticate: PAM_SUCCESS");
   return PAM_SUCCESS;
@@ -424,3 +507,18 @@ pam_sm_setcred (pam_handle_t *pamh, int 
     pam_syslog (pamh, LOG_DEBUG, "pam_sm_setcred: PAM_SUCCESS");
   return PAM_SUCCESS;
 }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Reply via email to