NeoMutt  2021-10-29-220-g2b1eec
Teaching an old dog new tricks
DOXYGEN
connaccount.c File Reference

Connection Credentials. More...

#include "config.h"
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "mutt/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "connaccount.h"
#include "mutt_globals.h"
#include "options.h"
+ Include dependency graph for connaccount.c:

Go to the source code of this file.

Functions

int mutt_account_getuser (struct ConnAccount *cac)
 Retrieve username into ConnAccount, if necessary. More...
 
int mutt_account_getlogin (struct ConnAccount *cac)
 Retrieve login info into ConnAccount, if necessary. More...
 
int mutt_account_getpass (struct ConnAccount *cac)
 Fetch password into ConnAccount, if necessary. More...
 
void mutt_account_unsetpass (struct ConnAccount *cac)
 Unset ConnAccount's password. More...
 
char * mutt_account_getoauthbearer (struct ConnAccount *cac, bool xoauth2)
 Get an OAUTHBEARER/XOAUTH2 token. More...
 

Detailed Description

Connection Credentials.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file connaccount.c.

Function Documentation

◆ mutt_account_getuser()

int mutt_account_getuser ( struct ConnAccount cac)

Retrieve username into ConnAccount, if necessary.

Parameters
cacConnAccount to fill
Return values
0Success
-1Failure

Definition at line 48 of file connaccount.c.

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 
68  struct Buffer *buf = mutt_buffer_pool_get();
69  const int rc = mutt_get_field_unbuffered(prompt, buf, MUTT_COMP_NO_FLAGS);
70  mutt_str_copy(cac->user, mutt_buffer_string(buf), sizeof(cac->user));
72  if (rc != 0)
73  return -1;
74  }
75 
76  cac->flags |= MUTT_ACCT_USER;
77  return 0;
78 }
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
@ MUTT_CA_USER
User name.
Definition: connaccount.h:36
#define MUTT_ACCT_USER
User field has been set.
Definition: connaccount.h:44
int mutt_get_field_unbuffered(const char *msg, struct Buffer *buf, CompletionFlags flags)
Ask the user for a string (ignoring macro buffer)
Definition: curs_lib.c:331
#define _(a)
Definition: message.h:28
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:560
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
char * Username
User's login name.
Definition: mutt_globals.h:52
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:53
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
String manipulation buffer.
Definition: buffer.h:34
char user[128]
Username.
Definition: connaccount.h:56
char host[128]
Server to login to.
Definition: connaccount.h:54
const char *(* get_field)(enum ConnAccountField field, void *gf_data)
Function to get some login credentials.
Definition: connaccount.h:68
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition: connaccount.h:60
void * gf_data
Private data to pass to get_field()
Definition: connaccount.h:70
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_account_getlogin()

int mutt_account_getlogin ( struct ConnAccount cac)

Retrieve login info into ConnAccount, if necessary.

Parameters
cacConnAccount to fill
Return values
0Success
-1Failure

Definition at line 86 of file connaccount.c.

87 {
88  if (cac->flags & MUTT_ACCT_LOGIN)
89  return 0;
90  if (!cac->get_field)
91  return -1;
92 
93  const char *login = cac->get_field(MUTT_CA_LOGIN, cac->gf_data);
94  if (!login && (mutt_account_getuser(cac) == 0))
95  {
96  login = cac->user;
97  }
98 
99  if (!login)
100  {
101  mutt_debug(LL_DEBUG1, "Couldn't get user info\n");
102  return -1;
103  }
104 
105  mutt_str_copy(cac->login, login, sizeof(cac->login));
106  cac->flags |= MUTT_ACCT_LOGIN;
107  return 0;
108 }
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
Definition: connaccount.c:48
@ MUTT_CA_LOGIN
Login name.
Definition: connaccount.h:35
#define MUTT_ACCT_LOGIN
Login field has been set.
Definition: connaccount.h:45
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
char login[128]
Login name.
Definition: connaccount.h:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_account_getpass()

int mutt_account_getpass ( struct ConnAccount cac)

Fetch password into ConnAccount, if necessary.

Parameters
cacConnAccount to fill
Return values
0Success
-1Failure

Definition at line 116 of file connaccount.c.

117 {
118  if (cac->flags & MUTT_ACCT_PASS)
119  return 0;
120  if (!cac->get_field)
121  return -1;
122 
123  const char *pass = cac->get_field(MUTT_CA_PASS, cac->gf_data);
124  if (pass)
125  mutt_str_copy(cac->pass, pass, sizeof(cac->pass));
126  else if (OptNoCurses)
127  return -1;
128  else
129  {
130  char prompt[256];
131  snprintf(prompt, sizeof(prompt), _("Password for %s@%s: "),
132  (cac->flags & MUTT_ACCT_LOGIN) ? cac->login : cac->user, cac->host);
133  cac->pass[0] = '\0';
134 
135  struct Buffer *buf = mutt_buffer_pool_get();
136  const int rc = mutt_get_field_unbuffered(prompt, buf, MUTT_COMP_PASS);
137  mutt_str_copy(cac->pass, mutt_buffer_string(buf), sizeof(cac->pass));
139  if (rc != 0)
140  return -1;
141  }
142 
143  cac->flags |= MUTT_ACCT_PASS;
144  return 0;
145 }
@ MUTT_CA_PASS
Password.
Definition: connaccount.h:37
#define MUTT_ACCT_PASS
Password field has been set.
Definition: connaccount.h:46
#define MUTT_COMP_PASS
Password mode (no echo)
Definition: mutt.h:63
char pass[256]
Password.
Definition: connaccount.h:57
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_account_unsetpass()

void mutt_account_unsetpass ( struct ConnAccount cac)

Unset ConnAccount's password.

Parameters
cacConnAccount to modify

Definition at line 151 of file connaccount.c.

152 {
153  cac->flags &= ~MUTT_ACCT_PASS;
154  memset(cac->pass, 0, sizeof(cac->pass));
155 }
+ Here is the caller graph for this function:

◆ mutt_account_getoauthbearer()

char* mutt_account_getoauthbearer ( struct ConnAccount cac,
bool  xoauth2 
)

Get an OAUTHBEARER/XOAUTH2 token.

Parameters
cacAccount to use
xoauth2Generate a deprecated XOAUTH2 token
Return values
ptrOAuth token
NULLError

Run an external command to generate the oauth refresh token for an account, then create and encode the OAUTHBEARER token based on RFC7628.

Note
Caller should free the token

Definition at line 169 of file connaccount.c.

170 {
171  if (!cac || !cac->get_field)
172  return NULL;
173 
174  /* The oauthbearer token includes the login */
175  if (mutt_account_getlogin(cac))
176  return NULL;
177 
178  const char *cmd = cac->get_field(MUTT_CA_OAUTH_CMD, cac->gf_data);
179  if (!cmd)
180  {
181  /* L10N: You will see this error message if (1) you have "oauthbearer" in
182  one of your $*_authenticators and (2) you do not have the corresponding
183  $*_oauth_refresh_command defined. So the message does not mean "None of
184  your $*_oauth_refresh_command's are defined." */
185  mutt_error(_("No OAUTH refresh command defined"));
186  return NULL;
187  }
188 
189  FILE *fp = NULL;
190  pid_t pid = filter_create(cmd, NULL, &fp, NULL);
191  if (pid < 0)
192  {
193  mutt_perror(_("Unable to run refresh command"));
194  return NULL;
195  }
196 
197  size_t token_size = 0;
198  char *token = mutt_file_read_line(NULL, &token_size, fp, NULL, MUTT_RL_NO_FLAGS);
199  mutt_file_fclose(&fp);
200  filter_wait(pid);
201 
202  /* The refresh cmd in some cases will invoke gpg to decrypt a token */
203  if (!OptNoCurses)
205 
206  /* The refresh cmd in some cases will invoke gpg to decrypt a token */
207  if (!OptNoCurses)
209 
210  if (!token || (*token == '\0'))
211  {
212  mutt_error(_("Command returned empty string"));
213  FREE(&token);
214  return NULL;
215  }
216 
217  if ((!xoauth2 && (token_size > 512)) || (xoauth2 && (token_size > 4096)))
218  {
219  mutt_error(_("OAUTH token is too big: %ld"), token_size);
220  FREE(&token);
221  return NULL;
222  }
223 
224  /* 4500 is chosen to allow for both a token that is 4096-long plus a
225  * username that can be up to 320-long. */
226  char oauthbearer[4500];
227  int oalen = 0;
228  if (xoauth2)
229  {
230  oalen = snprintf(oauthbearer, sizeof(oauthbearer),
231  "user=%s\001auth=Bearer %s\001\001", cac->login, token);
232  }
233  else
234  {
235  oalen = snprintf(oauthbearer, sizeof(oauthbearer),
236  "n,a=%s,\001host=%s\001port=%d\001auth=Bearer %s\001\001",
237  cac->login, cac->host, cac->port, token);
238  }
239  FREE(&token);
240 
241  size_t encoded_len = oalen * 4 / 3 + 10;
242  assert(encoded_len < 6010); // Assure LGTM that we won't overflow
243 
244  char *encoded_token = mutt_mem_malloc(encoded_len);
245  mutt_b64_encode(oauthbearer, oalen, encoded_token, encoded_len);
246 
247  return encoded_token;
248 }
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
int mutt_account_getlogin(struct ConnAccount *cac)
Retrieve login info into ConnAccount, if necessary.
Definition: connaccount.c:86
@ MUTT_CA_OAUTH_CMD
OAuth refresh command.
Definition: connaccount.h:38
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:136
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
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:695
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
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:87
#define mutt_perror(...)
Definition: logging.h:88
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:40
unsigned short port
Port to connect to.
Definition: connaccount.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function: