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