Download | Plain Text | No Line Numbers


  1. diff -Naur dovecot-2.2.21.orig/src/anvil/anvil-connection.c dovecot-2.2.21/src/anvil/anvil-connection.c
  2. --- dovecot-2.2.21.orig/src/anvil/anvil-connection.c 2015-12-09 16:39:10.000000000 +0100
  3. +++ dovecot-2.2.21/src/anvil/anvil-connection.c 2016-02-17 02:28:07.713478699 +0100
  4. @@ -109,18 +109,26 @@
  5. o_stream_nsend_str(conn->output,
  6. t_strdup_printf("%u %s\n", value, dec2str(stamp)));
  7. } else if (strcmp(cmd, "PENALTY-INC") == 0) {
  8. - if (args[0] == NULL || args[1] == NULL || args[2] == NULL) {
  9. + if (args[0] == NULL || args[1] == NULL) {
  10. *error_r = "PENALTY-INC: Not enough parameters";
  11. return -1;
  12. }
  13. - if (str_to_uint(args[1], &checksum) < 0 ||
  14. - str_to_uint(args[2], &value) < 0 ||
  15. - value > PENALTY_MAX_VALUE ||
  16. - (value == 0 && checksum != 0)) {
  17. + if (str_to_uint(args[1], &checksum) < 0) {
  18. *error_r = "PENALTY-INC: Invalid parameters";
  19. return -1;
  20. }
  21. - penalty_inc(penalty, args[0], checksum, value);
  22. + penalty_inc(penalty, args[0], checksum);
  23. + } else if (strcmp(cmd, "PENALTY-SET") == 0) {
  24. + if (args[0] == NULL) {
  25. + *error_r = "PENALTY-INC: Not enough parameters";
  26. + return -1;
  27. + }
  28. + if (str_to_uint(args[1], &value) < 0 ||
  29. + value > PENALTY_MAX_VALUE) {
  30. + *error_r = "PENALTY-SET: Invalid parameters";
  31. + return -1;
  32. + }
  33. + penalty_set(penalty, args[0], value);
  34. } else if (strcmp(cmd, "PENALTY-SET-EXPIRE-SECS") == 0) {
  35. if (args[0] == NULL || str_to_uint(args[0], &value) < 0) {
  36. *error_r = "PENALTY-SET-EXPIRE-SECS: "
  37. @@ -128,6 +136,14 @@
  38. return -1;
  39. }
  40. penalty_set_expire_secs(penalty, value);
  41. + } else if (strcmp(cmd, "PENALTY-SET-MAX-PENALTY") == 0) {
  42. + if (args[0] == NULL || str_to_uint(args[0], &value) < 0 ||
  43. + value > PENALTY_MAX_VALUE) {
  44. + *error_r = "PENALTY-SET-MAX-PENALTY: "
  45. + "Invalid parameters";
  46. + return -1;
  47. + }
  48. + penalty_set_max_penalty(penalty, value);
  49. } else if (strcmp(cmd, "PENALTY-DUMP") == 0) {
  50. penalty_dump(penalty, conn->output);
  51. } else {
  52. diff -Naur dovecot-2.2.21.orig/src/anvil/penalty.c dovecot-2.2.21/src/anvil/penalty.c
  53. --- dovecot-2.2.21.orig/src/anvil/penalty.c 2015-12-09 16:39:10.000000000 +0100
  54. +++ dovecot-2.2.21/src/anvil/penalty.c 2016-02-17 02:28:07.723478869 +0100
  55. @@ -16,6 +16,7 @@
  56. #include <time.h>
  57.  
  58. #define PENALTY_DEFAULT_EXPIRE_SECS (60*60)
  59. +#define PENALTY_DEFAULT_MAX_PENALTY 100
  60. #define PENALTY_CHECKSUM_SAVE_COUNT
  61. #define CHECKSUM_VALUE_COUNT 2
  62. #define CHECKSUM_VALUE_PTR_COUNT 10
  63. @@ -46,6 +47,7 @@
  64. struct penalty_rec *oldest, *newest;
  65.  
  66. unsigned int expire_secs;
  67. + unsigned int max_penalty:16;
  68. struct timeout *to;
  69. };
  70.  
  71. @@ -56,6 +58,7 @@
  72. penalty = i_new(struct penalty, 1);
  73. hash_table_create(&penalty->hash, default_pool, 0, str_hash, strcmp);
  74. penalty->expire_secs = PENALTY_DEFAULT_EXPIRE_SECS;
  75. + penalty->max_penalty = PENALTY_DEFAULT_MAX_PENALTY;
  76. return penalty;
  77. }
  78.  
  79. @@ -88,6 +91,11 @@
  80. penalty->expire_secs = expire_secs;
  81. }
  82.  
  83. +void penalty_set_max_penalty(struct penalty *penalty, unsigned int max_penalty)
  84. +{
  85. + penalty->max_penalty = max_penalty;
  86. +}
  87. +
  88. static bool
  89. penalty_bump_checksum(struct penalty_rec *rec, unsigned int checksum)
  90. {
  91. @@ -183,51 +191,84 @@
  92. }
  93. }
  94.  
  95. -void penalty_inc(struct penalty *penalty, const char *ident,
  96. - unsigned int checksum, unsigned int value)
  97. +static void penalty_update_times(struct penalty *penalty,
  98. + struct penalty_rec *rec)
  99. {
  100. - struct penalty_rec *rec;
  101. time_t diff;
  102.  
  103. - i_assert(value > 0 || checksum == 0);
  104. - i_assert(value <= INT_MAX);
  105. + diff = ioloop_time - rec->last_penalty;
  106. + if (diff >= (1 << LAST_UPDATE_BITS)) {
  107. + rec->last_update = (1 << LAST_UPDATE_BITS) - 1;
  108. + rec->last_penalty = ioloop_time - rec->last_update;
  109. + } else {
  110. + rec->last_update = diff;
  111. + }
  112. +
  113. + if (penalty->to == NULL) {
  114. + penalty->to = timeout_add(penalty->expire_secs * 1000,
  115. + penalty_timeout, penalty);
  116. + }
  117. +}
  118. +
  119. +void penalty_inc(struct penalty *penalty, const char *ident,
  120. + unsigned int checksum)
  121. +{
  122. + struct penalty_rec *rec;
  123. + unsigned int new_penalty;
  124.  
  125. rec = hash_table_lookup(penalty->hash, ident);
  126. if (rec == NULL) {
  127. rec = i_new(struct penalty_rec, 1);
  128. rec->ident = i_strdup(ident);
  129. + rec->penalty = 1;
  130. + rec->last_penalty = ioloop_time;
  131. hash_table_insert(penalty->hash, rec->ident, rec);
  132. + if (checksum != 0)
  133. + penalty_add_checksum(rec, checksum);
  134. } else {
  135. DLLIST2_REMOVE(&penalty->oldest, &penalty->newest, rec);
  136. - }
  137.  
  138. - if (checksum == 0) {
  139. - rec->penalty = value;
  140. - rec->last_penalty = ioloop_time;
  141. - } else {
  142. - if (penalty_bump_checksum(rec, checksum))
  143. - rec->penalty = value - 1;
  144. - else {
  145. - penalty_add_checksum(rec, checksum);
  146. - rec->penalty = value;
  147. + new_penalty = rec->penalty;
  148. + if (checksum == 0) {
  149. + new_penalty++;
  150. rec->last_penalty = ioloop_time;
  151. + } else {
  152. + if (!penalty_bump_checksum(rec, checksum)) {
  153. + penalty_add_checksum(rec, checksum);
  154. + new_penalty++;
  155. + rec->last_penalty = ioloop_time;
  156. + }
  157. }
  158. + rec->penalty = (new_penalty < penalty->max_penalty) ?
  159. + new_penalty : penalty->max_penalty;
  160. }
  161.  
  162. - diff = ioloop_time - rec->last_penalty;
  163. - if (diff >= (1 << LAST_UPDATE_BITS)) {
  164. - rec->last_update = (1 << LAST_UPDATE_BITS) - 1;
  165. - rec->last_penalty = ioloop_time - rec->last_update;
  166. + penalty_update_times(penalty, rec);
  167. + DLLIST2_APPEND(&penalty->oldest, &penalty->newest, rec);
  168. +}
  169. +
  170. +void penalty_set(struct penalty *penalty, const char *ident,
  171. + unsigned int value)
  172. +{
  173. + struct penalty_rec *rec;
  174. +
  175. + rec = hash_table_lookup(penalty->hash, ident);
  176. + if (rec == NULL) {
  177. + if (value == 0)
  178. + return;
  179. + rec = i_new(struct penalty_rec, 1);
  180. + rec->ident = i_strdup(ident);
  181. + hash_table_insert(penalty->hash, rec->ident, rec);
  182. } else {
  183. - rec->last_update = diff;
  184. + DLLIST2_REMOVE(&penalty->oldest, &penalty->newest, rec);
  185. }
  186.  
  187. - DLLIST2_APPEND(&penalty->oldest, &penalty->newest, rec);
  188. + rec->penalty = (value < penalty->max_penalty) ? value :
  189. + penalty->max_penalty;
  190. + rec->last_penalty = ioloop_time;
  191.  
  192. - if (penalty->to == NULL) {
  193. - penalty->to = timeout_add(penalty->expire_secs * 1000,
  194. - penalty_timeout, penalty);
  195. - }
  196. + penalty_update_times(penalty, rec);
  197. + DLLIST2_APPEND(&penalty->oldest, &penalty->newest, rec);
  198. }
  199.  
  200. bool penalty_has_checksum(struct penalty *penalty, const char *ident,
  201. diff -Naur dovecot-2.2.21.orig/src/anvil/penalty.h dovecot-2.2.21/src/anvil/penalty.h
  202. --- dovecot-2.2.21.orig/src/anvil/penalty.h 2015-12-09 16:39:10.000000000 +0100
  203. +++ dovecot-2.2.21/src/anvil/penalty.h 2016-02-17 02:28:07.724478886 +0100
  204. @@ -7,13 +7,14 @@
  205. void penalty_deinit(struct penalty **penalty);
  206.  
  207. void penalty_set_expire_secs(struct penalty *penalty, unsigned int expire_secs);
  208. +void penalty_set_max_penalty(struct penalty *penalty, unsigned int max_penalty);
  209.  
  210. unsigned int penalty_get(struct penalty *penalty, const char *ident,
  211. time_t *last_penalty_r);
  212. -/* if checksum is non-zero and it already exists for ident, the value
  213. - is set to "value-1", otherwise it's set to "value". */
  214. void penalty_inc(struct penalty *penalty, const char *ident,
  215. - unsigned int checksum, unsigned int value);
  216. + unsigned int checksum);
  217. +void penalty_set(struct penalty *penalty, const char *ident,
  218. + unsigned int value);
  219.  
  220. bool penalty_has_checksum(struct penalty *penalty, const char *ident,
  221. unsigned int checksum);
  222. diff -Naur dovecot-2.2.21.orig/src/anvil/test-penalty.c dovecot-2.2.21/src/anvil/test-penalty.c
  223. --- dovecot-2.2.21.orig/src/anvil/test-penalty.c 2015-12-09 16:39:10.000000000 +0100
  224. +++ dovecot-2.2.21/src/anvil/test-penalty.c 2016-02-17 02:28:07.724478886 +0100
  225. @@ -18,9 +18,10 @@
  226. penalty = penalty_init();
  227.  
  228. test_assert(penalty_get(penalty, "foo", &t) == 0);
  229. + penalty_set(penalty, "foo", 5);
  230. for (i = 1; i <= 10; i++) {
  231. ioloop_time = 12345678 + i;
  232. - penalty_inc(penalty, "foo", i, 5+i);
  233. + penalty_inc(penalty, "foo", i);
  234.  
  235. for (j = I_MIN(1, i-1); j <= i; j++) {
  236. test_assert(penalty_get(penalty, "foo", &t) == 5+i);
  237. @@ -31,20 +32,20 @@
  238. test_assert(t == (time_t)(12345678 + i));
  239. test_assert(!penalty_has_checksum(penalty, "foo", j));
  240. }
  241. - test_assert(penalty_get(penalty, "foo2", &t) == 0);
  242.  
  243. /* overflows checksum array */
  244. ioloop_time = 12345678 + i;
  245. - penalty_inc(penalty, "foo", i, 5 + i);
  246. - penalty_inc(penalty, "foo", i, 5 + i);
  247. - penalty_inc(penalty, "foo", 0, 5 + i);
  248. + penalty_set(penalty, "foo", 5+i);
  249. + penalty_inc(penalty, "foo", i);
  250. + penalty_inc(penalty, "foo", i);
  251. + penalty_inc(penalty, "foo", 0);
  252.  
  253. - test_assert(penalty_get(penalty, "foo", &t) == 5+i);
  254. + test_assert(penalty_get(penalty, "foo", &t) == 5+2+i);
  255. test_assert(t == (time_t)(12345678 + i));
  256. test_assert(!penalty_has_checksum(penalty, "foo", 1));
  257.  
  258. for (j = 2; j <= i; j++) {
  259. - test_assert(penalty_get(penalty, "foo", &t) == 5+i);
  260. + test_assert(penalty_get(penalty, "foo", &t) == 5+2+i);
  261. test_assert(t == (time_t)(12345678 + i));
  262. test_assert(penalty_has_checksum(penalty, "foo", i));
  263. }
  264. diff -Naur dovecot-2.2.21.orig/src/auth/auth-penalty.c dovecot-2.2.21/src/auth/auth-penalty.c
  265. --- dovecot-2.2.21.orig/src/auth/auth-penalty.c 2015-12-09 16:39:10.000000000 +0100
  266. +++ dovecot-2.2.21/src/auth/auth-penalty.c 2016-02-17 02:28:14.849599750 +0100
  267. @@ -39,6 +39,8 @@
  268. else {
  269. anvil_client_cmd(penalty->client, t_strdup_printf(
  270. "PENALTY-SET-EXPIRE-SECS\t%u", AUTH_PENALTY_TIMEOUT));
  271. + anvil_client_cmd(penalty->client, t_strdup_printf(
  272. + "PENALTY-SET-MAX-PENALTY\t%u", AUTH_PENALTY_MAX_PENALTY));
  273. }
  274. return penalty;
  275. }
  276. @@ -149,7 +151,7 @@
  277. auth_request->user);
  278. }
  279.  
  280. -void auth_penalty_update(struct auth_penalty *penalty,
  281. +void auth_penalty_set(struct auth_penalty *penalty,
  282. struct auth_request *auth_request, unsigned int value)
  283. {
  284. const char *ident;
  285. @@ -158,18 +160,29 @@
  286. if (penalty->disabled || ident == NULL || auth_request->no_penalty)
  287. return;
  288.  
  289. - if (value > AUTH_PENALTY_MAX_PENALTY) {
  290. - /* even if the actual value doesn't change, the last_change
  291. - timestamp does. */
  292. - value = AUTH_PENALTY_MAX_PENALTY;
  293. - }
  294. + T_BEGIN {
  295. + const char *cmd;
  296. +
  297. + cmd = t_strdup_printf("PENALTY-SET\t%s\t%u", ident, value);
  298. + anvil_client_cmd(penalty->client, cmd);
  299. + } T_END;
  300. +}
  301. +
  302. +void auth_penalty_inc(struct auth_penalty *penalty,
  303. + struct auth_request *auth_request)
  304. +{
  305. + const char *ident;
  306. +
  307. + ident = auth_penalty_get_ident(auth_request);
  308. + if (penalty->disabled || ident == NULL || auth_request->no_penalty)
  309. + return;
  310. +
  311. T_BEGIN {
  312. const char *cmd;
  313. unsigned int checksum;
  314.  
  315. - checksum = value == 0 ? 0 : get_userpass_checksum(auth_request);
  316. - cmd = t_strdup_printf("PENALTY-INC\t%s\t%u\t%u",
  317. - ident, checksum, value);
  318. + checksum = get_userpass_checksum(auth_request);
  319. + cmd = t_strdup_printf("PENALTY-INC\t%s\t%u", ident, checksum);
  320. anvil_client_cmd(penalty->client, cmd);
  321. } T_END;
  322. }
  323. diff -Naur dovecot-2.2.21.orig/src/auth/auth-penalty.h dovecot-2.2.21/src/auth/auth-penalty.h
  324. --- dovecot-2.2.21.orig/src/auth/auth-penalty.h 2015-12-09 16:39:10.000000000 +0100
  325. +++ dovecot-2.2.21/src/auth/auth-penalty.h 2016-02-17 02:29:25.160792445 +0100
  326. @@ -22,7 +22,9 @@
  327. void auth_penalty_lookup(struct auth_penalty *penalty,
  328. struct auth_request *auth_request,
  329. auth_penalty_callback_t *callback);
  330. -void auth_penalty_update(struct auth_penalty *penalty,
  331. +void auth_penalty_set(struct auth_penalty *penalty,
  332. struct auth_request *auth_request, unsigned int value);
  333. +void auth_penalty_inc(struct auth_penalty *penalty,
  334. + struct auth_request *auth_request);
  335.  
  336. #endif
  337. diff -Naur dovecot-2.2.21.orig/src/auth/auth-request-handler.c dovecot-2.2.21/src/auth/auth-request-handler.c
  338. --- dovecot-2.2.21.orig/src/auth/auth-request-handler.c 2015-12-09 16:39:10.000000000 +0100
  339. +++ dovecot-2.2.21/src/auth/auth-request-handler.c 2016-02-17 02:28:14.857599885 +0100
  340. @@ -228,8 +228,7 @@
  341. handler->refcount++;
  342.  
  343. if (auth_penalty != NULL) {
  344. - auth_penalty_update(auth_penalty, request,
  345. - request->last_penalty + 1);
  346. + auth_penalty_inc(auth_penalty, request);
  347. }
  348.  
  349. auth_request_refresh_last_access(request);
  350. @@ -249,7 +248,7 @@
  351.  
  352. if (request->last_penalty != 0 && auth_penalty != NULL) {
  353. /* reset penalty */
  354. - auth_penalty_update(auth_penalty, request, 0);
  355. + auth_penalty_set(auth_penalty, request, 0);
  356. }
  357.  
  358. /* sanitize these fields, since the login code currently assumes they
  359.