diff options
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | build/apr_common.m4 | 53 | ||||
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | passwd/apr_md5.c | 21 |
4 files changed, 83 insertions, 0 deletions
@@ -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. diff --git a/build/apr_common.m4 b/build/apr_common.m4 index 7ec02223a..876396af2 100644 --- a/build/apr_common.m4 +++ b/build/apr_common.m4 @@ -459,6 +459,59 @@ fi 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. diff --git a/configure.in b/configure.in index c0b293a20..b484e701f 100644 --- a/configure.in +++ b/configure.in @@ -830,6 +830,10 @@ AC_CHECK_FUNCS(strerror_r, [ strerror_r="1" ], [ strerror_r="0" ]) 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 diff --git a/passwd/apr_md5.c b/passwd/apr_md5.c index 2c21eee8e..76a16b494 100644 --- a/passwd/apr_md5.c +++ b/passwd/apr_md5.c @@ -699,7 +699,28 @@ APR_DECLARE(apr_status_t) apr_password_validate(const char *passwd, */ #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 |