diff --git a/dovecot-2.3-cve-2025-59032.patch b/dovecot-2.3-cve-2025-59032.patch new file mode 100644 index 0000000..8ca9054 --- /dev/null +++ b/dovecot-2.3-cve-2025-59032.patch @@ -0,0 +1,20 @@ +diff --git a/dovecot-pigeonhole/src/managesieve-login/client.c b/dovecot-pigeonhole/src/managesieve-login/client.c +index 3b2492ca..2ad47b4c 100644 +--- a/dovecot-pigeonhole/src/managesieve-login/client.c ++++ b/dovecot-pigeonhole/src/managesieve-login/client.c +@@ -345,10 +345,12 @@ static bool managesieve_client_input_next_cmd(struct client *client) + if (args[0].type != MANAGESIEVE_ARG_EOL) + ret = -1; + } +- } +- if (ret > 0) { ++ if (ret > 0) ++ ret = client->cmd->func(client, args); ++ } else { ++ /* Continue unfinished command */ + i_assert(client->cmd != NULL); +- ret = client->cmd->func(client, args); ++ ret = client->cmd->func(client, NULL); + } + + if (ret != 0) diff --git a/dovecot-2.3-cve-2026-27857p1of5.patch b/dovecot-2.3-cve-2026-27857p1of5.patch new file mode 100644 index 0000000..6392a16 --- /dev/null +++ b/dovecot-2.3-cve-2026-27857p1of5.patch @@ -0,0 +1,257 @@ +diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c +index c761f91d6e..84e6a90db4 100644 +--- a/src/imap-login/imap-login-client.c ++++ b/src/imap-login/imap-login-client.c +@@ -379,7 +379,7 @@ static void imap_client_create(struct cl + imap_client->parser = + imap_parser_create(imap_client->common.input, + imap_client->common.output, +- IMAP_LOGIN_MAX_LINE_LENGTH); ++ IMAP_LOGIN_MAX_LINE_LENGTH, NULL); + if (imap_client->set->imap_literal_minus) + imap_parser_enable_literal_minus(imap_client->parser); + client->io = io_add_istream(client->input, client_input, client); +@@ -473,7 +473,7 @@ static void imap_client_starttls(struct client *client) + imap_client->parser = + imap_parser_create(imap_client->common.input, + imap_client->common.output, +- IMAP_LOGIN_MAX_LINE_LENGTH); ++ IMAP_LOGIN_MAX_LINE_LENGTH, NULL); + + /* CRLF is lost from buffer when streams are reopened. */ + imap_client->skip_line = FALSE; +diff --git a/src/imap-login/imap-login-cmd-id.c b/src/imap-login/imap-login-cmd-id.c +index 24b365dc0c..be2097f70b 100644 +--- a/src/imap-login/imap-login-cmd-id.c ++++ b/src/imap-login/imap-login-cmd-id.c +@@ -391,7 +391,8 @@ int cmd_id(struct imap_client *client) + client->cmd_id = id = i_new(struct imap_client_cmd_id, 1); + id->parser = imap_parser_create(client->common.input, + client->common.output, +- IMAP_LOGIN_MAX_LINE_LENGTH); ++ IMAP_LOGIN_MAX_LINE_LENGTH, ++ NULL); + if (client->set->imap_literal_minus) + imap_parser_enable_literal_minus(id->parser); + parser_flags = IMAP_PARSE_FLAG_STOP_AT_LIST; +diff --git a/src/imap/cmd-append.c b/src/imap/cmd-append.c +index 8e1dec27e6..18f16fc119 100644 +--- a/src/imap/cmd-append.c ++++ b/src/imap/cmd-append.c +@@ -1202,7 +1202,8 @@ static bool cmd_append_full(struct client_command_context *cmd, bool replace) + o_stream_unset_flush_callback(client->output); + + ctx->save_parser = imap_parser_create(client->input, client->output, +- client->set->imap_max_line_length); ++ client->set->imap_max_line_length, ++ NULL); + if (client->set->imap_literal_minus) + imap_parser_enable_literal_minus(ctx->save_parser); + +diff --git a/src/imap/cmd-setmetadata.c b/src/imap/cmd-setmetadata.c +index 4278c8720e..686c72c984 100644 +--- a/src/imap/cmd-setmetadata.c ++++ b/src/imap/cmd-setmetadata.c +@@ -289,7 +289,8 @@ cmd_setmetadata_start(struct imap_setmetadata_context *ctx) + asynchronously the same way as APPEND does. */ + client->input_lock = cmd; + ctx->parser = imap_parser_create(client->input, client->output, +- client->set->imap_max_line_length); ++ client->set->imap_max_line_length, ++ NULL); + if (client->set->imap_literal_minus) + imap_parser_enable_literal_minus(ctx->parser); + o_stream_unset_flush_callback(client->output); +diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c +index 47709aa400..10a8968988 100644 +--- a/src/imap/imap-client.c ++++ b/src/imap/imap-client.c +@@ -994,7 +994,8 @@ client_command_new(struct client *client) + } else { + cmd->parser = + imap_parser_create(client->input, client->output, +- client->set->imap_max_line_length); ++ client->set->imap_max_line_length, ++ NULL); + if (client->set->imap_literal_minus) + imap_parser_enable_literal_minus(cmd->parser); + } +diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c +index 17aa54c3b0..25dfd32499 100644 +--- a/src/lib-imap-client/imapc-connection.c ++++ b/src/lib-imap-client/imapc-connection.c +@@ -1914,7 +1914,8 @@ static void imapc_connection_connect_next_ip(struct imapc_connection *conn) + o_stream_set_flush_callback(conn->output, imapc_connection_connected, + conn); + conn->parser = imap_parser_create(conn->input, NULL, +- conn->client->set.max_line_length); ++ conn->client->set.max_line_length, ++ NULL); + conn->to = timeout_add(conn->client->set.connect_timeout_msecs, + imapc_connection_timeout, conn); + conn->to_output = timeout_add(conn->client->set.max_idle_time*1000, +diff --git a/src/lib-imap-storage/imap-msgpart.c b/src/lib-imap-storage/imap-msgpart.c +index 0442a345b4..3c0bbf5a81 100644 +--- a/src/lib-imap-storage/imap-msgpart.c ++++ b/src/lib-imap-storage/imap-msgpart.c +@@ -149,7 +149,7 @@ imap_msgpart_get_header_fields(pool_t pool, const char *header_list, + int result = 0; + + input = i_stream_create_from_data(header_list, strlen(header_list)); +- parser = imap_parser_create(input, NULL, SIZE_MAX); ++ parser = imap_parser_create(input, NULL, SIZE_MAX, NULL); + + if (imap_parser_finish_line(parser, 0, 0, &args) > 0 && + imap_arg_get_list_full(args, &hdr_list, &list_count) && +diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c +index e3d4b3b564..7910bbcee1 100644 +--- a/src/lib-imap/imap-bodystructure.c ++++ b/src/lib-imap/imap-bodystructure.c +@@ -732,7 +732,7 @@ int imap_bodystructure_parse_full(const char *bodystructure, + input = i_stream_create_from_data(bodystructure, strlen(bodystructure)); + (void)i_stream_read(input); + +- parser = imap_parser_create(input, NULL, SIZE_MAX); ++ parser = imap_parser_create(input, NULL, SIZE_MAX, NULL); + ret = imap_parser_finish_line(parser, 0, + IMAP_PARSE_FLAG_LITERAL_TYPE, &args); + if (ret < 0) { +@@ -982,7 +982,7 @@ int imap_body_parse_from_bodystructure(const char *bodystructure, + input = i_stream_create_from_data(bodystructure, strlen(bodystructure)); + (void)i_stream_read(input); + +- parser = imap_parser_create(input, NULL, SIZE_MAX); ++ parser = imap_parser_create(input, NULL, SIZE_MAX, NULL); + ret = imap_parser_finish_line(parser, 0, IMAP_PARSE_FLAG_NO_UNESCAPE | + IMAP_PARSE_FLAG_LITERAL_TYPE, &args); + if (ret < 0) { +diff --git a/src/lib-imap/imap-envelope.c b/src/lib-imap/imap-envelope.c +index 395e189c70..2e305d7c42 100644 +--- a/src/lib-imap/imap-envelope.c ++++ b/src/lib-imap/imap-envelope.c +@@ -225,7 +225,7 @@ bool imap_envelope_parse(const char *envelope, + input = i_stream_create_from_data(envelope, strlen(envelope)); + (void)i_stream_read(input); + +- parser = imap_parser_create(input, NULL, SIZE_MAX); ++ parser = imap_parser_create(input, NULL, SIZE_MAX, NULL); + ret = imap_parser_finish_line(parser, 0, + IMAP_PARSE_FLAG_LITERAL_TYPE, &args); + if (ret < 0) { +diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c +index 643f80ceeb..532cb97dfb 100644 +--- a/src/lib-imap/imap-parser.c ++++ b/src/lib-imap/imap-parser.c +@@ -69,7 +69,8 @@ struct imap_parser { + + struct imap_parser * + imap_parser_create(struct istream *input, struct ostream *output, +- size_t max_line_size) ++ size_t max_line_size, ++ const struct imap_parser_params *params ATTR_UNUSED) + { + struct imap_parser *parser; + +diff --git a/src/lib-imap/imap-parser.h b/src/lib-imap/imap-parser.h +index cd3748c00f..16ef2c7a34 100644 +--- a/src/lib-imap/imap-parser.h ++++ b/src/lib-imap/imap-parser.h +@@ -38,6 +38,9 @@ enum imap_parser_error { + IMAP_PARSE_ERROR_LITERAL_TOO_BIG + }; + ++struct imap_parser_params { ++}; ++ + struct imap_parser; + + /* Create new IMAP argument parser. output is used for sending command +@@ -53,7 +56,8 @@ struct imap_parser; + 2 * max_line_size. */ + struct imap_parser * + imap_parser_create(struct istream *input, struct ostream *output, +- size_t max_line_size) ATTR_NULL(2); ++ size_t max_line_size, ++ const struct imap_parser_params *params); + void imap_parser_ref(struct imap_parser *parser); + void imap_parser_unref(struct imap_parser **parser); + +diff --git a/src/lib-imap/test-imap-parser.c b/src/lib-imap/test-imap-parser.c +index 32f8d89dea..58c5863d67 100644 +--- a/src/lib-imap/test-imap-parser.c ++++ b/src/lib-imap/test-imap-parser.c +@@ -16,7 +16,7 @@ static void test_imap_parser_crlf(void) + + test_begin("imap parser crlf handling"); + input = test_istream_create(test_input); +- parser = imap_parser_create(input, NULL, 1024); ++ parser = imap_parser_create(input, NULL, 1024, NULL); + + /* must return -2 until LF is read */ + for (i = 0; test_input[i] != '\n'; i++) { +@@ -60,7 +60,7 @@ static void test_imap_parser_partial_list(void) + + test_begin("imap parser partial list"); + input = test_istream_create(test_input); +- parser = imap_parser_create(input, NULL, 1024); ++ parser = imap_parser_create(input, NULL, 1024, NULL); + + (void)i_stream_read(input); + test_assert(imap_parser_read_args(parser, 0, +@@ -128,7 +128,7 @@ static void test_imap_parser_read_tag_cmd(void) + if (tests[i].type != COMMAND) { + input = test_istream_create(tests[i].input); + test_assert(i_stream_read(input) > 0); +- parser = imap_parser_create(input, NULL, 1024); ++ parser = imap_parser_create(input, NULL, 1024, NULL); + ret = imap_parser_read_tag(parser, &atom); + test_assert_idx(ret == tests[i].ret, i); + test_assert_idx(ret <= 0 || strcmp(tests[i].tag, atom) == 0, i); +@@ -139,7 +139,7 @@ static void test_imap_parser_read_tag_cmd(void) + if (tests[i].type != TAG) { + input = test_istream_create(tests[i].input); + test_assert(i_stream_read(input) > 0); +- parser = imap_parser_create(input, NULL, 1024); ++ parser = imap_parser_create(input, NULL, 1024, NULL); + ret = imap_parser_read_command_name(parser, &atom); + test_assert_idx(ret == tests[i].ret, i); + test_assert_idx(ret <= 0 || strcmp(tests[i].tag, atom) == 0, i); +diff --git a/src/plugins/virtual/virtual-config.c b/src/plugins/virtual/virtual-config.c +index f448c81d7d..6ec5aa260e 100644 +--- a/src/plugins/virtual/virtual-config.c ++++ b/src/plugins/virtual/virtual-config.c +@@ -54,7 +54,7 @@ virtual_search_args_parse(const string_t *rule, const char **error_r) + input = i_stream_create_from_data(str_data(rule), str_len(rule)); + (void)i_stream_read(input); + +- imap_parser = imap_parser_create(input, NULL, SIZE_MAX); ++ imap_parser = imap_parser_create(input, NULL, SIZE_MAX, NULL); + ret = imap_parser_finish_line(imap_parser, 0, 0, &args); + if (ret < 0) { + sargs = NULL; +diff --git a/src/lib-imap/imap-id.c b/src/lib-imap/imap-id.c +index f448c81d7d..6ec5aa260e 100644 +--- a/src/lib-imap/imap-id.c ++++ b/src/lib-imap/imap-id.c +@@ -111,7 +111,7 @@ const char *imap_id_reply_generate(const + input = i_stream_create_from_data(settings, strlen(settings)); + (void)i_stream_read(input); + +- parser = imap_parser_create(input, NULL, SIZE_MAX); ++ parser = imap_parser_create(input, NULL, SIZE_MAX, NULL); + if (imap_parser_finish_line(parser, 0, 0, &args) <= 0) + ret = "NIL"; + else +diff --git a/src/director/director-test.c b/src/director/director-test.c +index f448c81d7d..6ec5aa260e 100644 +--- a/src/director/director-test.c ++++ b/src/director/director-test.c +@@ -250,7 +250,7 @@ static void imap_client_create(int fd) + o_stream_set_no_error_handling(client->output, TRUE); + client->io = io_add(fd, IO_READ, imap_client_input, client); + client->parser = +- imap_parser_create(client->input, client->output, 4096); ++ imap_parser_create(client->input, client->output, 4096, NULL); + o_stream_nsend_str(client->output, + "* OK [CAPABILITY IMAP4rev1] director-test ready.\r\n"); + DLLIST_PREPEND(&imap_clients, client); diff --git a/dovecot-2.3-cve-2026-27857p2of5.patch b/dovecot-2.3-cve-2026-27857p2of5.patch new file mode 100644 index 0000000..91592f1 --- /dev/null +++ b/dovecot-2.3-cve-2026-27857p2of5.patch @@ -0,0 +1,149 @@ +diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c +index 532cb97dfb..6212aed33d 100644 +--- a/src/lib-imap/imap-parser.c ++++ b/src/lib-imap/imap-parser.c +@@ -39,6 +39,7 @@ struct imap_parser { + struct istream *input; + struct ostream *output; + size_t max_line_size; ++ unsigned int list_count_limit; + enum imap_parser_flags flags; + + /* reset by imap_parser_reset(): */ +@@ -46,6 +47,7 @@ struct imap_parser { + ARRAY_TYPE(imap_arg_list) root_list; + ARRAY_TYPE(imap_arg_list) *cur_list; + struct imap_arg *list_arg; ++ unsigned int list_count; + + enum arg_parse_type cur_type; + size_t cur_pos; /* parser position in input buffer */ +@@ -70,7 +72,7 @@ struct imap_parser { + struct imap_parser * + imap_parser_create(struct istream *input, struct ostream *output, + size_t max_line_size, +- const struct imap_parser_params *params ATTR_UNUSED) ++ const struct imap_parser_params *params) + { + struct imap_parser *parser; + +@@ -81,6 +83,10 @@ imap_parser_create(struct istream *input, struct ostream *output, + parser->input = input; + parser->output = output; + parser->max_line_size = max_line_size; ++ if (params != NULL && params->list_count_limit > 0) ++ parser->list_count_limit = params->list_count_limit; ++ else ++ parser->list_count_limit = UINT_MAX; + + p_array_init(&parser->root_list, parser->pool, LIST_INIT_COUNT); + parser->cur_list = &parser->root_list; +@@ -122,6 +128,7 @@ void imap_parser_reset(struct imap_parser *parser) + p_array_init(&parser->root_list, parser->pool, LIST_INIT_COUNT); + parser->cur_list = &parser->root_list; + parser->list_arg = NULL; ++ parser->list_count = 0; + + parser->cur_type = ARG_PARSE_NONE; + parser->cur_pos = 0; +@@ -210,6 +217,12 @@ static bool imap_parser_close_list(struct imap_parser *parser) + parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX; + return FALSE; + } ++ if (parser->list_count >= parser->list_count_limit) { ++ parser->error_msg = "Too many '('"; ++ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX; ++ return FALSE; ++ } ++ parser->list_count++; + + arg = imap_arg_create(parser); + arg->type = IMAP_ARG_EOL; +diff --git a/src/lib-imap/imap-parser.h b/src/lib-imap/imap-parser.h +index 16ef2c7a34..3832cc9b92 100644 +--- a/src/lib-imap/imap-parser.h ++++ b/src/lib-imap/imap-parser.h +@@ -39,6 +39,12 @@ enum imap_parser_error { + }; + + struct imap_parser_params { ++ /* How many open lists ('(' chars) to allow before faililng the parsing. ++ 0 means unlimited. This is mainly used to prevent excessive memory ++ usage in imap-login process. In imap process there are many other ++ ways to increase memory usage, so we let the max_line_size be the ++ only limit. */ ++ unsigned int list_count_limit; + }; + + struct imap_parser; +diff --git a/src/lib-imap/test-imap-parser.c b/src/lib-imap/test-imap-parser.c +index 58c5863d67..0350ea7352 100644 +--- a/src/lib-imap/test-imap-parser.c ++++ b/src/lib-imap/test-imap-parser.c +@@ -2,6 +2,7 @@ + + #include "lib.h" + #include "istream.h" ++#include "istream-chain.h" + #include "imap-parser.h" + #include "test-common.h" + +@@ -79,6 +80,50 @@ static void test_imap_parser_partial_list(void) + test_end(); + } + ++static void test_imap_parser_list_limit(void) ++{ ++ struct { ++ const char *input; ++ int ret; ++ } tests[] = { ++ { "(())\r\n", 1 }, ++ { "((()))\r\n", -1 }, ++ }; ++ struct istream_chain *chain; ++ struct istream *chain_input; ++ struct imap_parser *parser; ++ const struct imap_arg *args; ++ ++ test_begin("imap parser list limit"); ++ struct imap_parser_params params = { ++ .list_count_limit = 2, ++ }; ++ ++ for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) { ++ chain_input = i_stream_create_chain(&chain, SIZE_MAX); ++ parser = imap_parser_create(chain_input, NULL, 1024, ¶ms); ++ ++ for (unsigned int j = 0; j < 2; j++) { ++ struct istream *input = ++ test_istream_create(tests[i].input); ++ i_stream_chain_append(chain, input); ++ i_stream_unref(&input); ++ ++ (void)i_stream_read(chain_input); ++ ++ test_assert_cmp(imap_parser_read_args(parser, 0, 0, &args), ==, tests[i].ret); ++ /* skip over CRLF */ ++ i_stream_skip(chain_input, i_stream_get_data_size(chain_input)); ++ ++ /* make sure parser reset works */ ++ imap_parser_reset(parser); ++ } ++ imap_parser_unref(&parser); ++ i_stream_destroy(&chain_input); ++ } ++ test_end(); ++} ++ + static void test_imap_parser_read_tag_cmd(void) + { + enum read_type { +@@ -205,6 +250,7 @@ int main(void) + static void (*const test_functions[])(void) = { + test_imap_parser_crlf, + test_imap_parser_partial_list, ++ test_imap_parser_list_limit, + test_imap_parser_read_tag_cmd, + NULL + }; diff --git a/dovecot-2.3-cve-2026-27857p3of5.patch b/dovecot-2.3-cve-2026-27857p3of5.patch new file mode 100644 index 0000000..0cb8375 --- /dev/null +++ b/dovecot-2.3-cve-2026-27857p3of5.patch @@ -0,0 +1,71 @@ +diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c +index 84e6a90db4..93966b2d15 100644 +--- a/src/imap-login/imap-login-client.c ++++ b/src/imap-login/imap-login-client.c +@@ -380,11 +380,14 @@ static int imap_client_create(struct client *client) + { + struct imap_client *imap_client = (struct imap_client *)client; + ++ struct imap_parser_params params = { ++ .list_count_limit = IMAP_LOGIN_LIST_COUNT_LIMIT, ++ }; + imap_client->set = other_sets[0]; + imap_client->parser = + imap_parser_create(imap_client->common.input, + imap_client->common.output, +- IMAP_LOGIN_MAX_LINE_LENGTH, NULL); ++ IMAP_LOGIN_MAX_LINE_LENGTH, ¶ms); + if (imap_client->set->imap_literal_minus) + imap_parser_enable_literal_minus(imap_client->parser); + client->io = io_add_istream(client->input, client_input, client); +@@ -469,11 +472,14 @@ static void imap_client_starttls(struct client *client) + { + struct imap_client *imap_client = (struct imap_client *)client; + ++ struct imap_parser_params params = { ++ .list_count_limit = IMAP_LOGIN_LIST_COUNT_LIMIT, ++ }; + imap_parser_unref(&imap_client->parser); + imap_client->parser = + imap_parser_create(imap_client->common.input, + imap_client->common.output, +- IMAP_LOGIN_MAX_LINE_LENGTH, NULL); ++ IMAP_LOGIN_MAX_LINE_LENGTH, ¶ms); + + /* CRLF is lost from buffer when streams are reopened. */ + imap_client->skip_line = FALSE; +diff --git a/src/imap-login/imap-login-client.h b/src/imap-login/imap-login-client.h +index ffac6ec855..1ff88015b2 100644 +--- a/src/imap-login/imap-login-client.h ++++ b/src/imap-login/imap-login-client.h +@@ -11,6 +11,10 @@ + /* maximum length for IMAP command line. */ + #define IMAP_LOGIN_MAX_LINE_LENGTH 8192 + ++/* Maximum number of '(' allowed in an IMAP command. Pre-login only uses ++ lists in the ID command. */ ++#define IMAP_LOGIN_LIST_COUNT_LIMIT 1 ++ + enum imap_client_id_state { + IMAP_CLIENT_ID_STATE_LIST = 0, + IMAP_CLIENT_ID_STATE_KEY, +diff --git a/src/imap-login/imap-login-cmd-id.c b/src/imap-login/imap-login-cmd-id.c +index be2097f70b..a07b1f8f56 100644 +--- a/src/imap-login/imap-login-cmd-id.c ++++ b/src/imap-login/imap-login-cmd-id.c +@@ -389,10 +389,14 @@ int cmd_id(struct imap_client *client) + + if (client->cmd_id == NULL) { + client->cmd_id = id = i_new(struct imap_client_cmd_id, 1); ++ ++ struct imap_parser_params params = { ++ .list_count_limit = IMAP_LOGIN_LIST_COUNT_LIMIT, ++ }; + id->parser = imap_parser_create(client->common.input, + client->common.output, + IMAP_LOGIN_MAX_LINE_LENGTH, +- NULL); ++ ¶ms); + if (client->set->imap_literal_minus) + imap_parser_enable_literal_minus(id->parser); + parser_flags = IMAP_PARSE_FLAG_STOP_AT_LIST; diff --git a/dovecot-2.3-cve-2026-27857p4of5.patch b/dovecot-2.3-cve-2026-27857p4of5.patch new file mode 100644 index 0000000..8fb44f1 --- /dev/null +++ b/dovecot-2.3-cve-2026-27857p4of5.patch @@ -0,0 +1,48 @@ +diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c +index 93966b2d15..7e7578d4d4 100644 +--- a/src/imap-login/imap-login-client.c ++++ b/src/imap-login/imap-login-client.c +@@ -380,7 +380,7 @@ static int imap_client_create(struct client *client) + { + struct imap_client *imap_client = (struct imap_client *)client; + +- struct imap_parser_params params = { ++ const struct imap_parser_params params = { + .list_count_limit = IMAP_LOGIN_LIST_COUNT_LIMIT, + }; + imap_client->set = other_sets[0]; +@@ -415,7 +415,7 @@ static void imap_client_starttls(struct + { + struct imap_client *imap_client = (struct imap_client *)client; + +- struct imap_parser_params params = { ++ const struct imap_parser_params params = { + .list_count_limit = IMAP_LOGIN_LIST_COUNT_LIMIT, + }; + imap_parser_unref(&imap_client->parser); +diff --git a/src/imap-login/imap-login-cmd-id.c b/src/imap-login/imap-login-cmd-id.c +index a07b1f8f56..da254a2923 100644 +--- a/src/imap-login/imap-login-cmd-id.c ++++ b/src/imap-login/imap-login-cmd-id.c +@@ -390,7 +390,7 @@ int cmd_id(struct imap_client *client) + if (client->cmd_id == NULL) { + client->cmd_id = id = i_new(struct imap_client_cmd_id, 1); + +- struct imap_parser_params params = { ++ const struct imap_parser_params params = { + .list_count_limit = IMAP_LOGIN_LIST_COUNT_LIMIT, + }; + id->parser = imap_parser_create(client->common.input, +diff --git a/src/lib-imap/test-imap-parser.c b/src/lib-imap/test-imap-parser.c +index 0350ea7352..fb7c308a23 100644 +--- a/src/lib-imap/test-imap-parser.c ++++ b/src/lib-imap/test-imap-parser.c +@@ -95,7 +95,7 @@ static void test_imap_parser_list_limit(void) + const struct imap_arg *args; + + test_begin("imap parser list limit"); +- struct imap_parser_params params = { ++ const struct imap_parser_params params = { + .list_count_limit = 2, + }; + diff --git a/dovecot-2.3-cve-2026-27857p5of5.patch b/dovecot-2.3-cve-2026-27857p5of5.patch new file mode 100644 index 0000000..7a92637 --- /dev/null +++ b/dovecot-2.3-cve-2026-27857p5of5.patch @@ -0,0 +1,14 @@ +diff --git a/dovecot-pigeonhole/src/plugins/imap-filter-sieve/cmd-filter-sieve.c b/dovecot-pigeonhole/src/plugins/imap-filter-sieve/cmd-filter-sieve.c +index 6965b511..33d6804c 100644 +--- a/dovecot-pigeonhole/src/plugins/imap-filter-sieve/cmd-filter-sieve.c ++++ b/dovecot-pigeonhole/src/plugins/imap-filter-sieve/cmd-filter-sieve.c +@@ -379,7 +379,8 @@ bool cmd_filter_sieve(struct client_command_context *cmd) + asynchronously the same way as APPEND does. */ + client->input_lock = cmd; + ctx->parser = imap_parser_create(client->input, client->output, +- client->set->imap_max_line_length); ++ client->set->imap_max_line_length, ++ NULL); + if (client->set->imap_literal_minus) + imap_parser_enable_literal_minus(ctx->parser); + o_stream_unset_flush_callback(client->output); diff --git a/dovecot-2.3-cve-2026-27858.patch b/dovecot-2.3-cve-2026-27858.patch new file mode 100644 index 0000000..3bc7686 --- /dev/null +++ b/dovecot-2.3-cve-2026-27858.patch @@ -0,0 +1,17 @@ +diff --git a/dovecot-pigeonhole/src/managesieve-login/client-authenticate.c b/dovecot-pigeonhole/src/managesieve-login/client-authenticate.c +index cd7739d0..354e6746 100644 +--- a/dovecot-pigeonhole/src/managesieve-login/client-authenticate.c ++++ b/dovecot-pigeonhole/src/managesieve-login/client-authenticate.c +@@ -189,6 +189,11 @@ static int managesieve_client_auth_read_ + if ( i_stream_get_size + (msieve_client->auth_response_input, FALSE, &resp_size) <= 0 ) + resp_size = 0; ++ else if (resp_size > LOGIN_MAX_AUTH_BUF_SIZE) { ++ client_destroy(client, ++ "Authentication response too large"); ++ return -1; ++ } + + if (client->auth_response == NULL) + client->auth_response = str_new(default_pool, I_MAX(resp_size+1, 256)); + diff --git a/dovecot.spec b/dovecot.spec index 38ecf3a..c548c64 100644 --- a/dovecot.spec +++ b/dovecot.spec @@ -6,7 +6,7 @@ Name: dovecot Epoch: 1 Version: 2.3.21 %global prever %{nil} -Release: 17%{?dist} +Release: 18%{?dist} #dovecot itself is MIT, a few sources are PD, pigeonhole is LGPLv2 License: MIT AND LGPL-2.1-only @@ -69,6 +69,26 @@ Patch28: dovecot-2.3.21.1-CVE-2024-23184.patch # https://github.com/dovecot/core/compare/f020e13%5E...ce88c33.patch Patch29: dovecot-2.3.21.1-CVE-2024-23185.patch +# from upstream for < 2.4.3, RHEL-161626 +# https://github.com/dovecot/pigeonhole/commit/54f645225a8a7911d7e16e9d50f170d217b0be95 +Patch30: dovecot-2.3-cve-2026-27858.patch + +# from upstream for < 2.4.3, RHEL-162274 +# https://github.com/dovecot/pigeonhole/commit/efb68fac3a9d2d04d38c4ab14dd570cf0c23923c +Patch31: dovecot-2.3-cve-2025-59032.patch + +# from upstream for < 2.4.3, RHEL-161665 +# https://github.com/dovecot/core/commit/825bc297f87b856992aa14beac596ec838248210 +Patch32: dovecot-2.3-cve-2026-27857p1of5.patch +# https://github.com/dovecot/core/commit/d0f67b52914565a35f3817335ab9633cb291513c +Patch33: dovecot-2.3-cve-2026-27857p2of5.patch +# https://github.com/dovecot/core/commit/af1fb4da5c1c5c458dc1d54dee3aefde6d3aa835 +Patch34: dovecot-2.3-cve-2026-27857p3of5.patch +# https://github.com/dovecot/core/commit/3435e0d44c131eb1046a84fd83798f1e101b725e +Patch35: dovecot-2.3-cve-2026-27857p4of5.patch +# https://github.com/dovecot/pigeonhole/commit/5701db04455ee4d8e927d0b225634780a9b656b4 +Patch36: dovecot-2.3-cve-2026-27857p5of5.patch + BuildRequires: gcc, gcc-c++, openssl-devel, pam-devel, zlib-devel, bzip2-devel, libcap-devel BuildRequires: libtool, autoconf, automake, pkgconfig BuildRequires: sqlite-devel @@ -175,6 +195,13 @@ mv dovecot-2.3-pigeonhole-%{pigeonholever} dovecot-pigeonhole %patch -P 27 -p1 -b .test-socket-path %patch -P 28 -p1 -b .CVE-2024-23184 %patch -P 29 -p1 -b .CVE-2024-23185 +%patch -P 30 -p1 -b .cve-2026-27858 +%patch -P 31 -p1 -b .cve-2025-59032 +%patch -P 32 -p1 -b .cve-2026-27857p1of5 +%patch -P 33 -p1 -b .cve-2026-27857p2of5 +%patch -P 34 -p1 -b .cve-2026-27857p3of5 +%patch -P 35 -p1 -b .cve-2026-27857p4of5 +%patch -P 36 -p1 -b .cve-2026-27857p5of5 cp run-test-valgrind.supp dovecot-pigeonhole/ # valgrind would fail with shell wrapper echo "testsuite" >dovecot-pigeonhole/run-test-valgrind.exclude @@ -535,6 +562,11 @@ make check %{_libdir}/%{name}/dict/libdriver_pgsql.so %changelog +* Thu Apr 30 2026 Michal Hlavinka - 1:2.3.21-18 +- fix CVE-2026-27858: denial of service via crafted message before authentication (RHEL-161626) +- fix CVE-2025-59032: ManageSieve: Denial of Service via crafted SASL initial response in AUTHENTICATE command (RHEL-162274) +- fix CVE-2026-27857: denial of service via specially crafted NOOP command (RHEL-161665) + * Mon Jan 12 2026 Michal Hlavinka - 1:2.3.21-17 - fix building with latest openssl (RHEL-117460) - add /var/lib/dovecot to tmpfiles for image mode (RHEL-130953)