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;
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+