From 0840026a4b41600ad74717bf7b26ab4185ed7121 Mon Sep 17 00:00:00 2001 From: "Dmitrij D. Czarkoff" Date: Fri, 3 Apr 2015 22:38:46 +0200 Subject: [PATCH 1/7] fix crash in maildir_set_msg_flags() memcpy(3)'s behavior is undefined when source and destination addresses overlap, and it actually crashed on OpenBSD. use memmove() instead. --- src/drv_maildir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drv_maildir.c b/src/drv_maildir.c index 045dd9c..98e1687 100644 --- a/src/drv_maildir.c +++ b/src/drv_maildir.c @@ -1464,7 +1464,7 @@ maildir_set_msg_flags( store_t *gctx, message_t *gmsg, int uid ATTR_UNUSED, int for (i = 0; i < as(Flags); i++) { if ((p = strchr( s, Flags[i] ))) { if (del & (1 << i)) { - memcpy( p, p + 1, fl - (p - s) ); + memmove( p, p + 1, fl - (p - s) ); fl--; } } else if (add & (1 << i)) { From 8dc776c528bc29bda4e864f726f15916a77a3183 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 9 Apr 2015 10:05:45 +0200 Subject: [PATCH 2/7] fix SASL, take 2 USER (the authorization identity) specifies whom to act for. AUTHNAME (the authentication identity) specifies who is acting (and thus whose PASS is being used). USER is derived from AUTHNAME if omitted, but apparently the GSS-API module automatically adds the REALM, which is not helpful. it appears to be common to set both USER and AUTHNAME to the same value, so let's just do it as well. REFMAIL: 20150407194807.GA1714@leeloo.kyriasis.com --- src/drv_imap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/drv_imap.c b/src/drv_imap.c index 72a8fd1..2961769 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -1780,6 +1780,7 @@ ensure_password( imap_server_conf_t *srvc ) #ifdef HAVE_LIBSASL static sasl_callback_t sasl_callbacks[] = { + { SASL_CB_USER, NULL, NULL }, { SASL_CB_AUTHNAME, NULL, NULL }, { SASL_CB_PASS, NULL, NULL }, { SASL_CB_LIST_END, NULL, NULL } @@ -1794,6 +1795,7 @@ process_sasl_interact( sasl_interact_t *interact, imap_server_conf_t *srvc ) switch (interact->id) { case SASL_CB_LIST_END: return 0; + case SASL_CB_USER: case SASL_CB_AUTHNAME: val = ensure_user( srvc ); break; From 08dab9465b0470704662e96c083cac0a6fd76ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= Date: Sat, 11 Apr 2015 20:06:30 +0200 Subject: [PATCH 3/7] Make Berkley DB an optional dependency. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It doesn't seem necessary for any of the basic functionality. Signed-off-by: Reimar Döffinger --- README | 2 +- configure.ac | 13 ++++++++++--- src/Makefile.am | 13 ++++++++----- src/compat/Makefile.am | 2 +- src/drv_maildir.c | 1 - 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/README b/README index 66a0017..aa020de 100644 --- a/README +++ b/README @@ -61,7 +61,7 @@ isync executable still exists; it is a compatibility wrapper around mbsync. * Requirements - Berkley DB 4.2+ + Berkley DB 4.2+ (optional) OpenSSL for TLS/SSL support (optional) * Installation diff --git a/configure.ac b/configure.ac index 7b4086d..d7d3404 100644 --- a/configure.ac +++ b/configure.ac @@ -146,8 +146,9 @@ AC_CACHE_CHECK([for Berkley DB >= 4.2], ac_cv_berkdb4, db->truncate(db, 0, 0, 0); db->open(db, 0, "foo", "foo", DB_HASH, DB_CREATE, 0)], [ac_cv_berkdb4=yes])]) -if test "x$ac_cv_berkdb4" = xno; then - AC_MSG_ERROR([Berkley DB >= 4.2 not found.]) +if test "x$ac_cv_berkdb4" = xyes; then + AC_SUBST([DB_LIBS], ["-ldb"]) + AC_DEFINE(USE_DB, 1, [if Berkley DB should be used]) fi have_zlib= @@ -165,7 +166,8 @@ AC_ARG_ENABLE(compat, if test "x$ob_cv_enable_compat" != xno; then AC_CHECK_FUNCS(getopt_long) fi -AM_CONDITIONAL(with_compat, test "x$ob_cv_enable_compat" != xno) +AM_CONDITIONAL(with_compat, test "x$ob_cv_enable_compat" != xno -a "x$ac_cv_berkdb4" = xyes) +AM_CONDITIONAL(with_mdconvert, test "x$ac_cv_berkdb4" = xyes) AC_CONFIG_FILES([Makefile src/Makefile src/compat/Makefile isync.spec]) AC_OUTPUT @@ -186,4 +188,9 @@ if test -n "$have_zlib"; then else AC_MSG_RESULT([Not using zlib]) fi +if test "x$ac_cv_berkdb4" = xyes; then + AC_MSG_RESULT([Using Berkley DB]) +else + AC_MSG_RESULT([Not using Berkley DB]) +fi AC_MSG_RESULT() diff --git a/src/Makefile.am b/src/Makefile.am index 0a49f21..b548d60 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,20 +3,23 @@ compat_dir = compat endif SUBDIRS = $(compat_dir) -bin_PROGRAMS = mbsync mdconvert - mbsync_SOURCES = main.c sync.c config.c util.c socket.c driver.c drv_imap.c drv_maildir.c -mbsync_LDADD = -ldb $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS) +mbsync_LDADD = $(DB_LIBS) $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS) noinst_HEADERS = common.h config.h driver.h sync.h socket.h mdconvert_SOURCES = mdconvert.c -mdconvert_LDADD = -ldb +mdconvert_LDADD = $(DB_LIBS) +if with_mdconvert +mdconvert_prog = mdconvert +mdconvert_man = mdconvert.1 +endif EXTRA_PROGRAMS = tst_timers tst_timers_SOURCES = tst_timers.c util.c -man_MANS = mbsync.1 mdconvert.1 +bin_PROGRAMS = mbsync $(mdconvert_prog) +man_MANS = mbsync.1 $(mdconvert_man) exampledir = $(docdir)/examples example_DATA = mbsyncrc.sample diff --git a/src/compat/Makefile.am b/src/compat/Makefile.am index c234f0f..6a99942 100644 --- a/src/compat/Makefile.am +++ b/src/compat/Makefile.am @@ -1,7 +1,7 @@ bin_PROGRAMS = isync isync_SOURCES = main.c config.c convert.c util.c -isync_LDADD = -ldb +isync_LDADD = $(DB_LIBS) noinst_HEADERS = isync.h man_MANS = isync.1 diff --git a/src/drv_maildir.c b/src/drv_maildir.c index 98e1687..18ebbaf 100644 --- a/src/drv_maildir.c +++ b/src/drv_maildir.c @@ -38,7 +38,6 @@ #include #include -#define USE_DB 1 #ifdef __linux__ # define LEGACY_FLOCK 1 #endif From 83eaac8787dd4ee43a8635a12723da4b6a196e28 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 13 Apr 2015 09:17:56 +0200 Subject: [PATCH 4/7] fix uninitialized variable warning the returned UID is not used when trashing messages, but we still shouldn't just return an undefined value. --- src/drv_maildir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/drv_maildir.c b/src/drv_maildir.c index 18ebbaf..2797d8a 100644 --- a/src/drv_maildir.c +++ b/src/drv_maildir.c @@ -1365,6 +1365,7 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash, } box = gctx->path; } else { + uid = 0; box = ctx->trash; } From 41ed1012241c30c265109ca187bfe6751ed19828 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Sat, 18 Apr 2015 10:54:00 +0200 Subject: [PATCH 5/7] don't list IMAP Path under INBOX twice if NAMESPACE is "INBOX.", listing INBOX recursively will already include it. REFMAIL: 1890363108.1020695.1428757117731.JavaMail.yahoo@mail.yahoo.com --- src/drv_imap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drv_imap.c b/src/drv_imap.c index 2961769..7b41864 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -2612,7 +2612,7 @@ imap_list_store( store_t *gctx, int flags, imap_store_t *ctx = (imap_store_t *)gctx; struct imap_cmd_refcounted_state *sts = imap_refcounted_new_state( cb, aux ); - if (((flags & LIST_PATH) && + if (((flags & LIST_PATH) && (!(flags & LIST_INBOX) || !is_inbox( ctx, ctx->prefix, -1 )) && imap_exec( ctx, imap_refcounted_new_cmd( sts ), imap_refcounted_done_box, "LIST \"\" \"%\\s*\"", ctx->prefix ) < 0) || ((flags & LIST_INBOX) && (!(flags & LIST_PATH) || *ctx->prefix) && From 2d4ce72a8b164f04c059ca4a446e340f2919f086 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Sat, 18 Apr 2015 11:42:00 +0200 Subject: [PATCH 6/7] make handling of Inbox-in-Path nesting less obfuscated when we run into Inbox while listing Path, check whether Inbox is being listed anyway, and just skip it if so, instead of listing it right away and resetting LIST_INBOX (and thus having a calling order dependency). --- src/drv_maildir.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/drv_maildir.c b/src/drv_maildir.c index 2797d8a..a54c17b 100644 --- a/src/drv_maildir.c +++ b/src/drv_maildir.c @@ -228,10 +228,10 @@ maildir_invoke_bad_callback( store_t *ctx ) ctx->bad_callback( ctx->bad_callback_aux ); } -static int maildir_list_inbox( store_t *gctx, int *flags ); +static int maildir_list_inbox( store_t *gctx, int flags ); static int -maildir_list_recurse( store_t *gctx, int isBox, int *flags, const char *inbox, int inboxLen, +maildir_list_recurse( store_t *gctx, int isBox, int flags, const char *inbox, int inboxLen, char *path, int pathLen, char *name, int nameLen ) { DIR *dir; @@ -258,7 +258,8 @@ maildir_list_recurse( store_t *gctx, int isBox, int *flags, const char *inbox, i const char *ent = de->d_name; pl = pathLen + nfsnprintf( path + pathLen, _POSIX_PATH_MAX - pathLen, "%s", ent ); if (inbox && equals( path, pl, inbox, inboxLen )) { - if (maildir_list_inbox( gctx, flags ) < 0) { + /* Inbox nested into Path. List now if it won't be listed separately anyway. */ + if (!(flags & LIST_INBOX) && maildir_list_inbox( gctx, flags ) < 0) { closedir( dir ); return -1; } @@ -290,11 +291,10 @@ maildir_list_recurse( store_t *gctx, int isBox, int *flags, const char *inbox, i } static int -maildir_list_inbox( store_t *gctx, int *flags ) +maildir_list_inbox( store_t *gctx, int flags ) { char path[_POSIX_PATH_MAX], name[_POSIX_PATH_MAX]; - *flags &= ~LIST_INBOX; return maildir_list_recurse( gctx, 2, flags, 0, 0, path, nfsnprintf( path, _POSIX_PATH_MAX, "%s", ((maildir_store_conf_t *)gctx->conf)->inbox ), @@ -302,7 +302,7 @@ maildir_list_inbox( store_t *gctx, int *flags ) } static int -maildir_list_path( store_t *gctx, int *flags ) +maildir_list_path( store_t *gctx, int flags ) { const char *inbox = ((maildir_store_conf_t *)gctx->conf)->inbox; char path[_POSIX_PATH_MAX], name[_POSIX_PATH_MAX]; @@ -319,8 +319,8 @@ static void maildir_list_store( store_t *gctx, int flags, void (*cb)( int sts, void *aux ), void *aux ) { - if (((flags & LIST_PATH) && maildir_list_path( gctx, &flags ) < 0) || - ((flags & LIST_INBOX) && maildir_list_inbox( gctx, &flags ) < 0)) { + if (((flags & LIST_PATH) && maildir_list_path( gctx, flags ) < 0) || + ((flags & LIST_INBOX) && maildir_list_inbox( gctx, flags ) < 0)) { maildir_invoke_bad_callback( gctx ); cb( DRV_CANCELED, aux ); } else { From 98bd2b115d465440d1f24e1b91269a6a334864f2 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Sat, 18 Apr 2015 11:46:36 +0200 Subject: [PATCH 7/7] make it possible to nest maildir Path under Inbox simply make the code symmetrical to the inverse case. note that the result will be sort of awkward, as the folders under Path (and thus the subfolders of Inbox) don't start with a dot, while the subfolders of these folders do. this needs to be addressed separately. --- src/drv_maildir.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/drv_maildir.c b/src/drv_maildir.c index a54c17b..b96950c 100644 --- a/src/drv_maildir.c +++ b/src/drv_maildir.c @@ -228,10 +228,12 @@ maildir_invoke_bad_callback( store_t *ctx ) ctx->bad_callback( ctx->bad_callback_aux ); } -static int maildir_list_inbox( store_t *gctx, int flags ); +static int maildir_list_inbox( store_t *gctx, int flags, const char *basePath ); +static int maildir_list_path( store_t *gctx, int flags, const char *inbox ); static int -maildir_list_recurse( store_t *gctx, int isBox, int flags, const char *inbox, int inboxLen, +maildir_list_recurse( store_t *gctx, int isBox, int flags, + const char *inbox, int inboxLen, const char *basePath, int basePathLen, char *path, int pathLen, char *name, int nameLen ) { DIR *dir; @@ -259,7 +261,13 @@ maildir_list_recurse( store_t *gctx, int isBox, int flags, const char *inbox, in pl = pathLen + nfsnprintf( path + pathLen, _POSIX_PATH_MAX - pathLen, "%s", ent ); if (inbox && equals( path, pl, inbox, inboxLen )) { /* Inbox nested into Path. List now if it won't be listed separately anyway. */ - if (!(flags & LIST_INBOX) && maildir_list_inbox( gctx, flags ) < 0) { + if (!(flags & LIST_INBOX) && maildir_list_inbox( gctx, flags, 0 ) < 0) { + closedir( dir ); + return -1; + } + } else if (basePath && equals( path, pl, basePath, basePathLen )) { + /* Path nested into Inbox. List now if it won't be listed separately anyway. */ + if (!(flags & LIST_PATH) && maildir_list_path( gctx, flags, 0 ) < 0) { closedir( dir ); return -1; } @@ -280,7 +288,7 @@ maildir_list_recurse( store_t *gctx, int isBox, int flags, const char *inbox, in } } nl = nameLen + nfsnprintf( name + nameLen, _POSIX_PATH_MAX - nameLen, "%s", ent ); - if (maildir_list_recurse( gctx, 1, flags, inbox, inboxLen, path, pl, name, nl ) < 0) { + if (maildir_list_recurse( gctx, 1, flags, inbox, inboxLen, basePath, basePathLen, path, pl, name, nl ) < 0) { closedir( dir ); return -1; } @@ -291,26 +299,25 @@ maildir_list_recurse( store_t *gctx, int isBox, int flags, const char *inbox, in } static int -maildir_list_inbox( store_t *gctx, int flags ) +maildir_list_inbox( store_t *gctx, int flags, const char *basePath ) { char path[_POSIX_PATH_MAX], name[_POSIX_PATH_MAX]; return maildir_list_recurse( - gctx, 2, flags, 0, 0, + gctx, 2, flags, 0, 0, basePath, basePath ? strlen( basePath ) - 1 : 0, path, nfsnprintf( path, _POSIX_PATH_MAX, "%s", ((maildir_store_conf_t *)gctx->conf)->inbox ), name, nfsnprintf( name, _POSIX_PATH_MAX, "INBOX" ) ); } static int -maildir_list_path( store_t *gctx, int flags ) +maildir_list_path( store_t *gctx, int flags, const char *inbox ) { - const char *inbox = ((maildir_store_conf_t *)gctx->conf)->inbox; char path[_POSIX_PATH_MAX], name[_POSIX_PATH_MAX]; if (maildir_validate_path( gctx->conf ) < 0) return -1; return maildir_list_recurse( - gctx, 0, flags, inbox, strlen( inbox ), + gctx, 0, flags, inbox, inbox ? strlen( inbox ) : 0, 0, 0, path, nfsnprintf( path, _POSIX_PATH_MAX, "%s", gctx->conf->path ), name, 0 ); } @@ -319,8 +326,8 @@ static void maildir_list_store( store_t *gctx, int flags, void (*cb)( int sts, void *aux ), void *aux ) { - if (((flags & LIST_PATH) && maildir_list_path( gctx, flags ) < 0) || - ((flags & LIST_INBOX) && maildir_list_inbox( gctx, flags ) < 0)) { + if (((flags & LIST_PATH) && maildir_list_path( gctx, flags, ((maildir_store_conf_t *)gctx->conf)->inbox ) < 0) || + ((flags & LIST_INBOX) && maildir_list_inbox( gctx, flags, gctx->conf->path ) < 0)) { maildir_invoke_bad_callback( gctx ); cb( DRV_CANCELED, aux ); } else {