From f2f7c020778f0d36f3c3da959e84011b5c39519d Mon Sep 17 00:00:00 2001 From: Pietro Cerutti Date: Thu, 24 May 2018 11:51:28 +0100 Subject: [PATCH] Honour SASL-IR IMAP capability in SASL PLAIN * Honour SASL-IR IMAP capability * Tidy auth plain logic * Keep the buffer static Fixes #1211 --- conn/sasl_plain.c | 10 +++++++--- imap/auth_plain.c | 28 +++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/conn/sasl_plain.c b/conn/sasl_plain.c index 55b149948..acbfa7325 100644 --- a/conn/sasl_plain.c +++ b/conn/sasl_plain.c @@ -44,7 +44,8 @@ * This function can be used to build a protocol-specific SASL Response message * using the PLAIN mechanism. The protocol specific command is given in the cmd * parameter. The function appends a space, encodes the string derived from - * authz\0user\0pass using base64 encoding, and stores the result in buf. + * authz\0user\0pass using base64 encoding, and stores the result in buf. If + * cmd is either NULL or the empty string, the initial space is skipped. * * authz, user, and pass can each be up to 255 bytes, making up for a 765 bytes * string. Add the two NULL bytes in between plus one at the end and we get @@ -54,7 +55,7 @@ size_t mutt_sasl_plain_msg(char *buf, size_t buflen, const char *cmd, const char *authz, const char *user, const char *pass) { char tmp[768]; - size_t len; + size_t len = 0; size_t tmplen; if (!user || !*user || !pass || !*pass) @@ -62,7 +63,10 @@ size_t mutt_sasl_plain_msg(char *buf, size_t buflen, const char *cmd, tmplen = snprintf(tmp, sizeof(tmp), "%s%c%s%c%s", NONULL(authz), '\0', user, '\0', pass); - len = snprintf(buf, buflen, "%s ", cmd); + if (cmd && *cmd) + { + len = snprintf(buf, buflen, "%s ", cmd); + } len += mutt_b64_encode(buf + len, tmp, tmplen, buflen - len); return len; } diff --git a/imap/auth_plain.c b/imap/auth_plain.c index 4b0d6695f..8d2be3eed 100644 --- a/imap/auth_plain.c +++ b/imap/auth_plain.c @@ -47,6 +47,7 @@ enum ImapAuthRes imap_auth_plain(struct ImapData *idata, const char *method) { int rc; enum ImapAuthRes res = IMAP_AUTH_SUCCESS; + static const char auth_plain_cmd[] = "AUTHENTICATE PLAIN"; char buf[STRING]; if (mutt_account_getuser(&idata->conn->account) < 0) @@ -56,10 +57,31 @@ enum ImapAuthRes imap_auth_plain(struct ImapData *idata, const char *method) mutt_message(_("Logging in...")); - mutt_sasl_plain_msg(buf, STRING, "AUTHENTICATE PLAIN", idata->conn->account.user, - idata->conn->account.user, idata->conn->account.pass); + /* Prepare full AUTHENTICATE PLAIN message */ + mutt_sasl_plain_msg(buf, sizeof(buf), auth_plain_cmd, + idata->conn->account.user, idata->conn->account.user, + idata->conn->account.pass); + + if (mutt_bit_isset(idata->capabilities, SASL_IR)) + { + imap_cmd_start(idata, buf); + } + else + { + /* Split the message so we send AUTHENTICATE PLAIN first, and the + * credentials after the first command continuation request */ + buf[sizeof(auth_plain_cmd) - 1] = '\0'; + imap_cmd_start(idata, buf); + do + rc = imap_cmd_step(idata); + while (rc == IMAP_CMD_CONTINUE); + if (rc == IMAP_CMD_RESPOND) + { + mutt_socket_send(idata->conn, buf + sizeof(auth_plain_cmd)); + mutt_socket_send(idata->conn, "\r\n"); + } + } - imap_cmd_start(idata, buf); do rc = imap_cmd_step(idata); while (rc == IMAP_CMD_CONTINUE); -- 2.40.0