NeoMutt  2021-10-29-43-g6b8931
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 #include "mutt_socket.h"
42 
51  const char *method, bool xoauth2)
52 {
53  char *ibuf = NULL;
54  char *oauthbearer = NULL;
55  const char *authtype = xoauth2 ? "XOAUTH2" : "OAUTHBEARER";
56  int ilen;
57  int rc;
58 
59  /* For now, we only support SASL_IR also and over TLS */
60  if ((xoauth2 && !(adata->capabilities & IMAP_CAP_AUTH_XOAUTH2)) ||
61  (!xoauth2 && !(adata->capabilities & IMAP_CAP_AUTH_OAUTHBEARER)) ||
62  !(adata->capabilities & IMAP_CAP_SASL_IR) || (adata->conn->ssf == 0))
63  {
64  return IMAP_AUTH_UNAVAIL;
65  }
66 
67  /* If they did not explicitly request or configure oauth then fail quietly */
68  const char *const c_imap_oauth_refresh_command =
69  cs_subset_string(NeoMutt->sub, "imap_oauth_refresh_command");
70  if (!method && !c_imap_oauth_refresh_command)
71  return IMAP_AUTH_UNAVAIL;
72 
73  // L10N: (%s) is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
74  mutt_message(_("Authenticating (%s)..."), authtype);
75 
76  /* We get the access token from the imap_oauth_refresh_command */
77  oauthbearer = mutt_account_getoauthbearer(&adata->conn->account, xoauth2);
78  if (!oauthbearer)
79  return IMAP_AUTH_FAILURE;
80 
81  ilen = mutt_str_len(oauthbearer) + 30;
82  ibuf = mutt_mem_malloc(ilen);
83  snprintf(ibuf, ilen, "AUTHENTICATE %s %s", authtype, oauthbearer);
84 
85  /* This doesn't really contain a password, but the token is good for
86  * an hour, so suppress it anyways. */
87  rc = imap_exec(adata, ibuf, IMAP_CMD_PASS);
88 
89  FREE(&oauthbearer);
90  FREE(&ibuf);
91 
92  if (rc != IMAP_EXEC_SUCCESS)
93  {
94  /* The error response was in SASL continuation, so continue the SASL
95  * to cause a failure and exit SASL input. See RFC7628 3.2.3 */
96  mutt_socket_send(adata->conn, "\001");
97  rc = imap_exec(adata, ibuf, IMAP_CMD_NO_FLAGS);
98  }
99 
100  if (rc == IMAP_EXEC_SUCCESS)
101  {
103  return IMAP_AUTH_SUCCESS;
104  }
105 
106  // L10N: %s is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
107  mutt_error(_("%s authentication failed"), authtype);
108  return IMAP_AUTH_FAILURE;
109 }
110 
114 enum ImapAuthRes imap_auth_oauth(struct ImapAccountData *adata, const char *method)
115 {
116  return imap_auth_oauth_xoauth2(adata, method, false);
117 }
118 
122 enum ImapAuthRes imap_auth_xoauth2(struct ImapAccountData *adata, const char *method)
123 {
124  return imap_auth_oauth_xoauth2(adata, method, true);
125 }
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:122
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:50
enum ImapAuthRes imap_auth_oauth(struct ImapAccountData *adata, const char *method)
Authenticate an IMAP connection using OAUTHBEARER - Implements ImapAuth::authenticate()
Definition: auth_oauth.c:114
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:159
Convenience wrapper for the core headers.
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
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:1255
#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:40
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:475
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
NeoMutt Logging.
NeoMutt connections.
#define mutt_socket_send(conn, buf)
Definition: mutt_socket.h:37
Pop-specific Account data.
GUI display the mailboxes in a side panel.
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