From: Timo Sirainen Date: Wed, 3 Dec 2025 10:06:42 +0000 (+0200) Subject: login-common, *-login: Add proxy_dest_connection_limit error_code to proxy_session_fi... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=db0835c84bf754a260ce0d3dca1d69eb90f87518;p=thirdparty%2Fdovecot%2Fcore.git 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. --- diff --git a/src/imap-login/imap-proxy.c b/src/imap-login/imap-proxy.c index b4cdc8b924..3156a4bbf4 100644 --- a/src/imap-login/imap-proxy.c +++ b/src/imap-login/imap-proxy.c @@ -289,6 +289,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) @@ -435,6 +441,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)); } @@ -575,6 +583,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 f57e99e023..0d0135f67b 100644 --- a/src/login-common/client-common.c +++ b/src/login-common/client-common.c @@ -1467,6 +1467,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 2df51eb402..278142e8c7 100644 --- a/src/login-common/login-proxy.c +++ b/src/login-common/login-proxy.c @@ -859,6 +859,7 @@ bool login_proxy_failed(struct login_proxy *proxy, struct event *event, break; case LOGIN_PROXY_FAILURE_TYPE_AUTH_REPLIED: case LOGIN_PROXY_FAILURE_TYPE_AUTH_NOT_REPLIED: + case LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED: log_prefix = ""; try_reconnect = FALSE; break; @@ -888,6 +889,7 @@ bool login_proxy_failed(struct login_proxy *proxy, struct event *event, i_strdup_printf("%s%s", log_prefix, reason); if (type != LOGIN_PROXY_FAILURE_TYPE_AUTH_REPLIED && + type != LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED && type != LOGIN_PROXY_FAILURE_TYPE_AUTH_NOT_REPLIED && type != LOGIN_PROXY_FAILURE_TYPE_AUTH_TEMPFAIL) e_error(event, "%s%s", log_prefix, reason); diff --git a/src/login-common/login-proxy.h b/src/login-common/login-proxy.h index 0064b81258..cc554486e1 100644 --- a/src/login-common/login-proxy.h +++ b/src/login-common/login-proxy.h @@ -44,6 +44,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 c8cf43d918..2389dc6f09 100644 --- a/src/pop3-login/pop3-proxy.c +++ b/src/pop3-login/pop3-proxy.c @@ -316,6 +316,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; } @@ -358,6 +360,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 aa5534b9c8..a23a8c02b5 100644 --- a/src/submission-login/submission-proxy.c +++ b/src/submission-login/submission-proxy.c @@ -733,6 +733,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;