On Mon, 2013-06-24 at 23:40 +0300, Timo Sirainen wrote:
> Looks like Exchange 2013 IMAP has broken command pipelining :( See if it gets 
> fixed by http://hg.dovecot.org/dovecot-2.2/rev/6e8bbc150fa9 and the attached 
> patch on top of that? If it works, I'll commit that patch too.

Attached another patch that doesn't crash on successful logins :)

diff -r f68a955f4c5c src/imap-login/client.h
--- a/src/imap-login/client.h	Tue Jun 25 00:10:39 2013 +0300
+++ b/src/imap-login/client.h	Tue Jun 25 01:21:15 2013 +0300
@@ -19,6 +19,7 @@
 	unsigned int cmd_finished:1;
 	unsigned int proxy_sasl_ir:1;
 	unsigned int proxy_seen_banner:1;
+	unsigned int proxy_no_pipelining:1;
 	unsigned int skip_line:1;
 	unsigned int id_logged:1;
 	unsigned int client_ignores_capability_resp_code:1;
diff -r f68a955f4c5c src/imap-login/imap-proxy.c
--- a/src/imap-login/imap-proxy.c	Tue Jun 25 00:10:39 2013 +0300
+++ b/src/imap-login/imap-proxy.c	Tue Jun 25 01:21:15 2013 +0300
@@ -63,8 +63,12 @@
 	unsigned int len;
 	const char *mech_name, *error;
 
-	if (client->proxy_backend_capability == NULL)
+	if (client->proxy_backend_capability == NULL &&
+	    client->common.proxy_state != IMAP_PROXY_STATE_CAPABILITY) {
 		str_append(str, "C CAPABILITY\r\n");
+		if (client->proxy_no_pipelining)
+			return 0;
+	}
 
 	if (client->common.proxy_mech == NULL) {
 		/* logging in normally - use LOGIN command */
@@ -88,6 +92,7 @@
 		sasl_client_new(client->common.proxy_mech, &sasl_set);
 	mech_name = sasl_client_mech_get_name(client->common.proxy_mech);
 
+	client->common.pre_proxy_auth = ioloop_timeval;
 	str_append(str, "L AUTHENTICATE ");
 	str_append(str, mech_name);
 	if (client->proxy_sasl_ir) {
@@ -122,6 +127,11 @@
 			str_sanitize(line, 160)));
 		return -1;
 	}
+	if (strstr(line, "Microsoft Exchange") != NULL) {
+		/* Exchange 2013 hangs if we send the CAPABILITY pipelined
+		   with LOGIN */
+		client->proxy_no_pipelining = TRUE;
+	}
 
 	str = t_str_new(128);
 	if (strncmp(line + 5, "[CAPABILITY ", 12) == 0) {
@@ -203,6 +213,7 @@
 	output = login_proxy_get_ostream(client->login_proxy);
 	if (!imap_client->proxy_seen_banner) {
 		/* this is a banner */
+		client->proxy_banner = ioloop_timeval;
 		client->proxy_state = IMAP_PROXY_STATE_BANNER;
 		imap_client->proxy_seen_banner = TRUE;
 		if (proxy_input_banner(imap_client, output, line) < 0) {
@@ -270,9 +281,10 @@
 			return -1;
 		}
 		o_stream_nsend(output, str_data(str), str_len(str));
-		return 1;
+		return 0;
 	} else if (strncmp(line, "L OK ", 5) == 0) {
 		/* Login successful. Send this line to client. */
+		client->post_proxy_auth = ioloop_timeval;
 		client->proxy_state = IMAP_PROXY_STATE_LOGIN;
 		str = t_str_new(128);
 		client_send_login_reply(imap_client, str, line + 5);
@@ -328,6 +340,14 @@
 	} else if (strncmp(line, "C ", 2) == 0) {
 		/* Reply to CAPABILITY command we sent, ignore it */
 		client->proxy_state = IMAP_PROXY_STATE_CAPABILITY;
+		if (imap_client->proxy_no_pipelining) {
+			str = t_str_new(128);
+			if (proxy_write_login(imap_client, str) < 0) {
+				client_proxy_failed(client, TRUE);
+				return -1;
+			}
+			o_stream_nsend(output, str_data(str), str_len(str));
+		}
 		return 0;
 	} else if (strncasecmp(line, "I ", 2) == 0 ||
 		   strncasecmp(line, "* ID ", 5) == 0) {

Reply via email to