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]

Reply via email to