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) {