dovecot-1.2: Increase failed login's reply delay by 5 seconds fo...

dovecot at dovecot.org dovecot at dovecot.org
Fri Dec 19 09:37:17 EET 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/1b744c38bcac
changeset: 8574:1b744c38bcac
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Dec 19 09:31:18 2008 +0200
description:
Increase failed login's reply delay by 5 seconds for each failure.
Don't add any delays if passdb returned nodelay extra field.
Based on patch by Apple.

diffstat:

7 files changed, 110 insertions(+), 37 deletions(-)
src/auth/auth-request-handler.c      |    2 
src/imap-login/client-authenticate.c |   55 +++++++++++++++++++++-----
src/imap-login/client.c              |    5 --
src/imap-login/client.h              |    4 +
src/pop3-login/client-authenticate.c |   71 ++++++++++++++++++++++++----------
src/pop3-login/client.c              |    5 --
src/pop3-login/client.h              |    5 +-

diffs (truncated from 360 to 300 lines):

diff -r f9166a09423a -r 1b744c38bcac src/auth/auth-request-handler.c
--- a/src/auth/auth-request-handler.c	Fri Dec 19 09:06:38 2008 +0200
+++ b/src/auth/auth-request-handler.c	Fri Dec 19 09:31:18 2008 +0200
@@ -254,6 +254,8 @@ static void auth_callback(struct auth_re
 			   as the wanted user */
 			auth_stream_reply_add(reply, "authz", NULL);
 		}
+		if (request->no_failure_delay)
+			auth_stream_reply_add(reply, "nodelay", NULL);
 		get_client_extra_fields(request, reply);
 
 		auth_request_handle_failure(request, reply);
diff -r f9166a09423a -r 1b744c38bcac src/imap-login/client-authenticate.c
--- a/src/imap-login/client-authenticate.c	Fri Dec 19 09:06:38 2008 +0200
+++ b/src/imap-login/client-authenticate.c	Fri Dec 19 09:31:18 2008 +0200
@@ -18,6 +18,8 @@
 
 #include <stdlib.h>
 
+#define AUTH_FAILURE_DELAY_INCREASE_MSECS 5000
+
 #define IMAP_SERVICE_NAME "imap"
 #define IMAP_AUTH_FAILED_MSG "["IMAP_RESP_CODE_AUTHFAILED"] "AUTH_FAILED_MSG
 #define IMAP_AUTHZ_FAILED_MSG \
@@ -79,23 +81,50 @@ static void client_auth_input(struct ima
 	}
 }
 
-static void client_auth_failed(struct imap_client *client)
-{
+static void client_authfail_delay_timeout(struct imap_client *client)
+{
+	timeout_remove(&client->to_authfail_delay);
+
+	/* get back to normal client input. */
+	i_assert(client->io == NULL);
+	client->io = io_add(client->common.fd, IO_READ, client_input, client);
+	client_input(client);
+}
+
+static void client_auth_failed(struct imap_client *client, bool nodelay)
+{
+	unsigned int delay_msecs;
+
 	client->common.auth_command_tag = NULL;
 
 	if (client->auth_initializing)
 		return;
 
-	/* get back to normal client input. */
 	if (client->io != NULL)
 		io_remove(&client->io);
-	client->io = io_add(client->common.fd, IO_READ,
-			    client_input, client);
-	client_input(client);
+	if (nodelay) {
+		client->io = io_add(client->common.fd, IO_READ,
+				    client_input, client);
+		client_input(client);
+		return;
+	}
+
+	/* increase the timeout after each unsuccessful attempt, but don't
+	   increase it so high that the idle timeout would be triggered */
+	delay_msecs = client->common.auth_attempts *
+		AUTH_FAILURE_DELAY_INCREASE_MSECS;
+	if (delay_msecs > CLIENT_LOGIN_IDLE_TIMEOUT_MSECS)
+		delay_msecs = CLIENT_LOGIN_IDLE_TIMEOUT_MSECS - 1000;
+	timeout_reset(client->to_idle_disconnect);
+
+	i_assert(client->to_authfail_delay == NULL);
+	client->to_authfail_delay =
+		timeout_add(delay_msecs, client_authfail_delay_timeout, client);
 }
 
 static bool client_handle_args(struct imap_client *client,
-			       const char *const *args, bool success)
+			       const char *const *args, bool success,
+			       bool *nodelay_r)
 {
 	const char *reason = NULL, *host = NULL, *destuser = NULL, *pass = NULL;
 	const char *master_user = NULL;
@@ -104,9 +133,12 @@ static bool client_handle_args(struct im
 	bool proxy = FALSE, temp = FALSE, nologin = !success, proxy_self;
 	bool authz_failure = FALSE;
 
+	*nodelay_r = FALSE;
 	for (; *args != NULL; args++) {
 		if (strcmp(*args, "nologin") == 0)
 			nologin = TRUE;
+		else if (strcmp(*args, "nodelay") == 0)
+			*nodelay_r = TRUE;
 		else if (strcmp(*args, "proxy") == 0)
 			proxy = TRUE;
 		else if (strcmp(*args, "temp") == 0)
@@ -210,7 +242,7 @@ static bool client_handle_args(struct im
 	i_assert(nologin || proxy_self);
 
 	if (!client->destroyed)
-		client_auth_failed(client);
+		client_auth_failed(client, *nodelay_r);
 	return TRUE;
 }
 
@@ -221,6 +253,7 @@ static void sasl_callback(struct client 
 	struct const_iovec iov[3];
 	const char *msg;
 	size_t data_len;
+	bool nodelay;
 
 	i_assert(!client->destroyed ||
 		 reply == SASL_SERVER_REPLY_CLIENT_ERROR ||
@@ -231,7 +264,7 @@ static void sasl_callback(struct client 
 		if (client->to_auth_waiting != NULL)
 			timeout_remove(&client->to_auth_waiting);
 		if (args != NULL) {
-			if (client_handle_args(client, args, TRUE))
+			if (client_handle_args(client, args, TRUE, &nodelay))
 				break;
 		}
 		client_destroy_success(client, "Login");
@@ -241,7 +274,7 @@ static void sasl_callback(struct client 
 		if (client->to_auth_waiting != NULL)
 			timeout_remove(&client->to_auth_waiting);
 		if (args != NULL) {
-			if (client_handle_args(client, args, FALSE))
+			if (client_handle_args(client, args, FALSE, &nodelay))
 				break;
 		}
 
@@ -251,7 +284,7 @@ static void sasl_callback(struct client 
 		client_send_tagline(client, msg);
 
 		if (!client->destroyed)
-			client_auth_failed(client);
+			client_auth_failed(client, nodelay);
 		break;
 	case SASL_SERVER_REPLY_MASTER_FAILED:
 		if (data == NULL)
diff -r f9166a09423a -r 1b744c38bcac src/imap-login/client.c
--- a/src/imap-login/client.c	Fri Dec 19 09:06:38 2008 +0200
+++ b/src/imap-login/client.c	Fri Dec 19 09:31:18 2008 +0200
@@ -25,9 +25,6 @@
 
 /* maximum length for IMAP command line. */
 #define MAX_IMAP_LINE 8192
-
-/* Disconnect client after idling this many milliseconds */
-#define CLIENT_LOGIN_IDLE_TIMEOUT_MSECS (3*60*1000)
 
 /* Disconnect client when it sends too many bad commands */
 #define CLIENT_MAX_BAD_COMMANDS 10
@@ -572,6 +569,8 @@ void client_destroy(struct imap_client *
 		timeout_remove(&client->to_idle_disconnect);
 	if (client->to_auth_waiting != NULL)
 		timeout_remove(&client->to_auth_waiting);
+	if (client->to_authfail_delay != NULL)
+		timeout_remove(&client->to_authfail_delay);
 
 	if (client->common.fd != -1) {
 		net_disconnect(client->common.fd);
diff -r f9166a09423a -r 1b744c38bcac src/imap-login/client.h
--- a/src/imap-login/client.h	Fri Dec 19 09:06:38 2008 +0200
+++ b/src/imap-login/client.h	Fri Dec 19 09:31:18 2008 +0200
@@ -4,6 +4,9 @@
 #include "network.h"
 #include "master.h"
 #include "client-common.h"
+
+/* Disconnect client after idling this many milliseconds */
+#define CLIENT_LOGIN_IDLE_TIMEOUT_MSECS (3*60*1000)
 
 struct imap_client {
 	struct client common;
@@ -15,6 +18,7 @@ struct imap_client {
 	struct ostream *output;
 	struct imap_parser *parser;
 	struct timeout *to_idle_disconnect, *to_auth_waiting;
+	struct timeout *to_authfail_delay;
 
 	struct login_proxy *proxy;
 	char *proxy_user, *proxy_master_user, *proxy_password;
diff -r f9166a09423a -r 1b744c38bcac src/pop3-login/client-authenticate.c
--- a/src/pop3-login/client-authenticate.c	Fri Dec 19 09:06:38 2008 +0200
+++ b/src/pop3-login/client-authenticate.c	Fri Dec 19 09:31:18 2008 +0200
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 
 #define POP3_SERVICE_NAME "pop3"
+#define AUTH_FAILURE_DELAY_INCREASE_MSECS 5000
 
 const char *capability_string = POP3_CAPABILITY_REPLY;
 
@@ -82,8 +83,48 @@ static void client_auth_input(struct pop
 	}
 }
 
+static void client_authfail_delay_timeout(struct pop3_client *client)
+{
+	timeout_remove(&client->to_authfail_delay);
+
+	/* get back to normal client input. */
+	i_assert(client->io == NULL);
+	client->io = io_add(client->common.fd, IO_READ, client_input, client);
+	client_input(client);
+}
+
+static void client_auth_failed(struct pop3_client *client, bool nodelay)
+{
+	unsigned int delay_msecs;
+
+	if (client->auth_initializing)
+		return;
+
+	if (client->io != NULL)
+		io_remove(&client->io);
+	if (nodelay) {
+		client->io = io_add(client->common.fd, IO_READ,
+				    client_input, client);
+		client_input(client);
+		return;
+	}
+
+	/* increase the timeout after each unsuccessful attempt, but don't
+	   increase it so high that the idle timeout would be triggered */
+	delay_msecs = client->common.auth_attempts *
+		AUTH_FAILURE_DELAY_INCREASE_MSECS;
+	if (delay_msecs > CLIENT_LOGIN_IDLE_TIMEOUT_MSECS)
+		delay_msecs = CLIENT_LOGIN_IDLE_TIMEOUT_MSECS - 1000;
+	timeout_reset(client->to_idle_disconnect);
+
+	i_assert(client->to_authfail_delay == NULL);
+	client->to_authfail_delay =
+		timeout_add(delay_msecs, client_authfail_delay_timeout, client);
+}
+
 static bool client_handle_args(struct pop3_client *client,
-			       const char *const *args, bool success)
+			       const char *const *args, bool success,
+			       bool *nodelay_r)
 {
 	const char *reason = NULL, *host = NULL, *destuser = NULL, *pass = NULL;
 	const char *master_user = NULL;
@@ -91,9 +132,12 @@ static bool client_handle_args(struct po
 	unsigned int port = 110;
 	bool proxy = FALSE, temp = FALSE, nologin = !success;
 
+	*nodelay_r = FALSE;
 	for (; *args != NULL; args++) {
 		if (strcmp(*args, "nologin") == 0)
 			nologin = TRUE;
+		else if (strcmp(*args, "nodelay") == 0)
+			*nodelay_r = TRUE;
 		else if (strcmp(*args, "proxy") == 0)
 			proxy = TRUE;
 		else if (strcmp(*args, "temp") == 0)
@@ -150,14 +194,8 @@ static bool client_handle_args(struct po
 
 	client_send_line(client, str_c(reply));
 
-	if (!client->destroyed) {
-		/* get back to normal client input. */
-		if (client->io != NULL)
-			io_remove(&client->io);
-		client->io = io_add(client->common.fd, IO_READ,
-				    client_input, client);
-		client_input(client);
-	}
+	if (!client->destroyed)
+		client_auth_failed(client, *nodelay_r);
 	return TRUE;
 }
 
@@ -168,6 +206,7 @@ static void sasl_callback(struct client 
 	struct const_iovec iov[3];
 	const char *msg;
 	size_t data_len;
+	bool nodelay;
 
 	i_assert(!client->destroyed ||
 		 reply == SASL_SERVER_REPLY_CLIENT_ERROR ||
@@ -176,7 +215,7 @@ static void sasl_callback(struct client 
 	switch (reply) {
 	case SASL_SERVER_REPLY_SUCCESS:
 		if (args != NULL) {
-			if (client_handle_args(client, args, TRUE))
+			if (client_handle_args(client, args, TRUE, &nodelay))
 				break;
 		}
 
@@ -185,7 +224,7 @@ static void sasl_callback(struct client 
 	case SASL_SERVER_REPLY_AUTH_FAILED:
 	case SASL_SERVER_REPLY_CLIENT_ERROR:
 		if (args != NULL) {
-			if (client_handle_args(client, args, FALSE))
+			if (client_handle_args(client, args, FALSE, &nodelay))
 				break;
 		}
 
@@ -193,14 +232,8 @@ static void sasl_callback(struct client 


More information about the dovecot-cvs mailing list