NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
connaccount.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <assert.h>
31#include <stdbool.h>
32#include <stdio.h>
33#include <string.h>
34#include <sys/types.h>
35#include "mutt/lib.h"
36#include "gui/lib.h"
37#include "mutt.h"
38#include "connaccount.h"
39#include "editor/lib.h"
40#include "history/lib.h"
41#include "accountcmd.h"
42#include "globals.h"
43
51{
52 if (cac->flags & MUTT_ACCT_USER)
53 return 0;
54 if (!cac->get_field)
55 return -1;
56
57 const char *user = cac->get_field(MUTT_CA_USER, cac->gf_data);
58 if (user)
59 {
60 mutt_str_copy(cac->user, user, sizeof(cac->user));
61 }
63 {
64 /* The external command might interact with the screen */
65 if (!OptNoCurses)
67 return 0;
68 }
69 else if (OptNoCurses)
70 {
71 return -1;
72 }
73 else
74 {
75 /* prompt (defaults to unix username), copy into cac->user */
76 char prompt[256] = { 0 };
77 /* L10N: Example: Username at myhost.com */
78 snprintf(prompt, sizeof(prompt), _("Username at %s: "), cac->host);
79 mutt_str_copy(cac->user, Username, sizeof(cac->user));
80
81 struct Buffer *buf = buf_pool_get();
82 const int rc = mw_get_field(prompt, buf, MUTT_COMP_UNBUFFERED, HC_OTHER, NULL, NULL);
83 mutt_str_copy(cac->user, buf_string(buf), sizeof(cac->user));
84 buf_pool_release(&buf);
85 if (rc != 0)
86 return -1;
87 }
88
89 cac->flags |= MUTT_ACCT_USER;
90 return 0;
91}
92
100{
101 if (cac->flags & MUTT_ACCT_LOGIN)
102 return 0;
103 if (!cac->get_field)
104 return -1;
105
106 const char *login = cac->get_field(MUTT_CA_LOGIN, cac->gf_data);
107 if (!login && (mutt_account_getuser(cac) == 0))
108 {
109 login = cac->user;
110 }
111
112 if (!login)
113 {
114 mutt_debug(LL_DEBUG1, "Couldn't get user info\n");
115 return -1;
116 }
117
118 mutt_str_copy(cac->login, login, sizeof(cac->login));
119 cac->flags |= MUTT_ACCT_LOGIN;
120 return 0;
121}
122
130{
131 if (cac->flags & MUTT_ACCT_PASS)
132 return 0;
133 if (!cac->get_field)
134 return -1;
135
136 const char *pass = cac->get_field(MUTT_CA_PASS, cac->gf_data);
137 if (pass)
138 {
139 mutt_str_copy(cac->pass, pass, sizeof(cac->pass));
140 }
142 {
143 /* The external command might interact with the screen */
144 if (!OptNoCurses)
146 return 0;
147 }
148 else if (OptNoCurses)
149 {
150 return -1;
151 }
152 else
153 {
154 char prompt[256] = { 0 };
155 snprintf(prompt, sizeof(prompt), _("Password for %s@%s: "),
156 (cac->flags & MUTT_ACCT_LOGIN) ? cac->login : cac->user, cac->host);
157 cac->pass[0] = '\0';
158
159 struct Buffer *buf = buf_pool_get();
160 const int rc = mw_get_field(prompt, buf, MUTT_COMP_PASS | MUTT_COMP_UNBUFFERED,
161 HC_OTHER, NULL, NULL);
162 mutt_str_copy(cac->pass, buf_string(buf), sizeof(cac->pass));
163 buf_pool_release(&buf);
164 if (rc != 0)
165 return -1;
166 }
167
168 cac->flags |= MUTT_ACCT_PASS;
169 return 0;
170}
171
177{
178 cac->flags &= ~MUTT_ACCT_PASS;
179 memset(cac->pass, 0, sizeof(cac->pass));
180}
181
194char *mutt_account_getoauthbearer(struct ConnAccount *cac, bool xoauth2)
195{
196 if (!cac || !cac->get_field)
197 return NULL;
198
199 /* The oauthbearer token includes the login */
200 if (mutt_account_getlogin(cac))
201 return NULL;
202
203 const char *cmd = cac->get_field(MUTT_CA_OAUTH_CMD, cac->gf_data);
204 if (!cmd)
205 {
206 /* L10N: You will see this error message if (1) you have "oauthbearer" in
207 one of your $*_authenticators and (2) you do not have the corresponding
208 $*_oauth_refresh_command defined. So the message does not mean "None of
209 your $*_oauth_refresh_command's are defined." */
210 mutt_error(_("No OAUTH refresh command defined"));
211 return NULL;
212 }
213
214 FILE *fp = NULL;
215 pid_t pid = filter_create(cmd, NULL, &fp, NULL, EnvList);
216 if (pid < 0)
217 {
218 mutt_perror(_("Unable to run refresh command"));
219 return NULL;
220 }
221
222 size_t token_size = 0;
223 char *token = mutt_file_read_line(NULL, &token_size, fp, NULL, MUTT_RL_NO_FLAGS);
224 mutt_file_fclose(&fp);
225 filter_wait(pid);
226
227 /* The refresh cmd in some cases will invoke gpg to decrypt a token */
228 if (!OptNoCurses)
230
231 if (!token || (*token == '\0'))
232 {
233 mutt_error(_("Command returned empty string"));
234 FREE(&token);
235 return NULL;
236 }
237
238 if ((!xoauth2 && (token_size > 512)) || (xoauth2 && (token_size > 4096)))
239 {
240 mutt_error(_("OAUTH token is too big: %ld"), token_size);
241 FREE(&token);
242 return NULL;
243 }
244
245 /* 4500 is chosen to allow for both a token that is 4096-long plus a
246 * username that can be up to 320-long. */
247 char oauthbearer[4500] = { 0 };
248 int oalen = 0;
249 if (xoauth2)
250 {
251 oalen = snprintf(oauthbearer, sizeof(oauthbearer),
252 "user=%s\001auth=Bearer %s\001\001", cac->login, token);
253 }
254 else
255 {
256 oalen = snprintf(oauthbearer, sizeof(oauthbearer),
257 "n,a=%s,\001host=%s\001port=%d\001auth=Bearer %s\001\001",
258 cac->login, cac->host, cac->port, token);
259 }
260 FREE(&token);
261
262 size_t encoded_len = oalen * 4 / 3 + 10;
263 assert(encoded_len < 6010); // Assure LGTM that we won't overflow
264
265 char *encoded_token = mutt_mem_malloc(encoded_len);
266 mutt_b64_encode(oauthbearer, oalen, encoded_token, encoded_len);
267
268 return encoded_token;
269}
MuttAccountFlags mutt_account_call_external_cmd(struct ConnAccount *cac)
Retrieve account credentials via an external command.
Definition: accountcmd.c:165
Connection Credentials External Command.
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
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
int mutt_account_getpass(struct ConnAccount *cac)
Fetch password into ConnAccount, if necessary.
Definition: connaccount.c:129
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
Definition: connaccount.c:50
void mutt_account_unsetpass(struct ConnAccount *cac)
Unset ConnAccount's password.
Definition: connaccount.c:176
char * mutt_account_getoauthbearer(struct ConnAccount *cac, bool xoauth2)
Get an OAUTHBEARER/XOAUTH2 token.
Definition: connaccount.c:194
int mutt_account_getlogin(struct ConnAccount *cac)
Retrieve login info into ConnAccount, if necessary.
Definition: connaccount.c:99
Connection Credentials.
@ MUTT_CA_OAUTH_CMD
OAuth refresh command.
Definition: connaccount.h:38
@ MUTT_CA_USER
User name.
Definition: connaccount.h:36
@ MUTT_CA_LOGIN
Login name.
Definition: connaccount.h:35
@ MUTT_CA_PASS
Password.
Definition: connaccount.h:37
#define MUTT_ACCT_NO_FLAGS
No flags are set.
Definition: connaccount.h:42
#define MUTT_ACCT_PASS
Password field has been set.
Definition: connaccount.h:46
#define MUTT_ACCT_USER
User field has been set.
Definition: connaccount.h:44
#define MUTT_ACCT_LOGIN
Login field has been set.
Definition: connaccount.h:45
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:101
Enter a string.
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:763
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:39
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:218
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition: filter.c:207
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:79
char * Username
User's login name.
Definition: globals.c:42
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:85
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:275
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
#define mutt_perror(...)
Definition: logging2.h:93
Convenience wrapper for the gui headers.
Read/write command history from/to a file.
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:54
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:45
Convenience wrapper for the library headers.
#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:653
Many unsorted constants and some structs.
#define MUTT_COMP_PASS
Password mode (no echo)
Definition: mutt.h:57
#define MUTT_COMP_UNBUFFERED
Ignore macro buffer.
Definition: mutt.h:58
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
String manipulation buffer.
Definition: buffer.h:34
Login details for a remote server.
Definition: connaccount.h:53
char login[128]
Login name.
Definition: connaccount.h:55
char user[128]
Username.
Definition: connaccount.h:56
char pass[256]
Password.
Definition: connaccount.h:57
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
unsigned short port
Port to connect to.
Definition: connaccount.h:58