Merge branch '1.2'

Conflicts:
	src/drv_imap.c
This commit is contained in:
Oswald Buddenhagen 2016-12-11 12:52:46 +01:00
commit ab955ffe6b
2 changed files with 73 additions and 21 deletions

View File

@ -641,6 +641,12 @@ next_arg( char **ps )
return ret;
}
static int
is_opt_atom( list_t *list )
{
return list && list->val && list->val != LIST;
}
static int
is_atom( list_t *list )
{
@ -841,33 +847,50 @@ static int parse_namespace_rsp_p2( imap_store_t *, list_t *, char * );
static int parse_namespace_rsp_p3( imap_store_t *, list_t *, char * );
static int
parse_namespace_rsp_fail( void )
parse_namespace_check( list_t *list )
{
if (!list)
goto bad;
if (list->val == NIL)
return 0;
if (list->val != LIST)
goto bad;
for (list = list->child; list; list = list->next) {
if (list->val != LIST)
goto bad;
if (!is_atom( list->child ))
goto bad;
if (!is_opt_atom( list->child->next ))
goto bad;
/* Namespace response extensions may follow here; we don't care. */
}
return 0;
bad:
error( "IMAP error: malformed NAMESPACE response\n" );
return LIST_BAD;
return -1;
}
static int
parse_namespace_rsp( imap_store_t *ctx, list_t *list, char *s )
{
if (!(ctx->ns_personal = list))
return parse_namespace_rsp_fail();
if (parse_namespace_check( (ctx->ns_personal = list) ))
return LIST_BAD;
return parse_list( ctx, s, parse_namespace_rsp_p2 );
}
static int
parse_namespace_rsp_p2( imap_store_t *ctx, list_t *list, char *s )
{
if (!(ctx->ns_other = list))
return parse_namespace_rsp_fail();
if (parse_namespace_check( (ctx->ns_other = list) ))
return LIST_BAD;
return parse_list( ctx, s, parse_namespace_rsp_p3 );
}
static int
parse_namespace_rsp_p3( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
{
if (!(ctx->ns_shared = list))
return parse_namespace_rsp_fail();
if (parse_namespace_check( (ctx->ns_shared = list) ))
return LIST_BAD;
return LIST_OK;
}
@ -1964,7 +1987,9 @@ imap_open_store_authenticate2( imap_store_t *ctx )
imap_server_conf_t *srvc = cfg->server;
string_list_t *mech, *cmech;
int auth_login = 0;
int skipped_login = 0;
#ifdef HAVE_LIBSASL
const char *saslavail;
char saslmechs[1024], *saslend = saslmechs;
#endif
@ -1976,19 +2001,20 @@ imap_open_store_authenticate2( imap_store_t *ctx )
if (!strcasecmp( cmech->string, "LOGIN" )) {
#ifdef HAVE_LIBSSL
if (ctx->conn.ssl || !any)
#else
if (!any)
#endif
auth_login = 1;
} else {
else
skipped_login = 1;
#ifdef HAVE_LIBSASL
} else {
int len = strlen( cmech->string );
if (saslend + len + 2 > saslmechs + sizeof(saslmechs))
oob();
*saslend++ = ' ';
memcpy( saslend, cmech->string, len + 1 );
saslend += len;
#else
error( "IMAP error: authentication mechanism %s is not supported\n", cmech->string );
goto bail;
#endif
}
}
@ -2016,6 +2042,8 @@ imap_open_store_authenticate2( imap_store_t *ctx )
rc = sasl_client_new( "imap", srvc->sconf.host, NULL, NULL, NULL, 0, &ctx->sasl );
if (rc != SASL_OK) {
if (rc == SASL_NOMECH)
goto notsasl;
if (!ctx->sasl)
goto saslbail;
error( "Error: %s\n", sasl_errdetail( ctx->sasl ) );
@ -2023,6 +2051,8 @@ imap_open_store_authenticate2( imap_store_t *ctx )
}
rc = sasl_client_start( ctx->sasl, saslmechs + 1, &interact, CAP(SASLIR) ? &out : NULL, &out_len, &gotmech );
if (rc == SASL_NOMECH)
goto notsasl;
if (gotmech)
info( "Authenticating with SASL mechanism %s...\n", gotmech );
/* Technically, we are supposed to loop over sasl_client_start(),
@ -2041,6 +2071,16 @@ imap_open_store_authenticate2( imap_store_t *ctx )
imap_exec( ctx, cmd, done_sasl_auth, enc ? "AUTHENTICATE %s %s" : "AUTHENTICATE %s", gotmech, enc );
free( enc );
return;
notsasl:
if (!ctx->sasl || sasl_listmech( ctx->sasl, NULL, "", "", "", &saslavail, NULL, NULL ) != SASL_OK)
saslavail = "(none)"; /* EXTERNAL is always there anyway. */
if (!auth_login) {
error( "IMAP error: selected SASL mechanism(s) not available;\n"
" selected:%s\n available: %s\n", saslmechs, saslavail );
goto skipnote;
}
info( "NOT using available SASL mechanism(s): %s\n", saslavail );
sasl_dispose( &ctx->sasl );
}
#endif
if (auth_login) {
@ -2055,6 +2095,12 @@ imap_open_store_authenticate2( imap_store_t *ctx )
return;
}
error( "IMAP error: server supports no acceptable authentication mechanism\n" );
#ifdef HAVE_LIBSASL
skipnote:
#endif
if (skipped_login)
error( "Note: not using LOGIN because connection is not encrypted;\n"
" use 'AuthMechs LOGIN' explicitly to force it.\n" );
bail:
imap_open_store_bail( ctx, FAIL_FINAL );
@ -2129,22 +2175,20 @@ static void
imap_open_store_namespace2( imap_store_t *ctx )
{
imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf;
list_t *nsp, *nsp_1st, *nsp_1st_ns, *nsp_1st_dl;
list_t *nsp, *nsp_1st;
/* XXX for now assume 1st personal namespace */
if (is_list( (nsp = ctx->ns_personal) ) &&
is_list( (nsp_1st = nsp->child) ) &&
is_atom( (nsp_1st_ns = nsp_1st->child) ) &&
is_atom( (nsp_1st_dl = nsp_1st_ns->next) ))
is_list( (nsp_1st = nsp->child) ))
{
list_t *nsp_1st_ns = nsp_1st->child;
list_t *nsp_1st_dl = nsp_1st_ns->next;
if (!ctx->prefix && cfg->use_namespace)
ctx->prefix = nsp_1st_ns->val;
if (!ctx->delimiter[0])
if (!ctx->delimiter[0] && is_atom( nsp_1st_dl ))
ctx->delimiter[0] = nsp_1st_dl->val[0];
imap_open_store_finalize( ctx );
} else {
imap_open_store_bail( ctx, FAIL_FINAL );
}
imap_open_store_finalize( ctx );
}
static void
@ -2318,7 +2362,7 @@ imap_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int_array_t ex
imap_submit_load( ctx, buf, 0, sts );
}
if (maxuid == INT_MAX)
maxuid = ctx->gen.uidnext ? ctx->gen.uidnext - 1 : 1000000000;
maxuid = ctx->gen.uidnext ? ctx->gen.uidnext - 1 : 0x7fffffff;
if (maxuid >= minuid) {
if ((ctx->gen.opts & OPEN_FIND) && minuid < newuid) {
sprintf( buf, "%d:%d", minuid, newuid - 1 );

View File

@ -522,7 +522,15 @@ map_name( const char *arg, char **result, int reserve, const char *in, const cha
for (ll = 0; ll < inl; ll++)
if (arg[i + ll] != in[ll])
goto rnexti;
#ifdef __GNUC__
# pragma GCC diagnostic push
/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42145 */
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
memcpy( p, out, outl );
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif
p += outl;
i += inl;
continue;