From: Timo Sirainen Date: Sat, 25 Feb 2012 03:20:47 +0000 (+0200) Subject: pop3-login: Implemented XCLIENT command for forwarding client ip/port from proxy. X-Git-Tag: 2.1.2~125 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ad9da7356677de3b1176bbed0ec8a04e7a33ea03;p=thirdparty%2Fdovecot%2Fcore.git pop3-login: Implemented XCLIENT command for forwarding client ip/port from proxy. --- diff --git a/src/pop3-login/client.c b/src/pop3-login/client.c index f1a32dfa5b..a2cf9290a0 100644 --- a/src/pop3-login/client.c +++ b/src/pop3-login/client.c @@ -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; } diff --git a/src/pop3-login/client.h b/src/pop3-login/client.h index d4b2b3c410..3ae428a195 100644 --- a/src/pop3-login/client.h +++ b/src/pop3-login/client.h @@ -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 diff --git a/src/pop3-login/pop3-proxy.c b/src/pop3-login/pop3-proxy.c index 564e534a5b..53b1ec7174 100644 --- a/src/pop3-login/pop3-proxy.c +++ b/src/pop3-login/pop3-proxy.c @@ -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) {