diff --git a/0001-Fix-bugs-in-smtp-server.patch b/0001-Fix-bugs-in-smtp-server.patch deleted file mode 100644 index 392c878023258cad6661340de04b05f8a9eb3c94..0000000000000000000000000000000000000000 --- a/0001-Fix-bugs-in-smtp-server.patch +++ /dev/null @@ -1,40 +0,0 @@ -From a215a7d1a1c5eab40f6896fc07931a81d5504f18 Mon Sep 17 00:00:00 2001 -From: maminjie -Date: Sat, 27 Mar 2021 11:18:23 +0800 -Subject: [PATCH] Fix bugs in smtp server - -reference to: https://github.com/dovecot/core/pull/120 ---- - src/lib-smtp/smtp-server-cmd-data.c | 2 +- - src/lib-smtp/smtp-server-cmd-helo.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/lib-smtp/smtp-server-cmd-data.c b/src/lib-smtp/smtp-server-cmd-data.c -index 2650643..a7db425 100644 ---- a/src/lib-smtp/smtp-server-cmd-data.c -+++ b/src/lib-smtp/smtp-server-cmd-data.c -@@ -654,7 +654,7 @@ void smtp_server_cmd_bdat(struct smtp_server_cmd_ctx *cmd, - } - } - -- if (ret > 0 || size > 0) { -+ if (ret > 0 || (size > 0 && conn->smtp_parser)) { - /* read/skip data even in case of error, as long as size is - known */ - input = smtp_command_parse_data_with_size(conn->smtp_parser, -diff --git a/src/lib-smtp/smtp-server-cmd-helo.c b/src/lib-smtp/smtp-server-cmd-helo.c -index 330ceaa..40ba328 100644 ---- a/src/lib-smtp/smtp-server-cmd-helo.c -+++ b/src/lib-smtp/smtp-server-cmd-helo.c -@@ -155,7 +155,7 @@ smtp_server_cmd_ehlo_reply_create(struct smtp_server_cmd_ctx *cmd) - unsigned int extra_caps_count, i, j; - struct smtp_server_reply *reply; - -- i_assert(cmd->cmd->reg->func == smtp_server_cmd_ehlo); -+ i_assert(cmd->cmd->reg->func == smtp_server_cmd_ehlo || cmd->cmd->reg->func == smtp_server_cmd_helo); - reply = smtp_server_reply_create_ehlo(cmd->cmd); - - if (helo_data->helo.old_smtp) --- -2.23.0 - diff --git a/0002-Fix-assert-crash-if-parsing-invalid-BODYSTRUCTURE.patch b/0002-Fix-assert-crash-if-parsing-invalid-BODYSTRUCTURE.patch deleted file mode 100644 index 0b5ef6f2ccb74f41b21e9cbd8e00c9ae5eef2d54..0000000000000000000000000000000000000000 --- a/0002-Fix-assert-crash-if-parsing-invalid-BODYSTRUCTURE.patch +++ /dev/null @@ -1,27 +0,0 @@ -From c4c499cb5b9fc35e8b850a9faf6b700feb3b299f Mon Sep 17 00:00:00 2001 -From: maminjie -Date: Sat, 27 Mar 2021 11:55:31 +0800 -Subject: [PATCH] Fix assert-crash if parsing invalid BODYSTRUCTURE with empty - Content-Language list - -reference to: https://github.com/dovecot/core/commit/dd51ae09a8a688c8466e31d5b6108756d5154153 ---- - src/lib-imap/imap-bodystructure.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c -index a2d778f..b52af28 100644 ---- a/src/lib-imap/imap-bodystructure.c -+++ b/src/lib-imap/imap-bodystructure.c -@@ -245,6 +245,8 @@ imap_bodystructure_strlist_parse(const struct imap_arg *arg, - } else { - if (!imap_arg_get_list_full(arg, &list_args, &list_count)) - return -1; -+ if (list_count == 0) -+ return -1; - - list = p_new(pool, const char *, list_count+1); - for (i = 0; i < list_count; i++) { --- -2.23.0 - diff --git a/0003-Handle-empty-lists-in-IMAP-BODYSTRUCTURE-parsing-as-invalid.patch b/0003-Handle-empty-lists-in-IMAP-BODYSTRUCTURE-parsing-as-invalid.patch deleted file mode 100644 index eec02a6001a5c79d4bfedde002d2b39254bdd1a4..0000000000000000000000000000000000000000 --- a/0003-Handle-empty-lists-in-IMAP-BODYSTRUCTURE-parsing-as-invalid.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 269640a83ac140b48aaa191eec13ead5dd60519a Mon Sep 17 00:00:00 2001 -From: maminjie -Date: Thu, 3 Jun 2021 11:24:44 +0800 -Subject: [PATCH] Handle empty lists in IMAP BODYSTRUCTURE parsing as invalid - -reference: https://github.com/dovecot/core/commit/586cca576970cc377a40f995512dbc02981900a3 ---- - src/lib-imap/imap-bodystructure.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c -index b52af28..07bd5a4 100644 ---- a/src/lib-imap/imap-bodystructure.c -+++ b/src/lib-imap/imap-bodystructure.c -@@ -276,6 +276,8 @@ imap_bodystructure_params_parse(const struct imap_arg *arg, - return -1; - if ((list_count % 2) != 0) - return -1; -+ if (list_count == 0) -+ return -1; - - params_count = list_count/2; - params = p_new(pool, struct message_part_param, params_count+1); --- -2.23.0 - diff --git a/0004-Fix-writing-BODYSTRUCTURE-for-truncated-multipart-digest-part.patch b/0004-Fix-writing-BODYSTRUCTURE-for-truncated-multipart-digest-part.patch deleted file mode 100644 index 4e00675dac2bf6ee4cfc9ed04d44556b30e4cce8..0000000000000000000000000000000000000000 --- a/0004-Fix-writing-BODYSTRUCTURE-for-truncated-multipart-digest-part.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 7039d1c3bc054142eb4034b88df150fda1eb75e4 Mon Sep 17 00:00:00 2001 -From: maminjie -Date: Thu, 3 Jun 2021 16:48:55 +0800 -Subject: [PATCH] Fix writing BODYSTRUCTURE for truncated multipart/digest part - -reference: -https://github.com/dovecot/core/commit/84cde48e5859b1d20f2fd98b57b7410b4d3727fa -https://github.com/dovecot/core/commit/0f66865e0e3dae3e902abd8bb559d7706dbff437 ---- - src/lib-imap/imap-bodystructure.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c -index 07bd5a4..81ce529 100644 ---- a/src/lib-imap/imap-bodystructure.c -+++ b/src/lib-imap/imap-bodystructure.c -@@ -164,6 +164,10 @@ static void part_write_body(const struct message_part *part, - str_append_c(str, ' '); - imap_append_string(str, data->content_subtype); - } -+ bool part_is_text = (part->flags & MESSAGE_PART_FLAG_TEXT) != 0; -+ if (text != part_is_text) { -+ return; -+ } - } - - /* ("content type param key" "value" ...) */ --- -2.23.0 - diff --git a/CVE-2015-3420.patch b/CVE-2015-3420.patch deleted file mode 100644 index 3f02202f85f0a4fdb3e964cef413f81d691c56f9..0000000000000000000000000000000000000000 --- a/CVE-2015-3420.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -r 27ee6a472555 src/lib/strnum.h ---- a/src/lib/strnum.h Tue Dec 08 15:47:28 2015 +0200 -+++ b/src/lib/strnum.h Wed Dec 09 10:54:49 2015 +0200 -@@ -169,6 +169,7 @@ - int str_parse_uoff(const char *str, uoff_t *num_r, - const char **endp_r) ATTR_WARN_UNUSED_RESULT ATTR_NULL(3); - -+#define str_to_time str_to_time_no_collision - int str_to_time(const char *str, time_t *num_r) - ATTR_WARN_UNUSED_RESULT; - diff --git a/CVE-2016-8652.patch b/CVE-2016-8652.patch deleted file mode 100644 index c1465db9d41cf9dbf4981eb82e87b88756156185..0000000000000000000000000000000000000000 --- a/CVE-2016-8652.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 1f2c35da2b96905bec6e45f88af0f33ee63789e6 Mon Sep 17 00:00:00 2001 -From: Aki Tuomi -Date: Wed, 23 Nov 2016 13:16:19 +0200 -Subject: [PATCH] auth: Fix auth-policy crash when username is NULL - -If SASL request is invalid, or incomplete, and username -is left NULL, handle it gracefully by adding just -NUL byte in auth policy digest for username. ---- - src/auth/auth-policy.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff -Nur dovecot-2.3.3_old/src/auth/auth-policy.c dovecot-2.3.3/src/auth/auth-policy.c ---- dovecot-2.3.3_old/src/auth/auth-policy.c 2020-03-16 17:38:38.308283675 +0800 -+++ dovecot-2.3.3/src/auth/auth-policy.c 2020-03-16 17:42:41.873103352 +0800 -@@ -466,7 +466,10 @@ - else - requested_username = ""; - /* use +1 to make sure \0 gets included */ -- digest->loop(ctx, requested_username, strlen(requested_username)+1); -+ if (context->request->user == NULL) -+ digest->loop(ctx, "\0", 1); -+ else -+ digest->loop(ctx, context->request->user, strlen(context->request->user) + 1); - if (password != NULL) - digest->loop(ctx, password, strlen(password)); - ptr = buffer_get_modifiable_data(buffer, NULL); diff --git a/CVE-2020-12100-1.patch b/CVE-2020-12100-1.patch deleted file mode 100644 index 59ba23aac749b23074400aa26176204c325cca6e..0000000000000000000000000000000000000000 --- a/CVE-2020-12100-1.patch +++ /dev/null @@ -1,3283 +0,0 @@ -From 0ffcae6adfe1be48124429484a39acdf32979549 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 11:14:04 +0300 -Subject: [PATCH 01/15] lib-mail: test-message-parser - Add another test for - boundary matching - ---- - src/lib-mail/test-message-parser.c | 71 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 71 insertions(+) - -diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c -index 4f4d684083..529a36d59c 100644 ---- a/src/lib-mail/test-message-parser.c -+++ b/src/lib-mail/test-message-parser.c -@@ -613,6 +613,76 @@ static const char input_msg[] = - test_end(); - } - -+static void test_message_parser_continuing_mime_boundary_reverse(void) -+{ -+static const char input_msg[] = -+"Content-Type: multipart/mixed; boundary=\"ab\"\n" -+"\n" -+"--ab\n" -+"Content-Type: multipart/mixed; boundary=\"a\"\n" -+"\n" -+"--a\n" -+"Content-Type: text/plain\n" -+"\n" -+"body\n" -+"--ab\n" -+"Content-Type: text/html\n" -+"\n" -+"body2\n"; -+ struct message_parser_ctx *parser; -+ struct istream *input; -+ struct message_part *parts; -+ struct message_block block; -+ pool_t pool; -+ int ret; -+ -+ test_begin("message parser continuing mime boundary reverse"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(input_msg); -+ -+ parser = message_parser_init(pool, input, 0, 0); -+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; -+ test_assert(ret < 0); -+ message_parser_deinit(&parser, &parts); -+ -+ test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(parts->header_size.lines == 2); -+ test_assert(parts->header_size.physical_size == 46); -+ test_assert(parts->header_size.virtual_size == 46+2); -+ test_assert(parts->body_size.lines == 11); -+ test_assert(parts->body_size.physical_size == 121); -+ test_assert(parts->body_size.virtual_size == 121+11); -+ test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(parts->children->physical_pos == 51); -+ test_assert(parts->children->header_size.lines == 2); -+ test_assert(parts->children->header_size.physical_size == 45); -+ test_assert(parts->children->header_size.virtual_size == 45+2); -+ test_assert(parts->children->body_size.lines == 3); -+ test_assert(parts->children->body_size.physical_size == 34); -+ test_assert(parts->children->body_size.virtual_size == 34+3); -+ test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(parts->children->children->physical_pos == 100); -+ test_assert(parts->children->children->header_size.lines == 2); -+ test_assert(parts->children->children->header_size.physical_size == 26); -+ test_assert(parts->children->children->header_size.virtual_size == 26+2); -+ test_assert(parts->children->children->body_size.lines == 0); -+ test_assert(parts->children->children->body_size.physical_size == 4); -+ test_assert(parts->children->children->body_size.virtual_size == 4); -+ test_assert(parts->children->next->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(parts->children->next->physical_pos == 136); -+ test_assert(parts->children->next->header_size.lines == 2); -+ test_assert(parts->children->next->header_size.physical_size == 25); -+ test_assert(parts->children->next->header_size.virtual_size == 25+2); -+ test_assert(parts->children->next->body_size.lines == 1); -+ test_assert(parts->children->next->body_size.physical_size == 6); -+ test_assert(parts->children->next->body_size.virtual_size == 6+1); -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ - static void test_message_parser_no_eoh(void) - { - static const char input_msg[] = "a:b\n"; -@@ -653,6 +723,7 @@ int main(void) - test_message_parser_garbage_suffix_mime_boundary, - test_message_parser_continuing_mime_boundary, - test_message_parser_continuing_truncated_mime_boundary, -+ test_message_parser_continuing_mime_boundary_reverse, - test_message_parser_no_eoh, - NULL - }; --- -2.11.0 - -From 6defb282bec6b17bd1c0e2f62a4d365b453c39ef Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 11:27:14 +0300 -Subject: [PATCH 02/15] lib-mail: test-message-parser - Test that - children_count is correct - ---- - src/lib-mail/test-message-parser.c | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - -diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c -index 529a36d59c..c275707265 100644 ---- a/src/lib-mail/test-message-parser.c -+++ b/src/lib-mail/test-message-parser.c -@@ -59,6 +59,7 @@ static bool msg_parts_cmp(struct message_part *p1, struct message_part *p2) - p1->body_size.physical_size != p2->body_size.physical_size || - p1->body_size.virtual_size != p2->body_size.virtual_size || - p1->body_size.lines != p2->body_size.lines || -+ p1->children_count != p2->children_count || - p1->flags != p2->flags) - return FALSE; - -@@ -195,6 +196,7 @@ static const char input_msg[] = - message_parser_deinit(&parser, &parts); - - test_assert((parts->flags & MESSAGE_PART_FLAG_MULTIPART) != 0); -+ test_assert(parts->children_count == 4); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 48); - test_assert(parts->header_size.virtual_size == 48+2); -@@ -218,6 +220,7 @@ static const char input_msg[] = - test_assert(parts->children->next->next->next->header_size.virtual_size == 23); - test_assert(parts->children->next->next->next->header_size.lines == 0); - for (part = parts->children; part != NULL; part = part->next) { -+ test_assert(part->children_count == 0); - test_assert(part->body_size.physical_size == 0); - test_assert(part->body_size.virtual_size == 0); - } -@@ -258,6 +261,7 @@ static const char input_msg[] = - message_parser_deinit(&parser, &parts); - - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(parts->children_count == 2); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 46); - test_assert(parts->header_size.virtual_size == 46+2); -@@ -265,6 +269,7 @@ static const char input_msg[] = - test_assert(parts->body_size.physical_size == 86); - test_assert(parts->body_size.virtual_size == 86+8); - -+ test_assert(parts->children->children_count == 0); - test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->physical_pos == 51); - test_assert(parts->children->header_size.lines == 1); -@@ -274,6 +279,7 @@ static const char input_msg[] = - test_assert(parts->children->body_size.physical_size == 0); - test_assert(parts->children->children == NULL); - -+ test_assert(parts->children->next->children_count == 0); - test_assert(parts->children->next->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->next->physical_pos == 101); - test_assert(parts->children->next->header_size.lines == 2); -@@ -310,6 +316,7 @@ static const char input_msg[] = - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - -+ test_assert(parts->children_count == 0); - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->header_size.lines == 1); - test_assert(parts->header_size.physical_size == 45); -@@ -347,6 +354,7 @@ static const char input_msg[] = - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - -+ test_assert(parts->children_count == 0); - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 46); -@@ -391,6 +399,7 @@ static const char input_msg[] = - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - -+ test_assert(parts->children_count == 2); - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 45); -@@ -398,6 +407,7 @@ static const char input_msg[] = - test_assert(parts->body_size.lines == 7); - test_assert(parts->body_size.physical_size == 84); - test_assert(parts->body_size.virtual_size == 84+7); -+ test_assert(parts->children->children_count == 1); - test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->physical_pos == 49); - test_assert(parts->children->header_size.lines == 2); -@@ -406,6 +416,7 @@ static const char input_msg[] = - test_assert(parts->children->body_size.lines == 4); - test_assert(parts->children->body_size.physical_size == 35); - test_assert(parts->children->body_size.virtual_size == 35+4); -+ test_assert(parts->children->children->children_count == 0); - test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->children->physical_pos == 98); - test_assert(parts->children->children->header_size.lines == 2); -@@ -449,6 +460,7 @@ static const char input_msg[] = - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - -+ test_assert(parts->children_count == 2); - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 45); -@@ -456,6 +468,7 @@ static const char input_msg[] = - test_assert(parts->body_size.lines == 7); - test_assert(parts->body_size.physical_size == 86); - test_assert(parts->body_size.virtual_size == 86+7); -+ test_assert(parts->children->children_count == 1); - test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->physical_pos == 50); - test_assert(parts->children->header_size.lines == 2); -@@ -464,6 +477,7 @@ static const char input_msg[] = - test_assert(parts->children->body_size.lines == 4); - test_assert(parts->children->body_size.physical_size == 36); - test_assert(parts->children->body_size.virtual_size == 36+4); -+ test_assert(parts->children->children->children_count == 0); - test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->children->physical_pos == 100); - test_assert(parts->children->children->header_size.lines == 2); -@@ -507,6 +521,7 @@ static const char input_msg[] = - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - -+ test_assert(parts->children_count == 2); - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 45); -@@ -514,6 +529,7 @@ static const char input_msg[] = - test_assert(parts->body_size.lines == 7); - test_assert(parts->body_size.physical_size == 86); - test_assert(parts->body_size.virtual_size == 86+7); -+ test_assert(parts->children->children_count == 1); - test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->physical_pos == 49); - test_assert(parts->children->header_size.lines == 2); -@@ -522,6 +538,7 @@ static const char input_msg[] = - test_assert(parts->children->body_size.lines == 4); - test_assert(parts->children->body_size.physical_size == 36); - test_assert(parts->children->body_size.virtual_size == 36+4); -+ test_assert(parts->children->children->children_count == 0); - test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->children->physical_pos == 100); - test_assert(parts->children->children->header_size.lines == 2); -@@ -567,6 +584,7 @@ static const char input_msg[] = - message_parser_deinit(&parser, &parts); - - part = parts; -+ test_assert(part->children_count == 3); - 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); -@@ -576,6 +594,7 @@ static const char input_msg[] = - test_assert(part->body_size.virtual_size == 112+9); - - part = parts->children; -+ test_assert(part->children_count == 0); - test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(part->physical_pos == 49); - test_assert(part->header_size.lines == 1); -@@ -589,6 +608,7 @@ static const char input_msg[] = - we could make it, but it would complicate the message-parser even - more. */ - part = parts->children->next; -+ test_assert(part->children_count == 0); - test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(part->physical_pos == 117); - test_assert(part->header_size.lines == 1); -@@ -599,6 +619,7 @@ static const char input_msg[] = - test_assert(part->children == NULL); - - part = parts->children->next->next; -+ test_assert(part->children_count == 0); - test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(part->header_size.lines == 0); - test_assert(part->header_size.physical_size == 0); -@@ -645,6 +666,7 @@ static const char input_msg[] = - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - -+ test_assert(parts->children_count == 3); - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 46); -@@ -652,6 +674,7 @@ static const char input_msg[] = - test_assert(parts->body_size.lines == 11); - test_assert(parts->body_size.physical_size == 121); - test_assert(parts->body_size.virtual_size == 121+11); -+ test_assert(parts->children->children_count == 1); - test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->physical_pos == 51); - test_assert(parts->children->header_size.lines == 2); -@@ -660,6 +683,7 @@ static const char input_msg[] = - test_assert(parts->children->body_size.lines == 3); - test_assert(parts->children->body_size.physical_size == 34); - test_assert(parts->children->body_size.virtual_size == 34+3); -+ test_assert(parts->children->children->children_count == 0); - test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->children->physical_pos == 100); - test_assert(parts->children->children->header_size.lines == 2); -@@ -668,6 +692,7 @@ static const char input_msg[] = - test_assert(parts->children->children->body_size.lines == 0); - test_assert(parts->children->children->body_size.physical_size == 4); - test_assert(parts->children->children->body_size.virtual_size == 4); -+ test_assert(parts->children->next->children_count == 0); - test_assert(parts->children->next->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->next->physical_pos == 136); - test_assert(parts->children->next->header_size.lines == 2); --- -2.11.0 - -From 354d5b43a93b6f2ba80c7fc507b75fb1dc4c8df5 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 11:47:18 +0300 -Subject: [PATCH 03/15] lib-mail: Move message_parser_init_from_parts() - handling to its own file - -This helps to see what code they have in common. ---- - src/lib-mail/Makefile.am | 4 +- - src/lib-mail/message-parser-from-parts.c | 366 +++++++++++++++++++++++++++ - src/lib-mail/message-parser-private.h | 55 +++++ - src/lib-mail/message-parser.c | 410 +------------------------------ - 4 files changed, 428 insertions(+), 407 deletions(-) - create mode 100644 src/lib-mail/message-parser-from-parts.c - create mode 100644 src/lib-mail/message-parser-private.h - -diff --git a/src/lib-mail/Makefile.am b/src/lib-mail/Makefile.am -index 8fe43d69d0..57d9e2b8c4 100644 ---- a/src/lib-mail/Makefile.am -+++ b/src/lib-mail/Makefile.am -@@ -28,6 +28,7 @@ libmail_la_SOURCES = \ - message-header-parser.c \ - message-id.c \ - message-parser.c \ -+ message-parser-from-parts.c \ - message-part.c \ - message-part-data.c \ - message-part-serialize.c \ -@@ -42,7 +43,8 @@ libmail_la_SOURCES = \ - rfc822-parser.c - - noinst_HEADERS = \ -- html-entities.h -+ html-entities.h \ -+ message-parser-private.h - - headers = \ - istream-attachment-connector.h \ -diff --git a/src/lib-mail/message-parser-from-parts.c b/src/lib-mail/message-parser-from-parts.c -new file mode 100644 -index 0000000000..b23055ab9b ---- /dev/null -+++ b/src/lib-mail/message-parser-from-parts.c -@@ -0,0 +1,366 @@ -+/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ -+ -+#include "lib.h" -+#include "istream.h" -+#include "message-parser-private.h" -+ -+static int preparsed_parse_epilogue_init(struct message_parser_ctx *ctx, -+ struct message_block *block_r); -+static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx, -+ struct message_block *block_r); -+ -+static int preparsed_parse_eof(struct message_parser_ctx *ctx ATTR_UNUSED, -+ struct message_block *block_r ATTR_UNUSED) -+{ -+ return -1; -+} -+ -+static void preparsed_skip_to_next(struct message_parser_ctx *ctx) -+{ -+ ctx->parse_next_block = preparsed_parse_next_header_init; -+ while (ctx->part != NULL) { -+ if (ctx->part->next != NULL) { -+ ctx->part = ctx->part->next; -+ break; -+ } -+ -+ /* parse epilogue of multipart parent if requested */ -+ if (ctx->part->parent != NULL && -+ (ctx->part->parent->flags & MESSAGE_PART_FLAG_MULTIPART) != 0 && -+ (ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS) != 0) { -+ /* check for presence of epilogue */ -+ uoff_t part_end = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size + -+ ctx->part->body_size.physical_size; -+ uoff_t parent_end = ctx->part->parent->physical_pos + -+ ctx->part->parent->header_size.physical_size + -+ ctx->part->parent->body_size.physical_size; -+ -+ if (parent_end > part_end) { -+ ctx->parse_next_block = preparsed_parse_epilogue_init; -+ break; -+ } -+ } -+ ctx->part = ctx->part->parent; -+ } -+ if (ctx->part == NULL) -+ ctx->parse_next_block = preparsed_parse_eof; -+} -+ -+static int preparsed_parse_body_finish(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ i_stream_skip(ctx->input, ctx->skip); -+ ctx->skip = 0; -+ -+ preparsed_skip_to_next(ctx); -+ return ctx->parse_next_block(ctx, block_r); -+} -+ -+static int preparsed_parse_prologue_finish(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ i_stream_skip(ctx->input, ctx->skip); -+ ctx->skip = 0; -+ -+ ctx->parse_next_block = preparsed_parse_next_header_init; -+ ctx->part = ctx->part->children; -+ return ctx->parse_next_block(ctx, block_r); -+} -+ -+static int preparsed_parse_body_more(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t end_offset = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size + -+ ctx->part->body_size.physical_size; -+ bool full; -+ int ret; -+ -+ if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -+ return ret; -+ -+ if (ctx->input->v_offset + block_r->size >= end_offset) { -+ block_r->size = end_offset - ctx->input->v_offset; -+ ctx->parse_next_block = preparsed_parse_body_finish; -+ } -+ ctx->skip = block_r->size; -+ return 1; -+} -+ -+static int preparsed_parse_prologue_more(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t boundary_min_start, end_offset; -+ const unsigned char *cur; -+ bool full; -+ int ret; -+ -+ i_assert(ctx->part->children != NULL); -+ end_offset = ctx->part->children->physical_pos; -+ -+ if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -+ return ret; -+ -+ if (ctx->input->v_offset + block_r->size >= end_offset) { -+ /* we've got the full prologue: clip off the initial boundary */ -+ block_r->size = end_offset - ctx->input->v_offset; -+ cur = block_r->data + block_r->size - 1; -+ -+ /* [\r]\n--boundary[\r]\n */ -+ if (block_r->size < 5 || *cur != '\n') { -+ ctx->broken_reason = "Prologue boundary end not at expected position"; -+ return -1; -+ } -+ -+ cur--; -+ if (*cur == '\r') cur--; -+ -+ /* find newline just before boundary */ -+ for (; cur >= block_r->data; cur--) { -+ if (*cur == '\n') break; -+ } -+ -+ if (cur[0] != '\n' || cur[1] != '-' || cur[2] != '-') { -+ ctx->broken_reason = "Prologue boundary beginning not at expected position"; -+ return -1; -+ } -+ -+ if (cur != block_r->data && cur[-1] == '\r') cur--; -+ -+ /* clip boundary */ -+ block_r->size = cur - block_r->data; -+ -+ ctx->parse_next_block = preparsed_parse_prologue_finish; -+ ctx->skip = block_r->size; -+ return 1; -+ } -+ -+ /* retain enough data in the stream buffer to contain initial boundary */ -+ if (end_offset > BOUNDARY_END_MAX_LEN) -+ boundary_min_start = end_offset - BOUNDARY_END_MAX_LEN; -+ else -+ boundary_min_start = 0; -+ -+ if (ctx->input->v_offset + block_r->size >= boundary_min_start) { -+ if (boundary_min_start <= ctx->input->v_offset) -+ return 0; -+ block_r->size = boundary_min_start - ctx->input->v_offset; -+ } -+ ctx->skip = block_r->size; -+ return 1; -+} -+ -+static int preparsed_parse_epilogue_more(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t end_offset = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size + -+ ctx->part->body_size.physical_size; -+ bool full; -+ int ret; -+ -+ if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -+ return ret; -+ -+ if (ctx->input->v_offset + block_r->size >= end_offset) { -+ block_r->size = end_offset - ctx->input->v_offset; -+ ctx->parse_next_block = preparsed_parse_body_finish; -+ } -+ ctx->skip = block_r->size; -+ return 1; -+} -+ -+static int preparsed_parse_epilogue_boundary(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t end_offset = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size + -+ ctx->part->body_size.physical_size; -+ const unsigned char *data, *cur; -+ size_t size; -+ bool full; -+ int ret; -+ -+ if (end_offset - ctx->input->v_offset < 7) { -+ ctx->broken_reason = "Epilogue position is wrong"; -+ return -1; -+ } -+ -+ if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -+ return ret; -+ -+ /* [\r]\n--boundary--[\r]\n */ -+ if (block_r->size < 7) { -+ ctx->want_count = 7; -+ return 0; -+ } -+ -+ data = block_r->data; -+ size = block_r->size; -+ cur = data; -+ -+ if (*cur == '\r') cur++; -+ -+ if (cur[0] != '\n' || cur[1] != '-' || data[2] != '-') { -+ ctx->broken_reason = "Epilogue boundary start not at expected position"; -+ return -1; -+ } -+ -+ /* find the end of the line */ -+ cur += 3; -+ if ((cur = memchr(cur, '\n', size - (cur-data))) == NULL) { -+ if (end_offset < ctx->input->v_offset + size) { -+ ctx->broken_reason = "Epilogue boundary end not at expected position"; -+ return -1; -+ } else if (ctx->input->v_offset + size < end_offset && -+ size < BOUNDARY_END_MAX_LEN && -+ !ctx->input->eof && !full) { -+ ctx->want_count = BOUNDARY_END_MAX_LEN; -+ return 0; -+ } -+ } -+ -+ block_r->size = 0; -+ ctx->parse_next_block = preparsed_parse_epilogue_more; -+ ctx->skip = cur - data + 1; -+ return 0; -+} -+ -+static int preparsed_parse_body_init(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t offset = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size; -+ -+ if (offset < ctx->input->v_offset) { -+ /* header was actually larger than the cached size suggested */ -+ ctx->broken_reason = "Header larger than its cached size"; -+ return -1; -+ } -+ i_stream_skip(ctx->input, offset - ctx->input->v_offset); -+ -+ /* multipart messages may begin with --boundary--, which makes them -+ not have any children. */ -+ if ((ctx->part->flags & MESSAGE_PART_FLAG_MULTIPART) == 0 || -+ ctx->part->children == NULL) -+ ctx->parse_next_block = preparsed_parse_body_more; -+ else -+ ctx->parse_next_block = preparsed_parse_prologue_more; -+ return ctx->parse_next_block(ctx, block_r); -+} -+ -+static int preparsed_parse_epilogue_init(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t offset = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size + -+ ctx->part->body_size.physical_size; -+ -+ ctx->part = ctx->part->parent; -+ -+ if (offset < ctx->input->v_offset) { -+ /* last child was actually larger than the cached size -+ suggested */ -+ ctx->broken_reason = "Part larger than its cached size"; -+ return -1; -+ } -+ i_stream_skip(ctx->input, offset - ctx->input->v_offset); -+ -+ ctx->parse_next_block = preparsed_parse_epilogue_boundary; -+ return ctx->parse_next_block(ctx, block_r); -+} -+ -+static int preparsed_parse_finish_header(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ if (ctx->part->children != NULL) { -+ if ((ctx->part->flags & MESSAGE_PART_FLAG_MULTIPART) != 0 && -+ (ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS) != 0) -+ ctx->parse_next_block = preparsed_parse_body_init; -+ else { -+ ctx->parse_next_block = preparsed_parse_next_header_init; -+ ctx->part = ctx->part->children; -+ } -+ } else if ((ctx->flags & MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK) == 0) { -+ ctx->parse_next_block = preparsed_parse_body_init; -+ } else { -+ preparsed_skip_to_next(ctx); -+ } -+ return ctx->parse_next_block(ctx, block_r); -+} -+ -+static int preparsed_parse_next_header(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ struct message_header_line *hdr; -+ int ret; -+ -+ ret = message_parse_header_next(ctx->hdr_parser_ctx, &hdr); -+ if (ret == 0 || (ret < 0 && ctx->input->stream_errno != 0)) { -+ ctx->want_count = i_stream_get_data_size(ctx->input) + 1; -+ return ret; -+ } -+ -+ if (hdr != NULL) { -+ block_r->hdr = hdr; -+ block_r->size = 0; -+ return 1; -+ } -+ message_parse_header_deinit(&ctx->hdr_parser_ctx); -+ -+ ctx->parse_next_block = preparsed_parse_finish_header; -+ -+ /* return empty block as end of headers */ -+ block_r->hdr = NULL; -+ block_r->size = 0; -+ -+ i_assert(ctx->skip == 0); -+ if (ctx->input->v_offset != ctx->part->physical_pos + -+ ctx->part->header_size.physical_size) { -+ ctx->broken_reason = "Cached header size mismatch"; -+ return -1; -+ } -+ return 1; -+} -+ -+static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ struct istream *hdr_input; -+ -+ i_assert(ctx->hdr_parser_ctx == NULL); -+ -+ i_assert(ctx->part->physical_pos >= ctx->input->v_offset); -+ i_stream_skip(ctx->input, ctx->part->physical_pos - -+ ctx->input->v_offset); -+ -+ /* the header may become truncated by --boundaries. limit the header -+ stream's size to what it's supposed to be to avoid duplicating (and -+ keeping in sync!) all the same complicated logic as in -+ parse_next_header(). */ -+ hdr_input = i_stream_create_limit(ctx->input, ctx->part->header_size.physical_size); -+ ctx->hdr_parser_ctx = -+ message_parse_header_init(hdr_input, NULL, ctx->hdr_flags); -+ i_stream_unref(&hdr_input); -+ -+ ctx->parse_next_block = preparsed_parse_next_header; -+ return preparsed_parse_next_header(ctx, block_r); -+} -+ -+struct message_parser_ctx * -+message_parser_init_from_parts(struct message_part *parts, -+ struct istream *input, -+ enum message_header_parser_flags hdr_flags, -+ enum message_parser_flags flags) -+{ -+ struct message_parser_ctx *ctx; -+ -+ i_assert(parts != NULL); -+ -+ ctx = message_parser_init_int(input, hdr_flags, flags); -+ ctx->preparsed = TRUE; -+ ctx->parts = ctx->part = parts; -+ ctx->parse_next_block = preparsed_parse_next_header_init; -+ return ctx; -+} -diff --git a/src/lib-mail/message-parser-private.h b/src/lib-mail/message-parser-private.h -new file mode 100644 -index 0000000000..98a576eda4 ---- /dev/null -+++ b/src/lib-mail/message-parser-private.h -@@ -0,0 +1,55 @@ -+#ifndef MESSAGE_PARSER_PRIVATE_H -+#define MESSAGE_PARSER_PRIVATE_H -+ -+#include "message-parser.h" -+ -+/* RFC-2046 requires boundaries are max. 70 chars + "--" prefix + "--" suffix. -+ We'll add a bit more just in case. */ -+#define BOUNDARY_END_MAX_LEN (70 + 2 + 2 + 10) -+ -+struct message_boundary { -+ struct message_boundary *next; -+ -+ struct message_part *part; -+ const char *boundary; -+ size_t len; -+ -+ bool epilogue_found:1; -+}; -+ -+struct message_parser_ctx { -+ pool_t parser_pool, part_pool; -+ struct istream *input; -+ struct message_part *parts, *part; -+ const char *broken_reason; -+ -+ enum message_header_parser_flags hdr_flags; -+ enum message_parser_flags flags; -+ -+ const char *last_boundary; -+ struct message_boundary *boundaries; -+ -+ size_t skip; -+ char last_chr; -+ unsigned int want_count; -+ -+ struct message_header_parser_ctx *hdr_parser_ctx; -+ unsigned int prev_hdr_newline_size; -+ -+ int (*parse_next_block)(struct message_parser_ctx *ctx, -+ struct message_block *block_r); -+ -+ bool part_seen_content_type:1; -+ bool multipart:1; -+ bool preparsed:1; -+ bool eof:1; -+}; -+ -+struct message_parser_ctx * -+message_parser_init_int(struct istream *input, -+ enum message_header_parser_flags hdr_flags, -+ enum message_parser_flags flags); -+int message_parser_read_more(struct message_parser_ctx *ctx, -+ struct message_block *block_r, bool *full_r); -+ -+#endif -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index e7a4f4cc31..653f964118 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -6,49 +6,7 @@ - #include "istream.h" - #include "rfc822-parser.h" - #include "rfc2231-parser.h" --#include "message-parser.h" -- --/* RFC-2046 requires boundaries are max. 70 chars + "--" prefix + "--" suffix. -- We'll add a bit more just in case. */ --#define BOUNDARY_END_MAX_LEN (70 + 2 + 2 + 10) -- --struct message_boundary { -- struct message_boundary *next; -- -- struct message_part *part; -- const char *boundary; -- size_t len; -- -- bool epilogue_found:1; --}; -- --struct message_parser_ctx { -- pool_t parser_pool, part_pool; -- struct istream *input; -- struct message_part *parts, *part; -- const char *broken_reason; -- -- enum message_header_parser_flags hdr_flags; -- enum message_parser_flags flags; -- -- const char *last_boundary; -- struct message_boundary *boundaries; -- -- size_t skip; -- char last_chr; -- unsigned int want_count; -- -- struct message_header_parser_ctx *hdr_parser_ctx; -- unsigned int prev_hdr_newline_size; -- -- int (*parse_next_block)(struct message_parser_ctx *ctx, -- struct message_block *block_r); -- -- bool part_seen_content_type:1; -- bool multipart:1; -- bool preparsed:1; -- bool eof:1; --}; -+#include "message-parser-private.h" - - message_part_header_callback_t *null_message_part_header_callback = NULL; - -@@ -58,10 +16,6 @@ static int parse_next_body_to_boundary(struct message_parser_ctx *ctx, - struct message_block *block_r); - static int parse_next_body_to_eof(struct message_parser_ctx *ctx, - struct message_block *block_r); --static int preparsed_parse_epilogue_init(struct message_parser_ctx *ctx, -- struct message_block *block_r); --static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx, -- struct message_block *block_r); - - static struct message_boundary * - boundary_find(struct message_boundary *boundaries, -@@ -122,8 +76,8 @@ static void parse_body_add_block(struct message_parser_ctx *ctx, - ctx->part->body_size.virtual_size += block->size + missing_cr_count; - } - --static int message_parser_read_more(struct message_parser_ctx *ctx, -- struct message_block *block_r, bool *full_r) -+int message_parser_read_more(struct message_parser_ctx *ctx, -+ struct message_block *block_r, bool *full_r) - { - int ret; - -@@ -692,346 +646,7 @@ static int parse_next_header_init(struct message_parser_ctx *ctx, - return parse_next_header(ctx, block_r); - } - --static int preparsed_parse_eof(struct message_parser_ctx *ctx ATTR_UNUSED, -- struct message_block *block_r ATTR_UNUSED) --{ -- return -1; --} -- --static void preparsed_skip_to_next(struct message_parser_ctx *ctx) --{ -- ctx->parse_next_block = preparsed_parse_next_header_init; -- while (ctx->part != NULL) { -- if (ctx->part->next != NULL) { -- ctx->part = ctx->part->next; -- break; -- } -- -- /* parse epilogue of multipart parent if requested */ -- if (ctx->part->parent != NULL && -- (ctx->part->parent->flags & MESSAGE_PART_FLAG_MULTIPART) != 0 && -- (ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS) != 0) { -- /* check for presence of epilogue */ -- uoff_t part_end = ctx->part->physical_pos + -- ctx->part->header_size.physical_size + -- ctx->part->body_size.physical_size; -- uoff_t parent_end = ctx->part->parent->physical_pos + -- ctx->part->parent->header_size.physical_size + -- ctx->part->parent->body_size.physical_size; -- -- if (parent_end > part_end) { -- ctx->parse_next_block = preparsed_parse_epilogue_init; -- break; -- } -- } -- ctx->part = ctx->part->parent; -- } -- if (ctx->part == NULL) -- ctx->parse_next_block = preparsed_parse_eof; --} -- --static int preparsed_parse_body_finish(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- i_stream_skip(ctx->input, ctx->skip); -- ctx->skip = 0; -- -- preparsed_skip_to_next(ctx); -- return ctx->parse_next_block(ctx, block_r); --} -- --static int preparsed_parse_prologue_finish(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- i_stream_skip(ctx->input, ctx->skip); -- ctx->skip = 0; -- -- ctx->parse_next_block = preparsed_parse_next_header_init; -- ctx->part = ctx->part->children; -- return ctx->parse_next_block(ctx, block_r); --} -- --static int preparsed_parse_body_more(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t end_offset = ctx->part->physical_pos + -- ctx->part->header_size.physical_size + -- ctx->part->body_size.physical_size; -- bool full; -- int ret; -- -- if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -- return ret; -- -- if (ctx->input->v_offset + block_r->size >= end_offset) { -- block_r->size = end_offset - ctx->input->v_offset; -- ctx->parse_next_block = preparsed_parse_body_finish; -- } -- ctx->skip = block_r->size; -- return 1; --} -- --static int preparsed_parse_prologue_more(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t boundary_min_start, end_offset; -- const unsigned char *cur; -- bool full; -- int ret; -- -- i_assert(ctx->part->children != NULL); -- end_offset = ctx->part->children->physical_pos; -- -- if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -- return ret; -- -- if (ctx->input->v_offset + block_r->size >= end_offset) { -- /* we've got the full prologue: clip off the initial boundary */ -- block_r->size = end_offset - ctx->input->v_offset; -- cur = block_r->data + block_r->size - 1; -- -- /* [\r]\n--boundary[\r]\n */ -- if (block_r->size < 5 || *cur != '\n') { -- ctx->broken_reason = "Prologue boundary end not at expected position"; -- return -1; -- } -- -- cur--; -- if (*cur == '\r') cur--; -- -- /* find newline just before boundary */ -- for (; cur >= block_r->data; cur--) { -- if (*cur == '\n') break; -- } -- -- if (cur[0] != '\n' || cur[1] != '-' || cur[2] != '-') { -- ctx->broken_reason = "Prologue boundary beginning not at expected position"; -- return -1; -- } -- -- if (cur != block_r->data && cur[-1] == '\r') cur--; -- -- /* clip boundary */ -- block_r->size = cur - block_r->data; -- -- ctx->parse_next_block = preparsed_parse_prologue_finish; -- ctx->skip = block_r->size; -- return 1; -- } -- -- /* retain enough data in the stream buffer to contain initial boundary */ -- if (end_offset > BOUNDARY_END_MAX_LEN) -- boundary_min_start = end_offset - BOUNDARY_END_MAX_LEN; -- else -- boundary_min_start = 0; -- -- if (ctx->input->v_offset + block_r->size >= boundary_min_start) { -- if (boundary_min_start <= ctx->input->v_offset) -- return 0; -- block_r->size = boundary_min_start - ctx->input->v_offset; -- } -- ctx->skip = block_r->size; -- return 1; --} -- --static int preparsed_parse_epilogue_more(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t end_offset = ctx->part->physical_pos + -- ctx->part->header_size.physical_size + -- ctx->part->body_size.physical_size; -- bool full; -- int ret; -- -- if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -- return ret; -- -- if (ctx->input->v_offset + block_r->size >= end_offset) { -- block_r->size = end_offset - ctx->input->v_offset; -- ctx->parse_next_block = preparsed_parse_body_finish; -- } -- ctx->skip = block_r->size; -- return 1; --} -- --static int preparsed_parse_epilogue_boundary(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t end_offset = ctx->part->physical_pos + -- ctx->part->header_size.physical_size + -- ctx->part->body_size.physical_size; -- const unsigned char *data, *cur; -- size_t size; -- bool full; -- int ret; -- -- if (end_offset - ctx->input->v_offset < 7) { -- ctx->broken_reason = "Epilogue position is wrong"; -- return -1; -- } -- -- if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -- return ret; -- -- /* [\r]\n--boundary--[\r]\n */ -- if (block_r->size < 7) { -- ctx->want_count = 7; -- return 0; -- } -- -- data = block_r->data; -- size = block_r->size; -- cur = data; -- -- if (*cur == '\r') cur++; -- -- if (cur[0] != '\n' || cur[1] != '-' || data[2] != '-') { -- ctx->broken_reason = "Epilogue boundary start not at expected position"; -- return -1; -- } -- -- /* find the end of the line */ -- cur += 3; -- if ((cur = memchr(cur, '\n', size - (cur-data))) == NULL) { -- if (end_offset < ctx->input->v_offset + size) { -- ctx->broken_reason = "Epilogue boundary end not at expected position"; -- return -1; -- } else if (ctx->input->v_offset + size < end_offset && -- size < BOUNDARY_END_MAX_LEN && -- !ctx->input->eof && !full) { -- ctx->want_count = BOUNDARY_END_MAX_LEN; -- return 0; -- } -- } -- -- block_r->size = 0; -- ctx->parse_next_block = preparsed_parse_epilogue_more; -- ctx->skip = cur - data + 1; -- return 0; --} -- --static int preparsed_parse_body_init(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t offset = ctx->part->physical_pos + -- ctx->part->header_size.physical_size; -- -- if (offset < ctx->input->v_offset) { -- /* header was actually larger than the cached size suggested */ -- ctx->broken_reason = "Header larger than its cached size"; -- return -1; -- } -- i_stream_skip(ctx->input, offset - ctx->input->v_offset); -- -- /* multipart messages may begin with --boundary--, which makes them -- not have any children. */ -- if ((ctx->part->flags & MESSAGE_PART_FLAG_MULTIPART) == 0 || -- ctx->part->children == NULL) -- ctx->parse_next_block = preparsed_parse_body_more; -- else -- ctx->parse_next_block = preparsed_parse_prologue_more; -- return ctx->parse_next_block(ctx, block_r); --} -- --static int preparsed_parse_epilogue_init(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t offset = ctx->part->physical_pos + -- ctx->part->header_size.physical_size + -- ctx->part->body_size.physical_size; -- -- ctx->part = ctx->part->parent; -- -- if (offset < ctx->input->v_offset) { -- /* last child was actually larger than the cached size -- suggested */ -- ctx->broken_reason = "Part larger than its cached size"; -- return -1; -- } -- i_stream_skip(ctx->input, offset - ctx->input->v_offset); -- -- ctx->parse_next_block = preparsed_parse_epilogue_boundary; -- return ctx->parse_next_block(ctx, block_r); --} -- --static int preparsed_parse_finish_header(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- if (ctx->part->children != NULL) { -- if ((ctx->part->flags & MESSAGE_PART_FLAG_MULTIPART) != 0 && -- (ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS) != 0) -- ctx->parse_next_block = preparsed_parse_body_init; -- else { -- ctx->parse_next_block = preparsed_parse_next_header_init; -- ctx->part = ctx->part->children; -- } -- } else if ((ctx->flags & MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK) == 0) { -- ctx->parse_next_block = preparsed_parse_body_init; -- } else { -- preparsed_skip_to_next(ctx); -- } -- return ctx->parse_next_block(ctx, block_r); --} -- --static int preparsed_parse_next_header(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- struct message_header_line *hdr; -- int ret; -- -- ret = message_parse_header_next(ctx->hdr_parser_ctx, &hdr); -- if (ret == 0 || (ret < 0 && ctx->input->stream_errno != 0)) { -- ctx->want_count = i_stream_get_data_size(ctx->input) + 1; -- return ret; -- } -- -- if (hdr != NULL) { -- block_r->hdr = hdr; -- block_r->size = 0; -- return 1; -- } -- message_parse_header_deinit(&ctx->hdr_parser_ctx); -- -- ctx->parse_next_block = preparsed_parse_finish_header; -- -- /* return empty block as end of headers */ -- block_r->hdr = NULL; -- block_r->size = 0; -- -- i_assert(ctx->skip == 0); -- if (ctx->input->v_offset != ctx->part->physical_pos + -- ctx->part->header_size.physical_size) { -- ctx->broken_reason = "Cached header size mismatch"; -- return -1; -- } -- return 1; --} -- --static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- struct istream *hdr_input; -- -- i_assert(ctx->hdr_parser_ctx == NULL); -- -- i_assert(ctx->part->physical_pos >= ctx->input->v_offset); -- i_stream_skip(ctx->input, ctx->part->physical_pos - -- ctx->input->v_offset); -- -- /* the header may become truncated by --boundaries. limit the header -- stream's size to what it's supposed to be to avoid duplicating (and -- keeping in sync!) all the same complicated logic as in -- parse_next_header(). */ -- hdr_input = i_stream_create_limit(ctx->input, ctx->part->header_size.physical_size); -- ctx->hdr_parser_ctx = -- message_parse_header_init(hdr_input, NULL, ctx->hdr_flags); -- i_stream_unref(&hdr_input); -- -- ctx->parse_next_block = preparsed_parse_next_header; -- return preparsed_parse_next_header(ctx, block_r); --} -- --static struct message_parser_ctx * -+struct message_parser_ctx * - message_parser_init_int(struct istream *input, - enum message_header_parser_flags hdr_flags, - enum message_parser_flags flags) -@@ -1063,23 +678,6 @@ message_parser_init(pool_t part_pool, struct istream *input, - return ctx; - } - --struct message_parser_ctx * --message_parser_init_from_parts(struct message_part *parts, -- struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags) --{ -- struct message_parser_ctx *ctx; -- -- i_assert(parts != NULL); -- -- ctx = message_parser_init_int(input, hdr_flags, flags); -- ctx->preparsed = TRUE; -- ctx->parts = ctx->part = parts; -- ctx->parse_next_block = preparsed_parse_next_header_init; -- return ctx; --} -- - void message_parser_deinit(struct message_parser_ctx **_ctx, - struct message_part **parts_r) - { --- -2.11.0 - -From 1765e533f1172e4823413268493e8d4198004f37 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 11:33:31 +0300 -Subject: [PATCH 04/15] lib-mail: message-parser - Add a message_part_finish() - helper function - ---- - src/lib-mail/message-parser.c | 25 ++++++++++++------------- - 1 file changed, 12 insertions(+), 13 deletions(-) - -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index 653f964118..9a98cc83a3 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -150,6 +150,13 @@ message_part_append(pool_t pool, struct message_part *parent) - return part; - } - -+static void message_part_finish(struct message_parser_ctx *ctx) -+{ -+ message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size); -+ message_size_add(&ctx->part->parent->body_size, &ctx->part->header_size); -+ ctx->part = ctx->part->parent; -+} -+ - static void parse_next_body_multipart_init(struct message_parser_ctx *ctx) - { - struct message_boundary *b; -@@ -267,19 +274,16 @@ static int parse_part_finish(struct message_parser_ctx *ctx, - struct message_boundary *boundary, - struct message_block *block_r, bool first_line) - { -- struct message_part *part; - size_t line_size; - - i_assert(ctx->last_boundary == NULL); - - /* get back to parent MIME part, summing the child MIME part sizes - into parent's body sizes */ -- for (part = ctx->part; part != boundary->part; part = part->parent) { -- message_size_add(&part->parent->body_size, &part->body_size); -- message_size_add(&part->parent->body_size, &part->header_size); -+ while (ctx->part != boundary->part) { -+ message_part_finish(ctx); -+ i_assert(ctx->part != NULL); - } -- i_assert(part != NULL); -- ctx->part = part; - - if (boundary->epilogue_found) { - /* this boundary isn't needed anymore */ -@@ -734,13 +738,8 @@ int message_parser_parse_next_block(struct message_parser_ctx *ctx, - i_assert(ctx->input->eof || ctx->input->closed || - ctx->input->stream_errno != 0 || - ctx->broken_reason != NULL); -- while (ctx->part->parent != NULL) { -- message_size_add(&ctx->part->parent->body_size, -- &ctx->part->body_size); -- message_size_add(&ctx->part->parent->body_size, -- &ctx->part->header_size); -- ctx->part = ctx->part->parent; -- } -+ while (ctx->part->parent != NULL) -+ message_part_finish(ctx); - } - - if (block_r->size == 0) { --- -2.11.0 - -From 2dd9d73d7ec0e64c8a6fa055ce4bc382639d1826 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 11:34:22 +0300 -Subject: [PATCH 05/15] lib-mail: message-parser - Change message_part_append() - to do all work internally - ---- - src/lib-mail/message-parser.c | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index 9a98cc83a3..0edd4d267c 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -122,16 +122,17 @@ int message_parser_read_more(struct message_parser_ctx *ctx, - return 1; - } - --static struct message_part * --message_part_append(pool_t pool, struct message_part *parent) -+static void -+message_part_append(struct message_parser_ctx *ctx) - { -+ struct message_part *parent = ctx->part; - struct message_part *p, *part, **list; - - i_assert(parent != NULL); - i_assert((parent->flags & (MESSAGE_PART_FLAG_MULTIPART | - MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0); - -- part = p_new(pool, struct message_part, 1); -+ part = p_new(ctx->part_pool, struct message_part, 1); - part->parent = parent; - for (p = parent; p != NULL; p = p->parent) - p->children_count++; -@@ -147,7 +148,7 @@ message_part_append(pool_t pool, struct message_part *parent) - list = &(*list)->next; - - *list = part; -- return part; -+ ctx->part = part; - } - - static void message_part_finish(struct message_parser_ctx *ctx) -@@ -175,7 +176,7 @@ static void parse_next_body_multipart_init(struct message_parser_ctx *ctx) - static int parse_next_body_message_rfc822_init(struct message_parser_ctx *ctx, - struct message_block *block_r) - { -- ctx->part = message_part_append(ctx->part_pool, ctx->part); -+ message_part_append(ctx); - return parse_next_header_init(ctx, block_r); - } - -@@ -225,7 +226,7 @@ boundary_line_find(struct message_parser_ctx *ctx, - static int parse_next_mime_header_init(struct message_parser_ctx *ctx, - struct message_block *block_r) - { -- ctx->part = message_part_append(ctx->part_pool, ctx->part); -+ message_part_append(ctx); - ctx->part->flags |= MESSAGE_PART_FLAG_IS_MIME; - - return parse_next_header_init(ctx, block_r); --- -2.11.0 - -From 9f565d94ed7962f6c982387c25d093c34edbb5f0 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 11:36:48 +0300 -Subject: [PATCH 06/15] lib-mail: message-parser - Optimize updating - children_count - ---- - src/lib-mail/message-parser.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index 0edd4d267c..f19759c257 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -126,7 +126,7 @@ static void - message_part_append(struct message_parser_ctx *ctx) - { - struct message_part *parent = ctx->part; -- struct message_part *p, *part, **list; -+ struct message_part *part, **list; - - i_assert(parent != NULL); - i_assert((parent->flags & (MESSAGE_PART_FLAG_MULTIPART | -@@ -134,8 +134,6 @@ message_part_append(struct message_parser_ctx *ctx) - - part = p_new(ctx->part_pool, struct message_part, 1); - part->parent = parent; -- for (p = parent; p != NULL; p = p->parent) -- p->children_count++; - - /* set child position */ - part->physical_pos = -@@ -155,6 +153,7 @@ static void message_part_finish(struct message_parser_ctx *ctx) - { - message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size); - message_size_add(&ctx->part->parent->body_size, &ctx->part->header_size); -+ ctx->part->parent->children_count += 1 + ctx->part->children_count; - ctx->part = ctx->part->parent; - } - --- -2.11.0 - -From f543817877ce91e59386eb83144e00e288a19839 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 12:00:38 +0300 -Subject: [PATCH 07/15] lib-mail: message-parser - Optimize appending new part - to linked list - ---- - src/lib-mail/message-parser-private.h | 3 +++ - src/lib-mail/message-parser.c | 24 ++++++++++++++++++------ - 2 files changed, 21 insertions(+), 6 deletions(-) - -diff --git a/src/lib-mail/message-parser-private.h b/src/lib-mail/message-parser-private.h -index 98a576eda4..fd92a48776 100644 ---- a/src/lib-mail/message-parser-private.h -+++ b/src/lib-mail/message-parser-private.h -@@ -29,6 +29,9 @@ struct message_parser_ctx { - const char *last_boundary; - struct message_boundary *boundaries; - -+ struct message_part **next_part; -+ ARRAY(struct message_part **) next_part_stack; -+ - size_t skip; - char last_chr; - unsigned int want_count; -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index f19759c257..0f690ab689 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -1,7 +1,7 @@ - /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ - - #include "lib.h" --#include "buffer.h" -+#include "array.h" - #include "str.h" - #include "istream.h" - #include "rfc822-parser.h" -@@ -126,7 +126,7 @@ static void - message_part_append(struct message_parser_ctx *ctx) - { - struct message_part *parent = ctx->part; -- struct message_part *part, **list; -+ struct message_part *part; - - i_assert(parent != NULL); - i_assert((parent->flags & (MESSAGE_PART_FLAG_MULTIPART | -@@ -141,16 +141,26 @@ message_part_append(struct message_parser_ctx *ctx) - parent->body_size.physical_size + - parent->header_size.physical_size; - -- list = &part->parent->children; -- while (*list != NULL) -- list = &(*list)->next; -+ /* add to parent's linked list */ -+ *ctx->next_part = part; -+ /* update the parent's end-of-linked-list pointer */ -+ struct message_part **next_part = &part->next; -+ array_push_back(&ctx->next_part_stack, &next_part); -+ /* This part is now the new parent for the next message_part_append() -+ call. Its linked list begins with the children pointer. */ -+ ctx->next_part = &part->children; - -- *list = part; - ctx->part = part; - } - - static void message_part_finish(struct message_parser_ctx *ctx) - { -+ struct message_part **const *parent_next_partp; -+ -+ parent_next_partp = array_back(&ctx->next_part_stack); -+ array_pop_back(&ctx->next_part_stack); -+ ctx->next_part = *parent_next_partp; -+ - message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size); - message_size_add(&ctx->part->parent->body_size, &ctx->part->header_size); - ctx->part->parent->children_count += 1 + ctx->part->children_count; -@@ -678,7 +688,9 @@ message_parser_init(pool_t part_pool, struct istream *input, - ctx = message_parser_init_int(input, hdr_flags, flags); - ctx->part_pool = part_pool; - ctx->parts = ctx->part = p_new(part_pool, struct message_part, 1); -+ ctx->next_part = &ctx->part->children; - ctx->parse_next_block = parse_next_header_init; -+ p_array_init(&ctx->next_part_stack, ctx->parser_pool, 4); - return ctx; - } - --- -2.11.0 - -From f080cb2da2064005f35e1d16cd4efded21552491 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 12:10:07 +0300 -Subject: [PATCH 08/15] lib-mail: message-parser - Minor code cleanup to - finding the end of boundary line - ---- - src/lib-mail/message-parser.c | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index 0f690ab689..88c1b31564 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -211,17 +211,16 @@ boundary_line_find(struct message_parser_ctx *ctx, - } - - /* need to find the end of line */ -- if (memchr(data + 2, '\n', size - 2) == NULL && -- size < BOUNDARY_END_MAX_LEN && -+ data += 2; -+ size -= 2; -+ if (memchr(data, '\n', size) == NULL && -+ size+2 < BOUNDARY_END_MAX_LEN && - !ctx->input->eof && !full) { - /* no LF found */ - ctx->want_count = BOUNDARY_END_MAX_LEN; - return 0; - } - -- data += 2; -- size -= 2; -- - *boundary_r = boundary_find(ctx->boundaries, data, size); - if (*boundary_r == NULL) - return -1; --- -2.11.0 - -From 6c530af237d5f0486d5fff68d114de905ced9b97 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 12:53:12 +0300 -Subject: [PATCH 09/15] lib-mail: message-parser - Truncate excessively long - MIME boundaries - -RFC 2046 requires that the boundaries are a maximum of 70 characters -(excluding the "--" prefix and suffix). We allow 80 characters for a bit of -extra safety. Anything longer than that is truncated and treated the same -as if it was just 80 characters. ---- - src/lib-mail/message-parser-private.h | 3 +- - src/lib-mail/message-parser.c | 4 +- - src/lib-mail/test-message-parser.c | 95 +++++++++++++++++++++++++++++++++++ - 3 files changed, 100 insertions(+), 2 deletions(-) - -diff --git a/src/lib-mail/message-parser-private.h b/src/lib-mail/message-parser-private.h -index fd92a48776..d8116259ad 100644 ---- a/src/lib-mail/message-parser-private.h -+++ b/src/lib-mail/message-parser-private.h -@@ -5,7 +5,8 @@ - - /* RFC-2046 requires boundaries are max. 70 chars + "--" prefix + "--" suffix. - We'll add a bit more just in case. */ --#define BOUNDARY_END_MAX_LEN (70 + 2 + 2 + 10) -+#define BOUNDARY_STRING_MAX_LEN (70 + 10) -+#define BOUNDARY_END_MAX_LEN (BOUNDARY_STRING_MAX_LEN + 2 + 2) - - struct message_boundary { - struct message_boundary *next; -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index 88c1b31564..43142491b2 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -477,8 +477,10 @@ static void parse_content_type(struct message_parser_ctx *ctx, - rfc2231_parse(&parser, &results); - for (; *results != NULL; results += 2) { - if (strcasecmp(results[0], "boundary") == 0) { -+ /* truncate excessively long boundaries */ - ctx->last_boundary = -- p_strdup(ctx->parser_pool, results[1]); -+ p_strndup(ctx->parser_pool, results[1], -+ BOUNDARY_STRING_MAX_LEN); - break; - } - } -diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c -index c275707265..6bf1643e88 100644 ---- a/src/lib-mail/test-message-parser.c -+++ b/src/lib-mail/test-message-parser.c -@@ -736,6 +736,100 @@ static void test_message_parser_no_eoh(void) - test_end(); - } - -+static void test_message_parser_long_mime_boundary(void) -+{ -+ /* Close the boundaries in wrong reverse order. But because all -+ boundaries are actually truncated to the same size (..890) it -+ works the same as if all of them were duplicate boundaries. */ -+static const char input_msg[] = -+"Content-Type: multipart/mixed; boundary=\"1234567890123456789012345678901234567890123456789012345678901234567890123456789012\"\n" -+"\n" -+"--1234567890123456789012345678901234567890123456789012345678901234567890123456789012\n" -+"Content-Type: multipart/mixed; boundary=\"123456789012345678901234567890123456789012345678901234567890123456789012345678901\"\n" -+"\n" -+"--123456789012345678901234567890123456789012345678901234567890123456789012345678901\n" -+"Content-Type: multipart/mixed; boundary=\"12345678901234567890123456789012345678901234567890123456789012345678901234567890\"\n" -+"\n" -+"--12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" -+"Content-Type: text/plain\n" -+"\n" -+"1\n" -+"--1234567890123456789012345678901234567890123456789012345678901234567890123456789012\n" -+"Content-Type: text/plain\n" -+"\n" -+"22\n" -+"--123456789012345678901234567890123456789012345678901234567890123456789012345678901\n" -+"Content-Type: text/plain\n" -+"\n" -+"333\n" -+"--12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" -+"Content-Type: text/plain\n" -+"\n" -+"4444\n"; -+ 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 long mime boundary"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(input_msg); -+ -+ parser = message_parser_init(pool, input, 0, 0); -+ 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 == 6); -+ 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 == 126); -+ test_assert(part->header_size.virtual_size == 126+2); -+ test_assert(part->body_size.lines == 22); -+ test_assert(part->body_size.physical_size == 871); -+ test_assert(part->body_size.virtual_size == 871+22); -+ -+ part = parts->children; -+ test_assert(part->children_count == 5); -+ 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 == 125); -+ test_assert(part->header_size.virtual_size == 125+2); -+ test_assert(part->body_size.lines == 19); -+ test_assert(part->body_size.physical_size == 661); -+ test_assert(part->body_size.virtual_size == 661+19); -+ -+ part = parts->children->children; -+ test_assert(part->children_count == 4); -+ 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 == 124); -+ test_assert(part->header_size.virtual_size == 124+2); -+ test_assert(part->body_size.lines == 16); -+ test_assert(part->body_size.physical_size == 453); -+ test_assert(part->body_size.virtual_size == 453+16); -+ -+ part = parts->children->children->children; -+ for (unsigned int i = 1; i <= 3; i++, part = part->next) { -+ test_assert(part->children_count == 0); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 26); -+ test_assert(part->header_size.virtual_size == 26+2); -+ test_assert(part->body_size.lines == 0); -+ test_assert(part->body_size.physical_size == i); -+ test_assert(part->body_size.virtual_size == i); -+ } -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ - int main(void) - { - static void (*const test_functions[])(void) = { -@@ -749,6 +843,7 @@ int main(void) - test_message_parser_continuing_mime_boundary, - test_message_parser_continuing_truncated_mime_boundary, - test_message_parser_continuing_mime_boundary_reverse, -+ test_message_parser_long_mime_boundary, - test_message_parser_no_eoh, - NULL - }; --- -2.11.0 - -From f6a31b782088d9f626f4718654cb91cf723f3f9c Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 13:06:02 +0300 -Subject: [PATCH 10/15] lib-mail: message-parser - Optimize boundary lookups - when exact boundary is found - -When an exact boundary is found, there's no need to continue looking for -more boundaries. ---- - src/lib-mail/message-parser.c | 24 +++++++++++++++++++++--- - 1 file changed, 21 insertions(+), 3 deletions(-) - -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index 43142491b2..f0a0cf41f0 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -31,8 +31,14 @@ boundary_find(struct message_boundary *boundaries, - while (boundaries != NULL) { - if (boundaries->len <= len && - memcmp(boundaries->boundary, data, boundaries->len) == 0 && -- (best == NULL || best->len < boundaries->len)) -+ (best == NULL || best->len < boundaries->len)) { - best = boundaries; -+ if (best->len == len) { -+ /* This is exactly the wanted boundary. There -+ can't be a better one. */ -+ break; -+ } -+ } - - boundaries = boundaries->next; - } -@@ -213,15 +219,27 @@ boundary_line_find(struct message_parser_ctx *ctx, - /* need to find the end of line */ - data += 2; - size -= 2; -- if (memchr(data, '\n', size) == NULL && -+ const unsigned char *lf_pos = memchr(data, '\n', size); -+ if (lf_pos == NULL && - size+2 < BOUNDARY_END_MAX_LEN && - !ctx->input->eof && !full) { - /* no LF found */ - ctx->want_count = BOUNDARY_END_MAX_LEN; - return 0; - } -+ size_t find_size = size; -+ -+ if (lf_pos != NULL) { -+ find_size = lf_pos - data; -+ if (find_size > 0 && data[find_size-1] == '\r') -+ find_size--; -+ if (find_size > 2 && data[find_size-1] == '-' && -+ data[find_size-2] == '-') -+ find_size -= 2; -+ } else if (find_size > BOUNDARY_END_MAX_LEN) -+ find_size = BOUNDARY_END_MAX_LEN; - -- *boundary_r = boundary_find(ctx->boundaries, data, size); -+ *boundary_r = boundary_find(ctx->boundaries, data, find_size); - if (*boundary_r == NULL) - return -1; - --- -2.11.0 - -From 86adf700cc31775744ed48ff5aebe62b97e52c51 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 14:53:27 +0300 -Subject: [PATCH 11/15] lib-mail: message-parser - Add boundary_remove_until() - helper function - ---- - src/lib-mail/message-parser.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index f0a0cf41f0..0fb0f9181a 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -173,6 +173,13 @@ static void message_part_finish(struct message_parser_ctx *ctx) - ctx->part = ctx->part->parent; - } - -+static void -+boundary_remove_until(struct message_parser_ctx *ctx, -+ struct message_boundary *boundary) -+{ -+ ctx->boundaries = boundary; -+} -+ - static void parse_next_body_multipart_init(struct message_parser_ctx *ctx) - { - struct message_boundary *b; -@@ -314,10 +321,10 @@ static int parse_part_finish(struct message_parser_ctx *ctx, - - if (boundary->epilogue_found) { - /* this boundary isn't needed anymore */ -- ctx->boundaries = boundary->next; -+ boundary_remove_until(ctx, boundary->next); - } else { - /* forget about the boundaries we possibly skipped */ -- ctx->boundaries = boundary; -+ boundary_remove_until(ctx, boundary); - } - - /* the boundary itself should already be in buffer. add that. */ --- -2.11.0 - -From a6f9ff266c1a2458a1762cdb1206b50497cacb09 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 15:00:57 +0300 -Subject: [PATCH 12/15] lib-mail: message-parser - Don't use memory pool for - parser - -This reduces memory usage when parsing many MIME parts where boundaries are -being added and removed constantly. ---- - src/lib-mail/message-parser-private.h | 6 ++--- - src/lib-mail/message-parser.c | 41 ++++++++++++++++++++++++----------- - 2 files changed, 31 insertions(+), 16 deletions(-) - -diff --git a/src/lib-mail/message-parser-private.h b/src/lib-mail/message-parser-private.h -index d8116259ad..fe106819e2 100644 ---- a/src/lib-mail/message-parser-private.h -+++ b/src/lib-mail/message-parser-private.h -@@ -12,14 +12,14 @@ struct message_boundary { - struct message_boundary *next; - - struct message_part *part; -- const char *boundary; -+ char *boundary; - size_t len; - - bool epilogue_found:1; - }; - - struct message_parser_ctx { -- pool_t parser_pool, part_pool; -+ pool_t part_pool; - struct istream *input; - struct message_part *parts, *part; - const char *broken_reason; -@@ -27,7 +27,7 @@ struct message_parser_ctx { - enum message_header_parser_flags hdr_flags; - enum message_parser_flags flags; - -- const char *last_boundary; -+ char *last_boundary; - struct message_boundary *boundaries; - - struct message_part **next_part; -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index 0fb0f9181a..c9ff98576b 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -173,10 +173,24 @@ static void message_part_finish(struct message_parser_ctx *ctx) - ctx->part = ctx->part->parent; - } - -+static void message_boundary_free(struct message_boundary *b) -+{ -+ i_free(b->boundary); -+ i_free(b); -+} -+ - static void - boundary_remove_until(struct message_parser_ctx *ctx, - struct message_boundary *boundary) - { -+ while (ctx->boundaries != boundary) { -+ struct message_boundary *cur = ctx->boundaries; -+ -+ i_assert(cur != NULL); -+ ctx->boundaries = cur->next; -+ message_boundary_free(cur); -+ -+ } - ctx->boundaries = boundary; - } - -@@ -184,15 +198,14 @@ static void parse_next_body_multipart_init(struct message_parser_ctx *ctx) - { - struct message_boundary *b; - -- b = p_new(ctx->parser_pool, struct message_boundary, 1); -+ b = i_new(struct message_boundary, 1); - b->part = ctx->part; - b->boundary = ctx->last_boundary; -+ ctx->last_boundary = NULL; - b->len = strlen(b->boundary); - - b->next = ctx->boundaries; - ctx->boundaries = b; -- -- ctx->last_boundary = NULL; - } - - static int parse_next_body_message_rfc822_init(struct message_parser_ctx *ctx, -@@ -309,6 +322,8 @@ static int parse_part_finish(struct message_parser_ctx *ctx, - struct message_block *block_r, bool first_line) - { - size_t line_size; -+ size_t boundary_len = boundary->len; -+ bool boundary_epilogue_found = boundary->epilogue_found; - - i_assert(ctx->last_boundary == NULL); - -@@ -341,7 +356,7 @@ static int parse_part_finish(struct message_parser_ctx *ctx, - i_assert(block_r->data[0] == '\n'); - line_size = 1; - } -- line_size += 2 + boundary->len + (boundary->epilogue_found ? 2 : 0); -+ line_size += 2 + boundary_len + (boundary_epilogue_found ? 2 : 0); - i_assert(block_r->size >= ctx->skip + line_size); - block_r->size = line_size; - parse_body_add_block(ctx, block_r); -@@ -503,9 +518,9 @@ static void parse_content_type(struct message_parser_ctx *ctx, - for (; *results != NULL; results += 2) { - if (strcasecmp(results[0], "boundary") == 0) { - /* truncate excessively long boundaries */ -+ i_free(ctx->last_boundary); - ctx->last_boundary = -- p_strndup(ctx->parser_pool, results[1], -- BOUNDARY_STRING_MAX_LEN); -+ i_strndup(results[1], BOUNDARY_STRING_MAX_LEN); - break; - } - } -@@ -628,7 +643,7 @@ static int parse_next_header(struct message_parser_ctx *ctx, - i_assert(!ctx->multipart); - part->flags = 0; - } -- ctx->last_boundary = NULL; -+ i_free(ctx->last_boundary); - - if (!ctx->part_seen_content_type || - (part->flags & MESSAGE_PART_FLAG_IS_MIME) == 0) { -@@ -692,11 +707,8 @@ message_parser_init_int(struct istream *input, - enum message_parser_flags flags) - { - struct message_parser_ctx *ctx; -- pool_t pool; - -- pool = pool_alloconly_create("Message Parser", 1024); -- ctx = p_new(pool, struct message_parser_ctx, 1); -- ctx->parser_pool = pool; -+ ctx = i_new(struct message_parser_ctx, 1); - ctx->hdr_flags = hdr_flags; - ctx->flags = flags; - ctx->input = input; -@@ -716,7 +728,7 @@ message_parser_init(pool_t part_pool, struct istream *input, - ctx->parts = ctx->part = p_new(part_pool, struct message_part, 1); - ctx->next_part = &ctx->part->children; - ctx->parse_next_block = parse_next_header_init; -- p_array_init(&ctx->next_part_stack, ctx->parser_pool, 4); -+ i_array_init(&ctx->next_part_stack, 4); - return ctx; - } - -@@ -743,8 +755,11 @@ int message_parser_deinit_from_parts(struct message_parser_ctx **_ctx, - - if (ctx->hdr_parser_ctx != NULL) - message_parse_header_deinit(&ctx->hdr_parser_ctx); -+ boundary_remove_until(ctx, NULL); - i_stream_unref(&ctx->input); -- pool_unref(&ctx->parser_pool); -+ array_free(&ctx->next_part_stack); -+ i_free(ctx->last_boundary); -+ i_free(ctx); - i_assert(ret < 0 || *parts_r != NULL); - return ret; - } --- -2.11.0 - -From 45cd8d8fd39d301607b22ec6f4ac800331a30225 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 16:50:56 +0300 -Subject: [PATCH 13/15] lib-mail, global: message_parser_init*() - Convert - flags to settings structure - ---- - src/doveadm/doveadm-mail-fetch.c | 7 +++-- - src/lib-imap/test-imap-bodystructure.c | 10 +++--- - src/lib-imap/test-imap-envelope.c | 10 +++--- - src/lib-mail/istream-attachment-extractor.c | 8 +++-- - src/lib-mail/istream-binary-converter.c | 8 +++-- - src/lib-mail/message-parser-from-parts.c | 5 ++- - src/lib-mail/message-parser-private.h | 3 +- - src/lib-mail/message-parser.c | 12 +++----- - src/lib-mail/message-parser.h | 11 ++++--- - src/lib-mail/message-search.c | 9 +++--- - src/lib-mail/message-snippet.c | 3 +- - src/lib-mail/test-message-decoder.c | 4 ++- - src/lib-mail/test-message-parser.c | 47 +++++++++++++++++------------ - src/lib-mail/test-message-part.c | 3 +- - src/lib-storage/index/index-mail-headers.c | 22 ++++++-------- - src/plugins/fts/fts-build-mail.c | 7 +++-- - 16 files changed, 95 insertions(+), 74 deletions(-) - -diff --git a/src/doveadm/doveadm-mail-fetch.c b/src/doveadm/doveadm-mail-fetch.c -index 75b69e4242..d8b396a199 100644 ---- a/src/doveadm/doveadm-mail-fetch.c -+++ b/src/doveadm/doveadm-mail-fetch.c -@@ -265,6 +265,9 @@ static int fetch_text(struct fetch_cmd_context *ctx) - - static int fetch_text_utf8(struct fetch_cmd_context *ctx) - { -+ const struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE, -+ }; - struct istream *input; - struct message_parser_ctx *parser; - struct message_decoder_context *decoder; -@@ -275,9 +278,7 @@ static int fetch_text_utf8(struct fetch_cmd_context *ctx) - if (mail_get_stream(ctx->mail, NULL, NULL, &input) < 0) - return -1; - -- parser = message_parser_init(pool_datastack_create(), input, -- MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE, -- 0); -+ parser = message_parser_init(pool_datastack_create(), input, &parser_set); - decoder = message_decoder_init(NULL, 0); - - while ((ret = message_parser_parse_next_block(parser, &raw_block)) > 0) { -diff --git a/src/lib-imap/test-imap-bodystructure.c b/src/lib-imap/test-imap-bodystructure.c -index 6f456a4453..dfc9957488 100644 ---- a/src/lib-imap/test-imap-bodystructure.c -+++ b/src/lib-imap/test-imap-bodystructure.c -@@ -381,6 +381,11 @@ static const unsigned int normalize_tests_count = N_ELEMENTS(normalize_tests); - static struct message_part * - msg_parse(pool_t pool, const char *message, bool parse_bodystructure) - { -+ const struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -+ MESSAGE_HEADER_PARSER_FLAG_DROP_CR, -+ .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, -+ }; - struct message_parser_ctx *parser; - struct istream *input; - struct message_block block; -@@ -388,10 +393,7 @@ msg_parse(pool_t pool, const char *message, bool parse_bodystructure) - int ret; - - input = i_stream_create_from_data(message, strlen(message)); -- parser = message_parser_init(pool, input, -- MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -- MESSAGE_HEADER_PARSER_FLAG_DROP_CR, -- MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK); -+ parser = message_parser_init(pool, input, &parser_set); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) { - if (parse_bodystructure) { - message_part_data_parse_from_header(pool, block.part, -diff --git a/src/lib-imap/test-imap-envelope.c b/src/lib-imap/test-imap-envelope.c -index 0d0891701b..1f295e58ba 100644 ---- a/src/lib-imap/test-imap-envelope.c -+++ b/src/lib-imap/test-imap-envelope.c -@@ -118,6 +118,11 @@ static const unsigned int parse_tests_count = N_ELEMENTS(parse_tests); - static struct message_part_envelope * - msg_parse(pool_t pool, const char *message) - { -+ const struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -+ MESSAGE_HEADER_PARSER_FLAG_DROP_CR, -+ .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, -+ }; - struct message_parser_ctx *parser; - struct message_part_envelope *envlp = NULL; - struct istream *input; -@@ -126,10 +131,7 @@ msg_parse(pool_t pool, const char *message) - int ret; - - input = i_stream_create_from_data(message, strlen(message)); -- parser = message_parser_init(pool, input, -- MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -- MESSAGE_HEADER_PARSER_FLAG_DROP_CR, -- MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK); -+ parser = message_parser_init(pool, input, &parser_set); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) { - i_assert(block.part->parent == NULL); - message_part_envelope_parse_from_header(pool, &envlp, block.hdr); -diff --git a/src/lib-mail/istream-attachment-extractor.c b/src/lib-mail/istream-attachment-extractor.c -index e9655a5a67..7d4ac01072 100644 ---- a/src/lib-mail/istream-attachment-extractor.c -+++ b/src/lib-mail/istream-attachment-extractor.c -@@ -696,6 +696,10 @@ i_stream_create_attachment_extractor(struct istream *input, - struct istream_attachment_settings *set, - void *context) - { -+ const struct message_parser_settings parser_set = { -+ .flags = MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -+ MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES, -+ }; - struct attachment_istream *astream; - - i_assert(set->min_size > 0); -@@ -722,9 +726,7 @@ i_stream_create_attachment_extractor(struct istream *input, - astream->istream.istream.seekable = FALSE; - - astream->pool = pool_alloconly_create("istream attachment", 1024); -- astream->parser = message_parser_init(astream->pool, input, 0, -- MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -- MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES); -+ astream->parser = message_parser_init(astream->pool, input, &parser_set); - return i_stream_create(&astream->istream, input, - i_stream_get_fd(input), 0); - } -diff --git a/src/lib-mail/istream-binary-converter.c b/src/lib-mail/istream-binary-converter.c -index 201a588152..856b854738 100644 ---- a/src/lib-mail/istream-binary-converter.c -+++ b/src/lib-mail/istream-binary-converter.c -@@ -286,6 +286,10 @@ static void i_stream_binary_converter_close(struct iostream_private *stream, - - struct istream *i_stream_create_binary_converter(struct istream *input) - { -+ const struct message_parser_settings parser_set = { -+ .flags = MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -+ MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES, -+ }; - struct binary_converter_istream *bstream; - - bstream = i_new(struct binary_converter_istream, 1); -@@ -299,9 +303,7 @@ struct istream *i_stream_create_binary_converter(struct istream *input) - bstream->istream.istream.seekable = FALSE; - - bstream->pool = pool_alloconly_create("istream binary converter", 128); -- bstream->parser = message_parser_init(bstream->pool, input, 0, -- MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -- MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES); -+ bstream->parser = message_parser_init(bstream->pool, input, &parser_set); - return i_stream_create(&bstream->istream, input, - i_stream_get_fd(input), 0); - } -diff --git a/src/lib-mail/message-parser-from-parts.c b/src/lib-mail/message-parser-from-parts.c -index b23055ab9b..8e21ec8f18 100644 ---- a/src/lib-mail/message-parser-from-parts.c -+++ b/src/lib-mail/message-parser-from-parts.c -@@ -351,14 +351,13 @@ static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx, - struct message_parser_ctx * - message_parser_init_from_parts(struct message_part *parts, - struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags) -+ const struct message_parser_settings *set) - { - struct message_parser_ctx *ctx; - - i_assert(parts != NULL); - -- ctx = message_parser_init_int(input, hdr_flags, flags); -+ ctx = message_parser_init_int(input, set); - ctx->preparsed = TRUE; - ctx->parts = ctx->part = parts; - ctx->parse_next_block = preparsed_parse_next_header_init; -diff --git a/src/lib-mail/message-parser-private.h b/src/lib-mail/message-parser-private.h -index fe106819e2..dbf8464cfb 100644 ---- a/src/lib-mail/message-parser-private.h -+++ b/src/lib-mail/message-parser-private.h -@@ -51,8 +51,7 @@ struct message_parser_ctx { - - struct message_parser_ctx * - message_parser_init_int(struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags); -+ const struct message_parser_settings *set); - int message_parser_read_more(struct message_parser_ctx *ctx, - struct message_block *block_r, bool *full_r); - -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index c9ff98576b..41b9ed133a 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -703,14 +703,13 @@ static int parse_next_header_init(struct message_parser_ctx *ctx, - - struct message_parser_ctx * - message_parser_init_int(struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags) -+ const struct message_parser_settings *set) - { - struct message_parser_ctx *ctx; - - ctx = i_new(struct message_parser_ctx, 1); -- ctx->hdr_flags = hdr_flags; -- ctx->flags = flags; -+ ctx->hdr_flags = set->hdr_flags; -+ ctx->flags = set->flags; - ctx->input = input; - i_stream_ref(input); - return ctx; -@@ -718,12 +717,11 @@ message_parser_init_int(struct istream *input, - - struct message_parser_ctx * - message_parser_init(pool_t part_pool, struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags) -+ const struct message_parser_settings *set) - { - struct message_parser_ctx *ctx; - -- ctx = message_parser_init_int(input, hdr_flags, flags); -+ ctx = message_parser_init_int(input, set); - ctx->part_pool = part_pool; - ctx->parts = ctx->part = p_new(part_pool, struct message_part, 1); - ctx->next_part = &ctx->part->children; -diff --git a/src/lib-mail/message-parser.h b/src/lib-mail/message-parser.h -index 3efd851862..d159b2607d 100644 ---- a/src/lib-mail/message-parser.h -+++ b/src/lib-mail/message-parser.h -@@ -17,6 +17,11 @@ enum message_parser_flags { - MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES = 0x08 - }; - -+struct message_parser_settings { -+ enum message_header_parser_flags hdr_flags; -+ enum message_parser_flags flags; -+}; -+ - struct message_parser_ctx; - - struct message_block { -@@ -45,8 +50,7 @@ extern message_part_header_callback_t *null_message_part_header_callback; - are allocated from. */ - struct message_parser_ctx * - message_parser_init(pool_t part_pool, struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags); -+ const struct message_parser_settings *set); - /* Deinitialize message parser. The ctx must NOT have been created by - message_parser_init_from_parts(). */ - void message_parser_deinit(struct message_parser_ctx **ctx, -@@ -55,8 +59,7 @@ void message_parser_deinit(struct message_parser_ctx **ctx, - struct message_parser_ctx * - message_parser_init_from_parts(struct message_part *parts, - struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags); -+ const struct message_parser_settings *set); - /* Same as message_parser_deinit(), but return an error message describing - why the preparsed parts didn't match the message. This can also safely be - called even when preparsed parts weren't used - it'll always just return -diff --git a/src/lib-mail/message-search.c b/src/lib-mail/message-search.c -index 66c043c158..14d1a11470 100644 ---- a/src/lib-mail/message-search.c -+++ b/src/lib-mail/message-search.c -@@ -196,8 +196,9 @@ message_search_msg_real(struct message_search_context *ctx, - struct istream *input, struct message_part *parts, - const char **error_r) - { -- const enum message_header_parser_flags hdr_parser_flags = -- MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE; -+ const struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE, -+ }; - struct message_parser_ctx *parser_ctx; - struct message_block raw_block; - struct message_part *new_parts; -@@ -207,10 +208,10 @@ message_search_msg_real(struct message_search_context *ctx, - - if (parts != NULL) { - parser_ctx = message_parser_init_from_parts(parts, -- input, hdr_parser_flags, 0); -+ input, &parser_set); - } else { - parser_ctx = message_parser_init(pool_datastack_create(), -- input, hdr_parser_flags, 0); -+ input, &parser_set); - } - - while ((ret = message_parser_parse_next_block(parser_ctx, -diff --git a/src/lib-mail/message-snippet.c b/src/lib-mail/message-snippet.c -index 2100b70554..e6965fd707 100644 ---- a/src/lib-mail/message-snippet.c -+++ b/src/lib-mail/message-snippet.c -@@ -137,6 +137,7 @@ int message_snippet_generate(struct istream *input, - unsigned int max_snippet_chars, - string_t *snippet) - { -+ const struct message_parser_settings parser_set = { .flags = 0 }; - struct message_parser_ctx *parser; - struct message_part *parts; - struct message_decoder_context *decoder; -@@ -151,7 +152,7 @@ int message_snippet_generate(struct istream *input, - ctx.snippet.chars_left = max_snippet_chars; - ctx.quoted_snippet.snippet = str_new(pool, max_snippet_chars); - ctx.quoted_snippet.chars_left = max_snippet_chars - 1; /* -1 for '>' */ -- parser = message_parser_init(pool_datastack_create(), input, 0, 0); -+ parser = message_parser_init(pool_datastack_create(), input, &parser_set); - decoder = message_decoder_init(NULL, 0); - while ((ret = message_parser_parse_next_block(parser, &raw_block)) > 0) { - if (!message_decoder_decode_next_block(decoder, &raw_block, &block)) -diff --git a/src/lib-mail/test-message-decoder.c b/src/lib-mail/test-message-decoder.c -index e1faca29b4..3007283cad 100644 ---- a/src/lib-mail/test-message-decoder.c -+++ b/src/lib-mail/test-message-decoder.c -@@ -105,6 +105,7 @@ static void test_message_decoder_multipart(void) - "\n" - "?garbage\n" - "--foo--\n"; -+ const struct message_parser_settings parser_set = { .flags = 0, }; - struct message_parser_ctx *parser; - struct message_decoder_context *decoder; - struct message_part *parts; -@@ -116,7 +117,8 @@ static void test_message_decoder_multipart(void) - test_begin("message decoder multipart"); - - istream = test_istream_create(test_message_input); -- parser = message_parser_init(pool_datastack_create(), istream, 0, 0); -+ parser = message_parser_init(pool_datastack_create(), istream, -+ &parser_set); - decoder = message_decoder_init(NULL, 0); - - test_istream_set_allow_eof(istream, FALSE); -diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c -index 6bf1643e88..5e496275fe 100644 ---- a/src/lib-mail/test-message-parser.c -+++ b/src/lib-mail/test-message-parser.c -@@ -39,6 +39,8 @@ static const char test_msg[] = - "\n"; - #define TEST_MSG_LEN (sizeof(test_msg)-1) - -+static const struct message_parser_settings set_empty = { .flags = 0 }; -+ - static bool msg_parts_cmp(struct message_part *p1, struct message_part *p2) - { - while (p1 != NULL || p2 != NULL) { -@@ -71,6 +73,9 @@ static bool msg_parts_cmp(struct message_part *p1, struct message_part *p2) - - static void test_parsed_parts(struct istream *input, struct message_part *parts) - { -+ const struct message_parser_settings parser_set = { -+ .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, -+ }; - struct message_parser_ctx *parser; - struct message_block block; - struct message_part *parts2; -@@ -81,8 +86,7 @@ static void test_parsed_parts(struct istream *input, struct message_part *parts) - if (i_stream_get_size(input, TRUE, &input_size) < 0) - i_unreached(); - -- parser = message_parser_init_from_parts(parts, input, 0, -- MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK); -+ parser = message_parser_init_from_parts(parts, input, &parser_set); - for (i = 1; i <= input_size*2+1; i++) { - test_istream_set_size(input, i/2); - if (i > TEST_MSG_LEN*2) -@@ -111,9 +115,11 @@ static void test_message_parser_small_blocks(void) - output = t_str_new(128); - - /* full parsing */ -- parser = message_parser_init(pool, input, 0, -- MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -- MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES); -+ const struct message_parser_settings full_parser_set = { -+ .flags = MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -+ MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES, -+ }; -+ parser = message_parser_init(pool, input, &full_parser_set); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) { - if (block.hdr != NULL) - message_header_line_write(output, block.hdr); -@@ -129,7 +135,7 @@ static void test_message_parser_small_blocks(void) - i_stream_seek(input, 0); - test_istream_set_allow_eof(input, FALSE); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - for (i = 1; i <= TEST_MSG_LEN*2+1; i++) { - test_istream_set_size(input, i/2); - if (i > TEST_MSG_LEN*2) -@@ -147,8 +153,11 @@ static void test_message_parser_small_blocks(void) - test_istream_set_allow_eof(input, FALSE); - - end_of_headers_idx = (strstr(test_msg, "\n-----") - test_msg); -- parser = message_parser_init_from_parts(parts, input, 0, -- MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK); -+ const struct message_parser_settings preparsed_parser_set = { -+ .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, -+ }; -+ parser = message_parser_init_from_parts(parts, input, -+ &preparsed_parser_set); - for (i = 1; i <= TEST_MSG_LEN*2+1; i++) { - test_istream_set_size(input, i/2); - if (i > TEST_MSG_LEN*2) -@@ -190,7 +199,7 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); -@@ -255,7 +264,7 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); -@@ -311,7 +320,7 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); -@@ -349,7 +358,7 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); -@@ -394,7 +403,7 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); -@@ -455,7 +464,7 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); -@@ -516,7 +525,7 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); -@@ -578,7 +587,7 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); -@@ -661,7 +670,7 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); -@@ -721,7 +730,7 @@ static void test_message_parser_no_eoh(void) - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - test_assert(message_parser_parse_next_block(parser, &block) > 0 && - block.hdr != NULL && strcmp(block.hdr->name, "a") == 0 && - block.hdr->value_len == 1 && block.hdr->value[0] == 'b'); -@@ -777,7 +786,7 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); -diff --git a/src/lib-mail/test-message-part.c b/src/lib-mail/test-message-part.c -index 6cad8ffbd3..4a51a39f99 100644 ---- a/src/lib-mail/test-message-part.c -+++ b/src/lib-mail/test-message-part.c -@@ -65,6 +65,7 @@ static const char test_msg[] = - - static void test_message_part_idx(void) - { -+ const struct message_parser_settings set = { .flags = 0 }; - struct message_parser_ctx *parser; - struct istream *input; - struct message_part *parts, *part, *prev_part; -@@ -77,7 +78,7 @@ static void test_message_part_idx(void) - pool = pool_alloconly_create("message parser", 10240); - input = i_stream_create_from_data(test_msg, TEST_MSG_LEN); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) { - part_idx = message_part_to_idx(block.part); - test_assert(part_idx >= prev_idx); -diff --git a/src/lib-storage/index/index-mail-headers.c b/src/lib-storage/index/index-mail-headers.c -index 54a5883177..df21b9129e 100644 ---- a/src/lib-storage/index/index-mail-headers.c -+++ b/src/lib-storage/index/index-mail-headers.c -@@ -16,11 +16,11 @@ - #include "index-storage.h" - #include "index-mail.h" - --static const enum message_header_parser_flags hdr_parser_flags = -- MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -- MESSAGE_HEADER_PARSER_FLAG_DROP_CR; --static const enum message_parser_flags msg_parser_flags = -- MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK; -+static const struct message_parser_settings msg_parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -+ MESSAGE_HEADER_PARSER_FLAG_DROP_CR, -+ .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, -+}; - - static int header_line_cmp(const struct index_mail_line *l1, - const struct index_mail_line *l2) -@@ -399,7 +399,7 @@ index_mail_cache_parse_init(struct mail *_mail, struct istream *input) - mail->data.parser_input = input; - mail->data.parser_ctx = - message_parser_init(mail->mail.data_pool, input, -- hdr_parser_flags, msg_parser_flags); -+ &msg_parser_set); - i_stream_unref(&input); - return input2; - } -@@ -428,14 +428,12 @@ static void index_mail_init_parser(struct index_mail *mail) - data->parser_input = data->stream; - data->parser_ctx = message_parser_init(mail->mail.data_pool, - data->stream, -- hdr_parser_flags, -- msg_parser_flags); -+ &msg_parser_set); - } else { - data->parser_ctx = - message_parser_init_from_parts(data->parts, - data->stream, -- hdr_parser_flags, -- msg_parser_flags); -+ &msg_parser_set); - } - } - -@@ -468,7 +466,7 @@ int index_mail_parse_headers(struct index_mail *mail, - i_assert(!data->save_bodystructure_body || - data->parser_ctx != NULL); - message_parse_header(data->stream, &data->hdr_size, -- hdr_parser_flags, -+ msg_parser_set.hdr_flags, - index_mail_parse_header_cb, mail); - } - if (index_mail_stream_check_failure(mail) < 0) -@@ -526,7 +524,7 @@ int index_mail_headers_get_envelope(struct index_mail *mail) - if (mail->data.envelope == NULL) { - /* we got the headers from cache - parse them to get the - envelope */ -- message_parse_header(stream, NULL, hdr_parser_flags, -+ message_parse_header(stream, NULL, msg_parser_set.hdr_flags, - imap_envelope_parse_callback, mail); - if (stream->stream_errno != 0) { - index_mail_stream_log_failure_for(mail, stream); -diff --git a/src/plugins/fts/fts-build-mail.c b/src/plugins/fts/fts-build-mail.c -index 3cb4ea657f..e088e7397b 100644 ---- a/src/plugins/fts/fts-build-mail.c -+++ b/src/plugins/fts/fts-build-mail.c -@@ -475,6 +475,9 @@ fts_build_mail_real(struct fts_backend_update_context *update_ctx, - const char **retriable_err_msg_r, - bool *may_need_retry_r) - { -+ const struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE, -+ }; - struct fts_mail_build_context ctx; - struct istream *input; - struct message_parser_ctx *parser; -@@ -503,9 +506,7 @@ fts_build_mail_real(struct fts_backend_update_context *update_ctx, - ctx.pending_input = buffer_create_dynamic(default_pool, 128); - - prev_part = NULL; -- parser = message_parser_init(pool_datastack_create(), input, -- MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE, -- 0); -+ parser = message_parser_init(pool_datastack_create(), input, &parser_set); - - decoder = message_decoder_init(update_ctx->normalizer, 0); - for (;;) { --- -2.11.0 - -From e6fe2ef5d5a8620308d42a7ed1b35e907c645f72 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 16:59:40 +0300 -Subject: [PATCH 14/15] lib-mail: message-parser - Support limiting max number - of nested MIME parts - -The default is to allow 100 nested MIME parts. When the limit is reached, -the innermost MIME part's body contains all the rest of the inner bodies -until a parent MIME part is reached. ---- - src/lib-mail/message-parser-private.h | 2 + - src/lib-mail/message-parser.c | 39 ++++++-- - src/lib-mail/message-parser.h | 6 ++ - src/lib-mail/test-message-parser.c | 163 ++++++++++++++++++++++++++++++++++ - 4 files changed, 203 insertions(+), 7 deletions(-) - -diff --git a/src/lib-mail/message-parser-private.h b/src/lib-mail/message-parser-private.h -index dbf8464cfb..4bb0c3dbfd 100644 ---- a/src/lib-mail/message-parser-private.h -+++ b/src/lib-mail/message-parser-private.h -@@ -23,9 +23,11 @@ struct message_parser_ctx { - struct istream *input; - struct message_part *parts, *part; - const char *broken_reason; -+ unsigned int nested_parts_count; - - enum message_header_parser_flags hdr_flags; - enum message_parser_flags flags; -+ unsigned int max_nested_mime_parts; - - char *last_boundary; - struct message_boundary *boundaries; -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index 41b9ed133a..ea0154d5ed 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -157,12 +157,17 @@ message_part_append(struct message_parser_ctx *ctx) - ctx->next_part = &part->children; - - ctx->part = part; -+ ctx->nested_parts_count++; -+ i_assert(ctx->nested_parts_count < ctx->max_nested_mime_parts); - } - - static void message_part_finish(struct message_parser_ctx *ctx) - { - struct message_part **const *parent_next_partp; - -+ i_assert(ctx->nested_parts_count > 0); -+ ctx->nested_parts_count--; -+ - parent_next_partp = array_back(&ctx->next_part_stack); - array_pop_back(&ctx->next_part_stack); - ctx->next_part = *parent_next_partp; -@@ -542,6 +547,11 @@ static bool block_is_at_eoh(const struct message_block *block) - return FALSE; - } - -+static bool parse_too_many_nested_mime_parts(struct message_parser_ctx *ctx) -+{ -+ return ctx->nested_parts_count+1 >= ctx->max_nested_mime_parts; -+} -+ - #define MUTEX_FLAGS \ - (MESSAGE_PART_FLAG_MESSAGE_RFC822 | MESSAGE_PART_FLAG_MULTIPART) - -@@ -566,8 +576,12 @@ static int parse_next_header(struct message_parser_ctx *ctx, - "\n--boundary" belongs to us or to a previous boundary. - this is a problem if the boundary prefixes are identical, - because MIME requires only the prefix to match. */ -- parse_next_body_multipart_init(ctx); -- ctx->multipart = TRUE; -+ if (!parse_too_many_nested_mime_parts(ctx)) { -+ parse_next_body_multipart_init(ctx); -+ ctx->multipart = TRUE; -+ } else { -+ part->flags &= ~MESSAGE_PART_FLAG_MULTIPART; -+ } - } - - /* before parsing the header see if we can find a --boundary from here. -@@ -671,12 +685,16 @@ static int parse_next_header(struct message_parser_ctx *ctx, - i_assert(ctx->last_boundary == NULL); - ctx->multipart = FALSE; - ctx->parse_next_block = parse_next_body_to_boundary; -- } else if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0) -+ } else if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0 && -+ !parse_too_many_nested_mime_parts(ctx)) { - ctx->parse_next_block = parse_next_body_message_rfc822_init; -- else if (ctx->boundaries != NULL) -- ctx->parse_next_block = parse_next_body_to_boundary; -- else -- ctx->parse_next_block = parse_next_body_to_eof; -+ } else { -+ part->flags &= ~MESSAGE_PART_FLAG_MESSAGE_RFC822; -+ if (ctx->boundaries != NULL) -+ ctx->parse_next_block = parse_next_body_to_boundary; -+ else -+ ctx->parse_next_block = parse_next_body_to_eof; -+ } - - ctx->want_count = 1; - -@@ -710,6 +728,9 @@ message_parser_init_int(struct istream *input, - ctx = i_new(struct message_parser_ctx, 1); - ctx->hdr_flags = set->hdr_flags; - ctx->flags = set->flags; -+ ctx->max_nested_mime_parts = set->max_nested_mime_parts != 0 ? -+ set->max_nested_mime_parts : -+ MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS; - ctx->input = input; - i_stream_ref(input); - return ctx; -@@ -754,6 +775,10 @@ int message_parser_deinit_from_parts(struct message_parser_ctx **_ctx, - if (ctx->hdr_parser_ctx != NULL) - message_parse_header_deinit(&ctx->hdr_parser_ctx); - boundary_remove_until(ctx, NULL); -+ /* caller might have stopped the parsing early */ -+ i_assert(ctx->nested_parts_count == 0 || -+ i_stream_have_bytes_left(ctx->input)); -+ - i_stream_unref(&ctx->input); - array_free(&ctx->next_part_stack); - i_free(ctx->last_boundary); -diff --git a/src/lib-mail/message-parser.h b/src/lib-mail/message-parser.h -index d159b2607d..7f6ea04936 100644 ---- a/src/lib-mail/message-parser.h -+++ b/src/lib-mail/message-parser.h -@@ -17,9 +17,15 @@ enum message_parser_flags { - MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES = 0x08 - }; - -+#define MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS 100 -+ - struct message_parser_settings { - enum message_header_parser_flags hdr_flags; - enum message_parser_flags flags; -+ -+ /* Maximum nested MIME parts. -+ 0 = MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS. */ -+ unsigned int max_nested_mime_parts; - }; - - struct message_parser_ctx; -diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c -index 5e496275fe..df2586eddd 100644 ---- a/src/lib-mail/test-message-parser.c -+++ b/src/lib-mail/test-message-parser.c -@@ -175,6 +175,36 @@ static void test_message_parser_small_blocks(void) - test_end(); - } - -+static void test_message_parser_stop_early(void) -+{ -+ struct message_parser_ctx *parser; -+ struct istream *input; -+ struct message_part *parts; -+ struct message_block block; -+ unsigned int i; -+ pool_t pool; -+ int ret; -+ -+ test_begin("message parser in stop early"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(test_msg); -+ -+ test_istream_set_allow_eof(input, FALSE); -+ for (i = 1; i <= TEST_MSG_LEN+1; i++) { -+ i_stream_seek(input, 0); -+ test_istream_set_size(input, i); -+ parser = message_parser_init(pool, input, &set_empty); -+ while ((ret = message_parser_parse_next_block(parser, -+ &block)) > 0) ; -+ test_assert(ret == 0); -+ message_parser_deinit(&parser, &parts); -+ } -+ -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ - static void test_message_parser_truncated_mime_headers(void) - { - static const char input_msg[] = -@@ -839,10 +869,141 @@ static const char input_msg[] = - test_end(); - } - -+static void test_message_parser_mime_part_nested_limit(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: text/plain\n" -+"\n" -+"1\n" -+"--2\n" -+"Content-Type: text/plain\n" -+"\n" -+"22\n" -+"--1\n" -+"Content-Type: text/plain\n" -+"\n" -+"333\n"; -+ const struct message_parser_settings parser_set = { -+ .max_nested_mime_parts = 2, -+ }; -+ 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 nested limit"); -+ 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 == 15); -+ test_assert(part->body_size.physical_size == 148); -+ test_assert(part->body_size.virtual_size == 148+15); -+ -+ part = parts->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 == 45); -+ test_assert(part->header_size.virtual_size == 45+2); -+ test_assert(part->body_size.lines == 7); -+ test_assert(part->body_size.physical_size == 64); -+ test_assert(part->body_size.virtual_size == 64+7); -+ -+ part = parts->children->next; -+ test_assert(part->children_count == 0); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 26); -+ test_assert(part->header_size.virtual_size == 26+2); -+ test_assert(part->body_size.lines == 1); -+ test_assert(part->body_size.physical_size == 4); -+ test_assert(part->body_size.virtual_size == 4+1); -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ -+static void test_message_parser_mime_part_nested_limit_rfc822(void) -+{ -+static const char input_msg[] = -+"Content-Type: message/rfc822\n" -+"\n" -+"Content-Type: message/rfc822\n" -+"\n" -+"Content-Type: text/plain\n" -+"\n" -+"1\n"; -+ const struct message_parser_settings parser_set = { -+ .max_nested_mime_parts = 2, -+ }; -+ 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 nested 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 == 1); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_MESSAGE_RFC822 | 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 == 5); -+ test_assert(part->body_size.physical_size == 58); -+ test_assert(part->body_size.virtual_size == 58+5); -+ -+ part = parts->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 == 3); -+ test_assert(part->body_size.physical_size == 28); -+ test_assert(part->body_size.virtual_size == 28+3); -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ - int main(void) - { - static void (*const test_functions[])(void) = { - test_message_parser_small_blocks, -+ test_message_parser_stop_early, - test_message_parser_truncated_mime_headers, - test_message_parser_truncated_mime_headers2, - test_message_parser_truncated_mime_headers3, -@@ -854,6 +1015,8 @@ int main(void) - test_message_parser_continuing_mime_boundary_reverse, - test_message_parser_long_mime_boundary, - test_message_parser_no_eoh, -+ test_message_parser_mime_part_nested_limit, -+ test_message_parser_mime_part_nested_limit_rfc822, - NULL - }; - return test_run(test_functions); --- -2.11.0 - -From 39e1ba38c2b3a5e3e567a35b7f6c414c7ed43769 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 Apr 2020 17:09:33 +0300 -Subject: [PATCH 15/15] lib-mail: message-parser - Support limiting max number - of MIME parts - -The default is to allow 10000 MIME parts. When it's reached, no more -MIME boundary lines will be recognized, so the rest of the mail belongs -to the last added MIME part. ---- - src/lib-mail/message-parser-private.h | 2 + - src/lib-mail/message-parser.c | 12 +++++ - src/lib-mail/message-parser.h | 4 ++ - src/lib-mail/test-message-parser.c | 86 +++++++++++++++++++++++++++++++++++ - 4 files changed, 104 insertions(+) - -diff --git a/src/lib-mail/message-parser-private.h b/src/lib-mail/message-parser-private.h -index 4bb0c3dbfd..1f9c66b827 100644 ---- a/src/lib-mail/message-parser-private.h -+++ b/src/lib-mail/message-parser-private.h -@@ -24,10 +24,12 @@ struct message_parser_ctx { - struct message_part *parts, *part; - const char *broken_reason; - unsigned int nested_parts_count; -+ unsigned int total_parts_count; - - enum message_header_parser_flags hdr_flags; - enum message_parser_flags flags; - unsigned int max_nested_mime_parts; -+ unsigned int max_total_mime_parts; - - char *last_boundary; - struct message_boundary *boundaries; -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index ea0154d5ed..6370a1bff7 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -158,7 +158,9 @@ message_part_append(struct message_parser_ctx *ctx) - - ctx->part = part; - ctx->nested_parts_count++; -+ ctx->total_parts_count++; - i_assert(ctx->nested_parts_count < ctx->max_nested_mime_parts); -+ i_assert(ctx->total_parts_count <= ctx->max_total_mime_parts); - } - - static void message_part_finish(struct message_parser_ctx *ctx) -@@ -241,6 +243,12 @@ boundary_line_find(struct message_parser_ctx *ctx, - return -1; - } - -+ if (ctx->total_parts_count >= ctx->max_total_mime_parts) { -+ /* can't add any more MIME parts. just stop trying to find -+ more boundaries. */ -+ return -1; -+ } -+ - /* need to find the end of line */ - data += 2; - size -= 2; -@@ -731,6 +739,9 @@ message_parser_init_int(struct istream *input, - ctx->max_nested_mime_parts = set->max_nested_mime_parts != 0 ? - set->max_nested_mime_parts : - MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS; -+ ctx->max_total_mime_parts = set->max_total_mime_parts != 0 ? -+ set->max_total_mime_parts : -+ MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS; - ctx->input = input; - i_stream_ref(input); - return ctx; -@@ -747,6 +758,7 @@ message_parser_init(pool_t part_pool, struct istream *input, - ctx->parts = ctx->part = p_new(part_pool, struct message_part, 1); - ctx->next_part = &ctx->part->children; - ctx->parse_next_block = parse_next_header_init; -+ ctx->total_parts_count = 1; - i_array_init(&ctx->next_part_stack, 4); - return ctx; - } -diff --git a/src/lib-mail/message-parser.h b/src/lib-mail/message-parser.h -index 7f6ea04936..f19e526284 100644 ---- a/src/lib-mail/message-parser.h -+++ b/src/lib-mail/message-parser.h -@@ -18,6 +18,7 @@ enum message_parser_flags { - }; - - #define MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS 100 -+#define MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS 10000 - - struct message_parser_settings { - enum message_header_parser_flags hdr_flags; -@@ -26,6 +27,9 @@ struct message_parser_settings { - /* Maximum nested MIME parts. - 0 = MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS. */ - unsigned int max_nested_mime_parts; -+ /* Maximum MIME parts in total. -+ 0 = MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS. */ -+ unsigned int max_total_mime_parts; - }; - - struct message_parser_ctx; -diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c -index df2586eddd..0422b42265 100644 ---- a/src/lib-mail/test-message-parser.c -+++ b/src/lib-mail/test-message-parser.c -@@ -999,6 +999,91 @@ static const char input_msg[] = - test_end(); - } - -+static void test_message_parser_mime_part_limit(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: text/plain\n" -+"\n" -+"1\n" -+"--2\n" -+"Content-Type: text/plain\n" -+"\n" -+"22\n" -+"--1\n" -+"Content-Type: text/plain\n" -+"\n" -+"333\n"; -+ const struct message_parser_settings parser_set = { -+ .max_total_mime_parts = 4, -+ }; -+ 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"); -+ 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 == 3); -+ 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 == 15); -+ test_assert(part->body_size.physical_size == 148); -+ test_assert(part->body_size.virtual_size == 148+15); -+ -+ part = parts->children; -+ 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 == 12); -+ test_assert(part->body_size.physical_size == 99); -+ test_assert(part->body_size.virtual_size == 99+12); -+ -+ part = parts->children->children; -+ test_assert(part->children_count == 0); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 26); -+ test_assert(part->header_size.virtual_size == 26+2); -+ test_assert(part->body_size.lines == 0); -+ test_assert(part->body_size.physical_size == 1); -+ test_assert(part->body_size.virtual_size == 1); -+ -+ part = parts->children->children->next; -+ test_assert(part->children_count == 0); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 26); -+ test_assert(part->header_size.virtual_size == 26+2); -+ test_assert(part->body_size.lines == 5); -+ test_assert(part->body_size.physical_size == 37); -+ test_assert(part->body_size.virtual_size == 37+5); -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ - int main(void) - { - static void (*const test_functions[])(void) = { -@@ -1017,6 +1102,7 @@ int main(void) - test_message_parser_no_eoh, - test_message_parser_mime_part_nested_limit, - test_message_parser_mime_part_nested_limit_rfc822, -+ test_message_parser_mime_part_limit, - NULL - }; - return test_run(test_functions); --- -2.11.0 - -From 6001e4b48c5a23735eb9c4ca9a187a175fd1a1da Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 2 Jul 2020 17:31:19 +0300 -Subject: [PATCH] lib-mail: Fix handling trailing "--" in MIME boundaries - -Broken by 5b8ec27fae941d06516c30476dcf4820c6d200ab ---- - src/lib-mail/message-parser.c | 14 ++++++++---- - src/lib-mail/test-message-parser.c | 46 ++++++++++++++++++++++++++++++++++++++ - 2 files changed, 56 insertions(+), 4 deletions(-) - -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index 6370a1bff7..011dea9050 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -19,7 +19,7 @@ static int parse_next_body_to_eof(struct message_parser_ctx *ctx, - - static struct message_boundary * - boundary_find(struct message_boundary *boundaries, -- const unsigned char *data, size_t len) -+ const unsigned char *data, size_t len, bool trailing_dashes) - { - struct message_boundary *best = NULL; - -@@ -33,7 +33,11 @@ boundary_find(struct message_boundary *boundaries, - memcmp(boundaries->boundary, data, boundaries->len) == 0 && - (best == NULL || best->len < boundaries->len)) { - best = boundaries; -- if (best->len == len) { -+ /* If we see "foo--", it could either mean that there -+ is a boundary named "foo" that ends now or there's -+ a boundary "foo--" which continues. */ -+ if (best->len == len || -+ (best->len == len-2 && trailing_dashes)) { - /* This is exactly the wanted boundary. There - can't be a better one. */ - break; -@@ -261,6 +265,7 @@ boundary_line_find(struct message_parser_ctx *ctx, - return 0; - } - size_t find_size = size; -+ bool trailing_dashes = FALSE; - - if (lf_pos != NULL) { - find_size = lf_pos - data; -@@ -268,11 +273,12 @@ boundary_line_find(struct message_parser_ctx *ctx, - find_size--; - if (find_size > 2 && data[find_size-1] == '-' && - data[find_size-2] == '-') -- find_size -= 2; -+ trailing_dashes = TRUE; - } else if (find_size > BOUNDARY_END_MAX_LEN) - find_size = BOUNDARY_END_MAX_LEN; - -- *boundary_r = boundary_find(ctx->boundaries, data, find_size); -+ *boundary_r = boundary_find(ctx->boundaries, data, find_size, -+ trailing_dashes); - if (*boundary_r == NULL) - return -1; - -diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c -index 1b782f5df2..641edec4be 100644 ---- a/src/lib-mail/test-message-parser.c -+++ b/src/lib-mail/test-message-parser.c -@@ -532,6 +532,51 @@ static const char input_msg[] = - test_end(); - } - -+static void test_message_parser_trailing_dashes(void) -+{ -+static const char input_msg[] = -+"Content-Type: multipart/mixed; boundary=\"a--\"\n" -+"\n" -+"--a--\n" -+"Content-Type: multipart/mixed; boundary=\"a----\"\n" -+"\n" -+"--a----\n" -+"Content-Type: text/plain\n" -+"\n" -+"body\n" -+"--a------\n" -+"Content-Type: text/html\n" -+"\n" -+"body2\n" -+"--a----"; -+ struct message_parser_ctx *parser; -+ struct istream *input; -+ struct message_part *parts; -+ struct message_block block; -+ pool_t pool; -+ int ret; -+ -+ test_begin("message parser trailing dashes"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(input_msg); -+ -+ parser = message_parser_init(pool, input, &set_empty); -+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; -+ test_assert(ret < 0); -+ message_parser_deinit(&parser, &parts); -+ -+ test_assert(parts->children_count == 2); -+ test_assert(parts->children->next == NULL); -+ test_assert(parts->children->children_count == 1); -+ test_assert(parts->children->children->next == NULL); -+ test_assert(parts->children->children->children_count == 0); -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ - static void test_message_parser_continuing_mime_boundary(void) - { - static const char input_msg[] = -@@ -1095,6 +1140,7 @@ int main(void) - test_message_parser_empty_multipart, - test_message_parser_duplicate_mime_boundary, - test_message_parser_garbage_suffix_mime_boundary, -+ test_message_parser_trailing_dashes, - test_message_parser_continuing_mime_boundary, - test_message_parser_continuing_truncated_mime_boundary, - test_message_parser_continuing_mime_boundary_reverse, --- -2.11.0 - diff --git a/CVE-2020-12100-2.patch b/CVE-2020-12100-2.patch deleted file mode 100644 index 4abca048ab92d7d41f7809adf495599744328855..0000000000000000000000000000000000000000 --- a/CVE-2020-12100-2.patch +++ /dev/null @@ -1,70 +0,0 @@ -From f691580f7450b41bb3de36d825fc46fa5071cabf Mon Sep 17 00:00:00 2001 -Date: Mon, 26 Oct 2020 18:52:57 +0800 -Subject: [PATCH] fix CVE-2020-12100 - ---- - .../src/lib-sieve/plugins/notify/ext-notify-common.c | 3 ++- - .../src/lib-sieve/sieve-message.c | 12 ++++++------ - 2 files changed, 8 insertions(+), 7 deletions(-) - -diff --git a/dovecot-2.3-pigeonhole-0.5.10/src/lib-sieve/plugins/notify/ext-notify-common.c b/dovecot-2.3-pigeonhole-0.5.10/src/lib-sieve/plugins/notify/ext-notify-common.c -index 700b79d..9d950f3 100644 ---- a/dovecot-2.3-pigeonhole-0.5.10/src/lib-sieve/plugins/notify/ext-notify-common.c -+++ b/dovecot-2.3-pigeonhole-0.5.10/src/lib-sieve/plugins/notify/ext-notify-common.c -@@ -156,6 +156,7 @@ cmd_notify_extract_body_text(const struct sieve_runtime_env *renv, - { - const struct sieve_execute_env *eenv = renv->exec_env; - const struct sieve_extension *this_ext = renv->oprtn->ext; -+ const struct message_parser_settings parser_set = { .flags = 0 }; - struct ext_notify_message_context *mctx; - struct mail *mail = eenv->msgdata->mail; - struct message_parser_ctx *parser; -@@ -189,7 +190,7 @@ cmd_notify_extract_body_text(const struct sieve_runtime_env *renv, - /* Initialize body decoder */ - decoder = message_decoder_init(NULL, 0); - -- parser = message_parser_init(mctx->pool, input, 0, 0); -+ parser = message_parser_init(mctx->pool, input, &parser_set); - is_text = TRUE; - save_body = FALSE; - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) { -diff --git a/dovecot-2.3-pigeonhole-0.5.10/src/lib-sieve/sieve-message.c b/dovecot-2.3-pigeonhole-0.5.10/src/lib-sieve/sieve-message.c -index afbf31f..c791758 100644 ---- a/dovecot-2.3-pigeonhole-0.5.10/src/lib-sieve/sieve-message.c -+++ b/dovecot-2.3-pigeonhole-0.5.10/src/lib-sieve/sieve-message.c -@@ -1081,10 +1081,10 @@ static int sieve_message_parts_add_missing - struct sieve_message_context *msgctx = renv->msgctx; - pool_t pool = msgctx->context_pool; - struct mail *mail = sieve_message_get_mail(renv->msgctx); -- enum message_parser_flags mparser_flags = -- MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS; -- enum message_header_parser_flags hparser_flags = -- MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP; -+ struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP, -+ .flags = MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS, -+ }; - ARRAY(struct sieve_message_header) headers; - struct sieve_message_part *body_part, *header_part, *last_part; - struct message_parser_ctx *parser; -@@ -1121,7 +1121,7 @@ static int sieve_message_parts_add_missing - if (iter_all) { - t_array_init(&headers, 64); - hdr_content = t_str_new(512); -- hparser_flags |= MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE; -+ parser_set.hdr_flags |= MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE; - } else { - i_zero(&headers); - } -@@ -1133,7 +1133,7 @@ static int sieve_message_parts_add_missing - //parser = message_parser_init_from_parts(parts, input, - // hparser_flags, mparser_flags); - parser = message_parser_init(pool_datastack_create(), -- input, hparser_flags, mparser_flags); -+ input, &parser_set); - while ( (ret=message_parser_parse_next_block - (parser, &block)) > 0 ) { - struct sieve_message_part **body_part_idx; --- -2.23.0 - diff --git a/CVE-2020-12673.patch b/CVE-2020-12673.patch deleted file mode 100644 index 9dd26e0350f830d076ec205c3db910545a8064af..0000000000000000000000000000000000000000 --- a/CVE-2020-12673.patch +++ /dev/null @@ -1,31 +0,0 @@ -From fb246611e62ad8c5a95b0ca180a63f17aa34b0d8 Mon Sep 17 00:00:00 2001 -From: Aki Tuomi -Date: Mon, 18 May 2020 12:33:39 +0300 -Subject: [PATCH] lib-ntlm: Check buffer length on responses - -Add missing check for buffer length. - -If this is not checked, it is possible to send message which -causes read past buffer bug. - -Broken in c7480644202e5451fbed448508ea29a25cffc99c ---- - src/lib-ntlm/ntlm-message.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/lib-ntlm/ntlm-message.c b/src/lib-ntlm/ntlm-message.c -index 160b9f918c..a29413b47e 100644 ---- a/src/lib-ntlm/ntlm-message.c -+++ b/src/lib-ntlm/ntlm-message.c -@@ -184,6 +184,11 @@ static bool ntlmssp_check_buffer(const struct ntlmssp_buffer *buffer, - if (length == 0 && space == 0) - return TRUE; - -+ if (length > data_size) { -+ *error = "buffer length out of bounds"; -+ return FALSE; -+ } -+ - if (offset >= data_size) { - *error = "buffer offset out of bounds"; - return FALSE; diff --git a/CVE-2020-12674.patch b/CVE-2020-12674.patch deleted file mode 100644 index a9dca2a82dd1e176363418972a0cf1a712792cc8..0000000000000000000000000000000000000000 --- a/CVE-2020-12674.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 69ad3c902ea4bbf9f21ab1857d8923f975dc6145 Mon Sep 17 00:00:00 2001 -From: Aki Tuomi -Date: Wed, 6 May 2020 13:40:36 +0300 -Subject: [PATCH] auth: mech-rpa - Fail on zero len buffer - ---- - src/auth/mech-rpa.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/auth/mech-rpa.c b/src/auth/mech-rpa.c -index 08298ebdd6..2de8705b4f 100644 ---- a/src/auth/mech-rpa.c -+++ b/src/auth/mech-rpa.c -@@ -224,7 +224,7 @@ rpa_read_buffer(pool_t pool, const unsigned char **data, - return 0; - - len = *p++; -- if (p + len > end) -+ if (p + len > end || len == 0) - return 0; - - *buffer = p_malloc(pool, len); diff --git a/CVE-2020-24386.patch b/CVE-2020-24386.patch deleted file mode 100644 index a59ad9783450ad5711cdd878063a6b49f2a1210b..0000000000000000000000000000000000000000 --- a/CVE-2020-24386.patch +++ /dev/null @@ -1,55 +0,0 @@ -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 deleted file mode 100644 index 1953372171fd0a9f10550ccba0eb165176bf19ce..0000000000000000000000000000000000000000 --- a/CVE-2020-25275-1.patch +++ /dev/null @@ -1,63 +0,0 @@ -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 deleted file mode 100644 index 9c3c7400e320bd488201346f2c83dc71a5350fa8..0000000000000000000000000000000000000000 --- a/CVE-2020-25275-2.patch +++ /dev/null @@ -1,129 +0,0 @@ -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-2.1.10-waitonline.patch b/dovecot-2.1.10-waitonline.patch index 2b1cd420d13a7d48bdb527f40687d8be1661a94a..af3ce190979b60636192c03ced965d74a1f9af19 100644 --- a/dovecot-2.1.10-waitonline.patch +++ b/dovecot-2.1.10-waitonline.patch @@ -1,11 +1,11 @@ -diff -up dovecot-2.3.0.1/dovecot.service.in.waitonline dovecot-2.3.0.1/dovecot.service.in ---- dovecot-2.3.0.1/dovecot.service.in.waitonline 2018-03-01 10:35:39.888371078 +0100 -+++ dovecot-2.3.0.1/dovecot.service.in 2018-03-01 10:36:29.738784661 +0100 -@@ -12,6 +12,7 @@ After=local-fs.target network-online.tar +diff -up dovecot-2.3.15/dovecot.service.in.waitonline dovecot-2.3.15/dovecot.service.in +--- dovecot-2.3.15/dovecot.service.in.waitonline 2021-06-21 20:19:19.560494654 +0200 ++++ dovecot-2.3.15/dovecot.service.in 2021-06-21 20:21:17.443066248 +0200 +@@ -15,6 +15,7 @@ After=local-fs.target network-online.tar [Service] - Type=simple + Type=@systemdservicetype@ +ExecStartPre=/usr/libexec/dovecot/prestartscript ExecStart=@sbindir@/dovecot -F - PIDFile=@rundir@/master.pid ExecReload=@bindir@/doveadm reload + ExecStop=@bindir@/doveadm stop diff --git a/dovecot-2.2.20-initbysystemd.patch b/dovecot-2.2.20-initbysystemd.patch index 7e3d94ca0d34f3f8e7b5fa7ff628d1999466dffb..313e26be7b5d3290f355cfcc14d6887f251a0d0f 100644 --- a/dovecot-2.2.20-initbysystemd.patch +++ b/dovecot-2.2.20-initbysystemd.patch @@ -1,6 +1,6 @@ -diff -up dovecot-2.3.0.1/dovecot-init.service.initbysystemd dovecot-2.3.0.1/dovecot-init.service ---- dovecot-2.3.0.1/dovecot-init.service.initbysystemd 2018-03-01 10:38:22.059716008 +0100 -+++ dovecot-2.3.0.1/dovecot-init.service 2018-03-01 10:38:22.059716008 +0100 +diff -up dovecot-2.3.15/dovecot-init.service.initbysystemd dovecot-2.3.15/dovecot-init.service +--- dovecot-2.3.15/dovecot-init.service.initbysystemd 2021-06-21 20:21:49.250680889 +0200 ++++ dovecot-2.3.15/dovecot-init.service 2021-06-21 20:21:49.250680889 +0200 @@ -0,0 +1,13 @@ +[Unit] +Description=One-time Dovecot init service @@ -15,32 +15,37 @@ diff -up dovecot-2.3.0.1/dovecot-init.service.initbysystemd dovecot-2.3.0.1/dove + SSLDIR=/etc/pki/dovecot/ OPENSSLCONFIG=/etc/pki/dovecot/dovecot-openssl.cnf /usr/libexec/dovecot/mkcert.sh /dev/null 2>&1;\ +fi' + -diff -up dovecot-2.3.0.1/dovecot.service.in.initbysystemd dovecot-2.3.0.1/dovecot.service.in ---- dovecot-2.3.0.1/dovecot.service.in.initbysystemd 2018-03-01 10:38:22.060716016 +0100 -+++ dovecot-2.3.0.1/dovecot.service.in 2018-03-01 10:40:45.524901319 +0100 -@@ -8,7 +8,8 @@ +diff -up dovecot-2.3.15/dovecot.service.in.initbysystemd dovecot-2.3.15/dovecot.service.in +--- dovecot-2.3.15/dovecot.service.in.initbysystemd 2021-06-21 20:21:49.250680889 +0200 ++++ dovecot-2.3.15/dovecot.service.in 2021-06-21 20:22:46.935981920 +0200 +@@ -11,7 +11,8 @@ Description=Dovecot IMAP/POP3 email server Documentation=man:dovecot(1) - Documentation=http://wiki2.dovecot.org/ + Documentation=https://doc.dovecot.org/ -After=local-fs.target network-online.target +After=local-fs.target network-online.target dovecot-init.service +Requires=dovecot-init.service [Service] - Type=simple -diff -up dovecot-2.3.0.1/Makefile.am.initbysystemd dovecot-2.3.0.1/Makefile.am ---- dovecot-2.3.0.1/Makefile.am.initbysystemd 2018-02-28 15:28:57.000000000 +0100 -+++ dovecot-2.3.0.1/Makefile.am 2018-03-01 10:38:22.060716016 +0100 -@@ -63,9 +63,10 @@ if HAVE_SYSTEMD + Type=@systemdservicetype@ +diff -up dovecot-2.3.15/Makefile.am.initbysystemd dovecot-2.3.15/Makefile.am +--- dovecot-2.3.15/Makefile.am.initbysystemd 2021-06-21 20:21:49.250680889 +0200 ++++ dovecot-2.3.15/Makefile.am 2021-06-21 20:24:26.676765849 +0200 +@@ -21,6 +21,7 @@ EXTRA_DIST = \ + run-test-valgrind.supp \ + dovecot.service.in \ + dovecot.socket \ ++ dovecot-init.service \ + $(conf_DATA) + noinst_DATA = dovecot-config +@@ -69,7 +70,8 @@ dovecot-config: dovecot-config.in Makefi + if WANT_SYSTEMD systemdsystemunit_DATA = \ dovecot.socket \ - dovecot.service + dovecot.service \ + dovecot-init.service - else --EXTRA_DIST += dovecot.socket dovecot.service.in -+EXTRA_DIST += dovecot.socket dovecot.service.in dovecot-init.service endif install-exec-hook: diff --git a/dovecot-2.3-pigeonhole-0.5.10.tar.gz b/dovecot-2.3-pigeonhole-0.5.10.tar.gz deleted file mode 100644 index 51dbfc936e6258875ceed311d297e55b03336cae..0000000000000000000000000000000000000000 Binary files a/dovecot-2.3-pigeonhole-0.5.10.tar.gz and /dev/null differ diff --git a/dovecot-2.3-pigeonhole-0.5.15.tar.gz b/dovecot-2.3-pigeonhole-0.5.15.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..89207b2f82e2a766f56bf478b37c62f251854385 Binary files /dev/null and b/dovecot-2.3-pigeonhole-0.5.15.tar.gz differ diff --git a/dovecot-2.3.11-bigkey.patch b/dovecot-2.3.11-bigkey.patch new file mode 100644 index 0000000000000000000000000000000000000000..dc81a33c740cacf118c7ea3e4de57dda21e9421f --- /dev/null +++ b/dovecot-2.3.11-bigkey.patch @@ -0,0 +1,10 @@ +diff -up dovecot-2.3.15/doc/dovecot-openssl.cnf.bigkey dovecot-2.3.15/doc/dovecot-openssl.cnf +--- dovecot-2.3.15/doc/dovecot-openssl.cnf.bigkey 2021-06-21 20:24:51.913456628 +0200 ++++ dovecot-2.3.15/doc/dovecot-openssl.cnf 2021-06-21 20:25:36.352912123 +0200 +@@ -1,5 +1,5 @@ + [ req ] +-default_bits = 2048 ++default_bits = 3072 + encrypt_key = yes + distinguished_name = req_dn + x509_extensions = cert_type diff --git a/dovecot-2.3.15-fixvalcond.patch b/dovecot-2.3.15-fixvalcond.patch new file mode 100644 index 0000000000000000000000000000000000000000..6262271ce4a1c8bee9324b69d86c895991b5a91b --- /dev/null +++ b/dovecot-2.3.15-fixvalcond.patch @@ -0,0 +1,24 @@ +diff -up dovecot-2.3.15/dovecot-2.3-pigeonhole-0.5.15/src/lib-sieve/storage/dict/sieve-dict-script.c.fixvalcond dovecot-2.3.15/dovecot-2.3-pigeonhole-0.5.15/src/lib-sieve/storage/dict/sieve-dict-script.c +--- dovecot-2.3.15/dovecot-2.3-pigeonhole-0.5.15/src/lib-sieve/storage/dict/sieve-dict-script.c.fixvalcond 2021-06-21 23:07:55.269814896 +0200 ++++ dovecot-2.3.15/dovecot-2.3-pigeonhole-0.5.15/src/lib-sieve/storage/dict/sieve-dict-script.c 2021-06-21 23:07:55.298814544 +0200 +@@ -109,7 +109,7 @@ static int sieve_dict_script_get_stream + { + struct sieve_dict_script *dscript = + (struct sieve_dict_script *)script; +- const char *path, *name = script->name, *data, *error; ++ const char *path, *name = script->name, *data, *error = NULL; + int ret; + + dscript->data_pool = +diff -up dovecot-2.3.15/src/lib-storage/index/index-attribute.c.fixvalcond dovecot-2.3.15/src/lib-storage/index/index-attribute.c +--- dovecot-2.3.15/src/lib-storage/index/index-attribute.c.fixvalcond 2021-06-14 15:40:37.000000000 +0200 ++++ dovecot-2.3.15/src/lib-storage/index/index-attribute.c 2021-06-21 21:52:22.963171229 +0200 +@@ -249,7 +249,7 @@ int index_storage_attribute_get(struct m + struct mail_attribute_value *value_r) + { + struct dict *dict; +- const char *mailbox_prefix, *error; ++ const char *mailbox_prefix, *error = NULL; + int ret; + + i_zero(value_r); diff --git a/dovecot-2.3.15-valbasherr.patch b/dovecot-2.3.15-valbasherr.patch new file mode 100644 index 0000000000000000000000000000000000000000..bbcb86f034bb87b13063e0dbfba303bde838689c --- /dev/null +++ b/dovecot-2.3.15-valbasherr.patch @@ -0,0 +1,20 @@ +diff -up dovecot-2.3.15/run-test-valgrind.supp.valbasherr dovecot-2.3.15/run-test-valgrind.supp +--- dovecot-2.3.15/run-test-valgrind.supp.valbasherr 2021-06-21 22:52:53.272707239 +0200 ++++ dovecot-2.3.15/run-test-valgrind.supp 2021-06-21 22:54:19.786668430 +0200 +@@ -1,4 +1,16 @@ + { ++ ++ Memcheck:Leak ++ match-leak-kinds: definite ++ fun:malloc ++ fun:make_if_command ++ fun:yyparse ++ fun:parse_command ++ fun:read_command ++ fun:reader_loop ++ fun:main ++} ++{ + + Memcheck:Leak + fun:malloc diff --git a/dovecot-2.3.10.1.tar.gz b/dovecot-2.3.15.tar.gz similarity index 48% rename from dovecot-2.3.10.1.tar.gz rename to dovecot-2.3.15.tar.gz index 189c7fa43b90af869db2cac1d53707ab444ff3bd..28bcf0c7353d632e851c3730c96fea7cbf0a47ad 100644 Binary files a/dovecot-2.3.10.1.tar.gz and b/dovecot-2.3.15.tar.gz differ diff --git a/dovecot-2.3.6-opensslhmac.patch b/dovecot-2.3.6-opensslhmac.patch new file mode 100644 index 0000000000000000000000000000000000000000..ba6453be926795553187d51e4a7e04647a763405 --- /dev/null +++ b/dovecot-2.3.6-opensslhmac.patch @@ -0,0 +1,813 @@ +diff -up dovecot-2.3.14/src/auth/auth-token.c.opensslhmac dovecot-2.3.14/src/auth/auth-token.c +--- dovecot-2.3.14/src/auth/auth-token.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/auth/auth-token.c 2021-03-22 20:44:13.022912242 +0100 +@@ -161,17 +161,17 @@ void auth_token_deinit(void) + const char *auth_token_get(const char *service, const char *session_pid, + const char *username, const char *session_id) + { +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + unsigned char result[SHA1_RESULTLEN]; + +- hmac_init(&ctx, (const unsigned char*)username, strlen(username), ++ openssl_hmac_init(&ctx, (const unsigned char*)username, strlen(username), + &hash_method_sha1); +- hmac_update(&ctx, session_pid, strlen(session_pid)); ++ openssl_hmac_update(&ctx, session_pid, strlen(session_pid)); + if (session_id != NULL && *session_id != '\0') +- hmac_update(&ctx, session_id, strlen(session_id)); +- hmac_update(&ctx, service, strlen(service)); +- hmac_update(&ctx, auth_token_secret, sizeof(auth_token_secret)); +- hmac_final(&ctx, result); ++ openssl_hmac_update(&ctx, session_id, strlen(session_id)); ++ openssl_hmac_update(&ctx, service, strlen(service)); ++ openssl_hmac_update(&ctx, auth_token_secret, sizeof(auth_token_secret)); ++ openssl_hmac_final(&ctx, result); + + return binary_to_hex(result, sizeof(result)); + } +diff -up dovecot-2.3.14/src/auth/mech-cram-md5.c.opensslhmac dovecot-2.3.14/src/auth/mech-cram-md5.c +--- dovecot-2.3.14/src/auth/mech-cram-md5.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/auth/mech-cram-md5.c 2021-03-22 20:44:13.022912242 +0100 +@@ -51,7 +51,7 @@ static bool verify_credentials(struct cr + { + + unsigned char digest[MD5_RESULTLEN]; +- struct hmac_context ctx; ++ struct orig_hmac_context ctx; + const char *response_hex; + + if (size != CRAM_MD5_CONTEXTLEN) { +@@ -60,10 +60,10 @@ static bool verify_credentials(struct cr + return FALSE; + } + +- hmac_init(&ctx, NULL, 0, &hash_method_md5); ++ orig_hmac_init(&ctx, NULL, 0, &hash_method_md5); + hmac_md5_set_cram_context(&ctx, credentials); +- hmac_update(&ctx, request->challenge, strlen(request->challenge)); +- hmac_final(&ctx, digest); ++ orig_hmac_update(&ctx, request->challenge, strlen(request->challenge)); ++ orig_hmac_final(&ctx, digest); + + response_hex = binary_to_hex(digest, sizeof(digest)); + +diff -up dovecot-2.3.14/src/auth/mech-scram.c.opensslhmac dovecot-2.3.14/src/auth/mech-scram.c +--- dovecot-2.3.14/src/auth/mech-scram.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/auth/mech-scram.c 2021-03-22 20:44:13.022912242 +0100 +@@ -78,7 +78,7 @@ static const char *get_scram_server_firs + static const char *get_scram_server_final(struct scram_auth_request *request) + { + const struct hash_method *hmethod = request->hash_method; +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + const char *auth_message; + unsigned char server_signature[hmethod->digest_size]; + string_t *str; +@@ -87,9 +87,9 @@ static const char *get_scram_server_fina + request->server_first_message, ",", + request->client_final_message_without_proof, NULL); + +- hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod); +- hmac_update(&ctx, auth_message, strlen(auth_message)); +- hmac_final(&ctx, server_signature); ++ openssl_hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod); ++ openssl_hmac_update(&ctx, auth_message, strlen(auth_message)); ++ openssl_hmac_final(&ctx, server_signature); + + str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(server_signature))); + str_append(str, "v="); +@@ -228,7 +228,7 @@ static bool parse_scram_client_first(str + static bool verify_credentials(struct scram_auth_request *request) + { + const struct hash_method *hmethod = request->hash_method; +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + const char *auth_message; + unsigned char client_key[hmethod->digest_size]; + unsigned char client_signature[hmethod->digest_size]; +@@ -239,9 +239,9 @@ static bool verify_credentials(struct sc + request->server_first_message, ",", + request->client_final_message_without_proof, NULL); + +- hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod); +- hmac_update(&ctx, auth_message, strlen(auth_message)); +- hmac_final(&ctx, client_signature); ++ openssl_hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod); ++ openssl_hmac_update(&ctx, auth_message, strlen(auth_message)); ++ openssl_hmac_final(&ctx, client_signature); + + const unsigned char *proof_data = request->proof->data; + for (i = 0; i < sizeof(client_signature); i++) +diff -up dovecot-2.3.14/src/auth/password-scheme.c.opensslhmac dovecot-2.3.14/src/auth/password-scheme.c +--- dovecot-2.3.14/src/auth/password-scheme.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/auth/password-scheme.c 2021-03-22 20:44:13.022912242 +0100 +@@ -639,11 +639,11 @@ static void + cram_md5_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED, + const unsigned char **raw_password_r, size_t *size_r) + { +- struct hmac_context ctx; ++ struct orig_hmac_context ctx; + unsigned char *context_digest; + + context_digest = t_malloc_no0(CRAM_MD5_CONTEXTLEN); +- hmac_init(&ctx, (const unsigned char *)plaintext, ++ orig_hmac_init(&ctx, (const unsigned char *)plaintext, + strlen(plaintext), &hash_method_md5); + hmac_md5_get_cram_context(&ctx, context_digest); + +diff -up dovecot-2.3.14/src/auth/password-scheme-scram.c.opensslhmac dovecot-2.3.14/src/auth/password-scheme-scram.c +--- dovecot-2.3.14/src/auth/password-scheme-scram.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/auth/password-scheme-scram.c 2021-03-22 20:44:13.023912229 +0100 +@@ -30,23 +30,23 @@ Hi(const struct hash_method *hmethod, co + const unsigned char *salt, size_t salt_size, unsigned int i, + unsigned char *result) + { +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + unsigned char U[hmethod->digest_size]; + unsigned int j, k; + + /* Calculate U1 */ +- hmac_init(&ctx, str, str_size, hmethod); +- hmac_update(&ctx, salt, salt_size); +- hmac_update(&ctx, "\0\0\0\1", 4); +- hmac_final(&ctx, U); ++ openssl_hmac_init(&ctx, str, str_size, hmethod); ++ openssl_hmac_update(&ctx, salt, salt_size); ++ openssl_hmac_update(&ctx, "\0\0\0\1", 4); ++ openssl_hmac_final(&ctx, U); + + memcpy(result, U, hmethod->digest_size); + + /* Calculate U2 to Ui and Hi */ + for (j = 2; j <= i; j++) { +- hmac_init(&ctx, str, str_size, hmethod); +- hmac_update(&ctx, U, sizeof(U)); +- hmac_final(&ctx, U); ++ openssl_hmac_init(&ctx, str, str_size, hmethod); ++ openssl_hmac_update(&ctx, U, sizeof(U)); ++ openssl_hmac_final(&ctx, U); + for (k = 0; k < hmethod->digest_size; k++) + result[k] ^= U[k]; + } +@@ -102,7 +102,7 @@ int scram_verify(const struct hash_metho + const char *plaintext, const unsigned char *raw_password, + size_t size, const char **error_r) + { +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + const char *salt_base64; + unsigned int iter_count; + const unsigned char *salt; +@@ -126,9 +126,9 @@ int scram_verify(const struct hash_metho + salt, salt_len, iter_count, salted_password); + + /* Calculate ClientKey */ +- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); +- hmac_update(&ctx, "Client Key", 10); +- hmac_final(&ctx, client_key); ++ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); ++ openssl_hmac_update(&ctx, "Client Key", 10); ++ openssl_hmac_final(&ctx, client_key); + + /* Calculate StoredKey */ + hash_method_get_digest(hmethod, client_key, sizeof(client_key), +@@ -147,7 +147,7 @@ void scram_generate(const struct hash_me + const unsigned char **raw_password_r, size_t *size_r) + { + string_t *str; +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + unsigned char salt[16]; + unsigned char salted_password[hmethod->digest_size]; + unsigned char client_key[hmethod->digest_size]; +@@ -165,9 +165,9 @@ void scram_generate(const struct hash_me + sizeof(salt), SCRAM_DEFAULT_ITERATE_COUNT, salted_password); + + /* Calculate ClientKey */ +- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); +- hmac_update(&ctx, "Client Key", 10); +- hmac_final(&ctx, client_key); ++ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); ++ openssl_hmac_update(&ctx, "Client Key", 10); ++ openssl_hmac_final(&ctx, client_key); + + /* Calculate StoredKey */ + hash_method_get_digest(hmethod, client_key, sizeof(client_key), +@@ -176,9 +176,9 @@ void scram_generate(const struct hash_me + base64_encode(stored_key, sizeof(stored_key), str); + + /* Calculate ServerKey */ +- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); +- hmac_update(&ctx, "Server Key", 10); +- hmac_final(&ctx, server_key); ++ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); ++ openssl_hmac_update(&ctx, "Server Key", 10); ++ openssl_hmac_final(&ctx, server_key); + str_append_c(str, ','); + base64_encode(server_key, sizeof(server_key), str); + +diff -up dovecot-2.3.14/src/lib/hmac.c.opensslhmac dovecot-2.3.14/src/lib/hmac.c +--- dovecot-2.3.14/src/lib/hmac.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/hmac.c 2021-03-22 20:44:13.023912229 +0100 +@@ -7,6 +7,10 @@ + * This software is released under the MIT license. + */ + ++#include ++#include ++#include ++#include + #include "lib.h" + #include "hmac.h" + #include "safe-memset.h" +@@ -14,10 +18,65 @@ + + #include "hex-binary.h" + +-void hmac_init(struct hmac_context *_ctx, const unsigned char *key, ++#ifndef HAVE_HMAC_CTX_NEW ++# define HMAC_Init_ex(ctx, key, key_len, md, impl) \ ++ HMAC_Init_ex(&(ctx), key, key_len, md, impl) ++# define HMAC_Update(ctx, data, len) HMAC_Update(&(ctx), data, len) ++# define HMAC_Final(ctx, md, len) HMAC_Final(&(ctx), md, len) ++# define HMAC_CTX_free(ctx) HMAC_cleanup(&(ctx)) ++#else ++# define HMAC_CTX_free(ctx) \ ++ STMT_START { HMAC_CTX_free(ctx); (ctx) = NULL; } STMT_END ++#endif ++ ++ ++void openssl_hmac_init(struct openssl_hmac_context *_ctx, const unsigned char *key, + size_t key_len, const struct hash_method *meth) + { +- struct hmac_context_priv *ctx = &_ctx->u.priv; ++ struct openssl_hmac_context_priv *ctx = &_ctx->u.priv; ++ ++ const EVP_MD *md; ++ const char *ebuf = NULL; ++ const char **error_r = &ebuf; ++ ++ md = EVP_get_digestbyname(meth->name); ++ if(md == NULL) { ++ if (error_r != NULL) { ++ *error_r = t_strdup_printf("Invalid digest %s", ++ meth->name); ++ } ++ //return FALSE; ++ } ++ ++// int ec; ++ ++ i_assert(md != NULL); ++#ifdef HAVE_HMAC_CTX_NEW ++ ctx->ctx = HMAC_CTX_new(); ++/* if (ctx->ctx == NULL) ++ dcrypt_openssl_error(error_r);*/ ++#endif ++ /*ec = */HMAC_Init_ex(ctx->ctx, key, key_len, md, NULL); ++} ++ ++void orig_hmac_init(struct orig_hmac_context *_ctx, const unsigned char *key, ++ size_t key_len, const struct hash_method *meth) ++{ ++ static int no_fips = -1; ++ if (no_fips == -1) { ++ int fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY); ++ if (fd != -1) ++ { ++ char buf[4]; ++ if (read(fd, buf, 4) > 0) ++ { ++ no_fips = buf[0] == '0'; ++ } ++ close(fd); ++ } ++ } ++ i_assert(no_fips); ++ struct orig_hmac_context_priv *ctx = &_ctx->u.priv; + unsigned int i; + unsigned char k_ipad[meth->block_size]; + unsigned char k_opad[meth->block_size]; +@@ -53,9 +112,27 @@ void hmac_init(struct hmac_context *_ctx + safe_memset(k_opad, 0, meth->block_size); + } + +-void hmac_final(struct hmac_context *_ctx, unsigned char *digest) ++void openssl_hmac_final(struct openssl_hmac_context *_ctx, unsigned char *digest) ++{ ++ int ec; ++ unsigned char buf[HMAC_MAX_MD_CBLOCK]; ++ unsigned int outl; ++// const char *ebuf = NULL; ++// const char **error_r = &ebuf; ++ ++ struct openssl_hmac_context_priv *ctx = &_ctx->u.priv; ++ ec = HMAC_Final(ctx->ctx, buf, &outl); ++ HMAC_CTX_free(ctx->ctx); ++ if (ec == 1) ++ memcpy(digest, buf, outl); ++// else ++// dcrypt_openssl_error(error_r); ++ ++} ++ ++void orig_hmac_final(struct orig_hmac_context *_ctx, unsigned char *digest) + { +- struct hmac_context_priv *ctx = &_ctx->u.priv; ++ struct orig_hmac_context_priv *ctx = &_ctx->u.priv; + + ctx->hash->result(ctx->ctx, digest); + +@@ -63,53 +140,50 @@ void hmac_final(struct hmac_context *_ct + ctx->hash->result(ctx->ctxo, digest); + } + +-buffer_t *t_hmac_data(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_data(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const void *data, size_t data_len) + { +- struct hmac_context ctx; ++ struct openssl_hmac_context ctx; + i_assert(meth != NULL); + i_assert(key != NULL && key_len > 0); + i_assert(data != NULL || data_len == 0); + + buffer_t *res = t_buffer_create(meth->digest_size); +- hmac_init(&ctx, key, key_len, meth); ++ openssl_hmac_init(&ctx, key, key_len, meth); + if (data_len > 0) +- hmac_update(&ctx, data, data_len); ++ openssl_hmac_update(&ctx, data, data_len); + unsigned char *buf = buffer_get_space_unsafe(res, 0, meth->digest_size); +- hmac_final(&ctx, buf); ++ openssl_hmac_final(&ctx, buf); + return res; + } + +-buffer_t *t_hmac_buffer(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_buffer(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const buffer_t *data) + { +- return t_hmac_data(meth, key, key_len, data->data, data->used); ++ return openssl_t_hmac_data(meth, key, key_len, data->data, data->used); + } + +-buffer_t *t_hmac_str(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_str(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const char *data) + { +- return t_hmac_data(meth, key, key_len, data, strlen(data)); ++ return openssl_t_hmac_data(meth, key, key_len, data, strlen(data)); + } + +-void hmac_hkdf(const struct hash_method *method, ++void openssl_hmac_hkdf(const struct hash_method *method, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + buffer_t *okm_r, size_t okm_len) + { ++ const EVP_MD *md; ++ EVP_PKEY_CTX *pctx; ++ int r = 1; ++ + i_assert(method != NULL); + i_assert(okm_len < 255*method->digest_size); +- struct hmac_context key_mac; +- struct hmac_context info_mac; +- size_t remain = okm_len; +- unsigned char prk[method->digest_size]; +- unsigned char okm[method->digest_size]; +- /* N = ceil(L/HashLen) */ +- unsigned int rounds = (okm_len + method->digest_size - 1)/method->digest_size; + + /* salt and info can be NULL */ + i_assert(salt != NULL || salt_len == 0); +@@ -118,35 +192,30 @@ void hmac_hkdf(const struct hash_method + i_assert(ikm != NULL && ikm_len > 0); + i_assert(okm_r != NULL && okm_len > 0); + +- /* but they still need valid pointer, reduces +- complains from static analysers */ +- if (salt == NULL) +- salt = &uchar_nul; +- if (info == NULL) +- info = &uchar_nul; +- +- /* extract */ +- hmac_init(&key_mac, salt, salt_len, method); +- hmac_update(&key_mac, ikm, ikm_len); +- hmac_final(&key_mac, prk); +- +- /* expand */ +- for (unsigned int i = 0; remain > 0 && i < rounds; i++) { +- unsigned char round = (i+1); +- size_t amt = remain; +- if (amt > method->digest_size) +- amt = method->digest_size; +- hmac_init(&info_mac, prk, method->digest_size, method); +- if (i > 0) +- hmac_update(&info_mac, okm, method->digest_size); +- hmac_update(&info_mac, info, info_len); +- hmac_update(&info_mac, &round, 1); +- memset(okm, 0, method->digest_size); +- hmac_final(&info_mac, okm); +- buffer_append(okm_r, okm, amt); +- remain -= amt; ++ ++ md = EVP_get_digestbyname(method->name); ++ pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); ++ unsigned char *okm_buf = buffer_get_space_unsafe(okm_r, 0, okm_len); ++ ++ if ((r=EVP_PKEY_derive_init(pctx)) <= 0) ++ goto out; ++ if ((r=EVP_PKEY_CTX_set_hkdf_md(pctx, md)) <= 0) ++ goto out; ++ if ((r=EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, salt_len)) <= 0) ++ goto out; ++ if ((r=EVP_PKEY_CTX_set1_hkdf_key(pctx, ikm, ikm_len)) <= 0) ++ goto out; ++ if ((r=EVP_PKEY_CTX_add1_hkdf_info(pctx, info, info_len)) <= 0) ++ goto out; ++ if ((r=EVP_PKEY_derive(pctx, okm_buf, &okm_len)) <= 0) ++ goto out; ++ ++ out: ++ EVP_PKEY_CTX_free(pctx); ++ if (r <= 0) { ++ unsigned long ec = ERR_get_error(); ++ unsigned char *error = t_strdup_printf("%s", ERR_error_string(ec, NULL)); ++ i_error("%s", error); + } + +- safe_memset(prk, 0, sizeof(prk)); +- safe_memset(okm, 0, sizeof(okm)); + } +diff -up dovecot-2.3.14/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.14/src/lib/hmac-cram-md5.c +--- dovecot-2.3.14/src/lib/hmac-cram-md5.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/hmac-cram-md5.c 2021-03-22 20:44:13.023912229 +0100 +@@ -9,10 +9,10 @@ + #include "md5.h" + #include "hmac-cram-md5.h" + +-void hmac_md5_get_cram_context(struct hmac_context *_hmac_ctx, ++void hmac_md5_get_cram_context(struct orig_hmac_context *_hmac_ctx, + unsigned char context_digest[CRAM_MD5_CONTEXTLEN]) + { +- struct hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv; ++ struct orig_hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv; + unsigned char *cdp; + + struct md5_context *ctx = (void*)hmac_ctx->ctx; +@@ -35,10 +35,10 @@ void hmac_md5_get_cram_context(struct hm + CDPUT(cdp, ctx->d); + } + +-void hmac_md5_set_cram_context(struct hmac_context *_hmac_ctx, ++void hmac_md5_set_cram_context(struct orig_hmac_context *_hmac_ctx, + const unsigned char context_digest[CRAM_MD5_CONTEXTLEN]) + { +- struct hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv; ++ struct orig_hmac_context_priv *hmac_ctx = &_hmac_ctx->u.priv; + const unsigned char *cdp; + + struct md5_context *ctx = (void*)hmac_ctx->ctx; +diff -up dovecot-2.3.14/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.14/src/lib/hmac-cram-md5.h +--- dovecot-2.3.14/src/lib/hmac-cram-md5.h.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/hmac-cram-md5.h 2021-03-22 20:44:13.023912229 +0100 +@@ -5,9 +5,9 @@ + + #define CRAM_MD5_CONTEXTLEN 32 + +-void hmac_md5_get_cram_context(struct hmac_context *ctx, ++void hmac_md5_get_cram_context(struct orig_hmac_context *ctx, + unsigned char context_digest[CRAM_MD5_CONTEXTLEN]); +-void hmac_md5_set_cram_context(struct hmac_context *ctx, ++void hmac_md5_set_cram_context(struct orig_hmac_context *ctx, + const unsigned char context_digest[CRAM_MD5_CONTEXTLEN]); + + +diff -up dovecot-2.3.14/src/lib/hmac.h.opensslhmac dovecot-2.3.14/src/lib/hmac.h +--- dovecot-2.3.14/src/lib/hmac.h.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/hmac.h 2021-03-22 20:44:13.023912229 +0100 +@@ -4,60 +4,97 @@ + #include "hash-method.h" + #include "sha1.h" + #include "sha2.h" ++#include ++#include ++#include ++#include + + #define HMAC_MAX_CONTEXT_SIZE sizeof(struct sha512_ctx) + +-struct hmac_context_priv { ++struct openssl_hmac_context_priv { ++#ifdef HAVE_HMAC_CTX_NEW ++ HMAC_CTX *ctx; ++#else ++ HMAC_CTX ctx; ++#endif ++ const struct hash_method *hash; ++}; ++ ++struct orig_hmac_context_priv { + char ctx[HMAC_MAX_CONTEXT_SIZE]; + char ctxo[HMAC_MAX_CONTEXT_SIZE]; + const struct hash_method *hash; + }; + +-struct hmac_context { ++struct openssl_hmac_context { ++ union { ++ struct openssl_hmac_context_priv priv; ++ uint64_t padding_requirement; ++ } u; ++}; ++ ++struct orig_hmac_context { + union { +- struct hmac_context_priv priv; ++ struct orig_hmac_context_priv priv; + uint64_t padding_requirement; + } u; + }; + +-void hmac_init(struct hmac_context *ctx, const unsigned char *key, ++void openssl_hmac_init(struct openssl_hmac_context *ctx, const unsigned char *key, ++ size_t key_len, const struct hash_method *meth); ++void openssl_hmac_final(struct openssl_hmac_context *ctx, unsigned char *digest); ++ ++static inline void ++openssl_hmac_update(struct openssl_hmac_context *_ctx, const void *data, size_t size) ++{ ++ struct openssl_hmac_context_priv *ctx = &_ctx->u.priv; ++ HMAC_Update(ctx->ctx, data, size); ++/* if (ec != 1) ++ { ++ const char *ebuf = NULL; ++ const char **error_r = &ebuf; ++ dcrypt_openssl_error(error_r); ++ }*/ ++} ++ ++void orig_hmac_init(struct orig_hmac_context *ctx, const unsigned char *key, + size_t key_len, const struct hash_method *meth); +-void hmac_final(struct hmac_context *ctx, unsigned char *digest); ++void orig_hmac_final(struct orig_hmac_context *ctx, unsigned char *digest); + + + static inline void +-hmac_update(struct hmac_context *_ctx, const void *data, size_t size) ++orig_hmac_update(struct orig_hmac_context *_ctx, const void *data, size_t size) + { +- struct hmac_context_priv *ctx = &_ctx->u.priv; ++ struct orig_hmac_context_priv *ctx = &_ctx->u.priv; + + ctx->hash->loop(ctx->ctx, data, size); + } + +-buffer_t *t_hmac_data(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_data(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const void *data, size_t data_len); +-buffer_t *t_hmac_buffer(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_buffer(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const buffer_t *data); +-buffer_t *t_hmac_str(const struct hash_method *meth, ++buffer_t *openssl_t_hmac_str(const struct hash_method *meth, + const unsigned char *key, size_t key_len, + const char *data); + +-void hmac_hkdf(const struct hash_method *method, ++void openssl_hmac_hkdf(const struct hash_method *method, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + buffer_t *okm_r, size_t okm_len); + + static inline buffer_t * +-t_hmac_hkdf(const struct hash_method *method, ++openssl_t_hmac_hkdf(const struct hash_method *method, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + size_t okm_len) + { + buffer_t *okm_buffer = t_buffer_create(okm_len); +- hmac_hkdf(method, salt, salt_len, ikm, ikm_len, info, info_len, ++ openssl_hmac_hkdf(method, salt, salt_len, ikm, ikm_len, info, info_len, + okm_buffer, okm_len); + return okm_buffer; + } +diff -up dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c +--- dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c 2021-03-22 20:44:13.023912229 +0100 +@@ -85,15 +85,15 @@ imap_urlauth_internal_generate(const cha + const unsigned char mailbox_key[IMAP_URLAUTH_KEY_LEN], + size_t *token_len_r) + { +- struct hmac_context hmac; ++ struct openssl_hmac_context hmac; + unsigned char *token; + + token = t_new(unsigned char, SHA1_RESULTLEN + 1); + token[0] = IMAP_URLAUTH_MECH_INTERNAL_VERSION; + +- hmac_init(&hmac, mailbox_key, IMAP_URLAUTH_KEY_LEN, &hash_method_sha1); +- hmac_update(&hmac, rumpurl, strlen(rumpurl)); +- hmac_final(&hmac, token+1); ++ openssl_hmac_init(&hmac, mailbox_key, IMAP_URLAUTH_KEY_LEN, &hash_method_sha1); ++ openssl_hmac_update(&hmac, rumpurl, strlen(rumpurl)); ++ openssl_hmac_final(&hmac, token+1); + + *token_len_r = SHA1_RESULTLEN + 1; + return token; +diff -up dovecot-2.3.14/src/lib/Makefile.am.opensslhmac dovecot-2.3.14/src/lib/Makefile.am +--- dovecot-2.3.14/src/lib/Makefile.am.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/Makefile.am 2021-03-22 20:44:13.023912229 +0100 +@@ -352,6 +352,9 @@ headers = \ + wildcard-match.h \ + write-full.h + ++liblib_la_LIBADD = $(SSL_LIBS) ++liblib_la_CFLAGS = $(SSL_CFLAGS) ++ + test_programs = test-lib + noinst_PROGRAMS = $(test_programs) + +diff -up dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c.opensslhmac dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c +--- dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c 2021-03-22 20:44:13.024912217 +0100 +@@ -106,14 +106,14 @@ oauth2_validate_hmac(const struct oauth2 + if (oauth2_lookup_hmac_key(set, azp, alg, key_id, &key, error_r) < 0) + return -1; + +- struct hmac_context ctx; +- hmac_init(&ctx, key->data, key->used, method); +- hmac_update(&ctx, blobs[0], strlen(blobs[0])); +- hmac_update(&ctx, ".", 1); +- hmac_update(&ctx, blobs[1], strlen(blobs[1])); ++ struct openssl_hmac_context ctx; ++ openssl_hmac_init(&ctx, key->data, key->used, method); ++ openssl_hmac_update(&ctx, blobs[0], strlen(blobs[0])); ++ openssl_hmac_update(&ctx, ".", 1); ++ openssl_hmac_update(&ctx, blobs[1], strlen(blobs[1])); + unsigned char digest[method->digest_size]; + +- hmac_final(&ctx, digest); ++ openssl_hmac_final(&ctx, digest); + + buffer_t *their_digest = + t_base64url_decode_str(BASE64_DECODE_FLAG_NO_PADDING, blobs[2]); +diff -up dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c.opensslhmac dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c +--- dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c 2021-03-22 20:46:09.524440794 +0100 +@@ -236,7 +236,7 @@ static void save_key_to(const char *algo + static void sign_jwt_token_hs256(buffer_t *tokenbuf, buffer_t *key) + { + i_assert(key != NULL); +- buffer_t *sig = t_hmac_buffer(&hash_method_sha256, key->data, key->used, ++ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha256, key->data, key->used, + tokenbuf); + buffer_append(tokenbuf, ".", 1); + base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX, +@@ -246,7 +246,7 @@ static void sign_jwt_token_hs256(buffer_ + static void sign_jwt_token_hs384(buffer_t *tokenbuf, buffer_t *key) + { + i_assert(key != NULL); +- buffer_t *sig = t_hmac_buffer(&hash_method_sha384, key->data, key->used, ++ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha384, key->data, key->used, + tokenbuf); + buffer_append(tokenbuf, ".", 1); + base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX, +@@ -256,7 +256,7 @@ static void sign_jwt_token_hs384(buffer_ + static void sign_jwt_token_hs512(buffer_t *tokenbuf, buffer_t *key) + { + i_assert(key != NULL); +- buffer_t *sig = t_hmac_buffer(&hash_method_sha512, key->data, key->used, ++ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha512, key->data, key->used, + tokenbuf); + buffer_append(tokenbuf, ".", 1); + base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX, +diff -up dovecot-2.3.14/src/lib/pkcs5.c.opensslhmac dovecot-2.3.14/src/lib/pkcs5.c +--- dovecot-2.3.14/src/lib/pkcs5.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/pkcs5.c 2021-03-22 20:44:13.024912217 +0100 +@@ -52,7 +52,7 @@ int pkcs5_pbkdf2(const struct hash_metho + size_t l = (length + hash->digest_size - 1)/hash->digest_size; /* same as ceil(length/hash->digest_size) */ + unsigned char dk[l * hash->digest_size]; + unsigned char *block; +- struct hmac_context hctx; ++ struct openssl_hmac_context hctx; + unsigned int c,i,t; + unsigned char U_c[hash->digest_size]; + +@@ -60,17 +60,17 @@ int pkcs5_pbkdf2(const struct hash_metho + block = &(dk[t*hash->digest_size]); + /* U_1 = PRF(Password, Salt|| INT_BE32(Block_Number)) */ + c = htonl(t+1); +- hmac_init(&hctx, password, password_len, hash); +- hmac_update(&hctx, salt, salt_len); +- hmac_update(&hctx, &c, sizeof(c)); +- hmac_final(&hctx, U_c); ++ openssl_hmac_init(&hctx, password, password_len, hash); ++ openssl_hmac_update(&hctx, salt, salt_len); ++ openssl_hmac_update(&hctx, &c, sizeof(c)); ++ openssl_hmac_final(&hctx, U_c); + /* block = U_1 ^ .. ^ U_iter */ + memcpy(block, U_c, hash->digest_size); + /* U_c = PRF(Password, U_c-1) */ + for(c = 1; c < iter; c++) { +- hmac_init(&hctx, password, password_len, hash); +- hmac_update(&hctx, U_c, hash->digest_size); +- hmac_final(&hctx, U_c); ++ openssl_hmac_init(&hctx, password, password_len, hash); ++ openssl_hmac_update(&hctx, U_c, hash->digest_size); ++ openssl_hmac_final(&hctx, U_c); + for(i = 0; i < hash->digest_size; i++) + block[i] ^= U_c[i]; + } +diff -up dovecot-2.3.14/src/lib/test-hmac.c.opensslhmac dovecot-2.3.14/src/lib/test-hmac.c +--- dovecot-2.3.14/src/lib/test-hmac.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/test-hmac.c 2021-03-22 20:44:13.024912217 +0100 +@@ -206,11 +206,11 @@ static void test_hmac_rfc(void) + test_begin("hmac sha256 rfc4231 vectors"); + for(size_t i = 0; i < N_ELEMENTS(test_vectors); i++) { + const struct test_vector *vec = &(test_vectors[i]); +- struct hmac_context ctx; +- hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); +- hmac_update(&ctx, vec->data, vec->data_len); ++ struct openssl_hmac_context ctx; ++ openssl_hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); ++ openssl_hmac_update(&ctx, vec->data, vec->data_len); + unsigned char res[SHA256_RESULTLEN]; +- hmac_final(&ctx, res); ++ openssl_hmac_final(&ctx, res); + test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i); + } + test_end(); +@@ -221,11 +221,11 @@ static void test_hmac384_rfc(void) + test_begin("hmac sha384 rfc4231 vectors"); + for (size_t i = 0; i < N_ELEMENTS(test_vectors_hmac384); i++) { + const struct test_vector *vec = &(test_vectors_hmac384[i]); +- struct hmac_context ctx; +- hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); +- hmac_update(&ctx, vec->data, vec->data_len); ++ struct openssl_hmac_context ctx; ++ openssl_hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); ++ openssl_hmac_update(&ctx, vec->data, vec->data_len); + unsigned char res[SHA384_RESULTLEN]; +- hmac_final(&ctx, res); ++ openssl_hmac_final(&ctx, res); + test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i); + } + test_end(); +@@ -236,11 +236,11 @@ static void test_hmac512_rfc(void) + test_begin("hmac sha512 rfc4231 vectors"); + for (size_t i = 0; i < N_ELEMENTS(test_vectors_hmac512); i++) { + const struct test_vector *vec = &(test_vectors_hmac512[i]); +- struct hmac_context ctx; +- hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); +- hmac_update(&ctx, vec->data, vec->data_len); ++ struct openssl_hmac_context ctx; ++ openssl_hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); ++ openssl_hmac_update(&ctx, vec->data, vec->data_len); + unsigned char res[SHA512_RESULTLEN]; +- hmac_final(&ctx, res); ++ openssl_hmac_final(&ctx, res); + test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i); + } + test_end(); +@@ -253,7 +253,7 @@ static void test_hmac_buffer(void) + + buffer_t *tmp; + +- tmp = t_hmac_data(hash_method_lookup(vec->prf), vec->key, vec->key_len, ++ tmp = openssl_t_hmac_data(hash_method_lookup(vec->prf), vec->key, vec->key_len, + vec->data, vec->data_len); + + test_assert(tmp->used == vec->res_len && +@@ -270,7 +270,7 @@ static void test_hkdf_rfc(void) + buffer_set_used_size(res, 0); + const struct test_vector_5869 *vec = &(test_vectors_5869[i]); + const struct hash_method *m = hash_method_lookup(vec->prf); +- hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm, vec->ikm_len, ++ openssl_hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm, vec->ikm_len, + vec->info, vec->info_len, res, vec->okm_len); + test_assert_idx(memcmp(res->data, vec->okm, vec->okm_len) == 0, i); + } +@@ -283,7 +283,7 @@ static void test_hkdf_buffer(void) + test_begin("hkdf temporary buffer"); + const struct test_vector_5869 *vec = &(test_vectors_5869[0]); + const struct hash_method *m = hash_method_lookup(vec->prf); +- buffer_t *tmp = t_hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm, ++ buffer_t *tmp = openssl_t_hmac_hkdf(m, vec->salt, vec->salt_len, vec->ikm, + vec->ikm_len, vec->info, vec->info_len, + vec->okm_len); + test_assert(tmp->used == vec->okm_len && diff --git a/dovecot.conf.5 b/dovecot.conf.5 new file mode 100644 index 0000000000000000000000000000000000000000..a15f1f6dd4e759b267494af1e1517b5150da68c7 --- /dev/null +++ b/dovecot.conf.5 @@ -0,0 +1,19 @@ +.TH DOVECOT.CONF 5 2010/06/27 "dovecot" "File Formats and Conventions" +.SH NAME +\fBdovecot.conf\fP \- The configuration file for dovecot imap and pop3 server + +.SH FULL PATH +.B /etc/dovecot.conf + +.SH DESCRIPTION +The dovecot.conf file is a configuration file for the +.BR dovecot (1) +imap and pop3 server. The dovecot.conf configuration file contains description to all available options. Some of these options are described also in offline wiki documentation placed in /usr/share/doc/dovecot*/wiki/. + +For backup purposes unmodified version of dovecot.conf can be found in /usr/share/doc/dovecot-/example-config/dovecot.conf.default + +.SH "SEE ALSO" +.BR doveadm (1), +.BR dovecot (1), +.I /usr/share/doc/dovecot*/wiki/ +.I /usr/share/doc/dovecot*/dovecot.conf.default diff --git a/dovecot.init b/dovecot.init new file mode 100755 index 0000000000000000000000000000000000000000..49206f0abc52aefceda50d6ee42adeb9dd2caad6 --- /dev/null +++ b/dovecot.init @@ -0,0 +1,108 @@ +#!/bin/bash +# +# /etc/rc.d/init.d/dovecot +# +# Starts the dovecot daemon +# +# chkconfig: - 65 35 +# description: Dovecot Imap Server +# processname: dovecot +# config: /etc/dovecot.conf +# config: /etc/sysconfig/dovecot +# pidfile: /var/run/dovecot/master.pid + +### BEGIN INIT INFO +# Provides: dovecot +# Required-Start: $local_fs $network +# Required-Stop: $local_fs $network +# Should-Start: $remote_fs +# Should-Stop: $remote_fs +# Default-Start: +# Default-Stop: 0 1 2 3 4 5 6 +# Short-Description: start and stop Dovecot Imap server +# Description: Dovecot is an IMAP server for Linux/UNIX-like systems, +# written with security primarily in mind. It also contains +# a small POP3 server. +### END INIT INFO + +# Source function library. +. /etc/init.d/functions + +if [ -f /etc/sysconfig/dovecot -a $UID -eq 0 ]; then + . /etc/sysconfig/dovecot +fi + +RETVAL=0 +prog="Dovecot Imap" +exec="/usr/sbin/dovecot" +config="/etc/dovecot/dovecot.conf" +pidfile="/var/run/dovecot/master.pid" +lockfile="/var/lock/subsys/dovecot" + +start() { + [ $UID -eq 0 ] || exit 4 + [ -x $exec ] || exit 5 + [ -f $config ] || exit 6 + + echo -n $"Starting $prog: " + daemon --pidfile $pidfile $exec $OPTIONS + RETVAL=$? + [ $RETVAL -eq 0 ] && touch $lockfile + echo +} + +stop() { + [ $UID -eq 0 ] || exit 4 + echo -n $"Stopping $prog: " + killproc -p $pidfile $exec + RETVAL=$? + [ $RETVAL -eq 0 ] && rm -f $lockfile + echo +} + +reload() { + [ $UID -eq 0 ] || exit 4 + echo -n $"Reloading $prog: " + killproc -p $pidfile $exec -HUP + RETVAL=$? + echo +} + +# +# See how we were called. +# +case "$1" in + start) + start + ;; + stop) + stop + ;; + reload) + reload + ;; + force-reload|restart) + stop + sleep 1 + start + RETVAL=$? + ;; + condrestart|try-restart) + if [ -f $lockfile ]; then + stop + sleep 3 + start + fi + ;; + status) + status -p $pidfile $exec + RETVAL=$? + ;; + *) + echo $"Usage: $0 {condrestart|try-restart|start|stop|restart|reload|force-reload|status}" + RETVAL=2 + [ "$1" = 'usage' ] && RETVAL=0 +esac + +exit $RETVAL + diff --git a/dovecot.spec b/dovecot.spec index 496313d33873abc3dbd65b69d4c9c40f97995e92..1362c8391f31b1273a44c75db0d94aedbed08dee 100644 --- a/dovecot.spec +++ b/dovecot.spec @@ -5,23 +5,23 @@ %global _hardened_build 1 Name: dovecot -Version: 2.3.10.1 -Release: 6 +Version: 2.3.15 +Release: 1 Summary: Dovecot Secure imap server License: MIT and LGPLv2.1 URL: http://www.dovecot.org/ Epoch: 1 -Source: http://www.dovecot.org/releases/2.3/%{name}-%{version}%{?prever}.tar.gz +Source: http://www.dovecot.org/releases/2.3/%{name}-%{version}.tar.gz +Source1: dovecot.init Source2: dovecot.pam -%global pigeonholever 0.5.10 +%global pigeonholever 0.5.15 Source8: http://pigeonhole.dovecot.org/releases/2.3/dovecot-2.3-pigeonhole-%{pigeonholever}.tar.gz Source9: dovecot.sysconfig Source10: dovecot.tmpfilesd -Source11: https://raw.githubusercontent.com/QMailToaster/dovecot/master/dovecot.prestartscript +Source11: prestartscript +Source12: dovecot.conf.5 -Patch6000: CVE-2015-3420.patch -Patch6001: CVE-2016-8652.patch Patch6002: dovecot-2.0-defaultconfig.patch Patch6003: dovecot-1.0.beta2-mkcert-permissions.patch Patch6004: dovecot-1.0.rc7-mkcert-paths.patch @@ -31,22 +31,17 @@ Patch6005: dovecot-2.1.10-waitonline.patch Patch6006: dovecot-2.2.20-initbysystemd.patch Patch6007: dovecot-2.2.22-systemd_w_protectsystem.patch -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 -Patch6015: 0001-Fix-bugs-in-smtp-server.patch -Patch6016: 0002-Fix-assert-crash-if-parsing-invalid-BODYSTRUCTURE.patch -Patch6017: 0003-Handle-empty-lists-in-IMAP-BODYSTRUCTURE-parsing-as-invalid.patch -Patch6018: 0004-Fix-writing-BODYSTRUCTURE-for-truncated-multipart-digest-part.patch +Patch6009: dovecot-2.3.11-bigkey.patch +Patch6010: dovecot-2.3.6-opensslhmac.patch +Patch6011: dovecot-2.3.15-fixvalcond.patch +Patch6012: dovecot-2.3.15-valbasherr.patch BuildRequires: gcc-c++ openssl-devel pam-devel zlib-devel bzip2-devel libcap-devel BuildRequires: libtool autoconf automake pkgconfig sqlite-devel libpq-devel BuildRequires: mariadb-connector-c-devel libxcrypt-devel openldap-devel krb5-devel BuildRequires: quota-devel xz-devel gettext-devel clucene-core-devel libcurl-devel expat-devel +BuildRequires: lz4-devel libzstd-devel libicu-devel libstemmer-devel multilib-rpm-config +BuildRequires: systemd-devel Requires: openssl >= 0.9.7f-4 systemd Requires(pre): shadow-utils @@ -77,7 +72,7 @@ Man pages and other related help documents for %{name}. %prep -%autosetup -n %{name}-%{version}%{?prever} -a 8 -p1 +%autosetup -n %{name}-%{version} -a 8 -p1 sed -i '/DEFAULT_INCLUDES *=/s|$| '"$(pkg-config --cflags libclucene-core)|" src/plugins/fts-lucene/Makefile.in @@ -121,6 +116,7 @@ install -m 644 AUTHORS ChangeLog COPYING COPYING.LGPL INSTALL NEWS README $RPM_B cd - install -p -D -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/dovecot +install -p -D -m 644 %{SOURCE12} $RPM_BUILD_ROOT%{_mandir}/man5/dovecot.conf.5 install -p -D -m 755 %{SOURCE11} $RPM_BUILD_ROOT%{_libexecdir}/dovecot/prestartscript install -d $RPM_BUILD_ROOT%{ssldir}/certs @@ -226,6 +222,7 @@ make check %config(noreplace) %{_sysconfdir}/dovecot/conf.d/{auth-deny.conf.ext,auth-dict.conf.ext,auth-ldap.conf.ext} %config(noreplace) %{_sysconfdir}/dovecot/conf.d/{auth-master.conf.ext,auth-passwdfile.conf.ext,auth-sql.conf.ext} %config(noreplace) %{_sysconfdir}/dovecot/conf.d/{auth-static.conf.ext,auth-system.conf.ext,auth-vpopmail.conf.ext} +%config(noreplace) %{_sysconfdir}/dovecot/conf.d/10-metrics.conf %config(noreplace) %{_sysconfdir}/pam.d/dovecot %config(noreplace) %{ssldir}/dovecot-openssl.cnf @@ -242,7 +239,7 @@ make check %exclude %{_libdir}/dovecot/doveadm/*sieve* %{_libdir}/dovecot/*.so.* %{_libdir}/dovecot/*_plugin.so -%exclude %{_libdir}/dovecot/*_sieve_plugin.so +%{_libdir}/dovecot/*_sieve_plugin.so %{_libdir}/dovecot/auth/{lib20_auth_var_expand_crypt.so,libauthdb_imap.so,libauthdb_ldap.so} %{_libdir}/dovecot/auth/{libmech_gssapi.so,libdriver_sqlite.so} %{_libdir}/dovecot/dict/{libdriver_sqlite.so,libdict_ldap.so} @@ -288,11 +285,14 @@ make check %files help %{_mandir}/man1/* +%{_mandir}/man5/dovecot.conf.5* %{_mandir}/man7/doveadm-search-query.7* %{_mandir}/man7/pigeonhole.7* - %changelog +* Fri Jul 09 2021 wutao - 2.3.15-1 +- upgrade to 2.3.15 to fix CVE + * Thu Jun 03 2021 maminjie - 2.3.10.1-6 - backport some patches about imap-bodystructure diff --git a/dovecot.tmpfilesd b/dovecot.tmpfilesd index 717849854147501abd2c94c6e7b536bc00165b17..d96639a08c839f6e621ec81ff63091993a644f31 100644 --- a/dovecot.tmpfilesd +++ b/dovecot.tmpfilesd @@ -1,2 +1,2 @@ -d /var/run/dovecot 0755 root dovecot - +d /run/dovecot 0755 root dovecot - diff --git a/dovecot.prestartscript b/prestartscript similarity index 57% rename from dovecot.prestartscript rename to prestartscript index dd954ec675e924edd038f77bf55a91958a6da053..0c5492cba20bac5a84eb9dd9d577c7cad71495dd 100644 --- a/dovecot.prestartscript +++ b/prestartscript @@ -1,3 +1,3 @@ #!/bin/sh -/bin/systemctl -q is-enabled NetworkManager.service >/dev/null 2>&1 \ - && /usr/bin/nm-online -q --timeout 30 ||: +/bin/systemctl -q is-enabled NetworkManager.service >/dev/null 2>&1 && /usr/bin/nm-online -q --timeout 30 ||: +