import dovecot-2.3.16-1.el8

This commit is contained in:
CentOS Sources 2022-02-11 05:25:56 +00:00 committed by Stepan Oksanichenko
parent eaa66e18fe
commit 22f8d9cb48
34 changed files with 278 additions and 6319 deletions

View File

@ -1,2 +1,2 @@
b9c7290dad1ac3bc1ead11359812a137a3d173f7 SOURCES/dovecot-2.3-pigeonhole-0.5.8.tar.gz
65b93f7fd53705b3c97f9eee141a76c5f4f3a624 SOURCES/dovecot-2.3.8.tar.gz
4673c244c6ea73ee3da0bb61d0206a1fe3d0be0e SOURCES/dovecot-2.3-pigeonhole-0.5.16.tar.gz
b5c598ae8b9901bfabdf2c93271f57cde0bde73e SOURCES/dovecot-2.3.16.tar.gz

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/dovecot-2.3-pigeonhole-0.5.8.tar.gz
SOURCES/dovecot-2.3.8.tar.gz
SOURCES/dovecot-2.3-pigeonhole-0.5.16.tar.gz
SOURCES/dovecot-2.3.16.tar.gz

View File

@ -1,11 +1,11 @@
diff -up dovecot-2.3.0.1/dovecot.service.in.waitonline dovecot-2.3.0.1/dovecot.service.in
--- dovecot-2.3.0.1/dovecot.service.in.waitonline 2018-03-01 10:35:39.888371078 +0100
+++ dovecot-2.3.0.1/dovecot.service.in 2018-03-01 10:36:29.738784661 +0100
@@ -12,6 +12,7 @@ After=local-fs.target network-online.tar
diff -up dovecot-2.3.15/dovecot.service.in.waitonline dovecot-2.3.15/dovecot.service.in
--- dovecot-2.3.15/dovecot.service.in.waitonline 2021-06-21 20:19:19.560494654 +0200
+++ dovecot-2.3.15/dovecot.service.in 2021-06-21 20:21:17.443066248 +0200
@@ -15,6 +15,7 @@ After=local-fs.target network-online.tar
[Service]
Type=simple
Type=@systemdservicetype@
+ExecStartPre=/usr/libexec/dovecot/prestartscript
ExecStart=@sbindir@/dovecot -F
PIDFile=@rundir@/master.pid
ExecReload=@bindir@/doveadm reload
ExecStop=@bindir@/doveadm stop

View File

@ -1,6 +1,6 @@
diff -up dovecot-2.3.0.1/dovecot-init.service.initbysystemd dovecot-2.3.0.1/dovecot-init.service
--- dovecot-2.3.0.1/dovecot-init.service.initbysystemd 2018-03-01 10:38:22.059716008 +0100
+++ dovecot-2.3.0.1/dovecot-init.service 2018-03-01 10:38:22.059716008 +0100
diff -up dovecot-2.3.15/dovecot-init.service.initbysystemd dovecot-2.3.15/dovecot-init.service
--- dovecot-2.3.15/dovecot-init.service.initbysystemd 2021-06-21 20:21:49.250680889 +0200
+++ dovecot-2.3.15/dovecot-init.service 2021-06-21 20:21:49.250680889 +0200
@@ -0,0 +1,13 @@
+[Unit]
+Description=One-time Dovecot init service
@ -15,32 +15,37 @@ diff -up dovecot-2.3.0.1/dovecot-init.service.initbysystemd dovecot-2.3.0.1/dove
+ SSLDIR=/etc/pki/dovecot/ OPENSSLCONFIG=/etc/pki/dovecot/dovecot-openssl.cnf /usr/libexec/dovecot/mkcert.sh /dev/null 2>&1;\
+fi'
+
diff -up dovecot-2.3.0.1/dovecot.service.in.initbysystemd dovecot-2.3.0.1/dovecot.service.in
--- dovecot-2.3.0.1/dovecot.service.in.initbysystemd 2018-03-01 10:38:22.060716016 +0100
+++ dovecot-2.3.0.1/dovecot.service.in 2018-03-01 10:40:45.524901319 +0100
@@ -8,7 +8,8 @@
diff -up dovecot-2.3.15/dovecot.service.in.initbysystemd dovecot-2.3.15/dovecot.service.in
--- dovecot-2.3.15/dovecot.service.in.initbysystemd 2021-06-21 20:21:49.250680889 +0200
+++ dovecot-2.3.15/dovecot.service.in 2021-06-21 20:22:46.935981920 +0200
@@ -11,7 +11,8 @@
Description=Dovecot IMAP/POP3 email server
Documentation=man:dovecot(1)
Documentation=http://wiki2.dovecot.org/
Documentation=https://doc.dovecot.org/
-After=local-fs.target network-online.target
+After=local-fs.target network-online.target dovecot-init.service
+Requires=dovecot-init.service
[Service]
Type=simple
diff -up dovecot-2.3.0.1/Makefile.am.initbysystemd dovecot-2.3.0.1/Makefile.am
--- dovecot-2.3.0.1/Makefile.am.initbysystemd 2018-02-28 15:28:57.000000000 +0100
+++ dovecot-2.3.0.1/Makefile.am 2018-03-01 10:38:22.060716016 +0100
@@ -63,9 +63,10 @@ if HAVE_SYSTEMD
Type=@systemdservicetype@
diff -up dovecot-2.3.15/Makefile.am.initbysystemd dovecot-2.3.15/Makefile.am
--- dovecot-2.3.15/Makefile.am.initbysystemd 2021-06-21 20:21:49.250680889 +0200
+++ dovecot-2.3.15/Makefile.am 2021-06-21 20:24:26.676765849 +0200
@@ -21,6 +21,7 @@ EXTRA_DIST = \
run-test-valgrind.supp \
dovecot.service.in \
dovecot.socket \
+ dovecot-init.service \
$(conf_DATA)
noinst_DATA = dovecot-config
@@ -69,7 +70,8 @@ dovecot-config: dovecot-config.in Makefi
if WANT_SYSTEMD
systemdsystemunit_DATA = \
dovecot.socket \
- dovecot.service
+ dovecot.service \
+ dovecot-init.service
else
-EXTRA_DIST += dovecot.socket dovecot.service.in
+EXTRA_DIST += dovecot.socket dovecot.service.in dovecot-init.service
endif
install-exec-hook:

View File

@ -1,9 +1,9 @@
diff -up dovecot-2.2.36/doc/dovecot-openssl.cnf.bigkey dovecot-2.2.36/doc/dovecot-openssl.cnf
--- dovecot-2.2.36/doc/dovecot-openssl.cnf.bigkey 2017-06-23 13:18:28.000000000 +0200
+++ dovecot-2.2.36/doc/dovecot-openssl.cnf 2018-10-16 17:15:35.836205498 +0200
diff -up dovecot-2.3.15/doc/dovecot-openssl.cnf.bigkey dovecot-2.3.15/doc/dovecot-openssl.cnf
--- dovecot-2.3.15/doc/dovecot-openssl.cnf.bigkey 2021-06-21 20:24:51.913456628 +0200
+++ dovecot-2.3.15/doc/dovecot-openssl.cnf 2021-06-21 20:25:36.352912123 +0200
@@ -1,5 +1,5 @@
[ req ]
-default_bits = 1024
-default_bits = 2048
+default_bits = 3072
encrypt_key = yes
distinguished_name = req_dn

File diff suppressed because it is too large Load Diff

View File

@ -1,121 +0,0 @@
diff -up dovecot-2.3.8/src/lib-smtp/smtp-address.c.smtppre dovecot-2.3.8/src/lib-smtp/smtp-address.c
--- dovecot-2.3.8/src/lib-smtp/smtp-address.c.smtppre 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib-smtp/smtp-address.c 2020-05-29 19:11:19.340621409 +0200
@@ -467,7 +467,7 @@ void smtp_address_detail_parse(pool_t po
*detail_r = p+1;
}
- if (address->domain == NULL)
+ if (address->domain == NULL || *address->domain == '\0')
*username_r = user;
else if (strchr(user, '@') == NULL ) {
/* username is just glued to the domain... no SMTP escaping */
@@ -548,7 +548,7 @@ void smtp_address_write(string_t *out,
if (quoted)
str_append_c(out, '\"');
- if (address->domain == NULL)
+ if (address->domain == NULL || *address->domain == '\0')
return;
str_append_c(out, '@');
@@ -587,8 +587,12 @@ void smtp_address_init(struct smtp_addre
const char *localpart, const char *domain)
{
i_zero(address);
+ if (localpart == NULL || *localpart == '\0')
+ return;
+
address->localpart = localpart;
- address->domain = (localpart == NULL ? NULL : domain);
+ if (domain != NULL && *domain != '\0')
+ address->domain = domain;
}
int smtp_address_init_from_msg(struct smtp_address *address,
@@ -597,7 +601,7 @@ int smtp_address_init_from_msg(struct sm
const char *p;
i_zero(address);
- if (msg_addr->mailbox == NULL)
+ if (msg_addr->mailbox == NULL || *msg_addr->mailbox == '\0')
return 0;
/* The message_address_parse() function allows UTF-8 codepoints in
@@ -609,7 +613,8 @@ int smtp_address_init_from_msg(struct sm
}
address->localpart = msg_addr->mailbox;
- address->domain = msg_addr->domain;
+ if (msg_addr->domain != NULL && *msg_addr->domain != '\0')
+ address->domain = msg_addr->domain;
return 0;
}
@@ -617,8 +622,8 @@ struct smtp_address *
smtp_address_clone(pool_t pool, const struct smtp_address *src)
{
struct smtp_address *new;
- size_t size, lpsize, dsize = 0;
- char *data, *localpart, *domain = NULL;
+ size_t size, lpsize = 0, dsize = 0;
+ char *data, *localpart = NULL, *domain = NULL;
if (smtp_address_isnull(src))
return NULL;
@@ -626,17 +631,21 @@ smtp_address_clone(pool_t pool, const st
/* @UNSAFE */
size = sizeof(struct smtp_address);
- lpsize = strlen(src->localpart) + 1;
- size = MALLOC_ADD(size, lpsize);
- if (src->domain != NULL) {
+ if (src->localpart != NULL && *src->localpart != '\0') {
+ lpsize = strlen(src->localpart) + 1;
+ size = MALLOC_ADD(size, lpsize);
+ }
+ if (src->domain != NULL && *src->domain != '\0') {
dsize = strlen(src->domain) + 1;
size = MALLOC_ADD(size, dsize);
}
data = p_malloc(pool, size);
new = (struct smtp_address *)data;
- localpart = PTR_OFFSET(data, sizeof(*new));
- memcpy(localpart, src->localpart, lpsize);
+ if (lpsize > 0) {
+ localpart = PTR_OFFSET(data, sizeof(*new));
+ memcpy(localpart, src->localpart, lpsize);
+ }
if (dsize > 0) {
domain = PTR_OFFSET(data, sizeof(*new) + lpsize);
memcpy(domain, src->domain, dsize);
@@ -681,8 +690,8 @@ smtp_address_clone_temp(const struct smt
return NULL;
new = t_new(struct smtp_address, 1);
- new->localpart = t_strdup(src->localpart);
- new->domain = t_strdup(src->domain);
+ new->localpart = t_strdup_empty(src->localpart);
+ new->domain = t_strdup_empty(src->domain);
return new;
}
@@ -720,7 +729,7 @@ smtp_address_add_detail(pool_t pool, con
new_addr = p_new(pool, struct smtp_address, 1);
new_addr->localpart = p_strconcat(pool,
address->localpart, delim, detail, NULL);
- new_addr->domain = p_strdup(pool, address->domain);
+ new_addr->domain = p_strdup_empty(pool, address->domain);
return new_addr;
}
@@ -737,7 +746,7 @@ smtp_address_add_detail_temp(const struc
new_addr = t_new(struct smtp_address, 1);
new_addr->localpart = t_strconcat(
address->localpart, delim, detail, NULL);
- new_addr->domain = t_strdup(address->domain);
+ new_addr->domain = t_strdup_empty(address->domain);
return new_addr;
}

View File

@ -1,26 +0,0 @@
From 68165c8acc6d32a06f8dce2ef515c714c243ce4e Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 17 Aug 2020 18:33:20 +0300
Subject: [PATCH] imap: Escape tag when sending it to imap-hibernate process
---
src/imap/imap-client-hibernate.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c
index f639d722cb..4ef323453c 100644
--- a/src/imap/imap-client-hibernate.c
+++ b/src/imap/imap-client-hibernate.c
@@ -97,8 +97,10 @@ static void imap_hibernate_write_cmd(struct client *client, string_t *cmd,
str_printfa(cmd, "\tuid=%s", dec2str(user->uid));
if (user->gid != (gid_t)-1)
str_printfa(cmd, "\tgid=%s", dec2str(user->gid));
- if (tag != NULL)
- str_printfa(cmd, "\ttag=%s", tag);
+ if (tag != NULL) {
+ str_append(cmd, "\ttag=");
+ str_append_tabescaped(cmd, tag);
+ }
str_append(cmd, "\tstats=");
str_append_tabescaped(cmd, client_stats(client));
if (client->command_queue != NULL &&

View File

@ -1,25 +0,0 @@
From 73937b5fe7eb1dde76f30ef6b181c920bbbc4558 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 24 Aug 2020 16:58:16 +0300
Subject: [PATCH] imap: Fix crash if imap-hibernate socket can't be connected
to
The error was supposed to be returned to caller, not logged directly.
---
src/imap/imap-client-hibernate.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c
index 4ef323453c..d3451b1bf6 100644
--- a/src/imap/imap-client-hibernate.c
+++ b/src/imap/imap-client-hibernate.c
@@ -176,7 +176,8 @@ imap_hibernate_process_send(struct client *client, const buffer_t *state,
"/"IMAP_HIBERNATE_SOCKET_NAME, NULL);
fd = net_connect_unix_with_retries(path, 1000);
if (fd == -1) {
- i_error("net_connect_unix(%s) failed: %m", path);
+ *error_r = t_strdup_printf(
+ "net_connect_unix(%s) failed: %m", path);
return -1;
}
net_set_nonblock(fd, FALSE);

View File

@ -1,31 +0,0 @@
From c7d158681fabdb3044bd213c332e489b46625a3b Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 24 Aug 2020 19:10:10 +0300
Subject: [PATCH] imap: Delay initializing client IO until
client_create_finish()
This helps writing unit tests.
---
src/imap/imap-client.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c
index 95e57dbf53..c8ffeafc43 100644
--- a/src/imap/imap-client.c
+++ b/src/imap/imap-client.c
@@ -143,7 +143,6 @@ struct client *client_create(int fd_in, int fd_out,
o_stream_set_flush_callback(client->output, client_output, client);
p_array_init(&client->module_contexts, client->pool, 5);
- client->io = io_add_istream(client->input, client_input, client);
client->last_input = ioloop_time;
client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS,
client_idle_timeout, client);
@@ -228,6 +227,7 @@ int client_create_finish(struct client *client, const char **error_r)
return -1;
mail_namespaces_set_storage_callbacks(client->user->namespaces,
&mail_storage_callbacks, client);
+ client->io = io_add_istream(client->input, client_input, client);
client->v.init(client);
return 0;

View File

@ -1,105 +0,0 @@
From 1a27cfa8e337b7e3298ba230059e766cdbc1123d Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 24 Aug 2020 19:10:43 +0300
Subject: [PATCH] imap: imap_client_hibernate() - Return reason string on
failure
This helps writing a unit test for it.
---
src/imap/cmd-idle.c | 3 ++-
src/imap/imap-client-hibernate.c | 10 +++++++++-
src/imap/imap-client.h | 5 +++--
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/src/imap/cmd-idle.c b/src/imap/cmd-idle.c
index 8a05582d03..2b31dc714e 100644
--- a/src/imap/cmd-idle.c
+++ b/src/imap/cmd-idle.c
@@ -175,11 +175,12 @@ static void idle_add_keepalive_timeout(struct cmd_idle_context *ctx)
static void idle_hibernate_timeout(struct cmd_idle_context *ctx)
{
struct client *client = ctx->client;
+ const char *reason;
i_assert(ctx->sync_ctx == NULL);
i_assert(!ctx->sync_pending);
- if (imap_client_hibernate(&client)) {
+ if (imap_client_hibernate(&client, &reason)) {
/* client may be destroyed now */
} else {
/* failed - don't bother retrying */
diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c
index d3451b1bf6..0709e4a244 100644
--- a/src/imap/imap-client-hibernate.c
+++ b/src/imap/imap-client-hibernate.c
@@ -203,19 +203,23 @@ imap_hibernate_process_send(struct client *client, const buffer_t *state,
return 0;
}
-bool imap_client_hibernate(struct client **_client)
+bool imap_client_hibernate(struct client **_client, const char **reason_r)
{
struct client *client = *_client;
buffer_t *state;
const char *error;
int ret, fd_notify = -1, fd_hibernate = -1;
+ *reason_r = NULL;
+
if (client->fd_in != client->fd_out) {
/* we won't try to hibernate stdio clients */
+ *reason_r = "stdio clients can't be hibernated";
return FALSE;
}
if (o_stream_get_buffer_used_size(client->output) > 0) {
/* wait until we've sent the pending output to client */
+ *reason_r = "output pending to client";
return FALSE;
}
@@ -233,11 +237,13 @@ bool imap_client_hibernate(struct client **_client)
"Couldn't export state: %s (mailbox=%s)", error,
client->mailbox == NULL ? "" :
mailbox_get_vname(client->mailbox));
+ *reason_r = error;
} else if (ret == 0) {
e_debug(client->event, "Couldn't hibernate imap client: "
"Couldn't export state: %s (mailbox=%s)", error,
client->mailbox == NULL ? "" :
mailbox_get_vname(client->mailbox));
+ *reason_r = error;
}
if (ret > 0 && client->mailbox != NULL) {
fd_notify = mailbox_watch_extract_notify_fd(client->mailbox,
@@ -248,6 +254,7 @@ bool imap_client_hibernate(struct client **_client)
e_debug(client->event, "Couldn't hibernate imap client: "
"Couldn't extract notifications fd: %s",
error);
+ *reason_r = error;
ret = -1;
}
}
@@ -257,5 +264,6 @@ bool imap_client_hibernate(struct client **_client)
e_error(client->event,
"Couldn't hibernate imap client: %s", error);
+ *reason_r = error;
ret = -1;
}
}
diff --git a/src/imap/imap-client.h b/src/imap/imap-client.h
index f2ffe0d7c9..4e591d5c7c 100644
--- a/src/imap/imap-client.h
+++ b/src/imap/imap-client.h
@@ -323,8 +323,9 @@ enum mailbox_feature client_enabled_mailbox_features(struct client *client);
const char *const *client_enabled_features(struct client *client);
/* Send client processing to imap-idle process. If successful, returns TRUE
- and destroys the client. */
-bool imap_client_hibernate(struct client **client);
+ and destroys the client. If hibernation failed, the exact reason is
+ returned (mainly for unit tests). */
+bool imap_client_hibernate(struct client **client, const char **reason_r);
struct imap_search_update *
client_search_update_lookup(struct client *client, const char *tag,

View File

@ -1,129 +0,0 @@
diff -up dovecot-2.3.8/src/imap/imap-client-hibernate.c.CVE_2020_24386-prereq1 dovecot-2.3.8/src/imap/imap-client-hibernate.c
--- dovecot-2.3.8/src/imap/imap-client-hibernate.c.CVE_2020_24386-prereq1 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/imap/imap-client-hibernate.c 2021-01-08 17:14:40.051174282 +0100
@@ -19,24 +19,26 @@
#define IMAP_HIBERNATE_SEND_TIMEOUT_SECS 10
#define IMAP_HIBERNATE_HANDSHAKE "VERSION\timap-hibernate\t1\t0\n"
-static int imap_hibernate_handshake(int fd, const char *path)
+static int
+imap_hibernate_handshake(int fd, const char *path, const char **error_r)
{
char buf[1024];
ssize_t ret;
if (write_full(fd, IMAP_HIBERNATE_HANDSHAKE,
strlen(IMAP_HIBERNATE_HANDSHAKE)) < 0) {
- i_error("write(%s) failed: %m", path);
+ *error_r = t_strdup_printf("write(%s) failed: %m", path);
return -1;
} else if ((ret = read(fd, buf, sizeof(buf)-1)) < 0) {
- i_error("read(%s) failed: %m", path);
+ *error_r = t_strdup_printf("read(%s) failed: %m", path);
return -1;
} else if (ret > 0 && buf[ret-1] == '\n') {
buf[ret-1] = '\0';
if (version_string_verify(buf, "imap-hibernate", 1))
return 0;
}
- i_error("%s sent invalid VERSION handshake: %s", path, buf);
+ *error_r = t_strdup_printf("%s sent invalid VERSION handshake: %s",
+ path, buf);
return -1;
}
@@ -105,40 +107,42 @@ static void imap_hibernate_write_cmd(str
static int
imap_hibernate_process_send_cmd(int fd_socket, const char *path,
- const string_t *cmd, int fd_client)
+ const string_t *cmd, int fd_client,
+ const char **error_r)
{
ssize_t ret;
i_assert(fd_socket != -1);
i_assert(str_len(cmd) > 1);
- if (imap_hibernate_handshake(fd_socket, path) < 0)
+ if (imap_hibernate_handshake(fd_socket, path, error_r) < 0)
return -1;
if ((ret = fd_send(fd_socket, fd_client, str_data(cmd), 1)) < 0) {
- i_error("fd_send(%s) failed: %m", path);
+ *error_r = t_strdup_printf("fd_send(%s) failed: %m", path);
return -1;
}
if ((ret = write_full(fd_socket, str_data(cmd)+1, str_len(cmd)-1)) < 0) {
- i_error("write(%s) failed: %m", path);
+ *error_r = t_strdup_printf("write(%s) failed: %m", path);
return -1;
}
return 0;
}
-static int imap_hibernate_process_read(int fd, const char *path)
+static int
+imap_hibernate_process_read(int fd, const char *path, const char **error_r)
{
char buf[1024];
ssize_t ret;
if ((ret = read(fd, buf, sizeof(buf)-1)) < 0) {
- i_error("read(%s) failed: %m", path);
+ *error_r = t_strdup_printf("read(%s) failed: %m", path);
return -1;
} else if (ret == 0) {
- i_error("%s disconnected", path);
+ *error_r = t_strdup_printf("%s disconnected", path);
return -1;
} else if (buf[0] != '+') {
buf[ret] = '\0';
- i_error("%s returned failure: %s", path,
+ *error_r = t_strdup_printf("%s returned failure: %s", path,
ret > 0 && buf[0] == '-' ? buf+1 : buf);
return -1;
} else {
@@ -147,8 +151,8 @@ static int imap_hibernate_process_read(i
}
static int
-imap_hibernate_process_send(struct client *client,
- const buffer_t *state, int fd_notify, int *fd_r)
+imap_hibernate_process_send(struct client *client, const buffer_t *state,
+ int fd_notify, int *fd_r, const char **error_r)
{
string_t *cmd = t_str_new(512);
const char *path;
@@ -171,14 +175,14 @@ imap_hibernate_process_send(struct clien
imap_hibernate_write_cmd(client, cmd, state, fd_notify);
alarm(IMAP_HIBERNATE_SEND_TIMEOUT_SECS);
- if (imap_hibernate_process_send_cmd(fd, path, cmd, client->fd_in) < 0 ||
- imap_hibernate_process_read(fd, path) < 0)
+ if (imap_hibernate_process_send_cmd(fd, path, cmd, client->fd_in, error_r) < 0 ||
+ imap_hibernate_process_read(fd, path, error_r) < 0)
ret = -1;
else if (fd_notify != -1) {
if ((ret = fd_send(fd, fd_notify, "\n", 1)) < 0)
- i_error("fd_send(%s) failed: %m", path);
+ *error_r = t_strdup_printf("fd_send(%s) failed: %m", path);
else
- ret = imap_hibernate_process_read(fd, path);
+ ret = imap_hibernate_process_read(fd, path, error_r);
}
alarm(0);
if (ret < 0) {
@@ -229,8 +233,12 @@ bool imap_client_hibernate(struct client
}
}
if (ret > 0) {
- if (imap_hibernate_process_send(client, state, fd_notify, &fd_hibernate) < 0)
+ if (imap_hibernate_process_send(client, state, fd_notify,
+ &fd_hibernate, &error) < 0) {
+ e_error(client->event,
+ "Couldn't hibernate imap client: %s", error);
ret = -1;
+ }
}
i_close_fd(&fd_notify);
if (ret > 0) {

View File

@ -1,185 +0,0 @@
From b9a2f18466a0d3377bab3e7a57691bdd75d8507c Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 17 Aug 2020 17:32:11 +0300
Subject: [PATCH] lib-imap: Add imap_parser_read_tag() and _read_command_name()
---
src/lib-imap/imap-parser.c | 67 +++++++++++++++++++++++++++++++++
src/lib-imap/imap-parser.h | 7 ++++
src/lib-imap/test-imap-parser.c | 67 +++++++++++++++++++++++++++++++++
3 files changed, 141 insertions(+)
diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c
index b6c6e63fb1..52d79282fa 100644
--- a/src/lib-imap/imap-parser.c
+++ b/src/lib-imap/imap-parser.c
@@ -947,3 +947,70 @@ const char *imap_parser_read_word(struct imap_parser *parser)
return NULL;
}
}
+
+static int
+imap_parser_read_next_atom(struct imap_parser *parser, bool parsing_tag,
+ const char **atom_r)
+{
+ const unsigned char *data;
+ size_t i, data_size;
+
+ data = i_stream_get_data(parser->input, &data_size);
+
+ /*
+ tag = 1*<any ASTRING-CHAR except "+">
+ ASTRING-CHAR = ATOM-CHAR / resp-specials
+ ATOM-CHAR = <any CHAR except atom-specials>
+
+ x-command = "X" atom <experimental command arguments>
+ atom = 1*ATOM-CHAR
+ */
+ for (i = 0; i < data_size; i++) {
+ /* explicitly check for atom-specials, because
+ IS_ATOM_PARSER_INPUT() allows some atom-specials */
+ switch (data[i]) {
+ case ' ':
+ case '\r':
+ case '\n':
+ data_size = i + (data[i] == ' ' ? 1 : 0);
+ parser->line_size += data_size;
+ i_stream_skip(parser->input, data_size);
+ *atom_r = p_strndup(parser->pool, data, i);
+ /* don't allow empty string */
+ return i == 0 ? -1 : 1;
+ /* atom-specials: */
+ case '(':
+ case ')':
+ case '{':
+ /* list-wildcards: */
+ case '%':
+ case '*':
+ /* quoted-specials: */
+ case '"':
+ case '\\':
+ /* resp-specials: */
+ case ']':
+ return -1;
+ case '+':
+ if (parsing_tag)
+ return -1;
+ break;
+ default:
+ if ((unsigned char)data[i] < ' ' ||
+ (unsigned char)data[i] >= 0x80)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int imap_parser_read_tag(struct imap_parser *parser, const char **tag_r)
+{
+ return imap_parser_read_next_atom(parser, TRUE, tag_r);
+}
+
+int imap_parser_read_command_name(struct imap_parser *parser,
+ const char **name_r)
+{
+ return imap_parser_read_next_atom(parser, FALSE, name_r);
+}
diff --git a/src/lib-imap/imap-parser.h b/src/lib-imap/imap-parser.h
index e5d01c17f2..5e09d61d2b 100644
--- a/src/lib-imap/imap-parser.h
+++ b/src/lib-imap/imap-parser.h
@@ -101,5 +101,12 @@ int imap_parser_finish_line(struct imap_parser *parser, unsigned int count,
/* Read one word - used for reading tag and command name.
Returns NULL if more data is needed. */
const char *imap_parser_read_word(struct imap_parser *parser);
+/* Read command tag. Returns 1 if tag was returned, 0 if more data is needed,
+ -1 if input isn't a valid tag. */
+int imap_parser_read_tag(struct imap_parser *parser, const char **tag_r);
+/* Read command name. Returns 1 if command name was returned, 0 if more data is
+ needed, -1 if input isn't a valid command name string. */
+int imap_parser_read_command_name(struct imap_parser *parser,
+ const char **name_r);
#endif
diff --git a/src/lib-imap/test-imap-parser.c b/src/lib-imap/test-imap-parser.c
index 93ef8fd59b..3ca4e34858 100644
--- a/src/lib-imap/test-imap-parser.c
+++ b/src/lib-imap/test-imap-parser.c
@@ -79,10 +79,77 @@ static void test_imap_parser_partial_list(void)
test_end();
}
+static void test_imap_parser_read_tag_cmd(void)
+{
+ enum read_type {
+ BOTH,
+ TAG,
+ COMMAND
+ };
+ struct {
+ const char *input;
+ const char *tag;
+ int ret;
+ enum read_type type;
+ } tests[] = {
+ { "tag foo", "tag", 1, BOTH },
+ { "tag\r", "tag", 1, BOTH },
+ { "tag\rfoo", "tag", 1, BOTH },
+ { "tag\nfoo", "tag", 1, BOTH },
+ { "tag\r\nfoo", "tag", 1, BOTH },
+ { "\n", NULL, -1, BOTH },
+ { "tag", NULL, 0, BOTH },
+ { "tag\t", NULL, -1, BOTH },
+ { "tag\001", NULL, -1, BOTH },
+ { "tag\x80", NULL, -1, BOTH },
+ { "tag(", NULL, -1, BOTH },
+ { "tag)", NULL, -1, BOTH },
+ { "tag{", NULL, -1, BOTH },
+ { "tag/ ", "tag/", 1, BOTH },
+ { "tag%", NULL, -1, BOTH },
+ { "tag*", NULL, -1, BOTH },
+ { "tag\"", NULL, -1, BOTH },
+ { "tag\\", NULL, -1, BOTH },
+ { "tag+", NULL, -1, TAG },
+ { "tag+ ", "tag+", 1, COMMAND },
+ };
+ struct istream *input;
+ struct imap_parser *parser;
+ const char *atom;
+ int ret;
+
+ test_begin("imap_parser_read_tag and imap_parser_read_command_name");
+ for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) {
+ if (tests[i].type != COMMAND) {
+ input = test_istream_create(tests[i].input);
+ test_assert(i_stream_read(input) > 0);
+ parser = imap_parser_create(input, NULL, 1024);
+ ret = imap_parser_read_tag(parser, &atom);
+ test_assert_idx(ret == tests[i].ret, i);
+ test_assert_idx(ret <= 0 || strcmp(tests[i].tag, atom) == 0, i);
+ imap_parser_unref(&parser);
+ i_stream_destroy(&input);
+ }
+
+ if (tests[i].type != TAG) {
+ input = test_istream_create(tests[i].input);
+ test_assert(i_stream_read(input) > 0);
+ parser = imap_parser_create(input, NULL, 1024);
+ ret = imap_parser_read_command_name(parser, &atom);
+ test_assert_idx(ret == tests[i].ret, i);
+ test_assert_idx(ret <= 0 || strcmp(tests[i].tag, atom) == 0, i);
+ imap_parser_unref(&parser);
+ i_stream_destroy(&input);
+ }
+ }
+ test_end();
+}
+
int main(void)
{
static void (*const test_functions[])(void) = {
test_imap_parser_crlf,
+ test_imap_parser_read_tag_cmd,
NULL
};
return test_run(test_functions);

View File

@ -1,46 +0,0 @@
From eea57c8683325f9767b2eb1b44a0b23352541c1e Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 17 Aug 2020 17:59:19 +0300
Subject: [PATCH] imap: Split off client_command_failed_early()
---
src/imap/imap-client.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c
index 07b2a8018b..0bf03caa97 100644
--- a/src/imap/imap-client.c
+++ b/src/imap/imap-client.c
@@ -1176,6 +1176,19 @@ bool client_handle_unfinished_cmd(struct client_command_context *cmd)
return TRUE;
}
+static void
+client_command_failed_early(struct client_command_context **_cmd,
+ const char *error)
+{
+ struct client_command_context *cmd = *_cmd;
+
+ io_loop_time_refresh();
+ command_stats_start(cmd);
+ client_send_command_error(cmd, error);
+ cmd->param_error = TRUE;
+ client_command_free(_cmd);
+}
+
static bool client_command_input(struct client_command_context *cmd)
{
struct client *client = cmd->client;
@@ -1239,11 +1252,7 @@ static bool client_command_input(struct client_command_context *cmd)
if (cmd->func == NULL) {
/* unknown command */
- io_loop_time_refresh();
- command_stats_start(cmd);
- client_send_command_error(cmd, "Unknown command.");
- cmd->param_error = TRUE;
- client_command_free(&cmd);
+ client_command_failed_early(&cmd, "Unknown command.");
return TRUE;
} else {
i_assert(!client->disconnected);

View File

@ -1,77 +0,0 @@
From 0386140f61f9ba62225e90b419215f72bba6ad8b Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 17 Aug 2020 18:11:36 +0300
Subject: [PATCH] imap: Use imap_parser_read_tag() and _read_command_name()
---
src/imap/imap-client.c | 33 ++++++++++++++++++++++-----------
1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c
index 0bf03caa97..95e57dbf53 100644
--- a/src/imap/imap-client.c
+++ b/src/imap/imap-client.c
@@ -1182,6 +1182,9 @@ client_command_failed_early(struct client_command_context **_cmd,
{
struct client_command_context *cmd = *_cmd;
+ /* ignore the rest of this line */
+ cmd->client->input_skip_line = TRUE;
+
io_loop_time_refresh();
command_stats_start(cmd);
client_send_command_error(cmd, error);
@@ -1193,6 +1196,8 @@ static bool client_command_input(struct client_command_context *cmd)
{
struct client *client = cmd->client;
struct command *command;
+ const char *tag, *name;
+ int ret;
if (cmd->func != NULL) {
/* command is being executed - continue it */
@@ -1207,27 +1212,33 @@ static bool client_command_input(struct client_command_context *cmd)
}
if (cmd->tag == NULL) {
- cmd->tag = imap_parser_read_word(cmd->parser);
- if (cmd->tag == NULL)
+ ret = imap_parser_read_tag(cmd->parser, &tag);
+ if (ret == 0)
return FALSE; /* need more data */
- cmd->tag = p_strdup(cmd->pool, cmd->tag);
+ if (ret < 0) {
+ client_command_failed_early(&cmd, "Invalid tag.");
+ return TRUE;
+ }
+ cmd->tag = p_strdup(cmd->pool, tag);
}
if (cmd->name == NULL) {
- cmd->name = imap_parser_read_word(cmd->parser);
- if (cmd->name == NULL)
+ ret = imap_parser_read_command_name(cmd->parser, &name);
+ if (ret == 0)
return FALSE; /* need more data */
+ if (ret < 0) {
+ client_command_failed_early(&cmd, "Invalid command name.");
+ return TRUE;
+ }
/* UID commands are a special case. better to handle them
here. */
- if (!cmd->uid && strcasecmp(cmd->name, "UID") == 0) {
+ if (!cmd->uid && strcasecmp(name, "UID") == 0) {
cmd->uid = TRUE;
- cmd->name = imap_parser_read_word(cmd->parser);
- if (cmd->name == NULL)
- return FALSE; /* need more data */
+ return client_command_input(cmd);
}
- cmd->name = !cmd->uid ? p_strdup(cmd->pool, cmd->name) :
- p_strconcat(cmd->pool, "UID ", cmd->name, NULL);
+ cmd->name = !cmd->uid ? p_strdup(cmd->pool, name) :
+ p_strconcat(cmd->pool, "UID ", name, NULL);
client_command_init_finished(cmd);
imap_refresh_proctitle();
}

View File

@ -1,55 +0,0 @@
From 62061e8cf68f506c0ccaaba21fd4174764ca875f Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 17 Aug 2020 18:15:35 +0300
Subject: [PATCH] imap-login: Split off client_invalid_command()
---
src/imap-login/imap-login-client.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c
index e2af176309..ce5049d567 100644
--- a/src/imap-login/imap-login-client.c
+++ b/src/imap-login/imap-login-client.c
@@ -194,6 +194,22 @@ static int client_command_execute(struct imap_client *client, const char *cmd,
return login_cmd->func(client, args);
}
+static bool client_invalid_command(struct imap_client *client)
+{
+ if (*client->cmd_tag == '\0')
+ client->cmd_tag = "*";
+ if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) {
+ client_send_reply(&client->common, IMAP_CMD_REPLY_BYE,
+ "Too many invalid IMAP commands.");
+ client_destroy(&client->common,
+ "Disconnected: Too many invalid commands");
+ return FALSE;
+ }
+ client_send_reply(&client->common, IMAP_CMD_REPLY_BAD,
+ "Error in IMAP command received by server.");
+ return TRUE;
+}
+
static bool imap_is_valid_tag(const char *tag)
{
for (; *tag != '\0'; tag++) {
@@ -326,17 +342,8 @@ static bool imap_client_input_next_cmd(struct client *_client)
"not the command name. Add that before the command, "
"like: a login user pass");
} else if (ret < 0) {
- if (*client->cmd_tag == '\0')
- client->cmd_tag = "*";
- if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) {
- client_send_reply(&client->common, IMAP_CMD_REPLY_BYE,
- "Too many invalid IMAP commands.");
- client_destroy(&client->common,
- "Disconnected: Too many invalid commands");
+ if (!client_invalid_command(client))
return FALSE;
- }
- client_send_reply(&client->common, IMAP_CMD_REPLY_BAD,
- "Error in IMAP command received by server.");
}
return ret != 0 && !client->common.destroyed;

View File

@ -1,110 +0,0 @@
From 9d3ecff3de5553159334cf644e996a616dc52670 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 17 Aug 2020 18:22:42 +0300
Subject: [PATCH] imap-login: Use imap_parser_read_tag() and
_read_command_name()
---
src/imap-login/imap-login-client.c | 58 ++++++++++++------------------
1 file changed, 23 insertions(+), 35 deletions(-)
diff --git a/src/imap-login/imap-login-client.c b/src/imap-login/imap-login-client.c
index ce5049d567..b2c8af9cbf 100644
--- a/src/imap-login/imap-login-client.c
+++ b/src/imap-login/imap-login-client.c
@@ -196,7 +196,7 @@ static int client_command_execute(struct imap_client *client, const char *cmd,
static bool client_invalid_command(struct imap_client *client)
{
- if (*client->cmd_tag == '\0')
+ if (client->cmd_tag == NULL || *client->cmd_tag == '\0')
client->cmd_tag = "*";
if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) {
client_send_reply(&client->common, IMAP_CMD_REPLY_BYE,
@@ -210,33 +210,6 @@ static bool client_invalid_command(struct imap_client *client)
return TRUE;
}
-static bool imap_is_valid_tag(const char *tag)
-{
- for (; *tag != '\0'; tag++) {
- switch (*tag) {
- case '+':
- /* atom-specials: */
- case '(':
- case ')':
- case '{':
- case '/':
- case ' ':
- /* list-wildcards: */
- case '%':
- case '*':
- /* quoted-specials: */
- case '"':
- case '\\':
- return FALSE;
- default:
- if (*tag < ' ') /* CTL */
- return FALSE;
- break;
- }
- }
- return TRUE;
-}
-
static int client_parse_command(struct imap_client *client,
const struct imap_arg **args_r)
{
@@ -261,6 +234,9 @@ static int client_parse_command(struct imap_client *client,
static bool client_handle_input(struct imap_client *client)
{
+ const char *tag, *name;
+ int ret;
+
i_assert(!client->common.authenticating);
if (client->cmd_finished) {
@@ -282,23 +258,35 @@ static bool client_handle_input(struct imap_client *client)
}
if (client->cmd_tag == NULL) {
- client->cmd_tag = imap_parser_read_word(client->parser);
- if (client->cmd_tag == NULL)
+ ret = imap_parser_read_tag(client->parser, &tag);
+ if (ret == 0)
return FALSE; /* need more data */
- if (!imap_is_valid_tag(client->cmd_tag) ||
- strlen(client->cmd_tag) > IMAP_TAG_MAX_LEN) {
+ if (ret < 0 || strlen(tag) > IMAP_TAG_MAX_LEN) {
/* the tag is invalid, don't allow it and don't
send it back. this attempts to prevent any
potentially dangerous replies in case someone tries
to access us using HTTP protocol. */
- client->cmd_tag = "";
+ client->skip_line = TRUE;
+ client->cmd_finished = TRUE;
+ if (!client_invalid_command(client))
+ return FALSE;
+ return client_handle_input(client);
}
+ client->cmd_tag = tag;
}
if (client->cmd_name == NULL) {
- client->cmd_name = imap_parser_read_word(client->parser);
- if (client->cmd_name == NULL)
+ ret = imap_parser_read_command_name(client->parser, &name);
+ if (ret == 0)
return FALSE; /* need more data */
+ if (ret < 0) {
+ client->skip_line = TRUE;
+ client->cmd_finished = TRUE;
+ if (!client_invalid_command(client))
+ return FALSE;
+ return client_handle_input(client);
+ }
+ client->cmd_name = name;
}
return client->common.v.input_next_cmd(&client->common);
}

View File

@ -1,39 +0,0 @@
From 7a70f01fe8084431901433a2f74cb9c70fd00568 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 17 Aug 2020 18:26:01 +0300
Subject: [PATCH] lib-imap: Add imap_parser_client_read_tag()
---
src/lib-imap/imap-parser.c | 6 ++++++
src/lib-imap/imap-parser.h | 5 +++++
2 files changed, 11 insertions(+)
diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c
index 52d79282fa..cc283f5c06 100644
--- a/src/lib-imap/imap-parser.c
+++ b/src/lib-imap/imap-parser.c
@@ -1014,3 +1014,9 @@ int imap_parser_read_command_name(struct imap_parser *parser,
{
return imap_parser_read_next_atom(parser, FALSE, name_r);
}
+
+int imap_parser_client_read_tag(struct imap_parser *parser,
+ const char **tag_r)
+{
+ return imap_parser_read_next_atom(parser, FALSE, tag_r);
+}
diff --git a/src/lib-imap/imap-parser.h b/src/lib-imap/imap-parser.h
index 5e09d61d2b..cd3748c00f 100644
--- a/src/lib-imap/imap-parser.h
+++ b/src/lib-imap/imap-parser.h
@@ -108,5 +108,10 @@ int imap_parser_read_tag(struct imap_parser *parser, const char **tag_r);
needed, -1 if input isn't a valid command name string. */
int imap_parser_read_command_name(struct imap_parser *parser,
const char **name_r);
+/* For IMAP clients: Read the command tag, which could also be "+" or "*".
+ Returns 1 if tag was returned, 0 if more data is needed, -1 if input isn't
+ valid. */
+int imap_parser_client_read_tag(struct imap_parser *parser,
+ const char **tag_r);
#endif

View File

@ -1,126 +0,0 @@
From fb97a1cddbda4019e327fa736972a1c7433fedaa Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Fri, 11 Sep 2020 09:53:03 +0300
Subject: [PATCH] lib-mail: message-parser - Fix assert-crash when enforcing
MIME part limit
The limit could have been exceeded with message/rfc822 parts.
---
src/lib-mail/message-parser.c | 3 +-
src/lib-mail/test-message-parser.c | 82 ++++++++++++++++++++++++++++++
2 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
index 6ab4c3266f..40a504da0a 100644
--- a/src/lib-mail/message-parser.c
+++ b/src/lib-mail/message-parser.c
@@ -703,7 +703,8 @@ static int parse_next_header(struct message_parser_ctx *ctx,
ctx->multipart = FALSE;
ctx->parse_next_block = parse_next_body_to_boundary;
} else if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0 &&
- !parse_too_many_nested_mime_parts(ctx)) {
+ !parse_too_many_nested_mime_parts(ctx) &&
+ ctx->total_parts_count < ctx->max_total_mime_parts) {
ctx->parse_next_block = parse_next_body_message_rfc822_init;
} else {
part->flags &= ~MESSAGE_PART_FLAG_MESSAGE_RFC822;
diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c
index 8c5a3404f1..c4e117afc7 100644
--- a/src/lib-mail/test-message-parser.c
+++ b/src/lib-mail/test-message-parser.c
@@ -1127,6 +1127,87 @@ static const char input_msg[] =
test_end();
}
+static void test_message_parser_mime_part_limit_rfc822(void)
+{
+static const char input_msg[] =
+"Content-Type: multipart/mixed; boundary=\"1\"\n"
+"\n"
+"--1\n"
+"Content-Type: multipart/mixed; boundary=\"2\"\n"
+"\n"
+"--2\n"
+"Content-Type: message/rfc822\n"
+"\n"
+"Content-Type: text/plain\n"
+"\n"
+"1\n"
+"--2\n"
+"Content-Type: message/rfc822\n"
+"\n"
+"Content-Type: text/plain\n"
+"\n"
+"22\n"
+"--1\n"
+"Content-Type: message/rfc822\n"
+"\n"
+"Content-Type: text/plain\n"
+"\n"
+"333\n";
+ const struct message_parser_settings parser_set = {
+ .max_total_mime_parts = 3,
+ };
+ struct message_parser_ctx *parser;
+ struct istream *input;
+ struct message_part *parts, *part;
+ struct message_block block;
+ pool_t pool;
+ int ret;
+
+ test_begin("message parser mime part limit rfc822");
+ pool = pool_alloconly_create("message parser", 10240);
+ input = test_istream_create(input_msg);
+
+ parser = message_parser_init(pool, input, &parser_set);
+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
+ test_assert(ret < 0);
+ message_parser_deinit(&parser, &parts);
+
+ part = parts;
+ test_assert(part->children_count == 2);
+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
+ test_assert(part->header_size.lines == 2);
+ test_assert(part->header_size.physical_size == 45);
+ test_assert(part->header_size.virtual_size == 45+2);
+ test_assert(part->body_size.lines == 21);
+ test_assert(part->body_size.physical_size == 238);
+ test_assert(part->body_size.virtual_size == 238+21);
+
+ part = parts->children;
+ test_assert(part->children_count == 1);
+ test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
+ test_assert(part->header_size.lines == 2);
+ test_assert(part->header_size.physical_size == 45);
+ test_assert(part->header_size.virtual_size == 45+2);
+ test_assert(part->body_size.lines == 18);
+ test_assert(part->body_size.physical_size == 189);
+ test_assert(part->body_size.virtual_size == 189+18);
+
+ part = parts->children->children;
+ test_assert(part->children_count == 0);
+ test_assert(part->flags == MESSAGE_PART_FLAG_IS_MIME);
+ test_assert(part->header_size.lines == 2);
+ test_assert(part->header_size.physical_size == 30);
+ test_assert(part->header_size.virtual_size == 30+2);
+ test_assert(part->body_size.lines == 15);
+ test_assert(part->body_size.physical_size == 155);
+ test_assert(part->body_size.virtual_size == 155+15);
+
+ test_parsed_parts(input, parts);
+ i_stream_unref(&input);
+ pool_unref(&pool);
+ test_end();
+}
+
int main(void)
{
static void (*const test_functions[])(void) = {
@@ -1301,6 +1382,7 @@ int main(void)
test_message_parser_mime_part_nested_limit,
test_message_parser_mime_part_nested_limit_rfc822,
test_message_parser_mime_part_limit,
+ test_message_parser_mime_part_limit_rfc822,
NULL
};
return test_run(test_functions);

View File

@ -1,63 +0,0 @@
From 266e54b7b8c34c9a58dd60a2e53c5ca7d1deae19 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Fri, 11 Sep 2020 10:57:51 +0300
Subject: [PATCH] lib-imap: Don't generate invalid BODYSTRUCTURE when reaching
MIME part limit
If the last MIME part was message/rfc822 and its child was truncated away,
BODYSTRUCTURE was missing the ENVELOPE and BODY[STRUCTURE] parts. Fixed by
writing empty dummy ones.
---
src/lib-imap/imap-bodystructure.c | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c
index 4e379e56a9..e3da1090b4 100644
--- a/src/lib-imap/imap-bodystructure.c
+++ b/src/lib-imap/imap-bodystructure.c
@@ -146,11 +146,25 @@ static void part_write_body(const struct message_part *part,
string_t *str, bool extended)
{
const struct message_part_data *data = part->data;
- bool text;
+ bool text, message_rfc822;
i_assert(part->data != NULL);
- if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0) {
+ if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0)
+ message_rfc822 = TRUE;
+ else if (data->content_type != NULL &&
+ strcasecmp(data->content_type, "message") == 0 &&
+ strcasecmp(data->content_subtype, "rfc822") == 0) {
+ /* It's message/rfc822, but without
+ MESSAGE_PART_FLAG_MESSAGE_RFC822. That likely means maximum
+ MIME part count was reached while parsing the mail. Write
+ the missing child mail's ENVELOPE and BODY as empty dummy
+ values. */
+ message_rfc822 = TRUE;
+ } else
+ message_rfc822 = FALSE;
+
+ if (message_rfc822) {
str_append(str, "\"message\" \"rfc822\"");
text = FALSE;
} else {
@@ -200,6 +214,17 @@ static void part_write_body(const struct message_part *part,
part_write_bodystructure_siblings(part->children, str, extended);
str_printfa(str, " %u", part->body_size.lines);
+ } else if (message_rfc822) {
+ /* truncated MIME part - write out dummy values */
+ i_assert(part->children == NULL);
+
+ str_append(str, " (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) ");
+
+ if (!extended)
+ str_append(str, EMPTY_BODY);
+ else
+ str_append(str, EMPTY_BODYSTRUCTURE);
+ str_printfa(str, " %u", part->body_size.lines);
}
if (!extended)

View File

@ -1,228 +0,0 @@
From 530c1e950a1bb46ff4e4a7c8e4b7cd945ff28916 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Wed, 18 Nov 2020 18:55:34 +0200
Subject: [PATCH] lib-imap: Fix writing BODYSTRUCTURE for truncated
message/rfc822 part
If the max nesting limit is reached, write the last part out as
application/octet-stream instead of dummy message/rfc822.
Fixes error while parsing BODYSTRUCTURE:
message_part message/rfc822 flag doesn't match BODYSTRUCTURE
---
src/lib-imap/imap-bodystructure.c | 54 +++++++++----------
src/lib-imap/test-imap-bodystructure.c | 73 ++++++++++++++++++++++++--
2 files changed, 96 insertions(+), 31 deletions(-)
diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c
index e3da1090b4..ab422c00d2 100644
--- a/src/lib-imap/imap-bodystructure.c
+++ b/src/lib-imap/imap-bodystructure.c
@@ -142,31 +142,42 @@ static void part_write_body_multipart(const struct message_part *part,
part_write_bodystructure_common(data, str);
}
+static bool part_is_truncated(const struct message_part *part)
+{
+ const struct message_part_data *data = part->data;
+
+ i_assert((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) == 0);
+
+ if (data->content_type != NULL) {
+ if (strcasecmp(data->content_type, "message") == 0 &&
+ strcasecmp(data->content_subtype, "rfc822") == 0) {
+ /* It's message/rfc822, but without
+ MESSAGE_PART_FLAG_MESSAGE_RFC822. */
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
static void part_write_body(const struct message_part *part,
string_t *str, bool extended)
{
const struct message_part_data *data = part->data;
- bool text, message_rfc822;
+ bool text;
i_assert(part->data != NULL);
- if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0)
- message_rfc822 = TRUE;
- else if (data->content_type != NULL &&
- strcasecmp(data->content_type, "message") == 0 &&
- strcasecmp(data->content_subtype, "rfc822") == 0) {
- /* It's message/rfc822, but without
- MESSAGE_PART_FLAG_MESSAGE_RFC822. That likely means maximum
- MIME part count was reached while parsing the mail. Write
- the missing child mail's ENVELOPE and BODY as empty dummy
- values. */
- message_rfc822 = TRUE;
- } else
- message_rfc822 = FALSE;
-
- if (message_rfc822) {
+ if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0) {
str_append(str, "\"message\" \"rfc822\"");
text = FALSE;
+ } else if (part_is_truncated(part)) {
+ /* Maximum MIME part count was reached while parsing the mail.
+ Write this part out as application/octet-stream instead.
+ We're not using text/plain, because it would require
+ message-parser to use MESSAGE_PART_FLAG_TEXT for this part
+ to avoid losing line count in message_part serialization. */
+ str_append(str, "\"application\" \"octet-stream\"");
+ text = FALSE;
} else {
/* "content type" "subtype" */
if (data->content_type == NULL) {
@@ -214,17 +225,6 @@ static void part_write_body(const struct message_part *part,
part_write_bodystructure_siblings(part->children, str, extended);
str_printfa(str, " %u", part->body_size.lines);
- } else if (message_rfc822) {
- /* truncated MIME part - write out dummy values */
- i_assert(part->children == NULL);
-
- str_append(str, " (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) ");
-
- if (!extended)
- str_append(str, EMPTY_BODY);
- else
- str_append(str, EMPTY_BODYSTRUCTURE);
- str_printfa(str, " %u", part->body_size.lines);
}
if (!extended)
diff --git a/src/lib-imap/test-imap-bodystructure.c b/src/lib-imap/test-imap-bodystructure.c
index dfc9957488..6cb699e126 100644
--- a/src/lib-imap/test-imap-bodystructure.c
+++ b/src/lib-imap/test-imap-bodystructure.c
@@ -4,6 +4,7 @@
#include "istream.h"
#include "str.h"
#include "message-part-data.h"
+#include "message-part-serialize.h"
#include "message-parser.h"
#include "imap-bodystructure.h"
#include "test-common.h"
@@ -379,12 +380,14 @@ struct normalize_test normalize_tests[] = {
static const unsigned int normalize_tests_count = N_ELEMENTS(normalize_tests);
static struct message_part *
-msg_parse(pool_t pool, const char *message, bool parse_bodystructure)
+msg_parse(pool_t pool, const char *message, unsigned int max_nested_mime_parts,
+ bool parse_bodystructure)
{
const struct message_parser_settings parser_set = {
.hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP |
MESSAGE_HEADER_PARSER_FLAG_DROP_CR,
.flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK,
+ .max_nested_mime_parts = max_nested_mime_parts,
};
struct message_parser_ctx *parser;
struct istream *input;
@@ -418,7 +421,7 @@ static void test_imap_bodystructure_write(void)
pool_t pool = pool_alloconly_create("imap bodystructure write", 1024);
test_begin(t_strdup_printf("imap bodystructure write [%u]", i));
- parts = msg_parse(pool, test->message, TRUE);
+ parts = msg_parse(pool, test->message, 0, TRUE);
imap_bodystructure_write(parts, str, TRUE);
test_assert(strcmp(str_c(str), test->bodystructure) == 0);
@@ -445,7 +448,7 @@ static void test_imap_bodystructure_parse(void)
pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024);
test_begin(t_strdup_printf("imap bodystructure parser [%u]", i));
- parts = msg_parse(pool, test->message, FALSE);
+ parts = msg_parse(pool, test->message, 0, FALSE);
test_assert(imap_body_parse_from_bodystructure(test->bodystructure,
str, &error) == 0);
@@ -512,7 +515,7 @@ static void test_imap_bodystructure_normalize(void)
pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024);
test_begin(t_strdup_printf("imap bodystructure normalize [%u]", i));
- parts = msg_parse(pool, test->message, FALSE);
+ parts = msg_parse(pool, test->message, 0, FALSE);
ret = imap_bodystructure_parse(test->input,
pool, parts, &error);
@@ -531,6 +534,67 @@ static void test_imap_bodystructure_normalize(void)
} T_END;
}
+static const struct {
+ const char *input;
+ const char *bodystructure;
+ unsigned int max_depth;
+} truncation_tests[] = {
+ {
+ .input = "Content-Type: message/rfc822\n"
+ "\n"
+ "Content-Type: message/rfc822\n"
+ "Header2: value2\n"
+ "\n"
+ "Subject: hello world\n"
+ "Header2: value2\n"
+ "Header3: value3\n"
+ "\n"
+ "body line 1\n"
+ "body line 2\n"
+ "body line 4\n"
+ "body line 3\n",
+ .bodystructure = "\"message\" \"rfc822\" NIL NIL NIL \"7bit\" 159 (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) (\"application\" \"octet-stream\" NIL NIL NIL \"7bit\" 110 NIL NIL NIL NIL) 11 NIL NIL NIL NIL",
+ .max_depth = 2,
+ },
+};
+
+static void test_imap_bodystructure_truncation(void)
+{
+ struct message_part *parts;
+ const char *error;
+ string_t *str_body = t_str_new(128);
+ string_t *str_parts = t_str_new(128);
+ pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024);
+
+ test_begin("imap bodystructure truncation");
+
+ for (unsigned int i = 0; i < N_ELEMENTS(truncation_tests); i++) {
+ p_clear(pool);
+ str_truncate(str_body, 0);
+ str_truncate(str_parts, 0);
+
+ parts = msg_parse(pool, truncation_tests[i].input,
+ truncation_tests[i].max_depth,
+ TRUE);
+
+ /* write out BODYSTRUCTURE and serialize message_parts */
+ imap_bodystructure_write(parts, str_body, TRUE);
+ message_part_serialize(parts, str_parts);
+
+ /* now deserialize message_parts and make sure they can be used
+ to parse BODYSTRUCTURE */
+ parts = message_part_deserialize(pool, str_data(str_parts),
+ str_len(str_parts), &error);
+ test_assert(parts != NULL);
+ test_assert(imap_bodystructure_parse(str_c(str_body), pool,
+ parts, &error) == 0);
+ test_assert_strcmp(str_c(str_body),
+ truncation_tests[i].bodystructure);
+ }
+ pool_unref(&pool);
+ test_end();
+}
+
int main(void)
{
static void (*const test_functions[])(void) = {
@@ -538,6 +602,7 @@ int main(void)
test_imap_bodystructure_parse,
test_imap_bodystructure_normalize,
test_imap_bodystructure_parse_full,
+ test_imap_bodystructure_truncation,
NULL
};
return test_run(test_functions);

View File

@ -1,64 +0,0 @@
From ec2c5ffde7a1ca63219d47831725599e7de76f7f Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Wed, 18 Nov 2020 20:48:11 +0200
Subject: [PATCH] lib-imap: Fix writing BODYSTRUCTURE for truncated multipart/
part
If the max nesting limit is reached, write the last part out as
application/octet-stream. The original content-type could be confusing
IMAP clients when they don't see any child parts.
---
src/lib-imap/imap-bodystructure.c | 6 ++++++
src/lib-imap/test-imap-bodystructure.c | 15 +++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c
index ab422c00d2..bfb6e64197 100644
--- a/src/lib-imap/imap-bodystructure.c
+++ b/src/lib-imap/imap-bodystructure.c
@@ -147,6 +147,7 @@ static bool part_is_truncated(const struct message_part *part)
const struct message_part_data *data = part->data;
i_assert((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) == 0);
+ i_assert((part->flags & MESSAGE_PART_FLAG_MULTIPART) == 0);
if (data->content_type != NULL) {
if (strcasecmp(data->content_type, "message") == 0 &&
@@ -155,6 +156,11 @@ static bool part_is_truncated(const struct message_part *part)
MESSAGE_PART_FLAG_MESSAGE_RFC822. */
return TRUE;
}
+ if (strcasecmp(data->content_type, "multipart") == 0) {
+ /* It's multipart/, but without
+ MESSAGE_PART_FLAG_MULTIPART. */
+ return TRUE;
+ }
}
return FALSE;
}
diff --git a/src/lib-imap/test-imap-bodystructure.c b/src/lib-imap/test-imap-bodystructure.c
index 6cb699e126..2118907e78 100644
--- a/src/lib-imap/test-imap-bodystructure.c
+++ b/src/lib-imap/test-imap-bodystructure.c
@@ -556,6 +556,21 @@ static const struct {
.bodystructure = "\"message\" \"rfc822\" NIL NIL NIL \"7bit\" 159 (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) (\"application\" \"octet-stream\" NIL NIL NIL \"7bit\" 110 NIL NIL NIL NIL) 11 NIL NIL NIL NIL",
.max_depth = 2,
},
+ {
+ .input = "Content-Type: multipart/mixed; boundary=1\n"
+ "\n"
+ "--1\n"
+ "Content-Type: multipart/mixed; boundary=2\n"
+ "\n"
+ "--2\n"
+ "Content-Type: multipart/mixed; boundary=3\n"
+ "\n"
+ "--3\n"
+ "\n"
+ "body\n",
+ .bodystructure = "(\"application\" \"octet-stream\" (\"boundary\" \"2\") NIL NIL \"7bit\" 63 NIL NIL NIL NIL) \"mixed\" (\"boundary\" \"1\") NIL NIL NIL",
+ .max_depth = 2,
+ },
};
static void test_imap_bodystructure_truncation(void)

View File

@ -1,127 +0,0 @@
From a912198bdc38421ad84044089db84fc14c69c228 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Wed, 18 Nov 2020 21:22:45 +0200
Subject: [PATCH] lib-imap: Fix writing BODYSTRUCTURE for truncated
multipart/digest part
Fixes error while parsing BODYSTRUCTURE:
message_part message/rfc822 flag doesn't match lines in BODYSTRUCTURE
---
src/lib-imap/imap-bodystructure.c | 9 +++++++++
src/lib-imap/test-imap-bodystructure.c | 28 ++++++++++++++++++++++----
2 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/src/lib-imap/imap-bodystructure.c b/src/lib-imap/imap-bodystructure.c
index bfb6e64197..5d2e5a3a84 100644
--- a/src/lib-imap/imap-bodystructure.c
+++ b/src/lib-imap/imap-bodystructure.c
@@ -161,6 +161,14 @@ static bool part_is_truncated(const struct message_part *part)
MESSAGE_PART_FLAG_MULTIPART. */
return TRUE;
}
+ } else {
+ /* No Content-Type */
+ if (part->parent != NULL &&
+ (part->parent->flags & MESSAGE_PART_FLAG_MULTIPART_DIGEST) != 0) {
+ /* Parent is MESSAGE_PART_FLAG_MULTIPART_DIGEST
+ (so this should have been message/rfc822). */
+ return TRUE;
+ }
}
return FALSE;
}
@@ -195,6 +203,7 @@ static void part_write_body(const struct message_part *part,
str_append_c(str, ' ');
imap_append_string(str, data->content_subtype);
}
+ i_assert(text == ((part->flags & MESSAGE_PART_FLAG_TEXT) != 0));
}
/* ("content type param key" "value" ...) */
diff --git a/src/lib-imap/test-imap-bodystructure.c b/src/lib-imap/test-imap-bodystructure.c
index 2118907e78..0f70cb0035 100644
--- a/src/lib-imap/test-imap-bodystructure.c
+++ b/src/lib-imap/test-imap-bodystructure.c
@@ -381,13 +381,14 @@ static const unsigned int normalize_tests_count = N_ELEMENTS(normalize_tests);
static struct message_part *
msg_parse(pool_t pool, const char *message, unsigned int max_nested_mime_parts,
- bool parse_bodystructure)
+ unsigned int max_total_mime_parts, bool parse_bodystructure)
{
const struct message_parser_settings parser_set = {
.hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP |
MESSAGE_HEADER_PARSER_FLAG_DROP_CR,
.flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK,
.max_nested_mime_parts = max_nested_mime_parts,
+ .max_total_mime_parts = max_total_mime_parts,
};
struct message_parser_ctx *parser;
struct istream *input;
@@ -421,7 +422,7 @@ static void test_imap_bodystructure_write(void)
pool_t pool = pool_alloconly_create("imap bodystructure write", 1024);
test_begin(t_strdup_printf("imap bodystructure write [%u]", i));
- parts = msg_parse(pool, test->message, 0, TRUE);
+ parts = msg_parse(pool, test->message, 0, 0, TRUE);
imap_bodystructure_write(parts, str, TRUE);
test_assert(strcmp(str_c(str), test->bodystructure) == 0);
@@ -448,7 +449,7 @@ static void test_imap_bodystructure_parse(void)
pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024);
test_begin(t_strdup_printf("imap bodystructure parser [%u]", i));
- parts = msg_parse(pool, test->message, 0, FALSE);
+ parts = msg_parse(pool, test->message, 0, 0, FALSE);
test_assert(imap_body_parse_from_bodystructure(test->bodystructure,
str, &error) == 0);
@@ -515,7 +516,7 @@ static void test_imap_bodystructure_normalize(void)
pool_t pool = pool_alloconly_create("imap bodystructure parse", 1024);
test_begin(t_strdup_printf("imap bodystructure normalize [%u]", i));
- parts = msg_parse(pool, test->message, 0, FALSE);
+ parts = msg_parse(pool, test->message, 0, 0, FALSE);
ret = imap_bodystructure_parse(test->input,
pool, parts, &error);
@@ -538,6 +539,7 @@ static const struct {
const char *input;
const char *bodystructure;
unsigned int max_depth;
+ unsigned int max_total;
} truncation_tests[] = {
{
.input = "Content-Type: message/rfc822\n"
@@ -571,6 +573,23 @@ static const struct {
.bodystructure = "(\"application\" \"octet-stream\" (\"boundary\" \"2\") NIL NIL \"7bit\" 63 NIL NIL NIL NIL) \"mixed\" (\"boundary\" \"1\") NIL NIL NIL",
.max_depth = 2,
},
+ {
+ .input = "Content-Type: multipart/digest; boundary=1\n"
+ "\n"
+ "--1\n"
+ "\n"
+ "Subject: hdr1\n"
+ "\n"
+ "body1\n"
+ "--1\n"
+ "\n"
+ "Subject: hdr2\n"
+ "\n"
+ "body2\n",
+ .bodystructure = "(\"application\" \"octet-stream\" NIL NIL NIL \"7bit\" 55 NIL NIL NIL NIL) \"digest\" (\"boundary\" \"1\") NIL NIL NIL",
+ .max_total = 2,
+ },
+
};
static void test_imap_bodystructure_truncation(void)
@@ -590,6 +609,7 @@ static void test_imap_bodystructure_truncation(void)
parts = msg_parse(pool, truncation_tests[i].input,
truncation_tests[i].max_depth,
+ truncation_tests[i].max_total,
TRUE);
/* write out BODYSTRUCTURE and serialize message_parts */

View File

@ -0,0 +1,53 @@
commit ec4595097067a736717ef202fe8542b1b4bc2dd5
Author: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Tue Aug 10 12:22:08 2021 +0300
lib-index: Fix storing cache fields' last_used with 64bit big endian CPUs
diff --git a/src/lib-index/mail-cache-fields.c b/src/lib-index/mail-cache-fields.c
index e929fb559d..429e0d234c 100644
--- a/src/lib-index/mail-cache-fields.c
+++ b/src/lib-index/mail-cache-fields.c
@@ -524,6 +524,19 @@ static void copy_to_buf_byte(struct mail_cache *cache, buffer_t *dest,
}
}
+static void
+copy_to_buf_last_used(struct mail_cache *cache, buffer_t *dest, bool add_new)
+{
+ size_t offset = offsetof(struct mail_cache_field, last_used);
+#if defined(WORDS_BIGENDIAN) && SIZEOF_VOID_P == 8
+ /* 64bit time_t with big endian CPUs: copy the last 32 bits instead of
+ the first 32 bits (that are always 0). The 32 bits are enough until
+ year 2106, so we're not in a hurry to use 64 bits on disk. */
+ offset += sizeof(uint32_t);
+#endif
+ copy_to_buf(cache, dest, add_new, offset, sizeof(uint32_t));
+}
+
static int mail_cache_header_fields_update_locked(struct mail_cache *cache)
{
buffer_t *buffer;
@@ -536,9 +549,7 @@ static int mail_cache_header_fields_update_locked(struct mail_cache *cache)
buffer = t_buffer_create(256);
- copy_to_buf(cache, buffer, FALSE,
- offsetof(struct mail_cache_field, last_used),
- sizeof(uint32_t));
+ copy_to_buf_last_used(cache, buffer, FALSE);
ret = mail_cache_write(cache, buffer->data, buffer->used,
offset + MAIL_CACHE_FIELD_LAST_USED());
if (ret == 0) {
@@ -599,9 +610,7 @@ void mail_cache_header_fields_get(struct mail_cache *cache, buffer_t *dest)
buffer_append(dest, &hdr, sizeof(hdr));
/* we have to keep the field order for the existing fields. */
- copy_to_buf(cache, dest, TRUE,
- offsetof(struct mail_cache_field, last_used),
- sizeof(uint32_t));
+ copy_to_buf_last_used(cache, dest, TRUE);
copy_to_buf(cache, dest, TRUE,
offsetof(struct mail_cache_field, field_size),
sizeof(uint32_t));

View File

@ -1,6 +1,6 @@
diff -up dovecot-2.3.8/src/auth/auth-token.c.opensslhmac dovecot-2.3.8/src/auth/auth-token.c
--- dovecot-2.3.8/src/auth/auth-token.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/auth-token.c 2019-11-19 16:34:11.338037002 +0100
diff -up dovecot-2.3.14/src/auth/auth-token.c.opensslhmac dovecot-2.3.14/src/auth/auth-token.c
--- dovecot-2.3.14/src/auth/auth-token.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/auth/auth-token.c 2021-03-22 20:44:13.022912242 +0100
@@ -161,17 +161,17 @@ void auth_token_deinit(void)
const char *auth_token_get(const char *service, const char *session_pid,
const char *username, const char *session_id)
@ -26,9 +26,9 @@ diff -up dovecot-2.3.8/src/auth/auth-token.c.opensslhmac dovecot-2.3.8/src/auth/
return binary_to_hex(result, sizeof(result));
}
diff -up dovecot-2.3.8/src/auth/mech-cram-md5.c.opensslhmac dovecot-2.3.8/src/auth/mech-cram-md5.c
--- dovecot-2.3.8/src/auth/mech-cram-md5.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/mech-cram-md5.c 2019-11-19 16:34:11.338037002 +0100
diff -up dovecot-2.3.14/src/auth/mech-cram-md5.c.opensslhmac dovecot-2.3.14/src/auth/mech-cram-md5.c
--- dovecot-2.3.14/src/auth/mech-cram-md5.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/auth/mech-cram-md5.c 2021-03-22 20:44:13.022912242 +0100
@@ -51,7 +51,7 @@ static bool verify_credentials(struct cr
{
@ -52,59 +52,57 @@ diff -up dovecot-2.3.8/src/auth/mech-cram-md5.c.opensslhmac dovecot-2.3.8/src/au
response_hex = binary_to_hex(digest, sizeof(digest));
diff -up dovecot-2.3.8/src/auth/mech-scram-sha1.c.opensslhmac dovecot-2.3.8/src/auth/mech-scram-sha1.c
--- dovecot-2.3.8/src/auth/mech-scram-sha1.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/mech-scram-sha1.c 2019-11-19 16:34:11.338037002 +0100
@@ -71,7 +71,7 @@ static const char *get_scram_server_firs
diff -up dovecot-2.3.14/src/auth/mech-scram.c.opensslhmac dovecot-2.3.14/src/auth/mech-scram.c
--- dovecot-2.3.14/src/auth/mech-scram.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/auth/mech-scram.c 2021-03-22 20:44:13.022912242 +0100
@@ -78,7 +78,7 @@ static const char *get_scram_server_firs
static const char *get_scram_server_final(struct scram_auth_request *request)
{
const struct hash_method *hmethod = request->hash_method;
- struct hmac_context ctx;
+ struct openssl_hmac_context ctx;
const char *auth_message;
unsigned char server_signature[SHA1_RESULTLEN];
unsigned char server_signature[hmethod->digest_size];
string_t *str;
@@ -80,10 +80,10 @@ static const char *get_scram_server_fina
@@ -87,9 +87,9 @@ static const char *get_scram_server_fina
request->server_first_message, ",",
request->client_final_message_without_proof, NULL);
- hmac_init(&ctx, request->server_key, sizeof(request->server_key),
+ openssl_hmac_init(&ctx, request->server_key, sizeof(request->server_key),
&hash_method_sha1);
- hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod);
- hmac_update(&ctx, auth_message, strlen(auth_message));
- hmac_final(&ctx, server_signature);
+ openssl_hmac_init(&ctx, request->server_key, hmethod->digest_size, hmethod);
+ openssl_hmac_update(&ctx, auth_message, strlen(auth_message));
+ openssl_hmac_final(&ctx, server_signature);
str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(server_signature)));
str_append(str, "v=");
@@ -221,7 +221,7 @@ static bool parse_scram_client_first(str
@@ -228,7 +228,7 @@ static bool parse_scram_client_first(str
static bool verify_credentials(struct scram_auth_request *request)
{
const struct hash_method *hmethod = request->hash_method;
- struct hmac_context ctx;
+ struct openssl_hmac_context ctx;
const char *auth_message;
unsigned char client_key[SHA1_RESULTLEN];
unsigned char client_signature[SHA1_RESULTLEN];
@@ -232,10 +232,10 @@ static bool verify_credentials(struct sc
unsigned char client_key[hmethod->digest_size];
unsigned char client_signature[hmethod->digest_size];
@@ -239,9 +239,9 @@ static bool verify_credentials(struct sc
request->server_first_message, ",",
request->client_final_message_without_proof, NULL);
- hmac_init(&ctx, request->stored_key, sizeof(request->stored_key),
+ openssl_hmac_init(&ctx, request->stored_key, sizeof(request->stored_key),
&hash_method_sha1);
- hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod);
- hmac_update(&ctx, auth_message, strlen(auth_message));
- hmac_final(&ctx, client_signature);
+ openssl_hmac_init(&ctx, request->stored_key, hmethod->digest_size, hmethod);
+ openssl_hmac_update(&ctx, auth_message, strlen(auth_message));
+ openssl_hmac_final(&ctx, client_signature);
const unsigned char *proof_data = request->proof->data;
for (i = 0; i < sizeof(client_signature); i++)
client_key[i] =
diff -up dovecot-2.3.8/src/auth/password-scheme.c.opensslhmac dovecot-2.3.8/src/auth/password-scheme.c
--- dovecot-2.3.8/src/auth/password-scheme.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/password-scheme.c 2019-11-19 16:34:11.339036998 +0100
@@ -647,11 +647,11 @@ static void
diff -up dovecot-2.3.14/src/auth/password-scheme.c.opensslhmac dovecot-2.3.14/src/auth/password-scheme.c
--- dovecot-2.3.14/src/auth/password-scheme.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/auth/password-scheme.c 2021-03-22 20:44:13.022912242 +0100
@@ -639,11 +639,11 @@ static void
cram_md5_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
@ -118,104 +116,101 @@ diff -up dovecot-2.3.8/src/auth/password-scheme.c.opensslhmac dovecot-2.3.8/src/
strlen(plaintext), &hash_method_md5);
hmac_md5_get_cram_context(&ctx, context_digest);
diff -up dovecot-2.3.8/src/auth/password-scheme-scram.c.opensslhmac dovecot-2.3.8/src/auth/password-scheme-scram.c
--- dovecot-2.3.8/src/auth/password-scheme-scram.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/password-scheme-scram.c 2019-11-19 16:34:11.339036998 +0100
@@ -27,23 +27,23 @@ static void Hi(const unsigned char *str,
diff -up dovecot-2.3.14/src/auth/password-scheme-scram.c.opensslhmac dovecot-2.3.14/src/auth/password-scheme-scram.c
--- dovecot-2.3.14/src/auth/password-scheme-scram.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/auth/password-scheme-scram.c 2021-03-22 20:44:13.023912229 +0100
@@ -30,23 +30,23 @@ Hi(const struct hash_method *hmethod, co
const unsigned char *salt, size_t salt_size, unsigned int i,
unsigned char result[SHA1_RESULTLEN])
unsigned char *result)
{
- struct hmac_context ctx;
+ struct openssl_hmac_context ctx;
unsigned char U[SHA1_RESULTLEN];
unsigned char U[hmethod->digest_size];
unsigned int j, k;
/* Calculate U1 */
- hmac_init(&ctx, str, str_size, &hash_method_sha1);
- hmac_init(&ctx, str, str_size, hmethod);
- hmac_update(&ctx, salt, salt_size);
- hmac_update(&ctx, "\0\0\0\1", 4);
- hmac_final(&ctx, U);
+ openssl_hmac_init(&ctx, str, str_size, &hash_method_sha1);
+ openssl_hmac_init(&ctx, str, str_size, hmethod);
+ openssl_hmac_update(&ctx, salt, salt_size);
+ openssl_hmac_update(&ctx, "\0\0\0\1", 4);
+ openssl_hmac_final(&ctx, U);
memcpy(result, U, SHA1_RESULTLEN);
memcpy(result, U, hmethod->digest_size);
/* Calculate U2 to Ui and Hi */
for (j = 2; j <= i; j++) {
- hmac_init(&ctx, str, str_size, &hash_method_sha1);
- hmac_init(&ctx, str, str_size, hmethod);
- hmac_update(&ctx, U, sizeof(U));
- hmac_final(&ctx, U);
+ openssl_hmac_init(&ctx, str, str_size, &hash_method_sha1);
+ openssl_hmac_init(&ctx, str, str_size, hmethod);
+ openssl_hmac_update(&ctx, U, sizeof(U));
+ openssl_hmac_final(&ctx, U);
for (k = 0; k < SHA1_RESULTLEN; k++)
for (k = 0; k < hmethod->digest_size; k++)
result[k] ^= U[k];
}
@@ -94,7 +94,7 @@ int scram_sha1_verify(const char *plaint
const unsigned char *raw_password, size_t size,
const char **error_r)
@@ -102,7 +102,7 @@ int scram_verify(const struct hash_metho
const char *plaintext, const unsigned char *raw_password,
size_t size, const char **error_r)
{
- struct hmac_context ctx;
+ struct openssl_hmac_context ctx;
const char *salt_base64;
unsigned int iter_count;
const unsigned char *salt;
@@ -118,10 +118,10 @@ int scram_sha1_verify(const char *plaint
iter_count, salted_password);
@@ -126,9 +126,9 @@ int scram_verify(const struct hash_metho
salt, salt_len, iter_count, salted_password);
/* Calculate ClientKey */
- hmac_init(&ctx, salted_password, sizeof(salted_password),
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password),
&hash_method_sha1);
- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
- hmac_update(&ctx, "Client Key", 10);
- hmac_final(&ctx, client_key);
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
+ openssl_hmac_update(&ctx, "Client Key", 10);
+ openssl_hmac_final(&ctx, client_key);
/* Calculate StoredKey */
sha1_get_digest(client_key, sizeof(client_key), calculated_stored_key);
@@ -139,7 +139,7 @@ void scram_sha1_generate(const char *pla
hash_method_get_digest(hmethod, client_key, sizeof(client_key),
@@ -147,7 +147,7 @@ void scram_generate(const struct hash_me
const unsigned char **raw_password_r, size_t *size_r)
{
string_t *str;
- struct hmac_context ctx;
+ struct openssl_hmac_context ctx;
unsigned char salt[16];
unsigned char salted_password[SHA1_RESULTLEN];
unsigned char client_key[SHA1_RESULTLEN];
@@ -157,10 +157,10 @@ void scram_sha1_generate(const char *pla
unsigned char salted_password[hmethod->digest_size];
unsigned char client_key[hmethod->digest_size];
@@ -165,9 +165,9 @@ void scram_generate(const struct hash_me
sizeof(salt), SCRAM_DEFAULT_ITERATE_COUNT, salted_password);
/* Calculate ClientKey */
- hmac_init(&ctx, salted_password, sizeof(salted_password),
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password),
&hash_method_sha1);
- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
- hmac_update(&ctx, "Client Key", 10);
- hmac_final(&ctx, client_key);
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
+ openssl_hmac_update(&ctx, "Client Key", 10);
+ openssl_hmac_final(&ctx, client_key);
/* Calculate StoredKey */
sha1_get_digest(client_key, sizeof(client_key), stored_key);
@@ -168,10 +168,10 @@ void scram_sha1_generate(const char *pla
hash_method_get_digest(hmethod, client_key, sizeof(client_key),
@@ -176,9 +176,9 @@ void scram_generate(const struct hash_me
base64_encode(stored_key, sizeof(stored_key), str);
/* Calculate ServerKey */
- hmac_init(&ctx, salted_password, sizeof(salted_password),
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password),
&hash_method_sha1);
- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
- hmac_update(&ctx, "Server Key", 10);
- hmac_final(&ctx, server_key);
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
+ openssl_hmac_update(&ctx, "Server Key", 10);
+ openssl_hmac_final(&ctx, server_key);
str_append_c(str, ',');
base64_encode(server_key, sizeof(server_key), str);
diff -up dovecot-2.3.8/src/lib/hmac.c.opensslhmac dovecot-2.3.8/src/lib/hmac.c
--- dovecot-2.3.8/src/lib/hmac.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib/hmac.c 2019-11-19 17:25:28.045716181 +0100
diff -up dovecot-2.3.14/src/lib/hmac.c.opensslhmac dovecot-2.3.14/src/lib/hmac.c
--- dovecot-2.3.14/src/lib/hmac.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib/hmac.c 2021-03-22 20:44:13.023912229 +0100
@@ -7,6 +7,10 @@
* This software is released under the MIT license.
*/
@ -292,11 +287,11 @@ diff -up dovecot-2.3.8/src/lib/hmac.c.opensslhmac dovecot-2.3.8/src/lib/hmac.c
+ }
+ i_assert(no_fips);
+ struct orig_hmac_context_priv *ctx = &_ctx->u.priv;
int i;
unsigned char k_ipad[64];
unsigned char k_opad[64];
unsigned int i;
unsigned char k_ipad[meth->block_size];
unsigned char k_opad[meth->block_size];
@@ -53,9 +112,27 @@ void hmac_init(struct hmac_context *_ctx
safe_memset(k_opad, 0, 64);
safe_memset(k_opad, 0, meth->block_size);
}
-void hmac_final(struct hmac_context *_ctx, unsigned char *digest)
@ -453,9 +448,9 @@ diff -up dovecot-2.3.8/src/lib/hmac.c.opensslhmac dovecot-2.3.8/src/lib/hmac.c
- safe_memset(prk, 0, sizeof(prk));
- safe_memset(okm, 0, sizeof(okm));
}
diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.8/src/lib/hmac-cram-md5.c
--- dovecot-2.3.8/src/lib/hmac-cram-md5.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib/hmac-cram-md5.c 2019-11-19 16:34:11.339036998 +0100
diff -up dovecot-2.3.14/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.14/src/lib/hmac-cram-md5.c
--- dovecot-2.3.14/src/lib/hmac-cram-md5.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib/hmac-cram-md5.c 2021-03-22 20:44:13.023912229 +0100
@@ -9,10 +9,10 @@
#include "md5.h"
#include "hmac-cram-md5.h"
@ -482,9 +477,9 @@ diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.8/src/lib
const unsigned char *cdp;
struct md5_context *ctx = (void*)hmac_ctx->ctx;
diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.8/src/lib/hmac-cram-md5.h
--- dovecot-2.3.8/src/lib/hmac-cram-md5.h.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib/hmac-cram-md5.h 2019-11-19 16:34:11.339036998 +0100
diff -up dovecot-2.3.14/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.14/src/lib/hmac-cram-md5.h
--- dovecot-2.3.14/src/lib/hmac-cram-md5.h.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib/hmac-cram-md5.h 2021-03-22 20:44:13.023912229 +0100
@@ -5,9 +5,9 @@
#define CRAM_MD5_CONTEXTLEN 32
@ -497,19 +492,19 @@ diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.8/src/lib
const unsigned char context_digest[CRAM_MD5_CONTEXTLEN]);
diff -up dovecot-2.3.8/src/lib/hmac.h.opensslhmac dovecot-2.3.8/src/lib/hmac.h
--- dovecot-2.3.8/src/lib/hmac.h.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib/hmac.h 2019-11-19 16:34:11.339036998 +0100
@@ -3,60 +3,97 @@
diff -up dovecot-2.3.14/src/lib/hmac.h.opensslhmac dovecot-2.3.14/src/lib/hmac.h
--- dovecot-2.3.14/src/lib/hmac.h.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib/hmac.h 2021-03-22 20:44:13.023912229 +0100
@@ -4,60 +4,97 @@
#include "hash-method.h"
#include "sha1.h"
#include "sha2.h"
+#include <openssl/objects.h>
+#include <openssl/hmac.h>
+#include <openssl/kdf.h>
+#include <openssl/err.h>
#define HMAC_MAX_CONTEXT_SIZE 256
#define HMAC_MAX_CONTEXT_SIZE sizeof(struct sha512_ctx)
-struct hmac_context_priv {
+struct openssl_hmac_context_priv {
@ -611,9 +606,9 @@ diff -up dovecot-2.3.8/src/lib/hmac.h.opensslhmac dovecot-2.3.8/src/lib/hmac.h
okm_buffer, okm_len);
return okm_buffer;
}
diff -up dovecot-2.3.8/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac dovecot-2.3.8/src/lib-imap-urlauth/imap-urlauth.c
--- dovecot-2.3.8/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib-imap-urlauth/imap-urlauth.c 2019-11-19 16:34:11.339036998 +0100
diff -up dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c
--- dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib-imap-urlauth/imap-urlauth.c 2021-03-22 20:44:13.023912229 +0100
@@ -85,15 +85,15 @@ imap_urlauth_internal_generate(const cha
const unsigned char mailbox_key[IMAP_URLAUTH_KEY_LEN],
size_t *token_len_r)
@ -634,10 +629,10 @@ diff -up dovecot-2.3.8/src/lib-imap-urlauth/imap-urlauth.c.opensslhmac dovecot-2
*token_len_r = SHA1_RESULTLEN + 1;
return token;
diff -up dovecot-2.3.8/src/lib/Makefile.am.opensslhmac dovecot-2.3.8/src/lib/Makefile.am
--- dovecot-2.3.8/src/lib/Makefile.am.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib/Makefile.am 2019-11-19 16:34:11.340036994 +0100
@@ -323,6 +323,9 @@ headers = \
diff -up dovecot-2.3.14/src/lib/Makefile.am.opensslhmac dovecot-2.3.14/src/lib/Makefile.am
--- dovecot-2.3.14/src/lib/Makefile.am.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib/Makefile.am 2021-03-22 20:44:13.023912229 +0100
@@ -352,6 +352,9 @@ headers = \
wildcard-match.h \
write-full.h
@ -647,69 +642,63 @@ diff -up dovecot-2.3.8/src/lib/Makefile.am.opensslhmac dovecot-2.3.8/src/lib/Mak
test_programs = test-lib
noinst_PROGRAMS = $(test_programs)
diff -up dovecot-2.3.8/src/lib-ntlm/ntlm-encrypt.c.opensslhmac dovecot-2.3.8/src/lib-ntlm/ntlm-encrypt.c
--- dovecot-2.3.8/src/lib-ntlm/ntlm-encrypt.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib-ntlm/ntlm-encrypt.c 2019-11-19 16:34:11.340036994 +0100
@@ -61,12 +61,12 @@ void ntlm_v1_hash(const char *passwd, un
}
diff -up dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c.opensslhmac dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c
--- dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib-oauth2/oauth2-jwt.c 2021-03-22 20:44:13.024912217 +0100
@@ -106,14 +106,14 @@ oauth2_validate_hmac(const struct oauth2
if (oauth2_lookup_hmac_key(set, azp, alg, key_id, &key, error_r) < 0)
return -1;
static void
-hmac_md5_ucs2le_string_ucase(struct hmac_context *ctx, const char *str)
-{
- size_t len;
- unsigned char *wstr = t_unicode_str(str, TRUE, &len);
-
- hmac_update(ctx, wstr, len);
+hmac_md5_ucs2le_string_ucase(struct openssl_hmac_context *ctx, const char *str)
+ {
+ size_t len;
+ unsigned char *wstr = t_unicode_str(str, TRUE, &len);
+
+ openssl_hmac_update(ctx, wstr, len);
}
static void ATTR_NULL(2)
@@ -74,13 +74,13 @@ ntlm_v2_hash(const char *user, const cha
const unsigned char *hash_v1,
unsigned char hash[NTLMSSP_V2_HASH_SIZE])
{
- struct hmac_context ctx;
- hmac_init(&ctx, key->data, key->used, method);
- hmac_update(&ctx, blobs[0], strlen(blobs[0]));
- hmac_update(&ctx, ".", 1);
- hmac_update(&ctx, blobs[1], strlen(blobs[1]));
+ struct openssl_hmac_context ctx;
+ openssl_hmac_init(&ctx, key->data, key->used, method);
+ openssl_hmac_update(&ctx, blobs[0], strlen(blobs[0]));
+ openssl_hmac_update(&ctx, ".", 1);
+ openssl_hmac_update(&ctx, blobs[1], strlen(blobs[1]));
unsigned char digest[method->digest_size];
- hmac_init(&ctx, hash_v1, NTLMSSP_HASH_SIZE, &hash_method_md5);
+ openssl_hmac_init(&ctx, hash_v1, NTLMSSP_HASH_SIZE, &hash_method_md5);
hmac_md5_ucs2le_string_ucase(&ctx, user);
if (target != NULL)
hmac_md5_ucs2le_string_ucase(&ctx, target);
- hmac_final(&ctx, hash);
+ openssl_hmac_final(&ctx, hash);
}
- hmac_final(&ctx, digest);
+ openssl_hmac_final(&ctx, digest);
void
@@ -125,15 +125,15 @@ ntlmssp_v2_response(const char *user, co
const unsigned char *blob, size_t blob_size,
unsigned char response[NTLMSSP_V2_RESPONSE_SIZE])
buffer_t *their_digest =
t_base64url_decode_str(BASE64_DECODE_FLAG_NO_PADDING, blobs[2]);
diff -up dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c.opensslhmac dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c
--- dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib-oauth2/test-oauth2-jwt.c 2021-03-22 20:46:09.524440794 +0100
@@ -236,7 +236,7 @@ static void save_key_to(const char *algo
static void sign_jwt_token_hs256(buffer_t *tokenbuf, buffer_t *key)
{
- struct hmac_context ctx;
+ struct openssl_hmac_context ctx;
unsigned char hash[NTLMSSP_V2_HASH_SIZE];
ntlm_v2_hash(user, target, hash_v1, hash);
- hmac_init(&ctx, hash, NTLMSSP_V2_HASH_SIZE, &hash_method_md5);
- hmac_update(&ctx, challenge, NTLMSSP_CHALLENGE_SIZE);
- hmac_update(&ctx, blob, blob_size);
- hmac_final(&ctx, response);
+ openssl_hmac_init(&ctx, hash, NTLMSSP_V2_HASH_SIZE, &hash_method_md5);
+ openssl_hmac_update(&ctx, challenge, NTLMSSP_CHALLENGE_SIZE);
+ openssl_hmac_update(&ctx, blob, blob_size);
+ openssl_hmac_final(&ctx, response);
safe_memset(hash, 0, sizeof(hash));
}
diff -up dovecot-2.3.8/src/lib/pkcs5.c.opensslhmac dovecot-2.3.8/src/lib/pkcs5.c
--- dovecot-2.3.8/src/lib/pkcs5.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib/pkcs5.c 2019-11-19 16:34:11.340036994 +0100
i_assert(key != NULL);
- buffer_t *sig = t_hmac_buffer(&hash_method_sha256, key->data, key->used,
+ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha256, key->data, key->used,
tokenbuf);
buffer_append(tokenbuf, ".", 1);
base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX,
@@ -246,7 +246,7 @@ static void sign_jwt_token_hs256(buffer_
static void sign_jwt_token_hs384(buffer_t *tokenbuf, buffer_t *key)
{
i_assert(key != NULL);
- buffer_t *sig = t_hmac_buffer(&hash_method_sha384, key->data, key->used,
+ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha384, key->data, key->used,
tokenbuf);
buffer_append(tokenbuf, ".", 1);
base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX,
@@ -256,7 +256,7 @@ static void sign_jwt_token_hs384(buffer_
static void sign_jwt_token_hs512(buffer_t *tokenbuf, buffer_t *key)
{
i_assert(key != NULL);
- buffer_t *sig = t_hmac_buffer(&hash_method_sha512, key->data, key->used,
+ buffer_t *sig = openssl_t_hmac_buffer(&hash_method_sha512, key->data, key->used,
tokenbuf);
buffer_append(tokenbuf, ".", 1);
base64url_encode(BASE64_ENCODE_FLAG_NO_PADDING, SIZE_MAX,
diff -up dovecot-2.3.14/src/lib/pkcs5.c.opensslhmac dovecot-2.3.14/src/lib/pkcs5.c
--- dovecot-2.3.14/src/lib/pkcs5.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib/pkcs5.c 2021-03-22 20:44:13.024912217 +0100
@@ -52,7 +52,7 @@ int pkcs5_pbkdf2(const struct hash_metho
size_t l = (length + hash->digest_size - 1)/hash->digest_size; /* same as ceil(length/hash->digest_size) */
unsigned char dk[l * hash->digest_size];
@ -744,10 +733,10 @@ diff -up dovecot-2.3.8/src/lib/pkcs5.c.opensslhmac dovecot-2.3.8/src/lib/pkcs5.c
for(i = 0; i < hash->digest_size; i++)
block[i] ^= U_c[i];
}
diff -up dovecot-2.3.8/src/lib/test-hmac.c.opensslhmac dovecot-2.3.8/src/lib/test-hmac.c
--- dovecot-2.3.8/src/lib/test-hmac.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib/test-hmac.c 2019-11-19 16:34:11.340036994 +0100
@@ -112,11 +112,11 @@ static void test_hmac_rfc(void)
diff -up dovecot-2.3.14/src/lib/test-hmac.c.opensslhmac dovecot-2.3.14/src/lib/test-hmac.c
--- dovecot-2.3.14/src/lib/test-hmac.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib/test-hmac.c 2021-03-22 20:44:13.024912217 +0100
@@ -206,11 +206,11 @@ static void test_hmac_rfc(void)
test_begin("hmac sha256 rfc4231 vectors");
for(size_t i = 0; i < N_ELEMENTS(test_vectors); i++) {
const struct test_vector *vec = &(test_vectors[i]);
@ -763,7 +752,39 @@ diff -up dovecot-2.3.8/src/lib/test-hmac.c.opensslhmac dovecot-2.3.8/src/lib/tes
test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i);
}
test_end();
@@ -129,7 +129,7 @@ static void test_hmac_buffer(void)
@@ -221,11 +221,11 @@ static void test_hmac384_rfc(void)
test_begin("hmac sha384 rfc4231 vectors");
for (size_t i = 0; i < N_ELEMENTS(test_vectors_hmac384); i++) {
const struct test_vector *vec = &(test_vectors_hmac384[i]);
- struct hmac_context ctx;
- hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf));
- hmac_update(&ctx, vec->data, vec->data_len);
+ struct openssl_hmac_context ctx;
+ openssl_hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf));
+ openssl_hmac_update(&ctx, vec->data, vec->data_len);
unsigned char res[SHA384_RESULTLEN];
- hmac_final(&ctx, res);
+ openssl_hmac_final(&ctx, res);
test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i);
}
test_end();
@@ -236,11 +236,11 @@ static void test_hmac512_rfc(void)
test_begin("hmac sha512 rfc4231 vectors");
for (size_t i = 0; i < N_ELEMENTS(test_vectors_hmac512); i++) {
const struct test_vector *vec = &(test_vectors_hmac512[i]);
- struct hmac_context ctx;
- hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf));
- hmac_update(&ctx, vec->data, vec->data_len);
+ struct openssl_hmac_context ctx;
+ openssl_hmac_init(&ctx, vec->key, vec->key_len, hash_method_lookup(vec->prf));
+ openssl_hmac_update(&ctx, vec->data, vec->data_len);
unsigned char res[SHA512_RESULTLEN];
- hmac_final(&ctx, res);
+ openssl_hmac_final(&ctx, res);
test_assert_idx(memcmp(res, vec->res, vec->res_len) == 0, i);
}
test_end();
@@ -253,7 +253,7 @@ static void test_hmac_buffer(void)
buffer_t *tmp;
@ -772,7 +793,7 @@ diff -up dovecot-2.3.8/src/lib/test-hmac.c.opensslhmac dovecot-2.3.8/src/lib/tes
vec->data, vec->data_len);
test_assert(tmp->used == vec->res_len &&
@@ -146,7 +146,7 @@ static void test_hkdf_rfc(void)
@@ -270,7 +270,7 @@ static void test_hkdf_rfc(void)
buffer_set_used_size(res, 0);
const struct test_vector_5869 *vec = &(test_vectors_5869[i]);
const struct hash_method *m = hash_method_lookup(vec->prf);
@ -781,7 +802,7 @@ diff -up dovecot-2.3.8/src/lib/test-hmac.c.opensslhmac dovecot-2.3.8/src/lib/tes
vec->info, vec->info_len, res, vec->okm_len);
test_assert_idx(memcmp(res->data, vec->okm, vec->okm_len) == 0, i);
}
@@ -159,7 +159,7 @@ static void test_hkdf_buffer(void)
@@ -283,7 +283,7 @@ static void test_hkdf_buffer(void)
test_begin("hkdf temporary buffer");
const struct test_vector_5869 *vec = &(test_vectors_5869[0]);
const struct hash_method *m = hash_method_lookup(vec->prf);

File diff suppressed because it is too large Load Diff

View File

@ -1,56 +0,0 @@
diff -up dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c.CVE_2020_12100ph dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c
--- dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c.CVE_2020_12100ph 2019-10-08 10:48:14.000000000 +0200
+++ dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c 2020-08-07 16:42:56.515389867 +0200
@@ -148,6 +148,7 @@ static int cmd_notify_extract_body_text
const char **body_text_r, size_t *body_size_r)
{
const struct sieve_extension *this_ext = renv->oprtn->ext;
+ const struct message_parser_settings parser_set = { .flags = 0 };
struct ext_notify_message_context *mctx;
struct mail *mail = renv->msgdata->mail;
struct message_parser_ctx *parser;
@@ -181,7 +182,7 @@ static int cmd_notify_extract_body_text
/* Initialize body decoder */
decoder = message_decoder_init(NULL, 0);
- parser = message_parser_init(mctx->pool, input, 0, 0);
+ parser = message_parser_init(mctx->pool, input, &parser_set);
is_text = TRUE;
save_body = FALSE;
while ( (ret=message_parser_parse_next_block(parser, &block)) > 0 ) {
diff -up dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c.CVE_2020_12100ph dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c
--- dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c.CVE_2020_12100ph 2019-10-08 10:48:14.000000000 +0200
+++ dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c 2020-08-07 16:42:56.516389854 +0200
@@ -1077,10 +1077,10 @@ static int sieve_message_parts_add_missi
struct sieve_message_context *msgctx = renv->msgctx;
pool_t pool = msgctx->context_pool;
struct mail *mail = sieve_message_get_mail(renv->msgctx);
- enum message_parser_flags mparser_flags =
- MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS;
- enum message_header_parser_flags hparser_flags =
- MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP;
+ struct message_parser_settings parser_set = {
+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP,
+ .flags = MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS,
+ };
ARRAY(struct sieve_message_header) headers;
struct sieve_message_part *body_part, *header_part, *last_part;
struct message_parser_ctx *parser;
@@ -1117,7 +1117,7 @@ static int sieve_message_parts_add_missi
if (iter_all) {
t_array_init(&headers, 64);
hdr_content = t_str_new(512);
- hparser_flags |= MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE;
+ parser_set.hdr_flags |= MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE;
} else {
i_zero(&headers);
}
@@ -1129,7 +1129,7 @@ static int sieve_message_parts_add_missi
//parser = message_parser_init_from_parts(parts, input,
// hparser_flags, mparser_flags);
parser = message_parser_init(pool_datastack_create(),
- input, hparser_flags, mparser_flags);
+ input, &parser_set);
while ( (ret=message_parser_parse_next_block
(parser, &block)) > 0 ) {
struct sieve_message_part **body_part_idx;

View File

@ -1,224 +0,0 @@
diff -up dovecot-2.3.8/src/lib-mail/message-decoder.c.CVE_2020_12100prereq dovecot-2.3.8/src/lib-mail/message-decoder.c
--- dovecot-2.3.8/src/lib-mail/message-decoder.c.CVE_2020_12100prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib-mail/message-decoder.c 2020-08-07 17:48:58.320126698 +0200
@@ -13,9 +13,6 @@
#include "message-header-decode.h"
#include "message-decoder.h"
-/* base64 takes max 4 bytes per character, q-p takes max 3. */
-#define MAX_ENCODING_BUF_SIZE 3
-
struct message_decoder_context {
enum message_decoder_flags flags;
normalizer_func_t *normalizer;
@@ -30,7 +27,7 @@ struct message_decoder_context {
size_t translation_size;
struct qp_decoder *qp;
- buffer_t *encoding_buf;
+ struct base64_decoder base64_decoder;
char *content_type, *content_charset;
enum message_cte message_cte;
@@ -53,7 +50,7 @@ message_decoder_init(normalizer_func_t *
ctx->normalizer = normalizer;
ctx->buf = buffer_create_dynamic(default_pool, 8192);
ctx->buf2 = buffer_create_dynamic(default_pool, 8192);
- ctx->encoding_buf = buffer_create_dynamic(default_pool, 128);
+ base64_decode_init(&ctx->base64_decoder, &base64_scheme, 0);
return ctx;
}
@@ -68,7 +65,6 @@ void message_decoder_deinit(struct messa
if (ctx->qp != NULL)
qp_decoder_deinit(&ctx->qp);
- buffer_free(&ctx->encoding_buf);
buffer_free(&ctx->buf);
buffer_free(&ctx->buf2);
i_free(ctx->charset_trans_charset);
@@ -273,14 +269,9 @@ static bool message_decode_body(struct m
struct message_block *input,
struct message_block *output)
{
- struct base64_decoder b64dec;
const unsigned char *data = NULL;
- size_t pos = 0, size = 0;
+ size_t pos, size = 0;
const char *error;
- int ret;
-
- if (ctx->encoding_buf->used != 0)
- buffer_append(ctx->encoding_buf, input->data, input->size);
switch (ctx->message_cte) {
case MESSAGE_CTE_UNKNOWN:
@@ -289,12 +280,10 @@ static bool message_decode_body(struct m
case MESSAGE_CTE_78BIT:
case MESSAGE_CTE_BINARY:
- i_assert(ctx->encoding_buf->used == 0);
data = input->data;
- size = pos = input->size;
+ size = input->size;
break;
case MESSAGE_CTE_QP: {
- i_assert(ctx->encoding_buf->used == 0);
buffer_set_used_size(ctx->buf, 0);
if (ctx->qp == NULL)
ctx->qp = qp_decoder_init(ctx->buf);
@@ -302,45 +291,24 @@ static bool message_decode_body(struct m
&pos, &error);
data = ctx->buf->data;
size = ctx->buf->used;
- /* eat away all input. qp-decoder buffers it internally. */
- pos = input->size;
break;
}
case MESSAGE_CTE_BASE64:
buffer_set_used_size(ctx->buf, 0);
- base64_decode_init(&b64dec, &base64_scheme, 0);
- if (ctx->encoding_buf->used != 0) {
- ret = base64_decode_more(&b64dec,
- ctx->encoding_buf->data,
- ctx->encoding_buf->used,
- &pos, ctx->buf);
- } else {
- ret = base64_decode_more(&b64dec,
- input->data, input->size,
- &pos, ctx->buf);
- }
- if (ret < 0 || base64_decode_finish(&b64dec) < 0) {
- /* corrupted base64 data, don't bother with
- the rest of it */
- return FALSE;
- }
- if (ret == 0) {
- /* end of base64 input */
- pos = input->size;
- buffer_set_used_size(ctx->encoding_buf, 0);
+ if (!base64_decode_is_finished(&ctx->base64_decoder)) {
+ if (base64_decode_more(&ctx->base64_decoder,
+ input->data, input->size,
+ &pos, ctx->buf) <= 0) {
+ /* ignore the rest of the input in this
+ MIME part */
+ (void)base64_decode_finish(&ctx->base64_decoder);
+ }
}
data = ctx->buf->data;
size = ctx->buf->used;
break;
}
- if (ctx->encoding_buf->used != 0)
- buffer_delete(ctx->encoding_buf, 0, pos);
- else if (pos != input->size) {
- buffer_append(ctx->encoding_buf,
- input->data + pos, input->size - pos);
- }
-
if (ctx->binary_input) {
output->data = data;
output->size = size;
@@ -402,10 +370,11 @@ void message_decoder_decode_reset(struct
{
const char *error;
+ base64_decode_reset(&ctx->base64_decoder);
+
if (ctx->qp != NULL)
(void)qp_decoder_finish(ctx->qp, &error);
i_free_and_null(ctx->content_type);
i_free_and_null(ctx->content_charset);
ctx->message_cte = MESSAGE_CTE_78BIT;
- buffer_set_used_size(ctx->encoding_buf, 0);
}
diff -up dovecot-2.3.8/src/lib-mail/test-message-decoder.c.CVE_2020_12100prereq dovecot-2.3.8/src/lib-mail/test-message-decoder.c
--- dovecot-2.3.8/src/lib-mail/test-message-decoder.c.CVE_2020_12100prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib-mail/test-message-decoder.c 2020-08-07 17:50:04.612248484 +0200
@@ -1,7 +1,8 @@
/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
-#include "buffer.h"
+#include "str.h"
+#include "istream.h"
#include "charset-utf8.h"
#include "message-parser.h"
#include "message-header-decode.h"
@@ -82,6 +83,66 @@ static void test_message_decoder(void)
test_end();
}
+static void test_message_decoder_multipart(void)
+{
+ static const char test_message_input[] =
+ "Content-Type: multipart/mixed; boundary=foo\n"
+ "\n"
+ "--foo\n"
+ "Content-Transfer-Encoding: quoted-printable\n"
+ "Content-Type: text/plain; charset=utf-8\n"
+ "\n"
+ "p=C3=A4iv=C3=A4=C3=A4\n"
+ "\n"
+ "--foo\n"
+ "Content-Transfer-Encoding: base64\n"
+ "Content-Type: text/plain; charset=utf-8\n"
+ "\n"
+ "ecO2dMOkIHZhYW4uCg== ignored\n"
+ "--foo\n"
+ "Content-Transfer-Encoding: base64\n"
+ "Content-Type: text/plain; charset=utf-8\n"
+ "\n"
+ "?garbage\n"
+ "--foo--\n";
+ struct message_parser_ctx *parser;
+ struct message_decoder_context *decoder;
+ struct message_part *parts;
+ struct message_block input, output;
+ struct istream *istream;
+ string_t *str_out = t_str_new(20);
+ int ret;
+
+ test_begin("message decoder multipart");
+
+ istream = test_istream_create(test_message_input);
+ parser = message_parser_init(pool_datastack_create(), istream, 0, 0);
+ decoder = message_decoder_init(NULL, 0);
+
+ test_istream_set_allow_eof(istream, FALSE);
+ for (size_t i = 0; i < sizeof(test_message_input); i++) {
+ if (i == sizeof(test_message_input)-1)
+ test_istream_set_allow_eof(istream, TRUE);
+ test_istream_set_size(istream, i);
+ while ((ret = message_parser_parse_next_block(parser, &input)) > 0) {
+ if (message_decoder_decode_next_block(decoder, &input, &output) &&
+ output.hdr == NULL && output.size > 0)
+ str_append_data(str_out, output.data, output.size);
+ }
+ if (i == sizeof(test_message_input)-1)
+ test_assert(ret == -1);
+ else
+ test_assert(ret == 0);
+ }
+ /* NOTE: qp-decoder decoder changes \n into \r\n */
+ test_assert_strcmp(str_c(str_out), "p\xC3\xA4iv\xC3\xA4\xC3\xA4\r\ny\xC3\xB6t\xC3\xA4 vaan.\n");
+
+ message_decoder_deinit(&decoder);
+ message_parser_deinit(&parser, &parts);
+ i_stream_unref(&istream);
+ test_end();
+}
+
static void test_message_decoder_current_content_type(void)
{
struct message_decoder_context *ctx;
@@ -149,6 +210,7 @@ int main(void)
{
static void (*const test_functions[])(void) = {
test_message_decoder,
+ test_message_decoder_multipart,
test_message_decoder_current_content_type,
NULL
};

View File

@ -1,34 +0,0 @@
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 TRUE;
+ if (length > data_size) {
+ *error = "buffer length out of bounds";
+ return FALSE;
+ }
+
if (offset >= data_size) {
*error = "buffer offset out of bounds";
return FALSE;
--
2.11.0

View File

@ -1,234 +0,0 @@
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,196 @@
+/* Copyright (c) 2020 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "auth.h"
+#include "str.h"
+#include "auth-common.h"
+#include "auth-request.h"
+#include "auth-request-handler-private.h"
+#include "auth-settings.h"
+#include "otp.h"
+#include "mech-otp-skey-common.h"
+#include "settings-parser.h"
+#include "password-scheme.h"
+#include "test-common.h"
+#include "test-auth.h"
+#include "auth-token.h"
+
+#include <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)
+{
+ test_mechs_init();
+ static struct auth_request_handler handler = {
+ .callback = auth_client_request_mock_callback,
+ .reply_callback = request_handler_reply_mock_callback,
+ .reply_continue_callback = request_handler_reply_continue_mock_callback,
+ .verify_plain_continue_callback = verify_plain_continue_mock_callback,
+ };
+
+ const struct mech_module *mech = &mech_rpa;
+ test_begin("test rpa");
+ struct auth_request *req = mech->auth_new();
+ global_auth_settings->realms_arr = t_strsplit("example.com", " ");
+ req->set = global_auth_settings;
+ req->service = "login";
+ req->handler = &handler;
+ req->mech_event = event_create(NULL);
+ req->event = event_create(NULL);
+ req->mech = mech;
+ req->state = AUTH_REQUEST_STATE_MECH_CONTINUE;
+ auth_request_state_count[AUTH_REQUEST_STATE_MECH_CONTINUE] = 1;
+ mech->auth_initial(req, UCHAR_LEN("\x60\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x73\x01\x01\x01\x00\x04\x00\x00\x01"));
+ mech->auth_continue(req, UCHAR_LEN("\x60\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x73\x01\x01\x00\x03A@A\x00"));
+ test_assert(req->failed == TRUE);
+ test_assert(req->passdb_success == FALSE);
+ event_unref(&req->mech_event);
+ event_unref(&req->event);
+ mech->auth_free(req);
+ test_end();
+}
+
+static void test_ntlm(void)
+{
+ static struct auth_request_handler handler = {
+ .callback = auth_client_request_mock_callback,
+ .reply_callback = request_handler_reply_mock_callback,
+ .reply_continue_callback = request_handler_reply_continue_mock_callback,
+ .verify_plain_continue_callback = verify_plain_continue_mock_callback,
+ };
+
+ const struct mech_module *mech = &mech_ntlm;
+ test_begin("test ntlm");
+ struct auth_request *req = mech->auth_new();
+ global_auth_settings->realms_arr = t_strsplit("example.com", " ");
+ req->set = global_auth_settings;
+ req->service = "login";
+ req->handler = &handler;
+ req->mech_event = event_create(NULL);
+ req->event = event_create(NULL);
+ req->mech = mech;
+ req->state = AUTH_REQUEST_STATE_MECH_CONTINUE;
+ auth_request_state_count[AUTH_REQUEST_STATE_MECH_CONTINUE] = 1;
+ mech->auth_initial(req, UCHAR_LEN("NTLMSSP\x00\x01\x00\x00\x00\x00\x02\x00\x00""AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
+ mech->auth_continue(req, UCHAR_LEN("NTLMSSP\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00""AA\x00\x00\x41\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00""orange""\x00"));
+ test_assert(req->failed == TRUE);
+ test_assert(req->passdb_success == FALSE);
+ event_unref(&req->mech_event);
+ event_unref(&req->event);
+ mech->auth_free(req);
+ test_end();
+}
+
+int main(void)
+{
+ static void (*const test_functions[])(void) = {
+ test_rpa,
+ test_ntlm,
+ NULL
+ };
+
+ return test_run(test_functions);
+}

View File

@ -1,345 +0,0 @@
diff -up dovecot-2.3.8/src/auth/Makefile.am.CVE_2020_12674prereq dovecot-2.3.8/src/auth/Makefile.am
--- dovecot-2.3.8/src/auth/Makefile.am.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/Makefile.am 2020-08-07 20:46:56.095295825 +0200
@@ -38,6 +38,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib-oauth2 \
-I$(top_srcdir)/src/lib-ssl-iostream \
-I$(top_srcdir)/src/lib-lua \
+ -I$(top_srcdir)/src/lib-dcrypt \
-DAUTH_MODULE_DIR=\""$(auth_moduledir)"\" \
-DPKG_LIBEXECDIR=\""$(pkglibexecdir)"\" \
-DPKG_RUNDIR=\""$(rundir)"\" \
@@ -248,7 +249,8 @@ libstats_auth_la_SOURCES = auth-stats.c
test_programs = \
test-libpassword \
test-auth-cache \
- test-auth
+ test-auth \
+ test-mech
noinst_PROGRAMS = $(test_programs)
@@ -288,6 +290,13 @@ test_auth_SOURCES = \
test_auth_LDADD = $(test_libs) $(auth_libs) $(AUTH_LIBS)
test_auth_DEPENDENCIES = $(pkglibexec_PROGRAMS) $(test_libs)
+test_mech_SOURCES = \
+ test-mock.c \
+ test-mech.c
+
+test_mech_LDADD = $(test_libs) $(auth_libs) $(AUTH_LIBS)
+test_mech_DEPENDENCIES = $(pkglibexec_PROGRAMS) $(test_libs)
+
check-local:
for bin in $(test_programs); do \
if ! $(RUN_TEST) ./$$bin; then exit 1; fi; \
diff -up dovecot-2.3.8/src/auth/passdb.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/passdb.h
--- dovecot-2.3.8/src/auth/passdb.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/passdb.h 2020-08-07 20:35:16.295684287 +0200
@@ -24,6 +24,8 @@ enum passdb_result {
typedef void verify_plain_callback_t(enum passdb_result result,
struct auth_request *request);
+typedef void verify_plain_continue_callback_t(struct auth_request *request,
+ verify_plain_callback_t *callback);
typedef void lookup_credentials_callback_t(enum passdb_result result,
const unsigned char *credentials,
size_t size,
diff -up dovecot-2.3.8/src/auth/auth-request-handler-private.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request-handler-private.h
--- dovecot-2.3.8/src/auth/auth-request-handler-private.h.CVE_2020_12674prereq 2020-08-07 20:35:16.295684287 +0200
+++ dovecot-2.3.8/src/auth/auth-request-handler-private.h 2020-08-07 20:35:16.295684287 +0200
@@ -0,0 +1,27 @@
+#ifndef AUTH_REQUEST_HANDLER_PRIVATE_H
+#define AUTH_REQUEST_HANDLER_PRIVATE_H
+
+struct auth_request;
+struct auth_client_connection;
+
+struct auth_request_handler {
+ int refcount;
+ pool_t pool;
+ HASH_TABLE(void *, struct auth_request *) requests;
+
+ unsigned int connect_uid, client_pid;
+
+ auth_client_request_callback_t *callback;
+ struct auth_client_connection *conn;
+
+ auth_master_request_callback_t *master_callback;
+ auth_request_handler_reply_callback_t *reply_callback;
+ auth_request_handler_reply_continue_callback_t *reply_continue_callback;
+ verify_plain_continue_callback_t *verify_plain_continue_callback;
+
+ bool destroyed:1;
+ bool token_auth:1;
+};
+
+
+#endif
diff -up dovecot-2.3.8/src/auth/auth-request-handler.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request-handler.h
--- dovecot-2.3.8/src/auth/auth-request-handler.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/auth-request-handler.h 2020-08-07 20:35:16.295684287 +0200
@@ -17,6 +17,17 @@ auth_client_request_callback_t(const cha
typedef void
auth_master_request_callback_t(const char *reply, struct auth_master_connection *conn);
+typedef void
+auth_request_handler_reply_callback_t(struct auth_request *request,
+ enum auth_client_result result,
+ const void *auth_reply,
+ size_t reply_size);
+typedef void
+auth_request_handler_reply_continue_callback_t(struct auth_request *request,
+ const void *reply,
+ size_t reply_size);
+
+
struct auth_request_handler *
auth_request_handler_create(bool token_auth, auth_client_request_callback_t *callback,
struct auth_client_connection *conn,
diff -up dovecot-2.3.8/src/auth/test-mock.c.CVE_2020_12674prereq dovecot-2.3.8/src/auth/test-mock.c
--- dovecot-2.3.8/src/auth/test-mock.c.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/test-mock.c 2020-08-07 20:35:16.296684273 +0200
@@ -28,14 +28,22 @@ static void passdb_mock_verify_plain(str
callback(PASSDB_RESULT_OK, request);
}
+static void passdb_mock_lookup_credentials(struct auth_request *request,
+ lookup_credentials_callback_t *callback)
+{
+ passdb_handle_credentials(PASSDB_RESULT_OK, "password", "PLAIN",
+ callback, request);
+}
+
static struct passdb_module_interface mock_interface = {
.name = "mock",
.init = passdb_mock_init,
.deinit = passdb_mock_deinit,
.verify_plain = passdb_mock_verify_plain,
+ .lookup_credentials = passdb_mock_lookup_credentials,
};
-static struct auth_passdb_settings set = {
+struct auth_passdb_settings mock_passdb_set = {
.name = "mock",
.driver = "mock",
.args = "",
@@ -95,7 +103,7 @@ void passdb_mock_mod_deinit(void)
struct auth_passdb *passdb_mock(void)
{
struct auth_passdb *ret = i_new(struct auth_passdb, 1);
- ret->set = &set;
+ ret->set = &mock_passdb_set;
ret->passdb = mock_passdb_mod;
return ret;
}
diff -up dovecot-2.3.8/src/auth/test-auth.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/test-auth.h
--- dovecot-2.3.8/src/auth/test-auth.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/test-auth.h 2020-08-07 20:35:16.296684273 +0200
@@ -8,6 +8,8 @@
struct auth_passdb;
+extern struct auth_passdb_settings mock_passdb_set;
+
void test_auth_request_var_expand(void);
void test_db_dict_parse_cache_key(void);
void test_username_filter(void);
diff -up dovecot-2.3.8/src/auth/auth-request.c.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request.c
--- dovecot-2.3.8/src/auth/auth-request.c.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/auth-request.c 2020-08-07 20:35:16.295684287 +0200
@@ -16,6 +16,7 @@
#include "auth-cache.h"
#include "auth-request.h"
#include "auth-request-handler.h"
+#include "auth-request-handler-private.h"
#include "auth-request-stats.h"
#include "auth-client-connection.h"
#include "auth-master-connection.h"
@@ -67,9 +68,6 @@ static void
auth_request_userdb_import(struct auth_request *request, const char *args);
static
-void auth_request_verify_plain_continue(struct auth_request *request,
- verify_plain_callback_t *callback);
-static
void auth_request_lookup_credentials_policy_continue(struct auth_request *request,
lookup_credentials_callback_t *callback);
static
@@ -307,10 +307,12 @@ void auth_request_success_continue(struct auth_policy_check_ctx *ctx)
return;
}
- stats = auth_request_stats_get(request);
- stats->auth_success_count++;
- if (request->master_user != NULL)
- stats->auth_master_success_count++;
+ if (request->set->stats) {
+ stats = auth_request_stats_get(request);
+ stats->auth_success_count++;
+ if (request->master_user != NULL)
+ stats->auth_master_success_count++;
+ }
auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED);
auth_request_refresh_last_access(request);
@@ -324,8 +326,10 @@ void auth_request_fail(struct auth_request *request)
i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE);
- stats = auth_request_stats_get(request);
- stats->auth_failure_count++;
+ if (request->set->stats) {
+ stats = auth_request_stats_get(request);
+ stats->auth_failure_count++;
+ }
auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED);
auth_request_refresh_last_access(request);
@@ -1233,7 +1231,7 @@ void auth_request_policy_penalty_finish(
switch(ctx->type) {
case AUTH_POLICY_CHECK_TYPE_PLAIN:
- auth_request_verify_plain_continue(ctx->request, ctx->callback_plain);
+ ctx->request->handler->verify_plain_continue_callback(ctx->request, ctx->callback_plain);
return;
case AUTH_POLICY_CHECK_TYPE_LOOKUP:
auth_request_lookup_credentials_policy_continue(ctx->request, ctx->callback_lookup);
@@ -1284,7 +1282,8 @@ void auth_request_verify_plain(struct au
request->user_changed_by_lookup = FALSE;
if (request->policy_processed || !request->set->policy_check_before_auth) {
- auth_request_verify_plain_continue(request, callback);
+ request->handler->verify_plain_continue_callback(request,
+ callback);
} else {
ctx = p_new(request->pool, struct auth_policy_check_ctx, 1);
ctx->request = request;
@@ -1294,10 +1293,9 @@ void auth_request_verify_plain(struct au
}
}
-static
-void auth_request_verify_plain_continue(struct auth_request *request,
- verify_plain_callback_t *callback) {
-
+void auth_request_default_verify_plain_continue(struct auth_request *request,
+ verify_plain_callback_t *callback)
+{
struct auth_passdb *passdb;
enum passdb_result result;
const char *cache_key, *error;
diff -up dovecot-2.3.8/src/auth/auth-request-handler.c.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request-handler.c
--- dovecot-2.3.8/src/auth/auth-request-handler.c.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/auth-request-handler.c 2020-08-07 20:35:16.295684287 +0200
@@ -17,32 +17,28 @@
#include "auth-client-connection.h"
#include "auth-master-connection.h"
#include "auth-request-handler.h"
+#include "auth-request-handler-private.h"
#include "auth-policy.h"
#define AUTH_FAILURE_DELAY_CHECK_MSECS 500
-
-struct auth_request_handler {
- int refcount;
- pool_t pool;
- HASH_TABLE(void *, struct auth_request *) requests;
-
- unsigned int connect_uid, client_pid;
-
- auth_client_request_callback_t *callback;
- struct auth_client_connection *conn;
-
- auth_master_request_callback_t *master_callback;
-
- bool destroyed:1;
- bool token_auth:1;
-};
-
static ARRAY(struct auth_request *) auth_failures_arr;
static struct aqueue *auth_failures;
static struct timeout *to_auth_failures;
static void auth_failure_timeout(void *context) ATTR_NULL(1);
+
+static void
+auth_request_handler_default_reply_callback(struct auth_request *request,
+ enum auth_client_result result,
+ const void *auth_reply,
+ size_t reply_size);
+
+static void
+auth_request_handler_default_reply_continue(struct auth_request *request,
+ const void *reply,
+ size_t reply_size);
+
struct auth_request_handler *
auth_request_handler_create(bool token_auth, auth_client_request_callback_t *callback,
struct auth_client_connection *conn,
@@ -61,6 +57,12 @@ auth_request_handler_create(bool token_a
handler->conn = conn;
handler->master_callback = master_callback;
handler->token_auth = token_auth;
+ handler->reply_callback =
+ auth_request_handler_default_reply_callback;
+ handler->reply_continue_callback =
+ auth_request_handler_default_reply_continue;
+ handler->verify_plain_continue_callback =
+ auth_request_default_verify_plain_continue;
return handler;
}
@@ -355,6 +363,16 @@ void auth_request_handler_reply(struct a
enum auth_client_result result,
const void *auth_reply, size_t reply_size)
{
+ struct auth_request_handler *handler = request->handler;
+ handler->reply_callback(request, result, auth_reply, reply_size);
+}
+
+static void
+auth_request_handler_default_reply_callback(struct auth_request *request,
+ enum auth_client_result result,
+ const void *auth_reply,
+ size_t reply_size)
+{
struct auth_request_handler *handler = request->handler;
string_t *str;
int ret;
@@ -407,6 +425,14 @@ void auth_request_handler_reply(struct a
void auth_request_handler_reply_continue(struct auth_request *request,
const void *reply, size_t reply_size)
{
+ request->handler->reply_continue_callback(request, reply, reply_size);
+}
+
+static void
+auth_request_handler_default_reply_continue(struct auth_request *request,
+ const void *reply,
+ size_t reply_size)
+{
auth_request_handler_reply(request, AUTH_CLIENT_RESULT_CONTINUE,
reply, reply_size);
}
@@ -703,6 +729,7 @@ static void auth_str_append_userdb_extra
auth_str_add_keyvalue(dest, "master_user",
request->master_user);
}
+ auth_str_add_keyvalue(dest, "auth_mech", request->mech->mech_name);
if (*request->set->anonymous_username != '\0' &&
strcmp(request->user, request->set->anonymous_username) == 0) {
/* this is an anonymous login, either via ANONYMOUS
diff -up dovecot-2.3.8/src/auth/auth-request.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request.h
--- dovecot-2.3.8/src/auth/auth-request.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/auth-request.h 2020-08-07 20:35:16.295684287 +0200
@@ -295,6 +295,8 @@ void auth_request_set_credentials(struct
set_credentials_callback_t *callback);
void auth_request_userdb_callback(enum userdb_result result,
struct auth_request *request);
+void auth_request_default_verify_plain_continue(struct auth_request *request,
+ verify_plain_callback_t *callback);
void auth_request_refresh_last_access(struct auth_request *request);
void auth_str_append(string_t *dest, const char *key, const char *value);

View File

@ -1,73 +0,0 @@
diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c
index 011dea9050..8baf622e59 100644
--- a/src/lib-mail/message-parser.c
+++ b/src/lib-mail/message-parser.c
@@ -138,6 +138,7 @@ message_part_append(struct message_parser_ctx *ctx)
struct message_part *parent = ctx->part;
struct message_part *part;
+ i_assert(!ctx->preparsed);
i_assert(parent != NULL);
i_assert((parent->flags & (MESSAGE_PART_FLAG_MULTIPART |
MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0);
@@ -171,12 +172,14 @@ static void message_part_finish(struct message_parser_ctx *ctx)
{
struct message_part **const *parent_next_partp;
- i_assert(ctx->nested_parts_count > 0);
- ctx->nested_parts_count--;
+ if (!ctx->preparsed) {
+ i_assert(ctx->nested_parts_count > 0);
+ ctx->nested_parts_count--;
- parent_next_partp = array_back(&ctx->next_part_stack);
- array_pop_back(&ctx->next_part_stack);
- ctx->next_part = *parent_next_partp;
+ parent_next_partp = array_back(&ctx->next_part_stack);
+ array_pop_back(&ctx->next_part_stack);
+ ctx->next_part = *parent_next_partp;
+ }
message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size);
message_size_add(&ctx->part->parent->body_size, &ctx->part->header_size);
diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c
index 13984f939e..a00f0d6200 100644
--- a/src/lib-mail/test-message-parser.c
+++ b/src/lib-mail/test-message-parser.c
@@ -178,9 +178,10 @@ static void test_message_parser_small_blocks(void)
static void test_message_parser_stop_early(void)
{
struct message_parser_ctx *parser;
- struct istream *input;
+ struct istream *input, *input2;
struct message_part *parts;
struct message_block block;
+ const char *error;
unsigned int i;
pool_t pool;
int ret;
@@ -198,6 +199,24 @@ static void test_message_parser_stop_early(void)
&block)) > 0) ;
test_assert(ret == 0);
message_parser_deinit(&parser, &parts);
+
+ /* test preparsed - first re-parse everything with a stream
+ that sees EOF at this position */
+ input2 = i_stream_create_from_data(test_msg, i);
+ parser = message_parser_init(pool, input2, &set_empty);
+ while ((ret = message_parser_parse_next_block(parser,
+ &block)) > 0) ;
+ test_assert(ret == -1);
+ message_parser_deinit(&parser, &parts);
+
+ /* now parse from the parts */
+ i_stream_seek(input2, 0);
+ parser = message_parser_init_from_parts(parts, input2, &set_empty);
+ while ((ret = message_parser_parse_next_block(parser,
+ &block)) > 0) ;
+ test_assert(ret == -1);
+ test_assert(message_parser_deinit_from_parts(&parser, &parts, &error) == 0);
+ i_stream_unref(&input2);
}
i_stream_unref(&input);

View File

@ -1,20 +0,0 @@
diff -up dovecot-2.3.8/src/lib-storage/index/index-mail-binary.c.blockcount dovecot-2.3.8/src/lib-storage/index/index-mail-binary.c
--- dovecot-2.3.8/src/lib-storage/index/index-mail-binary.c.blockcount 2020-12-02 11:34:10.229027593 +0100
+++ dovecot-2.3.8/src/lib-storage/index/index-mail-binary.c 2020-12-02 11:36:47.328933276 +0100
@@ -339,13 +339,14 @@ blocks_count_lines(struct binary_ctx *ct
i_stream_skip(full_input, skip);
cur_block_offset += skip;
- if (cur_block->input->eof) {
+ if (i_stream_read_eof(cur_block->input)) {
/* go to the next block */
- if (++block_idx == block_count) {
+ if (block_idx+1 == block_count) {
i_assert(i_stream_read_eof(full_input));
ret = -1;
break;
}
+ block_idx++;
cur_block++;
cur_block_offset = 0;
}

View File

@ -3,9 +3,9 @@
Summary: Secure imap and pop3 server
Name: dovecot
Epoch: 1
Version: 2.3.8
Version: 2.3.16
%global prever %{nil}
Release: 9%{?dist}
Release: 1%{?dist}
#dovecot itself is MIT, a few sources are PD, pigeonhole is LGPLv2
License: MIT and LGPLv2
Group: System Environment/Daemons
@ -14,7 +14,7 @@ URL: http://www.dovecot.org/
Source: http://www.dovecot.org/releases/2.3/%{name}-%{version}%{?prever}.tar.gz
Source1: dovecot.init
Source2: dovecot.pam
%global pigeonholever 0.5.8
%global pigeonholever 0.5.16
Source8: http://pigeonhole.dovecot.org/releases/2.3/dovecot-2.3-pigeonhole-%{pigeonholever}.tar.gz
Source9: dovecot.sysconfig
Source10: dovecot.tmpfilesd
@ -43,39 +43,8 @@ Patch13: dovecot-2.2.36-bigkey.patch
# hard to break circular dependency between lib and lib-dcrypt
Patch14: dovecot-2.3.6-opensslhmac.patch
# from upstream, for dovecot < 2.3.10.1
Patch15: dovecot-2.3.10-smtppre.patch
Patch16: dovecot-2.3.10-CVE_2020_10957,10958,10967.patch
# from upstream, for dovecot <= 2.3.10.1
Patch17: dovecot-2.3.8-CVE_2020_12100prereq.patch
Patch18: dovecot-2.3.8-CVE_2020_12100.patch
Patch19: dovecot-2.3.8-CVE_2020_12100ph.patch
Patch20: dovecot-2.3.8-CVE_2020_12673.patch
Patch21: dovecot-2.3.8-CVE_2020_12674prereq.patch
Patch22: dovecot-2.3.8-CVE_2020_12674.patch
# from upstream, for dovecot <= 2.3.11.3, rhbz#1894418
Patch23: dovecot-2.3.8-blockcount.patch
# from upstream, for dovecot < 2.3.11.3, rhbz#1888111
Patch24: dovecot-2.3.8-a668d767.patch
Patch25: dovecot-2.3.13-CVE_2020_25275-part1.patch
Patch26: dovecot-2.3.13-CVE_2020_25275-part2.patch
Patch27: dovecot-2.3.13-CVE_2020_25275-part3.patch
Patch28: dovecot-2.3.13-CVE_2020_25275-part4.patch
Patch29: dovecot-2.3.13-CVE_2020_25275-part5.patch
Patch30: dovecot-2.3.13-CVE_2020_25275-part6.patch
Patch31: dovecot-2.3.13-CVE_2020_25275-part7.patch
Patch32: dovecot-2.3.13-CVE_2020_25275-part8.patch
Patch33: dovecot-2.3.13-CVE_2020_25275regr-part1.patch
Patch34: dovecot-2.3.13-CVE_2020_25275regr-part2.patch
Patch35: dovecot-2.3.13-CVE_2020_25275regr-part3.patch
Patch36: dovecot-2.3.13-CVE_2020_24386-prereq1.patch
Patch37: dovecot-2.3.13-CVE_2020_24386-part1.patch
Patch38: dovecot-2.3.13-CVE_2020_24386-part2.patch
Patch39: dovecot-2.3.13-CVE_2020_24386-part3.patch
Patch40: dovecot-2.3.13-CVE_2020_24386-part4.patch
# from upstream, for dovecot < 2.3.17, s390x FTBFS fix
Patch15: dovecot-2.3.16-ftbfsbigend.patch
Source15: prestartscript
@ -181,32 +150,7 @@ This package provides the development files for dovecot.
%patch11 -p1 -b .aclfix
%patch13 -p1 -b .bigkey
%patch14 -p1 -b .opensslhmac
%patch15 -p1 -b .smtppre
%patch16 -p1 -b .CVE_2020_10957,10958,10967
%patch17 -p1 -b .CVE_2020_12100prereq
%patch18 -p1 -b .CVE_2020_12100
%patch19 -p1 -b .CVE_2020_12100ph
%patch20 -p1 -b .CVE_2020_12673
%patch21 -p1 -b .CVE_2020_12674prereq
%patch22 -p1 -b .CVE_2020_12674
%patch23 -p1 -b .blockcount
%patch24 -p1 -b .a668d767
%patch25 -p1 -b .CVE_2020_25275-part1
%patch26 -p1 -b .CVE_2020_25275-part2
%patch27 -p1 -b .CVE_2020_25275-part3
%patch28 -p1 -b .CVE_2020_25275-part4
%patch29 -p1 -b .CVE_2020_25275-part5
%patch30 -p1 -b .CVE_2020_25275-part6
%patch31 -p1 -b .CVE_2020_25275-part7
%patch32 -p1 -b .CVE_2020_25275-part8
%patch33 -p1 -b .CVE_2020_25275regr-part1
%patch34 -p1 -b .CVE_2020_25275regr-part2
%patch35 -p1 -b .CVE_2020_25275regr-part3
%patch36 -p1 -b .CVE_2020_24386-prereq1
%patch37 -p1 -b .CVE_2020_24386-part1
%patch38 -p1 -b .CVE_2020_24386-part2
%patch39 -p1 -b .CVE_2020_24386-part3
%patch40 -p1 -b .CVE_2020_24386-part4
%patch15 -p1 -b .ftbfsbigend
pushd dovecot-2*3-pigeonhole-%{pigeonholever}
popd
@ -226,6 +170,7 @@ autoreconf -I . -fiv #required for aarch64 support
%configure \
INSTALL_DATA="install -c -p -m644" \
--with-rundir=%{_rundir}/%{name} \
--with-systemd \
--docdir=%{_docdir}/%{name} \
--disable-static \
--disable-rpath \
@ -427,6 +372,7 @@ make check
%{_bindir}/doveadm
%{_bindir}/doveconf
%{_bindir}/dsync
%{_bindir}/dovecot-sysreport
%if %{?fedora}0 > 140 || %{?rhel}0 > 60
@ -448,6 +394,7 @@ make check
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/10-logging.conf
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/10-mail.conf
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/10-master.conf
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/10-metrics.conf
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/10-ssl.conf
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/15-lda.conf
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/15-mailboxes.conf
@ -467,8 +414,6 @@ make check
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/auth-sql.conf.ext
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/auth-static.conf.ext
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/auth-system.conf.ext
%config(noreplace) %{_sysconfdir}/dovecot/conf.d/auth-vpopmail.conf.ext
%config(noreplace) %{_sysconfdir}/pam.d/dovecot
%config(noreplace) %{ssldir}/dovecot-openssl.cnf
@ -509,10 +454,11 @@ make check
%{_libexecdir}/%{name}
%exclude %{_libexecdir}/%{name}/managesieve*
%attr(0755,root,dovecot) %ghost /var/run/dovecot
%dir %attr(0755,root,dovecot) %ghost /var/run/dovecot
%attr(0750,root,dovenull) %ghost /var/run/dovecot/login
%attr(0750,root,dovenull) %ghost /var/run/dovecot/token-login
%attr(0755,root,root) %ghost /var/run/dovecot/empty
%attr(0750,dovecot,dovecot) /var/lib/dovecot
%{_datadir}/%{name}
@ -569,6 +515,10 @@ make check
%{_libdir}/%{name}/dict/libdriver_pgsql.so
%changelog
* Wed Dec 08 2021 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.16-1
- dovecot updated to 2.3.16, pigeonhole to 0.5.16
- fix CVE-2021-33515 plaintext commands injection (#1980014)
* Wed Feb 03 2021 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.8-9
- fix CVE-2020-24386 IMAP hibernation function allows mail access (#1913534)