]> granicus.if.org Git - linux-pam/commitdiff
Relevant BUGIDs:
authorThorsten Kukuk <kukuk@thkukuk.de>
Wed, 6 Oct 2004 13:42:36 +0000 (13:42 +0000)
committerThorsten Kukuk <kukuk@thkukuk.de>
Wed, 6 Oct 2004 13:42:36 +0000 (13:42 +0000)
Purpose of commit:

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

bugfix: Last part of fixes from Red Hat

CHANGELOG
_pam_aconf.h.in
configure
configure.in
libpam/pam_handlers.c
modules/pam_limits/pam_limits.c
modules/pam_unix/pam_unix_acct.c
modules/pam_unix/pam_unix_passwd.c
modules/pam_unix/support.c
modules/pam_unix/support.h
modules/pam_unix/unix_chkpwd.c

index 82b9ab91f840fee6bf7ff577107a93ee41debc8c..e72e4db9da8234d47803b39bc04ffcd0007eb3d0 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -119,6 +119,7 @@ BerliOS Bugs are marked with (BerliOS #XXXX).
 * Add patches to make PAM modules reentrant (Bug 440107 - kukuk)
 * Merge patches from Red Hat (Bug 477000 and other - kukuk)
 * Fix pam_rhosts option parsing (Bug 922648 - kukuk)
+* Add $ISA support in config files (from Red Hat - kukuk)
 
 0.77: Mon Sep 23 10:25:42 PDT 2002
 
index 1b1cde9581580ca6d1ba15be47d15b45afc245ce..68a391206fd6320b17a830c8e02e9e9db45847ba 100644 (file)
@@ -97,4 +97,8 @@
 # include <security/pam_malloc.h>
 #endif /* MEMORY_DEBUG */
 
+/* the path, relative to SECUREDIR, where PAMs specific to this architecture
+ * can be found */
+#undef _PAM_ISA
+
 #endif /* PAM_ACONF_H */
index 2775677941f7db90c34013adab4659419cd24727..32aad3bedc72d2ea40c3ff3008aee3859b3bde93 100755 (executable)
--- a/configure
+++ b/configure
@@ -846,6 +846,7 @@ Optional Features:
   --enable-libdebug        specify you are building debugging libraries
   --enable-fakeroot=<path to packaging directory>
   --enable-securedir=<path to location of PAMs> default \$libdir/security
+  --enable-isadir=<path to arch-specific module files> default ../../\`basename \$libdir\`/security
   --enable-sconfigdir=<path to module conf files> default \$sysconfdir/security
   --enable-suplementedir=<path to module helper binaries> default \$sbindir
   --enable-includedir=<path to include location> - where to put <security>
@@ -2795,6 +2796,22 @@ else
 fi;
 
 
+# Check whether --enable-isadir or --disable-isadir was given.
+if test "${enable_isadir+set}" = set; then
+  enableval="$enable_isadir"
+  ISA=$enableval
+else
+  ISA=../../`basename $libdir`/security
+fi;
+unset mylibdirbase
+
+cat >>confdefs.h <<_ACEOF
+#define _PAM_ISA "$ISA"
+_ACEOF
+
+echo "$as_me:$LINENO: result: Defining \$ISA to \\"$ISA\\"." >&5
+echo "${ECHO_T}Defining \$ISA to \\"$ISA\\"." >&6
+
 # Check whether --enable-sconfigdir or --disable-sconfigdir was given.
 if test "${enable_sconfigdir+set}" = set; then
   enableval="$enable_sconfigdir"
@@ -4410,13 +4427,17 @@ else
 fi
 
 
+
+if test $HAVE_LIBNSL = yes ; then
+       pwdblibs="$pwdblibs -lnsl"
+fi
 echo "$as_me:$LINENO: checking for pwdb_db_name in -lpwdb" >&5
 echo $ECHO_N "checking for pwdb_db_name in -lpwdb... $ECHO_C" >&6
 if test "${ac_cv_lib_pwdb_pwdb_db_name+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpwdb  $LIBS"
+LIBS="-lpwdb $pwdblibs $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -4484,6 +4505,8 @@ else
 fi
 
 
+unset pwdblibs
+
 echo "$as_me:$LINENO: checking for yywrap in -lfl" >&5
 echo $ECHO_N "checking for yywrap in -lfl... $ECHO_C" >&6
 if test "${ac_cv_lib_fl_yywrap+set}" = set; then
index d673e3af5c0ab0c42c70c35b77bb3e92e4045758..ce9c310df5f256f1a7e50798a45f65f013d8bc7d 100644 (file)
@@ -87,6 +87,14 @@ AC_ARG_ENABLE(securedir,
        SECUREDIR=$enableval, SECUREDIR=$libdir/security)
 AC_SUBST(SECUREDIR)
 
+AC_ARG_ENABLE(isadir,
+[  --enable-isadir=<path to arch-specific module files> [default ../../\`basename \$libdir\`/security]],
+ISA=$enableval,
+ISA=../../`basename $libdir`/security)
+unset mylibdirbase
+AC_DEFINE_UNQUOTED(_PAM_ISA,"$ISA",[Define to the path, relative to SECUREDIR, where PAMs specific to this architecture can be found.])
+AC_MSG_RESULT([Defining \$ISA to \"$ISA\".])
+
 AC_ARG_ENABLE(sconfigdir,
 [  --enable-sconfigdir=<path to module conf files> [default \$sysconfdir/security]],
        SCONFIGDIR=$enableval, SCONFIGDIR=$sysconfdir/security)
@@ -212,9 +220,15 @@ AC_SUBST(HAVE_LIBFL)
 AC_CHECK_LIB(nsl, yp_maplist, HAVE_LIBNSL=yes ; AC_DEFINE(HAVE_LIBNSL),
        HAVE_LIBNSL=no)
 AC_SUBST(HAVE_LIBNSL)
+
+if test $HAVE_LIBNSL = yes ; then
+       pwdblibs="$pwdblibs -lnsl"
+fi
 AC_CHECK_LIB(pwdb, pwdb_db_name, HAVE_LIBPWDB=yes ; AC_DEFINE(HAVE_LIBPWDB),
-       HAVE_LIBPWDB=no)
+       HAVE_LIBPWDB=no,$pwdblibs)
 AC_SUBST(HAVE_LIBPWDB)
+unset pwdblibs
+
 AC_CHECK_LIB(fl, yywrap, HAVE_LIBFLEX=yes ; AC_DEFINE(HAVE_LIBFLEX),
        HAVE_LIBFLEX=no)
 AC_SUBST(HAVE_LIBFLEX)
index 90c0968a2d7b3beddc19da6c6fe9196542aa9706..75519551a3ec3f12d42d813c5ac2e35c1c6384fe 100644 (file)
@@ -34,6 +34,9 @@
 #define BUF_SIZE                  1024
 #define MODULE_CHUNK              4
 #define UNKNOWN_MODULE_PATH       "<*unknown module path*>"
+#ifndef _PAM_ISA
+#define _PAM_ISA "."
+#endif
 
 static int _pam_assemble_line(FILE *f, char *buf, int buf_len);
 
@@ -313,7 +316,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
     }
 
     D(("_pam_init_handlers: initializing"));
-    
+
     /* First clean the service structure */
 
     _pam_free_handlers(pamh);
@@ -358,7 +361,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
      */
     {
        struct stat test_d;
-       
+
        /* Is there a PAM_CONFIG_D directory? */
        if ( stat(PAM_CONFIG_D, &test_d) == 0 && S_ISDIR(test_d.st_mode) ) {
            char *filename;
@@ -575,7 +578,7 @@ int _pam_add_handler(pam_handle_t *pamh
 #ifdef PAM_SHL
     const char *_sym, *_sym2;
 #endif
-    char *mod_full_path=NULL;
+    char *mod_full_path=NULL, *mod_full_isa_path=NULL, *isa=NULL;
     servicefn func, func2;
     int success;
 
@@ -639,6 +642,30 @@ int _pam_add_handler(pam_handle_t *pamh
            dlopen(mod_path, RTLD_NOW);
 # endif /* PAM_SHL */
        D(("_pam_add_handler: dlopen'ed"));
+       if (mod->dl_handle == NULL) {
+           if (strstr(mod_path, "$ISA")) {
+               mod_full_isa_path = malloc(strlen(mod_path) + strlen(_PAM_ISA) + 1);
+               if (mod_full_isa_path == NULL) {
+                   D(("_pam_handler: couldn't get memory for mod_path"));
+                   _pam_system_log(LOG_ERR, "no memory for module path");
+                   success = PAM_ABORT;
+               } else {
+                   strcpy(mod_full_isa_path, mod_path);
+                    isa = strstr(mod_full_isa_path, "$ISA");
+                   if (isa) {
+                       memmove(isa + strlen(_PAM_ISA), isa + 4, strlen(isa + 4) + 1);
+                       memmove(isa, _PAM_ISA, strlen(_PAM_ISA));
+                   }
+                   mod->dl_handle =
+# ifdef PAM_SHL
+                       shl_load(mod_full_isa_path, BIND_IMMEDIATE, 0L);
+# else /* PAM_SHL */
+                       dlopen(mod_full_isa_path, RTLD_NOW);
+# endif /* PAM_SHL */
+                   _pam_drop(mod_full_isa_path);
+               }
+           }
+       }
        if (mod->dl_handle == NULL) {
            D(("_pam_add_handler: dlopen(%s) failed", mod_path));
            _pam_system_log(LOG_ERR, "unable to dlopen(%s)", mod_path);
@@ -782,7 +809,7 @@ int _pam_add_handler(pam_handle_t *pamh
     }
 
     /* now identify this module's functions - for non-faulty modules */
-    
+
 #ifdef PAM_DYNAMIC
     if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
 # ifdef PAM_SHL
@@ -909,7 +936,7 @@ int _pam_free_handlers(pam_handle_t *pamh)
     }
 
     /* Free all the handlers */
-    
+
     _pam_free_handlers_aux(&(pamh->handlers.conf.authenticate));
     _pam_free_handlers_aux(&(pamh->handlers.conf.setcred));
     _pam_free_handlers_aux(&(pamh->handlers.conf.acct_mgmt));
@@ -949,7 +976,7 @@ void _pam_start_handlers(pam_handle_t *pamh)
     pamh->handlers.module = NULL;
 
     /* initialize the .conf and .other entries */
-    
+
     pamh->handlers.conf.authenticate = NULL;
     pamh->handlers.conf.setcred = NULL;
     pamh->handlers.conf.acct_mgmt = NULL;
index 4354d3e1239ac959c14602eae3773089da9b4b5a..66eae8e9daa1b408b1e62a20e19688352aa94f93 100644 (file)
@@ -207,12 +207,12 @@ check_logins (pam_handle_t *pamh, const char *name, int limit, int ctrl,
                 continue;
            }
        }
-       if (++count > limit) {
+       if (++count >= limit) {
            break;
        }
     }
     endutent();
-    if (count > limit) {
+    if (count >= limit) {
        if (name) {
            _pam_log(LOG_WARNING, "Too many logins (max %d) for %s",
                     limit, name);
index f87b13b145fae6ab5aa358815303dbb1c67bac05..2cd2679249f3cfb54563a6c1599c215313e4a799 100644 (file)
@@ -123,11 +123,10 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags,
                        setreuid( -1, save_euid );
                }
 
-       } else if (!strcmp( pwent->pw_passwd, "x" )) {
+       } else if (_unix_shadowed (pwent))
                spent = _pammodutil_getspnam (pamh, uname);
-       } else {
+       else
                return PAM_SUCCESS;
-       }
 
        if (!spent)
                if (on(UNIX_BROKEN_SHADOW,ctrl))
index 91625c614fd46487e2e78b0a1c607841ef44c083..4e90b764627ebedba0c78476c948b1e69b684550 100644 (file)
@@ -444,7 +444,7 @@ static int _update_passwd(pam_handle_t *pamh,
     }
 }
 
-static int _update_shadow(const char *forwho, char *towhat)
+static int _update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat)
 {
     struct spwd *spwdent = NULL, *stmpent = NULL;
     struct stat st;
@@ -516,6 +516,7 @@ static int _update_shadow(const char *forwho, char *towhat)
 
     if (!err) {
        rename(SH_TMPFILE, "/etc/shadow");
+       _log_err(LOG_NOTICE, pamh, "password changed for %s", forwho);
        return PAM_SUCCESS;
     } else {
        unlink(SH_TMPFILE);
@@ -535,7 +536,7 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat,
        if (pwd == NULL)
                return PAM_AUTHTOK_ERR;
 
-       if (on(UNIX_NIS, ctrl)) {
+       if (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, forwho, 0, 1)) {
                struct timeval timeout;
                struct yppasswd yppwd;
                CLIENT *clnt;
@@ -619,13 +620,18 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat,
        }
 #endif /* def USE_LCKPWDF */
 
-       if (on(UNIX_SHADOW, ctrl) || (strcmp(pwd->pw_passwd, "x") == 0)) {
-               retval = _update_shadow(forwho, towhat);
+       if (_unix_comesfromsource (pamh, forwho, 1, 0))
+         {
+           if (on(UNIX_SHADOW, ctrl) || _unix_shadowed (pwd))
+             {
+               retval = _update_shadow (pamh, forwho, towhat);
                if (retval == PAM_SUCCESS)
-                       retval = _update_passwd(pamh, forwho, "x");
-       } else {
-               retval = _update_passwd(pamh, forwho, towhat);
-       }
+                 if (!_unix_shadowed (pwd))
+                   retval = _update_passwd (pamh, forwho, "x");
+             }
+           else
+             retval = _update_passwd (pamh, forwho, towhat);
+         }
 
 #ifdef USE_LCKPWDF
        ulckpwdf();
@@ -646,7 +652,7 @@ static int _unix_verify_shadow(const char *user, unsigned int ctrl)
        if (pwd == NULL)
                return PAM_AUTHINFO_UNAVAIL;    /* We don't need to do the rest... */
 
-       if (strcmp(pwd->pw_passwd, "x") == 0) {
+       if (_unix_shadowed(pwd)) {
                /* ...and shadow password file entry for this user, if shadowing
                   is enabled */
                setspent();
@@ -738,7 +744,7 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh
 #else
                if (strlen(pass_new) < 6)
                        remark = "You must choose a longer password";
-               D(("lenth check [%s]", remark));
+               D(("length check [%s]", remark));
 #endif
                if (on(UNIX_REMEMBER_PASSWD, ctrl))
                        if ((retval = check_old_password(user, pass_new)) != PAM_SUCCESS)
@@ -795,6 +801,30 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
 
        D(("Got username of %s", user));
 
+       /*
+        * Before we do anything else, check to make sure that the user's
+        * info is in one of the databases we can modify from this module,
+        * which currently is 'files' and 'nis'.  We have to do this because
+        * getpwnam() doesn't tell you *where* the information it gives you
+        * came from, nor should it.  That's our job.
+        */
+       if (_unix_comesfromsource(pamh, user, 1, 1) == 0) {
+               _log_err(LOG_DEBUG, pamh,
+                        "user \"%s\" does not exist in /etc/passwd or NIS",
+                        user);
+               return PAM_USER_UNKNOWN;
+       } else {
+               struct passwd *pwd;
+               _unix_getpwnam(pamh, user, 1, 1, &pwd);
+               if (!_unix_shadowed(pwd) &&
+                   (strchr(pwd->pw_passwd, '*') != NULL)) {
+                       _log_err(LOG_DEBUG, pamh,
+                               "user \"%s\" does not have modifiable password",
+                               user);
+                       return PAM_USER_UNKNOWN;
+               }
+       }
+
        /*
         * This is not an AUTH module!
         */
index 05c51fed10bab38cb440083641489a783a3f0c7b..5b23b8e9784cf73e49c79bb21f722f3647a04427 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdarg.h>
+#include <stdio.h>
 #include <string.h>
 #include <malloc.h>
 #include <pwd.h>
@@ -17,6 +18,8 @@
 #include <utmp.h>
 #include <errno.h>
 #include <signal.h>
+#include <ctype.h>
+#include <rpcsvc/ypclnt.h>
 
 #include <security/_pam_macros.h>
 #include <security/pam_modules.h>
@@ -135,10 +138,6 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int argc,
                D(("PRELIM_CHECK"));
                set(UNIX__PRELIM, ctrl);
        }
-       if (flags & PAM_DISALLOW_NULL_AUTHTOK) {
-               D(("DISALLOW_NULL_AUTHTOK"));
-               set(UNIX__NONULL, ctrl);
-       }
        if (flags & PAM_SILENT) {
                D(("SILENT"));
                set(UNIX__QUIET, ctrl);
@@ -178,6 +177,11 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int argc,
                ++argv;         /* step to next argument */
        }
 
+       if (flags & PAM_DISALLOW_NULL_AUTHTOK) {
+               D(("DISALLOW_NULL_AUTHTOK"));
+               set(UNIX__NONULL, ctrl);
+       }
+
        /* auditing is a more sensitive version of debug */
 
        if (on(UNIX_AUDIT, ctrl)) {
@@ -275,6 +279,165 @@ static void _cleanup_failures(pam_handle_t * pamh, void *fl, int err)
        }
 }
 
+/*
+ * _unix_getpwnam() searches only /etc/passwd and NIS to find user information
+ */
+static void _unix_cleanup(pam_handle_t *pamh, void *data, int error_status)
+{
+       free(data);
+}
+
+int _unix_getpwnam(pam_handle_t *pamh, const char *name,
+                  int files, int nis, struct passwd **ret)
+{
+       FILE *passwd;
+       char buf[16384];
+       int matched = 0, buflen;
+       char *slogin, *spasswd, *suid, *sgid, *sgecos, *shome, *sshell, *p;
+
+       memset(buf, 0, sizeof(buf));
+
+       if (!matched && files) {
+               int userlen = strlen(name);
+               passwd = fopen("/etc/passwd", "r");
+               if (passwd != NULL) {
+                       while (fgets(buf, sizeof(buf), passwd) != NULL) {
+                               if ((buf[userlen] == ':') &&
+                                   (strncmp(name, buf, userlen) == 0)) {
+                                       p = buf + strlen(buf) - 1;
+                                       while (isspace(*p) && (p >= buf)) {
+                                               *p-- = '\0';
+                                       }
+                                       matched = 1;
+                                       break;
+                               }
+                       }
+                       fclose(passwd);
+               }
+       }
+
+       if (!matched && nis) {
+               char *userinfo = NULL, *domain = NULL;
+               int len = 0, i;
+               len = yp_get_default_domain(&domain);
+               if (len == YPERR_SUCCESS) {
+                       len = yp_bind(domain);
+               }
+               if (len == YPERR_SUCCESS) {
+                       i = yp_match(domain, "passwd.byname", name,
+                                    strlen(name), &userinfo, &len);
+                       yp_unbind(domain);
+                       if ((i == YPERR_SUCCESS) && (len < sizeof(buf))) {
+                               strncpy(buf, userinfo, sizeof(buf) - 1);
+                               buf[sizeof(buf) - 1] = '\0';
+                               matched = 1;
+                       }
+               }
+       }
+
+       if (matched && (ret != NULL)) {
+               *ret = NULL;
+
+               slogin = buf;
+
+               spasswd = strchr(slogin, ':');
+               if (spasswd == NULL) {
+                       return matched;
+               }
+               *spasswd++ = '\0';
+
+               suid = strchr(spasswd, ':');
+               if (suid == NULL) {
+                       return matched;
+               }
+               *suid++ = '\0';
+
+               sgid = strchr(suid, ':');
+               if (sgid == NULL) {
+                       return matched;
+               }
+               *sgid++ = '\0';
+
+               sgecos = strchr(sgid, ':');
+               if (sgecos == NULL) {
+                       return matched;
+               }
+               *sgecos++ = '\0';
+
+               shome = strchr(sgecos, ':');
+               if (shome == NULL) {
+                       return matched;
+               }
+               *shome++ = '\0';
+
+               sshell = strchr(shome, ':');
+               if (sshell == NULL) {
+                       return matched;
+               }
+               *sshell++ = '\0';
+
+               buflen = sizeof(struct passwd) +
+                        strlen(slogin) + 1 +
+                        strlen(spasswd) + 1 +
+                        strlen(suid) + 1 +
+                        strlen(sgid) + 1 +
+                        strlen(sgecos) + 1 +
+                        strlen(shome) + 1 +
+                        strlen(sshell) + 1;
+               *ret = malloc(buflen);
+               if (*ret == NULL) {
+                       return matched;
+               }
+               memset(*ret, '\0', buflen);
+
+               (*ret)->pw_uid = strtol(suid, &p, 0);
+               if ((strlen(sgid) == 0) || (*p != '\0')) {
+                       free(*ret);
+                       *ret = NULL;
+                       return matched;
+               }
+
+               (*ret)->pw_gid = strtol(sgid, &p, 0);
+               if ((strlen(sgid) == 0) || (*p != '\0')) {
+                       free(*ret);
+                       *ret = NULL;
+                       return matched;
+               }
+
+               p = ((char*)(*ret)) + sizeof(struct passwd);
+               (*ret)->pw_name = strcpy(p, slogin);
+               p += strlen(p) + 1;
+               (*ret)->pw_passwd = strcpy(p, spasswd);
+               p += strlen(p) + 1;
+               (*ret)->pw_gecos = strcpy(p, sgecos);
+               p += strlen(p) + 1;
+               (*ret)->pw_dir = strcpy(p, shome);
+               p += strlen(p) + 1;
+               (*ret)->pw_shell = strcpy(p, sshell);
+
+               snprintf(buf, sizeof(buf), "_pam_unix_getpwnam_%s", name);
+
+               if (pam_set_data(pamh, buf,
+                                *ret, _unix_cleanup) != PAM_SUCCESS) {
+                       free(*ret);
+                       *ret = NULL;
+               }
+       }
+
+       return matched;
+}
+
+/*
+ * _unix_comsefromsource() is a quick check to see if information about a given
+ * user comes from a particular source (just files and nis for now)
+ *
+ */
+int _unix_comesfromsource(pam_handle_t *pamh,
+                         const char *name, int files, int nis)
+{
+       return _unix_getpwnam(pamh, name, files, nis, NULL);
+}
+
 /*
  * _unix_blankpasswd() is a quick check for a blank password
  *
@@ -331,10 +494,10 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
                                setreuid( save_uid, save_euid );
                        else {
                                if (setreuid( -1, 0 ) == -1)
-                               setreuid( save_uid, -1 );
+                                       setreuid( save_uid, -1 );
                                setreuid( -1, save_euid );
                        }
-               } else if (strcmp(pwd->pw_passwd, "x") == 0) {
+               } else if (_unix_shadowed(pwd)) {
                        /*
                         * ...and shadow password file entry for this user,
                         * if shadowing is enabled
@@ -501,7 +664,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
                                setreuid( save_uid, -1 );
                                setreuid( -1, save_euid );
                        }
-               } else if (strcmp(pwd->pw_passwd, "x") == 0) {
+               } else if (_unix_shadowed(pwd)) {
                        /*
                         * ...and shadow password file entry for this user,
                         * if shadowing is enabled
@@ -523,7 +686,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
        }
 
        retval = PAM_SUCCESS;
-       if (pwd == NULL || salt == NULL || strlen(salt) == 1) {
+       if (pwd == NULL || salt == NULL || !strcmp(salt, "x") || ((salt[0] == '#') && (salt[1] == '#') && !strcmp(salt + 2, name))) {
                if (geteuid()) {
                        /* we are not root perhaps this is the reason? Run helper */
                        D(("running helper binary"));
@@ -850,6 +1013,21 @@ int _unix_read_password(pam_handle_t * pamh
        return PAM_SUCCESS;
 }
 
+int _unix_shadowed(const struct passwd *pwd)
+{
+       if (pwd != NULL) {
+               if (strcmp(pwd->pw_passwd, "x") == 0) {
+                       return 1;
+               }
+               if ((pwd->pw_passwd[0] == '#') &&
+                   (pwd->pw_passwd[1] == '#') &&
+                   (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
 /* ****************************************************************** *
  * Copyright (c) Jan Rêkorajski 1999.
  * Copyright (c) Andrew G. Morgan 1996-8.
index 7219cd99bd103c0d7760d1434eddb4af548dd2df..b2aa4b409a980f57223e48b38a52c78d4e205328 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef _PAM_UNIX_SUPPORT_H
 #define _PAM_UNIX_SUPPORT_H
 
+#include <pwd.h>
 
 /*
  * here is the string to inform the user that the new passwords they
@@ -133,6 +134,11 @@ extern int _make_remark(pam_handle_t * pamh, unsigned int ctrl
                       ,int type, const char *text);
 extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int argc,
                     const char **argv);
+extern int _unix_getpwnam (pam_handle_t *pamh,
+                          const char *name, int files, int nis,
+                          struct passwd **ret);
+extern int _unix_comesfromsource (pam_handle_t *pamh,
+                                 const char *name, int files, int nis);
 extern int _unix_blankpasswd(pam_handle_t *pamh,unsigned int ctrl,
                             const char *name);
 extern int _unix_verify_password(pam_handle_t * pamh, const char *name
@@ -144,6 +150,6 @@ extern int _unix_read_password(pam_handle_t * pamh
                        ,const char *prompt2
                        ,const char *data_name
                        ,const char **pass);
+extern int _unix_shadowed(const struct passwd *pwd);
 
 #endif /* _PAM_UNIX_SUPPORT_H */
-
index dd07960c4996e4c2da3ba1b38c87efd577ec0a6b..e65728d84811cb3ff37106c0130856f1e22dfb9f 100644 (file)
@@ -57,6 +57,24 @@ static void _log_err(int err, const char *format,...)
        closelog();
 }
 
+static int _unix_shadowed(const struct passwd *pwd)
+{
+       char hashpass[1024];
+       if (pwd != NULL) {
+               if (strcmp(pwd->pw_passwd, "x") == 0) {
+                       return 1;
+               }
+               if (strlen(pwd->pw_name) < sizeof(hashpass) - 2) {
+                       strcpy(hashpass, "##");
+                       strcpy(hashpass + 2, pwd->pw_name);
+                       if (strcmp(pwd->pw_passwd, hashpass) == 0) {
+                               return 1;
+                       }
+               }
+       }
+       return 0;
+}
+
 static void su_sighandler(int sig)
 {
        if (sig > 0) {
@@ -87,7 +105,7 @@ static void setup_signals(void)
        (void) sigaction(SIGQUIT, &action, NULL);
 }
 
-static int _unix_verify_password(const char *name, const char *p, int opt)
+static int _unix_verify_password(const char *name, const char *p, int nullok)
 {
        struct passwd *pwd = NULL;
        struct spwd *spwdent = NULL;
@@ -101,7 +119,7 @@ static int _unix_verify_password(const char *name, const char *p, int opt)
        pwd = getpwnam(name);   /* Get password file entry... */
        endpwent();
        if (pwd != NULL) {
-               if (strcmp(pwd->pw_passwd, "x") == 0) {
+               if (_unix_shadowed(pwd)) {
                        /*
                         * ...and shadow password file entry for this user,
                         * if shadowing is enabled
@@ -136,7 +154,10 @@ static int _unix_verify_password(const char *name, const char *p, int opt)
 
        salt_len = strlen(salt);
        if (salt_len == 0) {
-               return (opt == 0) ? UNIX_FAILED : UNIX_PASSED;
+               return (nullok == 0) ? UNIX_FAILED : UNIX_PASSED;
+       }
+       if (p == NULL) {
+               return UNIX_FAILED;
        }
 
        /* the moment of truth -- do we agree with the password? */
@@ -202,7 +223,7 @@ int main(int argc, char *argv[])
 {
        char pass[MAXPASS + 1];
        char option[8];
-       int npass, opt;
+       int npass, nullok;
        int force_failure = 0;
        int retval = UNIX_FAILED;
        char *user;
@@ -255,9 +276,9 @@ int main(int argc, char *argv[])
        } else {
                option[7] = '\0';
                if (strncmp(option, "nullok", 8) == 0)
-                       opt = 1;
+                       nullok = 1;
                else
-                       opt = 0;
+                       nullok = 0;
        }
 
        /* read the password from stdin (a pipe from the pam_unix module) */
@@ -276,13 +297,13 @@ int main(int argc, char *argv[])
                if (npass == 0) {
                        /* the password is NULL */
 
-                       retval = _unix_verify_password(user, NULL, opt);
+                       retval = _unix_verify_password(user, NULL, nullok);
 
                } else {
                        /* does pass agree with the official one? */
 
                        pass[npass] = '\0';     /* NUL terminate */
-                       retval = _unix_verify_password(user, pass, opt);
+                       retval = _unix_verify_password(user, pass, nullok);
 
                }
        }