summaryrefslogtreecommitdiffstats
path: root/account.c
diff options
context:
space:
mode:
authorBrandon Long <blong@fiction.net>2018-06-26 15:42:08 -0700
committerKevin McCarthy <kevin@8t8.us>2018-07-16 19:21:45 -0700
commit98cc42365ac97b0dfeafadf5561043e06744fcf6 (patch)
tree9c82c0088a9cfe90ae6c578811eef6fbd7954fe2 /account.c
parent363c3a95a8c5ed55a4ab8618363aa848453f3d19 (diff)
Improve OAUTHBEARER support.
Move token refresh commands to their own config variables. Consolidate code for refreshing tokens and generating the SASL OAUTHBEARER argument in account.c. Add support for OAUTHBEARER to pop. Fix pop_auth_oauth() mutt_from_base64() call from 1.10.1 release.
Diffstat (limited to 'account.c')
-rw-r--r--account.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/account.c b/account.c
index ce71180d..9e7f9154 100644
--- a/account.c
+++ b/account.c
@@ -238,3 +238,83 @@ void mutt_account_unsetpass (ACCOUNT* account)
{
account->flags &= ~MUTT_ACCT_PASS;
}
+
+/* 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.
+ */
+char* mutt_account_getoauthbearer (ACCOUNT* account)
+{
+ 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;
+
+ /* The oauthbearer token includes the login */
+ if (mutt_account_getlogin (account))
+ return NULL;
+
+#ifdef USE_IMAP
+ if ((account->type == MUTT_ACCT_TYPE_IMAP) && ImapOauthRefreshCmd)
+ cmd = ImapOauthRefreshCmd;
+#endif
+#ifdef USE_POP
+ else if ((account->type == MUTT_ACCT_TYPE_POP) && PopOauthRefreshCmd)
+ cmd = PopOauthRefreshCmd;
+#endif
+#ifdef USE_SMTP
+ else if ((account->type == MUTT_ACCT_TYPE_SMTP) && SmtpOauthRefreshCmd)
+ cmd = SmtpOauthRefreshCmd;
+#endif
+
+ if (cmd == NULL)
+ {
+ mutt_error (_("mutt_account_getoauthbearer: No OAUTH refresh command defined"));
+ return NULL;
+ }
+
+ if ((pid = mutt_create_filter (cmd, NULL, &fp, NULL)) < 0)
+ {
+ mutt_perror _("mutt_account_getoauthbearer: Unable to run refresh command");
+ return NULL;
+ }
+
+ /* read line */
+ token = mutt_read_line (NULL, &token_size, fp, NULL, 0);
+ safe_fclose (&fp);
+ mutt_wait_filter (pid);
+
+ if (token == NULL || *token == '\0')
+ {
+ mutt_error (_("mutt_account_getoauthbearer: Command returned empty string"));
+ FREE (&token);
+ return NULL;
+ }
+
+ /* 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);
+
+ snprintf (oauthbearer, oalen,
+ "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;
+}