# HG changeset patch # User Timo Sirainen # Date 1296493318 -7200 # Node ID 4244c828b59d806788304e7da887cc60e94d37ff # Parent b9baa9db8950fc81eec37fabac222d85ab757a5d imapc: Don't use AUTHENTICATE PLAIN if server doesn't advertise AUTH=PLAIN capability. diff -r b9baa9db8950 -r 4244c828b59d src/lib-storage/index/imapc/imapc-client.c --- a/src/lib-storage/index/imapc/imapc-client.c Mon Jan 31 19:01:22 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-client.c Mon Jan 31 19:01:58 2011 +0200 @@ -25,6 +25,7 @@ { "QRESYNC", IMAPC_CAPABILITY_QRESYNC }, { "IDLE", IMAPC_CAPABILITY_IDLE }, { "UIDPLUS", IMAPC_CAPABILITY_UIDPLUS }, + { "AUTH=PLAIN", IMAPC_CAPABILITY_AUTH_PLAIN }, { "IMAP4REV1", IMAPC_CAPABILITY_IMAP4REV1 }, { NULL, 0 } diff -r b9baa9db8950 -r 4244c828b59d src/lib-storage/index/imapc/imapc-client.h --- a/src/lib-storage/index/imapc/imapc-client.h Mon Jan 31 19:01:22 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-client.h Mon Jan 31 19:01:58 2011 +0200 @@ -14,6 +14,7 @@ IMAPC_CAPABILITY_QRESYNC = 0x04, IMAPC_CAPABILITY_IDLE = 0x08, IMAPC_CAPABILITY_UIDPLUS = 0x10, + IMAPC_CAPABILITY_AUTH_PLAIN = 0x20, IMAPC_CAPABILITY_IMAP4REV1 = 0x400000000 }; diff -r b9baa9db8950 -r 4244c828b59d src/lib-storage/index/imapc/imapc-connection.c --- a/src/lib-storage/index/imapc/imapc-connection.c Mon Jan 31 19:01:22 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-connection.c Mon Jan 31 19:01:58 2011 +0200 @@ -514,24 +514,6 @@ return ret; } -static void -imapc_connection_capability_cb(const struct imapc_command_reply *reply, - void *context) -{ - struct imapc_connection *conn = context; - - if (reply->state != IMAPC_COMMAND_STATE_OK) { - imapc_connection_input_error(conn, - "Failed to get capabilities: %s", reply->text_full); - } else if (conn->capabilities == 0) { - imapc_connection_input_error(conn, - "Capabilities not returned by server"); - } else { - timeout_remove(&conn->to); - imapc_connection_set_state(conn, IMAPC_CONNECTION_STATE_DONE); - } -} - static void imapc_connection_login_cb(const struct imapc_command_reply *reply, void *context) { @@ -543,14 +525,6 @@ return; } - if (conn->capabilities == 0) { - /* server didn't send capabilities automatically. - request them manually before we're done. */ - imapc_connection_cmd(conn, "CAPABILITY", - imapc_connection_capability_cb, conn); - return; - } - timeout_remove(&conn->to); imapc_connection_set_state(conn, IMAPC_CONNECTION_STATE_DONE); } @@ -578,23 +552,14 @@ return str_c(out); } -static int imapc_connection_input_banner(struct imapc_connection *conn) +static void imapc_connection_authenticate(struct imapc_connection *conn) { const struct imapc_client_settings *set = &conn->client->set; - const struct imap_arg *imap_args; - const char *cmd, *key, *value; - int ret; - - if ((ret = imapc_connection_read_line(conn, &imap_args)) <= 0) - return ret; + const char *cmd; - if (imapc_connection_handle_imap_resp_text(conn, imap_args, - &key, &value) < 0) - return -1; - imapc_connection_set_state(conn, IMAPC_CONNECTION_STATE_AUTHENTICATING); - - if (set->master_user == NULL && - need_literal(set->username) && need_literal(set->password)) { + if ((set->master_user == NULL && + need_literal(set->username) && need_literal(set->password)) || + (conn->capabilities & IMAPC_CAPABILITY_AUTH_PLAIN) == 0) { /* We can use LOGIN command */ imapc_connection_cmdf(conn, imapc_connection_login_cb, conn, "LOGIN %s %s", @@ -610,6 +575,46 @@ imapc_connection_cmd(conn, cmd, imapc_connection_login_cb, conn); } +} + +static void +imapc_connection_capability_cb(const struct imapc_command_reply *reply, + void *context) +{ + struct imapc_connection *conn = context; + + if (reply->state != IMAPC_COMMAND_STATE_OK) { + imapc_connection_input_error(conn, + "Failed to get capabilities: %s", reply->text_full); + } else if (conn->capabilities == 0) { + imapc_connection_input_error(conn, + "Capabilities not returned by server"); + } else { + imapc_connection_authenticate(conn); + } +} + +static int imapc_connection_input_banner(struct imapc_connection *conn) +{ + const struct imap_arg *imap_args; + const char *key, *value; + int ret; + + if ((ret = imapc_connection_read_line(conn, &imap_args)) <= 0) + return ret; + + if (imapc_connection_handle_imap_resp_text(conn, imap_args, + &key, &value) < 0) + return -1; + imapc_connection_set_state(conn, IMAPC_CONNECTION_STATE_AUTHENTICATING); + + if (conn->capabilities == 0) { + /* capabilities weren't sent in the banner. ask for them. */ + imapc_connection_cmd(conn, "CAPABILITY", + imapc_connection_capability_cb, conn); + } else { + imapc_connection_authenticate(conn); + } conn->input_callback = NULL; imapc_connection_input_reset(conn); return 1; @@ -618,7 +623,7 @@ static int imapc_connection_input_untagged(struct imapc_connection *conn) { const struct imap_arg *imap_args; - const char *name; + const char *name, *value; struct imapc_untagged_reply reply; int ret; @@ -663,6 +668,10 @@ &reply.resp_text_key, &reply.resp_text_value) < 0) return -1; + } else if (strcasecmp(name, "CAPABILITY") == 0) { + value = imap_args_to_str(imap_args); + if (imapc_connection_parse_capability(conn, value) < 0) + return -1; } reply.name = name;