]> granicus.if.org Git - neomutt/commitdiff
Support for using OAUTHBEARER for smtp.
authorBrandon Long <blong@fiction.net>
Tue, 12 Jun 2018 21:11:47 +0000 (14:11 -0700)
committerRichard Russon <rich@flatcap.org>
Tue, 12 Jun 2018 21:11:47 +0000 (14:11 -0700)
This also means a bunch of smtp auth stuff is now compiled in by
default (with --enable-smtp) without having sasl

smtp.c

diff --git a/smtp.c b/smtp.c
index 3d1cc860fbb44800c4db67d79f5dc5cfa276be24..21977acecc87373a166e0ce20303233d2decf81d 100644 (file)
--- a/smtp.c
+++ b/smtp.c
@@ -501,6 +501,62 @@ fail:
   FREE(&buf);
   return SMTP_AUTH_FAIL;
 }
+#endif
+
+/* smtp_auth_oauth: AUTH=OAUTHBEARER support. See RFC 7628 */
+static int smtp_auth_oauth(struct Connection *conn)
+{
+  char *ibuf = NULL;
+  char *oauth_buf = NULL;
+  int len, ilen, oalen;
+  int rc;
+
+  mutt_message(_("Authenticating (OAUTHBEARER)..."));
+
+  /* get auth info */
+  if (mutt_account_getlogin(&conn->account))
+    return SMTP_AUTH_FAIL;
+
+  /* We get the access token from the "smtp_pass" field */
+  if (mutt_account_getpass(&conn->account))
+    return SMTP_AUTH_FAIL;
+
+  /* Determine the length of the keyed message digest, add 50 for
+   * overhead.
+   */
+  oalen = strlen(conn->account.user) + strlen(conn->account.host) +
+          strlen(conn->account.pass) + 50;
+  oauth_buf = mutt_mem_malloc(oalen);
+
+  snprintf(oauth_buf, oalen, "n,a=%s,\001host=%s\001port=%d\001auth=Bearer %s\001\001",
+           conn->account.user, conn->account.host, conn->account.port,
+           conn->account.pass);
+
+  /* ibuf must be long enough to store the base64 encoding of
+   * oauth_buf, plus the additional debris.
+   */
+
+  ilen = strlen(oauth_buf) * 2 + 30;
+  ibuf = mutt_mem_malloc(ilen);
+  ibuf[0] = '\0';
+
+  mutt_str_strcat(ibuf, ilen, "AUTH OAUTHBEARER ");
+  len = strlen(ibuf);
+
+  mutt_b64_encode(oauth_buf, strlen(oauth_buf), (ibuf + len), ilen - len);
+  mutt_str_strcat(ibuf, ilen, "\r\n");
+
+  rc = mutt_socket_send(conn, ibuf);
+  FREE(&oauth_buf);
+  FREE(&ibuf);
+
+  if (rc == -1)
+    return SMTP_AUTH_FAIL;
+  if (smtp_get_resp(conn) != 0)
+    return SMTP_AUTH_FAIL;
+
+  return SMTP_AUTH_SUCCESS;
+}
 
 /**
  * smtp_auth - Authenticate to an SMTP server
@@ -528,7 +584,19 @@ static int smtp_auth(struct Connection *conn)
 
       mutt_debug(2, "Trying method %s\n", method);
 
-      r = smtp_auth_sasl(conn, method);
+      if (!strcmp(method, "oauthbearer"))
+      {
+        r = smtp_auth_oauth(conn);
+      }
+      else
+      {
+#ifdef USE_SASL
+        r = smtp_auth_sasl(conn, method);
+#else
+        mutt_error(_("SMTP authentication method %s requires SASL"), method);
+        continue;
+#endif
+      }
 
       if (r == SMTP_AUTH_FAIL && delim)
       {
@@ -541,7 +609,14 @@ static int smtp_auth(struct Connection *conn)
     FREE(&methods);
   }
   else
+  {
+#ifdef USE_SASL
     r = smtp_auth_sasl(conn, AuthMechs);
+#else
+    mutt_error(_("SMTP authentication requires SASL"));
+    r = SMTP_AUTH_UNAVAIL;
+#endif
+  }
 
   if (r != SMTP_AUTH_SUCCESS)
     mutt_account_unsetpass(&conn->account);
@@ -558,8 +633,7 @@ static int smtp_auth(struct Connection *conn)
   return (r == SMTP_AUTH_SUCCESS) ? 0 : -1;
 }
 
-#else  /* USE_SASL */
-
+#ifdef USE_SASL
 /**
  * smtp_auth_plain - Authenticate using plain text
  * @param conn SMTP Connection
@@ -685,11 +759,10 @@ static int smtp_open(struct Connection *conn, bool esmtp)
       return -1;
     }
 
-#ifdef USE_SASL
     return smtp_auth(conn);
-#else
+#ifdef USE_SASL
     return smtp_auth_plain(conn);
-#endif /* USE_SASL */
+#endif
   }
 
   return 0;