Hello community, here is the log from the commit of package pam-modules for openSUSE:Factory checked in at Thu Sep 1 15:34:11 CEST 2011.
-------- --- pam-modules/pam-modules.changes 2011-06-29 15:55:45.000000000 +0200 +++ /mounts/work_src_done/STABLE/pam-modules/pam-modules.changes 2011-08-31 10:41:43.000000000 +0200 @@ -1,0 +2,17 @@ +Wed Aug 31 10:06:03 CEST 2011 - [email protected] + +- unix2_chkpwd should call pam_acct_mgmt (bnc#707645, CVE-2011-3172) +- unix2_chkpwd should only sleep 5 sec on failed logins + +------------------------------------------------------------------- +Thu Jul 7 14:53:44 UTC 2011 - [email protected] + +- add compat mode options to deal with crypt_blowfish signedness bug + (bnc#700876) + +------------------------------------------------------------------- +Wed Jul 6 08:22:49 UTC 2011 - [email protected] + +- use crypt_gensalt_rn from glibc instead of built-in code + +------------------------------------------------------------------- calling whatdependson for head-i586 New: ---- 0001-gettext.diff 0002-change-default-crypt-to-sha512.diff 0003-use-crypt_gensalt_rn-from-glibc.diff 0004-add-workarounds-for-blowfish-signedness-bug.diff 0005-catch-retval-magic-by-ow-crypt-libxcrypt.diff ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pam-modules.spec ++++++ --- /var/tmp/diff_new_pack.9AFDQT/_old 2011-09-01 15:32:31.000000000 +0200 +++ /var/tmp/diff_new_pack.9AFDQT/_new 2011-09-01 15:32:31.000000000 +0200 @@ -25,8 +25,8 @@ Name: pam-modules Summary: Additional PAM Modules -Version: 11.5 -Release: 4 +Version: 12.1 +Release: 1 License: BSD3c ; GPLv2+ Group: System/Libraries AutoReqProv: on @@ -38,6 +38,11 @@ Source21: unix2_chkpwd.c Source41: unix2_chkpwd.8 Source50: dlopen.sh +Patch0: 0001-gettext.diff +Patch1: 0002-change-default-crypt-to-sha512.diff +Patch2: 0003-use-crypt_gensalt_rn-from-glibc.diff +Patch3: 0004-add-workarounds-for-blowfish-signedness-bug.diff +Patch4: 0005-catch-retval-magic-by-ow-crypt-libxcrypt.diff # BuildRoot: %{_tmppath}/%{name}-%{version}-build PreReq: permissions @@ -63,6 +68,15 @@ %prep %setup -q -c %{name} -b1 -b2 +pushd pam_unix2-* +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +gettextize -f +autoreconf -f -i +popd %build for i in * ; do @@ -122,6 +136,7 @@ %files -f pam_unix2.lang %defattr(-,root,root,755) %doc %{_defaultdocdir}/pam +#attr(644,root,root) %config(noreplace) /etc/default/passwd %verify(not mode) %attr(4755,root,shadow) /sbin/unix2_chkpwd %attr(755,root,root) /%{_lib}/security/pam_homecheck.so %attr(755,root,root) /%{_lib}/security/pam_pwcheck.so ++++++ 0001-gettext.diff ++++++ >From 1b5d06d15a082675e841205fcc855ddcbd88b1df Mon Sep 17 00:00:00 2001 From: Ludwig Nussel <[email protected]> Date: Tue, 5 Jul 2011 16:12:51 +0200 Subject: [PATCH 1/4] gettext --- configure.in | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/configure.in b/configure.in index 4a093ea..f4cdcd1 100644 --- a/configure.in +++ b/configure.in @@ -93,7 +93,7 @@ else LDFLAGS="${LDFLAGS} -G" fi -AM_GNU_GETTEXT_VERSION +AM_GNU_GETTEXT_VERSION([0.12]) AM_GNU_GETTEXT([external]) AC_SUBST(LIBPAM) -- 1.7.3.4 ++++++ 0002-change-default-crypt-to-sha512.diff ++++++ >From 81c25a0ddf92dc1568cfbf0e9c3ccb4bd243c1cf Mon Sep 17 00:00:00 2001 From: Ludwig Nussel <[email protected]> Date: Thu, 14 Jul 2011 14:30:11 +0200 Subject: [PATCH 2/4] change default crypt to sha512 also use implicit defaults --- etc/passwd | 35 +++++++++++++++++++++++------------ src/logindefs.c | 2 +- src/unix_passwd.c | 2 +- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/etc/passwd b/etc/passwd index c14bab5..bd86963 100644 --- a/etc/passwd +++ b/etc/passwd @@ -1,27 +1,38 @@ # This file contains some information for -# the passwd (1) command and other tools +# the passwd (1) command and other tools # creating or modifying passwords. -# Define default crypt hash -# CRYPT={des,md5,blowfish} -CRYPT=des +# Define default crypt hash. +# CRYPT={des,md5,blowfish,sha256,sha512} +CRYPT= -# Use another crypt hash for group passwowrds. +# Use another crypt hash for group passwords. # This is used by gpasswd, fallback is the CRYPT entry. # GROUP_CRYPT=des +# We can override the default for a specific service +# by appending the service name (FILES, YP, NISPLUS, LDAP) + +# for local files, use a more secure hash. We +# don't need to be portable here: +# CRYPT_FILES=sha512 +# +# For NIS, we should always use DES: +# CRYPT_YP=des + # We can override the default for a special service # by appending the service name (FILES, YP, NISPLUS, LDAP) # for local files, use a more secure hash. We # don't need to be portable here: -CRYPT_FILES=blowfish -# sometimes we need to specify special options for -# a hash (variable is prepended by the name of the -# crypt hash). -BLOWFISH_CRYPT_FILES=5 +# CRYPT_FILES=blowfish -# For NIS, we should always use DES: -CRYPT_YP=des +# sometimes we need to specify special options for a hash (variable +# is prepended by the name of the crypt hash). In case of blowfish +# and sha* this is the number of rounds +# blowfish: 4-31 +# BLOWFISH_CRYPT_FILES=5 +# sha256/sha512: 1000-9999999 +# SHA512_CRYPT_FILES=1000 diff --git a/src/logindefs.c b/src/logindefs.c index 452cd7e..2316ae4 100644 --- a/src/logindefs.c +++ b/src/logindefs.c @@ -82,7 +82,7 @@ search (const char *name) while (ptr != NULL) { if (strcasecmp (name, ptr->name) == 0) - return ptr->value; + return *ptr->value?ptr->value:NULL; ptr = ptr->next; } diff --git a/src/unix_passwd.c b/src/unix_passwd.c index c4bec5e..a2e2387 100644 --- a/src/unix_passwd.c +++ b/src/unix_passwd.c @@ -557,7 +557,7 @@ __do_setpass (pam_handle_t *pamh, int flags, user_t *data, if (crypt_str == NULL) { opt_str = "CRYPT"; - crypt_str = getlogindefs_str (opt_str, "DES"); + crypt_str = getlogindefs_str (opt_str, data->service == S_YP?"des":"sha512"); } if (strcasecmp (crypt_str, "des") == 0) -- 1.7.3.4 ++++++ 0003-use-crypt_gensalt_rn-from-glibc.diff ++++++ >From 97692d668c87cf67a80e4e89cf0984924bb276f7 Mon Sep 17 00:00:00 2001 From: Ludwig Nussel <[email protected]> Date: Wed, 6 Jul 2011 10:21:04 +0200 Subject: [PATCH 3/4] use crypt_gensalt_rn from glibc --- src/Makefile.am | 2 +- src/crypt_gensalt.c | 375 --------------------------------------------------- src/unix_passwd.c | 8 +- 3 files changed, 3 insertions(+), 382 deletions(-) delete mode 100644 src/crypt_gensalt.c diff --git a/src/Makefile.am b/src/Makefile.am index 46448ae..f2fa4dd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,5 +24,5 @@ pam_unix2_so_LDFLAGS = -Wl,-soname,pam_unix2.so \ pam_unix2_so_SOURCES = passwd_nss.c unix_acct.c get_options.c \ unix_passwd.c yppasswd_xdr.c support.c \ unix_auth.c unix_sess.c read-files.c getuser.c copy_xattr.c \ - selinux_utils.c logindefs.c crypt_gensalt.c + selinux_utils.c logindefs.c diff --git a/src/crypt_gensalt.c b/src/crypt_gensalt.c deleted file mode 100644 index 0c63edc..0000000 --- a/src/crypt_gensalt.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Written by Solar Designer and placed in the public domain. - * See crypt_blowfish.c for more information. - * - * This file contains salt generation functions for the traditional and - * other common crypt(3) algorithms, except for bcrypt which is defined - * entirely in crypt_blowfish.c. - */ - - -#if defined(HAVE_CONFIG_H) -#include "config.h" -#endif - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include <errno.h> -#ifndef __set_errno -#define __set_errno(val) errno = (val) -#endif - -#undef __CONST -#ifdef __GNUC__ -#define __CONST __const -#else -#define __CONST -#endif - -static unsigned char _xcrypt_itoa64[64 + 1] = - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - -static char *_xcrypt_gensalt_traditional_rn(unsigned long count, - __CONST char *input, int size, char *output, int output_size) -{ - if (size < 2 || output_size < 2 + 1 || (count && count != 25)) { - if (output_size > 0) output[0] = '\0'; - __set_errno((output_size < 2 + 1) ? ERANGE : EINVAL); - return NULL; - } - - output[0] = _xcrypt_itoa64[(unsigned int)input[0] & 0x3f]; - output[1] = _xcrypt_itoa64[(unsigned int)input[1] & 0x3f]; - output[2] = '\0'; - - return output; -} - -static char *_xcrypt_gensalt_extended_rn(unsigned long count, - __CONST char *input, int size, char *output, int output_size) -{ - unsigned long value; - -/* Even iteration counts make it easier to detect weak DES keys from a look - * at the hash, so they should be avoided */ - if (size < 3 || output_size < 1 + 4 + 4 + 1 || - (count && (count > 0xffffff || !(count & 1)))) { - if (output_size > 0) output[0] = '\0'; - __set_errno((output_size < 1 + 4 + 4 + 1) ? ERANGE : EINVAL); - return NULL; - } - - if (!count) count = 725; - - output[0] = '_'; - output[1] = _xcrypt_itoa64[count & 0x3f]; - output[2] = _xcrypt_itoa64[(count >> 6) & 0x3f]; - output[3] = _xcrypt_itoa64[(count >> 12) & 0x3f]; - output[4] = _xcrypt_itoa64[(count >> 18) & 0x3f]; - value = (unsigned long)(unsigned char)input[0] | - ((unsigned long)(unsigned char)input[1] << 8) | - ((unsigned long)(unsigned char)input[2] << 16); - output[5] = _xcrypt_itoa64[value & 0x3f]; - output[6] = _xcrypt_itoa64[(value >> 6) & 0x3f]; - output[7] = _xcrypt_itoa64[(value >> 12) & 0x3f]; - output[8] = _xcrypt_itoa64[(value >> 18) & 0x3f]; - output[9] = '\0'; - - return output; -} - -static char * -_xcrypt_gensalt_md5_rn (unsigned long count __attribute__((unused)), - const char *input, int size, - char *output, int output_size) -{ - unsigned long value; - - if (size < 3 || output_size < 3 + 4 + 1) - { - if (output_size > 0) - output[0] = '\0'; - errno = ERANGE; - return NULL; - } - - output[0] = '$'; - output[1] = '1'; - output[2] = '$'; - value = (unsigned long)(unsigned char)input[0] | - ((unsigned long)(unsigned char)input[1] << 8) | - ((unsigned long)(unsigned char)input[2] << 16); - output[3] = _xcrypt_itoa64[value & 0x3f]; - output[4] = _xcrypt_itoa64[(value >> 6) & 0x3f]; - output[5] = _xcrypt_itoa64[(value >> 12) & 0x3f]; - output[6] = _xcrypt_itoa64[(value >> 18) & 0x3f]; - output[7] = '\0'; - - if (size >= 6 && output_size >= 3 + 4 + 4 + 1) { - value = (unsigned long)(unsigned char)input[3] | - ((unsigned long)(unsigned char)input[4] << 8) | - ((unsigned long)(unsigned char)input[5] << 16); - output[7] = _xcrypt_itoa64[value & 0x3f]; - output[8] = _xcrypt_itoa64[(value >> 6) & 0x3f]; - output[9] = _xcrypt_itoa64[(value >> 12) & 0x3f]; - output[10] = _xcrypt_itoa64[(value >> 18) & 0x3f]; - output[11] = '\0'; - } - - return output; -} - -static char * -_xcrypt_gensalt_sha256_rn (unsigned long count, const char *input, int size, - char *output, int output_size) -{ - unsigned long value; - char *buf; - char buf2[12]; - - if (count > 0) - { - if (asprintf (&buf, "$5$rounds=%ld$", count) < 0) - { - if (output_size > 0) - output[0] = '\0'; - errno = ENOMEM; - return NULL; - } - } - else - { - if (asprintf (&buf, "$5$") < 0) - { - if (output_size > 0) - output[0] = '\0'; - errno = ENOMEM; - return NULL; - } - } - - if (size < 3 || output_size < (int)strlen (buf) + 4 + 1) - { - free (buf); - if (output_size > 0) - output[0] = '\0'; - errno = ERANGE; - return NULL; - } - - value = (unsigned long)(unsigned char)input[0] | - ((unsigned long)(unsigned char)input[1] << 8) | - ((unsigned long)(unsigned char)input[2] << 16); - buf2[0] = _xcrypt_itoa64[value & 0x3f]; - buf2[1] = _xcrypt_itoa64[(value >> 6) & 0x3f]; - buf2[2] = _xcrypt_itoa64[(value >> 12) & 0x3f]; - buf2[3] = _xcrypt_itoa64[(value >> 18) & 0x3f]; - buf2[4] = '\0'; - - if (size >= 6 && output_size >= (int)strlen (buf) + 4 + 4 + 1) - { - value = (unsigned long)(unsigned char)input[3] | - ((unsigned long)(unsigned char)input[4] << 8) | - ((unsigned long)(unsigned char)input[5] << 16); - buf2[4] = _xcrypt_itoa64[value & 0x3f]; - buf2[5] = _xcrypt_itoa64[(value >> 6) & 0x3f]; - buf2[6] = _xcrypt_itoa64[(value >> 12) & 0x3f]; - buf2[7] = _xcrypt_itoa64[(value >> 18) & 0x3f]; - buf2[8] = '\0'; - } - - snprintf (output, output_size, "%s%s", buf, buf2); - free (buf); - - return output; -} - -static char * -_xcrypt_gensalt_sha512_rn (unsigned long count, const char *input, int size, - char *output, int output_size) -{ - unsigned long value; - char *buf; - char buf2[12]; - - if (count > 0) - { - if (asprintf (&buf, "$6$rounds=%ld$", count) < 0) - { - if (output_size > 0) - output[0] = '\0'; - errno = ENOMEM; - return NULL; - } - } - else - { - if (asprintf (&buf, "$6$") < 0) - { - if (output_size > 0) - output[0] = '\0'; - errno = ENOMEM; - return NULL; - } - } - - if (size < 3 || output_size < (int)strlen (buf) + 4 + 1) - { - free (buf); - if (output_size > 0) - output[0] = '\0'; - __set_errno(ERANGE); - return NULL; - } - - value = (unsigned long)(unsigned char)input[0] | - ((unsigned long)(unsigned char)input[1] << 8) | - ((unsigned long)(unsigned char)input[2] << 16); - buf2[0] = _xcrypt_itoa64[value & 0x3f]; - buf2[1] = _xcrypt_itoa64[(value >> 6) & 0x3f]; - buf2[2] = _xcrypt_itoa64[(value >> 12) & 0x3f]; - buf2[3] = _xcrypt_itoa64[(value >> 18) & 0x3f]; - buf2[4] = '\0'; - - if (size >= 6 && output_size >= (int)strlen (buf) + 4 + 4 + 1) - { - value = (unsigned long)(unsigned char)input[3] | - ((unsigned long)(unsigned char)input[4] << 8) | - ((unsigned long)(unsigned char)input[5] << 16); - buf2[4] = _xcrypt_itoa64[value & 0x3f]; - buf2[5] = _xcrypt_itoa64[(value >> 6) & 0x3f]; - buf2[6] = _xcrypt_itoa64[(value >> 12) & 0x3f]; - buf2[7] = _xcrypt_itoa64[(value >> 18) & 0x3f]; - buf2[8] = '\0'; - } - - snprintf (output, output_size, "%s%s", buf, buf2); - free (buf); - - return output; -} - -typedef unsigned int BF_word; -static unsigned char BF_itoa64[64 + 1] = - "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - -static void -BF_encode (char *dst, __CONST BF_word *src, int size) -{ - const unsigned char *sptr = (const unsigned char *)src; - const unsigned char *end = sptr + size; - unsigned char *dptr = (unsigned char *)dst; - unsigned int c1, c2; - - do { - c1 = *sptr++; - *dptr++ = BF_itoa64[c1 >> 2]; - c1 = (c1 & 0x03) << 4; - if (sptr >= end) { - *dptr++ = BF_itoa64[c1]; - break; - } - - c2 = *sptr++; - c1 |= c2 >> 4; - *dptr++ = BF_itoa64[c1]; - c1 = (c2 & 0x0f) << 2; - if (sptr >= end) { - *dptr++ = BF_itoa64[c1]; - break; - } - - c2 = *sptr++; - c1 |= c2 >> 6; - *dptr++ = BF_itoa64[c1]; - *dptr++ = BF_itoa64[c2 & 0x3f]; - } while (sptr < end); -} - -static char * -_xcrypt_gensalt_blowfish_rn (unsigned long count, __CONST char *input, - int size, char *output, int output_size) -{ - if (size < 16 || output_size < 7 + 22 + 1 || - (count && (count < 4 || count > 31))) { - if (output_size > 0) output[0] = '\0'; - __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL); - return NULL; - } - - if (!count) count = 5; - - output[0] = '$'; - output[1] = '2'; - output[2] = 'a'; - output[3] = '$'; - output[4] = '0' + count / 10; - output[5] = '0' + count % 10; - output[6] = '$'; - - BF_encode(&output[7], (const unsigned int *)input, 16); - output[7 + 22] = '\0'; - - return output; -} - - - -char * -crypt_gensalt_r (__const char *prefix, unsigned long count, - __const char *input, int size, char *output, - int output_size) -{ - char *(*use) (unsigned long count, - __const char *input, int size, char *output, int output_size); - - /* This may be supported on some platforms in the future */ - if (!input) - { - __set_errno (EINVAL); - return NULL; - } - - if (prefix[0] == '$') - { - char *hash_id = strdup (&prefix[1]); - char *c = strchr (hash_id, '$'); - - if (c == NULL) - { - free (hash_id); - return NULL; - } - - *c = '\0'; - - if (hash_id[0] == '1') /* md5 */ - use = _xcrypt_gensalt_md5_rn; - else if (hash_id[0] == '2' && hash_id[1] == 'a') /* blowfish */ - use = _xcrypt_gensalt_blowfish_rn; - else if (hash_id[0] == '5') /* sha256 */ - use = _xcrypt_gensalt_sha256_rn; - else if (hash_id[0] == '6') /* sha512 */ - use = _xcrypt_gensalt_sha512_rn; - else - use = _xcrypt_gensalt_traditional_rn; - - free (hash_id); - } - else if (prefix[0] == '_') - use = _xcrypt_gensalt_extended_rn; - else if (!prefix[0] || - (prefix[0] && prefix[1] && - memchr (_xcrypt_itoa64, prefix[0], 64) && - memchr (_xcrypt_itoa64, prefix[1], 64))) - use = _xcrypt_gensalt_traditional_rn; - else - { - __set_errno (EINVAL); - return NULL; - } - - return use (count, input, size, output, output_size); -} diff --git a/src/unix_passwd.c b/src/unix_passwd.c index a2e2387..8491adf 100644 --- a/src/unix_passwd.c +++ b/src/unix_passwd.c @@ -63,6 +63,7 @@ #endif #if defined(HAVE_CRYPT_H) +#define _OW_SOURCE #include <crypt.h> #endif @@ -87,11 +88,6 @@ static int __do_setpass (pam_handle_t *pamh, int flags, user_t *user, options_t *options, struct crypt_data *output); -extern char * -crypt_gensalt_r (__const char *prefix, unsigned long count, - __const char *input, int size, char *output, - int output_size); - PAM_EXTERN int pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) { @@ -502,7 +498,7 @@ make_crypt_salt (const char *crypt_prefix, int crypt_rounds, close (fd); - retval = crypt_gensalt_r (crypt_prefix, crypt_rounds, entropy, + retval = crypt_gensalt_rn (crypt_prefix, crypt_rounds, entropy, sizeof (entropy), output, sizeof(output)); memset (entropy, 0, sizeof (entropy)); -- 1.7.3.4 ++++++ 0004-add-workarounds-for-blowfish-signedness-bug.diff ++++++ >From 7a3e5fd2d79657674e72212ad13ea350d72e8306 Mon Sep 17 00:00:00 2001 From: Ludwig Nussel <[email protected]> Date: Wed, 13 Jul 2011 08:50:58 +0200 Subject: [PATCH 4/4] add workarounds for blowfish signedness bug The option BLOWFISH_2a2x allows to enable compat modes. --- configure.in | 18 +++++++++++++++++- etc/passwd | 16 ++++++++++++++++ src/get_options.c | 11 +++++++++++ src/public.h | 4 ++++ src/support.c | 30 ++++++++++++++++++++++++++++++ src/unix_auth.c | 8 +------- src/unix_passwd.c | 10 +++++++--- 7 files changed, 86 insertions(+), 11 deletions(-) diff --git a/configure.in b/configure.in index f4cdcd1..10c4e1f 100644 --- a/configure.in +++ b/configure.in @@ -48,13 +48,29 @@ dnl Should we compile with SELinux support? default: yes AC_ARG_ENABLE([selinux], AC_HELP_STRING([--disable-selinux],[Enable SELinux support (default=yes)]), WITH_SELINUX=$enableval, WITH_SELINUX=yes) -if test "$WITH_SELINUX" == "yes" ; then +if test "$WITH_SELINUX" = "yes" ; then AC_CHECK_LIB(selinux,is_selinux_enabled, [AC_DEFINE(WITH_SELINUX,1, [Define if you want to compile in SELinux support]) LIBS="$LIBS -lselinux"]) fi +AC_ARG_ENABLE([blowfish-bug-workaround], + AC_HELP_STRING([--disable-blowfish-bug-workaround],[Enable workarounds for blowfish signedness bug]), + CRYPT_BLOWFISH_SIGNEDNESS_BUG_WORKAROUNDS=$enableval, CRYPT_BLOWFISH_SIGNEDNESS_BUG_WORKAROUNDS=yes) +if test "$CRYPT_BLOWFISH_SIGNEDNESS_BUG_WORKAROUNDS" = "yes" ; then + AC_DEFINE(CRYPT_BLOWFISH_SIGNEDNESS_BUG_WORKAROUNDS,1, + [Define if you want to enable workarounds for blowfish signedness bug]) +fi + +AC_ARG_ENABLE([blowfish-bug-compatmode], + AC_HELP_STRING([--enable-blowfish-bug-compatmode],[Enable blowfish compat mode by default]), + CRYPT_BLOWFISH_COMPATMODE=$enableval, CRYPT_BLOWFISH_COMPATMODE=no) +if test "$CRYPT_BLOWFISH_COMPATMODE" = "yes" ; then + AC_DEFINE(CRYPT_BLOWFISH_COMPATMODE,1, + [Define if you want to enable blowfish compat mode by default]) +fi + dnl Check standard headers AC_HEADER_STDC AC_CHECK_HEADERS(crypt.h) diff --git a/etc/passwd b/etc/passwd index bd86963..ec6f0d4 100644 --- a/etc/passwd +++ b/etc/passwd @@ -36,3 +36,19 @@ CRYPT= # sha256/sha512: 1000-9999999 # SHA512_CRYPT_FILES=1000 +# In June 2011 it was discovered that the Linux crypt_blowfish +# implementation contained a bug that made passwords with non-ASCII +# characters easier to crack (CVE-2011-2483). Affected passwords are +# also incompatible with the original, correct OpenBSD +# implementation. Therefore the $2a hash identifier previously used +# for blowfish now is ambiguous as it could mean the hash was +# generated with the correct implementation on OpenBSD or the buggy +# one on Linux. To avoid the ambiguity two new identifier were +# introduced. $2x now explicitly identifies hashes that were +# generated with the buggy algorithm while $2y is used for hashes +# generated with the correct algorithm. New passwords are now +# generated with the $2y identifier. +# +# Setting the following option to "yes" tells the sytem that $2a +# hashes are to be treated as generated with the buggy algorithm. +BLOWFISH_2a2x= diff --git a/src/get_options.c b/src/get_options.c index faf8aa0..f899155 100644 --- a/src/get_options.c +++ b/src/get_options.c @@ -138,6 +138,17 @@ get_options (pam_handle_t *pamh, options_t *options, const char *type, /* Set some default values, which could be overwritten later. */ options->use_crypt = NONE; +#ifdef CRYPT_BLOWFISH_SIGNEDNESS_BUG_WORKAROUNDS + options->blowfish_2a2x = getlogindefs_bool("BLOWFISH_2a2x", +#ifdef CRYPT_BLOWFISH_COMPATMODE + 1 +#else + 0 +#endif + ); + free_getlogindefs_data(); +#endif + /* Parse parameters for module */ for ( ; argc-- > 0; argv++) parse_option (pamh, *argv, type, options); diff --git a/src/public.h b/src/public.h index 7200759..ec476b8 100644 --- a/src/public.h +++ b/src/public.h @@ -68,6 +68,7 @@ struct options_t { int nullok; int use_authtok; int use_first_pass; + int blowfish_2a2x; char **use_other_modules; char *nisdir; crypt_t use_crypt; @@ -86,6 +87,9 @@ extern int __call_other_module(pam_handle_t * pamh, int flags, const char *mod_name, const char *func_name, options_t *options); +extern int __check_password_match (const char *hash, const char *pass, + options_t *options); + extern int get_options (pam_handle_t *pamh, options_t *options, const char *type, int argc, const char **argv); diff --git a/src/support.c b/src/support.c index 6a1ce5e..b3b94c8 100644 --- a/src/support.c +++ b/src/support.c @@ -48,6 +48,11 @@ #include <security/pam_ext.h> #endif +#if defined(HAVE_CRYPT_H) +#define _OW_SOURCE +#include <crypt.h> +#endif + #include "public.h" int @@ -360,3 +365,28 @@ struct pam_module _pam_unix2_modstruct = pam_sm_chauthtok }; #endif + +int +__check_password_match (const char *hash, const char *pass, options_t *options) +{ + struct crypt_data output; + char *h = NULL; + int r; + + memset (&output, 0, sizeof (output)); + +#ifdef CRYPT_BLOWFISH_SIGNEDNESS_BUG_WORKAROUNDS + if ((options->blowfish_2a2x) + && !strncmp(hash, "$2a$", 4)) + { + h = strdupa(hash); + h[2] = 'x'; + hash = h; + } +#endif + + r = (strcmp (hash, crypt_r (pass, hash, &output)) == 0); + if (h) + _pam_overwrite(h); + return r; +} diff --git a/src/unix_auth.c b/src/unix_auth.c index e61c45e..e78c520 100644 --- a/src/unix_auth.c +++ b/src/unix_auth.c @@ -61,10 +61,6 @@ #include <security/pam_ext.h> #endif -#if defined(HAVE_CRYPT_H) -#include <crypt.h> -#endif - #include "public.h" @@ -124,7 +120,6 @@ int pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv) { - struct crypt_data output; int retval; int sp_buflen = 256; char *sp_buffer = alloca (sp_buflen); @@ -141,7 +136,6 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, options_t options; int ask_user, ask_password; - memset (&output, 0, sizeof (output)); memset (&options, 0, sizeof (options)); if (get_options (pamh, &options, "auth", argc, argv) < 0) @@ -325,7 +319,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, *cp = '\0'; } - if (strcmp (crypt_r (password, salt, &output), salt) != 0) + if (!__check_password_match(salt, password, &options)) { if (options.debug) pam_syslog (pamh, LOG_DEBUG, "wrong password, return PAM_AUTH_ERR"); diff --git a/src/unix_passwd.c b/src/unix_passwd.c index 8491adf..e00615b 100644 --- a/src/unix_passwd.c +++ b/src/unix_passwd.c @@ -257,8 +257,7 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) /* Check if the old password was correct. */ if ((getuid () || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) && - strcmp (data->oldpassword, - crypt_r (oldpass, data->oldpassword, &output)) != 0) + !__check_password_match(data->oldpassword, oldpass, &options)) { if (options.debug) pam_syslog (pamh, LOG_DEBUG, @@ -686,7 +685,12 @@ __do_setpass (pam_handle_t *pamh, int flags, user_t *data, case BLOWFISH: salt = make_crypt_salt ("$2a$", options->crypt_rounds, pamh, flags); if (salt != NULL) - newpassword = crypt_r (data->newpassword, salt, output); + { +#ifdef CRYPT_BLOWFISH_SIGNEDNESS_BUG_WORKAROUNDS + salt[2] = 'y'; +#endif + newpassword = crypt_r (data->newpassword, salt, output); + } else { __write_message (pamh, flags, PAM_ERROR_MSG, -- 1.7.3.4 ++++++ 0005-catch-retval-magic-by-ow-crypt-libxcrypt.diff ++++++ >From f0e1dcc08789da62c26236e3bc0e3b68ba6d0fd0 Mon Sep 17 00:00:00 2001 From: Ludwig Nussel <[email protected]> Date: Wed, 20 Jul 2011 11:16:56 +0200 Subject: [PATCH pam_unix2] catch retval magic by ow-crypt/libxcrypt Instead of returning NULL ow-crypt's retval magic returns "*0" or "*1". --- src/unix_passwd.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/src/unix_passwd.c b/src/unix_passwd.c index e00615b..80319d7 100644 --- a/src/unix_passwd.c +++ b/src/unix_passwd.c @@ -729,7 +729,9 @@ __do_setpass (pam_handle_t *pamh, int flags, user_t *data, options->use_crypt); return PAM_AUTHTOK_ERR; } - if (newpassword == NULL) + if (newpassword == NULL + /* catch retval magic by ow-crypt/libxcrypt */ + || !strcmp(newpassword, "*0") || !strcmp(newpassword, "*1")) { __write_message (pamh, flags, PAM_ERROR_MSG, _("crypt_r() returns NULL pointer")); -- 1.7.3.4 ++++++ unix2_chkpwd.c ++++++ --- /var/tmp/diff_new_pack.9AFDQT/_old 2011-09-01 15:32:32.000000000 +0200 +++ /var/tmp/diff_new_pack.9AFDQT/_new 2011-09-01 15:32:32.000000000 +0200 @@ -148,15 +148,23 @@ if (err == PAM_SUCCESS) { - int err2 = pam_setcred(pamh, PAM_REFRESH_CRED); - if (err2 != PAM_SUCCESS) - _log_err(LOG_ERR, "pam_setcred(%s, %s): %s", - service, user, - pam_strerror(pamh, err2)); - /* - * ignore errors on refresh credentials. - * If this did not work we use the old once. - */ + err = pam_acct_mgmt(pamh, 0); + if (err == PAM_SUCCESS) + { + int err2 = pam_setcred(pamh, PAM_REFRESH_CRED); + if (err2 != PAM_SUCCESS) + _log_err(LOG_ERR, "pam_setcred(%s, %s): %s", + service, user, + pam_strerror(pamh, err2)); + /* + * ignore errors on refresh credentials. + * If this did not work we use the old once. + */ + } else { + _log_err(LOG_ERR, "pam_acct_mgmt(%s, %s): %s", + service, user, + pam_strerror(pamh, err)); + } } pam_end(pamh, err); @@ -206,6 +214,7 @@ const char *program_name; char *service, *user; int fd; + int result = UNIX_FAILED; uid_t uid; uid = getuid(); @@ -269,10 +278,12 @@ user = getuidname(uid); if (argc == 3 && strcmp(user, argv[2])) { user = argv[2]; - /* Discourage use of this program as a - * password cracker */ - if (uid != 0) - sleep(5); } - return _authenticate(service, user); + result = _authenticate(service, user); + /* Discourage use of this program as a + * password cracker */ + usleep(500000); + if (result != UNIX_PASSED && uid != 0) + sleep(5); + return result; } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
