Переглянути джерело

Merge branch '1.2'

Conflicts:
	src/drv_imap.c
Oswald Buddenhagen 8 роки тому
батько
коміт
ab955ffe6b
2 змінених файлів з 73 додано та 21 видалено
  1. 65 21
      src/drv_imap.c
  2. 8 0
      src/util.c

+ 65 - 21
src/drv_imap.c

@@ -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 );

+ 8 - 0
src/util.c

@@ -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;