From 17babc1695e82ca80d032b79e920fcb86ede2347 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Sat, 8 Sep 2018 18:36:16 +0200 Subject: [PATCH 1/3] use SNI when connecting with SSL based on patch by Vincent Bernat . --- src/socket.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/socket.c b/src/socket.c index dd79619..e3fda42 100644 --- a/src/socket.c +++ b/src/socket.c @@ -271,6 +271,8 @@ socket_start_tls( conn_t *conn, void (*cb)( int ok, void *aux ) ) init_wakeup( &conn->ssl_fake, ssl_fake_cb, conn ); conn->ssl = SSL_new( ((server_conf_t *)conn->conf)->SSLContext ); + if (ssl_return( "set server name", conn, SSL_set_tlsext_host_name( conn->ssl, conn->conf->host ) ) < 0) + return; SSL_set_fd( conn->ssl, conn->fd ); SSL_set_mode( conn->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER ); socket_expect_read( conn, 1 ); From f7cec3064d0563cf38940cb3662d938000a06442 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Sun, 9 Sep 2018 13:35:05 +0200 Subject: [PATCH 2/3] bump IMAP command buffer size to 4KiB while only 1KiB is required by the IMAP spec, AUTHENTICATE GSSAPI with Kerberos requires about 1700 bytes. accomodate that, plus some reserve. fix suggested by Tollef Fog Heen via Debian BTS. --- src/drv_imap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drv_imap.c b/src/drv_imap.c index d76328e..06414e2 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -287,7 +287,7 @@ send_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd ) int bufl, litplus, iovcnt = 1; const char *buffmt; conn_iovec_t iov[3]; - char buf[1024]; + char buf[4096]; cmd->tag = ++ctx->nexttag; if (!cmd->param.data) { @@ -444,7 +444,7 @@ imap_vprintf( const char *fmt, va_list ap ) char *d, *ed; int maxlen; char c; - char buf[1024]; /* Minimal supported command buffer size per IMAP spec. */ + char buf[4096]; d = buf; ed = d + sizeof(buf); From acfa3a2bbc0f4243096843d08671521ae2ad545f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Sat, 24 Nov 2018 14:15:53 +0100 Subject: [PATCH 3/3] sort messages from UID FETCH request turns out that some IMAP servers (e.g., poczta.o2.pl) do not return messages in ascending UID order in response to a UID FETCH request, which makes the driver violate the API contract. counter this by sorting the messages. this also addresses the long-standing (but hypothetical) issue that parallel UID FETCH requests could be handled out-of-order and thus also lead to mixed up results. based on patch by Marcin Niestroj . --- src/driver.c | 9 +++++++++ src/driver.h | 1 + src/drv_imap.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/driver.c b/src/driver.c index e522d14..e28d817 100644 --- a/src/driver.c +++ b/src/driver.c @@ -27,6 +27,15 @@ driver_t *drivers[N_DRIVERS] = { &maildir_driver, &imap_driver }; +int +count_generic_messages( message_t *msgs ) +{ + int count = 0; + for (; msgs; msgs = msgs->next) + count++; + return count; +} + void free_generic_messages( message_t *msgs ) { diff --git a/src/driver.h b/src/driver.h index 7dc047a..18f8bfd 100644 --- a/src/driver.h +++ b/src/driver.h @@ -259,6 +259,7 @@ struct driver { int (*get_fail_state)( store_conf_t *conf ); }; +int count_generic_messages( message_t * ); void free_generic_messages( message_t * ); void parse_generic_store( store_conf_t *store, conffile_t *cfg ); diff --git a/src/drv_imap.c b/src/drv_imap.c index 06414e2..9e137cf 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -597,8 +597,9 @@ imap_refcounted_new_cmd( imap_cmd_refcounted_state_t *sts ) free( sts ); \ } -#define DONE_REFCOUNTED_STATE_ARGS(sts, ...) \ +#define DONE_REFCOUNTED_STATE_ARGS(sts, finalize, ...) \ if (!--sts->gen.ref_count) { \ + finalize \ sts->callback( sts->gen.ret_val, __VA_ARGS__, sts->callback_aux ); \ free( sts ); \ } @@ -1102,7 +1103,6 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) if (status & M_FLAGS) msgdata->flags = mask; } else { - /* XXX this will need sorting for out-of-order (multiple queries) */ cur = nfcalloc( sizeof(*cur) ); *ctx->msgapp = &cur->gen; ctx->msgapp = &cur->gen.next; @@ -2587,6 +2587,47 @@ imap_load_box( store_t *gctx, uint minuid, uint maxuid, uint newuid, uint seenui } } +static int +imap_sort_msgs_comp( const void *a_, const void *b_ ) +{ + const message_t *a = *(const message_t * const *)a_; + const message_t *b = *(const message_t * const *)b_; + + if (a->uid < b->uid) + return -1; + if (a->uid > b->uid) + return 1; + return 0; +} + +static void +imap_sort_msgs( imap_store_t *ctx ) +{ + int count = count_generic_messages( ctx->msgs ); + if (count <= 1) + return; + + message_t **t = nfmalloc( sizeof(*t) * count ); + + message_t *m = ctx->msgs; + for (int i = 0; i < count; i++) { + t[i] = m; + m = m->next; + } + + qsort( t, count, sizeof(*t), imap_sort_msgs_comp ); + + ctx->msgs = t[0]; + + int j; + for (j = 0; j < count - 1; j++) + t[j]->next = t[j + 1]; + ctx->msgapp = &t[j]->next; + *ctx->msgapp = NULL; + + free( t ); +} + static void imap_submit_load_p2( imap_store_t *, imap_cmd_t *, int ); static void @@ -2615,7 +2656,10 @@ imap_submit_load_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response ) static void imap_submit_load_p3( imap_store_t *ctx, imap_load_box_state_t *sts ) { - DONE_REFCOUNTED_STATE_ARGS(sts, ctx->msgs, ctx->total_msgs, ctx->recent_msgs) + DONE_REFCOUNTED_STATE_ARGS(sts, { + if (sts->gen.ret_val == DRV_OK) + imap_sort_msgs( ctx ); + }, ctx->msgs, ctx->total_msgs, ctx->recent_msgs) } /******************* imap_fetch_msg *******************/ @@ -3013,7 +3057,7 @@ imap_list_store_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response ) static void imap_list_store_p3( imap_store_t *ctx, imap_list_store_state_t *sts ) { - DONE_REFCOUNTED_STATE_ARGS(sts, ctx->boxes) + DONE_REFCOUNTED_STATE_ARGS(sts, , ctx->boxes) } /******************* imap_cancel_cmds *******************/