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 - mc(a)suse.de
+
+- 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 - lnussel(a)suse.de
+
+- add compat mode options to deal with crypt_blowfish signedness bug
+ (bnc#700876)
+
+-------------------------------------------------------------------
+Wed Jul 6 08:22:49 UTC 2011 - lnussel(a)suse.de
+
+- 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 <ludwig.nussel(a)suse.de>
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 <ludwig.nussel(a)suse.de>
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 <ludwig.nussel(a)suse.de>
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 <ludwig.nussel(a)suse.de>
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 <ludwig.nussel(a)suse.de>
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: opensuse-commit+unsubscribe(a)opensuse.org
For additional commands, e-mail: opensuse-commit+help(a)opensuse.org