Don't add any delays if passdb returned nodelay extra field.
Based on patch by Apple.
--HG--
branch : HEAD
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);
#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 \
}
}
-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;
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)
i_assert(nologin || proxy_self);
if (!client->destroyed)
- client_auth_failed(client);
+ client_auth_failed(client, *nodelay_r);
return TRUE;
}
struct const_iovec iov[3];
const char *msg;
size_t data_len;
+ bool nodelay;
i_assert(!client->destroyed ||
reply == SASL_SERVER_REPLY_CLIENT_ERROR ||
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");
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;
}
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)
/* 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
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);
#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;
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;
#include <stdlib.h>
#define POP3_SERVICE_NAME "pop3"
+#define AUTH_FAILURE_DELAY_INCREASE_MSECS 5000
const char *capability_string = POP3_CAPABILITY_REPLY;
}
}
+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;
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)
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;
}
struct const_iovec iov[3];
const char *msg;
size_t data_len;
+ bool nodelay;
i_assert(!client->destroyed ||
reply == SASL_SERVER_REPLY_CLIENT_ERROR ||
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;
}
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;
}
data : AUTH_FAILED_MSG, NULL);
client_send_line(client, msg);
- if (!client->destroyed && !client->auth_initializing) {
- /* 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);
break;
case SASL_SERVER_REPLY_MASTER_FAILED:
if (data == NULL)
SASL authentication gives the largest output. */
#define MAX_OUTBUF_SIZE 4096
-/* 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
io_remove(&client->io);
if (client->to_idle_disconnect != NULL)
timeout_remove(&client->to_idle_disconnect);
+ if (client->to_authfail_delay != NULL)
+ timeout_remove(&client->to_authfail_delay);
if (client->common.fd != -1) {
net_disconnect(client->common.fd);
#include "client-common.h"
#include "auth-client.h"
+/* Disconnect client after idling this many milliseconds */
+#define CLIENT_LOGIN_IDLE_TIMEOUT_MSECS (3*60*1000)
+
struct pop3_client {
struct client common;
struct io *io;
struct ostream *output;
- struct timeout *to_idle_disconnect;
+ struct timeout *to_idle_disconnect, *to_authfail_delay;
struct login_proxy *proxy;
char *proxy_user, *proxy_master_user, *proxy_password;