summaryrefslogtreecommitdiffstats
path: root/account.c
diff options
context:
space:
mode:
authorKevin McCarthy <kevin@8t8.us>2020-06-11 16:11:36 -0700
committerKevin McCarthy <kevin@8t8.us>2020-06-13 14:44:17 -0700
commitc7a872d1eeea39df148396869c1cbbc0fa26552f (patch)
tree0fa80c6f4e6e0a7f8693ee087f18b3870a16b718 /account.c
parent5b844328bb7d7fb0357328bed002e7672f9b9e2a (diff)
Add basic XOAUTH2 support.
This still relies on an external script to obtain the resource access token. Since XOAUTH2 should be slowly going away, use the same refresh_commands as with OAUTHBEARER. Unlike OAUTHBEARER, XOAUTH2 must be explicitly added to the $imap/smtp/pop_authenticators list. To keep the shared functions simpler, convert them to use buffers. RFC 7628 indicates that upon authentication failure the clients should be sending an BASE 64 encoded '^a' ("AQ=="), to terminate the SASL session, so change all the handlers to do that and read the following response. The RFC doesn't comment about a line terminator being required, but I assume it is, so add that too.
Diffstat (limited to 'account.c')
-rw-r--r--account.c56
1 files changed, 29 insertions, 27 deletions
diff --git a/account.c b/account.c
index a005fa86..28c0749b 100644
--- a/account.c
+++ b/account.c
@@ -241,25 +241,26 @@ void mutt_account_unsetpass (ACCOUNT* account)
/* mutt_account_getoauthbearer: call external command to generate the
* oauth refresh token for this ACCOUNT, then create and encode the
- * OAUTHBEARER token based on RFC 7628. Returns NULL on failure.
- * Resulting token is dynamically allocated and should be FREE'd by the
- * caller.
+ * OAUTHBEARER token based on RFC 7628.
+ *
+ * Returns 0 on success, -1 on failure.
+ *
+ * If xoauth2 is set, a deprecated XOAUTH2 token will be generated instead.
*/
-char* mutt_account_getoauthbearer (ACCOUNT* account)
+int mutt_account_getoauthbearer (ACCOUNT* account, BUFFER *authbearer, int xoauth2)
{
FILE *fp;
char *cmd = NULL;
char *token = NULL;
size_t token_size = 0;
- char *oauthbearer = NULL;
- size_t oalen;
- char *encoded_token = NULL;
- size_t encoded_len;
pid_t pid;
+ BUFFER *unencoded_bearertoken = NULL;
+
+ mutt_buffer_clear (authbearer);
/* The oauthbearer token includes the login */
if (mutt_account_getlogin (account))
- return NULL;
+ return -1;
#ifdef USE_IMAP
if ((account->type == MUTT_ACCT_TYPE_IMAP) && ImapOauthRefreshCmd)
@@ -282,13 +283,13 @@ char* mutt_account_getoauthbearer (ACCOUNT* account)
your $*_oauth_refresh_command's are defined."
*/
mutt_error (_("mutt_account_getoauthbearer: No OAUTH refresh command defined"));
- return NULL;
+ return -1;
}
if ((pid = mutt_create_filter (cmd, NULL, &fp, NULL)) < 0)
{
mutt_perror _("mutt_account_getoauthbearer: Unable to run refresh command");
- return NULL;
+ return -1;
}
/* read line */
@@ -300,26 +301,27 @@ char* mutt_account_getoauthbearer (ACCOUNT* account)
{
mutt_error (_("mutt_account_getoauthbearer: Command returned empty string"));
FREE (&token);
- return NULL;
+ return -1;
}
- /* Determine the length of the keyed message digest, add 50 for
- * overhead.
- */
- oalen = strlen (account->login) + strlen (account->host) + strlen (token) + 50;
- oauthbearer = safe_malloc (oalen);
+ unencoded_bearertoken = mutt_buffer_pool_get ();
- snprintf (oauthbearer, oalen,
- "n,a=%s,\001host=%s\001port=%d\001auth=Bearer %s\001\001",
- account->login, account->host, account->port, token);
+ if (xoauth2)
+ mutt_buffer_printf (unencoded_bearertoken,
+ "user=%s\001auth=Bearer %s\001\001",
+ account->login, token);
+ else
+ mutt_buffer_printf (unencoded_bearertoken,
+ "n,a=%s,\001host=%s\001port=%d\001auth=Bearer %s\001\001",
+ account->login, account->host, account->port, token);
FREE (&token);
- encoded_len = strlen (oauthbearer) * 4 / 3 + 10;
- encoded_token = safe_malloc (encoded_len);
- mutt_to_base64 ((unsigned char*) encoded_token,
- (unsigned char*) oauthbearer, strlen (oauthbearer),
- encoded_len);
- FREE (&oauthbearer);
- return encoded_token;
+ mutt_buffer_to_base64 (authbearer,
+ (const unsigned char *) mutt_b2s (unencoded_bearertoken),
+ mutt_buffer_len (unencoded_bearertoken));
+
+ mutt_buffer_pool_release (&unencoded_bearertoken);
+
+ return 0;
}