]> granicus.if.org Git - mutt/commitdiff
Support for using OAUTHBEARER for smtp.
authorBrandon Long <blong@fiction.net>
Tue, 12 Jun 2018 21:11:47 +0000 (14:11 -0700)
committerKevin McCarthy <kevin@8t8.us>
Thu, 14 Jun 2018 01:42:57 +0000 (09:42 +0800)
This also means a bunch of smtp auth stuff is now compiled in by
default (with --enable-smtp) without having sasl

init.h
smtp.c

diff --git a/init.h b/init.h
index 44d7fabd26fcbc005a05fcd1137f97c4593d3b70..983fde4bfcbefb6045f2ab944ebd729f8f7b2e09 100644 (file)
--- a/init.h
+++ b/init.h
@@ -3333,7 +3333,6 @@ struct option_t MuttVars[] = {
   ** (S/MIME only)
   */
 #ifdef USE_SMTP
-# ifdef USE_SASL
   { "smtp_authenticators", DT_STR, R_NONE, UL &SmtpAuthenticators, UL 0 },
   /*
   ** .pp
@@ -3350,7 +3349,6 @@ struct option_t MuttVars[] = {
   ** set smtp_authenticators="digest-md5:cram-md5"
   ** .te
   */
-# endif /* USE_SASL */
   { "smtp_pass",       DT_STR,  R_NONE, UL &SmtpPass, UL 0 },
   /*
   ** .pp
diff --git a/smtp.c b/smtp.c
index 1d147a5af51daab55657403cf11035144642c779..0948af0afc55fdefa6a46f6ea8d2c85ce5f38c8d 100644 (file)
--- a/smtp.c
+++ b/smtp.c
@@ -66,8 +66,9 @@ enum {
   CAPMAX
 };
 
-#ifdef USE_SASL
 static int smtp_auth (CONNECTION* conn);
+static int smtp_auth_oauth (CONNECTION* conn);
+#ifdef USE_SASL
 static int smtp_auth_sasl (CONNECTION* conn, const char* mechanisms);
 #endif
 
@@ -495,19 +496,12 @@ static int smtp_open (CONNECTION* conn)
       return -1;
     }
 
-#ifdef USE_SASL
     return smtp_auth (conn);
-#else
-    mutt_error (_("SMTP authentication requires SASL"));
-    mutt_sleep (1);
-    return -1;
-#endif /* USE_SASL */
   }
 
   return 0;
 }
 
-#ifdef USE_SASL
 static int smtp_auth (CONNECTION* conn)
 {
   int r = SMTP_AUTH_UNAVAIL;
@@ -528,21 +522,41 @@ static int smtp_auth (CONNECTION* conn)
 
       dprint (2, (debugfile, "smtp_authenticate: 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);
+       mutt_sleep (1);
+       continue;
+#endif
+      }
       if (r == SMTP_AUTH_FAIL && delim)
       {
-        mutt_error (_("%s authentication failed, trying next method"), method);
-        mutt_sleep (1);
+       mutt_error (_("%s authentication failed, trying next method"), method);
+       mutt_sleep (1);
       }
       else if (r != SMTP_AUTH_UNAVAIL)
-        break;
+       break;
     }
 
     FREE (&methods);
   }
   else
+  {
+#ifdef USE_SASL
     r = smtp_auth_sasl (conn, AuthMechs);
+#else
+    mutt_error (_("SMTP authentication requires SASL"));
+    mutt_sleep (1);
+    r = SMTP_AUTH_UNAVAIL;
+#endif
+  }
 
   if (r != SMTP_AUTH_SUCCESS)
     mutt_account_unsetpass (&conn->account);
@@ -561,6 +575,7 @@ static int smtp_auth (CONNECTION* conn)
   return r == SMTP_AUTH_SUCCESS ? 0 : -1;
 }
 
+#ifdef USE_SASL
 static int smtp_auth_sasl (CONNECTION* conn, const char* mechlist)
 {
   sasl_conn_t* saslconn;
@@ -663,3 +678,63 @@ fail:
   return SMTP_AUTH_FAIL;
 }
 #endif /* USE_SASL */
+
+
+/* smtp_auth_oauth: AUTH=OAUTHBEARER support. See RFC 7628 */
+static int smtp_auth_oauth (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 = safe_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 = safe_malloc (ilen);
+  ibuf[0] = '\0';
+
+  safe_strcat (ibuf, ilen, "AUTH OAUTHBEARER ");
+  len = strlen(ibuf);
+  
+  mutt_to_base64 ((unsigned char*) (ibuf + len),
+                  (unsigned char*) oauth_buf, strlen (oauth_buf),
+                 ilen - len);
+  safe_strcat (ibuf, ilen, "\r\n");
+
+  rc = mutt_socket_write (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;
+}