]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
*-login: Reload settings after ID/XCLIENT has changed addresses
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 30 Jan 2026 18:53:50 +0000 (20:53 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 6 Feb 2026 07:58:43 +0000 (07:58 +0000)
src/imap-login/imap-login-client.h
src/imap-login/imap-login-cmd-id.c
src/login-common/client-common.c
src/login-common/client-common.h
src/pop3-login/client.c
src/submission-login/client.c

index cf7fb2be503739ccf5b706bdaeee455099fb1c32..ffac6ec855030cc48360626ee91b5a48e4afd08a 100644 (file)
@@ -55,6 +55,9 @@ struct imap_client_cmd_id {
           an ID command with some parameters. Note that Dovecot proxy can
           send an ID command with both internal and external keys. */
        bool seen_external_keys;
+       /* ID contained internal x-* keys which can affect settings. Reload
+          the login settings after the ID command handling is finished. */
+       bool reload_settings;
 };
 
 struct imap_client {
index f7520d2196a562a2ab80ac12173af4a4a31ba1e6..24b365dc0c39272d38ee6dfcb6c5cabd34c06b45 100644 (file)
@@ -6,6 +6,7 @@
 #include "connection.h"
 #include "imap-parser.h"
 #include "imap-quote.h"
+#include "imap-resp-code.h"
 #include "imap-login-settings.h"
 #include "imap-login-client.h"
 
@@ -30,6 +31,7 @@ struct imap_id_params {
 
 enum imap_id_param_flag {
        IMAP_ID_PARAM_FLAG_KEY_IS_PREFIX = BIT(0),
+       IMAP_ID_PARAM_FLAG_RELOAD_SETTINGS = BIT(1),
 };
 
 struct imap_id_param_handler {
@@ -146,11 +148,16 @@ cmd_id_x_connected_name(struct imap_id_params *params,
 }
 
 static const struct imap_id_param_handler imap_login_id_params[] = {
-       { "x-originating-ip", 0, cmd_id_x_originating_ip },
-       { "x-originating-port", 0, cmd_id_x_originating_port },
-       { "x-connected-ip", 0, cmd_id_x_connected_ip },
-       { "x-connected-port", 0, cmd_id_x_connected_port },
-       { "x-connected-name", 0, cmd_id_x_connected_name },
+       { "x-originating-ip", IMAP_ID_PARAM_FLAG_RELOAD_SETTINGS,
+         cmd_id_x_originating_ip },
+       { "x-originating-port", IMAP_ID_PARAM_FLAG_RELOAD_SETTINGS,
+         cmd_id_x_originating_port },
+       { "x-connected-ip", IMAP_ID_PARAM_FLAG_RELOAD_SETTINGS,
+         cmd_id_x_connected_ip },
+       { "x-connected-port", IMAP_ID_PARAM_FLAG_RELOAD_SETTINGS,
+         cmd_id_x_connected_port },
+       { "x-connected-name", IMAP_ID_PARAM_FLAG_RELOAD_SETTINGS,
+         cmd_id_x_connected_name },
        { "x-proxy-ttl", 0, cmd_id_x_proxy_ttl },
        { "x-session-id", 0, cmd_id_x_session_id },
        { "x-session-ext-id", 0, cmd_id_x_session_id },
@@ -204,6 +211,8 @@ static bool cmd_id_handle_keyvalue(struct imap_client *client,
                                "Client sent invalid ID parameter '%s'", key);
                        return FALSE;
                }
+               if ((handler->flags & IMAP_ID_PARAM_FLAG_RELOAD_SETTINGS) != 0)
+                       client->cmd_id->reload_settings = TRUE;
        }
 
        if (client->set->imap_id_retain && !is_login_id_param &&
@@ -297,7 +306,7 @@ static void cmd_id_copy_params(struct imap_client *client,
        }
 }
 
-static void cmd_id_finish(struct imap_client *client)
+static int cmd_id_finish(struct imap_client *client)
 {
        if (!client->id_logged) {
                client->id_logged = TRUE;
@@ -335,7 +344,20 @@ static void cmd_id_finish(struct imap_client *client)
                cmd_id_copy_params(client, client->cmd_id->params);
                msg = "Trusted ID completed.";
        }
+
+       if (client->cmd_id->reload_settings) {
+               const char *error;
+               if (client_addresses_changed(&client->common, &error) < 0) {
+                       client_send_reply_code(&client->common,
+                                              IMAP_CMD_REPLY_NO,
+                                              IMAP_RESP_CODE_SERVERBUG,
+                                              "Failed to reload configuration");
+                       client_destroy(&client->common, error);
+                       return -1;
+               }
+       }
        client_send_reply(&client->common, IMAP_CMD_REPLY_OK, msg);
+       return 0;
 }
 
 void cmd_id_free(struct imap_client *client)
@@ -406,7 +428,8 @@ int cmd_id(struct imap_client *client)
        }
        if (ret == 0) {
                /* finished the line */
-               cmd_id_finish(client);
+               if (cmd_id_finish(client) < 0)
+                       return -1;
                cmd_id_free(client);
                return 1;
        } else if (ret == -1) {
index 0d0135f67b6cdd85651a9f29fcf05bb156fa9e03..17a4ca30b62108e1bcb7f7ca8db113059af86271 100644 (file)
@@ -705,6 +705,24 @@ void clients_destroy_all(void)
        clients_destroy_all_reason(MASTER_SERVICE_SHUTTING_DOWN_MSG);
 }
 
+int client_addresses_changed(struct client *client, const char **error_r)
+{
+       const char *error;
+
+       event_add_ip(client->event, "local_ip", &client->local_ip);
+       event_add_int(client->event, "local_port", client->local_port);
+       event_add_ip(client->event, "remote_ip", &client->ip);
+       event_add_int(client->event, "remote_port", client->remote_port);
+       event_add_str(client->event, "local_name", client->local_name);
+
+       if (client_settings_reload(client, &error) < 0) {
+               e_error(client->event, "%s", error);
+               *error_r = error;
+               return -1;
+       }
+       return 0;
+}
+
 int client_settings_reload(struct client *client, const char **error_r)
 {
        const struct login_settings *old_set = client->set;
index 1a3f58e25052f7b41028808612e337b7d211c325..bc6af6f7a01053c2ef02c73bb3ca6360d6ae659a 100644 (file)
@@ -361,6 +361,8 @@ bool client_unref(struct client **client) ATTR_NOWARN_UNUSED_RESULT;
 
 int client_settings_reload(struct client *client, const char **error_r)
        ATTR_WARN_UNUSED_RESULT;
+int client_addresses_changed(struct client *client, const char **error_r)
+       ATTR_WARN_UNUSED_RESULT;
 
 void client_rawlog_init(struct client *client);
 void client_rawlog_deinit(struct client *client);
index 46755e0c0a631f011880a6e0a7fa601e557ac256..ad7d9d263d1820e35d43f18a92e15718135197c7 100644 (file)
@@ -95,6 +95,15 @@ static bool cmd_xclient(struct pop3_client *client, const char *args)
        }
 
        /* args ok, set them and reset the state */
+       const char *error;
+       if (client_addresses_changed(&client->common, &error) < 0) {
+               client_send_reply(&client->common,
+                                 POP3_CMD_REPLY_ERROR,
+                                 "Failed to reload configuration");
+               client_destroy(&client->common, error);
+               return TRUE;
+       }
+
        client_send_reply(&client->common, POP3_CMD_REPLY_OK, "Updated");
        return TRUE;
 }
index 1309deaed88d939c1f5f8b0a1695314c06adf8c2..322b60cf432daca8d194588c2ffcc59f97bf5db8 100644 (file)
@@ -250,6 +250,14 @@ client_connection_cmd_xclient(void *context,
                        }
                }
        }
+
+       const char *error;
+       if (client_addresses_changed(&client->common, &error) < 0) {
+               client_notify_disconnect(&client->common,
+                       CLIENT_DISCONNECT_INTERNAL_ERROR,
+                       "Failed to reload configuration");
+               client_disconnect(&client->common, error);
+       }
 }
 
 static void client_connection_disconnect(void *context, const char *reason)