Browse Source

dovecot package update

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

4
SOURCES/dovecot-1.0.beta2-mkcert-permissions.patch

@ -2,10 +2,10 @@ @@ -2,10 +2,10 @@
+++ dovecot-1.0.beta2/doc/mkcert.sh 2006-01-26 14:28:38.000000000 +0100
@@ -29,6 +29,7 @@
fi

$OPENSSL req -new -x509 -nodes -config $OPENSSLCONFIG -out $CERTFILE -keyout $KEYFILE -days 365 || exit 2
-chmod 0600 $KEYFILE
+chown root:root $CERTFILE $KEYFILE
+chmod 0600 $CERTFILE $KEYFILE
echo
echo
$OPENSSL x509 -subject -fingerprint -noout -in $CERTFILE || exit 2

4
SOURCES/dovecot-1.0.rc7-mkcert-paths.patch

@ -2,13 +2,13 @@ diff -up dovecot-2.2.27/doc/mkcert.sh.mkcert-paths dovecot-2.2.27/doc/mkcert.sh @@ -2,13 +2,13 @@ diff -up dovecot-2.2.27/doc/mkcert.sh.mkcert-paths dovecot-2.2.27/doc/mkcert.sh
--- dovecot-2.2.27/doc/mkcert.sh.mkcert-paths 2016-12-05 10:26:07.913515286 +0100
+++ dovecot-2.2.27/doc/mkcert.sh 2016-12-05 10:28:25.439634417 +0100
@@ -5,8 +5,8 @@

umask 077
OPENSSL=${OPENSSL-openssl}
-SSLDIR=${SSLDIR-/etc/ssl}
-OPENSSLCONFIG=${OPENSSLCONFIG-dovecot-openssl.cnf}
+SSLDIR=${SSLDIR-/etc/pki/dovecot}
+OPENSSLCONFIG=${OPENSSLCONFIG-/etc/pki/dovecot/dovecot-openssl.cnf}

CERTDIR=$SSLDIR/certs
KEYDIR=$SSLDIR/private

8
SOURCES/dovecot-2.0-defaultconfig.patch

@ -8,14 +8,14 @@ diff -up dovecot-2.2.10/doc/example-config/conf.d/10-mail.conf.default-settings @@ -8,14 +8,14 @@ diff -up dovecot-2.2.10/doc/example-config/conf.d/10-mail.conf.default-settings
-#first_valid_uid = 500
+first_valid_uid = 1000
#last_valid_uid = 0

# Valid GID range for users, defaults to non-root/wheel. Users having
@@ -286,6 +286,7 @@ namespace inbox {
# them simultaneously.
#mbox_read_locks = fcntl
#mbox_write_locks = dotlock fcntl
+mbox_write_locks = fcntl

# Maximum time to wait for lock (all of them) before aborting.
#mbox_lock_timeout = 5 mins
diff -up dovecot-2.2.10/doc/example-config/conf.d/10-ssl.conf.default-settings dovecot-2.2.10/doc/example-config/conf.d/10-ssl.conf
@ -23,12 +23,12 @@ diff -up dovecot-2.2.10/doc/example-config/conf.d/10-ssl.conf.default-settings d @@ -23,12 +23,12 @@ diff -up dovecot-2.2.10/doc/example-config/conf.d/10-ssl.conf.default-settings d
+++ dovecot-2.2.10/doc/example-config/conf.d/10-ssl.conf 2016-06-17 17:54:18.749626750 +0200
@@ -3,7 +3,9 @@
##

# SSL/TLS support: yes, no, required. <doc/wiki/SSL.txt>
-#ssl = yes
+# disable plain pop3 and imap, allowed are only pop3+TLS, pop3s, imap+TLS and imaps
+# plain imap and pop3 are still allowed for local connections
+ssl = required

# PEM encoded X.509 SSL/TLS certificate and private key. They're opened before
# dropping root privileges, so keep the key file unreadable by anyone but

2
SOURCES/dovecot-2.1.10-waitonline.patch

@ -7,7 +7,7 @@ diff -up dovecot-2.2.36/dovecot.service.in.waitonline dovecot-2.2.36/dovecot.ser @@ -7,7 +7,7 @@ diff -up dovecot-2.2.36/dovecot.service.in.waitonline dovecot-2.2.36/dovecot.ser
Documentation=http://wiki2.dovecot.org/
-After=local-fs.target network.target
+After=local-fs.target network.target network-online.target

[Service]
Type=forking
+ExecStartPre=/usr/libexec/dovecot/prestartscript

41
SOURCES/dovecot-2.2-gidcheck.patch

@ -15,45 +15,46 @@ diff -up dovecot-2.2.36/src/auth/auth-settings.c.gidcheck dovecot-2.2.36/src/aut @@ -15,45 +15,46 @@ diff -up dovecot-2.2.36/src/auth/auth-settings.c.gidcheck dovecot-2.2.36/src/aut
--- dovecot-2.2.36/src/auth/auth-settings.c.gidcheck 2018-04-30 15:52:05.000000000 +0200
+++ dovecot-2.2.36/src/auth/auth-settings.c 2018-09-17 12:17:13.132032699 +0200
@@ -272,6 +272,8 @@ static const struct setting_define auth_
DEF_NOPREFIX(SET_BOOL, verbose_proctitle),
DEF_NOPREFIX(SET_UINT, first_valid_uid),
DEF_NOPREFIX(SET_UINT, last_valid_uid),
DEF_NOPREFIX(SET_BOOL, verbose_proctitle),
DEF_NOPREFIX(SET_UINT, first_valid_uid),
DEF_NOPREFIX(SET_UINT, last_valid_uid),
+ DEF_NOPREFIX(SET_UINT, first_valid_gid),
+ DEF_NOPREFIX(SET_UINT, last_valid_gid),

DEF_NOPREFIX(SET_STR, ssl_client_ca_dir),
DEF_NOPREFIX(SET_STR, ssl_client_ca_file),
DEF_NOPREFIX(SET_STR, ssl_client_ca_dir),
DEF_NOPREFIX(SET_STR, ssl_client_ca_file),
@@ -331,6 +333,8 @@ static const struct auth_settings auth_d
.verbose_proctitle = FALSE,
.first_valid_uid = 500,
.last_valid_uid = 0,
.verbose_proctitle = FALSE,
.first_valid_uid = 500,
.last_valid_uid = 0,
+ .first_valid_gid = 1,
+ .last_valid_gid = 0,
};

const struct setting_parser_info auth_setting_parser_info = {
diff -up dovecot-2.2.36/src/auth/auth-settings.h.gidcheck dovecot-2.2.36/src/auth/auth-settings.h
--- dovecot-2.2.36/src/auth/auth-settings.h.gidcheck 2018-04-30 15:52:05.000000000 +0200
+++ dovecot-2.2.36/src/auth/auth-settings.h 2018-09-17 12:13:30.540159133 +0200
@@ -88,6 +88,8 @@ struct auth_settings {
bool verbose_proctitle;
unsigned int first_valid_uid;
unsigned int last_valid_uid;
bool verbose_proctitle;
unsigned int first_valid_uid;
unsigned int last_valid_uid;
+ unsigned int first_valid_gid;
+ unsigned int last_valid_gid;

/* generated: */
char username_chars_map[256];
/* generated: */
char username_chars_map[256];
diff -up dovecot-2.2.36/src/auth/userdb-passwd.c.gidcheck dovecot-2.2.36/src/auth/userdb-passwd.c
--- dovecot-2.2.36/src/auth/userdb-passwd.c.gidcheck 2018-04-30 15:52:05.000000000 +0200
+++ dovecot-2.2.36/src/auth/userdb-passwd.c 2018-09-17 12:13:30.540159133 +0200
@@ -145,6 +145,10 @@ passwd_iterate_want_pw(struct passwd *pw
return FALSE;
if (pw->pw_uid > (uid_t)set->last_valid_uid && set->last_valid_uid != 0)
return FALSE;
return FALSE;
if (pw->pw_uid > (uid_t)set->last_valid_uid && set->last_valid_uid != 0)
return FALSE;
+ if (pw->pw_gid < (gid_t)set->first_valid_gid)
+ return FALSE;
+ if (pw->pw_gid > (gid_t)set->last_valid_gid && set->last_valid_gid != 0)
+ return FALSE;
return TRUE;
return TRUE;
}

12
SOURCES/dovecot-2.2.36-aclfix.patch

@ -2,12 +2,12 @@ diff -up dovecot-2.2.36/src/plugins/acl/acl-backend-vfile.c.aclfix dovecot-2.2.3 @@ -2,12 +2,12 @@ diff -up dovecot-2.2.36/src/plugins/acl/acl-backend-vfile.c.aclfix dovecot-2.2.3
--- dovecot-2.2.36/src/plugins/acl/acl-backend-vfile.c.aclfix 2018-09-18 15:00:08.778823903 +0200
+++ dovecot-2.2.36/src/plugins/acl/acl-backend-vfile.c 2018-09-18 15:00:08.814823737 +0200
@@ -161,8 +161,7 @@ acl_backend_vfile_object_init(struct acl
T_BEGIN {
if (*name == '\0' ||
mailbox_list_is_valid_name(_backend->list, name, &error)) {
T_BEGIN {
if (*name == '\0' ||
mailbox_list_is_valid_name(_backend->list, name, &error)) {
- vname = *name == '\0' ? "" :
- mailbox_list_get_vname(_backend->list, name);
+ vname = mailbox_list_get_vname(_backend->list, name);

dir = acl_backend_vfile_get_local_dir(_backend, name, vname);
aclobj->local_path = dir == NULL ? NULL :
dir = acl_backend_vfile_get_local_dir(_backend, name, vname);
aclobj->local_path = dir == NULL ? NULL :

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

24
SOURCES/dovecot-2.2.9-nodevrand.patch

@ -2,16 +2,16 @@ diff -up dovecot-2.2.9/src/lib-master/master-service.c.fixit dovecot-2.2.9/src/l @@ -2,16 +2,16 @@ diff -up dovecot-2.2.9/src/lib-master/master-service.c.fixit dovecot-2.2.9/src/l
--- dovecot-2.2.9/src/lib-master/master-service.c.fixit 2013-11-24 14:37:39.000000000 +0100
+++ dovecot-2.2.9/src/lib-master/master-service.c 2013-11-27 17:52:48.802843395 +0100
@@ -559,6 +559,11 @@ const char *master_service_get_name(stru
return service->name;
return service->name;
}

+const enum master_service_flags master_service_get_flags(struct master_service *service)
+{
+ return service->flags;
+}
+
void master_service_run(struct master_service *service,
master_service_connection_callback_t *callback)
master_service_connection_callback_t *callback)
{
diff -up dovecot-2.2.9/src/lib-master/master-service.h.fixit dovecot-2.2.9/src/lib-master/master-service.h
--- dovecot-2.2.9/src/lib-master/master-service.h.fixit 2013-11-24 14:37:39.000000000 +0100
@ -19,23 +19,23 @@ diff -up dovecot-2.2.9/src/lib-master/master-service.h.fixit dovecot-2.2.9/src/l @@ -19,23 +19,23 @@ diff -up dovecot-2.2.9/src/lib-master/master-service.h.fixit dovecot-2.2.9/src/l
@@ -134,6 +134,8 @@ const char *master_service_get_version_s
/* Returns name of the service, as given in name parameter to _init(). */
const char *master_service_get_name(struct master_service *service);

+const enum master_service_flags master_service_get_flags(struct master_service *service);
+
/* Start the service. Blocks until finished */
void master_service_run(struct master_service *service,
master_service_connection_callback_t *callback)
master_service_connection_callback_t *callback)
diff -up dovecot-2.2.9/src/ssl-params/main.c.fixit dovecot-2.2.9/src/ssl-params/main.c
--- dovecot-2.2.9/src/ssl-params/main.c.fixit 2013-11-24 14:37:39.000000000 +0100
+++ dovecot-2.2.9/src/ssl-params/main.c 2013-11-27 17:51:06.664694558 +0100
@@ -103,7 +103,10 @@ static void sig_chld(const siginfo_t *si
if (waitpid(-1, &status, WNOHANG) < 0)
i_error("waitpid() failed: %m");
else if (status != 0)
if (waitpid(-1, &status, WNOHANG) < 0)
i_error("waitpid() failed: %m");
else if (status != 0)
+ {
i_error("child process failed with status %d", status);
i_error("child process failed with status %d", status);
+ if(master_service_get_flags(master_service) & MASTER_SERVICE_FLAG_STANDALONE) exit(1);
+ }
else {
/* params should have been created now. try refreshing. */
ssl_params_refresh(param);
else {
/* params should have been created now. try refreshing. */
ssl_params_refresh(param);

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. */

3
SOURCES/dovecot.init

@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
# Required-Stop: $local_fs $network
# Should-Start: $remote_fs
# Should-Stop: $remote_fs
# Default-Start:
# Default-Start:
# Default-Stop: 0 1 2 3 4 5 6
# Short-Description: start and stop Dovecot Imap server
# Description: Dovecot is an IMAP server for Linux/UNIX-like systems,
@ -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 ||:

134
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
@ -94,8 +113,8 @@ BuildRequires: libcurl-devel expat-devel @@ -94,8 +113,8 @@ BuildRequires: libcurl-devel expat-devel
%global restart_flag /var/run/%{name}/%{name}-restart-after-rpm-install

%description
Dovecot is an IMAP server for Linux/UNIX-like systems, written with security
primarily in mind. It also contains a small POP3 server. It supports mail
Dovecot is an IMAP server for Linux/UNIX-like systems, written with security
primarily in mind. It also contains a small POP3 server. It supports mail
in either of maildir or mbox formats.

The SQL drivers and authentication plug-ins are in their subpackages.
@ -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
@ -276,7 +317,7 @@ rm -rf $RPM_BUILD_ROOT @@ -276,7 +317,7 @@ rm -rf $RPM_BUILD_ROOT


%pre
#dovecot uid and gid are reserved, see /usr/share/doc/setup-*/uidgid
#dovecot uid and gid are reserved, see /usr/share/doc/setup-*/uidgid
getent group dovecot >/dev/null || groupadd -r --gid 97 dovecot
getent passwd dovecot >/dev/null || \
useradd -r --uid 97 -g dovecot -d /usr/libexec/dovecot -s /sbin/nologin -c "Dovecot IMAP server" dovecot
@ -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)
@ -604,7 +670,7 @@ make check @@ -604,7 +670,7 @@ make check
- maildir: Fixed a crash after dovecot-keywords file was re-read.
- maildir: If files had reappeared unexpectedly to a Maildir, they
were ignored until index files were deleted.
- Maildir: Fixed handling over 26 keywords in a mailbox.
- Maildir: Fixed handling over 26 keywords in a mailbox.
- imap/pop3-login proxying: Fixed a crash if TCP connection succeeded,
but the remote login timed out.

@ -701,7 +767,7 @@ make check @@ -701,7 +767,7 @@ make check
the header wasn't lowercased.
- fts-squat: Fixed crash when searching a virtual mailbox.
- pop3: Fixed assert crash when doing UIDL on empty mailbox on some
setups.
setups.
- auth: GSSAPI RFC compliancy and error handling fixes.
- Various fixes related to handling shared namespaces

@ -743,7 +809,7 @@ make check @@ -743,7 +809,7 @@ make check
prefix is non-empty, don't assert-crash when rebuilding indexes.
- sdbox: Don't use more fds than necessary when copying mails.
- auth: Fixed crash with DIGEST-MD5 when attempting to do master user
login without master passdbs.
login without master passdbs.
- Several fixes to mail_shared_explicit_inbox=no
- imapc: Use imapc_list_prefix also for listing subscriptions.

@ -812,7 +878,7 @@ make check @@ -812,7 +878,7 @@ make check
- dovecot updated to 2.1.1
- acl plugin + autocreated mailboxes crashed when listing mailboxes
- doveadm force-resync: Don't skip autocreated mailboxes (especially
INBOX).
INBOX).
- If process runs out of fds, stop listening for new connections only
temporarily, not permanently (avoids hangs with process_limit=1
services)
@ -932,7 +998,7 @@ make check @@ -932,7 +998,7 @@ make check

* Mon Mar 07 2011 Michal Hlavinka <mhlavink@redhat.com> - 1:2.0.11-1
- IMAP: Fixed hangs with COMPRESS extension
- IMAP: Fixed a hang when trying to COPY to a nonexistent mailbox.
- IMAP: Fixed a hang when trying to COPY to a nonexistent mailbox.
- IMAP: Fixed hang/crash with SEARCHRES + pipelining $.
- IMAP: Fixed assert-crash if IDLE+DONE is sent in same TCP packet.

@ -971,7 +1037,7 @@ make check @@ -971,7 +1037,7 @@ make check
* Tue Nov 09 2010 Michal Hlavinka <mhlavink@redhat.com> - 1:2.0.7-1
- dovecot updated to 2.0.7
- IMAP: Fixed LIST-STATUS when listing subscriptions with subscriptions=no namespaces.
- IMAP: Fixed SELECT QRESYNC not to crash on mailbox close if a lot of changes were being sent.
- IMAP: Fixed SELECT QRESYNC not to crash on mailbox close if a lot of changes were being sent.
- quota: Don't count virtual mailboxes in quota
- doveadm expunge didn't always actually do the physical expunging
- Fixed some index reading optimizations introduced by v2.0.5.
@ -995,21 +1061,21 @@ make check @@ -995,21 +1061,21 @@ make check
* Mon Oct 04 2010 Michal Hlavinka <mhlavink@redhat.com> - 1:2.0.5-1
- dovecot updated to 2.0.5
- acl: Fixed the logic of merging multiple ACL entries
- sdbox: Fixed memory leak when copying messages with hard links.
- sdbox: Fixed memory leak when copying messages with hard links.
- zlib: Fixed several crashes, which mainly showed up with mbox.
- quota: Don't crash if user has quota disabled, but plugin loaded.
- acl: Fixed crashing when sometimes listing shared mailboxes via dict proxy.

* Tue Sep 28 2010 Michal Hlavinka <mhlavink@redhat.com> - 1:2.0.4-1
- dovecot updated to 2.0.4
- multi-dbox: If :INDEX=path is specified, keep storage/dovecot.map.index*
- multi-dbox: If :INDEX=path is specified, keep storage/dovecot.map.index*
files also in the index path rather than in the main storage directory.
- dsync: POP3 UIDLs weren't copied with Maildir
- dict file: Fixed fd leak (showed up easily with LMTP + quota)

* Mon Sep 20 2010 Michal Hlavinka <mhlavink@redhat.com> - 1:2.0.3-1
- dovecot updated to 2.0.3
- dovecot-lda: Removed use of non-standard Envelope-To: header as
- dovecot-lda: Removed use of non-standard Envelope-To: header as
a default for -a
- dsync: Fixed handling \Noselect mailboxes
- Fixed an infinite loop introduced by v2.0.2's message parser changes.
@ -1027,7 +1093,7 @@ make check @@ -1027,7 +1093,7 @@ make check
* Wed Aug 25 2010 Michal Hlavinka <mhlavink@redhat.com> - 1:2.0.1-1
- dovecot and pigeonhole updated
- sieve: sieved renamed to sieve-dump
- when dsync is started as root, remote dsync command is now also executed
- when dsync is started as root, remote dsync command is now also executed
as root instead of with dropped privileges.
- IMAP: QRESYNC parameters for SELECT weren't handled correctly.
- UTF-8 string validity checking wasn't done correctly
@ -1043,14 +1109,14 @@ make check @@ -1043,14 +1109,14 @@ make check
- Using more than 2 plugins could have caused broken behavior
- Listescape plugin fixes
- mbox: Fixed a couple of assert-crashes
- mdbox: Fixed potential assert-crash when saving multiple messages
- mdbox: Fixed potential assert-crash when saving multiple messages
in one transaction

* Thu Aug 05 2010 Michal Hlavinka <mhlavink@redhat.com> - 1:2.0-0.20.rc4
- dovecot and pigeonhole updated
- doveadm mailbox status: Fixed listing non-ASCII mailbox names.
- doveadm mailbox status: Fixed listing non-ASCII mailbox names.
- doveadm fetch: Fixed output when fetching message header or body
- doveadm director map/add/remove: Fixed handling IP address as parameter.
- doveadm director map/add/remove: Fixed handling IP address as parameter.
- dsync: A few more fixes

* Wed Jul 21 2010 Michal Hlavinka <mhlavink@redhat.com> - 1:2.0-0.19.rc3
@ -1090,7 +1156,7 @@ make check @@ -1090,7 +1156,7 @@ make check
- master: Fixed crash on deinit (maybe also on reload)

* Thu Jun 10 2010 Michal Hlavinka <mhlavink@redhat.com> - 1:2.0-0.14.beta5.20100610
- dovecot updated
- dovecot updated
- lib-storage: Fixed accessing uncommitted saved mails with dsync
- example-config: Moved ACL and quota settings to a separate .conf files
- dbox, mdbox: Fixed race conditions when creating mailboxes
@ -1118,7 +1184,7 @@ make check @@ -1118,7 +1184,7 @@ make check
- example-config: auth-checkpassword include wasn't listed in 10-auth.conf
- doveadm: Added search command
- lib-master: Don't crash after timeouting an auth-master request
- master: If inet listener uses DNS name, which returns multiple IPs,
- master: If inet listener uses DNS name, which returns multiple IPs,
listen in all of them

* Wed Apr 28 2010 Michal Hlavinka <mhlavink@redhat.com> - 1:2.0-0.7.beta4.20100427
@ -1220,7 +1286,7 @@ make check @@ -1220,7 +1286,7 @@ make check

* Tue Dec 22 2009 Michal Hlavinka <mhlavink@redhat.com> - 1:1.2.9-2
- sieve updated to 0.1.14
- managesieve updated to 0.11.10
- managesieve updated to 0.11.10

* Fri Dec 18 2009 Michal Hlavinka <mhlavink@redhat.com> - 1:1.2.9-1
- updated to 1.2.9
@ -1273,7 +1339,7 @@ make check @@ -1273,7 +1339,7 @@ make check
- spec cleanup

* Wed Oct 21 2009 Michal Hlavinka <mhlavink@redhat.com> - 1:1.2.6-4
- imap-login: If imap_capability is set, show it in the banner
- imap-login: If imap_capability is set, show it in the banner
instead of the default (#524485)

* Mon Oct 19 2009 Michal Hlavinka <mhlavink@redhat.com> - 1:1.2.6-3
@ -1370,7 +1436,7 @@ make check @@ -1370,7 +1436,7 @@ make check
* Mon Jul 13 2009 Michal Hlavinka <mhlavink@redhat.com> - 1:1.2.1-1
- updated to 1.2.1
- GSSAPI authentication is fixed (#506782)
- logins now fail if home directory path is relative, because it was
- logins now fail if home directory path is relative, because it was
not working correctly and never was expected to work
- sieve and managesieve update

@ -1395,7 +1461,7 @@ make check @@ -1395,7 +1461,7 @@ make check
- IMAP: PERMANENTFLAGS list didn't contain \*, causing some clients
not to save keywords.
- auth: Using "username" or "domain" passdb fields caused problems
with cache and blocking passdbs in v1.1.8 .. v1.1.10.
with cache and blocking passdbs in v1.1.8 .. v1.1.10.
- userdb prefetch + blocking passdbs was broken with non-plaintext
auth in v1.1.8 .. v1.1.10.

@ -1414,7 +1480,7 @@ make check @@ -1414,7 +1480,7 @@ make check

* Tue Dec 2 2008 Michal Hlavinka <mhlavink@redhat.com> - 1:1.1.7-2
- revert changes from 1:1.1.6-2 and 1:1.1.6-1
- password can be stored in different file readable only for root
- password can be stored in different file readable only for root
via !include_try directive

* Tue Dec 2 2008 Michal Hlavinka <mhlavink@redhat.com> - 1:1.1.7-1
@ -1750,7 +1816,7 @@ make check @@ -1750,7 +1816,7 @@ make check

* Wed Sep 8 2004 John Dennis <jdennis@redhat.com> 0.99.11-1.FC3.1
- bring up to latest upstream,
comments from Timo Sirainen <tss at iki.fi> on release v0.99.11 2004-09-04
comments from Timo Sirainen <tss at iki.fi> on release v0.99.11 2004-09-04
+ 127.* and ::1 IP addresses are treated as secured with
disable_plaintext_auth = yes
+ auth_debug setting for extra authentication debugging
@ -1840,7 +1906,7 @@ make check @@ -1840,7 +1906,7 @@ make check
- update to 0.99.10.4

* Mon Oct 6 2003 Jeremy Katz <katzj@redhat.com> 0.99.10-7
- another patch from upstream to fix returning invalid data on partial
- another patch from upstream to fix returning invalid data on partial
BODY[part] fetches
- patch to avoid confusion of draft/deleted in indexes

@ -1877,9 +1943,9 @@ make check @@ -1877,9 +1943,9 @@ make check

* Thu May 8 2003 Jeremy Katz <katzj@redhat.com> 0.99.9.1-1
- update to 0.99.9.1
- add patch from upstream to fix potential bug when fetching with
- add patch from upstream to fix potential bug when fetching with
CR+LF linefeeds
- tweak some things in the initscript and config file noticed by the
- tweak some things in the initscript and config file noticed by the
fedora folks

* Sun Mar 16 2003 Jeremy Katz <katzj@redhat.com> 0.99.8.1-2

Loading…
Cancel
Save