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