diff options
author | Kevin McCarthy <kevin@8t8.us> | 2023-03-06 18:55:06 -0800 |
---|---|---|
committer | Kevin McCarthy <kevin@8t8.us> | 2023-03-12 19:29:32 -0700 |
commit | 216dd145d41dd079fc9676fd2eb09ad16097627d (patch) | |
tree | de5ae5a117b76991124f1438b65017c6b0ede6d0 | |
parent | 5df86199463b5cf893fb6a37457fa02804d3b02a (diff) |
Improve smtp oauth authentication.
Split XOAUTH2 to use two steps.
This follows the microsoft.com documentation example for smtp. Since
office365 is the main site using XOAUTH2 now, it's better to match
their documentation.
It also matches msmtp's behavior, which probably means somewhere or
another needs it that way.
At the same time, improve response code checking. Mutt was using
smtp_get_resp() before, which returns 0 for both a ready and success
response code. Make sure it's a success response code when done
authenticating.
-rw-r--r-- | smtp.c | 37 |
1 files changed, 31 insertions, 6 deletions
@@ -849,8 +849,9 @@ fail: /* smtp_auth_oauth: AUTH=OAUTHBEARER support. See RFC 7628 */ static int smtp_auth_oauth (CONNECTION* conn, int xoauth2) { - int rc = SMTP_AUTH_FAIL; + int rc = SMTP_AUTH_FAIL, smtp_rc; BUFFER *bearertoken = NULL, *authline = NULL; + BUFFER *input_buf = NULL, *smtp_response_buf = NULL; const char *authtype; authtype = xoauth2 ? "XOAUTH2" : "OAUTHBEARER"; @@ -862,16 +863,41 @@ static int smtp_auth_oauth (CONNECTION* conn, int xoauth2) bearertoken = mutt_buffer_pool_get (); authline = mutt_buffer_pool_get (); + input_buf = mutt_buffer_pool_get (); + smtp_response_buf = mutt_buffer_pool_get (); /* We get the access token from the smtp_oauth_refresh_command */ if (mutt_account_getoauthbearer (&conn->account, bearertoken, xoauth2)) goto cleanup; - mutt_buffer_printf (authline, "AUTH %s %s\r\n", authtype, mutt_b2s (bearertoken)); + if (xoauth2) + { + mutt_buffer_printf (authline, "AUTH %s\r\n", authtype); + if (mutt_socket_write (conn, mutt_b2s (authline)) == -1) + goto cleanup; + if (smtp_get_auth_response (conn, input_buf, &smtp_rc, smtp_response_buf) < 0) + goto saslcleanup; + if (smtp_rc != smtp_ready) + goto saslcleanup; + + mutt_buffer_printf (authline, "%s\r\n", mutt_b2s (bearertoken)); + } + else + { + mutt_buffer_printf (authline, "AUTH %s %s\r\n", authtype, mutt_b2s (bearertoken)); + } if (mutt_socket_write (conn, mutt_b2s (authline)) == -1) goto cleanup; - if (smtp_get_resp (conn) != 0) + if (smtp_get_auth_response (conn, input_buf, &smtp_rc, smtp_response_buf) < 0) + goto saslcleanup; + if (!smtp_success (smtp_rc)) + goto saslcleanup; + + rc = SMTP_AUTH_SUCCESS; + +saslcleanup: + if (rc != SMTP_AUTH_SUCCESS) { /* The error response was in SASL continuation, so continue the SASL * to cause a failure and exit SASL input. See RFC 7628 3.2.3 @@ -879,13 +905,12 @@ static int smtp_auth_oauth (CONNECTION* conn, int xoauth2) */ mutt_socket_write (conn, "AQ==\r\n"); smtp_get_resp (conn); - goto cleanup; } - rc = SMTP_AUTH_SUCCESS; - cleanup: mutt_buffer_pool_release (&bearertoken); mutt_buffer_pool_release (&authline); + mutt_buffer_pool_release (&input_buf); + mutt_buffer_pool_release (&smtp_response_buf); return rc; } |