commit 9f7f0c94b67e9506ebf8ca674dd6cbb6a7989f44
Author: Oswald Buddenhagen <[email protected]>
Date: Wed Nov 24 16:57:00 2021 +0100
CVE-2021-3657: security fixes
unlike in the 1.4 branch, we use signed ints for offsets and lengths, so
many of the qualifying statements from the 1.4 series don't apply.
src/drv_imap.c | 9 +++++++++
src/drv_maildir.c | 8 +++++++-
src/socket.c | 8 ++++++--
src/sync.c | 15 ++++++++++-----
4 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 4cc3b2a..0d6c869 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -780,6 +780,11 @@ parse_imap_list( imap_store_t *ctx, char **sp,
parse_list_state_t *sts )
bytes = cur->len = strtol( s + 1, &s, 10 );
if (*s != '}' || *++s)
goto bail;
+ if ((uint)bytes >= INT_MAX) {
+ error( "IMAP error: excessively large literal
from %s "
+ "- THIS MIGHT BE AN ATTEMPT TO HACK
YOU!\n", ctx->conn.name );
+ goto bail;
+ }
s = cur->val = nfmalloc( cur->len + 1 );
s[cur->len] = 0;
@@ -1279,6 +1284,10 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char
*cmd ATTR_UNUSED )
}
arg = list->val;
argl = list->len;
+ if (argl > 1000) {
+ warn( "IMAP warning: ignoring unreasonably long mailbox name
'%.100s[...]'\n", arg );
+ goto skip;
+ }
if ((l = strlen( ctx->prefix ))) {
if (!starts_with( arg, argl, ctx->prefix, l )) {
if (is_inbox( ctx, arg, argl )) {
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index e1622d3..40a4d2a 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -1147,7 +1147,8 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t
*msglist )
}
goto retry;
}
- entry->size = st.st_size;
+ // The clipped value is good enough for MaxSize
comparisons.
+ entry->size = st.st_size > INT_MAX ? INT_MAX :
(int)st.st_size;
}
if (want_tuid || want_msgid) {
if (!(f = fopen( buf, "r" ))) {
@@ -1534,12 +1535,17 @@ maildir_fetch_msg( store_t *gctx, message_t *gmsg,
msg_data_t *data,
}
}
fstat( fd, &st );
+ if (st.st_size > INT_MAX) {
+ error( "Maildir error: %s is too big", buf );
+ goto mbad;
+ }
data->len = st.st_size;
if (data->date == -1)
data->date = st.st_mtime;
data->data = nfmalloc( data->len );
if (read( fd, data->data, data->len ) != data->len) {
sys_error( "Maildir error: cannot read %s", buf );
+ mbad:
close( fd );
cb( DRV_MSG_BAD, aux );
return;
diff --git a/src/socket.c b/src/socket.c
index 84449e7..d8548a9 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -898,6 +898,8 @@ do_append( conn_t *conn, buff_chunk_t *bc )
/* This is big enough to avoid excessive chunking, but is
* sufficiently small to keep SSL latency low with a slow uplink. */
#define WRITE_CHUNK_SIZE 1024
+// Huge data blocks (message payloads) are forcibly chunked.
+#define MAX_WRITE_CHUNK_SIZE (1 << 30)
static void
do_flush( conn_t *conn )
@@ -952,7 +954,8 @@ do_flush( conn_t *conn )
void
socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
{
- int i, buf_avail, len, offset = 0, total = 0;
+ int i, buf_avail, len, offset = 0;
+ uint total = 0;
buff_chunk_t *bc;
for (i = 0; i < iovcnt; i++)
@@ -971,7 +974,8 @@ socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt )
* predict a reasonable output buffer size anyway -
deflatePending() does
* not account for consumed but not yet compressed
input, and adding up
* the deflateBound()s would be a tad *too*
pessimistic. */
- buf_avail = total > WRITE_CHUNK_SIZE ? total :
WRITE_CHUNK_SIZE;
+ buf_avail = total > MAX_WRITE_CHUNK_SIZE ?
MAX_WRITE_CHUNK_SIZE :
+ total > WRITE_CHUNK_SIZE ? total :
WRITE_CHUNK_SIZE;
bc = nfmalloc( offsetof(buff_chunk_t, data) + buf_avail
);
bc->len = 0;
#ifndef HAVE_LIBZ
diff --git a/src/sync.c b/src/sync.c
index 7d3fe79..46e089c 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -333,7 +333,7 @@ copy_msg_bytes( char **out_ptr, const char *in_buf, int
*in_idx, int in_len, int
}
static int
-copy_msg_convert( int in_cr, int out_cr, copy_vars_t *vars )
+copy_msg_convert( int in_cr, int out_cr, copy_vars_t *vars, int t )
{
char *in_buf = vars->data.data;
int in_len = vars->data.len;
@@ -361,7 +361,8 @@ copy_msg_convert( int in_cr, int out_cr, copy_vars_t *vars )
goto nloop;
}
}
- /* invalid message */
+ warn( "Warning: message %u from %s has incomplete header;
skipping.\n",
+ vars->msg->uid, str_ms[1-t] );
free( in_buf );
return 0;
oke:
@@ -382,6 +383,12 @@ copy_msg_convert( int in_cr, int out_cr, copy_vars_t *vars
)
}
vars->data.len = in_len + extra;
+ if ((uint)vars->data.len > INT_MAX) {
+ warn( "Warning: message %u from %s is too big after conversion;
skipping.\n",
+ vars->msg->uid, str_ms[1-t] );
+ free( in_buf );
+ return 0;
+ }
char *out_buf = vars->data.data = nfmalloc( vars->data.len );
idx = 0;
if (vars->srec) {
@@ -423,9 +430,7 @@ msg_fetched( int sts, void *aux )
scr = (svars->drv[1-t]->get_caps( svars->ctx[1-t] ) / DRV_CRLF)
& 1;
tcr = (svars->drv[t]->get_caps( svars->ctx[t] ) / DRV_CRLF) & 1;
if (vars->srec || scr != tcr) {
- if (!copy_msg_convert( scr, tcr, vars )) {
- warn( "Warning: message %u from %s has
incomplete header.\n",
- vars->msg->uid, str_ms[1-t] );
+ if (!copy_msg_convert( scr, tcr, vars, t )) {
vars->cb( SYNC_NOGOOD, 0, vars );
return;
}
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel