NeoMutt  2024-04-25-1-g3de005
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
POP Authenticaion 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 317 of file auth.c.

318{
319 struct Md5Ctx md5ctx = { 0 };
320 unsigned char digest[16];
321 char hash[33] = { 0 };
322 char buf[1024] = { 0 };
323
324 if (mutt_account_getpass(&adata->conn->account) || !adata->conn->account.pass[0])
325 return POP_A_FAILURE;
326
327 if (!adata->timestamp)
328 return POP_A_UNAVAIL;
329
330 if (!mutt_addr_valid_msgid(adata->timestamp))
331 {
332 mutt_error(_("POP timestamp is invalid"));
333 return POP_A_UNAVAIL;
334 }
335
336 // L10N: (%s) is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
337 mutt_message(_("Authenticating (%s)..."), "APOP");
338
339 /* Compute the authentication hash to send to the server */
340 mutt_md5_init_ctx(&md5ctx);
341 mutt_md5_process(adata->timestamp, &md5ctx);
342 mutt_md5_process(adata->conn->account.pass, &md5ctx);
343 mutt_md5_finish_ctx(&md5ctx, digest);
344 mutt_md5_toascii(digest, hash);
345
346 /* Send APOP command to server */
347 snprintf(buf, sizeof(buf), "APOP %s %s\r\n", adata->conn->account.user, hash);
348
349 switch (pop_query(adata, buf, sizeof(buf)))
350 {
351 case 0:
352 return POP_A_SUCCESS;
353 case -1:
354 return POP_A_SOCKET;
355 }
356
357 // L10N: %s is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
358 mutt_error(_("%s authentication failed"), "APOP");
359
360 return POP_A_FAILURE;
361}
bool mutt_addr_valid_msgid(const char *msgid)
Is this a valid Message ID?
Definition: address.c:792
int mutt_account_getpass(struct ConnAccount *cac)
Fetch password into ConnAccount, if necessary.
Definition: connaccount.c:131
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
void mutt_md5_process(const char *str, struct Md5Ctx *md5ctx)
Process a NULL-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:62
@ POP_A_SUCCESS
Authenticated successfully.
Definition: private.h:59
@ POP_A_FAILURE
Authentication failed.
Definition: private.h:61
@ POP_A_SOCKET
Connection lost.
Definition: private.h:60
#define pop_query(adata, buf, buflen)
Definition: private.h:111
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
Definition: adata.h:54
+ 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 366 of file auth.c.

367{
368 if (!adata->cmd_user)
369 return POP_A_UNAVAIL;
370
371 if (mutt_account_getpass(&adata->conn->account) || !adata->conn->account.pass[0])
372 return POP_A_FAILURE;
373
374 mutt_message(_("Logging in..."));
375
376 char buf[1024] = { 0 };
377 snprintf(buf, sizeof(buf), "USER %s\r\n", adata->conn->account.user);
378 int rc = pop_query(adata, buf, sizeof(buf));
379
380 if (adata->cmd_user == 2)
381 {
382 if (rc == 0)
383 {
384 adata->cmd_user = 1;
385
386 mutt_debug(LL_DEBUG1, "set USER capability\n");
387 }
388
389 if (rc == -2)
390 {
391 adata->cmd_user = 0;
392
393 mutt_debug(LL_DEBUG1, "unset USER capability\n");
394 snprintf(adata->err_msg, sizeof(adata->err_msg), "%s",
395 _("Command USER is not supported by server"));
396 }
397 }
398
399 if (rc == 0)
400 {
401 snprintf(buf, sizeof(buf), "PASS %s\r\n", adata->conn->account.pass);
402 const short c_debug_level = cs_subset_number(NeoMutt->sub, "debug_level");
403 rc = pop_query_d(adata, buf, sizeof(buf),
404 /* don't print the password unless we're at the ungodly debugging level */
405 (c_debug_level < MUTT_SOCK_LOG_FULL) ? "PASS *\r\n" : NULL);
406 }
407
408 switch (rc)
409 {
410 case 0:
411 return POP_A_SUCCESS;
412 case -1:
413 return POP_A_SOCKET;
414 }
415
416 mutt_error("%s %s", _("Login failed"), adata->err_msg);
417
418 return POP_A_FAILURE;
419}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:144
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
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
Definition: socket.h:54
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
char err_msg[POP_CMD_RESPONSE]
Definition: adata.h:56
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 424 of file auth.c.

425{
426 /* If they did not explicitly request or configure oauth then fail quietly */
427 const char *const c_pop_oauth_refresh_command = cs_subset_string(NeoMutt->sub, "pop_oauth_refresh_command");
428 if (!method && !c_pop_oauth_refresh_command)
429 return POP_A_UNAVAIL;
430
431 // L10N: (%s) is the method name, e.g. Anonymous, CRAM-MD5, GSSAPI, SASL
432 mutt_message(_("Authenticating (%s)..."), "OAUTHBEARER");
433
434 char *oauthbearer = mutt_account_getoauthbearer(&adata->conn->account, false);
435 if (!oauthbearer)
436 return POP_A_FAILURE;
437
438 char *auth_cmd = NULL;
439 mutt_str_asprintf(&auth_cmd, "AUTH OAUTHBEARER %s\r\n", oauthbearer);
440 FREE(&oauthbearer);
441
442 int rc = pop_query_d(adata, auth_cmd, strlen(auth_cmd),
443#ifdef DEBUG
444 /* don't print the bearer token unless we're at the ungodly debugging level */
445 (cs_subset_number(NeoMutt->sub, "debug_level") < MUTT_SOCK_LOG_FULL) ?
446 "AUTH OAUTHBEARER *\r\n" :
447#endif
448 NULL);
449 FREE(&auth_cmd);
450
451 switch (rc)
452 {
453 case 0:
454 return POP_A_SUCCESS;
455 case -1:
456 return POP_A_SOCKET;
457 }
458
459 /* The error response was a SASL continuation, so "continue" it.
460 * See RFC7628 3.2.3 */
461 mutt_socket_send(adata->conn, "\001");
462
463 char *err = adata->err_msg;
464 char decoded_err[1024] = { 0 };
465 int len = mutt_b64_decode(adata->err_msg, decoded_err, sizeof(decoded_err) - 1);
466 if (len >= 0)
467 {
468 decoded_err[len] = '\0';
469 err = decoded_err;
470 }
471 mutt_error("%s %s", _("Authentication failed"), err);
472
473 return POP_A_FAILURE;
474}
int mutt_b64_decode(const char *in, char *out, size_t olen)
Convert null-terminated base64 string to raw bytes.
Definition: base64.c:135
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
char * mutt_account_getoauthbearer(struct ConnAccount *cac, bool xoauth2)
Get an OAUTHBEARER/XOAUTH2 token.
Definition: connaccount.c:196
#define FREE(x)
Definition: memory.h:45
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:797
#define mutt_socket_send(conn, buf)
Definition: socket.h:57
+ Here is the call graph for this function: