dovecot-1.2: Support transferring original IPs and ports through...

dovecot at dovecot.org dovecot at dovecot.org
Sat Jun 21 10:10:44 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/3644883cf44e
changeset: 7920:3644883cf44e
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Jun 21 10:10:06 2008 +0300
description:
Support transferring original IPs and ports through IMAP proxies.
Clients from login_trusted_networks are allowed to override them. Dovecot's
IMAP proxy sends them via IMAP ID command. They're always sent if the remote
advertises ID in the banner's CAPABILITY.

diffstat:

12 files changed, 118 insertions(+), 5 deletions(-)
dovecot-example.conf              |    6 +++++
src/imap-login/client.c           |   34 +++++++++++++++++++++++++++++--
src/imap-login/imap-proxy.c       |   40 ++++++++++++++++++++++++++++++++++++-
src/login-common/client-common.c  |   23 +++++++++++++++++++++
src/login-common/client-common.h  |    2 +
src/login-common/common.h         |    1 
src/login-common/main.c           |    3 ++
src/master/login-process.c        |    4 +++
src/master/master-settings-defs.c |    1 
src/master/master-settings.c      |    1 
src/master/master-settings.h      |    1 
src/pop3-login/client.c           |    7 ++++--

diffs (283 lines):

diff -r 423b8e3fedbb -r 3644883cf44e dovecot-example.conf
--- a/dovecot-example.conf	Sat Jun 21 09:54:26 2008 +0300
+++ b/dovecot-example.conf	Sat Jun 21 10:10:06 2008 +0300
@@ -173,6 +173,12 @@
 
 # Greeting message for clients.
 #login_greeting = Dovecot ready.
+
+# Space separated list of trusted network ranges. Connections from these
+# IPs are allowed to override their IP addresses and ports (for logging and
+# for authentication checks). disable_plaintext_auth is also ignored for
+# these networks. Typically you'd specify your IMAP proxy servers here.
+#login_trusted_networks =
 
 # Space-separated list of elements we want to log. The elements which have
 # a non-empty variable value are joined together to form a comma-separated
diff -r 423b8e3fedbb -r 3644883cf44e src/imap-login/client.c
--- a/src/imap-login/client.c	Sat Jun 21 09:54:26 2008 +0300
+++ b/src/imap-login/client.c	Sat Jun 21 10:10:06 2008 +0300
@@ -200,12 +200,40 @@ static int cmd_starttls(struct imap_clie
 	return 1;
 }
 
+static void
+client_update_info(struct imap_client *client, const struct imap_arg *args)
+{
+	const char *key, *value;
+
+	if (args->type != IMAP_ARG_LIST)
+		return;
+	args = IMAP_ARG_LIST_ARGS(args);
+
+	while (args->type == IMAP_ARG_STRING &&
+	       args[1].type == IMAP_ARG_STRING) {
+		key = IMAP_ARG_STR_NONULL(&args[0]);
+		value = IMAP_ARG_STR_NONULL(&args[1]);
+		if (strcasecmp(key, "x-originating-ip") == 0)
+			(void)net_addr2ip(value, &client->common.ip);
+		else if (strcasecmp(key, "x-originating-port") == 0)
+			client->common.remote_port = atoi(value);
+		else if (strcasecmp(key, "x-local-ip") == 0)
+			(void)net_addr2ip(value, &client->common.local_ip);
+		else if (strcasecmp(key, "x-local-port") == 0)
+			client->common.local_port = atoi(value);
+		args += 2;
+	}
+}
+
 static int cmd_id(struct imap_client *client, const struct imap_arg *args)
 {
 	const char *env, *value;
 
 	if (!client->id_logged) {
 		client->id_logged = TRUE;
+		if (client->common.trusted)
+			client_update_info(client, args);
+
 		env = getenv("IMAP_ID_LOG");
 		value = imap_id_args_get_log_reply(args, env);
 		if (value != NULL) {
@@ -478,12 +506,14 @@ struct client *client_create(int fd, boo
 	client = i_new(struct imap_client, 1);
 	client->created = ioloop_time;
 	client->refcount = 1;
-	client->common.tls = ssl;
-	client->common.secured = ssl || net_ip_compare(ip, local_ip);
 
 	client->common.local_ip = *local_ip;
 	client->common.ip = *ip;
 	client->common.fd = fd;
+	client->common.tls = ssl;
+	client->common.trusted = client_is_trusted(&client->common);
+	client->common.secured = ssl || client->common.trusted ||
+		net_ip_compare(ip, local_ip);
 
 	client_open_streams(client, fd);
 	client->io = io_add(fd, IO_READ, client_input, client);
diff -r 423b8e3fedbb -r 3644883cf44e src/imap-login/imap-proxy.c
--- a/src/imap-login/imap-proxy.c	Sat Jun 21 09:54:26 2008 +0300
+++ b/src/imap-login/imap-proxy.c	Sat Jun 21 10:10:06 2008 +0300
@@ -11,6 +11,41 @@
 #include "imap-quote.h"
 #include "imap-proxy.h"
 
+static bool imap_banner_has_capability(const char *line, const char *capability)
+{
+	unsigned int capability_len = strlen(capability);
+
+	if (strncmp(line, "[CAPABILITY ", 12) != 0)
+		return FALSE;
+
+	line += 12;
+	while (strncmp(line, capability, capability_len) != 0 ||
+	       (line[capability_len] != ' ' &&
+		line[capability_len] != '\0')) {
+		/* skip over the capability */
+		while (*line != ' ') {
+			if (*line == '\0')
+				return FALSE;
+			line++;
+		}
+		line++;
+	}
+	return TRUE;
+}
+
+static void proxy_write_id(struct imap_client *client, string_t *str)
+{
+	str_printfa(str, "I ID ("
+		    "\"x-originating-ip\" \"%s\" "
+		    "\"x-originating-port\" \"%u\" "
+		    "\"x-local-ip\" \"%s\" "
+		    "\"x-local-port\" \"%u\")\r\n",
+		    net_ip2addr(&client->common.ip),
+		    client->common.remote_port,
+		    net_ip2addr(&client->common.local_ip),
+		    client->common.local_port);
+}
+
 static int proxy_input_line(struct imap_client *client,
 			    struct ostream *output, const char *line)
 {
@@ -29,8 +64,11 @@ static int proxy_input_line(struct imap_
 			return -1;
 		}
 
+		str = t_str_new(128);
+		if (imap_banner_has_capability(line + 5, "ID"))
+			proxy_write_id(client, str);
+
 		/* send LOGIN command */
-		str = t_str_new(128);
 		str_append(str, "P LOGIN ");
 		imap_quote_append_string(str, client->proxy_user, FALSE);
 		str_append_c(str, ' ');
diff -r 423b8e3fedbb -r 3644883cf44e src/login-common/client-common.c
--- a/src/login-common/client-common.c	Sat Jun 21 09:54:26 2008 +0300
+++ b/src/login-common/client-common.c	Sat Jun 21 10:10:06 2008 +0300
@@ -151,3 +151,26 @@ void client_syslog(struct client *client
 		client_syslog_real(client, msg);
 	} T_END;
 }
+
+bool client_is_trusted(struct client *client)
+{
+	const char *const *net;
+	struct ip_addr net_ip;
+	unsigned int bits;
+
+	if (trusted_networks == NULL)
+		return FALSE;
+
+	net = t_strsplit_spaces(trusted_networks, ", ");
+	for (; *net != NULL; net++) {
+		if (net_parse_range(*net, &net_ip, &bits) < 0) {
+			i_error("login_trusted_networks: "
+				"Invalid network '%s'", *net);
+			break;
+		}
+
+		if (net_is_in_network(&client->ip, &net_ip, bits))
+			return TRUE;
+	}
+	return FALSE;
+}
diff -r 423b8e3fedbb -r 3644883cf44e src/login-common/client-common.h
--- a/src/login-common/client-common.h	Sat Jun 21 09:54:26 2008 +0300
+++ b/src/login-common/client-common.h	Sat Jun 21 10:10:06 2008 +0300
@@ -27,6 +27,7 @@ struct client {
 	char *virtual_user;
 	unsigned int tls:1;
 	unsigned int secured:1;
+	unsigned int trusted:1;
 	unsigned int authenticating:1;
 	unsigned int auth_tried_disabled_plaintext:1;
 	/* ... */
@@ -42,6 +43,7 @@ unsigned int clients_get_count(void) ATT
 unsigned int clients_get_count(void) ATTR_PURE;
 
 void client_syslog(struct client *client, const char *msg);
+bool client_is_trusted(struct client *client);
 
 void clients_notify_auth_connected(void);
 void client_destroy_oldest(void);
diff -r 423b8e3fedbb -r 3644883cf44e src/login-common/common.h
--- a/src/login-common/common.h	Sat Jun 21 09:54:26 2008 +0300
+++ b/src/login-common/common.h	Sat Jun 21 10:10:06 2008 +0300
@@ -18,6 +18,7 @@ extern const char *greeting, *log_format
 extern const char *greeting, *log_format;
 extern const char *const *log_format_elements;
 extern const char *capability_string;
+extern const char *trusted_networks;
 extern unsigned int max_connections;
 extern unsigned int login_process_uid;
 extern struct auth_client *auth_client;
diff -r 423b8e3fedbb -r 3644883cf44e src/login-common/main.c
--- a/src/login-common/main.c	Sat Jun 21 09:54:26 2008 +0300
+++ b/src/login-common/main.c	Sat Jun 21 10:10:06 2008 +0300
@@ -23,6 +23,7 @@ bool verbose_proctitle, verbose_ssl, ver
 bool verbose_proctitle, verbose_ssl, verbose_auth;
 const char *greeting, *log_format;
 const char *const *log_format_elements;
+const char *trusted_networks;
 unsigned int max_connections;
 unsigned int login_process_uid;
 struct auth_client *auth_client;
@@ -329,6 +330,8 @@ static void main_init(void)
 	if (log_format == NULL)
 		log_format = "%$: %s";
 
+	trusted_networks = getenv("TRUSTED_NETWORKS");
+
 	value = getenv("PROCESS_UID");
 	if (value == NULL)
 		i_fatal("BUG: PROCESS_UID environment not given");
diff -r 423b8e3fedbb -r 3644883cf44e src/master/login-process.c
--- a/src/master/login-process.c	Sat Jun 21 09:54:26 2008 +0300
+++ b/src/master/login-process.c	Sat Jun 21 10:10:06 2008 +0300
@@ -582,6 +582,10 @@ static void login_process_init_env(struc
 				    set->imap_capability :
 				    set->imap_generated_capability, NULL));
 	}
+	if (*set->login_trusted_networks != '\0') {
+		env_put(t_strconcat("TRUSTED_NETWORKS=",
+				    set->login_trusted_networks, NULL));
+	}
 }
 
 static pid_t create_login_process(struct login_group *group)
diff -r 423b8e3fedbb -r 3644883cf44e src/master/master-settings-defs.c
--- a/src/master/master-settings-defs.c	Sat Jun 21 09:54:26 2008 +0300
+++ b/src/master/master-settings-defs.c	Sat Jun 21 10:10:06 2008 +0300
@@ -46,6 +46,7 @@ static struct setting_def setting_defs[]
 	DEF_BOOL(login_process_per_connection),
 	DEF_BOOL(login_chroot),
 	DEF_BOOL(login_greeting_capability),
+	DEF_STR(login_trusted_networks),
 
 	DEF_INT(login_process_size),
 	DEF_INT(login_processes_count),
diff -r 423b8e3fedbb -r 3644883cf44e src/master/master-settings.c
--- a/src/master/master-settings.c	Sat Jun 21 09:54:26 2008 +0300
+++ b/src/master/master-settings.c	Sat Jun 21 10:10:06 2008 +0300
@@ -208,6 +208,7 @@ struct settings default_settings = {
 	MEMBER(login_process_per_connection) TRUE,
 	MEMBER(login_chroot) TRUE,
 	MEMBER(login_greeting_capability) FALSE,
+	MEMBER(login_trusted_networks) "",
 
 	MEMBER(login_process_size) 64,
 	MEMBER(login_processes_count) 3,
diff -r 423b8e3fedbb -r 3644883cf44e src/master/master-settings.h
--- a/src/master/master-settings.h	Sat Jun 21 09:54:26 2008 +0300
+++ b/src/master/master-settings.h	Sat Jun 21 10:10:06 2008 +0300
@@ -60,6 +60,7 @@ struct settings {
 	bool login_process_per_connection;
 	bool login_chroot;
 	bool login_greeting_capability;
+	const char *login_trusted_networks;
 
 	unsigned int login_process_size;
 	unsigned int login_processes_count;
diff -r 423b8e3fedbb -r 3644883cf44e src/pop3-login/client.c
--- a/src/pop3-login/client.c	Sat Jun 21 09:54:26 2008 +0300
+++ b/src/pop3-login/client.c	Sat Jun 21 10:10:06 2008 +0300
@@ -317,12 +317,15 @@ struct client *client_create(int fd, boo
 	client = i_new(struct pop3_client, 1);
 	client->created = ioloop_time;
 	client->refcount = 1;
-	client->common.tls = ssl;
-	client->common.secured = ssl || net_ip_compare(ip, local_ip);
 
 	client->common.local_ip = *local_ip;
 	client->common.ip = *ip;
 	client->common.fd = fd;
+	client->common.tls = ssl;
+	client->common.trusted = client_is_trusted(&client->common);
+	client->common.secured = ssl || client->common.trusted ||
+		net_ip_compare(ip, local_ip);
+
 	client_open_streams(client, fd);
 	client_link(&client->common);
 


More information about the dovecot-cvs mailing list