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