diff --git a/CVE-2020-24386.patch b/CVE-2020-24386.patch new file mode 100644 index 0000000000000000000000000000000000000000..a59ad9783450ad5711cdd878063a6b49f2a1210b --- /dev/null +++ b/CVE-2020-24386.patch @@ -0,0 +1,55 @@ +From 62061e8cf68f506c0ccaaba21fd4174764ca875f Mon Sep 17 00:00:00 2001 +From: Timo Sirainen +Date: Mon, 17 Aug 2020 18:15:35 +0300 +Subject: [PATCH] imap-login: Split off client_invalid_command() + +--- + src/imap-login/imap-login-client.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c +index e2af176309..ce5049d567 100644 +--- a/src/imap-login/imap-login-client.c ++++ b/src/imap-login/imap-login-client.c +@@ -194,6 +194,22 @@ static int client_command_execute(struct imap_client *client, const char *cmd, + return login_cmd->func(client, args); + } + ++static bool client_invalid_command(struct imap_client *client) ++{ ++ if (*client->cmd_tag == '\0') ++ client->cmd_tag = "*"; ++ if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) { ++ client_send_reply(&client->common, IMAP_CMD_REPLY_BYE, ++ "Too many invalid IMAP commands."); ++ client_destroy(&client->common, ++ "Disconnected: Too many invalid commands"); ++ return FALSE; ++ } ++ client_send_reply(&client->common, IMAP_CMD_REPLY_BAD, ++ "Error in IMAP command received by server."); ++ return TRUE; ++} ++ + static bool imap_is_valid_tag(const char *tag) + { + for (; *tag != '\0'; tag++) { +@@ -326,17 +342,8 @@ static bool imap_client_input_next_cmd(struct client *_client) + "not the command name. Add that before the command, " + "like: a login user pass"); + } else if (ret < 0) { +- if (*client->cmd_tag == '\0') +- client->cmd_tag = "*"; +- if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) { +- client_send_reply(&client->common, IMAP_CMD_REPLY_BYE, +- "Too many invalid IMAP commands."); +- client_destroy(&client->common, +- "Disconnected: Too many invalid commands"); ++ if (!client_invalid_command(client)) + return FALSE; +- } +- client_send_reply(&client->common, IMAP_CMD_REPLY_BAD, +- "Error in IMAP command received by server."); + } + + return ret != 0 && !client->common.destroyed; diff --git a/CVE-2020-25275-1.patch b/CVE-2020-25275-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..1953372171fd0a9f10550ccba0eb165176bf19ce --- /dev/null +++ b/CVE-2020-25275-1.patch @@ -0,0 +1,63 @@ +From 266e54b7b8c34c9a58dd60a2e53c5ca7d1deae19 Mon Sep 17 00:00:00 2001 +From: Timo Sirainen +Date: Fri, 11 Sep 2020 10:57:51 +0300 +Subject: [PATCH] lib-imap: Don't generate invalid BODYSTRUCTURE when reaching + MIME part limit + +If the last MIME part was message/rfc822 and its child was truncated away, +BODYSTRUCTURE was missing the ENVELOPE and BODY[STRUCTURE] parts. Fixed by +writing empty dummy ones. +--- + src/lib-imap/imap-bodystructure.c | 29 +++++++++++++++++++++++++++-- + 1 file changed, 27 insertions(+), 2 deletions(-) + +diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c +index 4e379e56a9..e3da1090b4 100644 +--- a/src/lib-imap/imap-bodystructure.c ++++ b/src/lib-imap/imap-bodystructure.c +@@ -146,11 +146,25 @@ static void part_write_body(const struct message_part *part, + string_t *str, bool extended) + { + const struct message_part_data *data = part->data; +- bool text; ++ bool text, message_rfc822; + + i_assert(part->data != NULL); + +- if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0) { ++ if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0) ++ message_rfc822 = TRUE; ++ else if (data->content_type != NULL && ++ strcasecmp(data->content_type, "message") == 0 && ++ strcasecmp(data->content_subtype, "rfc822") == 0) { ++ /* It's message/rfc822, but without ++ MESSAGE_PART_FLAG_MESSAGE_RFC822. That likely means maximum ++ MIME part count was reached while parsing the mail. Write ++ the missing child mail's ENVELOPE and BODY as empty dummy ++ values. */ ++ message_rfc822 = TRUE; ++ } else ++ message_rfc822 = FALSE; ++ ++ if (message_rfc822) { + str_append(str, "\"message\" \"rfc822\""); + text = FALSE; + } else { +@@ -200,6 +214,17 @@ static void part_write_body(const struct message_part *part, + + part_write_bodystructure_siblings(part->children, str, extended); + str_printfa(str, " %u", part->body_size.lines); ++ } else if (message_rfc822) { ++ /* truncated MIME part - write out dummy values */ ++ i_assert(part->children == NULL); ++ ++ str_append(str, " (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) "); ++ ++ if (!extended) ++ str_append(str, EMPTY_BODY); ++ else ++ str_append(str, EMPTY_BODYSTRUCTURE); ++ str_printfa(str, " %u", part->body_size.lines); + } + + if (!extended) diff --git a/CVE-2020-25275-2.patch b/CVE-2020-25275-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..9c3c7400e320bd488201346f2c83dc71a5350fa8 --- /dev/null +++ b/CVE-2020-25275-2.patch @@ -0,0 +1,129 @@ +From 3df3d432073390bb403e9b022790497ae2f0dece Mon Sep 17 00:00:00 2001 +From: Timo Sirainen +Date: Wed, 3 Feb 2021 16:31:26 +0800 +Subject: [PATCH] lib-mail: message-parser - Fix assert-crash when enforcing + MIME part limit + +The limit could have been exceeded with message/rfc822 parts. +--- + src/lib-mail/message-parser.c | 3 +- + src/lib-mail/test-message-parser.c | 82 ++++++++++++++++++++++++++++++ + 2 files changed, 84 insertions(+), 1 deletion(-) + +diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c +index 011dea9..8bc5972 100644 +--- a/src/lib-mail/message-parser.c ++++ b/src/lib-mail/message-parser.c +@@ -700,7 +700,8 @@ static int parse_next_header(struct message_parser_ctx *ctx, + ctx->multipart = FALSE; + ctx->parse_next_block = parse_next_body_to_boundary; + } else if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0 && +- !parse_too_many_nested_mime_parts(ctx)) { ++ !parse_too_many_nested_mime_parts(ctx) && ++ ctx->total_parts_count < ctx->max_total_mime_parts) { + ctx->parse_next_block = parse_next_body_message_rfc822_init; + } else { + part->flags &= ~MESSAGE_PART_FLAG_MESSAGE_RFC822; +diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c +index 71a738d..5dfe491 100644 +--- a/src/lib-mail/test-message-parser.c ++++ b/src/lib-mail/test-message-parser.c +@@ -1131,6 +1131,87 @@ static const char input_msg[] = + test_end(); + } + ++static void test_message_parser_mime_part_limit_rfc822(void) ++{ ++static const char input_msg[] = ++"Content-Type: multipart/mixed; boundary=\"1\"\n" ++"\n" ++"--1\n" ++"Content-Type: multipart/mixed; boundary=\"2\"\n" ++"\n" ++"--2\n" ++"Content-Type: message/rfc822\n" ++"\n" ++"Content-Type: text/plain\n" ++"\n" ++"1\n" ++"--2\n" ++"Content-Type: message/rfc822\n" ++"\n" ++"Content-Type: text/plain\n" ++"\n" ++"22\n" ++"--1\n" ++"Content-Type: message/rfc822\n" ++"\n" ++"Content-Type: text/plain\n" ++"\n" ++"333\n"; ++ const struct message_parser_settings parser_set = { ++ .max_total_mime_parts = 3, ++ }; ++ struct message_parser_ctx *parser; ++ struct istream *input; ++ struct message_part *parts, *part; ++ struct message_block block; ++ pool_t pool; ++ int ret; ++ ++ test_begin("message parser mime part limit rfc822"); ++ pool = pool_alloconly_create("message parser", 10240); ++ input = test_istream_create(input_msg); ++ ++ parser = message_parser_init(pool, input, &parser_set); ++ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; ++ test_assert(ret < 0); ++ message_parser_deinit(&parser, &parts); ++ ++ part = parts; ++ test_assert(part->children_count == 2); ++ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); ++ test_assert(part->header_size.lines == 2); ++ test_assert(part->header_size.physical_size == 45); ++ test_assert(part->header_size.virtual_size == 45+2); ++ test_assert(part->body_size.lines == 21); ++ test_assert(part->body_size.physical_size == 238); ++ test_assert(part->body_size.virtual_size == 238+21); ++ ++ part = parts->children; ++ test_assert(part->children_count == 1); ++ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); ++ test_assert(part->header_size.lines == 2); ++ test_assert(part->header_size.physical_size == 45); ++ test_assert(part->header_size.virtual_size == 45+2); ++ test_assert(part->body_size.lines == 18); ++ test_assert(part->body_size.physical_size == 189); ++ test_assert(part->body_size.virtual_size == 189+18); ++ ++ part = parts->children->children; ++ test_assert(part->children_count == 0); ++ test_assert(part->flags == MESSAGE_PART_FLAG_IS_MIME); ++ test_assert(part->header_size.lines == 2); ++ test_assert(part->header_size.physical_size == 30); ++ test_assert(part->header_size.virtual_size == 30+2); ++ test_assert(part->body_size.lines == 15); ++ test_assert(part->body_size.physical_size == 155); ++ test_assert(part->body_size.virtual_size == 155+15); ++ ++ test_parsed_parts(input, parts); ++ i_stream_unref(&input); ++ pool_unref(&pool); ++ test_end(); ++} ++ + int main(void) + { + static void (*const test_functions[])(void) = { +@@ -1151,6 +1232,7 @@ int main(void) + test_message_parser_mime_part_nested_limit, + test_message_parser_mime_part_nested_limit_rfc822, + test_message_parser_mime_part_limit, ++ test_message_parser_mime_part_limit_rfc822, + NULL + }; + return test_run(test_functions); +-- +2.23.0 + diff --git a/dovecot.spec b/dovecot.spec index 58e53b9ecd5353244ae53b81c8a40818dffb1f8a..077fdb20d6a3751e5e5c1abe35693f9659a5b82d 100644 --- a/dovecot.spec +++ b/dovecot.spec @@ -6,9 +6,9 @@ Name: dovecot Version: 2.3.10.1 -Release: 4 +Release: 5 Summary: Dovecot Secure imap server -License: MIT and LGPLv2 +License: MIT and LGPLv2.1 URL: http://www.dovecot.org/ Epoch: 1 @@ -35,6 +35,9 @@ Patch6008: CVE-2020-12673.patch Patch6009: CVE-2020-12674.patch Patch6010: CVE-2020-12100-1.patch Patch6011: CVE-2020-12100-2.patch +Patch6012: CVE-2020-25275-1.patch +Patch6013: CVE-2020-25275-2.patch +Patch6014: CVE-2020-24386.patch BuildRequires: gcc-c++ openssl-devel pam-devel zlib-devel bzip2-devel libcap-devel BuildRequires: libtool autoconf automake pkgconfig sqlite-devel libpq-devel @@ -286,6 +289,9 @@ make check %changelog +* Fri Feb 5 2021 wangyue - 2.3.10.1-5 +- Fix CVE-2020-25275 CVE-2020-24386 + * Thu Nov 5 2020 Guoshuai Sun - 2.3.10.1-4 - Add prestartscript from github