NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
connaccount.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <assert.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include "mutt/lib.h"
35 #include "gui/lib.h"
36 #include "mutt.h"
37 #include "connaccount.h"
38 #include "mutt_globals.h"
39 #include "options.h"
40 
48 {
49  if (cac->flags & MUTT_ACCT_USER)
50  return 0;
51  if (!cac->get_field)
52  return -1;
53 
54  const char *user = cac->get_field(MUTT_CA_USER, cac->gf_data);
55  if (user)
56  mutt_str_copy(cac->user, user, sizeof(cac->user));
57  else if (OptNoCurses)
58  return -1;
59  else
60  {
61  /* prompt (defaults to unix username), copy into cac->user */
62  char prompt[256];
63  /* L10N: Example: Username at myhost.com */
64  snprintf(prompt, sizeof(prompt), _("Username at %s: "), cac->host);
65  mutt_str_copy(cac->user, Username, sizeof(cac->user));
66  if (mutt_get_field_unbuffered(prompt, cac->user, sizeof(cac->user), MUTT_COMP_NO_FLAGS))
67  return -1;
68  }
69 
70  cac->flags |= MUTT_ACCT_USER;
71  return 0;
72 }
73 
81 {
82  if (cac->flags & MUTT_ACCT_LOGIN)
83  return 0;
84  if (!cac->get_field)
85  return -1;
86 
87  const char *login = cac->get_field(MUTT_CA_LOGIN, cac->gf_data);
88  if (!login && (mutt_account_getuser(cac) == 0))
89  {
90  login = cac->user;
91  }
92 
93  if (!login)
94  {
95  mutt_debug(LL_DEBUG1, "Couldn't get user info\n");
96  return -1;
97  }
98 
99  mutt_str_copy(cac->login, login, sizeof(cac->login));
100  cac->flags |= MUTT_ACCT_LOGIN;
101  return 0;
102 }
103 
111 {
112  if (cac->flags & MUTT_ACCT_PASS)
113  return 0;
114  if (!cac->get_field)
115  return -1;
116 
117  const char *pass = cac->get_field(MUTT_CA_PASS, cac->gf_data);
118  if (pass)
119  mutt_str_copy(cac->pass, pass, sizeof(cac->pass));
120  else if (OptNoCurses)
121  return -1;
122  else
123  {
124  char prompt[256];
125  snprintf(prompt, sizeof(prompt), _("Password for %s@%s: "),
126  (cac->flags & MUTT_ACCT_LOGIN) ? cac->login : cac->user, cac->host);
127  cac->pass[0] = '\0';
128  if (mutt_get_field_unbuffered(prompt, cac->pass, sizeof(cac->pass), MUTT_PASS))
129  return -1;
130  }
131 
132  cac->flags |= MUTT_ACCT_PASS;
133  return 0;
134 }
135 
141 {
142  cac->flags &= ~MUTT_ACCT_PASS;
143  memset(cac->pass, 0, sizeof(cac->pass));
144 }
145 
158 {
159  if (!cac || !cac->get_field)
160  return NULL;
161 
162  /* The oauthbearer token includes the login */
163  if (mutt_account_getlogin(cac))
164  return NULL;
165 
166  const char *cmd = cac->get_field(MUTT_CA_OAUTH_CMD, cac->gf_data);
167  if (!cmd)
168  {
169  /* L10N: You will see this error message if (1) you have "oauthbearer" in
170  one of your $*_authenticators and (2) you do not have the corresponding
171  $*_oauth_refresh_command defined. So the message does not mean "None of
172  your $*_oauth_refresh_command's are defined." */
173  mutt_error(_("No OAUTH refresh command defined"));
174  return NULL;
175  }
176 
177  FILE *fp = NULL;
178  pid_t pid = filter_create(cmd, NULL, &fp, NULL);
179  if (pid < 0)
180  {
181  mutt_perror(_("Unable to run refresh command"));
182  return NULL;
183  }
184 
185  size_t token_size = 0;
186  char *token = mutt_file_read_line(NULL, &token_size, fp, NULL, MUTT_RL_NO_FLAGS);
187  mutt_file_fclose(&fp);
188  filter_wait(pid);
189 
190  if (!token || (*token == '\0'))
191  {
192  mutt_error(_("Command returned empty string"));
193  FREE(&token);
194  return NULL;
195  }
196 
197  if (token_size > 512)
198  {
199  mutt_error(_("OAUTH token is too big: %ld"), token_size);
200  FREE(&token);
201  return NULL;
202  }
203 
204  char oauthbearer[1024];
205  int oalen = snprintf(oauthbearer, sizeof(oauthbearer), "n,a=%s,\001host=%s\001port=%d\001auth=Bearer %s\001\001",
206  cac->login, cac->host, cac->port, token);
207  FREE(&token);
208 
209  size_t encoded_len = oalen * 4 / 3 + 10;
210  assert(encoded_len < 1400); // Assure LGTM that we won't overflow
211 
212  char *encoded_token = mutt_mem_malloc(encoded_len);
213  mutt_b64_encode(oauthbearer, oalen, encoded_token, encoded_len);
214 
215  return encoded_token;
216 }
Convenience wrapper for the gui headers.
char login[128]
Login name.
Definition: connaccount.h:54
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
Definition: connaccount.c:47
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
#define mutt_error(...)
Definition: logging.h:88
char user[128]
Username.
Definition: connaccount.h:55
#define _(a)
Definition: message.h:28
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:47
Password.
Definition: connaccount.h:36
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:667
#define mutt_perror(...)
Definition: logging.h:89
#define MUTT_ACCT_USER
User field has been set.
Definition: connaccount.h:43
char host[128]
Server to login to.
Definition: connaccount.h:53
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:48
#define MUTT_ACCT_PASS
Password field has been set.
Definition: connaccount.h:45
Many unsorted constants and some structs.
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
char pass[256]
Password.
Definition: connaccount.h:56
size_t mutt_b64_encode(const char *in, size_t inlen, char *out, size_t outlen)
Convert raw bytes to null-terminated base64 string.
Definition: base64.c:88
unsigned short port
Port to connect to.
Definition: connaccount.h:57
void mutt_account_unsetpass(struct ConnAccount *cac)
Unset ConnAccount&#39;s password.
Definition: connaccount.c:140
const char *(* get_field)(enum ConnAccountField field, void *gf_data)
Function to get some login credentials.
Definition: connaccount.h:67
#define MUTT_PASS
Password mode (no echo)
Definition: mutt.h:57
void * gf_data
Private data to pass to get_field()
Definition: connaccount.h:69
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
User name.
Definition: connaccount.h:35
#define MUTT_ACCT_LOGIN
Login field has been set.
Definition: connaccount.h:44
int mutt_account_getlogin(struct ConnAccount *cac)
Retrieve login info into ConnAccount, if necessary.
Definition: connaccount.c:80
OAuth refresh command.
Definition: connaccount.h:37
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Login details for a remote server.
Definition: connaccount.h:51
int mutt_get_field_unbuffered(const char *msg, char *buf, size_t buflen, CompletionFlags flags)
Ask the user for a string (ignoring macro buffer)
Definition: curs_lib.c:359
Log at debug level 1.
Definition: logging.h:40
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
#define FREE(x)
Definition: memory.h:40
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
Connection Credentials.
Login name.
Definition: connaccount.h:34
Convenience wrapper for the library headers.
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
char * mutt_account_getoauthbearer(struct ConnAccount *cac)
Get an OAUTHBEARER token.
Definition: connaccount.c:157
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition: connaccount.h:59
int mutt_account_getpass(struct ConnAccount *cac)
Fetch password into ConnAccount, if necessary.
Definition: connaccount.c:110