changeset 21768:a1bf55c221c2

imap-login: Retain ID request without dovecot specials
author Aki Tuomi <aki.tuomi@dovecot.fi>
date Mon, 20 Feb 2017 19:11:01 +0200
parents b86e6d2abf23
children 6985bf43b94f
files src/imap-login/imap-login-client.c src/login-common/client-common.h
diffstat 2 files changed, 58 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap-login/imap-login-client.c	Tue Feb 21 14:46:31 2017 +0200
+++ b/src/imap-login/imap-login-client.c	Mon Feb 20 19:11:01 2017 +0200
@@ -19,6 +19,7 @@
 #include "auth-client.h"
 #include "ssl-proxy.h"
 #include "imap-proxy.h"
+#include "imap-quote.h"
 #include "imap-login-commands.h"
 #include "imap-login-settings.h"
 
@@ -32,6 +33,17 @@
 /* Disconnect client when it sends too many bad commands */
 #define CLIENT_MAX_BAD_COMMANDS 3
 
+static const char *const imap_login_reserved_id_keys[] = {
+	"x-originating-ip",
+	"x-originating-port",
+	"x-connected-ip",
+	"x-connected-port",
+	"x-proxy-ttl",
+	"x-session-id",
+	"x-session-ext-id",
+	NULL
+};
+
 /* Skip incoming data until newline is found,
    returns TRUE if newline was found. */
 bool client_skip_line(struct imap_client *client)
@@ -146,13 +158,16 @@
 		client_send_reply(client, IMAP_CMD_REPLY_BAD, text);
 }
 
-static void
+static bool
 client_update_info(struct imap_client *client,
 		   const char *key, const char *value)
 {
 	/* do not try to process NIL value */
 	if (value == NULL)
-		return;
+		return FALSE;
+
+	/* SYNC WITH imap_login_reserved_id_keys */
+
 	if (strcasecmp(key, "x-originating-ip") == 0) {
 		(void)net_addr2ip(value, &client->common.ip);
 	} else if (strcasecmp(key, "x-originating-port") == 0) {
@@ -171,14 +186,49 @@
 			client->common.session_id =
 				p_strdup(client->common.pool, value);
 		}
+	} else {
+		return FALSE;
 	}
+	return TRUE;
+}
+
+static bool client_id_reserved_word(const char *key)
+{
+	i_assert(key != NULL);
+	return str_array_icase_find(imap_login_reserved_id_keys, key);
 }
 
 static void cmd_id_handle_keyvalue(struct imap_client *client,
 				   const char *key, const char *value)
 {
-	if (client->common.trusted && !client->id_logged)
-		client_update_info(client, key, value);
+	bool client_id_str;
+	/* length of key + length of value (NIL for NULL) and two set of
+	   quotes and space */
+	size_t kvlen = strlen(key) + 2 + 1 +
+		       (value == NULL ? 3 : strlen(value)) + 2;
+
+	if (client->common.trusted && !client->id_logged) {
+		client_id_str = !client_update_info(client, key, value);
+		i_assert(client_id_str == !client_id_reserved_word(key));
+	} else {
+		client_id_str = !client_id_reserved_word(key);
+	}
+
+	if (client_id_str &&
+	    (client->common.client_id == NULL ||
+	     str_len(client->common.client_id) + kvlen < LOGIN_MAX_CLIENT_ID_LEN)) {
+		if (client->common.client_id == NULL) {
+			client->common.client_id = str_new(client->common.preproxy_pool, 64);
+		} else {
+			str_append_c(client->common.client_id, ' ');
+		}
+		imap_append_quoted(client->common.client_id, key);
+		str_append_c(client->common.client_id, ' ');
+		if (value == NULL)
+			str_append(client->common.client_id, "NIL");
+		else
+			imap_append_quoted(client->common.client_id, value);
+	}
 
 	if (client->cmd_id->log_reply != NULL &&
 	    (client->cmd_id->log_keys == NULL ||
@@ -270,6 +320,9 @@
 	const struct imap_arg *args;
 	int ret;
 
+	if (client->common.client_id != NULL)
+		str_truncate(client->common.client_id, 0);
+
 	if (client->cmd_id == NULL) {
 		client->cmd_id = id = i_new(struct imap_client_cmd_id, 1);
 		id->parser = imap_parser_create(client->common.input,
--- a/src/login-common/client-common.h	Tue Feb 21 14:46:31 2017 +0200
+++ b/src/login-common/client-common.h	Mon Feb 20 19:11:01 2017 +0200
@@ -10,6 +10,7 @@
 
 #define LOGIN_MAX_SESSION_ID_LEN 64
 #define LOGIN_MAX_MASTER_PREFIX_LEN 128
+#define LOGIN_MAX_CLIENT_ID_LEN 256
 
 /* max. size of input buffer. this means: