summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsana kazi <sanakazisk19@gmail.com>2021-12-03 17:57:19 +0530
committerArmin Kuster <akuster808@gmail.com>2021-12-03 12:23:33 -0800
commit00ad99f4f9a06d66bd5686d2b1dd07c578c8dc2a (patch)
treea809ba1c690bd15d55625d725624ebe2b11b1603
parente0e79bbde23f17185cc59908fee97c0cea098428 (diff)
downloadmeta-openembedded-00ad99f4f9a06d66bd5686d2b1dd07c578c8dc2a.tar.gz
dovecot: Fix CVE-2020-12100
Added patches to fix CVE-2020-12100 Link: http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com> Signed-off-by: Sana Kazi <sanakazisk19@gmail.com> Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0001-lib-mail-message-parser-Add-a-message_part_finish-he.patch76
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0002-lib-mail-message-parser-Change-message_part_append-t.patch71
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0003-lib-mail-message-parser-Optimize-updating-children_c.patch49
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0004-lib-mail-message-parser-Optimize-appending-new-part-.patch88
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0005-lib-mail-message-parser-Minor-code-cleanup-to-findin.patch45
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0006-lib-mail-message-parser-Truncate-excessively-long-MI.patch163
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0007-lib-mail-message-parser-Optimize-boundary-lookups-wh.patch72
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0008-lib-mail-message-parser-Add-boundary_remove_until-he.patch50
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0009-lib-mail-message-parser-Don-t-use-memory-pool-for-pa.patch169
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0010-lib-mail-message-parser-Support-limiting-max-number-.patch188
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0011-lib-mail-message-parser-Support-limiting-max-number-.patch87
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0012-lib-mail-Fix-handling-trailing-in-MIME-boundaries.patch133
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/0013-lib-mail-Fix-parse_too_many_nested_mime_parts.patch32
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/buffer_free_fix.patch27
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot_2.2.36.4.bb14
15 files changed, 1264 insertions, 0 deletions
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0001-lib-mail-message-parser-Add-a-message_part_finish-he.patch b/meta-networking/recipes-support/dovecot/dovecot/0001-lib-mail-message-parser-Add-a-message_part_finish-he.patch
new file mode 100644
index 000000000..583f71ca5
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0001-lib-mail-message-parser-Add-a-message_part_finish-he.patch
@@ -0,0 +1,76 @@
1From 667d353b0f217372e8cc43ea4fe13466689c7ed0 Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 23 Apr 2020 11:33:31 +0300
4Subject: [PATCH 01/13] lib-mail: message-parser - Add a message_part_finish()
5 helper function
6
7---
8 src/lib-mail/message-parser.c | 25 ++++++++++++-------------
9 1 file changed, 12 insertions(+), 13 deletions(-)
10
11Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
12
13CVE: CVE-2020-12100
14Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
15Comment: No change in any hunk
16
17diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
18index b1de1950a..aaa8dd8b7 100644
19--- a/src/lib-mail/message-parser.c
20+++ b/src/lib-mail/message-parser.c
21@@ -195,6 +195,13 @@ message_part_append(pool_t pool, struct message_part *parent)
22 return part;
23 }
24
25+static void message_part_finish(struct message_parser_ctx *ctx)
26+{
27+ message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size);
28+ message_size_add(&ctx->part->parent->body_size, &ctx->part->header_size);
29+ ctx->part = ctx->part->parent;
30+}
31+
32 static void parse_next_body_multipart_init(struct message_parser_ctx *ctx)
33 {
34 struct message_boundary *b;
35@@ -312,19 +319,16 @@ static int parse_part_finish(struct message_parser_ctx *ctx,
36 struct message_boundary *boundary,
37 struct message_block *block_r, bool first_line)
38 {
39- struct message_part *part;
40 size_t line_size;
41
42 i_assert(ctx->last_boundary == NULL);
43
44 /* get back to parent MIME part, summing the child MIME part sizes
45 into parent's body sizes */
46- for (part = ctx->part; part != boundary->part; part = part->parent) {
47- message_size_add(&part->parent->body_size, &part->body_size);
48- message_size_add(&part->parent->body_size, &part->header_size);
49+ while (ctx->part != boundary->part) {
50+ message_part_finish(ctx);
51+ i_assert(ctx->part != NULL);
52 }
53- i_assert(part != NULL);
54- ctx->part = part;
55
56 if (boundary->epilogue_found) {
57 /* this boundary isn't needed anymore */
58@@ -1132,13 +1136,8 @@ int message_parser_parse_next_block(struct message_parser_ctx *ctx,
59 i_assert(ctx->input->eof || ctx->input->closed ||
60 ctx->input->stream_errno != 0 ||
61 ctx->broken_reason != NULL);
62- while (ctx->part->parent != NULL) {
63- message_size_add(&ctx->part->parent->body_size,
64- &ctx->part->body_size);
65- message_size_add(&ctx->part->parent->body_size,
66- &ctx->part->header_size);
67- ctx->part = ctx->part->parent;
68- }
69+ while (ctx->part->parent != NULL)
70+ message_part_finish(ctx);
71 }
72
73 if (block_r->size == 0) {
74--
752.11.0
76
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0002-lib-mail-message-parser-Change-message_part_append-t.patch b/meta-networking/recipes-support/dovecot/dovecot/0002-lib-mail-message-parser-Change-message_part_append-t.patch
new file mode 100644
index 000000000..9f24320eb
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0002-lib-mail-message-parser-Change-message_part_append-t.patch
@@ -0,0 +1,71 @@
1From de0da7bc8df55521db8fa787f88e293618c96386 Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 23 Apr 2020 11:34:22 +0300
4Subject: [PATCH 02/13] lib-mail: message-parser - Change message_part_append()
5 to do all work internally
6
7---
8 src/lib-mail/message-parser.c | 13 +++++++------
9 1 file changed, 7 insertions(+), 6 deletions(-)
10
11Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
12
13CVE: CVE-2020-12100
14Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
15Comment: No change in any hunk
16
17diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
18index aaa8dd8b7..2edf3e7a6 100644
19--- a/src/lib-mail/message-parser.c
20+++ b/src/lib-mail/message-parser.c
21@@ -167,16 +167,17 @@ static int message_parser_read_more(struct message_parser_ctx *ctx,
22 return 1;
23 }
24
25-static struct message_part *
26-message_part_append(pool_t pool, struct message_part *parent)
27+static void
28+message_part_append(struct message_parser_ctx *ctx)
29 {
30+ struct message_part *parent = ctx->part;
31 struct message_part *p, *part, **list;
32
33 i_assert(parent != NULL);
34 i_assert((parent->flags & (MESSAGE_PART_FLAG_MULTIPART |
35 MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0);
36
37- part = p_new(pool, struct message_part, 1);
38+ part = p_new(ctx->part_pool, struct message_part, 1);
39 part->parent = parent;
40 for (p = parent; p != NULL; p = p->parent)
41 p->children_count++;
42@@ -192,7 +193,7 @@ message_part_append(pool_t pool, struct message_part *parent)
43 list = &(*list)->next;
44
45 *list = part;
46- return part;
47+ ctx->part = part;
48 }
49
50 static void message_part_finish(struct message_parser_ctx *ctx)
51@@ -220,7 +221,7 @@ static void parse_next_body_multipart_init(struct message_parser_ctx *ctx)
52 static int parse_next_body_message_rfc822_init(struct message_parser_ctx *ctx,
53 struct message_block *block_r)
54 {
55- ctx->part = message_part_append(ctx->part_pool, ctx->part);
56+ message_part_append(ctx);
57 return parse_next_header_init(ctx, block_r);
58 }
59
60@@ -270,7 +271,7 @@ boundary_line_find(struct message_parser_ctx *ctx,
61 static int parse_next_mime_header_init(struct message_parser_ctx *ctx,
62 struct message_block *block_r)
63 {
64- ctx->part = message_part_append(ctx->part_pool, ctx->part);
65+ message_part_append(ctx);
66 ctx->part->flags |= MESSAGE_PART_FLAG_IS_MIME;
67
68 return parse_next_header_init(ctx, block_r);
69--
702.11.0
71
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0003-lib-mail-message-parser-Optimize-updating-children_c.patch b/meta-networking/recipes-support/dovecot/dovecot/0003-lib-mail-message-parser-Optimize-updating-children_c.patch
new file mode 100644
index 000000000..e53090235
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0003-lib-mail-message-parser-Optimize-updating-children_c.patch
@@ -0,0 +1,49 @@
1From a9800b436fcf1f9633c2b136a9c5cb7a486a8a52 Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 23 Apr 2020 11:36:48 +0300
4Subject: [PATCH 03/13] lib-mail: message-parser - Optimize updating
5 children_count
6
7---
8 src/lib-mail/message-parser.c | 5 ++---
9 1 file changed, 2 insertions(+), 3 deletions(-)
10
11Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
12
13CVE: CVE-2020-12100
14Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
15Comment: No change in any hunk
16
17diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
18index 2edf3e7a6..05768a058 100644
19--- a/src/lib-mail/message-parser.c
20+++ b/src/lib-mail/message-parser.c
21@@ -171,7 +171,7 @@ static void
22 message_part_append(struct message_parser_ctx *ctx)
23 {
24 struct message_part *parent = ctx->part;
25- struct message_part *p, *part, **list;
26+ struct message_part *part, **list;
27
28 i_assert(parent != NULL);
29 i_assert((parent->flags & (MESSAGE_PART_FLAG_MULTIPART |
30@@ -179,8 +179,6 @@ message_part_append(struct message_parser_ctx *ctx)
31
32 part = p_new(ctx->part_pool, struct message_part, 1);
33 part->parent = parent;
34- for (p = parent; p != NULL; p = p->parent)
35- p->children_count++;
36
37 /* set child position */
38 part->physical_pos =
39@@ -200,6 +198,7 @@ static void message_part_finish(struct message_parser_ctx *ctx)
40 {
41 message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size);
42 message_size_add(&ctx->part->parent->body_size, &ctx->part->header_size);
43+ ctx->part->parent->children_count += 1 + ctx->part->children_count;
44 ctx->part = ctx->part->parent;
45 }
46
47--
482.11.0
49
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0004-lib-mail-message-parser-Optimize-appending-new-part-.patch b/meta-networking/recipes-support/dovecot/dovecot/0004-lib-mail-message-parser-Optimize-appending-new-part-.patch
new file mode 100644
index 000000000..c35bf883e
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0004-lib-mail-message-parser-Optimize-appending-new-part-.patch
@@ -0,0 +1,88 @@
1From 99ee7596712cf0ea0a288b712bc898ecb2b35f9b Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 23 Apr 2020 12:00:38 +0300
4Subject: [PATCH 04/13] lib-mail: message-parser - Optimize appending new part
5 to linked list
6
7---
8 src/lib-mail/message-parser.c | 28 ++++++++++++++++++++++------
9 1 file changed, 22 insertions(+), 6 deletions(-)
10
11Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
12
13CVE: CVE-2020-12100
14Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
15Comment: No change in any hunk
16
17--- a/src/lib-mail/message-parser.c
18+++ b/src/lib-mail/message-parser.c
19@@ -1,7 +1,7 @@
20 /* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
21
22 #include "lib.h"
23-#include "buffer.h"
24+#include "array.h"
25 #include "str.h"
26 #include "istream.h"
27 #include "rfc822-parser.h"
28@@ -34,6 +34,9 @@ struct message_parser_ctx {
29 const char *last_boundary;
30 struct message_boundary *boundaries;
31
32+ struct message_part **next_part;
33+ ARRAY(struct message_part **) next_part_stack;
34+
35 size_t skip;
36 char last_chr;
37 unsigned int want_count;
38@@ -171,7 +174,7 @@ static void
39 message_part_append(struct message_parser_ctx *ctx)
40 {
41 struct message_part *parent = ctx->part;
42- struct message_part *part, **list;
43+ struct message_part *part;
44
45 i_assert(parent != NULL);
46 i_assert((parent->flags & (MESSAGE_PART_FLAG_MULTIPART |
47@@ -186,16 +189,27 @@ message_part_append(struct message_parse
48 parent->body_size.physical_size +
49 parent->header_size.physical_size;
50
51- list = &part->parent->children;
52- while (*list != NULL)
53- list = &(*list)->next;
54+ /* add to parent's linked list */
55+ *ctx->next_part = part;
56+ /* update the parent's end-of-linked-list pointer */
57+ struct message_part **next_part = &part->next;
58+ array_append(&ctx->next_part_stack, &next_part, 1);
59+ /* This part is now the new parent for the next message_part_append()
60+ call. Its linked list begins with the children pointer. */
61+ ctx->next_part = &part->children;
62
63- *list = part;
64 ctx->part = part;
65 }
66
67 static void message_part_finish(struct message_parser_ctx *ctx)
68 {
69+ struct message_part **const *parent_next_partp;
70+ unsigned int count = array_count(&ctx->next_part_stack);
71+
72+ parent_next_partp = array_idx(&ctx->next_part_stack, count-1);
73+ array_delete(&ctx->next_part_stack, count-1, 1);
74+ ctx->next_part = *parent_next_partp;
75+
76 message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size);
77 message_size_add(&ctx->part->parent->body_size, &ctx->part->header_size);
78 ctx->part->parent->children_count += 1 + ctx->part->children_count;
79@@ -1062,7 +1076,9 @@ message_parser_init(pool_t part_pool, st
80 ctx = message_parser_init_int(input, hdr_flags, flags);
81 ctx->part_pool = part_pool;
82 ctx->parts = ctx->part = p_new(part_pool, struct message_part, 1);
83+ ctx->next_part = &ctx->part->children;
84 ctx->parse_next_block = parse_next_header_init;
85+ p_array_init(&ctx->next_part_stack, ctx->parser_pool, 4);
86 return ctx;
87 }
88
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0005-lib-mail-message-parser-Minor-code-cleanup-to-findin.patch b/meta-networking/recipes-support/dovecot/dovecot/0005-lib-mail-message-parser-Minor-code-cleanup-to-findin.patch
new file mode 100644
index 000000000..4e63509b4
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0005-lib-mail-message-parser-Minor-code-cleanup-to-findin.patch
@@ -0,0 +1,45 @@
1From e39c95b248917eb2b596ca55a957f3cbc7fd406f Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 23 Apr 2020 12:10:07 +0300
4Subject: [PATCH 05/13] lib-mail: message-parser - Minor code cleanup to
5 finding the end of boundary line
6
7---
8 src/lib-mail/message-parser.c | 9 ++++-----
9 1 file changed, 4 insertions(+), 5 deletions(-)
10
11Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
12
13CVE: CVE-2020-12100
14Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
15Comment: No change in any hunk
16
17diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
18index ff4e09e5a..6c6a680b5 100644
19--- a/src/lib-mail/message-parser.c
20+++ b/src/lib-mail/message-parser.c
21@@ -260,17 +260,16 @@ boundary_line_find(struct message_parser_ctx *ctx,
22 }
23
24 /* need to find the end of line */
25- if (memchr(data + 2, '\n', size - 2) == NULL &&
26- size < BOUNDARY_END_MAX_LEN &&
27+ data += 2;
28+ size -= 2;
29+ if (memchr(data, '\n', size) == NULL &&
30+ size+2 < BOUNDARY_END_MAX_LEN &&
31 !ctx->input->eof && !full) {
32 /* no LF found */
33 ctx->want_count = BOUNDARY_END_MAX_LEN;
34 return 0;
35 }
36
37- data += 2;
38- size -= 2;
39-
40 *boundary_r = boundary_find(ctx->boundaries, data, size);
41 if (*boundary_r == NULL)
42 return -1;
43--
442.11.0
45
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0006-lib-mail-message-parser-Truncate-excessively-long-MI.patch b/meta-networking/recipes-support/dovecot/dovecot/0006-lib-mail-message-parser-Truncate-excessively-long-MI.patch
new file mode 100644
index 000000000..1012d7983
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0006-lib-mail-message-parser-Truncate-excessively-long-MI.patch
@@ -0,0 +1,163 @@
1From aed125484a346b4893c1a169088c39fe7ced01f3 Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 23 Apr 2020 12:53:12 +0300
4Subject: [PATCH 06/13] lib-mail: message-parser - Truncate excessively long
5 MIME boundaries
6
7RFC 2046 requires that the boundaries are a maximum of 70 characters
8(excluding the "--" prefix and suffix). We allow 80 characters for a bit of
9extra safety. Anything longer than that is truncated and treated the same
10as if it was just 80 characters.
11---
12 src/lib-mail/message-parser.c | 7 ++-
13 src/lib-mail/test-message-parser.c | 95 ++++++++++++++++++++++++++++++++++++++
14 2 files changed, 100 insertions(+), 2 deletions(-)
15
16Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
17
18CVE: CVE-2020-12100
19Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
20Comment: No change in any hunk
21
22diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
23index 6c6a680b5..92f541b02 100644
24--- a/src/lib-mail/message-parser.c
25+++ b/src/lib-mail/message-parser.c
26@@ -10,7 +10,8 @@
27
28 /* RFC-2046 requires boundaries are max. 70 chars + "--" prefix + "--" suffix.
29 We'll add a bit more just in case. */
30-#define BOUNDARY_END_MAX_LEN (70 + 2 + 2 + 10)
31+#define BOUNDARY_STRING_MAX_LEN (70 + 10)
32+#define BOUNDARY_END_MAX_LEN (BOUNDARY_STRING_MAX_LEN + 2 + 2)
33
34 struct message_boundary {
35 struct message_boundary *next;
36@@ -526,8 +527,10 @@ static void parse_content_type(struct message_parser_ctx *ctx,
37 rfc2231_parse(&parser, &results);
38 for (; *results != NULL; results += 2) {
39 if (strcasecmp(results[0], "boundary") == 0) {
40+ /* truncate excessively long boundaries */
41 ctx->last_boundary =
42- p_strdup(ctx->parser_pool, results[1]);
43+ p_strndup(ctx->parser_pool, results[1],
44+ BOUNDARY_STRING_MAX_LEN);
45 break;
46 }
47 }
48diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c
49index 1f1aa1437..94aa3eb7c 100644
50--- a/src/lib-mail/test-message-parser.c
51+++ b/src/lib-mail/test-message-parser.c
52@@ -642,6 +642,100 @@ static void test_message_parser_no_eoh(void)
53 test_end();
54 }
55
56+static void test_message_parser_long_mime_boundary(void)
57+{
58+ /* Close the boundaries in wrong reverse order. But because all
59+ boundaries are actually truncated to the same size (..890) it
60+ works the same as if all of them were duplicate boundaries. */
61+static const char input_msg[] =
62+"Content-Type: multipart/mixed; boundary=\"1234567890123456789012345678901234567890123456789012345678901234567890123456789012\"\n"
63+"\n"
64+"--1234567890123456789012345678901234567890123456789012345678901234567890123456789012\n"
65+"Content-Type: multipart/mixed; boundary=\"123456789012345678901234567890123456789012345678901234567890123456789012345678901\"\n"
66+"\n"
67+"--123456789012345678901234567890123456789012345678901234567890123456789012345678901\n"
68+"Content-Type: multipart/mixed; boundary=\"12345678901234567890123456789012345678901234567890123456789012345678901234567890\"\n"
69+"\n"
70+"--12345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
71+"Content-Type: text/plain\n"
72+"\n"
73+"1\n"
74+"--1234567890123456789012345678901234567890123456789012345678901234567890123456789012\n"
75+"Content-Type: text/plain\n"
76+"\n"
77+"22\n"
78+"--123456789012345678901234567890123456789012345678901234567890123456789012345678901\n"
79+"Content-Type: text/plain\n"
80+"\n"
81+"333\n"
82+"--12345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
83+"Content-Type: text/plain\n"
84+"\n"
85+"4444\n";
86+ struct message_parser_ctx *parser;
87+ struct istream *input;
88+ struct message_part *parts, *part;
89+ struct message_block block;
90+ pool_t pool;
91+ int ret;
92+
93+ test_begin("message parser long mime boundary");
94+ pool = pool_alloconly_create("message parser", 10240);
95+ input = test_istream_create(input_msg);
96+
97+ parser = message_parser_init(pool, input, 0, 0);
98+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
99+ test_assert(ret < 0);
100+ message_parser_deinit(&parser, &parts);
101+
102+ part = parts;
103+ test_assert(part->children_count == 6);
104+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
105+ test_assert(part->header_size.lines == 2);
106+ test_assert(part->header_size.physical_size == 126);
107+ test_assert(part->header_size.virtual_size == 126+2);
108+ test_assert(part->body_size.lines == 22);
109+ test_assert(part->body_size.physical_size == 871);
110+ test_assert(part->body_size.virtual_size == 871+22);
111+
112+ part = parts->children;
113+ test_assert(part->children_count == 5);
114+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
115+ test_assert(part->header_size.lines == 2);
116+ test_assert(part->header_size.physical_size == 125);
117+ test_assert(part->header_size.virtual_size == 125+2);
118+ test_assert(part->body_size.lines == 19);
119+ test_assert(part->body_size.physical_size == 661);
120+ test_assert(part->body_size.virtual_size == 661+19);
121+
122+ part = parts->children->children;
123+ test_assert(part->children_count == 4);
124+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
125+ test_assert(part->header_size.lines == 2);
126+ test_assert(part->header_size.physical_size == 124);
127+ test_assert(part->header_size.virtual_size == 124+2);
128+ test_assert(part->body_size.lines == 16);
129+ test_assert(part->body_size.physical_size == 453);
130+ test_assert(part->body_size.virtual_size == 453+16);
131+
132+ part = parts->children->children->children;
133+ for (unsigned int i = 1; i <= 3; i++, part = part->next) {
134+ test_assert(part->children_count == 0);
135+ test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME));
136+ test_assert(part->header_size.lines == 2);
137+ test_assert(part->header_size.physical_size == 26);
138+ test_assert(part->header_size.virtual_size == 26+2);
139+ test_assert(part->body_size.lines == 0);
140+ test_assert(part->body_size.physical_size == i);
141+ test_assert(part->body_size.virtual_size == i);
142+ }
143+
144+ test_parsed_parts(input, parts);
145+ i_stream_unref(&input);
146+ pool_unref(&pool);
147+ test_end();
148+}
149+
150 int main(void)
151 {
152 static void (*test_functions[])(void) = {
153@@ -654,6 +748,7 @@ int main(void)
154 test_message_parser_garbage_suffix_mime_boundary,
155 test_message_parser_continuing_mime_boundary,
156 test_message_parser_continuing_truncated_mime_boundary,
157+ test_message_parser_long_mime_boundary,
158 test_message_parser_no_eoh,
159 NULL
160 };
161--
1622.11.0
163
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0007-lib-mail-message-parser-Optimize-boundary-lookups-wh.patch b/meta-networking/recipes-support/dovecot/dovecot/0007-lib-mail-message-parser-Optimize-boundary-lookups-wh.patch
new file mode 100644
index 000000000..eeb6c96f1
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0007-lib-mail-message-parser-Optimize-boundary-lookups-wh.patch
@@ -0,0 +1,72 @@
1From 5f8de52fec3191a1aa68a399ee2068485737dc4f Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 23 Apr 2020 13:06:02 +0300
4Subject: [PATCH 07/13] lib-mail: message-parser - Optimize boundary lookups
5 when exact boundary is found
6
7When an exact boundary is found, there's no need to continue looking for
8more boundaries.
9---
10 src/lib-mail/message-parser.c | 26 ++++++++++++++++++++++----
11 1 file changed, 22 insertions(+), 4 deletions(-)
12
13Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
14
15CVE: CVE-2020-12100
16Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
17Comment: No change in any hunk
18
19diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
20index 92f541b02..c2934c761 100644
21--- a/src/lib-mail/message-parser.c
22+++ b/src/lib-mail/message-parser.c
23@@ -80,8 +80,14 @@ boundary_find(struct message_boundary *boundaries,
24 while (boundaries != NULL) {
25 if (boundaries->len <= len &&
26 memcmp(boundaries->boundary, data, boundaries->len) == 0 &&
27- (best == NULL || best->len < boundaries->len))
28+ (best == NULL || best->len < boundaries->len)) {
29 best = boundaries;
30+ if (best->len == len) {
31+ /* This is exactly the wanted boundary. There
32+ can't be a better one. */
33+ break;
34+ }
35+ }
36
37 boundaries = boundaries->next;
38 }
39@@ -263,15 +269,27 @@ boundary_line_find(struct message_parser_ctx *ctx,
40 /* need to find the end of line */
41 data += 2;
42 size -= 2;
43- if (memchr(data, '\n', size) == NULL &&
44+ const unsigned char *lf_pos = memchr(data, '\n', size);
45+ if (lf_pos == NULL &&
46 size+2 < BOUNDARY_END_MAX_LEN &&
47 !ctx->input->eof && !full) {
48 /* no LF found */
49 ctx->want_count = BOUNDARY_END_MAX_LEN;
50 return 0;
51 }
52-
53- *boundary_r = boundary_find(ctx->boundaries, data, size);
54+ size_t find_size = size;
55+
56+ if (lf_pos != NULL) {
57+ find_size = lf_pos - data;
58+ if (find_size > 0 && data[find_size-1] == '\r')
59+ find_size--;
60+ if (find_size > 2 && data[find_size-1] == '-' &&
61+ data[find_size-2] == '-')
62+ find_size -= 2;
63+ } else if (find_size > BOUNDARY_END_MAX_LEN)
64+ find_size = BOUNDARY_END_MAX_LEN;
65+
66+ *boundary_r = boundary_find(ctx->boundaries, data, find_size);
67 if (*boundary_r == NULL)
68 return -1;
69
70--
712.11.0
72
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0008-lib-mail-message-parser-Add-boundary_remove_until-he.patch b/meta-networking/recipes-support/dovecot/dovecot/0008-lib-mail-message-parser-Add-boundary_remove_until-he.patch
new file mode 100644
index 000000000..4af070a87
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0008-lib-mail-message-parser-Add-boundary_remove_until-he.patch
@@ -0,0 +1,50 @@
1From 929396767d831bedbdec6392aaa835b045332fd3 Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 23 Apr 2020 14:53:27 +0300
4Subject: [PATCH 08/13] lib-mail: message-parser - Add boundary_remove_until()
5 helper function
6
7---
8 src/lib-mail/message-parser.c | 11 +++++++++--
9 1 file changed, 9 insertions(+), 2 deletions(-)
10
11Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
12
13CVE: CVE-2020-12100
14Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
15Comment: No change in any hunk
16
17diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
18index c2934c761..028f74159 100644
19--- a/src/lib-mail/message-parser.c
20+++ b/src/lib-mail/message-parser.c
21@@ -223,6 +223,13 @@ static void message_part_finish(struct message_parser_ctx *ctx)
22 ctx->part = ctx->part->parent;
23 }
24
25+static void
26+boundary_remove_until(struct message_parser_ctx *ctx,
27+ struct message_boundary *boundary)
28+{
29+ ctx->boundaries = boundary;
30+}
31+
32 static void parse_next_body_multipart_init(struct message_parser_ctx *ctx)
33 {
34 struct message_boundary *b;
35@@ -364,10 +371,10 @@ static int parse_part_finish(struct message_parser_ctx *ctx,
36
37 if (boundary->epilogue_found) {
38 /* this boundary isn't needed anymore */
39- ctx->boundaries = boundary->next;
40+ boundary_remove_until(ctx, boundary->next);
41 } else {
42 /* forget about the boundaries we possibly skipped */
43- ctx->boundaries = boundary;
44+ boundary_remove_until(ctx, boundary);
45 }
46
47 /* the boundary itself should already be in buffer. add that. */
48--
492.11.0
50
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0009-lib-mail-message-parser-Don-t-use-memory-pool-for-pa.patch b/meta-networking/recipes-support/dovecot/dovecot/0009-lib-mail-message-parser-Don-t-use-memory-pool-for-pa.patch
new file mode 100644
index 000000000..aade7dc2b
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0009-lib-mail-message-parser-Don-t-use-memory-pool-for-pa.patch
@@ -0,0 +1,169 @@
1From d53d83214b1d635446a8cf8ff9438cc530133d62 Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 23 Apr 2020 15:00:57 +0300
4Subject: [PATCH 09/13] lib-mail: message-parser - Don't use memory pool for
5 parser
6
7This reduces memory usage when parsing many MIME parts where boundaries are
8being added and removed constantly.
9---
10 src/lib-mail/message-parser.c | 48 ++++++++++++++++++++++++++++---------------
11 1 file changed, 32 insertions(+), 16 deletions(-)
12
13Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
14
15CVE: CVE-2020-12100
16Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
17Comment: No change in any hunk
18
19diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
20index 028f74159..8970d8e0e 100644
21--- a/src/lib-mail/message-parser.c
22+++ b/src/lib-mail/message-parser.c
23@@ -17,14 +17,14 @@ struct message_boundary {
24 struct message_boundary *next;
25
26 struct message_part *part;
27- const char *boundary;
28+ char *boundary;
29 size_t len;
30
31 unsigned int epilogue_found:1;
32 };
33
34 struct message_parser_ctx {
35- pool_t parser_pool, part_pool;
36+ pool_t part_pool;
37 struct istream *input;
38 struct message_part *parts, *part;
39 const char *broken_reason;
40@@ -32,7 +32,7 @@ struct message_parser_ctx {
41 enum message_header_parser_flags hdr_flags;
42 enum message_parser_flags flags;
43
44- const char *last_boundary;
45+ char *last_boundary;
46 struct message_boundary *boundaries;
47
48 struct message_part **next_part;
49@@ -223,10 +223,24 @@ static void message_part_finish(struct message_parser_ctx *ctx)
50 ctx->part = ctx->part->parent;
51 }
52
53+static void message_boundary_free(struct message_boundary *b)
54+{
55+ i_free(b->boundary);
56+ i_free(b);
57+}
58+
59 static void
60 boundary_remove_until(struct message_parser_ctx *ctx,
61 struct message_boundary *boundary)
62 {
63+ while (ctx->boundaries != boundary) {
64+ struct message_boundary *cur = ctx->boundaries;
65+
66+ i_assert(cur != NULL);
67+ ctx->boundaries = cur->next;
68+ message_boundary_free(cur);
69+
70+ }
71 ctx->boundaries = boundary;
72 }
73
74@@ -234,15 +248,14 @@ static void parse_next_body_multipart_init(struct message_parser_ctx *ctx)
75 {
76 struct message_boundary *b;
77
78- b = p_new(ctx->parser_pool, struct message_boundary, 1);
79+ b = i_new(struct message_boundary, 1);
80 b->part = ctx->part;
81 b->boundary = ctx->last_boundary;
82+ ctx->last_boundary = NULL;
83 b->len = strlen(b->boundary);
84
85 b->next = ctx->boundaries;
86 ctx->boundaries = b;
87-
88- ctx->last_boundary = NULL;
89 }
90
91 static int parse_next_body_message_rfc822_init(struct message_parser_ctx *ctx,
92@@ -359,6 +372,8 @@ static int parse_part_finish(struct message_parser_ctx *ctx,
93 struct message_block *block_r, bool first_line)
94 {
95 size_t line_size;
96+ size_t boundary_len = boundary->len;
97+ bool boundary_epilogue_found = boundary->epilogue_found;
98
99 i_assert(ctx->last_boundary == NULL);
100
101@@ -391,7 +406,7 @@ static int parse_part_finish(struct message_parser_ctx *ctx,
102 i_assert(block_r->data[0] == '\n');
103 line_size = 1;
104 }
105- line_size += 2 + boundary->len + (boundary->epilogue_found ? 2 : 0);
106+ line_size += 2 + boundary_len + (boundary_epilogue_found ? 2 : 0);
107 i_assert(block_r->size >= ctx->skip + line_size);
108 block_r->size = line_size;
109 parse_body_add_block(ctx, block_r);
110@@ -553,9 +568,9 @@ static void parse_content_type(struct message_parser_ctx *ctx,
111 for (; *results != NULL; results += 2) {
112 if (strcasecmp(results[0], "boundary") == 0) {
113 /* truncate excessively long boundaries */
114+ i_free(ctx->last_boundary);
115 ctx->last_boundary =
116- p_strndup(ctx->parser_pool, results[1],
117- BOUNDARY_STRING_MAX_LEN);
118+ i_strndup(results[1], BOUNDARY_STRING_MAX_LEN);
119 break;
120 }
121 }
122@@ -678,7 +693,7 @@ static int parse_next_header(struct message_parser_ctx *ctx,
123 i_assert(!ctx->multipart);
124 part->flags = 0;
125 }
126- ctx->last_boundary = NULL;
127+ i_free(ctx->last_boundary);
128
129 if (!ctx->part_seen_content_type ||
130 (part->flags & MESSAGE_PART_FLAG_IS_MIME) == 0) {
131@@ -1081,11 +1096,8 @@ message_parser_init_int(struct istream *input,
132 enum message_parser_flags flags)
133 {
134 struct message_parser_ctx *ctx;
135- pool_t pool;
136
137- pool = pool_alloconly_create("Message Parser", 1024);
138- ctx = p_new(pool, struct message_parser_ctx, 1);
139- ctx->parser_pool = pool;
140+ ctx = i_new(struct message_parser_ctx, 1);
141 ctx->hdr_flags = hdr_flags;
142 ctx->flags = flags;
143 ctx->input = input;
144@@ -1105,7 +1117,7 @@ message_parser_init(pool_t part_pool, struct istream *input,
145 ctx->parts = ctx->part = p_new(part_pool, struct message_part, 1);
146 ctx->next_part = &ctx->part->children;
147 ctx->parse_next_block = parse_next_header_init;
148- p_array_init(&ctx->next_part_stack, ctx->parser_pool, 4);
149+ i_array_init(&ctx->next_part_stack, 4);
150 return ctx;
151 }
152
153@@ -1146,8 +1158,12 @@ int message_parser_deinit_from_parts(struct message_parser_ctx **_ctx,
154
155 if (ctx->hdr_parser_ctx != NULL)
156 message_parse_header_deinit(&ctx->hdr_parser_ctx);
157+ boundary_remove_until(ctx, NULL);
158 i_stream_unref(&ctx->input);
159- pool_unref(&ctx->parser_pool);
160+ if (array_is_created(&ctx->next_part_stack))
161+ array_free(&ctx->next_part_stack);
162+ i_free(ctx->last_boundary);
163+ i_free(ctx);
164 i_assert(ret < 0 || *parts_r != NULL);
165 return ret;
166 }
167--
1682.11.0
169
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0010-lib-mail-message-parser-Support-limiting-max-number-.patch b/meta-networking/recipes-support/dovecot/dovecot/0010-lib-mail-message-parser-Support-limiting-max-number-.patch
new file mode 100644
index 000000000..ae5254466
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0010-lib-mail-message-parser-Support-limiting-max-number-.patch
@@ -0,0 +1,188 @@
1From df9e0d358ef86e3342525dcdefcf79dc2d749a30 Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 23 Apr 2020 16:59:40 +0300
4Subject: [PATCH 10/13] lib-mail: message-parser - Support limiting max number
5 of nested MIME parts
6
7The default is to allow 100 nested MIME parts. When the limit is reached,
8the innermost MIME part's body contains all the rest of the inner bodies
9until a parent MIME part is reached.
10---
11 src/lib-mail/message-parser.c | 43 +++++++++++++++++++++++++++++++-------
12 src/lib-mail/test-message-parser.c | 31 +++++++++++++++++++++++++++
13 2 files changed, 67 insertions(+), 7 deletions(-)
14
15Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
16
17CVE: CVE-2020-12100
18Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
19Comment: No change in any hunk
20
21diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
22index 8970d8e0e..721615f76 100644
23--- a/src/lib-mail/message-parser.c
24+++ b/src/lib-mail/message-parser.c
25@@ -13,6 +13,8 @@
26 #define BOUNDARY_STRING_MAX_LEN (70 + 10)
27 #define BOUNDARY_END_MAX_LEN (BOUNDARY_STRING_MAX_LEN + 2 + 2)
28
29+#define MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS 100
30+
31 struct message_boundary {
32 struct message_boundary *next;
33
34@@ -28,9 +30,11 @@ struct message_parser_ctx {
35 struct istream *input;
36 struct message_part *parts, *part;
37 const char *broken_reason;
38+ unsigned int nested_parts_count;
39
40 enum message_header_parser_flags hdr_flags;
41 enum message_parser_flags flags;
42+ unsigned int max_nested_mime_parts;
43
44 char *last_boundary;
45 struct message_boundary *boundaries;
46@@ -206,6 +210,8 @@ message_part_append(struct message_parser_ctx *ctx)
47 ctx->next_part = &part->children;
48
49 ctx->part = part;
50+ ctx->nested_parts_count++;
51+ i_assert(ctx->nested_parts_count < ctx->max_nested_mime_parts);
52 }
53
54 static void message_part_finish(struct message_parser_ctx *ctx)
55@@ -213,8 +219,12 @@ static void message_part_finish(struct message_parser_ctx *ctx)
56 struct message_part **const *parent_next_partp;
57 unsigned int count = array_count(&ctx->next_part_stack);
58
59+ i_assert(ctx->nested_parts_count > 0);
60+ ctx->nested_parts_count--;
61+
62 parent_next_partp = array_idx(&ctx->next_part_stack, count-1);
63 array_delete(&ctx->next_part_stack, count-1, 1);
64+
65 ctx->next_part = *parent_next_partp;
66
67 message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size);
68@@ -592,6 +602,11 @@ static bool block_is_at_eoh(const struct message_block *block)
69 return FALSE;
70 }
71
72+static bool parse_too_many_nested_mime_parts(struct message_parser_ctx *ctx)
73+{
74+ return ctx->nested_parts_count > ctx->max_nested_mime_parts;
75+}
76+
77 #define MUTEX_FLAGS \
78 (MESSAGE_PART_FLAG_MESSAGE_RFC822 | MESSAGE_PART_FLAG_MULTIPART)
79
80@@ -616,8 +631,12 @@ static int parse_next_header(struct message_parser_ctx *ctx,
81 "\n--boundary" belongs to us or to a previous boundary.
82 this is a problem if the boundary prefixes are identical,
83 because MIME requires only the prefix to match. */
84- parse_next_body_multipart_init(ctx);
85- ctx->multipart = TRUE;
86+ if (!parse_too_many_nested_mime_parts(ctx)) {
87+ parse_next_body_multipart_init(ctx);
88+ ctx->multipart = TRUE;
89+ } else {
90+ part->flags &= ~MESSAGE_PART_FLAG_MULTIPART;
91+ }
92 }
93
94 /* before parsing the header see if we can find a --boundary from here.
95@@ -721,12 +740,16 @@ static int parse_next_header(struct message_parser_ctx *ctx,
96 i_assert(ctx->last_boundary == NULL);
97 ctx->multipart = FALSE;
98 ctx->parse_next_block = parse_next_body_to_boundary;
99- } else if (part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822)
100+ } else if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0 &&
101+ !parse_too_many_nested_mime_parts(ctx)) {
102 ctx->parse_next_block = parse_next_body_message_rfc822_init;
103- else if (ctx->boundaries != NULL)
104- ctx->parse_next_block = parse_next_body_to_boundary;
105- else
106- ctx->parse_next_block = parse_next_body_to_eof;
107+ } else {
108+ part->flags &= ~MESSAGE_PART_FLAG_MESSAGE_RFC822;
109+ if (ctx->boundaries != NULL)
110+ ctx->parse_next_block = parse_next_body_to_boundary;
111+ else
112+ ctx->parse_next_block = parse_next_body_to_eof;
113+ }
114
115 ctx->want_count = 1;
116
117@@ -1100,6 +1123,8 @@ message_parser_init_int(struct istream *input,
118 ctx = i_new(struct message_parser_ctx, 1);
119 ctx->hdr_flags = hdr_flags;
120 ctx->flags = flags;
121+ ctx->max_nested_mime_parts =
122+ MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS;
123 ctx->input = input;
124 i_stream_ref(input);
125 return ctx;
126@@ -1159,6 +1184,10 @@ int message_parser_deinit_from_parts(struct message_parser_ctx **_ctx,
127 if (ctx->hdr_parser_ctx != NULL)
128 message_parse_header_deinit(&ctx->hdr_parser_ctx);
129 boundary_remove_until(ctx, NULL);
130+ /* caller might have stopped the parsing early */
131+ i_assert(ctx->nested_parts_count == 0 ||
132+ i_stream_have_bytes_left(ctx->input));
133+
134 i_stream_unref(&ctx->input);
135 if (array_is_created(&ctx->next_part_stack))
136 array_free(&ctx->next_part_stack);
137diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c
138index 94aa3eb7c..481d05942 100644
139--- a/src/lib-mail/test-message-parser.c
140+++ b/src/lib-mail/test-message-parser.c
141@@ -166,6 +166,36 @@ static void test_message_parser_small_blocks(void)
142 test_end();
143 }
144
145+static void test_message_parser_stop_early(void)
146+{
147+ struct message_parser_ctx *parser;
148+ struct istream *input;
149+ struct message_part *parts;
150+ struct message_block block;
151+ unsigned int i;
152+ pool_t pool;
153+ int ret;
154+
155+ test_begin("message parser stop early");
156+ pool = pool_alloconly_create("message parser", 10240);
157+ input = test_istream_create(test_msg);
158+
159+ test_istream_set_allow_eof(input, FALSE);
160+ for (i = 1; i <= TEST_MSG_LEN+1; i++) {
161+ i_stream_seek(input, 0);
162+ test_istream_set_size(input, i);
163+ parser = message_parser_init(pool, input, 0, 0);
164+ while ((ret = message_parser_parse_next_block(parser,
165+ &block)) > 0) ;
166+ test_assert(ret == 0);
167+ message_parser_deinit(&parser, &parts);
168+ }
169+
170+ i_stream_unref(&input);
171+ pool_unref(&pool);
172+ test_end();
173+}
174+
175 static void test_message_parser_truncated_mime_headers(void)
176 {
177 static const char input_msg[] =
178@@ -740,6 +770,7 @@ int main(void)
179 {
180 static void (*test_functions[])(void) = {
181 test_message_parser_small_blocks,
182+ test_message_parser_stop_early,
183 test_message_parser_truncated_mime_headers,
184 test_message_parser_truncated_mime_headers2,
185 test_message_parser_truncated_mime_headers3,
186--
1872.11.0
188
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0011-lib-mail-message-parser-Support-limiting-max-number-.patch b/meta-networking/recipes-support/dovecot/dovecot/0011-lib-mail-message-parser-Support-limiting-max-number-.patch
new file mode 100644
index 000000000..52848bf3a
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0011-lib-mail-message-parser-Support-limiting-max-number-.patch
@@ -0,0 +1,87 @@
1From d7bba401dd234802bcdb55ff27dfb99bffdab804 Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 23 Apr 2020 17:09:33 +0300
4Subject: [PATCH 11/13] lib-mail: message-parser - Support limiting max number
5 of MIME parts
6
7The default is to allow 10000 MIME parts. When it's reached, no more
8MIME boundary lines will be recognized, so the rest of the mail belongs
9to the last added MIME part.
10---
11 src/lib-mail/message-parser.c | 14 ++++++++++++++
12 1 file changed, 14 insertions(+)
13
14Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
15
16CVE: CVE-2020-12100
17Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
18Comment: No change in any hunk
19
20diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
21index 721615f76..646307802 100644
22--- a/src/lib-mail/message-parser.c
23+++ b/src/lib-mail/message-parser.c
24@@ -14,6 +14,7 @@
25 #define BOUNDARY_END_MAX_LEN (BOUNDARY_STRING_MAX_LEN + 2 + 2)
26
27 #define MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS 100
28+#define MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS 10000
29
30 struct message_boundary {
31 struct message_boundary *next;
32@@ -31,10 +32,12 @@ struct message_parser_ctx {
33 struct message_part *parts, *part;
34 const char *broken_reason;
35 unsigned int nested_parts_count;
36+ unsigned int total_parts_count;
37
38 enum message_header_parser_flags hdr_flags;
39 enum message_parser_flags flags;
40 unsigned int max_nested_mime_parts;
41+ unsigned int max_total_mime_parts;
42
43 char *last_boundary;
44 struct message_boundary *boundaries;
45@@ -211,7 +214,9 @@ message_part_append(struct message_parser_ctx *ctx)
46
47 ctx->part = part;
48 ctx->nested_parts_count++;
49+ ctx->total_parts_count++;
50 i_assert(ctx->nested_parts_count < ctx->max_nested_mime_parts);
51+ i_assert(ctx->total_parts_count <= ctx->max_total_mime_parts);
52 }
53
54 static void message_part_finish(struct message_parser_ctx *ctx)
55@@ -296,6 +301,12 @@ boundary_line_find(struct message_parser_ctx *ctx,
56 return -1;
57 }
58
59+ if (ctx->total_parts_count >= ctx->max_total_mime_parts) {
60+ /* can't add any more MIME parts. just stop trying to find
61+ more boundaries. */
62+ return -1;
63+ }
64+
65 /* need to find the end of line */
66 data += 2;
67 size -= 2;
68@@ -1125,6 +1136,8 @@ message_parser_init_int(struct istream *input,
69 ctx->flags = flags;
70 ctx->max_nested_mime_parts =
71 MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS;
72+ ctx->max_total_mime_parts =
73+ MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS;
74 ctx->input = input;
75 i_stream_ref(input);
76 return ctx;
77@@ -1142,6 +1155,7 @@ message_parser_init(pool_t part_pool, struct istream *input,
78 ctx->parts = ctx->part = p_new(part_pool, struct message_part, 1);
79 ctx->next_part = &ctx->part->children;
80 ctx->parse_next_block = parse_next_header_init;
81+ ctx->total_parts_count = 1;
82 i_array_init(&ctx->next_part_stack, 4);
83 return ctx;
84 }
85--
862.11.0
87
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0012-lib-mail-Fix-handling-trailing-in-MIME-boundaries.patch b/meta-networking/recipes-support/dovecot/dovecot/0012-lib-mail-Fix-handling-trailing-in-MIME-boundaries.patch
new file mode 100644
index 000000000..a81177d2b
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0012-lib-mail-Fix-handling-trailing-in-MIME-boundaries.patch
@@ -0,0 +1,133 @@
1From 0c9d56b41b992a868f299e05677a67c4d0495523 Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Thu, 2 Jul 2020 17:31:19 +0300
4Subject: [PATCH 12/13] lib-mail: Fix handling trailing "--" in MIME boundaries
5
6Broken by 5b8ec27fae941d06516c30476dcf4820c6d200ab
7---
8 src/lib-mail/message-parser.c | 14 ++++++++----
9 src/lib-mail/test-message-parser.c | 46 ++++++++++++++++++++++++++++++++++++++
10 2 files changed, 56 insertions(+), 4 deletions(-)
11
12Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
13
14CVE: CVE-2020-12100
15Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
16Comment: No change in any hunk
17
18diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
19index 646307802..175d4b488 100644
20--- a/src/lib-mail/message-parser.c
21+++ b/src/lib-mail/message-parser.c
22@@ -75,7 +75,7 @@ static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx,
23
24 static struct message_boundary *
25 boundary_find(struct message_boundary *boundaries,
26- const unsigned char *data, size_t len)
27+ const unsigned char *data, size_t len, bool trailing_dashes)
28 {
29 struct message_boundary *best = NULL;
30
31@@ -89,7 +89,11 @@ boundary_find(struct message_boundary *boundaries,
32 memcmp(boundaries->boundary, data, boundaries->len) == 0 &&
33 (best == NULL || best->len < boundaries->len)) {
34 best = boundaries;
35- if (best->len == len) {
36+ /* If we see "foo--", it could either mean that there
37+ is a boundary named "foo" that ends now or there's
38+ a boundary "foo--" which continues. */
39+ if (best->len == len ||
40+ (best->len == len-2 && trailing_dashes)) {
41 /* This is exactly the wanted boundary. There
42 can't be a better one. */
43 break;
44@@ -319,6 +323,7 @@ boundary_line_find(struct message_parser_ctx *ctx,
45 return 0;
46 }
47 size_t find_size = size;
48+ bool trailing_dashes = FALSE;
49
50 if (lf_pos != NULL) {
51 find_size = lf_pos - data;
52@@ -326,11 +331,12 @@ boundary_line_find(struct message_parser_ctx *ctx,
53 find_size--;
54 if (find_size > 2 && data[find_size-1] == '-' &&
55 data[find_size-2] == '-')
56- find_size -= 2;
57+ trailing_dashes = TRUE;
58 } else if (find_size > BOUNDARY_END_MAX_LEN)
59 find_size = BOUNDARY_END_MAX_LEN;
60
61- *boundary_r = boundary_find(ctx->boundaries, data, find_size);
62+ *boundary_r = boundary_find(ctx->boundaries, data, find_size,
63+ trailing_dashes);
64 if (*boundary_r == NULL)
65 return -1;
66
67diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c
68index 481d05942..113454ea0 100644
69--- a/src/lib-mail/test-message-parser.c
70+++ b/src/lib-mail/test-message-parser.c
71@@ -510,6 +510,51 @@ static const char input_msg[] =
72 test_end();
73 }
74
75+static void test_message_parser_trailing_dashes(void)
76+{
77+static const char input_msg[] =
78+"Content-Type: multipart/mixed; boundary=\"a--\"\n"
79+"\n"
80+"--a--\n"
81+"Content-Type: multipart/mixed; boundary=\"a----\"\n"
82+"\n"
83+"--a----\n"
84+"Content-Type: text/plain\n"
85+"\n"
86+"body\n"
87+"--a------\n"
88+"Content-Type: text/html\n"
89+"\n"
90+"body2\n"
91+"--a----";
92+ struct message_parser_ctx *parser;
93+ struct istream *input;
94+ struct message_part *parts;
95+ struct message_block block;
96+ pool_t pool;
97+ int ret;
98+
99+ test_begin("message parser trailing dashes");
100+ pool = pool_alloconly_create("message parser", 10240);
101+ input = test_istream_create(input_msg);
102+
103+ parser = message_parser_init(pool, input, 0, 0);
104+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
105+ test_assert(ret < 0);
106+ message_parser_deinit(&parser, &parts);
107+
108+ test_assert(parts->children_count == 2);
109+ test_assert(parts->children->next == NULL);
110+ test_assert(parts->children->children_count == 1);
111+ test_assert(parts->children->children->next == NULL);
112+ test_assert(parts->children->children->children_count == 0);
113+
114+ test_parsed_parts(input, parts);
115+ i_stream_unref(&input);
116+ pool_unref(&pool);
117+ test_end();
118+}
119+
120 static void test_message_parser_continuing_mime_boundary(void)
121 {
122 static const char input_msg[] =
123@@ -777,6 +822,7 @@ int main(void)
124 test_message_parser_empty_multipart,
125 test_message_parser_duplicate_mime_boundary,
126 test_message_parser_garbage_suffix_mime_boundary,
127+ test_message_parser_trailing_dashes,
128 test_message_parser_continuing_mime_boundary,
129 test_message_parser_continuing_truncated_mime_boundary,
130 test_message_parser_long_mime_boundary,
131--
1322.11.0
133
diff --git a/meta-networking/recipes-support/dovecot/dovecot/0013-lib-mail-Fix-parse_too_many_nested_mime_parts.patch b/meta-networking/recipes-support/dovecot/dovecot/0013-lib-mail-Fix-parse_too_many_nested_mime_parts.patch
new file mode 100644
index 000000000..97068345f
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/0013-lib-mail-Fix-parse_too_many_nested_mime_parts.patch
@@ -0,0 +1,32 @@
1From f77a2b6c3ffe2ea96f4a4b05ec38dc9d53266ecb Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Wed, 27 May 2020 11:35:55 +0300
4Subject: [PATCH 13/13] lib-mail: Fix parse_too_many_nested_mime_parts()
5
6This was originally correct, until it was "optimized" wrong and got merged.
7---
8 src/lib-mail/message-parser.c | 2 +-
9 1 file changed, 1 insertion(+), 1 deletion(-)
10
11Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
12
13CVE: CVE-2020-12100
14Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
15Comment: No change in any hunk
16
17diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
18index 175d4b488..5b11772ff 100644
19--- a/src/lib-mail/message-parser.c
20+++ b/src/lib-mail/message-parser.c
21@@ -621,7 +621,7 @@ static bool block_is_at_eoh(const struct message_block *block)
22
23 static bool parse_too_many_nested_mime_parts(struct message_parser_ctx *ctx)
24 {
25- return ctx->nested_parts_count > ctx->max_nested_mime_parts;
26+ return ctx->nested_parts_count+1 >= ctx->max_nested_mime_parts;
27 }
28
29 #define MUTEX_FLAGS \
30--
312.11.0
32
diff --git a/meta-networking/recipes-support/dovecot/dovecot/buffer_free_fix.patch b/meta-networking/recipes-support/dovecot/dovecot/buffer_free_fix.patch
new file mode 100644
index 000000000..44f6564f8
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/buffer_free_fix.patch
@@ -0,0 +1,27 @@
1From 1a6ff0beebf0ab0c71081eaff1d5d7fd26015a94 Mon Sep 17 00:00:00 2001
2From: Josef 'Jeff' Sipek <jeff.sipek@dovecot.fi>
3Date: Tue, 19 Sep 2017 13:26:57 +0300
4Subject: [PATCH] lib: buffer_free(NULL) should be a no-op
5
6---
7 src/lib/buffer.c | 3 +++
8 1 file changed, 3 insertions(+)
9
10Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
11
12CVE: CVE-2020-12100
13Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/d/dovecot/dovecot_2.2.33.2-1ubuntu4.7.debian.tar.xz]
14Comment: No change in any hunk
15
16--- a/src/lib/buffer.c
17+++ b/src/lib/buffer.c
18@@ -148,6 +148,9 @@ void buffer_free(buffer_t **_buf)
19 {
20 struct real_buffer *buf = (struct real_buffer *)*_buf;
21
22+ if (buf == NULL)
23+ return;
24+
25 *_buf = NULL;
26 if (buf->alloced)
27 p_free(buf->pool, buf->w_buffer);
diff --git a/meta-networking/recipes-support/dovecot/dovecot_2.2.36.4.bb b/meta-networking/recipes-support/dovecot/dovecot_2.2.36.4.bb
index e21a94ad6..407604c81 100644
--- a/meta-networking/recipes-support/dovecot/dovecot_2.2.36.4.bb
+++ b/meta-networking/recipes-support/dovecot/dovecot_2.2.36.4.bb
@@ -10,6 +10,20 @@ SRC_URI = "http://dovecot.org/releases/2.2/dovecot-${PV}.tar.gz \
10 file://dovecot.service \ 10 file://dovecot.service \
11 file://dovecot.socket \ 11 file://dovecot.socket \
12 file://0001-doveadm-Fix-parallel-build.patch \ 12 file://0001-doveadm-Fix-parallel-build.patch \
13 file://0001-lib-mail-message-parser-Add-a-message_part_finish-he.patch \
14 file://0002-lib-mail-message-parser-Change-message_part_append-t.patch \
15 file://0003-lib-mail-message-parser-Optimize-updating-children_c.patch \
16 file://0004-lib-mail-message-parser-Optimize-appending-new-part-.patch \
17 file://0005-lib-mail-message-parser-Minor-code-cleanup-to-findin.patch \
18 file://0006-lib-mail-message-parser-Truncate-excessively-long-MI.patch \
19 file://0007-lib-mail-message-parser-Optimize-boundary-lookups-wh.patch \
20 file://0008-lib-mail-message-parser-Add-boundary_remove_until-he.patch \
21 file://0009-lib-mail-message-parser-Don-t-use-memory-pool-for-pa.patch \
22 file://0010-lib-mail-message-parser-Support-limiting-max-number-.patch \
23 file://0011-lib-mail-message-parser-Support-limiting-max-number-.patch \
24 file://0012-lib-mail-Fix-handling-trailing-in-MIME-boundaries.patch \
25 file://0013-lib-mail-Fix-parse_too_many_nested_mime_parts.patch \
26 file://buffer_free_fix.patch \
13 " 27 "
14 28
15SRC_URI[md5sum] = "66c4d71858b214afee5b390ee602dee2" 29SRC_URI[md5sum] = "66c4d71858b214afee5b390ee602dee2"