From 39483af547d33022ff9e18b741165f0551bdc090 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Wed, 5 Dec 2007 10:03:29 +0000 Subject: Relevant BUGIDs: Purpose of commit: cleanup Commit summary: --------------- 2007-12-05 Tomas Mraz * 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 | 16 +++++ modules/pam_unix/Makefile.am | 7 ++- modules/pam_unix/pam_unix_acct.c | 1 + modules/pam_unix/pam_unix_passwd.c | 1 + modules/pam_unix/passverify.c | 125 +++++++++++++++++++++++++++++++++++++ modules/pam_unix/passverify.h | 43 +++++++++++++ modules/pam_unix/support.c | 64 +------------------ modules/pam_unix/support.h | 1 - modules/pam_unix/unix_chkpwd.c | 82 ++---------------------- 9 files changed, 197 insertions(+), 143 deletions(-) create mode 100644 modules/pam_unix/passverify.c create mode 100644 modules/pam_unix/passverify.h diff --git a/ChangeLog b/ChangeLog index b572b38b..61b2e5e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2007-12-05 Tomas Mraz + + * 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 * modules/pam_unix/Makefile.am (unix_chkpwd_LDADD): Don't link diff --git a/modules/pam_unix/Makefile.am b/modules/pam_unix/Makefile.am index caccdf05..a74d9762 100644 --- a/modules/pam_unix/Makefile.am +++ b/modules/pam_unix/Makefile.am @@ -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@ diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index 6b04ed2f..aeecb132 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -63,6 +63,7 @@ #include #include "support.h" +#include "passverify.h" #ifdef WITH_SELINUX diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index c8ee5492..3a61925e 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -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 index 00000000..6587bace --- /dev/null +++ b/modules/pam_unix/passverify.c @@ -0,0 +1,125 @@ +/* + * Copyright information at end of file. + */ +#include "config.h" +#include +#include +#include "support.h" +#include +#include +#include + +#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 index 00000000..a3ae9210 --- /dev/null +++ b/modules/pam_unix/passverify.h @@ -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. + */ diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 1472b966..60acc958 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -26,9 +26,8 @@ #include #include -#include "md5.h" #include "support.h" -#include "bigcrypt.h" +#include "passverify.h" #ifdef WITH_SELINUX #include #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. diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h index 9873b161..94a9b393 100644 --- a/modules/pam_unix/support.h +++ b/modules/pam_unix/support.h @@ -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 */ diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c index 486a8498..1e8944e9 100644 --- a/modules/pam_unix/unix_chkpwd.c +++ b/modules/pam_unix/unix_chkpwd.c @@ -39,8 +39,7 @@ static int selinux_enabled=-1; #include #include -#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; } -- cgit v1.2.3