130 lines
4.4 KiB
Diff
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) {
|