From: Aki Tuomi Date: Fri, 3 May 2024 11:47:14 +0000 (+0300) Subject: login-common: Defer notify auth ready until TLS is ready X-Git-Tag: 2.4.1~479 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=563dc0a28020f808074b4bec15fb84b95215911d;p=thirdparty%2Fdovecot%2Fcore.git login-common: Defer notify auth ready until TLS is ready --- diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c index 15ddd559b7..332080f1fe 100644 --- a/src/imap-login/imap-login-client.c +++ b/src/imap-login/imap-login-client.c @@ -399,7 +399,6 @@ static int imap_client_create(struct client *client) settings_override(set_instance, "imap_capability/LITERAL-", "no", SETTINGS_OVERRIDE_TYPE_CODE); - client->io = io_add_istream(client->input, client_input, client); if (imap_client_reload_config(client, &error) < 0) { e_error(client->event, "%s", error); return -1; @@ -448,6 +447,8 @@ static void imap_client_notify_auth_ready(struct client *client) client_send_raw(client, str_c(greet)); client->banner_sent = TRUE; + i_assert(client->io == NULL); + client->io = io_add_istream(client->input, client_input, client); } static void imap_client_starttls(struct client *client) diff --git a/src/imap-urlauth-login/imap-urlauth-login.c b/src/imap-urlauth-login/imap-urlauth-login.c index 2de90c08c3..adf1df4213 100644 --- a/src/imap-urlauth-login/imap-urlauth-login.c +++ b/src/imap-urlauth-login/imap-urlauth-login.c @@ -140,9 +140,8 @@ static struct client *imap_urlauth_client_alloc(pool_t pool) return &uauth_client->common; } -static int imap_urlauth_client_create(struct client *client) +static int imap_urlauth_client_create(struct client *client ATTR_UNUSED) { - client->io = io_add_istream(client->input, client_input, client); return 0; } @@ -159,6 +158,8 @@ static void imap_urlauth_client_notify_auth_ready(struct client *client) client_send_raw(client, str_c(version)); client->banner_sent = TRUE; + i_assert(client->io == NULL); + client->io = io_add_istream(client->input, client_input, client); } static void imap_urlauth_login_preinit(void) diff --git a/src/login-common/client-common-auth.c b/src/login-common/client-common-auth.c index fb5fb72c77..2ad85aba71 100644 --- a/src/login-common/client-common-auth.c +++ b/src/login-common/client-common-auth.c @@ -1168,7 +1168,8 @@ void clients_notify_auth_connected(void) timeout_remove(&client->to_auth_waiting); T_BEGIN { - client_notify_auth_ready(client); + if (!client->defer_auth_ready) + client_notify_auth_ready(client); } T_END; if (!client_does_custom_io(client) && client->input_blocked) { diff --git a/src/login-common/client-common.c b/src/login-common/client-common.c index 82048a5521..d4c27622cb 100644 --- a/src/login-common/client-common.c +++ b/src/login-common/client-common.c @@ -312,6 +312,13 @@ int client_alloc(int fd, const struct master_service_connection *conn, return 0; } +/* Perform one read to ensure TLS handshake is started. */ +static void initial_client_read(struct client *client) +{ + if (client_read(client)) + io_remove(&client->io); +} + int client_init(struct client *client) { if (last_client == NULL) @@ -328,7 +335,18 @@ int client_init(struct client *client) if (client->v.create(client) < 0) return -1; client->create_finished = TRUE; - + /* Do not allow clients to start IO just yet, wait until + TLS handshake and auth client are finished. */ + i_assert(client->io == NULL); + /* If we are deferring auth, create initial io for reading the + client to ensure we do TLS handshake. Otherwise we can start + with client_input. */ + if (client->defer_auth_ready) { + client->io = + io_add_istream(client->input, initial_client_read, client); + } else if (!client_does_custom_io(client)) + client->io = io_add_istream(client->input, client_input, client); + /* Ensure we start connecting to auth server right away. */ client_notify_auth_ready(client); login_refresh_proctitle(); @@ -466,6 +484,7 @@ void client_destroy(struct client *client, const char *reason) timeout_remove(&client->to_disconnect); timeout_remove(&client->to_auth_waiting); + timeout_remove(&client->to_notify_auth_ready); str_free(&client->auth_response); i_free(client->auth_conn_cookie); @@ -680,6 +699,11 @@ int client_sni_callback(const char *name, const char **error_r, settings_free(ssl_set); ssl_iostream_change_context(client->ssl_iostream, ssl_ctx); ssl_iostream_context_unref(&ssl_ctx); + + client->defer_auth_ready = FALSE; + client->to_notify_auth_ready = + timeout_add_short(0, client_notify_auth_ready, client); + return 0; } @@ -689,6 +713,8 @@ int client_init_ssl(struct client *client) i_assert(client->fd != -1); + client->defer_auth_ready = TRUE; + if (strcmp(client->ssl_server_set->ssl, "no") == 0) { e_info(client->event, "SSL is disabled (ssl=no)"); return -1; @@ -1398,10 +1424,16 @@ void client_notify_disconnect(struct client *client, void client_notify_auth_ready(struct client *client) { + timeout_remove(&client->to_notify_auth_ready); if (client->notified_auth_ready) return; + if (client->to_auth_waiting != NULL) + return; if (auth_client_is_connected(auth_client)) { + if (client->defer_auth_ready) + return; + io_remove(&client->io); if (client->v.notify_auth_ready != NULL) client->v.notify_auth_ready(client); client->notified_auth_ready = TRUE; diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index bac8851368..b43127915b 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -209,6 +209,7 @@ struct client { struct io *io; struct iostream_proxy *iostream_fd_proxy; struct timeout *to_auth_waiting; + struct timeout *to_notify_auth_ready; struct timeout *to_disconnect; unsigned char *master_data_prefix; @@ -317,6 +318,9 @@ struct client { bool fd_proxying:1; bool shutting_down:1; bool resource_constraint:1; + /* Defer calling auth ready callback until TLS handshake has been + finished. */ + bool defer_auth_ready:1; /* ... */ }; diff --git a/src/pop3-login/client.c b/src/pop3-login/client.c index d7dcdeff8d..ae4e357d79 100644 --- a/src/pop3-login/client.c +++ b/src/pop3-login/client.c @@ -257,6 +257,7 @@ static void pop3_client_notify_auth_ready(struct client *client) struct pop3_client *pop3_client = (struct pop3_client *)client; string_t *str; + i_assert(client->io == NULL); client->io = io_add_istream(client->input, client_input, client); str = t_str_new(128); diff --git a/src/submission-login/client.c b/src/submission-login/client.c index c85ad40699..f4125e2766 100644 --- a/src/submission-login/client.c +++ b/src/submission-login/client.c @@ -154,8 +154,10 @@ static void submission_client_notify_auth_ready(struct client *client) struct submission_client *subm_client = container_of(client, struct submission_client, common); + i_assert(client->io == NULL); client->banner_sent = TRUE; - smtp_server_connection_start(subm_client->conn); + if (!smtp_server_connection_is_started(subm_client->conn)) + smtp_server_connection_start(subm_client->conn); } static void