diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c index 705179fb9c..0340a4d320 100644 --- a/src/auth/auth-request.c +++ b/src/auth/auth-request.c @@ -950,6 +950,7 @@ void auth_request_verify_plain_callback(enum passdb_result result, &result, TRUE)) { auth_request_log_info(request, AUTH_SUBSYS_DB, "Falling back to expired data from cache"); + return; } } @@ -1098,7 +1099,6 @@ void auth_request_verify_plain_continue(struct auth_request *request, cache_key = passdb_cache == NULL ? NULL : passdb->cache_key; if (passdb_cache_verify_plain(request, cache_key, password, &result, FALSE)) { - auth_request_verify_plain_callback_finish(result, request); return; } diff --git a/src/auth/auth-settings.c b/src/auth/auth-settings.c index bf5667f6f3..53a4fec5e4 100644 --- a/src/auth/auth-settings.c +++ b/src/auth/auth-settings.c @@ -230,6 +230,7 @@ static const struct setting_define auth_setting_defines[] = { DEF(SET_SIZE, cache_size), DEF(SET_TIME, cache_ttl), DEF(SET_TIME, cache_negative_ttl), + DEF(SET_BOOL, cache_verify_password_with_worker), DEF(SET_STR, username_chars), DEF(SET_STR, username_translation), DEF(SET_STR, username_format), @@ -284,6 +285,7 @@ static const struct auth_settings auth_default_settings = { .cache_size = 0, .cache_ttl = 60*60, .cache_negative_ttl = 60*60, + .cache_verify_password_with_worker = FALSE, .username_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@", .username_translation = "", .username_format = "%Lu", diff --git a/src/auth/auth-settings.h b/src/auth/auth-settings.h index 3c69a6733d..07ade86a62 100644 --- a/src/auth/auth-settings.h +++ b/src/auth/auth-settings.h @@ -44,6 +44,7 @@ struct auth_settings { uoff_t cache_size; unsigned int cache_ttl; unsigned int cache_negative_ttl; + bool cache_verify_password_with_worker; const char *username_chars; const char *username_translation; const char *username_format; diff --git a/src/auth/passdb-cache.c b/src/auth/passdb-cache.c index f85ca1dd94..dc52350c03 100644 --- a/src/auth/passdb-cache.c +++ b/src/auth/passdb-cache.c @@ -1,12 +1,15 @@ /* Copyright (c) 2004-2018 Dovecot authors, see the included COPYING file */ #include "auth-common.h" +#include "str.h" #include "strescape.h" #include "restrict-process-size.h" #include "auth-request-stats.h" +#include "auth-worker-server.h" #include "password-scheme.h" #include "passdb.h" #include "passdb-cache.h" +#include "passdb-blocking.h" struct auth_cache *passdb_cache = NULL; @@ -50,6 +53,17 @@ passdb_cache_lookup(struct auth_request *request, const char *key, return TRUE; } +static bool passdb_cache_verify_plain_callback(const char *reply, void *context) +{ + struct auth_request *request = context; + enum passdb_result result; + + result = passdb_blocking_auth_worker_reply_parse(request, reply); + auth_request_verify_plain_callback_finish(result, request); + auth_request_unref(&request); + return TRUE; +} + bool passdb_cache_verify_plain(struct auth_request *request, const char *key, const char *password, enum passdb_result *result_r, bool use_expired) @@ -70,6 +84,7 @@ bool passdb_cache_verify_plain(struct auth_request *request, const char *key, /* negative cache entry */ auth_request_log_unknown_user(request, AUTH_SUBSYS_DB); *result_r = PASSDB_RESULT_USER_UNKNOWN; + auth_request_verify_plain_callback_finish(*result_r, request); return TRUE; } @@ -81,6 +96,23 @@ bool passdb_cache_verify_plain(struct auth_request *request, const char *key, auth_request_log_info(request, AUTH_SUBSYS_DB, "Cached NULL password access"); ret = 1; + } else if (request->set->cache_verify_password_with_worker) { + string_t *str; + + str = t_str_new(128); + str_printfa(str, "PASSW\t%u\t", request->passdb->passdb->id); + str_append_tabescaped(str, password); + str_append_c(str, '\t'); + str_append_tabescaped(str, cached_pw); + str_append_c(str, '\t'); + auth_request_export(request, str); + + auth_request_log_debug(request, AUTH_SUBSYS_DB, "cache: " + "validating password on worker"); + auth_request_ref(request); + auth_worker_call(request->pool, request->user, str_c(str), + passdb_cache_verify_plain_callback, request); + return TRUE; } else { scheme = password_get_scheme(&cached_pw); i_assert(scheme != NULL); @@ -106,6 +138,8 @@ bool passdb_cache_verify_plain(struct auth_request *request, const char *key, *result_r = ret > 0 ? PASSDB_RESULT_OK : PASSDB_RESULT_PASSWORD_MISMATCH; + + auth_request_verify_plain_callback_finish(*result_r, request); return TRUE; }