NeoMutt  2025-12-11-911-gd8d604
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)
 SASL callback functions, e.g. mutt_sasl_cb_authname(), mutt_sasl_cb_pass()
 
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)

SASL callback functions, e.g. mutt_sasl_cb_authname(), mutt_sasl_cb_pass()

SASL secret, to store the password 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 133 of file sasl.c.

134{
135 for (size_t i = 0; i < countof(SaslAuthenticators); i++)
136 {
137 const char *auth = SaslAuthenticators[i];
138 if (mutt_istr_equal(auth, authenticator))
139 return true;
140 }
141
142 return false;
143}
#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:677
static const char *const SaslAuthenticators[]
Authentication methods supported by Cyrus SASL.
Definition sasl.c:107
+ 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 610 of file sasl.c.

611{
612 if (mutt_sasl_start() != SASL_OK)
613 return -1;
614
615 if (!conn->account.service)
616 {
617 mutt_error(_("Unknown SASL profile"));
618 return -1;
619 }
620
621 socklen_t size;
622
623 struct sockaddr_storage local = { 0 };
624 char iplocalport[IP_PORT_BUFLEN] = { 0 };
625 char *plp = NULL;
626 size = sizeof(local);
627 if (getsockname(conn->fd, (struct sockaddr *) &local, &size) == 0)
628 {
629 if (iptostring((struct sockaddr *) &local, size, iplocalport, IP_PORT_BUFLEN) == SASL_OK)
630 plp = iplocalport;
631 else
632 mutt_debug(LL_DEBUG2, "SASL failed to parse local IP address\n");
633 }
634 else
635 {
636 mutt_debug(LL_DEBUG2, "SASL failed to get local IP address\n");
637 }
638
639 struct sockaddr_storage remote = { 0 };
640 char ipremoteport[IP_PORT_BUFLEN] = { 0 };
641 char *prp = NULL;
642 size = sizeof(remote);
643 if (getpeername(conn->fd, (struct sockaddr *) &remote, &size) == 0)
644 {
645 if (iptostring((struct sockaddr *) &remote, size, ipremoteport, IP_PORT_BUFLEN) == SASL_OK)
646 prp = ipremoteport;
647 else
648 mutt_debug(LL_DEBUG2, "SASL failed to parse remote IP address\n");
649 }
650 else
651 {
652 mutt_debug(LL_DEBUG2, "SASL failed to get remote IP address\n");
653 }
654
655 mutt_debug(LL_DEBUG2, "SASL local ip: %s, remote ip:%s\n", NONULL(plp), NONULL(prp));
656
657 int rc = sasl_client_new(conn->account.service, conn->account.host, plp, prp,
658 mutt_sasl_get_callbacks(&conn->account), 0, saslconn);
659 if (rc != SASL_OK)
660 {
661 mutt_error(_("Error allocating SASL connection"));
662 return -1;
663 }
664
665 /* Work around a casting bug in the SASL krb4 module */
666 sasl_security_properties_t secprops = { 0 };
667 secprops.max_ssf = 0x7fff;
668 secprops.maxbufsize = MUTT_SASL_MAXBUF;
669 if (sasl_setprop(*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
670 {
671 mutt_error(_("Error setting SASL security properties"));
672 sasl_dispose(saslconn);
673 return -1;
674 }
675
676 if (conn->ssf != 0)
677 {
678 /* I'm not sure this actually has an effect, at least with SASLv2 */
679 mutt_debug(LL_DEBUG2, "External SSF: %d\n", conn->ssf);
680 if (sasl_setprop(*saslconn, SASL_SSF_EXTERNAL, &conn->ssf) != SASL_OK)
681 {
682 mutt_error(_("Error setting SASL external security strength"));
683 sasl_dispose(saslconn);
684 return -1;
685 }
686 }
687 if (conn->account.user[0])
688 {
689 mutt_debug(LL_DEBUG2, "External authentication name: %s\n", conn->account.user);
690 if (sasl_setprop(*saslconn, SASL_AUTH_EXTERNAL, conn->account.user) != SASL_OK)
691 {
692 mutt_error(_("Error setting SASL external user name"));
693 sasl_dispose(saslconn);
694 return -1;
695 }
696 }
697
698 return 0;
699}
#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:117
#define IP_PORT_BUFLEN
Buffer size for "host;port" string (NI_MAXHOST + NI_MAXSERV)
Definition sasl.c:120
int mutt_sasl_start(void)
Initialise SASL library.
Definition sasl.c:274
static sasl_callback_t * mutt_sasl_get_callbacks(struct ConnAccount *cac)
Get the SASL callback functions.
Definition sasl.c:389
static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out, unsigned int outlen)
Convert IP Address to string.
Definition sasl.c:204
#define NONULL(x)
Definition string2.h:44
char user[128]
Username.
Definition connaccount.h:62
const char * service
Name of the service, e.g. "imap".
Definition connaccount.h:67
char host[128]
Server to login to.
Definition connaccount.h:60
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 789 of file sasl.c.

790{
791 /* As we never use the server-side, the silently ignore the return value */
792 sasl_client_done();
793}
+ 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 708 of file sasl.c.

709{
710 int rc = SASL_OK;
711 char prompt[128] = { 0 };
712 struct Buffer *resp = buf_pool_get();
713
714 while (interaction->id != SASL_CB_LIST_END)
715 {
716 mutt_debug(LL_DEBUG2, "filling in SASL interaction %ld\n", interaction->id);
717
718 snprintf(prompt, sizeof(prompt), "%s: ", interaction->prompt);
719 buf_reset(resp);
720
721 if (!OptGui || (mw_get_field(prompt, resp, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) != 0))
722 {
723 rc = SASL_FAIL;
724 break;
725 }
726
727 interaction->len = buf_len(resp) + 1;
728 interaction->result = buf_strdup(resp);
729 interaction++;
730 }
731
732 buf_pool_release(&resp);
733 return rc;
734}
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
@ MUTT_COMP_NONE
No flags are set.
Definition wdata.h:46
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:502
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:61
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 744 of file sasl.c.

745{
746 struct SaslSockData *sasldata = MUTT_MEM_MALLOC(1, struct SaslSockData);
747 /* work around sasl_getprop aliasing issues */
748 const void *tmp = NULL;
749
750 sasldata->saslconn = saslconn;
751 /* get ssf so we know whether we have to (en|de)code read/write */
752 sasl_getprop(saslconn, SASL_SSF, &tmp);
753 sasldata->ssf = tmp;
754 mutt_debug(LL_DEBUG3, "SASL protection strength: %u\n", *sasldata->ssf);
755 /* Add SASL SSF to transport SSF */
756 conn->ssf += *sasldata->ssf;
757 sasl_getprop(saslconn, SASL_MAXOUTBUF, &tmp);
758 sasldata->pbufsize = tmp;
759 mutt_debug(LL_DEBUG3, "SASL protection buffer size: %u\n", *sasldata->pbufsize);
760
761 /* clear input buffer */
762 sasldata->buf = NULL;
763 sasldata->bpos = 0;
764 sasldata->blen = 0;
765
766 /* preserve old functions */
767 sasldata->sockdata = conn->sockdata;
768 sasldata->open = conn->open;
769 sasldata->read = conn->read;
770 sasldata->write = conn->write;
771 sasldata->poll = conn->poll;
772 sasldata->close = conn->close;
773
774 /* and set up new functions */
775 conn->sockdata = sasldata;
781}
static int mutt_sasl_conn_close(struct Connection *conn)
Close SASL connection - Implements Connection::close() -.
Definition sasl.c:447
int(* close)(struct Connection *conn)
Close a socket Connection - Implements Connection::close() -.
Definition sasl.c:101
int(* open)(struct Connection *conn)
Open a socket Connection - Implements Connection::open() -.
Definition sasl.c:81
static int mutt_sasl_conn_open(struct Connection *conn)
Empty wrapper for underlying open function - Implements Connection::open() -.
Definition sasl.c:431
int(* poll)(struct Connection *conn, time_t wait_secs)
Check if any data is waiting on a socket - Implements Connection::poll() -.
Definition sasl.c:96
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:588
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:472
int(* read)(struct Connection *conn, char *buf, size_t count)
Read from a socket Connection - Implements Connection::read() -.
Definition sasl.c:86
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:538
int(* write)(struct Connection *conn, const char *buf, size_t count)
Write to a socket Connection - Implements Connection::write() -.
Definition sasl.c:91
@ 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:66
void * sockdata
Underlying socket data.
Definition sasl.c:76
unsigned int blen
Size of the read buffer.
Definition sasl.c:73
unsigned int bpos
Current read position.
Definition sasl.c:74
const sasl_ssf_t * ssf
Security strength factor, in bits.
Definition sasl.c:68
const unsigned int * pbufsize
Buffer size.
Definition sasl.c:69
const char * buf
Buffer for data read from the connection.
Definition sasl.c:72
sasl_conn_t * saslconn
Raw SASL connection.
Definition sasl.c:67
+ 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 274 of file sasl.c.

275{
276 static bool sasl_init = false;
277
278 static sasl_callback_t callbacks[2];
279 int rc;
280
281 if (sasl_init)
282 return SASL_OK;
283
284 /* set up default logging callback */
285 callbacks[0].id = SASL_CB_LOG;
286 callbacks[0].proc = (int (*)(void))(intptr_t) mutt_sasl_cb_log;
287 callbacks[0].context = NULL;
288
289 callbacks[1].id = SASL_CB_LIST_END;
290 callbacks[1].proc = NULL;
291 callbacks[1].context = NULL;
292
293 rc = sasl_client_init(callbacks);
294
295 if (rc != SASL_OK)
296 {
297 mutt_debug(LL_DEBUG1, "libsasl initialisation failed\n");
298 return SASL_FAIL;
299 }
300
301 sasl_init = true;
302
303 return SASL_OK;
304}
@ 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:237
+ Here is the call graph for this function:
+ Here is the caller graph for this function: