]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
*-login: Forward end_client_tls_secured state through proxies
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 4 Nov 2022 20:37:43 +0000 (22:37 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 16 Nov 2022 08:09:54 +0000 (08:09 +0000)
src/imap-login/imap-login-cmd-id.c
src/imap-login/imap-proxy.c
src/login-common/client-common.c
src/login-common/client-common.h
src/pop3-login/client.c
src/pop3-login/pop3-proxy.c
src/submission-login/client.c
src/submission-login/submission-proxy.c

index 9a0aa95dd90169751e4d4ace002e4077921dedfe..57d635b9a7a45de10fc0eba472619a19c40c3c1c 100644 (file)
@@ -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 }
index 61dfff5d8a8357ef27760dca5c7b88b158dbf89d..a615aca4f1066d9e77b3a0443a0278586d8eca03 100644 (file)
@@ -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++) {
index a586be1a0653bf7be1ffd62a3c17611da1a1cad1..5d2991726a89d2a5504872e101f44f70beab3a1d 100644 (file)
@@ -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);
index d0c2b8391714f6744dec138f12ed73a91fdc81ae..4315f5a613da158681f9cac9f57590a1dcc7696f 100644 (file)
@@ -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. */
index 26d0250bd0adb7e0878a931ed43797e71922f7c5..2e0abc2f4f8a5bb8a84ae647557d79ae9bc417b2 100644 (file)
@@ -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;
index 12820bd16ce60992b77b92101b10d8891fe65c54..33786971f2a4f41c849306981dc5320cb2d851eb 100644 (file)
@@ -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);
index d2d02c71727077c2c7271f3c81a33543ed43e27e..402c54ab7305ea24742188157f398f0910e45d4e 100644 (file)
@@ -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;
index b6b6b61b12e6e28e212d1dc6c0dd61233ab7ac8f..a98d0bd59d9fc1366a6fe0e0e8767141b4463a47 100644 (file)
@@ -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);