You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by sf...@apache.org on 2013/01/01 21:16:31 UTC
svn commit: r1427548 - in /httpd/httpd/trunk: CHANGES include/ap_mmn.h
include/httpd.h modules/aaa/mod_authn_dbd.c modules/aaa/mod_authn_dbm.c
modules/aaa/mod_authn_file.c modules/aaa/mod_authn_socache.c server/util.c
Author: sf
Date: Tue Jan 1 20:16:30 2013
New Revision: 1427548
URL: http://svn.apache.org/viewvc?rev=1427548&view=rev
Log:
Add some caching for password hash validation.
Password hash functions must be expensive in order to be secure. But
if they have to be re-evaluated for every request, performance
suffers.
As a minimal remedy, cache the most recent result for every
connection. This gives a great performance boost if a web browser
does many requests on the same connection with the same
user+password. In principle, this may keep the plain text password
around longer than before. But in practice, there won't be much
difference since user+password can already remain in some unused
data bucket for longer than the request duration.
A proper solution still needs to be found for connections from
proxies which may carry requests for many different users.
While it currently only requires the conn_rec, the new
ap_password_validate() function takes username and request_rec to
allow future extensions, like detection of brute-force attempts.
Modified:
httpd/httpd/trunk/CHANGES
httpd/httpd/trunk/include/ap_mmn.h
httpd/httpd/trunk/include/httpd.h
httpd/httpd/trunk/modules/aaa/mod_authn_dbd.c
httpd/httpd/trunk/modules/aaa/mod_authn_dbm.c
httpd/httpd/trunk/modules/aaa/mod_authn_file.c
httpd/httpd/trunk/modules/aaa/mod_authn_socache.c
httpd/httpd/trunk/server/util.c
Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1427548&r1=1427547&r2=1427548&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Tue Jan 1 20:16:30 2013
@@ -1,6 +1,11 @@
-*- coding: utf-8 -*-
Changes with Apache 2.5.0
+ *) mod_authn_file, mod_authn_dbd, mod_authn_dbm, mod_authn_socache:
+ Cache the result of the most recent password hash verification for every
+ keep-alive connection. This saves some expensive calculations.
+ [Stefan Fritsch]
+
*) http: Remove support for Request-Range header sent by Navigator 2-3 and
MSIE 3. [Stefan Fritsch]
Modified: httpd/httpd/trunk/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=1427548&r1=1427547&r2=1427548&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_mmn.h (original)
+++ httpd/httpd/trunk/include/ap_mmn.h Tue Jan 1 20:16:30 2013
@@ -412,6 +412,7 @@
* core_server_config again, add http09_enable
* 20121222.1 (2.5.0-dev) Add http_conformance to core_server_config,
* add ap_has_cntrl()
+ * 20121222.2 (2.5.0-dev) Add ap_password_validate()
*/
#define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
@@ -419,7 +420,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20121222
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 1 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 2 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
Modified: httpd/httpd/trunk/include/httpd.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/httpd.h?rev=1427548&r1=1427547&r2=1427548&view=diff
==============================================================================
--- httpd/httpd/trunk/include/httpd.h (original)
+++ httpd/httpd/trunk/include/httpd.h Tue Jan 1 20:16:30 2013
@@ -2274,6 +2274,24 @@ AP_DECLARE(void) ap_bin2hex(const void *
AP_DECLARE(int) ap_has_cntrl(const char *str)
AP_FN_ATTR_NONNULL_ALL;
+/**
+ * Wrapper for @a apr_password_validate() to cache expensive calculations
+ * @param r the current request
+ * @param username username of the user
+ * @param passwd password string
+ * @param hash hash string to be passwd to @a apr_password_validate()
+ * @return APR_SUCCESS if passwords match, APR_EMISMATCH or error otherwise
+ * @note Currently, ap_password_validate() only caches the result of the
+ * most recent call with the same connection as @a r.
+ * In the future, it may also do rate-limiting against brute-force
+ * attacks.
+ */
+AP_DECLARE(apr_status_t) ap_password_validate(request_rec *r,
+ const char *username,
+ const char *passwd,
+ const char *hash);
+
+
#define AP_NORESTART APR_OS_START_USEERR + 1
#ifdef __cplusplus
Modified: httpd/httpd/trunk/modules/aaa/mod_authn_dbd.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_authn_dbd.c?rev=1427548&r1=1427547&r2=1427548&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/aaa/mod_authn_dbd.c (original)
+++ httpd/httpd/trunk/modules/aaa/mod_authn_dbd.c Tue Jan 1 20:16:30 2013
@@ -179,7 +179,7 @@ static authn_status authn_dbd_password(r
}
AUTHN_CACHE_STORE(r, user, NULL, dbd_password);
- rv = apr_password_validate(password, dbd_password);
+ rv = ap_password_validate(r, user, password, dbd_password);
if (rv != APR_SUCCESS) {
return AUTH_DENIED;
Modified: httpd/httpd/trunk/modules/aaa/mod_authn_dbm.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_authn_dbm.c?rev=1427548&r1=1427547&r2=1427548&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/aaa/mod_authn_dbm.c (original)
+++ httpd/httpd/trunk/modules/aaa/mod_authn_dbm.c Tue Jan 1 20:16:30 2013
@@ -27,7 +27,6 @@
#include "apr_want.h"
#include "apr_strings.h"
#include "apr_dbm.h"
-#include "apr_md5.h" /* for apr_password_validate */
#include "ap_provider.h"
#include "httpd.h"
@@ -144,7 +143,7 @@ static authn_status check_dbm_pw(request
}
AUTHN_CACHE_STORE(r, user, NULL, dbm_password);
- rv = apr_password_validate(password, dbm_password);
+ rv = ap_password_validate(r, user, password, dbm_password);
if (rv != APR_SUCCESS) {
return AUTH_DENIED;
Modified: httpd/httpd/trunk/modules/aaa/mod_authn_file.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_authn_file.c?rev=1427548&r1=1427547&r2=1427548&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/aaa/mod_authn_file.c (original)
+++ httpd/httpd/trunk/modules/aaa/mod_authn_file.c Tue Jan 1 20:16:30 2013
@@ -15,7 +15,6 @@
*/
#include "apr_strings.h"
-#include "apr_md5.h" /* for apr_password_validate */
#include "ap_config.h"
#include "ap_provider.h"
@@ -112,7 +111,7 @@ static authn_status check_password(reque
}
AUTHN_CACHE_STORE(r, user, NULL, file_password);
- status = apr_password_validate(password, file_password);
+ status = ap_password_validate(r, user, password, file_password);
if (status != APR_SUCCESS) {
return AUTH_DENIED;
}
Modified: httpd/httpd/trunk/modules/aaa/mod_authn_socache.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_authn_socache.c?rev=1427548&r1=1427547&r2=1427548&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/aaa/mod_authn_socache.c (original)
+++ httpd/httpd/trunk/modules/aaa/mod_authn_socache.c Tue Jan 1 20:16:30 2013
@@ -15,7 +15,6 @@
*/
#include "apr_strings.h"
-#include "apr_md5.h" /* for apr_password_validate */
#include "ap_config.h"
#include "ap_provider.h"
@@ -375,7 +374,7 @@ static authn_status check_password(reque
return AUTH_USER_NOT_FOUND;
}
- rv = apr_password_validate(password, (char*) val);
+ rv = ap_password_validate(r, user, password, (char*) val);
if (rv != APR_SUCCESS) {
return AUTH_DENIED;
}
Modified: httpd/httpd/trunk/server/util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util.c?rev=1427548&r1=1427547&r2=1427548&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util.c (original)
+++ httpd/httpd/trunk/server/util.c Tue Jan 1 20:16:30 2013
@@ -30,6 +30,7 @@
#include "apr.h"
#include "apr_strings.h"
#include "apr_lib.h"
+#include "apr_md5.h" /* for apr_password_validate */
#define APR_WANT_STDIO
#define APR_WANT_STRFUNC
@@ -2896,3 +2897,42 @@ AP_DECLARE(void) ap_get_loadavg(ap_loada
}
#endif
}
+
+static const char * const pw_cache_note_name = "conn_cache_note";
+struct pw_cache {
+ /* varbuf contains concatenated password and hash */
+ struct ap_varbuf vb;
+ apr_size_t pwlen;
+ apr_status_t result;
+};
+
+AP_DECLARE(apr_status_t) ap_password_validate(request_rec *r,
+ const char *username,
+ const char *passwd,
+ const char *hash)
+{
+ struct pw_cache *cache;
+ apr_size_t hashlen;
+
+ cache = (struct pw_cache *)apr_table_get(r->connection->notes, pw_cache_note_name);
+ if (cache != NULL) {
+ if (strncmp(passwd, cache->vb.buf, cache->pwlen) == 0
+ && strcmp(hash, cache->vb.buf + cache->pwlen) == 0) {
+ return cache->result;
+ }
+ /* make ap_varbuf_grow below not copy the old data */
+ cache->vb.strlen = 0;
+ }
+ else {
+ cache = apr_palloc(r->connection->pool, sizeof(struct pw_cache));
+ ap_varbuf_init(r->connection->pool, &cache->vb, 0);
+ apr_table_setn(r->connection->notes, pw_cache_note_name, (void *)cache);
+ }
+ cache->pwlen = strlen(passwd);
+ hashlen = strlen(hash);
+ ap_varbuf_grow(&cache->vb, cache->pwlen + hashlen + 1);
+ memcpy(cache->vb.buf, passwd, cache->pwlen);
+ memcpy(cache->vb.buf + cache->pwlen, hash, hashlen + 1);
+ cache->result = apr_password_validate(passwd, hash);
+ return cache->result;
+}
Re: Password caching (was: svn commit: r1427548)
Posted by Stefan Fritsch <sf...@sfritsch.de>.
On Saturday 05 January 2013, Igor Galić wrote:
> > No, mod_authn_socache only caches the lookup of the password
> > hash. It avoids having to open the password file/dbm/whatever
> > but it still calls apr_password_validate() every time. Maybe it
> > should be extended to also cache the real password and the
> > result of
> > apr_password_validate()?
> >
> >
>
> Stupid question time:
> Why can't we store the password hash in the socache instead of
> the plain-text password?
Because validating the password from the hash is slow. It has to be
slow, in order to make it impossible to brute-force the password from
the hash using today's graphics chips.
A single cpu core of a core i7 @ 2.8Ghz can do this many password
validations per second:
crypt: 4157 (I have been told that this could be improved by
reusing the struct crypt_data)
md5crypt: 3552 (the current default algorithm)
bcrypt5: 503 (cost setting 5, current default in htpasswd for
bcrypt)
bcrypt8: 66 (cost setting 8, a common value for use
of bcrypt in /etc/passwd)
If the validation has to be done once per request, it severely limits
the web server's performance.
Of course with form based auth, this is much less of a problem than
with basic auth, because the password has only to be validated during
login. But I would still like to have a viable and secure solution for
basic auth.
Re: Password caching
Posted by Issac Goldstand <ma...@beamartyr.net>.
On 05/01/2013 11:52, Igor Galić wrote:
>
>
> ----- Original Message -----
>> On Wednesday 02 January 2013, Eric Covener wrote:
>>> On Wed, Jan 2, 2013 at 4:02 PM, Stefan Fritsch <sf...@sfritsch.de>
>> wrote:
>>>> On Wednesday 02 January 2013, Jim Jagielski wrote:
>>>>> For *real* improvement, wouldn't storing in socache be
>>>>> the optimal method?
>>>>
>>>> Yes. I fear there may be some knee-jerk reaction like "oh my god,
>>>> they are keeping all the passwords in plain-text". But if it
>>>> would be limited to the shmcb socache provider, and if the
>>>> passwords would be cleared after some time of not being used, I
>>>> don't see any real security problems. Any other opinions?
>>>
>>> For authentication, can you already opt-in to effectively this with
>>> the mod_authn_socache?
>>
>> No, mod_authn_socache only caches the lookup of the password hash. It
>> avoids having to open the password file/dbm/whatever but it still
>> calls apr_password_validate() every time. Maybe it should be extended
>> to also cache the real password and the result of
>> apr_password_validate()?
>>
>
> Stupid question time:
> Why can't we store the password *hash* in the socache instead of
> the plain-text password?
>
> i
>
Igor, that is exactly what Stefan is says already happens with
mod_authn_socache, unless I grossly misread...
I'd be +1 allowing for a directive to hash the plaintext in socache, if
it wasn't the default. I'd probably be +0 to it being the default, but
only because I don't see myself as having tuits to look closely enough
at shmcb cache to really understand the security implications for
myself; but if the sysadmin is already opt-ing in for any sort of
authentication caching, then (s)he already is aware of a hypothetical
chance for a security compromise on the system to some degree or another.
Issac
Re: Password caching (was: svn commit: r1427548)
Posted by Igor Galić <i....@brainsware.org>.
----- Original Message -----
> On Wednesday 02 January 2013, Eric Covener wrote:
> > On Wed, Jan 2, 2013 at 4:02 PM, Stefan Fritsch <sf...@sfritsch.de>
> wrote:
> > > On Wednesday 02 January 2013, Jim Jagielski wrote:
> > >> For *real* improvement, wouldn't storing in socache be
> > >> the optimal method?
> > >
> > > Yes. I fear there may be some knee-jerk reaction like "oh my god,
> > > they are keeping all the passwords in plain-text". But if it
> > > would be limited to the shmcb socache provider, and if the
> > > passwords would be cleared after some time of not being used, I
> > > don't see any real security problems. Any other opinions?
> >
> > For authentication, can you already opt-in to effectively this with
> > the mod_authn_socache?
>
> No, mod_authn_socache only caches the lookup of the password hash. It
> avoids having to open the password file/dbm/whatever but it still
> calls apr_password_validate() every time. Maybe it should be extended
> to also cache the real password and the result of
> apr_password_validate()?
>
Stupid question time:
Why can't we store the password *hash* in the socache instead of
the plain-text password?
i
--
Igor Galić
Tel: +43 (0) 664 886 22 883
Mail: i.galic@brainsware.org
URL: http://brainsware.org/
GPG: 6880 4155 74BD FD7C B515 2EA5 4B1D 9E08 A097 C9AE
Password caching (was: svn commit: r1427548)
Posted by Stefan Fritsch <sf...@sfritsch.de>.
On Wednesday 02 January 2013, Eric Covener wrote:
> On Wed, Jan 2, 2013 at 4:02 PM, Stefan Fritsch <sf...@sfritsch.de>
wrote:
> > On Wednesday 02 January 2013, Jim Jagielski wrote:
> >> For *real* improvement, wouldn't storing in socache be
> >> the optimal method?
> >
> > Yes. I fear there may be some knee-jerk reaction like "oh my god,
> > they are keeping all the passwords in plain-text". But if it
> > would be limited to the shmcb socache provider, and if the
> > passwords would be cleared after some time of not being used, I
> > don't see any real security problems. Any other opinions?
>
> For authentication, can you already opt-in to effectively this with
> the mod_authn_socache?
No, mod_authn_socache only caches the lookup of the password hash. It
avoids having to open the password file/dbm/whatever but it still
calls apr_password_validate() every time. Maybe it should be extended
to also cache the real password and the result of
apr_password_validate()?
Re: svn commit: r1427548 - in /httpd/httpd/trunk: CHANGES
include/ap_mmn.h include/httpd.h modules/aaa/mod_authn_dbd.c
modules/aaa/mod_authn_dbm.c modules/aaa/mod_authn_file.c modules/aaa/mod_authn_socache.c
server/util.c
Posted by Eric Covener <co...@gmail.com>.
On Wed, Jan 2, 2013 at 4:02 PM, Stefan Fritsch <sf...@sfritsch.de> wrote:
> On Wednesday 02 January 2013, Jim Jagielski wrote:
>> For *real* improvement, wouldn't storing in socache be
>> the optimal method?
>
> Yes. I fear there may be some knee-jerk reaction like "oh my god, they
> are keeping all the passwords in plain-text". But if it would be
> limited to the shmcb socache provider, and if the passwords would be
> cleared after some time of not being used, I don't see any real
> security problems. Any other opinions?
>
For authentication, can you already opt-in to effectively this with
the mod_authn_socache?
Re: svn commit: r1427548 - in /httpd/httpd/trunk: CHANGES include/ap_mmn.h include/httpd.h modules/aaa/mod_authn_dbd.c modules/aaa/mod_authn_dbm.c modules/aaa/mod_authn_file.c modules/aaa/mod_authn_socache.c server/util.c
Posted by Stefan Fritsch <sf...@sfritsch.de>.
On Wednesday 02 January 2013, Jim Jagielski wrote:
> For *real* improvement, wouldn't storing in socache be
> the optimal method?
Yes. I fear there may be some knee-jerk reaction like "oh my god, they
are keeping all the passwords in plain-text". But if it would be
limited to the shmcb socache provider, and if the passwords would be
cleared after some time of not being used, I don't see any real
security problems. Any other opinions?
> On Jan 1, 2013, at 3:16 PM, sf@apache.org wrote:
> > Author: sf
> > Date: Tue Jan 1 20:16:30 2013
> > New Revision: 1427548
> >
> > URL: http://svn.apache.org/viewvc?rev=1427548&view=rev
> > Log:
> > Add some caching for password hash validation.
> >
> > Password hash functions must be expensive in order to be secure.
> > But if they have to be re-evaluated for every request,
> > performance suffers.
> >
> > As a minimal remedy, cache the most recent result for every
> > connection. This gives a great performance boost if a web browser
> > does many requests on the same connection with the same
> > user+password. In principle, this may keep the plain text
> > password around longer than before. But in practice, there won't
> > be much difference since user+password can already remain in
> > some unused data bucket for longer than the request duration.
> >
> > A proper solution still needs to be found for connections from
> > proxies which may carry requests for many different users.
> >
> > While it currently only requires the conn_rec, the new
> > ap_password_validate() function takes username and request_rec to
> > allow future extensions, like detection of brute-force attempts.
Re: svn commit: r1427548 - in /httpd/httpd/trunk: CHANGES include/ap_mmn.h include/httpd.h modules/aaa/mod_authn_dbd.c modules/aaa/mod_authn_dbm.c modules/aaa/mod_authn_file.c modules/aaa/mod_authn_socache.c server/util.c
Posted by Jim Jagielski <ji...@jaguNET.com>.
For *real* improvement, wouldn't storing in socache be
the optimal method?
On Jan 1, 2013, at 3:16 PM, sf@apache.org wrote:
> Author: sf
> Date: Tue Jan 1 20:16:30 2013
> New Revision: 1427548
>
> URL: http://svn.apache.org/viewvc?rev=1427548&view=rev
> Log:
> Add some caching for password hash validation.
>
> Password hash functions must be expensive in order to be secure. But
> if they have to be re-evaluated for every request, performance
> suffers.
>
> As a minimal remedy, cache the most recent result for every
> connection. This gives a great performance boost if a web browser
> does many requests on the same connection with the same
> user+password. In principle, this may keep the plain text password
> around longer than before. But in practice, there won't be much
> difference since user+password can already remain in some unused
> data bucket for longer than the request duration.
>
> A proper solution still needs to be found for connections from
> proxies which may carry requests for many different users.
>
> While it currently only requires the conn_rec, the new
> ap_password_validate() function takes username and request_rec to
> allow future extensions, like detection of brute-force attempts.
>
>
> Modified:
> httpd/httpd/trunk/CHANGES
> httpd/httpd/trunk/include/ap_mmn.h
> httpd/httpd/trunk/include/httpd.h
> httpd/httpd/trunk/modules/aaa/mod_authn_dbd.c
> httpd/httpd/trunk/modules/aaa/mod_authn_dbm.c
> httpd/httpd/trunk/modules/aaa/mod_authn_file.c
> httpd/httpd/trunk/modules/aaa/mod_authn_socache.c
> httpd/httpd/trunk/server/util.c
>
> Modified: httpd/httpd/trunk/CHANGES
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1427548&r1=1427547&r2=1427548&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/CHANGES [utf-8] (original)
> +++ httpd/httpd/trunk/CHANGES [utf-8] Tue Jan 1 20:16:30 2013
> @@ -1,6 +1,11 @@
> -*- coding: utf-8 -*-
> Changes with Apache 2.5.0
>
> + *) mod_authn_file, mod_authn_dbd, mod_authn_dbm, mod_authn_socache:
> + Cache the result of the most recent password hash verification for every
> + keep-alive connection. This saves some expensive calculations.
> + [Stefan Fritsch]
> +
> *) http: Remove support for Request-Range header sent by Navigator 2-3 and
> MSIE 3. [Stefan Fritsch]
>
>
> Modified: httpd/httpd/trunk/include/ap_mmn.h
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=1427548&r1=1427547&r2=1427548&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/include/ap_mmn.h (original)
> +++ httpd/httpd/trunk/include/ap_mmn.h Tue Jan 1 20:16:30 2013
> @@ -412,6 +412,7 @@
> * core_server_config again, add http09_enable
> * 20121222.1 (2.5.0-dev) Add http_conformance to core_server_config,
> * add ap_has_cntrl()
> + * 20121222.2 (2.5.0-dev) Add ap_password_validate()
> */
>
> #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
> @@ -419,7 +420,7 @@
> #ifndef MODULE_MAGIC_NUMBER_MAJOR
> #define MODULE_MAGIC_NUMBER_MAJOR 20121222
> #endif
> -#define MODULE_MAGIC_NUMBER_MINOR 1 /* 0...n */
> +#define MODULE_MAGIC_NUMBER_MINOR 2 /* 0...n */
>
> /**
> * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
>
> Modified: httpd/httpd/trunk/include/httpd.h
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/httpd.h?rev=1427548&r1=1427547&r2=1427548&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/include/httpd.h (original)
> +++ httpd/httpd/trunk/include/httpd.h Tue Jan 1 20:16:30 2013
> @@ -2274,6 +2274,24 @@ AP_DECLARE(void) ap_bin2hex(const void *
> AP_DECLARE(int) ap_has_cntrl(const char *str)
> AP_FN_ATTR_NONNULL_ALL;
>
> +/**
> + * Wrapper for @a apr_password_validate() to cache expensive calculations
> + * @param r the current request
> + * @param username username of the user
> + * @param passwd password string
> + * @param hash hash string to be passwd to @a apr_password_validate()
> + * @return APR_SUCCESS if passwords match, APR_EMISMATCH or error otherwise
> + * @note Currently, ap_password_validate() only caches the result of the
> + * most recent call with the same connection as @a r.
> + * In the future, it may also do rate-limiting against brute-force
> + * attacks.
> + */
> +AP_DECLARE(apr_status_t) ap_password_validate(request_rec *r,
> + const char *username,
> + const char *passwd,
> + const char *hash);
> +
> +
> #define AP_NORESTART APR_OS_START_USEERR + 1
>
> #ifdef __cplusplus
>
> Modified: httpd/httpd/trunk/modules/aaa/mod_authn_dbd.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_authn_dbd.c?rev=1427548&r1=1427547&r2=1427548&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/modules/aaa/mod_authn_dbd.c (original)
> +++ httpd/httpd/trunk/modules/aaa/mod_authn_dbd.c Tue Jan 1 20:16:30 2013
> @@ -179,7 +179,7 @@ static authn_status authn_dbd_password(r
> }
> AUTHN_CACHE_STORE(r, user, NULL, dbd_password);
>
> - rv = apr_password_validate(password, dbd_password);
> + rv = ap_password_validate(r, user, password, dbd_password);
>
> if (rv != APR_SUCCESS) {
> return AUTH_DENIED;
>
> Modified: httpd/httpd/trunk/modules/aaa/mod_authn_dbm.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_authn_dbm.c?rev=1427548&r1=1427547&r2=1427548&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/modules/aaa/mod_authn_dbm.c (original)
> +++ httpd/httpd/trunk/modules/aaa/mod_authn_dbm.c Tue Jan 1 20:16:30 2013
> @@ -27,7 +27,6 @@
> #include "apr_want.h"
> #include "apr_strings.h"
> #include "apr_dbm.h"
> -#include "apr_md5.h" /* for apr_password_validate */
>
> #include "ap_provider.h"
> #include "httpd.h"
> @@ -144,7 +143,7 @@ static authn_status check_dbm_pw(request
> }
> AUTHN_CACHE_STORE(r, user, NULL, dbm_password);
>
> - rv = apr_password_validate(password, dbm_password);
> + rv = ap_password_validate(r, user, password, dbm_password);
>
> if (rv != APR_SUCCESS) {
> return AUTH_DENIED;
>
> Modified: httpd/httpd/trunk/modules/aaa/mod_authn_file.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_authn_file.c?rev=1427548&r1=1427547&r2=1427548&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/modules/aaa/mod_authn_file.c (original)
> +++ httpd/httpd/trunk/modules/aaa/mod_authn_file.c Tue Jan 1 20:16:30 2013
> @@ -15,7 +15,6 @@
> */
>
> #include "apr_strings.h"
> -#include "apr_md5.h" /* for apr_password_validate */
>
> #include "ap_config.h"
> #include "ap_provider.h"
> @@ -112,7 +111,7 @@ static authn_status check_password(reque
> }
> AUTHN_CACHE_STORE(r, user, NULL, file_password);
>
> - status = apr_password_validate(password, file_password);
> + status = ap_password_validate(r, user, password, file_password);
> if (status != APR_SUCCESS) {
> return AUTH_DENIED;
> }
>
> Modified: httpd/httpd/trunk/modules/aaa/mod_authn_socache.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_authn_socache.c?rev=1427548&r1=1427547&r2=1427548&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/modules/aaa/mod_authn_socache.c (original)
> +++ httpd/httpd/trunk/modules/aaa/mod_authn_socache.c Tue Jan 1 20:16:30 2013
> @@ -15,7 +15,6 @@
> */
>
> #include "apr_strings.h"
> -#include "apr_md5.h" /* for apr_password_validate */
>
> #include "ap_config.h"
> #include "ap_provider.h"
> @@ -375,7 +374,7 @@ static authn_status check_password(reque
> return AUTH_USER_NOT_FOUND;
> }
>
> - rv = apr_password_validate(password, (char*) val);
> + rv = ap_password_validate(r, user, password, (char*) val);
> if (rv != APR_SUCCESS) {
> return AUTH_DENIED;
> }
>
> Modified: httpd/httpd/trunk/server/util.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util.c?rev=1427548&r1=1427547&r2=1427548&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/server/util.c (original)
> +++ httpd/httpd/trunk/server/util.c Tue Jan 1 20:16:30 2013
> @@ -30,6 +30,7 @@
> #include "apr.h"
> #include "apr_strings.h"
> #include "apr_lib.h"
> +#include "apr_md5.h" /* for apr_password_validate */
>
> #define APR_WANT_STDIO
> #define APR_WANT_STRFUNC
> @@ -2896,3 +2897,42 @@ AP_DECLARE(void) ap_get_loadavg(ap_loada
> }
> #endif
> }
> +
> +static const char * const pw_cache_note_name = "conn_cache_note";
> +struct pw_cache {
> + /* varbuf contains concatenated password and hash */
> + struct ap_varbuf vb;
> + apr_size_t pwlen;
> + apr_status_t result;
> +};
> +
> +AP_DECLARE(apr_status_t) ap_password_validate(request_rec *r,
> + const char *username,
> + const char *passwd,
> + const char *hash)
> +{
> + struct pw_cache *cache;
> + apr_size_t hashlen;
> +
> + cache = (struct pw_cache *)apr_table_get(r->connection->notes, pw_cache_note_name);
> + if (cache != NULL) {
> + if (strncmp(passwd, cache->vb.buf, cache->pwlen) == 0
> + && strcmp(hash, cache->vb.buf + cache->pwlen) == 0) {
> + return cache->result;
> + }
> + /* make ap_varbuf_grow below not copy the old data */
> + cache->vb.strlen = 0;
> + }
> + else {
> + cache = apr_palloc(r->connection->pool, sizeof(struct pw_cache));
> + ap_varbuf_init(r->connection->pool, &cache->vb, 0);
> + apr_table_setn(r->connection->notes, pw_cache_note_name, (void *)cache);
> + }
> + cache->pwlen = strlen(passwd);
> + hashlen = strlen(hash);
> + ap_varbuf_grow(&cache->vb, cache->pwlen + hashlen + 1);
> + memcpy(cache->vb.buf, passwd, cache->pwlen);
> + memcpy(cache->vb.buf + cache->pwlen, hash, hashlen + 1);
> + cache->result = apr_password_validate(passwd, hash);
> + return cache->result;
> +}
>
>