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