NeoMutt  2025-12-11-435-g4ac674
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
sasl.h File Reference

SASL authentication support. More...

#include <sasl/sasl.h>
#include <stdbool.h>
+ Include dependency graph for sasl.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

bool sasl_auth_validator (const char *authenticator)
 Validate an auth method against Cyrus SASL methods.
 
int mutt_sasl_client_new (struct Connection *conn, sasl_conn_t **saslconn)
 Wrapper for sasl_client_new()
 
void mutt_sasl_cleanup (void)
 Invoke when processing is complete.
 
int mutt_sasl_interact (sasl_interact_t *interaction)
 Perform an SASL interaction with the user.
 
void mutt_sasl_setup_conn (struct Connection *conn, sasl_conn_t *saslconn)
 Set up an SASL connection.
 
int mutt_sasl_start (void)
 Initialise SASL library.
 

Detailed Description

SASL authentication support.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file sasl.h.

Function Documentation

◆ sasl_auth_validator()

bool sasl_auth_validator ( const char * authenticator)

Validate an auth method against Cyrus SASL methods.

Parameters
authenticatorName of the authenticator to validate
Return values
trueArgument matches an accepted auth method

Definition at line 131 of file sasl.c.

132{
133 for (size_t i = 0; i < countof(SaslAuthenticators); i++)
134 {
135 const char *auth = SaslAuthenticators[i];
136 if (mutt_istr_equal(auth, authenticator))
137 return true;
138 }
139
140 return false;
141}
#define countof(x)
Definition memory.h:49
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:674
static const char *const SaslAuthenticators[]
Authentication methods supported by Cyrus SASL.
Definition sasl.c:105
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_sasl_client_new()

int mutt_sasl_client_new ( struct Connection * conn,
sasl_conn_t ** saslconn )

Wrapper for sasl_client_new()

Parameters
[in]connConnection to a server
[out]saslconnSASL connection
Return values
0Success
-1Error

which also sets various security properties. If this turns out to be fine for POP too we can probably stop exporting mutt_sasl_get_callbacks().

Definition at line 601 of file sasl.c.

602{
603 if (mutt_sasl_start() != SASL_OK)
604 return -1;
605
606 if (!conn->account.service)
607 {
608 mutt_error(_("Unknown SASL profile"));
609 return -1;
610 }
611
612 socklen_t size;
613
614 struct sockaddr_storage local = { 0 };
615 char iplocalport[IP_PORT_BUFLEN] = { 0 };
616 char *plp = NULL;
617 size = sizeof(local);
618 if (getsockname(conn->fd, (struct sockaddr *) &local, &size) == 0)
619 {
620 if (iptostring((struct sockaddr *) &local, size, iplocalport, IP_PORT_BUFLEN) == SASL_OK)
621 plp = iplocalport;
622 else
623 mutt_debug(LL_DEBUG2, "SASL failed to parse local IP address\n");
624 }
625 else
626 {
627 mutt_debug(LL_DEBUG2, "SASL failed to get local IP address\n");
628 }
629
630 struct sockaddr_storage remote = { 0 };
631 char ipremoteport[IP_PORT_BUFLEN] = { 0 };
632 char *prp = NULL;
633 size = sizeof(remote);
634 if (getpeername(conn->fd, (struct sockaddr *) &remote, &size) == 0)
635 {
636 if (iptostring((struct sockaddr *) &remote, size, ipremoteport, IP_PORT_BUFLEN) == SASL_OK)
637 prp = ipremoteport;
638 else
639 mutt_debug(LL_DEBUG2, "SASL failed to parse remote IP address\n");
640 }
641 else
642 {
643 mutt_debug(LL_DEBUG2, "SASL failed to get remote IP address\n");
644 }
645
646 mutt_debug(LL_DEBUG2, "SASL local ip: %s, remote ip:%s\n", NONULL(plp), NONULL(prp));
647
648 int rc = sasl_client_new(conn->account.service, conn->account.host, plp, prp,
649 mutt_sasl_get_callbacks(&conn->account), 0, saslconn);
650 if (rc != SASL_OK)
651 {
652 mutt_error(_("Error allocating SASL connection"));
653 return -1;
654 }
655
656 /* Work around a casting bug in the SASL krb4 module */
657 sasl_security_properties_t secprops = { 0 };
658 secprops.max_ssf = 0x7fff;
659 secprops.maxbufsize = MUTT_SASL_MAXBUF;
660 if (sasl_setprop(*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
661 {
662 mutt_error(_("Error setting SASL security properties"));
663 sasl_dispose(saslconn);
664 return -1;
665 }
666
667 if (conn->ssf != 0)
668 {
669 /* I'm not sure this actually has an effect, at least with SASLv2 */
670 mutt_debug(LL_DEBUG2, "External SSF: %d\n", conn->ssf);
671 if (sasl_setprop(*saslconn, SASL_SSF_EXTERNAL, &conn->ssf) != SASL_OK)
672 {
673 mutt_error(_("Error setting SASL external security strength"));
674 sasl_dispose(saslconn);
675 return -1;
676 }
677 }
678 if (conn->account.user[0])
679 {
680 mutt_debug(LL_DEBUG2, "External authentication name: %s\n", conn->account.user);
681 if (sasl_setprop(*saslconn, SASL_AUTH_EXTERNAL, conn->account.user) != SASL_OK)
682 {
683 mutt_error(_("Error setting SASL external user name"));
684 sasl_dispose(saslconn);
685 return -1;
686 }
687 }
688
689 return 0;
690}
#define mutt_error(...)
Definition logging2.h:94
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
#define _(a)
Definition message.h:28
#define MUTT_SASL_MAXBUF
Maximum size for SASL protection buffer.
Definition sasl.c:115
#define IP_PORT_BUFLEN
Buffer size for "host;port" string (NI_MAXHOST + NI_MAXSERV)
Definition sasl.c:118
int mutt_sasl_start(void)
Initialise SASL library.
Definition sasl.c:272
static sasl_callback_t * mutt_sasl_get_callbacks(struct ConnAccount *cac)
Get the SASL callback functions.
Definition sasl.c:384
static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out, unsigned int outlen)
Convert IP Address to string.
Definition sasl.c:202
#define NONULL(x)
Definition string2.h:44
char user[128]
Username.
Definition connaccount.h:56
const char * service
Name of the service, e.g. "imap".
Definition connaccount.h:61
char host[128]
Server to login to.
Definition connaccount.h:54
unsigned int ssf
Security strength factor, in bits (see notes)
Definition connection.h:50
struct ConnAccount account
Account details: username, password, etc.
Definition connection.h:49
int fd
Socket file descriptor.
Definition connection.h:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_sasl_cleanup()

void mutt_sasl_cleanup ( void )

Invoke when processing is complete.

This is a cleanup function, used to free all memory used by the library. Invoke when processing is complete.

Definition at line 781 of file sasl.c.

782{
783 /* As we never use the server-side, the silently ignore the return value */
784 sasl_client_done();
785}
+ Here is the caller graph for this function:

◆ mutt_sasl_interact()

int mutt_sasl_interact ( sasl_interact_t * interaction)

Perform an SASL interaction with the user.

Parameters
interactionDetails of interaction
Return values
numSASL error code: SASL_OK or SASL_FAIL

An example interaction might be asking the user for a password.

Definition at line 699 of file sasl.c.

700{
701 int rc = SASL_OK;
702 char prompt[128] = { 0 };
703 struct Buffer *resp = buf_pool_get();
704
705 while (interaction->id != SASL_CB_LIST_END)
706 {
707 mutt_debug(LL_DEBUG2, "filling in SASL interaction %ld\n", interaction->id);
708
709 snprintf(prompt, sizeof(prompt), "%s: ", interaction->prompt);
710 buf_reset(resp);
711
712 if (!OptGui ||
713 (mw_get_field(prompt, resp, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0))
714 {
715 rc = SASL_FAIL;
716 break;
717 }
718
719 interaction->len = buf_len(resp) + 1;
720 interaction->result = buf_strdup(resp);
721 interaction++;
722 }
723
724 buf_pool_release(&resp);
725 return rc;
726}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:491
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition wdata.h:42
bool OptGui
(pseudo) when the gui (and curses) are started
Definition globals.c:48
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:270
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:60
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
String manipulation buffer.
Definition buffer.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_sasl_setup_conn()

void mutt_sasl_setup_conn ( struct Connection * conn,
sasl_conn_t * saslconn )

Set up an SASL connection.

Parameters
connConnection to a server
saslconnSASL connection

Replace connection methods, sockdata with SASL wrappers, for protection layers. Also get ssf, as a fastpath for the read/write methods.

Definition at line 736 of file sasl.c.

737{
738 struct SaslSockData *sasldata = MUTT_MEM_MALLOC(1, struct SaslSockData);
739 /* work around sasl_getprop aliasing issues */
740 const void *tmp = NULL;
741
742 sasldata->saslconn = saslconn;
743 /* get ssf so we know whether we have to (en|de)code read/write */
744 sasl_getprop(saslconn, SASL_SSF, &tmp);
745 sasldata->ssf = tmp;
746 mutt_debug(LL_DEBUG3, "SASL protection strength: %u\n", *sasldata->ssf);
747 /* Add SASL SSF to transport SSF */
748 conn->ssf += *sasldata->ssf;
749 sasl_getprop(saslconn, SASL_MAXOUTBUF, &tmp);
750 sasldata->pbufsize = tmp;
751 mutt_debug(LL_DEBUG3, "SASL protection buffer size: %u\n", *sasldata->pbufsize);
752
753 /* clear input buffer */
754 sasldata->buf = NULL;
755 sasldata->bpos = 0;
756 sasldata->blen = 0;
757
758 /* preserve old functions */
759 sasldata->sockdata = conn->sockdata;
760 sasldata->open = conn->open;
761 sasldata->read = conn->read;
762 sasldata->write = conn->write;
763 sasldata->poll = conn->poll;
764 sasldata->close = conn->close;
765
766 /* and set up new functions */
767 conn->sockdata = sasldata;
773}
static int mutt_sasl_conn_close(struct Connection *conn)
Close SASL connection - Implements Connection::close() -.
Definition sasl.c:438
int(* close)(struct Connection *conn)
Close a socket Connection - Implements Connection::close() -.
Definition sasl.c:99
int(* open)(struct Connection *conn)
Open a socket Connection - Implements Connection::open() -.
Definition sasl.c:79
static int mutt_sasl_conn_open(struct Connection *conn)
Empty wrapper for underlying open function - Implements Connection::open() -.
Definition sasl.c:422
int(* poll)(struct Connection *conn, time_t wait_secs)
Check if any data is waiting on a socket - Implements Connection::poll() -.
Definition sasl.c:94
static int mutt_sasl_conn_poll(struct Connection *conn, time_t wait_secs)
Check if any data is waiting on a socket - Implements Connection::poll() -.
Definition sasl.c:579
static int mutt_sasl_conn_read(struct Connection *conn, char *buf, size_t count)
Read data from an SASL connection - Implements Connection::read() -.
Definition sasl.c:463
int(* read)(struct Connection *conn, char *buf, size_t count)
Read from a socket Connection - Implements Connection::read() -.
Definition sasl.c:84
static int mutt_sasl_conn_write(struct Connection *conn, const char *buf, size_t count)
Write to an SASL connection - Implements Connection::write() -.
Definition sasl.c:529
int(* write)(struct Connection *conn, const char *buf, size_t count)
Write to a socket Connection - Implements Connection::write() -.
Definition sasl.c:89
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:53
void * sockdata
Backend-specific socket data.
Definition connection.h:55
int(* poll)(struct Connection *conn, time_t wait_secs)
Definition connection.h:105
int(* write)(struct Connection *conn, const char *buf, size_t count)
Definition connection.h:92
int(* close)(struct Connection *conn)
Definition connection.h:116
int(* open)(struct Connection *conn)
Definition connection.h:66
int(* read)(struct Connection *conn, char *buf, size_t count)
Definition connection.h:79
SASL authentication API -.
Definition sasl.c:64
void * sockdata
Underlying socket data.
Definition sasl.c:74
unsigned int blen
Size of the read buffer.
Definition sasl.c:71
unsigned int bpos
Current read position.
Definition sasl.c:72
const sasl_ssf_t * ssf
Security strength factor, in bits.
Definition sasl.c:66
const unsigned int * pbufsize
Buffer size.
Definition sasl.c:67
const char * buf
Buffer for data read from the connection.
Definition sasl.c:70
sasl_conn_t * saslconn
Raw SASL connection.
Definition sasl.c:65
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_sasl_start()

int mutt_sasl_start ( void )

Initialise SASL library.

Return values
numSASL error code, e.g. SASL_OK

Call before doing an SASL exchange (initialises library if necessary).

Definition at line 272 of file sasl.c.

273{
274 static bool sasl_init = false;
275
276 static sasl_callback_t callbacks[2];
277 int rc;
278
279 if (sasl_init)
280 return SASL_OK;
281
282 /* set up default logging callback */
283 callbacks[0].id = SASL_CB_LOG;
284 callbacks[0].proc = (int (*)(void))(intptr_t) mutt_sasl_cb_log;
285 callbacks[0].context = NULL;
286
287 callbacks[1].id = SASL_CB_LIST_END;
288 callbacks[1].proc = NULL;
289 callbacks[1].context = NULL;
290
291 rc = sasl_client_init(callbacks);
292
293 if (rc != SASL_OK)
294 {
295 mutt_debug(LL_DEBUG1, "libsasl initialisation failed\n");
296 return SASL_FAIL;
297 }
298
299 sasl_init = true;
300
301 return SASL_OK;
302}
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
static int mutt_sasl_cb_log(void *context, int priority, const char *message)
Callback to log SASL messages.
Definition sasl.c:235
+ Here is the call graph for this function:
+ Here is the caller graph for this function: