From: Brandon Long Date: Tue, 12 Jun 2018 21:11:47 +0000 (-0700) Subject: Support for using OAUTHBEARER for smtp. X-Git-Tag: mutt-1-11-rel~141 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fcd333986c0d15dec67870b7b74fef0e00e8c28b;p=mutt Support for using OAUTHBEARER for smtp. This also means a bunch of smtp auth stuff is now compiled in by default (with --enable-smtp) without having sasl --- diff --git a/init.h b/init.h index 44d7fabd..983fde4b 100644 --- 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 1d147a5a..0948af0a 100644 --- 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; +}