diff --git a/README b/README index 13f2071..bccbdce 100644 --- a/README +++ b/README @@ -26,6 +26,8 @@ maintained, and all flags are synchronized. ``isync'' has been tested with the following IMAP servers: * Microsoft Exchange 2000 IMAP4rev1 server version 6.0.4417.0 + * Courier-IMAP 1.2.3 + * WU-IMAP 2000 * Platforms diff --git a/imap.c b/imap.c index ddecab9..1ec5c08 100644 --- a/imap.c +++ b/imap.c @@ -132,6 +132,14 @@ init_ssl (config_t * conf) ERR_error_string (ERR_get_error (), 0)); return -1; } + + if (!conf->use_sslv2) + SSL_CTX_set_options (SSLContext, SSL_OP_NO_SSLv2); + if (!conf->use_sslv3) + SSL_CTX_set_options (SSLContext, SSL_OP_NO_SSLv3); + if (!conf->use_tlsv1) + SSL_CTX_set_options (SSLContext, SSL_OP_NO_TLSv1); + /* we check the result of the verification after SSL_connect() */ SSL_CTX_set_verify (SSLContext, SSL_VERIFY_NONE, 0); return 0; @@ -169,22 +177,27 @@ buffer_gets (buffer_t * b, char **s) for (;;) { - if (b->offset + 2 > b->bytes) + /* make sure we have enough data to read the \r\n sequence */ + if (b->offset + 1 >= b->bytes) { - /* shift down used bytes */ - *s = b->buf; + if (start != 0) + { + /* shift down used bytes */ + *s = b->buf; - assert (start <= b->bytes); - n = b->bytes - start; + assert (start <= b->bytes); + n = b->bytes - start; - if (n) - memmove (b->buf, b->buf + start, n); - b->offset = n; - start = 0; + if (n) + memmove (b->buf, b->buf + start, n); + b->offset -= start; + b->bytes = n; + start = 0; + } n = - socket_read (b->sock, b->buf + b->offset, - sizeof (b->buf) - b->offset); + socket_read (b->sock, b->buf + b->bytes, + sizeof (b->buf) - b->bytes); if (n <= 0) { @@ -194,17 +207,18 @@ buffer_gets (buffer_t * b, char **s) puts ("EOF"); return -1; } - b->bytes = b->offset + n; -// printf ("buffer_gets:read %d bytes\n", n); + b->bytes += n; } if (b->buf[b->offset] == '\r') { + assert (b->offset + 1 < b->bytes); if (b->buf[b->offset + 1] == '\n') { b->buf[b->offset] = 0; /* terminate the string */ b->offset += 2; /* next line */ +// assert (strchr (*s, '\r') == 0); return 0; } } @@ -241,6 +255,8 @@ parse_fetch (imap_t * imap, list_t * list) /* already saw this message */ return 0; } + else if (uid > imap->maxuid) + imap->maxuid = uid; } else puts ("Error, unable to parse UID"); @@ -288,6 +304,15 @@ parse_fetch (imap_t * imap, list_t * list) } } +#if 0 + if (uid == 221) + { + int loop = 1; + + while (loop); + } +#endif + cur = calloc (1, sizeof (message_t)); cur->next = imap->msgs; imap->msgs = cur; @@ -522,12 +547,12 @@ imap_open (config_t * box, unsigned int minuid) #endif puts ("Logging in..."); - ret = imap_exec (imap, "LOGIN %s %s", box->user, box->pass); + ret = imap_exec (imap, "LOGIN \"%s\" \"%s\"", box->user, box->pass); if (!ret) { /* get NAMESPACE info */ - if (!imap_exec (imap, "NAMESPACE")) + if (box->use_namespace && !imap_exec (imap, "NAMESPACE")) { /* XXX for now assume personal namespace */ if (is_list (imap->ns_personal) && diff --git a/isync.1 b/isync.1 index 1be053b..ac8ea30 100644 --- a/isync.1 +++ b/isync.1 @@ -160,6 +160,16 @@ large attachments. If .I bytes is 0, the maximum file size is .B unlimited. +.. +.TP +\fBUseNamespace\fR \fIyes|no\fR +Selects whether +.B isync +should select mailboxes using the namespace given by the NAMESPACE command. +This is useful with broken IMAP servers. (Default: +.I yes +) +.. .TP \fBRequireSSL\fR \fIyes|no\fR .B isync @@ -172,6 +182,30 @@ server can not be established. (Default: \fBCertificateFile\fR \fIpath\fR File containing X.509 CA certificates used to verify server identities. .. +.TP +\fBUseSSLv2\fR \fIyes|no\fR +Should +.B isync +use SSLv2 for communication with the IMAP server over SSL? (Default: +.I yes +) +.. +.TP +\fBUseSSLv3\fR \fIyes|no\fR +Should +.B isync +use SSLv3 for communication with the IMAP server over SSL? (Default: +.I yes +) +.. +.TP +\fBUseTLSv1\fR \fIyes|no\fR +Should +.B isync +use TLSv1 for communication with the IMAP server over SSL? (Default: +.I yes +) +.. .P Configuration commands that appear prior to the first .B Mailbox diff --git a/isync.h b/isync.h index a968ead..d175fe8 100644 --- a/isync.h +++ b/isync.h @@ -60,7 +60,11 @@ struct config char *cert_file; unsigned int use_imaps:1; unsigned int require_ssl:1; + unsigned int use_sslv2:1; + unsigned int use_sslv3:1; + unsigned int use_tlsv1:1; #endif + unsigned int use_namespace:1; }; /* struct representing local mailbox file */ @@ -118,9 +122,6 @@ typedef struct buffer_t *buf; /* input buffer for reading server output */ message_t *msgs; /* list of messages on the server */ config_t *box; /* mailbox to open */ - message_t *recent_msgs; /* list of recent messages - only contains - * UID to be used in a FETCH FLAGS command - */ unsigned int deleted; /* # of deleted messages */ unsigned int uidvalidity; unsigned int maxuid; diff --git a/main.c b/main.c index c98f3f9..c81817f 100644 --- a/main.c +++ b/main.c @@ -95,10 +95,14 @@ config_defaults (config_t * conf) conf->box = global.box; conf->host = global.host; conf->max_size = global.max_size; + conf->use_namespace = global.use_namespace; #if HAVE_LIBSSL conf->require_ssl = global.require_ssl; conf->use_imaps = global.use_imaps; conf->cert_file = global.cert_file; + conf->use_sslv2 = global.use_sslv2; + conf->use_sslv3 = global.use_sslv3; + conf->use_tlsv1 = global.use_tlsv1; #endif } @@ -138,9 +142,9 @@ load_config (char *where) if (buf[0] == '#') continue; p = buf; - while (*p && !isspace ((unsigned char)*p)) + while (*p && !isspace ((unsigned char) *p)) p++; - while (isspace ((unsigned char)*p)) + while (isspace ((unsigned char) *p)) p++; if (!strncasecmp ("mailbox", buf, 7)) { @@ -213,6 +217,13 @@ load_config (char *where) else global.max_size = atol (p); } + else if (!strncasecmp ("UseNamespace", buf, 12)) + { + if (*cur) + (*cur)->use_namespace = (strcasecmp (p, "yes") == 0); + else + global.use_namespace = (strcasecmp (p, "yes") == 0); + } #if HAVE_LIBSSL else if (!strncasecmp ("CertificateFile", buf, 15)) { @@ -228,6 +239,27 @@ load_config (char *where) else global.require_ssl = (strcasecmp (p, "yes") == 0); } + else if (!strncasecmp ("UseSSLv2", buf, 8)) + { + if (*cur) + (*cur)->use_sslv2 = (strcasecmp (p, "yes") == 0); + else + global.use_sslv2 = (strcasecmp (p, "yes") == 0); + } + else if (!strncasecmp ("UseSSLv3", buf, 8)) + { + if (*cur) + (*cur)->use_sslv3 = (strcasecmp (p, "yes") == 0); + else + global.use_sslv3 = (strcasecmp (p, "yes") == 0); + } + else if (!strncasecmp ("UseTLSv1", buf, 8)) + { + if (*cur) + (*cur)->use_tlsv1 = (strcasecmp (p, "yes") == 0); + else + global.use_tlsv1 = (strcasecmp (p, "yes") == 0); + } #endif else if (buf[0]) printf ("%s:%d:unknown command:%s", path, line, buf); @@ -255,7 +287,7 @@ next_arg (char **s) return 0; if (!*s) return 0; - while (isspace ((unsigned char)**s)) + while (isspace ((unsigned char) **s)) (*s)++; if (!**s) { @@ -263,7 +295,7 @@ next_arg (char **s) return 0; } ret = *s; - while (**s && !isspace ((unsigned char)**s)) + while (**s && !isspace ((unsigned char) **s)) (*s)++; if (**s) *(*s)++ = 0; @@ -293,11 +325,15 @@ main (int argc, char **argv) global.box = "INBOX"; global.user = strdup (pw->pw_name); global.max_size = 0; + global.use_namespace = 1; #if HAVE_LIBSSL /* this will probably annoy people, but its the best default just in * case people forget to turn it on */ global.require_ssl = 1; + global.use_sslv2 = 1; + global.use_sslv3 = 1; + global.use_tlsv1 = 1; #endif #if HAVE_GETOPT_LONG