+
+ mutt_message (_("Authenticating (%s)..."), mech);
+
+ snprintf (buf, sizeof (buf), "AUTHENTICATE %s", mech);
+ imap_cmd_start (idata, buf);
+ irc = IMAP_CMD_CONTINUE;
+
+ /* looping protocol */
+ while (rc == SASL_CONTINUE || olen > 0) {
+ do
+ irc = imap_cmd_step (idata);
+ while (irc == IMAP_CMD_CONTINUE);
+
+ if (method && irc == IMAP_CMD_NO) {
+ sasl_dispose (&saslconn);
+ return IMAP_AUTH_UNAVAIL;
+ }
+
+ if (irc == IMAP_CMD_BAD || irc == IMAP_CMD_NO)
+ goto bail;
+
+ if (irc == IMAP_CMD_RESPOND) {
+ if (sasl_decode64(idata->cmd.buf.data + 2, idata->cmd.buf.len - 2, buf,
+ LONG_STRING - 1, &len) != SASL_OK)
+ {
+ goto bail;
+ }
+ }
+
+ /* client-start is only available with the SASL-IR extension, but
+ * SASL 2.1 seems to want to use it regardless, at least for DIGEST
+ * fast reauth. Override if the server sent an initial continuation */
+ if (!client_start || buf[0]) {
+ do {
+ rc = sasl_client_step (saslconn, buf, len, &interaction, &pc, &olen);
+ if (rc == SASL_INTERACT)
+ mutt_sasl_interact (interaction);
+ }
+ while (rc == SASL_INTERACT);
+ }
+ else
+ client_start = 0;
+
+ /* send out response, or line break if none needed */
+ if (olen) {
+ if (sasl_encode64 (pc, olen, buf, sizeof (buf), &olen) != SASL_OK) {
+ goto bail;
+ }
+ }
+
+ if (irc == IMAP_CMD_RESPOND) {
+ m_strcpy(buf + olen, sizeof(buf) - olen, "\r\n");
+ mutt_socket_write (idata->conn, buf);