diff options
Diffstat (limited to 'imap-send.c')
| -rw-r--r-- | imap-send.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/imap-send.c b/imap-send.c index 6c33318102..54dab627d6 100644 --- a/imap-send.c +++ b/imap-send.c @@ -139,6 +139,7 @@ enum CAPABILITY { LITERALPLUS, NAMESPACE, STARTTLS, + AUTH_PLAIN, AUTH_CRAM_MD5, AUTH_OAUTHBEARER, AUTH_XOAUTH2, @@ -150,6 +151,7 @@ static const char *cap_list[] = { "LITERAL+", "NAMESPACE", "STARTTLS", + "AUTH=PLAIN", "AUTH=CRAM-MD5", "AUTH=OAUTHBEARER", "AUTH=XOAUTH2", @@ -851,6 +853,38 @@ static char hexchar(unsigned int b) } #define ENCODED_SIZE(n) (4 * DIV_ROUND_UP((n), 3)) +static char *plain_base64(const char *user, const char *pass) +{ + struct strbuf raw = STRBUF_INIT; + int b64_len; + char *b64; + + /* + * Compose the PLAIN string + * + * The username and password are combined to one string and base64 encoded. + * "\0user\0pass" + * + * The method has been described in RFC4616. + * + * https://datatracker.ietf.org/doc/html/rfc4616 + */ + strbuf_addch(&raw, '\0'); + strbuf_addstr(&raw, user); + strbuf_addch(&raw, '\0'); + strbuf_addstr(&raw, pass); + + b64 = xmallocz(ENCODED_SIZE(raw.len)); + b64_len = EVP_EncodeBlock((unsigned char *)b64, (unsigned char *)raw.buf, raw.len); + strbuf_release(&raw); + + if (b64_len < 0) { + free(b64); + return NULL; + } + return b64; +} + static char *cram(const char *challenge_64, const char *user, const char *pass) { int i, resp_len, encoded_len, decoded_len; @@ -947,6 +981,26 @@ static char *xoauth2_base64(const char *user, const char *access_token) return b64; } +static int auth_plain(struct imap_store *ctx, const char *prompt UNUSED) +{ + int ret; + char *b64; + + b64 = plain_base64(ctx->cfg->user, ctx->cfg->pass); + if (!b64) + return error("PLAIN: base64 encoding failed"); + + /* Send the base64-encoded response */ + ret = socket_write(&ctx->imap->buf.sock, b64, strlen(b64)); + if (ret != (int)strlen(b64)) { + free(b64); + return error("IMAP error: sending PLAIN response failed"); + } + + free(b64); + return 0; +} + static int auth_cram_md5(struct imap_store *ctx, const char *prompt) { int ret; @@ -1007,6 +1061,7 @@ static int auth_xoauth2(struct imap_store *ctx, const char *prompt UNUSED) #else +#define auth_plain NULL #define auth_cram_md5 NULL #define auth_oauthbearer NULL #define auth_xoauth2 NULL @@ -1219,7 +1274,10 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, const c server_fill_credential(srvc, &cred); if (srvc->auth_method) { - if (!strcmp(srvc->auth_method, "CRAM-MD5")) { + if (!strcmp(srvc->auth_method, "PLAIN")) { + if (try_auth_method(srvc, ctx, imap, "PLAIN", AUTH_PLAIN, auth_plain)) + goto bail; + } else if (!strcmp(srvc->auth_method, "CRAM-MD5")) { if (try_auth_method(srvc, ctx, imap, "CRAM-MD5", AUTH_CRAM_MD5, auth_cram_md5)) goto bail; } else if (!strcmp(srvc->auth_method, "OAUTHBEARER")) { |
