NeoMutt  2020-06-26-89-g172cd3
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 "lib.h"
39 #include "mutt_globals.h"
40 #include "options.h"
41 
49 {
50  if (cac->flags & MUTT_ACCT_USER)
51  return 0;
52  if (!cac->get_field)
53  return -1;
54 
55  const char *user = cac->get_field(MUTT_CA_USER, cac->gf_data);
56  if (user)
57  mutt_str_copy(cac->user, user, sizeof(cac->user));
58  else if (OptNoCurses)
59  return -1;
60  else
61  {
62  /* prompt (defaults to unix username), copy into cac->user */
63  char prompt[256];
64  /* L10N: Example: Username at myhost.com */
65  snprintf(prompt, sizeof(prompt), _("Username at %s: "), cac->host);
66  mutt_str_copy(cac->user, Username, sizeof(cac->user));
67  if (mutt_get_field_unbuffered(prompt, cac->user, sizeof(cac->user), MUTT_COMP_NO_FLAGS))
68  return -1;
69  }
70 
71  cac->flags |= MUTT_ACCT_USER;
72  return 0;
73 }
74 
82 {
83  if (cac->flags & MUTT_ACCT_LOGIN)
84  return 0;
85  if (!cac->get_field)
86  return -1;
87 
88  const char *login = cac->get_field(MUTT_CA_LOGIN, cac->gf_data);
89  if (!login && (mutt_account_getuser(cac) == 0))
90  {
91  login = cac->user;
92  }
93 
94  if (!login)
95  {
96  mutt_debug(LL_DEBUG1, "Couldn't get user info\n");
97  return -1;
98  }
99 
100  mutt_str_copy(cac->login, login, sizeof(cac->login));
101  cac->flags |= MUTT_ACCT_LOGIN;
102  return 0;
103 }
104 
112 {
113  if (cac->flags & MUTT_ACCT_PASS)
114  return 0;
115  if (!cac->get_field)
116  return -1;
117 
118  const char *pass = cac->get_field(MUTT_CA_PASS, cac->gf_data);
119  if (pass)
120  mutt_str_copy(cac->pass, pass, sizeof(cac->pass));
121  else if (OptNoCurses)
122  return -1;
123  else
124  {
125  char prompt[256];
126  snprintf(prompt, sizeof(prompt), _("Password for %s@%s: "),
127  (cac->flags & MUTT_ACCT_LOGIN) ? cac->login : cac->user, cac->host);
128  cac->pass[0] = '\0';
129  if (mutt_get_password(prompt, cac->pass, sizeof(cac->pass)))
130  return -1;
131  }
132 
133  cac->flags |= MUTT_ACCT_PASS;
134  return 0;
135 }
136 
142 {
143  cac->flags &= ~MUTT_ACCT_PASS;
144  memset(cac->pass, 0, sizeof(cac->pass));
145 }
146 
159 {
160  if (!cac || !cac->get_field)
161  return NULL;
162 
163  /* The oauthbearer token includes the login */
164  if (mutt_account_getlogin(cac))
165  return NULL;
166 
167  const char *cmd = cac->get_field(MUTT_CA_OAUTH_CMD, cac->gf_data);
168  if (!cmd)
169  {
170  /* L10N: You will see this error message if (1) you have "oauthbearer" in
171  one of your $*_authenticators and (2) you do not have the corresponding
172  $*_oauth_refresh_command defined. So the message does not mean "None of
173  your $*_oauth_refresh_command's are defined." */
174  mutt_error(_("No OAUTH refresh command defined"));
175  return NULL;
176  }
177 
178  FILE *fp = NULL;
179  pid_t pid = filter_create(cmd, NULL, &fp, NULL);
180  if (pid < 0)
181  {
182  mutt_perror(_("Unable to run refresh command"));
183  return NULL;
184  }
185 
186  size_t token_size = 0;
187  char *token = mutt_file_read_line(NULL, &token_size, fp, NULL, 0);
188  mutt_file_fclose(&fp);
189  filter_wait(pid);
190 
191  if (!token || (*token == '\0'))
192  {
193  mutt_error(_("Command returned empty string"));
194  FREE(&token);
195  return NULL;
196  }
197 
198  if (token_size > 512)
199  {
200  mutt_error(_("OAUTH token is too big: %ld"), token_size);
201  FREE(&token);
202  return NULL;
203  }
204 
205  char oauthbearer[1024];
206  int oalen = snprintf(oauthbearer, sizeof(oauthbearer), "n,a=%s,\001host=%s\001port=%d\001auth=Bearer %s\001\001",
207  cac->login, cac->host, cac->port, token);
208  FREE(&token);
209 
210  size_t encoded_len = oalen * 4 / 3 + 10;
211  assert(encoded_len < 1400); // Assure LGTM that we won't overflow
212 
213  char *encoded_token = mutt_mem_malloc(encoded_len);
214  mutt_b64_encode(oauthbearer, oalen, encoded_token, encoded_len);
215 
216  return encoded_token;
217 }
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:48
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_perror(...)
Definition: logging.h:85
#define mutt_get_password(msg, buf, buflen)
Definition: curs_lib.h:92
char user[128]
Username.
Definition: connaccount.h:55
#define _(a)
Definition: message.h:28
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, int flags)
Read a line from a file.
Definition: file.c:667
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:48
Password.
Definition: connaccount.h:36
#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:53
#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:56
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:141
const char *(* get_field)(enum ConnAccountField field, void *gf_data)
Function to get some login credentials.
Definition: connaccount.h:67
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:81
OAuth refresh command.
Definition: connaccount.h:37
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:332
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:721
#define mutt_error(...)
Definition: logging.h:84
Connection Library.
#define FREE(x)
Definition: memory.h:40
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
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:158
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:111