From: Brandon Long Date: Tue, 12 Jun 2018 21:11:47 +0000 (-0700) Subject: Support for using OAUTHBEARER for smtp. X-Git-Tag: 2019-10-25~666^2~4 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1a9fca07a1b7deb67daf4962756be657debc23b1;p=neomutt 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/smtp.c b/smtp.c index 3d1cc860f..21977acec 100644 --- 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;