apr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s.@apache.org
Subject svn commit: r1358137 - in /apr/apr-util/branches/1.5.x: ./ CHANGES build.conf crypto/apr_md5.c crypto/apr_passwd.c crypto/crypt_blowfish.c crypto/crypt_blowfish.h include/apr_md5.h test/testpass.c test/testutil.c test/testutil.h
Date Fri, 06 Jul 2012 11:41:24 GMT
Author: sf
Date: Fri Jul  6 11:41:24 2012
New Revision: 1358137

URL: http://svn.apache.org/viewvc?rev=1358137&view=rev
Log:
Merge r1357761,1357772,1357780,1357966,1357968,1357979 from ARP trunk:

    Add support for bcrypt encoded passwords.
    
    The bcrypt implementation uses code from crypt_blowfish written by Solar
    Designer <solar openwall com>. The x86 assembler implementation is not used
    becaused it did not result in significant speed-up on my system.
    
    apr_bcrypt_encode creates hashes with "$2y$" prefix, but
    apr_password_validate also accepts the old prefix "$2a$".
    
    * crypto/crypt_blowfish.[ch]: Imported from crypt_blowfish 1.2. The only
      change compared to the upstream version is setting BF_ASM to 0.
    
    * crypto/apr_passwd.c: Add bcrypt support to apr_password_validate, add
      apr_bcrypt_encode
    
    * test/testpass.c: Add new tests, for bcrypt and the old schemes.
    
    * include/apr_md5.h: apr_password_validate() is left here fore backward
      compatibility and apr_bcrypt_encode() is added here as well.

    
    Move non-MD5-related things from apr_md5.c to new file apr_passwd.c

    
    Add an APR_ASSERT_FAILURE macro for tests that must fail


Added:
    apr/apr-util/branches/1.5.x/crypto/apr_passwd.c
      - copied, changed from r1357772, apr/apr/trunk/crypto/apr_passwd.c
    apr/apr-util/branches/1.5.x/crypto/crypt_blowfish.c
      - copied unchanged from r1357780, apr/apr/trunk/crypto/crypt_blowfish.c
    apr/apr-util/branches/1.5.x/crypto/crypt_blowfish.h
      - copied unchanged from r1357780, apr/apr/trunk/crypto/crypt_blowfish.h
Modified:
    apr/apr-util/branches/1.5.x/   (props changed)
    apr/apr-util/branches/1.5.x/CHANGES
    apr/apr-util/branches/1.5.x/build.conf
    apr/apr-util/branches/1.5.x/crypto/apr_md5.c
    apr/apr-util/branches/1.5.x/include/apr_md5.h
    apr/apr-util/branches/1.5.x/test/testpass.c
    apr/apr-util/branches/1.5.x/test/testutil.c
    apr/apr-util/branches/1.5.x/test/testutil.h

Propchange: apr/apr-util/branches/1.5.x/
------------------------------------------------------------------------------
  Merged /apr/apr/trunk:r1357761,1357772,1357780,1357966,1357968,1357979

Modified: apr/apr-util/branches/1.5.x/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.5.x/CHANGES?rev=1358137&r1=1358136&r2=1358137&view=diff
==============================================================================
--- apr/apr-util/branches/1.5.x/CHANGES [utf-8] (original)
+++ apr/apr-util/branches/1.5.x/CHANGES [utf-8] Fri Jul  6 11:41:24 2012
@@ -1,6 +1,11 @@
                                                      -*- coding: utf-8 -*-
 Changes with APR-util 1.5.0
 
+  *) apr_password_validate, apr_bcrypt_encode: Add support for bcrypt encoded
+     passwords. The bcrypt implementation uses code from crypt_blowfish
+     written by Solar Designer <solar openwall com>. apr_bcrypt_encode creates
+     hashes with "$2y$" prefix, but apr_password_validate also accepts the old
+     prefix "$2a$". [Stefan Fritsch]
 
 Changes with APR-util 1.4.0
 

Modified: apr/apr-util/branches/1.5.x/build.conf
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.5.x/build.conf?rev=1358137&r1=1358136&r2=1358137&view=diff
==============================================================================
--- apr/apr-util/branches/1.5.x/build.conf (original)
+++ apr/apr-util/branches/1.5.x/build.conf Fri Jul  6 11:41:24 2012
@@ -10,9 +10,11 @@ paths =
   crypto/apr_crypto.c
   crypto/apr_md4.c
   crypto/apr_md5.c
+  crypto/apr_passwd.c
   crypto/apr_sha1.c
   crypto/getuuid.c
   crypto/uuid.c
+  crypto/crypt_blowfish.c
   dbm/apr_dbm_sdbm.c
   dbm/apr_dbm.c
   dbm/sdbm/*.c

Modified: apr/apr-util/branches/1.5.x/crypto/apr_md5.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.5.x/crypto/apr_md5.c?rev=1358137&r1=1358136&r2=1358137&view=diff
==============================================================================
--- apr/apr-util/branches/1.5.x/crypto/apr_md5.c (original)
+++ apr/apr-util/branches/1.5.x/crypto/apr_md5.c Fri Jul  6 11:41:24 2012
@@ -61,20 +61,10 @@
 #include "apr_md5.h"
 #include "apr_lib.h"
 #include "apu_config.h"
-#include "apr_sha1.h"
 
 #if APR_HAVE_STRING_H
 #include <string.h>
 #endif
-#if APR_HAVE_CRYPT_H
-#include <crypt.h>
-#endif
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if APR_HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
 
 /* Constants for MD5Transform routine.
  */
@@ -478,7 +468,7 @@ APU_DECLARE(apr_status_t) apr_MD5InitEBC
  * Define the Magic String prefix that identifies a password as being
  * hashed using our algorithm.
  */
-static const char *apr1_id = "$apr1$";
+static const char const *apr1_id = "$apr1$";
 
 /*
  * The following MD5 password encryption code was largely borrowed from
@@ -660,110 +650,3 @@ APU_DECLARE(apr_status_t) apr_md5_encode
     apr_cpystrn(result, passwd, nbytes - 1);
     return APR_SUCCESS;
 }
-
-#if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
-#if defined(APU_CRYPT_THREADSAFE) || !APR_HAS_THREADS || \
-    defined(CRYPT_R_CRYPTD) || defined(CRYPT_R_STRUCT_CRYPT_DATA)
-
-#define crypt_mutex_lock()
-#define crypt_mutex_unlock()
-
-#elif APR_HAVE_PTHREAD_H && defined(PTHREAD_MUTEX_INITIALIZER)
-
-static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
-static void crypt_mutex_lock(void)
-{
-    pthread_mutex_lock(&crypt_mutex);
-}
-
-static void crypt_mutex_unlock(void)
-{
-    pthread_mutex_unlock(&crypt_mutex);
-}
-
-#else
-
-#error apr_password_validate() is not threadsafe.  rebuild APR without thread support.
-
-#endif
-#endif
-
-/*
- * Validate a plaintext password against a smashed one.  Uses either
- * crypt() (if available) or apr_md5_encode() or apr_sha1_base64(), depending
- * upon the format of the smashed input password.  Returns APR_SUCCESS if
- * they match, or APR_EMISMATCH if they don't.  If the platform doesn't
- * support crypt, then the default check is against a clear text string.
- */
-APU_DECLARE(apr_status_t) apr_password_validate(const char *passwd, 
-                                                const char *hash)
-{
-    char sample[120];
-#if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
-    char *crypt_pw;
-#endif
-    if (!strncmp(hash, apr1_id, strlen(apr1_id))) {
-        /*
-         * The hash was created using our custom algorithm.
-         */
-        apr_md5_encode(passwd, hash, sample, sizeof(sample));
-    }
-    else if (!strncmp(hash, APR_SHA1PW_ID, APR_SHA1PW_IDLEN)) {
-         apr_sha1_base64(passwd, (int)strlen(passwd), sample);
-    }
-    else {
-        /*
-         * It's not our algorithm, so feed it to crypt() if possible.
-         */
-#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);
-        if (!crypt_pw) {
-            return APR_EMISMATCH;
-        }
-        apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
-#elif defined(CRYPT_R_STRUCT_CRYPT_DATA)
-        struct crypt_data buffer;
-
-#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2,4)
-        buffer.initialized = 0;
-#else
-        /*
-         * glibc before 2.3.2 had a bug that required clearing the
-         * whole struct
-         */
-        memset(&buffer, 0, sizeof(buffer));
-#endif
-        crypt_pw = crypt_r(passwd, hash, &buffer);
-        if (!crypt_pw) {
-            return APR_EMISMATCH;
-        }
-        apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
-#else
-        /* Do a bit of sanity checking since we know that crypt_r()
-         * should always be used for threaded builds on AIX, and
-         * problems in configure logic can result in the wrong
-         * choice being made.
-         */
-#if defined(_AIX) && APR_HAS_THREADS
-#error Configuration error!  crypt_r() should have been selected!
-#endif
-
-        /* Handle thread safety issues by holding a mutex around the
-         * call to crypt().
-         */
-        crypt_mutex_lock();
-        crypt_pw = crypt(passwd, hash);
-        if (!crypt_pw) {
-            crypt_mutex_unlock();
-            return APR_EMISMATCH;
-        }
-        apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
-        crypt_mutex_unlock();
-#endif
-    }
-    return (strcmp(sample, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
-}

Copied: apr/apr-util/branches/1.5.x/crypto/apr_passwd.c (from r1357772, apr/apr/trunk/crypto/apr_passwd.c)
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.5.x/crypto/apr_passwd.c?p2=apr/apr-util/branches/1.5.x/crypto/apr_passwd.c&p1=apr/apr/trunk/crypto/apr_passwd.c&r1=1357772&r2=1358137&rev=1358137&view=diff
==============================================================================
--- apr/apr/trunk/crypto/apr_passwd.c (original)
+++ apr/apr-util/branches/1.5.x/crypto/apr_passwd.c Fri Jul  6 11:41:24 2012
@@ -17,8 +17,8 @@
 #include "apr_strings.h"
 #include "apr_md5.h"
 #include "apr_lib.h"
-#include "apr_private.h"
 #include "apr_sha1.h"
+#include "crypt_blowfish.h"
 
 #if APR_HAVE_STRING_H
 #include <string.h>
@@ -55,32 +55,6 @@ static void crypt_mutex_unlock(void)
     pthread_mutex_unlock(&crypt_mutex);
 }
 
-#elif defined(OS2)
-
-static HMTX crypt_mutex = 0;
-static void crypt_mutex_lock()
-{
-    if (crypt_mutex == 0) {
-        /* Prevent race condition where two threads could try to create the
-         * mutex concurrently
-         */
-        DosEnterCritSec();
-
-        if (crypt_mutex == 0) {
-            DosCreateMutexSem(NULL, &crypt_mutex, 0, FALSE);
-        }
-
-        DosExitCritSec();
-    }
-
-    DosRequestMutexSem(crypt_mutex, SEM_INDEFINITE_WAIT);
-}
-
-static void crypt_mutex_unlock()
-{
-    DosReleaseMutexSem(crypt_mutex);
-}
-
 #else
 
 #error apr_password_validate() is not threadsafe.  rebuild APR without thread support.
@@ -95,18 +69,26 @@ static void crypt_mutex_unlock()
  * they match, or APR_EMISMATCH if they don't.  If the platform doesn't
  * support crypt, then the default check is against a clear text string.
  */
-APR_DECLARE(apr_status_t) apr_password_validate(const char *passwd, 
+APU_DECLARE(apr_status_t) apr_password_validate(const char *passwd, 
                                                 const char *hash)
 {
     char sample[120];
 #if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
     char *crypt_pw;
 #endif
-    if (!strncmp(hash, apr1_id, strlen(apr1_id))) {
-        /*
-         * The hash was created using our custom algorithm.
-         */
-        apr_md5_encode(passwd, hash, sample, sizeof(sample));
+    if (hash[0] == '$') {
+        if (hash[1] == '2' && (hash[2] == 'a' || hash[2] == 'y')
+            && hash[3] == '$')
+        {
+            if (_crypt_blowfish_rn(passwd, hash, sample, sizeof(sample)) == NULL)
+                return APR_FROM_OS_ERROR(errno);
+        }
+        else if (!strncmp(hash, apr1_id, strlen(apr1_id))) {
+            /*
+             * The hash was created using our custom algorithm.
+             */
+            apr_md5_encode(passwd, hash, sample, sizeof(sample));
+        }
     }
     else if (!strncmp(hash, APR_SHA1PW_ID, APR_SHA1PW_IDLEN)) {
          apr_sha1_base64(passwd, (int)strlen(passwd), sample);
@@ -167,3 +149,19 @@ APR_DECLARE(apr_status_t) apr_password_v
     }
     return (strcmp(sample, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
 }
+
+static const char const *bcrypt_id = "$2y$";
+APU_DECLARE(apr_status_t) apr_bcrypt_encode(const char *pw,
+                                            unsigned int count,
+                                            const unsigned char *salt,
+                                            apr_size_t salt_len,
+                                            char *out, apr_size_t out_len)
+{
+    char setting[40];
+    if (_crypt_gensalt_blowfish_rn(bcrypt_id, count, (const char *)salt,
+                                   salt_len, setting, sizeof(setting)) == NULL)
+        return APR_FROM_OS_ERROR(errno);
+    if (_crypt_blowfish_rn(pw, setting, out, out_len) == NULL)
+        return APR_FROM_OS_ERROR(errno);
+    return APR_SUCCESS;
+}

Modified: apr/apr-util/branches/1.5.x/include/apr_md5.h
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.5.x/include/apr_md5.h?rev=1358137&r1=1358136&r2=1358137&view=diff
==============================================================================
--- apr/apr-util/branches/1.5.x/include/apr_md5.h (original)
+++ apr/apr-util/branches/1.5.x/include/apr_md5.h Fri Jul  6 11:41:24 2012
@@ -132,16 +132,30 @@ APU_DECLARE(apr_status_t) apr_md5(unsign
 /**
  * Encode a password using an MD5 algorithm
  * @param password The password to encode
- * @param salt The salt to use for the encoding
+ * @param salt The salt string to use for the encoding
  * @param result The string to store the encoded password in
  * @param nbytes The size of the result buffer
  */
 APU_DECLARE(apr_status_t) apr_md5_encode(const char *password, const char *salt,
                                          char *result, apr_size_t nbytes);
 
+/**
+ * Encode a password using the bcrypt algorithm
+ * @param password The password to encode
+ * @param count The cost of the encoding, possible values are 4 to 31
+ * @param salt Pointer to binary data to be used as salt for the encoding
+ * @param salt_len The size of the salt data (must be >= 16)
+ * @param out The string to store the encoded password in
+ * @param out_len The size of the result buffer (must be >= 61)
+ */
+APU_DECLARE(apr_status_t) apr_bcrypt_encode(const char *pw,
+                                            unsigned int count,
+                                            const unsigned char *salt,
+                                            apr_size_t salt_len,
+                                            char *out, apr_size_t out_len);
 
 /**
- * Validate hashes created by APR-supported algorithms: md5 and sha1.
+ * Validate hashes created by APR-supported algorithms: md5, bcrypt, and sha1.
  * hashes created by crypt are supported only on platforms that provide
  * crypt(3), so don't rely on that function unless you know that your
  * application will be run only on platforms that support it.  On platforms

Modified: apr/apr-util/branches/1.5.x/test/testpass.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.5.x/test/testpass.c?rev=1358137&r1=1358136&r2=1358137&view=diff
==============================================================================
--- apr/apr-util/branches/1.5.x/test/testpass.c (original)
+++ apr/apr-util/branches/1.5.x/test/testpass.c Fri Jul  6 11:41:24 2012
@@ -117,25 +117,53 @@ static void test_threadsafe(abts_case *t
 static void test_shapass(abts_case *tc, void *data)
 {
     const char *pass = "hellojed";
+    const char *pass2 = "hellojed2";
     char hash[100];
 
     apr_sha1_base64(pass, strlen(pass), hash);
 
     apr_assert_success(tc, "SHA1 password validated",
                        apr_password_validate(pass, hash));
+    APR_ASSERT_FAILURE(tc, "wrong SHA1 password should not validate",
+                       apr_password_validate(pass2, hash));
 }
 
 static void test_md5pass(abts_case *tc, void *data)
 {
     const char *pass = "hellojed", *salt = "sardine";
+    const char *pass2 = "hellojed2";
     char hash[100];
 
     apr_md5_encode(pass, salt, hash, sizeof hash);
 
     apr_assert_success(tc, "MD5 password validated",
                        apr_password_validate(pass, hash));
+    APR_ASSERT_FAILURE(tc, "wrong MD5 password should not validate",
+                       apr_password_validate(pass2, hash));
 }
 
+static void test_bcryptpass(abts_case *tc, void *data)
+{
+    const char *pass = "hellojed";
+    const char *pass2 = "hellojed2";
+    unsigned char salt[] = "sardine_sardine";
+    char hash[100];
+    const char *hash2 = "$2a$08$qipUJiI9fySUN38hcbz.lucXvAmtgowKOWYtB9y3CXyl6lTknruou";
+    const char *pass3 = "foobar";
+
+    apr_assert_success(tc, "bcrypt encode password", 
+                       apr_bcrypt_encode(pass, 5, salt, sizeof(salt), hash,
+                                         sizeof(hash)));
+
+    apr_assert_success(tc, "bcrypt password validated",
+                       apr_password_validate(pass, hash));
+    APR_ASSERT_FAILURE(tc, "wrong bcrypt password should not validate",
+                       apr_password_validate(pass2, hash));
+    apr_assert_success(tc, "bcrypt password validated",
+                       apr_password_validate(pass3, hash2));
+}
+
+
 abts_suite *testpass(abts_suite *suite)
 {
     suite = ADD_SUITE(suite);
@@ -148,6 +176,7 @@ abts_suite *testpass(abts_suite *suite)
 #endif /* CRYPT_ALGO_SUPPORTED */
     abts_run_test(suite, test_shapass, NULL);
     abts_run_test(suite, test_md5pass, NULL);
+    abts_run_test(suite, test_bcryptpass, NULL);
     
     return suite;
 }

Modified: apr/apr-util/branches/1.5.x/test/testutil.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.5.x/test/testutil.c?rev=1358137&r1=1358136&r2=1358137&view=diff
==============================================================================
--- apr/apr-util/branches/1.5.x/test/testutil.c (original)
+++ apr/apr-util/branches/1.5.x/test/testutil.c Fri Jul  6 11:41:24 2012
@@ -37,6 +37,18 @@ void apr_assert_success(abts_case* tc, c
     }
 }
 
+void apr_assert_failure(abts_case* tc, const char* context, apr_status_t rv,
+                        int lineno)
+{
+    if (rv == APR_ENOTIMPL) {
+        abts_not_impl(tc, context, lineno);
+    } else if (rv == APR_SUCCESS) {
+        char buf[STRING_MAX];
+        sprintf(buf, "%s (%d): expected failure, got success\n", context, rv);
+        abts_fail(tc, buf, lineno);
+    }
+}
+
 void initialize(void) {
     if (apr_initialize() != APR_SUCCESS) {
         abort();

Modified: apr/apr-util/branches/1.5.x/test/testutil.h
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.5.x/test/testutil.h?rev=1358137&r1=1358136&r2=1358137&view=diff
==============================================================================
--- apr/apr-util/branches/1.5.x/test/testutil.h (original)
+++ apr/apr-util/branches/1.5.x/test/testutil.h Fri Jul  6 11:41:24 2012
@@ -41,6 +41,12 @@ extern apr_pool_t *p;
  * for RV and CONTEXT message. */
 void apr_assert_success(abts_case* tc, const char *context, apr_status_t rv);
 
+void apr_assert_failure(abts_case* tc, const char *context,
+                        apr_status_t rv, int lineno);
+#define APR_ASSERT_FAILURE(tc, ctxt, rv) \
+             apr_assert_failure(tc, ctxt, rv, __LINE__)
+
+
 void initialize(void);
 
 abts_suite *teststrmatch(abts_suite *suite);



Mime
View raw message