dovecot/SOURCES/dovecot-2.3.13-CVE_2020_243...

130 lines
4.4 KiB
Diff

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) {