NeoMutt  2022-04-29-249-gaae397
Teaching an old dog new tricks
DOXYGEN
auth_oauth.c
Go to the documentation of this file.
1
30#include "config.h"
31#include <stdbool.h>
32#include <stdio.h>
33#include "private.h"
34#include "mutt/lib.h"
35#include "config/lib.h"
36#include "core/lib.h"
37#include "conn/lib.h"
38#include "auth.h"
39#include "adata.h"
40#include "mutt_logging.h"
41
50 const char *method, bool xoauth2)
51{
52 char *ibuf = NULL;
53 char *oauthbearer = NULL;
54 const char *authtype = xoauth2 ? "XOAUTH2" : "OAUTHBEARER";
55 int ilen;
56 int rc;
57
58 /* For now, we only support SASL_IR also and over TLS */
59 if ((xoauth2 && !(adata->capabilities & IMAP_CAP_AUTH_XOAUTH2)) ||
60 (!xoauth2 && !(adata->capabilities & IMAP_CAP_AUTH_OAUTHBEARER)) ||
61 !(adata->capabilities & IMAP_CAP_SASL_IR) || (adata->conn->ssf == 0))
62 {
63 return IMAP_AUTH_UNAVAIL;
64 }
65
66 /* If they did not explicitly request or configure oauth then fail quietly */
67 const char *const c_imap_oauth_refresh_command = cs_subset_string(NeoMutt->sub, "imap_oauth_refresh_command");
68 if (!method && !c_imap_oauth_refresh_command)
69 return IMAP_AUTH_UNAVAIL;
70
71 // L10N: (%s) is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
72 mutt_message(_("Authenticating (%s)..."), authtype);
73
74 /* We get the access token from the imap_oauth_refresh_command */
75 oauthbearer = mutt_account_getoauthbearer(&adata->conn->account, xoauth2);
76 if (!oauthbearer)
77 return IMAP_AUTH_FAILURE;
78
79 ilen = mutt_str_len(oauthbearer) + 30;
80 ibuf = mutt_mem_malloc(ilen);
81 snprintf(ibuf, ilen, "AUTHENTICATE %s %s", authtype, oauthbearer);
82
83 /* This doesn't really contain a password, but the token is good for
84 * an hour, so suppress it anyways. */
85 rc = imap_exec(adata, ibuf, IMAP_CMD_PASS);
86
87 FREE(&oauthbearer);
88 FREE(&ibuf);
89
90 if (rc != IMAP_EXEC_SUCCESS)
91 {
92 /* The error response was in SASL continuation, so continue the SASL
93 * to cause a failure and exit SASL input. See RFC7628 3.2.3 */
94 mutt_socket_send(adata->conn, "\001");
95 rc = imap_exec(adata, ibuf, IMAP_CMD_NO_FLAGS);
96 }
97
98 if (rc == IMAP_EXEC_SUCCESS)
99 {
101 return IMAP_AUTH_SUCCESS;
102 }
103
104 // L10N: %s is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
105 mutt_error(_("%s authentication failed"), authtype);
106 return IMAP_AUTH_FAILURE;
107}
108
112enum ImapAuthRes imap_auth_oauth(struct ImapAccountData *adata, const char *method)
113{
114 return imap_auth_oauth_xoauth2(adata, method, false);
115}
116
120enum ImapAuthRes imap_auth_xoauth2(struct ImapAccountData *adata, const char *method)
121{
122 return imap_auth_oauth_xoauth2(adata, method, true);
123}
IMAP authenticator multiplexor.
ImapAuthRes
Results of IMAP Authentication.
Definition: auth.h:38
@ IMAP_AUTH_FAILURE
Authentication failed.
Definition: auth.h:40
@ IMAP_AUTH_SUCCESS
Authentication successful.
Definition: auth.h:39
@ IMAP_AUTH_UNAVAIL
Authentication method not permitted.
Definition: auth.h:41
enum ImapAuthRes imap_auth_xoauth2(struct ImapAccountData *adata, const char *method)
Authenticate an IMAP connection using XOAUTH2 - Implements ImapAuth::authenticate()
Definition: auth_oauth.c:120
enum ImapAuthRes imap_auth_oauth_xoauth2(struct ImapAccountData *adata, const char *method, bool xoauth2)
Authenticate an IMAP connection using OAUTHBEARER or XOAUTH2.
Definition: auth_oauth.c:49
enum ImapAuthRes imap_auth_oauth(struct ImapAccountData *adata, const char *method)
Authenticate an IMAP connection using OAUTHBEARER - Implements ImapAuth::authenticate()
Definition: auth_oauth.c:112
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Convenience wrapper for the config headers.
Connection Library.
char * mutt_account_getoauthbearer(struct ConnAccount *cac, bool xoauth2)
Get an OAUTHBEARER/XOAUTH2 token.
Definition: connaccount.c:195
Convenience wrapper for the core headers.
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Execute a command and wait for the response from the server.
Definition: command.c:1247
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:73
#define IMAP_CMD_PASS
Command contains a password. Suppress logging.
Definition: private.h:74
@ IMAP_EXEC_SUCCESS
Imap command executed or queued successfully.
Definition: private.h:84
#define IMAP_CAP_SASL_IR
SASL initial response draft.
Definition: private.h:136
#define IMAP_CAP_AUTH_XOAUTH2
AUTH=XOAUTH2, deprecated but used by OWA.
Definition: private.h:132
#define IMAP_CAP_AUTH_OAUTHBEARER
RFC7628: AUTH=OAUTHBEARER.
Definition: private.h:131
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:43
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
NeoMutt Logging.
Pop-specific Account data.
GUI display the mailboxes in a side panel.
#define mutt_socket_send(conn, buf)
Definition: socket.h:59
unsigned int ssf
Security strength factor, in bits (see notes)
Definition: connection.h:51
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:50
IMAP-specific Account data -.
Definition: adata.h:40
ImapCapFlags capabilities
Capability flags.
Definition: adata.h:55
struct Connection * conn
Connection to IMAP server.
Definition: adata.h:41
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39