Mercurial > dovecot > core-2.2
changeset 14302:5bbcf636bbeb
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).
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 07 Mar 2012 13:36:34 +0200 |
parents | 49b832c5de0e |
children | d048cebc1fd4 |
files | src/imap-login/client.c src/imap-login/imap-proxy.c src/imap/imap-client.c src/imap/imap-client.h src/imap/main.c src/lib-master/master-login.c src/lib-master/master-login.h src/lib-storage/mail-storage-service.c src/lib-storage/mail-storage-service.h src/login-common/client-common.c src/login-common/client-common.h src/login-common/sasl-server.c src/pop3-login/client.c src/pop3-login/pop3-proxy.c src/pop3/main.c src/pop3/pop3-client.c src/pop3/pop3-client.h |
diffstat | 17 files changed, 105 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- 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; } }
--- 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),
--- 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);
--- 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);
--- 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);
--- 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,
--- 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]; };
--- 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; }
--- 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;
--- 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; }
--- 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); +const char *client_get_session_id(struct client *client); bool client_read(struct client *client); void client_input(struct client *client);
--- a/src/login-common/sasl-server.c Wed Mar 07 13:32:40 2012 +0200 +++ b/src/login-common/sasl-server.c Wed Mar 07 13:36:34 2012 +0200 @@ -124,6 +124,7 @@ const unsigned char *data; size_t size; buffer_t *buf; + const char *session_id = client_get_session_id(client); memset(&req, 0, sizeof(req)); req.auth_pid = anvil_request->auth_pid; @@ -137,9 +138,12 @@ memcpy(req.cookie, anvil_request->cookie, sizeof(req.cookie)); buf = buffer_create_dynamic(pool_datastack_create(), 256); + /* session ID */ + buffer_append(buf, session_id, strlen(session_id)+1); + /* protocol specific data (e.g. IMAP tag) */ buffer_append(buf, client->master_data_prefix, client->master_data_prefix_len); - + /* buffered client input */ data = i_stream_get_data(client->input, &size); buffer_append(buf, data, size); req.data_size = buf->used;
--- a/src/pop3-login/client.c Wed Mar 07 13:32:40 2012 +0200 +++ b/src/pop3-login/client.c Wed Mar 07 13:36:34 2012 +0200 @@ -56,6 +56,9 @@ args_ok = FALSE; else client->common.remote_port = remote_port; + } else if (strncasecmp(*tmp, "SESSION=", 8) == 0) { + client->common.session_id = + p_strdup(client->common.pool, *tmp + 8); } } if (!args_ok) {
--- a/src/pop3-login/pop3-proxy.c Wed Mar 07 13:32:40 2012 +0200 +++ b/src/pop3-login/pop3-proxy.c Wed Mar 07 13:36:34 2012 +0200 @@ -40,9 +40,10 @@ 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", + "XCLIENT ADDR=%s PORT=%u SESSION=%s\r\n", net_ip2addr(&client->common.ip), - client->common.remote_port)); + client->common.remote_port, + client_get_session_id(&client->common))); client->common.proxy_state = POP3_PROXY_XCLIENT; } else { client->common.proxy_state = POP3_PROXY_LOGIN1;
--- a/src/pop3/main.c Wed Mar 07 13:32:40 2012 +0200 +++ b/src/pop3/main.c Wed Mar 07 13:36:34 2012 +0200 @@ -107,7 +107,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, input->session_id, + mail_user, user, set); if (client != NULL) T_BEGIN { client_add_input(client, input_buf); } T_END; @@ -155,6 +156,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);
--- a/src/pop3/pop3-client.c Wed Mar 07 13:32:40 2012 +0200 +++ b/src/pop3/pop3-client.c Wed Mar 07 13:36:34 2012 +0200 @@ -271,7 +271,8 @@ return mask; } -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 pop3_settings *set) { @@ -290,6 +291,7 @@ client = i_new(struct client, 1); client->service_user = service_user; client->set = set; + client->session_id = i_strdup(session_id); client->fd_in = fd_in; client->fd_out = fd_out; client->input = i_stream_create_fd(fd_in, MAX_INBUF_SIZE, FALSE); @@ -424,6 +426,7 @@ { 'i', NULL, "input" }, { 'o', NULL, "output" }, { 'u', NULL, "uidl_change" }, + { '\0', NULL, "session" }, { '\0', NULL, NULL } }; struct var_expand_table *tab; @@ -442,6 +445,7 @@ tab[7].value = dec2str(client->input->v_offset); tab[8].value = dec2str(client->output->offset); tab[9].value = client_build_uidl_change_string(client); + tab[10].value = client->session_id; str = t_str_new(128); var_expand(str, client->set->pop3_logout_format, tab); @@ -513,6 +517,7 @@ if (client->fd_in != client->fd_out) net_disconnect(client->fd_out); mail_storage_service_user_free(&client->service_user); + i_free(client->session_id); i_free(client); master_service_client_connection_destroyed(master_service);
--- a/src/pop3/pop3-client.h Wed Mar 07 13:32:40 2012 +0200 +++ b/src/pop3/pop3-client.h Wed Mar 07 13:36:34 2012 +0200 @@ -18,6 +18,7 @@ struct client { struct client *prev, *next; + char *session_id; int fd_in, fd_out; struct io *io; struct istream *input; @@ -77,7 +78,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 pop3_settings *set); void client_destroy(struct client *client, const char *reason);