diff --git a/.dovecot.metadata b/.dovecot.metadata index e2aab88..99acbac 100644 --- a/.dovecot.metadata +++ b/.dovecot.metadata @@ -1,2 +1,2 @@ -b9c7290dad1ac3bc1ead11359812a137a3d173f7 SOURCES/dovecot-2.3-pigeonhole-0.5.8.tar.gz -65b93f7fd53705b3c97f9eee141a76c5f4f3a624 SOURCES/dovecot-2.3.8.tar.gz +4673c244c6ea73ee3da0bb61d0206a1fe3d0be0e SOURCES/dovecot-2.3-pigeonhole-0.5.16.tar.gz +b5c598ae8b9901bfabdf2c93271f57cde0bde73e SOURCES/dovecot-2.3.16.tar.gz diff --git a/.gitignore b/.gitignore index c1a5ba9..465afeb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -SOURCES/dovecot-2.3-pigeonhole-0.5.8.tar.gz -SOURCES/dovecot-2.3.8.tar.gz +SOURCES/dovecot-2.3-pigeonhole-0.5.16.tar.gz +SOURCES/dovecot-2.3.16.tar.gz diff --git a/SOURCES/dovecot-2.1.10-waitonline.patch b/SOURCES/dovecot-2.1.10-waitonline.patch index 2b1cd42..af3ce19 100644 --- a/SOURCES/dovecot-2.1.10-waitonline.patch +++ b/SOURCES/dovecot-2.1.10-waitonline.patch @@ -1,11 +1,11 @@ -diff -up dovecot-2.3.0.1/dovecot.service.in.waitonline dovecot-2.3.0.1/dovecot.service.in ---- dovecot-2.3.0.1/dovecot.service.in.waitonline 2018-03-01 10:35:39.888371078 +0100 -+++ dovecot-2.3.0.1/dovecot.service.in 2018-03-01 10:36:29.738784661 +0100 -@@ -12,6 +12,7 @@ After=local-fs.target network-online.tar +diff -up dovecot-2.3.15/dovecot.service.in.waitonline dovecot-2.3.15/dovecot.service.in +--- dovecot-2.3.15/dovecot.service.in.waitonline 2021-06-21 20:19:19.560494654 +0200 ++++ dovecot-2.3.15/dovecot.service.in 2021-06-21 20:21:17.443066248 +0200 +@@ -15,6 +15,7 @@ After=local-fs.target network-online.tar [Service] - Type=simple + Type=@systemdservicetype@ +ExecStartPre=/usr/libexec/dovecot/prestartscript ExecStart=@sbindir@/dovecot -F - PIDFile=@rundir@/master.pid ExecReload=@bindir@/doveadm reload + ExecStop=@bindir@/doveadm stop diff --git a/SOURCES/dovecot-2.2.20-initbysystemd.patch b/SOURCES/dovecot-2.2.20-initbysystemd.patch index 7e3d94c..313e26b 100644 --- a/SOURCES/dovecot-2.2.20-initbysystemd.patch +++ b/SOURCES/dovecot-2.2.20-initbysystemd.patch @@ -1,6 +1,6 @@ -diff -up dovecot-2.3.0.1/dovecot-init.service.initbysystemd dovecot-2.3.0.1/dovecot-init.service ---- dovecot-2.3.0.1/dovecot-init.service.initbysystemd 2018-03-01 10:38:22.059716008 +0100 -+++ dovecot-2.3.0.1/dovecot-init.service 2018-03-01 10:38:22.059716008 +0100 +diff -up dovecot-2.3.15/dovecot-init.service.initbysystemd dovecot-2.3.15/dovecot-init.service +--- dovecot-2.3.15/dovecot-init.service.initbysystemd 2021-06-21 20:21:49.250680889 +0200 ++++ dovecot-2.3.15/dovecot-init.service 2021-06-21 20:21:49.250680889 +0200 @@ -0,0 +1,13 @@ +[Unit] +Description=One-time Dovecot init service @@ -15,32 +15,37 @@ diff -up dovecot-2.3.0.1/dovecot-init.service.initbysystemd dovecot-2.3.0.1/dove + SSLDIR=/etc/pki/dovecot/ OPENSSLCONFIG=/etc/pki/dovecot/dovecot-openssl.cnf /usr/libexec/dovecot/mkcert.sh /dev/null 2>&1;\ +fi' + -diff -up dovecot-2.3.0.1/dovecot.service.in.initbysystemd dovecot-2.3.0.1/dovecot.service.in ---- dovecot-2.3.0.1/dovecot.service.in.initbysystemd 2018-03-01 10:38:22.060716016 +0100 -+++ dovecot-2.3.0.1/dovecot.service.in 2018-03-01 10:40:45.524901319 +0100 -@@ -8,7 +8,8 @@ +diff -up dovecot-2.3.15/dovecot.service.in.initbysystemd dovecot-2.3.15/dovecot.service.in +--- dovecot-2.3.15/dovecot.service.in.initbysystemd 2021-06-21 20:21:49.250680889 +0200 ++++ dovecot-2.3.15/dovecot.service.in 2021-06-21 20:22:46.935981920 +0200 +@@ -11,7 +11,8 @@ Description=Dovecot IMAP/POP3 email server Documentation=man:dovecot(1) - Documentation=http://wiki2.dovecot.org/ + Documentation=https://doc.dovecot.org/ -After=local-fs.target network-online.target +After=local-fs.target network-online.target dovecot-init.service +Requires=dovecot-init.service [Service] - Type=simple -diff -up dovecot-2.3.0.1/Makefile.am.initbysystemd dovecot-2.3.0.1/Makefile.am ---- dovecot-2.3.0.1/Makefile.am.initbysystemd 2018-02-28 15:28:57.000000000 +0100 -+++ dovecot-2.3.0.1/Makefile.am 2018-03-01 10:38:22.060716016 +0100 -@@ -63,9 +63,10 @@ if HAVE_SYSTEMD + Type=@systemdservicetype@ +diff -up dovecot-2.3.15/Makefile.am.initbysystemd dovecot-2.3.15/Makefile.am +--- dovecot-2.3.15/Makefile.am.initbysystemd 2021-06-21 20:21:49.250680889 +0200 ++++ dovecot-2.3.15/Makefile.am 2021-06-21 20:24:26.676765849 +0200 +@@ -21,6 +21,7 @@ EXTRA_DIST = \ + run-test-valgrind.supp \ + dovecot.service.in \ + dovecot.socket \ ++ dovecot-init.service \ + $(conf_DATA) + noinst_DATA = dovecot-config +@@ -69,7 +70,8 @@ dovecot-config: dovecot-config.in Makefi + if WANT_SYSTEMD systemdsystemunit_DATA = \ dovecot.socket \ - dovecot.service + dovecot.service \ + dovecot-init.service - else --EXTRA_DIST += dovecot.socket dovecot.service.in -+EXTRA_DIST += dovecot.socket dovecot.service.in dovecot-init.service endif install-exec-hook: diff --git a/SOURCES/dovecot-2.2.36-bigkey.patch b/SOURCES/dovecot-2.2.36-bigkey.patch index c5b23d9..dc81a33 100644 --- a/SOURCES/dovecot-2.2.36-bigkey.patch +++ b/SOURCES/dovecot-2.2.36-bigkey.patch @@ -1,9 +1,9 @@ -diff -up dovecot-2.2.36/doc/dovecot-openssl.cnf.bigkey dovecot-2.2.36/doc/dovecot-openssl.cnf ---- dovecot-2.2.36/doc/dovecot-openssl.cnf.bigkey 2017-06-23 13:18:28.000000000 +0200 -+++ dovecot-2.2.36/doc/dovecot-openssl.cnf 2018-10-16 17:15:35.836205498 +0200 +diff -up dovecot-2.3.15/doc/dovecot-openssl.cnf.bigkey dovecot-2.3.15/doc/dovecot-openssl.cnf +--- dovecot-2.3.15/doc/dovecot-openssl.cnf.bigkey 2021-06-21 20:24:51.913456628 +0200 ++++ dovecot-2.3.15/doc/dovecot-openssl.cnf 2021-06-21 20:25:36.352912123 +0200 @@ -1,5 +1,5 @@ [ req ] --default_bits = 1024 +-default_bits = 2048 +default_bits = 3072 encrypt_key = yes distinguished_name = req_dn diff --git a/SOURCES/dovecot-2.3.10-CVE_2020_10957,10958,10967.patch b/SOURCES/dovecot-2.3.10-CVE_2020_10957,10958,10967.patch deleted file mode 100644 index 67a810d..0000000 --- a/SOURCES/dovecot-2.3.10-CVE_2020_10957,10958,10967.patch +++ /dev/null @@ -1,1090 +0,0 @@ -diff -up dovecot-2.3.8/src/lib-smtp/Makefile.am.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lib-smtp/Makefile.am ---- dovecot-2.3.8/src/lib-smtp/Makefile.am.CVE_2020_10957,10958,10967 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-smtp/Makefile.am 2020-05-29 19:11:53.357162340 +0200 -@@ -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 -up dovecot-2.3.8/src/lib-smtp/smtp-address.c.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lib-smtp/smtp-address.c ---- dovecot-2.3.8/src/lib-smtp/smtp-address.c.CVE_2020_10957,10958,10967 2020-05-29 19:11:53.356162354 +0200 -+++ dovecot-2.3.8/src/lib-smtp/smtp-address.c 2020-05-29 19:13:33.310813425 +0200 -@@ -625,13 +625,13 @@ smtp_address_clone(pool_t pool, const st - size_t size, lpsize = 0, dsize = 0; - char *data, *localpart = NULL, *domain = NULL; - -- if (smtp_address_isnull(src)) -+ if (src == NULL) - return NULL; - - /* @UNSAFE */ - - size = sizeof(struct smtp_address); -- if (src->localpart != NULL && *src->localpart != '\0') { -+ if (!smtp_address_isnull(src)) { - lpsize = strlen(src->localpart) + 1; - size = MALLOC_ADD(size, lpsize); - } -@@ -686,7 +686,7 @@ smtp_address_clone_temp(const struct smt - { - struct smtp_address *new; - -- if (smtp_address_isnull(src)) -+ if (src == NULL) - return NULL; - - new = t_new(struct smtp_address, 1); -diff -up dovecot-2.3.8/src/lib-smtp/smtp-address.h.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lib-smtp/smtp-address.h ---- dovecot-2.3.8/src/lib-smtp/smtp-address.h.CVE_2020_10957,10958,10967 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-smtp/smtp-address.h 2020-05-29 19:11:53.358162327 +0200 -@@ -122,8 +122,14 @@ smtp_address_equals(const struct smtp_ad - static inline bool ATTR_NULL(1) ATTR_PURE - smtp_address_isnull(const struct smtp_address *address) - { -- return (address == NULL || address->localpart == NULL || -- *address->localpart == '\0'); -+ return (address == NULL || address->localpart == NULL); - } - -+static inline bool ATTR_NULL(1) ATTR_PURE -+smtp_address_is_broken(const struct smtp_address *address) -+{ -+ return (address != NULL && -+ smtp_address_isnull(address) /*&& -+ (address->raw != NULL && *address->raw != '\0')*/); -+} - #endif -diff -up dovecot-2.3.8/src/lib-smtp/smtp-server-cmd-noop.c.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lib-smtp/smtp-server-cmd-noop.c ---- dovecot-2.3.8/src/lib-smtp/smtp-server-cmd-noop.c.CVE_2020_10957,10958,10967 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-smtp/smtp-server-cmd-noop.c 2020-05-29 19:11:53.358162327 +0200 -@@ -13,11 +13,15 @@ void smtp_server_cmd_noop(struct smtp_se - 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 -up dovecot-2.3.8/src/lib-smtp/smtp-server-cmd-vrfy.c.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lib-smtp/smtp-server-cmd-vrfy.c ---- dovecot-2.3.8/src/lib-smtp/smtp-server-cmd-vrfy.c.CVE_2020_10957,10958,10967 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-smtp/smtp-server-cmd-vrfy.c 2020-05-29 19:11:53.358162327 +0200 -@@ -17,15 +17,13 @@ void smtp_server_cmd_vrfy(struct smtp_se - int ret; - - /* vrfy = "VRFY" SP String CRLF */ -- if ((ret=smtp_string_parse(params, ¶m, &error)) <= 0) { -- if (ret < 0) { -- smtp_server_reply(cmd, -- 501, "5.5.4", -- "Invalid string parameter: %s", error); -- } else { -- 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; -+ } else if (ret == 0) { -+ smtp_server_reply(cmd, 501, "5.5.4", "Invalid parameters"); - return; - } - -diff -up dovecot-2.3.8/src/lib-smtp/smtp-server-command.c.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lib-smtp/smtp-server-command.c ---- dovecot-2.3.8/src/lib-smtp/smtp-server-command.c.CVE_2020_10957,10958,10967 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-smtp/smtp-server-command.c 2020-05-29 19:11:53.358162327 +0200 -@@ -179,14 +179,15 @@ smtp_server_command_new_invalid(struct s - - struct smtp_server_command * - smtp_server_command_new(struct smtp_server_connection *conn, -- const char *name, const char *params) -+ const char *name) - { - struct smtp_server *server = conn->server; -- const struct smtp_server_command_reg *cmd_reg; - struct smtp_server_command *cmd; - - cmd = smtp_server_command_alloc(conn); - cmd->context.name = p_strdup(cmd->context.pool, name); -+ cmd->reg = smtp_server_command_find(server, name); -+ - smtp_server_command_update_event(cmd); - - struct event_passthrough *e = -@@ -194,7 +195,15 @@ smtp_server_command_new(struct smtp_serv - set_name("smtp_server_command_started"); - e_debug(e->event(), "New command"); - -- if ((cmd_reg=smtp_server_command_find(server, name)) == NULL) { -+ return cmd; -+} -+ -+void smtp_server_command_execute(struct smtp_server_command *cmd, -+ const char *params) -+{ -+ struct smtp_server_connection *conn = cmd->context.conn; -+ -+ if (cmd->reg == NULL) { - /* RFC 5321, Section 4.2.4: Reply Code 502 - - Questions have been raised as to when reply code 502 (Command -@@ -207,7 +216,7 @@ smtp_server_command_new(struct smtp_serv - 500, "5.5.1", "Unknown command"); - - } else if (!conn->ssl_secured && conn->set.tls_required && -- (cmd_reg->flags & SMTP_SERVER_CMD_FLAG_PRETLS) == 0) { -+ (cmd->reg->flags & SMTP_SERVER_CMD_FLAG_PRETLS) == 0) { - /* RFC 3207, Section 4: - - A SMTP server that is not publicly referenced may choose to -@@ -226,7 +235,7 @@ smtp_server_command_new(struct smtp_serv - 530, "5.7.0", "TLS required."); - - } else if (!conn->authenticated && !conn->set.auth_optional && -- (cmd_reg->flags & SMTP_SERVER_CMD_FLAG_PREAUTH) == 0) { -+ (cmd->reg->flags & SMTP_SERVER_CMD_FLAG_PREAUTH) == 0) { - /* RFC 4954, Section 6: Status Codes - - 530 5.7.0 Authentication required -@@ -242,16 +251,14 @@ smtp_server_command_new(struct smtp_serv - } else { - struct smtp_server_command *tmp_cmd = cmd; - -- i_assert(cmd_reg->func != NULL); -+ i_assert(cmd->reg->func != NULL); - smtp_server_command_ref(tmp_cmd); -- tmp_cmd->reg = cmd_reg; -- cmd_reg->func(&tmp_cmd->context, params); -+ cmd->reg->func(&tmp_cmd->context, params); - if (tmp_cmd->state == SMTP_SERVER_COMMAND_STATE_NEW) - tmp_cmd->state = SMTP_SERVER_COMMAND_STATE_PROCESSING; - if (!smtp_server_command_unref(&tmp_cmd)) - cmd = NULL; - } -- return cmd; - } - - void smtp_server_command_ref(struct smtp_server_command *cmd) -@@ -389,8 +396,11 @@ bool smtp_server_command_call_hooks(stru - struct smtp_server_command *cmd = *_cmd; - struct smtp_server_command_hook *hook; - -- if (type != SMTP_SERVER_COMMAND_HOOK_DESTROY) -+ if (type != SMTP_SERVER_COMMAND_HOOK_DESTROY) { -+ if (cmd->state >= SMTP_SERVER_COMMAND_STATE_FINISHED) -+ return FALSE; - smtp_server_command_ref(cmd); -+ } - - hook = cmd->hooks_head; - while (hook != NULL) { -diff -up dovecot-2.3.8/src/lib-smtp/smtp-server-connection.c.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lib-smtp/smtp-server-connection.c ---- dovecot-2.3.8/src/lib-smtp/smtp-server-connection.c.CVE_2020_10957,10958,10967 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-smtp/smtp-server-connection.c 2020-05-29 19:11:53.358162327 +0200 -@@ -293,20 +293,28 @@ smtp_server_connection_handle_command(st - { - struct smtp_server_connection *tmp_conn = conn; - struct smtp_server_command *cmd; -+ bool finished; -+ -+ cmd = smtp_server_command_new(tmp_conn, cmd_name); -+ -+ smtp_server_command_ref(cmd); - - smtp_server_connection_ref(tmp_conn); -- cmd = smtp_server_command_new(tmp_conn, cmd_name, cmd_params); -+ smtp_server_command_execute(cmd, cmd_params); - if (!smtp_server_connection_unref(&tmp_conn)) { - /* the command start callback managed to get this connection - destroyed */ -+ smtp_server_command_unref(&cmd); - return FALSE; - } - -- if (cmd != NULL && conn->command_queue_head == cmd) -+ if (conn->command_queue_head == cmd) - (void)smtp_server_command_next_to_reply(&cmd); - - smtp_server_connection_timeout_update(conn); -- return (cmd == NULL || !cmd->input_locked); -+ -+ finished = !cmd->input_locked; -+ return (!smtp_server_command_unref(&cmd) || finished); - } - - static int -diff -up dovecot-2.3.8/src/lib-smtp/smtp-server-private.h.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lib-smtp/smtp-server-private.h ---- dovecot-2.3.8/src/lib-smtp/smtp-server-private.h.CVE_2020_10957,10958,10967 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-smtp/smtp-server-private.h 2020-05-29 19:11:53.358162327 +0200 -@@ -241,8 +241,11 @@ void smtp_server_command_debug(struct sm - struct smtp_server_command * - smtp_server_command_new_invalid(struct smtp_server_connection *conn); - struct smtp_server_command * --smtp_server_command_new(struct smtp_server_connection *conn, -- const char *name, const char *params); -+smtp_server_command_new(struct smtp_server_connection *conn, const char *name); -+ -+void smtp_server_command_execute(struct smtp_server_command *cmd, -+ const char *params); -+ - void smtp_server_command_ref(struct smtp_server_command *cmd); - bool smtp_server_command_unref(struct smtp_server_command **_cmd); - void smtp_server_command_abort(struct smtp_server_command **_cmd); -diff -up dovecot-2.3.8/src/lib-smtp/smtp-syntax.c.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lib-smtp/smtp-syntax.c ---- dovecot-2.3.8/src/lib-smtp/smtp-syntax.c.CVE_2020_10957,10958,10967 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-smtp/smtp-syntax.c 2020-05-29 19:11:53.358162327 +0200 -@@ -17,18 +17,19 @@ 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 = ""; -- return 1; -+ return 0; - } - - 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) { -@@ -85,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) { -@@ -109,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; - } - } -@@ -249,12 +249,10 @@ static int smtp_parse_ehlo_line(struct s - (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 s - 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 s - 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 *ehl - 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 -up dovecot-2.3.8/src/lib-smtp/test-smtp-server-errors.c.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lib-smtp/test-smtp-server-errors.c ---- dovecot-2.3.8/src/lib-smtp/test-smtp-server-errors.c.CVE_2020_10957,10958,10967 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-smtp/test-smtp-server-errors.c 2020-05-29 19:11:53.359162313 +0200 -@@ -574,6 +574,174 @@ static void test_bad_command(void) - } - - /* -+ * Many bad commands -+ */ -+ -+/* client */ -+ -+struct _many_bad_commands_client { -+ struct smtp_reply_parser *parser; -+ unsigned int reply; -+ bool replied:1; -+}; -+ -+static void -+test_many_bad_commands_client_input(struct client_connection *conn) -+{ -+ struct _many_bad_commands_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++) { -+ /* greeting */ -+ case 0: -+ i_assert(reply->status == 220); -+ break; -+ /* bad command reply */ -+ case 1: case 2: case 3: case 4: case 5: -+ case 6: case 7: case 8: case 9: case 10: -+ i_assert(reply->status == 500); -+ break; -+ case 11: -+ i_assert(reply->status == 421); -+ ctx->replied = TRUE; -+ io_loop_stop(ioloop); -+ connection_disconnect(&conn->conn); -+ return; -+ default: -+ i_unreached(); -+ } -+ } -+ -+ i_assert(ret >= 0); -+} -+ -+static void -+test_many_bad_commands_client_connected(struct client_connection *conn) -+{ -+ struct _many_bad_commands_client *ctx; -+ -+ ctx = p_new(conn->pool, struct _many_bad_commands_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, -+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); -+ break; -+ case 1: -+ o_stream_nsend_str(conn->conn.output, -+ "a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\n" -+ "i\r\nj\r\nk\r\nl\r\nm\r\nn\r\no\r\np\r\n"); -+ break; -+ default: -+ i_unreached(); -+ } -+} -+ -+static void -+test_many_bad_commands_client_deinit(struct client_connection *conn) -+{ -+ struct _many_bad_commands_client *ctx = conn->context; -+ -+ i_assert(ctx->replied); -+ smtp_reply_parser_deinit(&ctx->parser); -+} -+ -+static void test_client_many_bad_commands(unsigned int index) -+{ -+ test_client_input = test_many_bad_commands_client_input; -+ test_client_connected = test_many_bad_commands_client_connected; -+ test_client_deinit = test_many_bad_commands_client_deinit; -+ test_client_run(index); -+} -+ -+/* server */ -+ -+struct _many_bad_commands { -+ struct istream *payload_input; -+ struct io *io; -+ -+ bool serviced:1; -+}; -+ -+static void -+test_server_many_bad_commands_disconnect(void *context ATTR_UNUSED, -+ const char *reason) -+{ -+ if (debug) -+ i_debug("Disconnect: %s", reason); -+ io_loop_stop(ioloop); -+} -+ -+static int -+test_server_many_bad_commands_helo( -+ void *conn_ctx ATTR_UNUSED, struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, -+ struct smtp_server_cmd_helo *data ATTR_UNUSED) -+{ -+ test_assert(FALSE); -+ return 1; -+} -+ -+static int -+test_server_many_bad_commands_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_many_bad_commands_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_many_bad_commands -+(const struct smtp_server_settings *server_set) -+{ -+ server_callbacks.conn_disconnect = -+ test_server_many_bad_commands_disconnect; -+ -+ server_callbacks.conn_cmd_helo = -+ test_server_many_bad_commands_helo; -+ server_callbacks.conn_cmd_rcpt = -+ test_server_many_bad_commands_rcpt; -+ server_callbacks.conn_cmd_data_begin = -+ test_server_many_bad_commands_data_begin; -+ test_server_run(server_set); -+} -+ -+/* test */ -+ -+static void test_many_bad_commands(void) -+{ -+ struct smtp_server_settings smtp_server_set; -+ -+ test_server_defaults(&smtp_server_set); -+ smtp_server_set.max_client_idle_time_msecs = 1000; -+ smtp_server_set.max_bad_commands = 10; -+ -+ test_begin("many bad commands"); -+ test_run_client_server(&smtp_server_set, -+ test_server_many_bad_commands, -+ test_client_many_bad_commands, 2); -+ test_end(); -+} -+ -+/* - * Long command - */ - -@@ -1274,6 +1442,316 @@ static void test_bad_rcpt(void) - } - - /* -+ * 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 - */ - -@@ -2023,11 +2501,14 @@ static void (*const test_functions[])(vo - test_slow_client, - test_hanging_command_payload, - test_bad_command, -+ test_many_bad_commands, - test_long_command, - test_big_data, - 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 -up dovecot-2.3.8/src/lib-smtp/test-smtp-syntax.c.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lib-smtp/test-smtp-syntax.c ---- dovecot-2.3.8/src/lib-smtp/test-smtp-syntax.c.CVE_2020_10957,10958,10967 2020-05-29 19:11:53.359162313 +0200 -+++ dovecot-2.3.8/src/lib-smtp/test-smtp-syntax.c 2020-05-29 19:11:53.359162313 +0200 -@@ -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 -up dovecot-2.3.8/src/lmtp/lmtp-commands.c.CVE_2020_10957,10958,10967 dovecot-2.3.8/src/lmtp/lmtp-commands.c ---- dovecot-2.3.8/src/lmtp/lmtp-commands.c.CVE_2020_10957,10958,10967 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lmtp/lmtp-commands.c 2020-05-29 19:11:53.359162313 +0200 -@@ -66,10 +66,18 @@ int client_default_cmd_rcpt(struct clien - char delim = '\0'; - int ret; - -+ i_assert(!smtp_address_isnull(rcpt->path)); -+ if (*rcpt->path->localpart == '\0' && rcpt->path->domain == NULL) { -+ smtp_server_recipient_reply( -+ rcpt, 550, "5.1.1", -+ "Unacceptable TO: Empty path not allowed"); -+ return -1; -+ } - - smtp_address_detail_parse_temp( - client->unexpanded_lda_set->recipient_delimiter, - rcpt->path, &username, &delim, &detail); -+ i_assert(*username != '\0'); - - /* Make user name and detail available in the recipient event. The - mail_user event (for local delivery) also adds the user field, but diff --git a/SOURCES/dovecot-2.3.10-smtppre.patch b/SOURCES/dovecot-2.3.10-smtppre.patch deleted file mode 100644 index 7bef066..0000000 --- a/SOURCES/dovecot-2.3.10-smtppre.patch +++ /dev/null @@ -1,121 +0,0 @@ -diff -up dovecot-2.3.8/src/lib-smtp/smtp-address.c.smtppre dovecot-2.3.8/src/lib-smtp/smtp-address.c ---- dovecot-2.3.8/src/lib-smtp/smtp-address.c.smtppre 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-smtp/smtp-address.c 2020-05-29 19:11:19.340621409 +0200 -@@ -467,7 +467,7 @@ void smtp_address_detail_parse(pool_t po - *detail_r = p+1; - } - -- if (address->domain == NULL) -+ if (address->domain == NULL || *address->domain == '\0') - *username_r = user; - else if (strchr(user, '@') == NULL ) { - /* username is just glued to the domain... no SMTP escaping */ -@@ -548,7 +548,7 @@ void smtp_address_write(string_t *out, - if (quoted) - str_append_c(out, '\"'); - -- if (address->domain == NULL) -+ if (address->domain == NULL || *address->domain == '\0') - return; - - str_append_c(out, '@'); -@@ -587,8 +587,12 @@ void smtp_address_init(struct smtp_addre - const char *localpart, const char *domain) - { - i_zero(address); -+ if (localpart == NULL || *localpart == '\0') -+ return; -+ - address->localpart = localpart; -- address->domain = (localpart == NULL ? NULL : domain); -+ if (domain != NULL && *domain != '\0') -+ address->domain = domain; - } - - int smtp_address_init_from_msg(struct smtp_address *address, -@@ -597,7 +601,7 @@ int smtp_address_init_from_msg(struct sm - const char *p; - - i_zero(address); -- if (msg_addr->mailbox == NULL) -+ if (msg_addr->mailbox == NULL || *msg_addr->mailbox == '\0') - return 0; - - /* The message_address_parse() function allows UTF-8 codepoints in -@@ -609,7 +613,8 @@ int smtp_address_init_from_msg(struct sm - } - - address->localpart = msg_addr->mailbox; -- address->domain = msg_addr->domain; -+ if (msg_addr->domain != NULL && *msg_addr->domain != '\0') -+ address->domain = msg_addr->domain; - return 0; - } - -@@ -617,8 +622,8 @@ struct smtp_address * - smtp_address_clone(pool_t pool, const struct smtp_address *src) - { - struct smtp_address *new; -- size_t size, lpsize, dsize = 0; -- char *data, *localpart, *domain = NULL; -+ size_t size, lpsize = 0, dsize = 0; -+ char *data, *localpart = NULL, *domain = NULL; - - if (smtp_address_isnull(src)) - return NULL; -@@ -626,17 +631,21 @@ smtp_address_clone(pool_t pool, const st - /* @UNSAFE */ - - size = sizeof(struct smtp_address); -- lpsize = strlen(src->localpart) + 1; -- size = MALLOC_ADD(size, lpsize); -- if (src->domain != NULL) { -+ if (src->localpart != NULL && *src->localpart != '\0') { -+ lpsize = strlen(src->localpart) + 1; -+ size = MALLOC_ADD(size, lpsize); -+ } -+ if (src->domain != NULL && *src->domain != '\0') { - dsize = strlen(src->domain) + 1; - size = MALLOC_ADD(size, dsize); - } - - data = p_malloc(pool, size); - new = (struct smtp_address *)data; -- localpart = PTR_OFFSET(data, sizeof(*new)); -- memcpy(localpart, src->localpart, lpsize); -+ if (lpsize > 0) { -+ localpart = PTR_OFFSET(data, sizeof(*new)); -+ memcpy(localpart, src->localpart, lpsize); -+ } - if (dsize > 0) { - domain = PTR_OFFSET(data, sizeof(*new) + lpsize); - memcpy(domain, src->domain, dsize); -@@ -681,8 +690,8 @@ smtp_address_clone_temp(const struct smt - return NULL; - - new = t_new(struct smtp_address, 1); -- new->localpart = t_strdup(src->localpart); -- new->domain = t_strdup(src->domain); -+ new->localpart = t_strdup_empty(src->localpart); -+ new->domain = t_strdup_empty(src->domain); - return new; - } - -@@ -720,7 +729,7 @@ smtp_address_add_detail(pool_t pool, con - new_addr = p_new(pool, struct smtp_address, 1); - new_addr->localpart = p_strconcat(pool, - address->localpart, delim, detail, NULL); -- new_addr->domain = p_strdup(pool, address->domain); -+ new_addr->domain = p_strdup_empty(pool, address->domain); - - return new_addr; - } -@@ -737,7 +746,7 @@ smtp_address_add_detail_temp(const struc - new_addr = t_new(struct smtp_address, 1); - new_addr->localpart = t_strconcat( - address->localpart, delim, detail, NULL); -- new_addr->domain = t_strdup(address->domain); -+ new_addr->domain = t_strdup_empty(address->domain); - - return new_addr; - } diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_24386-part1.patch b/SOURCES/dovecot-2.3.13-CVE_2020_24386-part1.patch deleted file mode 100644 index 5347f43..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_24386-part1.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 68165c8acc6d32a06f8dce2ef515c714c243ce4e Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 17 Aug 2020 18:33:20 +0300 -Subject: [PATCH] imap: Escape tag when sending it to imap-hibernate process - ---- - src/imap/imap-client-hibernate.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c -index f639d722cb..4ef323453c 100644 ---- a/src/imap/imap-client-hibernate.c -+++ b/src/imap/imap-client-hibernate.c -@@ -97,8 +97,10 @@ static void imap_hibernate_write_cmd(struct client *client, string_t *cmd, - str_printfa(cmd, "\tuid=%s", dec2str(user->uid)); - if (user->gid != (gid_t)-1) - str_printfa(cmd, "\tgid=%s", dec2str(user->gid)); -- if (tag != NULL) -- str_printfa(cmd, "\ttag=%s", tag); -+ if (tag != NULL) { -+ str_append(cmd, "\ttag="); -+ str_append_tabescaped(cmd, tag); -+ } - str_append(cmd, "\tstats="); - str_append_tabescaped(cmd, client_stats(client)); - if (client->command_queue != NULL && diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_24386-part2.patch b/SOURCES/dovecot-2.3.13-CVE_2020_24386-part2.patch deleted file mode 100644 index e829001..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_24386-part2.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 73937b5fe7eb1dde76f30ef6b181c920bbbc4558 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 24 Aug 2020 16:58:16 +0300 -Subject: [PATCH] imap: Fix crash if imap-hibernate socket can't be connected - to - -The error was supposed to be returned to caller, not logged directly. ---- - src/imap/imap-client-hibernate.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c -index 4ef323453c..d3451b1bf6 100644 ---- a/src/imap/imap-client-hibernate.c -+++ b/src/imap/imap-client-hibernate.c -@@ -176,7 +176,8 @@ imap_hibernate_process_send(struct client *client, const buffer_t *state, - "/"IMAP_HIBERNATE_SOCKET_NAME, NULL); - fd = net_connect_unix_with_retries(path, 1000); - if (fd == -1) { -- i_error("net_connect_unix(%s) failed: %m", path); -+ *error_r = t_strdup_printf( -+ "net_connect_unix(%s) failed: %m", path); - return -1; - } - net_set_nonblock(fd, FALSE); diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_24386-part3.patch b/SOURCES/dovecot-2.3.13-CVE_2020_24386-part3.patch deleted file mode 100644 index 830b5e4..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_24386-part3.patch +++ /dev/null @@ -1,31 +0,0 @@ -From c7d158681fabdb3044bd213c332e489b46625a3b Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 24 Aug 2020 19:10:10 +0300 -Subject: [PATCH] imap: Delay initializing client IO until - client_create_finish() - -This helps writing unit tests. ---- - src/imap/imap-client.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c -index 95e57dbf53..c8ffeafc43 100644 ---- a/src/imap/imap-client.c -+++ b/src/imap/imap-client.c -@@ -143,7 +143,6 @@ struct client *client_create(int fd_in, int fd_out, - o_stream_set_flush_callback(client->output, client_output, client); - - p_array_init(&client->module_contexts, client->pool, 5); -- client->io = io_add_istream(client->input, client_input, client); - client->last_input = ioloop_time; - client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS, - client_idle_timeout, client); -@@ -228,6 +227,7 @@ int client_create_finish(struct client *client, const char **error_r) - return -1; - mail_namespaces_set_storage_callbacks(client->user->namespaces, - &mail_storage_callbacks, client); -+ client->io = io_add_istream(client->input, client_input, client); - - client->v.init(client); - return 0; diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_24386-part4.patch b/SOURCES/dovecot-2.3.13-CVE_2020_24386-part4.patch deleted file mode 100644 index e6af09e..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_24386-part4.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 1a27cfa8e337b7e3298ba230059e766cdbc1123d Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 24 Aug 2020 19:10:43 +0300 -Subject: [PATCH] imap: imap_client_hibernate() - Return reason string on - failure - -This helps writing a unit test for it. ---- - src/imap/cmd-idle.c | 3 ++- - src/imap/imap-client-hibernate.c | 10 +++++++++- - src/imap/imap-client.h | 5 +++-- - 3 files changed, 14 insertions(+), 4 deletions(-) - -diff --git a/src/imap/cmd-idle.c b/src/imap/cmd-idle.c -index 8a05582d03..2b31dc714e 100644 ---- a/src/imap/cmd-idle.c -+++ b/src/imap/cmd-idle.c -@@ -175,11 +175,12 @@ static void idle_add_keepalive_timeout(struct cmd_idle_context *ctx) - static void idle_hibernate_timeout(struct cmd_idle_context *ctx) - { - struct client *client = ctx->client; -+ const char *reason; - - i_assert(ctx->sync_ctx == NULL); - i_assert(!ctx->sync_pending); - -- if (imap_client_hibernate(&client)) { -+ if (imap_client_hibernate(&client, &reason)) { - /* client may be destroyed now */ - } else { - /* failed - don't bother retrying */ -diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c -index d3451b1bf6..0709e4a244 100644 ---- a/src/imap/imap-client-hibernate.c -+++ b/src/imap/imap-client-hibernate.c -@@ -203,19 +203,23 @@ imap_hibernate_process_send(struct client *client, const buffer_t *state, - return 0; - } - --bool imap_client_hibernate(struct client **_client) -+bool imap_client_hibernate(struct client **_client, const char **reason_r) - { - struct client *client = *_client; - buffer_t *state; - const char *error; - int ret, fd_notify = -1, fd_hibernate = -1; - -+ *reason_r = NULL; -+ - if (client->fd_in != client->fd_out) { - /* we won't try to hibernate stdio clients */ -+ *reason_r = "stdio clients can't be hibernated"; - return FALSE; - } - if (o_stream_get_buffer_used_size(client->output) > 0) { - /* wait until we've sent the pending output to client */ -+ *reason_r = "output pending to client"; - return FALSE; - } - -@@ -233,11 +237,13 @@ bool imap_client_hibernate(struct client **_client) - "Couldn't export state: %s (mailbox=%s)", error, - client->mailbox == NULL ? "" : - mailbox_get_vname(client->mailbox)); -+ *reason_r = error; - } else if (ret == 0) { - e_debug(client->event, "Couldn't hibernate imap client: " - "Couldn't export state: %s (mailbox=%s)", error, - client->mailbox == NULL ? "" : - mailbox_get_vname(client->mailbox)); -+ *reason_r = error; - } - if (ret > 0 && client->mailbox != NULL) { - fd_notify = mailbox_watch_extract_notify_fd(client->mailbox, -@@ -248,6 +254,7 @@ bool imap_client_hibernate(struct client **_client) - e_debug(client->event, "Couldn't hibernate imap client: " - "Couldn't extract notifications fd: %s", - error); -+ *reason_r = error; - ret = -1; - } - } -@@ -257,5 +264,6 @@ bool imap_client_hibernate(struct client **_client) - e_error(client->event, - "Couldn't hibernate imap client: %s", error); -+ *reason_r = error; - ret = -1; - } - } -diff --git a/src/imap/imap-client.h b/src/imap/imap-client.h -index f2ffe0d7c9..4e591d5c7c 100644 ---- a/src/imap/imap-client.h -+++ b/src/imap/imap-client.h -@@ -323,8 +323,9 @@ enum mailbox_feature client_enabled_mailbox_features(struct client *client); - const char *const *client_enabled_features(struct client *client); - - /* Send client processing to imap-idle process. If successful, returns TRUE -- and destroys the client. */ --bool imap_client_hibernate(struct client **client); -+ and destroys the client. If hibernation failed, the exact reason is -+ returned (mainly for unit tests). */ -+bool imap_client_hibernate(struct client **client, const char **reason_r); - - struct imap_search_update * - client_search_update_lookup(struct client *client, const char *tag, diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_24386-prereq1.patch b/SOURCES/dovecot-2.3.13-CVE_2020_24386-prereq1.patch deleted file mode 100644 index 00ee47f..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_24386-prereq1.patch +++ /dev/null @@ -1,129 +0,0 @@ -diff -up dovecot-2.3.8/src/imap/imap-client-hibernate.c.CVE_2020_24386-prereq1 dovecot-2.3.8/src/imap/imap-client-hibernate.c ---- dovecot-2.3.8/src/imap/imap-client-hibernate.c.CVE_2020_24386-prereq1 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/imap/imap-client-hibernate.c 2021-01-08 17:14:40.051174282 +0100 -@@ -19,24 +19,26 @@ - #define IMAP_HIBERNATE_SEND_TIMEOUT_SECS 10 - #define IMAP_HIBERNATE_HANDSHAKE "VERSION\timap-hibernate\t1\t0\n" - --static int imap_hibernate_handshake(int fd, const char *path) -+static int -+imap_hibernate_handshake(int fd, const char *path, const char **error_r) - { - char buf[1024]; - ssize_t ret; - - if (write_full(fd, IMAP_HIBERNATE_HANDSHAKE, - strlen(IMAP_HIBERNATE_HANDSHAKE)) < 0) { -- i_error("write(%s) failed: %m", path); -+ *error_r = t_strdup_printf("write(%s) failed: %m", path); - return -1; - } else if ((ret = read(fd, buf, sizeof(buf)-1)) < 0) { -- i_error("read(%s) failed: %m", path); -+ *error_r = t_strdup_printf("read(%s) failed: %m", path); - return -1; - } else if (ret > 0 && buf[ret-1] == '\n') { - buf[ret-1] = '\0'; - if (version_string_verify(buf, "imap-hibernate", 1)) - return 0; - } -- i_error("%s sent invalid VERSION handshake: %s", path, buf); -+ *error_r = t_strdup_printf("%s sent invalid VERSION handshake: %s", -+ path, buf); - return -1; - } - -@@ -105,40 +107,42 @@ static void imap_hibernate_write_cmd(str - - static int - imap_hibernate_process_send_cmd(int fd_socket, const char *path, -- const string_t *cmd, int fd_client) -+ const string_t *cmd, int fd_client, -+ const char **error_r) - { - ssize_t ret; - - i_assert(fd_socket != -1); - i_assert(str_len(cmd) > 1); - -- if (imap_hibernate_handshake(fd_socket, path) < 0) -+ if (imap_hibernate_handshake(fd_socket, path, error_r) < 0) - return -1; - if ((ret = fd_send(fd_socket, fd_client, str_data(cmd), 1)) < 0) { -- i_error("fd_send(%s) failed: %m", path); -+ *error_r = t_strdup_printf("fd_send(%s) failed: %m", path); - return -1; - } - if ((ret = write_full(fd_socket, str_data(cmd)+1, str_len(cmd)-1)) < 0) { -- i_error("write(%s) failed: %m", path); -+ *error_r = t_strdup_printf("write(%s) failed: %m", path); - return -1; - } - return 0; - } - --static int imap_hibernate_process_read(int fd, const char *path) -+static int -+imap_hibernate_process_read(int fd, const char *path, const char **error_r) - { - char buf[1024]; - ssize_t ret; - - if ((ret = read(fd, buf, sizeof(buf)-1)) < 0) { -- i_error("read(%s) failed: %m", path); -+ *error_r = t_strdup_printf("read(%s) failed: %m", path); - return -1; - } else if (ret == 0) { -- i_error("%s disconnected", path); -+ *error_r = t_strdup_printf("%s disconnected", path); - return -1; - } else if (buf[0] != '+') { - buf[ret] = '\0'; -- i_error("%s returned failure: %s", path, -+ *error_r = t_strdup_printf("%s returned failure: %s", path, - ret > 0 && buf[0] == '-' ? buf+1 : buf); - return -1; - } else { -@@ -147,8 +151,8 @@ static int imap_hibernate_process_read(i - } - - static int --imap_hibernate_process_send(struct client *client, -- const buffer_t *state, int fd_notify, int *fd_r) -+imap_hibernate_process_send(struct client *client, const buffer_t *state, -+ int fd_notify, int *fd_r, const char **error_r) - { - string_t *cmd = t_str_new(512); - const char *path; -@@ -171,14 +175,14 @@ imap_hibernate_process_send(struct clien - imap_hibernate_write_cmd(client, cmd, state, fd_notify); - - alarm(IMAP_HIBERNATE_SEND_TIMEOUT_SECS); -- if (imap_hibernate_process_send_cmd(fd, path, cmd, client->fd_in) < 0 || -- imap_hibernate_process_read(fd, path) < 0) -+ if (imap_hibernate_process_send_cmd(fd, path, cmd, client->fd_in, error_r) < 0 || -+ imap_hibernate_process_read(fd, path, error_r) < 0) - ret = -1; - else if (fd_notify != -1) { - if ((ret = fd_send(fd, fd_notify, "\n", 1)) < 0) -- i_error("fd_send(%s) failed: %m", path); -+ *error_r = t_strdup_printf("fd_send(%s) failed: %m", path); - else -- ret = imap_hibernate_process_read(fd, path); -+ ret = imap_hibernate_process_read(fd, path, error_r); - } - alarm(0); - if (ret < 0) { -@@ -229,8 +233,12 @@ bool imap_client_hibernate(struct client - } - } - if (ret > 0) { -- if (imap_hibernate_process_send(client, state, fd_notify, &fd_hibernate) < 0) -+ if (imap_hibernate_process_send(client, state, fd_notify, -+ &fd_hibernate, &error) < 0) { -+ e_error(client->event, -+ "Couldn't hibernate imap client: %s", error); - ret = -1; -+ } - } - i_close_fd(&fd_notify); - if (ret > 0) { diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part1.patch b/SOURCES/dovecot-2.3.13-CVE_2020_25275-part1.patch deleted file mode 100644 index b5c630f..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part1.patch +++ /dev/null @@ -1,185 +0,0 @@ -From b9a2f18466a0d3377bab3e7a57691bdd75d8507c Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 17 Aug 2020 17:32:11 +0300 -Subject: [PATCH] lib-imap: Add imap_parser_read_tag() and _read_command_name() - ---- - src/lib-imap/imap-parser.c | 67 +++++++++++++++++++++++++++++++++ - src/lib-imap/imap-parser.h | 7 ++++ - src/lib-imap/test-imap-parser.c | 67 +++++++++++++++++++++++++++++++++ - 3 files changed, 141 insertions(+) - -diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c -index b6c6e63fb1..52d79282fa 100644 ---- a/src/lib-imap/imap-parser.c -+++ b/src/lib-imap/imap-parser.c -@@ -947,3 +947,70 @@ const char *imap_parser_read_word(struct imap_parser *parser) - return NULL; - } - } -+ -+static int -+imap_parser_read_next_atom(struct imap_parser *parser, bool parsing_tag, -+ const char **atom_r) -+{ -+ const unsigned char *data; -+ size_t i, data_size; -+ -+ data = i_stream_get_data(parser->input, &data_size); -+ -+ /* -+ tag = 1* -+ ASTRING-CHAR = ATOM-CHAR / resp-specials -+ ATOM-CHAR = -+ -+ x-command = "X" atom -+ atom = 1*ATOM-CHAR -+ */ -+ for (i = 0; i < data_size; i++) { -+ /* explicitly check for atom-specials, because -+ IS_ATOM_PARSER_INPUT() allows some atom-specials */ -+ switch (data[i]) { -+ case ' ': -+ case '\r': -+ case '\n': -+ data_size = i + (data[i] == ' ' ? 1 : 0); -+ parser->line_size += data_size; -+ i_stream_skip(parser->input, data_size); -+ *atom_r = p_strndup(parser->pool, data, i); -+ /* don't allow empty string */ -+ return i == 0 ? -1 : 1; -+ /* atom-specials: */ -+ case '(': -+ case ')': -+ case '{': -+ /* list-wildcards: */ -+ case '%': -+ case '*': -+ /* quoted-specials: */ -+ case '"': -+ case '\\': -+ /* resp-specials: */ -+ case ']': -+ return -1; -+ case '+': -+ if (parsing_tag) -+ return -1; -+ break; -+ default: -+ if ((unsigned char)data[i] < ' ' || -+ (unsigned char)data[i] >= 0x80) -+ return -1; -+ } -+ } -+ return 0; -+} -+ -+int imap_parser_read_tag(struct imap_parser *parser, const char **tag_r) -+{ -+ return imap_parser_read_next_atom(parser, TRUE, tag_r); -+} -+ -+int imap_parser_read_command_name(struct imap_parser *parser, -+ const char **name_r) -+{ -+ return imap_parser_read_next_atom(parser, FALSE, name_r); -+} -diff --git a/src/lib-imap/imap-parser.h b/src/lib-imap/imap-parser.h -index e5d01c17f2..5e09d61d2b 100644 ---- a/src/lib-imap/imap-parser.h -+++ b/src/lib-imap/imap-parser.h -@@ -101,5 +101,12 @@ int imap_parser_finish_line(struct imap_parser *parser, unsigned int count, - /* Read one word - used for reading tag and command name. - Returns NULL if more data is needed. */ - const char *imap_parser_read_word(struct imap_parser *parser); -+/* Read command tag. Returns 1 if tag was returned, 0 if more data is needed, -+ -1 if input isn't a valid tag. */ -+int imap_parser_read_tag(struct imap_parser *parser, const char **tag_r); -+/* Read command name. Returns 1 if command name was returned, 0 if more data is -+ needed, -1 if input isn't a valid command name string. */ -+int imap_parser_read_command_name(struct imap_parser *parser, -+ const char **name_r); - - #endif -diff --git a/src/lib-imap/test-imap-parser.c b/src/lib-imap/test-imap-parser.c -index 93ef8fd59b..3ca4e34858 100644 ---- a/src/lib-imap/test-imap-parser.c -+++ b/src/lib-imap/test-imap-parser.c -@@ -79,10 +79,77 @@ static void test_imap_parser_partial_list(void) - test_end(); - } - -+static void test_imap_parser_read_tag_cmd(void) -+{ -+ enum read_type { -+ BOTH, -+ TAG, -+ COMMAND -+ }; -+ struct { -+ const char *input; -+ const char *tag; -+ int ret; -+ enum read_type type; -+ } tests[] = { -+ { "tag foo", "tag", 1, BOTH }, -+ { "tag\r", "tag", 1, BOTH }, -+ { "tag\rfoo", "tag", 1, BOTH }, -+ { "tag\nfoo", "tag", 1, BOTH }, -+ { "tag\r\nfoo", "tag", 1, BOTH }, -+ { "\n", NULL, -1, BOTH }, -+ { "tag", NULL, 0, BOTH }, -+ { "tag\t", NULL, -1, BOTH }, -+ { "tag\001", NULL, -1, BOTH }, -+ { "tag\x80", NULL, -1, BOTH }, -+ { "tag(", NULL, -1, BOTH }, -+ { "tag)", NULL, -1, BOTH }, -+ { "tag{", NULL, -1, BOTH }, -+ { "tag/ ", "tag/", 1, BOTH }, -+ { "tag%", NULL, -1, BOTH }, -+ { "tag*", NULL, -1, BOTH }, -+ { "tag\"", NULL, -1, BOTH }, -+ { "tag\\", NULL, -1, BOTH }, -+ { "tag+", NULL, -1, TAG }, -+ { "tag+ ", "tag+", 1, COMMAND }, -+ }; -+ struct istream *input; -+ struct imap_parser *parser; -+ const char *atom; -+ int ret; -+ -+ test_begin("imap_parser_read_tag and imap_parser_read_command_name"); -+ for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) { -+ 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); -+ 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); -+ imap_parser_unref(&parser); -+ i_stream_destroy(&input); -+ } -+ -+ 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); -+ 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); -+ imap_parser_unref(&parser); -+ i_stream_destroy(&input); -+ } -+ } -+ test_end(); -+} -+ - int main(void) - { - static void (*const test_functions[])(void) = { - test_imap_parser_crlf, -+ test_imap_parser_read_tag_cmd, - NULL - }; - return test_run(test_functions); diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part2.patch b/SOURCES/dovecot-2.3.13-CVE_2020_25275-part2.patch deleted file mode 100644 index d50ae5b..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part2.patch +++ /dev/null @@ -1,46 +0,0 @@ -From eea57c8683325f9767b2eb1b44a0b23352541c1e Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 17 Aug 2020 17:59:19 +0300 -Subject: [PATCH] imap: Split off client_command_failed_early() - ---- - src/imap/imap-client.c | 19 ++++++++++++++----- - 1 file changed, 14 insertions(+), 5 deletions(-) - -diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c -index 07b2a8018b..0bf03caa97 100644 ---- a/src/imap/imap-client.c -+++ b/src/imap/imap-client.c -@@ -1176,6 +1176,19 @@ bool client_handle_unfinished_cmd(struct client_command_context *cmd) - return TRUE; - } - -+static void -+client_command_failed_early(struct client_command_context **_cmd, -+ const char *error) -+{ -+ struct client_command_context *cmd = *_cmd; -+ -+ io_loop_time_refresh(); -+ command_stats_start(cmd); -+ client_send_command_error(cmd, error); -+ cmd->param_error = TRUE; -+ client_command_free(_cmd); -+} -+ - static bool client_command_input(struct client_command_context *cmd) - { - struct client *client = cmd->client; -@@ -1239,11 +1252,7 @@ static bool client_command_input(struct client_command_context *cmd) - - if (cmd->func == NULL) { - /* unknown command */ -- io_loop_time_refresh(); -- command_stats_start(cmd); -- client_send_command_error(cmd, "Unknown command."); -- cmd->param_error = TRUE; -- client_command_free(&cmd); -+ client_command_failed_early(&cmd, "Unknown command."); - return TRUE; - } else { - i_assert(!client->disconnected); diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part3.patch b/SOURCES/dovecot-2.3.13-CVE_2020_25275-part3.patch deleted file mode 100644 index 5c176c3..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part3.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 0386140f61f9ba62225e90b419215f72bba6ad8b Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 17 Aug 2020 18:11:36 +0300 -Subject: [PATCH] imap: Use imap_parser_read_tag() and _read_command_name() - ---- - src/imap/imap-client.c | 33 ++++++++++++++++++++++----------- - 1 file changed, 22 insertions(+), 11 deletions(-) - -diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c -index 0bf03caa97..95e57dbf53 100644 ---- a/src/imap/imap-client.c -+++ b/src/imap/imap-client.c -@@ -1182,6 +1182,9 @@ client_command_failed_early(struct client_command_context **_cmd, - { - struct client_command_context *cmd = *_cmd; - -+ /* ignore the rest of this line */ -+ cmd->client->input_skip_line = TRUE; -+ - io_loop_time_refresh(); - command_stats_start(cmd); - client_send_command_error(cmd, error); -@@ -1193,6 +1196,8 @@ static bool client_command_input(struct client_command_context *cmd) - { - struct client *client = cmd->client; - struct command *command; -+ const char *tag, *name; -+ int ret; - - if (cmd->func != NULL) { - /* command is being executed - continue it */ -@@ -1207,27 +1212,33 @@ static bool client_command_input(struct client_command_context *cmd) - } - - if (cmd->tag == NULL) { -- cmd->tag = imap_parser_read_word(cmd->parser); -- if (cmd->tag == NULL) -+ ret = imap_parser_read_tag(cmd->parser, &tag); -+ if (ret == 0) - return FALSE; /* need more data */ -- cmd->tag = p_strdup(cmd->pool, cmd->tag); -+ if (ret < 0) { -+ client_command_failed_early(&cmd, "Invalid tag."); -+ return TRUE; -+ } -+ cmd->tag = p_strdup(cmd->pool, tag); - } - - if (cmd->name == NULL) { -- cmd->name = imap_parser_read_word(cmd->parser); -- if (cmd->name == NULL) -+ ret = imap_parser_read_command_name(cmd->parser, &name); -+ if (ret == 0) - return FALSE; /* need more data */ -+ if (ret < 0) { -+ client_command_failed_early(&cmd, "Invalid command name."); -+ return TRUE; -+ } - - /* UID commands are a special case. better to handle them - here. */ -- if (!cmd->uid && strcasecmp(cmd->name, "UID") == 0) { -+ if (!cmd->uid && strcasecmp(name, "UID") == 0) { - cmd->uid = TRUE; -- cmd->name = imap_parser_read_word(cmd->parser); -- if (cmd->name == NULL) -- return FALSE; /* need more data */ -+ return client_command_input(cmd); - } -- cmd->name = !cmd->uid ? p_strdup(cmd->pool, cmd->name) : -- p_strconcat(cmd->pool, "UID ", cmd->name, NULL); -+ cmd->name = !cmd->uid ? p_strdup(cmd->pool, name) : -+ p_strconcat(cmd->pool, "UID ", name, NULL); - client_command_init_finished(cmd); - imap_refresh_proctitle(); - } diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part4.patch b/SOURCES/dovecot-2.3.13-CVE_2020_25275-part4.patch deleted file mode 100644 index a59ad97..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part4.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 62061e8cf68f506c0ccaaba21fd4174764ca875f Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 17 Aug 2020 18:15:35 +0300 -Subject: [PATCH] imap-login: Split off client_invalid_command() - ---- - src/imap-login/imap-login-client.c | 27 +++++++++++++++++---------- - 1 file changed, 17 insertions(+), 10 deletions(-) - -diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c -index e2af176309..ce5049d567 100644 ---- a/src/imap-login/imap-login-client.c -+++ b/src/imap-login/imap-login-client.c -@@ -194,6 +194,22 @@ static int client_command_execute(struct imap_client *client, const char *cmd, - return login_cmd->func(client, args); - } - -+static bool client_invalid_command(struct imap_client *client) -+{ -+ if (*client->cmd_tag == '\0') -+ client->cmd_tag = "*"; -+ if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) { -+ client_send_reply(&client->common, IMAP_CMD_REPLY_BYE, -+ "Too many invalid IMAP commands."); -+ client_destroy(&client->common, -+ "Disconnected: Too many invalid commands"); -+ return FALSE; -+ } -+ client_send_reply(&client->common, IMAP_CMD_REPLY_BAD, -+ "Error in IMAP command received by server."); -+ return TRUE; -+} -+ - static bool imap_is_valid_tag(const char *tag) - { - for (; *tag != '\0'; tag++) { -@@ -326,17 +342,8 @@ static bool imap_client_input_next_cmd(struct client *_client) - "not the command name. Add that before the command, " - "like: a login user pass"); - } else if (ret < 0) { -- if (*client->cmd_tag == '\0') -- client->cmd_tag = "*"; -- if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) { -- client_send_reply(&client->common, IMAP_CMD_REPLY_BYE, -- "Too many invalid IMAP commands."); -- client_destroy(&client->common, -- "Disconnected: Too many invalid commands"); -+ if (!client_invalid_command(client)) - return FALSE; -- } -- client_send_reply(&client->common, IMAP_CMD_REPLY_BAD, -- "Error in IMAP command received by server."); - } - - return ret != 0 && !client->common.destroyed; diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part5.patch b/SOURCES/dovecot-2.3.13-CVE_2020_25275-part5.patch deleted file mode 100644 index 8c3d0eb..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part5.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 9d3ecff3de5553159334cf644e996a616dc52670 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 17 Aug 2020 18:22:42 +0300 -Subject: [PATCH] imap-login: Use imap_parser_read_tag() and - _read_command_name() - ---- - src/imap-login/imap-login-client.c | 58 ++++++++++++------------------ - 1 file changed, 23 insertions(+), 35 deletions(-) - -diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c -index ce5049d567..b2c8af9cbf 100644 ---- a/src/imap-login/imap-login-client.c -+++ b/src/imap-login/imap-login-client.c -@@ -196,7 +196,7 @@ static int client_command_execute(struct imap_client *client, const char *cmd, - - static bool client_invalid_command(struct imap_client *client) - { -- if (*client->cmd_tag == '\0') -+ if (client->cmd_tag == NULL || *client->cmd_tag == '\0') - client->cmd_tag = "*"; - if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) { - client_send_reply(&client->common, IMAP_CMD_REPLY_BYE, -@@ -210,33 +210,6 @@ static bool client_invalid_command(struct imap_client *client) - return TRUE; - } - --static bool imap_is_valid_tag(const char *tag) --{ -- for (; *tag != '\0'; tag++) { -- switch (*tag) { -- case '+': -- /* atom-specials: */ -- case '(': -- case ')': -- case '{': -- case '/': -- case ' ': -- /* list-wildcards: */ -- case '%': -- case '*': -- /* quoted-specials: */ -- case '"': -- case '\\': -- return FALSE; -- default: -- if (*tag < ' ') /* CTL */ -- return FALSE; -- break; -- } -- } -- return TRUE; --} -- - static int client_parse_command(struct imap_client *client, - const struct imap_arg **args_r) - { -@@ -261,6 +234,9 @@ static int client_parse_command(struct imap_client *client, - - static bool client_handle_input(struct imap_client *client) - { -+ const char *tag, *name; -+ int ret; -+ - i_assert(!client->common.authenticating); - - if (client->cmd_finished) { -@@ -282,23 +258,35 @@ static bool client_handle_input(struct imap_client *client) - } - - if (client->cmd_tag == NULL) { -- client->cmd_tag = imap_parser_read_word(client->parser); -- if (client->cmd_tag == NULL) -+ ret = imap_parser_read_tag(client->parser, &tag); -+ if (ret == 0) - return FALSE; /* need more data */ -- if (!imap_is_valid_tag(client->cmd_tag) || -- strlen(client->cmd_tag) > IMAP_TAG_MAX_LEN) { -+ if (ret < 0 || strlen(tag) > IMAP_TAG_MAX_LEN) { - /* the tag is invalid, don't allow it and don't - send it back. this attempts to prevent any - potentially dangerous replies in case someone tries - to access us using HTTP protocol. */ -- client->cmd_tag = ""; -+ client->skip_line = TRUE; -+ client->cmd_finished = TRUE; -+ if (!client_invalid_command(client)) -+ return FALSE; -+ return client_handle_input(client); - } -+ client->cmd_tag = tag; - } - - if (client->cmd_name == NULL) { -- client->cmd_name = imap_parser_read_word(client->parser); -- if (client->cmd_name == NULL) -+ ret = imap_parser_read_command_name(client->parser, &name); -+ if (ret == 0) - return FALSE; /* need more data */ -+ if (ret < 0) { -+ client->skip_line = TRUE; -+ client->cmd_finished = TRUE; -+ if (!client_invalid_command(client)) -+ return FALSE; -+ return client_handle_input(client); -+ } -+ client->cmd_name = name; - } - return client->common.v.input_next_cmd(&client->common); - } diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part6.patch b/SOURCES/dovecot-2.3.13-CVE_2020_25275-part6.patch deleted file mode 100644 index 0233807..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part6.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 7a70f01fe8084431901433a2f74cb9c70fd00568 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 17 Aug 2020 18:26:01 +0300 -Subject: [PATCH] lib-imap: Add imap_parser_client_read_tag() - ---- - src/lib-imap/imap-parser.c | 6 ++++++ - src/lib-imap/imap-parser.h | 5 +++++ - 2 files changed, 11 insertions(+) - -diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c -index 52d79282fa..cc283f5c06 100644 ---- a/src/lib-imap/imap-parser.c -+++ b/src/lib-imap/imap-parser.c -@@ -1014,3 +1014,9 @@ int imap_parser_read_command_name(struct imap_parser *parser, - { - return imap_parser_read_next_atom(parser, FALSE, name_r); - } -+ -+int imap_parser_client_read_tag(struct imap_parser *parser, -+ const char **tag_r) -+{ -+ return imap_parser_read_next_atom(parser, FALSE, tag_r); -+} -diff --git a/src/lib-imap/imap-parser.h b/src/lib-imap/imap-parser.h -index 5e09d61d2b..cd3748c00f 100644 ---- a/src/lib-imap/imap-parser.h -+++ b/src/lib-imap/imap-parser.h -@@ -108,5 +108,10 @@ int imap_parser_read_tag(struct imap_parser *parser, const char **tag_r); - needed, -1 if input isn't a valid command name string. */ - int imap_parser_read_command_name(struct imap_parser *parser, - const char **name_r); -+/* For IMAP clients: Read the command tag, which could also be "+" or "*". -+ Returns 1 if tag was returned, 0 if more data is needed, -1 if input isn't -+ valid. */ -+int imap_parser_client_read_tag(struct imap_parser *parser, -+ const char **tag_r); - - #endif diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part7.patch b/SOURCES/dovecot-2.3.13-CVE_2020_25275-part7.patch deleted file mode 100644 index 87b52ea..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part7.patch +++ /dev/null @@ -1,126 +0,0 @@ -From fb97a1cddbda4019e327fa736972a1c7433fedaa Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Fri, 11 Sep 2020 09:53:03 +0300 -Subject: [PATCH] lib-mail: message-parser - Fix assert-crash when enforcing - MIME part limit - -The limit could have been exceeded with message/rfc822 parts. ---- - src/lib-mail/message-parser.c | 3 +- - src/lib-mail/test-message-parser.c | 82 ++++++++++++++++++++++++++++++ - 2 files changed, 84 insertions(+), 1 deletion(-) - -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index 6ab4c3266f..40a504da0a 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -703,7 +703,8 @@ static int parse_next_header(struct message_parser_ctx *ctx, - ctx->multipart = FALSE; - ctx->parse_next_block = parse_next_body_to_boundary; - } else if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0 && -- !parse_too_many_nested_mime_parts(ctx)) { -+ !parse_too_many_nested_mime_parts(ctx) && -+ ctx->total_parts_count < ctx->max_total_mime_parts) { - ctx->parse_next_block = parse_next_body_message_rfc822_init; - } else { - part->flags &= ~MESSAGE_PART_FLAG_MESSAGE_RFC822; -diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c -index 8c5a3404f1..c4e117afc7 100644 ---- a/src/lib-mail/test-message-parser.c -+++ b/src/lib-mail/test-message-parser.c -@@ -1127,6 +1127,87 @@ static const char input_msg[] = - test_end(); - } - -+static void test_message_parser_mime_part_limit_rfc822(void) -+{ -+static const char input_msg[] = -+"Content-Type: multipart/mixed; boundary=\"1\"\n" -+"\n" -+"--1\n" -+"Content-Type: multipart/mixed; boundary=\"2\"\n" -+"\n" -+"--2\n" -+"Content-Type: message/rfc822\n" -+"\n" -+"Content-Type: text/plain\n" -+"\n" -+"1\n" -+"--2\n" -+"Content-Type: message/rfc822\n" -+"\n" -+"Content-Type: text/plain\n" -+"\n" -+"22\n" -+"--1\n" -+"Content-Type: message/rfc822\n" -+"\n" -+"Content-Type: text/plain\n" -+"\n" -+"333\n"; -+ const struct message_parser_settings parser_set = { -+ .max_total_mime_parts = 3, -+ }; -+ struct message_parser_ctx *parser; -+ struct istream *input; -+ struct message_part *parts, *part; -+ struct message_block block; -+ pool_t pool; -+ int ret; -+ -+ test_begin("message parser mime part limit rfc822"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(input_msg); -+ -+ parser = message_parser_init(pool, input, &parser_set); -+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; -+ test_assert(ret < 0); -+ message_parser_deinit(&parser, &parts); -+ -+ part = parts; -+ test_assert(part->children_count == 2); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 45); -+ test_assert(part->header_size.virtual_size == 45+2); -+ test_assert(part->body_size.lines == 21); -+ test_assert(part->body_size.physical_size == 238); -+ test_assert(part->body_size.virtual_size == 238+21); -+ -+ part = parts->children; -+ test_assert(part->children_count == 1); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 45); -+ test_assert(part->header_size.virtual_size == 45+2); -+ test_assert(part->body_size.lines == 18); -+ test_assert(part->body_size.physical_size == 189); -+ test_assert(part->body_size.virtual_size == 189+18); -+ -+ part = parts->children->children; -+ test_assert(part->children_count == 0); -+ test_assert(part->flags == MESSAGE_PART_FLAG_IS_MIME); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 30); -+ test_assert(part->header_size.virtual_size == 30+2); -+ test_assert(part->body_size.lines == 15); -+ test_assert(part->body_size.physical_size == 155); -+ test_assert(part->body_size.virtual_size == 155+15); -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ - int main(void) - { - static void (*const test_functions[])(void) = { -@@ -1301,6 +1382,7 @@ int main(void) - test_message_parser_mime_part_nested_limit, - test_message_parser_mime_part_nested_limit_rfc822, - test_message_parser_mime_part_limit, -+ test_message_parser_mime_part_limit_rfc822, - NULL - }; - return test_run(test_functions); diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part8.patch b/SOURCES/dovecot-2.3.13-CVE_2020_25275-part8.patch deleted file mode 100644 index 1953372..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_25275-part8.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 266e54b7b8c34c9a58dd60a2e53c5ca7d1deae19 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Fri, 11 Sep 2020 10:57:51 +0300 -Subject: [PATCH] lib-imap: Don't generate invalid BODYSTRUCTURE when reaching - MIME part limit - -If the last MIME part was message/rfc822 and its child was truncated away, -BODYSTRUCTURE was missing the ENVELOPE and BODY[STRUCTURE] parts. Fixed by -writing empty dummy ones. ---- - src/lib-imap/imap-bodystructure.c | 29 +++++++++++++++++++++++++++-- - 1 file changed, 27 insertions(+), 2 deletions(-) - -diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c -index 4e379e56a9..e3da1090b4 100644 ---- a/src/lib-imap/imap-bodystructure.c -+++ b/src/lib-imap/imap-bodystructure.c -@@ -146,11 +146,25 @@ static void part_write_body(const struct message_part *part, - string_t *str, bool extended) - { - const struct message_part_data *data = part->data; -- bool text; -+ bool text, message_rfc822; - - i_assert(part->data != NULL); - -- if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0) { -+ if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0) -+ message_rfc822 = TRUE; -+ else if (data->content_type != NULL && -+ strcasecmp(data->content_type, "message") == 0 && -+ strcasecmp(data->content_subtype, "rfc822") == 0) { -+ /* It's message/rfc822, but without -+ MESSAGE_PART_FLAG_MESSAGE_RFC822. That likely means maximum -+ MIME part count was reached while parsing the mail. Write -+ the missing child mail's ENVELOPE and BODY as empty dummy -+ values. */ -+ message_rfc822 = TRUE; -+ } else -+ message_rfc822 = FALSE; -+ -+ if (message_rfc822) { - str_append(str, "\"message\" \"rfc822\""); - text = FALSE; - } else { -@@ -200,6 +214,17 @@ static void part_write_body(const struct message_part *part, - - part_write_bodystructure_siblings(part->children, str, extended); - str_printfa(str, " %u", part->body_size.lines); -+ } else if (message_rfc822) { -+ /* truncated MIME part - write out dummy values */ -+ i_assert(part->children == NULL); -+ -+ str_append(str, " (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) "); -+ -+ if (!extended) -+ str_append(str, EMPTY_BODY); -+ else -+ str_append(str, EMPTY_BODYSTRUCTURE); -+ str_printfa(str, " %u", part->body_size.lines); - } - - if (!extended) diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_25275regr-part1.patch b/SOURCES/dovecot-2.3.13-CVE_2020_25275regr-part1.patch deleted file mode 100644 index 8781d5f..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_25275regr-part1.patch +++ /dev/null @@ -1,228 +0,0 @@ -From 530c1e950a1bb46ff4e4a7c8e4b7cd945ff28916 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 18 Nov 2020 18:55:34 +0200 -Subject: [PATCH] lib-imap: Fix writing BODYSTRUCTURE for truncated - message/rfc822 part - -If the max nesting limit is reached, write the last part out as -application/octet-stream instead of dummy message/rfc822. - -Fixes error while parsing BODYSTRUCTURE: -message_part message/rfc822 flag doesn't match BODYSTRUCTURE ---- - src/lib-imap/imap-bodystructure.c | 54 +++++++++---------- - src/lib-imap/test-imap-bodystructure.c | 73 ++++++++++++++++++++++++-- - 2 files changed, 96 insertions(+), 31 deletions(-) - -diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c -index e3da1090b4..ab422c00d2 100644 ---- a/src/lib-imap/imap-bodystructure.c -+++ b/src/lib-imap/imap-bodystructure.c -@@ -142,31 +142,42 @@ static void part_write_body_multipart(const struct message_part *part, - part_write_bodystructure_common(data, str); - } - -+static bool part_is_truncated(const struct message_part *part) -+{ -+ const struct message_part_data *data = part->data; -+ -+ i_assert((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) == 0); -+ -+ if (data->content_type != NULL) { -+ if (strcasecmp(data->content_type, "message") == 0 && -+ strcasecmp(data->content_subtype, "rfc822") == 0) { -+ /* It's message/rfc822, but without -+ MESSAGE_PART_FLAG_MESSAGE_RFC822. */ -+ return TRUE; -+ } -+ } -+ return FALSE; -+} -+ - static void part_write_body(const struct message_part *part, - string_t *str, bool extended) - { - const struct message_part_data *data = part->data; -- bool text, message_rfc822; -+ bool text; - - i_assert(part->data != NULL); - -- if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0) -- message_rfc822 = TRUE; -- else if (data->content_type != NULL && -- strcasecmp(data->content_type, "message") == 0 && -- strcasecmp(data->content_subtype, "rfc822") == 0) { -- /* It's message/rfc822, but without -- MESSAGE_PART_FLAG_MESSAGE_RFC822. That likely means maximum -- MIME part count was reached while parsing the mail. Write -- the missing child mail's ENVELOPE and BODY as empty dummy -- values. */ -- message_rfc822 = TRUE; -- } else -- message_rfc822 = FALSE; -- -- if (message_rfc822) { -+ if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0) { - str_append(str, "\"message\" \"rfc822\""); - text = FALSE; -+ } else if (part_is_truncated(part)) { -+ /* Maximum MIME part count was reached while parsing the mail. -+ Write this part out as application/octet-stream instead. -+ We're not using text/plain, because it would require -+ message-parser to use MESSAGE_PART_FLAG_TEXT for this part -+ to avoid losing line count in message_part serialization. */ -+ str_append(str, "\"application\" \"octet-stream\""); -+ text = FALSE; - } else { - /* "content type" "subtype" */ - if (data->content_type == NULL) { -@@ -214,17 +225,6 @@ static void part_write_body(const struct message_part *part, - - part_write_bodystructure_siblings(part->children, str, extended); - str_printfa(str, " %u", part->body_size.lines); -- } else if (message_rfc822) { -- /* truncated MIME part - write out dummy values */ -- i_assert(part->children == NULL); -- -- str_append(str, " (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) "); -- -- if (!extended) -- str_append(str, EMPTY_BODY); -- else -- str_append(str, EMPTY_BODYSTRUCTURE); -- str_printfa(str, " %u", part->body_size.lines); - } - - if (!extended) -diff --git a/src/lib-imap/test-imap-bodystructure.c b/src/lib-imap/test-imap-bodystructure.c -index dfc9957488..6cb699e126 100644 ---- a/src/lib-imap/test-imap-bodystructure.c -+++ b/src/lib-imap/test-imap-bodystructure.c -@@ -4,6 +4,7 @@ - #include "istream.h" - #include "str.h" - #include "message-part-data.h" -+#include "message-part-serialize.h" - #include "message-parser.h" - #include "imap-bodystructure.h" - #include "test-common.h" -@@ -379,12 +380,14 @@ struct normalize_test normalize_tests[] = { - static const unsigned int normalize_tests_count = N_ELEMENTS(normalize_tests); - - static struct message_part * --msg_parse(pool_t pool, const char *message, bool parse_bodystructure) -+msg_parse(pool_t pool, const char *message, unsigned int max_nested_mime_parts, -+ bool parse_bodystructure) - { - const struct message_parser_settings parser_set = { - .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | - MESSAGE_HEADER_PARSER_FLAG_DROP_CR, - .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, -+ .max_nested_mime_parts = max_nested_mime_parts, - }; - struct message_parser_ctx *parser; - struct istream *input; -@@ -418,7 +421,7 @@ static void test_imap_bodystructure_write(void) - pool_t pool = pool_alloconly_create("imap bodystructure write", 1024); - - test_begin(t_strdup_printf("imap bodystructure write [%u]", i)); -- parts = msg_parse(pool, test->message, TRUE); -+ parts = msg_parse(pool, test->message, 0, TRUE); - - imap_bodystructure_write(parts, str, TRUE); - test_assert(strcmp(str_c(str), test->bodystructure) == 0); -@@ -445,7 +448,7 @@ static void test_imap_bodystructure_parse(void) - pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024); - - test_begin(t_strdup_printf("imap bodystructure parser [%u]", i)); -- parts = msg_parse(pool, test->message, FALSE); -+ parts = msg_parse(pool, test->message, 0, FALSE); - - test_assert(imap_body_parse_from_bodystructure(test->bodystructure, - str, &error) == 0); -@@ -512,7 +515,7 @@ static void test_imap_bodystructure_normalize(void) - pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024); - - test_begin(t_strdup_printf("imap bodystructure normalize [%u]", i)); -- parts = msg_parse(pool, test->message, FALSE); -+ parts = msg_parse(pool, test->message, 0, FALSE); - - ret = imap_bodystructure_parse(test->input, - pool, parts, &error); -@@ -531,6 +534,67 @@ static void test_imap_bodystructure_normalize(void) - } T_END; - } - -+static const struct { -+ const char *input; -+ const char *bodystructure; -+ unsigned int max_depth; -+} truncation_tests[] = { -+ { -+ .input = "Content-Type: message/rfc822\n" -+ "\n" -+ "Content-Type: message/rfc822\n" -+ "Header2: value2\n" -+ "\n" -+ "Subject: hello world\n" -+ "Header2: value2\n" -+ "Header3: value3\n" -+ "\n" -+ "body line 1\n" -+ "body line 2\n" -+ "body line 4\n" -+ "body line 3\n", -+ .bodystructure = "\"message\" \"rfc822\" NIL NIL NIL \"7bit\" 159 (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) (\"application\" \"octet-stream\" NIL NIL NIL \"7bit\" 110 NIL NIL NIL NIL) 11 NIL NIL NIL NIL", -+ .max_depth = 2, -+ }, -+}; -+ -+static void test_imap_bodystructure_truncation(void) -+{ -+ struct message_part *parts; -+ const char *error; -+ string_t *str_body = t_str_new(128); -+ string_t *str_parts = t_str_new(128); -+ pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024); -+ -+ test_begin("imap bodystructure truncation"); -+ -+ for (unsigned int i = 0; i < N_ELEMENTS(truncation_tests); i++) { -+ p_clear(pool); -+ str_truncate(str_body, 0); -+ str_truncate(str_parts, 0); -+ -+ parts = msg_parse(pool, truncation_tests[i].input, -+ truncation_tests[i].max_depth, -+ TRUE); -+ -+ /* write out BODYSTRUCTURE and serialize message_parts */ -+ imap_bodystructure_write(parts, str_body, TRUE); -+ message_part_serialize(parts, str_parts); -+ -+ /* now deserialize message_parts and make sure they can be used -+ to parse BODYSTRUCTURE */ -+ parts = message_part_deserialize(pool, str_data(str_parts), -+ str_len(str_parts), &error); -+ test_assert(parts != NULL); -+ test_assert(imap_bodystructure_parse(str_c(str_body), pool, -+ parts, &error) == 0); -+ test_assert_strcmp(str_c(str_body), -+ truncation_tests[i].bodystructure); -+ } -+ pool_unref(&pool); -+ test_end(); -+} -+ - int main(void) - { - static void (*const test_functions[])(void) = { -@@ -538,6 +602,7 @@ int main(void) - test_imap_bodystructure_parse, - test_imap_bodystructure_normalize, - test_imap_bodystructure_parse_full, -+ test_imap_bodystructure_truncation, - NULL - }; - return test_run(test_functions); diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_25275regr-part2.patch b/SOURCES/dovecot-2.3.13-CVE_2020_25275regr-part2.patch deleted file mode 100644 index db36512..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_25275regr-part2.patch +++ /dev/null @@ -1,64 +0,0 @@ -From ec2c5ffde7a1ca63219d47831725599e7de76f7f Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 18 Nov 2020 20:48:11 +0200 -Subject: [PATCH] lib-imap: Fix writing BODYSTRUCTURE for truncated multipart/ - part - -If the max nesting limit is reached, write the last part out as -application/octet-stream. The original content-type could be confusing -IMAP clients when they don't see any child parts. ---- - src/lib-imap/imap-bodystructure.c | 6 ++++++ - src/lib-imap/test-imap-bodystructure.c | 15 +++++++++++++++ - 2 files changed, 21 insertions(+) - -diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c -index ab422c00d2..bfb6e64197 100644 ---- a/src/lib-imap/imap-bodystructure.c -+++ b/src/lib-imap/imap-bodystructure.c -@@ -147,6 +147,7 @@ static bool part_is_truncated(const struct message_part *part) - const struct message_part_data *data = part->data; - - i_assert((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) == 0); -+ i_assert((part->flags & MESSAGE_PART_FLAG_MULTIPART) == 0); - - if (data->content_type != NULL) { - if (strcasecmp(data->content_type, "message") == 0 && -@@ -155,6 +156,11 @@ static bool part_is_truncated(const struct message_part *part) - MESSAGE_PART_FLAG_MESSAGE_RFC822. */ - return TRUE; - } -+ if (strcasecmp(data->content_type, "multipart") == 0) { -+ /* It's multipart/, but without -+ MESSAGE_PART_FLAG_MULTIPART. */ -+ return TRUE; -+ } - } - return FALSE; - } -diff --git a/src/lib-imap/test-imap-bodystructure.c b/src/lib-imap/test-imap-bodystructure.c -index 6cb699e126..2118907e78 100644 ---- a/src/lib-imap/test-imap-bodystructure.c -+++ b/src/lib-imap/test-imap-bodystructure.c -@@ -556,6 +556,21 @@ static const struct { - .bodystructure = "\"message\" \"rfc822\" NIL NIL NIL \"7bit\" 159 (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) (\"application\" \"octet-stream\" NIL NIL NIL \"7bit\" 110 NIL NIL NIL NIL) 11 NIL NIL NIL NIL", - .max_depth = 2, - }, -+ { -+ .input = "Content-Type: multipart/mixed; boundary=1\n" -+ "\n" -+ "--1\n" -+ "Content-Type: multipart/mixed; boundary=2\n" -+ "\n" -+ "--2\n" -+ "Content-Type: multipart/mixed; boundary=3\n" -+ "\n" -+ "--3\n" -+ "\n" -+ "body\n", -+ .bodystructure = "(\"application\" \"octet-stream\" (\"boundary\" \"2\") NIL NIL \"7bit\" 63 NIL NIL NIL NIL) \"mixed\" (\"boundary\" \"1\") NIL NIL NIL", -+ .max_depth = 2, -+ }, - }; - - static void test_imap_bodystructure_truncation(void) diff --git a/SOURCES/dovecot-2.3.13-CVE_2020_25275regr-part3.patch b/SOURCES/dovecot-2.3.13-CVE_2020_25275regr-part3.patch deleted file mode 100644 index b8eeb62..0000000 --- a/SOURCES/dovecot-2.3.13-CVE_2020_25275regr-part3.patch +++ /dev/null @@ -1,127 +0,0 @@ -From a912198bdc38421ad84044089db84fc14c69c228 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 18 Nov 2020 21:22:45 +0200 -Subject: [PATCH] lib-imap: Fix writing BODYSTRUCTURE for truncated - multipart/digest part - -Fixes error while parsing BODYSTRUCTURE: -message_part message/rfc822 flag doesn't match lines in BODYSTRUCTURE ---- - src/lib-imap/imap-bodystructure.c | 9 +++++++++ - src/lib-imap/test-imap-bodystructure.c | 28 ++++++++++++++++++++++---- - 2 files changed, 33 insertions(+), 4 deletions(-) - -diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c -index bfb6e64197..5d2e5a3a84 100644 ---- a/src/lib-imap/imap-bodystructure.c -+++ b/src/lib-imap/imap-bodystructure.c -@@ -161,6 +161,14 @@ static bool part_is_truncated(const struct message_part *part) - MESSAGE_PART_FLAG_MULTIPART. */ - return TRUE; - } -+ } else { -+ /* No Content-Type */ -+ if (part->parent != NULL && -+ (part->parent->flags & MESSAGE_PART_FLAG_MULTIPART_DIGEST) != 0) { -+ /* Parent is MESSAGE_PART_FLAG_MULTIPART_DIGEST -+ (so this should have been message/rfc822). */ -+ return TRUE; -+ } - } - return FALSE; - } -@@ -195,6 +203,7 @@ static void part_write_body(const struct message_part *part, - str_append_c(str, ' '); - imap_append_string(str, data->content_subtype); - } -+ i_assert(text == ((part->flags & MESSAGE_PART_FLAG_TEXT) != 0)); - } - - /* ("content type param key" "value" ...) */ -diff --git a/src/lib-imap/test-imap-bodystructure.c b/src/lib-imap/test-imap-bodystructure.c -index 2118907e78..0f70cb0035 100644 ---- a/src/lib-imap/test-imap-bodystructure.c -+++ b/src/lib-imap/test-imap-bodystructure.c -@@ -381,13 +381,14 @@ static const unsigned int normalize_tests_count = N_ELEMENTS(normalize_tests); - - static struct message_part * - msg_parse(pool_t pool, const char *message, unsigned int max_nested_mime_parts, -- bool parse_bodystructure) -+ unsigned int max_total_mime_parts, bool parse_bodystructure) - { - const struct message_parser_settings parser_set = { - .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | - MESSAGE_HEADER_PARSER_FLAG_DROP_CR, - .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, - .max_nested_mime_parts = max_nested_mime_parts, -+ .max_total_mime_parts = max_total_mime_parts, - }; - struct message_parser_ctx *parser; - struct istream *input; -@@ -421,7 +422,7 @@ static void test_imap_bodystructure_write(void) - pool_t pool = pool_alloconly_create("imap bodystructure write", 1024); - - test_begin(t_strdup_printf("imap bodystructure write [%u]", i)); -- parts = msg_parse(pool, test->message, 0, TRUE); -+ parts = msg_parse(pool, test->message, 0, 0, TRUE); - - imap_bodystructure_write(parts, str, TRUE); - test_assert(strcmp(str_c(str), test->bodystructure) == 0); -@@ -448,7 +449,7 @@ static void test_imap_bodystructure_parse(void) - pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024); - - test_begin(t_strdup_printf("imap bodystructure parser [%u]", i)); -- parts = msg_parse(pool, test->message, 0, FALSE); -+ parts = msg_parse(pool, test->message, 0, 0, FALSE); - - test_assert(imap_body_parse_from_bodystructure(test->bodystructure, - str, &error) == 0); -@@ -515,7 +516,7 @@ static void test_imap_bodystructure_normalize(void) - pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024); - - test_begin(t_strdup_printf("imap bodystructure normalize [%u]", i)); -- parts = msg_parse(pool, test->message, 0, FALSE); -+ parts = msg_parse(pool, test->message, 0, 0, FALSE); - - ret = imap_bodystructure_parse(test->input, - pool, parts, &error); -@@ -538,6 +539,7 @@ static const struct { - const char *input; - const char *bodystructure; - unsigned int max_depth; -+ unsigned int max_total; - } truncation_tests[] = { - { - .input = "Content-Type: message/rfc822\n" -@@ -571,6 +573,23 @@ static const struct { - .bodystructure = "(\"application\" \"octet-stream\" (\"boundary\" \"2\") NIL NIL \"7bit\" 63 NIL NIL NIL NIL) \"mixed\" (\"boundary\" \"1\") NIL NIL NIL", - .max_depth = 2, - }, -+ { -+ .input = "Content-Type: multipart/digest; boundary=1\n" -+ "\n" -+ "--1\n" -+ "\n" -+ "Subject: hdr1\n" -+ "\n" -+ "body1\n" -+ "--1\n" -+ "\n" -+ "Subject: hdr2\n" -+ "\n" -+ "body2\n", -+ .bodystructure = "(\"application\" \"octet-stream\" NIL NIL NIL \"7bit\" 55 NIL NIL NIL NIL) \"digest\" (\"boundary\" \"1\") NIL NIL NIL", -+ .max_total = 2, -+ }, -+ - }; - - static void test_imap_bodystructure_truncation(void) -@@ -590,6 +609,7 @@ static void test_imap_bodystructure_truncation(void) - - parts = msg_parse(pool, truncation_tests[i].input, - truncation_tests[i].max_depth, -+ truncation_tests[i].max_total, - TRUE); - - /* write out BODYSTRUCTURE and serialize message_parts */ diff --git a/SOURCES/dovecot-2.3.16-ftbfsbigend.patch b/SOURCES/dovecot-2.3.16-ftbfsbigend.patch new file mode 100644 index 0000000..762503b --- /dev/null +++ b/SOURCES/dovecot-2.3.16-ftbfsbigend.patch @@ -0,0 +1,53 @@ +commit ec4595097067a736717ef202fe8542b1b4bc2dd5 +Author: Timo Sirainen +Date: Tue Aug 10 12:22:08 2021 +0300 + + lib-index: Fix storing cache fields' last_used with 64bit big endian CPUs + +diff --git a/src/lib-index/mail-cache-fields.c b/src/lib-index/mail-cache-fields.c +index e929fb559d..429e0d234c 100644 +--- a/src/lib-index/mail-cache-fields.c ++++ b/src/lib-index/mail-cache-fields.c +@@ -524,6 +524,19 @@ static void copy_to_buf_byte(struct mail_cache *cache, buffer_t *dest, + } + } + ++static void ++copy_to_buf_last_used(struct mail_cache *cache, buffer_t *dest, bool add_new) ++{ ++ size_t offset = offsetof(struct mail_cache_field, last_used); ++#if defined(WORDS_BIGENDIAN) && SIZEOF_VOID_P == 8 ++ /* 64bit time_t with big endian CPUs: copy the last 32 bits instead of ++ the first 32 bits (that are always 0). The 32 bits are enough until ++ year 2106, so we're not in a hurry to use 64 bits on disk. */ ++ offset += sizeof(uint32_t); ++#endif ++ copy_to_buf(cache, dest, add_new, offset, sizeof(uint32_t)); ++} ++ + static int mail_cache_header_fields_update_locked(struct mail_cache *cache) + { + buffer_t *buffer; +@@ -536,9 +549,7 @@ static int mail_cache_header_fields_update_locked(struct mail_cache *cache) + + buffer = t_buffer_create(256); + +- copy_to_buf(cache, buffer, FALSE, +- offsetof(struct mail_cache_field, last_used), +- sizeof(uint32_t)); ++ copy_to_buf_last_used(cache, buffer, FALSE); + ret = mail_cache_write(cache, buffer->data, buffer->used, + offset + MAIL_CACHE_FIELD_LAST_USED()); + if (ret == 0) { +@@ -599,9 +610,7 @@ void mail_cache_header_fields_get(struct mail_cache *cache, buffer_t *dest) + buffer_append(dest, &hdr, sizeof(hdr)); + + /* we have to keep the field order for the existing fields. */ +- copy_to_buf(cache, dest, TRUE, +- offsetof(struct mail_cache_field, last_used), +- sizeof(uint32_t)); ++ copy_to_buf_last_used(cache, dest, TRUE); + copy_to_buf(cache, dest, TRUE, + offsetof(struct mail_cache_field, field_size), + sizeof(uint32_t)); + diff --git a/SOURCES/dovecot-2.3.16-keeplzma.patch b/SOURCES/dovecot-2.3.16-keeplzma.patch new file mode 100644 index 0000000..b43c7b8 --- /dev/null +++ b/SOURCES/dovecot-2.3.16-keeplzma.patch @@ -0,0 +1,353 @@ +diff -up dovecot-2.3.16/configure.ac.keeplzma dovecot-2.3.16/configure.ac +--- dovecot-2.3.16/configure.ac.keeplzma 2021-08-06 11:25:51.000000000 +0200 ++++ dovecot-2.3.16/configure.ac 2022-02-28 13:58:02.337149927 +0100 +@@ -173,7 +173,7 @@ AS_HELP_STRING([--with-bzlib], [Build wi + want_bzlib=auto) + + AC_ARG_WITH(lzma, +-AS_HELP_STRING([--with-lzma], [Build with LZMA decompression support (auto)]), ++AS_HELP_STRING([--with-lzma], [Build with LZMA compression support (auto)]), + TEST_WITH(lzma, $withval), + want_lzma=auto) + +diff -up dovecot-2.3.16/run-test-valgrind.supp.keeplzma dovecot-2.3.16/run-test-valgrind.supp +--- dovecot-2.3.16/run-test-valgrind.supp.keeplzma 2021-08-06 11:25:51.000000000 +0200 ++++ dovecot-2.3.16/run-test-valgrind.supp 2022-02-28 13:58:02.337149927 +0100 +@@ -5,6 +5,17 @@ + obj:*/bash + } + { ++ ++ Memcheck:Cond ++ obj:/lib/x86_64-linux-gnu/liblzma.so.5.* ++ obj:/lib/x86_64-linux-gnu/liblzma.so.5.* ++ obj:/lib/x86_64-linux-gnu/liblzma.so.5.* ++ obj:/lib/x86_64-linux-gnu/liblzma.so.5.* ++ obj:/lib/x86_64-linux-gnu/liblzma.so.5.* ++ fun:lzma_stream_encoder ++ fun:lzma_easy_encoder ++} ++{ + + Memcheck:Leak + fun:malloc +diff -up dovecot-2.3.16/src/lib-compression/compression.c.keeplzma dovecot-2.3.16/src/lib-compression/compression.c +--- dovecot-2.3.16/src/lib-compression/compression.c.keeplzma 2021-08-06 11:25:51.000000000 +0200 ++++ dovecot-2.3.16/src/lib-compression/compression.c 2022-02-28 14:22:32.467944396 +0100 +@@ -25,6 +25,7 @@ + #endif + #ifndef HAVE_LZMA + # define i_stream_create_lzma NULL ++# define o_stream_create_lzma NULL + #endif + #ifndef HAVE_LZ4 + # define i_stream_create_lz4 NULL +@@ -216,7 +217,7 @@ const struct compression_handler compres + .ext = ".xz", + .is_compressed = is_compressed_xz, + .create_istream = i_stream_create_lzma, +- .create_ostream = NULL, ++ .create_ostream = o_stream_create_lzma, + .get_min_level = compression_get_min_level_unsupported, + .get_default_level = compression_get_default_level_unsupported, + .get_max_level = compression_get_max_level_unsupported, +diff -up dovecot-2.3.16/src/lib-compression/Makefile.am.keeplzma dovecot-2.3.16/src/lib-compression/Makefile.am +--- dovecot-2.3.16/src/lib-compression/Makefile.am.keeplzma 2021-08-06 11:25:51.000000000 +0200 ++++ dovecot-2.3.16/src/lib-compression/Makefile.am 2022-02-28 13:58:02.337149927 +0100 +@@ -13,6 +13,7 @@ libcompression_la_SOURCES = \ + istream-zlib.c \ + istream-bzlib.c \ + istream-zstd.c \ ++ ostream-lzma.c \ + ostream-lz4.c \ + ostream-zlib.c \ + ostream-bzlib.c \ +diff -up dovecot-2.3.16/src/lib-compression/ostream-lzma.c.keeplzma dovecot-2.3.16/src/lib-compression/ostream-lzma.c +--- dovecot-2.3.16/src/lib-compression/ostream-lzma.c.keeplzma 2022-02-28 13:58:02.338149934 +0100 ++++ dovecot-2.3.16/src/lib-compression/ostream-lzma.c 2022-02-28 13:58:02.338149934 +0100 +@@ -0,0 +1,263 @@ ++/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */ ++ ++#include "lib.h" ++ ++#ifdef HAVE_LZMA ++ ++#include "ostream-private.h" ++#include "ostream-zlib.h" ++#include ++ ++#define CHUNK_SIZE (1024*64) ++ ++struct lzma_ostream { ++ struct ostream_private ostream; ++ lzma_stream strm; ++ ++ unsigned char outbuf[CHUNK_SIZE]; ++ unsigned int outbuf_offset, outbuf_used; ++ ++ bool flushed:1; ++}; ++ ++static void o_stream_lzma_close(struct iostream_private *stream, ++ bool close_parent) ++{ ++ struct lzma_ostream *zstream = (struct lzma_ostream *)stream; ++ i_assert(zstream->ostream.finished || ++ zstream->ostream.ostream.stream_errno != 0 || ++ zstream->ostream.error_handling_disabled); ++ lzma_end(&zstream->strm); ++ if (close_parent) ++ o_stream_close(zstream->ostream.parent); ++} ++ ++static int o_stream_zlib_send_outbuf(struct lzma_ostream *zstream) ++{ ++ ssize_t ret; ++ size_t size; ++ ++ if (zstream->outbuf_used == 0) ++ return 1; ++ ++ size = zstream->outbuf_used - zstream->outbuf_offset; ++ i_assert(size > 0); ++ ret = o_stream_send(zstream->ostream.parent, ++ zstream->outbuf + zstream->outbuf_offset, size); ++ if (ret < 0) { ++ o_stream_copy_error_from_parent(&zstream->ostream); ++ return -1; ++ } ++ if ((size_t)ret != size) { ++ zstream->outbuf_offset += ret; ++ return 0; ++ } ++ zstream->outbuf_offset = 0; ++ zstream->outbuf_used = 0; ++ return 1; ++} ++ ++static ssize_t ++o_stream_lzma_send_chunk(struct lzma_ostream *zstream, ++ const void *data, size_t size) ++{ ++ lzma_stream *zs = &zstream->strm; ++ int ret; ++ ++ i_assert(zstream->outbuf_used == 0); ++ ++ zs->next_in = (void *)data; ++ zs->avail_in = size; ++ while (zs->avail_in > 0) { ++ if (zs->avail_out == 0) { ++ /* previous block was compressed. send it and start ++ compression for a new block. */ ++ zs->next_out = zstream->outbuf; ++ zs->avail_out = sizeof(zstream->outbuf); ++ ++ zstream->outbuf_used = sizeof(zstream->outbuf); ++ if ((ret = o_stream_zlib_send_outbuf(zstream)) < 0) ++ return -1; ++ if (ret == 0) { ++ /* parent stream's buffer full */ ++ break; ++ } ++ } ++ ++ ret = lzma_code(zs, LZMA_RUN); ++ switch (ret) { ++ case LZMA_OK: ++ break; ++ case LZMA_MEM_ERROR: ++ i_fatal_status(FATAL_OUTOFMEM, ++ "lzma.write(%s): Out of memory", ++ o_stream_get_name(&zstream->ostream.ostream)); ++ default: ++ i_panic("lzma.write(%s) failed with unexpected code %d", ++ o_stream_get_name(&zstream->ostream.ostream), ret); ++ } ++ } ++ size -= zs->avail_in; ++ ++ return size; ++} ++ ++static int o_stream_lzma_send_flush(struct lzma_ostream *zstream, bool final) ++{ ++ lzma_stream *zs = &zstream->strm; ++ size_t len; ++ bool done = FALSE; ++ int ret; ++ ++ i_assert(zs->avail_in == 0); ++ ++ if (zstream->flushed) { ++ i_assert(zstream->outbuf_used == 0); ++ return 1; ++ } ++ ++ if ((ret = o_stream_flush_parent_if_needed(&zstream->ostream)) <= 0) ++ return ret; ++ if ((ret = o_stream_zlib_send_outbuf(zstream)) <= 0) ++ return ret; ++ ++ if (!final) ++ return 1; ++ ++ i_assert(zstream->outbuf_used == 0); ++ do { ++ len = sizeof(zstream->outbuf) - zs->avail_out; ++ if (len != 0) { ++ zs->next_out = zstream->outbuf; ++ zs->avail_out = sizeof(zstream->outbuf); ++ ++ zstream->outbuf_used = len; ++ if ((ret = o_stream_zlib_send_outbuf(zstream)) <= 0) ++ return ret; ++ if (done) ++ break; ++ } ++ ret = lzma_code(zs, LZMA_FINISH); ++ switch (ret) { ++ case LZMA_OK: ++ /* still unfinished - need to call lzma_code() again */ ++ break; ++ case LZMA_STREAM_END: ++ /* output is fully finished */ ++ done = TRUE; ++ break; ++ case LZMA_MEM_ERROR: ++ i_fatal_status(FATAL_OUTOFMEM, ++ "lzma.write(%s): Out of memory", ++ o_stream_get_name(&zstream->ostream.ostream)); ++ default: ++ i_panic("lzma.write(%s) flush failed with unexpected code %d", ++ o_stream_get_name(&zstream->ostream.ostream), ret); ++ } ++ } while (zs->avail_out != sizeof(zstream->outbuf)); ++ ++ if (final) ++ zstream->flushed = TRUE; ++ i_assert(zstream->outbuf_used == 0); ++ return 1; ++} ++ ++static int o_stream_lzma_flush(struct ostream_private *stream) ++{ ++ struct lzma_ostream *zstream = (struct lzma_ostream *)stream; ++ int ret; ++ ++ if ((ret = o_stream_lzma_send_flush(zstream, stream->finished)) < 0) ++ return -1; ++ else if (ret > 0) ++ return o_stream_flush_parent(stream); ++ return ret; ++} ++ ++static size_t ++o_stream_lzma_get_buffer_used_size(const struct ostream_private *stream) ++{ ++ const struct lzma_ostream *zstream = ++ (const struct lzma_ostream *)stream; ++ ++ /* outbuf has already compressed data that we're trying to send to the ++ parent stream. We're not including lzma's internal compression ++ buffer size. */ ++ return (zstream->outbuf_used - zstream->outbuf_offset) + ++ o_stream_get_buffer_used_size(stream->parent); ++} ++ ++static size_t ++o_stream_lzma_get_buffer_avail_size(const struct ostream_private *stream) ++{ ++ /* FIXME: not correct - this is counting compressed size, which may be ++ too larger than uncompressed size in some situations. Fixing would ++ require some kind of additional buffering. */ ++ return o_stream_get_buffer_avail_size(stream->parent); ++} ++ ++static ssize_t ++o_stream_lzma_sendv(struct ostream_private *stream, ++ const struct const_iovec *iov, unsigned int iov_count) ++{ ++ struct lzma_ostream *zstream = (struct lzma_ostream *)stream; ++ ssize_t ret, bytes = 0; ++ unsigned int i; ++ ++ if ((ret = o_stream_zlib_send_outbuf(zstream)) <= 0) { ++ /* error / we still couldn't flush existing data to ++ parent stream. */ ++ return ret; ++ } ++ ++ for (i = 0; i < iov_count; i++) { ++ ret = o_stream_lzma_send_chunk(zstream, iov[i].iov_base, ++ iov[i].iov_len); ++ if (ret < 0) ++ return -1; ++ bytes += ret; ++ if ((size_t)ret != iov[i].iov_len) ++ break; ++ } ++ stream->ostream.offset += bytes; ++ ++ /* avail_in!=0 check is used to detect errors. if it's non-zero here ++ it simply means we didn't send all the data */ ++ zstream->strm.avail_in = 0; ++ return bytes; ++} ++ ++struct ostream *o_stream_create_lzma(struct ostream *output, int level) ++{ ++ struct lzma_ostream *zstream; ++ lzma_ret ret; ++ ++ i_assert(level >= 1 && level <= 9); ++ ++ zstream = i_new(struct lzma_ostream, 1); ++ zstream->ostream.sendv = o_stream_lzma_sendv; ++ zstream->ostream.flush = o_stream_lzma_flush; ++ zstream->ostream.get_buffer_used_size = ++ o_stream_lzma_get_buffer_used_size; ++ zstream->ostream.get_buffer_avail_size = ++ o_stream_lzma_get_buffer_avail_size; ++ zstream->ostream.iostream.close = o_stream_lzma_close; ++ ++ ret = lzma_easy_encoder(&zstream->strm, level, LZMA_CHECK_CRC64); ++ switch (ret) { ++ case LZMA_OK: ++ break; ++ case LZMA_MEM_ERROR: ++ i_fatal_status(FATAL_OUTOFMEM, "lzma: Out of memory"); ++ case LZMA_OPTIONS_ERROR: ++ i_fatal("lzma: Invalid level"); ++ default: ++ i_fatal("lzma_easy_encoder() failed with %d", ret); ++ } ++ ++ zstream->strm.next_out = zstream->outbuf; ++ zstream->strm.avail_out = sizeof(zstream->outbuf); ++ return o_stream_create(&zstream->ostream, output, ++ o_stream_get_fd(output)); ++} ++#endif +diff -up dovecot-2.3.16/src/lib-compression/ostream-zlib.h.keeplzma dovecot-2.3.16/src/lib-compression/ostream-zlib.h +--- dovecot-2.3.16/src/lib-compression/ostream-zlib.h.keeplzma 2021-08-06 11:25:51.000000000 +0200 ++++ dovecot-2.3.16/src/lib-compression/ostream-zlib.h 2022-02-28 13:58:02.338149934 +0100 +@@ -4,6 +4,7 @@ + struct ostream *o_stream_create_gz(struct ostream *output, int level); + struct ostream *o_stream_create_deflate(struct ostream *output, int level); + struct ostream *o_stream_create_bz2(struct ostream *output, int level); ++struct ostream *o_stream_create_lzma(struct ostream *output, int level); + struct ostream *o_stream_create_lz4(struct ostream *output, int level); + struct ostream *o_stream_create_zstd(struct ostream *output, int level); + +diff -up dovecot-2.3.16/src/lib-compression/test-compression.c.keeplzma dovecot-2.3.16/src/lib-compression/test-compression.c +--- dovecot-2.3.16/src/lib-compression/test-compression.c.keeplzma 2021-08-06 11:25:51.000000000 +0200 ++++ dovecot-2.3.16/src/lib-compression/test-compression.c 2022-02-28 13:58:02.338149934 +0100 +@@ -730,7 +730,6 @@ static void test_compression_int(bool au + + for (i = 0; compression_handlers[i].name != NULL; i++) { + if (compression_handlers[i].create_istream != NULL && +- compression_handlers[i].create_ostream != NULL && + (!autodetect || + compression_handlers[i].is_compressed != NULL)) T_BEGIN { + if (compression_handlers[i].is_compressed != NULL && diff --git a/SOURCES/dovecot-2.3.6-opensslhmac.patch b/SOURCES/dovecot-2.3.6-opensslhmac.patch index 18b9904..ba6453b 100644 --- a/SOURCES/dovecot-2.3.6-opensslhmac.patch +++ b/SOURCES/dovecot-2.3.6-opensslhmac.patch @@ -1,6 +1,6 @@ -diff -up dovecot-2.3.8/src/auth/auth-token.c.opensslhmac dovecot-2.3.8/src/auth/auth-token.c ---- dovecot-2.3.8/src/auth/auth-token.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/auth-token.c 2019-11-19 16:34:11.338037002 +0100 +diff -up dovecot-2.3.14/src/auth/auth-token.c.opensslhmac dovecot-2.3.14/src/auth/auth-token.c +--- dovecot-2.3.14/src/auth/auth-token.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/auth/auth-token.c 2021-03-22 20:44:13.022912242 +0100 @@ -161,17 +161,17 @@ void auth_token_deinit(void) const char *auth_token_get(const char *service, const char *session_pid, const char *username, const char *session_id) @@ -26,9 +26,9 @@ diff -up dovecot-2.3.8/src/auth/auth-token.c.opensslhmac dovecot-2.3.8/src/auth/ return binary_to_hex(result, sizeof(result)); } -diff -up dovecot-2.3.8/src/auth/mech-cram-md5.c.opensslhmac dovecot-2.3.8/src/auth/mech-cram-md5.c ---- dovecot-2.3.8/src/auth/mech-cram-md5.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/mech-cram-md5.c 2019-11-19 16:34:11.338037002 +0100 +diff -up dovecot-2.3.14/src/auth/mech-cram-md5.c.opensslhmac dovecot-2.3.14/src/auth/mech-cram-md5.c +--- dovecot-2.3.14/src/auth/mech-cram-md5.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/auth/mech-cram-md5.c 2021-03-22 20:44:13.022912242 +0100 @@ -51,7 +51,7 @@ static bool verify_credentials(struct cr { @@ -52,59 +52,57 @@ diff -up dovecot-2.3.8/src/auth/mech-cram-md5.c.opensslhmac dovecot-2.3.8/src/au response_hex = binary_to_hex(digest, sizeof(digest)); -diff -up dovecot-2.3.8/src/auth/mech-scram-sha1.c.opensslhmac dovecot-2.3.8/src/auth/mech-scram-sha1.c ---- dovecot-2.3.8/src/auth/mech-scram-sha1.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/mech-scram-sha1.c 2019-11-19 16:34:11.338037002 +0100 -@@ -71,7 +71,7 @@ static const char *get_scram_server_firs - +diff -up dovecot-2.3.14/src/auth/mech-scram.c.opensslhmac dovecot-2.3.14/src/auth/mech-scram.c +--- dovecot-2.3.14/src/auth/mech-scram.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/auth/mech-scram.c 2021-03-22 20:44:13.022912242 +0100 +@@ -78,7 +78,7 @@ static const char *get_scram_server_firs static const char *get_scram_server_final(struct scram_auth_request *request) { + const struct hash_method *hmethod = request->hash_method; - struct hmac_context ctx; + struct openssl_hmac_context ctx; const char *auth_message; - unsigned char server_signature[SHA1_RESULTLEN]; + unsigned char server_signature[hmethod->digest_size]; string_t *str; -@@ -80,10 +80,10 @@ static const char *get_scram_server_fina +@@ -87,9 +87,9 @@ static const char *get_scram_server_fina request->server_first_message, ",", request->client_final_message_without_proof, NULL); -- hmac_init(&ctx, request->server_key, sizeof(request->server_key), -+ openssl_hmac_init(&ctx, request->server_key, sizeof(request->server_key), - &hash_method_sha1); +- hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod); - hmac_update(&ctx, auth_message, strlen(auth_message)); - hmac_final(&ctx, server_signature); ++ openssl_hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod); + openssl_hmac_update(&ctx, auth_message, strlen(auth_message)); + openssl_hmac_final(&ctx, server_signature); str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(server_signature))); str_append(str, "v="); -@@ -221,7 +221,7 @@ static bool parse_scram_client_first(str - +@@ -228,7 +228,7 @@ static bool parse_scram_client_first(str static bool verify_credentials(struct scram_auth_request *request) { + const struct hash_method *hmethod = request->hash_method; - struct hmac_context ctx; + struct openssl_hmac_context ctx; const char *auth_message; - unsigned char client_key[SHA1_RESULTLEN]; - unsigned char client_signature[SHA1_RESULTLEN]; -@@ -232,10 +232,10 @@ static bool verify_credentials(struct sc + unsigned char client_key[hmethod->digest_size]; + unsigned char client_signature[hmethod->digest_size]; +@@ -239,9 +239,9 @@ static bool verify_credentials(struct sc request->server_first_message, ",", request->client_final_message_without_proof, NULL); -- hmac_init(&ctx, request->stored_key, sizeof(request->stored_key), -+ openssl_hmac_init(&ctx, request->stored_key, sizeof(request->stored_key), - &hash_method_sha1); +- hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod); - hmac_update(&ctx, auth_message, strlen(auth_message)); - hmac_final(&ctx, client_signature); ++ openssl_hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod); + openssl_hmac_update(&ctx, auth_message, strlen(auth_message)); + openssl_hmac_final(&ctx, client_signature); + const unsigned char *proof_data = request->proof->data; for (i = 0; i < sizeof(client_signature); i++) - client_key[i] = -diff -up dovecot-2.3.8/src/auth/password-scheme.c.opensslhmac dovecot-2.3.8/src/auth/password-scheme.c ---- dovecot-2.3.8/src/auth/password-scheme.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/password-scheme.c 2019-11-19 16:34:11.339036998 +0100 -@@ -647,11 +647,11 @@ static void +diff -up dovecot-2.3.14/src/auth/password-scheme.c.opensslhmac dovecot-2.3.14/src/auth/password-scheme.c +--- dovecot-2.3.14/src/auth/password-scheme.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/auth/password-scheme.c 2021-03-22 20:44:13.022912242 +0100 +@@ -639,11 +639,11 @@ static void cram_md5_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED, const unsigned char **raw_password_r, size_t *size_r) { @@ -118,104 +116,101 @@ diff -up dovecot-2.3.8/src/auth/password-scheme.c.opensslhmac dovecot-2.3.8/src/ strlen(plaintext), &hash_method_md5); hmac_md5_get_cram_context(&ctx, context_digest); -diff -up dovecot-2.3.8/src/auth/password-scheme-scram.c.opensslhmac dovecot-2.3.8/src/auth/password-scheme-scram.c ---- dovecot-2.3.8/src/auth/password-scheme-scram.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/password-scheme-scram.c 2019-11-19 16:34:11.339036998 +0100 -@@ -27,23 +27,23 @@ static void Hi(const unsigned char *str, - const unsigned char *salt, size_t salt_size, unsigned int i, - unsigned char result[SHA1_RESULTLEN]) +diff -up dovecot-2.3.14/src/auth/password-scheme-scram.c.opensslhmac dovecot-2.3.14/src/auth/password-scheme-scram.c +--- dovecot-2.3.14/src/auth/password-scheme-scram.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/auth/password-scheme-scram.c 2021-03-22 20:44:13.023912229 +0100 +@@ -30,23 +30,23 @@ Hi(const struct hash_method *hmethod, co + const unsigned char *salt, size_t salt_size, unsigned int i, + unsigned char *result) { - struct hmac_context ctx; + struct openssl_hmac_context ctx; - unsigned char U[SHA1_RESULTLEN]; + unsigned char U[hmethod->digest_size]; unsigned int j, k; /* Calculate U1 */ -- hmac_init(&ctx, str, str_size, &hash_method_sha1); +- hmac_init(&ctx, str, str_size, hmethod); - hmac_update(&ctx, salt, salt_size); - hmac_update(&ctx, "\0\0\0\1", 4); - hmac_final(&ctx, U); -+ openssl_hmac_init(&ctx, str, str_size, &hash_method_sha1); ++ openssl_hmac_init(&ctx, str, str_size, hmethod); + openssl_hmac_update(&ctx, salt, salt_size); + openssl_hmac_update(&ctx, "\0\0\0\1", 4); + openssl_hmac_final(&ctx, U); - memcpy(result, U, SHA1_RESULTLEN); + memcpy(result, U, hmethod->digest_size); /* Calculate U2 to Ui and Hi */ for (j = 2; j <= i; j++) { -- hmac_init(&ctx, str, str_size, &hash_method_sha1); +- hmac_init(&ctx, str, str_size, hmethod); - hmac_update(&ctx, U, sizeof(U)); - hmac_final(&ctx, U); -+ openssl_hmac_init(&ctx, str, str_size, &hash_method_sha1); ++ openssl_hmac_init(&ctx, str, str_size, hmethod); + openssl_hmac_update(&ctx, U, sizeof(U)); + openssl_hmac_final(&ctx, U); - for (k = 0; k < SHA1_RESULTLEN; k++) + for (k = 0; k < hmethod->digest_size; k++) result[k] ^= U[k]; } -@@ -94,7 +94,7 @@ int scram_sha1_verify(const char *plaint - const unsigned char *raw_password, size_t size, - const char **error_r) +@@ -102,7 +102,7 @@ int scram_verify(const struct hash_metho + const char *plaintext, const unsigned char *raw_password, + size_t size, const char **error_r) { - struct hmac_context ctx; + struct openssl_hmac_context ctx; const char *salt_base64; unsigned int iter_count; const unsigned char *salt; -@@ -118,10 +118,10 @@ int scram_sha1_verify(const char *plaint - iter_count, salted_password); +@@ -126,9 +126,9 @@ int scram_verify(const struct hash_metho + salt, salt_len, iter_count, salted_password); /* Calculate ClientKey */ -- hmac_init(&ctx, salted_password, sizeof(salted_password), -+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), - &hash_method_sha1); +- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); - hmac_update(&ctx, "Client Key", 10); - hmac_final(&ctx, client_key); ++ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); + openssl_hmac_update(&ctx, "Client Key", 10); + openssl_hmac_final(&ctx, client_key); /* Calculate StoredKey */ - sha1_get_digest(client_key, sizeof(client_key), calculated_stored_key); -@@ -139,7 +139,7 @@ void scram_sha1_generate(const char *pla - const unsigned char **raw_password_r, size_t *size_r) + hash_method_get_digest(hmethod, client_key, sizeof(client_key), +@@ -147,7 +147,7 @@ void scram_generate(const struct hash_me + const unsigned char **raw_password_r, size_t *size_r) { string_t *str; - struct hmac_context ctx; + struct openssl_hmac_context ctx; unsigned char salt[16]; - unsigned char salted_password[SHA1_RESULTLEN]; - unsigned char client_key[SHA1_RESULTLEN]; -@@ -157,10 +157,10 @@ void scram_sha1_generate(const char *pla + unsigned char salted_password[hmethod->digest_size]; + unsigned char client_key[hmethod->digest_size]; +@@ -165,9 +165,9 @@ void scram_generate(const struct hash_me sizeof(salt), SCRAM_DEFAULT_ITERATE_COUNT, salted_password); /* Calculate ClientKey */ -- hmac_init(&ctx, salted_password, sizeof(salted_password), -+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), - &hash_method_sha1); +- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); - hmac_update(&ctx, "Client Key", 10); - hmac_final(&ctx, client_key); ++ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); + openssl_hmac_update(&ctx, "Client Key", 10); + openssl_hmac_final(&ctx, client_key); /* Calculate StoredKey */ - sha1_get_digest(client_key, sizeof(client_key), stored_key); -@@ -168,10 +168,10 @@ void scram_sha1_generate(const char *pla + hash_method_get_digest(hmethod, client_key, sizeof(client_key), +@@ -176,9 +176,9 @@ void scram_generate(const struct hash_me base64_encode(stored_key, sizeof(stored_key), str); /* Calculate ServerKey */ -- hmac_init(&ctx, salted_password, sizeof(salted_password), -+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), - &hash_method_sha1); +- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); - hmac_update(&ctx, "Server Key", 10); - hmac_final(&ctx, server_key); ++ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod); + openssl_hmac_update(&ctx, "Server Key", 10); + openssl_hmac_final(&ctx, server_key); str_append_c(str, ','); base64_encode(server_key, sizeof(server_key), str); -diff -up dovecot-2.3.8/src/lib/hmac.c.opensslhmac dovecot-2.3.8/src/lib/hmac.c ---- dovecot-2.3.8/src/lib/hmac.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib/hmac.c 2019-11-19 17:25:28.045716181 +0100 +diff -up dovecot-2.3.14/src/lib/hmac.c.opensslhmac dovecot-2.3.14/src/lib/hmac.c +--- dovecot-2.3.14/src/lib/hmac.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/hmac.c 2021-03-22 20:44:13.023912229 +0100 @@ -7,6 +7,10 @@ * This software is released under the MIT license. */ @@ -292,11 +287,11 @@ diff -up dovecot-2.3.8/src/lib/hmac.c.opensslhmac dovecot-2.3.8/src/lib/hmac.c + } + i_assert(no_fips); + struct orig_hmac_context_priv *ctx = &_ctx->u.priv; - int i; - unsigned char k_ipad[64]; - unsigned char k_opad[64]; + unsigned int i; + unsigned char k_ipad[meth->block_size]; + unsigned char k_opad[meth->block_size]; @@ -53,9 +112,27 @@ void hmac_init(struct hmac_context *_ctx - safe_memset(k_opad, 0, 64); + safe_memset(k_opad, 0, meth->block_size); } -void hmac_final(struct hmac_context *_ctx, unsigned char *digest) @@ -453,9 +448,9 @@ diff -up dovecot-2.3.8/src/lib/hmac.c.opensslhmac dovecot-2.3.8/src/lib/hmac.c - safe_memset(prk, 0, sizeof(prk)); - safe_memset(okm, 0, sizeof(okm)); } -diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.8/src/lib/hmac-cram-md5.c ---- dovecot-2.3.8/src/lib/hmac-cram-md5.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib/hmac-cram-md5.c 2019-11-19 16:34:11.339036998 +0100 +diff -up dovecot-2.3.14/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.14/src/lib/hmac-cram-md5.c +--- dovecot-2.3.14/src/lib/hmac-cram-md5.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/hmac-cram-md5.c 2021-03-22 20:44:13.023912229 +0100 @@ -9,10 +9,10 @@ #include "md5.h" #include "hmac-cram-md5.h" @@ -482,9 +477,9 @@ diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.8/src/lib const unsigned char *cdp; struct md5_context *ctx = (void*)hmac_ctx->ctx; -diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.8/src/lib/hmac-cram-md5.h ---- dovecot-2.3.8/src/lib/hmac-cram-md5.h.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib/hmac-cram-md5.h 2019-11-19 16:34:11.339036998 +0100 +diff -up dovecot-2.3.14/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.14/src/lib/hmac-cram-md5.h +--- dovecot-2.3.14/src/lib/hmac-cram-md5.h.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/hmac-cram-md5.h 2021-03-22 20:44:13.023912229 +0100 @@ -5,9 +5,9 @@ #define CRAM_MD5_CONTEXTLEN 32 @@ -497,19 +492,19 @@ diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.8/src/lib const unsigned char context_digest[CRAM_MD5_CONTEXTLEN]); -diff -up dovecot-2.3.8/src/lib/hmac.h.opensslhmac dovecot-2.3.8/src/lib/hmac.h ---- dovecot-2.3.8/src/lib/hmac.h.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib/hmac.h 2019-11-19 16:34:11.339036998 +0100 -@@ -3,60 +3,97 @@ - +diff -up dovecot-2.3.14/src/lib/hmac.h.opensslhmac dovecot-2.3.14/src/lib/hmac.h +--- dovecot-2.3.14/src/lib/hmac.h.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/hmac.h 2021-03-22 20:44:13.023912229 +0100 +@@ -4,60 +4,97 @@ #include "hash-method.h" #include "sha1.h" + #include "sha2.h" +#include +#include +#include +#include - #define HMAC_MAX_CONTEXT_SIZE 256 + #define HMAC_MAX_CONTEXT_SIZE sizeof(struct sha512_ctx) -struct hmac_context_priv { +struct openssl_hmac_context_priv { @@ -611,9 +606,9 @@ diff -up dovecot-2.3.8/src/lib/hmac.h.opensslhmac dovecot-2.3.8/src/lib/hmac.h okm_buffer, okm_len); return okm_buffer; } -diff -up dovecot-2.3.8/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac dovecot-2.3.8/src/lib-imap-urlauth/imap-urlauth.c ---- dovecot-2.3.8/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-imap-urlauth/imap-urlauth.c 2019-11-19 16:34:11.339036998 +0100 +diff -up dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c +--- dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c 2021-03-22 20:44:13.023912229 +0100 @@ -85,15 +85,15 @@ imap_urlauth_internal_generate(const cha const unsigned char mailbox_key[IMAP_URLAUTH_KEY_LEN], size_t *token_len_r) @@ -634,10 +629,10 @@ diff -up dovecot-2.3.8/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac dovecot-2 *token_len_r = SHA1_RESULTLEN + 1; return token; -diff -up dovecot-2.3.8/src/lib/Makefile.am.opensslhmac dovecot-2.3.8/src/lib/Makefile.am ---- dovecot-2.3.8/src/lib/Makefile.am.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib/Makefile.am 2019-11-19 16:34:11.340036994 +0100 -@@ -323,6 +323,9 @@ headers = \ +diff -up dovecot-2.3.14/src/lib/Makefile.am.opensslhmac dovecot-2.3.14/src/lib/Makefile.am +--- dovecot-2.3.14/src/lib/Makefile.am.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/Makefile.am 2021-03-22 20:44:13.023912229 +0100 +@@ -352,6 +352,9 @@ headers = \ wildcard-match.h \ write-full.h @@ -647,69 +642,63 @@ diff -up dovecot-2.3.8/src/lib/Makefile.am.opensslhmac dovecot-2.3.8/src/lib/Mak test_programs = test-lib noinst_PROGRAMS = $(test_programs) -diff -up dovecot-2.3.8/src/lib-ntlm/ntlm-encrypt.c.opensslhmac dovecot-2.3.8/src/lib-ntlm/ntlm-encrypt.c ---- dovecot-2.3.8/src/lib-ntlm/ntlm-encrypt.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-ntlm/ntlm-encrypt.c 2019-11-19 16:34:11.340036994 +0100 -@@ -61,12 +61,12 @@ void ntlm_v1_hash(const char *passwd, un - } +diff -up dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c.opensslhmac dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c +--- dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c 2021-03-22 20:44:13.024912217 +0100 +@@ -106,14 +106,14 @@ oauth2_validate_hmac(const struct oauth2 + if (oauth2_lookup_hmac_key(set, azp, alg, key_id, &key, error_r) < 0) + return -1; - static void --hmac_md5_ucs2le_string_ucase(struct hmac_context *ctx, const char *str) --{ -- size_t len; -- unsigned char *wstr = t_unicode_str(str, TRUE, &len); -- -- hmac_update(ctx, wstr, len); -+hmac_md5_ucs2le_string_ucase(struct openssl_hmac_context *ctx, const char *str) -+ { -+ size_t len; -+ unsigned char *wstr = t_unicode_str(str, TRUE, &len); -+ -+ openssl_hmac_update(ctx, wstr, len); - } - - static void ATTR_NULL(2) -@@ -74,13 +74,13 @@ ntlm_v2_hash(const char *user, const cha - const unsigned char *hash_v1, - unsigned char hash[NTLMSSP_V2_HASH_SIZE]) - { - struct hmac_context ctx; +- hmac_init(&ctx, key->data, key->used, method); +- hmac_update(&ctx, blobs[0], strlen(blobs[0])); +- hmac_update(&ctx, ".", 1); +- hmac_update(&ctx, blobs[1], strlen(blobs[1])); + struct openssl_hmac_context ctx; ++ openssl_hmac_init(&ctx, key->data, key->used, method); ++ openssl_hmac_update(&ctx, blobs[0], strlen(blobs[0])); ++ openssl_hmac_update(&ctx, ".", 1); ++ openssl_hmac_update(&ctx, blobs[1], strlen(blobs[1])); + unsigned char digest[method->digest_size]; -- hmac_init(&ctx, hash_v1, NTLMSSP_HASH_SIZE, &hash_method_md5); -+ openssl_hmac_init(&ctx, hash_v1, NTLMSSP_HASH_SIZE, &hash_method_md5); - hmac_md5_ucs2le_string_ucase(&ctx, user); - if (target != NULL) - hmac_md5_ucs2le_string_ucase(&ctx, target); -- hmac_final(&ctx, hash); -+ openssl_hmac_final(&ctx, hash); - } +- hmac_final(&ctx, digest); ++ openssl_hmac_final(&ctx, digest); - void -@@ -125,15 +125,15 @@ ntlmssp_v2_response(const char *user, co - const unsigned char *blob, size_t blob_size, - unsigned char response[NTLMSSP_V2_RESPONSE_SIZE]) + buffer_t *their_digest = + t_base64url_decode_str(BASE64_DECODE_FLAG_NO_PADDING, blobs[2]); +diff -up dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c.opensslhmac dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c +--- dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c 2021-03-22 20:46:09.524440794 +0100 +@@ -236,7 +236,7 @@ static void save_key_to(const char *algo + static void sign_jwt_token_hs256(buffer_t *tokenbuf, buffer_t *key) { -- struct hmac_context ctx; -+ struct openssl_hmac_context ctx; - unsigned char hash[NTLMSSP_V2_HASH_SIZE]; - - ntlm_v2_hash(user, target, hash_v1, hash); - -- hmac_init(&ctx, hash, NTLMSSP_V2_HASH_SIZE, &hash_method_md5); -- hmac_update(&ctx, challenge, NTLMSSP_CHALLENGE_SIZE); -- hmac_update(&ctx, blob, blob_size); -- hmac_final(&ctx, response); -+ openssl_hmac_init(&ctx, hash, NTLMSSP_V2_HASH_SIZE, &hash_method_md5); -+ openssl_hmac_update(&ctx, challenge, NTLMSSP_CHALLENGE_SIZE); -+ openssl_hmac_update(&ctx, blob, blob_size); -+ openssl_hmac_final(&ctx, response); - - safe_memset(hash, 0, sizeof(hash)); - } -diff -up dovecot-2.3.8/src/lib/pkcs5.c.opensslhmac dovecot-2.3.8/src/lib/pkcs5.c ---- dovecot-2.3.8/src/lib/pkcs5.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib/pkcs5.c 2019-11-19 16:34:11.340036994 +0100 + i_assert(key != NULL); +- buffer_t *sig = t_hmac_buffer(&hash_method_sha256, key->data, key->used, ++ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha256, key->data, key->used, + tokenbuf); + buffer_append(tokenbuf, ".", 1); + base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX, +@@ -246,7 +246,7 @@ static void sign_jwt_token_hs256(buffer_ + static void sign_jwt_token_hs384(buffer_t *tokenbuf, buffer_t *key) + { + i_assert(key != NULL); +- buffer_t *sig = t_hmac_buffer(&hash_method_sha384, key->data, key->used, ++ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha384, key->data, key->used, + tokenbuf); + buffer_append(tokenbuf, ".", 1); + base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX, +@@ -256,7 +256,7 @@ static void sign_jwt_token_hs384(buffer_ + static void sign_jwt_token_hs512(buffer_t *tokenbuf, buffer_t *key) + { + i_assert(key != NULL); +- buffer_t *sig = t_hmac_buffer(&hash_method_sha512, key->data, key->used, ++ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha512, key->data, key->used, + tokenbuf); + buffer_append(tokenbuf, ".", 1); + base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX, +diff -up dovecot-2.3.14/src/lib/pkcs5.c.opensslhmac dovecot-2.3.14/src/lib/pkcs5.c +--- dovecot-2.3.14/src/lib/pkcs5.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/pkcs5.c 2021-03-22 20:44:13.024912217 +0100 @@ -52,7 +52,7 @@ int pkcs5_pbkdf2(const struct hash_metho size_t l = (length + hash->digest_size - 1)/hash->digest_size; /* same as ceil(length/hash->digest_size) */ unsigned char dk[l * hash->digest_size]; @@ -744,10 +733,10 @@ diff -up dovecot-2.3.8/src/lib/pkcs5.c.opensslhmac dovecot-2.3.8/src/lib/pkcs5.c for(i = 0; i < hash->digest_size; i++) block[i] ^= U_c[i]; } -diff -up dovecot-2.3.8/src/lib/test-hmac.c.opensslhmac dovecot-2.3.8/src/lib/test-hmac.c ---- dovecot-2.3.8/src/lib/test-hmac.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib/test-hmac.c 2019-11-19 16:34:11.340036994 +0100 -@@ -112,11 +112,11 @@ static void test_hmac_rfc(void) +diff -up dovecot-2.3.14/src/lib/test-hmac.c.opensslhmac dovecot-2.3.14/src/lib/test-hmac.c +--- dovecot-2.3.14/src/lib/test-hmac.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100 ++++ dovecot-2.3.14/src/lib/test-hmac.c 2021-03-22 20:44:13.024912217 +0100 +@@ -206,11 +206,11 @@ static void test_hmac_rfc(void) test_begin("hmac sha256 rfc4231 vectors"); for(size_t i = 0; i < N_ELEMENTS(test_vectors); i++) { const struct test_vector *vec = &(test_vectors[i]); @@ -763,7 +752,39 @@ diff -up dovecot-2.3.8/src/lib/test-hmac.c.opensslhmac dovecot-2.3.8/src/lib/tes test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i); } test_end(); -@@ -129,7 +129,7 @@ static void test_hmac_buffer(void) +@@ -221,11 +221,11 @@ static void test_hmac384_rfc(void) + test_begin("hmac sha384 rfc4231 vectors"); + for (size_t i = 0; i < N_ELEMENTS(test_vectors_hmac384); i++) { + const struct test_vector *vec = &(test_vectors_hmac384[i]); +- struct hmac_context ctx; +- hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); +- hmac_update(&ctx, vec->data, vec->data_len); ++ struct openssl_hmac_context ctx; ++ openssl_hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); ++ openssl_hmac_update(&ctx, vec->data, vec->data_len); + unsigned char res[SHA384_RESULTLEN]; +- hmac_final(&ctx, res); ++ openssl_hmac_final(&ctx, res); + test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i); + } + test_end(); +@@ -236,11 +236,11 @@ static void test_hmac512_rfc(void) + test_begin("hmac sha512 rfc4231 vectors"); + for (size_t i = 0; i < N_ELEMENTS(test_vectors_hmac512); i++) { + const struct test_vector *vec = &(test_vectors_hmac512[i]); +- struct hmac_context ctx; +- hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); +- hmac_update(&ctx, vec->data, vec->data_len); ++ struct openssl_hmac_context ctx; ++ openssl_hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf)); ++ openssl_hmac_update(&ctx, vec->data, vec->data_len); + unsigned char res[SHA512_RESULTLEN]; +- hmac_final(&ctx, res); ++ openssl_hmac_final(&ctx, res); + test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i); + } + test_end(); +@@ -253,7 +253,7 @@ static void test_hmac_buffer(void) buffer_t *tmp; @@ -772,7 +793,7 @@ diff -up dovecot-2.3.8/src/lib/test-hmac.c.opensslhmac dovecot-2.3.8/src/lib/tes vec->data, vec->data_len); test_assert(tmp->used == vec->res_len && -@@ -146,7 +146,7 @@ static void test_hkdf_rfc(void) +@@ -270,7 +270,7 @@ static void test_hkdf_rfc(void) buffer_set_used_size(res, 0); const struct test_vector_5869 *vec = &(test_vectors_5869[i]); const struct hash_method *m = hash_method_lookup(vec->prf); @@ -781,7 +802,7 @@ diff -up dovecot-2.3.8/src/lib/test-hmac.c.opensslhmac dovecot-2.3.8/src/lib/tes vec->info, vec->info_len, res, vec->okm_len); test_assert_idx(memcmp(res->data, vec->okm, vec->okm_len) == 0, i); } -@@ -159,7 +159,7 @@ static void test_hkdf_buffer(void) +@@ -283,7 +283,7 @@ static void test_hkdf_buffer(void) test_begin("hkdf temporary buffer"); const struct test_vector_5869 *vec = &(test_vectors_5869[0]); const struct hash_method *m = hash_method_lookup(vec->prf); diff --git a/SOURCES/dovecot-2.3.8-CVE_2020_12100.patch b/SOURCES/dovecot-2.3.8-CVE_2020_12100.patch deleted file mode 100644 index c1ddfdd..0000000 --- a/SOURCES/dovecot-2.3.8-CVE_2020_12100.patch +++ /dev/null @@ -1,2437 +0,0 @@ -diff -up dovecot-2.3.8/src/doveadm/doveadm-mail-fetch.c.CVE_2020_12100 dovecot-2.3.8/src/doveadm/doveadm-mail-fetch.c ---- dovecot-2.3.8/src/doveadm/doveadm-mail-fetch.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/doveadm/doveadm-mail-fetch.c 2020-08-07 12:29:39.975827486 +0200 -@@ -265,6 +265,9 @@ static int fetch_text(struct fetch_cmd_c - - static int fetch_text_utf8(struct fetch_cmd_context *ctx) - { -+ const struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE, -+ }; - struct istream *input; - struct message_parser_ctx *parser; - struct message_decoder_context *decoder; -@@ -275,9 +278,7 @@ static int fetch_text_utf8(struct fetch_ - if (mail_get_stream(ctx->mail, NULL, NULL, &input) < 0) - return -1; - -- parser = message_parser_init(pool_datastack_create(), input, -- MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE, -- 0); -+ parser = message_parser_init(pool_datastack_create(), input, &parser_set); - decoder = message_decoder_init(NULL, 0); - - while ((ret = message_parser_parse_next_block(parser, &raw_block)) > 0) { -diff -up dovecot-2.3.8/src/lib-imap/test-imap-bodystructure.c.CVE_2020_12100 dovecot-2.3.8/src/lib-imap/test-imap-bodystructure.c ---- dovecot-2.3.8/src/lib-imap/test-imap-bodystructure.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-imap/test-imap-bodystructure.c 2020-08-07 12:29:39.975827486 +0200 -@@ -381,6 +381,11 @@ static const unsigned int normalize_test - static struct message_part * - msg_parse(pool_t pool, const char *message, bool parse_bodystructure) - { -+ const struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -+ MESSAGE_HEADER_PARSER_FLAG_DROP_CR, -+ .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, -+ }; - struct message_parser_ctx *parser; - struct istream *input; - struct message_block block; -@@ -388,10 +393,7 @@ msg_parse(pool_t pool, const char *messa - int ret; - - input = i_stream_create_from_data(message, strlen(message)); -- parser = message_parser_init(pool, input, -- MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -- MESSAGE_HEADER_PARSER_FLAG_DROP_CR, -- MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK); -+ parser = message_parser_init(pool, input, &parser_set); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) { - if (parse_bodystructure) { - message_part_data_parse_from_header(pool, block.part, -diff -up dovecot-2.3.8/src/lib-imap/test-imap-envelope.c.CVE_2020_12100 dovecot-2.3.8/src/lib-imap/test-imap-envelope.c ---- dovecot-2.3.8/src/lib-imap/test-imap-envelope.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-imap/test-imap-envelope.c 2020-08-07 12:29:39.975827486 +0200 -@@ -118,6 +118,11 @@ static const unsigned int parse_tests_co - static struct message_part_envelope * - msg_parse(pool_t pool, const char *message) - { -+ const struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -+ MESSAGE_HEADER_PARSER_FLAG_DROP_CR, -+ .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, -+ }; - struct message_parser_ctx *parser; - struct message_part_envelope *envlp = NULL; - struct istream *input; -@@ -126,10 +131,7 @@ msg_parse(pool_t pool, const char *messa - int ret; - - input = i_stream_create_from_data(message, strlen(message)); -- parser = message_parser_init(pool, input, -- MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -- MESSAGE_HEADER_PARSER_FLAG_DROP_CR, -- MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK); -+ parser = message_parser_init(pool, input, &parser_set); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) { - i_assert(block.part->parent == NULL); - message_part_envelope_parse_from_header(pool, &envlp, block.hdr); -diff -up dovecot-2.3.8/src/lib-mail/istream-attachment-extractor.c.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/istream-attachment-extractor.c ---- dovecot-2.3.8/src/lib-mail/istream-attachment-extractor.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-mail/istream-attachment-extractor.c 2020-08-07 12:29:39.975827486 +0200 -@@ -696,6 +696,10 @@ i_stream_create_attachment_extractor(str - struct istream_attachment_settings *set, - void *context) - { -+ const struct message_parser_settings parser_set = { -+ .flags = MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -+ MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES, -+ }; - struct attachment_istream *astream; - - i_assert(set->min_size > 0); -@@ -722,9 +726,7 @@ i_stream_create_attachment_extractor(str - astream->istream.istream.seekable = FALSE; - - astream->pool = pool_alloconly_create("istream attachment", 1024); -- astream->parser = message_parser_init(astream->pool, input, 0, -- MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -- MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES); -+ astream->parser = message_parser_init(astream->pool, input, &parser_set); - return i_stream_create(&astream->istream, input, - i_stream_get_fd(input), 0); - } -diff -up dovecot-2.3.8/src/lib-mail/istream-binary-converter.c.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/istream-binary-converter.c ---- dovecot-2.3.8/src/lib-mail/istream-binary-converter.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-mail/istream-binary-converter.c 2020-08-07 12:29:39.975827486 +0200 -@@ -286,6 +286,10 @@ static void i_stream_binary_converter_cl - - struct istream *i_stream_create_binary_converter(struct istream *input) - { -+ const struct message_parser_settings parser_set = { -+ .flags = MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -+ MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES, -+ }; - struct binary_converter_istream *bstream; - - bstream = i_new(struct binary_converter_istream, 1); -@@ -299,9 +303,7 @@ struct istream *i_stream_create_binary_c - bstream->istream.istream.seekable = FALSE; - - bstream->pool = pool_alloconly_create("istream binary converter", 128); -- bstream->parser = message_parser_init(bstream->pool, input, 0, -- MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -- MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES); -+ bstream->parser = message_parser_init(bstream->pool, input, &parser_set); - return i_stream_create(&bstream->istream, input, - i_stream_get_fd(input), 0); - } -diff -up dovecot-2.3.8/src/lib-mail/Makefile.am.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/Makefile.am ---- dovecot-2.3.8/src/lib-mail/Makefile.am.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-mail/Makefile.am 2020-08-07 12:29:39.972827528 +0200 -@@ -28,6 +28,7 @@ libmail_la_SOURCES = \ - message-header-parser.c \ - message-id.c \ - message-parser.c \ -+ message-parser-from-parts.c \ - message-part.c \ - message-part-data.c \ - message-part-serialize.c \ -@@ -42,7 +43,8 @@ libmail_la_SOURCES = \ - rfc822-parser.c - - noinst_HEADERS = \ -- html-entities.h -+ html-entities.h \ -+ message-parser-private.h - - headers = \ - istream-attachment-connector.h \ -diff -up dovecot-2.3.8/src/lib-mail/message-parser.c.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/message-parser.c ---- dovecot-2.3.8/src/lib-mail/message-parser.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-mail/message-parser.c 2020-08-07 12:29:39.978827444 +0200 -@@ -1,54 +1,12 @@ - /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ - - #include "lib.h" --#include "buffer.h" -+#include "array.h" - #include "str.h" - #include "istream.h" - #include "rfc822-parser.h" - #include "rfc2231-parser.h" --#include "message-parser.h" -- --/* RFC-2046 requires boundaries are max. 70 chars + "--" prefix + "--" suffix. -- We'll add a bit more just in case. */ --#define BOUNDARY_END_MAX_LEN (70 + 2 + 2 + 10) -- --struct message_boundary { -- struct message_boundary *next; -- -- struct message_part *part; -- const char *boundary; -- size_t len; -- -- bool epilogue_found:1; --}; -- --struct message_parser_ctx { -- pool_t parser_pool, part_pool; -- struct istream *input; -- struct message_part *parts, *part; -- const char *broken_reason; -- -- enum message_header_parser_flags hdr_flags; -- enum message_parser_flags flags; -- -- const char *last_boundary; -- struct message_boundary *boundaries; -- -- size_t skip; -- char last_chr; -- unsigned int want_count; -- -- struct message_header_parser_ctx *hdr_parser_ctx; -- unsigned int prev_hdr_newline_size; -- -- int (*parse_next_block)(struct message_parser_ctx *ctx, -- struct message_block *block_r); -- -- bool part_seen_content_type:1; -- bool multipart:1; -- bool preparsed:1; -- bool eof:1; --}; -+#include "message-parser-private.h" - - message_part_header_callback_t *null_message_part_header_callback = NULL; - -@@ -58,14 +16,10 @@ static int parse_next_body_to_boundary(s - struct message_block *block_r); - static int parse_next_body_to_eof(struct message_parser_ctx *ctx, - struct message_block *block_r); --static int preparsed_parse_epilogue_init(struct message_parser_ctx *ctx, -- struct message_block *block_r); --static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx, -- struct message_block *block_r); - - static struct message_boundary * - boundary_find(struct message_boundary *boundaries, -- const unsigned char *data, size_t len) -+ const unsigned char *data, size_t len, bool trailing_dashes) - { - struct message_boundary *best = NULL; - -@@ -77,8 +31,18 @@ boundary_find(struct message_boundary *b - while (boundaries != NULL) { - if (boundaries->len <= len && - memcmp(boundaries->boundary, data, boundaries->len) == 0 && -- (best == NULL || best->len < boundaries->len)) -+ (best == NULL || best->len < boundaries->len)) { - best = boundaries; -+ /* If we see "foo--", it could either mean that there -+ is a boundary named "foo" that ends now or there's -+ a boundary "foo--" which continues. */ -+ if (best->len == len || -+ (best->len == len-2 && trailing_dashes)) { -+ /* This is exactly the wanted boundary. There -+ can't be a better one. */ -+ break; -+ } -+ } - - boundaries = boundaries->next; - } -@@ -122,8 +86,8 @@ static void parse_body_add_block(struct - ctx->part->body_size.virtual_size += block->size + missing_cr_count; - } - --static int message_parser_read_more(struct message_parser_ctx *ctx, -- struct message_block *block_r, bool *full_r) -+int message_parser_read_more(struct message_parser_ctx *ctx, -+ struct message_block *block_r, bool *full_r) - { - int ret; - -@@ -168,19 +132,18 @@ static int message_parser_read_more(stru - return 1; - } - --static struct message_part * --message_part_append(pool_t pool, struct message_part *parent) -+static void -+message_part_append(struct message_parser_ctx *ctx) - { -- struct message_part *p, *part, **list; -+ struct message_part *parent = ctx->part; -+ struct message_part *part; - - i_assert(parent != NULL); - i_assert((parent->flags & (MESSAGE_PART_FLAG_MULTIPART | - MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0); - -- part = p_new(pool, struct message_part, 1); -+ part = p_new(ctx->part_pool, struct message_part, 1); - part->parent = parent; -- for (p = parent; p != NULL; p = p->parent) -- p->children_count++; - - /* set child position */ - part->physical_pos = -@@ -188,33 +151,78 @@ message_part_append(pool_t pool, struct - parent->body_size.physical_size + - parent->header_size.physical_size; - -- list = &part->parent->children; -- while (*list != NULL) -- list = &(*list)->next; -+ /* add to parent's linked list */ -+ *ctx->next_part = part; -+ /* update the parent's end-of-linked-list pointer */ -+ struct message_part **next_part = &part->next; -+ array_push_back(&ctx->next_part_stack, &next_part); -+ /* This part is now the new parent for the next message_part_append() -+ call. Its linked list begins with the children pointer. */ -+ ctx->next_part = &part->children; -+ -+ ctx->part = part; -+ ctx->nested_parts_count++; -+ ctx->total_parts_count++; -+ i_assert(ctx->nested_parts_count < ctx->max_nested_mime_parts); -+ i_assert(ctx->total_parts_count <= ctx->max_total_mime_parts); -+} -+ -+static void message_part_finish(struct message_parser_ctx *ctx) -+{ -+ struct message_part **const *parent_next_partp; -+ -+ i_assert(ctx->nested_parts_count > 0); -+ ctx->nested_parts_count--; -+ -+ parent_next_partp = array_back(&ctx->next_part_stack); -+ array_pop_back(&ctx->next_part_stack); -+ ctx->next_part = *parent_next_partp; -+ -+ message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size); -+ message_size_add(&ctx->part->parent->body_size, &ctx->part->header_size); -+ ctx->part->parent->children_count += 1 + ctx->part->children_count; -+ ctx->part = ctx->part->parent; -+} -+ -+static void message_boundary_free(struct message_boundary *b) -+{ -+ i_free(b->boundary); -+ i_free(b); -+} -+ -+static void -+boundary_remove_until(struct message_parser_ctx *ctx, -+ struct message_boundary *boundary) -+{ -+ while (ctx->boundaries != boundary) { -+ struct message_boundary *cur = ctx->boundaries; - -- *list = part; -- return part; -+ i_assert(cur != NULL); -+ ctx->boundaries = cur->next; -+ message_boundary_free(cur); -+ -+ } -+ ctx->boundaries = boundary; - } - - static void parse_next_body_multipart_init(struct message_parser_ctx *ctx) - { - struct message_boundary *b; - -- b = p_new(ctx->parser_pool, struct message_boundary, 1); -+ b = i_new(struct message_boundary, 1); - b->part = ctx->part; - b->boundary = ctx->last_boundary; -+ ctx->last_boundary = NULL; - b->len = strlen(b->boundary); - - b->next = ctx->boundaries; - ctx->boundaries = b; -- -- ctx->last_boundary = NULL; - } - - static int parse_next_body_message_rfc822_init(struct message_parser_ctx *ctx, - struct message_block *block_r) - { -- ctx->part = message_part_append(ctx->part_pool, ctx->part); -+ message_part_append(ctx); - return parse_next_header_init(ctx, block_r); - } - -@@ -239,19 +247,38 @@ boundary_line_find(struct message_parser - return -1; - } - -+ if (ctx->total_parts_count >= ctx->max_total_mime_parts) { -+ /* can't add any more MIME parts. just stop trying to find -+ more boundaries. */ -+ return -1; -+ } -+ - /* need to find the end of line */ -- if (memchr(data + 2, '\n', size - 2) == NULL && -- size < BOUNDARY_END_MAX_LEN && -+ data += 2; -+ size -= 2; -+ const unsigned char *lf_pos = memchr(data, '\n', size); -+ if (lf_pos == NULL && -+ size+2 < BOUNDARY_END_MAX_LEN && - !ctx->input->eof && !full) { - /* no LF found */ - ctx->want_count = BOUNDARY_END_MAX_LEN; - return 0; - } -+ size_t find_size = size; -+ bool trailing_dashes = FALSE; - -- data += 2; -- size -= 2; -+ if (lf_pos != NULL) { -+ find_size = lf_pos - data; -+ if (find_size > 0 && data[find_size-1] == '\r') -+ find_size--; -+ if (find_size > 2 && data[find_size-1] == '-' && -+ data[find_size-2] == '-') -+ trailing_dashes = TRUE; -+ } else if (find_size > BOUNDARY_END_MAX_LEN) -+ find_size = BOUNDARY_END_MAX_LEN; - -- *boundary_r = boundary_find(ctx->boundaries, data, size); -+ *boundary_r = boundary_find(ctx->boundaries, data, find_size, -+ trailing_dashes); - if (*boundary_r == NULL) - return -1; - -@@ -264,7 +291,7 @@ boundary_line_find(struct message_parser - static int parse_next_mime_header_init(struct message_parser_ctx *ctx, - struct message_block *block_r) - { -- ctx->part = message_part_append(ctx->part_pool, ctx->part); -+ message_part_append(ctx); - ctx->part->flags |= MESSAGE_PART_FLAG_IS_MIME; - - return parse_next_header_init(ctx, block_r); -@@ -313,26 +340,25 @@ static int parse_part_finish(struct mess - struct message_boundary *boundary, - struct message_block *block_r, bool first_line) - { -- struct message_part *part; - size_t line_size; -+ size_t boundary_len = boundary->len; -+ bool boundary_epilogue_found = boundary->epilogue_found; - - i_assert(ctx->last_boundary == NULL); - - /* get back to parent MIME part, summing the child MIME part sizes - into parent's body sizes */ -- for (part = ctx->part; part != boundary->part; part = part->parent) { -- message_size_add(&part->parent->body_size, &part->body_size); -- message_size_add(&part->parent->body_size, &part->header_size); -+ while (ctx->part != boundary->part) { -+ message_part_finish(ctx); -+ i_assert(ctx->part != NULL); - } -- i_assert(part != NULL); -- ctx->part = part; - - if (boundary->epilogue_found) { - /* this boundary isn't needed anymore */ -- ctx->boundaries = boundary->next; -+ boundary_remove_until(ctx, boundary->next); - } else { - /* forget about the boundaries we possibly skipped */ -- ctx->boundaries = boundary; -+ boundary_remove_until(ctx, boundary); - } - - /* the boundary itself should already be in buffer. add that. */ -@@ -349,7 +375,7 @@ static int parse_part_finish(struct mess - i_assert(block_r->data[0] == '\n'); - line_size = 1; - } -- line_size += 2 + boundary->len + (boundary->epilogue_found ? 2 : 0); -+ line_size += 2 + boundary_len + (boundary_epilogue_found ? 2 : 0); - i_assert(block_r->size >= ctx->skip + line_size); - block_r->size = line_size; - parse_body_add_block(ctx, block_r); -@@ -510,8 +536,10 @@ static void parse_content_type(struct me - rfc2231_parse(&parser, &results); - for (; *results != NULL; results += 2) { - if (strcasecmp(results[0], "boundary") == 0) { -+ /* truncate excessively long boundaries */ -+ i_free(ctx->last_boundary); - ctx->last_boundary = -- p_strdup(ctx->parser_pool, results[1]); -+ i_strndup(results[1], BOUNDARY_STRING_MAX_LEN); - break; - } - } -@@ -533,6 +561,11 @@ static bool block_is_at_eoh(const struct - return FALSE; - } - -+static bool parse_too_many_nested_mime_parts(struct message_parser_ctx *ctx) -+{ -+ return ctx->nested_parts_count+1 >= ctx->max_nested_mime_parts; -+} -+ - #define MUTEX_FLAGS \ - (MESSAGE_PART_FLAG_MESSAGE_RFC822 | MESSAGE_PART_FLAG_MULTIPART) - -@@ -557,8 +590,12 @@ static int parse_next_header(struct mess - "\n--boundary" belongs to us or to a previous boundary. - this is a problem if the boundary prefixes are identical, - because MIME requires only the prefix to match. */ -- parse_next_body_multipart_init(ctx); -- ctx->multipart = TRUE; -+ if (!parse_too_many_nested_mime_parts(ctx)) { -+ parse_next_body_multipart_init(ctx); -+ ctx->multipart = TRUE; -+ } else { -+ part->flags &= ~MESSAGE_PART_FLAG_MULTIPART; -+ } - } - - /* before parsing the header see if we can find a --boundary from here. -@@ -634,7 +671,7 @@ static int parse_next_header(struct mess - i_assert(!ctx->multipart); - part->flags = 0; - } -- ctx->last_boundary = NULL; -+ i_free(ctx->last_boundary); - - if (!ctx->part_seen_content_type || - (part->flags & MESSAGE_PART_FLAG_IS_MIME) == 0) { -@@ -662,12 +699,16 @@ static int parse_next_header(struct mess - i_assert(ctx->last_boundary == NULL); - ctx->multipart = FALSE; - ctx->parse_next_block = parse_next_body_to_boundary; -- } else if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0) -+ } else if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0 && -+ !parse_too_many_nested_mime_parts(ctx)) { - ctx->parse_next_block = parse_next_body_message_rfc822_init; -- else if (ctx->boundaries != NULL) -- ctx->parse_next_block = parse_next_body_to_boundary; -- else -- ctx->parse_next_block = parse_next_body_to_eof; -+ } else { -+ part->flags &= ~MESSAGE_PART_FLAG_MESSAGE_RFC822; -+ if (ctx->boundaries != NULL) -+ ctx->parse_next_block = parse_next_body_to_boundary; -+ else -+ ctx->parse_next_block = parse_next_body_to_eof; -+ } - - ctx->want_count = 1; - -@@ -692,358 +733,21 @@ static int parse_next_header_init(struct - return parse_next_header(ctx, block_r); - } - --static int preparsed_parse_eof(struct message_parser_ctx *ctx ATTR_UNUSED, -- struct message_block *block_r ATTR_UNUSED) --{ -- return -1; --} -- --static void preparsed_skip_to_next(struct message_parser_ctx *ctx) --{ -- ctx->parse_next_block = preparsed_parse_next_header_init; -- while (ctx->part != NULL) { -- if (ctx->part->next != NULL) { -- ctx->part = ctx->part->next; -- break; -- } -- -- /* parse epilogue of multipart parent if requested */ -- if (ctx->part->parent != NULL && -- (ctx->part->parent->flags & MESSAGE_PART_FLAG_MULTIPART) != 0 && -- (ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS) != 0) { -- /* check for presence of epilogue */ -- uoff_t part_end = ctx->part->physical_pos + -- ctx->part->header_size.physical_size + -- ctx->part->body_size.physical_size; -- uoff_t parent_end = ctx->part->parent->physical_pos + -- ctx->part->parent->header_size.physical_size + -- ctx->part->parent->body_size.physical_size; -- -- if (parent_end > part_end) { -- ctx->parse_next_block = preparsed_parse_epilogue_init; -- break; -- } -- } -- ctx->part = ctx->part->parent; -- } -- if (ctx->part == NULL) -- ctx->parse_next_block = preparsed_parse_eof; --} -- --static int preparsed_parse_body_finish(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- i_stream_skip(ctx->input, ctx->skip); -- ctx->skip = 0; -- -- preparsed_skip_to_next(ctx); -- return ctx->parse_next_block(ctx, block_r); --} -- --static int preparsed_parse_prologue_finish(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- i_stream_skip(ctx->input, ctx->skip); -- ctx->skip = 0; -- -- ctx->parse_next_block = preparsed_parse_next_header_init; -- ctx->part = ctx->part->children; -- return ctx->parse_next_block(ctx, block_r); --} -- --static int preparsed_parse_body_more(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t end_offset = ctx->part->physical_pos + -- ctx->part->header_size.physical_size + -- ctx->part->body_size.physical_size; -- bool full; -- int ret; -- -- if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -- return ret; -- -- if (ctx->input->v_offset + block_r->size >= end_offset) { -- block_r->size = end_offset - ctx->input->v_offset; -- ctx->parse_next_block = preparsed_parse_body_finish; -- } -- ctx->skip = block_r->size; -- return 1; --} -- --static int preparsed_parse_prologue_more(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t boundary_min_start, end_offset; -- const unsigned char *cur; -- bool full; -- int ret; -- -- i_assert(ctx->part->children != NULL); -- end_offset = ctx->part->children->physical_pos; -- -- if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -- return ret; -- -- if (ctx->input->v_offset + block_r->size >= end_offset) { -- /* we've got the full prologue: clip off the initial boundary */ -- block_r->size = end_offset - ctx->input->v_offset; -- cur = block_r->data + block_r->size - 1; -- -- /* [\r]\n--boundary[\r]\n */ -- if (block_r->size < 5 || *cur != '\n') { -- ctx->broken_reason = "Prologue boundary end not at expected position"; -- return -1; -- } -- -- cur--; -- if (*cur == '\r') cur--; -- -- /* find newline just before boundary */ -- for (; cur >= block_r->data; cur--) { -- if (*cur == '\n') break; -- } -- -- if (cur[0] != '\n' || cur[1] != '-' || cur[2] != '-') { -- ctx->broken_reason = "Prologue boundary beginning not at expected position"; -- return -1; -- } -- -- if (cur != block_r->data && cur[-1] == '\r') cur--; -- -- /* clip boundary */ -- block_r->size = cur - block_r->data; -- -- ctx->parse_next_block = preparsed_parse_prologue_finish; -- ctx->skip = block_r->size; -- return 1; -- } -- -- /* retain enough data in the stream buffer to contain initial boundary */ -- if (end_offset > BOUNDARY_END_MAX_LEN) -- boundary_min_start = end_offset - BOUNDARY_END_MAX_LEN; -- else -- boundary_min_start = 0; -- -- if (ctx->input->v_offset + block_r->size >= boundary_min_start) { -- if (boundary_min_start <= ctx->input->v_offset) -- return 0; -- block_r->size = boundary_min_start - ctx->input->v_offset; -- } -- ctx->skip = block_r->size; -- return 1; --} -- --static int preparsed_parse_epilogue_more(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t end_offset = ctx->part->physical_pos + -- ctx->part->header_size.physical_size + -- ctx->part->body_size.physical_size; -- bool full; -- int ret; -- -- if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -- return ret; -- -- if (ctx->input->v_offset + block_r->size >= end_offset) { -- block_r->size = end_offset - ctx->input->v_offset; -- ctx->parse_next_block = preparsed_parse_body_finish; -- } -- ctx->skip = block_r->size; -- return 1; --} -- --static int preparsed_parse_epilogue_boundary(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t end_offset = ctx->part->physical_pos + -- ctx->part->header_size.physical_size + -- ctx->part->body_size.physical_size; -- const unsigned char *data, *cur; -- size_t size; -- bool full; -- int ret; -- -- if (end_offset - ctx->input->v_offset < 7) { -- ctx->broken_reason = "Epilogue position is wrong"; -- return -1; -- } -- -- if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -- return ret; -- -- /* [\r]\n--boundary--[\r]\n */ -- if (block_r->size < 7) { -- ctx->want_count = 7; -- return 0; -- } -- -- data = block_r->data; -- size = block_r->size; -- cur = data; -- -- if (*cur == '\r') cur++; -- -- if (cur[0] != '\n' || cur[1] != '-' || data[2] != '-') { -- ctx->broken_reason = "Epilogue boundary start not at expected position"; -- return -1; -- } -- -- /* find the end of the line */ -- cur += 3; -- if ((cur = memchr(cur, '\n', size - (cur-data))) == NULL) { -- if (end_offset < ctx->input->v_offset + size) { -- ctx->broken_reason = "Epilogue boundary end not at expected position"; -- return -1; -- } else if (ctx->input->v_offset + size < end_offset && -- size < BOUNDARY_END_MAX_LEN && -- !ctx->input->eof && !full) { -- ctx->want_count = BOUNDARY_END_MAX_LEN; -- return 0; -- } -- } -- -- block_r->size = 0; -- ctx->parse_next_block = preparsed_parse_epilogue_more; -- ctx->skip = cur - data + 1; -- return 0; --} -- --static int preparsed_parse_body_init(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t offset = ctx->part->physical_pos + -- ctx->part->header_size.physical_size; -- -- if (offset < ctx->input->v_offset) { -- /* header was actually larger than the cached size suggested */ -- ctx->broken_reason = "Header larger than its cached size"; -- return -1; -- } -- i_stream_skip(ctx->input, offset - ctx->input->v_offset); -- -- /* multipart messages may begin with --boundary--, which makes them -- not have any children. */ -- if ((ctx->part->flags & MESSAGE_PART_FLAG_MULTIPART) == 0 || -- ctx->part->children == NULL) -- ctx->parse_next_block = preparsed_parse_body_more; -- else -- ctx->parse_next_block = preparsed_parse_prologue_more; -- return ctx->parse_next_block(ctx, block_r); --} -- --static int preparsed_parse_epilogue_init(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- uoff_t offset = ctx->part->physical_pos + -- ctx->part->header_size.physical_size + -- ctx->part->body_size.physical_size; -- -- ctx->part = ctx->part->parent; -- -- if (offset < ctx->input->v_offset) { -- /* last child was actually larger than the cached size -- suggested */ -- ctx->broken_reason = "Part larger than its cached size"; -- return -1; -- } -- i_stream_skip(ctx->input, offset - ctx->input->v_offset); -- -- ctx->parse_next_block = preparsed_parse_epilogue_boundary; -- return ctx->parse_next_block(ctx, block_r); --} -- --static int preparsed_parse_finish_header(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- if (ctx->part->children != NULL) { -- if ((ctx->part->flags & MESSAGE_PART_FLAG_MULTIPART) != 0 && -- (ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS) != 0) -- ctx->parse_next_block = preparsed_parse_body_init; -- else { -- ctx->parse_next_block = preparsed_parse_next_header_init; -- ctx->part = ctx->part->children; -- } -- } else if ((ctx->flags & MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK) == 0) { -- ctx->parse_next_block = preparsed_parse_body_init; -- } else { -- preparsed_skip_to_next(ctx); -- } -- return ctx->parse_next_block(ctx, block_r); --} -- --static int preparsed_parse_next_header(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- struct message_header_line *hdr; -- int ret; -- -- ret = message_parse_header_next(ctx->hdr_parser_ctx, &hdr); -- if (ret == 0 || (ret < 0 && ctx->input->stream_errno != 0)) { -- ctx->want_count = i_stream_get_data_size(ctx->input) + 1; -- return ret; -- } -- -- if (hdr != NULL) { -- block_r->hdr = hdr; -- block_r->size = 0; -- return 1; -- } -- message_parse_header_deinit(&ctx->hdr_parser_ctx); -- -- ctx->parse_next_block = preparsed_parse_finish_header; -- -- /* return empty block as end of headers */ -- block_r->hdr = NULL; -- block_r->size = 0; -- -- i_assert(ctx->skip == 0); -- if (ctx->input->v_offset != ctx->part->physical_pos + -- ctx->part->header_size.physical_size) { -- ctx->broken_reason = "Cached header size mismatch"; -- return -1; -- } -- return 1; --} -- --static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx, -- struct message_block *block_r) --{ -- struct istream *hdr_input; -- -- i_assert(ctx->hdr_parser_ctx == NULL); -- -- i_assert(ctx->part->physical_pos >= ctx->input->v_offset); -- i_stream_skip(ctx->input, ctx->part->physical_pos - -- ctx->input->v_offset); -- -- /* the header may become truncated by --boundaries. limit the header -- stream's size to what it's supposed to be to avoid duplicating (and -- keeping in sync!) all the same complicated logic as in -- parse_next_header(). */ -- hdr_input = i_stream_create_limit(ctx->input, ctx->part->header_size.physical_size); -- ctx->hdr_parser_ctx = -- message_parse_header_init(hdr_input, NULL, ctx->hdr_flags); -- i_stream_unref(&hdr_input); -- -- ctx->parse_next_block = preparsed_parse_next_header; -- return preparsed_parse_next_header(ctx, block_r); --} -- --static struct message_parser_ctx * -+struct message_parser_ctx * - message_parser_init_int(struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags) -+ const struct message_parser_settings *set) - { - struct message_parser_ctx *ctx; -- pool_t pool; - -- pool = pool_alloconly_create("Message Parser", 1024); -- ctx = p_new(pool, struct message_parser_ctx, 1); -- ctx->parser_pool = pool; -- ctx->hdr_flags = hdr_flags; -- ctx->flags = flags; -+ ctx = i_new(struct message_parser_ctx, 1); -+ ctx->hdr_flags = set->hdr_flags; -+ ctx->flags = set->flags; -+ ctx->max_nested_mime_parts = set->max_nested_mime_parts != 0 ? -+ set->max_nested_mime_parts : -+ MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS; -+ ctx->max_total_mime_parts = set->max_total_mime_parts != 0 ? -+ set->max_total_mime_parts : -+ MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS; - ctx->input = input; - i_stream_ref(input); - return ctx; -@@ -1051,32 +755,17 @@ message_parser_init_int(struct istream * - - struct message_parser_ctx * - message_parser_init(pool_t part_pool, struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags) -+ const struct message_parser_settings *set) - { - struct message_parser_ctx *ctx; - -- ctx = message_parser_init_int(input, hdr_flags, flags); -+ ctx = message_parser_init_int(input, set); - ctx->part_pool = part_pool; - ctx->parts = ctx->part = p_new(part_pool, struct message_part, 1); -+ ctx->next_part = &ctx->part->children; - ctx->parse_next_block = parse_next_header_init; -- return ctx; --} -- --struct message_parser_ctx * --message_parser_init_from_parts(struct message_part *parts, -- struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags) --{ -- struct message_parser_ctx *ctx; -- -- i_assert(parts != NULL); -- -- ctx = message_parser_init_int(input, hdr_flags, flags); -- ctx->preparsed = TRUE; -- ctx->parts = ctx->part = parts; -- ctx->parse_next_block = preparsed_parse_next_header_init; -+ ctx->total_parts_count = 1; -+ i_array_init(&ctx->next_part_stack, 4); - return ctx; - } - -@@ -1103,8 +792,15 @@ int message_parser_deinit_from_parts(str - - if (ctx->hdr_parser_ctx != NULL) - message_parse_header_deinit(&ctx->hdr_parser_ctx); -+ boundary_remove_until(ctx, NULL); -+ /* caller might have stopped the parsing early */ -+ i_assert(ctx->nested_parts_count == 0 || -+ i_stream_have_bytes_left(ctx->input)); -+ - i_stream_unref(&ctx->input); -- pool_unref(&ctx->parser_pool); -+ array_free(&ctx->next_part_stack); -+ i_free(ctx->last_boundary); -+ i_free(ctx); - i_assert(ret < 0 || *parts_r != NULL); - return ret; - } -@@ -1136,13 +832,8 @@ int message_parser_parse_next_block(stru - i_assert(ctx->input->eof || ctx->input->closed || - ctx->input->stream_errno != 0 || - ctx->broken_reason != NULL); -- while (ctx->part->parent != NULL) { -- message_size_add(&ctx->part->parent->body_size, -- &ctx->part->body_size); -- message_size_add(&ctx->part->parent->body_size, -- &ctx->part->header_size); -- ctx->part = ctx->part->parent; -- } -+ while (ctx->part->parent != NULL) -+ message_part_finish(ctx); - } - - if (block_r->size == 0) { -diff -up dovecot-2.3.8/src/lib-mail/message-parser-from-parts.c.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/message-parser-from-parts.c ---- dovecot-2.3.8/src/lib-mail/message-parser-from-parts.c.CVE_2020_12100 2020-08-07 12:29:39.972827528 +0200 -+++ dovecot-2.3.8/src/lib-mail/message-parser-from-parts.c 2020-08-07 12:29:39.975827486 +0200 -@@ -0,0 +1,365 @@ -+/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ -+ -+#include "lib.h" -+#include "istream.h" -+#include "message-parser-private.h" -+ -+static int preparsed_parse_epilogue_init(struct message_parser_ctx *ctx, -+ struct message_block *block_r); -+static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx, -+ struct message_block *block_r); -+ -+static int preparsed_parse_eof(struct message_parser_ctx *ctx ATTR_UNUSED, -+ struct message_block *block_r ATTR_UNUSED) -+{ -+ return -1; -+} -+ -+static void preparsed_skip_to_next(struct message_parser_ctx *ctx) -+{ -+ ctx->parse_next_block = preparsed_parse_next_header_init; -+ while (ctx->part != NULL) { -+ if (ctx->part->next != NULL) { -+ ctx->part = ctx->part->next; -+ break; -+ } -+ -+ /* parse epilogue of multipart parent if requested */ -+ if (ctx->part->parent != NULL && -+ (ctx->part->parent->flags & MESSAGE_PART_FLAG_MULTIPART) != 0 && -+ (ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS) != 0) { -+ /* check for presence of epilogue */ -+ uoff_t part_end = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size + -+ ctx->part->body_size.physical_size; -+ uoff_t parent_end = ctx->part->parent->physical_pos + -+ ctx->part->parent->header_size.physical_size + -+ ctx->part->parent->body_size.physical_size; -+ -+ if (parent_end > part_end) { -+ ctx->parse_next_block = preparsed_parse_epilogue_init; -+ break; -+ } -+ } -+ ctx->part = ctx->part->parent; -+ } -+ if (ctx->part == NULL) -+ ctx->parse_next_block = preparsed_parse_eof; -+} -+ -+static int preparsed_parse_body_finish(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ i_stream_skip(ctx->input, ctx->skip); -+ ctx->skip = 0; -+ -+ preparsed_skip_to_next(ctx); -+ return ctx->parse_next_block(ctx, block_r); -+} -+ -+static int preparsed_parse_prologue_finish(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ i_stream_skip(ctx->input, ctx->skip); -+ ctx->skip = 0; -+ -+ ctx->parse_next_block = preparsed_parse_next_header_init; -+ ctx->part = ctx->part->children; -+ return ctx->parse_next_block(ctx, block_r); -+} -+ -+static int preparsed_parse_body_more(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t end_offset = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size + -+ ctx->part->body_size.physical_size; -+ bool full; -+ int ret; -+ -+ if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -+ return ret; -+ -+ if (ctx->input->v_offset + block_r->size >= end_offset) { -+ block_r->size = end_offset - ctx->input->v_offset; -+ ctx->parse_next_block = preparsed_parse_body_finish; -+ } -+ ctx->skip = block_r->size; -+ return 1; -+} -+ -+static int preparsed_parse_prologue_more(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t boundary_min_start, end_offset; -+ const unsigned char *cur; -+ bool full; -+ int ret; -+ -+ i_assert(ctx->part->children != NULL); -+ end_offset = ctx->part->children->physical_pos; -+ -+ if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -+ return ret; -+ -+ if (ctx->input->v_offset + block_r->size >= end_offset) { -+ /* we've got the full prologue: clip off the initial boundary */ -+ block_r->size = end_offset - ctx->input->v_offset; -+ cur = block_r->data + block_r->size - 1; -+ -+ /* [\r]\n--boundary[\r]\n */ -+ if (block_r->size < 5 || *cur != '\n') { -+ ctx->broken_reason = "Prologue boundary end not at expected position"; -+ return -1; -+ } -+ -+ cur--; -+ if (*cur == '\r') cur--; -+ -+ /* find newline just before boundary */ -+ for (; cur >= block_r->data; cur--) { -+ if (*cur == '\n') break; -+ } -+ -+ if (cur[0] != '\n' || cur[1] != '-' || cur[2] != '-') { -+ ctx->broken_reason = "Prologue boundary beginning not at expected position"; -+ return -1; -+ } -+ -+ if (cur != block_r->data && cur[-1] == '\r') cur--; -+ -+ /* clip boundary */ -+ block_r->size = cur - block_r->data; -+ -+ ctx->parse_next_block = preparsed_parse_prologue_finish; -+ ctx->skip = block_r->size; -+ return 1; -+ } -+ -+ /* retain enough data in the stream buffer to contain initial boundary */ -+ if (end_offset > BOUNDARY_END_MAX_LEN) -+ boundary_min_start = end_offset - BOUNDARY_END_MAX_LEN; -+ else -+ boundary_min_start = 0; -+ -+ if (ctx->input->v_offset + block_r->size >= boundary_min_start) { -+ if (boundary_min_start <= ctx->input->v_offset) -+ return 0; -+ block_r->size = boundary_min_start - ctx->input->v_offset; -+ } -+ ctx->skip = block_r->size; -+ return 1; -+} -+ -+static int preparsed_parse_epilogue_more(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t end_offset = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size + -+ ctx->part->body_size.physical_size; -+ bool full; -+ int ret; -+ -+ if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -+ return ret; -+ -+ if (ctx->input->v_offset + block_r->size >= end_offset) { -+ block_r->size = end_offset - ctx->input->v_offset; -+ ctx->parse_next_block = preparsed_parse_body_finish; -+ } -+ ctx->skip = block_r->size; -+ return 1; -+} -+ -+static int preparsed_parse_epilogue_boundary(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t end_offset = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size + -+ ctx->part->body_size.physical_size; -+ const unsigned char *data, *cur; -+ size_t size; -+ bool full; -+ int ret; -+ -+ if (end_offset - ctx->input->v_offset < 7) { -+ ctx->broken_reason = "Epilogue position is wrong"; -+ return -1; -+ } -+ -+ if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0) -+ return ret; -+ -+ /* [\r]\n--boundary--[\r]\n */ -+ if (block_r->size < 7) { -+ ctx->want_count = 7; -+ return 0; -+ } -+ -+ data = block_r->data; -+ size = block_r->size; -+ cur = data; -+ -+ if (*cur == '\r') cur++; -+ -+ if (cur[0] != '\n' || cur[1] != '-' || data[2] != '-') { -+ ctx->broken_reason = "Epilogue boundary start not at expected position"; -+ return -1; -+ } -+ -+ /* find the end of the line */ -+ cur += 3; -+ if ((cur = memchr(cur, '\n', size - (cur-data))) == NULL) { -+ if (end_offset < ctx->input->v_offset + size) { -+ ctx->broken_reason = "Epilogue boundary end not at expected position"; -+ return -1; -+ } else if (ctx->input->v_offset + size < end_offset && -+ size < BOUNDARY_END_MAX_LEN && -+ !ctx->input->eof && !full) { -+ ctx->want_count = BOUNDARY_END_MAX_LEN; -+ return 0; -+ } -+ } -+ -+ block_r->size = 0; -+ ctx->parse_next_block = preparsed_parse_epilogue_more; -+ ctx->skip = cur - data + 1; -+ return 0; -+} -+ -+static int preparsed_parse_body_init(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t offset = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size; -+ -+ if (offset < ctx->input->v_offset) { -+ /* header was actually larger than the cached size suggested */ -+ ctx->broken_reason = "Header larger than its cached size"; -+ return -1; -+ } -+ i_stream_skip(ctx->input, offset - ctx->input->v_offset); -+ -+ /* multipart messages may begin with --boundary--, which makes them -+ not have any children. */ -+ if ((ctx->part->flags & MESSAGE_PART_FLAG_MULTIPART) == 0 || -+ ctx->part->children == NULL) -+ ctx->parse_next_block = preparsed_parse_body_more; -+ else -+ ctx->parse_next_block = preparsed_parse_prologue_more; -+ return ctx->parse_next_block(ctx, block_r); -+} -+ -+static int preparsed_parse_epilogue_init(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ uoff_t offset = ctx->part->physical_pos + -+ ctx->part->header_size.physical_size + -+ ctx->part->body_size.physical_size; -+ -+ ctx->part = ctx->part->parent; -+ -+ if (offset < ctx->input->v_offset) { -+ /* last child was actually larger than the cached size -+ suggested */ -+ ctx->broken_reason = "Part larger than its cached size"; -+ return -1; -+ } -+ i_stream_skip(ctx->input, offset - ctx->input->v_offset); -+ -+ ctx->parse_next_block = preparsed_parse_epilogue_boundary; -+ return ctx->parse_next_block(ctx, block_r); -+} -+ -+static int preparsed_parse_finish_header(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ if (ctx->part->children != NULL) { -+ if ((ctx->part->flags & MESSAGE_PART_FLAG_MULTIPART) != 0 && -+ (ctx->flags & MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS) != 0) -+ ctx->parse_next_block = preparsed_parse_body_init; -+ else { -+ ctx->parse_next_block = preparsed_parse_next_header_init; -+ ctx->part = ctx->part->children; -+ } -+ } else if ((ctx->flags & MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK) == 0) { -+ ctx->parse_next_block = preparsed_parse_body_init; -+ } else { -+ preparsed_skip_to_next(ctx); -+ } -+ return ctx->parse_next_block(ctx, block_r); -+} -+ -+static int preparsed_parse_next_header(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ struct message_header_line *hdr; -+ int ret; -+ -+ ret = message_parse_header_next(ctx->hdr_parser_ctx, &hdr); -+ if (ret == 0 || (ret < 0 && ctx->input->stream_errno != 0)) { -+ ctx->want_count = i_stream_get_data_size(ctx->input) + 1; -+ return ret; -+ } -+ -+ if (hdr != NULL) { -+ block_r->hdr = hdr; -+ block_r->size = 0; -+ return 1; -+ } -+ message_parse_header_deinit(&ctx->hdr_parser_ctx); -+ -+ ctx->parse_next_block = preparsed_parse_finish_header; -+ -+ /* return empty block as end of headers */ -+ block_r->hdr = NULL; -+ block_r->size = 0; -+ -+ i_assert(ctx->skip == 0); -+ if (ctx->input->v_offset != ctx->part->physical_pos + -+ ctx->part->header_size.physical_size) { -+ ctx->broken_reason = "Cached header size mismatch"; -+ return -1; -+ } -+ return 1; -+} -+ -+static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx, -+ struct message_block *block_r) -+{ -+ struct istream *hdr_input; -+ -+ i_assert(ctx->hdr_parser_ctx == NULL); -+ -+ i_assert(ctx->part->physical_pos >= ctx->input->v_offset); -+ i_stream_skip(ctx->input, ctx->part->physical_pos - -+ ctx->input->v_offset); -+ -+ /* the header may become truncated by --boundaries. limit the header -+ stream's size to what it's supposed to be to avoid duplicating (and -+ keeping in sync!) all the same complicated logic as in -+ parse_next_header(). */ -+ hdr_input = i_stream_create_limit(ctx->input, ctx->part->header_size.physical_size); -+ ctx->hdr_parser_ctx = -+ message_parse_header_init(hdr_input, NULL, ctx->hdr_flags); -+ i_stream_unref(&hdr_input); -+ -+ ctx->parse_next_block = preparsed_parse_next_header; -+ return preparsed_parse_next_header(ctx, block_r); -+} -+ -+struct message_parser_ctx * -+message_parser_init_from_parts(struct message_part *parts, -+ struct istream *input, -+ const struct message_parser_settings *set) -+{ -+ struct message_parser_ctx *ctx; -+ -+ i_assert(parts != NULL); -+ -+ ctx = message_parser_init_int(input, set); -+ ctx->preparsed = TRUE; -+ ctx->parts = ctx->part = parts; -+ ctx->parse_next_block = preparsed_parse_next_header_init; -+ return ctx; -+} -diff -up dovecot-2.3.8/src/lib-mail/message-parser.h.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/message-parser.h ---- dovecot-2.3.8/src/lib-mail/message-parser.h.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-mail/message-parser.h 2020-08-07 12:29:39.978827444 +0200 -@@ -17,6 +17,21 @@ enum message_parser_flags { - MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES = 0x08 - }; - -+#define MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS 100 -+#define MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS 10000 -+ -+struct message_parser_settings { -+ enum message_header_parser_flags hdr_flags; -+ enum message_parser_flags flags; -+ -+ /* Maximum nested MIME parts. -+ 0 = MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS. */ -+ unsigned int max_nested_mime_parts; -+ /* Maximum MIME parts in total. -+ 0 = MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS. */ -+ unsigned int max_total_mime_parts; -+}; -+ - struct message_parser_ctx; - - struct message_block { -@@ -45,8 +60,7 @@ extern message_part_header_callback_t *n - are allocated from. */ - struct message_parser_ctx * - message_parser_init(pool_t part_pool, struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags); -+ const struct message_parser_settings *set); - /* Deinitialize message parser. The ctx must NOT have been created by - message_parser_init_from_parts(). */ - void message_parser_deinit(struct message_parser_ctx **ctx, -@@ -55,8 +69,7 @@ void message_parser_deinit(struct messag - struct message_parser_ctx * - message_parser_init_from_parts(struct message_part *parts, - struct istream *input, -- enum message_header_parser_flags hdr_flags, -- enum message_parser_flags flags); -+ const struct message_parser_settings *set); - /* Same as message_parser_deinit(), but return an error message describing - why the preparsed parts didn't match the message. This can also safely be - called even when preparsed parts weren't used - it'll always just return -diff -up dovecot-2.3.8/src/lib-mail/message-parser-private.h.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/message-parser-private.h ---- dovecot-2.3.8/src/lib-mail/message-parser-private.h.CVE_2020_12100 2020-08-07 12:29:39.972827528 +0200 -+++ dovecot-2.3.8/src/lib-mail/message-parser-private.h 2020-08-07 12:29:39.978827444 +0200 -@@ -0,0 +1,62 @@ -+#ifndef MESSAGE_PARSER_PRIVATE_H -+#define MESSAGE_PARSER_PRIVATE_H -+ -+#include "message-parser.h" -+ -+/* RFC-2046 requires boundaries are max. 70 chars + "--" prefix + "--" suffix. -+ We'll add a bit more just in case. */ -+#define BOUNDARY_STRING_MAX_LEN (70 + 10) -+#define BOUNDARY_END_MAX_LEN (BOUNDARY_STRING_MAX_LEN + 2 + 2) -+ -+struct message_boundary { -+ struct message_boundary *next; -+ -+ struct message_part *part; -+ char *boundary; -+ size_t len; -+ -+ bool epilogue_found:1; -+}; -+ -+struct message_parser_ctx { -+ pool_t part_pool; -+ struct istream *input; -+ struct message_part *parts, *part; -+ const char *broken_reason; -+ unsigned int nested_parts_count; -+ unsigned int total_parts_count; -+ -+ enum message_header_parser_flags hdr_flags; -+ enum message_parser_flags flags; -+ unsigned int max_nested_mime_parts; -+ unsigned int max_total_mime_parts; -+ -+ char *last_boundary; -+ struct message_boundary *boundaries; -+ -+ struct message_part **next_part; -+ ARRAY(struct message_part **) next_part_stack; -+ -+ size_t skip; -+ char last_chr; -+ unsigned int want_count; -+ -+ struct message_header_parser_ctx *hdr_parser_ctx; -+ unsigned int prev_hdr_newline_size; -+ -+ int (*parse_next_block)(struct message_parser_ctx *ctx, -+ struct message_block *block_r); -+ -+ bool part_seen_content_type:1; -+ bool multipart:1; -+ bool preparsed:1; -+ bool eof:1; -+}; -+ -+struct message_parser_ctx * -+message_parser_init_int(struct istream *input, -+ const struct message_parser_settings *set); -+int message_parser_read_more(struct message_parser_ctx *ctx, -+ struct message_block *block_r, bool *full_r); -+ -+#endif -diff -up dovecot-2.3.8/src/lib-mail/message-search.c.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/message-search.c ---- dovecot-2.3.8/src/lib-mail/message-search.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-mail/message-search.c 2020-08-07 12:29:39.976827472 +0200 -@@ -196,8 +196,9 @@ message_search_msg_real(struct message_s - struct istream *input, struct message_part *parts, - const char **error_r) - { -- const enum message_header_parser_flags hdr_parser_flags = -- MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE; -+ const struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE, -+ }; - struct message_parser_ctx *parser_ctx; - struct message_block raw_block; - struct message_part *new_parts; -@@ -207,10 +208,10 @@ message_search_msg_real(struct message_s - - if (parts != NULL) { - parser_ctx = message_parser_init_from_parts(parts, -- input, hdr_parser_flags, 0); -+ input, &parser_set); - } else { - parser_ctx = message_parser_init(pool_datastack_create(), -- input, hdr_parser_flags, 0); -+ input, &parser_set); - } - - while ((ret = message_parser_parse_next_block(parser_ctx, -diff -up dovecot-2.3.8/src/lib-mail/message-snippet.c.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/message-snippet.c ---- dovecot-2.3.8/src/lib-mail/message-snippet.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-mail/message-snippet.c 2020-08-07 12:30:01.710525318 +0200 -@@ -99,6 +99,7 @@ int message_snippet_generate(struct istr - unsigned int max_snippet_chars, - string_t *snippet) - { -+ const struct message_parser_settings parser_set = { .flags = 0 }; - struct message_parser_ctx *parser; - struct message_part *parts; - struct message_decoder_context *decoder; -@@ -112,7 +113,7 @@ int message_snippet_generate(struct istr - ctx.snippet = snippet; - ctx.chars_left = max_snippet_chars; - -- parser = message_parser_init(pool_datastack_create(), input, 0, 0); -+ parser = message_parser_init(pool_datastack_create(), input, &parser_set); - decoder = message_decoder_init(NULL, 0); - while ((ret = message_parser_parse_next_block(parser, &raw_block)) > 0) { - if (!message_decoder_decode_next_block(decoder, &raw_block, &block)) -diff -up dovecot-2.3.8/src/lib-mail/test-message-decoder.c.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/test-message-decoder.c ---- dovecot-2.3.8/src/lib-mail/test-message-decoder.c.CVE_2020_12100 2020-08-07 12:29:39.970827555 +0200 -+++ dovecot-2.3.8/src/lib-mail/test-message-decoder.c 2020-08-07 12:29:39.976827472 +0200 -@@ -105,6 +105,7 @@ static void test_message_decoder_multipa - "\n" - "?garbage\n" - "--foo--\n"; -+ const struct message_parser_settings parser_set = { .flags = 0, }; - struct message_parser_ctx *parser; - struct message_decoder_context *decoder; - struct message_part *parts; -@@ -116,7 +117,8 @@ static void test_message_decoder_multipa - test_begin("message decoder multipart"); - - istream = test_istream_create(test_message_input); -- parser = message_parser_init(pool_datastack_create(), istream, 0, 0); -+ parser = message_parser_init(pool_datastack_create(), istream, -+ &parser_set); - decoder = message_decoder_init(NULL, 0); - - test_istream_set_allow_eof(istream, FALSE); -diff -up dovecot-2.3.8/src/lib-mail/test-message-parser.c.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/test-message-parser.c ---- dovecot-2.3.8/src/lib-mail/test-message-parser.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-mail/test-message-parser.c 2020-08-07 12:29:39.979827431 +0200 -@@ -39,6 +39,8 @@ static const char test_msg[] = - "\n"; - #define TEST_MSG_LEN (sizeof(test_msg)-1) - -+static const struct message_parser_settings set_empty = { .flags = 0 }; -+ - static bool msg_parts_cmp(struct message_part *p1, struct message_part *p2) - { - while (p1 != NULL || p2 != NULL) { -@@ -59,6 +61,7 @@ static bool msg_parts_cmp(struct message - p1->body_size.physical_size != p2->body_size.physical_size || - p1->body_size.virtual_size != p2->body_size.virtual_size || - p1->body_size.lines != p2->body_size.lines || -+ p1->children_count != p2->children_count || - p1->flags != p2->flags) - return FALSE; - -@@ -70,6 +73,9 @@ static bool msg_parts_cmp(struct message - - static void test_parsed_parts(struct istream *input, struct message_part *parts) - { -+ const struct message_parser_settings parser_set = { -+ .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, -+ }; - struct message_parser_ctx *parser; - struct message_block block; - struct message_part *parts2; -@@ -81,8 +87,7 @@ static void test_parsed_parts(struct ist - if (i_stream_get_size(input, TRUE, &input_size) < 0) - i_unreached(); - -- parser = message_parser_init_from_parts(parts, input, 0, -- MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK); -+ parser = message_parser_init_from_parts(parts, input, &parser_set); - for (i = 1; i <= input_size*2+1; i++) { - test_istream_set_size(input, i/2); - if (i > TEST_MSG_LEN*2) -@@ -112,9 +117,11 @@ static void test_message_parser_small_bl - output = t_str_new(128); - - /* full parsing */ -- parser = message_parser_init(pool, input, 0, -- MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -- MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES); -+ const struct message_parser_settings full_parser_set = { -+ .flags = MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | -+ MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES, -+ }; -+ parser = message_parser_init(pool, input, &full_parser_set); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) { - if (block.hdr != NULL) - message_header_line_write(output, block.hdr); -@@ -130,7 +137,7 @@ static void test_message_parser_small_bl - i_stream_seek(input, 0); - test_istream_set_allow_eof(input, FALSE); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - for (i = 1; i <= TEST_MSG_LEN*2+1; i++) { - test_istream_set_size(input, i/2); - if (i > TEST_MSG_LEN*2) -@@ -148,8 +155,11 @@ static void test_message_parser_small_bl - test_istream_set_allow_eof(input, FALSE); - - end_of_headers_idx = (strstr(test_msg, "\n-----") - test_msg); -- parser = message_parser_init_from_parts(parts, input, 0, -- MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK); -+ const struct message_parser_settings preparsed_parser_set = { -+ .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, -+ }; -+ parser = message_parser_init_from_parts(parts, input, -+ &preparsed_parser_set); - for (i = 1; i <= TEST_MSG_LEN*2+1; i++) { - test_istream_set_size(input, i/2); - if (i > TEST_MSG_LEN*2) -@@ -167,6 +177,36 @@ static void test_message_parser_small_bl - test_end(); - } - -+static void test_message_parser_stop_early(void) -+{ -+ struct message_parser_ctx *parser; -+ struct istream *input; -+ struct message_part *parts; -+ struct message_block block; -+ unsigned int i; -+ pool_t pool; -+ int ret; -+ -+ test_begin("message parser in stop early"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(test_msg); -+ -+ test_istream_set_allow_eof(input, FALSE); -+ for (i = 1; i <= TEST_MSG_LEN+1; i++) { -+ i_stream_seek(input, 0); -+ test_istream_set_size(input, i); -+ parser = message_parser_init(pool, input, &set_empty); -+ while ((ret = message_parser_parse_next_block(parser, -+ &block)) > 0) ; -+ test_assert(ret == 0); -+ message_parser_deinit(&parser, &parts); -+ } -+ -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ - static void test_message_parser_truncated_mime_headers(void) - { - static const char input_msg[] = -@@ -191,12 +231,13 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - - test_assert((parts->flags & MESSAGE_PART_FLAG_MULTIPART) != 0); -+ test_assert(parts->children_count == 4); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 48); - test_assert(parts->header_size.virtual_size == 48+2); -@@ -220,6 +261,7 @@ static const char input_msg[] = - test_assert(parts->children->next->next->next->header_size.virtual_size == 23); - test_assert(parts->children->next->next->next->header_size.lines == 0); - for (part = parts->children; part != NULL; part = part->next) { -+ test_assert(part->children_count == 0); - test_assert(part->body_size.physical_size == 0); - test_assert(part->body_size.virtual_size == 0); - } -@@ -254,12 +296,13 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(parts->children_count == 2); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 46); - test_assert(parts->header_size.virtual_size == 46+2); -@@ -267,6 +310,7 @@ static const char input_msg[] = - test_assert(parts->body_size.physical_size == 86); - test_assert(parts->body_size.virtual_size == 86+8); - -+ test_assert(parts->children->children_count == 0); - test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->physical_pos == 51); - test_assert(parts->children->header_size.lines == 1); -@@ -276,6 +320,7 @@ static const char input_msg[] = - test_assert(parts->children->body_size.physical_size == 0); - test_assert(parts->children->children == NULL); - -+ test_assert(parts->children->next->children_count == 0); - test_assert(parts->children->next->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->next->physical_pos == 101); - test_assert(parts->children->next->header_size.lines == 2); -@@ -307,11 +352,12 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - -+ test_assert(parts->children_count == 0); - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->header_size.lines == 1); - test_assert(parts->header_size.physical_size == 45); -@@ -344,11 +390,12 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - -+ test_assert(parts->children_count == 0); - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 46); -@@ -388,11 +435,12 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - -+ test_assert(parts->children_count == 2); - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 45); -@@ -400,6 +448,7 @@ static const char input_msg[] = - test_assert(parts->body_size.lines == 7); - test_assert(parts->body_size.physical_size == 84); - test_assert(parts->body_size.virtual_size == 84+7); -+ test_assert(parts->children->children_count == 1); - test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->physical_pos == 49); - test_assert(parts->children->header_size.lines == 2); -@@ -408,6 +457,7 @@ static const char input_msg[] = - test_assert(parts->children->body_size.lines == 4); - test_assert(parts->children->body_size.physical_size == 35); - test_assert(parts->children->body_size.virtual_size == 35+4); -+ test_assert(parts->children->children->children_count == 0); - test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->children->physical_pos == 98); - test_assert(parts->children->children->header_size.lines == 2); -@@ -446,11 +496,12 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - -+ test_assert(parts->children_count == 2); - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 45); -@@ -458,6 +509,7 @@ static const char input_msg[] = - test_assert(parts->body_size.lines == 7); - test_assert(parts->body_size.physical_size == 86); - test_assert(parts->body_size.virtual_size == 86+7); -+ test_assert(parts->children->children_count == 1); - test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->physical_pos == 50); - test_assert(parts->children->header_size.lines == 2); -@@ -466,6 +518,7 @@ static const char input_msg[] = - test_assert(parts->children->body_size.lines == 4); - test_assert(parts->children->body_size.physical_size == 36); - test_assert(parts->children->body_size.virtual_size == 36+4); -+ test_assert(parts->children->children->children_count == 0); - test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->children->physical_pos == 100); - test_assert(parts->children->children->header_size.lines == 2); -@@ -481,6 +534,51 @@ static const char input_msg[] = - test_end(); - } - -+static void test_message_parser_trailing_dashes(void) -+{ -+static const char input_msg[] = -+"Content-Type: multipart/mixed; boundary=\"a--\"\n" -+"\n" -+"--a--\n" -+"Content-Type: multipart/mixed; boundary=\"a----\"\n" -+"\n" -+"--a----\n" -+"Content-Type: text/plain\n" -+"\n" -+"body\n" -+"--a------\n" -+"Content-Type: text/html\n" -+"\n" -+"body2\n" -+"--a----"; -+ struct message_parser_ctx *parser; -+ struct istream *input; -+ struct message_part *parts; -+ struct message_block block; -+ pool_t pool; -+ int ret; -+ -+ test_begin("message parser trailing dashes"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(input_msg); -+ -+ parser = message_parser_init(pool, input, &set_empty); -+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; -+ test_assert(ret < 0); -+ message_parser_deinit(&parser, &parts); -+ -+ test_assert(parts->children_count == 2); -+ test_assert(parts->children->next == NULL); -+ test_assert(parts->children->children_count == 1); -+ test_assert(parts->children->children->next == NULL); -+ test_assert(parts->children->children->children_count == 0); -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ - static void test_message_parser_continuing_mime_boundary(void) - { - static const char input_msg[] = -@@ -504,11 +602,12 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - -+ test_assert(parts->children_count == 2); - test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->header_size.lines == 2); - test_assert(parts->header_size.physical_size == 45); -@@ -516,6 +615,7 @@ static const char input_msg[] = - test_assert(parts->body_size.lines == 7); - test_assert(parts->body_size.physical_size == 86); - test_assert(parts->body_size.virtual_size == 86+7); -+ test_assert(parts->children->children_count == 1); - test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->physical_pos == 49); - test_assert(parts->children->header_size.lines == 2); -@@ -524,6 +624,7 @@ static const char input_msg[] = - test_assert(parts->children->body_size.lines == 4); - test_assert(parts->children->body_size.physical_size == 36); - test_assert(parts->children->body_size.virtual_size == 36+4); -+ test_assert(parts->children->children->children_count == 0); - test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(parts->children->children->physical_pos == 100); - test_assert(parts->children->children->header_size.lines == 2); -@@ -563,12 +664,13 @@ static const char input_msg[] = - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; - test_assert(ret < 0); - message_parser_deinit(&parser, &parts); - - part = parts; -+ test_assert(part->children_count == 3); - test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(part->header_size.lines == 2); - test_assert(part->header_size.physical_size == 45); -@@ -578,6 +680,7 @@ static const char input_msg[] = - test_assert(part->body_size.virtual_size == 112+9); - - part = parts->children; -+ test_assert(part->children_count == 0); - test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(part->physical_pos == 49); - test_assert(part->header_size.lines == 1); -@@ -591,6 +694,7 @@ static const char input_msg[] = - we could make it, but it would complicate the message-parser even - more. */ - part = parts->children->next; -+ test_assert(part->children_count == 0); - test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(part->physical_pos == 117); - test_assert(part->header_size.lines == 1); -@@ -601,6 +705,7 @@ static const char input_msg[] = - test_assert(part->children == NULL); - - part = parts->children->next->next; -+ test_assert(part->children_count == 0); - test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); - test_assert(part->header_size.lines == 0); - test_assert(part->header_size.physical_size == 0); -@@ -615,6 +720,80 @@ static const char input_msg[] = - test_end(); - } - -+static void test_message_parser_continuing_mime_boundary_reverse(void) -+{ -+static const char input_msg[] = -+"Content-Type: multipart/mixed; boundary=\"ab\"\n" -+"\n" -+"--ab\n" -+"Content-Type: multipart/mixed; boundary=\"a\"\n" -+"\n" -+"--a\n" -+"Content-Type: text/plain\n" -+"\n" -+"body\n" -+"--ab\n" -+"Content-Type: text/html\n" -+"\n" -+"body2\n"; -+ struct message_parser_ctx *parser; -+ struct istream *input; -+ struct message_part *parts; -+ struct message_block block; -+ pool_t pool; -+ int ret; -+ -+ test_begin("message parser continuing mime boundary reverse"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(input_msg); -+ -+ parser = message_parser_init(pool, input, &set_empty); -+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; -+ test_assert(ret < 0); -+ message_parser_deinit(&parser, &parts); -+ -+ test_assert(parts->children_count == 3); -+ test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(parts->header_size.lines == 2); -+ test_assert(parts->header_size.physical_size == 46); -+ test_assert(parts->header_size.virtual_size == 46+2); -+ test_assert(parts->body_size.lines == 11); -+ test_assert(parts->body_size.physical_size == 121); -+ test_assert(parts->body_size.virtual_size == 121+11); -+ test_assert(parts->children->children_count == 1); -+ test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(parts->children->physical_pos == 51); -+ test_assert(parts->children->header_size.lines == 2); -+ test_assert(parts->children->header_size.physical_size == 45); -+ test_assert(parts->children->header_size.virtual_size == 45+2); -+ test_assert(parts->children->body_size.lines == 3); -+ test_assert(parts->children->body_size.physical_size == 34); -+ test_assert(parts->children->body_size.virtual_size == 34+3); -+ test_assert(parts->children->children->children_count == 0); -+ test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(parts->children->children->physical_pos == 100); -+ test_assert(parts->children->children->header_size.lines == 2); -+ test_assert(parts->children->children->header_size.physical_size == 26); -+ test_assert(parts->children->children->header_size.virtual_size == 26+2); -+ test_assert(parts->children->children->body_size.lines == 0); -+ test_assert(parts->children->children->body_size.physical_size == 4); -+ test_assert(parts->children->children->body_size.virtual_size == 4); -+ test_assert(parts->children->next->children_count == 0); -+ test_assert(parts->children->next->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(parts->children->next->physical_pos == 136); -+ test_assert(parts->children->next->header_size.lines == 2); -+ test_assert(parts->children->next->header_size.physical_size == 25); -+ test_assert(parts->children->next->header_size.virtual_size == 25+2); -+ test_assert(parts->children->next->body_size.lines == 1); -+ test_assert(parts->children->next->body_size.physical_size == 6); -+ test_assert(parts->children->next->body_size.virtual_size == 6+1); -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ - static void test_message_parser_no_eoh(void) - { - static const char input_msg[] = "a:b\n"; -@@ -628,7 +807,7 @@ static void test_message_parser_no_eoh(v - pool = pool_alloconly_create("message parser", 10240); - input = test_istream_create(input_msg); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set_empty); - test_assert(message_parser_parse_next_block(parser, &block) > 0 && - block.hdr != NULL && strcmp(block.hdr->name, "a") == 0 && - block.hdr->value_len == 1 && block.hdr->value[0] == 'b'); -@@ -643,19 +822,335 @@ static void test_message_parser_no_eoh(v - test_end(); - } - -+static void test_message_parser_long_mime_boundary(void) -+{ -+ /* Close the boundaries in wrong reverse order. But because all -+ boundaries are actually truncated to the same size (..890) it -+ works the same as if all of them were duplicate boundaries. */ -+static const char input_msg[] = -+"Content-Type: multipart/mixed; boundary=\"1234567890123456789012345678901234567890123456789012345678901234567890123456789012\"\n" -+"\n" -+"--1234567890123456789012345678901234567890123456789012345678901234567890123456789012\n" -+"Content-Type: multipart/mixed; boundary=\"123456789012345678901234567890123456789012345678901234567890123456789012345678901\"\n" -+"\n" -+"--123456789012345678901234567890123456789012345678901234567890123456789012345678901\n" -+"Content-Type: multipart/mixed; boundary=\"12345678901234567890123456789012345678901234567890123456789012345678901234567890\"\n" -+"\n" -+"--12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" -+"Content-Type: text/plain\n" -+"\n" -+"1\n" -+"--1234567890123456789012345678901234567890123456789012345678901234567890123456789012\n" -+"Content-Type: text/plain\n" -+"\n" -+"22\n" -+"--123456789012345678901234567890123456789012345678901234567890123456789012345678901\n" -+"Content-Type: text/plain\n" -+"\n" -+"333\n" -+"--12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" -+"Content-Type: text/plain\n" -+"\n" -+"4444\n"; -+ struct message_parser_ctx *parser; -+ struct istream *input; -+ struct message_part *parts, *part; -+ struct message_block block; -+ pool_t pool; -+ int ret; -+ -+ test_begin("message parser long mime boundary"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(input_msg); -+ -+ parser = message_parser_init(pool, input, &set_empty); -+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; -+ test_assert(ret < 0); -+ message_parser_deinit(&parser, &parts); -+ -+ part = parts; -+ test_assert(part->children_count == 6); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 126); -+ test_assert(part->header_size.virtual_size == 126+2); -+ test_assert(part->body_size.lines == 22); -+ test_assert(part->body_size.physical_size == 871); -+ test_assert(part->body_size.virtual_size == 871+22); -+ -+ part = parts->children; -+ test_assert(part->children_count == 5); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 125); -+ test_assert(part->header_size.virtual_size == 125+2); -+ test_assert(part->body_size.lines == 19); -+ test_assert(part->body_size.physical_size == 661); -+ test_assert(part->body_size.virtual_size == 661+19); -+ -+ part = parts->children->children; -+ test_assert(part->children_count == 4); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 124); -+ test_assert(part->header_size.virtual_size == 124+2); -+ test_assert(part->body_size.lines == 16); -+ test_assert(part->body_size.physical_size == 453); -+ test_assert(part->body_size.virtual_size == 453+16); -+ -+ part = parts->children->children->children; -+ for (unsigned int i = 1; i <= 3; i++, part = part->next) { -+ test_assert(part->children_count == 0); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 26); -+ test_assert(part->header_size.virtual_size == 26+2); -+ test_assert(part->body_size.lines == 0); -+ test_assert(part->body_size.physical_size == i); -+ test_assert(part->body_size.virtual_size == i); -+ } -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ -+static void test_message_parser_mime_part_nested_limit(void) -+{ -+static const char input_msg[] = -+"Content-Type: multipart/mixed; boundary=\"1\"\n" -+"\n" -+"--1\n" -+"Content-Type: multipart/mixed; boundary=\"2\"\n" -+"\n" -+"--2\n" -+"Content-Type: text/plain\n" -+"\n" -+"1\n" -+"--2\n" -+"Content-Type: text/plain\n" -+"\n" -+"22\n" -+"--1\n" -+"Content-Type: text/plain\n" -+"\n" -+"333\n"; -+ const struct message_parser_settings parser_set = { -+ .max_nested_mime_parts = 2, -+ }; -+ struct message_parser_ctx *parser; -+ struct istream *input; -+ struct message_part *parts, *part; -+ struct message_block block; -+ pool_t pool; -+ int ret; -+ -+ test_begin("message parser mime part nested limit"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(input_msg); -+ -+ parser = message_parser_init(pool, input, &parser_set); -+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; -+ test_assert(ret < 0); -+ message_parser_deinit(&parser, &parts); -+ -+ part = parts; -+ test_assert(part->children_count == 2); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 45); -+ test_assert(part->header_size.virtual_size == 45+2); -+ test_assert(part->body_size.lines == 15); -+ test_assert(part->body_size.physical_size == 148); -+ test_assert(part->body_size.virtual_size == 148+15); -+ -+ part = parts->children; -+ test_assert(part->children_count == 0); -+ test_assert(part->flags == MESSAGE_PART_FLAG_IS_MIME); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 45); -+ test_assert(part->header_size.virtual_size == 45+2); -+ test_assert(part->body_size.lines == 7); -+ test_assert(part->body_size.physical_size == 64); -+ test_assert(part->body_size.virtual_size == 64+7); -+ -+ part = parts->children->next; -+ test_assert(part->children_count == 0); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 26); -+ test_assert(part->header_size.virtual_size == 26+2); -+ test_assert(part->body_size.lines == 1); -+ test_assert(part->body_size.physical_size == 4); -+ test_assert(part->body_size.virtual_size == 4+1); -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ -+static void test_message_parser_mime_part_nested_limit_rfc822(void) -+{ -+static const char input_msg[] = -+"Content-Type: message/rfc822\n" -+"\n" -+"Content-Type: message/rfc822\n" -+"\n" -+"Content-Type: text/plain\n" -+"\n" -+"1\n"; -+ const struct message_parser_settings parser_set = { -+ .max_nested_mime_parts = 2, -+ }; -+ struct message_parser_ctx *parser; -+ struct istream *input; -+ struct message_part *parts, *part; -+ struct message_block block; -+ pool_t pool; -+ int ret; -+ -+ test_begin("message parser mime part nested limit rfc822"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(input_msg); -+ -+ parser = message_parser_init(pool, input, &parser_set); -+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; -+ test_assert(ret < 0); -+ message_parser_deinit(&parser, &parts); -+ -+ part = parts; -+ test_assert(part->children_count == 1); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_MESSAGE_RFC822 | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 30); -+ test_assert(part->header_size.virtual_size == 30+2); -+ test_assert(part->body_size.lines == 5); -+ test_assert(part->body_size.physical_size == 58); -+ test_assert(part->body_size.virtual_size == 58+5); -+ -+ part = parts->children; -+ test_assert(part->children_count == 0); -+ test_assert(part->flags == MESSAGE_PART_FLAG_IS_MIME); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 30); -+ test_assert(part->header_size.virtual_size == 30+2); -+ test_assert(part->body_size.lines == 3); -+ test_assert(part->body_size.physical_size == 28); -+ test_assert(part->body_size.virtual_size == 28+3); -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ -+static void test_message_parser_mime_part_limit(void) -+{ -+static const char input_msg[] = -+"Content-Type: multipart/mixed; boundary=\"1\"\n" -+"\n" -+"--1\n" -+"Content-Type: multipart/mixed; boundary=\"2\"\n" -+"\n" -+"--2\n" -+"Content-Type: text/plain\n" -+"\n" -+"1\n" -+"--2\n" -+"Content-Type: text/plain\n" -+"\n" -+"22\n" -+"--1\n" -+"Content-Type: text/plain\n" -+"\n" -+"333\n"; -+ const struct message_parser_settings parser_set = { -+ .max_total_mime_parts = 4, -+ }; -+ struct message_parser_ctx *parser; -+ struct istream *input; -+ struct message_part *parts, *part; -+ struct message_block block; -+ pool_t pool; -+ int ret; -+ -+ test_begin("message parser mime part limit"); -+ pool = pool_alloconly_create("message parser", 10240); -+ input = test_istream_create(input_msg); -+ -+ parser = message_parser_init(pool, input, &parser_set); -+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; -+ test_assert(ret < 0); -+ message_parser_deinit(&parser, &parts); -+ -+ part = parts; -+ test_assert(part->children_count == 3); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 45); -+ test_assert(part->header_size.virtual_size == 45+2); -+ test_assert(part->body_size.lines == 15); -+ test_assert(part->body_size.physical_size == 148); -+ test_assert(part->body_size.virtual_size == 148+15); -+ -+ part = parts->children; -+ test_assert(part->children_count == 2); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 45); -+ test_assert(part->header_size.virtual_size == 45+2); -+ test_assert(part->body_size.lines == 12); -+ test_assert(part->body_size.physical_size == 99); -+ test_assert(part->body_size.virtual_size == 99+12); -+ -+ part = parts->children->children; -+ test_assert(part->children_count == 0); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 26); -+ test_assert(part->header_size.virtual_size == 26+2); -+ test_assert(part->body_size.lines == 0); -+ test_assert(part->body_size.physical_size == 1); -+ test_assert(part->body_size.virtual_size == 1); -+ -+ part = parts->children->children->next; -+ test_assert(part->children_count == 0); -+ test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME)); -+ test_assert(part->header_size.lines == 2); -+ test_assert(part->header_size.physical_size == 26); -+ test_assert(part->header_size.virtual_size == 26+2); -+ test_assert(part->body_size.lines == 5); -+ test_assert(part->body_size.physical_size == 37); -+ test_assert(part->body_size.virtual_size == 37+5); -+ -+ test_parsed_parts(input, parts); -+ i_stream_unref(&input); -+ pool_unref(&pool); -+ test_end(); -+} -+ - int main(void) - { - static void (*const test_functions[])(void) = { - test_message_parser_small_blocks, -+ test_message_parser_stop_early, - test_message_parser_truncated_mime_headers, - test_message_parser_truncated_mime_headers2, - test_message_parser_truncated_mime_headers3, - test_message_parser_empty_multipart, - test_message_parser_duplicate_mime_boundary, - test_message_parser_garbage_suffix_mime_boundary, -+ test_message_parser_trailing_dashes, - test_message_parser_continuing_mime_boundary, - test_message_parser_continuing_truncated_mime_boundary, -+ test_message_parser_continuing_mime_boundary_reverse, -+ test_message_parser_long_mime_boundary, - test_message_parser_no_eoh, -+ test_message_parser_mime_part_nested_limit, -+ test_message_parser_mime_part_nested_limit_rfc822, -+ test_message_parser_mime_part_limit, - NULL - }; - return test_run(test_functions); -diff -up dovecot-2.3.8/src/lib-mail/test-message-part.c.CVE_2020_12100 dovecot-2.3.8/src/lib-mail/test-message-part.c ---- dovecot-2.3.8/src/lib-mail/test-message-part.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-mail/test-message-part.c 2020-08-07 12:29:39.976827472 +0200 -@@ -65,6 +65,7 @@ static const char test_msg[] = - - static void test_message_part_idx(void) - { -+ const struct message_parser_settings set = { .flags = 0 }; - struct message_parser_ctx *parser; - struct istream *input; - struct message_part *parts, *part, *prev_part; -@@ -77,7 +78,7 @@ static void test_message_part_idx(void) - pool = pool_alloconly_create("message parser", 10240); - input = i_stream_create_from_data(test_msg, TEST_MSG_LEN); - -- parser = message_parser_init(pool, input, 0, 0); -+ parser = message_parser_init(pool, input, &set); - while ((ret = message_parser_parse_next_block(parser, &block)) > 0) { - part_idx = message_part_to_idx(block.part); - test_assert(part_idx >= prev_idx); -diff -up dovecot-2.3.8/src/lib-storage/index/index-mail-headers.c.CVE_2020_12100 dovecot-2.3.8/src/lib-storage/index/index-mail-headers.c ---- dovecot-2.3.8/src/lib-storage/index/index-mail-headers.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-storage/index/index-mail-headers.c 2020-08-07 12:31:09.948576696 +0200 -@@ -16,11 +16,11 @@ - #include "index-storage.h" - #include "index-mail.h" - --static const enum message_header_parser_flags hdr_parser_flags = -- MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -- MESSAGE_HEADER_PARSER_FLAG_DROP_CR; --static const enum message_parser_flags msg_parser_flags = -- MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK; -+static const struct message_parser_settings msg_parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | -+ MESSAGE_HEADER_PARSER_FLAG_DROP_CR, -+ .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, -+}; - - static int header_line_cmp(const struct index_mail_line *l1, - const struct index_mail_line *l2) -@@ -397,7 +397,7 @@ index_mail_cache_parse_init(struct mail - mail->data.parser_input = input; - mail->data.parser_ctx = - message_parser_init(mail->mail.data_pool, input, -- hdr_parser_flags, msg_parser_flags); -+ &msg_parser_set); - i_stream_unref(&input); - return input2; - } -@@ -426,14 +426,12 @@ static void index_mail_init_parser(struc - data->parser_input = data->stream; - data->parser_ctx = message_parser_init(mail->mail.data_pool, - data->stream, -- hdr_parser_flags, -- msg_parser_flags); -+ &msg_parser_set); - } else { - data->parser_ctx = - message_parser_init_from_parts(data->parts, - data->stream, -- hdr_parser_flags, -- msg_parser_flags); -+ &msg_parser_set); - } - } - -@@ -466,7 +464,7 @@ int index_mail_parse_headers(struct inde - i_assert(!data->save_bodystructure_body || - data->parser_ctx != NULL); - message_parse_header(data->stream, &data->hdr_size, -- hdr_parser_flags, -+ msg_parser_set.hdr_flags, - index_mail_parse_header_cb, mail); - } - if (index_mail_stream_check_failure(mail) < 0) -@@ -521,7 +519,7 @@ int index_mail_headers_get_envelope(stru - if (mail->data.envelope == NULL && stream != NULL) { - /* we got the headers from cache - parse them to get the - envelope */ -- message_parse_header(stream, NULL, hdr_parser_flags, -+ message_parse_header(stream, NULL, msg_parser_set.hdr_flags, - imap_envelope_parse_callback, mail); - if (stream->stream_errno != 0) { - index_mail_stream_log_failure_for(mail, stream); -diff -up dovecot-2.3.8/src/plugins/fts/fts-build-mail.c.CVE_2020_12100 dovecot-2.3.8/src/plugins/fts/fts-build-mail.c ---- dovecot-2.3.8/src/plugins/fts/fts-build-mail.c.CVE_2020_12100 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/plugins/fts/fts-build-mail.c 2020-08-07 12:29:39.977827458 +0200 -@@ -475,6 +475,9 @@ fts_build_mail_real(struct fts_backend_u - const char **retriable_err_msg_r, - bool *may_need_retry_r) - { -+ const struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE, -+ }; - struct fts_mail_build_context ctx; - struct istream *input; - struct message_parser_ctx *parser; -@@ -503,9 +506,7 @@ fts_build_mail_real(struct fts_backend_u - ctx.pending_input = buffer_create_dynamic(default_pool, 128); - - prev_part = NULL; -- parser = message_parser_init(pool_datastack_create(), input, -- MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE, -- 0); -+ parser = message_parser_init(pool_datastack_create(), input, &parser_set); - - decoder = message_decoder_init(update_ctx->normalizer, 0); - for (;;) { diff --git a/SOURCES/dovecot-2.3.8-CVE_2020_12100ph.patch b/SOURCES/dovecot-2.3.8-CVE_2020_12100ph.patch deleted file mode 100644 index 3a8045d..0000000 --- a/SOURCES/dovecot-2.3.8-CVE_2020_12100ph.patch +++ /dev/null @@ -1,56 +0,0 @@ -diff -up dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c.CVE_2020_12100ph dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c ---- dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c.CVE_2020_12100ph 2019-10-08 10:48:14.000000000 +0200 -+++ dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c 2020-08-07 16:42:56.515389867 +0200 -@@ -148,6 +148,7 @@ static int cmd_notify_extract_body_text - const char **body_text_r, size_t *body_size_r) - { - const struct sieve_extension *this_ext = renv->oprtn->ext; -+ const struct message_parser_settings parser_set = { .flags = 0 }; - struct ext_notify_message_context *mctx; - struct mail *mail = renv->msgdata->mail; - struct message_parser_ctx *parser; -@@ -181,7 +182,7 @@ static int cmd_notify_extract_body_text - /* Initialize body decoder */ - decoder = message_decoder_init(NULL, 0); - -- parser = message_parser_init(mctx->pool, input, 0, 0); -+ parser = message_parser_init(mctx->pool, input, &parser_set); - is_text = TRUE; - save_body = FALSE; - while ( (ret=message_parser_parse_next_block(parser, &block)) > 0 ) { -diff -up dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c.CVE_2020_12100ph dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c ---- dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c.CVE_2020_12100ph 2019-10-08 10:48:14.000000000 +0200 -+++ dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c 2020-08-07 16:42:56.516389854 +0200 -@@ -1077,10 +1077,10 @@ static int sieve_message_parts_add_missi - struct sieve_message_context *msgctx = renv->msgctx; - pool_t pool = msgctx->context_pool; - struct mail *mail = sieve_message_get_mail(renv->msgctx); -- enum message_parser_flags mparser_flags = -- MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS; -- enum message_header_parser_flags hparser_flags = -- MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP; -+ struct message_parser_settings parser_set = { -+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP, -+ .flags = MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS, -+ }; - ARRAY(struct sieve_message_header) headers; - struct sieve_message_part *body_part, *header_part, *last_part; - struct message_parser_ctx *parser; -@@ -1117,7 +1117,7 @@ static int sieve_message_parts_add_missi - if (iter_all) { - t_array_init(&headers, 64); - hdr_content = t_str_new(512); -- hparser_flags |= MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE; -+ parser_set.hdr_flags |= MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE; - } else { - i_zero(&headers); - } -@@ -1129,7 +1129,7 @@ static int sieve_message_parts_add_missi - //parser = message_parser_init_from_parts(parts, input, - // hparser_flags, mparser_flags); - parser = message_parser_init(pool_datastack_create(), -- input, hparser_flags, mparser_flags); -+ input, &parser_set); - while ( (ret=message_parser_parse_next_block - (parser, &block)) > 0 ) { - struct sieve_message_part **body_part_idx; diff --git a/SOURCES/dovecot-2.3.8-CVE_2020_12100prereq.patch b/SOURCES/dovecot-2.3.8-CVE_2020_12100prereq.patch deleted file mode 100644 index 1af8c55..0000000 --- a/SOURCES/dovecot-2.3.8-CVE_2020_12100prereq.patch +++ /dev/null @@ -1,224 +0,0 @@ -diff -up dovecot-2.3.8/src/lib-mail/message-decoder.c.CVE_2020_12100prereq dovecot-2.3.8/src/lib-mail/message-decoder.c ---- dovecot-2.3.8/src/lib-mail/message-decoder.c.CVE_2020_12100prereq 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-mail/message-decoder.c 2020-08-07 17:48:58.320126698 +0200 -@@ -13,9 +13,6 @@ - #include "message-header-decode.h" - #include "message-decoder.h" - --/* base64 takes max 4 bytes per character, q-p takes max 3. */ --#define MAX_ENCODING_BUF_SIZE 3 -- - struct message_decoder_context { - enum message_decoder_flags flags; - normalizer_func_t *normalizer; -@@ -30,7 +27,7 @@ struct message_decoder_context { - size_t translation_size; - - struct qp_decoder *qp; -- buffer_t *encoding_buf; -+ struct base64_decoder base64_decoder; - - char *content_type, *content_charset; - enum message_cte message_cte; -@@ -53,7 +50,7 @@ message_decoder_init(normalizer_func_t * - ctx->normalizer = normalizer; - ctx->buf = buffer_create_dynamic(default_pool, 8192); - ctx->buf2 = buffer_create_dynamic(default_pool, 8192); -- ctx->encoding_buf = buffer_create_dynamic(default_pool, 128); -+ base64_decode_init(&ctx->base64_decoder, &base64_scheme, 0); - return ctx; - } - -@@ -68,7 +65,6 @@ void message_decoder_deinit(struct messa - if (ctx->qp != NULL) - qp_decoder_deinit(&ctx->qp); - -- buffer_free(&ctx->encoding_buf); - buffer_free(&ctx->buf); - buffer_free(&ctx->buf2); - i_free(ctx->charset_trans_charset); -@@ -273,14 +269,9 @@ static bool message_decode_body(struct m - struct message_block *input, - struct message_block *output) - { -- struct base64_decoder b64dec; - const unsigned char *data = NULL; -- size_t pos = 0, size = 0; -+ size_t pos, size = 0; - const char *error; -- int ret; -- -- if (ctx->encoding_buf->used != 0) -- buffer_append(ctx->encoding_buf, input->data, input->size); - - switch (ctx->message_cte) { - case MESSAGE_CTE_UNKNOWN: -@@ -289,12 +280,10 @@ static bool message_decode_body(struct m - - case MESSAGE_CTE_78BIT: - case MESSAGE_CTE_BINARY: -- i_assert(ctx->encoding_buf->used == 0); - data = input->data; -- size = pos = input->size; -+ size = input->size; - break; - case MESSAGE_CTE_QP: { -- i_assert(ctx->encoding_buf->used == 0); - buffer_set_used_size(ctx->buf, 0); - if (ctx->qp == NULL) - ctx->qp = qp_decoder_init(ctx->buf); -@@ -302,45 +291,24 @@ static bool message_decode_body(struct m - &pos, &error); - data = ctx->buf->data; - size = ctx->buf->used; -- /* eat away all input. qp-decoder buffers it internally. */ -- pos = input->size; - break; - } - case MESSAGE_CTE_BASE64: - buffer_set_used_size(ctx->buf, 0); -- base64_decode_init(&b64dec, &base64_scheme, 0); -- if (ctx->encoding_buf->used != 0) { -- ret = base64_decode_more(&b64dec, -- ctx->encoding_buf->data, -- ctx->encoding_buf->used, -- &pos, ctx->buf); -- } else { -- ret = base64_decode_more(&b64dec, -- input->data, input->size, -- &pos, ctx->buf); -- } -- if (ret < 0 || base64_decode_finish(&b64dec) < 0) { -- /* corrupted base64 data, don't bother with -- the rest of it */ -- return FALSE; -- } -- if (ret == 0) { -- /* end of base64 input */ -- pos = input->size; -- buffer_set_used_size(ctx->encoding_buf, 0); -+ if (!base64_decode_is_finished(&ctx->base64_decoder)) { -+ if (base64_decode_more(&ctx->base64_decoder, -+ input->data, input->size, -+ &pos, ctx->buf) <= 0) { -+ /* ignore the rest of the input in this -+ MIME part */ -+ (void)base64_decode_finish(&ctx->base64_decoder); -+ } - } - data = ctx->buf->data; - size = ctx->buf->used; - break; - } - -- if (ctx->encoding_buf->used != 0) -- buffer_delete(ctx->encoding_buf, 0, pos); -- else if (pos != input->size) { -- buffer_append(ctx->encoding_buf, -- input->data + pos, input->size - pos); -- } -- - if (ctx->binary_input) { - output->data = data; - output->size = size; -@@ -402,10 +370,11 @@ void message_decoder_decode_reset(struct - { - const char *error; - -+ base64_decode_reset(&ctx->base64_decoder); -+ - if (ctx->qp != NULL) - (void)qp_decoder_finish(ctx->qp, &error); - i_free_and_null(ctx->content_type); - i_free_and_null(ctx->content_charset); - ctx->message_cte = MESSAGE_CTE_78BIT; -- buffer_set_used_size(ctx->encoding_buf, 0); - } -diff -up dovecot-2.3.8/src/lib-mail/test-message-decoder.c.CVE_2020_12100prereq dovecot-2.3.8/src/lib-mail/test-message-decoder.c ---- dovecot-2.3.8/src/lib-mail/test-message-decoder.c.CVE_2020_12100prereq 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/lib-mail/test-message-decoder.c 2020-08-07 17:50:04.612248484 +0200 -@@ -1,7 +1,8 @@ - /* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */ - - #include "lib.h" --#include "buffer.h" -+#include "str.h" -+#include "istream.h" - #include "charset-utf8.h" - #include "message-parser.h" - #include "message-header-decode.h" -@@ -82,6 +83,66 @@ static void test_message_decoder(void) - test_end(); - } - -+static void test_message_decoder_multipart(void) -+{ -+ static const char test_message_input[] = -+ "Content-Type: multipart/mixed; boundary=foo\n" -+ "\n" -+ "--foo\n" -+ "Content-Transfer-Encoding: quoted-printable\n" -+ "Content-Type: text/plain; charset=utf-8\n" -+ "\n" -+ "p=C3=A4iv=C3=A4=C3=A4\n" -+ "\n" -+ "--foo\n" -+ "Content-Transfer-Encoding: base64\n" -+ "Content-Type: text/plain; charset=utf-8\n" -+ "\n" -+ "ecO2dMOkIHZhYW4uCg== ignored\n" -+ "--foo\n" -+ "Content-Transfer-Encoding: base64\n" -+ "Content-Type: text/plain; charset=utf-8\n" -+ "\n" -+ "?garbage\n" -+ "--foo--\n"; -+ struct message_parser_ctx *parser; -+ struct message_decoder_context *decoder; -+ struct message_part *parts; -+ struct message_block input, output; -+ struct istream *istream; -+ string_t *str_out = t_str_new(20); -+ int ret; -+ -+ test_begin("message decoder multipart"); -+ -+ istream = test_istream_create(test_message_input); -+ parser = message_parser_init(pool_datastack_create(), istream, 0, 0); -+ decoder = message_decoder_init(NULL, 0); -+ -+ test_istream_set_allow_eof(istream, FALSE); -+ for (size_t i = 0; i < sizeof(test_message_input); i++) { -+ if (i == sizeof(test_message_input)-1) -+ test_istream_set_allow_eof(istream, TRUE); -+ test_istream_set_size(istream, i); -+ while ((ret = message_parser_parse_next_block(parser, &input)) > 0) { -+ if (message_decoder_decode_next_block(decoder, &input, &output) && -+ output.hdr == NULL && output.size > 0) -+ str_append_data(str_out, output.data, output.size); -+ } -+ if (i == sizeof(test_message_input)-1) -+ test_assert(ret == -1); -+ else -+ test_assert(ret == 0); -+ } -+ /* NOTE: qp-decoder decoder changes \n into \r\n */ -+ test_assert_strcmp(str_c(str_out), "p\xC3\xA4iv\xC3\xA4\xC3\xA4\r\ny\xC3\xB6t\xC3\xA4 vaan.\n"); -+ -+ message_decoder_deinit(&decoder); -+ message_parser_deinit(&parser, &parts); -+ i_stream_unref(&istream); -+ test_end(); -+} -+ - static void test_message_decoder_current_content_type(void) - { - struct message_decoder_context *ctx; -@@ -149,6 +210,7 @@ int main(void) - { - static void (*const test_functions[])(void) = { - test_message_decoder, -+ test_message_decoder_multipart, - test_message_decoder_current_content_type, - NULL - }; diff --git a/SOURCES/dovecot-2.3.8-CVE_2020_12673.patch b/SOURCES/dovecot-2.3.8-CVE_2020_12673.patch deleted file mode 100644 index a48760b..0000000 --- a/SOURCES/dovecot-2.3.8-CVE_2020_12673.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 1c6405d3026e5ceae3d214d63945bba85251af4c Mon Sep 17 00:00:00 2001 -From: Aki Tuomi -Date: Mon, 18 May 2020 12:33:39 +0300 -Subject: [PATCH 2/3] lib-ntlm: Check buffer length on responses - -Add missing check for buffer length. - -If this is not checked, it is possible to send message which -causes read past buffer bug. - -Broken in c7480644202e5451fbed448508ea29a25cffc99c ---- - src/lib-ntlm/ntlm-message.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/lib-ntlm/ntlm-message.c b/src/lib-ntlm/ntlm-message.c -index 160b9f918c..a29413b47e 100644 ---- a/src/lib-ntlm/ntlm-message.c -+++ b/src/lib-ntlm/ntlm-message.c -@@ -184,6 +184,11 @@ static bool ntlmssp_check_buffer(const struct ntlmssp_buffer *buffer, - if (length == 0 && space == 0) - return TRUE; - -+ if (length > data_size) { -+ *error = "buffer length out of bounds"; -+ return FALSE; -+ } -+ - if (offset >= data_size) { - *error = "buffer offset out of bounds"; - return FALSE; --- -2.11.0 - diff --git a/SOURCES/dovecot-2.3.8-CVE_2020_12674.patch b/SOURCES/dovecot-2.3.8-CVE_2020_12674.patch deleted file mode 100644 index c786011..0000000 --- a/SOURCES/dovecot-2.3.8-CVE_2020_12674.patch +++ /dev/null @@ -1,234 +0,0 @@ -From bd9d2fe7da833f0e4705a8280efc56930371806b Mon Sep 17 00:00:00 2001 -From: Aki Tuomi -Date: Wed, 6 May 2020 13:40:36 +0300 -Subject: [PATCH 1/3] auth: mech-rpa - Fail on zero len buffer - ---- - src/auth/mech-rpa.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/auth/mech-rpa.c b/src/auth/mech-rpa.c -index 08298ebdd6..2de8705b4f 100644 ---- a/src/auth/mech-rpa.c -+++ b/src/auth/mech-rpa.c -@@ -224,7 +224,7 @@ rpa_read_buffer(pool_t pool, const unsigned char **data, - return 0; - - len = *p++; -- if (p + len > end) -+ if (p + len > end || len == 0) - return 0; - - *buffer = p_malloc(pool, len); --- -2.11.0 - -From 98c39fd633adf9b1d11a7bad58ef0784a25042e6 Mon Sep 17 00:00:00 2001 -From: Aki Tuomi -Date: Mon, 18 May 2020 13:08:45 +0300 -Subject: [PATCH 3/3] auth: test-mech - Add tests for RPA and NTLM bug - ---- - src/auth/test-mech.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 66 insertions(+) - -diff -up dovecot-2.3.8/src/auth/test-mech.c.CVE_2020_12674prereq dovecot-2.3.8/src/auth/test-mech.c ---- dovecot-2.3.8/src/auth/test-mech.c.CVE_2020_12674prereq 2020-08-07 20:46:56.095295825 +0200 -+++ dovecot-2.3.8/src/auth/test-mech.c 2020-08-07 20:47:08.742124304 +0200 -@@ -0,0 +1,196 @@ -+/* Copyright (c) 2020 Dovecot authors, see the included COPYING file */ -+ -+#include "lib.h" -+#include "auth.h" -+#include "str.h" -+#include "auth-common.h" -+#include "auth-request.h" -+#include "auth-request-handler-private.h" -+#include "auth-settings.h" -+#include "otp.h" -+#include "mech-otp-skey-common.h" -+#include "settings-parser.h" -+#include "password-scheme.h" -+#include "test-common.h" -+#include "test-auth.h" -+#include "auth-token.h" -+ -+#include -+#include -+ -+#define UCHAR_LEN(str) (const unsigned char *)(str), sizeof(str)-1 -+ -+extern const struct mech_module mech_oauthbearer; -+extern const struct mech_module mech_otp; -+extern const struct mech_module mech_ntlm; -+extern const struct mech_module mech_rpa; -+ -+static struct auth_settings set; -+static struct mechanisms_register *mech_reg; -+ -+struct test_case { -+ const struct mech_module *mech; -+ const unsigned char *in; -+ size_t len; -+ const char *username; -+ const char *expect_error; -+ bool success; -+ bool set_username_before_test; -+ bool set_cert_username; -+}; -+ -+static void -+verify_plain_continue_mock_callback(struct auth_request *request, -+ verify_plain_callback_t *callback) -+{ -+ request->passdb_success = TRUE; -+ callback(PASSDB_RESULT_OK, request); -+} -+ -+static void -+request_handler_reply_mock_callback(struct auth_request *request, -+ enum auth_client_result result, -+ const void *auth_reply ATTR_UNUSED, -+ size_t reply_size ATTR_UNUSED) -+{ -+ request->failed = result != AUTH_CLIENT_RESULT_SUCCESS; -+ -+ if (request->passdb_result == PASSDB_RESULT_OK) -+ request->failed = FALSE; -+ else if (request->mech == &mech_otp) { -+ if (null_strcmp(request->user, "otp_phase_2") == 0) -+ request->failed = FALSE; -+ } else if (request->mech == &mech_oauthbearer) { -+ } -+}; -+ -+static void -+request_handler_reply_continue_mock_callback(struct auth_request *request, -+ const void *reply, -+ size_t reply_size) -+{ -+ request->context = p_strndup(request->pool, reply, reply_size); -+} -+ -+static void -+auth_client_request_mock_callback(const char *reply ATTR_UNUSED, -+ struct auth_client_connection *conn ATTR_UNUSED) -+{ -+} -+ -+static void test_mechs_init(void) -+{ -+ const char *const services[] = {NULL}; -+ process_start_time = time(NULL); -+ -+ /* Copy default settings */ -+ set = *(struct auth_settings *) auth_setting_parser_info.defaults; -+ global_auth_settings = &set; -+ global_auth_settings->base_dir = "."; -+ memset((&set)->username_chars_map, 1, sizeof((&set)->username_chars_map)); -+ set.username_format = ""; -+ -+ t_array_init(&set.passdbs, 2); -+ struct auth_passdb_settings *mock_set = t_new(struct auth_passdb_settings, 1); -+ *mock_set = mock_passdb_set; -+ array_push_back(&set.passdbs, &mock_set); -+ mock_set = t_new(struct auth_passdb_settings, 1); -+ *mock_set = mock_passdb_set; -+ mock_set->master = TRUE; -+ array_push_back(&set.passdbs, &mock_set); -+ t_array_init(&set.userdbs, 1); -+ -+ /* Disable stats */ -+ set.stats = FALSE; -+ -+ /* For tests of digest-md5. */ -+ set.realms_arr = t_strsplit_spaces("example.com ", " "); -+ /* For tests of mech-anonymous. */ -+ set.anonymous_username = "anonuser"; -+ -+ mech_init(global_auth_settings); -+ mech_reg = mech_register_init(global_auth_settings); -+ passdbs_init(); -+ userdbs_init(); -+ passdb_mock_mod_init(); -+ password_schemes_init(); -+ -+ auths_preinit(&set, pool_datastack_create(), mech_reg, services); -+ auths_init(); -+ auth_token_init(); -+} -+ -+ -+static void test_rpa(void) -+{ -+ test_mechs_init(); -+ static struct auth_request_handler handler = { -+ .callback = auth_client_request_mock_callback, -+ .reply_callback = request_handler_reply_mock_callback, -+ .reply_continue_callback = request_handler_reply_continue_mock_callback, -+ .verify_plain_continue_callback = verify_plain_continue_mock_callback, -+ }; -+ -+ const struct mech_module *mech = &mech_rpa; -+ test_begin("test rpa"); -+ struct auth_request *req = mech->auth_new(); -+ global_auth_settings->realms_arr = t_strsplit("example.com", " "); -+ req->set = global_auth_settings; -+ req->service = "login"; -+ req->handler = &handler; -+ req->mech_event = event_create(NULL); -+ req->event = event_create(NULL); -+ req->mech = mech; -+ req->state = AUTH_REQUEST_STATE_MECH_CONTINUE; -+ auth_request_state_count[AUTH_REQUEST_STATE_MECH_CONTINUE] = 1; -+ mech->auth_initial(req, UCHAR_LEN("\x60\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x73\x01\x01\x01\x00\x04\x00\x00\x01")); -+ mech->auth_continue(req, UCHAR_LEN("\x60\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x73\x01\x01\x00\x03A@A\x00")); -+ test_assert(req->failed == TRUE); -+ test_assert(req->passdb_success == FALSE); -+ event_unref(&req->mech_event); -+ event_unref(&req->event); -+ mech->auth_free(req); -+ test_end(); -+} -+ -+static void test_ntlm(void) -+{ -+ static struct auth_request_handler handler = { -+ .callback = auth_client_request_mock_callback, -+ .reply_callback = request_handler_reply_mock_callback, -+ .reply_continue_callback = request_handler_reply_continue_mock_callback, -+ .verify_plain_continue_callback = verify_plain_continue_mock_callback, -+ }; -+ -+ const struct mech_module *mech = &mech_ntlm; -+ test_begin("test ntlm"); -+ struct auth_request *req = mech->auth_new(); -+ global_auth_settings->realms_arr = t_strsplit("example.com", " "); -+ req->set = global_auth_settings; -+ req->service = "login"; -+ req->handler = &handler; -+ req->mech_event = event_create(NULL); -+ req->event = event_create(NULL); -+ req->mech = mech; -+ req->state = AUTH_REQUEST_STATE_MECH_CONTINUE; -+ auth_request_state_count[AUTH_REQUEST_STATE_MECH_CONTINUE] = 1; -+ mech->auth_initial(req, UCHAR_LEN("NTLMSSP\x00\x01\x00\x00\x00\x00\x02\x00\x00""AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); -+ mech->auth_continue(req, UCHAR_LEN("NTLMSSP\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00""AA\x00\x00\x41\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00""orange""\x00")); -+ test_assert(req->failed == TRUE); -+ test_assert(req->passdb_success == FALSE); -+ event_unref(&req->mech_event); -+ event_unref(&req->event); -+ mech->auth_free(req); -+ test_end(); -+} -+ -+int main(void) -+{ -+ static void (*const test_functions[])(void) = { -+ test_rpa, -+ test_ntlm, -+ NULL -+ }; -+ -+ return test_run(test_functions); -+} diff --git a/SOURCES/dovecot-2.3.8-CVE_2020_12674prereq.patch b/SOURCES/dovecot-2.3.8-CVE_2020_12674prereq.patch deleted file mode 100644 index 931ce9a..0000000 --- a/SOURCES/dovecot-2.3.8-CVE_2020_12674prereq.patch +++ /dev/null @@ -1,345 +0,0 @@ -diff -up dovecot-2.3.8/src/auth/Makefile.am.CVE_2020_12674prereq dovecot-2.3.8/src/auth/Makefile.am ---- dovecot-2.3.8/src/auth/Makefile.am.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/Makefile.am 2020-08-07 20:46:56.095295825 +0200 -@@ -38,6 +38,7 @@ AM_CPPFLAGS = \ - -I$(top_srcdir)/src/lib-oauth2 \ - -I$(top_srcdir)/src/lib-ssl-iostream \ - -I$(top_srcdir)/src/lib-lua \ -+ -I$(top_srcdir)/src/lib-dcrypt \ - -DAUTH_MODULE_DIR=\""$(auth_moduledir)"\" \ - -DPKG_LIBEXECDIR=\""$(pkglibexecdir)"\" \ - -DPKG_RUNDIR=\""$(rundir)"\" \ -@@ -248,7 +249,8 @@ libstats_auth_la_SOURCES = auth-stats.c - test_programs = \ - test-libpassword \ - test-auth-cache \ -- test-auth -+ test-auth \ -+ test-mech - - noinst_PROGRAMS = $(test_programs) - -@@ -288,6 +290,13 @@ test_auth_SOURCES = \ - test_auth_LDADD = $(test_libs) $(auth_libs) $(AUTH_LIBS) - test_auth_DEPENDENCIES = $(pkglibexec_PROGRAMS) $(test_libs) - -+test_mech_SOURCES = \ -+ test-mock.c \ -+ test-mech.c -+ -+test_mech_LDADD = $(test_libs) $(auth_libs) $(AUTH_LIBS) -+test_mech_DEPENDENCIES = $(pkglibexec_PROGRAMS) $(test_libs) -+ - check-local: - for bin in $(test_programs); do \ - if ! $(RUN_TEST) ./$$bin; then exit 1; fi; \ -diff -up dovecot-2.3.8/src/auth/passdb.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/passdb.h ---- dovecot-2.3.8/src/auth/passdb.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/passdb.h 2020-08-07 20:35:16.295684287 +0200 -@@ -24,6 +24,8 @@ enum passdb_result { - - typedef void verify_plain_callback_t(enum passdb_result result, - struct auth_request *request); -+typedef void verify_plain_continue_callback_t(struct auth_request *request, -+ verify_plain_callback_t *callback); - typedef void lookup_credentials_callback_t(enum passdb_result result, - const unsigned char *credentials, - size_t size, -diff -up dovecot-2.3.8/src/auth/auth-request-handler-private.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request-handler-private.h ---- dovecot-2.3.8/src/auth/auth-request-handler-private.h.CVE_2020_12674prereq 2020-08-07 20:35:16.295684287 +0200 -+++ dovecot-2.3.8/src/auth/auth-request-handler-private.h 2020-08-07 20:35:16.295684287 +0200 -@@ -0,0 +1,27 @@ -+#ifndef AUTH_REQUEST_HANDLER_PRIVATE_H -+#define AUTH_REQUEST_HANDLER_PRIVATE_H -+ -+struct auth_request; -+struct auth_client_connection; -+ -+struct auth_request_handler { -+ int refcount; -+ pool_t pool; -+ HASH_TABLE(void *, struct auth_request *) requests; -+ -+ unsigned int connect_uid, client_pid; -+ -+ auth_client_request_callback_t *callback; -+ struct auth_client_connection *conn; -+ -+ auth_master_request_callback_t *master_callback; -+ auth_request_handler_reply_callback_t *reply_callback; -+ auth_request_handler_reply_continue_callback_t *reply_continue_callback; -+ verify_plain_continue_callback_t *verify_plain_continue_callback; -+ -+ bool destroyed:1; -+ bool token_auth:1; -+}; -+ -+ -+#endif -diff -up dovecot-2.3.8/src/auth/auth-request-handler.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request-handler.h ---- dovecot-2.3.8/src/auth/auth-request-handler.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/auth-request-handler.h 2020-08-07 20:35:16.295684287 +0200 -@@ -17,6 +17,17 @@ auth_client_request_callback_t(const cha - typedef void - auth_master_request_callback_t(const char *reply, struct auth_master_connection *conn); - -+typedef void -+auth_request_handler_reply_callback_t(struct auth_request *request, -+ enum auth_client_result result, -+ const void *auth_reply, -+ size_t reply_size); -+typedef void -+auth_request_handler_reply_continue_callback_t(struct auth_request *request, -+ const void *reply, -+ size_t reply_size); -+ -+ - struct auth_request_handler * - auth_request_handler_create(bool token_auth, auth_client_request_callback_t *callback, - struct auth_client_connection *conn, -diff -up dovecot-2.3.8/src/auth/test-mock.c.CVE_2020_12674prereq dovecot-2.3.8/src/auth/test-mock.c ---- dovecot-2.3.8/src/auth/test-mock.c.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/test-mock.c 2020-08-07 20:35:16.296684273 +0200 -@@ -28,14 +28,22 @@ static void passdb_mock_verify_plain(str - callback(PASSDB_RESULT_OK, request); - } - -+static void passdb_mock_lookup_credentials(struct auth_request *request, -+ lookup_credentials_callback_t *callback) -+{ -+ passdb_handle_credentials(PASSDB_RESULT_OK, "password", "PLAIN", -+ callback, request); -+} -+ - static struct passdb_module_interface mock_interface = { - .name = "mock", - .init = passdb_mock_init, - .deinit = passdb_mock_deinit, - .verify_plain = passdb_mock_verify_plain, -+ .lookup_credentials = passdb_mock_lookup_credentials, - }; - --static struct auth_passdb_settings set = { -+struct auth_passdb_settings mock_passdb_set = { - .name = "mock", - .driver = "mock", - .args = "", -@@ -95,7 +103,7 @@ void passdb_mock_mod_deinit(void) - struct auth_passdb *passdb_mock(void) - { - struct auth_passdb *ret = i_new(struct auth_passdb, 1); -- ret->set = &set; -+ ret->set = &mock_passdb_set; - ret->passdb = mock_passdb_mod; - return ret; - } -diff -up dovecot-2.3.8/src/auth/test-auth.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/test-auth.h ---- dovecot-2.3.8/src/auth/test-auth.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/test-auth.h 2020-08-07 20:35:16.296684273 +0200 -@@ -8,6 +8,8 @@ - - struct auth_passdb; - -+extern struct auth_passdb_settings mock_passdb_set; -+ - void test_auth_request_var_expand(void); - void test_db_dict_parse_cache_key(void); - void test_username_filter(void); -diff -up dovecot-2.3.8/src/auth/auth-request.c.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request.c ---- dovecot-2.3.8/src/auth/auth-request.c.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/auth-request.c 2020-08-07 20:35:16.295684287 +0200 -@@ -16,6 +16,7 @@ - #include "auth-cache.h" - #include "auth-request.h" - #include "auth-request-handler.h" -+#include "auth-request-handler-private.h" - #include "auth-request-stats.h" - #include "auth-client-connection.h" - #include "auth-master-connection.h" -@@ -67,9 +68,6 @@ static void - auth_request_userdb_import(struct auth_request *request, const char *args); - - static --void auth_request_verify_plain_continue(struct auth_request *request, -- verify_plain_callback_t *callback); --static - void auth_request_lookup_credentials_policy_continue(struct auth_request *request, - lookup_credentials_callback_t *callback); - static -@@ -307,10 +307,12 @@ void auth_request_success_continue(struct auth_policy_check_ctx *ctx) - return; - } - -- stats = auth_request_stats_get(request); -- stats->auth_success_count++; -- if (request->master_user != NULL) -- stats->auth_master_success_count++; -+ if (request->set->stats) { -+ stats = auth_request_stats_get(request); -+ stats->auth_success_count++; -+ if (request->master_user != NULL) -+ stats->auth_master_success_count++; -+ } - - auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED); - auth_request_refresh_last_access(request); -@@ -324,8 +326,10 @@ void auth_request_fail(struct auth_request *request) - - i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE); - -- stats = auth_request_stats_get(request); -- stats->auth_failure_count++; -+ if (request->set->stats) { -+ stats = auth_request_stats_get(request); -+ stats->auth_failure_count++; -+ } - - auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED); - auth_request_refresh_last_access(request); -@@ -1233,7 +1231,7 @@ void auth_request_policy_penalty_finish( - - switch(ctx->type) { - case AUTH_POLICY_CHECK_TYPE_PLAIN: -- auth_request_verify_plain_continue(ctx->request, ctx->callback_plain); -+ ctx->request->handler->verify_plain_continue_callback(ctx->request, ctx->callback_plain); - return; - case AUTH_POLICY_CHECK_TYPE_LOOKUP: - auth_request_lookup_credentials_policy_continue(ctx->request, ctx->callback_lookup); -@@ -1284,7 +1282,8 @@ void auth_request_verify_plain(struct au - request->user_changed_by_lookup = FALSE; - - if (request->policy_processed || !request->set->policy_check_before_auth) { -- auth_request_verify_plain_continue(request, callback); -+ request->handler->verify_plain_continue_callback(request, -+ callback); - } else { - ctx = p_new(request->pool, struct auth_policy_check_ctx, 1); - ctx->request = request; -@@ -1294,10 +1293,9 @@ void auth_request_verify_plain(struct au - } - } - --static --void auth_request_verify_plain_continue(struct auth_request *request, -- verify_plain_callback_t *callback) { -- -+void auth_request_default_verify_plain_continue(struct auth_request *request, -+ verify_plain_callback_t *callback) -+{ - struct auth_passdb *passdb; - enum passdb_result result; - const char *cache_key, *error; -diff -up dovecot-2.3.8/src/auth/auth-request-handler.c.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request-handler.c ---- dovecot-2.3.8/src/auth/auth-request-handler.c.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/auth-request-handler.c 2020-08-07 20:35:16.295684287 +0200 -@@ -17,32 +17,28 @@ - #include "auth-client-connection.h" - #include "auth-master-connection.h" - #include "auth-request-handler.h" -+#include "auth-request-handler-private.h" - #include "auth-policy.h" - - #define AUTH_FAILURE_DELAY_CHECK_MSECS 500 -- --struct auth_request_handler { -- int refcount; -- pool_t pool; -- HASH_TABLE(void *, struct auth_request *) requests; -- -- unsigned int connect_uid, client_pid; -- -- auth_client_request_callback_t *callback; -- struct auth_client_connection *conn; -- -- auth_master_request_callback_t *master_callback; -- -- bool destroyed:1; -- bool token_auth:1; --}; -- - static ARRAY(struct auth_request *) auth_failures_arr; - static struct aqueue *auth_failures; - static struct timeout *to_auth_failures; - - static void auth_failure_timeout(void *context) ATTR_NULL(1); - -+ -+static void -+auth_request_handler_default_reply_callback(struct auth_request *request, -+ enum auth_client_result result, -+ const void *auth_reply, -+ size_t reply_size); -+ -+static void -+auth_request_handler_default_reply_continue(struct auth_request *request, -+ const void *reply, -+ size_t reply_size); -+ - struct auth_request_handler * - auth_request_handler_create(bool token_auth, auth_client_request_callback_t *callback, - struct auth_client_connection *conn, -@@ -61,6 +57,12 @@ auth_request_handler_create(bool token_a - handler->conn = conn; - handler->master_callback = master_callback; - handler->token_auth = token_auth; -+ handler->reply_callback = -+ auth_request_handler_default_reply_callback; -+ handler->reply_continue_callback = -+ auth_request_handler_default_reply_continue; -+ handler->verify_plain_continue_callback = -+ auth_request_default_verify_plain_continue; - return handler; - } - -@@ -355,6 +363,16 @@ void auth_request_handler_reply(struct a - enum auth_client_result result, - const void *auth_reply, size_t reply_size) - { -+ struct auth_request_handler *handler = request->handler; -+ handler->reply_callback(request, result, auth_reply, reply_size); -+} -+ -+static void -+auth_request_handler_default_reply_callback(struct auth_request *request, -+ enum auth_client_result result, -+ const void *auth_reply, -+ size_t reply_size) -+{ - struct auth_request_handler *handler = request->handler; - string_t *str; - int ret; -@@ -407,6 +425,14 @@ void auth_request_handler_reply(struct a - void auth_request_handler_reply_continue(struct auth_request *request, - const void *reply, size_t reply_size) - { -+ request->handler->reply_continue_callback(request, reply, reply_size); -+} -+ -+static void -+auth_request_handler_default_reply_continue(struct auth_request *request, -+ const void *reply, -+ size_t reply_size) -+{ - auth_request_handler_reply(request, AUTH_CLIENT_RESULT_CONTINUE, - reply, reply_size); - } -@@ -703,6 +729,7 @@ static void auth_str_append_userdb_extra - auth_str_add_keyvalue(dest, "master_user", - request->master_user); - } -+ auth_str_add_keyvalue(dest, "auth_mech", request->mech->mech_name); - if (*request->set->anonymous_username != '\0' && - strcmp(request->user, request->set->anonymous_username) == 0) { - /* this is an anonymous login, either via ANONYMOUS -diff -up dovecot-2.3.8/src/auth/auth-request.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request.h ---- dovecot-2.3.8/src/auth/auth-request.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200 -+++ dovecot-2.3.8/src/auth/auth-request.h 2020-08-07 20:35:16.295684287 +0200 -@@ -295,6 +295,8 @@ void auth_request_set_credentials(struct - set_credentials_callback_t *callback); - void auth_request_userdb_callback(enum userdb_result result, - struct auth_request *request); -+void auth_request_default_verify_plain_continue(struct auth_request *request, -+ verify_plain_callback_t *callback); - - void auth_request_refresh_last_access(struct auth_request *request); - void auth_str_append(string_t *dest, const char *key, const char *value); diff --git a/SOURCES/dovecot-2.3.8-a668d767.patch b/SOURCES/dovecot-2.3.8-a668d767.patch deleted file mode 100644 index 71aba2a..0000000 --- a/SOURCES/dovecot-2.3.8-a668d767.patch +++ /dev/null @@ -1,73 +0,0 @@ -diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c -index 011dea9050..8baf622e59 100644 ---- a/src/lib-mail/message-parser.c -+++ b/src/lib-mail/message-parser.c -@@ -138,6 +138,7 @@ message_part_append(struct message_parser_ctx *ctx) - struct message_part *parent = ctx->part; - struct message_part *part; - -+ i_assert(!ctx->preparsed); - i_assert(parent != NULL); - i_assert((parent->flags & (MESSAGE_PART_FLAG_MULTIPART | - MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0); -@@ -171,12 +172,14 @@ static void message_part_finish(struct message_parser_ctx *ctx) - { - struct message_part **const *parent_next_partp; - -- i_assert(ctx->nested_parts_count > 0); -- ctx->nested_parts_count--; -+ if (!ctx->preparsed) { -+ i_assert(ctx->nested_parts_count > 0); -+ ctx->nested_parts_count--; - -- parent_next_partp = array_back(&ctx->next_part_stack); -- array_pop_back(&ctx->next_part_stack); -- ctx->next_part = *parent_next_partp; -+ parent_next_partp = array_back(&ctx->next_part_stack); -+ array_pop_back(&ctx->next_part_stack); -+ ctx->next_part = *parent_next_partp; -+ } - - message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size); - message_size_add(&ctx->part->parent->body_size, &ctx->part->header_size); -diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c -index 13984f939e..a00f0d6200 100644 ---- a/src/lib-mail/test-message-parser.c -+++ b/src/lib-mail/test-message-parser.c -@@ -178,9 +178,10 @@ static void test_message_parser_small_blocks(void) - static void test_message_parser_stop_early(void) - { - struct message_parser_ctx *parser; -- struct istream *input; -+ struct istream *input, *input2; - struct message_part *parts; - struct message_block block; -+ const char *error; - unsigned int i; - pool_t pool; - int ret; -@@ -198,6 +199,24 @@ static void test_message_parser_stop_early(void) - &block)) > 0) ; - test_assert(ret == 0); - message_parser_deinit(&parser, &parts); -+ -+ /* test preparsed - first re-parse everything with a stream -+ that sees EOF at this position */ -+ input2 = i_stream_create_from_data(test_msg, i); -+ parser = message_parser_init(pool, input2, &set_empty); -+ while ((ret = message_parser_parse_next_block(parser, -+ &block)) > 0) ; -+ test_assert(ret == -1); -+ message_parser_deinit(&parser, &parts); -+ -+ /* now parse from the parts */ -+ i_stream_seek(input2, 0); -+ parser = message_parser_init_from_parts(parts, input2, &set_empty); -+ while ((ret = message_parser_parse_next_block(parser, -+ &block)) > 0) ; -+ test_assert(ret == -1); -+ test_assert(message_parser_deinit_from_parts(&parser, &parts, &error) == 0); -+ i_stream_unref(&input2); - } - - i_stream_unref(&input); diff --git a/SOURCES/dovecot-2.3.8-blockcount.patch b/SOURCES/dovecot-2.3.8-blockcount.patch deleted file mode 100644 index fb0a9b0..0000000 --- a/SOURCES/dovecot-2.3.8-blockcount.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff -up dovecot-2.3.8/src/lib-storage/index/index-mail-binary.c.blockcount dovecot-2.3.8/src/lib-storage/index/index-mail-binary.c ---- dovecot-2.3.8/src/lib-storage/index/index-mail-binary.c.blockcount 2020-12-02 11:34:10.229027593 +0100 -+++ dovecot-2.3.8/src/lib-storage/index/index-mail-binary.c 2020-12-02 11:36:47.328933276 +0100 -@@ -339,13 +339,14 @@ blocks_count_lines(struct binary_ctx *ct - i_stream_skip(full_input, skip); - cur_block_offset += skip; - -- if (cur_block->input->eof) { -+ if (i_stream_read_eof(cur_block->input)) { - /* go to the next block */ -- if (++block_idx == block_count) { -+ if (block_idx+1 == block_count) { - i_assert(i_stream_read_eof(full_input)); - ret = -1; - break; - } -+ block_idx++; - cur_block++; - cur_block_offset = 0; - } diff --git a/SPECS/dovecot.spec b/SPECS/dovecot.spec index c79e55d..1599774 100644 --- a/SPECS/dovecot.spec +++ b/SPECS/dovecot.spec @@ -3,9 +3,9 @@ Summary: Secure imap and pop3 server Name: dovecot Epoch: 1 -Version: 2.3.8 +Version: 2.3.16 %global prever %{nil} -Release: 9%{?dist} +Release: 2%{?dist} #dovecot itself is MIT, a few sources are PD, pigeonhole is LGPLv2 License: MIT and LGPLv2 Group: System Environment/Daemons @@ -14,7 +14,7 @@ URL: http://www.dovecot.org/ Source: http://www.dovecot.org/releases/2.3/%{name}-%{version}%{?prever}.tar.gz Source1: dovecot.init Source2: dovecot.pam -%global pigeonholever 0.5.8 +%global pigeonholever 0.5.16 Source8: http://pigeonhole.dovecot.org/releases/2.3/dovecot-2.3-pigeonhole-%{pigeonholever}.tar.gz Source9: dovecot.sysconfig Source10: dovecot.tmpfilesd @@ -43,39 +43,9 @@ Patch13: dovecot-2.2.36-bigkey.patch # hard to break circular dependency between lib and lib-dcrypt Patch14: dovecot-2.3.6-opensslhmac.patch -# from upstream, for dovecot < 2.3.10.1 -Patch15: dovecot-2.3.10-smtppre.patch -Patch16: dovecot-2.3.10-CVE_2020_10957,10958,10967.patch - -# from upstream, for dovecot <= 2.3.10.1 -Patch17: dovecot-2.3.8-CVE_2020_12100prereq.patch -Patch18: dovecot-2.3.8-CVE_2020_12100.patch -Patch19: dovecot-2.3.8-CVE_2020_12100ph.patch -Patch20: dovecot-2.3.8-CVE_2020_12673.patch -Patch21: dovecot-2.3.8-CVE_2020_12674prereq.patch -Patch22: dovecot-2.3.8-CVE_2020_12674.patch - -# from upstream, for dovecot <= 2.3.11.3, rhbz#1894418 -Patch23: dovecot-2.3.8-blockcount.patch - -# from upstream, for dovecot < 2.3.11.3, rhbz#1888111 -Patch24: dovecot-2.3.8-a668d767.patch -Patch25: dovecot-2.3.13-CVE_2020_25275-part1.patch -Patch26: dovecot-2.3.13-CVE_2020_25275-part2.patch -Patch27: dovecot-2.3.13-CVE_2020_25275-part3.patch -Patch28: dovecot-2.3.13-CVE_2020_25275-part4.patch -Patch29: dovecot-2.3.13-CVE_2020_25275-part5.patch -Patch30: dovecot-2.3.13-CVE_2020_25275-part6.patch -Patch31: dovecot-2.3.13-CVE_2020_25275-part7.patch -Patch32: dovecot-2.3.13-CVE_2020_25275-part8.patch -Patch33: dovecot-2.3.13-CVE_2020_25275regr-part1.patch -Patch34: dovecot-2.3.13-CVE_2020_25275regr-part2.patch -Patch35: dovecot-2.3.13-CVE_2020_25275regr-part3.patch -Patch36: dovecot-2.3.13-CVE_2020_24386-prereq1.patch -Patch37: dovecot-2.3.13-CVE_2020_24386-part1.patch -Patch38: dovecot-2.3.13-CVE_2020_24386-part2.patch -Patch39: dovecot-2.3.13-CVE_2020_24386-part3.patch -Patch40: dovecot-2.3.13-CVE_2020_24386-part4.patch +# from upstream, for dovecot < 2.3.17, s390x FTBFS fix +Patch15: dovecot-2.3.16-ftbfsbigend.patch +Patch16: dovecot-2.3.16-keeplzma.patch Source15: prestartscript @@ -181,32 +151,8 @@ This package provides the development files for dovecot. %patch11 -p1 -b .aclfix %patch13 -p1 -b .bigkey %patch14 -p1 -b .opensslhmac -%patch15 -p1 -b .smtppre -%patch16 -p1 -b .CVE_2020_10957,10958,10967 -%patch17 -p1 -b .CVE_2020_12100prereq -%patch18 -p1 -b .CVE_2020_12100 -%patch19 -p1 -b .CVE_2020_12100ph -%patch20 -p1 -b .CVE_2020_12673 -%patch21 -p1 -b .CVE_2020_12674prereq -%patch22 -p1 -b .CVE_2020_12674 -%patch23 -p1 -b .blockcount -%patch24 -p1 -b .a668d767 -%patch25 -p1 -b .CVE_2020_25275-part1 -%patch26 -p1 -b .CVE_2020_25275-part2 -%patch27 -p1 -b .CVE_2020_25275-part3 -%patch28 -p1 -b .CVE_2020_25275-part4 -%patch29 -p1 -b .CVE_2020_25275-part5 -%patch30 -p1 -b .CVE_2020_25275-part6 -%patch31 -p1 -b .CVE_2020_25275-part7 -%patch32 -p1 -b .CVE_2020_25275-part8 -%patch33 -p1 -b .CVE_2020_25275regr-part1 -%patch34 -p1 -b .CVE_2020_25275regr-part2 -%patch35 -p1 -b .CVE_2020_25275regr-part3 -%patch36 -p1 -b .CVE_2020_24386-prereq1 -%patch37 -p1 -b .CVE_2020_24386-part1 -%patch38 -p1 -b .CVE_2020_24386-part2 -%patch39 -p1 -b .CVE_2020_24386-part3 -%patch40 -p1 -b .CVE_2020_24386-part4 +%patch15 -p1 -b .ftbfsbigend +%patch16 -p1 -b .keeplzma pushd dovecot-2*3-pigeonhole-%{pigeonholever} popd @@ -226,6 +172,7 @@ autoreconf -I . -fiv #required for aarch64 support %configure \ INSTALL_DATA="install -c -p -m644" \ --with-rundir=%{_rundir}/%{name} \ + --with-systemd \ --docdir=%{_docdir}/%{name} \ --disable-static \ --disable-rpath \ @@ -427,6 +374,7 @@ make check %{_bindir}/doveadm %{_bindir}/doveconf %{_bindir}/dsync +%{_bindir}/dovecot-sysreport %if %{?fedora}0 > 140 || %{?rhel}0 > 60 @@ -448,6 +396,7 @@ make check %config(noreplace) %{_sysconfdir}/dovecot/conf.d/10-logging.conf %config(noreplace) %{_sysconfdir}/dovecot/conf.d/10-mail.conf %config(noreplace) %{_sysconfdir}/dovecot/conf.d/10-master.conf +%config(noreplace) %{_sysconfdir}/dovecot/conf.d/10-metrics.conf %config(noreplace) %{_sysconfdir}/dovecot/conf.d/10-ssl.conf %config(noreplace) %{_sysconfdir}/dovecot/conf.d/15-lda.conf %config(noreplace) %{_sysconfdir}/dovecot/conf.d/15-mailboxes.conf @@ -467,8 +416,6 @@ make check %config(noreplace) %{_sysconfdir}/dovecot/conf.d/auth-sql.conf.ext %config(noreplace) %{_sysconfdir}/dovecot/conf.d/auth-static.conf.ext %config(noreplace) %{_sysconfdir}/dovecot/conf.d/auth-system.conf.ext -%config(noreplace) %{_sysconfdir}/dovecot/conf.d/auth-vpopmail.conf.ext - %config(noreplace) %{_sysconfdir}/pam.d/dovecot %config(noreplace) %{ssldir}/dovecot-openssl.cnf @@ -509,10 +456,11 @@ make check %{_libexecdir}/%{name} %exclude %{_libexecdir}/%{name}/managesieve* -%attr(0755,root,dovecot) %ghost /var/run/dovecot +%dir %attr(0755,root,dovecot) %ghost /var/run/dovecot %attr(0750,root,dovenull) %ghost /var/run/dovecot/login %attr(0750,root,dovenull) %ghost /var/run/dovecot/token-login %attr(0755,root,root) %ghost /var/run/dovecot/empty + %attr(0750,dovecot,dovecot) /var/lib/dovecot %{_datadir}/%{name} @@ -569,6 +517,13 @@ make check %{_libdir}/%{name}/dict/libdriver_pgsql.so %changelog +* Wed Dec 08 2021 Michal Hlavinka - 1:2.3.16-2 +- do not disable xz/lzma for now despite being deprecated + +* Wed Dec 08 2021 Michal Hlavinka - 1:2.3.16-1 +- dovecot updated to 2.3.16, pigeonhole to 0.5.16 +- fix CVE-2021-33515 plaintext commands injection (#1980014) + * Wed Feb 03 2021 Michal Hlavinka - 1:2.3.8-9 - fix CVE-2020-24386 IMAP hibernation function allows mail access (#1913534)