NeoMutt  2025-12-11-911-gd8d604
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 342 of file auth.c.

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}
bool mutt_addr_valid_msgid(const char *msgid)
Is this a valid Message ID?
Definition address.c:801
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 391 of file auth.c.

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}
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 449 of file auth.c.

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}
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:808
#define mutt_socket_send(conn, buf)
Definition socket.h:56
+ Here is the call graph for this function: