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