dovecot-2.2: Added a "session ID" string for imap/pop3 connectio...

dovecot at dovecot.org dovecot at dovecot.org
Sun May 20 03:26:26 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/5bbcf636bbeb
changeset: 14302:5bbcf636bbeb
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Mar 07 13:36:34 2012 +0200
description:
Added a "session ID" string for imap/pop3 connections, available in %{session} variable.
The session ID passes through Dovecot IMAP/POP3 proxying to backend server.
The same session ID is can be reused after a long time (currently a bit
under 9 years).

diffstat:

 src/imap-login/client.c                |   4 +++
 src/imap-login/imap-proxy.c            |   2 +
 src/imap/imap-client.c                 |   6 ++++-
 src/imap/imap-client.h                 |   4 ++-
 src/imap/main.c                        |   4 ++-
 src/lib-master/master-login.c          |  16 +++++++++++++-
 src/lib-master/master-login.h          |   3 ++
 src/lib-storage/mail-storage-service.c |   2 +
 src/lib-storage/mail-storage-service.h |   1 +
 src/login-common/client-common.c       |  39 ++++++++++++++++++++++++++++++++++
 src/login-common/client-common.h       |   6 ++++-
 src/login-common/sasl-server.c         |   6 ++++-
 src/pop3-login/client.c                |   3 ++
 src/pop3-login/pop3-proxy.c            |   5 ++-
 src/pop3/main.c                        |   4 ++-
 src/pop3/pop3-client.c                 |   7 +++++-
 src/pop3/pop3-client.h                 |   4 ++-
 17 files changed, 105 insertions(+), 11 deletions(-)

diffs (truncated from 445 to 300 lines):

diff -r 49b832c5de0e -r 5bbcf636bbeb src/imap-login/client.c
--- a/src/imap-login/client.c	Wed Mar 07 13:32:40 2012 +0200
+++ b/src/imap-login/client.c	Wed Mar 07 13:36:34 2012 +0200
@@ -111,6 +111,10 @@
 			(void)net_addr2ip(value, &client->common.local_ip);
 		else if (strcasecmp(key, "x-connected-port") == 0)
 			client->common.local_port = atoi(value);
+		else if (strcasecmp(key, "x-session-id") == 0) {
+			client->common.session_id =
+				p_strdup(client->common.pool, value);
+		}
 		args += 2;
 	}
 }
diff -r 49b832c5de0e -r 5bbcf636bbeb src/imap-login/imap-proxy.c
--- a/src/imap-login/imap-proxy.c	Wed Mar 07 13:32:40 2012 +0200
+++ b/src/imap-login/imap-proxy.c	Wed Mar 07 13:36:34 2012 +0200
@@ -30,10 +30,12 @@
 static void proxy_write_id(struct imap_client *client, string_t *str)
 {
 	str_printfa(str, "I ID ("
+		    "\"x-session-id\" \"%s\" "
 		    "\"x-originating-ip\" \"%s\" "
 		    "\"x-originating-port\" \"%u\" "
 		    "\"x-connected-ip\" \"%s\" "
 		    "\"x-connected-port\" \"%u\")\r\n",
+		    client_get_session_id(&client->common),
 		    net_ip2addr(&client->common.ip),
 		    client->common.remote_port,
 		    net_ip2addr(&client->common.local_ip),
diff -r 49b832c5de0e -r 5bbcf636bbeb src/imap/imap-client.c
--- a/src/imap/imap-client.c	Wed Mar 07 13:32:40 2012 +0200
+++ b/src/imap/imap-client.c	Wed Mar 07 13:36:34 2012 +0200
@@ -32,7 +32,8 @@
 	client_destroy(client, "Disconnected for inactivity");
 }
 
-struct client *client_create(int fd_in, int fd_out, struct mail_user *user,
+struct client *client_create(int fd_in, int fd_out, const char *session_id,
+			     struct mail_user *user,
 			     struct mail_storage_service_user *service_user,
 			     const struct imap_settings *set)
 {
@@ -49,6 +50,7 @@
 	client->pool = pool;
 	client->set = set;
 	client->service_user = service_user;
+	client->session_id = p_strdup(pool, session_id);
 	client->fd_in = fd_in;
 	client->fd_out = fd_out;
 	client->input = i_stream_create_fd(fd_in,
@@ -143,6 +145,7 @@
 	static struct var_expand_table static_tab[] = {
 		{ 'i', NULL, "input" },
 		{ 'o', NULL, "output" },
+		{ '\0', NULL, "session" },
 		{ '\0', NULL, NULL }
 	};
 	struct var_expand_table *tab;
@@ -153,6 +156,7 @@
 
 	tab[0].value = dec2str(i_stream_get_absolute_offset(client->input));
 	tab[1].value = dec2str(client->output->offset);
+	tab[2].value = client->session_id;
 
 	str = t_str_new(128);
 	var_expand(str, client->set->imap_logout_format, tab);
diff -r 49b832c5de0e -r 5bbcf636bbeb src/imap/imap-client.h
--- a/src/imap/imap-client.h	Wed Mar 07 13:32:40 2012 +0200
+++ b/src/imap/imap-client.h	Wed Mar 07 13:36:34 2012 +0200
@@ -99,6 +99,7 @@
 struct client {
 	struct client *prev, *next;
 
+	const char *session_id;
 	int fd_in, fd_out;
 	struct io *io;
 	struct istream *input;
@@ -170,7 +171,8 @@
 
 /* Create new client with specified input/output handles. socket specifies
    if the handle is a socket. */
-struct client *client_create(int fd_in, int fd_out, struct mail_user *user,
+struct client *client_create(int fd_in, int fd_out, const char *session_id,
+			     struct mail_user *user,
 			     struct mail_storage_service_user *service_user,
 			     const struct imap_settings *set);
 void client_destroy(struct client *client, const char *reason);
diff -r 49b832c5de0e -r 5bbcf636bbeb src/imap/main.c
--- a/src/imap/main.c	Wed Mar 07 13:32:40 2012 +0200
+++ b/src/imap/main.c	Wed Mar 07 13:36:34 2012 +0200
@@ -208,7 +208,8 @@
 	if (set->verbose_proctitle)
 		verbose_proctitle = TRUE;
 
-	client = client_create(fd_in, fd_out, mail_user, user, set);
+	client = client_create(fd_in, fd_out, login_client->session_id,
+			       mail_user, user, set);
 	T_BEGIN {
 		client_add_input(client, input_buf);
 	} T_END;
@@ -261,6 +262,7 @@
 	input.remote_ip = client->auth_req.remote_ip;
 	input.username = username;
 	input.userdb_fields = extra_fields;
+	input.session_id = client->session_id;
 
 	buffer_create_const_data(&input_buf, client->data,
 				 client->auth_req.data_size);
diff -r 49b832c5de0e -r 5bbcf636bbeb src/lib-master/master-login.c
--- a/src/lib-master/master-login.c	Wed Mar 07 13:32:40 2012 +0200
+++ b/src/lib-master/master-login.c	Wed Mar 07 13:36:34 2012 +0200
@@ -392,6 +392,7 @@
 	struct master_login_client *client;
 	struct master_login *login = conn->login;
 	unsigned char data[MASTER_AUTH_MAX_DATA_SIZE];
+	unsigned int i, session_len = 0;
 	int ret, client_fd;
 
 	ret = master_login_conn_read_request(conn, &req, data, &client_fd);
@@ -408,12 +409,25 @@
 	}
 	fd_close_on_exec(client_fd, TRUE);
 
+	/* extract the session ID from the request data */
+	for (i = 0; i < req.data_size; i++) {
+		if (data[i] == '\0') {
+			session_len = i++;
+			break;
+		}
+	}
+	if (session_len >= sizeof(client->session_id)) {
+		i_error("login client: Session ID too long");
+		session_len = 0;
+	}
+
 	/* @UNSAFE: we have a request. do userdb lookup for it. */
 	client = i_malloc(sizeof(struct master_login_client) + req.data_size);
 	client->conn = conn;
 	client->fd = client_fd;
 	client->auth_req = req;
-	memcpy(client->data, data, req.data_size);
+	memcpy(client->session_id, data, session_len);
+	memcpy(client->data, data+i, req.data_size-i);
 	conn->refcount++;
 
 	master_login_auth_request(login->auth, &req,
diff -r 49b832c5de0e -r 5bbcf636bbeb src/lib-master/master-login.h
--- a/src/lib-master/master-login.h	Wed Mar 07 13:32:40 2012 +0200
+++ b/src/lib-master/master-login.h	Wed Mar 07 13:36:34 2012 +0200
@@ -4,12 +4,15 @@
 #include "master-auth.h"
 
 #define MASTER_POSTLOGIN_TIMEOUT_DEFAULT 60
+/* base64(<IPv6><port><48bit timestamp>) + NUL */
+#define LOGIN_MAX_SESSION_ID_LEN 33
 
 struct master_login_client {
 	struct master_login_connection *conn;
 	int fd;
 
 	struct master_auth_request auth_req;
+	char session_id[LOGIN_MAX_SESSION_ID_LEN];
 	unsigned char data[FLEXIBLE_ARRAY_MEMBER];
 };
 
diff -r 49b832c5de0e -r 5bbcf636bbeb src/lib-storage/mail-storage-service.c
--- a/src/lib-storage/mail-storage-service.c	Wed Mar 07 13:32:40 2012 +0200
+++ b/src/lib-storage/mail-storage-service.c	Wed Mar 07 13:36:34 2012 +0200
@@ -374,6 +374,7 @@
 		{ 'p', NULL, "pid" },
 		{ 'i', NULL, "uid" },
 		{ '\0', NULL, "gid" },
+		{ '\0', NULL, "session" },
 		{ '\0', NULL, NULL }
 	};
 	struct var_expand_table *tab;
@@ -391,6 +392,7 @@
 	tab[6].value = my_pid;
 	tab[7].value = dec2str(priv->uid == (uid_t)-1 ? geteuid() : priv->uid);
 	tab[8].value = dec2str(priv->gid == (gid_t)-1 ? getegid() : priv->gid);
+	tab[9].value = input->session_id;
 	return tab;
 }
 
diff -r 49b832c5de0e -r 5bbcf636bbeb src/lib-storage/mail-storage-service.h
--- a/src/lib-storage/mail-storage-service.h	Wed Mar 07 13:32:40 2012 +0200
+++ b/src/lib-storage/mail-storage-service.h	Wed Mar 07 13:36:34 2012 +0200
@@ -40,6 +40,7 @@
 	const char *module;
 	const char *service;
 	const char *username;
+	const char *session_id;
 	struct ip_addr local_ip, remote_ip;
 	unsigned int local_port, remote_port;
 
diff -r 49b832c5de0e -r 5bbcf636bbeb src/login-common/client-common.c
--- a/src/login-common/client-common.c	Wed Mar 07 13:32:40 2012 +0200
+++ b/src/login-common/client-common.c	Wed Mar 07 13:36:34 2012 +0200
@@ -7,7 +7,9 @@
 #include "ostream.h"
 #include "iostream-rawlog.h"
 #include "process-title.h"
+#include "buffer.h"
 #include "str.h"
+#include "base64.h"
 #include "str-sanitize.h"
 #include "safe-memset.h"
 #include "var-expand.h"
@@ -376,6 +378,41 @@
 	return clients_count;
 }
 
+const char *client_get_session_id(struct client *client)
+{
+	buffer_t *buf, *base64_buf;
+	struct timeval tv;
+	uint64_t timestamp;
+	unsigned int i;
+
+	if (client->session_id != NULL)
+		return client->session_id;
+
+	buf = buffer_create_dynamic(pool_datastack_create(), 24);
+	base64_buf = buffer_create_dynamic(pool_datastack_create(), 24*2);
+
+	if (gettimeofday(&tv, NULL) < 0)
+		i_fatal("gettimeofday(): %m");
+	timestamp = tv.tv_usec + (long long)tv.tv_sec * 1000ULL*1000ULL;
+
+	/* add lowest 48 bits of the timestamp. this gives us a bit less than
+	   9 years until it wraps */
+	for (i = 0; i < 48; i += 8)
+		buffer_append_c(buf, (timestamp >> i) & 0xff);
+
+	buffer_append_c(buf, client->remote_port & 0xff);
+	buffer_append_c(buf, (client->remote_port >> 16) & 0xff);
+#ifdef HAVE_IPV6
+	if (IPADDR_IS_V6(&client->ip))
+		buffer_append(buf, &client->ip.u.ip6, sizeof(client->ip.u.ip6));
+	else
+#endif
+		buffer_append(buf, &client->ip.u.ip4, sizeof(client->ip.u.ip4));
+	base64_encode(buf->data, buf->used, base64_buf);
+	client->session_id = p_strdup(client->pool, str_c(base64_buf));
+	return client->session_id;
+}
+
 static struct var_expand_table login_var_expand_empty_tab[] = {
 	{ 'u', NULL, "user" },
 	{ 'n', NULL, "username" },
@@ -391,6 +428,7 @@
 	{ 'c', NULL, "secured" },
 	{ 'k', NULL, "ssl_security" },
 	{ 'e', NULL, "mail_pid" },
+	{ '\0', NULL, "session" },
 	{ '\0', NULL, NULL }
 };
 
@@ -439,6 +477,7 @@
 	}
 	tab[13].value = client->mail_pid == 0 ? "" :
 		dec2str(client->mail_pid);
+	tab[14].value = client_get_session_id(client);
 	return tab;
 }
 
diff -r 49b832c5de0e -r 5bbcf636bbeb src/login-common/client-common.h
--- a/src/login-common/client-common.h	Wed Mar 07 13:32:40 2012 +0200
+++ b/src/login-common/client-common.h	Wed Mar 07 13:36:34 2012 +0200
@@ -4,6 +4,7 @@
 #include "network.h"
 #include "login-proxy.h"
 #include "sasl-server.h"
+#include "master-login.h" /* for LOGIN_MAX_SESSION_ID_LEN */
 
 #define LOGIN_MAX_MASTER_PREFIX_LEN 128
 
@@ -14,7 +15,8 @@
    POP3: Max. length of a command line (spec says 512 would be enough)
 */
 #define LOGIN_MAX_INBUF_SIZE \
-	(MASTER_AUTH_MAX_DATA_SIZE - LOGIN_MAX_MASTER_PREFIX_LEN)
+	(MASTER_AUTH_MAX_DATA_SIZE - LOGIN_MAX_MASTER_PREFIX_LEN - \
+	 LOGIN_MAX_SESSION_ID_LEN)
 /* max. size of output buffer. if it gets full, the client is disconnected.
    SASL authentication gives the largest output. */
 #define LOGIN_MAX_OUTBUF_SIZE 4096
@@ -89,6 +91,7 @@
 	unsigned int local_port, remote_port;
 	struct ssl_proxy *ssl_proxy;
 	const struct login_settings *set;
+	const char *session_id;
 
 	int fd;
 	struct istream *input;
@@ -163,6 +166,7 @@
 const char *client_get_extra_disconnect_reason(struct client *client);
 bool client_is_trusted(struct client *client);
 void client_auth_failed(struct client *client);


More information about the dovecot-cvs mailing list