From: Timo Sirainen Date: Fri, 4 Nov 2022 20:37:43 +0000 (+0200) Subject: *-login: Forward end_client_tls_secured state through proxies X-Git-Tag: 2.4.0~3412 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c83a66d93dd7e69f981545a4facde9790884eaa9;p=thirdparty%2Fdovecot%2Fcore.git *-login: Forward end_client_tls_secured state through proxies --- diff --git a/src/imap-login/imap-login-cmd-id.c b/src/imap-login/imap-login-cmd-id.c index 9a0aa95dd9..57d635b9a7 100644 --- a/src/imap-login/imap-login-cmd-id.c +++ b/src/imap-login/imap-login-cmd-id.c @@ -62,6 +62,17 @@ cmd_id_x_session_id(struct imap_client *client, } } +static void +cmd_id_x_client_transport(struct imap_client *client, + const char *key ATTR_UNUSED, const char *value) +{ + /* for now values are either "insecure" or "TLS", but plan ahead already + in case we want to transfer e.g. the TLS security string */ + client->common.end_client_tls_secured_set = TRUE; + client->common.end_client_tls_secured = + str_begins_with(value, CLIENT_TRANSPORT_TLS); +} + static void cmd_id_x_forward_(struct imap_client *client, const char *key, const char *value) @@ -81,6 +92,7 @@ static const struct imap_id_param_handler imap_login_id_params[] = { { "x-proxy-ttl", FALSE, cmd_id_x_proxy_ttl }, { "x-session-id", FALSE, cmd_id_x_session_id }, { "x-session-ext-id", FALSE, cmd_id_x_session_id }, + { "x-client-transport", FALSE, cmd_id_x_client_transport }, { "x-forward-", TRUE, cmd_id_x_forward_ }, { NULL, FALSE, NULL } diff --git a/src/imap-login/imap-proxy.c b/src/imap-login/imap-proxy.c index 61dfff5d8a..a615aca4f1 100644 --- a/src/imap-login/imap-proxy.c +++ b/src/imap-login/imap-proxy.c @@ -41,13 +41,16 @@ static void proxy_write_id(struct imap_client *client, string_t *str) "\"x-originating-port\" \"%u\" " "\"x-connected-ip\" \"%s\" " "\"x-connected-port\" \"%u\" " - "\"x-proxy-ttl\" \"%u\"", + "\"x-proxy-ttl\" \"%u\" " + "\"x-client-transport\" \"%s\"", client_get_session_id(&client->common), net_ip2addr(&client->common.ip), client->common.remote_port, net_ip2addr(&client->common.local_ip), client->common.local_port, - client->common.proxy_ttl - 1); + client->common.proxy_ttl - 1, + client->common.end_client_tls_secured ? + CLIENT_TRANSPORT_TLS : CLIENT_TRANSPORT_INSECURE); /* append any forward_ variables to request */ for(const char *const *ptr = client->common.auth_passdb_args; *ptr != NULL; ptr++) { diff --git a/src/login-common/client-common.c b/src/login-common/client-common.c index a586be1a06..5d2991726a 100644 --- a/src/login-common/client-common.c +++ b/src/login-common/client-common.c @@ -228,6 +228,8 @@ client_alloc(int fd, pool_t pool, TLS secured anyway. */ client->connection_tls_secured = conn->haproxy.ssl; client->haproxy_terminated_tls = conn->haproxy.ssl; + /* Start by assuming this is the end client connection. + Later on this can be overwritten. */ client->end_client_tls_secured = conn->haproxy.ssl; client->local_name = conn->haproxy.hostname; client->client_cert_common_name = conn->haproxy.cert_common_name; @@ -600,7 +602,8 @@ int client_init_ssl(struct client *client) client->connection_tls_secured = TRUE; client->connection_secured = TRUE; - client->end_client_tls_secured = TRUE; + if (!client->end_client_tls_secured_set) + client->end_client_tls_secured = TRUE; if (client->connection_used_starttls) { io_remove(&client->io); diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index d0c2b83917..4315f5a613 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -41,6 +41,9 @@ struct module; #define CLIENT_UNAUTHENTICATED_LOGOUT_MSG \ "Aborted login by logging out" +#define CLIENT_TRANSPORT_TLS "TLS" +#define CLIENT_TRANSPORT_INSECURE "insecure" + struct master_service_connection; enum client_disconnect_reason { @@ -242,11 +245,12 @@ struct client { previous hop is secured. */ bool connection_secured:1; /* End client is using TLS connection. The TLS termination may be either - on Dovecot side or HAProxy side. FIXME: This is broken on a proxying - setup, because it indicates whether the previous hop connection is - TLS secured, not whether the original client connection is TLS - secured. */ + on Dovecot side or HAProxy side. This value is forwarded through + trusted Dovecot proxies. */ bool end_client_tls_secured:1; + /* TRUE if end_client_tls_secured is set via ID/XCLIENT and must not + be changed anymore. */ + bool end_client_tls_secured_set:1; /* Connection is from a trusted client/proxy, which is allowed to e.g. forward the original client IP address. Note that a trusted connection is not necessarily considered secured. */ diff --git a/src/pop3-login/client.c b/src/pop3-login/client.c index 26d0250bd0..2e0abc2f4f 100644 --- a/src/pop3-login/client.c +++ b/src/pop3-login/client.c @@ -66,6 +66,10 @@ static bool cmd_xclient(struct pop3_client *client, const char *args) } else if (str_begins_icase(*tmp, "TTL=", &value)) { if (str_to_uint(value, &client->common.proxy_ttl) < 0) args_ok = FALSE; + } else if (str_begins_icase(*tmp, "CLIENT-TRANSPORT=", &value)) { + client->common.end_client_tls_secured_set = TRUE; + client->common.end_client_tls_secured = + str_begins_with(value, CLIENT_TRANSPORT_TLS); } else if (str_begins_icase(*tmp, "FORWARD=", &value)) { if (!client_forward_decode_base64(&client->common, value)) args_ok = FALSE; diff --git a/src/pop3-login/pop3-proxy.c b/src/pop3-login/pop3-proxy.c index 12820bd16c..33786971f2 100644 --- a/src/pop3-login/pop3-proxy.c +++ b/src/pop3-login/pop3-proxy.c @@ -38,11 +38,14 @@ static int proxy_send_login(struct pop3_client *client, struct ostream *output) } } - str_printfa(str, "XCLIENT ADDR=%s PORT=%u SESSION=%s TTL=%u", + str_printfa(str, "XCLIENT ADDR=%s PORT=%u SESSION=%s TTL=%u " + "CLIENT-TRANSPORT=%s", net_ip2addr(&client->common.ip), client->common.remote_port, client_get_session_id(&client->common), - client->common.proxy_ttl - 1); + client->common.proxy_ttl - 1, + client->common.end_client_tls_secured ? + CLIENT_TRANSPORT_TLS : CLIENT_TRANSPORT_INSECURE); if (str_len(fwd) > 0) { str_append(str, " FORWARD="); base64_encode(str_data(fwd), str_len(fwd), str); diff --git a/src/submission-login/client.c b/src/submission-login/client.c index d2d02c7172..402c54ab73 100644 --- a/src/submission-login/client.c +++ b/src/submission-login/client.c @@ -188,6 +188,12 @@ client_connection_cmd_xclient(void *context, client->common.session_id = p_strdup(client->common.pool, data->session); } + if (data->client_transport != NULL) { + client->common.end_client_tls_secured_set = TRUE; + client->common.end_client_tls_secured = + str_begins_with(data->client_transport, + CLIENT_TRANSPORT_TLS); + } for (i = 0; i < data->extra_fields_count; i++) { const char *name = data->extra_fields[i].name; diff --git a/src/submission-login/submission-proxy.c b/src/submission-login/submission-proxy.c index b6b6b61b12..a98d0bd59d 100644 --- a/src/submission-login/submission-proxy.c +++ b/src/submission-login/submission-proxy.c @@ -186,6 +186,11 @@ proxy_send_xclient(struct submission_client *client, struct ostream *output) proxy_send_xclient_more(client, output, str, "SESSION", client_get_session_id(&client->common)); } + if (str_array_icase_find(client->proxy_xclient, "CLIENT-TRANSPORT")) { + proxy_send_xclient_more(client, output, str, "CLIENT-TRANSPORT", + client->common.end_client_tls_secured ? + CLIENT_TRANSPORT_TLS : CLIENT_TRANSPORT_INSECURE); + } if (str_array_icase_find(client->proxy_xclient, "FORWARD")) { buffer_t *fwd = proxy_compose_xclient_forward(client);