added OpenSSL support
This commit is contained in:
parent
813618f041
commit
b6089a2dcb
|
@ -5,5 +5,7 @@ if test $CC = gcc; then
|
||||||
CFLAGS="$CFLAGS -pipe"
|
CFLAGS="$CFLAGS -pipe"
|
||||||
fi
|
fi
|
||||||
AC_CHECK_FUNCS(getopt_long)
|
AC_CHECK_FUNCS(getopt_long)
|
||||||
|
AC_CHECK_LIB(crypto,ERR_error_string)
|
||||||
|
AC_CHECK_LIB(ssl,SSL_library_init)
|
||||||
CFLAGS="$CFLAGS -W -Wall -pedantic -Wmissing-prototypes -Wmissing-declarations"
|
CFLAGS="$CFLAGS -W -Wall -pedantic -Wmissing-prototypes -Wmissing-declarations"
|
||||||
AC_OUTPUT(Makefile)
|
AC_OUTPUT(Makefile)
|
||||||
|
|
118
imap.c
118
imap.c
|
@ -29,6 +29,9 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#endif
|
||||||
#include "isync.h"
|
#include "isync.h"
|
||||||
|
|
||||||
const char *Flags[] = {
|
const char *Flags[] = {
|
||||||
|
@ -40,6 +43,56 @@ const char *Flags[] = {
|
||||||
"\\Draft"
|
"\\Draft"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
SSL_CTX *SSLContext = 0;
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_ssl (config_t * conf)
|
||||||
|
{
|
||||||
|
if (!conf->cert_file)
|
||||||
|
{
|
||||||
|
puts ("Error, CertificateFile not defined");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SSL_library_init ();
|
||||||
|
SSL_load_error_strings ();
|
||||||
|
SSLContext = SSL_CTX_new (SSLv23_client_method ());
|
||||||
|
if (!SSL_CTX_load_verify_locations (SSLContext, conf->cert_file, NULL))
|
||||||
|
{
|
||||||
|
printf ("Error, SSL_CTX_load_verify_locations: %s\n",
|
||||||
|
ERR_error_string (ERR_get_error (), 0));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SSL_CTX_set_verify (SSLContext,
|
||||||
|
SSL_VERIFY_PEER |
|
||||||
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
|
||||||
|
SSL_VERIFY_CLIENT_ONCE, NULL);
|
||||||
|
SSL_CTX_set_verify_depth (SSLContext, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
socket_read (Socket_t * sock, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
if (sock->use_ssl)
|
||||||
|
return SSL_read (sock->ssl, buf, len);
|
||||||
|
#endif
|
||||||
|
return read (sock->fd, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
socket_write (Socket_t * sock, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
if (sock->use_ssl)
|
||||||
|
return SSL_write (sock->ssl, buf, len);
|
||||||
|
#endif
|
||||||
|
return write (sock->fd, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
/* simple line buffering */
|
/* simple line buffering */
|
||||||
static int
|
static int
|
||||||
buffer_gets (buffer_t * b, char **s)
|
buffer_gets (buffer_t * b, char **s)
|
||||||
|
@ -64,7 +117,10 @@ buffer_gets (buffer_t * b, char **s)
|
||||||
b->offset = n;
|
b->offset = n;
|
||||||
start = 0;
|
start = 0;
|
||||||
|
|
||||||
n = read (b->fd, b->buf + b->offset, sizeof (b->buf) - b->offset);
|
n =
|
||||||
|
socket_read (b->sock, b->buf + b->offset,
|
||||||
|
sizeof (b->buf) - b->offset);
|
||||||
|
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
{
|
{
|
||||||
if (n == -1)
|
if (n == -1)
|
||||||
|
@ -112,7 +168,7 @@ imap_exec (imap_t * imap, const char *fmt, ...)
|
||||||
snprintf (buf, sizeof (buf), "%d %s\r\n", ++Tag, tmp);
|
snprintf (buf, sizeof (buf), "%d %s\r\n", ++Tag, tmp);
|
||||||
if (Verbose)
|
if (Verbose)
|
||||||
fputs (buf, stdout);
|
fputs (buf, stdout);
|
||||||
write (imap->fd, buf, strlen (buf));
|
socket_write (imap->sock, buf, strlen (buf));
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -223,7 +279,6 @@ imap_exec (imap_t * imap, const char *fmt, ...)
|
||||||
arg = next_arg (&cmd);
|
arg = next_arg (&cmd);
|
||||||
if (!strcmp ("OK", arg))
|
if (!strcmp ("OK", arg))
|
||||||
return 0;
|
return 0;
|
||||||
puts ("IMAP command failed");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,6 +344,15 @@ imap_open (config_t * box, int fast)
|
||||||
int s;
|
int s;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
struct hostent *he;
|
struct hostent *he;
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
int use_ssl = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
/* initialize SSL */
|
||||||
|
if (init_ssl (box))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* open connection to IMAP server */
|
/* open connection to IMAP server */
|
||||||
|
|
||||||
|
@ -321,12 +385,46 @@ imap_open (config_t * box, int fast)
|
||||||
puts ("ok");
|
puts ("ok");
|
||||||
|
|
||||||
imap = calloc (1, sizeof (imap_t));
|
imap = calloc (1, sizeof (imap_t));
|
||||||
imap->fd = s;
|
imap->sock = calloc (1, sizeof (Socket_t));
|
||||||
//imap->state = imap_state_init;
|
imap->sock->fd = s;
|
||||||
imap->buf = calloc (1, sizeof (buffer_t));
|
imap->buf = calloc (1, sizeof (buffer_t));
|
||||||
imap->buf->fd = s;
|
imap->buf->sock = imap->sock;
|
||||||
imap->box = box;
|
imap->box = box;
|
||||||
|
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
if (!box->use_imaps)
|
||||||
|
{
|
||||||
|
/* always try to select SSL support if available */
|
||||||
|
ret = imap_exec (imap, "STARTTLS");
|
||||||
|
if (!ret)
|
||||||
|
use_ssl = 1;
|
||||||
|
else if (box->require_ssl)
|
||||||
|
{
|
||||||
|
puts ("Error, SSL support not available");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
puts ("Warning, SSL support not available");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
use_ssl = 1;
|
||||||
|
|
||||||
|
if (use_ssl)
|
||||||
|
{
|
||||||
|
imap->sock->ssl = SSL_new (SSLContext);
|
||||||
|
SSL_set_fd (imap->sock->ssl, imap->sock->fd);
|
||||||
|
ret = SSL_connect (imap->sock->ssl);
|
||||||
|
if (ret <= 0)
|
||||||
|
{
|
||||||
|
ret = SSL_get_error (imap->sock->ssl, ret);
|
||||||
|
printf ("Error, SSL_connect: %s\n", ERR_error_string (ret, 0));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
imap->sock->use_ssl = 1;
|
||||||
|
puts ("SSL support enabled");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
puts ("Logging in...");
|
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)
|
if (!ret)
|
||||||
|
@ -395,7 +493,7 @@ write_strip (int fd, char *buf, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_server (int fd, const char *fmt, ...)
|
send_server (Socket_t * sock, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
char cmd[128];
|
char cmd[128];
|
||||||
|
@ -406,7 +504,7 @@ send_server (int fd, const char *fmt, ...)
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
|
|
||||||
snprintf (cmd, sizeof (cmd), "%d %s\r\n", ++Tag, buf);
|
snprintf (cmd, sizeof (cmd), "%d %s\r\n", ++Tag, buf);
|
||||||
write (fd, cmd, strlen (cmd));
|
socket_write (sock, cmd, strlen (cmd));
|
||||||
|
|
||||||
if (Verbose)
|
if (Verbose)
|
||||||
fputs (cmd, stdout);
|
fputs (cmd, stdout);
|
||||||
|
@ -421,7 +519,7 @@ imap_fetch_message (imap_t * imap, unsigned int uid, int fd)
|
||||||
size_t n;
|
size_t n;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
|
||||||
send_server (imap->fd, "UID FETCH %d RFC822.PEEK", uid);
|
send_server (imap->sock, "UID FETCH %d RFC822.PEEK", uid);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -477,7 +575,7 @@ imap_fetch_message (imap_t * imap, unsigned int uid, int fd)
|
||||||
n = bytes;
|
n = bytes;
|
||||||
if (n > sizeof (buf))
|
if (n > sizeof (buf))
|
||||||
n = sizeof (buf);
|
n = sizeof (buf);
|
||||||
n = read (imap->fd, buf, n);
|
n = socket_read (imap->sock, buf, n);
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
{
|
{
|
||||||
// printf("imap_fetch_message:%d:read %d bytes\n", __LINE__, n);
|
// printf("imap_fetch_message:%d:read %d bytes\n", __LINE__, n);
|
||||||
|
|
32
isync.1
32
isync.1
|
@ -115,7 +115,19 @@ command, apply to this mailbox only.
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBHost\fR \fIname\fR
|
\fBHost\fR \fIname\fR
|
||||||
Defines the DNS name or IP address of the IMAP server
|
Defines the DNS name or IP address of the IMAP server. If the hostname is
|
||||||
|
prefixed with
|
||||||
|
.I imaps:
|
||||||
|
the connection is assumed to be a SSL connection to port 993 (though you can
|
||||||
|
change this by placing a
|
||||||
|
.B Port
|
||||||
|
command
|
||||||
|
.B after
|
||||||
|
the
|
||||||
|
.B Host
|
||||||
|
command. Note that some servers support SSL on the default port 143.
|
||||||
|
.B isync
|
||||||
|
will always attempt to use SSL if available.
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBPort\fR \fIport\fR
|
\fBPort\fR \fIport\fR
|
||||||
|
@ -144,6 +156,18 @@ will prompt you for it.
|
||||||
\fBAlias\fR \fIstring\fR
|
\fBAlias\fR \fIstring\fR
|
||||||
Defines an alias for the mailbox which can be used as a shortcut on the
|
Defines an alias for the mailbox which can be used as a shortcut on the
|
||||||
command line.
|
command line.
|
||||||
|
..
|
||||||
|
.TP
|
||||||
|
\fBRequireSSL\fR \fIyes|no\fR
|
||||||
|
.B isync will abort the connection if a TLS/SSL session to the IMAP
|
||||||
|
server can not be established. (Default:
|
||||||
|
.I yes
|
||||||
|
)
|
||||||
|
..
|
||||||
|
.TP
|
||||||
|
\fBCertificateFile\fR \fIpath\fR
|
||||||
|
File containing X.509 CA certificates used to verify server identities.
|
||||||
|
..
|
||||||
.P
|
.P
|
||||||
Configuration commands that appear prior to the first
|
Configuration commands that appear prior to the first
|
||||||
.B Mailbox
|
.B Mailbox
|
||||||
|
@ -176,9 +200,3 @@ http://www.sigpipe.org/isync/.
|
||||||
..
|
..
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
Written by Michael R. Elkins <me@mutt.org>.
|
Written by Michael R. Elkins <me@mutt.org>.
|
||||||
..
|
|
||||||
.SH BUGS
|
|
||||||
SSL is currently not used when connecting to the IMAP server. A future
|
|
||||||
version of
|
|
||||||
.B isync
|
|
||||||
is expected to support this.
|
|
||||||
|
|
23
isync.h
23
isync.h
|
@ -19,10 +19,22 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
SSL *ssl;
|
||||||
|
unsigned int use_ssl:1;
|
||||||
|
#endif
|
||||||
|
} Socket_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Socket_t *sock;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int bytes;
|
int bytes;
|
||||||
int offset;
|
int offset;
|
||||||
|
@ -43,6 +55,11 @@ struct config
|
||||||
char *box;
|
char *box;
|
||||||
char *alias;
|
char *alias;
|
||||||
config_t *next;
|
config_t *next;
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
char *cert_file;
|
||||||
|
unsigned int use_imaps:1;
|
||||||
|
unsigned int require_ssl:1;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* struct representing local mailbox file */
|
/* struct representing local mailbox file */
|
||||||
|
@ -78,7 +95,7 @@ struct message
|
||||||
/* imap connection info */
|
/* imap connection info */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int fd; /* server socket */
|
Socket_t *sock;
|
||||||
unsigned int count; /* # of msgs */
|
unsigned int count; /* # of msgs */
|
||||||
unsigned int recent; /* # of recent messages */
|
unsigned int recent; /* # of recent messages */
|
||||||
buffer_t *buf; /* input buffer for reading server output */
|
buffer_t *buf; /* input buffer for reading server output */
|
||||||
|
@ -101,6 +118,10 @@ extern unsigned int Tag;
|
||||||
extern char Hostname[256];
|
extern char Hostname[256];
|
||||||
extern int Verbose;
|
extern int Verbose;
|
||||||
|
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
extern SSL_CTX *SSLContext;
|
||||||
|
#endif
|
||||||
|
|
||||||
char *next_arg (char **);
|
char *next_arg (char **);
|
||||||
|
|
||||||
int sync_mailbox (mailbox_t *, imap_t *, int);
|
int sync_mailbox (mailbox_t *, imap_t *, int);
|
||||||
|
|
75
main.c
75
main.c
|
@ -107,6 +107,22 @@ enter_password (void)
|
||||||
return strdup (pass);
|
return strdup (pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* set defaults from the global configuration section */
|
||||||
|
static void
|
||||||
|
config_defaults (config_t * conf)
|
||||||
|
{
|
||||||
|
conf->user = global.user;
|
||||||
|
conf->pass = global.pass;
|
||||||
|
conf->port = global.port;
|
||||||
|
conf->box = global.box;
|
||||||
|
conf->host = global.host;
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
conf->require_ssl = global.require_ssl;
|
||||||
|
conf->use_imaps = global.use_imaps;
|
||||||
|
conf->cert_file = global.cert_file;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_config (char *where)
|
load_config (char *where)
|
||||||
{
|
{
|
||||||
|
@ -152,10 +168,25 @@ load_config (char *where)
|
||||||
if (*cur)
|
if (*cur)
|
||||||
cur = &(*cur)->next;
|
cur = &(*cur)->next;
|
||||||
*cur = calloc (1, sizeof (config_t));
|
*cur = calloc (1, sizeof (config_t));
|
||||||
|
config_defaults (*cur);
|
||||||
(*cur)->path = strdup (p);
|
(*cur)->path = strdup (p);
|
||||||
}
|
}
|
||||||
else if (!strncasecmp ("host", buf, 4))
|
else if (!strncasecmp ("host", buf, 4))
|
||||||
{
|
{
|
||||||
|
if (!strncasecmp ("imaps:", p, 6))
|
||||||
|
{
|
||||||
|
p += 6;
|
||||||
|
if (*cur)
|
||||||
|
{
|
||||||
|
(*cur)->use_imaps = 1;
|
||||||
|
(*cur)->port = 993;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
global.use_imaps = 1;
|
||||||
|
global.port = 993;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (*cur)
|
if (*cur)
|
||||||
(*cur)->host = strdup (p);
|
(*cur)->host = strdup (p);
|
||||||
else
|
else
|
||||||
|
@ -194,6 +225,22 @@ load_config (char *where)
|
||||||
if (*cur)
|
if (*cur)
|
||||||
(*cur)->alias = strdup (p);
|
(*cur)->alias = strdup (p);
|
||||||
}
|
}
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
else if (!strncasecmp ("CertificateFile", buf, 15))
|
||||||
|
{
|
||||||
|
if (*cur)
|
||||||
|
(*cur)->cert_file = strdup (p);
|
||||||
|
else
|
||||||
|
global.cert_file = strdup (p);
|
||||||
|
}
|
||||||
|
else if (!strncasecmp ("RequireSSL", buf, 10))
|
||||||
|
{
|
||||||
|
if (*cur)
|
||||||
|
(*cur)->require_ssl = (strcasecmp (p, "yes") == 0);
|
||||||
|
else
|
||||||
|
global.require_ssl = (strcasecmp (p, "yes") == 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else if (buf[0])
|
else if (buf[0])
|
||||||
printf ("%s:%d:unknown command:%s", path, line, buf);
|
printf ("%s:%d:unknown command:%s", path, line, buf);
|
||||||
}
|
}
|
||||||
|
@ -257,6 +304,12 @@ main (int argc, char **argv)
|
||||||
global.port = 143;
|
global.port = 143;
|
||||||
global.box = "INBOX";
|
global.box = "INBOX";
|
||||||
global.user = strdup (pw->pw_name);
|
global.user = strdup (pw->pw_name);
|
||||||
|
#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;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if HAVE_GETOPT_LONG
|
#if HAVE_GETOPT_LONG
|
||||||
while ((i = getopt_long (argc, argv, "defhp:u:r:s:vV", Opts, NULL)) != -1)
|
while ((i = getopt_long (argc, argv, "defhp:u:r:s:vV", Opts, NULL)) != -1)
|
||||||
|
@ -326,29 +379,15 @@ main (int argc, char **argv)
|
||||||
box = &global;
|
box = &global;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill in missing info with defaults */
|
|
||||||
if (!box->pass)
|
if (!box->pass)
|
||||||
{
|
{
|
||||||
if (!global.pass)
|
box->pass = enter_password ();
|
||||||
|
if (!box->pass)
|
||||||
{
|
{
|
||||||
box->pass = enter_password ();
|
puts ("Aborting, no password");
|
||||||
if (!box->pass)
|
exit (1);
|
||||||
{
|
|
||||||
puts ("Aborting, no password");
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
box->pass = global.pass;
|
|
||||||
}
|
}
|
||||||
if (!box->user)
|
|
||||||
box->user = global.user;
|
|
||||||
if (!box->port)
|
|
||||||
box->port = global.port;
|
|
||||||
if (!box->host)
|
|
||||||
box->host = global.host;
|
|
||||||
if (!box->box)
|
|
||||||
box->box = global.box;
|
|
||||||
|
|
||||||
printf ("Reading %s\n", box->path);
|
printf ("Reading %s\n", box->path);
|
||||||
mail = maildir_open (box->path, fast);
|
mail = maildir_open (box->path, fast);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user