NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
POP Authentication API

Authenticate a POP connection. More...

Functions

static enum PopAuthRes pop_auth_apop (struct PopAccountData *adata, const char *method)
 APOP authenticator - Implements PopAuth::authenticate() -.
 
static enum PopAuthRes pop_auth_user (struct PopAccountData *adata, const char *method)
 USER authenticator - Implements PopAuth::authenticate() -.
 
static enum PopAuthRes pop_auth_oauth (struct PopAccountData *adata, const char *method)
 Authenticate a POP connection using OAUTHBEARER - Implements PopAuth::authenticate() -.
 

Detailed Description

Authenticate a POP connection.

Parameters
adataPOP Account data
methodName of this authentication method (UNUSED)
Return values
enumPopAuthRes, e.g. POP_A_SUCCESS

Function Documentation

◆ pop_auth_apop()

static enum PopAuthRes pop_auth_apop ( struct PopAccountData * adata,
const char * method )
static

APOP authenticator - Implements PopAuth::authenticate() -.

Definition at line 343 of file auth.c.

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)))
376 {
377 case 0:
378 return POP_A_SUCCESS;
379 case -1:
380 return POP_A_SOCKET;
381 }
382
383 // L10N: %s is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
384 mutt_error(_("%s authentication failed"), "APOP");
385
386 return POP_A_FAILURE;
387}
bool mutt_addr_valid_msgid(const char *msgid)
Is this a valid Message ID?
Definition address.c:803
int mutt_account_getpass(struct ConnAccount *cac)
Fetch password into ConnAccount, if necessary.
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
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 _(a)
Definition message.h:28
@ 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
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
Cursor for the MD5 hashing.
Definition md5.h:37
struct Connection * conn
Connection to POP server.
Definition adata.h:38
char * timestamp
APOP timestamp.
Definition adata.h:55
+ Here is the call graph for this function:

◆ pop_auth_user()

static enum PopAuthRes pop_auth_user ( struct PopAccountData * adata,
const char * method )
static

USER authenticator - Implements PopAuth::authenticate() -.

Definition at line 392 of file auth.c.

393{
394 if (!adata->cmd_user)
395 return POP_A_UNAVAIL;
396
397 if (mutt_account_getpass(&adata->conn->account) || !adata->conn->account.pass[0])
398 return POP_A_FAILURE;
399
400 mutt_message(_("Logging in..."));
401
402 char buf[1024] = { 0 };
403 snprintf(buf, sizeof(buf), "USER %s\r\n", adata->conn->account.user);
404 int rc = pop_query(adata, buf, sizeof(buf));
405
406 if (adata->cmd_user == 2)
407 {
408 if (rc == 0)
409 {
410 adata->cmd_user = 1;
411
412 mutt_debug(LL_DEBUG1, "set USER capability\n");
413 }
414
415 if (rc == -2)
416 {
417 adata->cmd_user = 0;
418
419 mutt_debug(LL_DEBUG1, "unset USER capability\n");
420 snprintf(adata->err_msg, sizeof(adata->err_msg), "%s",
421 _("Command USER is not supported by server"));
422 }
423 }
424
425 if (rc == 0)
426 {
427 snprintf(buf, sizeof(buf), "PASS %s\r\n", adata->conn->account.pass);
428 const short c_debug_level = cs_subset_number(NeoMutt->sub, "debug_level");
429 rc = pop_query_d(adata, buf, sizeof(buf),
430 /* don't print the password unless we're at the ungodly debugging level */
431 (c_debug_level < MUTT_SOCK_LOG_FULL) ? "PASS *\r\n" : NULL);
432 }
433
434 switch (rc)
435 {
436 case 0:
437 return POP_A_SUCCESS;
438 case -1:
439 return POP_A_SOCKET;
440 }
441
442 mutt_error("%s %s", _("Login failed"), adata->err_msg);
443
444 return POP_A_FAILURE;
445}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
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
#define MUTT_SOCK_LOG_FULL
Log everything including full protocol.
Definition socket.h:53
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
char err_msg[POP_CMD_RESPONSE]
Last error message.
Definition adata.h:57
unsigned int cmd_user
optional command USER
Definition adata.h:44
+ Here is the call graph for this function:

◆ pop_auth_oauth()

static enum PopAuthRes pop_auth_oauth ( struct PopAccountData * adata,
const char * method )
static

Authenticate a POP connection using OAUTHBEARER - Implements PopAuth::authenticate() -.

Definition at line 450 of file auth.c.

451{
452 /* If they did not explicitly request or configure oauth then fail quietly */
453 const char *const c_pop_oauth_refresh_command = cs_subset_string(NeoMutt->sub, "pop_oauth_refresh_command");
454 if (!method && !c_pop_oauth_refresh_command)
455 return POP_A_UNAVAIL;
456
457 // L10N: (%s) is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
458 mutt_message(_("Authenticating (%s)..."), "OAUTHBEARER");
459
460 char *oauthbearer = mutt_account_getoauthbearer(&adata->conn->account, false);
461 if (!oauthbearer)
462 return POP_A_FAILURE;
463
464 char *auth_cmd = NULL;
465 mutt_str_asprintf(&auth_cmd, "AUTH OAUTHBEARER %s\r\n", oauthbearer);
466 FREE(&oauthbearer);
467
468 int rc = pop_query_d(adata, auth_cmd, strlen(auth_cmd),
469#ifdef DEBUG
470 /* don't print the bearer token unless we're at the ungodly debugging level */
471 (cs_subset_number(NeoMutt->sub, "debug_level") < MUTT_SOCK_LOG_FULL) ?
472 "AUTH OAUTHBEARER *\r\n" :
473#endif
474 NULL);
475 FREE(&auth_cmd);
476
477 switch (rc)
478 {
479 case 0:
480 return POP_A_SUCCESS;
481 case -1:
482 return POP_A_SOCKET;
483 }
484
485 /* The error response was a SASL continuation, so "continue" it.
486 * See RFC7628 3.2.3 */
487 mutt_socket_send(adata->conn, "\001");
488
489 char *err = adata->err_msg;
490 char decoded_err[1024] = { 0 };
491 int len = mutt_b64_decode(adata->err_msg, decoded_err, sizeof(decoded_err) - 1);
492 if (len >= 0)
493 {
494 decoded_err[len] = '\0';
495 err = decoded_err;
496 }
497 mutt_error("%s %s", _("Authentication failed"), err);
498
499 return POP_A_FAILURE;
500}
int mutt_b64_decode(const char *in, char *out, size_t olen)
Convert NUL-terminated base64 string to raw bytes.
Definition base64.c:180
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
char * mutt_account_getoauthbearer(struct ConnAccount *cac, bool xoauth2)
Get an OAUTHBEARER/XOAUTH2 token.
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition string.c:809
#define mutt_socket_send(conn, buf)
Definition socket.h:56
+ Here is the call graph for this function: