From 311a5d443aab1aaeacc3757e16fe480c16aca159 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jul 13 2020 20:06:35 +0000 Subject: import dovecot-2.3.8-2.el8_2.1 --- diff --git a/SOURCES/dovecot-2.3.10-CVE_2020_10957p1.patch b/SOURCES/dovecot-2.3.10-CVE_2020_10957p1.patch new file mode 100644 index 0000000..70adc9a --- /dev/null +++ b/SOURCES/dovecot-2.3.10-CVE_2020_10957p1.patch @@ -0,0 +1,60 @@ +From 606724bd528b92347dce580d3ab48fc1e3c2f4d7 Mon Sep 17 00:00:00 2001 +From: Stephan Bosch +Date: Tue, 24 Mar 2020 20:57:03 +0100 +Subject: [PATCH] lib-smtp: smtp-syntax - Do not allow NULL return parameters + for smtp_string_parse(). + +--- + src/lib-smtp/smtp-server-cmd-noop.c | 8 ++++++-- + src/lib-smtp/smtp-syntax.c | 9 +++++---- + 2 files changed, 11 insertions(+), 6 deletions(-) + +diff --git a/src/lib-smtp/smtp-server-cmd-noop.c b/src/lib-smtp/smtp-server-cmd-noop.c +index 4986f800c8..550d709eab 100644 +--- a/src/lib-smtp/smtp-server-cmd-noop.c ++++ b/src/lib-smtp/smtp-server-cmd-noop.c +@@ -13,11 +13,15 @@ void smtp_server_cmd_noop(struct smtp_server_cmd_ctx *cmd, + struct smtp_server_connection *conn = cmd->conn; + struct smtp_server_command *command = cmd->cmd; + const struct smtp_server_callbacks *callbacks = conn->callbacks; ++ const char *param, *error; + int ret; + + /* "NOOP" [ SP String ] CRLF */ +- if (*params != '\0' && smtp_string_parse(params, NULL, NULL) < 0) { +- smtp_server_reply(cmd, 501, "5.5.4", "Invalid parameters"); ++ ret = smtp_string_parse(params, ¶m, &error); ++ if (ret < 0) { ++ smtp_server_reply(cmd, 501, "5.5.4", ++ "Invalid string parameter: %s", ++ error); + return; + } + +diff --git a/src/lib-smtp/smtp-syntax.c b/src/lib-smtp/smtp-syntax.c +index 5d22445f72..6826682af1 100644 +--- a/src/lib-smtp/smtp-syntax.c ++++ b/src/lib-smtp/smtp-syntax.c +@@ -17,7 +17,9 @@ int smtp_string_parse(const char *string, + const char **value_r, const char **error_r) + { + struct smtp_parser parser; +- int ret; ++ ++ *value_r = NULL; ++ *error_r = NULL; + + if (string == NULL || *string == '\0') { + *value_r = ""; +@@ -26,9 +28,8 @@ int smtp_string_parse(const char *string, + + smtp_parser_init(&parser, pool_datastack_create(), string); + +- if ((ret=smtp_parser_parse_string(&parser, value_r)) < 0) { +- if (error_r != NULL) +- *error_r = parser.error; ++ if (smtp_parser_parse_string(&parser, value_r) < 0) { ++ *error_r = parser.error; + return -1; + } + if (parser.cur < parser.end) { diff --git a/SOURCES/dovecot-2.3.10-CVE_2020_10957p2.patch b/SOURCES/dovecot-2.3.10-CVE_2020_10957p2.patch new file mode 100644 index 0000000..8aa5f8a --- /dev/null +++ b/SOURCES/dovecot-2.3.10-CVE_2020_10957p2.patch @@ -0,0 +1,51 @@ +From aedb205c79395de77127fb7166b29b09319df23c Mon Sep 17 00:00:00 2001 +From: Stephan Bosch +Date: Tue, 24 Mar 2020 21:11:01 +0100 +Subject: [PATCH] lib-smtp: smtp-syntax - Do not allow NULL return parameters + for smtp_xtext_parse(). + +--- + src/lib-smtp/smtp-syntax.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/src/lib-smtp/smtp-syntax.c b/src/lib-smtp/smtp-syntax.c +index 6826682af1..0b0a91ce07 100644 +--- a/src/lib-smtp/smtp-syntax.c ++++ b/src/lib-smtp/smtp-syntax.c +@@ -86,20 +86,20 @@ int smtp_xtext_parse(const char *xtext, + { + struct smtp_parser parser; + string_t *value = NULL; +- int ret; ++ ++ *value_r = NULL; ++ *error_r = NULL; + + if (xtext == NULL || *xtext == '\0') { + *value_r = ""; + return 1; + } + +- if (value_r != NULL) +- value = t_str_new(256); ++ value = t_str_new(256); + smtp_parser_init(&parser, pool_datastack_create(), xtext); + +- if ((ret=smtp_parser_parse_xtext(&parser, value)) < 0) { +- if (error_r != NULL) +- *error_r = parser.error; ++ if (smtp_parser_parse_xtext(&parser, value) < 0) { ++ *error_r = parser.error; + return -1; + } + if (parser.cur < parser.end) { +@@ -110,8 +110,7 @@ int smtp_xtext_parse(const char *xtext, + if (value_r != NULL) { + *value_r = str_c(value); + if (strlen(*value_r) != str_len(value)) { +- if (*error_r != NULL) +- *error_r = "Encountered NUL character in xtext"; ++ *error_r = "Encountered NUL character in xtext"; + return -1; + } + } diff --git a/SOURCES/dovecot-2.3.10-CVE_2020_10957p3.patch b/SOURCES/dovecot-2.3.10-CVE_2020_10957p3.patch new file mode 100644 index 0000000..c5a2fd7 --- /dev/null +++ b/SOURCES/dovecot-2.3.10-CVE_2020_10957p3.patch @@ -0,0 +1,96 @@ +From 874817b169d19a4ae51d80ad5798a396bfe90136 Mon Sep 17 00:00:00 2001 +From: Stephan Bosch +Date: Tue, 24 Mar 2020 21:14:34 +0100 +Subject: [PATCH] lib-smtp: smtp-syntax - Do not allow NULL return parameters + for smtp_ehlo_line_parse(). + +--- + src/lib-smtp/smtp-syntax.c | 39 +++++++++++++++++--------------------- + 1 file changed, 17 insertions(+), 22 deletions(-) + +diff --git a/src/lib-smtp/smtp-syntax.c b/src/lib-smtp/smtp-syntax.c +index 0b0a91ce07..5cca6c40fd 100644 +--- a/src/lib-smtp/smtp-syntax.c ++++ b/src/lib-smtp/smtp-syntax.c +@@ -249,12 +249,10 @@ static int smtp_parse_ehlo_line(struct smtp_parser *parser, + (i_isalnum(*parser->cur) || *parser->cur == '-')) + parser->cur++; + +- if (key_r != NULL) +- *key_r = p_strdup_until(parser->pool, pbegin, parser->cur); ++ *key_r = p_strdup_until(parser->pool, pbegin, parser->cur); + + if (parser->cur >= parser->end) { +- if (params_r != NULL) +- *params_r = p_new(parser->pool, const char *, 1); ++ *params_r = p_new(parser->pool, const char *, 1); + return 1; + } + if (*parser->cur != ' ') { +@@ -264,18 +262,16 @@ static int smtp_parse_ehlo_line(struct smtp_parser *parser, + parser->cur++; + + pbegin = parser->cur; +- if (params_r != NULL) +- p_array_init(¶ms, parser->pool, 32); ++ p_array_init(¶ms, parser->pool, 32); + while (parser->cur < parser->end) { + if (*parser->cur == ' ') { + if (parser->cur+1 >= parser->end || *(parser->cur+1) == ' ') { + parser->error = "Missing EHLO parameter after ' '"; + return -1; + } +- if (params_r != NULL) { +- param = p_strdup_until(parser->pool, pbegin, parser->cur); +- array_push_back(¶ms, ¶m); +- } ++ param = p_strdup_until(parser->pool, pbegin, ++ parser->cur); ++ array_push_back(¶ms, ¶m); + pbegin = parser->cur + 1; + } else if (!smtp_char_is_ehlo_param(*parser->cur)) { + parser->error = "Unexpected character in EHLO parameter"; +@@ -284,12 +280,10 @@ static int smtp_parse_ehlo_line(struct smtp_parser *parser, + parser->cur++; + } + +- if (params_r != NULL) { +- param = p_strdup_until(parser->pool, pbegin, parser->cur); +- array_push_back(¶ms, ¶m); +- array_append_zero(¶ms); +- *params_r = array_front(¶ms); +- } ++ param = p_strdup_until(parser->pool, pbegin, parser->cur); ++ array_push_back(¶ms, ¶m); ++ array_append_zero(¶ms); ++ *params_r = array_front(¶ms); + return 1; + } + +@@ -297,19 +291,20 @@ int smtp_ehlo_line_parse(const char *ehlo_line, const char **key_r, + const char *const **params_r, const char **error_r) + { + struct smtp_parser parser; +- int ret; ++ ++ *key_r = NULL; ++ *params_r = NULL; ++ *error_r = NULL; + + if (ehlo_line == NULL || *ehlo_line == '\0') { +- if (error_r != NULL) +- *error_r = "Parameter is empty"; ++ *error_r = "Parameter is empty"; + return -1; + } + + smtp_parser_init(&parser, pool_datastack_create(), ehlo_line); + +- if ((ret=smtp_parse_ehlo_line(&parser, key_r, params_r)) <= 0) { +- if (error_r != NULL) +- *error_r = parser.error; ++ if (smtp_parse_ehlo_line(&parser, key_r, params_r) <= 0) { ++ *error_r = parser.error; + return -1; + } + return 1; diff --git a/SOURCES/dovecot-2.3.10-CVE_2020_10957p4.patch b/SOURCES/dovecot-2.3.10-CVE_2020_10957p4.patch new file mode 100644 index 0000000..70a1251 --- /dev/null +++ b/SOURCES/dovecot-2.3.10-CVE_2020_10957p4.patch @@ -0,0 +1,24 @@ +From 5efeccc10beccbf8d7700adec1278f97d416cbc6 Mon Sep 17 00:00:00 2001 +From: Stephan Bosch +Date: Tue, 24 Mar 2020 22:42:15 +0100 +Subject: [PATCH] lib-smtp: smtp-syntax - Return 0 for smtp_string_parse() with + empty input. + +This is what the current users of this function actually expect. +--- + src/lib-smtp/smtp-syntax.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lib-smtp/smtp-syntax.c b/src/lib-smtp/smtp-syntax.c +index 5cca6c40fd..cf86f87336 100644 +--- a/src/lib-smtp/smtp-syntax.c ++++ b/src/lib-smtp/smtp-syntax.c +@@ -23,7 +23,7 @@ int smtp_string_parse(const char *string, + + if (string == NULL || *string == '\0') { + *value_r = ""; +- return 1; ++ return 0; + } + + smtp_parser_init(&parser, pool_datastack_create(), string); diff --git a/SOURCES/dovecot-2.3.10-CVE_2020_10957p5.patch b/SOURCES/dovecot-2.3.10-CVE_2020_10957p5.patch new file mode 100644 index 0000000..271c79f --- /dev/null +++ b/SOURCES/dovecot-2.3.10-CVE_2020_10957p5.patch @@ -0,0 +1,191 @@ +From 363af76535f8137ba76d9de7935023bab9a045ef Mon Sep 17 00:00:00 2001 +From: Stephan Bosch +Date: Tue, 24 Mar 2020 22:24:20 +0100 +Subject: [PATCH] lib-smtp: Add tests for smtp_string_parse() and + smtp_string_write(). + +--- + src/lib-smtp/Makefile.am | 5 ++ + src/lib-smtp/test-smtp-syntax.c | 150 ++++++++++++++++++++++++++++++++ + 2 files changed, 155 insertions(+) + create mode 100644 src/lib-smtp/test-smtp-syntax.c + +diff --git a/src/lib-smtp/Makefile.am b/src/lib-smtp/Makefile.am +index b03761df8b..d87cd4e6d3 100644 +--- a/src/lib-smtp/Makefile.am ++++ b/src/lib-smtp/Makefile.am +@@ -72,6 +72,7 @@ pkginc_libdir=$(pkgincludedir) + pkginc_lib_HEADERS = $(headers) + + test_programs = \ ++ test-smtp-syntax \ + test-smtp-address \ + test-smtp-params \ + test-smtp-reply \ +@@ -121,6 +122,10 @@ if BUILD_OPENSSL + test_libs_ssl += ../lib-ssl-iostream/libssl_iostream_openssl.la + endif + ++test_smtp_syntax_SOURCES = test-smtp-syntax.c ++test_smtp_syntax_LDADD = $(test_libs) ++test_smtp_syntax_DEPENDENCIES = $(test_deps) ++ + test_smtp_address_SOURCES = test-smtp-address.c + test_smtp_address_LDFLAGS = -export-dynamic + test_smtp_address_LDADD = $(test_libs) +diff --git a/src/lib-smtp/test-smtp-syntax.c b/src/lib-smtp/test-smtp-syntax.c +new file mode 100644 +index 0000000000..735cd01220 +--- /dev/null ++++ b/src/lib-smtp/test-smtp-syntax.c +@@ -0,0 +1,150 @@ ++/* Copyright (c) 2020 Dovecot authors, see the included COPYING file */ ++ ++#include "lib.h" ++#include "str.h" ++#include "str-sanitize.h" ++#include "test-common.h" ++#include "smtp-syntax.h" ++ ++/* ++ * Valid string parse tests ++ */ ++ ++struct valid_string_parse_test { ++ const char *input, *parsed, *output; ++}; ++ ++static const struct valid_string_parse_test ++valid_string_parse_tests[] = { ++ { ++ .input = "", ++ .parsed = "", ++ }, ++ { ++ .input = "atom", ++ .parsed = "atom", ++ }, ++ { ++ .input = "abcdefghijklmnopqrstuvwxyz" ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++ "0123456789!#$%&'*+-/=?^_`{|}~", ++ .parsed = "abcdefghijklmnopqrstuvwxyz" ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++ "0123456789!#$%&'*+-/=?^_`{|}~", ++ }, ++ { ++ .input = "\"quoted-string\"", ++ .parsed = "quoted-string", ++ .output = "quoted-string", ++ }, ++ { ++ .input = "\"quoted \\\"string\\\"\"", ++ .parsed = "quoted \"string\"", ++ }, ++ { ++ .input = "\"quoted \\\\string\\\\\"", ++ .parsed = "quoted \\string\\", ++ }, ++}; ++ ++static const unsigned int valid_string_parse_test_count = ++ N_ELEMENTS(valid_string_parse_tests); ++ ++static void test_smtp_string_parse_valid(void) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < valid_string_parse_test_count; i++) T_BEGIN { ++ const struct valid_string_parse_test *test = ++ &valid_string_parse_tests[i]; ++ const char *parsed, *error = NULL; ++ int ret; ++ ++ ret = smtp_string_parse(test->input, &parsed, &error); ++ ++ test_begin(t_strdup_printf("smtp string valid [%d]", i)); ++ test_out_reason(t_strdup_printf("parse(\"%s\")", test->input), ++ ret >= 0, error); ++ test_assert(ret != 0 || *test->input == '\0'); ++ ++ if (!test_has_failed()) { ++ string_t *encoded; ++ const char *output; ++ ++ test_out(t_strdup_printf("parsed = \"%s\"", parsed), ++ null_strcmp(parsed, test->parsed) == 0); ++ ++ encoded = t_str_new(255); ++ smtp_string_write(encoded, parsed); ++ output = (test->output == NULL ? ++ test->input : test->output); ++ test_out(t_strdup_printf("write() = \"%s\"", ++ str_c(encoded)), ++ strcmp(str_c(encoded), output) == 0); ++ } ++ test_end(); ++ } T_END; ++} ++ ++/* ++ * Invalid string parse tests ++ */ ++ ++struct invalid_string_parse_test { ++ const char *input; ++}; ++ ++static const struct invalid_string_parse_test ++invalid_string_parse_tests[] = { ++ { ++ .input = " ", ++ }, ++ { ++ .input = "\\", ++ }, ++ { ++ .input = "\"", ++ }, ++ { ++ .input = "\"aa", ++ }, ++ { ++ .input = "aa\"", ++ }, ++}; ++ ++static const unsigned int invalid_string_parse_test_count = ++ N_ELEMENTS(invalid_string_parse_tests); ++ ++static void test_smtp_string_parse_invalid(void) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < invalid_string_parse_test_count; i++) T_BEGIN { ++ const struct invalid_string_parse_test *test = ++ &invalid_string_parse_tests[i]; ++ const char *parsed, *error; ++ int ret; ++ ++ ret = smtp_string_parse(test->input, &parsed, &error); ++ ++ test_begin(t_strdup_printf("smtp string invalid [%d]", i)); ++ test_out_reason(t_strdup_printf("parse(\"%s\")", test->input), ++ ret < 0, error); ++ test_end(); ++ } T_END; ++} ++ ++/* ++ * Tests ++ */ ++ ++int main(void) ++{ ++ static void (*test_functions[])(void) = { ++ test_smtp_string_parse_valid, ++ test_smtp_string_parse_invalid, ++ NULL ++ }; ++ return test_run(test_functions); ++} diff --git a/SOURCES/dovecot-2.3.10-CVE_2020_10957p6.patch b/SOURCES/dovecot-2.3.10-CVE_2020_10957p6.patch new file mode 100644 index 0000000..cffe0cf --- /dev/null +++ b/SOURCES/dovecot-2.3.10-CVE_2020_10957p6.patch @@ -0,0 +1,340 @@ +From f206dc478d1b22183f645ea8c98ffe3712e106b2 Mon Sep 17 00:00:00 2001 +From: Stephan Bosch +Date: Tue, 24 Mar 2020 22:33:45 +0100 +Subject: [PATCH] lib-smtp: test-smtp-server-errors - Add tests for VRFY and + NOOP commands with invalid parameters. + +--- + src/lib-smtp/test-smtp-server-errors.c | 312 +++++++++++++++++++++++++ + 1 file changed, 312 insertions(+) + +diff --git a/src/lib-smtp/test-smtp-server-errors.c b/src/lib-smtp/test-smtp-server-errors.c +index 759c332d88..13d3b97def 100644 +--- a/src/lib-smtp/test-smtp-server-errors.c ++++ b/src/lib-smtp/test-smtp-server-errors.c +@@ -1273,6 +1273,316 @@ static void test_bad_rcpt(void) + test_end(); + } + ++/* ++ * Bad VRFY ++ */ ++ ++/* client */ ++ ++struct _bad_vrfy_client { ++ struct smtp_reply_parser *parser; ++ unsigned int reply; ++ ++ bool replied:1; ++}; ++ ++static void ++test_bad_vrfy_client_input(struct client_connection *conn) ++{ ++ struct _bad_vrfy_client *ctx = conn->context; ++ struct smtp_reply *reply; ++ const char *error; ++ int ret; ++ ++ while ((ret = smtp_reply_parse_next(ctx->parser, FALSE, ++ &reply, &error)) > 0) { ++ if (debug) ++ i_debug("REPLY: %s", smtp_reply_log(reply)); ++ ++ switch (ctx->reply++) { ++ case 0: /* greeting */ ++ i_assert(reply->status == 220); ++ break; ++ case 1: /* bad command reply */ ++ switch (client_index) { ++ case 0: case 1: case 2: ++ i_assert(reply->status == 501); ++ break; ++ case 3: ++ i_assert(smtp_reply_is_success(reply)); ++ break; ++ default: ++ i_unreached(); ++ } ++ ctx->replied = TRUE; ++ io_loop_stop(ioloop); ++ connection_disconnect(&conn->conn); ++ return; ++ default: ++ i_unreached(); ++ } ++ } ++ ++ i_assert(ret == 0); ++} ++ ++static void ++test_bad_vrfy_client_connected(struct client_connection *conn) ++{ ++ struct _bad_vrfy_client *ctx; ++ ++ ctx = p_new(conn->pool, struct _bad_vrfy_client, 1); ++ ctx->parser = smtp_reply_parser_init(conn->conn.input, (size_t)-1); ++ conn->context = ctx; ++ ++ switch (client_index) { ++ case 0: ++ o_stream_nsend_str(conn->conn.output, ++ "VRFY\r\n"); ++ break; ++ case 1: ++ o_stream_nsend_str(conn->conn.output, ++ "VRFY \"hendrik\r\n"); ++ break; ++ case 2: ++ o_stream_nsend_str(conn->conn.output, ++ "VRFY hen\"drik\r\n"); ++ break; ++ case 3: ++ o_stream_nsend_str(conn->conn.output, ++ "VRFY \"hendrik\"\r\n"); ++ break; ++ default: ++ i_unreached(); ++ } ++} ++ ++static void ++test_bad_vrfy_client_deinit(struct client_connection *conn) ++{ ++ struct _bad_vrfy_client *ctx = conn->context; ++ ++ i_assert(ctx->replied); ++ smtp_reply_parser_deinit(&ctx->parser); ++} ++ ++static void test_client_bad_vrfy(unsigned int index) ++{ ++ test_client_input = test_bad_vrfy_client_input; ++ test_client_connected = test_bad_vrfy_client_connected; ++ test_client_deinit = test_bad_vrfy_client_deinit; ++ test_client_run(index); ++} ++ ++/* server */ ++ ++static void ++test_server_bad_vrfy_disconnect(void *context ATTR_UNUSED, const char *reason) ++{ ++ if (debug) ++ i_debug("Disconnect: %s", reason); ++} ++ ++static int ++test_server_bad_vrfy_rcpt(void *conn_ctx ATTR_UNUSED, ++ struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, ++ struct smtp_server_recipient *rcpt ATTR_UNUSED) ++{ ++ test_assert(FALSE); ++ return 1; ++} ++ ++static int ++test_server_bad_vrfy_data_begin( ++ void *conn_ctx ATTR_UNUSED, struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, ++ struct smtp_server_transaction *trans ATTR_UNUSED, ++ struct istream *data_input ATTR_UNUSED) ++{ ++ test_assert(FALSE); ++ return 1; ++} ++ ++static void ++test_server_bad_vrfy(const struct smtp_server_settings *server_set) ++{ ++ server_callbacks.conn_disconnect = test_server_bad_vrfy_disconnect; ++ ++ server_callbacks.conn_cmd_rcpt = test_server_bad_vrfy_rcpt; ++ server_callbacks.conn_cmd_data_begin = test_server_bad_vrfy_data_begin; ++ test_server_run(server_set); ++} ++ ++/* test */ ++ ++static void test_bad_vrfy(void) ++{ ++ struct smtp_server_settings smtp_server_set; ++ ++ test_server_defaults(&smtp_server_set); ++ smtp_server_set.max_client_idle_time_msecs = 1000; ++ ++ test_begin("bad VRFY"); ++ test_run_client_server(&smtp_server_set, ++ test_server_bad_vrfy, ++ test_client_bad_vrfy, 4); ++ test_end(); ++} ++ ++/* ++ * Bad NOOP ++ */ ++ ++/* client */ ++ ++struct _bad_noop_client { ++ struct smtp_reply_parser *parser; ++ unsigned int reply; ++ ++ bool replied:1; ++}; ++ ++static void ++test_bad_noop_client_input(struct client_connection *conn) ++{ ++ struct _bad_noop_client *ctx = conn->context; ++ struct smtp_reply *reply; ++ const char *error; ++ int ret; ++ ++ while ((ret = smtp_reply_parse_next(ctx->parser, FALSE, ++ &reply, &error)) > 0) { ++ if (debug) ++ i_debug("REPLY: %s", smtp_reply_log(reply)); ++ ++ switch (ctx->reply++) { ++ case 0: /* greeting */ ++ i_assert(reply->status == 220); ++ break; ++ case 1: /* bad command reply */ ++ switch (client_index) { ++ case 1: case 2: ++ i_assert(reply->status == 501); ++ break; ++ case 0: case 3: ++ i_assert(smtp_reply_is_success(reply)); ++ break; ++ default: ++ i_unreached(); ++ } ++ ctx->replied = TRUE; ++ io_loop_stop(ioloop); ++ connection_disconnect(&conn->conn); ++ return; ++ default: ++ i_unreached(); ++ } ++ } ++ ++ i_assert(ret == 0); ++} ++ ++static void ++test_bad_noop_client_connected(struct client_connection *conn) ++{ ++ struct _bad_noop_client *ctx; ++ ++ ctx = p_new(conn->pool, struct _bad_noop_client, 1); ++ ctx->parser = smtp_reply_parser_init(conn->conn.input, (size_t)-1); ++ conn->context = ctx; ++ ++ switch (client_index) { ++ case 0: ++ o_stream_nsend_str(conn->conn.output, ++ "NOOP\r\n"); ++ break; ++ case 1: ++ o_stream_nsend_str(conn->conn.output, ++ "NOOP \"frop\r\n"); ++ break; ++ case 2: ++ o_stream_nsend_str(conn->conn.output, ++ "NOOP fr\"op\r\n"); ++ break; ++ case 3: ++ o_stream_nsend_str(conn->conn.output, ++ "NOOP \"frop\"\r\n"); ++ break; ++ default: ++ i_unreached(); ++ } ++} ++ ++static void ++test_bad_noop_client_deinit(struct client_connection *conn) ++{ ++ struct _bad_noop_client *ctx = conn->context; ++ ++ i_assert(ctx->replied); ++ smtp_reply_parser_deinit(&ctx->parser); ++} ++ ++static void test_client_bad_noop(unsigned int index) ++{ ++ test_client_input = test_bad_noop_client_input; ++ test_client_connected = test_bad_noop_client_connected; ++ test_client_deinit = test_bad_noop_client_deinit; ++ test_client_run(index); ++} ++ ++/* server */ ++ ++static void ++test_server_bad_noop_disconnect(void *context ATTR_UNUSED, const char *reason) ++{ ++ if (debug) ++ i_debug("Disconnect: %s", reason); ++} ++ ++static int ++test_server_bad_noop_rcpt(void *conn_ctx ATTR_UNUSED, ++ struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, ++ struct smtp_server_recipient *rcpt ATTR_UNUSED) ++{ ++ test_assert(FALSE); ++ return 1; ++} ++ ++static int ++test_server_bad_noop_data_begin( ++ void *conn_ctx ATTR_UNUSED, struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, ++ struct smtp_server_transaction *trans ATTR_UNUSED, ++ struct istream *data_input ATTR_UNUSED) ++{ ++ test_assert(FALSE); ++ return 1; ++} ++ ++static void ++test_server_bad_noop(const struct smtp_server_settings *server_set) ++{ ++ server_callbacks.conn_disconnect = test_server_bad_noop_disconnect; ++ ++ server_callbacks.conn_cmd_rcpt = test_server_bad_noop_rcpt; ++ server_callbacks.conn_cmd_data_begin = test_server_bad_noop_data_begin; ++ test_server_run(server_set); ++} ++ ++/* test */ ++ ++static void test_bad_noop(void) ++{ ++ struct smtp_server_settings smtp_server_set; ++ ++ test_server_defaults(&smtp_server_set); ++ smtp_server_set.max_client_idle_time_msecs = 1000; ++ ++ test_begin("bad NOOP"); ++ test_run_client_server(&smtp_server_set, ++ test_server_bad_noop, ++ test_client_bad_noop, 4); ++ test_end(); ++} ++ + /* + * MAIL workarounds + */ +@@ -2246,6 +2556,8 @@ static void (*const test_functions[])(void) = { + test_bad_ehlo, + test_bad_mail, + test_bad_rcpt, ++ test_bad_vrfy, ++ test_bad_noop, + test_mail_workarounds, + test_rcpt_workarounds, + test_too_many_recipients, diff --git a/SPECS/dovecot.spec b/SPECS/dovecot.spec index 0b2e247..45c6ef1 100644 --- a/SPECS/dovecot.spec +++ b/SPECS/dovecot.spec @@ -5,7 +5,7 @@ Name: dovecot Epoch: 1 Version: 2.3.8 %global prever %{nil} -Release: 2%{?dist} +Release: 2%{?dist}.1 #dovecot itself is MIT, a few sources are PD, pigeonhole is LGPLv2 License: MIT and LGPLv2 Group: System Environment/Daemons @@ -43,6 +43,12 @@ Patch13: dovecot-2.2.36-bigkey.patch # not sent upstream as proper fix would use dovecot's lib-dcrypt but it introduces # hard to break circular dependency between lib and lib-dcrypt Patch14: dovecot-2.3.6-opensslhmac.patch +Patch15: dovecot-2.3.10-CVE_2020_10957p1.patch +Patch16: dovecot-2.3.10-CVE_2020_10957p2.patch +Patch17: dovecot-2.3.10-CVE_2020_10957p3.patch +Patch18: dovecot-2.3.10-CVE_2020_10957p4.patch +Patch19: dovecot-2.3.10-CVE_2020_10957p5.patch +Patch20: dovecot-2.3.10-CVE_2020_10957p6.patch Source15: prestartscript @@ -148,6 +154,12 @@ This package provides the development files for dovecot. %patch11 -p1 -b .aclfix %patch13 -p1 -b .bigkey %patch14 -p1 -b .opensslhmac +%patch15 -p1 -b .CVE_2020_10957p1 +%patch16 -p1 -b .CVE_2020_10957p2 +%patch17 -p1 -b .CVE_2020_10957p3 +%patch18 -p1 -b .CVE_2020_10957p4 +%patch19 -p1 -b .CVE_2020_10957p5 +%patch20 -p1 -b .CVE_2020_10957p6 pushd dovecot-2*3-pigeonhole-%{pigeonholever} popd @@ -507,6 +519,9 @@ make check %{_libdir}/%{name}/dict/libdriver_pgsql.so %changelog +* Fri Jun 05 2020 Michal Hlavinka - 1:2.3.8-2.1 +- fix CVE-2020-10957: malformed NOOP commands leads to DoS (#1840353) + * Thu Jan 09 2020 Michal Hlavinka - 1:2.3.8-2 - fix default attributes for ghost files