NeoMutt  2024-12-12-14-g7b49f7
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
auth.c
Go to the documentation of this file.
1
32#include "config.h"
33#include <stdbool.h>
34#include <stdio.h>
35#include <string.h>
36#include "private.h"
37#include "mutt/lib.h"
38#include "address/lib.h"
39#include "config/lib.h"
40#include "core/lib.h"
41#include "conn/lib.h"
42#include "adata.h"
43#ifdef USE_SASL_CYRUS
44#include <sasl/sasl.h>
45#include <sasl/saslutil.h>
46#endif
47#ifdef USE_SASL_GNU
48#include <gsasl.h>
49#endif
50
51#ifdef USE_SASL_GNU
55static enum PopAuthRes pop_auth_gsasl(struct PopAccountData *adata, const char *method)
56{
57 Gsasl_session *gsasl_session = NULL;
58 struct Buffer *output_buf = NULL;
59 struct Buffer *input_buf = NULL;
60 int rc = POP_A_FAILURE;
61 int gsasl_rc = GSASL_OK;
62
63 const char *chosen_mech = mutt_gsasl_get_mech(method, buf_string(&adata->auth_list));
64 if (!chosen_mech)
65 {
66 mutt_debug(LL_DEBUG2, "returned no usable mech\n");
67 return POP_A_UNAVAIL;
68 }
69
70 mutt_debug(LL_DEBUG2, "using mech %s\n", chosen_mech);
71
72 if (mutt_gsasl_client_new(adata->conn, chosen_mech, &gsasl_session) < 0)
73 {
74 mutt_debug(LL_DEBUG1, "Error allocating GSASL connection\n");
75 return POP_A_UNAVAIL;
76 }
77
78 mutt_message(_("Authenticating (%s)..."), chosen_mech);
79
80 output_buf = buf_pool_get();
81 input_buf = buf_pool_get();
82 buf_printf(output_buf, "AUTH %s\r\n", chosen_mech);
83
84 do
85 {
86 if (mutt_socket_send(adata->conn, buf_string(output_buf)) < 0)
87 {
88 adata->status = POP_DISCONNECTED;
89 rc = POP_A_SOCKET;
90 goto fail;
91 }
92
93 if (mutt_socket_buffer_readln(input_buf, adata->conn) < 0)
94 {
95 adata->status = POP_DISCONNECTED;
96 rc = POP_A_SOCKET;
97 goto fail;
98 }
99
100 if (!mutt_strn_equal(buf_string(input_buf), "+ ", 2))
101 break;
102
103 const char *pop_auth_data = buf_string(input_buf) + 2;
104 char *gsasl_step_output = NULL;
105 gsasl_rc = gsasl_step64(gsasl_session, pop_auth_data, &gsasl_step_output);
106 if ((gsasl_rc == GSASL_NEEDS_MORE) || (gsasl_rc == GSASL_OK))
107 {
108 buf_strcpy(output_buf, gsasl_step_output);
109 buf_addstr(output_buf, "\r\n");
110 gsasl_free(gsasl_step_output);
111 }
112 else
113 {
114 mutt_debug(LL_DEBUG1, "gsasl_step64() failed (%d): %s\n", gsasl_rc,
115 gsasl_strerror(gsasl_rc));
116 }
117 } while ((gsasl_rc == GSASL_NEEDS_MORE) || (gsasl_rc == GSASL_OK));
118
119 if (mutt_strn_equal(buf_string(input_buf), "+ ", 2))
120 {
121 mutt_socket_send(adata->conn, "*\r\n");
122 goto fail;
123 }
124
125 if (mutt_strn_equal(buf_string(input_buf), "+OK", 3) && (gsasl_rc == GSASL_OK))
126 rc = POP_A_SUCCESS;
127
128fail:
129 buf_pool_release(&input_buf);
130 buf_pool_release(&output_buf);
131 mutt_gsasl_client_finish(&gsasl_session);
132
133 if (rc == POP_A_FAILURE)
134 {
135 mutt_debug(LL_DEBUG2, "%s failed\n", chosen_mech);
136 mutt_error(_("SASL authentication failed"));
137 }
138
139 return rc;
140}
141#endif
142
143#ifdef USE_SASL_CYRUS
147static enum PopAuthRes pop_auth_sasl(struct PopAccountData *adata, const char *method)
148{
149 sasl_conn_t *saslconn = NULL;
150 sasl_interact_t *interaction = NULL;
151 int rc;
152 char inbuf[1024] = { 0 };
153 const char *mech = NULL;
154 const char *pc = NULL;
155 unsigned int len = 0, olen = 0;
156
157 if (mutt_account_getpass(&adata->conn->account) || !adata->conn->account.pass[0])
158 return POP_A_FAILURE;
159
160 if (mutt_sasl_client_new(adata->conn, &saslconn) < 0)
161 {
162 mutt_debug(LL_DEBUG1, "Error allocating SASL connection\n");
163 return POP_A_FAILURE;
164 }
165
166 if (!method)
167 method = adata->auth_list.data;
168
169 while (true)
170 {
171 rc = sasl_client_start(saslconn, method, &interaction, &pc, &olen, &mech);
172 if (rc != SASL_INTERACT)
173 break;
174 mutt_sasl_interact(interaction);
175 }
176
177 if ((rc != SASL_OK) && (rc != SASL_CONTINUE))
178 {
179 mutt_debug(LL_DEBUG1, "Failure starting authentication exchange. No shared mechanisms?\n");
180
181 /* SASL doesn't support suggested mechanisms, so fall back */
182 sasl_dispose(&saslconn);
183 return POP_A_UNAVAIL;
184 }
185
186 /* About client_start: If sasl_client_start() returns data via pc/olen,
187 * the client is expected to send this first (after the AUTH string is sent).
188 * sasl_client_start() may in fact return SASL_OK in this case. */
189 unsigned int client_start = olen;
190
191 // L10N: (%s) is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
192 mutt_message(_("Authenticating (%s)..."), "SASL");
193
194 size_t bufsize = MAX((olen * 2), 1024);
195 char *buf = MUTT_MEM_MALLOC(bufsize, char);
196
197 snprintf(buf, bufsize, "AUTH %s", mech);
198 olen = strlen(buf);
199
200 /* looping protocol */
201 while (true)
202 {
203 mutt_str_copy(buf + olen, "\r\n", bufsize - olen);
204 mutt_socket_send(adata->conn, buf);
205 if (mutt_socket_readln_d(inbuf, sizeof(inbuf), adata->conn, MUTT_SOCK_LOG_FULL) < 0)
206 {
207 sasl_dispose(&saslconn);
208 adata->status = POP_DISCONNECTED;
209 FREE(&buf);
210 return POP_A_SOCKET;
211 }
212
213 /* Note we don't exit if rc==SASL_OK when client_start is true.
214 * This is because the first loop has only sent the AUTH string, we
215 * need to loop at least once more to send the pc/olen returned
216 * by sasl_client_start(). */
217 if (!client_start && (rc != SASL_CONTINUE))
218 break;
219
220 if (mutt_str_startswith(inbuf, "+ ") &&
221 (sasl_decode64(inbuf + 2, strlen(inbuf + 2), buf, bufsize - 1, &len) != SASL_OK))
222 {
223 mutt_debug(LL_DEBUG1, "error base64-decoding server response\n");
224 goto bail;
225 }
226
227 if (client_start)
228 {
229 olen = client_start;
230 client_start = 0;
231 }
232 else
233 {
234 while (true)
235 {
236 rc = sasl_client_step(saslconn, buf, len, &interaction, &pc, &olen);
237 if (rc != SASL_INTERACT)
238 break;
239 mutt_sasl_interact(interaction);
240 }
241 }
242
243 /* Even if sasl_client_step() returns SASL_OK, we should send at
244 * least one more line to the server. */
245 if ((rc != SASL_CONTINUE) && (rc != SASL_OK))
246 break;
247
248 /* send out response, or line break if none needed */
249 if (pc)
250 {
251 if ((olen * 2) > bufsize)
252 {
253 bufsize = olen * 2;
254 MUTT_MEM_REALLOC(&buf, bufsize, char);
255 }
256 if (sasl_encode64(pc, olen, buf, bufsize, &olen) != SASL_OK)
257 {
258 mutt_debug(LL_DEBUG1, "error base64-encoding client response\n");
259 goto bail;
260 }
261 }
262 }
263
264 if (rc != SASL_OK)
265 goto bail;
266
267 if (mutt_str_startswith(inbuf, "+OK"))
268 {
269 mutt_sasl_setup_conn(adata->conn, saslconn);
270 FREE(&buf);
271 return POP_A_SUCCESS;
272 }
273
274bail:
275 sasl_dispose(&saslconn);
276
277 /* terminate SASL session if the last response is not +OK nor -ERR */
278 if (mutt_str_startswith(inbuf, "+ "))
279 {
280 snprintf(buf, bufsize, "*\r\n");
281 if (pop_query(adata, buf, bufsize) == -1)
282 {
283 FREE(&buf);
284 return POP_A_SOCKET;
285 }
286 }
287
288 FREE(&buf);
289 // L10N: %s is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
290 mutt_error(_("%s authentication failed"), "SASL");
291
292 return POP_A_FAILURE;
293}
294#endif
295
301void pop_apop_timestamp(struct PopAccountData *adata, char *buf)
302{
303 char *p1 = NULL, *p2 = NULL;
304
305 FREE(&adata->timestamp);
306
307 if ((p1 = strchr(buf, '<')) && (p2 = strchr(p1, '>')))
308 {
309 p2[1] = '\0';
310 adata->timestamp = mutt_str_dup(p1);
311 }
312}
313
317static enum PopAuthRes pop_auth_apop(struct PopAccountData *adata, const char *method)
318{
319 struct Md5Ctx md5ctx = { 0 };
320 unsigned char digest[16];
321 char hash[33] = { 0 };
322 char buf[1024] = { 0 };
323
324 if (mutt_account_getpass(&adata->conn->account) || !adata->conn->account.pass[0])
325 return POP_A_FAILURE;
326
327 if (!adata->timestamp)
328 return POP_A_UNAVAIL;
329
330 if (!mutt_addr_valid_msgid(adata->timestamp))
331 {
332 mutt_error(_("POP timestamp is invalid"));
333 return POP_A_UNAVAIL;
334 }
335
336 // L10N: (%s) is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
337 mutt_message(_("Authenticating (%s)..."), "APOP");
338
339 /* Compute the authentication hash to send to the server */
340 mutt_md5_init_ctx(&md5ctx);
341 mutt_md5_process(adata->timestamp, &md5ctx);
342 mutt_md5_process(adata->conn->account.pass, &md5ctx);
343 mutt_md5_finish_ctx(&md5ctx, digest);
344 mutt_md5_toascii(digest, hash);
345
346 /* Send APOP command to server */
347 snprintf(buf, sizeof(buf), "APOP %s %s\r\n", adata->conn->account.user, hash);
348
349 switch (pop_query(adata, buf, sizeof(buf)))
350 {
351 case 0:
352 return POP_A_SUCCESS;
353 case -1:
354 return POP_A_SOCKET;
355 }
356
357 // L10N: %s is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
358 mutt_error(_("%s authentication failed"), "APOP");
359
360 return POP_A_FAILURE;
361}
362
366static enum PopAuthRes pop_auth_user(struct PopAccountData *adata, const char *method)
367{
368 if (!adata->cmd_user)
369 return POP_A_UNAVAIL;
370
371 if (mutt_account_getpass(&adata->conn->account) || !adata->conn->account.pass[0])
372 return POP_A_FAILURE;
373
374 mutt_message(_("Logging in..."));
375
376 char buf[1024] = { 0 };
377 snprintf(buf, sizeof(buf), "USER %s\r\n", adata->conn->account.user);
378 int rc = pop_query(adata, buf, sizeof(buf));
379
380 if (adata->cmd_user == 2)
381 {
382 if (rc == 0)
383 {
384 adata->cmd_user = 1;
385
386 mutt_debug(LL_DEBUG1, "set USER capability\n");
387 }
388
389 if (rc == -2)
390 {
391 adata->cmd_user = 0;
392
393 mutt_debug(LL_DEBUG1, "unset USER capability\n");
394 snprintf(adata->err_msg, sizeof(adata->err_msg), "%s",
395 _("Command USER is not supported by server"));
396 }
397 }
398
399 if (rc == 0)
400 {
401 snprintf(buf, sizeof(buf), "PASS %s\r\n", adata->conn->account.pass);
402 const short c_debug_level = cs_subset_number(NeoMutt->sub, "debug_level");
403 rc = pop_query_d(adata, buf, sizeof(buf),
404 /* don't print the password unless we're at the ungodly debugging level */
405 (c_debug_level < MUTT_SOCK_LOG_FULL) ? "PASS *\r\n" : NULL);
406 }
407
408 switch (rc)
409 {
410 case 0:
411 return POP_A_SUCCESS;
412 case -1:
413 return POP_A_SOCKET;
414 }
415
416 mutt_error("%s %s", _("Login failed"), adata->err_msg);
417
418 return POP_A_FAILURE;
419}
420
424static enum PopAuthRes pop_auth_oauth(struct PopAccountData *adata, const char *method)
425{
426 /* If they did not explicitly request or configure oauth then fail quietly */
427 const char *const c_pop_oauth_refresh_command = cs_subset_string(NeoMutt->sub, "pop_oauth_refresh_command");
428 if (!method && !c_pop_oauth_refresh_command)
429 return POP_A_UNAVAIL;
430
431 // L10N: (%s) is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
432 mutt_message(_("Authenticating (%s)..."), "OAUTHBEARER");
433
434 char *oauthbearer = mutt_account_getoauthbearer(&adata->conn->account, false);
435 if (!oauthbearer)
436 return POP_A_FAILURE;
437
438 char *auth_cmd = NULL;
439 mutt_str_asprintf(&auth_cmd, "AUTH OAUTHBEARER %s\r\n", oauthbearer);
440 FREE(&oauthbearer);
441
442 int rc = pop_query_d(adata, auth_cmd, strlen(auth_cmd),
443#ifdef DEBUG
444 /* don't print the bearer token unless we're at the ungodly debugging level */
445 (cs_subset_number(NeoMutt->sub, "debug_level") < MUTT_SOCK_LOG_FULL) ?
446 "AUTH OAUTHBEARER *\r\n" :
447#endif
448 NULL);
449 FREE(&auth_cmd);
450
451 switch (rc)
452 {
453 case 0:
454 return POP_A_SUCCESS;
455 case -1:
456 return POP_A_SOCKET;
457 }
458
459 /* The error response was a SASL continuation, so "continue" it.
460 * See RFC7628 3.2.3 */
461 mutt_socket_send(adata->conn, "\001");
462
463 char *err = adata->err_msg;
464 char decoded_err[1024] = { 0 };
465 int len = mutt_b64_decode(adata->err_msg, decoded_err, sizeof(decoded_err) - 1);
466 if (len >= 0)
467 {
468 decoded_err[len] = '\0';
469 err = decoded_err;
470 }
471 mutt_error("%s %s", _("Authentication failed"), err);
472
473 return POP_A_FAILURE;
474}
475
479static const struct PopAuth PopAuthenticators[] = {
480 // clang-format off
481 { pop_auth_oauth, "oauthbearer" },
482#ifdef USE_SASL_CYRUS
483 { pop_auth_sasl, NULL },
484#endif
485#ifdef USE_SASL_GNU
486 { pop_auth_gsasl, NULL },
487#endif
488 { pop_auth_apop, "apop" },
489 { pop_auth_user, "user" },
490 { NULL, NULL },
491 // clang-format on
492};
493
502bool pop_auth_is_valid(const char *authenticator)
503{
504 for (size_t i = 0; i < mutt_array_size(PopAuthenticators); i++)
505 {
506 const struct PopAuth *auth = &PopAuthenticators[i];
507 if (auth->method && mutt_istr_equal(auth->method, authenticator))
508 return true;
509 }
510
511 return false;
512}
513
524{
525 struct ConnAccount *cac = &adata->conn->account;
526 const struct PopAuth *authenticator = NULL;
527 int attempts = 0;
528 int rc = POP_A_UNAVAIL;
529
530 if ((mutt_account_getuser(cac) < 0) || (cac->user[0] == '\0'))
531 {
532 return -3;
533 }
534
535 const struct Slist *c_pop_authenticators = cs_subset_slist(NeoMutt->sub, "pop_authenticators");
536 const bool c_pop_auth_try_all = cs_subset_bool(NeoMutt->sub, "pop_auth_try_all");
537 if (c_pop_authenticators && (c_pop_authenticators->count > 0))
538 {
539 /* Try user-specified list of authentication methods */
540 struct ListNode *np = NULL;
541 STAILQ_FOREACH(np, &c_pop_authenticators->head, entries)
542 {
543 mutt_debug(LL_DEBUG2, "Trying method %s\n", np->data);
544 authenticator = PopAuthenticators;
545
546 while (authenticator->authenticate)
547 {
548 if (!authenticator->method || mutt_istr_equal(authenticator->method, np->data))
549 {
550 rc = authenticator->authenticate(adata, np->data);
551 if (rc == POP_A_SOCKET)
552 {
553 switch (pop_connect(adata))
554 {
555 case 0:
556 {
557 rc = authenticator->authenticate(adata, np->data);
558 break;
559 }
560 case -2:
561 rc = POP_A_FAILURE;
562 }
563 }
564
565 if (rc != POP_A_UNAVAIL)
566 attempts++;
567 if ((rc == POP_A_SUCCESS) || (rc == POP_A_SOCKET) ||
568 ((rc == POP_A_FAILURE) && !c_pop_auth_try_all))
569 {
570 break;
571 }
572 }
573 authenticator++;
574 }
575 }
576 }
577 else
578 {
579 /* Fall back to default: any authenticator */
580 mutt_debug(LL_DEBUG2, "Using any available method\n");
581 authenticator = PopAuthenticators;
582
583 while (authenticator->authenticate)
584 {
585 rc = authenticator->authenticate(adata, NULL);
586 if (rc == POP_A_SOCKET)
587 {
588 switch (pop_connect(adata))
589 {
590 case 0:
591 {
592 rc = authenticator->authenticate(adata, NULL);
593 break;
594 }
595 case -2:
596 rc = POP_A_FAILURE;
597 }
598 }
599
600 if (rc != POP_A_UNAVAIL)
601 attempts++;
602 if ((rc == POP_A_SUCCESS) || (rc == POP_A_SOCKET) ||
603 ((rc == POP_A_FAILURE) && !c_pop_auth_try_all))
604 {
605 break;
606 }
607
608 authenticator++;
609 }
610 }
611
612 switch (rc)
613 {
614 case POP_A_SUCCESS:
615 return 0;
616 case POP_A_SOCKET:
617 return -1;
618 case POP_A_UNAVAIL:
619 if (attempts == 0)
620 mutt_error(_("No authenticators available"));
621 }
622
623 return -2;
624}
bool mutt_addr_valid_msgid(const char *msgid)
Is this a valid Message ID?
Definition: address.c:792
Email Address Handling.
int mutt_b64_decode(const char *in, char *out, size_t olen)
Convert null-terminated base64 string to raw bytes.
Definition: base64.c:135
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:291
const struct Slist * cs_subset_slist(const struct ConfigSubset *sub, const char *name)
Get a string-list config item by name.
Definition: helpers.c:242
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:143
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:47
Convenience wrapper for the config headers.
Connection Library.
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
char * mutt_account_getoauthbearer(struct ConnAccount *cac, bool xoauth2)
Get an OAUTHBEARER/XOAUTH2 token.
Definition: connaccount.c:195
Convenience wrapper for the core headers.
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
static enum PopAuthRes pop_auth_user(struct PopAccountData *adata, const char *method)
USER authenticator - Implements PopAuth::authenticate() -.
Definition: auth.c:366
static enum PopAuthRes pop_auth_apop(struct PopAccountData *adata, const char *method)
APOP authenticator - Implements PopAuth::authenticate() -.
Definition: auth.c:317
static enum PopAuthRes pop_auth_oauth(struct PopAccountData *adata, const char *method)
Authenticate a POP connection using OAUTHBEARER - Implements PopAuth::authenticate() -.
Definition: auth.c:424
const char * mutt_gsasl_get_mech(const char *requested_mech, const char *server_mechlist)
Pick a connection mechanism.
Definition: gsasl.c:164
int mutt_gsasl_client_new(struct Connection *conn, const char *mech, Gsasl_session **sctx)
Create a new GNU SASL client.
Definition: gsasl.c:199
void mutt_gsasl_client_finish(Gsasl_session **sctx)
Free a GNU SASL client.
Definition: gsasl.c:220
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
void mutt_md5_process(const char *str, struct Md5Ctx *md5ctx)
Process a NULL-terminated string.
Definition: md5.c:355
void mutt_md5_init_ctx(struct Md5Ctx *md5ctx)
Initialise the MD5 computation.
Definition: md5.c:261
void * mutt_md5_finish_ctx(struct Md5Ctx *md5ctx, void *resbuf)
Process the remaining bytes in the buffer.
Definition: md5.c:285
void mutt_md5_toascii(const void *digest, char *resbuf)
Convert a binary MD5 digest into ASCII Hexadecimal.
Definition: md5.c:456
#define FREE(x)
Definition: memory.h:55
#define MUTT_MEM_REALLOC(pptr, n, type)
Definition: memory.h:43
#define MUTT_MEM_MALLOC(n, type)
Definition: memory.h:41
#define MAX(a, b)
Definition: memory.h:31
#define mutt_array_size(x)
Definition: memory.h:38
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:672
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:803
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:425
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:230
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
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:96
Pop-specific Account data.
bool pop_auth_is_valid(const char *authenticator)
Check if string is a valid pop authentication method.
Definition: auth.c:502
static const struct PopAuth PopAuthenticators[]
Accepted authentication methods.
Definition: auth.c:479
void pop_apop_timestamp(struct PopAccountData *adata, char *buf)
Get the server timestamp for APOP authentication.
Definition: auth.c:301
int pop_authenticate(struct PopAccountData *adata)
Authenticate with a POP server.
Definition: auth.c:523
int pop_connect(struct PopAccountData *adata)
Open connection.
Definition: lib.c:281
int pop_query_d(struct PopAccountData *adata, char *buf, size_t buflen, char *msg)
Send data from buffer and receive answer to the same buffer.
Definition: lib.c:465
PopAuthRes
POP authentication responses.
Definition: private.h:58
@ POP_A_UNAVAIL
No valid authentication method.
Definition: private.h:62
@ POP_A_SUCCESS
Authenticated successfully.
Definition: private.h:59
@ POP_A_FAILURE
Authentication failed.
Definition: private.h:61
@ POP_A_SOCKET
Connection lost.
Definition: private.h:60
#define pop_query(adata, buf, buflen)
Definition: private.h:111
@ POP_DISCONNECTED
Disconnected from server.
Definition: private.h:51
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
int mutt_sasl_interact(sasl_interact_t *interaction)
Perform an SASL interaction with the user.
Definition: sasl.c:704
int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
Wrapper for sasl_client_new()
Definition: sasl.c:606
void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
Set up an SASL connection.
Definition: sasl.c:741
GUI display the mailboxes in a side panel.
int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
Read a line from a socket.
Definition: socket.c:238
#define MUTT_SOCK_LOG_FULL
Definition: socket.h:54
#define mutt_socket_send(conn, buf)
Definition: socket.h:57
#define mutt_socket_buffer_readln(buf, conn)
Definition: socket.h:61
String manipulation buffer.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:37
Login details for a remote server.
Definition: connaccount.h:53
char user[128]
Username.
Definition: connaccount.h:56
char pass[256]
Password.
Definition: connaccount.h:57
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:49
A List node for strings.
Definition: list.h:37
char * data
String.
Definition: list.h:38
Cursor for the MD5 hashing.
Definition: md5.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
POP-specific Account data -.
Definition: adata.h:37
char err_msg[POP_CMD_RESPONSE]
Definition: adata.h:56
unsigned int status
Definition: adata.h:39
struct Connection * conn
Connection to POP server.
Definition: adata.h:38
char * timestamp
Definition: adata.h:54
unsigned int cmd_user
optional command USER
Definition: adata.h:44
struct Buffer auth_list
list of auth mechanisms
Definition: adata.h:53
POP authentication multiplexor.
Definition: private.h:78
const char * method
Name of authentication method supported, NULL means variable.
Definition: private.h:89
enum PopAuthRes(* authenticate)(struct PopAccountData *adata, const char *method)
Definition: private.h:87
String list.
Definition: slist.h:37
struct ListHead head
List containing values.
Definition: slist.h:38
size_t count
Number of values in list.
Definition: slist.h:39