aboutsummaryrefslogtreecommitdiffstats
path: root/imap-send.c
diff options
context:
space:
mode:
Diffstat (limited to 'imap-send.c')
-rw-r--r--imap-send.c60
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")) {