# HG changeset patch # User Timo Sirainen # Date 1098325389 -10800 # Node ID 54b29901a79381b97a40ec6cf7e09fbd405c4121 # Parent 322b580e0eb4c73ab1f945321e4a3d69078272c2 Added simple LRU cache for auth requests. Currently only for sql passdb. diff -r 322b580e0eb4 -r 54b29901a793 dovecot-example.conf --- a/dovecot-example.conf Thu Oct 21 02:34:34 2004 +0300 +++ b/dovecot-example.conf Thu Oct 21 05:23:09 2004 +0300 @@ -468,6 +468,12 @@ # Set max. process size in megabytes. #auth_process_size = 256 +# Authentication cache size in kilobytes. +#auth_cache_size = 0 +# Time to live in seconds for cached data. After this many seconds a cached +# record is forced out of cache. +#auth_cache_ttl = 3600 + # Space separated list of realms for SASL authentication mechanisms that need # them. You can leave it empty if you don't want to support multiple realms. # Many clients simply use the first one listed here, so keep the default realm diff -r 322b580e0eb4 -r 54b29901a793 src/auth/Makefile.am --- a/src/auth/Makefile.am Thu Oct 21 02:34:34 2004 +0300 +++ b/src/auth/Makefile.am Thu Oct 21 05:23:09 2004 +0300 @@ -32,6 +32,7 @@ $(MODULE_LIBS) dovecot_auth_SOURCES = \ + auth-cache.c \ auth-client-connection.c \ auth-master-connection.c \ auth-module.c \ @@ -50,6 +51,7 @@ mech-apop.c \ passdb.c \ passdb-bsdauth.c \ + passdb-cache.c \ passdb-ldap.c \ passdb-passwd.c \ passdb-passwd-file.c \ @@ -67,6 +69,7 @@ userdb-sql.c noinst_HEADERS = \ + auth-cache.h \ auth-client-connection.h \ auth-client-interface.h \ auth-master-interface.h \ @@ -79,6 +82,7 @@ mech.h \ mycrypt.h \ passdb.h \ + passdb-cache.h \ password-scheme.h \ userdb.h \ userdb-vpopmail.h diff -r 322b580e0eb4 -r 54b29901a793 src/auth/auth-cache.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/auth-cache.c Thu Oct 21 05:23:09 2004 +0300 @@ -0,0 +1,181 @@ +/* Copyright (C) 2004 Timo Sirainen */ + +#include "common.h" +#include "hash.h" +#include "str.h" +#include "strescape.h" +#include "var-expand.h" +#include "mech.h" +#include "auth-cache.h" + +#include + +struct cache_node { + struct cache_node *prev, *next; + time_t created; + uint32_t alloc_size; + char data[4]; /* key \0 value \0 */ +}; + +struct auth_cache { + struct hash_table *hash; + struct cache_node *head, *tail; + + size_t size_left; + unsigned int ttl_secs; +}; + +char *auth_cache_parse_key(const char *query) +{ + string_t *str; + + str = str_new(default_pool, 32); + for (; *query != '\0'; query++) { + if (*query == '%' && query[1] != '\0') { + query++; + if (*query != '%') { + if (str_len(str) != 0) + str_append_c(str, '\t'); + str_append_c(str, '%'); + str_append_c(str, *query); + } + } + } + return str_c_modifyable(str); +} + +static void +auth_cache_node_unlink(struct auth_cache *cache, struct cache_node *node) +{ + if (node->prev != NULL) + node->prev->next = node->next; + else { + /* unlinking tail */ + cache->tail = node->next; + } + + if (node->next != NULL) + node->next->prev = node->prev; + else { + /* unlinking head */ + cache->head = node->prev; + } +} + +static void +auth_cache_node_link_head(struct auth_cache *cache, struct cache_node *node) +{ + node->prev = cache->head; + cache->head = node; + if (node->prev != NULL) + node->prev->next = node; + else + cache->tail = node; +} + +static void +auth_cache_node_destroy(struct auth_cache *cache, struct cache_node *node) +{ + auth_cache_node_unlink(cache, node); + + cache->size_left += node->alloc_size; + hash_remove(cache->hash, node->data); + i_free(node); +} + +struct auth_cache *auth_cache_new(size_t max_size, unsigned int ttl_secs) +{ + struct auth_cache *cache; + + cache = i_new(struct auth_cache, 1); + cache->hash = hash_create(default_pool, default_pool, 0, str_hash, + (hash_cmp_callback_t *)strcmp); + cache->size_left = max_size; + cache->ttl_secs = ttl_secs; + return cache; +} + +void auth_cache_free(struct auth_cache *cache) +{ + auth_cache_clear(cache); + hash_destroy(cache->hash); + i_free(cache); +} + +void auth_cache_clear(struct auth_cache *cache) +{ + while (cache->tail != NULL) + auth_cache_node_destroy(cache, cache->tail); + hash_clear(cache->hash, FALSE); +} + +const char *auth_cache_lookup(struct auth_cache *cache, + const struct auth_request *request, + const char *key) +{ + string_t *str; + struct cache_node *node; + + str = t_str_new(256); + var_expand(str, key, + auth_request_get_var_expand_table(request, str_escape)); + + node = hash_lookup(cache->hash, str_c(str)); + if (node == NULL) + return NULL; + + if (node->created < time(NULL) - (time_t)cache->ttl_secs) { + /* TTL expired, destroy */ + auth_cache_node_destroy(cache, node); + return NULL; + } + + /* move to head */ + if (node != cache->head) { + auth_cache_node_unlink(cache, node); + auth_cache_node_link_head(cache, node); + } + + return node->data + strlen(node->data) + 1; +} + +void auth_cache_insert(struct auth_cache *cache, + const struct auth_request *request, + const char *key, const char *value) +{ + string_t *str; + time_t now, ttl_time; + struct cache_node *node; + size_t data_size, alloc_size, value_len = strlen(value); + + now = time(NULL); + + str = t_str_new(256); + var_expand(str, key, + auth_request_get_var_expand_table(request, str_escape)); + + data_size = str_len(str) + 1 + value_len + 1; + alloc_size = sizeof(struct cache_node) - sizeof(node->data) + data_size; + + ttl_time = now - cache->ttl_secs; + while (cache->tail != NULL && cache->tail->created < ttl_time) { + /* TTL expired, destroy */ + auth_cache_node_destroy(cache, cache->tail); + } + + /* make sure we have enough space */ + while (cache->size_left < alloc_size) + auth_cache_node_destroy(cache, cache->tail); + + /* @UNSAFE */ + node = i_malloc(alloc_size); + node->created = now; + node->alloc_size = alloc_size; + memcpy(node->data, str_data(str), str_len(str)); + memcpy(node->data + str_len(str) + 1, value, value_len); + + auth_cache_node_link_head(cache, node); + + cache->size_left -= alloc_size; + hash_insert(cache->hash, node->data, node); +} diff -r 322b580e0eb4 -r 54b29901a793 src/auth/auth-cache.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/auth-cache.h Thu Oct 21 05:23:09 2004 +0300 @@ -0,0 +1,30 @@ +#ifndef __AUTH_CACHE_H +#define __AUTH_CACHE_H + +struct auth_cache; +struct auth_request; + +/* Parses all %x variables from query and compresses them into tab-separated + list, so it can be used as a cache key. */ +char *auth_cache_parse_key(const char *query); + +/* Create a new cache. max_size specifies the maximum amount of memory in + bytes to use for cache (it's not fully exact). ttl_secs specifies time to + live for cache record, requests older than that are not used. */ +struct auth_cache *auth_cache_new(size_t max_size, unsigned int ttl_secs); +void auth_cache_free(struct auth_cache *cache); + +/* Clear the cache. */ +void auth_cache_clear(struct auth_cache *cache); + +/* Look key from cache. key should be the same string as returned by + auth_cache_parse_key(). */ +const char *auth_cache_lookup(struct auth_cache *cache, + const struct auth_request *request, + const char *key); +/* Insert key => value into cache. */ +void auth_cache_insert(struct auth_cache *cache, + const struct auth_request *request, + const char *key, const char *value); + +#endif diff -r 322b580e0eb4 -r 54b29901a793 src/auth/mech.c --- a/src/auth/mech.c Thu Oct 21 02:34:34 2004 +0300 +++ b/src/auth/mech.c Thu Oct 21 05:23:09 2004 +0300 @@ -5,14 +5,22 @@ #include "buffer.h" #include "hash.h" #include "mech.h" +#include "safe-memset.h" #include "str.h" #include "str-sanitize.h" #include "var-expand.h" #include "auth-client-connection.h" #include "auth-master-connection.h" +#include "passdb-cache.h" #include +struct auth_request_extra { + struct auth_request *request; + string_t *str; + char *user_password, *password; +}; + struct mech_module_list *mech_modules; buffer_t *mech_handshake; @@ -187,6 +195,103 @@ return FALSE; } +struct auth_request_extra * +auth_request_extra_begin(struct auth_request *request, + const char *user_password) +{ + struct auth_request_extra *extra; + + extra = i_new(struct auth_request_extra, 1); + extra->request = request; + extra->user_password = i_strdup(user_password); + return extra; +} + +void auth_request_extra_next(struct auth_request_extra *extra, + const char *name, const char *value) +{ + string_t *str; + + i_assert(value != NULL); + + if (strcmp(name, "password") == 0) { + i_assert(extra->password == NULL); + extra->password = i_strdup(value); + return; + } + + if (strcmp(name, "nodelay") == 0) { + /* don't delay replying to client of the failure */ + extra->request->no_failure_delay = TRUE; + return; + } + + str = extra->str; + if (str == NULL) + extra->str = str = str_new(extra->request->pool, 64); + + if (strcmp(name, "nologin") == 0) { + /* user can't actually login - don't keep this + reply for master */ + extra->request->no_login = TRUE; + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_append(str, name); + } else if (strcmp(name, "proxy") == 0) { + /* we're proxying authentication for this user. send + password back if using plaintext authentication. */ + extra->request->proxy = TRUE; + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_append(str, name); + } else { + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_printfa(str, "%s=%s", name, value); + } +} + +void auth_request_extra_finish(struct auth_request_extra *extra, + const char *cache_key) +{ + string_t *str; + + if (passdb_cache != NULL && cache_key != NULL) { + str = t_str_new(64); + str_append_str(str, extra->str); + if (extra->request->no_failure_delay) { + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_append(str, "nodelay"); + } + auth_cache_insert(passdb_cache, extra->request, cache_key, + t_strconcat(extra->password == NULL ? "" : + extra->password, "\t", + str_c(str), NULL)); + } + + if (extra->user_password != NULL) { + if (extra->request->proxy) { + /* we're proxying - send back the password that was + sent by user (not the password in passdb). */ + str_printfa(extra->str, "\tpass=%s", + extra->user_password); + } + safe_memset(extra->user_password, 0, + strlen(extra->user_password)); + i_free(extra->user_password); + } + + if (extra->str != NULL) + extra->request->extra_fields = str_c(extra->str); + + if (extra->password != NULL) { + safe_memset(extra->password, 0, strlen(extra->password)); + i_free(extra->password); + } + i_free(extra); +} + static const char *escape_none(const char *str) { return str; diff -r 322b580e0eb4 -r 54b29901a793 src/auth/mech.h --- a/src/auth/mech.h Thu Oct 21 02:34:34 2004 +0300 +++ b/src/auth/mech.h Thu Oct 21 05:23:09 2004 +0300 @@ -89,6 +89,13 @@ void auth_request_ref(struct auth_request *request); int auth_request_unref(struct auth_request *request); +struct auth_request_extra * +auth_request_extra_begin(struct auth_request *request, const char *password); +void auth_request_extra_next(struct auth_request_extra *extra, + const char *name, const char *value); +void auth_request_extra_finish(struct auth_request_extra *extra, + const char *cache_key); + const struct var_expand_table * auth_request_get_var_expand_table(const struct auth_request *auth_request, const char *(*escape_func)(const char *)); diff -r 322b580e0eb4 -r 54b29901a793 src/auth/passdb-cache.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/passdb-cache.c Thu Oct 21 05:23:09 2004 +0300 @@ -0,0 +1,143 @@ +/* Copyright (C) 2004 Timo Sirainen */ + +#include "common.h" +#include "password-scheme.h" +#include "passdb.h" +#include "passdb-cache.h" + +#include + +struct auth_cache *passdb_cache = NULL; + +static void list_save(struct auth_request *request, const char *password, + const char *const *list) +{ + struct auth_request_extra *extra; + const char *name, *value; + + if (*list == NULL) + return; + + extra = auth_request_extra_begin(request, password); + for (; *list != NULL; list++) { + t_push(); + value = strchr(*list, '='); + if (value == NULL) { + name = *list; + value = ""; + } else { + name = t_strcut(*list, '='); + value++; + } + + auth_request_extra_next(extra, name, value); + t_pop(); + } + auth_request_extra_finish(extra, NULL); +} + +int passdb_cache_verify_plain(struct auth_request *request, const char *key, + const char *password, const char *default_scheme, + enum passdb_result *result_r) +{ + const char *value, *cached_pw, *scheme, *const *list; + int ret; + + i_assert(default_scheme != NULL); + + if (passdb_cache == NULL) + return FALSE; + + /* value = password \t ... */ + value = auth_cache_lookup(passdb_cache, request, key); + if (value == NULL) + return FALSE; + + if (*value == '\0') { + /* negative cache entry */ + *result_r = PASSDB_RESULT_USER_UNKNOWN; + return TRUE; + } + + list = t_strsplit(value, "\t"); + cached_pw = list[0]; + + scheme = password_get_scheme(&cached_pw); + if (scheme == NULL) + scheme = default_scheme; + list_save(request, password, list+1); + + ret = password_verify(password, cached_pw, scheme, request->user); + if (ret < 0) { + i_error("cache(%s): Unknown password scheme %s", + get_log_prefix(request), scheme); + } else if (ret == 0) { + if (verbose) { + i_info("cache(%s): Password mismatch", + get_log_prefix(request)); + } + } + + *result_r = ret > 0 ? PASSDB_RESULT_OK : + PASSDB_RESULT_PASSWORD_MISMATCH; + return TRUE; +} + +int passdb_cache_lookup_credentials(struct auth_request *request, + const char *key, const char **result_r, + const char **scheme_r) +{ + const char *value, *const *list; + const char *cached_pw; + + if (passdb_cache == NULL) + return FALSE; + + value = auth_cache_lookup(passdb_cache, request, key); + if (value == NULL) + return FALSE; + + if (*value == '\0') { + /* negative cache entry */ + *result_r = NULL; + *scheme_r = NULL; + return TRUE; + } + + list = t_strsplit(value, "\t"); + list_save(request, NULL, list+1); + + *result_r = list[0]; + *scheme_r = password_get_scheme(&cached_pw); + return TRUE; +} + +void passdb_cache_init(void) +{ + const char *env; + size_t max_size; + unsigned int cache_ttl; + + env = getenv("CACHE_SIZE"); + if (env == NULL) + return; + + max_size = (size_t)strtoul(env, NULL, 10) * 1024; + if (max_size == 0) + return; + + env = getenv("CACHE_TTL"); + if (env == NULL) + return; + + cache_ttl = (unsigned int)strtoul(env, NULL, 10); + if (cache_ttl == 0) + return; + + passdb_cache = auth_cache_new(max_size, cache_ttl); +} + +void passdb_cache_deinit(void) +{ + auth_cache_free(passdb_cache); +} diff -r 322b580e0eb4 -r 54b29901a793 src/auth/passdb-cache.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/auth/passdb-cache.h Thu Oct 21 05:23:09 2004 +0300 @@ -0,0 +1,19 @@ +#ifndef __PASSDB_CACHE_H +#define __PASSDB_CACHE_H + +#include "auth-cache.h" + +enum passdb_result; +extern struct auth_cache *passdb_cache; + +int passdb_cache_verify_plain(struct auth_request *request, const char *key, + const char *password, const char *default_scheme, + enum passdb_result *result_r); +int passdb_cache_lookup_credentials(struct auth_request *request, + const char *key, const char **result_r, + const char **scheme_r); + +void passdb_cache_init(void); +void passdb_cache_deinit(void); + +#endif diff -r 322b580e0eb4 -r 54b29901a793 src/auth/passdb-ldap.c --- a/src/auth/passdb-ldap.c Thu Oct 21 02:34:34 2004 +0300 +++ b/src/auth/passdb-ldap.c Thu Oct 21 05:23:09 2004 +0300 @@ -11,6 +11,7 @@ #include "password-scheme.h" #include "db-ldap.h" #include "passdb.h" +#include "passdb-cache.h" #include #include @@ -45,6 +46,7 @@ }; static struct passdb_ldap_connection *passdb_ldap_conn; +static char *passdb_ldap_cache_key; static void handle_request(struct ldap_connection *conn, struct ldap_request *request, LDAPMessage *res) @@ -116,7 +118,7 @@ if (ldap_request->credentials != -1) { passdb_handle_credentials(ldap_request->credentials, - user, password, scheme, + password, scheme, ldap_request->callback.lookup_credentials, auth_request); return; @@ -177,7 +179,15 @@ ldap_verify_plain(struct auth_request *request, const char *password, verify_plain_callback_t *callback) { + struct ldap_connection *conn = passdb_ldap_conn->conn; struct passdb_ldap_request *ldap_request; + enum passdb_result result; + + if (passdb_cache_verify_plain(request, passdb_ldap_cache_key, password, + conn->set.default_pass_scheme, &result)) { + callback(result, request); + return; + } ldap_request = i_malloc(sizeof(struct passdb_ldap_request) + strlen(password)); @@ -193,6 +203,18 @@ lookup_credentials_callback_t *callback) { struct passdb_ldap_request *ldap_request; + const char *result, *scheme; + + if (passdb_cache_lookup_credentials(request, passdb_ldap_cache_key, + &result, &scheme)) { + if (scheme == NULL) { + scheme = passdb_ldap_conn->conn->set. + default_pass_scheme; + } + passdb_handle_credentials(credentials, result, scheme, + callback, request); + return; + } ldap_request = i_new(struct passdb_ldap_request, 1); ldap_request->credentials = credentials; @@ -212,6 +234,7 @@ conn->set.pass_attrs : DEFAULT_ATTRIBUTES, &passdb_ldap_conn->attrs, &passdb_ldap_conn->attr_names); + passdb_ldap_cache_key = auth_cache_parse_key(conn->set.pass_filter); } static void passdb_ldap_init(const char *args __attr_unused__) @@ -222,6 +245,7 @@ static void passdb_ldap_deinit(void) { db_ldap_unref(passdb_ldap_conn->conn); + i_free(passdb_ldap_cache_key); i_free(passdb_ldap_conn); } diff -r 322b580e0eb4 -r 54b29901a793 src/auth/passdb-passwd-file.c --- a/src/auth/passdb-passwd-file.c Thu Oct 21 02:34:34 2004 +0300 +++ b/src/auth/passdb-passwd-file.c Thu Oct 21 05:23:09 2004 +0300 @@ -63,7 +63,7 @@ crypted_pass = pu->password; scheme = password_get_scheme(&crypted_pass); - passdb_handle_credentials(credentials, request->user, crypted_pass, + passdb_handle_credentials(credentials, crypted_pass, scheme, callback, request); } diff -r 322b580e0eb4 -r 54b29901a793 src/auth/passdb-sql.c --- a/src/auth/passdb-sql.c Thu Oct 21 02:34:34 2004 +0300 +++ b/src/auth/passdb-sql.c Thu Oct 21 05:23:09 2004 +0300 @@ -12,6 +12,7 @@ #include "password-scheme.h" #include "db-sql.h" #include "passdb.h" +#include "passdb-cache.h" #include #include @@ -28,67 +29,28 @@ }; static struct sql_connection *passdb_sql_conn; +static char *passdb_sql_cache_key; static void result_save_extra_fields(struct sql_result *result, - struct passdb_sql_request *sql_request, + struct passdb_sql_request *sql_request, struct auth_request *auth_request) { + struct auth_request_extra *extra; unsigned int i, fields_count; const char *name, *value; - string_t *str; + + extra = auth_request_extra_begin(auth_request, sql_request->password); fields_count = sql_result_get_fields_count(result); - if (fields_count == 1) - return; - - str = NULL; for (i = 0; i < fields_count; i++) { name = sql_result_get_field_name(result, i); value = sql_result_get_field_value(result, i); - if (value == NULL) - continue; - - if (strcmp(name, "password") == 0) - continue; - - if (strcmp(name, "nodelay") == 0) { - /* don't delay replying to client of the failure */ - auth_request->no_failure_delay = TRUE; - continue; - } - - if (str == NULL) - str = str_new(auth_request->pool, 64); - - if (strcmp(name, "nologin") == 0) { - /* user can't actually login - don't keep this - reply for master */ - auth_request->no_login = TRUE; - if (str_len(str) > 0) - str_append_c(str, '\t'); - str_append(str, name); - } else if (strcmp(name, "proxy") == 0) { - /* we're proxying authentication for this user. send - password back if using plaintext authentication. */ - auth_request->proxy = TRUE; - if (str_len(str) > 0) - str_append_c(str, '\t'); - str_append(str, name); - - if (*sql_request->password != '\0') { - str_printfa(str, "\tpass=%s", - sql_request->password); - } - } else { - if (str_len(str) > 0) - str_append_c(str, '\t'); - str_printfa(str, "%s=%s", name, value); - } + if (value != NULL) + auth_request_extra_next(extra, name, value); } - if (str != NULL) - auth_request->extra_fields = str_c(str); + auth_request_extra_finish(extra, passdb_sql_cache_key); } static void sql_query_callback(struct sql_result *result, void *context) @@ -111,6 +73,10 @@ i_info("sql(%s): Unknown user", get_log_prefix(auth_request)); } + if (passdb_cache != NULL) { + auth_cache_insert(passdb_cache, auth_request, + passdb_sql_cache_key, ""); + } } else if ((idx = sql_result_find_field(result, "password")) < 0) { i_error("sql(%s): Password query didn't return password", get_log_prefix(auth_request)); @@ -136,7 +102,7 @@ if (sql_request->credentials != -1) { passdb_handle_credentials(sql_request->credentials, - user, password, scheme, + password, scheme, sql_request->callback.lookup_credentials, auth_request); return; @@ -182,6 +148,14 @@ verify_plain_callback_t *callback) { struct passdb_sql_request *sql_request; + enum passdb_result result; + + if (passdb_cache_verify_plain(request, passdb_sql_cache_key, password, + passdb_sql_conn->set.default_pass_scheme, + &result)) { + callback(result, request); + return; + } sql_request = i_malloc(sizeof(struct passdb_sql_request) + strlen(password)); @@ -198,6 +172,16 @@ lookup_credentials_callback_t *callback) { struct passdb_sql_request *sql_request; + const char *result, *scheme; + + if (passdb_cache_lookup_credentials(request, passdb_sql_cache_key, + &result, &scheme)) { + if (scheme == NULL) + scheme = passdb_sql_conn->set.default_pass_scheme; + passdb_handle_credentials(credentials, result, scheme, + callback, request); + return; + } sql_request = i_new(struct passdb_sql_request, 1); sql_request->auth_request = request; @@ -210,6 +194,8 @@ static void passdb_sql_preinit(const char *args) { passdb_sql_conn = db_sql_init(args); + passdb_sql_cache_key = + auth_cache_parse_key(passdb_sql_conn->set.password_query); } static void passdb_sql_init(const char *args __attr_unused__) @@ -220,6 +206,7 @@ static void passdb_sql_deinit(void) { db_sql_unref(passdb_sql_conn); + i_free(passdb_sql_cache_key); } struct passdb_module passdb_sql = { diff -r 322b580e0eb4 -r 54b29901a793 src/auth/passdb.c --- a/src/auth/passdb.c Thu Oct 21 02:34:34 2004 +0300 +++ b/src/auth/passdb.c Thu Oct 21 05:23:09 2004 +0300 @@ -5,6 +5,7 @@ #include "auth-module.h" #include "password-scheme.h" #include "passdb.h" +#include "passdb-cache.h" #include @@ -41,8 +42,7 @@ } void passdb_handle_credentials(enum passdb_credentials credentials, - const char *user, const char *password, - const char *scheme, + const char *password, const char *scheme, lookup_credentials_callback_t *callback, struct auth_request *auth_request) { @@ -63,13 +63,15 @@ strcasecmp(scheme, "CLEARTEXT") == 0) { /* we can generate anything out of plaintext passwords */ - password = password_generate(password, user, + password = password_generate(password, + auth_request->user, wanted_scheme); } else { if (verbose) { i_info("password(%s): Requested %s " "scheme, but we have only %s", - user, wanted_scheme, scheme); + auth_request->user, + wanted_scheme, scheme); } password = NULL; } @@ -173,6 +175,7 @@ void passdb_init(void) { + passdb_cache_init(); if (passdb->init != NULL) passdb->init(passdb_args); } @@ -185,5 +188,6 @@ if (passdb_module != NULL) auth_module_close(passdb_module); #endif + passdb_cache_deinit(); i_free(passdb_args); } diff -r 322b580e0eb4 -r 54b29901a793 src/auth/passdb.h --- a/src/auth/passdb.h Thu Oct 21 02:34:34 2004 +0300 +++ b/src/auth/passdb.h Thu Oct 21 05:23:09 2004 +0300 @@ -49,8 +49,7 @@ }; void passdb_handle_credentials(enum passdb_credentials credentials, - const char *user, const char *password, - const char *scheme, + const char *password, const char *scheme, lookup_credentials_callback_t *callback, struct auth_request *auth_request); diff -r 322b580e0eb4 -r 54b29901a793 src/master/auth-process.c --- a/src/master/auth-process.c Thu Oct 21 02:34:34 2004 +0300 +++ b/src/master/auth-process.c Thu Oct 21 05:23:09 2004 +0300 @@ -442,6 +442,8 @@ group->set->username_translation, NULL)); env_put(t_strconcat("ANONYMOUS_USERNAME=", group->set->anonymous_username, NULL)); + env_put(t_strdup_printf("CACHE_SIZE=%u", group->set->cache_size)); + env_put(t_strdup_printf("CACHE_TTL=%u", group->set->cache_ttl)); for (as = group->set->sockets, i = 1; as != NULL; as = as->next, i++) { if (strcmp(as->type, "listen") != 0) diff -r 322b580e0eb4 -r 54b29901a793 src/master/master-settings.c --- a/src/master/master-settings.c Thu Oct 21 02:34:34 2004 +0300 +++ b/src/master/master-settings.c Thu Oct 21 05:23:09 2004 +0300 @@ -139,6 +139,8 @@ DEF(SET_STR, default_realm), DEF(SET_STR, userdb), DEF(SET_STR, passdb), + DEF(SET_INT, cache_size), + DEF(SET_INT, cache_ttl), DEF(SET_STR, executable), DEF(SET_STR, user), DEF(SET_STR, chroot), @@ -310,6 +312,8 @@ MEMBER(default_realm) NULL, MEMBER(userdb) "passwd", MEMBER(passdb) "pam", + MEMBER(cache_size) 0, + MEMBER(cache_ttl) 3600, MEMBER(executable) PKG_LIBEXECDIR"/dovecot-auth", MEMBER(user) "root", MEMBER(chroot) NULL, diff -r 322b580e0eb4 -r 54b29901a793 src/master/master-settings.h --- a/src/master/master-settings.h Thu Oct 21 02:34:34 2004 +0300 +++ b/src/master/master-settings.h Thu Oct 21 05:23:09 2004 +0300 @@ -129,6 +129,8 @@ const char *default_realm; const char *userdb; const char *passdb; + unsigned int cache_size; + unsigned int cache_ttl; const char *executable; const char *user; const char *chroot;