trawick 02/05/10 12:10:58
Modified: . CHANGES configure.in
build apr_common.m4
passwd apr_md5.c
Log:
Linux, AIX: Use crypt_r() instead of crypt() because the native
crypt() is not thread-safe. The misuse of crypt() led to
intermittent failures with Apache basic authentication when crypt
passwords were being used.
Revision Changes Path
1.285 +5 -0 apr/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apr/CHANGES,v
retrieving revision 1.284
retrieving revision 1.285
diff -u -r1.284 -r1.285
--- CHANGES 9 May 2002 23:27:20 -0000 1.284
+++ CHANGES 10 May 2002 19:10:58 -0000 1.285
@@ -1,5 +1,10 @@
Changes with APR b1
+ *) Linux, AIX: Use crypt_r() instead of crypt() because the native
+ crypt() is not thread-safe. The misuse of crypt() led to
+ intermittent failures with Apache basic authentication when crypt
+ passwords were being used. [Jeff Trawick]
+
*) AIX: Global mutexes don't need an intraprocess mutex when SysV
sems are used for the crossprocess mutex.
Darwin: The same optimization was applied for Posix sems.
1.448 +4 -0 apr/configure.in
Index: configure.in
===================================================================
RCS file: /home/cvs/apr/configure.in,v
retrieving revision 1.447
retrieving revision 1.448
diff -u -r1.447 -r1.448
--- configure.in 9 May 2002 18:56:43 -0000 1.447
+++ configure.in 10 May 2002 19:10:58 -0000 1.448
@@ -830,6 +830,10 @@
if test "$strerror_r" = "1"; then
APR_CHECK_STRERROR_R_RC
fi
+AC_CHECK_FUNCS(crypt_r, [ crypt_r="1" ], [ crypt_r="0" ])
+if test "$crypt_r" = "1"; then
+ APR_CHECK_CRYPT_R_STYLE
+fi
AC_CHECK_FUNCS(iconv, [ iconv="1" ], [ iconv="0" ])
if test "$iconv" = "1"; then
APR_CHECK_ICONV_INBUF
1.31 +53 -0 apr/build/apr_common.m4
Index: apr_common.m4
===================================================================
RCS file: /home/cvs/apr/build/apr_common.m4,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- apr_common.m4 18 Apr 2002 09:01:32 -0000 1.30
+++ apr_common.m4 10 May 2002 19:10:58 -0000 1.31
@@ -459,6 +459,59 @@
AC_MSG_RESULT([$msg])
] )
dnl
+dnl APR_CHECK_CRYPT_R_STYLE
+dnl
+dnl Decide which of a couple of flavors of crypt_r() is necessary for
+dnl this platform.
+dnl
+AC_DEFUN(APR_CHECK_CRYPT_R_STYLE,[
+AC_CACHE_CHECK(style of crypt_r, ac_cv_crypt_r_style,[
+dnl
+ac_cv_crypt_r_style=none
+dnl
+AC_TRY_COMPILE([
+#include <crypt.h>
+],[
+CRYPTD buffer;
+crypt_r("passwd", "hash", &buffer);
+], ac_cv_crypt_r_style=cryptd)
+dnl
+if test "$ac_cv_crypt_r_style" = "none"; then
+AC_TRY_COMPILE([
+#include <crypt.h>
+],[
+struct crypt_data buffer;
+crypt_r("passwd", "hash", &buffer);
+], ac_cv_crypt_r_style=struct_crypt_data)
+fi
+dnl
+if test "$ac_cv_crypt_r_style" = "none"; then
+dnl same as previous test, but see if defining _GNU_SOURCE helps
+AC_TRY_COMPILE([
+#define _GNU_SOURCE
+#include <crypt.h>
+],[
+struct crypt_data buffer;
+crypt_r("passwd", "hash", &buffer);
+], ac_cv_crypt_r_style=struct_crypt_data_gnu_source)
+fi
+dnl
+])
+if test "$ac_cv_crypt_r_style" = "cryptd"; then
+ AC_DEFINE(CRYPT_R_CRYPTD, 1, [Define if crypt_r has uses CRYPTD])
+fi
+dnl if we don't combine these conditions, CRYPT_R_STRUCT_CRYPT_DATA
+dnl will end up defined twice
+if test "$ac_cv_crypt_r_style" = "struct_crypt_data" -o \
+ "$ac_cv_crypt_r_style" = "struct_crypt_data_gnu_source"; then
+ AC_DEFINE(CRYPT_R_STRUCT_CRYPT_DATA, 1, [Define if crypt_r uses struct
crypt_data])
+fi
+if test "$ac_cv_crypt_r_style" = "struct_crypt_data_gnu_source"; then
+ APR_ADDTO(CPPFLAGS, [-D_GNU_SOURCE])
+fi
+])
+
+dnl
dnl APR_CHECK_ICONV_INBUF
dnl
dnl Decide whether or not the inbuf parameter to iconv() is const.
1.18 +21 -0 apr/passwd/apr_md5.c
Index: apr_md5.c
===================================================================
RCS file: /home/cvs/apr/passwd/apr_md5.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- apr_md5.c 13 Mar 2002 20:39:26 -0000 1.17
+++ apr_md5.c 10 May 2002 19:10:58 -0000 1.18
@@ -699,7 +699,28 @@
*/
#if defined(WIN32) || defined(BEOS) || defined(NETWARE)
apr_cpystrn(sample, passwd, sizeof(sample) - 1);
+#elif defined(CRYPT_R_CRYPTD)
+ CRYPTD buffer;
+
+ crypt_pw = crypt_r(passwd, hash, &buffer);
+ apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
+#elif defined(CRYPT_R_STRUCT_CRYPT_DATA)
+ struct crypt_data buffer;
+
+ /* having to clear this seems bogus... GNU doc is
+ * confusing... user report found from google says
+ * the crypt_data struct had to be cleared to get
+ * the same result as plain crypt()
+ */
+ memset(&buffer, 0, sizeof(buffer));
+ crypt_pw = crypt_r(passwd, hash, &buffer);
+ apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
#else
+ /* XXX if this is a threaded build, we should hold a mutex
+ * around the next two lines... but note that on some
+ * platforms (e.g., Solaris, HP-UX) crypt() returns a
+ * pointer to thread-specific data
+ */
crypt_pw = crypt(passwd, hash);
apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
#endif