NeoMutt  2025-12-11-435-g4ac674
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 318 of file auth.c.

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}
bool mutt_addr_valid_msgid(const char *msgid)
Is this a valid Message ID?
Definition address.c:796
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:56
char pass[256]
Password.
Definition connaccount.h:57
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 367 of file auth.c.

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

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