NeoMutt  2023-05-17-56-ga67199
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 "enter/lib.h"
#include "accountcmd.h"
#include "globals.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 49 of file connaccount.c.

50{
51 if (cac->flags & MUTT_ACCT_USER)
52 return 0;
53 if (!cac->get_field)
54 return -1;
55
56 const char *user = cac->get_field(MUTT_CA_USER, cac->gf_data);
57 if (user)
58 {
59 mutt_str_copy(cac->user, user, sizeof(cac->user));
60 }
62 {
63 /* The external command might interact with the screen */
64 if (!OptNoCurses)
66 return 0;
67 }
68 else if (OptNoCurses)
69 {
70 return -1;
71 }
72 else
73 {
74 /* prompt (defaults to unix username), copy into cac->user */
75 char prompt[256] = { 0 };
76 /* L10N: Example: Username at myhost.com */
77 snprintf(prompt, sizeof(prompt), _("Username at %s: "), cac->host);
78 mutt_str_copy(cac->user, Username, sizeof(cac->user));
79
80 struct Buffer *buf = buf_pool_get();
81 const int rc = buf_get_field(prompt, buf, MUTT_COMP_UNBUFFERED, false, NULL, NULL, NULL);
82 mutt_str_copy(cac->user, buf_string(buf), sizeof(cac->user));
83 buf_pool_release(&buf);
84 if (rc != 0)
85 return -1;
86 }
87
88 cac->flags |= MUTT_ACCT_USER;
89 return 0;
90}
MuttAccountFlags mutt_account_call_external_cmd(struct ConnAccount *cac)
Retrieve account credentials via an external command.
Definition: accountcmd.c:163
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:90
@ MUTT_CA_USER
User name.
Definition: connaccount.h:36
#define MUTT_ACCT_NO_FLAGS
No flags are set.
Definition: connaccount.h:42
#define MUTT_ACCT_USER
User field has been set.
Definition: connaccount.h:44
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:163
int buf_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: window.c:180
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:82
char * Username
User's login name.
Definition: globals.c:42
#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
#define MUTT_COMP_UNBUFFERED
Ignore macro buffer.
Definition: mutt.h:67
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
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 98 of file connaccount.c.

99{
100 if (cac->flags & MUTT_ACCT_LOGIN)
101 return 0;
102 if (!cac->get_field)
103 return -1;
104
105 const char *login = cac->get_field(MUTT_CA_LOGIN, cac->gf_data);
106 if (!login && (mutt_account_getuser(cac) == 0))
107 {
108 login = cac->user;
109 }
110
111 if (!login)
112 {
113 mutt_debug(LL_DEBUG1, "Couldn't get user info\n");
114 return -1;
115 }
116
117 mutt_str_copy(cac->login, login, sizeof(cac->login));
118 cac->flags |= MUTT_ACCT_LOGIN;
119 return 0;
120}
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
Definition: connaccount.c:49
@ 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: logging2.h:87
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
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 128 of file connaccount.c.

129{
130 if (cac->flags & MUTT_ACCT_PASS)
131 return 0;
132 if (!cac->get_field)
133 return -1;
134
135 const char *pass = cac->get_field(MUTT_CA_PASS, cac->gf_data);
136 if (pass)
137 {
138 mutt_str_copy(cac->pass, pass, sizeof(cac->pass));
139 }
141 {
142 /* The external command might interact with the screen */
143 if (!OptNoCurses)
145 return 0;
146 }
147 else if (OptNoCurses)
148 {
149 return -1;
150 }
151 else
152 {
153 char prompt[256] = { 0 };
154 snprintf(prompt, sizeof(prompt), _("Password for %s@%s: "),
155 (cac->flags & MUTT_ACCT_LOGIN) ? cac->login : cac->user, cac->host);
156 cac->pass[0] = '\0';
157
158 struct Buffer *buf = buf_pool_get();
159 const int rc = buf_get_field(prompt, buf, MUTT_COMP_PASS | MUTT_COMP_UNBUFFERED,
160 false, NULL, NULL, NULL);
161 mutt_str_copy(cac->pass, buf_string(buf), sizeof(cac->pass));
162 buf_pool_release(&buf);
163 if (rc != 0)
164 return -1;
165 }
166
167 cac->flags |= MUTT_ACCT_PASS;
168 return 0;
169}
@ 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:66
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 175 of file connaccount.c.

176{
177 cac->flags &= ~MUTT_ACCT_PASS;
178 memset(cac->pass, 0, sizeof(cac->pass));
179}
+ 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 193 of file connaccount.c.

194{
195 if (!cac || !cac->get_field)
196 return NULL;
197
198 /* The oauthbearer token includes the login */
199 if (mutt_account_getlogin(cac))
200 return NULL;
201
202 const char *cmd = cac->get_field(MUTT_CA_OAUTH_CMD, cac->gf_data);
203 if (!cmd)
204 {
205 /* L10N: You will see this error message if (1) you have "oauthbearer" in
206 one of your $*_authenticators and (2) you do not have the corresponding
207 $*_oauth_refresh_command defined. So the message does not mean "None of
208 your $*_oauth_refresh_command's are defined." */
209 mutt_error(_("No OAUTH refresh command defined"));
210 return NULL;
211 }
212
213 FILE *fp = NULL;
214 pid_t pid = filter_create(cmd, NULL, &fp, NULL);
215 if (pid < 0)
216 {
217 mutt_perror(_("Unable to run refresh command"));
218 return NULL;
219 }
220
221 size_t token_size = 0;
222 char *token = mutt_file_read_line(NULL, &token_size, fp, NULL, MUTT_RL_NO_FLAGS);
223 mutt_file_fclose(&fp);
224 filter_wait(pid);
225
226 /* The refresh cmd in some cases will invoke gpg to decrypt a token */
227 if (!OptNoCurses)
229
230 if (!token || (*token == '\0'))
231 {
232 mutt_error(_("Command returned empty string"));
233 FREE(&token);
234 return NULL;
235 }
236
237 if ((!xoauth2 && (token_size > 512)) || (xoauth2 && (token_size > 4096)))
238 {
239 mutt_error(_("OAUTH token is too big: %ld"), token_size);
240 FREE(&token);
241 return NULL;
242 }
243
244 /* 4500 is chosen to allow for both a token that is 4096-long plus a
245 * username that can be up to 320-long. */
246 char oauthbearer[4500] = { 0 };
247 int oalen = 0;
248 if (xoauth2)
249 {
250 oalen = snprintf(oauthbearer, sizeof(oauthbearer),
251 "user=%s\001auth=Bearer %s\001\001", cac->login, token);
252 }
253 else
254 {
255 oalen = snprintf(oauthbearer, sizeof(oauthbearer),
256 "n,a=%s,\001host=%s\001port=%d\001auth=Bearer %s\001\001",
257 cac->login, cac->host, cac->port, token);
258 }
259 FREE(&token);
260
261 size_t encoded_len = oalen * 4 / 3 + 10;
262 assert(encoded_len < 6010); // Assure LGTM that we won't overflow
263
264 char *encoded_token = mutt_mem_malloc(encoded_len);
265 mutt_b64_encode(oauthbearer, oalen, encoded_token, encoded_len);
266
267 return encoded_token;
268}
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:98
@ MUTT_CA_OAUTH_CMD
OAuth refresh command.
Definition: connaccount.h:38
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:738
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:150
#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: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: logging2.h:90
#define mutt_perror(...)
Definition: logging2.h:91
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define FREE(x)
Definition: memory.h:43
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: