Merge branch '1.3'

This commit is contained in:
Oswald Buddenhagen 2019-10-03 20:17:54 +02:00
commit 462fed556a
6 changed files with 114 additions and 48 deletions

View File

@ -18,14 +18,14 @@ fi
need_perl=5.14
AC_CACHE_CHECK([whether perl is recent enough], ob_cv_perl_ver, [
if $PERL -e "use v$need_perl;"; then
if $PERL -e "use v$need_perl;" 2> /dev/null; then
ob_cv_perl_ver=yes
else
ob_cv_perl_ver=no
fi
])
if test "x$ob_cv_perl_ver" = "xno"; then
AC_MSG_ERROR([perl is too old])
AC_MSG_ERROR([perl is too old, need v$need_perl])
fi
AC_CACHE_CHECK([whether strftime supports %z], ob_cv_strftime_z,
@ -94,7 +94,7 @@ if test "x$ob_cv_with_ssl" != xno; then
sav_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS $SSL_LDFLAGS"
AC_CHECK_LIB(dl, dlopen, [LIBDL=-ldl])
AC_CHECK_LIB(crypto, CRYPTO_lock, [LIBCRYPTO=-lcrypto])
AC_CHECK_LIB(crypto, X509_cmp, [LIBCRYPTO=-lcrypto])
AC_CHECK_LIB(ssl, SSL_connect,
[SSL_LIBS="-lssl $LIBCRYPTO $LIBDL" have_ssl_paths=yes])
LDFLAGS=$sav_LDFLAGS

View File

@ -33,6 +33,7 @@
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
#define as(ar) (sizeof(ar)/sizeof(ar[0]))

View File

@ -953,7 +953,7 @@ parse_date( const char *str )
struct tm datetime;
memset( &datetime, 0, sizeof(datetime) );
if (!(end = strptime( str, "%d-%b-%Y %H:%M:%S ", &datetime )))
if (!(end = strptime( str, "%e-%b-%Y %H:%M:%S ", &datetime )))
return -1;
if ((date = timegm( &datetime )) == -1)
return -1;
@ -1203,17 +1203,16 @@ parse_response_code( imap_store_t *ctx, imap_cmd_t *cmd, char *s )
return RESP_OK;
}
static int parse_list_rsp_p1( imap_store_t *, list_t *, char * );
static int parse_list_rsp_p2( imap_store_t *, list_t *, char * );
static int
parse_list_rsp( imap_store_t *ctx, list_t *list, char *cmd )
{
char *arg;
list_t *lp;
if (!is_list( list )) {
free_list( list );
bad_list:
error( "IMAP error: malformed LIST response\n" );
return LIST_BAD;
}
@ -1223,10 +1222,19 @@ parse_list_rsp( imap_store_t *ctx, list_t *list, char *cmd )
return LIST_OK;
}
free_list( list );
if (!(arg = next_arg( &cmd )))
goto bad_list;
if (!ctx->delimiter[0])
ctx->delimiter[0] = arg[0];
return parse_list( ctx, cmd, parse_list_rsp_p1 );
}
static int
parse_list_rsp_p1( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED )
{
if (!is_opt_atom( list )) {
error( "IMAP error: malformed LIST response\n" );
free_list( list );
return LIST_BAD;
}
if (!ctx->delimiter[0] && is_atom( list ))
ctx->delimiter[0] = list->val[0];
return parse_list( ctx, cmd, parse_list_rsp_p2 );
}
@ -1873,7 +1881,7 @@ ensure_password( imap_server_conf_t *srvc )
if (cmd) {
FILE *fp;
int ret;
char buffer[80];
char buffer[2048]; // Hopefully more than enough room for XOAUTH2, etc. tokens
if (*cmd == '+') {
flushn();
@ -2079,7 +2087,7 @@ done_sasl_auth( imap_store_t *ctx, imap_cmd_t *cmd ATTR_UNUSED, int response )
int rc = sasl_client_step( ctx->sasl, NULL, 0, &interact, &out, &out_len );
if (process_sasl_step( ctx, rc, NULL, 0, interact, &out, &out_len ) < 0)
warn( "Warning: SASL reported failure despite successful IMAP authentication. Ignoring...\n" );
else if (out)
else if (out_len > 0)
warn( "Warning: SASL wants more steps despite successful IMAP authentication. Ignoring...\n" );
}

View File

@ -109,6 +109,7 @@ sub type_to_format($)
{
$_ = shift;
s/xint /\%\#x/g;
s/uint /\%u/g;
s/int /\%d/g;
s/const char \*/\%s/g;
return $_;

View File

@ -267,7 +267,7 @@ with DOS/Windows file systems.
.TP
\fBSubFolders\fR \fBVerbatim\fR|\fBMaildir++\fR|\fBLegacy\fR
The on-disk folder naming style used for hierarchical mailboxes.
This has option has no effect when \fBFlatten\fR is used.
This option has no effect when \fBFlatten\fR is used.
.br
Suppose mailboxes with the canonical paths \fBtop/sub/subsub\fR and
\fBINBOX/sub/subsub\fR, the styles will yield the following on-disk paths:
@ -601,12 +601,13 @@ which in turn are overridden by command line switches.
..
.TP
\fBSyncState\fR {\fB*\fR|\fIpath\fR}
Set the location of this Channel's synchronization state files. \fB*\fR means
that the state should be saved in a file named .mbsyncstate in the
Slave mailbox itself; this has the advantage that you needn't to care for the
state file if you delete the mailbox, but it works only with Maildir mailboxes,
obviously. Otherwise this is interpreted as a string to prepend to the Slave
mailbox name to make up a complete path.
Set the location of this Channel's synchronization state files.
\fB*\fR means that the state should be saved in a file named .mbsyncstate
in the Slave mailbox itself; this has the advantage that you do not need
to handle the state file separately if you delete the mailbox, but it works
only with Maildir mailboxes, obviously.
Otherwise this is interpreted as a string to prepend to the Slave mailbox
name to make up a complete path.
.br
This option can be used outside any section for a global effect. In this case
the appended string is made up according to the pattern

View File

@ -63,6 +63,34 @@ socket_fail( conn_t *conn )
}
#ifdef HAVE_LIBSSL
static void ATTR_PRINTFLIKE(1, 2)
print_ssl_errors( const char *fmt, ... )
{
char *action;
va_list va;
ulong err;
va_start( va, fmt );
nfvasprintf( &action, fmt, va );
va_end( va );
while ((err = ERR_get_error()))
error( "Error while %s: %s\n", action, ERR_error_string( err, 0 ) );
free( action );
}
static int
print_ssl_socket_errors( const char *func, conn_t *conn )
{
ulong err;
int num = 0;
while ((err = ERR_get_error())) {
error( "Socket error: secure %s %s: %s\n", func, conn->name, ERR_error_string( err, 0 ) );
num++;
}
return num;
}
static int
ssl_return( const char *func, conn_t *conn, int ret )
{
@ -76,9 +104,12 @@ ssl_return( const char *func, conn_t *conn, int ret )
FALLTHROUGH
case SSL_ERROR_WANT_READ:
return 0;
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
if (!(err = ERR_get_error())) {
print_ssl_socket_errors( func, conn );
break;
case SSL_ERROR_SYSCALL:
if (print_ssl_socket_errors( func, conn ))
break;
if (ret == 0) {
case SSL_ERROR_ZERO_RETURN:
/* Callers take the short path out, so signal higher layers from here. */
@ -87,9 +118,6 @@ ssl_return( const char *func, conn_t *conn, int ret )
return -1;
}
sys_error( "Socket error: secure %s %s", func, conn->name );
} else {
error( "Socket error: secure %s %s: %s\n", func, conn->name, ERR_error_string( err, 0 ) );
}
break;
default:
error( "Socket error: secure %s %s: unhandled SSL error %d\n", func, conn->name, err );
@ -176,22 +204,29 @@ verify_cert_host( const server_conf_t *conf, conn_t *sock )
trusted = (STACK_OF(X509_OBJECT) *)sock->conf->trusted_certs;
for (i = 0; i < sk_X509_OBJECT_num( trusted ); i++) {
if (!X509_cmp( cert, X509_OBJECT_get0_X509( sk_X509_OBJECT_value( trusted, i ) ) ))
if (!X509_cmp( cert, X509_OBJECT_get0_X509( sk_X509_OBJECT_value( trusted, i ) ) )) {
X509_free( cert );
return 0;
}
}
err = SSL_get_verify_result( sock->ssl );
if (err != X509_V_OK) {
error( "SSL error connecting %s: %s\n", sock->name, X509_verify_cert_error_string( err ) );
X509_free( cert );
return -1;
}
if (!conf->host) {
error( "SSL error connecting %s: Neither host nor matching certificate specified\n", sock->name );
X509_free( cert );
return -1;
}
return verify_hostname( cert, conf->host );
int ret = verify_hostname( cert, conf->host );
X509_free( cert );
return ret;
}
static int
@ -203,7 +238,15 @@ init_ssl_ctx( const server_conf_t *conf )
if (conf->SSLContext)
return conf->ssl_ctx_valid;
mconf->SSLContext = SSL_CTX_new( SSLv23_client_method() );
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
const SSL_METHOD *method = TLS_client_method();
#else
const SSL_METHOD *method = SSLv23_client_method();
#endif
if (!(mconf->SSLContext = SSL_CTX_new( method ))) {
print_ssl_errors( "initializing SSL context" );
return 0;
}
if (!(conf->ssl_versions & SSLv3))
options |= SSL_OP_NO_SSLv3;
@ -221,25 +264,24 @@ init_ssl_ctx( const server_conf_t *conf )
SSL_CTX_set_options( mconf->SSLContext, options );
if (conf->cert_file && !SSL_CTX_load_verify_locations( mconf->SSLContext, conf->cert_file, 0 )) {
error( "Error while loading certificate file '%s': %s\n",
conf->cert_file, ERR_error_string( ERR_get_error(), 0 ) );
print_ssl_errors( "loading certificate file '%s'", conf->cert_file );
return 0;
}
mconf->trusted_certs = (_STACK *)sk_X509_OBJECT_dup( X509_STORE_get0_objects( SSL_CTX_get_cert_store( mconf->SSLContext ) ) );
if (mconf->system_certs && !SSL_CTX_set_default_verify_paths( mconf->SSLContext ))
warn( "Warning: Unable to load default certificate files: %s\n",
ERR_error_string( ERR_get_error(), 0 ) );
if (mconf->system_certs && !SSL_CTX_set_default_verify_paths( mconf->SSLContext )) {
ulong err;
while ((err = ERR_get_error()))
warn( "Warning: Unable to load default certificate files: %s\n", ERR_error_string( err, 0 ) );
}
SSL_CTX_set_verify( mconf->SSLContext, SSL_VERIFY_NONE, NULL );
if (conf->client_certfile && !SSL_CTX_use_certificate_chain_file( mconf->SSLContext, conf->client_certfile)) {
error( "Error while loading client certificate file '%s': %s\n",
conf->client_certfile, ERR_error_string( ERR_get_error(), 0 ) );
print_ssl_errors( "loading client certificate file '%s'", conf->client_certfile );
return 0;
}
if (conf->client_keyfile && !SSL_CTX_use_PrivateKey_file( mconf->SSLContext, conf->client_keyfile, SSL_FILETYPE_PEM)) {
error( "Error while loading client private key '%s': %s\n",
conf->client_keyfile, ERR_error_string( ERR_get_error(), 0 ) );
print_ssl_errors( "loading client private key '%s'", conf->client_keyfile );
return 0;
}
@ -270,10 +312,21 @@ 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)
if (!(conn->ssl = SSL_new( ((server_conf_t *)conn->conf)->SSLContext ))) {
print_ssl_errors( "initializing SSL connection" );
start_tls_p3( conn, 0 );
return;
SSL_set_fd( conn->ssl, conn->fd );
}
if (!SSL_set_tlsext_host_name( conn->ssl, conn->conf->host )) {
print_ssl_errors( "setting SSL server host name" );
start_tls_p3( conn, 0 );
return;
}
if (!SSL_set_fd( conn->ssl, conn->fd )) {
print_ssl_errors( "setting SSL socket fd" );
start_tls_p3( conn, 0 );
return;
}
SSL_set_mode( conn->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER );
socket_expect_read( conn, 1 );
conn->state = SCK_STARTTLS;
@ -545,8 +598,10 @@ static void
socket_connected( conn_t *conn )
{
#ifdef HAVE_IPV6
if (conn->addrs) {
freeaddrinfo( conn->addrs );
conn->addrs = 0;
}
#endif
conf_notifier( &conn->notify, 0, POLLIN );
socket_expect_read( conn, 0 );