Blame SOURCES/dovecot-2.3.13-CVE_2020_25275regr-part3.patch

b62b43
From a912198bdc38421ad84044089db84fc14c69c228 Mon Sep 17 00:00:00 2001
b62b43
From: Timo Sirainen <timo.sirainen@open-xchange.com>
b62b43
Date: Wed, 18 Nov 2020 21:22:45 +0200
b62b43
Subject: [PATCH] lib-imap: Fix writing BODYSTRUCTURE for truncated
b62b43
 multipart/digest part
b62b43
b62b43
Fixes error while parsing BODYSTRUCTURE:
b62b43
message_part message/rfc822 flag doesn't match lines in BODYSTRUCTURE
b62b43
---
b62b43
 src/lib-imap/imap-bodystructure.c      |  9 +++++++++
b62b43
 src/lib-imap/test-imap-bodystructure.c | 28 ++++++++++++++++++++++----
b62b43
 2 files changed, 33 insertions(+), 4 deletions(-)
b62b43
b62b43
diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c
b62b43
index bfb6e64197..5d2e5a3a84 100644
b62b43
--- a/src/lib-imap/imap-bodystructure.c
b62b43
+++ b/src/lib-imap/imap-bodystructure.c
b62b43
@@ -161,6 +161,14 @@ static bool part_is_truncated(const struct message_part *part)
b62b43
 			   MESSAGE_PART_FLAG_MULTIPART. */
b62b43
 			return TRUE;
b62b43
 		}
b62b43
+	} else {
b62b43
+		/* No Content-Type */
b62b43
+		if (part->parent != NULL &&
b62b43
+		    (part->parent->flags & MESSAGE_PART_FLAG_MULTIPART_DIGEST) != 0) {
b62b43
+			/* Parent is MESSAGE_PART_FLAG_MULTIPART_DIGEST
b62b43
+			   (so this should have been message/rfc822). */
b62b43
+			return TRUE;
b62b43
+		}
b62b43
 	}
b62b43
 	return FALSE;
b62b43
 }
b62b43
@@ -195,6 +203,7 @@ static void part_write_body(const struct message_part *part,
b62b43
 			str_append_c(str, ' ');
b62b43
 			imap_append_string(str, data->content_subtype);
b62b43
 		}
b62b43
+		i_assert(text == ((part->flags & MESSAGE_PART_FLAG_TEXT) != 0));
b62b43
 	}
b62b43
 
b62b43
 	/* ("content type param key" "value" ...) */
b62b43
diff --git a/src/lib-imap/test-imap-bodystructure.c b/src/lib-imap/test-imap-bodystructure.c
b62b43
index 2118907e78..0f70cb0035 100644
b62b43
--- a/src/lib-imap/test-imap-bodystructure.c
b62b43
+++ b/src/lib-imap/test-imap-bodystructure.c
b62b43
@@ -381,13 +381,14 @@ static const unsigned int normalize_tests_count = N_ELEMENTS(normalize_tests);
b62b43
 
b62b43
 static struct message_part *
b62b43
 msg_parse(pool_t pool, const char *message, unsigned int max_nested_mime_parts,
b62b43
-	  bool parse_bodystructure)
b62b43
+	  unsigned int max_total_mime_parts, bool parse_bodystructure)
b62b43
 {
b62b43
 	const struct message_parser_settings parser_set = {
b62b43
 		.hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP |
b62b43
 			MESSAGE_HEADER_PARSER_FLAG_DROP_CR,
b62b43
 		.flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK,
b62b43
 		.max_nested_mime_parts = max_nested_mime_parts,
b62b43
+		.max_total_mime_parts = max_total_mime_parts,
b62b43
 	};
b62b43
 	struct message_parser_ctx *parser;
b62b43
 	struct istream *input;
b62b43
@@ -421,7 +422,7 @@ static void test_imap_bodystructure_write(void)
b62b43
 		pool_t pool = pool_alloconly_create("imap bodystructure write", 1024);
b62b43
 
b62b43
 		test_begin(t_strdup_printf("imap bodystructure write [%u]", i));
b62b43
-		parts = msg_parse(pool, test->message, 0, TRUE);
b62b43
+		parts = msg_parse(pool, test->message, 0, 0, TRUE);
b62b43
 
b62b43
 		imap_bodystructure_write(parts, str, TRUE);
b62b43
 		test_assert(strcmp(str_c(str), test->bodystructure) == 0);
b62b43
@@ -448,7 +449,7 @@ static void test_imap_bodystructure_parse(void)
b62b43
 		pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024);
b62b43
 
b62b43
 		test_begin(t_strdup_printf("imap bodystructure parser [%u]", i));
b62b43
-		parts = msg_parse(pool, test->message, 0, FALSE);
b62b43
+		parts = msg_parse(pool, test->message, 0, 0, FALSE);
b62b43
 
b62b43
 		test_assert(imap_body_parse_from_bodystructure(test->bodystructure,
b62b43
 								     str, &error) == 0);
b62b43
@@ -515,7 +516,7 @@ static void test_imap_bodystructure_normalize(void)
b62b43
 		pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024);
b62b43
 
b62b43
 		test_begin(t_strdup_printf("imap bodystructure normalize [%u]", i));
b62b43
-		parts = msg_parse(pool, test->message, 0, FALSE);
b62b43
+		parts = msg_parse(pool, test->message, 0, 0, FALSE);
b62b43
 
b62b43
 		ret = imap_bodystructure_parse(test->input,
b62b43
 							   pool, parts, &error);
b62b43
@@ -538,6 +539,7 @@ static const struct {
b62b43
 	const char *input;
b62b43
 	const char *bodystructure;
b62b43
 	unsigned int max_depth;
b62b43
+	unsigned int max_total;
b62b43
 } truncation_tests[] = {
b62b43
 	{
b62b43
 		.input = "Content-Type: message/rfc822\n"
b62b43
@@ -571,6 +573,23 @@ static const struct {
b62b43
 		.bodystructure = "(\"application\" \"octet-stream\" (\"boundary\" \"2\") NIL NIL \"7bit\" 63 NIL NIL NIL NIL) \"mixed\" (\"boundary\" \"1\") NIL NIL NIL",
b62b43
 		.max_depth = 2,
b62b43
 	},
b62b43
+	{
b62b43
+		.input = "Content-Type: multipart/digest; boundary=1\n"
b62b43
+			"\n"
b62b43
+			"--1\n"
b62b43
+			"\n"
b62b43
+			"Subject: hdr1\n"
b62b43
+			"\n"
b62b43
+			"body1\n"
b62b43
+			"--1\n"
b62b43
+			"\n"
b62b43
+			"Subject: hdr2\n"
b62b43
+			"\n"
b62b43
+			"body2\n",
b62b43
+		.bodystructure = "(\"application\" \"octet-stream\" NIL NIL NIL \"7bit\" 55 NIL NIL NIL NIL) \"digest\" (\"boundary\" \"1\") NIL NIL NIL",
b62b43
+		.max_total = 2,
b62b43
+	},
b62b43
+
b62b43
 };
b62b43
 
b62b43
 static void test_imap_bodystructure_truncation(void)
b62b43
@@ -590,6 +609,7 @@ static void test_imap_bodystructure_truncation(void)
b62b43
 
b62b43
 		parts = msg_parse(pool, truncation_tests[i].input,
b62b43
 				  truncation_tests[i].max_depth,
b62b43
+				  truncation_tests[i].max_total,
b62b43
 				  TRUE);
b62b43
 
b62b43
 		/* write out BODYSTRUCTURE and serialize message_parts */