From: Aki Tuomi Date: Mon, 20 Feb 2017 17:11:01 +0000 (+0200) Subject: imap-login: Retain ID request without dovecot specials X-Git-Tag: 2.3.0.rc1~1925 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2f7c73483ff5474a74a83a646f82e1b60f687680;p=thirdparty%2Fdovecot%2Fcore.git imap-login: Retain ID request without dovecot specials --- diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c index fe547b9f7f..bfe51c284c 100644 --- a/src/imap-login/imap-login-client.c +++ b/src/imap-login/imap-login-client.c @@ -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) @@ -160,13 +172,16 @@ imap_client_notify_starttls(struct client *client, 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) { @@ -185,14 +200,49 @@ client_update_info(struct imap_client *client, 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 || @@ -284,6 +334,9 @@ static int cmd_id(struct imap_client *client) 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, diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h index 6b30b9e8d7..26359e9c26 100644 --- a/src/login-common/client-common.h +++ b/src/login-common/client-common.h @@ -10,6 +10,7 @@ struct module; #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: