NeoMutt  2025-12-11-1039-g550ac6
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, NULL) == -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;
329 char *p2 = NULL;
330
331 FREE(&adata->timestamp);
332
333 if ((p1 = strchr(buf, '<')) && (p2 = strchr(p1, '>')))
334 {
335 p2[1] = '\0';
336 adata->timestamp = mutt_str_dup(p1);
337 }
338}
339
343static enum PopAuthRes pop_auth_apop(struct PopAccountData *adata, const char *method)
344{
345 struct Md5Ctx md5ctx = { 0 };
346 unsigned char digest[16] = { 0 };
347 char hash[33] = { 0 };
348 char buf[1024] = { 0 };
349
350 if (mutt_account_getpass(&adata->conn->account) || !adata->conn->account.pass[0])
351 return POP_A_FAILURE;
352
353 if (!adata->timestamp)
354 return POP_A_UNAVAIL;
355
356 if (!mutt_addr_valid_msgid(adata->timestamp))
357 {
358 mutt_error(_("POP timestamp is invalid"));
359 return POP_A_UNAVAIL;
360 }
361
362 // L10N: (%s) is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
363 mutt_message(_("Authenticating (%s)..."), "APOP");
364
365 /* Compute the authentication hash to send to the server */
366 mutt_md5_init_ctx(&md5ctx);
367 mutt_md5_process(adata->timestamp, &md5ctx);
368 mutt_md5_process(adata->conn->account.pass, &md5ctx);
369 mutt_md5_finish_ctx(&md5ctx, digest);
370 mutt_md5_toascii(digest, hash);
371
372 /* Send APOP command to server */
373 snprintf(buf, sizeof(buf), "APOP %s %s\r\n", adata->conn->account.user, hash);
374
375 switch (pop_query(adata, buf, sizeof(buf), NULL))
376 {
377 case 0:
378 return POP_A_SUCCESS;
379 case -1:
380 return POP_A_SOCKET;
381 default:
382 break;
383 }
384
385 // L10N: %s is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
386 mutt_error(_("%s authentication failed"), "APOP");
387
388 return POP_A_FAILURE;
389}
390
394static enum PopAuthRes pop_auth_user(struct PopAccountData *adata, const char *method)
395{
396 if (!adata->cmd_user)
397 return POP_A_UNAVAIL;
398
399 if (mutt_account_getpass(&adata->conn->account) || !adata->conn->account.pass[0])
400 return POP_A_FAILURE;
401
402 mutt_message(_("Logging in..."));
403
404 char buf[1024] = { 0 };
405 snprintf(buf, sizeof(buf), "USER %s\r\n", adata->conn->account.user);
406 int rc = pop_query(adata, buf, sizeof(buf), NULL);
407
408 if (adata->cmd_user == 2)
409 {
410 if (rc == 0)
411 {
412 adata->cmd_user = 1;
413
414 mutt_debug(LL_DEBUG1, "set USER capability\n");
415 }
416
417 if (rc == -2)
418 {
419 adata->cmd_user = 0;
420
421 mutt_debug(LL_DEBUG1, "unset USER capability\n");
422 snprintf(adata->err_msg, sizeof(adata->err_msg), "%s",
423 _("Command USER is not supported by server"));
424 }
425 }
426
427 if (rc == 0)
428 {
429 snprintf(buf, sizeof(buf), "PASS %s\r\n", adata->conn->account.pass);
430 const short c_debug_level = cs_subset_number(NeoMutt->sub, "debug_level");
431 rc = pop_query(adata, buf, sizeof(buf),
432 /* don't print the password unless we're at the ungodly debugging level */
433 (c_debug_level < MUTT_SOCK_LOG_FULL) ? "PASS *\r\n" : NULL);
434 }
435
436 switch (rc)
437 {
438 case 0:
439 return POP_A_SUCCESS;
440 case -1:
441 return POP_A_SOCKET;
442 default:
443 break;
444 }
445
446 mutt_error("%s %s", _("Login failed"), adata->err_msg);
447
448 return POP_A_FAILURE;
449}
450
454static enum PopAuthRes pop_auth_oauth(struct PopAccountData *adata, const char *method)
455{
456 /* If they did not explicitly request or configure oauth then fail quietly */
457 const char *const c_pop_oauth_refresh_command = cs_subset_string(NeoMutt->sub, "pop_oauth_refresh_command");
458 if (!method && !c_pop_oauth_refresh_command)
459 return POP_A_UNAVAIL;
460
461 // L10N: (%s) is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
462 mutt_message(_("Authenticating (%s)..."), "OAUTHBEARER");
463
464 char *oauthbearer = mutt_account_getoauthbearer(&adata->conn->account, false);
465 if (!oauthbearer)
466 return POP_A_FAILURE;
467
468 char *auth_cmd = NULL;
469 mutt_str_asprintf(&auth_cmd, "AUTH OAUTHBEARER %s\r\n", oauthbearer);
470 FREE(&oauthbearer);
471
472 int rc = pop_query(adata, auth_cmd, strlen(auth_cmd),
473#ifdef DEBUG
474 /* don't print the bearer token unless we're at the ungodly debugging level */
475 (cs_subset_number(NeoMutt->sub, "debug_level") < MUTT_SOCK_LOG_FULL) ?
476 "AUTH OAUTHBEARER *\r\n" :
477#endif
478 NULL);
479 FREE(&auth_cmd);
480
481 switch (rc)
482 {
483 case 0:
484 return POP_A_SUCCESS;
485 case -1:
486 return POP_A_SOCKET;
487 default:
488 break;
489 }
490
491 /* The error response was a SASL continuation, so "continue" it.
492 * See RFC7628 3.2.3 */
493 mutt_socket_send(adata->conn, "\001");
494
495 char *err = adata->err_msg;
496 char decoded_err[1024] = { 0 };
497 int len = mutt_b64_decode(adata->err_msg, decoded_err, sizeof(decoded_err) - 1);
498 if (len >= 0)
499 {
500 decoded_err[len] = '\0';
501 err = decoded_err;
502 }
503 mutt_error("%s %s", _("Authentication failed"), err);
504
505 return POP_A_FAILURE;
506}
507
511static const struct PopAuth PopAuthenticators[] = {
512 // clang-format off
513 { pop_auth_oauth, "oauthbearer" },
514#ifdef USE_SASL_CYRUS
515 { pop_auth_sasl, NULL },
516#endif
517#ifdef USE_SASL_GNU
518 { pop_auth_gsasl, NULL },
519#endif
520 { pop_auth_apop, "apop" },
521 { pop_auth_user, "user" },
522 { NULL, NULL },
523 // clang-format on
524};
525
534bool pop_auth_is_valid(const char *authenticator)
535{
536 for (size_t i = 0; i < countof(PopAuthenticators); i++)
537 {
538 const struct PopAuth *auth = &PopAuthenticators[i];
539 if (auth->method && mutt_istr_equal(auth->method, authenticator))
540 return true;
541 }
542
543 return false;
544}
545
556{
557 struct ConnAccount *cac = &adata->conn->account;
558 const struct PopAuth *authenticator = NULL;
559 int attempts = 0;
560 int rc = POP_A_UNAVAIL;
561
562 if ((mutt_account_getuser(cac) < 0) || (cac->user[0] == '\0'))
563 {
564 return -3;
565 }
566
567 const struct Slist *c_pop_authenticators = cs_subset_slist(NeoMutt->sub, "pop_authenticators");
568 const bool c_pop_auth_try_all = cs_subset_bool(NeoMutt->sub, "pop_auth_try_all");
569 if (c_pop_authenticators && (c_pop_authenticators->count > 0))
570 {
571 /* Try user-specified list of authentication methods */
572 struct ListNode *np = NULL;
573 STAILQ_FOREACH(np, &c_pop_authenticators->head, entries)
574 {
575 mutt_debug(LL_DEBUG2, "Trying method %s\n", np->data);
576 authenticator = PopAuthenticators;
577
578 /* Walk the built-in authenticator table looking for a match */
579 while (authenticator->authenticate)
580 {
581 if (!authenticator->method || mutt_istr_equal(authenticator->method, np->data))
582 {
583 rc = authenticator->authenticate(adata, np->data);
584 if (rc == POP_A_SOCKET)
585 {
586 /* Connection dropped; try reconnecting and retrying once */
587 switch (pop_connect(adata))
588 {
589 case 0:
590 {
591 rc = authenticator->authenticate(adata, np->data);
592 break;
593 }
594 case -2:
595 rc = POP_A_FAILURE;
596 break;
597 default:
598 break;
599 }
600 }
601
602 if (rc != POP_A_UNAVAIL)
603 attempts++;
604 if ((rc == POP_A_SUCCESS) || (rc == POP_A_SOCKET) ||
605 ((rc == POP_A_FAILURE) && !c_pop_auth_try_all))
606 {
607 break;
608 }
609 }
610 authenticator++;
611 }
612 }
613 }
614 else
615 {
616 /* Fall back to default: try every authenticator in order */
617 mutt_debug(LL_DEBUG2, "Using any available method\n");
618 authenticator = PopAuthenticators;
619
620 while (authenticator->authenticate)
621 {
622 rc = authenticator->authenticate(adata, NULL);
623 if (rc == POP_A_SOCKET)
624 {
625 switch (pop_connect(adata))
626 {
627 case 0:
628 {
629 rc = authenticator->authenticate(adata, NULL);
630 break;
631 }
632 case -2:
633 rc = POP_A_FAILURE;
634 break;
635 default:
636 break;
637 }
638 }
639
640 if (rc != POP_A_UNAVAIL)
641 attempts++;
642 if ((rc == POP_A_SUCCESS) || (rc == POP_A_SOCKET) ||
643 ((rc == POP_A_FAILURE) && !c_pop_auth_try_all))
644 {
645 break;
646 }
647
648 authenticator++;
649 }
650 }
651
652 /* Map internal result code to the caller's return values */
653 switch (rc)
654 {
655 case POP_A_SUCCESS:
656 return 0;
657 case POP_A_SOCKET:
658 return -1;
659 case POP_A_UNAVAIL:
660 if (attempts == 0)
661 mutt_error(_("No authenticators available"));
662 break;
663
664 default:
665 break;
666 }
667
668 return -2;
669}
bool mutt_addr_valid_msgid(const char *msgid)
Is this a valid Message ID?
Definition address.c:803
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:168
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:233
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:401
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:394
static enum PopAuthRes pop_auth_apop(struct PopAccountData *adata, const char *method)
APOP authenticator - Implements PopAuth::authenticate() -.
Definition auth.c:343
static enum PopAuthRes pop_auth_oauth(struct PopAccountData *adata, const char *method)
Authenticate a POP connection using OAUTHBEARER - Implements PopAuth::authenticate() -.
Definition auth.c:454
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:678
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:809
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:587
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:534
static const struct PopAuth PopAuthenticators[]
Accepted authentication methods.
Definition auth.c:511
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:555
int pop_connect(struct PopAccountData *adata)
Open connection.
Definition lib.c:282
int pop_query(struct PopAccountData *adata, char *buf, size_t buflen, char *msg)
Send data from buffer and receive answer to the same buffer.
Definition lib.c:467
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
@ 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:710
int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
Wrapper for sasl_client_new().
Definition sasl.c:612
void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
Set up an SASL connection.
Definition sasl.c:746
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