From a1acd71cf65e6a6b92a6bdd1c1a5479f24d4aa35 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Wed, 6 May 2020 20:21:15 +0300 Subject: [PATCH] *-login: Change proxy_error() API to proxy_failed() API The protocol-specific code is now able to control better what kind of a reply is sent to client on proxying failure. --- src/imap-login/imap-login-client.c | 2 +- src/imap-login/imap-proxy.c | 38 +++++++++++++++++++++++-- src/imap-login/imap-proxy.h | 4 ++- src/login-common/client-common-auth.c | 22 ++++++-------- src/login-common/client-common.h | 7 ++++- src/login-common/login-proxy.h | 2 ++ src/pop3-login/client.c | 2 +- src/pop3-login/pop3-proxy.c | 29 +++++++++++++++++-- src/pop3-login/pop3-proxy.h | 4 ++- src/submission-login/client.c | 2 +- src/submission-login/submission-proxy.c | 37 ++++++++++++++++++++---- src/submission-login/submission-proxy.h | 4 ++- 12 files changed, 121 insertions(+), 32 deletions(-) diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c index 91b1c5afc7..e2af176309 100644 --- a/src/imap-login/imap-login-client.c +++ b/src/imap-login/imap-login-client.c @@ -546,7 +546,7 @@ static struct client_vfuncs imap_client_vfuncs = { .auth_result = imap_client_auth_result, .proxy_reset = imap_proxy_reset, .proxy_parse_line = imap_proxy_parse_line, - .proxy_error = imap_proxy_error, + .proxy_failed = imap_proxy_failed, .proxy_get_state = imap_proxy_get_state, .send_raw_data = client_common_send_raw_data, .input_next_cmd = imap_client_input_next_cmd, diff --git a/src/imap-login/imap-proxy.c b/src/imap-login/imap-proxy.c index afcd8a6e9c..09c10b80b2 100644 --- a/src/imap-login/imap-proxy.c +++ b/src/imap-login/imap-proxy.c @@ -449,10 +449,42 @@ void imap_proxy_reset(struct client *client) imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_NONE; } -void imap_proxy_error(struct client *client, const char *text) +static void +imap_proxy_send_failure_reply(struct imap_client *imap_client, + enum login_proxy_failure_type type, + const char *reason ATTR_UNUSED) +{ + switch (type) { + case LOGIN_PROXY_FAILURE_TYPE_CONNECT: + case LOGIN_PROXY_FAILURE_TYPE_INTERNAL: + case LOGIN_PROXY_FAILURE_TYPE_REMOTE: + case LOGIN_PROXY_FAILURE_TYPE_PROTOCOL: + client_send_reply_code(&imap_client->common, IMAP_CMD_REPLY_NO, + IMAP_RESP_CODE_UNAVAILABLE, + LOGIN_PROXY_FAILURE_MSG); + break; + case LOGIN_PROXY_FAILURE_TYPE_REMOTE_CONFIG: + case LOGIN_PROXY_FAILURE_TYPE_INTERNAL_CONFIG: + client_send_reply_code(&imap_client->common, IMAP_CMD_REPLY_NO, + IMAP_RESP_CODE_SERVERBUG, + LOGIN_PROXY_FAILURE_MSG); + break; + case LOGIN_PROXY_FAILURE_TYPE_AUTH: + /* reply was already sent */ + break; + } +} + +void imap_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting) { - client_send_reply_code(client, IMAP_CMD_REPLY_NO, - IMAP_RESP_CODE_UNAVAILABLE, text); + struct imap_client *imap_client = + container_of(client, struct imap_client, common); + + if (!reconnecting) + imap_proxy_send_failure_reply(imap_client, type, reason); + client_common_proxy_failed(client, type, reason, reconnecting); } const char *imap_proxy_get_state(struct client *client) diff --git a/src/imap-login/imap-proxy.h b/src/imap-login/imap-proxy.h index b437ef509c..71c2f64e78 100644 --- a/src/imap-login/imap-proxy.h +++ b/src/imap-login/imap-proxy.h @@ -4,7 +4,9 @@ void imap_proxy_reset(struct client *client); int imap_proxy_parse_line(struct client *client, const char *line); -void imap_proxy_error(struct client *client, const char *text); +void imap_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting); const char *imap_proxy_get_state(struct client *client); #endif diff --git a/src/login-common/client-common-auth.c b/src/login-common/client-common-auth.c index 57e2f082bc..1cc9cce7f2 100644 --- a/src/login-common/client-common-auth.c +++ b/src/login-common/client-common-auth.c @@ -16,8 +16,6 @@ #include "master-service-ssl-settings.h" #include "client-common.h" -#define PROXY_FAILURE_MSG "Account is temporarily unavailable." - /* If we've been waiting auth server to respond for over this many milliseconds, send a "waiting" message. */ #define AUTH_WAITING_TIMEOUT_MSECS (30*1000) @@ -283,11 +281,6 @@ void client_proxy_finish_destroy_client(struct client *client) client_destroy_success(client, NULL); } -static void client_proxy_error(struct client *client, const char *text) -{ - client->v.proxy_error(client, text); -} - const char *client_proxy_get_state(struct client *client) { return client->v.proxy_get_state(client); @@ -361,10 +354,10 @@ static void proxy_input(struct client *client) o_stream_unref(&output); } -static void proxy_failed(struct client *client, - enum login_proxy_failure_type type, - const char *reason ATTR_UNUSED, - bool reconnecting) +void client_common_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason ATTR_UNUSED, + bool reconnecting) { if (client->proxy_sasl_client != NULL) dsasl_client_free(&client->proxy_sasl_client); @@ -380,7 +373,6 @@ static void proxy_failed(struct client *client, case LOGIN_PROXY_FAILURE_TYPE_REMOTE: case LOGIN_PROXY_FAILURE_TYPE_REMOTE_CONFIG: case LOGIN_PROXY_FAILURE_TYPE_PROTOCOL: - client_proxy_error(client, PROXY_FAILURE_MSG); break; case LOGIN_PROXY_FAILURE_TYPE_AUTH: client->proxy_auth_failed = TRUE; @@ -456,7 +448,9 @@ static int proxy_start(struct client *client, "proxy(%s): ", client->virtual_user)); if (!proxy_check_start(client, event, reply, &sasl_mech, &ip)) { - client_proxy_error(client, PROXY_FAILURE_MSG); + client->v.proxy_failed(client, + LOGIN_PROXY_FAILURE_TYPE_INTERNAL, + LOGIN_PROXY_FAILURE_MSG, FALSE); event_unref(&event); return -1; } @@ -486,7 +480,7 @@ static int proxy_start(struct client *client, net_ip2addr(&proxy_set.ip), proxy_set.port)); if (login_proxy_new(client, event, &proxy_set, proxy_input, - proxy_failed) < 0) { + client->v.proxy_failed) < 0) { event_unref(&event); return -1; } diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index 7bf5de4fd0..cacd347049 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -123,7 +123,9 @@ struct client_vfuncs { const char *text); void (*proxy_reset)(struct client *client); int (*proxy_parse_line)(struct client *client, const char *line); - void (*proxy_error)(struct client *client, const char *text); + void (*proxy_failed)(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting); const char *(*proxy_get_state)(struct client *client); void (*send_raw_data)(struct client *client, const void *data, size_t size); @@ -310,6 +312,9 @@ void client_send_raw(struct client *client, const char *data); void client_common_send_raw_data(struct client *client, const void *data, size_t size); void client_common_default_free(struct client *client); +void client_common_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting); void client_set_auth_waiting(struct client *client); void client_auth_send_challenge(struct client *client, const char *data); diff --git a/src/login-common/login-proxy.h b/src/login-common/login-proxy.h index ae460c32e9..4729c70a84 100644 --- a/src/login-common/login-proxy.h +++ b/src/login-common/login-proxy.h @@ -10,6 +10,8 @@ TTL extension feature. */ #define LOGIN_PROXY_TTL 5 +#define LOGIN_PROXY_FAILURE_MSG "Account is temporarily unavailable." + struct client; struct login_proxy; diff --git a/src/pop3-login/client.c b/src/pop3-login/client.c index 267b6240e1..c687e37f24 100644 --- a/src/pop3-login/client.c +++ b/src/pop3-login/client.c @@ -326,7 +326,7 @@ static struct client_vfuncs pop3_client_vfuncs = { .auth_result = pop3_client_auth_result, .proxy_reset = pop3_proxy_reset, .proxy_parse_line = pop3_proxy_parse_line, - .proxy_error = pop3_proxy_error, + .proxy_failed = pop3_proxy_failed, .proxy_get_state = pop3_proxy_get_state, .send_raw_data = client_common_send_raw_data, .input_next_cmd = pop3_client_input_next_cmd, diff --git a/src/pop3-login/pop3-proxy.c b/src/pop3-login/pop3-proxy.c index de04ae7c60..30ae5a8a4f 100644 --- a/src/pop3-login/pop3-proxy.c +++ b/src/pop3-login/pop3-proxy.c @@ -270,9 +270,34 @@ void pop3_proxy_reset(struct client *client) pop3_client->proxy_state = POP3_PROXY_BANNER; } -void pop3_proxy_error(struct client *client, const char *text) +static void +pop3_proxy_send_failure_reply(struct client *client, + enum login_proxy_failure_type type, + const char *reason ATTR_UNUSED) { - client_send_reply(client, POP3_CMD_REPLY_ERROR, text); + switch (type) { + case LOGIN_PROXY_FAILURE_TYPE_CONNECT: + case LOGIN_PROXY_FAILURE_TYPE_INTERNAL: + case LOGIN_PROXY_FAILURE_TYPE_INTERNAL_CONFIG: + case LOGIN_PROXY_FAILURE_TYPE_REMOTE: + case LOGIN_PROXY_FAILURE_TYPE_REMOTE_CONFIG: + case LOGIN_PROXY_FAILURE_TYPE_PROTOCOL: + client_send_reply(client, POP3_CMD_REPLY_ERROR, + LOGIN_PROXY_FAILURE_MSG); + break; + case LOGIN_PROXY_FAILURE_TYPE_AUTH: + /* reply was already sent */ + break; + } +} + +void pop3_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting) +{ + if (!reconnecting) + pop3_proxy_send_failure_reply(client, type, reason); + client_common_proxy_failed(client, type, reason, reconnecting); } const char *pop3_proxy_get_state(struct client *client) diff --git a/src/pop3-login/pop3-proxy.h b/src/pop3-login/pop3-proxy.h index b6758d5484..9e23475cd9 100644 --- a/src/pop3-login/pop3-proxy.h +++ b/src/pop3-login/pop3-proxy.h @@ -4,7 +4,9 @@ void pop3_proxy_reset(struct client *client); int pop3_proxy_parse_line(struct client *client, const char *line); -void pop3_proxy_error(struct client *client, const char *text); +void pop3_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting); const char *pop3_proxy_get_state(struct client *client); #endif diff --git a/src/submission-login/client.c b/src/submission-login/client.c index 673d3ce6e3..d2f03a0225 100644 --- a/src/submission-login/client.c +++ b/src/submission-login/client.c @@ -292,7 +292,7 @@ static struct client_vfuncs submission_client_vfuncs = { .auth_result = submission_client_auth_result, .proxy_reset = submission_proxy_reset, .proxy_parse_line = submission_proxy_parse_line, - .proxy_error = submission_proxy_error, + .proxy_failed = submission_proxy_failed, .proxy_get_state = submission_proxy_get_state, }; diff --git a/src/submission-login/submission-proxy.c b/src/submission-login/submission-proxy.c index 652d041c44..c7548bc493 100644 --- a/src/submission-login/submission-proxy.c +++ b/src/submission-login/submission-proxy.c @@ -456,16 +456,41 @@ void submission_proxy_reset(struct client *client) subm_client->proxy_reply = NULL; } -void submission_proxy_error(struct client *client, const char *text) +static void +submission_proxy_send_failure_reply(struct submission_client *subm_client, + enum login_proxy_failure_type type, + const char *reason ATTR_UNUSED) +{ + struct smtp_server_cmd_ctx *cmd = subm_client->pending_auth; + if (cmd == NULL) + return; + + subm_client->pending_auth = NULL; + switch (type) { + case LOGIN_PROXY_FAILURE_TYPE_CONNECT: + case LOGIN_PROXY_FAILURE_TYPE_INTERNAL: + case LOGIN_PROXY_FAILURE_TYPE_INTERNAL_CONFIG: + case LOGIN_PROXY_FAILURE_TYPE_REMOTE: + case LOGIN_PROXY_FAILURE_TYPE_REMOTE_CONFIG: + case LOGIN_PROXY_FAILURE_TYPE_PROTOCOL: + smtp_server_reply(cmd, 535, "5.7.8", LOGIN_PROXY_FAILURE_MSG); + break; + case LOGIN_PROXY_FAILURE_TYPE_AUTH: + /* reply was already sent */ + break; + } +} + +void submission_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting) { struct submission_client *subm_client = container_of(client, struct submission_client, common); - struct smtp_server_cmd_ctx *cmd = subm_client->pending_auth; - if (cmd != NULL) { - subm_client->pending_auth = NULL; - smtp_server_reply(cmd, 535, "5.7.8", "%s", text); - } + if (!reconnecting) + submission_proxy_send_failure_reply(subm_client, type, reason); + client_common_proxy_failed(client, type, reason, reconnecting); } const char *submission_proxy_get_state(struct client *client) diff --git a/src/submission-login/submission-proxy.h b/src/submission-login/submission-proxy.h index b9370e6013..19342cf35d 100644 --- a/src/submission-login/submission-proxy.h +++ b/src/submission-login/submission-proxy.h @@ -4,7 +4,9 @@ void submission_proxy_reset(struct client *client); int submission_proxy_parse_line(struct client *client, const char *line); -void submission_proxy_error(struct client *client, const char *text); +void submission_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting); const char *submission_proxy_get_state(struct client *client); #endif -- 2.47.3