Browse Source

dovecot package update

Signed-off-by: webbuilder_pel7ppc64lebuilder0 <webbuilder@powerel.org>
master
webbuilder_pel7ppc64lebuilder0 3 years ago
parent
commit
796e7b7651
  1. 1
      SOURCES/dovecot-2.2-gidcheck.patch
  2. 10
      SOURCES/dovecot-2.2.36-bigkey.patch
  3. 37
      SOURCES/dovecot-2.2.36-cve2019_11500_part1of4.patch
  4. 33
      SOURCES/dovecot-2.2.36-cve2019_11500_part2of4.patch
  5. 36
      SOURCES/dovecot-2.2.36-cve2019_11500_part3of4.patch
  6. 33
      SOURCES/dovecot-2.2.36-cve2019_11500_part4of4.patch
  7. 69
      SOURCES/dovecot-2.2.36-cve_2019_3814part1of3.patch
  8. 29
      SOURCES/dovecot-2.2.36-cve_2019_3814part2of3.patch
  9. 22
      SOURCES/dovecot-2.2.36-cve_2019_3814part3of3.patch
  10. 32
      SOURCES/dovecot-2.2.36-cve_2019_7524part1of2.patch
  11. 22
      SOURCES/dovecot-2.2.36-cve_2019_7524part2of2.patch
  12. 11
      SOURCES/dovecot-2.2.36-portreserve.patch
  13. 2432
      SOURCES/dovecot-2.3.8-CVE_2020_12100.patch
  14. 56
      SOURCES/dovecot-2.3.8-CVE_2020_12100ph.patch
  15. 121
      SOURCES/dovecot-2.3.8-CVE_2020_12100prereq.patch
  16. 34
      SOURCES/dovecot-2.3.8-CVE_2020_12673.patch
  17. 237
      SOURCES/dovecot-2.3.8-CVE_2020_12674.patch
  18. 818
      SOURCES/dovecot-2.3.8-CVE_2020_12674prereq.patch
  19. 1
      SOURCES/dovecot.init
  20. 5
      SOURCES/dovecot.portreserve
  21. 1
      SOURCES/dovecot.tmpfilesd
  22. 3
      SOURCES/prestartscript
  23. 80
      SPECS/dovecot.spec

1
SOURCES/dovecot-2.2-gidcheck.patch

@ -57,3 +57,4 @@ diff -up dovecot-2.2.36/src/auth/userdb-passwd.c.gidcheck dovecot-2.2.36/src/aut @@ -57,3 +57,4 @@ diff -up dovecot-2.2.36/src/auth/userdb-passwd.c.gidcheck dovecot-2.2.36/src/aut
+ return FALSE;
return TRUE;
}

10
SOURCES/dovecot-2.2.36-bigkey.patch

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
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
@@ -1,5 +1,5 @@
[ req ]
-default_bits = 1024
+default_bits = 3072
encrypt_key = yes
distinguished_name = req_dn
x509_extensions = cert_type

37
SOURCES/dovecot-2.2.36-cve2019_11500_part1of4.patch

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
From 58ffd3e8a02e54fc98b6be78e02b0511ee9263eb Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Fri, 10 May 2019 19:24:51 +0300
Subject: [PATCH 1/2] lib-imap: Don't accept strings with NULs

IMAP doesn't allow NULs except in binary literals. We'll still allow them
in regular literals as well, but just not in strings.

This fixes a bug with unescaping a string with NULs: str_unescape() could
have been called for memory that points outside the allocated string,
causing heap corruption. This could cause crashes or theoretically even
result in remote code execution exploit.

Found by Nick Roessler and Rafi Rubin
---
src/lib-imap/imap-parser.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c
index dddf55189..f41668d7a 100644
--- a/src/lib-imap/imap-parser.c
+++ b/src/lib-imap/imap-parser.c
@@ -363,6 +363,11 @@ static bool imap_parser_read_string(struct imap_parser *parser,
break;
}
+ if (data[i] == '\0') {
+ parser->error = "NULs not allowed in strings";
+ return FALSE;
+ }
+
if (data[i] == '\\') {
if (i+1 == data_size) {
/* known data ends with '\' - leave it to
--
2.11.0

33
SOURCES/dovecot-2.2.36-cve2019_11500_part2of4.patch

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
From a56b0636b1bf9c7677c6fca9681f48752af700a1 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Fri, 17 May 2019 10:33:53 +0300
Subject: [PATCH 2/2] lib-imap: Make sure str_unescape() won't be writing past
allocated memory

The previous commit should already prevent this, but this makes sure it
can't become broken in the future either. It makes the performance a tiny
bit worse, but that's not practically noticeable.
---
src/lib-imap/imap-parser.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c
index f41668d7a..7f58d99e2 100644
--- a/src/lib-imap/imap-parser.c
+++ b/src/lib-imap/imap-parser.c
@@ -267,10 +267,8 @@ static void imap_parser_save_arg(struct imap_parser *parser,
/* remove the escapes */
if (parser->str_first_escape >= 0 &&
- (parser->flags & IMAP_PARSE_FLAG_NO_UNESCAPE) == 0) {
- /* -1 because we skipped the '"' prefix */
- (void)str_unescape(str + parser->str_first_escape-1);
- }
+ (parser->flags & IMAP_PARSE_FLAG_NO_UNESCAPE) == 0)
+ (void)str_unescape(str);
arg->_data.str = str;
arg->str_len = strlen(str);
break;
--
2.11.0

36
SOURCES/dovecot-2.2.36-cve2019_11500_part3of4.patch

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
From 7ce9990a5e6ba59e89b7fe1c07f574279aed922c Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Fri, 10 May 2019 19:43:55 +0300
Subject: [PATCH 1/2] lib-managesieve: Don't accept strings with NULs

ManageSieve doesn't allow NULs in strings.

This fixes a bug with unescaping a string with NULs: str_unescape() could
have been called for memory that points outside the allocated string,
causing heap corruption. This could cause crashes or theoretically even
result in remote code execution exploit.

Found by Nick Roessler and Rafi Rubin
---
src/lib-managesieve/managesieve-parser.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/src/lib-managesieve/managesieve-parser.c b/src/lib-managesieve/managesieve-parser.c
index d3eb2101..f5f9d323 100644
--- a/src/lib-managesieve/managesieve-parser.c
+++ b/src/lib-managesieve/managesieve-parser.c
@@ -258,6 +258,11 @@ managesieve_parser_read_string(struct managesieve_parser *parser,
break;
}
+ if (data[i] == '\0') {
+ parser->error = "NULs not allowed in strings";
+ return FALSE;
+ }
+
if (data[i] == '\\') {
if (i+1 == data_size) {
/* known data ends with '\' - leave it to
--
2.11.0

33
SOURCES/dovecot-2.2.36-cve2019_11500_part4of4.patch

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
From 4a299840cdb51f61f8d1ebc0210b19c40dfbc1cc Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Fri, 17 May 2019 10:39:25 +0300
Subject: [PATCH 2/2] lib-managesieve: Make sure str_unescape() won't be
writing past allocated memory

The previous commit should already prevent this, but this makes sure it
can't become broken in the future either. It makes the performance a tiny
bit worse, but that's not practically noticeable.
---
src/lib-managesieve/managesieve-parser.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/lib-managesieve/managesieve-parser.c b/src/lib-managesieve/managesieve-parser.c
index f5f9d323..dc7d1fa9 100644
--- a/src/lib-managesieve/managesieve-parser.c
+++ b/src/lib-managesieve/managesieve-parser.c
@@ -169,10 +169,8 @@ static void managesieve_parser_save_arg(struct managesieve_parser *parser,
/* remove the escapes */
if (parser->str_first_escape >= 0 &&
- (parser->flags & MANAGESIEVE_PARSE_FLAG_NO_UNESCAPE) == 0) {
- /* -1 because we skipped the '"' prefix */
- str_unescape(str + parser->str_first_escape-1);
- }
+ (parser->flags & MANAGESIEVE_PARSE_FLAG_NO_UNESCAPE) == 0)
+ (void)str_unescape(str);
arg->_data.str = str;
arg->str_len = strlen(str);
--
2.11.0

69
SOURCES/dovecot-2.2.36-cve_2019_3814part1of3.patch

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
From eb5ffe2641febe0fa5e9038f2e216c130e1e7519 Mon Sep 17 00:00:00 2001
From: Aki Tuomi <aki.tuomi@open-xchange.com>
Date: Mon, 21 Jan 2019 11:36:30 +0200
Subject: [PATCH] login-common: Ensure we get username from certificate

---
src/login-common/sasl-server.c | 42 ++++++++++++++++++++++++++++++++--
1 file changed, 40 insertions(+), 2 deletions(-)

diff --git a/src/login-common/sasl-server.c b/src/login-common/sasl-server.c
index a833c9a6d4..9465da9657 100644
--- a/src/login-common/sasl-server.c
+++ b/src/login-common/sasl-server.c
@@ -321,6 +321,37 @@ authenticate_callback(struct auth_client_request *request,
}
}
+static bool get_cert_username(struct client *client, const char **username_r,
+ const char **error_r)
+{
+ /* no SSL */
+ if (client->ssl_proxy == NULL) {
+ *username_r = NULL;
+ return TRUE;
+ }
+
+ /* no client certificate */
+ if (!ssl_proxy_has_valid_client_cert(client->ssl_proxy)) {
+ *username_r = NULL;
+ return TRUE;
+ }
+
+ /* get peer name */
+ const char *username = ssl_proxy_get_peer_name(client->ssl_proxy);
+
+ /* if we wanted peer name, but it was not there, fail */
+ if (client->set->auth_ssl_username_from_cert &&
+ (username == NULL || *username == '\0')) {
+ if (client->set->auth_ssl_require_client_cert) {
+ *error_r = "Missing username in certificate";
+ return FALSE;
+ }
+ }
+
+ *username_r = username;
+ return TRUE;
+}
+
void sasl_server_auth_begin(struct client *client,
const char *service, const char *mech_name,
const char *initial_resp_base64,
@@ -359,8 +390,15 @@ void sasl_server_auth_begin(struct client *client,
info.mech = mech->name;
info.service = service;
info.session_id = client_get_session_id(client);
- info.cert_username = client->ssl_proxy == NULL ? NULL :
- ssl_proxy_get_peer_name(client->ssl_proxy);
+ if (client->set->auth_ssl_username_from_cert) {
+ const char *error;
+ if (!get_cert_username(client, &info.cert_username, &error)) {
+ client_log_err(client, t_strdup_printf("Cannot get username "
+ "from certificate: %s", error));
+ sasl_server_auth_failed(client, "Unable to validate certificate");
+ return;
+ }
+ }
info.flags = client_get_auth_flags(client);
info.local_ip = client->local_ip;
info.remote_ip = client->ip;

29
SOURCES/dovecot-2.2.36-cve_2019_3814part2of3.patch

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
From 7525fece60f01b52deb13df3620976ee1d616837 Mon Sep 17 00:00:00 2001
From: Aki Tuomi <aki.tuomi@open-xchange.com>
Date: Mon, 21 Jan 2019 10:54:06 +0200
Subject: [PATCH] auth: Fail authentication if certificate username was
unexpectedly missing

---
src/auth/auth-request-handler.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/src/auth/auth-request-handler.c b/src/auth/auth-request-handler.c
index 617dc1883d..3044e94f91 100644
--- a/src/auth/auth-request-handler.c
+++ b/src/auth/auth-request-handler.c
@@ -560,6 +560,14 @@ bool auth_request_handler_auth_begin(struct auth_request_handler *handler,
return TRUE;
}
+ if (request->set->ssl_require_client_cert &&
+ request->set->ssl_username_from_cert &&
+ !request->cert_username) {
+ auth_request_handler_auth_fail(handler, request,
+ "SSL certificate didn't contain username");
+ return TRUE;
+ }
+
/* Empty initial response is a "=" base64 string. Completely empty
string shouldn't really be sent, but at least Exim does it,
so just allow it for backwards compatibility.. */

22
SOURCES/dovecot-2.2.36-cve_2019_3814part3of3.patch

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
From e5d428297d70e3ac8b6dfce7e0de182b86825082 Mon Sep 17 00:00:00 2001
From: Aki Tuomi <aki.tuomi@open-xchange.com>
Date: Wed, 16 Jan 2019 18:28:57 +0200
Subject: [PATCH] auth: Do not import empty certificate username

---
src/auth/auth-request.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c
index dd288b6d23..1cb665ec8c 100644
--- a/src/auth/auth-request.c
+++ b/src/auth/auth-request.c
@@ -445,7 +445,7 @@ bool auth_request_import_auth(struct auth_request *request,
else if (strcmp(key, "valid-client-cert") == 0)
request->valid_client_cert = TRUE;
else if (strcmp(key, "cert_username") == 0) {
- if (request->set->ssl_username_from_cert) {
+ if (request->set->ssl_username_from_cert && *value != '\0') {
/* get username from SSL certificate. it overrides
the username given by the auth mechanism. */
request->user = p_strdup(request->pool, value);

32
SOURCES/dovecot-2.2.36-cve_2019_7524part1of2.patch

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
From fcd786753b2ba6b4fb82cc2affea8e0d61889c95 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 4 Feb 2019 19:23:02 -0800
Subject: [PATCH] lib-storage: Fix buffer overflow when reading oversized
hdr-pop3-uidl header

---
src/lib-storage/index/index-pop3-uidl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/lib-storage/index/index-pop3-uidl.c b/src/lib-storage/index/index-pop3-uidl.c
index 13b7363ef6..e537e9ff51 100644
--- a/src/lib-storage/index/index-pop3-uidl.c
+++ b/src/lib-storage/index/index-pop3-uidl.c
@@ -37,7 +37,7 @@ bool index_pop3_uidl_can_exist(struct mail *mail)
/* this header isn't set yet */
return TRUE;
}
- memcpy(&uidl, data, size);
+ memcpy(&uidl, data, sizeof(uidl));
return mail->uid <= uidl.max_uid_with_pop3_uidl;
}
@@ -95,7 +95,7 @@ void index_pop3_uidl_update_exists_finish(struct mailbox_transaction_context *tr
/* check if we have already the same header */
if (size >= sizeof(uidl)) {
- memcpy(&uidl, data, size);
+ memcpy(&uidl, data, sizeof(uidl));
if (trans->highest_pop3_uidl_uid == uidl.max_uid_with_pop3_uidl)
return;
}

22
SOURCES/dovecot-2.2.36-cve_2019_7524part2of2.patch

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
From df17cee615377f2474c86eb6a5b3fe5caa8b70fe Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 4 Feb 2019 19:25:13 -0800
Subject: [PATCH] fts: Fix buffer overflow when reading oversized fts header

---
src/plugins/fts/fts-api.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/plugins/fts/fts-api.c b/src/plugins/fts/fts-api.c
index 5a5b2a919e..4f8a1c125d 100644
--- a/src/plugins/fts/fts-api.c
+++ b/src/plugins/fts/fts-api.c
@@ -425,7 +425,7 @@ bool fts_index_get_header(struct mailbox *box, struct fts_index_header *hdr_r)
i_zero(hdr_r);
ret = FALSE;
} else {
- memcpy(hdr_r, data, data_size);
+ memcpy(hdr_r, data, sizeof(*hdr_r));
ret = TRUE;
}
mail_index_view_close(&view);

11
SOURCES/dovecot-2.2.36-portreserve.patch

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
diff -up dovecot-2.2.36/dovecot.service.in.portreserve dovecot-2.2.36/dovecot.service.in
--- dovecot-2.2.36/dovecot.service.in.portreserve 2019-08-13 13:16:17.660982741 +0200
+++ dovecot-2.2.36/dovecot.service.in 2019-08-13 13:16:17.664982728 +0200
@@ -13,6 +13,7 @@ After=local-fs.target network.target net
[Service]
Type=forking
ExecStartPre=/usr/libexec/dovecot/prestartscript
+ExecStartPre=-/usr/sbin/portrelease dovecot
ExecStart=@sbindir@/dovecot
PIDFile=@rundir@/master.pid
ExecReload=@bindir@/doveadm reload

2432
SOURCES/dovecot-2.3.8-CVE_2020_12100.patch

File diff suppressed because it is too large Load Diff

56
SOURCES/dovecot-2.3.8-CVE_2020_12100ph.patch

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
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;

121
SOURCES/dovecot-2.3.8-CVE_2020_12100prereq.patch

@ -0,0 +1,121 @@ @@ -0,0 +1,121 @@
diff -up dovecot-2.2.36/src/lib/array.h.CVE_2020_12100prereq dovecot-2.2.36/src/lib/array.h
--- dovecot-2.2.36/src/lib/array.h.CVE_2020_12100prereq 2018-04-30 15:52:05.000000000 +0200
+++ dovecot-2.2.36/src/lib/array.h 2020-08-09 20:22:36.326347911 +0200
@@ -219,6 +219,15 @@ array_idx_i(const struct array *array, u
i_assert(idx * array->element_size < array->buffer->used);
return CONST_PTR_OFFSET(array->buffer->data, idx * array->element_size);
}
+
+#define array_front(array) array_idx(array, 0)
+#define array_front_modifiable(array) array_idx_modifiable(array, 0)
+#define array_back(array) array_idx(array, array_count(array)-1)
+#define array_back_modifiable(array) array_idx_modifiable(array, array_count(array)-1)
+#define array_pop_back(array) array_delete(array, array_count(array)-1, 1);
+#define array_push_back(array, item) array_append(array, (item), 1)
+#define array_pop_front(array) array_delete(array, 0, 1)
+#define array_push_front(array, item) array_insert(array, 0, (item), 1)
#define array_idx(array, idx) \
ARRAY_TYPE_CAST_CONST(array)array_idx_i(&(array)->arr, idx)
diff -up dovecot-2.2.36/src/lib/buffer.c.CVE_2020_12100prereq dovecot-2.2.36/src/lib/buffer.c
--- dovecot-2.2.36/src/lib/buffer.c.CVE_2020_12100prereq 2020-08-09 20:22:57.566465762 +0200
+++ dovecot-2.2.36/src/lib/buffer.c 2020-08-09 20:22:57.580465840 +0200
@@ -148,6 +148,10 @@ void buffer_free(buffer_t **_buf)
{
struct real_buffer *buf = (struct real_buffer *)*_buf;
+
+ if (buf == NULL)
+ return;
+
*_buf = NULL;
if (buf->alloced)
p_free(buf->pool, buf->w_buffer);
diff -up dovecot-2.2.36/src/lib-mail/test-message-decoder.c.CVE_2020_12100prereq dovecot-2.2.36/src/lib-mail/test-message-decoder.c
--- dovecot-2.2.36/src/lib-mail/test-message-decoder.c.CVE_2020_12100prereq 2018-04-30 15:52:05.000000000 +0200
+++ dovecot-2.2.36/src/lib-mail/test-message-decoder.c 2020-08-09 20:22:36.326347911 +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 (*test_functions[])(void) = {
test_message_decoder,
+ //test_message_decoder_multipart,
test_message_decoder_current_content_type,
NULL
};

34
SOURCES/dovecot-2.3.8-CVE_2020_12673.patch

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
From 1c6405d3026e5ceae3d214d63945bba85251af4c Mon Sep 17 00:00:00 2001
From: Aki Tuomi <aki.tuomi@open-xchange.com>
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 1;
+ if (length > data_size) {
+ *error = "buffer length out of bounds";
+ return 0;
+ }
+
if (offset >= data_size) {
*error = "buffer offset out of bounds";
return 0;
--
2.11.0

237
SOURCES/dovecot-2.3.8-CVE_2020_12674.patch

@ -0,0 +1,237 @@ @@ -0,0 +1,237 @@
From bd9d2fe7da833f0e4705a8280efc56930371806b Mon Sep 17 00:00:00 2001
From: Aki Tuomi <aki.tuomi@open-xchange.com>
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 <aki.tuomi@open-xchange.com>
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,199 @@
+/* Copyright (c) 2020 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "auth.h"
+#include "array.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 <unistd.h>
+#include <time.h>
+
+#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)
+{
+ 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
+ };
+ lib_init();
+ test_mechs_init();
+ int ret = test_run(test_functions);
+ mech_register_deinit(&mech_reg);
+ return ret;
+}

818
SOURCES/dovecot-2.3.8-CVE_2020_12674prereq.patch

@ -0,0 +1,818 @@ @@ -0,0 +1,818 @@
diff -up dovecot-2.2.36/src/auth/auth-request.c.CVE_2020_12674prereq dovecot-2.2.36/src/auth/auth-request.c
--- dovecot-2.2.36/src/auth/auth-request.c.CVE_2020_12674prereq 2020-08-09 14:37:53.468591087 +0200
+++ dovecot-2.2.36/src/auth/auth-request.c 2020-08-09 14:37:53.482591165 +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"
@@ -68,9 +69,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
@@ -211,10 +209,12 @@ void auth_request_success_continue(struc
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);
@@ -228,8 +228,10 @@ void auth_request_fail(struct auth_reque
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);
@@ -989,7 +991,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);
@@ -1036,7 +1038,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;
@@ -1046,9 +1049,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;
diff -up dovecot-2.2.36/src/auth/auth-request-handler.c.CVE_2020_12674prereq dovecot-2.2.36/src/auth/auth-request-handler.c
--- dovecot-2.2.36/src/auth/auth-request-handler.c.CVE_2020_12674prereq 2020-08-09 14:37:53.467591082 +0200
+++ dovecot-2.2.36/src/auth/auth-request-handler.c 2020-08-09 14:37:53.482591165 +0200
@@ -16,32 +16,29 @@
#include "auth-token.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;
-
- unsigned int destroyed:1;
- unsigned int 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,
@@ -60,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;
}
@@ -342,6 +345,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;
@@ -394,6 +407,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);
}
@@ -657,6 +678,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.2.36/src/auth/auth-request-handler.h.CVE_2020_12674prereq dovecot-2.2.36/src/auth/auth-request-handler.h
--- dovecot-2.2.36/src/auth/auth-request-handler.h.CVE_2020_12674prereq 2017-06-23 13:18:28.000000000 +0200
+++ dovecot-2.2.36/src/auth/auth-request-handler.h 2020-08-09 14:37:53.482591165 +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.2.36/src/auth/auth-request-handler-private.h.CVE_2020_12674prereq dovecot-2.2.36/src/auth/auth-request-handler-private.h
--- dovecot-2.2.36/src/auth/auth-request-handler-private.h.CVE_2020_12674prereq 2020-08-09 14:37:53.482591165 +0200
+++ dovecot-2.2.36/src/auth/auth-request-handler-private.h 2020-08-09 14:37:53.482591165 +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.2.36/src/auth/auth-request.h.CVE_2020_12674prereq dovecot-2.2.36/src/auth/auth-request.h
--- dovecot-2.2.36/src/auth/auth-request.h.CVE_2020_12674prereq 2018-04-30 15:52:05.000000000 +0200
+++ dovecot-2.2.36/src/auth/auth-request.h 2020-08-09 14:37:53.482591165 +0200
@@ -269,6 +269,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 -up dovecot-2.2.36/src/auth/Makefile.am.CVE_2020_12674prereq dovecot-2.2.36/src/auth/Makefile.am
--- dovecot-2.2.36/src/auth/Makefile.am.CVE_2020_12674prereq 2018-04-30 15:52:05.000000000 +0200
+++ dovecot-2.2.36/src/auth/Makefile.am 2020-08-09 14:37:53.482591165 +0200
@@ -227,7 +227,8 @@ test_programs = \
test-auth-cache \
test-auth-request-var-expand \
test-username-filter \
- test-db-dict
+ test-db-dict \
+ test-mech
noinst_PROGRAMS = $(test_programs)
@@ -253,6 +254,13 @@ test_db_dict_SOURCES = test-db-dict.c
test_db_dict_LDADD = $(test_libs) libauth.la
test_db_dict_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: check-am check-test
check-test: all-am
for bin in $(test_programs); do \
diff -up dovecot-2.2.36/src/auth/passdb.h.CVE_2020_12674prereq dovecot-2.2.36/src/auth/passdb.h
--- dovecot-2.2.36/src/auth/passdb.h.CVE_2020_12674prereq 2018-04-30 15:52:05.000000000 +0200
+++ dovecot-2.2.36/src/auth/passdb.h 2020-08-09 14:37:53.482591165 +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.2.36/src/auth/test-auth.h.CVE_2020_12674prereq dovecot-2.2.36/src/auth/test-auth.h
--- dovecot-2.2.36/src/auth/test-auth.h.CVE_2020_12674prereq 2020-08-09 14:38:24.950765769 +0200
+++ dovecot-2.2.36/src/auth/test-auth.h 2020-08-09 14:38:06.304662311 +0200
@@ -0,0 +1,21 @@
+/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
+
+#ifndef TEST_AUTH_H
+#define TEST_AUTH_H 1
+
+#include "lib.h"
+#include "test-common.h"
+
+struct auth_passdb;
+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);
+void test_db_lua(void);
+struct auth_passdb *passdb_mock(void);
+void passdb_mock_mod_init(void);
+void passdb_mock_mod_deinit(void);
+
+#endif
+
diff -up dovecot-2.2.36/src/auth/test-mock.c.CVE_2020_12674prereq dovecot-2.2.36/src/auth/test-mock.c
--- dovecot-2.2.36/src/auth/test-mock.c.CVE_2020_12674prereq 2020-08-09 14:37:53.483591170 +0200
+++ dovecot-2.2.36/src/auth/test-mock.c 2020-08-09 14:37:53.483591170 +0200
@@ -0,0 +1,109 @@
+/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
+
+#include "test-auth.h"
+#include "auth-common.h"
+#include "passdb.h"
+
+struct auth_penalty *auth_penalty;
+time_t process_start_time;
+bool worker, worker_restart_request;
+static struct passdb_module *mock_passdb_mod = NULL;
+static pool_t mock_pool;
+
+void auth_module_load(const char *names ATTR_UNUSED)
+{
+}
+void auth_refresh_proctitle(void) {
+}
+
+static void passdb_mock_init(struct passdb_module *module ATTR_UNUSED)
+{
+}
+static void passdb_mock_deinit(struct passdb_module *module ATTR_UNUSED)
+{
+}
+static void passdb_mock_verify_plain(struct auth_request *request, const char *password ATTR_UNUSED,
+ verify_plain_callback_t *callback)
+{
+ 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,
+};
+
+struct auth_passdb_settings mock_passdb_set = {
+ .name = "mock",
+ .driver = "mock",
+ .args = "",
+ .default_fields = "",
+ .override_fields = "",
+ .mechanisms = "",
+ .username_filter = "",
+ .skip = "never",
+ .result_success = "return-ok",
+ .result_failure = "continue",
+ .result_internalfail = "continue",
+ .deny = FALSE,
+ .pass = FALSE,
+ .master = FALSE,
+ .auth_verbose = "default"
+};
+
+void passdb_mock_mod_init(void)
+{
+ if (mock_passdb_mod != NULL)
+ return;
+
+ mock_pool = pool_allocfree_create("auth mock");
+
+ passdb_register_module(&mock_interface);
+
+ struct auth_passdb_settings set = {
+ .name = "mock",
+ .driver = "mock",
+ .args = "",
+ .default_fields = "",
+ .override_fields = "",
+ .mechanisms = "",
+ .username_filter = "",
+
+ .skip = "never",
+ .result_success = "return-ok",
+ .result_failure = "continue",
+ .result_internalfail = "continue",
+
+ .deny = FALSE,
+ .pass = FALSE,
+ .master = FALSE,
+ .auth_verbose = "default"
+ };
+ mock_passdb_mod = passdb_preinit(mock_pool, &set);
+ passdb_init(mock_passdb_mod);
+}
+
+void passdb_mock_mod_deinit(void)
+{
+ passdb_deinit(mock_passdb_mod);
+ passdb_unregister_module(&mock_interface);
+ pool_unref(&mock_pool);
+}
+
+struct auth_passdb *passdb_mock(void)
+{
+ struct auth_passdb *ret = i_new(struct auth_passdb, 1);
+ ret->set = &mock_passdb_set;
+ ret->passdb = mock_passdb_mod;
+ return ret;
+}
diff -up dovecot-2.2.36/src/lib/lib.c.CVE_2020_12674prereq dovecot-2.2.36/src/lib/lib.c
--- dovecot-2.2.36/src/lib/lib.c.CVE_2020_12674prereq 2018-04-30 15:52:05.000000000 +0200
+++ dovecot-2.2.36/src/lib/lib.c 2020-08-09 14:37:53.483591170 +0200
@@ -175,7 +175,7 @@ void lib_init(void)
hostpid_init();
lib_open_non_stdio_dev_null();
var_expand_extensions_init();
-
+ random_init();
lib_initialized = TRUE;
}
diff -up dovecot-2.2.36/src/lib/lib.h.CVE_2020_12674prereq dovecot-2.2.36/src/lib/lib.h
--- dovecot-2.2.36/src/lib/lib.h.CVE_2020_12674prereq 2020-08-24 14:42:44.084069002 +0200
+++ dovecot-2.2.36/src/lib/lib.h 2020-08-24 14:42:44.108068770 +0200
@@ -33,6 +33,7 @@
#include "imem.h"
#include "byteorder.h"
#include "rand.h"
+#include "randgen.h"
typedef struct buffer buffer_t;
typedef struct buffer string_t;
diff -up dovecot-2.2.36/src/lib/Makefile.am.CVE_2020_12674prereq dovecot-2.2.36/src/lib/Makefile.am
--- dovecot-2.2.36/src/lib/Makefile.am.CVE_2020_12674prereq 2020-08-09 14:37:53.464591065 +0200
+++ dovecot-2.2.36/src/lib/Makefile.am 2020-08-09 14:37:53.483591170 +0200
@@ -98,6 +98,7 @@ liblib_la_SOURCES = \
md4.c \
md5.c \
mempool.c \
+ mempool-allocfree.c \
mempool-alloconly.c \
mempool-datastack.c \
mempool-system.c \
diff -up dovecot-2.2.36/src/lib/mempool-allocfree.c.CVE_2020_12674prereq dovecot-2.2.36/src/lib/mempool-allocfree.c
--- dovecot-2.2.36/src/lib/mempool-allocfree.c.CVE_2020_12674prereq 2020-08-09 14:37:53.483591170 +0200
+++ dovecot-2.2.36/src/lib/mempool-allocfree.c 2020-08-09 14:37:53.483591170 +0200
@@ -0,0 +1,328 @@
+/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
+
+/* @UNSAFE: whole file */
+#include "lib.h"
+#include "safe-memset.h"
+#include "mempool.h"
+#include "llist.h"
+
+/*
+ * As the name implies, allocfree pools support both allocating and freeing
+ * memory.
+ *
+ * Implementation
+ * ==============
+ *
+ * Each allocfree pool contains a pool structure (struct allocfree_pool) to
+ * keep track of allocfree-specific pool information and zero or more blocks
+ * (struct pool_block) that keep track of ranges of memory used to back the
+ * allocations. The blocks are kept in a doubly-linked list used to keep
+ * track of all allocations that belong to the pool.
+ *
+ * +-----------+
+ * | allocfree |
+ * | pool |
+ * +-----+-----+
+ * |
+ * | blocks +------------+ next +------------+ next
+ * \------->| pool block |<=====>| pool block |<=====>...<====> NULL
+ * +------------+ prev +------------+ prev
+ * | <data> | | <data> |
+ * . .
+ * . .
+ * . | <data> |
+ * . +------------+
+ * | <data> |
+ * +------------+
+ *
+ * Creation
+ * --------
+ *
+ * When an allocfree pool is created the linked list of allocated blocks is
+ * initialized to be empty.
+ *
+ * Allocation & Freeing
+ * --------------------
+ *
+ * Since each allocation (via p_malloc()) corresponds to one block,
+ * allocations are simply a matter of:
+ *
+ * - allocating enough memory from the system heap (via calloc()) to hold
+ * the block header and the requested number of bytes,
+ * - making a note of the user-requested size in the block header,
+ * - adding the new block to the pool's linked list of blocks, and
+ * - returning a pointer to the payload area of the block to the caller.
+ *
+ * Freeing memory is simpler. The passed in pointer is converted to a
+ * struct pool_block pointer. Then the block is removed from the pool's
+ * linked list and free()d.
+ *
+ * If the pool was created via pool_allocfree_create_clean(), all blocks are
+ * safe_memset() to zero just before being free()d.
+ *
+ * Reallocation
+ * ------------
+ *
+ * Reallocation is done by calling realloc() with a new size that is large
+ * enough to cover the requested number of bytes plus the block header
+ * overhead.
+ *
+ * Clearing
+ * --------
+ *
+ * Clearing the pool is supposed to return the pool to the same state it was
+ * in when it was first created. To that end, the allocfree pool frees all
+ * the blocks allocated since the pool's creation. In other words, clearing
+ * is equivalent to (but faster than) calling p_free() for each allocation
+ * in the pool.
+ *
+ * Finally, if the pool was created via pool_allocfree_create_clean(), all
+ * blocks are safe_memset() to zero before being free()d.
+ *
+ * Destruction
+ * -----------
+ *
+ * Destroying a pool first clears it (see above) and then the pool structure
+ * itself is safe_memset() to zero (if pool_allocfree_create_clean() was
+ * used) and free()d. (The clearing leaves the pool in a minimal state
+ * with no blocks allocated.)
+ */
+
+struct allocfree_pool {
+ struct pool pool;
+ int refcount;
+ size_t total_alloc_count;
+ size_t total_alloc_used;
+
+ struct pool_block *blocks;
+#ifdef DEBUG
+ char *name;
+#endif
+ bool clean_frees;
+};
+
+struct pool_block {
+ struct pool_block *prev,*next;
+
+ size_t size;
+ unsigned char *block;
+};
+
+#define SIZEOF_ALLOCFREE_POOL MEM_ALIGN(sizeof(struct allocfree_pool))
+#define SIZEOF_POOLBLOCK (MEM_ALIGN(sizeof(struct pool_block)))
+
+static const char *pool_allocfree_get_name(pool_t pool);
+static void pool_allocfree_ref(pool_t pool);
+static void pool_allocfree_unref(pool_t *pool);
+static void *pool_allocfree_malloc(pool_t pool, size_t size);
+static void pool_allocfree_free(pool_t pool, void *mem);
+static void *pool_allocfree_realloc(pool_t pool, void *mem,
+ size_t old_size, size_t new_size);
+static void pool_allocfree_clear(pool_t pool);
+static size_t pool_allocfree_get_max_easy_alloc_size(pool_t pool);
+
+static const struct pool_vfuncs static_allocfree_pool_vfuncs = {
+ pool_allocfree_get_name,
+
+ pool_allocfree_ref,
+ pool_allocfree_unref,
+
+ pool_allocfree_malloc,
+ pool_allocfree_free,
+
+ pool_allocfree_realloc,
+
+ pool_allocfree_clear,
+ pool_allocfree_get_max_easy_alloc_size
+};
+
+static const struct pool static_allocfree_pool = {
+ .v = &static_allocfree_pool_vfuncs,
+
+ .alloconly_pool = FALSE,
+ .datastack_pool = FALSE
+};
+
+pool_t pool_allocfree_create(const char *name ATTR_UNUSED)
+{
+ struct allocfree_pool *pool;
+
+ if (SIZEOF_POOLBLOCK > (SSIZE_T_MAX - POOL_MAX_ALLOC_SIZE))
+ i_panic("POOL_MAX_ALLOC_SIZE is too large");
+
+ pool = calloc(1, SIZEOF_ALLOCFREE_POOL);
+ if (pool == NULL)
+ i_fatal_status(FATAL_OUTOFMEM, "calloc(1, %"PRIuSIZE_T"): Out of memory",
+ SIZEOF_ALLOCFREE_POOL);
+#ifdef DEBUG
+ pool->name = strdup(name);
+#endif
+ pool->pool = static_allocfree_pool;
+ pool->refcount = 1;
+ return &pool->pool;
+}
+
+pool_t pool_allocfree_create_clean(const char *name)
+{
+ struct allocfree_pool *apool;
+ pool_t pool;
+
+ pool = pool_allocfree_create(name);
+ apool = (struct allocfree_pool *)pool;
+ apool->clean_frees = TRUE;
+ return pool;
+}
+
+static void pool_allocfree_destroy(struct allocfree_pool *apool)
+{
+ pool_allocfree_clear(&apool->pool);
+ if (apool->clean_frees)
+ safe_memset(apool, 0, SIZEOF_ALLOCFREE_POOL);
+#ifdef DEBUG
+ free(apool->name);
+#endif
+ free(apool);
+}
+
+static const char *pool_allocfree_get_name(pool_t pool ATTR_UNUSED)
+{
+#ifdef DEBUG
+ struct allocfree_pool *apool =
+ container_of(pool, struct allocfree_pool, pool);
+ return apool->name;
+#else
+ return "alloc";
+#endif
+}
+
+static void pool_allocfree_ref(pool_t pool)
+{
+ struct allocfree_pool *apool =
+ container_of(pool, struct allocfree_pool, pool);
+ i_assert(apool->refcount > 0);
+
+ apool->refcount++;
+}
+
+static void pool_allocfree_unref(pool_t *_pool)
+{
+ pool_t pool = *_pool;
+ struct allocfree_pool *apool =
+ container_of(pool, struct allocfree_pool, pool);
+ i_assert(apool->refcount > 0);
+
+ /* erase the pointer before freeing anything, as the pointer may
+ exist inside the pool's memory area */
+ *_pool = NULL;
+
+ if (--apool->refcount > 0)
+ return;
+
+ pool_allocfree_destroy(apool);
+}
+
+static void *pool_block_attach(struct allocfree_pool *apool, struct pool_block *block)
+{
+ i_assert(block->size > 0);
+ DLLIST_PREPEND(&apool->blocks, block);
+ block->block = PTR_OFFSET(block,SIZEOF_POOLBLOCK);
+ apool->total_alloc_used += block->size;
+ apool->total_alloc_count++;
+ return block->block;
+}
+
+static struct pool_block *
+pool_block_detach(struct allocfree_pool *apool, unsigned char *mem)
+{
+ struct pool_block *block = PTR_OFFSET(mem, -SIZEOF_POOLBLOCK);
+
+ /* make sure the block we are dealing with is correct */
+ i_assert(block->block == mem);
+ i_assert((block->prev == NULL || block->prev->next == block) &&
+ (block->next == NULL || block->next->prev == block));
+
+ i_assert(apool->total_alloc_used >= block->size);
+ i_assert(apool->total_alloc_count > 0);
+ DLLIST_REMOVE(&apool->blocks, block);
+ apool->total_alloc_used -= block->size;
+ apool->total_alloc_count--;
+
+ return block;
+}
+
+static void *pool_allocfree_malloc(pool_t pool, size_t size)
+{
+ struct allocfree_pool *apool =
+ container_of(pool, struct allocfree_pool, pool);
+
+ struct pool_block *block = calloc(1, SIZEOF_POOLBLOCK + size);
+ if (block == NULL)
+ i_fatal_status(FATAL_OUTOFMEM, "calloc(1, %"PRIuSIZE_T"): Out of memory",
+ SIZEOF_POOLBLOCK + size);
+ block->size = size;
+ return pool_block_attach(apool, block);
+}
+
+static void pool_allocfree_free(pool_t pool, void *mem)
+{
+ struct allocfree_pool *apool =
+ container_of(pool, struct allocfree_pool, pool);
+ struct pool_block *block = pool_block_detach(apool, mem);
+ if (apool->clean_frees)
+ safe_memset(block, 0, SIZEOF_POOLBLOCK+block->size);
+ free(block);
+}
+
+static void *pool_allocfree_realloc(pool_t pool, void *mem,
+ size_t old_size, size_t new_size)
+{
+ struct allocfree_pool *apool =
+ container_of(pool, struct allocfree_pool, pool);
+ unsigned char *new_mem;
+
+ struct pool_block *block = pool_block_detach(apool, mem);
+ if ((new_mem = realloc(block, SIZEOF_POOLBLOCK+new_size)) == NULL)
+ i_fatal_status(FATAL_OUTOFMEM, "realloc(block, %"PRIuSIZE_T")",
+ SIZEOF_POOLBLOCK+new_size);
+
+ /* zero out new memory */
+ if (new_size > old_size)
+ memset(new_mem + SIZEOF_POOLBLOCK + old_size, 0,
+ new_size - old_size);
+ block = (struct pool_block*)new_mem;
+ block->size = new_size;
+ return pool_block_attach(apool, block);
+}
+
+static void pool_allocfree_clear(pool_t pool)
+{
+ struct allocfree_pool *apool =
+ container_of(pool, struct allocfree_pool, pool);
+ struct pool_block *block, *next;
+
+ for (block = apool->blocks; block != NULL; block = next) {
+ next = block->next;
+ pool_allocfree_free(pool, block->block);
+ }
+ i_assert(apool->total_alloc_used == 0 && apool->total_alloc_count == 0);
+}
+
+static size_t pool_allocfree_get_max_easy_alloc_size(pool_t pool ATTR_UNUSED)
+{
+ return 0;
+}
+
+size_t pool_allocfree_get_total_used_size(pool_t pool)
+{
+ struct allocfree_pool *apool =
+ container_of(pool, struct allocfree_pool, pool);
+ return apool->total_alloc_used;
+}
+
+size_t pool_allocfree_get_total_alloc_size(pool_t pool)
+{
+ struct allocfree_pool *apool =
+ container_of(pool, struct allocfree_pool, pool);
+ return apool->total_alloc_used +
+ SIZEOF_POOLBLOCK*apool->total_alloc_count + sizeof(*apool);
+}
diff -up dovecot-2.2.36/src/lib/mempool.h.CVE_2020_12674prereq dovecot-2.2.36/src/lib/mempool.h
--- dovecot-2.2.36/src/lib/mempool.h.CVE_2020_12674prereq 2018-04-30 15:52:05.000000000 +0200
+++ dovecot-2.2.36/src/lib/mempool.h 2020-08-09 14:37:53.483591170 +0200
@@ -10,6 +10,11 @@
pools to disable the warning. */
#define MEMPOOL_GROWING "GROWING-"
+/* The maximum allocation size that's allowed. Anything larger than that
+ will panic. No pool ever should need more than 4kB of overhead per
+ allocation. */
+#define POOL_MAX_ALLOC_SIZE (SSIZE_T_MAX - 4096)
+
/* Memory allocated and reallocated (the new data in it) in pools is always
zeroed, it will cost only a few CPU cycles and may well save some debug
time. */
@@ -63,6 +68,10 @@ pool_t pool_alloconly_create(const char
needed. */
pool_t pool_alloconly_create_clean(const char *name, size_t size);
+/* Create new alloc pool. This is very similar to system pool, but it
+ will deallocate all memory on deinit. */
+pool_t pool_allocfree_create(const char *name);
+
/* When allocating memory from returned pool, the data stack frame must be
the same as it was when calling this function. pool_unref() also checks
that the stack frame is the same. This should make it quite safe to use. */

1
SOURCES/dovecot.init

@ -105,3 +105,4 @@ case "$1" in @@ -105,3 +105,4 @@ case "$1" in
esac

exit $RETVAL


5
SOURCES/dovecot.portreserve

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
imap/tcp
imaps/tcp
pop3/tcp
pop3s/tcp
sieve/tcp

1
SOURCES/dovecot.tmpfilesd

@ -1 +1,2 @@ @@ -1 +1,2 @@
d /var/run/dovecot 0755 root dovecot -


3
SOURCES/prestartscript

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
#!/bin/sh
/bin/systemctl -q is-enabled NetworkManager.service >/dev/null 2>&1 && /usr/bin/nm-online -q --timeout 30 ||:

80
SPECS/dovecot.spec

@ -5,7 +5,7 @@ Name: dovecot @@ -5,7 +5,7 @@ Name: dovecot
Epoch: 1
Version: 2.2.36
%global prever %{nil}
Release: 3%{?dist}
Release: 8%{?dist}
#dovecot itself is MIT, a few sources are PD, pigeonhole is LGPLv2
License: MIT and LGPLv2
Group: System Environment/Daemons
@ -23,14 +23,14 @@ Source10: dovecot.tmpfilesd @@ -23,14 +23,14 @@ Source10: dovecot.tmpfilesd

#our own
Source14: dovecot.conf.5
Source15: prestartscript
Source16: dovecot.portreserve

# 3x Fedora/RHEL specific
Patch1: dovecot-2.0-defaultconfig.patch
Patch2: dovecot-1.0.beta2-mkcert-permissions.patch
Patch3: dovecot-1.0.rc7-mkcert-paths.patch

Patch5: dovecot-2.1-privatetmp.patch

#wait for network
Patch6: dovecot-2.1.10-waitonline.patch

@ -42,9 +42,26 @@ Patch9: dovecot-2.2.36-aclfix.patch @@ -42,9 +42,26 @@ Patch9: dovecot-2.2.36-aclfix.patch

# dovecot < 2.3, rhbz#1280436
Patch10: dovecot-2.2-gidcheck.patch


Source15: prestartscript
Patch11: dovecot-2.2.36-portreserve.patch
Patch12: dovecot-2.2.36-cve_2019_3814part1of3.patch
Patch13: dovecot-2.2.36-cve_2019_3814part2of3.patch
Patch14: dovecot-2.2.36-cve_2019_3814part3of3.patch
Patch15: dovecot-2.2.36-cve_2019_7524part1of2.patch
Patch16: dovecot-2.2.36-cve_2019_7524part2of2.patch

Patch19: dovecot-2.2.36-cve2019_11500_part1of4.patch
Patch20: dovecot-2.2.36-cve2019_11500_part2of4.patch
Patch21: dovecot-2.2.36-cve2019_11500_part3of4.patch
Patch22: dovecot-2.2.36-cve2019_11500_part4of4.patch
Patch23: dovecot-2.2.36-bigkey.patch

# from upstream, for dovecot <= 2.3.10.1
Patch24: dovecot-2.3.8-CVE_2020_12100prereq.patch
Patch25: dovecot-2.3.8-CVE_2020_12100.patch
Patch26: dovecot-2.3.8-CVE_2020_12100ph.patch
Patch27: dovecot-2.3.8-CVE_2020_12673.patch
Patch28: dovecot-2.3.8-CVE_2020_12674prereq.patch
Patch29: dovecot-2.3.8-CVE_2020_12674.patch

Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: openssl-devel, pam-devel, zlib-devel, bzip2-devel, xz-devel, libcap-devel
@ -77,6 +94,8 @@ Requires(preun): chkconfig initscripts @@ -77,6 +94,8 @@ Requires(preun): chkconfig initscripts
Requires(postun): initscripts
%endif

Requires: portreserve

%if %{?fedora}0 > 150 || %{?rhel}0 >60
#clucene in fedora <=15 and rhel<=6 is too old
BuildRequires: clucene-core-devel
@ -141,10 +160,30 @@ This package provides the development files for dovecot. @@ -141,10 +160,30 @@ This package provides the development files for dovecot.
%patch7 -p1 -b .nodevrand
%patch9 -p1 -b .aclfix
%patch10 -p1 -b .gidcheck
%patch11 -p1 -b .portreserve
%patch12 -p1 -b .cve_2019_3814part1of3
%patch13 -p1 -b .cve_2019_3814part2of3
%patch14 -p1 -b .cve_2019_3814part3of3
%patch15 -p1 -b .cve_2019_7524part1of2
%patch16 -p1 -b .cve_2019_7524part2of2
%patch19 -p1 -b .cve2019_11500_part1of4
%patch20 -p1 -b .cve2019_11500_part2of4
%patch23 -p1 -b .bigkey
sed -i '/DEFAULT_INCLUDES *=/s|$| '"$(pkg-config --cflags libclucene-core)|" src/plugins/fts-lucene/Makefile.in
#pigeonhole
pushd dovecot-2*2-pigeonhole-%{pigeonholever}
%patch21 -p1 -b .cve2019_11500_part3of4
%patch22 -p1 -b .cve2019_11500_part4of4
popd
%patch24 -p1 -b .CVE_2020_12100prereq
%patch25 -p1 -b .CVE_2020_12100
pushd dovecot-2*2-pigeonhole-%{pigeonholever}
%patch26 -p2 -b .CVE_2020_12100ph
popd
%patch27 -p1 -b .CVE_2020_12673
%patch28 -p1 -b .CVE_2020_12674prereq
%patch29 -p1 -b .CVE_2020_12674


%build
#required for fdpass.c line 125,190: dereferencing type-punned pointer will break strict-aliasing rules
@ -209,7 +248,6 @@ make install DESTDIR=$RPM_BUILD_ROOT @@ -209,7 +248,6 @@ make install DESTDIR=$RPM_BUILD_ROOT
#move doc dir back to build dir so doc macro in files section can use it
mv $RPM_BUILD_ROOT/%{_docdir}/%{name}-%{version} %{_builddir}/%{name}-%{version}%{?prever}/docinstall


pushd dovecot-2*2-pigeonhole-%{pigeonholever}
make install DESTDIR=$RPM_BUILD_ROOT

@ -231,6 +269,9 @@ install -p -D -m 644 %{SOURCE14} $RPM_BUILD_ROOT%{_mandir}/man5/dovecot.conf.5 @@ -231,6 +269,9 @@ install -p -D -m 644 %{SOURCE14} $RPM_BUILD_ROOT%{_mandir}/man5/dovecot.conf.5
#install waitonline script
install -p -D -m 755 %{SOURCE15} $RPM_BUILD_ROOT%{_libexecdir}/dovecot/prestartscript

# install portreserve dovecot config
install -p -D -m 644 %{SOURCE16} $RPM_BUILD_ROOT%{_sysconfdir}/portreserve/dovecot

# generate ghost .pem files
mkdir -p $RPM_BUILD_ROOT%{ssldir}/certs
mkdir -p $RPM_BUILD_ROOT%{ssldir}/private
@ -413,6 +454,7 @@ make check @@ -413,6 +454,7 @@ make check
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/auth-system.conf.ext
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/auth-vpopmail.conf.ext

%config(noreplace) %{_sysconfdir}/portreserve/dovecot
%config(noreplace) %{_sysconfdir}/pam.d/dovecot
%config(noreplace) %{ssldir}/dovecot-openssl.cnf

@ -517,6 +559,30 @@ make check @@ -517,6 +559,30 @@ make check


%changelog
* Mon Aug 24 2020 Michal Hlavinka <mhlavink@redhat.com> - 1:2.2.36-8
- update release number

* Mon Aug 10 2020 Michal Hlavinka <mhlavink@redhat.com> - 1:2.2.36-7.1
- fix CVE-2020-12100 resource exhaustion via deeply nested MIME parts (#1866752)
- fix CVE-2020-12673 out of bound reads in dovecot NTLM implementation (#1866757)
- fix CVE-2020-12674 crash due to assert in RPA implementation (#1866764)

* Mon Mar 02 2020 Michal Hlavinka <mhlavink@redhat.com> - 1:2.2.36-7
- generated key was too small (#1086365)

* Thu Aug 29 2019 Michal Hlavinka <mhlavink@redhat.com> - 1:2.2.36-6
- fix CVE-2019-11500: IMAP protocol parser does not properly handle NUL byte
when scanning data in quoted strings, leading to out of bounds heap
memory writes (#1741787)

* Tue Aug 13 2019 Michal Hlavinka <mhlavink@redhat.com> - 1:2.2.36-5
- fix CVE-2019-3814: improper certificate validation (#1674369)
- fix CVE-2019-7524: buffer overflow in indexer-worker process resulting in privilege
escalation (#1700398)

* Tue Aug 13 2019 Michal Hlavinka <mhlavink@redhat.com> - 1:2.2.36-4
- use portreserve to avoid port conflicts(#1270283)

* Wed Sep 19 2018 Michal Hlavinka <mhlavink@redhat.com> - 1:2.2.36-3
- fix global ACL directory configuration search path (#1630380)
- update first/last_valid_gid range patch (#1630409)

Loading…
Cancel
Save