From d54ef477a9a741cdcc096eb4aa4ce90f5372d45e Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Wed, 3 Dec 2025 12:06:42 +0200 Subject: [PATCH] [PATCH] login-common, *-login: Add proxy_dest_connection_limit error_code to proxy_session_finished If IMAP backend returns with [LIMIT] or POP3 backend returns with [IN-USE], use this error code rather than the generic proxy_dest_auth_failed. Error messages are also updated. Gbp-Pq: Name 0001-login-common-login-Add-proxy_dest_connection_limit-e.patch --- src/imap-login/imap-proxy.c | 9 +++++++++ src/login-common/client-common.c | 4 ++++ src/login-common/login-proxy.c | 2 ++ src/login-common/login-proxy.h | 3 +++ src/pop3-login/pop3-proxy.c | 3 +++ src/submission-login/submission-proxy.c | 1 + 6 files changed, 22 insertions(+) diff --git a/src/imap-login/imap-proxy.c b/src/imap-login/imap-proxy.c index 6f81dc8..69680ea 100644 --- a/src/imap-login/imap-proxy.c +++ b/src/imap-login/imap-proxy.c @@ -284,6 +284,12 @@ static bool auth_resp_code_is_serverbug(const char *resp) strlen(IMAP_RESP_CODE_SERVERBUG"]")) == 0; } +static bool auth_resp_code_is_limit(const char *resp) +{ + return strncasecmp(resp, IMAP_RESP_CODE_LIMIT"]", + strlen(IMAP_RESP_CODE_LIMIT"]")) == 0; +} + static bool auth_resp_code_parse_referral(struct client *client, const char *resp, const char **userhostport_r) @@ -448,6 +454,8 @@ int imap_proxy_parse_line(struct client *client, const char *line) else if (auth_resp_code_is_serverbug(line + 4)) failure_type = LOGIN_PROXY_FAILURE_TYPE_REMOTE; else { + if (auth_resp_code_is_limit(line + 4)) + failure_type = LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED; client_send_raw(client, t_strconcat( imap_client->cmd_tag, " ", line, "\r\n", NULL)); } @@ -587,6 +595,7 @@ imap_proxy_send_failure_reply(struct imap_client *imap_client, imap_client->cmd_tag, " NO ", reason, "\r\n", NULL)); break; case LOGIN_PROXY_FAILURE_TYPE_AUTH_REPLIED: + case LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED: /* reply was already sent */ break; } diff --git a/src/login-common/client-common.c b/src/login-common/client-common.c index cefe157..0c11a92 100644 --- a/src/login-common/client-common.c +++ b/src/login-common/client-common.c @@ -1397,6 +1397,10 @@ bool client_get_extra_disconnect_reason(struct client *client, event_reason = "redirected"; last_reason = "redirected"; break; + case LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED: + event_reason = "connection_limit"; + last_reason = "connection limit reached"; + break; default: i_unreached(); } diff --git a/src/login-common/login-proxy.c b/src/login-common/login-proxy.c index cba9d9d..0e3e8c9 100644 --- a/src/login-common/login-proxy.c +++ b/src/login-common/login-proxy.c @@ -830,6 +830,7 @@ bool login_proxy_failed(struct login_proxy *proxy, struct event *event, log_prefix = "Remote server sent invalid input: "; break; case LOGIN_PROXY_FAILURE_TYPE_AUTH_REPLIED: + case LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED: log_prefix = ""; try_reconnect = FALSE; break; @@ -855,6 +856,7 @@ bool login_proxy_failed(struct login_proxy *proxy, struct event *event, } if (type != LOGIN_PROXY_FAILURE_TYPE_AUTH_REPLIED && + type != LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED && type != LOGIN_PROXY_FAILURE_TYPE_AUTH_TEMPFAIL) e_error(event, "%s%s", log_prefix, reason); else if (proxy->client->set->auth_verbose) diff --git a/src/login-common/login-proxy.h b/src/login-common/login-proxy.h index 6465cfc..65895f3 100644 --- a/src/login-common/login-proxy.h +++ b/src/login-common/login-proxy.h @@ -41,6 +41,9 @@ enum login_proxy_failure_type { /* Authentication requests connecting to another host. The reason string contains the host (and optionally :port). */ LOGIN_PROXY_FAILURE_TYPE_AUTH_REDIRECT, + /* Authentication failed because user has reached some limit. + The LOGIN/AUTH command reply was already sent to the client. */ + LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED, }; struct login_proxy_settings { diff --git a/src/pop3-login/pop3-proxy.c b/src/pop3-login/pop3-proxy.c index 1f2934c..f8010d3 100644 --- a/src/pop3-login/pop3-proxy.c +++ b/src/pop3-login/pop3-proxy.c @@ -333,6 +333,8 @@ int pop3_proxy_parse_line(struct client *client, const char *line) } else if (pop3_proxy_parse_referral(client, line + 5, &line)) { failure_type = LOGIN_PROXY_FAILURE_TYPE_AUTH_REDIRECT; } else { + if (str_begins_with(line, "-ERR [IN-USE]")) + failure_type = LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED; client_send_raw(client, t_strconcat(line, "\r\n", NULL)); line += 5; } @@ -374,6 +376,7 @@ pop3_proxy_send_failure_reply(struct client *client, client_send_reply(client, POP3_CMD_REPLY_ERROR, reason); break; case LOGIN_PROXY_FAILURE_TYPE_AUTH_REPLIED: + case LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED: /* reply was already sent */ break; } diff --git a/src/submission-login/submission-proxy.c b/src/submission-login/submission-proxy.c index ef1a25c..a2b7d2f 100644 --- a/src/submission-login/submission-proxy.c +++ b/src/submission-login/submission-proxy.c @@ -750,6 +750,7 @@ submission_proxy_send_failure_reply(struct submission_client *subm_client, smtp_server_reply_submit(subm_client->proxy_reply); break; case LOGIN_PROXY_FAILURE_TYPE_AUTH_REPLIED: + case LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED: /* reply was already sent */ i_assert(cmd == NULL); break; -- 2.39.5