Compare commits

...

3 Commits

Author SHA1 Message Date
eabdullin 250994a74c Import from AlmaLinux stable repository 2024-05-31 17:33:47 +00:00
CentOS Sources df423e2991 import dovecot-2.3.16-3.el8 2022-11-08 12:16:31 +00:00
CentOS Sources 4eb6e2fb3c import dovecot-2.3.16-2.el8 2022-05-10 07:21:12 +00:00
39 changed files with 1421 additions and 6326 deletions

View File

@ -1,2 +0,0 @@
b9c7290dad1ac3bc1ead11359812a137a3d173f7 SOURCES/dovecot-2.3-pigeonhole-0.5.8.tar.gz
65b93f7fd53705b3c97f9eee141a76c5f4f3a624 SOURCES/dovecot-2.3.8.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,17 @@
diff --git a/src/lib-index/mail-index-sync.c b/src/lib-index/mail-index-sync.c
index 6322ee1869..c847f1cc01 100644
--- a/src/lib-index/mail-index-sync.c
+++ b/src/lib-index/mail-index-sync.c
@@ -544,6 +544,12 @@ static bool mail_index_sync_view_have_any(struct mail_index_view *view,
return TRUE;
mail_transaction_log_get_head(view->index->log, &log_seq, &log_offset);
+ if (log_seq < view->map->hdr.log_file_seq ||
+ ((log_seq == view->map->hdr.log_file_seq &&
+ log_offset < view->map->hdr.log_file_tail_offset))) {
+ /* invalid offsets - let the syncing handle the error */
+ return TRUE;
+ }
if (mail_transaction_log_view_set(view->log_view,
view->map->hdr.log_file_seq,
view->map->hdr.log_file_tail_offset,

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

@ -0,0 +1,353 @@
diff -up dovecot-2.3.16/configure.ac.keeplzma dovecot-2.3.16/configure.ac
--- dovecot-2.3.16/configure.ac.keeplzma 2021-08-06 11:25:51.000000000 +0200
+++ dovecot-2.3.16/configure.ac 2022-02-28 13:58:02.337149927 +0100
@@ -173,7 +173,7 @@ AS_HELP_STRING([--with-bzlib], [Build wi
want_bzlib=auto)
AC_ARG_WITH(lzma,
-AS_HELP_STRING([--with-lzma], [Build with LZMA decompression support (auto)]),
+AS_HELP_STRING([--with-lzma], [Build with LZMA compression support (auto)]),
TEST_WITH(lzma, $withval),
want_lzma=auto)
diff -up dovecot-2.3.16/run-test-valgrind.supp.keeplzma dovecot-2.3.16/run-test-valgrind.supp
--- dovecot-2.3.16/run-test-valgrind.supp.keeplzma 2021-08-06 11:25:51.000000000 +0200
+++ dovecot-2.3.16/run-test-valgrind.supp 2022-02-28 13:58:02.337149927 +0100
@@ -5,6 +5,17 @@
obj:*/bash
}
{
+ <liblzma>
+ Memcheck:Cond
+ obj:/lib/x86_64-linux-gnu/liblzma.so.5.*
+ obj:/lib/x86_64-linux-gnu/liblzma.so.5.*
+ obj:/lib/x86_64-linux-gnu/liblzma.so.5.*
+ obj:/lib/x86_64-linux-gnu/liblzma.so.5.*
+ obj:/lib/x86_64-linux-gnu/liblzma.so.5.*
+ fun:lzma_stream_encoder
+ fun:lzma_easy_encoder
+}
+{
<openssl_centos6_i386_v1_0_1_compression_methods>
Memcheck:Leak
fun:malloc
diff -up dovecot-2.3.16/src/lib-compression/compression.c.keeplzma dovecot-2.3.16/src/lib-compression/compression.c
--- dovecot-2.3.16/src/lib-compression/compression.c.keeplzma 2021-08-06 11:25:51.000000000 +0200
+++ dovecot-2.3.16/src/lib-compression/compression.c 2022-02-28 14:22:32.467944396 +0100
@@ -25,6 +25,7 @@
#endif
#ifndef HAVE_LZMA
# define i_stream_create_lzma NULL
+# define o_stream_create_lzma NULL
#endif
#ifndef HAVE_LZ4
# define i_stream_create_lz4 NULL
@@ -216,7 +217,7 @@ const struct compression_handler compres
.ext = ".xz",
.is_compressed = is_compressed_xz,
.create_istream = i_stream_create_lzma,
- .create_ostream = NULL,
+ .create_ostream = o_stream_create_lzma,
.get_min_level = compression_get_min_level_unsupported,
.get_default_level = compression_get_default_level_unsupported,
.get_max_level = compression_get_max_level_unsupported,
diff -up dovecot-2.3.16/src/lib-compression/Makefile.am.keeplzma dovecot-2.3.16/src/lib-compression/Makefile.am
--- dovecot-2.3.16/src/lib-compression/Makefile.am.keeplzma 2021-08-06 11:25:51.000000000 +0200
+++ dovecot-2.3.16/src/lib-compression/Makefile.am 2022-02-28 13:58:02.337149927 +0100
@@ -13,6 +13,7 @@ libcompression_la_SOURCES = \
istream-zlib.c \
istream-bzlib.c \
istream-zstd.c \
+ ostream-lzma.c \
ostream-lz4.c \
ostream-zlib.c \
ostream-bzlib.c \
diff -up dovecot-2.3.16/src/lib-compression/ostream-lzma.c.keeplzma dovecot-2.3.16/src/lib-compression/ostream-lzma.c
--- dovecot-2.3.16/src/lib-compression/ostream-lzma.c.keeplzma 2022-02-28 13:58:02.338149934 +0100
+++ dovecot-2.3.16/src/lib-compression/ostream-lzma.c 2022-02-28 13:58:02.338149934 +0100
@@ -0,0 +1,263 @@
+/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+
+#ifdef HAVE_LZMA
+
+#include "ostream-private.h"
+#include "ostream-zlib.h"
+#include <lzma.h>
+
+#define CHUNK_SIZE (1024*64)
+
+struct lzma_ostream {
+ struct ostream_private ostream;
+ lzma_stream strm;
+
+ unsigned char outbuf[CHUNK_SIZE];
+ unsigned int outbuf_offset, outbuf_used;
+
+ bool flushed:1;
+};
+
+static void o_stream_lzma_close(struct iostream_private *stream,
+ bool close_parent)
+{
+ struct lzma_ostream *zstream = (struct lzma_ostream *)stream;
+ i_assert(zstream->ostream.finished ||
+ zstream->ostream.ostream.stream_errno != 0 ||
+ zstream->ostream.error_handling_disabled);
+ lzma_end(&zstream->strm);
+ if (close_parent)
+ o_stream_close(zstream->ostream.parent);
+}
+
+static int o_stream_zlib_send_outbuf(struct lzma_ostream *zstream)
+{
+ ssize_t ret;
+ size_t size;
+
+ if (zstream->outbuf_used == 0)
+ return 1;
+
+ size = zstream->outbuf_used - zstream->outbuf_offset;
+ i_assert(size > 0);
+ ret = o_stream_send(zstream->ostream.parent,
+ zstream->outbuf + zstream->outbuf_offset, size);
+ if (ret < 0) {
+ o_stream_copy_error_from_parent(&zstream->ostream);
+ return -1;
+ }
+ if ((size_t)ret != size) {
+ zstream->outbuf_offset += ret;
+ return 0;
+ }
+ zstream->outbuf_offset = 0;
+ zstream->outbuf_used = 0;
+ return 1;
+}
+
+static ssize_t
+o_stream_lzma_send_chunk(struct lzma_ostream *zstream,
+ const void *data, size_t size)
+{
+ lzma_stream *zs = &zstream->strm;
+ int ret;
+
+ i_assert(zstream->outbuf_used == 0);
+
+ zs->next_in = (void *)data;
+ zs->avail_in = size;
+ while (zs->avail_in > 0) {
+ if (zs->avail_out == 0) {
+ /* previous block was compressed. send it and start
+ compression for a new block. */
+ zs->next_out = zstream->outbuf;
+ zs->avail_out = sizeof(zstream->outbuf);
+
+ zstream->outbuf_used = sizeof(zstream->outbuf);
+ if ((ret = o_stream_zlib_send_outbuf(zstream)) < 0)
+ return -1;
+ if (ret == 0) {
+ /* parent stream's buffer full */
+ break;
+ }
+ }
+
+ ret = lzma_code(zs, LZMA_RUN);
+ switch (ret) {
+ case LZMA_OK:
+ break;
+ case LZMA_MEM_ERROR:
+ i_fatal_status(FATAL_OUTOFMEM,
+ "lzma.write(%s): Out of memory",
+ o_stream_get_name(&zstream->ostream.ostream));
+ default:
+ i_panic("lzma.write(%s) failed with unexpected code %d",
+ o_stream_get_name(&zstream->ostream.ostream), ret);
+ }
+ }
+ size -= zs->avail_in;
+
+ return size;
+}
+
+static int o_stream_lzma_send_flush(struct lzma_ostream *zstream, bool final)
+{
+ lzma_stream *zs = &zstream->strm;
+ size_t len;
+ bool done = FALSE;
+ int ret;
+
+ i_assert(zs->avail_in == 0);
+
+ if (zstream->flushed) {
+ i_assert(zstream->outbuf_used == 0);
+ return 1;
+ }
+
+ if ((ret = o_stream_flush_parent_if_needed(&zstream->ostream)) <= 0)
+ return ret;
+ if ((ret = o_stream_zlib_send_outbuf(zstream)) <= 0)
+ return ret;
+
+ if (!final)
+ return 1;
+
+ i_assert(zstream->outbuf_used == 0);
+ do {
+ len = sizeof(zstream->outbuf) - zs->avail_out;
+ if (len != 0) {
+ zs->next_out = zstream->outbuf;
+ zs->avail_out = sizeof(zstream->outbuf);
+
+ zstream->outbuf_used = len;
+ if ((ret = o_stream_zlib_send_outbuf(zstream)) <= 0)
+ return ret;
+ if (done)
+ break;
+ }
+ ret = lzma_code(zs, LZMA_FINISH);
+ switch (ret) {
+ case LZMA_OK:
+ /* still unfinished - need to call lzma_code() again */
+ break;
+ case LZMA_STREAM_END:
+ /* output is fully finished */
+ done = TRUE;
+ break;
+ case LZMA_MEM_ERROR:
+ i_fatal_status(FATAL_OUTOFMEM,
+ "lzma.write(%s): Out of memory",
+ o_stream_get_name(&zstream->ostream.ostream));
+ default:
+ i_panic("lzma.write(%s) flush failed with unexpected code %d",
+ o_stream_get_name(&zstream->ostream.ostream), ret);
+ }
+ } while (zs->avail_out != sizeof(zstream->outbuf));
+
+ if (final)
+ zstream->flushed = TRUE;
+ i_assert(zstream->outbuf_used == 0);
+ return 1;
+}
+
+static int o_stream_lzma_flush(struct ostream_private *stream)
+{
+ struct lzma_ostream *zstream = (struct lzma_ostream *)stream;
+ int ret;
+
+ if ((ret = o_stream_lzma_send_flush(zstream, stream->finished)) < 0)
+ return -1;
+ else if (ret > 0)
+ return o_stream_flush_parent(stream);
+ return ret;
+}
+
+static size_t
+o_stream_lzma_get_buffer_used_size(const struct ostream_private *stream)
+{
+ const struct lzma_ostream *zstream =
+ (const struct lzma_ostream *)stream;
+
+ /* outbuf has already compressed data that we're trying to send to the
+ parent stream. We're not including lzma's internal compression
+ buffer size. */
+ return (zstream->outbuf_used - zstream->outbuf_offset) +
+ o_stream_get_buffer_used_size(stream->parent);
+}
+
+static size_t
+o_stream_lzma_get_buffer_avail_size(const struct ostream_private *stream)
+{
+ /* FIXME: not correct - this is counting compressed size, which may be
+ too larger than uncompressed size in some situations. Fixing would
+ require some kind of additional buffering. */
+ return o_stream_get_buffer_avail_size(stream->parent);
+}
+
+static ssize_t
+o_stream_lzma_sendv(struct ostream_private *stream,
+ const struct const_iovec *iov, unsigned int iov_count)
+{
+ struct lzma_ostream *zstream = (struct lzma_ostream *)stream;
+ ssize_t ret, bytes = 0;
+ unsigned int i;
+
+ if ((ret = o_stream_zlib_send_outbuf(zstream)) <= 0) {
+ /* error / we still couldn't flush existing data to
+ parent stream. */
+ return ret;
+ }
+
+ for (i = 0; i < iov_count; i++) {
+ ret = o_stream_lzma_send_chunk(zstream, iov[i].iov_base,
+ iov[i].iov_len);
+ if (ret < 0)
+ return -1;
+ bytes += ret;
+ if ((size_t)ret != iov[i].iov_len)
+ break;
+ }
+ stream->ostream.offset += bytes;
+
+ /* avail_in!=0 check is used to detect errors. if it's non-zero here
+ it simply means we didn't send all the data */
+ zstream->strm.avail_in = 0;
+ return bytes;
+}
+
+struct ostream *o_stream_create_lzma(struct ostream *output, int level)
+{
+ struct lzma_ostream *zstream;
+ lzma_ret ret;
+
+ i_assert(level >= 1 && level <= 9);
+
+ zstream = i_new(struct lzma_ostream, 1);
+ zstream->ostream.sendv = o_stream_lzma_sendv;
+ zstream->ostream.flush = o_stream_lzma_flush;
+ zstream->ostream.get_buffer_used_size =
+ o_stream_lzma_get_buffer_used_size;
+ zstream->ostream.get_buffer_avail_size =
+ o_stream_lzma_get_buffer_avail_size;
+ zstream->ostream.iostream.close = o_stream_lzma_close;
+
+ ret = lzma_easy_encoder(&zstream->strm, level, LZMA_CHECK_CRC64);
+ switch (ret) {
+ case LZMA_OK:
+ break;
+ case LZMA_MEM_ERROR:
+ i_fatal_status(FATAL_OUTOFMEM, "lzma: Out of memory");
+ case LZMA_OPTIONS_ERROR:
+ i_fatal("lzma: Invalid level");
+ default:
+ i_fatal("lzma_easy_encoder() failed with %d", ret);
+ }
+
+ zstream->strm.next_out = zstream->outbuf;
+ zstream->strm.avail_out = sizeof(zstream->outbuf);
+ return o_stream_create(&zstream->ostream, output,
+ o_stream_get_fd(output));
+}
+#endif
diff -up dovecot-2.3.16/src/lib-compression/ostream-zlib.h.keeplzma dovecot-2.3.16/src/lib-compression/ostream-zlib.h
--- dovecot-2.3.16/src/lib-compression/ostream-zlib.h.keeplzma 2021-08-06 11:25:51.000000000 +0200
+++ dovecot-2.3.16/src/lib-compression/ostream-zlib.h 2022-02-28 13:58:02.338149934 +0100
@@ -4,6 +4,7 @@
struct ostream *o_stream_create_gz(struct ostream *output, int level);
struct ostream *o_stream_create_deflate(struct ostream *output, int level);
struct ostream *o_stream_create_bz2(struct ostream *output, int level);
+struct ostream *o_stream_create_lzma(struct ostream *output, int level);
struct ostream *o_stream_create_lz4(struct ostream *output, int level);
struct ostream *o_stream_create_zstd(struct ostream *output, int level);
diff -up dovecot-2.3.16/src/lib-compression/test-compression.c.keeplzma dovecot-2.3.16/src/lib-compression/test-compression.c
--- dovecot-2.3.16/src/lib-compression/test-compression.c.keeplzma 2021-08-06 11:25:51.000000000 +0200
+++ dovecot-2.3.16/src/lib-compression/test-compression.c 2022-02-28 13:58:02.338149934 +0100
@@ -730,7 +730,6 @@ static void test_compression_int(bool au
for (i = 0; compression_handlers[i].name != NULL; i++) {
if (compression_handlers[i].create_istream != NULL &&
- compression_handlers[i].create_ostream != NULL &&
(!autodetect ||
compression_handlers[i].is_compressed != NULL)) T_BEGIN {
if (compression_handlers[i].is_compressed != NULL &&

View File

@ -0,0 +1,578 @@
From 9f3002393fe1c1fe317121d03591569dac120739 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Tue, 17 Aug 2021 19:09:13 +0200
Subject: [PATCH 01/12] lib-sieve: sieve-interpreter - Fix field mixup in debug
message.
---
src/lib-sieve/sieve-interpreter.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 9ee6c659..274e142d 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -1003,8 +1003,8 @@ int sieve_interpreter_continue(struct sieve_interpreter *interp,
}
e_debug(e->event(), "Finished running script `%s' "
"(status=%s, resource usage: %s)",
- sieve_execution_exitcode_to_str(ret),
sieve_binary_source(interp->runenv.sbin),
+ sieve_execution_exitcode_to_str(ret),
sieve_resource_usage_get_summary(&interp->rusage));
interp->running = FALSE;
}
From 54e020c1212f626049bffc6c6fea8e606a893af2 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 18 Aug 2021 01:44:23 +0200
Subject: [PATCH 02/12] lib-sieve: sieve-result - Remove success parameter from
sieve_result_implicit_keep_execute().
---
src/lib-sieve/sieve-result.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 55eb9f54..d3f2f925 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -1475,8 +1475,7 @@ void sieve_result_execution_destroy(struct sieve_result_execution **_rexec)
}
static void
-sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec,
- bool success)
+sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec)
{
const struct sieve_action_exec_env *aenv = &rexec->action_env;
struct sieve_result *result = aenv->result;
@@ -1486,6 +1485,7 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec,
struct sieve_action_execution *aexec_keep = &rexec->keep;
struct sieve_result_action *ract_keep = &rexec->keep_action;
struct sieve_action *act_keep = &ract_keep->action;
+ bool success = (rexec->status == SIEVE_EXEC_OK);
if (rexec->keep_equiv_action != NULL) {
e_debug(rexec->event, "No implicit keep needed "
@@ -1579,8 +1579,8 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec,
}
}
- e_debug(rexec->event, "Execute implicit keep (failure=%s)",
- (!success ? "yes" : "no"));
+ e_debug(rexec->event, "Execute implicit keep (status=%s)",
+ sieve_execution_exitcode_to_str(rexec->status));
/* Initialize side effects */
sieve_action_execution_add_side_effects(rexec, aexec_keep, ract_keep);
@@ -1633,7 +1633,7 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec,
/* Start keep if necessary */
if (act_keep->def == NULL ||
aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
- sieve_result_implicit_keep_execute(rexec, success);
+ sieve_result_implicit_keep_execute(rexec);
/* Switch to failure keep if necessary. */
} else if (rexec->keep_success && !success){
e_debug(rexec->event, "Switch to failure implicit keep");
@@ -1645,7 +1645,7 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec,
i_zero(aexec_keep);
/* Start failure keep action. */
- sieve_result_implicit_keep_execute(rexec, success);
+ sieve_result_implicit_keep_execute(rexec);
}
if (act_keep->def == NULL)
return rexec->keep_status;
@@ -1931,10 +1931,8 @@ int sieve_result_execute(struct sieve_result_execution *rexec, int status,
/* Execute implicit keep if the transaction failed or when the
implicit keep was not canceled during transaction.
*/
- if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit) {
- sieve_result_implicit_keep_execute(
- rexec, (rexec->status == SIEVE_EXEC_OK));
- }
+ if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit)
+ sieve_result_implicit_keep_execute(rexec);
}
/* Transaction commit/rollback */
From 291f2fdb77b86db566dca7c028dd93fc741f6b31 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 18 Aug 2021 01:40:57 +0200
Subject: [PATCH 03/12] lib-sieve: sieve-result - Remove success parameter from
sieve_result_implicit_keep_finalize().
---
src/lib-sieve/sieve-result.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index d3f2f925..3cf2c02a 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -1603,8 +1603,7 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec)
}
static int
-sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec,
- bool success)
+sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
{
const struct sieve_action_exec_env *aenv = &rexec->action_env;
const struct sieve_execute_env *eenv = aenv->exec_env;
@@ -1612,6 +1611,7 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec,
struct sieve_result_action *ract_keep = &rexec->keep_action;
struct sieve_action *act_keep = &ract_keep->action;
int commit_status = SIEVE_EXEC_OK;
+ bool success = (rexec->status == SIEVE_EXEC_OK);
if (rexec->keep_equiv_action != NULL) {
struct sieve_action_execution *ke_aexec =
@@ -1627,8 +1627,8 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec,
return rexec->keep_status;
}
- e_debug(rexec->event, "Finalize implicit keep (failure=%s)",
- (!success ? "yes" : "no"));
+ e_debug(rexec->event, "Finalize implicit keep (status=%s)",
+ sieve_execution_exitcode_to_str(rexec->status));
/* Start keep if necessary */
if (act_keep->def == NULL ||
@@ -1950,8 +1950,7 @@ int sieve_result_execute(struct sieve_result_execution *rexec, int status,
implicit keep was not canceled during transaction.
*/
if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit) {
- ret = sieve_result_implicit_keep_finalize(
- rexec, (rexec->status == SIEVE_EXEC_OK));
+ ret = sieve_result_implicit_keep_finalize(rexec);
switch (ret) {
case SIEVE_EXEC_OK:
if (result_status == SIEVE_EXEC_TEMP_FAILURE)
From 10e347e3c9eb5e7bf5bc6f178389005357f527fe Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 18 Aug 2021 02:07:01 +0200
Subject: [PATCH 04/12] lib-sieve: sieve-result - Move temp failure status
checks into sieve_result_implicit_keep_execute().
---
src/lib-sieve/sieve-result.c | 38 ++++++++++++++++++++++++------------
1 file changed, 26 insertions(+), 12 deletions(-)
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 3cf2c02a..44afeef7 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -934,6 +934,7 @@ struct sieve_result_execution {
bool keep_success:1;
bool keep_explicit:1;
bool keep_implicit:1;
+ bool keep_finalizing:1;
bool seen_delivery:1;
bool executed:1;
bool executed_delivery:1;
@@ -1485,7 +1486,24 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec)
struct sieve_action_execution *aexec_keep = &rexec->keep;
struct sieve_result_action *ract_keep = &rexec->keep_action;
struct sieve_action *act_keep = &ract_keep->action;
- bool success = (rexec->status == SIEVE_EXEC_OK);
+ bool success = FALSE;
+
+ switch (rexec->status) {
+ case SIEVE_EXEC_OK:
+ success = TRUE;
+ break;
+ case SIEVE_EXEC_TEMP_FAILURE:
+ case SIEVE_EXEC_RESOURCE_LIMIT:
+ if (rexec->executed)
+ break;
+ if (rexec->committed)
+ break;
+ if (rexec->keep_finalizing)
+ break;
+ return;
+ default:
+ break;
+ }
if (rexec->keep_equiv_action != NULL) {
e_debug(rexec->event, "No implicit keep needed "
@@ -1630,6 +1648,8 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
e_debug(rexec->event, "Finalize implicit keep (status=%s)",
sieve_execution_exitcode_to_str(rexec->status));
+ rexec->keep_finalizing = TRUE;
+
/* Start keep if necessary */
if (act_keep->def == NULL ||
aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
@@ -1923,17 +1943,11 @@ int sieve_result_execute(struct sieve_result_execution *rexec, int status,
return rexec->status;
}
- /* Execute implicit keep if necessary */
-
- if (rexec->executed ||
- (rexec->status != SIEVE_EXEC_TEMP_FAILURE &&
- rexec->status != SIEVE_EXEC_RESOURCE_LIMIT)) {
- /* Execute implicit keep if the transaction failed or when the
- implicit keep was not canceled during transaction.
- */
- if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit)
- sieve_result_implicit_keep_execute(rexec);
- }
+ /* Execute implicit keep if the transaction failed or when the
+ implicit keep was not canceled during transaction.
+ */
+ if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit)
+ sieve_result_implicit_keep_execute(rexec);
/* Transaction commit/rollback */
From c84e6e5d8d1d8b03a0ba5958804d200c6e1916d8 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 18 Aug 2021 02:26:32 +0200
Subject: [PATCH 05/12] lib-sieve: sieve-result - Move temp failure status
checks into sieve_result_implicit_keep_finalize().
---
src/lib-sieve/sieve-result.c | 56 +++++++++++++++++++++---------------
1 file changed, 33 insertions(+), 23 deletions(-)
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 44afeef7..10cc3b95 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -1629,7 +1629,20 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
struct sieve_result_action *ract_keep = &rexec->keep_action;
struct sieve_action *act_keep = &ract_keep->action;
int commit_status = SIEVE_EXEC_OK;
- bool success = (rexec->status == SIEVE_EXEC_OK);
+ bool success = FALSE;
+
+ switch (rexec->status) {
+ case SIEVE_EXEC_OK:
+ success = TRUE;
+ break;
+ case SIEVE_EXEC_TEMP_FAILURE:
+ case SIEVE_EXEC_RESOURCE_LIMIT:
+ if (rexec->committed)
+ break;
+ return rexec->status;
+ default:
+ break;
+ }
if (rexec->keep_equiv_action != NULL) {
struct sieve_action_execution *ke_aexec =
@@ -1957,32 +1970,29 @@ int sieve_result_execute(struct sieve_result_execution *rexec, int status,
/* Commit implicit keep if necessary */
result_status = rexec->status;
- if (rexec->committed ||
- (rexec->status != SIEVE_EXEC_TEMP_FAILURE &&
- rexec->status != SIEVE_EXEC_RESOURCE_LIMIT)) {
- /* Commit implicit keep if the transaction failed or when the
- implicit keep was not canceled during transaction.
- */
- if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit) {
- ret = sieve_result_implicit_keep_finalize(rexec);
- switch (ret) {
- case SIEVE_EXEC_OK:
- if (result_status == SIEVE_EXEC_TEMP_FAILURE)
- result_status = SIEVE_EXEC_FAILURE;
+
+ /* Commit implicit keep if the transaction failed or when the
+ implicit keep was not canceled during transaction.
+ */
+ if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit) {
+ ret = sieve_result_implicit_keep_finalize(rexec);
+ switch (ret) {
+ case SIEVE_EXEC_OK:
+ if (result_status == SIEVE_EXEC_TEMP_FAILURE)
+ result_status = SIEVE_EXEC_FAILURE;
+ break;
+ case SIEVE_EXEC_TEMP_FAILURE:
+ if (!rexec->committed) {
+ result_status = ret;
break;
- case SIEVE_EXEC_TEMP_FAILURE:
- if (!rexec->committed) {
- result_status = ret;
- break;
- }
- /* fall through */
- default:
- result_status = SIEVE_EXEC_KEEP_FAILED;
}
+ /* fall through */
+ default:
+ result_status = SIEVE_EXEC_KEEP_FAILED;
}
- if (rexec->status == SIEVE_EXEC_OK)
- rexec->status = result_status;
}
+ if (rexec->status == SIEVE_EXEC_OK)
+ rexec->status = result_status;
/* Finish execution */
From 92b4b06d5d8deeefdd17d5fb18d7f0d23e8e414b Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 18 Aug 2021 02:46:18 +0200
Subject: [PATCH 06/12] lib-sieve: sieve-result - Skip implicit keep in
execution stage upon temp failure.
It will be executed in the commit phase if necessary; don't do it early; it will
only be rolled back.
---
src/lib-sieve/sieve-result.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 10cc3b95..82354831 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -1494,8 +1494,6 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec)
break;
case SIEVE_EXEC_TEMP_FAILURE:
case SIEVE_EXEC_RESOURCE_LIMIT:
- if (rexec->executed)
- break;
if (rexec->committed)
break;
if (rexec->keep_finalizing)
From f2b81cc6ebaa3001bde693f7abdb990f467f7831 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 18 Aug 2021 02:56:32 +0200
Subject: [PATCH 07/12] lib-sieve: sieve-result - Fix handling of resource
limit status after implicit keep commit.
---
src/lib-sieve/sieve-result.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 82354831..96582075 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -1980,6 +1980,7 @@ int sieve_result_execute(struct sieve_result_execution *rexec, int status,
result_status = SIEVE_EXEC_FAILURE;
break;
case SIEVE_EXEC_TEMP_FAILURE:
+ case SIEVE_EXEC_RESOURCE_LIMIT:
if (!rexec->committed) {
result_status = ret;
break;
From 293f0027106a725e4cbcf56b673f1eedda00c317 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 18 Aug 2021 02:54:25 +0200
Subject: [PATCH 08/12] lib-sieve: sieve-result - Fix resource leak occurring
when implicit keep is executed before temporary failure at commit.
In the commit phase the implicit keep was never finalized, meaning that it was
not rolled back and thus not cleaned up properly. This leads to a memory leak
and a mailbox reference leak. This in turn causes an assert crash at the end
of delivery when the mail user is destroyed.
---
src/lib-sieve/sieve-result.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 96582075..10ea349c 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -1627,7 +1627,7 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
struct sieve_result_action *ract_keep = &rexec->keep_action;
struct sieve_action *act_keep = &ract_keep->action;
int commit_status = SIEVE_EXEC_OK;
- bool success = FALSE;
+ bool success = FALSE, temp_failure = FALSE;
switch (rexec->status) {
case SIEVE_EXEC_OK:
@@ -1637,7 +1637,15 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
case SIEVE_EXEC_RESOURCE_LIMIT:
if (rexec->committed)
break;
- return rexec->status;
+
+ if (aexec_keep->state !=
+ SIEVE_ACTION_EXECUTION_STATE_EXECUTED)
+ return rexec->status;
+ /* Roll back for temporary failure when no other action
+ is committed. */
+ commit_status = rexec->status;
+ temp_failure = TRUE;
+ break;
default:
break;
}
@@ -1662,8 +1670,10 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
rexec->keep_finalizing = TRUE;
/* Start keep if necessary */
- if (act_keep->def == NULL ||
- aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
+ if (temp_failure) {
+ rexec->keep_status = rexec->status;
+ } else if (act_keep->def == NULL ||
+ aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
sieve_result_implicit_keep_execute(rexec);
/* Switch to failure keep if necessary. */
} else if (rexec->keep_success && !success){
From 81bd53d6c9fa14fc6b32304e49dddb8fd022de91 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 18 Aug 2021 13:29:41 +0200
Subject: [PATCH 09/12] lib-sieve: sieve-result - Assert that implicit keep is
executed in sieve_result_implicit_keep_finalize().
---
src/lib-sieve/sieve-result.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 10ea349c..de97d6ae 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -1691,6 +1691,8 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
if (act_keep->def == NULL)
return rexec->keep_status;
+ i_assert(aexec_keep->state == SIEVE_ACTION_EXECUTION_STATE_EXECUTED);
+
/* Finalize keep action */
rexec->keep_status = sieve_result_action_commit_or_rollback(
rexec, aexec_keep, rexec->keep_status, &commit_status);
From dbf5b62ba82766a7d824e81005b2517d96984ef0 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 18 Aug 2021 02:43:05 +0200
Subject: [PATCH 10/12] lib-sieve: sieve-result - Add debug messages for temp
failure handling.
---
src/lib-sieve/sieve-result.c | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index de97d6ae..c21c8017 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -1494,10 +1494,21 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec)
break;
case SIEVE_EXEC_TEMP_FAILURE:
case SIEVE_EXEC_RESOURCE_LIMIT:
- if (rexec->committed)
+ if (rexec->committed) {
+ e_debug(rexec->event,
+ "Temporary failure occurred (status=%s), "
+ "but other actions were already committed: "
+ "execute failure implicit keep",
+ sieve_execution_exitcode_to_str(rexec->status));
break;
+ }
if (rexec->keep_finalizing)
break;
+
+ e_debug(rexec->event,
+ "Skip implicit keep for temporary failure "
+ "(state=execute, status=%s)",
+ sieve_execution_exitcode_to_str(rexec->status));
return;
default:
break;
@@ -1635,12 +1646,23 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
break;
case SIEVE_EXEC_TEMP_FAILURE:
case SIEVE_EXEC_RESOURCE_LIMIT:
- if (rexec->committed)
+ if (rexec->committed) {
+ e_debug(rexec->event,
+ "Temporary failure occurred (status=%s), "
+ "but other actions were already committed: "
+ "commit failure implicit keep",
+ sieve_execution_exitcode_to_str(rexec->status));
break;
+ }
if (aexec_keep->state !=
- SIEVE_ACTION_EXECUTION_STATE_EXECUTED)
+ SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
+ e_debug(rexec->event,
+ "Skip implicit keep for temporary failure "
+ "(state=commit, status=%s)",
+ sieve_execution_exitcode_to_str(rexec->status));
return rexec->status;
+ }
/* Roll back for temporary failure when no other action
is committed. */
commit_status = rexec->status;
From 65d771c15bf443690580dbb0643556794106522b Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 18 Aug 2021 13:26:26 +0200
Subject: [PATCH 11/12] lib-sieve: sieve-result - Indicate in
sieve_result_transaction_execute() debug message whether actions were
executed.
---
src/lib-sieve/sieve-result.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index c21c8017..6f3cb954 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -1796,10 +1796,11 @@ sieve_result_transaction_execute(struct sieve_result_execution *rexec,
}
e_debug(rexec->event, "Finished executing actions "
- "(status=%s, keep=%s)",
+ "(status=%s, keep=%s, executed=%s)",
sieve_execution_exitcode_to_str(status),
(rexec->keep_explicit ? "explicit" :
- (rexec->keep_implicit ? "implicit" : "none")));
+ (rexec->keep_implicit ? "implicit" : "none")),
+ (rexec->executed ? "yes" : "no"));
return status;
}
From 4596d39908a868783fae9a0c2fd264409c0aaa96 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 18 Aug 2021 13:27:50 +0200
Subject: [PATCH 12/12] lib-sieve: sieve-result - Indicate in
sieve_result_transaction_finalize() debug message whether actions were
committed.
---
src/lib-sieve/sieve-result.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 6f3cb954..effd6f28 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -1859,10 +1859,11 @@ sieve_result_transaction_commit_or_rollback(
}
e_debug(rexec->event, "Finished finalizing actions "
- "(status=%s, keep=%s)",
+ "(status=%s, keep=%s, committed=%s)",
sieve_execution_exitcode_to_str(status),
(rexec->keep_explicit ? "explicit" :
- (rexec->keep_implicit ? "implicit" : "none")));
+ (rexec->keep_implicit ? "implicit" : "none")),
+ (rexec->committed ? "yes" : "no"));
return commit_status;
}

View File

@ -0,0 +1,31 @@
From bdf4474ed82aaf964e7d94e72ca56b496e3815f9 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Fri, 1 Oct 2021 15:08:45 +0300
Subject: [PATCH] virtual: Fix leaking mailboxes if virtual mailbox can't be
opened
Fixes also a crash at deinit:
Panic: file mail-user.c: line 232 (mail_user_deinit): assertion failed: ((*user)->refcount == 1)
---
src/plugins/virtual/virtual-storage.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/plugins/virtual/virtual-storage.c b/src/plugins/virtual/virtual-storage.c
index 2f31503d53..a0779cc186 100644
--- a/src/plugins/virtual/virtual-storage.c
+++ b/src/plugins/virtual/virtual-storage.c
@@ -495,12 +495,12 @@ static int virtual_mailbox_open(struct mailbox *box)
ret = virtual_mailboxes_open(mbox, box->flags);
array_pop_back(&mbox->storage->open_stack);
}
+ if (ret == 0)
+ ret = index_storage_mailbox_open(box, FALSE);
if (ret < 0) {
virtual_mailbox_close_internal(mbox);
return -1;
}
- if (index_storage_mailbox_open(box, FALSE) < 0)
- return -1;
mbox->virtual_ext_id =
mail_index_ext_register(mbox->box.index, "virtual", 0,

View File

@ -0,0 +1,131 @@
From 7bad6a24160e34bce8f10e73dbbf9e5fbbcd1904 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 9 May 2022 15:23:33 +0300
Subject: [PATCH] auth: Fix handling passdbs with identical driver/args but
different mechanisms/username_filter
The passdb was wrongly deduplicated in this situation, causing wrong
mechanisms or username_filter setting to be used. This would be a rather
unlikely configuration though.
Fixed by moving mechanisms and username_filter from struct passdb_module
to struct auth_passdb, which is where they should have been in the first
place.
---
src/auth/auth-request.c | 6 +++---
src/auth/auth.c | 18 ++++++++++++++++++
src/auth/auth.h | 5 +++++
src/auth/passdb.c | 15 ++-------------
src/auth/passdb.h | 4 ----
5 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c
index cd08b1fa02..0ca29f3674 100644
--- a/src/auth/auth-request.c
+++ b/src/auth/auth-request.c
@@ -534,8 +534,8 @@ auth_request_want_skip_passdb(struct auth_request *request,
struct auth_passdb *passdb)
{
/* if mechanism is not supported, skip */
- const char *const *mechs = passdb->passdb->mechanisms;
- const char *const *username_filter = passdb->passdb->username_filter;
+ const char *const *mechs = passdb->mechanisms;
+ const char *const *username_filter = passdb->username_filter;
const char *username;
username = request->fields.user;
@@ -548,7 +548,7 @@ auth_request_want_skip_passdb(struct auth_request *request,
return TRUE;
}
- if (passdb->passdb->username_filter != NULL &&
+ if (passdb->username_filter != NULL &&
!auth_request_username_accepted(username_filter, username)) {
auth_request_log_debug(request,
request->mech != NULL ? AUTH_SUBSYS_MECH
diff --git a/src/auth/auth.c b/src/auth/auth.c
index f2f3fda20c..9f6c4ba60c 100644
--- a/src/auth/auth.c
+++ b/src/auth/auth.c
@@ -99,6 +99,24 @@ auth_passdb_preinit(struct auth *auth, const struct auth_passdb_settings *set,
auth_passdb->override_fields_tmpl =
passdb_template_build(auth->pool, set->override_fields);
+ if (*set->mechanisms == '\0') {
+ auth_passdb->mechanisms = NULL;
+ } else if (strcasecmp(set->mechanisms, "none") == 0) {
+ auth_passdb->mechanisms = (const char *const[]){ NULL };
+ } else {
+ auth_passdb->mechanisms =
+ (const char *const *)p_strsplit_spaces(auth->pool,
+ set->mechanisms, " ,");
+ }
+
+ if (*set->username_filter == '\0') {
+ auth_passdb->username_filter = NULL;
+ } else {
+ auth_passdb->username_filter =
+ (const char *const *)p_strsplit_spaces(auth->pool,
+ set->username_filter, " ,");
+ }
+
/* for backwards compatibility: */
if (set->pass)
auth_passdb->result_success = AUTH_DB_RULE_CONTINUE;
diff --git a/src/auth/auth.h b/src/auth/auth.h
index f700e29d5c..460a179765 100644
--- a/src/auth/auth.h
+++ b/src/auth/auth.h
@@ -41,6 +41,11 @@ struct auth_passdb {
struct passdb_template *default_fields_tmpl;
struct passdb_template *override_fields_tmpl;
+ /* Supported authentication mechanisms, NULL is all, {NULL} is none */
+ const char *const *mechanisms;
+ /* Username filter, NULL is no filter */
+ const char *const *username_filter;
+
enum auth_passdb_skip skip;
enum auth_db_rule result_success;
enum auth_db_rule result_failure;
diff --git a/src/auth/passdb.c b/src/auth/passdb.c
index eb4ac8ae82..f5eed1af4f 100644
--- a/src/auth/passdb.c
+++ b/src/auth/passdb.c
@@ -224,19 +224,8 @@ passdb_preinit(pool_t pool, const struct auth_passdb_settings *set)
passdb->id = ++auth_passdb_id;
passdb->iface = *iface;
passdb->args = p_strdup(pool, set->args);
- if (*set->mechanisms == '\0') {
- passdb->mechanisms = NULL;
- } else if (strcasecmp(set->mechanisms, "none") == 0) {
- passdb->mechanisms = (const char *const[]){NULL};
- } else {
- passdb->mechanisms = (const char* const*)p_strsplit_spaces(pool, set->mechanisms, " ,");
- }
-
- if (*set->username_filter == '\0') {
- passdb->username_filter = NULL;
- } else {
- passdb->username_filter = (const char* const*)p_strsplit_spaces(pool, set->username_filter, " ,");
- }
+ /* NOTE: if anything else than driver & args are added here,
+ passdb_find() also needs to be updated. */
array_push_back(&passdb_modules, &passdb);
return passdb;
}
diff --git a/src/auth/passdb.h b/src/auth/passdb.h
index 2e95328e5c..e466a9fdb6 100644
--- a/src/auth/passdb.h
+++ b/src/auth/passdb.h
@@ -63,10 +63,6 @@ struct passdb_module {
/* Default password scheme for this module.
If default_cache_key is set, must not be NULL. */
const char *default_pass_scheme;
- /* Supported authentication mechanisms, NULL is all, [NULL] is none*/
- const char *const *mechanisms;
- /* Username filter, NULL is no filter */
- const char *const *username_filter;
/* If blocking is set to TRUE, use child processes to access
this passdb. */

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,
const unsigned char *salt, size_t salt_size, unsigned int i,
unsigned char result[SHA1_RESULTLEN])
diff -up dovecot-2.3.14/src/auth/password-scheme-scram.c.opensslhmac dovecot-2.3.14/src/auth/password-scheme-scram.c
--- dovecot-2.3.14/src/auth/password-scheme-scram.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/auth/password-scheme-scram.c 2021-03-22 20:44:13.023912229 +0100
@@ -30,23 +30,23 @@ Hi(const struct hash_method *hmethod, co
const unsigned char *salt, size_t salt_size, unsigned int i,
unsigned char *result)
{
- struct hmac_context ctx;
+ struct openssl_hmac_context ctx;
unsigned char U[SHA1_RESULTLEN];
unsigned char U[hmethod->digest_size];
unsigned int j, k;
/* Calculate U1 */
- hmac_init(&ctx, str, str_size, &hash_method_sha1);
- hmac_init(&ctx, str, str_size, hmethod);
- hmac_update(&ctx, salt, salt_size);
- hmac_update(&ctx, "\0\0\0\1", 4);
- hmac_final(&ctx, U);
+ openssl_hmac_init(&ctx, str, str_size, &hash_method_sha1);
+ openssl_hmac_init(&ctx, str, str_size, hmethod);
+ openssl_hmac_update(&ctx, salt, salt_size);
+ openssl_hmac_update(&ctx, "\0\0\0\1", 4);
+ openssl_hmac_final(&ctx, U);
memcpy(result, U, SHA1_RESULTLEN);
memcpy(result, U, hmethod->digest_size);
/* Calculate U2 to Ui and Hi */
for (j = 2; j <= i; j++) {
- hmac_init(&ctx, str, str_size, &hash_method_sha1);
- hmac_init(&ctx, str, str_size, hmethod);
- hmac_update(&ctx, U, sizeof(U));
- hmac_final(&ctx, U);
+ openssl_hmac_init(&ctx, str, str_size, &hash_method_sha1);
+ openssl_hmac_init(&ctx, str, str_size, hmethod);
+ openssl_hmac_update(&ctx, U, sizeof(U));
+ openssl_hmac_final(&ctx, U);
for (k = 0; k < SHA1_RESULTLEN; k++)
for (k = 0; k < hmethod->digest_size; k++)
result[k] ^= U[k];
}
@@ -94,7 +94,7 @@ int scram_sha1_verify(const char *plaint
const unsigned char *raw_password, size_t size,
const char **error_r)
@@ -102,7 +102,7 @@ int scram_verify(const struct hash_metho
const char *plaintext, const unsigned char *raw_password,
size_t size, const char **error_r)
{
- struct hmac_context ctx;
+ struct openssl_hmac_context ctx;
const char *salt_base64;
unsigned int iter_count;
const unsigned char *salt;
@@ -118,10 +118,10 @@ int scram_sha1_verify(const char *plaint
iter_count, salted_password);
@@ -126,9 +126,9 @@ int scram_verify(const struct hash_metho
salt, salt_len, iter_count, salted_password);
/* Calculate ClientKey */
- hmac_init(&ctx, salted_password, sizeof(salted_password),
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password),
&hash_method_sha1);
- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
- hmac_update(&ctx, "Client Key", 10);
- hmac_final(&ctx, client_key);
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
+ openssl_hmac_update(&ctx, "Client Key", 10);
+ openssl_hmac_final(&ctx, client_key);
/* Calculate StoredKey */
sha1_get_digest(client_key, sizeof(client_key), calculated_stored_key);
@@ -139,7 +139,7 @@ void scram_sha1_generate(const char *pla
const unsigned char **raw_password_r, size_t *size_r)
hash_method_get_digest(hmethod, client_key, sizeof(client_key),
@@ -147,7 +147,7 @@ void scram_generate(const struct hash_me
const unsigned char **raw_password_r, size_t *size_r)
{
string_t *str;
- struct hmac_context ctx;
+ struct openssl_hmac_context ctx;
unsigned char salt[16];
unsigned char salted_password[SHA1_RESULTLEN];
unsigned char client_key[SHA1_RESULTLEN];
@@ -157,10 +157,10 @@ void scram_sha1_generate(const char *pla
unsigned char salted_password[hmethod->digest_size];
unsigned char client_key[hmethod->digest_size];
@@ -165,9 +165,9 @@ void scram_generate(const struct hash_me
sizeof(salt), SCRAM_DEFAULT_ITERATE_COUNT, salted_password);
/* Calculate ClientKey */
- hmac_init(&ctx, salted_password, sizeof(salted_password),
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password),
&hash_method_sha1);
- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
- hmac_update(&ctx, "Client Key", 10);
- hmac_final(&ctx, client_key);
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
+ openssl_hmac_update(&ctx, "Client Key", 10);
+ openssl_hmac_final(&ctx, client_key);
/* Calculate StoredKey */
sha1_get_digest(client_key, sizeof(client_key), stored_key);
@@ -168,10 +168,10 @@ void scram_sha1_generate(const char *pla
hash_method_get_digest(hmethod, client_key, sizeof(client_key),
@@ -176,9 +176,9 @@ void scram_generate(const struct hash_me
base64_encode(stored_key, sizeof(stored_key), str);
/* Calculate ServerKey */
- hmac_init(&ctx, salted_password, sizeof(salted_password),
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password),
&hash_method_sha1);
- hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
- hmac_update(&ctx, "Server Key", 10);
- hmac_final(&ctx, server_key);
+ openssl_hmac_init(&ctx, salted_password, sizeof(salted_password), hmethod);
+ openssl_hmac_update(&ctx, "Server Key", 10);
+ openssl_hmac_final(&ctx, server_key);
str_append_c(str, ',');
base64_encode(server_key, sizeof(server_key), str);
diff -up dovecot-2.3.8/src/lib/hmac.c.opensslhmac dovecot-2.3.8/src/lib/hmac.c
--- dovecot-2.3.8/src/lib/hmac.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib/hmac.c 2019-11-19 17:25:28.045716181 +0100
diff -up dovecot-2.3.14/src/lib/hmac.c.opensslhmac dovecot-2.3.14/src/lib/hmac.c
--- dovecot-2.3.14/src/lib/hmac.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib/hmac.c 2021-03-22 20:44:13.023912229 +0100
@@ -7,6 +7,10 @@
* This software is released under the MIT license.
*/
@ -292,11 +287,11 @@ diff -up dovecot-2.3.8/src/lib/hmac.c.opensslhmac dovecot-2.3.8/src/lib/hmac.c
+ }
+ i_assert(no_fips);
+ struct orig_hmac_context_priv *ctx = &_ctx->u.priv;
int i;
unsigned char k_ipad[64];
unsigned char k_opad[64];
unsigned int i;
unsigned char k_ipad[meth->block_size];
unsigned char k_opad[meth->block_size];
@@ -53,9 +112,27 @@ void hmac_init(struct hmac_context *_ctx
safe_memset(k_opad, 0, 64);
safe_memset(k_opad, 0, meth->block_size);
}
-void hmac_final(struct hmac_context *_ctx, unsigned char *digest)
@ -453,9 +448,9 @@ diff -up dovecot-2.3.8/src/lib/hmac.c.opensslhmac dovecot-2.3.8/src/lib/hmac.c
- safe_memset(prk, 0, sizeof(prk));
- safe_memset(okm, 0, sizeof(okm));
}
diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.8/src/lib/hmac-cram-md5.c
--- dovecot-2.3.8/src/lib/hmac-cram-md5.c.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib/hmac-cram-md5.c 2019-11-19 16:34:11.339036998 +0100
diff -up dovecot-2.3.14/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.14/src/lib/hmac-cram-md5.c
--- dovecot-2.3.14/src/lib/hmac-cram-md5.c.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib/hmac-cram-md5.c 2021-03-22 20:44:13.023912229 +0100
@@ -9,10 +9,10 @@
#include "md5.h"
#include "hmac-cram-md5.h"
@ -482,9 +477,9 @@ diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.c.opensslhmac dovecot-2.3.8/src/lib
const unsigned char *cdp;
struct md5_context *ctx = (void*)hmac_ctx->ctx;
diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.8/src/lib/hmac-cram-md5.h
--- dovecot-2.3.8/src/lib/hmac-cram-md5.h.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib/hmac-cram-md5.h 2019-11-19 16:34:11.339036998 +0100
diff -up dovecot-2.3.14/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.14/src/lib/hmac-cram-md5.h
--- dovecot-2.3.14/src/lib/hmac-cram-md5.h.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib/hmac-cram-md5.h 2021-03-22 20:44:13.023912229 +0100
@@ -5,9 +5,9 @@
#define CRAM_MD5_CONTEXTLEN 32
@ -497,19 +492,19 @@ diff -up dovecot-2.3.8/src/lib/hmac-cram-md5.h.opensslhmac dovecot-2.3.8/src/lib
const unsigned char context_digest[CRAM_MD5_CONTEXTLEN]);
diff -up dovecot-2.3.8/src/lib/hmac.h.opensslhmac dovecot-2.3.8/src/lib/hmac.h
--- dovecot-2.3.8/src/lib/hmac.h.opensslhmac 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib/hmac.h 2019-11-19 16:34:11.339036998 +0100
@@ -3,60 +3,97 @@
diff -up dovecot-2.3.14/src/lib/hmac.h.opensslhmac dovecot-2.3.14/src/lib/hmac.h
--- dovecot-2.3.14/src/lib/hmac.h.opensslhmac 2021-03-04 09:38:06.000000000 +0100
+++ dovecot-2.3.14/src/lib/hmac.h 2021-03-22 20:44:13.023912229 +0100
@@ -4,60 +4,97 @@
#include "hash-method.h"
#include "sha1.h"
#include "sha2.h"
+#include <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: 5%{?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,20 @@ 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.17, s390x FTBFS fix
Patch15: dovecot-2.3.16-ftbfsbigend.patch
Patch16: dovecot-2.3.16-keeplzma.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 <= 2.3.19.1, rhbz#2106232
Patch17: dovecot-2.3.19.1-7bad6a24.patch
# from upstream, for dovecot <= 2.3.11.3, rhbz#1894418
Patch23: dovecot-2.3.8-blockcount.patch
# from upstream, for < 2.3.19.1, rhbz#2128857
Patch18: dovecot-2.3.18-9f300239..4596d399.patch
Patch19: dovecot-2.3.18-bdf447e4.patch
# from upstream, for < 2.3.21, RHEL-22854
Patch20: dovecot-2.3.16-d7705bc6.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
Source15: prestartscript
@ -172,42 +153,22 @@ This package provides the development files for dovecot.
%prep
%setup -q -n %{name}-%{version}%{?prever} -a 8
%patch1 -p1 -b .default-settings
%patch2 -p1 -b .mkcert-permissions
%patch3 -p1 -b .mkcert-paths
%patch6 -p1 -b .waitonline
%patch8 -p1 -b .initbysystemd
%patch9 -p1 -b .systemd_w_protectsystem
%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
%patch -P 1 -p1 -b .default-settings
%patch -P 2 -p1 -b .mkcert-permissions
%patch -P 3 -p1 -b .mkcert-paths
%patch -P 6 -p1 -b .waitonline
%patch -P 8 -p1 -b .initbysystemd
%patch -P 9 -p1 -b .systemd_w_protectsystem
%patch -P 11 -p1 -b .aclfix
%patch -P 13 -p1 -b .bigkey
%patch -P 14 -p1 -b .opensslhmac
%patch -P 15 -p1 -b .ftbfsbigend
%patch -P 16 -p1 -b .keeplzma
%patch -P 17 -p1 -b .7bad6a24
%patch -P 19 -p1 -b .bdf447e4
%patch -P 20 -p1 -b .d7705bc6
pushd dovecot-2*3-pigeonhole-%{pigeonholever}
%patch -P 18 -p1 -b .9f300239..4596d399
popd
@ -226,6 +187,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 \
@ -286,7 +248,6 @@ mv $RPM_BUILD_ROOT/%{_docdir}/%{name} $RPM_BUILD_ROOT/%{_docdir}/%{name}-pigeonh
install -m 644 AUTHORS ChangeLog COPYING COPYING.LGPL INSTALL NEWS README $RPM_BUILD_ROOT/%{_docdir}/%{name}-pigeonhole
popd
%if %{?fedora}00%{?rhel} < 6
sed -i 's|password-auth|system-auth|' %{SOURCE2}
%endif
@ -427,6 +388,7 @@ make check
%{_bindir}/doveadm
%{_bindir}/doveconf
%{_bindir}/dsync
%{_bindir}/dovecot-sysreport
%if %{?fedora}0 > 140 || %{?rhel}0 > 60
@ -448,6 +410,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 +430,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 +470,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 +531,22 @@ make check
%{_libdir}/%{name}/dict/libdriver_pgsql.so
%changelog
* Fri Feb 16 2024 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.16-5
- fixes assert-crash when IMAP client uses QRESYNC (#RHEL-22854)
* Fri Aug 04 2023 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.16-4
- fix leaking mailboxes if virtual mailbox can't be opened (#2128857)
* Tue Jul 19 2022 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.16-3
- fix possible privilege escalation when similar master and non-master passdbs are used (#2106231)
* Wed Dec 08 2021 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.16-2
- do not disable xz/lzma for now despite being deprecated
* 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)