Compare commits

...

44 commits

Author SHA1 Message Date
Oswald Buddenhagen
4dc7e17f3e fix a bunch of warnings
(cherry picked from commit 61d98c5a1d)

Conflicts:
	src/drv_imap.c
	src/sync.c
2013-02-20 08:33:59 +01:00
Oswald Buddenhagen
f8a913ac80 avoid preprocessor warnings on missing features: #if => #ifdef
(cherry picked from commit 4afd31a457)

Conflicts:
	src/drv_imap.c
2013-02-20 08:27:48 +01:00
Oswald Buddenhagen
af863bb601 bump version 2013-02-20 08:20:15 +01:00
Oswald Buddenhagen
c4824c8f38 fix CVE-2013-0289: add SSL subject verification
we did not check a valid certificate's subject at all so far.
this is no problem if the certificate file contains only exactly the
wanted host's certificate - before revision 04fdf7d1 (dec 2000, < v0.4),
this was even enforced (more or less - if the peer cert had been
signed directly by a root cert, it would be accepted as well).
however, when the file contains root certificates (like the system-wide
certificate file typically does), any host with a valid certificate
could pretend to be the wanted host.
2013-02-17 18:32:18 +01:00
Oswald Buddenhagen
9f1320ff0c disable debian stuff when shadow-building
the stuff needs to be run in the source dir and modifies it, which is a
bit against the idea of a shadow build.
fixes "make distcheck".
2012-04-28 12:10:30 +02:00
Oswald Buddenhagen
e895cd11f7 cvsignore => gitignore
(cherry picked from commit 4729b1ee23)
2012-04-28 11:38:14 +02:00
Oswald Buddenhagen
b6ae600419 adjust ChangeLog generation to git
now that log generation is cheap, don't store it in the SCM any more.
(cherry picked from commit 474ce08b3a)
2012-04-28 11:36:22 +02:00
Oswald Buddenhagen
2074a7ab03 backport: memmove for overlapping mem copies. 2011-11-29 22:40:39 +01:00
Oswald Buddenhagen
1af2cfde4f fix UIDNEXT handling
UIDNEXT *can* be legally zero, so deal with it.

-REFMAIL: 4CA62BA1.4020104@lemma.co.uk
2010-10-03 14:34:16 +02:00
Oswald Buddenhagen
2d5a73c55d don't hang after failed start_tls()
we'd send a LOGOUT command in plain text while the server was already
expecting an encrypted command, which would typically lead to waiting
for more data and thus an indefinite hang.
so close the socket immediately instead of letting the normal shutdown
path take care of it.
inspired by a patch by Steven Flintham.

-REFMAIL: 4C9AB98E.3000400@lemma.co.uk
2010-10-03 12:05:40 +02:00
Oswald Buddenhagen
608a2863e0 handle failure to store message. this helps with invalid messages like
0-byte files after crashes.
2009-03-21 16:05:51 +00:00
Oswald Buddenhagen
b546877d70 bump version 2009-03-21 14:11:07 +00:00
Oswald Buddenhagen
d47cca7dd9 backport: deal with UIDVALIDITY of 0 properly.
CCMAIL: skinner@destiny-denied.co.uk
-REF: 20080822094543.GA3528@ugly.local
2008-08-23 07:55:15 +00:00
Oswald Buddenhagen
d2ccc93584 backport: give the implicitly created imap account config the name of
the store.
2008-04-13 09:57:27 +00:00
Oswald Buddenhagen
dff2f6a9f5 backport: compat wrapper: don't crash if neither host nor tunnel are
specified.
2008-02-23 14:19:13 +00:00
Oswald Buddenhagen
5e43508aec bump version 2008-02-23 09:41:19 +00:00
Oswald Buddenhagen
8616ed393d regen 2008-02-23 09:39:10 +00:00
Oswald Buddenhagen
6636d7ebb7 backport: quote user name in generated config. 2008-02-23 09:38:00 +00:00
Oswald Buddenhagen
e161af47bb backport: don't overlook 2nd and later single-letter options in last
argument.
2008-02-23 09:22:06 +00:00
Oswald Buddenhagen
1b9b5f8bfd backport: put pointers to bdb open() into parentheses, so they won't be
macro-expanded as libc open.
2008-02-23 09:03:22 +00:00
Oswald Buddenhagen
5d03247bec backport: don't use #ifdef inside htons() arguments - it can be a macro. 2007-09-22 08:49:05 +00:00
Oswald Buddenhagen
0d27c5f4cb avoid crash in case of a rather weird (==misconfigured?) sync state
location.
2007-04-04 17:55:13 +00:00
Oswald Buddenhagen
0eb399c672 accept empty SEARCH IMAP responses - reasonable servers omit them
alltogether, but this is allowed, too. patch by
CCMAIL: Alexander Gerasiov <gq@cs.msu.su>
fixes debian bug #413336

fixed in HEAD a year ago - accidentally ...
2007-04-04 13:27:24 +00:00
Oswald Buddenhagen
9a0539868a backport: fix crash due to uninited var when parsing IMAPServer.
-REF: <E1HFuIM-00041h-Nn@sc8-pr-cvs2.sourceforge.net>
2007-02-10 15:41:32 +00:00
Oswald Buddenhagen
43f23fb180 backport: reverse-map <Inbox> to INBOX when encountered during listing. 2006-11-18 13:17:31 +00:00
Oswald Buddenhagen
d51a91aeba backport: make compat wrapper default to current user for imap login 2006-11-09 18:01:27 +00:00
Oswald Buddenhagen
f7ba199d35 re-gen 2006-11-03 13:06:01 +00:00
Oswald Buddenhagen
a54459af1c add target for creating signed package 2006-11-03 13:05:34 +00:00
Oswald Buddenhagen
3759f0c802 backport:
- un-document "Host imaps:[...]" syntax and introduce new option UseIMAPS
  instead
- apply ted's patch to support UseIMAPS in conjunction with Tunnel
- document that SSLv2 is No Good (TM)
2006-11-01 07:19:26 +00:00
Oswald Buddenhagen
6494cfc438 backport: move assigning default port to the place of use 2006-11-01 07:14:50 +00:00
Oswald Buddenhagen
afc48600fa bump version 2006-11-01 06:33:37 +00:00
Oswald Buddenhagen
4b70d9b96c backport: put INBOX in Maildir 2006-11-01 06:20:56 +00:00
Oswald Buddenhagen
41c4e0d681 backport: don't crash on truncating db 2006-10-24 17:39:24 +00:00
Oswald Buddenhagen
b6c6299ea6 another attempt at working around glibc breakage. 2006-07-31 05:31:17 +00:00
Oswald Buddenhagen
2e39fa9930 work around glibc bug: printf("%.*s", INT_MAX, s) tries to allocate 2G. 2006-07-29 11:53:47 +00:00
Oswald Buddenhagen
927feae988 make config parsing more robust against bogus input and report errors
more clearly.
2006-03-19 10:46:33 +00:00
Oswald Buddenhagen
3f1009a839 regen 2006-01-31 16:17:18 +00:00
Oswald Buddenhagen
fd3f4f33ff bump version 2006-01-31 15:45:15 +00:00
Oswald Buddenhagen
314287cbb4 backport: deal with branches in "make log" 2006-01-31 15:21:35 +00:00
Oswald Buddenhagen
b40fb7f281 backport: fix 'isync -w' writing .mbsyncrc to a wrong directory 2006-01-31 15:17:43 +00:00
Oswald Buddenhagen
534ccb326a backport: less confusing uid ranges in debug 2006-01-31 15:16:27 +00:00
Oswald Buddenhagen
63c065a127 backport: compile fixes 2006-01-31 15:15:00 +00:00
Oswald Buddenhagen
161a4b1159 backport:
- sanitize flag handling of expired messages
- don't record we synced flags if we didn't
- remove now superfluous temporary rflags
2006-01-31 15:12:34 +00:00
Oswald Buddenhagen
9a5920c028 backport: flush debug output 2006-01-31 14:25:18 +00:00
17 changed files with 335 additions and 1585 deletions

View file

@ -1,4 +1,6 @@
.autoconf_trace
ChangeLog
INSTALL
Makefile
Makefile.in
autom4te.cache
@ -14,9 +16,13 @@ config.sub
configure
configure.lineno
configure-stamp
depcomp
install-sh
isync.spec
isync-*.tar.gz
missing
patch-stamp
stamp-h
stamp-h.in
stamp-h1
*~

1445
ChangeLog

File diff suppressed because it is too large Load diff

View file

@ -2,11 +2,59 @@ SUBDIRS = src
bin_SCRIPTS = get-cert
EXTRA_DIST = debian isync.spec $(bin_SCRIPTS)
log:
@perl -p -e "s/^(\\S+)\\s+(\\S.+\\S)\\s+(\\S+)\\s*\$$/\$$1:'\$$2 <\$$3>'\\n/" < ../CVSROOT/accounts > .usermap
cvs2cl -U .usermap --no-wrap --separate-header -I ChangeLog -I NEWS -I TODO -I debian/
@rm -f .usermap ChangeLog.bak
LOG_PL = \
use POSIX qw(strftime); \
use Date::Parse; \
use Text::Wrap; \
$$Text::Wrap::columns = 72; \
while (defined($$_ = <>)) { \
/^commit / or die "commit missing: $$_"; \
<> =~ /^log size (\d+)$$/ or die "wrong size"; \
$$len = $$1; \
read(STDIN, $$log, $$len) == $$len or die "unexpected EOF"; \
$$log =~ s/^Author: ([^>]+>)\nDate: (\d{4}-\d\d-\d\d \d\d:\d\d:\d\d [-+]\d{4})\n(.*)$$/$$3/s or die "unexpected log format"; \
$$author = $$1; $$date = str2time($$2); \
scalar(<>); \
@files = (); \
$$pfx = ""; \
while (defined($$l = <>) and $$l ne "\n") { \
chomp $$l; \
next if ($$l =~ m,^(ChangeLog$$|NEWS$$|TODO$$|debian/),); \
if (!@files) { \
$$pfx = $$l; \
$$pfx =~ s,/?[^/]+$$,,; \
} else { \
while (length($$pfx)) { \
$$l =~ m,^\Q$$pfx/\E, and last; \
$$pfx =~ s,/?[^/]+$$,,; \
} \
} \
push @files, $$l; \
} \
next if (!@files); \
print strftime("%F %H:%M", gmtime($$date))." ".$$author."\n\n"; \
if (@files > 1 and ($$len = length($$pfx))) { \
@efiles = (); \
for $$f (@files) { push @efiles, substr($$f, $$len + 1); } \
$$fstr = $$pfx."/: "; \
} else { \
@efiles = @files; \
$$fstr = ""; \
} \
print wrap("\t* ", "\t ", $$fstr.join(", ", @efiles).":")."\n"; \
$$log =~ s, +$$,,gm; \
$$log =~ s,^ ,\t,gm; \
print $$log."\n"; \
}
$(srcdir)/ChangeLog: log
log:
@test -z "$(srcdir)" || cd $(srcdir) && \
( ! test -d .git || \
git log --date=iso --log-size --name-only | \
perl -e '$(LOG_PL)' > ChangeLog )
if in_source_build
deb:
CFLAGS="-O2 -mcpu=i686" fakeroot debian/rules binary
@ -17,7 +65,11 @@ deb-clean:
distdir distclean: deb-clean
dist-hook:
find $(distdir)/debian \( -name CVS -o -name .cvsignore -o -name .#\*# -o -type l \) -print0 | xargs -0r rm -rf
find $(distdir)/debian \( -name .git -o -name .gitignore -o -name .#\*# -o -type l \) -print0 | xargs -0r rm -rf
endif
dist-sign: dist
gpg -b -a $(PACKAGE)-$(VERSION).tar.gz
rpm:
make dist

View file

@ -1,5 +1,6 @@
#! /bin/sh
set -e -v
make -f Makefile.am log
aclocal
autoheader
automake --add-missing

View file

@ -1,6 +1,6 @@
AC_INIT(src/isync.h)
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(isync, 1.0.1)
AM_INIT_AUTOMAKE(isync, 1.0.6)
AM_MAINTAINER_MODE
@ -9,6 +9,7 @@ if test "$GCC" = yes; then
CFLAGS="$CFLAGS -pipe -W -Wall -Wshadow -Wstrict-prototypes"
fi
AC_CHECK_HEADERS([sys/filio.h])
AC_CHECK_FUNCS(vasprintf)
AC_CHECK_LIB(socket, socket, [SOCK_LIBS="-lsocket"])
@ -93,6 +94,8 @@ if test "x$ob_cv_enable_compat" != xno; then
fi
AM_CONDITIONAL(with_compat, test "x$ob_cv_enable_compat" != xno)
AM_CONDITIONAL(in_source_build, test "x$srcdir" = x.)
AC_OUTPUT(Makefile src/Makefile src/compat/Makefile isync.spec)
if test -n "$have_ssl_paths"; then

View file

@ -3,3 +3,4 @@ Makefile
Makefile.in
mbsync
mdconvert
*.o

View file

@ -2,3 +2,4 @@
Makefile
Makefile.in
isync
*.o

View file

@ -250,8 +250,9 @@ write_imap_server( FILE *fp, config_t *cfg )
cfg->server_name, cfg->tunnel );
} else {
if (sscanf( cfg->host, "%d.%d.%d.%d", &a1, &a2, &a3, &a4 ) == 4)
/* XXX this does not avoid clashes. add port? */
cfg->server_name = nfstrdup( cfg->host );
else {
else if (cfg->host) {
p = strrchr( cfg->host, '.' );
if (!p)
hl = nfsnprintf( buf, sizeof(buf), "%s", cfg->host );
@ -270,6 +271,9 @@ write_imap_server( FILE *fp, config_t *cfg )
cfg->server_name = nfstrdup( buf );
cfg->servers = 1;
gotsrv: ;
} else {
fprintf( stderr, "ERROR: Neither host nor tunnel specified for mailbox %s.\n", cfg->path );
exit( 1 );
}
fprintf( fp, "IMAPAccount %s\n", cfg->server_name );
if (cfg->use_imaps)
@ -279,7 +283,7 @@ write_imap_server( FILE *fp, config_t *cfg )
fprintf( fp, "Port %d\n", cfg->port );
}
if (cfg->user)
fprintf( fp, "User %s\n", cfg->user );
fprintf( fp, "User \"%s\"\n", cfg->user );
if (cfg->pass)
fprintf( fp, "Pass \"%s\"\n", cfg->pass );
fprintf( fp, "RequireCRAM %s\nRequireSSL %s\n"
@ -350,7 +354,8 @@ write_config( int fd )
fprintf( fp, "SyncState *\n\n" );
if (local_home || o2o)
fprintf( fp, "MaildirStore local\nPath \"%s/\"\nAltMap %s\n\n", maildir, tb( altmap > 0 ) );
fprintf( fp, "MaildirStore local\nPath \"%s/\"\nInbox \"%s/INBOX\"\nAltMap %s\n\n",
maildir, maildir, tb( altmap > 0 ) );
if (local_root)
fprintf( fp, "MaildirStore local_root\nPath /\nAltMap %s\n\n", tb( altmap > 0 ) );
if (o2o) {

View file

@ -73,7 +73,7 @@ convert( config_t *box )
FILE *fp;
msg_t *msgs;
DB *db;
int i, ret, fd, uidval, maxuid, bl, uid, rmsgs, nmsgs, uv[2];
int i, ret, fd, uidval, maxuid, uid, rmsgs, nmsgs, uv[2];
unsigned u;
struct stat sb;
char buf[_POSIX_PATH_MAX], diumname[_POSIX_PATH_MAX],
@ -145,7 +145,7 @@ convert( config_t *box )
fputs( "dbcreate failed\n", stderr );
goto err2;
}
if (db->open( db, 0, iumname, 0, DB_HASH, 0, 0 )) {
if ((db->open)( db, 0, iumname, 0, DB_HASH, 0, 0 )) {
fputs( "cannot open db\n", stderr );
db->close( db, 0 );
goto err2;
@ -160,7 +160,7 @@ convert( config_t *box )
rmsgs = 0;
nmsgs = 0;
for (i = 0; i < 2; i++) {
bl = nfsnprintf( buf, sizeof(buf), "%s/%s/", mboxdir, subdirs[i] );
nfsnprintf( buf, sizeof(buf), "%s/%s/", mboxdir, subdirs[i] );
if (!(d = opendir( buf ))) {
perror( "opendir" );
err4:

View file

@ -22,6 +22,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
@ -33,7 +34,7 @@
#include <ctype.h>
#include <dirent.h>
#if HAVE_GETOPT_LONG
#ifdef HAVE_GETOPT_LONG
# define _GNU_SOURCE
# include <getopt.h>
struct option Opts[] = {
@ -167,6 +168,11 @@ main( int argc, char **argv )
/* defaults */
/* XXX the precedence is borked:
it's defaults < cmdline < file instead of defaults < file < cmdline */
#ifdef BSD
global.user = getenv( "USER" );
#else
global.user = getenv( "LOGNAME" );
#endif
global.port = 143;
global.box = "INBOX";
global.use_namespace = 1;
@ -179,7 +185,7 @@ main( int argc, char **argv )
#define FLAGS "wW:alCLRc:defhp:qu:r:F:M:1I:s:vVD"
mod = all = list = ops = writeout = Quiet = Verbose = Debug = 0;
#if HAVE_GETOPT_LONG
#ifdef HAVE_GETOPT_LONG
while ((i = getopt_long( argc, argv, FLAGS, Opts, NULL )) != -1)
#else
while ((i = getopt( argc, argv, FLAGS )) != -1)
@ -244,7 +250,7 @@ main( int argc, char **argv )
mod = 1;
break;
case 's':
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
if (!strncasecmp( "imaps:", optarg, 6 )) {
global.use_imaps = 1;
global.port = 993;
@ -331,8 +337,8 @@ main( int argc, char **argv )
while ((de = readdir( dir ))) {
if (*de->d_name == '.')
continue;
nfsnprintf( path1, sizeof(path1), "%s/%s/cur", xmaildir, de->d_name );
if (stat( path1, &st ) || !S_ISDIR( st.st_mode ))
nfsnprintf( path2, sizeof(path2), "%s/%s/cur", xmaildir, de->d_name );
if (stat( path2, &st ) || !S_ISDIR( st.st_mode ))
continue;
global.path = de->d_name;
global.box = (inbox && !strcmp( inbox, global.path )) ?

View file

@ -31,19 +31,24 @@
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_FILIO_H
# include <sys/filio.h>
#endif
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
# include <openssl/ssl.h>
# include <openssl/err.h>
# include <openssl/hmac.h>
# include <openssl/x509v3.h>
#endif
typedef struct imap_server_conf {
@ -54,7 +59,7 @@ typedef struct imap_server_conf {
int port;
char *user;
char *pass;
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
char *cert_file;
unsigned use_imaps:1;
unsigned require_ssl:1;
@ -87,7 +92,7 @@ typedef struct _list {
typedef struct {
int fd;
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
SSL *ssl;
unsigned int use_ssl:1;
#endif
@ -112,7 +117,7 @@ typedef struct imap {
/* command queue */
int nexttag, num_in_progress, literal_pending;
struct imap_cmd *in_progress, **in_progress_append;
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
SSL_CTX *SSLContext;
#endif
buffer_t buf; /* this is BIG, so put it last */
@ -149,7 +154,7 @@ enum CAPABILITY {
UIDPLUS,
LITERALPLUS,
NAMESPACE,
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
CRAM,
STARTTLS,
#endif
@ -160,7 +165,7 @@ static const char *cap_list[] = {
"UIDPLUS",
"LITERAL+",
"NAMESPACE",
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
"AUTH=CRAM-MD5",
"STARTTLS",
#endif
@ -181,11 +186,67 @@ static const char *Flags[] = {
"Deleted",
};
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
static int
host_matches( const char *host, const char *pattern )
{
if (pattern[0] == '*' && pattern[1] == '.') {
pattern += 2;
if (!(host = strchr( host, '.' )))
return 0;
host++;
}
return *host && *pattern && !strcasecmp( host, pattern );
}
static int
verify_hostname( X509 *cert, const char *hostname )
{
int i, len, found;
X509_NAME *subj;
STACK_OF(GENERAL_NAME) *subj_alt_names;
char cname[1000];
/* try the DNS subjectAltNames */
found = 0;
if ((subj_alt_names = X509_get_ext_d2i( cert, NID_subject_alt_name, NULL, NULL ))) {
int num_subj_alt_names = sk_GENERAL_NAME_num( subj_alt_names );
for (i = 0; i < num_subj_alt_names; i++) {
GENERAL_NAME *subj_alt_name = sk_GENERAL_NAME_value( subj_alt_names, i );
if (subj_alt_name->type == GEN_DNS &&
strlen( (const char *)subj_alt_name->d.ia5->data ) == (size_t)subj_alt_name->d.ia5->length &&
host_matches( hostname, (const char *)(subj_alt_name->d.ia5->data) ))
{
found = 1;
break;
}
}
sk_GENERAL_NAME_pop_free( subj_alt_names, GENERAL_NAME_free );
}
if (found)
return 0;
/* try the common name */
if (!(subj = X509_get_subject_name( cert ))) {
fprintf( stderr, "Error, cannot get certificate subject\n" );
return -1;
}
if ((len = X509_NAME_get_text_by_NID( subj, NID_commonName, cname, sizeof(cname) )) < 0) {
fprintf( stderr, "Error, cannot get certificate common name\n" );
return -1;
}
if (strlen( cname ) == (size_t)len && host_matches( hostname, cname ))
return 0;
fprintf( stderr, "Error, certificate owner does not match hostname %s\n", hostname );
return -1;
}
/* this gets called when a certificate is to be verified */
static int
verify_cert( SSL *ssl )
verify_cert( SSL *ssl, const char *hostname )
{
X509 *cert;
int err;
@ -200,12 +261,16 @@ verify_cert( SSL *ssl )
}
err = SSL_get_verify_result( ssl );
if (err == X509_V_OK)
return 0;
fprintf( stderr, "Error, can't verify certificate: %s (%d)\n",
X509_verify_cert_error_string(err), err );
if (err != X509_V_OK) {
fprintf( stderr, "Error, can't verify certificate: %s (%d)\n",
X509_verify_cert_error_string(err), err );
goto intcheck;
}
if (hostname && verify_hostname( cert, hostname ) < 0)
goto intcheck;
return 0;
intcheck:
X509_NAME_oneline( X509_get_subject_name( cert ), buf, sizeof(buf) );
info( "\nSubject: %s\n", buf );
X509_NAME_oneline( X509_get_issuer_name( cert ), buf, sizeof(buf) );
@ -238,7 +303,7 @@ init_ssl_ctx( imap_store_t *ctx )
imap_t *imap = ctx->imap;
imap_store_conf_t *conf = (imap_store_conf_t *)ctx->gen.conf;
imap_server_conf_t *srvc = conf->server;
SSL_METHOD *method;
const SSL_METHOD *method;
int options = 0;
if (srvc->use_tlsv1 && !srvc->use_sslv2 && !srvc->use_sslv3)
@ -250,11 +315,9 @@ init_ssl_ctx( imap_store_t *ctx )
if (!srvc->cert_file) {
fprintf( stderr, "Error, CertificateFile not defined\n" );
return -1;
} else if (access( srvc->cert_file, R_OK ))
warn( "*** Warning: can't read CertificateFile, so can't verify server certificates\n" );
else if (!SSL_CTX_load_verify_locations( imap->SSLContext, srvc->cert_file, NULL )) {
fprintf( stderr, "Error, SSL_CTX_load_verify_locations: %s\n",
ERR_error_string( ERR_get_error(), 0 ) );
} else if (!SSL_CTX_load_verify_locations( imap->SSLContext, srvc->cert_file, NULL )) {
fprintf( stderr, "Error while loading certificate file '%s': %s\n",
srvc->cert_file, ERR_error_string( ERR_get_error(), 0 ) );
return -1;
}
@ -276,7 +339,7 @@ init_ssl_ctx( imap_store_t *ctx )
static void
socket_perror( const char *func, Socket_t *sock, int ret )
{
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
int err;
if (sock->use_ssl) {
@ -310,7 +373,7 @@ static int
socket_read( Socket_t *sock, char *buf, int len )
{
int n =
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
sock->use_ssl ? SSL_read( sock->ssl, buf, len ) :
#endif
read( sock->fd, buf, len );
@ -326,7 +389,7 @@ static int
socket_write( Socket_t *sock, char *buf, int len )
{
int n =
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
sock->use_ssl ? SSL_write( sock->ssl, buf, len ) :
#endif
write( sock->fd, buf, len );
@ -347,7 +410,7 @@ socket_pending( Socket_t *sock )
return -1;
if (num > 0)
return num;
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
if (sock->use_ssl)
return SSL_pending( sock->ssl );
#endif
@ -374,7 +437,7 @@ buffer_gets( buffer_t * b, char **s )
n = b->bytes - start;
if (n)
memcpy( b->buf, b->buf + start, n );
memmove( b->buf, b->buf + start, n );
b->offset -= start;
b->bytes = n;
start = 0;
@ -815,7 +878,7 @@ static int
parse_response_code( imap_store_t *ctx, struct imap_cmd_cb *cb, char *s )
{
imap_t *imap = ctx->imap;
char *arg, *p;
char *arg, *earg, *p;
if (*s != '[')
return RESP_OK; /* no response code */
@ -827,12 +890,14 @@ parse_response_code( imap_store_t *ctx, struct imap_cmd_cb *cb, char *s )
*p++ = 0;
arg = next_arg( &s );
if (!strcmp( "UIDVALIDITY", arg )) {
if (!(arg = next_arg( &s )) || !(ctx->gen.uidvalidity = atoi( arg ))) {
if (!(arg = next_arg( &s )) ||
(ctx->gen.uidvalidity = strtoll( arg, &earg, 10 ), *earg))
{
fprintf( stderr, "IMAP error: malformed UIDVALIDITY status\n" );
return RESP_BAD;
}
} else if (!strcmp( "UIDNEXT", arg )) {
if (!(arg = next_arg( &s )) || !(imap->uidnext = atoi( arg ))) {
if (!(arg = next_arg( &s )) || (imap->uidnext = strtol( arg, &p, 10 ), *p)) {
fprintf( stderr, "IMAP error: malformed NEXTUID status\n" );
return RESP_BAD;
}
@ -845,7 +910,8 @@ parse_response_code( imap_store_t *ctx, struct imap_cmd_cb *cb, char *s )
for (; isspace( (unsigned char)*p ); p++);
fprintf( stderr, "*** IMAP ALERT *** %s\n", p );
} else if (cb && cb->ctx && !strcmp( "APPENDUID", arg )) {
if (!(arg = next_arg( &s )) || !(ctx->gen.uidvalidity = atoi( arg )) ||
if (!(arg = next_arg( &s )) ||
(ctx->gen.uidvalidity = strtoll( arg, &earg, 10 ), *earg) ||
!(arg = next_arg( &s )) || !(*(int *)cb->ctx = atoi( arg )))
{
fprintf( stderr, "IMAP error: malformed APPENDUID status\n" );
@ -863,7 +929,9 @@ parse_search( imap_t *imap, char *cmd )
int uid;
arg = next_arg( &cmd );
if (!arg || !(uid = atoi( arg ))) {
if (!arg)
return;
if (!(uid = atoi( arg ))) {
fprintf( stderr, "IMAP error: malformed SEARCH response\n" );
return;
}
@ -1096,7 +1164,7 @@ start_tls( imap_store_t *ctx )
}
/* verify the server certificate */
if (verify_cert( imap->buf.sock.ssl ))
if (verify_cert( imap->buf.sock.ssl, ((imap_store_conf_t *)ctx->gen.conf)->server->host ))
return 1;
imap->buf.sock.use_ssl = 1;
@ -1192,7 +1260,7 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
struct hostent *he;
struct sockaddr_in addr;
int s, a[2], preauth;
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
int use_ssl;
#endif
@ -1212,7 +1280,7 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
imap->in_progress_append = &imap->in_progress;
/* open connection to IMAP server */
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
use_ssl = 0;
#endif
@ -1240,7 +1308,11 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
info( "ok\n" );
} else {
memset( &addr, 0, sizeof(addr) );
addr.sin_port = htons( srvc->port );
addr.sin_port = srvc->port ? htons( srvc->port ) :
#ifdef HAVE_LIBSSL
srvc->use_imaps ? htons( 993 ) :
#endif
htons( 143 );
addr.sin_family = AF_INET;
info( "Resolving %s... ", srvc->host );
@ -1264,16 +1336,16 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
info( "ok\n" );
imap->buf.sock.fd = s;
#if HAVE_LIBSSL
if (srvc->use_imaps) {
if (start_tls( ctx ))
goto bail;
use_ssl = 1;
}
#endif
}
#ifdef HAVE_LIBSSL
if (srvc->use_imaps) {
if (start_tls( ctx ))
goto ssl_bail;
use_ssl = 1;
}
#endif
/* read the greeting string */
if (buffer_gets( &imap->buf, &rsp )) {
fprintf( stderr, "IMAP error: no greeting response\n" );
@ -1296,14 +1368,14 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
goto bail;
if (!preauth) {
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
if (!srvc->use_imaps && (srvc->use_sslv2 || srvc->use_sslv3 || srvc->use_tlsv1)) {
/* always try to select SSL support if available */
if (CAP(STARTTLS)) {
if (imap_exec( ctx, 0, "STARTTLS" ) != RESP_OK)
goto bail;
if (start_tls( ctx ))
goto bail;
goto ssl_bail;
use_ssl = 1;
if (imap_exec( ctx, 0, "CAPABILITY" ) != RESP_OK)
@ -1341,7 +1413,7 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
*/
srvc->pass = nfstrdup( arg );
}
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
if (CAP(CRAM)) {
struct imap_cmd_cb cb;
@ -1360,7 +1432,7 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
fprintf( stderr, "Skipping account %s@%s, server forbids LOGIN\n", srvc->user, srvc->host );
goto bail;
}
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
if (!use_ssl)
#endif
warn( "*** IMAP Warning *** Password is being sent in the clear\n" );
@ -1388,6 +1460,12 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
ctx->trashnc = 1;
return (store_t *)ctx;
#ifdef HAVE_LIBSSL
ssl_bail:
/* This avoids that we try to send LOGOUT to an unusable socket. */
close( imap->buf.sock.fd );
imap->buf.sock.fd = -1;
#endif
bail:
imap_close_store( &ctx->gen );
return 0;
@ -1420,6 +1498,8 @@ imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
prefix = ctx->prefix;
}
imap->uidnext = -1;
memset( &cb, 0, sizeof(cb) );
cb.create = (gctx->opts & OPEN_CREATE) != 0;
cb.trycreate = 1;
@ -1445,7 +1525,7 @@ imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
goto bail;
}
if (maxuid == INT_MAX)
maxuid = imap->uidnext ? imap->uidnext - 1 : 1000000000;
maxuid = imap->uidnext >= 0 ? imap->uidnext - 1 : 1000000000;
if (maxuid >= minuid &&
(ret = imap_exec_b( ctx, 0, "UID FETCH %d:%d (UID%s%s)", minuid, maxuid,
(gctx->opts & OPEN_FLAGS) ? " FLAGS" : "",
@ -1575,6 +1655,7 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
}
/* invalid message */
free( fmap );
fprintf( stderr, "IMAP warning: storing message with incomplete header.\n" );
return DRV_MSG_BAD;
mktid:
for (j = 0; j < TUIDL; j++)
@ -1691,6 +1772,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep, int *err )
{
imap_store_conf_t *store;
imap_server_conf_t *server, *srv, sserver;
int acc_opt = 0;
if (!strcasecmp( "IMAPAccount", cfg->cmd )) {
server = nfcalloc( sizeof(*server) );
@ -1698,17 +1780,19 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep, int *err )
*serverapp = server;
serverapp = &server->next;
store = 0;
*storep = 0;
} else if (!strcasecmp( "IMAPStore", cfg->cmd )) {
store = nfcalloc( sizeof(*store) );
store->gen.driver = &imap_driver;
store->gen.name = nfstrdup( cfg->val );
store->use_namespace = 1;
*storep = &store->gen;
memset( &sserver, 0, sizeof(sserver) );
server = &sserver;
} else
return 0;
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
/* this will probably annoy people, but its the best default just in
* case people forget to turn it on
*/
@ -1717,32 +1801,19 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep, int *err )
#endif
while (getcline( cfg ) && cfg->cmd) {
if (!strcasecmp( "Account", cfg->cmd )) {
for (srv = servers; srv; srv = srv->next)
if (srv->name && !strcmp( srv->name, cfg->val ))
goto gotsrv;
fprintf( stderr, "%s:%d: unknown IMAP account '%s'\n",
cfg->file, cfg->line, cfg->val );
*err = 1;
continue;
gotsrv:
store->server = srv;
} else if (!strcasecmp( "Host", cfg->cmd )) {
#if HAVE_LIBSSL
if (!strcasecmp( "Host", cfg->cmd )) {
/* The imap[s]: syntax is just a backwards compat hack. */
#ifdef HAVE_LIBSSL
if (!memcmp( "imaps:", cfg->val, 6 )) {
cfg->val += 6;
server->use_imaps = 1;
server->use_sslv2 = 1;
server->use_sslv3 = 1;
if (!server->port)
server->port = 993;
} else
#endif
{
if (!memcmp( "imap:", cfg->val, 5 ))
cfg->val += 5;
if (!server->port)
server->port = 143;
}
if (!memcmp( "//", cfg->val, 2 ))
cfg->val += 2;
@ -1754,11 +1825,18 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep, int *err )
server->pass = nfstrdup( cfg->val );
else if (!strcasecmp( "Port", cfg->cmd ))
server->port = parse_int( cfg );
#if HAVE_LIBSSL
else if (!strcasecmp( "CertificateFile", cfg->cmd ))
#ifdef HAVE_LIBSSL
else if (!strcasecmp( "CertificateFile", cfg->cmd )) {
server->cert_file = expand_strdup( cfg->val );
else if (!strcasecmp( "RequireSSL", cfg->cmd ))
if (access( server->cert_file, R_OK )) {
fprintf( stderr, "%s:%d: CertificateFile '%s': %s\n",
cfg->file, cfg->line, server->cert_file, strerror( errno ) );
*err = 1;
}
} else if (!strcasecmp( "RequireSSL", cfg->cmd ))
server->require_ssl = parse_bool( cfg );
else if (!strcasecmp( "UseIMAPS", cfg->cmd ))
server->use_imaps = parse_bool( cfg );
else if (!strcasecmp( "UseSSLv2", cfg->cmd ))
server->use_sslv2 = parse_bool( cfg );
else if (!strcasecmp( "UseSSLv3", cfg->cmd ))
@ -1771,34 +1849,50 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep, int *err )
else if (!strcasecmp( "Tunnel", cfg->cmd ))
server->tunnel = nfstrdup( cfg->val );
else if (store) {
if (!strcasecmp( "UseNamespace", cfg->cmd ))
if (!strcasecmp( "Account", cfg->cmd )) {
for (srv = servers; srv; srv = srv->next)
if (srv->name && !strcmp( srv->name, cfg->val ))
goto gotsrv;
fprintf( stderr, "%s:%d: unknown IMAP account '%s'\n",
cfg->file, cfg->line, cfg->val );
*err = 1;
continue;
gotsrv:
store->server = srv;
} else if (!strcasecmp( "UseNamespace", cfg->cmd ))
store->use_namespace = parse_bool( cfg );
else if (!strcasecmp( "Path", cfg->cmd ))
store->gen.path = nfstrdup( cfg->val );
else
parse_generic_store( &store->gen, cfg, err );
continue;
} else {
fprintf( stderr, "%s:%d: unknown keyword '%s'\n",
fprintf( stderr, "%s:%d: unknown/misplaced keyword '%s'\n",
cfg->file, cfg->line, cfg->cmd );
*err = 1;
continue;
}
acc_opt = 1;
}
if (!store || !store->server) {
if (!server->tunnel && !server->host) {
if (store)
fprintf( stderr, "IMAP store '%s' has incomplete connection details\n", store->gen.name );
fprintf( stderr, "IMAP store '%s' has incomplete/missing connection details\n", store->gen.name );
else
fprintf( stderr, "IMAP account '%s' has incomplete connection details\n", server->name );
fprintf( stderr, "IMAP account '%s' has incomplete/missing connection details\n", server->name );
*err = 1;
/* leaking server/store */
*storep = 0;
return 1;
}
}
*storep = &store->gen;
if (store && !store->server) {
store->server = nfmalloc( sizeof(sserver) );
memcpy( store->server, &sserver, sizeof(sserver) );
if (store) {
if (!store->server) {
store->server = nfmalloc( sizeof(sserver) );
memcpy( store->server, &sserver, sizeof(sserver) );
store->server->name = store->gen.name;
} else if (acc_opt) {
fprintf( stderr, "IMAP store '%s' has both Account and account-specific options\n", store->gen.name );
*err = 1;
}
}
return 1;
}

View file

@ -161,15 +161,17 @@ maildir_list( store_t *gctx, string_list_t **retb )
}
*retb = 0;
while ((de = readdir( dir ))) {
const char *inbox = ((maildir_store_conf_t *)gctx->conf)->inbox;
int bl;
struct stat st;
char buf[PATH_MAX];
if (*de->d_name == '.')
continue;
nfsnprintf( buf, sizeof(buf), "%s%s/cur", gctx->conf->path, de->d_name );
bl = nfsnprintf( buf, sizeof(buf), "%s%s/cur", gctx->conf->path, de->d_name );
if (stat( buf, &st ) || !S_ISDIR(st.st_mode))
continue;
add_string_list( retb, de->d_name );
add_string_list( retb, !memcmp( buf, inbox, bl - 4 ) && !inbox[bl - 4] ? "INBOX" : de->d_name );
}
closedir (dir);
@ -345,7 +347,8 @@ maildir_init_uid( maildir_store_t *ctx, const char *msg )
ctx->uvok = 0;
#ifdef USE_DB
if (ctx->db) {
ctx->db->truncate( ctx->db, 0, 0 /* &u_int32_t_dummy */, 0 );
u_int32_t count;
ctx->db->truncate( ctx->db, 0, &count, 0 );
return maildir_set_uid( ctx, 0, 0 );
}
#endif /* USE_DB */
@ -475,7 +478,7 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
DBC *dbc;
#endif /* USE_DB */
msg_t *entry;
int i, j, uid, bl, ml, fnl, ret;
int i, j, uid, bl, fnl, ret;
struct stat st;
char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX];
@ -496,7 +499,7 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
fputs( "Maildir error: db_create() failed\n", stderr );
return DRV_BOX_BAD;
}
if (tdb->open( tdb, 0, 0, 0, DB_HASH, DB_CREATE, 0 )) {
if ((tdb->open)( tdb, 0, 0, 0, DB_HASH, DB_CREATE, 0 )) {
fputs( "Maildir error: tdb->open() failed\n", stderr );
tdb->close( tdb, 0 );
return DRV_BOX_BAD;
@ -637,11 +640,10 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
for (ru = u + 3; isdigit( (unsigned char)*ru ); ru++);
else
u = ru = strchr( entry->base, ':' );
if (u)
ml = u - entry->base;
else
ru = "", ml = INT_MAX;
fnl = nfsnprintf( buf + bl, sizeof(buf) - bl, "%s/%.*s,U=%d%s", subdirs[entry->recent], ml, entry->base, uid, ru ) + 1 - 4;
fnl = (u ?
nfsnprintf( buf + bl, sizeof(buf) - bl, "%s/%.*s,U=%d%s", subdirs[entry->recent], (int)(u - entry->base), entry->base, uid, ru ) :
nfsnprintf( buf + bl, sizeof(buf) - bl, "%s/%s,U=%d", subdirs[entry->recent], entry->base, uid ))
+ 1 - 4;
memcpy( nbuf, buf, bl + 4 );
nfsnprintf( nbuf + bl + 4, sizeof(nbuf) - bl - 4, "%s", entry->base );
if (rename( nbuf, buf )) {
@ -781,7 +783,7 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
fputs( "Maildir error: db_create() failed\n", stderr );
goto bork;
}
if ((ret = ctx->db->open( ctx->db, 0, uvpath, 0, DB_HASH, DB_CREATE, 0 ))) {
if ((ret = (ctx->db->open)( ctx->db, 0, uvpath, 0, DB_HASH, DB_CREATE, 0 ))) {
ctx->db->err( ctx->db, ret, "Maildir error: db->open(%s)", uvpath );
dbork:
ctx->db->close( ctx->db, 0 );

View file

@ -70,7 +70,7 @@ PACKAGE " " VERSION " - mailbox synchronizer\n"
"--create and --expunge can be suffixed with -master/-slave. Read the man page.\n"
"\nSupported mailbox formats are: IMAP4rev1, Maildir\n"
"\nCompile time options:\n"
#if HAVE_LIBSSL
#ifdef HAVE_LIBSSL
" +HAVE_LIBSSL\n"
#else
" -HAVE_LIBSSL\n"
@ -178,8 +178,10 @@ main( int argc, char **argv )
}
arc4_init();
for (oind = 1, ochar = 0; oind < argc; ) {
for (oind = 1, ochar = 0; ; ) {
if (!ochar || !*ochar) {
if (oind >= argc)
break;
if (argv[oind][0] != '-')
break;
if (argv[oind][1] == '-') {

View file

@ -210,17 +210,13 @@ The location of the \fBINBOX\fR. This is \fInot\fR relative to \fBPath\fR.
Define the IMAP4 Account \fIname\fR, opening a section for its parameters.
..
.TP
\fBHost\fR [\fBimaps:\fR]\fIhost\fR
Specify the DNS name or IP address of the IMAP server. If \fIhost\fR is
prefixed with \fBimaps:\fR the connection is assumed to be an SSL connection
to port 993.
Note that modern servers support SSL on the default port 143 via the
STARTTLS extension, which will be used automatically by default.
\fBHost\fR \fIhost\fR
Specify the DNS name or IP address of the IMAP server.
..
.TP
\fBPort\fR \fIport\fR
Specify the TCP port number of the IMAP server. (Default: 143 for imap,
993 for imaps)
Specify the TCP port number of the IMAP server. (Default: 143 for IMAP,
993 for IMAPS)
..
.TP
\fBUser\fR \fIusername\fR
@ -245,6 +241,15 @@ If set to \fIyes\fR, \fBmbsync\fR will abort the connection if no CRAM-MD5
authentication is possible. (Default: \fIno\fR)
..
.TP
\fBUseIMAPS\fR \fIyes\fR|\fIno\fR
If set to \fIyes\fR, the default for \fBPort\fR is changed to 993 and
\fBmbsync\fR will start SSL negotiation immediately after establishing
the connection to the server.
.br
Note that modern servers support SSL on the regular IMAP port 143 via the
STARTTLS extension, which will be used automatically by default.
..
.TP
\fBRequireSSL\fR \fIyes\fR|\fIno\fR
\fBmbsync\fR will abort the connection if a TLS/SSL session cannot be
established with the IMAP server. (Default: \fIyes\fR)
@ -257,12 +262,14 @@ This option is \fImandatory\fR if SSL is used. See \fBSSL CERTIFICATES\fR below.
.TP
\fBUseSSLv2\fR \fIyes\fR|\fIno\fR
Use SSLv2 for communication with the IMAP server over SSL?
(Default: \fIyes\fR if an imaps \fBHost\fR is used, otherwise \fIno\fR)
.br
Note that this option is deprecated for security reasons.
(Default: \fIno\fR)
..
.TP
\fBUseSSLv3\fR \fIyes\fR|\fIno\fR
Use SSLv3 for communication with the IMAP server over SSL?
(Default: \fIyes\fR if an imaps \fBHost\fR is used, otherwise \fIno\fR)
(Default: \fIno\fR)
..
.TP
\fBUseTLSv1\fR \fIyes\fR|\fIno\fR

View file

@ -96,7 +96,7 @@ convert( const char *box, int altmap )
fputs( "Error: db_create() failed\n", stderr );
goto tbork;
}
if ((ret = db->open( db, 0, dbpath, 0, DB_HASH, DB_CREATE, 0 ))) {
if ((ret = (db->open)( db, 0, dbpath, 0, DB_HASH, DB_CREATE, 0 ))) {
db->err( db, ret, "Error: db->open(%s)", dbpath );
dbork:
db->close( db, 0 );
@ -154,7 +154,7 @@ convert( const char *box, int altmap )
if (u)
ml = u - e->d_name;
else
ru = "", ml = INT_MAX;
ru = "", ml = sizeof(buf);
if (altmap) {
if (!p)
continue;

View file

@ -119,7 +119,7 @@ dump_box( store_t *ctx )
if (Debug)
for (msg = ctx->msgs; msg; msg = msg->next) {
make_flags( msg->flags, fbuf );
printf( " message %d, %s, %d\n", msg->uid, fbuf, msg->size );
printf( " message %d, %s, %lu\n", msg->uid, fbuf, msg->size );
}
}
@ -251,7 +251,7 @@ sync_old( int tops, store_t *sctx, store_t *tctx, store_conf_t *tconf, FILE *jfp
{
driver_t *tdriver = tctx->conf->driver, *sdriver = sctx->conf->driver;
int uid, tuid, unex;
unsigned char sflags, aflags, dflags, rflags;
unsigned char sflags, aflags, dflags;
msg_data_t msgdata;
/* excludes (push) c.3) d.2) d.3) d.4) / (pull) b.3) d.7) d.8) d.9) */
@ -301,6 +301,13 @@ sync_old( int tops, store_t *sctx, store_t *tctx, store_conf_t *tconf, FILE *jfp
case DRV_OK:
smsg->flags = msgdata.flags;
switch (tdriver->store_msg( tctx, &msgdata, &uid )) {
case DRV_MSG_BAD:
warn( pull ?
"Warning: Slave refuses to store message %d from master.\n" :
"Warning: Master refuses to store message %d from slave.\n",
smsg->uid );
smsg->status |= M_NOT_SYNCED;
break;
case DRV_STORE_BAD: return pull ? SYNC_SLAVE_BAD : SYNC_MASTER_BAD;
default: return SYNC_FAIL;
case DRV_OK:
@ -332,20 +339,18 @@ sync_old( int tops, store_t *sctx, store_t *tctx, store_conf_t *tconf, FILE *jfp
unex = 0;
if (srec->status & S_EXPIRED) {
if (!pull) {
if (sflags & F_DELETED) {
if (!(sflags & F_FLAGGED))
aflags &= ~F_DELETED;
} else
unex = 1;
if ((aflags & ~F_DELETED) || dflags)
info( "Info: Flags of expired message changed in (%d,%d)\n", srec->muid, srec->suid );
return SYNC_OK;
} else {
if ((sflags & F_FLAGGED) && !(sflags & F_DELETED)) {
unex = 1;
dflags |= F_DELETED;
}
} else
return SYNC_OK;
}
}
rflags = (*nflags | aflags) & ~dflags;
if ((tops & OP_EXPUNGE) && (rflags & F_DELETED) &&
if ((tops & OP_EXPUNGE) && (sflags & F_DELETED) &&
(!tctx->conf->trash || tctx->conf->trash_only_new))
{
aflags &= F_DELETED;
@ -356,7 +361,7 @@ sync_old( int tops, store_t *sctx, store_t *tctx, store_conf_t *tconf, FILE *jfp
case DRV_BOX_BAD: return SYNC_FAIL;
default: /* ok */ break;
case DRV_OK:
*nflags = rflags;
*nflags = (*nflags | aflags) & ~dflags;
if (unex) {
debug( "unexpiring pair(%d,%d)\n", srec->muid, srec->suid );
/* log last, so deletion can't be misinterpreted! */
@ -401,6 +406,13 @@ sync_new( int tops, store_t *sctx, store_t *tctx, store_conf_t *tconf, FILE *jfp
}
msg->flags = msgdata.flags;
switch (tdriver->store_msg( tctx, &msgdata, &uid )) {
case DRV_MSG_BAD:
warn( pull ?
"Warning: Slave refuses to store message %d from master.\n" :
"Warning: Master refuses to store message %d from slave.\n",
msg->uid );
msg->status |= M_NOT_SYNCED;
continue;
case DRV_STORE_BAD: return pull ? SYNC_SLAVE_BAD : SYNC_MASTER_BAD;
default: return SYNC_FAIL;
case DRV_OK: break;
@ -476,7 +488,7 @@ sync_boxes( store_t *mctx, const char *mname,
nmmsg = nsmsg = 0;
mctx->uidvalidity = sctx->uidvalidity = 0;
mctx->uidvalidity = sctx->uidvalidity = -1;
mopts = sopts = 0;
makeopts( chan->sops, chan->slave, &sopts, chan->master, &mopts );
makeopts( chan->mops, chan->master, &mopts, chan->slave, &sopts );
@ -512,7 +524,8 @@ sync_boxes( store_t *mctx, const char *mname,
nfasprintf( &jname, "%s.journal", dname );
nfasprintf( &nname, "%s.new", dname );
nfasprintf( &lname, "%s.lock", dname );
muidval = suidval = smaxxuid = mmaxuid = smaxuid = 0;
muidval = suidval = -1;
smaxxuid = mmaxuid = smaxuid = 0;
memset( &lck, 0, sizeof(lck) );
#if SEEK_SET != 0
lck.l_whence = SEEK_SET;
@ -699,7 +712,7 @@ sync_boxes( store_t *mctx, const char *mname,
} else
maxwuid = 0;
info( "Selecting slave %s... ", sname );
debug( "selecting slave [1,%d]\n", maxwuid );
debug( maxwuid == INT_MAX ? "selecting slave [1,inf]\n" : "selecting slave [1,%d]\n", maxwuid );
switch (sdriver->select( sctx, (sctx->opts & OPEN_OLD) ? 1 : smaxuid + 1, maxwuid, 0, 0 )) {
case DRV_STORE_BAD: ret = SYNC_SLAVE_BAD; goto bail;
case DRV_BOX_BAD: ret = SYNC_FAIL; goto bail;
@ -707,16 +720,17 @@ sync_boxes( store_t *mctx, const char *mname,
info( "%d messages, %d recent\n", sctx->count, sctx->recent );
dump_box( sctx );
if (suidval && suidval != sctx->uidvalidity) {
if (suidval >= 0 && suidval != sctx->uidvalidity) {
fprintf( stderr, "Error: UIDVALIDITY of slave changed\n" );
ret = SYNC_FAIL;
goto bail;
}
s = strrchr( dname, '/' );
*s = 0;
mkdir( dname, 0700 );
*s = '/';
if ((s = strrchr( dname, '/' ))) {
*s = 0;
mkdir( dname, 0700 );
*s = '/';
}
if (lfd < 0) {
if ((lfd = open( lname, O_WRONLY|O_CREAT, 0666 )) < 0)
goto lferr;
@ -802,7 +816,7 @@ sync_boxes( store_t *mctx, const char *mname,
} else
maxwuid = 0;
info( "Selecting master %s... ", mname );
debug( "selecting master [%d,%d]\n", minwuid, maxwuid );
debug( maxwuid == INT_MAX ? "selecting master [%d,inf]\n" : "selecting master [%d,%d]\n", minwuid, maxwuid );
switch (mdriver->select( mctx, minwuid, maxwuid, mexcs, nmexcs )) {
case DRV_STORE_BAD: ret = SYNC_MASTER_BAD; goto finish;
case DRV_BOX_BAD: ret = SYNC_FAIL; goto finish;
@ -810,13 +824,13 @@ sync_boxes( store_t *mctx, const char *mname,
info( "%d messages, %d recent\n", mctx->count, mctx->recent );
dump_box( mctx );
if (muidval && muidval != mctx->uidvalidity) {
if (muidval >= 0 && muidval != mctx->uidvalidity) {
fprintf( stderr, "Error: UIDVALIDITY of master changed\n" );
ret = SYNC_FAIL;
goto finish;
}
if (!muidval || !suidval) {
if (muidval < 0 || suidval < 0) {
muidval = mctx->uidvalidity;
suidval = sctx->uidvalidity;
Fprintf( jfp, "| %d %d\n", muidval, suidval );

View file

@ -41,6 +41,7 @@ debug( const char *msg, ... )
va_start( va, msg );
vprintf( msg, va );
va_end( va );
fflush( stdout );
}
}