]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
pop3-login: Implemented XCLIENT command for forwarding client ip/port from proxy.
authorTimo Sirainen <tss@iki.fi>
Sat, 25 Feb 2012 03:20:47 +0000 (05:20 +0200)
committerTimo Sirainen <tss@iki.fi>
Sat, 25 Feb 2012 03:20:47 +0000 (05:20 +0200)
src/pop3-login/client.c
src/pop3-login/client.h
src/pop3-login/pop3-proxy.c

index f1a32dfa5bc72c785430c4600be5b8a1ed1d58ec..a2cf9290a057f26cd6dbb2b8a5fa1dad7390c250 100644 (file)
@@ -35,6 +35,40 @@ static bool cmd_quit(struct pop3_client *client)
        return TRUE;
 }
 
+static bool cmd_xclient(struct pop3_client *client, const char *args)
+{
+       const char *const *tmp;
+       unsigned int remote_port;
+       bool args_ok = TRUE;
+
+       if (!client->common.trusted) {
+               client_send_line(&client->common, CLIENT_CMD_REPLY_BAD,
+                                "You are not from trusted IP");
+               return TRUE;
+       }
+       for (tmp = t_strsplit(args, " "); *tmp != NULL; tmp++) {
+               if (strncasecmp(*tmp, "ADDR=", 5) == 0) {
+                       if (net_addr2ip(*tmp + 5, &client->common.ip) < 0)
+                               args_ok = FALSE;
+               } else if (strncasecmp(*tmp, "PORT=", 5) == 0) {
+                       if (str_to_uint(*tmp + 5, &remote_port) < 0 ||
+                           remote_port == 0 || remote_port > 65535)
+                               args_ok = FALSE;
+                       else
+                               client->common.remote_port = remote_port;
+               }
+       }
+       if (!args_ok) {
+               client_send_line(&client->common, CLIENT_CMD_REPLY_BAD,
+                                "Invalid parameters");
+               return TRUE;
+       }
+
+       /* args ok, set them and reset the state */
+       client_send_line(&client->common, CLIENT_CMD_REPLY_OK, "Updated");
+       return TRUE;
+}
+
 static bool client_command_execute(struct pop3_client *client, const char *cmd,
                                   const char *args)
 {
@@ -53,6 +87,8 @@ static bool client_command_execute(struct pop3_client *client, const char *cmd,
                return cmd_stls(client);
        if (strcmp(cmd, "QUIT") == 0)
                return cmd_quit(client);
+       if (strcmp(cmd, "XCLIENT") == 0)
+               return cmd_xclient(client, args);
 
        client_send_line(&client->common, CLIENT_CMD_REPLY_BAD,
                         "Unknown command.");
@@ -149,18 +185,20 @@ static char *get_apop_challenge(struct pop3_client *client)
 static void pop3_client_send_greeting(struct client *client)
 {
        struct pop3_client *pop3_client = (struct pop3_client *)client;
+       string_t *str;
 
        client->io = io_add(client->fd, IO_READ, client_input, client);
 
-       pop3_client->apop_challenge = get_apop_challenge(pop3_client);
-       if (pop3_client->apop_challenge == NULL) {
-               client_send_line(client, CLIENT_CMD_REPLY_OK,
-                                client->set->login_greeting);
-       } else {
-               client_send_line(client, CLIENT_CMD_REPLY_OK,
-                       t_strconcat(client->set->login_greeting, " ",
-                                   pop3_client->apop_challenge, NULL));
+       str = t_str_new(128);
+       if (client->trusted) {
+               /* Dovecot extension to avoid extra roundtrip for CAPA */
+               str_append(str, "[XCLIENT] ");
        }
+       str_append(str, client->set->login_greeting);
+       pop3_client->apop_challenge = get_apop_challenge(pop3_client);
+       if (pop3_client->apop_challenge != NULL)
+               str_printfa(str, " %s", pop3_client->apop_challenge);
+       client_send_line(client, CLIENT_CMD_REPLY_OK, str_c(str));
        client->greeting_sent = TRUE;
 }
 
index d4b2b3c410529bf2114acd4a1cf89daec50fad09..3ae428a195bf5aff73d18ff37eb5f89520b0e18b 100644 (file)
@@ -18,6 +18,7 @@ struct pop3_client {
        char *last_user;
        char *apop_challenge;
        unsigned int apop_server_pid, apop_connect_uid;
+       bool proxy_xclient;
 };
 
 #endif
index 564e534a5b776af40bf860276fe34e941277b3eb..53b1ec71749b0fc13a6031911dd54e4ac12d87aa 100644 (file)
@@ -37,6 +37,14 @@ static void proxy_send_login(struct pop3_client *client, struct ostream *output)
 {
        string_t *str;
 
+       if (client->proxy_xclient) {
+               /* remote supports XCLIENT, send it */
+               (void)o_stream_send_str(output, t_strdup_printf(
+                       "XCLIENT ADDR=%s PORT=%u\r\n",
+                       net_ip2addr(&client->common.ip),
+                       client->common.remote_port));
+       }
+
        str = t_str_new(128);
        if (client->common.proxy_master_user == NULL) {
                /* send USER command */
@@ -71,6 +79,8 @@ int pop3_proxy_parse_line(struct client *client, const char *line)
                        client_proxy_failed(client, TRUE);
                        return -1;
                }
+               pop3_client->proxy_xclient =
+                       strncmp(line+3, " [XCLIENT]", 10) == 0;
 
                ssl_flags = login_proxy_get_ssl_flags(client->login_proxy);
                if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) {