Download | Plain Text | Line Numbers
diff -Naur dovecot-2.2.21.orig/src/anvil/anvil-connection.c dovecot-2.2.21/src/anvil/anvil-connection.c
--- dovecot-2.2.21.orig/src/anvil/anvil-connection.c 2015-12-09 16:39:10.000000000 +0100
+++ dovecot-2.2.21/src/anvil/anvil-connection.c 2016-02-17 02:28:07.713478699 +0100
@@ -109,18 +109,26 @@
o_stream_nsend_str(conn->output,
t_strdup_printf("%u %s\n", value, dec2str(stamp)));
} else if (strcmp(cmd, "PENALTY-INC") == 0) {
- if (args[0] == NULL || args[1] == NULL || args[2] == NULL) {
+ if (args[0] == NULL || args[1] == NULL) {
*error_r = "PENALTY-INC: Not enough parameters";
return -1;
}
- if (str_to_uint(args[1], &checksum) < 0 ||
- str_to_uint(args[2], &value) < 0 ||
- value > PENALTY_MAX_VALUE ||
- (value == 0 && checksum != 0)) {
+ if (str_to_uint(args[1], &checksum) < 0) {
*error_r = "PENALTY-INC: Invalid parameters";
return -1;
}
- penalty_inc(penalty, args[0], checksum, value);
+ penalty_inc(penalty, args[0], checksum);
+ } else if (strcmp(cmd, "PENALTY-SET") == 0) {
+ if (args[0] == NULL) {
+ *error_r = "PENALTY-INC: Not enough parameters";
+ return -1;
+ }
+ if (str_to_uint(args[1], &value) < 0 ||
+ value > PENALTY_MAX_VALUE) {
+ *error_r = "PENALTY-SET: Invalid parameters";
+ return -1;
+ }
+ penalty_set(penalty, args[0], value);
} else if (strcmp(cmd, "PENALTY-SET-EXPIRE-SECS") == 0) {
if (args[0] == NULL || str_to_uint(args[0], &value) < 0) {
*error_r = "PENALTY-SET-EXPIRE-SECS: "
@@ -128,6 +136,14 @@
return -1;
}
penalty_set_expire_secs(penalty, value);
+ } else if (strcmp(cmd, "PENALTY-SET-MAX-PENALTY") == 0) {
+ if (args[0] == NULL || str_to_uint(args[0], &value) < 0 ||
+ value > PENALTY_MAX_VALUE) {
+ *error_r = "PENALTY-SET-MAX-PENALTY: "
+ "Invalid parameters";
+ return -1;
+ }
+ penalty_set_max_penalty(penalty, value);
} else if (strcmp(cmd, "PENALTY-DUMP") == 0) {
penalty_dump(penalty, conn->output);
} else {
diff -Naur dovecot-2.2.21.orig/src/anvil/penalty.c dovecot-2.2.21/src/anvil/penalty.c
--- dovecot-2.2.21.orig/src/anvil/penalty.c 2015-12-09 16:39:10.000000000 +0100
+++ dovecot-2.2.21/src/anvil/penalty.c 2016-02-17 02:28:07.723478869 +0100
@@ -16,6 +16,7 @@
#include <time.h>
#define PENALTY_DEFAULT_EXPIRE_SECS (60*60)
+#define PENALTY_DEFAULT_MAX_PENALTY 100
#define PENALTY_CHECKSUM_SAVE_COUNT
#define CHECKSUM_VALUE_COUNT 2
#define CHECKSUM_VALUE_PTR_COUNT 10
@@ -46,6 +47,7 @@
struct penalty_rec *oldest, *newest;
unsigned int expire_secs;
+ unsigned int max_penalty:16;
struct timeout *to;
};
@@ -56,6 +58,7 @@
penalty = i_new(struct penalty, 1);
hash_table_create(&penalty->hash, default_pool, 0, str_hash, strcmp);
penalty->expire_secs = PENALTY_DEFAULT_EXPIRE_SECS;
+ penalty->max_penalty = PENALTY_DEFAULT_MAX_PENALTY;
return penalty;
}
@@ -88,6 +91,11 @@
penalty->expire_secs = expire_secs;
}
+void penalty_set_max_penalty(struct penalty *penalty, unsigned int max_penalty)
+{
+ penalty->max_penalty = max_penalty;
+}
+
static bool
penalty_bump_checksum(struct penalty_rec *rec, unsigned int checksum)
{
@@ -183,51 +191,84 @@
}
}
-void penalty_inc(struct penalty *penalty, const char *ident,
- unsigned int checksum, unsigned int value)
+static void penalty_update_times(struct penalty *penalty,
+ struct penalty_rec *rec)
{
- struct penalty_rec *rec;
time_t diff;
- i_assert(value > 0 || checksum == 0);
- i_assert(value <= INT_MAX);
+ diff = ioloop_time - rec->last_penalty;
+ if (diff >= (1 << LAST_UPDATE_BITS)) {
+ rec->last_update = (1 << LAST_UPDATE_BITS) - 1;
+ rec->last_penalty = ioloop_time - rec->last_update;
+ } else {
+ rec->last_update = diff;
+ }
+
+ if (penalty->to == NULL) {
+ penalty->to = timeout_add(penalty->expire_secs * 1000,
+ penalty_timeout, penalty);
+ }
+}
+
+void penalty_inc(struct penalty *penalty, const char *ident,
+ unsigned int checksum)
+{
+ struct penalty_rec *rec;
+ unsigned int new_penalty;
rec = hash_table_lookup(penalty->hash, ident);
if (rec == NULL) {
rec = i_new(struct penalty_rec, 1);
rec->ident = i_strdup(ident);
+ rec->penalty = 1;
+ rec->last_penalty = ioloop_time;
hash_table_insert(penalty->hash, rec->ident, rec);
+ if (checksum != 0)
+ penalty_add_checksum(rec, checksum);
} else {
DLLIST2_REMOVE(&penalty->oldest, &penalty->newest, rec);
- }
- if (checksum == 0) {
- rec->penalty = value;
- rec->last_penalty = ioloop_time;
- } else {
- if (penalty_bump_checksum(rec, checksum))
- rec->penalty = value - 1;
- else {
- penalty_add_checksum(rec, checksum);
- rec->penalty = value;
+ new_penalty = rec->penalty;
+ if (checksum == 0) {
+ new_penalty++;
rec->last_penalty = ioloop_time;
+ } else {
+ if (!penalty_bump_checksum(rec, checksum)) {
+ penalty_add_checksum(rec, checksum);
+ new_penalty++;
+ rec->last_penalty = ioloop_time;
+ }
}
+ rec->penalty = (new_penalty < penalty->max_penalty) ?
+ new_penalty : penalty->max_penalty;
}
- diff = ioloop_time - rec->last_penalty;
- if (diff >= (1 << LAST_UPDATE_BITS)) {
- rec->last_update = (1 << LAST_UPDATE_BITS) - 1;
- rec->last_penalty = ioloop_time - rec->last_update;
+ penalty_update_times(penalty, rec);
+ DLLIST2_APPEND(&penalty->oldest, &penalty->newest, rec);
+}
+
+void penalty_set(struct penalty *penalty, const char *ident,
+ unsigned int value)
+{
+ struct penalty_rec *rec;
+
+ rec = hash_table_lookup(penalty->hash, ident);
+ if (rec == NULL) {
+ if (value == 0)
+ return;
+ rec = i_new(struct penalty_rec, 1);
+ rec->ident = i_strdup(ident);
+ hash_table_insert(penalty->hash, rec->ident, rec);
} else {
- rec->last_update = diff;
+ DLLIST2_REMOVE(&penalty->oldest, &penalty->newest, rec);
}
- DLLIST2_APPEND(&penalty->oldest, &penalty->newest, rec);
+ rec->penalty = (value < penalty->max_penalty) ? value :
+ penalty->max_penalty;
+ rec->last_penalty = ioloop_time;
- if (penalty->to == NULL) {
- penalty->to = timeout_add(penalty->expire_secs * 1000,
- penalty_timeout, penalty);
- }
+ penalty_update_times(penalty, rec);
+ DLLIST2_APPEND(&penalty->oldest, &penalty->newest, rec);
}
bool penalty_has_checksum(struct penalty *penalty, const char *ident,
diff -Naur dovecot-2.2.21.orig/src/anvil/penalty.h dovecot-2.2.21/src/anvil/penalty.h
--- dovecot-2.2.21.orig/src/anvil/penalty.h 2015-12-09 16:39:10.000000000 +0100
+++ dovecot-2.2.21/src/anvil/penalty.h 2016-02-17 02:28:07.724478886 +0100
@@ -7,13 +7,14 @@
void penalty_deinit(struct penalty **penalty);
void penalty_set_expire_secs(struct penalty *penalty, unsigned int expire_secs);
+void penalty_set_max_penalty(struct penalty *penalty, unsigned int max_penalty);
unsigned int penalty_get(struct penalty *penalty, const char *ident,
time_t *last_penalty_r);
-/* if checksum is non-zero and it already exists for ident, the value
- is set to "value-1", otherwise it's set to "value". */
void penalty_inc(struct penalty *penalty, const char *ident,
- unsigned int checksum, unsigned int value);
+ unsigned int checksum);
+void penalty_set(struct penalty *penalty, const char *ident,
+ unsigned int value);
bool penalty_has_checksum(struct penalty *penalty, const char *ident,
unsigned int checksum);
diff -Naur dovecot-2.2.21.orig/src/anvil/test-penalty.c dovecot-2.2.21/src/anvil/test-penalty.c
--- dovecot-2.2.21.orig/src/anvil/test-penalty.c 2015-12-09 16:39:10.000000000 +0100
+++ dovecot-2.2.21/src/anvil/test-penalty.c 2016-02-17 02:28:07.724478886 +0100
@@ -18,9 +18,10 @@
penalty = penalty_init();
test_assert(penalty_get(penalty, "foo", &t) == 0);
+ penalty_set(penalty, "foo", 5);
for (i = 1; i <= 10; i++) {
ioloop_time = 12345678 + i;
- penalty_inc(penalty, "foo", i, 5+i);
+ penalty_inc(penalty, "foo", i);
for (j = I_MIN(1, i-1); j <= i; j++) {
test_assert(penalty_get(penalty, "foo", &t) == 5+i);
@@ -31,20 +32,20 @@
test_assert(t == (time_t)(12345678 + i));
test_assert(!penalty_has_checksum(penalty, "foo", j));
}
- test_assert(penalty_get(penalty, "foo2", &t) == 0);
/* overflows checksum array */
ioloop_time = 12345678 + i;
- penalty_inc(penalty, "foo", i, 5 + i);
- penalty_inc(penalty, "foo", i, 5 + i);
- penalty_inc(penalty, "foo", 0, 5 + i);
+ penalty_set(penalty, "foo", 5+i);
+ penalty_inc(penalty, "foo", i);
+ penalty_inc(penalty, "foo", i);
+ penalty_inc(penalty, "foo", 0);
- test_assert(penalty_get(penalty, "foo", &t) == 5+i);
+ test_assert(penalty_get(penalty, "foo", &t) == 5+2+i);
test_assert(t == (time_t)(12345678 + i));
test_assert(!penalty_has_checksum(penalty, "foo", 1));
for (j = 2; j <= i; j++) {
- test_assert(penalty_get(penalty, "foo", &t) == 5+i);
+ test_assert(penalty_get(penalty, "foo", &t) == 5+2+i);
test_assert(t == (time_t)(12345678 + i));
test_assert(penalty_has_checksum(penalty, "foo", i));
}
diff -Naur dovecot-2.2.21.orig/src/auth/auth-penalty.c dovecot-2.2.21/src/auth/auth-penalty.c
--- dovecot-2.2.21.orig/src/auth/auth-penalty.c 2015-12-09 16:39:10.000000000 +0100
+++ dovecot-2.2.21/src/auth/auth-penalty.c 2016-02-17 02:28:14.849599750 +0100
@@ -39,6 +39,8 @@
else {
anvil_client_cmd(penalty->client, t_strdup_printf(
"PENALTY-SET-EXPIRE-SECS\t%u", AUTH_PENALTY_TIMEOUT));
+ anvil_client_cmd(penalty->client, t_strdup_printf(
+ "PENALTY-SET-MAX-PENALTY\t%u", AUTH_PENALTY_MAX_PENALTY));
}
return penalty;
}
@@ -149,7 +151,7 @@
auth_request->user);
}
-void auth_penalty_update(struct auth_penalty *penalty,
+void auth_penalty_set(struct auth_penalty *penalty,
struct auth_request *auth_request, unsigned int value)
{
const char *ident;
@@ -158,18 +160,29 @@
if (penalty->disabled || ident == NULL || auth_request->no_penalty)
return;
- if (value > AUTH_PENALTY_MAX_PENALTY) {
- /* even if the actual value doesn't change, the last_change
- timestamp does. */
- value = AUTH_PENALTY_MAX_PENALTY;
- }
+ T_BEGIN {
+ const char *cmd;
+
+ cmd = t_strdup_printf("PENALTY-SET\t%s\t%u", ident, value);
+ anvil_client_cmd(penalty->client, cmd);
+ } T_END;
+}
+
+void auth_penalty_inc(struct auth_penalty *penalty,
+ struct auth_request *auth_request)
+{
+ const char *ident;
+
+ ident = auth_penalty_get_ident(auth_request);
+ if (penalty->disabled || ident == NULL || auth_request->no_penalty)
+ return;
+
T_BEGIN {
const char *cmd;
unsigned int checksum;
- checksum = value == 0 ? 0 : get_userpass_checksum(auth_request);
- cmd = t_strdup_printf("PENALTY-INC\t%s\t%u\t%u",
- ident, checksum, value);
+ checksum = get_userpass_checksum(auth_request);
+ cmd = t_strdup_printf("PENALTY-INC\t%s\t%u", ident, checksum);
anvil_client_cmd(penalty->client, cmd);
} T_END;
}
diff -Naur dovecot-2.2.21.orig/src/auth/auth-penalty.h dovecot-2.2.21/src/auth/auth-penalty.h
--- dovecot-2.2.21.orig/src/auth/auth-penalty.h 2015-12-09 16:39:10.000000000 +0100
+++ dovecot-2.2.21/src/auth/auth-penalty.h 2016-02-17 02:29:25.160792445 +0100
@@ -22,7 +22,9 @@
void auth_penalty_lookup(struct auth_penalty *penalty,
struct auth_request *auth_request,
auth_penalty_callback_t *callback);
-void auth_penalty_update(struct auth_penalty *penalty,
+void auth_penalty_set(struct auth_penalty *penalty,
struct auth_request *auth_request, unsigned int value);
+void auth_penalty_inc(struct auth_penalty *penalty,
+ struct auth_request *auth_request);
#endif
diff -Naur dovecot-2.2.21.orig/src/auth/auth-request-handler.c dovecot-2.2.21/src/auth/auth-request-handler.c
--- dovecot-2.2.21.orig/src/auth/auth-request-handler.c 2015-12-09 16:39:10.000000000 +0100
+++ dovecot-2.2.21/src/auth/auth-request-handler.c 2016-02-17 02:28:14.857599885 +0100
@@ -228,8 +228,7 @@
handler->refcount++;
if (auth_penalty != NULL) {
- auth_penalty_update(auth_penalty, request,
- request->last_penalty + 1);
+ auth_penalty_inc(auth_penalty, request);
}
auth_request_refresh_last_access(request);
@@ -249,7 +248,7 @@
if (request->last_penalty != 0 && auth_penalty != NULL) {
/* reset penalty */
- auth_penalty_update(auth_penalty, request, 0);
+ auth_penalty_set(auth_penalty, request, 0);
}
/* sanitize these fields, since the login code currently assumes they