]> granicus.if.org Git - linux-pam/commitdiff
Relevant BUGIDs: pam_unix_refactor
authorTomas Mraz <tm@t8m.info>
Wed, 5 Dec 2007 10:03:29 +0000 (10:03 +0000)
committerTomas Mraz <tm@t8m.info>
Wed, 5 Dec 2007 10:03:29 +0000 (10:03 +0000)
Purpose of commit: cleanup

Commit summary:
---------------
2007-12-05  Tomas Mraz  <t8m@centrum.cz>

        * modules/pam_unix/Makefile.am: Add passverify.h and passverify.c
        as first part of pam_unix refactorization.
        * modules/pam_unix/pam_unix/pam_unix_acct.c: Include passverify.h.
        * modules/pam_unix/pam_unix_passwd.c: Likewise.
        * modules/pam_unix/passverify.c: New file with common functions.
        * modules/pam_unix/passverify.h: Prototypes for the common functions.
        * modules/pam_unix/support.c: Include passverify.h, move
        _unix_shadowed() to passverify.c.
        (_unix_verify_password): Refactor out verify_pwd_hash() function.
        * modules/pam_unix/support.h: Move _unix_shadowed() prototype to
        passverify.h
        * modules/pam_unix/unix_chkpwd.c: Use _unix_shadowed() and
        verify_pwd_hash() from passverify.c.

ChangeLog
modules/pam_unix/Makefile.am
modules/pam_unix/pam_unix_acct.c
modules/pam_unix/pam_unix_passwd.c
modules/pam_unix/passverify.c [new file with mode: 0644]
modules/pam_unix/passverify.h [new file with mode: 0644]
modules/pam_unix/support.c
modules/pam_unix/support.h
modules/pam_unix/unix_chkpwd.c

index b572b38bf1857abbe191729f938a9b05059a7810..61b2e5e1c187c8d8276cf596a568ac27cee1da98 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2007-12-05  Tomas Mraz  <t8m@centrum.cz>
+
+       * modules/pam_unix/Makefile.am: Add passverify.h and passverify.c
+       as first part of pam_unix refactorization.
+       * modules/pam_unix/pam_unix/pam_unix_acct.c: Include passverify.h.
+       * modules/pam_unix/pam_unix_passwd.c: Likewise.
+       * modules/pam_unix/passverify.c: New file with common functions.
+       * modules/pam_unix/passverify.h: Prototypes for the common functions.
+       * modules/pam_unix/support.c: Include passverify.h, move
+       _unix_shadowed() to passverify.c.
+       (_unix_verify_password): Refactor out verify_pwd_hash() function.
+       * modules/pam_unix/support.h: Move _unix_shadowed() prototype to
+       passverify.h
+       * modules/pam_unix/unix_chkpwd.c: Use _unix_shadowed() and
+       verify_pwd_hash() from passverify.c.
+
 2007-11-20  Thorsten Kukuk  <kukuk@thkukuk.de>
 
        * modules/pam_unix/Makefile.am (unix_chkpwd_LDADD): Don't link
index caccdf057e736d02407c567b2a1cd84c055339de..a74d97622b1283001812063f8ced287ef5347a59 100644 (file)
@@ -34,7 +34,7 @@ pam_unix_la_LIBADD = @LIBCRACK@ @LIBNSL@ -L$(top_builddir)/libpam -lpam \
 
 securelib_LTLIBRARIES = pam_unix.la
 
-noinst_HEADERS = md5.h support.h yppasswd.h bigcrypt.h
+noinst_HEADERS = md5.h support.h yppasswd.h bigcrypt.h passverify.h
 
 sbin_PROGRAMS = unix_chkpwd
 
@@ -42,13 +42,14 @@ noinst_PROGRAMS = bigcrypt
 
 pam_unix_la_SOURCES = bigcrypt.c pam_unix_acct.c \
        pam_unix_auth.c pam_unix_passwd.c pam_unix_sess.c support.c \
-       yppasswd_xdr.c md5_good.c md5_broken.c
+       passverify.c yppasswd_xdr.c md5_good.c md5_broken.c
 
 bigcrypt_SOURCES = bigcrypt.c bigcrypt_main.c
 bigcrypt_CFLAGS = $(AM_CFLAGS)
 bigcrypt_LDADD = @LIBCRYPT@
 
-unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c
+unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c \
+       passverify.c
 unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
 unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@ 
 unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@
index 6b04ed2f8fe737d910bce153e4400919ef4e5c8f..aeecb13201956d4f7bd4efb760cad06f64b16350 100644 (file)
@@ -63,6 +63,7 @@
 #include <security/pam_modutil.h>
 
 #include "support.h"
+#include "passverify.h"
 
 #ifdef WITH_SELINUX
 
index c8ee54924fbbaa8aa278a9297eaf7240ed9bfcf8..3a61925e47929a2ff2578e8c2cd8070b3a09703d 100644 (file)
@@ -84,6 +84,7 @@ static security_context_t prev_context=NULL;
 #include "yppasswd.h"
 #include "md5.h"
 #include "support.h"
+#include "passverify.h"
 #include "bigcrypt.h"
 
 #if !((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
new file mode 100644 (file)
index 0000000..6587bac
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright information at end of file.
+ */
+#include "config.h"
+#include <security/_pam_macros.h>
+#include <security/pam_modules.h>
+#include "support.h"
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "md5.h"
+#include "bigcrypt.h"
+#include "passverify.h"
+
+int
+verify_pwd_hash(const char *p, const char *hash, unsigned int nullok)
+{
+       size_t hash_len = strlen(hash);
+       char *pp = NULL;
+       int retval;
+       D(("called"));
+
+       if (!hash_len) {
+               /* the stored password is NULL */
+               if (nullok) { /* this means we've succeeded */
+                       D(("user has empty password - access granted"));
+                       retval = PAM_SUCCESS;
+               } else {
+                       D(("user has empty password - access denied"));
+                       retval = PAM_AUTH_ERR;
+               }
+       } else if (!p || *hash == '*' || *hash == '!') {
+               retval = PAM_AUTH_ERR;
+       } else {
+               if (!strncmp(hash, "$1$", 3)) {
+                       pp = Goodcrypt_md5(p, hash);
+                       if (pp && strcmp(pp, hash) != 0) {
+                               _pam_delete(pp);
+                               pp = Brokencrypt_md5(p, hash);
+                       }
+               } else if (*hash != '$' && hash_len >= 13) {
+                       pp = bigcrypt(p, hash);
+                       if (pp && hash_len == 13 && strlen(pp) > hash_len) {
+                               _pam_overwrite(pp + hash_len);
+                       }
+               } else {
+                       /*
+                        * Ok, we don't know the crypt algorithm, but maybe
+                        * libcrypt nows about it? We should try it.
+                        */
+                       pp = x_strdup(crypt(p, hash));
+               }
+               p = NULL;               /* no longer needed here */
+
+               /* the moment of truth -- do we agree with the password? */
+               D(("comparing state of pp[%s] and salt[%s]", pp, salt));
+
+               if (pp && strcmp(pp, hash) == 0) {
+                       retval = PAM_SUCCESS;
+               } else {
+                       retval = PAM_AUTH_ERR;
+               }
+       }
+       
+       if (pp)
+               _pam_delete(pp);
+       D(("done [%d].", retval));
+
+       return retval;
+}
+
+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.
+ * Copyright (c) Alex O. Yuriev, 1996.
+ * Copyright (c) Cristian Gafton 1996.
+ * Copyright (c) Red Hat, Inc. 2007.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h
new file mode 100644 (file)
index 0000000..a3ae921
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright information at end of file.
+ */
+int
+verify_pwd_hash(const char *p, const char *hash, unsigned int nullok);
+
+int
+_unix_shadowed(const struct passwd *pwd);
+
+/* ****************************************************************** *
+ * Copyright (c) Red Hat, Inc. 2007.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
index 1472b96686f31523f5726d8d3c4236d7dbc323ea..60acc9583983bb6565e5f6a8cb6d9382d1684a8d 100644 (file)
@@ -26,9 +26,8 @@
 #include <security/pam_ext.h>
 #include <security/pam_modutil.h>
 
-#include "md5.h"
 #include "support.h"
-#include "bigcrypt.h"
+#include "passverify.h"
 #ifdef WITH_SELINUX
 #include <selinux/selinux.h>
 #define SELINUX_ENABLED is_selinux_enabled()>0
@@ -579,7 +578,6 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
        struct passwd *pwd = NULL;
        struct spwd *spwdent = NULL;
        char *salt = NULL;
-       char *pp = NULL;
        char *data_name;
        int retval;
 
@@ -679,48 +677,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
                        }
                }
        } else {
-           size_t salt_len = strlen(salt);
-           if (!salt_len) {
-               /* the stored password is NULL */
-               if (off(UNIX__NONULL, ctrl)) {/* this means we've succeeded */
-                   D(("user has empty password - access granted"));
-                   retval = PAM_SUCCESS;
-               } else {
-                   D(("user has empty password - access denied"));
-                   retval = PAM_AUTH_ERR;
-               }
-           } else if (!p || *salt == '*' || *salt == '!') {
-               retval = PAM_AUTH_ERR;
-           } else {
-               if (!strncmp(salt, "$1$", 3)) {
-                   pp = Goodcrypt_md5(p, salt);
-                   if (pp && strcmp(pp, salt) != 0) {
-                       _pam_delete(pp);
-                       pp = Brokencrypt_md5(p, salt);
-                   }
-               } else if (*salt != '$' && salt_len >= 13) {
-                   pp = bigcrypt(p, salt);
-                   if (pp && salt_len == 13 && strlen(pp) > salt_len) {
-                       _pam_overwrite(pp + salt_len);
-                   }
-               } else {
-                    /*
-                    * Ok, we don't know the crypt algorithm, but maybe
-                    * libcrypt nows about it? We should try it.
-                    */
-                   pp = x_strdup (crypt(p, salt));
-               }
-               p = NULL;               /* no longer needed here */
-
-               /* the moment of truth -- do we agree with the password? */
-               D(("comparing state of pp[%s] and salt[%s]", pp, salt));
-
-               if (pp && strcmp(pp, salt) == 0) {
-                   retval = PAM_SUCCESS;
-               } else {
-                   retval = PAM_AUTH_ERR;
-               }
-           }
+               retval = verify_pwd_hash(p, salt, off(UNIX__NONULL, ctrl));
        }
 
        if (retval == PAM_SUCCESS) {
@@ -809,8 +766,6 @@ cleanup:
                _pam_delete(data_name);
        if (salt)
                _pam_delete(salt);
-       if (pp)
-               _pam_delete(pp);
 
        D(("done [%d].", retval));
 
@@ -971,21 +926,6 @@ 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 9873b161c5a5dd7043a975b889e6ef3ebd6b4044..94a9b393e21379f87582bb424ca9c56dd77cf2f8 100644 (file)
@@ -149,7 +149,6 @@ extern int _unix_read_password(pam_handle_t * pamh
                        ,const char *prompt2
                        ,const char *data_name
                        ,const void **pass);
-extern int _unix_shadowed(const struct passwd *pwd);
 
 extern struct spwd *_unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user);
 #endif /* _PAM_UNIX_SUPPORT_H */
index 486a8498b610322451af9774db223afca73444c3..1e8944e9d6d67f5335e76586f7bac45548b3185d 100644 (file)
@@ -39,8 +39,7 @@ static int selinux_enabled=-1;
 #include <security/_pam_types.h>
 #include <security/_pam_macros.h>
 
-#include "md5.h"
-#include "bigcrypt.h"
+#include "passverify.h"
 
 /* syslogging function for errors and other information */
 
@@ -55,24 +54,6 @@ 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)
 {
 #ifndef SA_RESETHAND
@@ -142,9 +123,7 @@ static int _unix_verify_password(const char *name, const char *p, int nullok)
        struct passwd *pwd = NULL;
        struct spwd *spwdent = NULL;
        char *salt = NULL;
-       char *pp = NULL;
        int retval = PAM_AUTH_ERR;
-       size_t salt_len;
 
        /* UNIX passwords area */
        setpwent();
@@ -180,69 +159,18 @@ static int _unix_verify_password(const char *name, const char *p, int nullok)
        }
        if (pwd == NULL || salt == NULL) {
                _log_err(LOG_WARNING, "check pass; user unknown");
-               p = NULL;
-               return PAM_USER_UNKNOWN;
+               retval = PAM_USER_UNKNOWN;
+       } else {
+               retval = verify_pwd_hash(p, salt, nullok);
        }
 
-       salt_len = strlen(salt);
-       if (salt_len == 0) {
-               return (nullok == 0) ? PAM_AUTH_ERR : PAM_SUCCESS;
-       }
-       if (p == NULL || strlen(p) == 0) {
+       if (salt) {
                _pam_overwrite(salt);
                _pam_drop(salt);
-               return PAM_AUTHTOK_ERR;
        }
 
-       /* the moment of truth -- do we agree with the password? */
-       retval = PAM_AUTH_ERR;
-       if (!strncmp(salt, "$1$", 3)) {
-               pp = Goodcrypt_md5(p, salt);
-               if (pp && strcmp(pp, salt) == 0) {
-                       retval = PAM_SUCCESS;
-               } else {
-                       _pam_overwrite(pp);
-                       _pam_drop(pp);
-                       pp = Brokencrypt_md5(p, salt);
-                       if (pp && strcmp(pp, salt) == 0)
-                               retval = PAM_SUCCESS;
-               }
-       } else if (*salt == '$') {
-               /*
-                * Ok, we don't know the crypt algorithm, but maybe
-                * libcrypt nows about it? We should try it.
-                */
-               pp = x_strdup (crypt(p, salt));
-               if (pp && strcmp(pp, salt) == 0) {
-                       retval = PAM_SUCCESS;
-               }
-       } else if (*salt == '*' || *salt == '!' || salt_len < 13) {
-           retval = PAM_AUTH_ERR;
-       } else {
-               pp = bigcrypt(p, salt);
-               /*
-                * Note, we are comparing the bigcrypt of the password with
-                * the contents of the password field. If the latter was
-                * encrypted with regular crypt (and not bigcrypt) it will
-                * have been truncated for storage relative to the output
-                * of bigcrypt here. As such we need to compare only the
-                * stored string with the subset of bigcrypt's result.
-                * Bug 521314.
-                */
-               if (pp && salt_len == 13 && strlen(pp) > salt_len) {
-                   _pam_overwrite(pp+salt_len);
-               }
-               
-               if (pp && strcmp(pp, salt) == 0) {
-                       retval = PAM_SUCCESS;
-               }
-       }
        p = NULL;               /* no longer needed here */
 
-       /* clean up */
-       _pam_overwrite(pp);
-       _pam_drop(pp);
-
        return retval;
 }