changeset 9110:8a23ab43132a HEAD

auth_cache_negative_ttl is now also used for password mismatches.
author Timo Sirainen <tss@iki.fi>
date Sun, 31 May 2009 23:35:56 -0400
parents 0c99b67068cb
children 228100f53e88
files dovecot-example.conf src/auth/auth-cache.c src/auth/auth-cache.h src/auth/auth-request.c src/auth/passdb-cache.c
diffstat 5 files changed, 23 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/dovecot-example.conf	Sun May 31 22:41:22 2009 -0400
+++ b/dovecot-example.conf	Sun May 31 23:35:56 2009 -0400
@@ -754,7 +754,8 @@
 # user's previous authentication was successful, but this one wasn't, the
 # cache isn't used. For now this works only with plaintext authentication.
 #auth_cache_ttl = 3600
-# TTL for negative hits (user not found). 0 disables caching them completely.
+# TTL for negative hits (user not found, password mismatch).
+# 0 disables caching them completely.
 #auth_cache_negative_ttl = 3600
 
 # Space separated list of realms for SASL authentication mechanisms that need
--- a/src/auth/auth-cache.c	Sun May 31 22:41:22 2009 -0400
+++ b/src/auth/auth-cache.c	Sun May 31 23:35:56 2009 -0400
@@ -162,14 +162,16 @@
 const char *
 auth_cache_lookup(struct auth_cache *cache, const struct auth_request *request,
 		  const char *key, struct auth_cache_node **node_r,
-		  bool *expired_r)
+		  bool *expired_r, bool *neg_expired_r)
 {
 	string_t *str;
 	struct auth_cache_node *node;
 	const char *value;
 	unsigned int ttl_secs;
+	time_t now;
 
 	*expired_r = FALSE;
+	*neg_expired_r = FALSE;
 
 	/* %! is prepended automatically. it contains the passdb ID number. */
 	str = t_str_new(256);
@@ -187,7 +189,8 @@
 	value = node->data + strlen(node->data) + 1;
 	ttl_secs = *value == '\0' ? cache->neg_ttl_secs : cache->ttl_secs;
 
-	if (node->created < time(NULL) - (time_t)ttl_secs) {
+	now = time(NULL);
+	if (node->created < now - (time_t)ttl_secs) {
 		/* TTL expired */
 		*expired_r = TRUE;
 	} else {
@@ -197,6 +200,8 @@
 			auth_cache_node_link_head(cache, node);
 		}
 	}
+	if (node->created < now - (time_t)cache->neg_ttl_secs)
+		*neg_expired_r = TRUE;
 
 	if (node_r != NULL)
 		*node_r = node;
--- a/src/auth/auth-cache.h	Sun May 31 22:41:22 2009 -0400
+++ b/src/auth/auth-cache.h	Sun May 31 23:35:56 2009 -0400
@@ -37,7 +37,7 @@
 const char *
 auth_cache_lookup(struct auth_cache *cache, const struct auth_request *request,
 		  const char *key, struct auth_cache_node **node_r,
-		  bool *expired_r);
+		  bool *expired_r, bool *neg_expired_r);
 /* Insert key => value into cache. "" value means negative cache entry. */
 void auth_cache_insert(struct auth_cache *cache, struct auth_request *request,
 		       const char *key, const char *value, bool last_success);
--- a/src/auth/auth-request.c	Sun May 31 22:41:22 2009 -0400
+++ b/src/auth/auth-request.c	Sun May 31 23:35:56 2009 -0400
@@ -658,10 +658,10 @@
 {
 	const char *value;
 	struct auth_cache_node *node;
-	bool expired;
+	bool expired, neg_expired;
 
 	value = auth_cache_lookup(passdb_cache, request, key, &node,
-				  &expired);
+				  &expired, &neg_expired);
 	if (value == NULL || (expired && !use_expired))
 		return FALSE;
 
--- a/src/auth/passdb-cache.c	Sun May 31 22:41:22 2009 -0400
+++ b/src/auth/passdb-cache.c	Sun May 31 23:35:56 2009 -0400
@@ -30,13 +30,14 @@
 	const char *value, *cached_pw, *scheme, *const *list;
 	struct auth_cache_node *node;
 	int ret;
-	bool expired;
+	bool expired, neg_expired;
 
 	if (passdb_cache == NULL || key == NULL)
 		return FALSE;
 
 	/* value = password \t ... */
-	value = auth_cache_lookup(passdb_cache, request, key, &node, &expired);
+	value = auth_cache_lookup(passdb_cache, request, key, &node,
+				  &expired, &neg_expired);
 	if (value == NULL || (expired && !use_expired)) {
 		auth_request_log_debug(request, "cache",
 				       value == NULL ? "miss" : "expired");
@@ -65,9 +66,11 @@
 		ret = auth_request_password_verify(request, password, cached_pw,
 						   scheme, "cache");
 
-		if (ret == 0 && node->last_success) {
-			/* the last authentication was successful. assume that
-			   the password was changed and cache is expired. */
+		if (ret == 0 && (node->last_success || neg_expired)) {
+			/* a) the last authentication was successful. assume
+			   that the password was changed and cache is expired.
+			   b) negative TTL reached, use it for password
+			   mismatches too. */
 			node->last_success = FALSE;
 			return FALSE;
 		}
@@ -91,12 +94,13 @@
 {
 	const char *value, *const *list;
 	struct auth_cache_node *node;
-	bool expired;
+	bool expired, neg_expired;
 
 	if (passdb_cache == NULL)
 		return FALSE;
 
-	value = auth_cache_lookup(passdb_cache, request, key, &node, &expired);
+	value = auth_cache_lookup(passdb_cache, request, key, &node,
+				  &expired, &neg_expired);
 	if (value == NULL || (expired && !use_expired)) {
 		auth_request_log_debug(request, "cache",
 				       value == NULL ? "miss" : "expired");