50#include <sys/socket.h>
68 const sasl_ssf_t *
ssf;
108 "ANONYMOUS",
"CRAM-MD5",
"DIGEST-MD5",
"EXTERNAL",
109 "GS2-IAKERB",
"GS2-KRB5",
"GSS-SPNEGO",
"GSSAPI",
110 "LOGIN",
"NTLM",
"OTP-MD4",
"OTP-MD5",
111 "OTP-SHA1",
"PASSDSS-3DES-1",
"PLAIN",
"SCRAM-SHA-1",
112 "SCRAM-SHA-224",
"SCRAM-SHA-256",
"SCRAM-SHA-384",
"SCRAM-SHA-512",
117#define MUTT_SASL_MAXBUF 65536
120#define IP_PORT_BUFLEN (NI_MAXHOST + NI_MAXSERV)
157 mutt_debug(
LL_DEBUG1,
"The name could not be resolved at this time. Future attempts may succeed\n");
169 mutt_debug(
LL_DEBUG1,
"The address family was not recognized or the address length was invalid for the specified family\n");
178 "NI_NAMEREQD is set and the host's name can't be located, or both nodename and servname were null.\n");
182 mutt_debug(
LL_DEBUG1,
"A system error occurred. The error code can be found in errno(%d,%s))\n",
183 errno, strerror(errno));
204static int iptostring(
const struct sockaddr *addr, socklen_t addrlen,
char *out,
207 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
211 return SASL_BADPARAM;
213 rc = getnameinfo(addr, addrlen, hbuf,
sizeof(hbuf), pbuf,
sizeof(pbuf),
222 if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
225 snprintf(out, outlen,
"%s;%s", hbuf, pbuf);
239 if (priority == SASL_LOG_NONE)
242 int mutt_priority = 0;
264 mutt_debug(mutt_priority,
"SASL: %s\n", message);
276 static bool sasl_init =
false;
278 static sasl_callback_t callbacks[2];
285 callbacks[0].id = SASL_CB_LOG;
287 callbacks[0].context = NULL;
289 callbacks[1].id = SASL_CB_LIST_END;
290 callbacks[1].proc = NULL;
291 callbacks[1].context = NULL;
293 rc = sasl_client_init(callbacks);
326 return SASL_BADPARAM;
329 (
id == SASL_CB_AUTHNAME) ?
"authname" :
"user", cac->
host, cac->
port);
331 if (
id == SASL_CB_AUTHNAME)
335 *result = cac->
login;
345 *len = strlen(*result);
363 if (!cac || !psecret)
364 return SASL_BADPARAM;
372 len = strlen(cac->
pass);
374 sasl_secret_t *secret = mod_data->secret_ptr;
376 memcpy((
char *) secret->data, cac->
pass, (
size_t) len);
378 mod_data->secret_ptr = secret;
392 if (!mod_data->mutt_sasl_callbacks)
393 mod_data->mutt_sasl_callbacks =
mutt_mem_calloc(5,
sizeof(sasl_callback_t));
395 sasl_callback_t *callback = mod_data->mutt_sasl_callbacks;
397 callback->id = SASL_CB_USER;
399 callback->context = cac;
402 callback->id = SASL_CB_AUTHNAME;
404 callback->context = cac;
407 callback->id = SASL_CB_PASS;
409 callback->context = cac;
412 callback->id = SASL_CB_GETREALM;
413 callback->proc = NULL;
414 callback->context = NULL;
417 callback->id = SASL_CB_LIST_END;
418 callback->proc = NULL;
419 callback->context = NULL;
421 return mod_data->mutt_sasl_callbacks;
435 int rc = sasldata->
open(conn);
464 int rc = conn->
close(conn);
480 if (sasldata->
blen > sasldata->
bpos)
482 olen = ((sasldata->
blen - sasldata->
bpos) > count) ?
486 memcpy(
buf, sasldata->
buf + sasldata->
bpos, olen);
487 sasldata->
bpos += olen;
498 if (*sasldata->
ssf != 0)
503 rc = sasldata->
read(conn,
buf, count);
513 }
while (sasldata->
blen == 0);
515 olen = ((sasldata->
blen - sasldata->
bpos) > count) ?
519 memcpy(
buf, sasldata->
buf, olen);
520 sasldata->
bpos += olen;
526 rc = sasldata->
read(conn,
buf, count);
541 const char *pbuf = NULL;
542 unsigned int olen, plen;
548 if (*sasldata->
ssf != 0)
555 rc = sasl_encode(sasldata->
saslconn,
buf, olen, &pbuf, &plen);
562 rc = sasldata->
write(conn, pbuf, plen);
568 }
while (count > *sasldata->
pbufsize);
573 rc = sasldata->
write(conn,
buf, count);
594 rc = sasldata->
poll(conn, wait_secs);
623 struct sockaddr_storage local = { 0 };
626 size =
sizeof(local);
627 if (getsockname(conn->
fd, (
struct sockaddr *) &local, &size) == 0)
639 struct sockaddr_storage remote = { 0 };
642 size =
sizeof(remote);
643 if (getpeername(conn->
fd, (
struct sockaddr *) &remote, &size) == 0)
666 sasl_security_properties_t secprops = { 0 };
667 secprops.max_ssf = 0x7fff;
669 if (sasl_setprop(*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
671 mutt_error(
_(
"Error setting SASL security properties"));
672 sasl_dispose(saslconn);
680 if (sasl_setprop(*saslconn, SASL_SSF_EXTERNAL, &conn->
ssf) != SASL_OK)
682 mutt_error(
_(
"Error setting SASL external security strength"));
683 sasl_dispose(saslconn);
690 if (sasl_setprop(*saslconn, SASL_AUTH_EXTERNAL, conn->
account.
user) != SASL_OK)
692 mutt_error(
_(
"Error setting SASL external user name"));
693 sasl_dispose(saslconn);
711 char prompt[128] = { 0 };
714 while (interaction->id != SASL_CB_LIST_END)
718 snprintf(prompt,
sizeof(prompt),
"%s: ", interaction->prompt);
727 interaction->len =
buf_len(resp) + 1;
748 const void *tmp = NULL;
752 sasl_getprop(
saslconn, SASL_SSF, &tmp);
756 conn->
ssf += *sasldata->
ssf;
757 sasl_getprop(
saslconn, SASL_MAXOUTBUF, &tmp);
762 sasldata->
buf = NULL;
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Conn private Module data.
int mutt_account_getpass(struct ConnAccount *cac)
Fetch password into ConnAccount, if necessary.
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
int mutt_account_getlogin(struct ConnAccount *cac)
Retrieve login info into ConnAccount, if necessary.
An open network connection (socket)
Convenience wrapper for the core headers.
@ MUTT_COMP_NONE
No flags are set.
bool OptGui
(pseudo) when the gui (and curses) are started
static int mutt_sasl_conn_close(struct Connection *conn)
Close SASL connection - Implements Connection::close() -.
int(* close)(struct Connection *conn)
Close a socket Connection - Implements Connection::close() -.
int(* open)(struct Connection *conn)
Open a socket Connection - Implements Connection::open() -.
static int mutt_sasl_conn_open(struct Connection *conn)
Empty wrapper for underlying open function - Implements Connection::open() -.
int(* poll)(struct Connection *conn, time_t wait_secs)
Check if any data is waiting on a socket - Implements Connection::poll() -.
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() -.
static int mutt_sasl_conn_read(struct Connection *conn, char *buf, size_t count)
Read data from an SASL connection - Implements Connection::read() -.
int(* read)(struct Connection *conn, char *buf, size_t count)
Read from a socket Connection - Implements Connection::read() -.
static int mutt_sasl_conn_write(struct Connection *conn, const char *buf, size_t count)
Write to an SASL connection - Implements Connection::write() -.
int(* write)(struct Connection *conn, const char *buf, size_t count)
Write to a socket Connection - Implements Connection::write() -.
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 -.
#define mutt_debug(LEVEL,...)
Read/write command history from/to a file.
@ HC_OTHER
Miscellaneous strings.
@ LL_DEBUG3
Log at debug level 3.
@ LL_DEBUG2
Log at debug level 2.
@ LL_DEBUG1
Log at debug level 1.
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
void mutt_mem_realloc(void *pptr, size_t size)
Resize a block of memory on the heap.
#define FREE(x)
Free memory and set the pointer to NULL.
#define MUTT_MEM_MALLOC(n, type)
@ MODULE_ID_CONN
ModuleConn, Network connections
Convenience wrapper for the library headers.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
static int mutt_sasl_cb_pass(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret)
SASL callback function to get password.
#define MUTT_SASL_MAXBUF
Maximum size for SASL protection buffer.
static int mutt_sasl_cb_authname(void *context, int id, const char **result, unsigned int *len)
Callback to retrieve authname or user from ConnAccount.
void mutt_sasl_cleanup(void)
Invoke when processing is complete.
#define IP_PORT_BUFLEN
Buffer size for "host;port" string (NI_MAXHOST + NI_MAXSERV)
int mutt_sasl_start(void)
Initialise SASL library.
static int getnameinfo_err(int rc)
Convert a getaddrinfo() error code into an SASL error code.
int mutt_sasl_interact(sasl_interact_t *interaction)
Perform an SASL interaction with the user.
static int mutt_sasl_cb_log(void *context, int priority, const char *message)
Callback to log SASL messages.
static sasl_callback_t * mutt_sasl_get_callbacks(struct ConnAccount *cac)
Get the SASL callback functions.
static const char *const SaslAuthenticators[]
Authentication methods supported by Cyrus SASL.
static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out, unsigned int outlen)
Convert IP Address to string.
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_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
Set up an SASL connection.
SASL authentication support.
String manipulation buffer.
Login details for a remote server.
char login[128]
Login name.
const char * service
Name of the service, e.g. "imap".
char host[128]
Server to login to.
unsigned short port
Port to connect to.
Conn private Module data.
void * sockdata
Backend-specific socket data.
int(* poll)(struct Connection *conn, time_t wait_secs)
int(* write)(struct Connection *conn, const char *buf, size_t count)
unsigned int ssf
Security strength factor, in bits (see notes)
int(* close)(struct Connection *conn)
struct ConnAccount account
Account details: username, password, etc.
int(* open)(struct Connection *conn)
int fd
Socket file descriptor.
int(* read)(struct Connection *conn, char *buf, size_t count)
Container for Accounts, Notifications.
SASL authentication API -.
void * sockdata
Underlying socket data.
unsigned int blen
Size of the read buffer.
unsigned int bpos
Current read position.
const sasl_ssf_t * ssf
Security strength factor, in bits.
const unsigned int * pbufsize
Buffer size.
const char * buf
Buffer for data read from the connection.
sasl_conn_t * saslconn
Raw SASL connection.