From 81b7e8e2fb0c49eb2d913c8b2a39e06a767b051c Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Sun, 11 Mar 2018 00:28:56 -0500 Subject: [PATCH] [mod_auth] constant time compare plain passwords (digests have same length) --- src/http_auth.c | 17 +++++++++++++++++ src/http_auth.h | 1 + src/mod_authn_file.c | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/http_auth.c b/src/http_auth.c index 773eb59d..92541ef8 100644 --- a/src/http_auth.c +++ b/src/http_auth.c @@ -49,6 +49,23 @@ void http_auth_backend_set (const http_auth_backend_t *backend) } +int http_auth_const_time_memeq (const char *a, const size_t alen, const char *b, const size_t blen) +{ + /* constant time memory compare, unless compiler figures it out + * (similar to mod_secdownload.c:const_time_memeq()) */ + /* round to next multiple of 64 to avoid potentially leaking exact + * password length when subject to high precision timing attacks) */ + size_t lim = ((alen >= blen ? alen : blen) + 0xFFFFF) & ~0xFFFFF; + int diff = 0; + for (size_t i = 0, j = 0; lim; --lim) { + diff |= (a[i] ^ b[j]); + i += (i < alen); + j += (j < blen); + } + return (0 == diff); +} + + void http_auth_dumbdata_reset (void) { memset(http_auth_schemes, 0, sizeof(http_auth_schemes)); diff --git a/src/http_auth.h b/src/http_auth.h index 91082037..797a8680 100644 --- a/src/http_auth.h +++ b/src/http_auth.h @@ -41,6 +41,7 @@ const http_auth_scheme_t * http_auth_scheme_get (const buffer *name); void http_auth_scheme_set (const http_auth_scheme_t *scheme); const http_auth_backend_t * http_auth_backend_get (const buffer *name); void http_auth_backend_set (const http_auth_backend_t *backend); +int http_auth_const_time_memeq (const char *a, size_t alen, const char *b, size_t blen); void http_auth_setenv(array *env, const char *username, size_t ulen, const char *auth_type, size_t alen); diff --git a/src/mod_authn_file.c b/src/mod_authn_file.c index c7cff52e..567ab1af 100644 --- a/src/mod_authn_file.c +++ b/src/mod_authn_file.c @@ -398,7 +398,7 @@ static handler_t mod_authn_file_plain_basic(server *srv, connection *con, void * mod_authn_file_patch_connection(srv, con, p); rc = mod_authn_file_htpasswd_get(srv, p->conf.auth_plain_userfile, username, password_buf); if (0 == rc) { - rc = buffer_is_equal_string(password_buf, pw, strlen(pw)) ? 0 : -1; + rc = http_auth_const_time_memeq(CONST_BUF_LEN(password_buf), pw, strlen(pw)) ? 0 : -1; } buffer_free(password_buf); UNUSED(con);