diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/config/all-settings.c dovecot-2.3.21/src/config/all-settings.c --- dovecot-2.3.21-orig/src/config/all-settings.c 2023-09-14 15:18:20.000000000 +0200 +++ dovecot-2.3.21/src/config/all-settings.c 2024-06-09 11:31:45.820319492 +0200 @@ -1750,6 +1750,7 @@ struct pop3_settings { bool verbose_proctitle; const char *rawlog_dir; + unsigned int max_bad_commands; /* pop3: */ bool pop3_no_flag_updates; @@ -1849,6 +1850,10 @@ unsigned int mail_max_userip_connections; + const char *rbl_check; + unsigned int rbl_check_timeout; + unsigned int max_login_command_errors; + /* generated: */ char *const *log_format_elements_split; }; @@ -1907,6 +1912,7 @@ struct imap_settings { bool verbose_proctitle; const char *rawlog_dir; + unsigned int max_command_errors; /* imap: */ uoff_t imap_max_line_length; @@ -3277,6 +3283,7 @@ static const struct setting_define pop3_setting_defines[] = { DEF(BOOL, verbose_proctitle), DEF(STR_VARS, rawlog_dir), + DEF(UINT, max_bad_commands), DEF(BOOL, pop3_no_flag_updates), DEF(BOOL, pop3_enable_last), @@ -3295,6 +3302,7 @@ static const struct pop3_settings pop3_default_settings = { .verbose_proctitle = FALSE, .rawlog_dir = "", + .max_bad_commands = 20, .pop3_no_flag_updates = FALSE, .pop3_enable_last = FALSE, @@ -4183,6 +4191,10 @@ DEF(UINT, mail_max_userip_connections), + DEF(STR, rbl_check), + DEF(TIME_MSECS, rbl_check_timeout), + DEF(UINT, max_login_command_errors), + SETTING_DEFINE_LIST_END }; static const struct login_settings login_default_settings = { @@ -4209,7 +4221,11 @@ .auth_debug = FALSE, .verbose_proctitle = FALSE, - .mail_max_userip_connections = 10 + .mail_max_userip_connections = 10, + + .rbl_check = "", + .rbl_check_timeout = 10*1000, + .max_login_command_errors = 3 }; const struct setting_parser_info login_setting_parser_info = { .module_name = "login", @@ -4656,6 +4672,7 @@ static const struct setting_define imap_setting_defines[] = { DEF(BOOL, verbose_proctitle), DEF(STR_VARS, rawlog_dir), + DEF(UINT, max_command_errors), DEF(SIZE, imap_max_line_length), DEF(TIME, imap_idle_notify_interval), @@ -4677,6 +4694,7 @@ static const struct imap_settings imap_default_settings = { .verbose_proctitle = FALSE, .rawlog_dir = "", + .max_command_errors = 20, /* RFC-2683 recommends at least 8000 bytes. Some clients however don't break large message sets to multiple commands, so we're pretty diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/imap/imap-client.c dovecot-2.3.21/src/imap/imap-client.c --- dovecot-2.3.21-orig/src/imap/imap-client.c 2023-09-14 15:17:46.000000000 +0200 +++ dovecot-2.3.21/src/imap/imap-client.c 2024-06-09 11:08:27.416859461 +0200 @@ -726,7 +726,7 @@ client_send_tagline(cmd, error); - if (++client->bad_counter >= CLIENT_MAX_BAD_COMMANDS) { + if (++client->bad_counter >= client->set->max_command_errors) { client_disconnect_with_error(client, "Too many invalid IMAP commands."); } diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/imap/imap-common.h dovecot-2.3.21/src/imap/imap-common.h --- dovecot-2.3.21-orig/src/imap/imap-common.h 2023-09-14 15:17:46.000000000 +0200 +++ dovecot-2.3.21/src/imap/imap-common.h 2024-06-09 11:08:27.417859463 +0200 @@ -10,9 +10,6 @@ /* Stop buffering more data into output stream after this many bytes */ #define CLIENT_OUTPUT_OPTIMAL_SIZE 2048 -/* Disconnect client when it sends too many bad commands in a row */ -#define CLIENT_MAX_BAD_COMMANDS 20 - #include "lib.h" #include "imap-client.h" #include "imap-settings.h" diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/imap/imap-settings.c dovecot-2.3.21/src/imap/imap-settings.c --- dovecot-2.3.21-orig/src/imap/imap-settings.c 2023-09-14 15:17:46.000000000 +0200 +++ dovecot-2.3.21/src/imap/imap-settings.c 2024-06-09 11:08:27.417859463 +0200 @@ -67,6 +67,7 @@ static const struct setting_define imap_setting_defines[] = { DEF(BOOL, verbose_proctitle), DEF(STR_VARS, rawlog_dir), + DEF(UINT, max_command_errors), DEF(SIZE, imap_max_line_length), DEF(TIME, imap_idle_notify_interval), @@ -89,6 +90,7 @@ static const struct imap_settings imap_default_settings = { .verbose_proctitle = FALSE, .rawlog_dir = "", + .max_command_errors = 20, /* RFC-2683 recommends at least 8000 bytes. Some clients however don't break large message sets to multiple commands, so we're pretty diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/imap/imap-settings.h dovecot-2.3.21/src/imap/imap-settings.h --- dovecot-2.3.21-orig/src/imap/imap-settings.h 2023-09-14 15:17:46.000000000 +0200 +++ dovecot-2.3.21/src/imap/imap-settings.h 2024-06-09 11:08:27.417859463 +0200 @@ -22,6 +22,7 @@ struct imap_settings { bool verbose_proctitle; const char *rawlog_dir; + unsigned int max_command_errors; /* imap: */ uoff_t imap_max_line_length; diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/imap-login/imap-login-client.c dovecot-2.3.21/src/imap-login/imap-login-client.c --- dovecot-2.3.21-orig/src/imap-login/imap-login-client.c 2023-09-14 15:17:46.000000000 +0200 +++ dovecot-2.3.21/src/imap-login/imap-login-client.c 2024-06-09 11:08:27.417859463 +0200 @@ -25,9 +25,6 @@ # error LOGIN_MAX_INBUF_SIZE too short to fit all ID command parameters #endif -/* Disconnect client when it sends too many bad commands */ -#define CLIENT_MAX_BAD_COMMANDS 3 - /* Skip incoming data until newline is found, returns TRUE if newline was found. */ bool client_skip_line(struct imap_client *client) @@ -197,7 +194,7 @@ { if (client->cmd_tag == NULL || *client->cmd_tag == '\0') client->cmd_tag = "*"; - if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) { + if (++client->common.bad_counter >= client->common.set->max_login_command_errors) { client_send_reply(&client->common, IMAP_CMD_REPLY_BYE, "Too many invalid IMAP commands."); client_destroy(&client->common, "Too many invalid commands"); diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/lib/net.c dovecot-2.3.21/src/lib/net.c --- dovecot-2.3.21-orig/src/lib/net.c 2023-09-14 15:17:47.000000000 +0200 +++ dovecot-2.3.21/src/lib/net.c 2024-06-09 11:08:27.418859465 +0200 @@ -8,8 +8,10 @@ #include #include #include +#include #include #include +#include #if defined(HAVE_UCRED_H) # include /* for getpeerucred() */ #elif defined(HAVE_SYS_UCRED_H) @@ -898,6 +900,60 @@ return addr; } +const char *net_ip2raddr(const struct ip_addr *ip) +{ + char *raddr = t_malloc_no0(MAX_IP_LEN*2); + if (inet_rntop(ip->family, &ip->u.ip6, raddr, MAX_IP_LEN*2) == NULL) { + return ""; + } + return raddr; +} + +static const char * inet_rntop4 (const u_char *src, char *dst, socklen_t size) +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + if ((socklen_t)sprintf(tmp, fmt, src[3], src[2], src[1], src[0]) >= size) { + return (NULL); + } + return strcpy(dst, tmp); +} + +static const char * inet_rntop6 (const u_char *src, char *dst, socklen_t size) +{ + char tmp[MAX_IP_LEN*2], buf[3],*tp; + int i; + tp = tmp; + for (i=15;i>0;i--) { + sprintf(buf,"%02x",src[i]); + *tp++ = buf[1]; + *tp++ = '.'; + *tp++ = buf[0]; + *tp++ = '.'; + } + sprintf(buf,"%02x",src[0]); + *tp++ = buf[1]; + *tp++ = '.'; + *tp++ = buf[0]; + *tp = '\0'; + if ((socklen_t)(tp - tmp) > size) { + return (NULL); + } + return strcpy(dst, tmp); +} + +const char * inet_rntop (int af, const void *src, char *dst, socklen_t size) +{ + switch (af) { + case AF_INET: + return (inet_rntop4(src, dst, size)); + case AF_INET6: + return (inet_rntop6(src, dst, size)); + default: + return (NULL); + } +} + static bool net_addr2ip_inet4_fast(const char *addr, struct ip_addr *ip) { uint8_t *saddr = (void *)&ip->u.ip4.s_addr; @@ -1235,3 +1291,34 @@ } return TRUE; } + +bool net_rbl_match(const char * ip, const char * filter) +{ + regex_t regex; + int ret; + + /* Compile regular expression */ + ret = regcomp(®ex, filter, 0); + if (ret) { + i_error("Could not compile regex"); + return FALSE; + } + + /* Execute regular expression */ + ret = regexec(®ex, ip, 0, NULL, 0); + if (!ret) { + regfree(®ex); + return TRUE; + } + else if (ret == REG_NOMATCH) { + regfree(®ex); + return FALSE; + } + else { + i_error("Regex match failed"); + return FALSE; + } +} + + + diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/lib/net.h dovecot-2.3.21/src/lib/net.h --- dovecot-2.3.21-orig/src/lib/net.h 2023-09-14 15:17:47.000000000 +0200 +++ dovecot-2.3.21/src/lib/net.h 2024-06-09 11:08:27.419859467 +0200 @@ -155,6 +155,11 @@ /* Returns ip_addr as string, or "" if ip isn't valid IPv4 or IPv6 address. */ const char *net_ip2addr(const struct ip_addr *ip); + +const char *net_ip2raddr(const struct ip_addr *ip); + +const char * inet_rntop (int af, const void *src, char *dst, socklen_t size); + /* char* -> struct ip_addr translation. */ int net_addr2ip(const char *addr, struct ip_addr *ip); /* char* -> in_port_t translation */ @@ -196,4 +201,5 @@ bool net_is_in_network(const struct ip_addr *ip, const struct ip_addr *net_ip, unsigned int bits) ATTR_PURE; +bool net_rbl_match(const char * ip, const char * filter); #endif diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/login-common/client-common.c dovecot-2.3.21/src/login-common/client-common.c --- dovecot-2.3.21-orig/src/login-common/client-common.c 2023-09-14 15:17:47.000000000 +0200 +++ dovecot-2.3.21/src/login-common/client-common.c 2024-06-09 14:10:29.805269915 +0200 @@ -29,6 +29,7 @@ #include "dsasl-client.h" #include "login-proxy.h" #include "client-common.h" +#include "dns-lookup.h" struct client *clients = NULL; struct client *destroyed_clients = NULL; @@ -232,8 +233,62 @@ return client; } +static void +dns_lookup_callback(const struct dns_lookup_result *result, + struct rbl_context * r) +{ + const char *user_reason, *destroy_reason; + if (result->ret != 0) + { + i_info("rbl_check negative, cannot resolve': %s", result->error); + client_init_continue(r->client); + } + else + { + i_info("rbl_check got %d IPs", result->ips_count); + int match = FALSE; + for (unsigned int i = 0; iips_count; i++) { + if (net_rbl_match(net_ip2addr(&result->ips[i]),r->filter)) { + match = TRUE; + i_info("ip: %s filter %s match",net_ip2addr(&result->ips[i]),r->filter); + } else { + i_info("ip: %s filter %s no match",net_ip2addr(&result->ips[i]),r->filter); + } + } + if (match) { + user_reason = "Disconnected for policy."; + destroy_reason = "Policy"; + client_notify_disconnect(r->client, CLIENT_DISCONNECT_POLICY, user_reason); + client_destroy(r->client, destroy_reason); + } else { + i_info("No match"); + client_init_continue(r->client); + } + } + free(r->filter); + free(r); +} + +void client_init_continue(struct client * client) +{ + client->access_checks_done = TRUE; + if (auth_client_is_connected(auth_client)) + client_notify_auth_ready(client); + else + client_set_auth_waiting(client); + login_refresh_proctitle(); +} + void client_init(struct client *client, void **other_sets) { + struct dns_lookup_settings dns_set; + struct dns_lookup *lookup; + char * revip = (char *) malloc(MAX_IP_LEN*2+strlen(client->set->rbl_check)+1); + char * rbl = (char *) malloc(strlen(client->set->rbl_check)+1); + char * filter = (char *) malloc(100); + char * sep; + int rbl_len; + if (last_client == NULL) last_client = client; client->list_type = CLIENT_LIST_TYPE_ACTIVE; @@ -247,15 +302,40 @@ hook_login_client_allocated(client); client->v.create(client, other_sets); client->create_finished = TRUE; + client->access_checks_done = FALSE; - if (auth_client_is_connected(auth_client)) - client_notify_auth_ready(client); - else - client_set_auth_waiting(client); - - login_refresh_proctitle(); + i_debug("listner name %s login remote ip: %s rbl_check: %s",client->listener_name,net_ip2addr(&client->real_remote_ip),client->set->rbl_check); + if (strlen(client->set->rbl_check)>0) { + sep = strchr(client->set->rbl_check,'='); + if (sep == NULL) { + strcpy(rbl,client->set->rbl_check); + filter[0] ='\0'; + } else { + rbl_len = sep-client->set->rbl_check; + strncpy(rbl,client->set->rbl_check,rbl_len); + rbl[rbl_len]='\0'; + if(*(sep+1) != '\0') { + strcpy(filter,sep+1); + } + } + i_zero(&dns_set); + dns_set.dns_client_socket_path = DNS_CLIENT_SOCKET_NAME; + dns_set.timeout_msecs = client->set->rbl_check_timeout; + dns_set.event_parent = client->event; + sprintf(revip,"%s.%s",net_ip2raddr(&client->real_remote_ip),rbl); + struct rbl_context * r = ( struct rbl_context *) malloc(sizeof(struct rbl_context)); + r->client = client; + r->filter = filter; + i_info("rbl_check: %s",revip); + dns_lookup(revip, &dns_set, dns_lookup_callback, r, &lookup); + } + else { + i_info("No rbl check"); + client_init_continue(client); + } } + void client_disconnect(struct client *client, const char *reason, bool add_disconnected_prefix) { @@ -1124,7 +1204,7 @@ void client_notify_auth_ready(struct client *client) { - if (!client->notified_auth_ready) { + if (client->access_checks_done && !client->notified_auth_ready) { if (client->v.notify_auth_ready != NULL) client->v.notify_auth_ready(client); client->notified_auth_ready = TRUE; diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/login-common/client-common.h dovecot-2.3.21/src/login-common/client-common.h --- dovecot-2.3.21-orig/src/login-common/client-common.h 2023-09-14 15:17:47.000000000 +0200 +++ dovecot-2.3.21/src/login-common/client-common.h 2024-06-09 14:09:28.885136093 +0200 @@ -47,7 +47,8 @@ CLIENT_DISCONNECT_TIMEOUT, CLIENT_DISCONNECT_SYSTEM_SHUTDOWN, CLIENT_DISCONNECT_RESOURCE_CONSTRAINT, - CLIENT_DISCONNECT_INTERNAL_ERROR + CLIENT_DISCONNECT_INTERNAL_ERROR, + CLIENT_DISCONNECT_POLICY }; enum client_auth_fail_code { @@ -258,6 +259,7 @@ bool proxy_nopipelining:1; bool proxy_not_trusted:1; bool auth_waiting:1; + bool access_checks_done:1; bool notified_auth_ready:1; bool notified_disconnect:1; bool fd_proxying:1; @@ -265,6 +267,12 @@ /* ... */ }; +struct rbl_context { + struct client * client; + char * filter; +}; + + union login_client_module_context { struct client_vfuncs super; struct login_module_register *reg; @@ -289,6 +297,7 @@ const struct master_service_ssl_settings *ssl_set, const struct master_service_ssl_server_settings *ssl_server_set); void client_init(struct client *client, void **other_sets); +void client_init_continue(struct client *client); void client_disconnect(struct client *client, const char *reason, bool add_disconnected_prefix); void client_destroy(struct client *client, const char *reason); diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/login-common/login-settings.c dovecot-2.3.21/src/login-common/login-settings.c --- dovecot-2.3.21-orig/src/login-common/login-settings.c 2023-09-14 15:17:47.000000000 +0200 +++ dovecot-2.3.21/src/login-common/login-settings.c 2024-06-09 11:08:27.424859476 +0200 @@ -45,6 +45,10 @@ DEF(UINT, mail_max_userip_connections), + DEF(STR, rbl_check), + DEF(TIME_MSECS, rbl_check_timeout), + DEF(UINT, max_login_command_errors), + SETTING_DEFINE_LIST_END }; @@ -72,7 +76,11 @@ .auth_debug = FALSE, .verbose_proctitle = FALSE, - .mail_max_userip_connections = 10 + .mail_max_userip_connections = 10, + + .rbl_check = "", + .rbl_check_timeout = 10*1000, + .max_login_command_errors = 3 }; const struct setting_parser_info login_setting_parser_info = { diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/login-common/login-settings.h dovecot-2.3.21/src/login-common/login-settings.h --- dovecot-2.3.21-orig/src/login-common/login-settings.h 2023-09-14 15:17:47.000000000 +0200 +++ dovecot-2.3.21/src/login-common/login-settings.h 2024-06-09 11:08:27.425859478 +0200 @@ -30,6 +30,10 @@ unsigned int mail_max_userip_connections; + const char *rbl_check; + unsigned int rbl_check_timeout; + unsigned int max_login_command_errors; + /* generated: */ char *const *log_format_elements_split; }; diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/login-common/Makefile.am dovecot-2.3.21/src/login-common/Makefile.am --- dovecot-2.3.21-orig/src/login-common/Makefile.am 2023-09-14 15:17:47.000000000 +0200 +++ dovecot-2.3.21/src/login-common/Makefile.am 2024-06-09 11:08:27.435859495 +0200 @@ -4,6 +4,7 @@ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-settings \ -I$(top_srcdir)/src/lib-auth \ + -I$(top_srcdir)/src/lib-dns \ -I$(top_srcdir)/src/lib-sasl \ -I$(top_srcdir)/src/lib-master \ -I$(top_srcdir)/src/lib-ssl-iostream \ diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/login-common/Makefile.in dovecot-2.3.21/src/login-common/Makefile.in --- dovecot-2.3.21-orig/src/login-common/Makefile.in 2023-09-14 15:17:58.000000000 +0200 +++ dovecot-2.3.21/src/login-common/Makefile.in 2024-06-09 11:08:27.435859495 +0200 @@ -487,6 +487,7 @@ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-settings \ -I$(top_srcdir)/src/lib-auth \ + -I$(top_srcdir)/src/lib-dns \ -I$(top_srcdir)/src/lib-sasl \ -I$(top_srcdir)/src/lib-master \ -I$(top_srcdir)/src/lib-ssl-iostream \ diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/pop3/pop3-client.c dovecot-2.3.21/src/pop3/pop3-client.c --- dovecot-2.3.21-orig/src/pop3/pop3-client.c 2023-09-14 15:17:47.000000000 +0200 +++ dovecot-2.3.21/src/pop3/pop3-client.c 2024-06-09 11:08:27.425859478 +0200 @@ -27,9 +27,6 @@ /* max. length of input command line (spec says 512) */ #define MAX_INBUF_SIZE 2048 -/* Disconnect client when it sends too many bad commands in a row */ -#define CLIENT_MAX_BAD_COMMANDS 20 - /* Disconnect client after idling this many milliseconds */ #define CLIENT_IDLE_TIMEOUT_MSECS (10*60*1000) /* If client starts idling for this many milliseconds, commit the current @@ -765,7 +762,7 @@ client->waiting_input = TRUE; break; } - } else if (++client->bad_counter > CLIENT_MAX_BAD_COMMANDS) { + } else if (++client->bad_counter > client->set->max_bad_commands) { client_send_line(client, "-ERR Too many bad commands."); client_disconnect(client, "Too many bad commands."); } diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/pop3/pop3-settings.c dovecot-2.3.21/src/pop3/pop3-settings.c --- dovecot-2.3.21-orig/src/pop3/pop3-settings.c 2023-09-14 15:17:47.000000000 +0200 +++ dovecot-2.3.21/src/pop3/pop3-settings.c 2024-06-09 11:08:27.433859492 +0200 @@ -63,6 +63,7 @@ static const struct setting_define pop3_setting_defines[] = { DEF(BOOL, verbose_proctitle), DEF(STR_VARS, rawlog_dir), + DEF(UINT, max_bad_commands), DEF(BOOL, pop3_no_flag_updates), DEF(BOOL, pop3_enable_last), @@ -82,6 +83,7 @@ static const struct pop3_settings pop3_default_settings = { .verbose_proctitle = FALSE, .rawlog_dir = "", + .max_bad_commands = 20, .pop3_no_flag_updates = FALSE, .pop3_enable_last = FALSE, diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/pop3/pop3-settings.h dovecot-2.3.21/src/pop3/pop3-settings.h --- dovecot-2.3.21-orig/src/pop3/pop3-settings.h 2023-09-14 15:17:47.000000000 +0200 +++ dovecot-2.3.21/src/pop3/pop3-settings.h 2024-06-09 11:08:27.434859494 +0200 @@ -17,6 +17,7 @@ struct pop3_settings { bool verbose_proctitle; const char *rawlog_dir; + unsigned int max_bad_commands; /* pop3: */ bool pop3_no_flag_updates; diff -x '*.log' -x '*.status' -x '*.deps' -x '*.a' -x '*.o' -ur dovecot-2.3.21-orig/src/pop3-login/client.c dovecot-2.3.21/src/pop3-login/client.c --- dovecot-2.3.21-orig/src/pop3-login/client.c 2023-09-14 15:17:47.000000000 +0200 +++ dovecot-2.3.21/src/pop3-login/client.c 2024-06-09 11:08:27.434859494 +0200 @@ -20,8 +20,6 @@ #include -/* Disconnect client when it sends too many bad commands */ -#define CLIENT_MAX_BAD_COMMANDS 3 #define CLIENT_MAX_CMD_LEN 8 static bool cmd_stls(struct pop3_client *client) @@ -190,7 +188,7 @@ if (client_command_execute(pop3_client, pop3_client->current_cmd, args)) client->bad_counter = 0; - else if (++client->bad_counter >= CLIENT_MAX_BAD_COMMANDS) { + else if (++client->bad_counter >= pop3_client->common.set->max_login_command_errors ) { client_send_reply(client, POP3_CMD_REPLY_ERROR, "Too many invalid bad commands."); client_destroy(client,