44 #include <sasl/sasl.h> 48 #include <sys/socket.h> 49 #include <sys/types.h> 63 const sasl_ssf_t *
ssf;
103 "ANONYMOUS",
"CRAM-MD5",
"DIGEST-MD5",
"EXTERNAL",
104 "GS2-IAKERB",
"GS2-KRB5",
"GSS-SPNEGO",
"GSSAPI",
105 "LOGIN",
"NTLM",
"OTP-MD4",
"OTP-MD5",
106 "OTP-SHA1",
"PASSDSS-3DES-1",
"PLAIN",
"SCRAM-SHA-1",
107 "SCRAM-SHA-224",
"SCRAM-SHA-256",
"SCRAM-SHA-384",
"SCRAM-SHA-512",
114 #define MUTT_SASL_MAXBUF 65536 116 #define IP_PORT_BUFLEN 1024 152 "The name could not be resolved at this time. Future " 153 "attempts may succeed\n");
166 "The address family was not recognized or the address " 167 "length was invalid for the specified family\n");
176 "The name does not resolve for the supplied parameters. " 177 "NI_NAMEREQD is set and the host's name can't be located, " 178 "or both nodename and servname were null.\n");
183 "A system error occurred. The error code can be found in " 185 errno, strerror(errno));
206 static int iptostring(
const struct sockaddr *addr, socklen_t addrlen,
char *out,
209 char hbuf[NI_MAXHOST],
pbuf[NI_MAXSERV];
213 return SASL_BADPARAM;
215 ret = getnameinfo(addr, addrlen, hbuf,
sizeof(hbuf), pbuf,
sizeof(pbuf),
217 #ifdef NI_WITHSCOPEID
224 if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
227 snprintf(out, outlen,
"%s;%s", hbuf, pbuf);
241 if (priority == SASL_LOG_NONE)
244 int mutt_priority = 0;
266 mutt_debug(mutt_priority,
"SASL: %s\n", message);
278 static bool sasl_init =
false;
280 static sasl_callback_t callbacks[2];
287 callbacks[0].id = SASL_CB_LOG;
289 callbacks[0].context = NULL;
291 callbacks[1].id = SASL_CB_LIST_END;
292 callbacks[1].proc = NULL;
293 callbacks[1].context = NULL;
295 rc = sasl_client_init(callbacks);
328 return SASL_BADPARAM;
331 (
id == SASL_CB_AUTHNAME) ?
"authname" :
"user", cac->
host, cac->
port);
333 if (
id == SASL_CB_AUTHNAME)
337 *result = cac->
login;
347 *len = strlen(*result);
365 if (!cac || !psecret)
366 return SASL_BADPARAM;
373 len = strlen(cac->
pass);
392 callback->id = SASL_CB_USER;
394 callback->context = cac;
397 callback->id = SASL_CB_AUTHNAME;
399 callback->context = cac;
402 callback->id = SASL_CB_PASS;
404 callback->context = cac;
407 callback->id = SASL_CB_GETREALM;
408 callback->proc = NULL;
409 callback->context = NULL;
412 callback->id = SASL_CB_LIST_END;
413 callback->proc = NULL;
414 callback->context = NULL;
430 int rc = sasldata->
open(conn);
459 int rc = conn->
close(conn);
475 if (sasldata->
blen > sasldata->
bpos)
477 olen = ((sasldata->
blen - sasldata->
bpos) > count) ?
481 memcpy(buf, sasldata->
buf + sasldata->
bpos, olen);
482 sasldata->
bpos += olen;
493 if (*sasldata->
ssf != 0)
498 rc = sasldata->
read(conn, buf, count);
502 rc = sasl_decode(sasldata->
saslconn, buf, rc, &sasldata->
buf, &sasldata->
blen);
508 }
while (sasldata->
blen == 0);
510 olen = ((sasldata->
blen - sasldata->
bpos) > count) ?
514 memcpy(buf, sasldata->
buf, olen);
515 sasldata->
bpos += olen;
520 rc = sasldata->
read(conn, buf, count);
534 const char *
pbuf = NULL;
535 unsigned int olen,
plen;
541 if (*sasldata->
ssf != 0)
548 rc = sasl_encode(sasldata->
saslconn, buf, olen, &pbuf, &plen);
555 rc = sasldata->
write(conn, pbuf, plen);
561 }
while (count > *sasldata->
pbufsize);
566 rc = sasldata->
write(conn, buf, count);
587 rc = sasldata->
poll(conn, wait_secs);
605 sasl_security_properties_t secprops;
606 struct sockaddr_storage local, remote;
622 size =
sizeof(local);
623 if (getsockname(conn->
fd, (
struct sockaddr *) &local, &size) == 0)
633 size =
sizeof(remote);
634 if (getpeername(conn->
fd, (
struct sockaddr *) &remote, &size) == 0)
655 memset(&secprops, 0,
sizeof(secprops));
657 secprops.max_ssf = 0x7fff;
659 if (sasl_setprop(*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
661 mutt_error(
_(
"Error setting SASL security properties"));
662 sasl_dispose(saslconn);
670 if (sasl_setprop(*saslconn, SASL_SSF_EXTERNAL, &conn->
ssf) != SASL_OK)
672 mutt_error(
_(
"Error setting SASL external security strength"));
673 sasl_dispose(saslconn);
680 if (sasl_setprop(*saslconn, SASL_AUTH_EXTERNAL, conn->
account.
user) != SASL_OK)
682 mutt_error(
_(
"Error setting SASL external user name"));
683 sasl_dispose(saslconn);
703 while (interaction->id != SASL_CB_LIST_END)
707 snprintf(prompt,
sizeof(prompt),
"%s: ", interaction->prompt);
714 memcpy(result, resp, interaction->len);
715 interaction->result = result;
735 const void *tmp = NULL;
739 sasl_getprop(saslconn, SASL_SSF, &tmp);
743 conn->
ssf += *sasldata->
ssf;
744 sasl_getprop(saslconn, SASL_MAXOUTBUF, &tmp);
749 sasldata->
buf = NULL;
778 #ifdef HAVE_SASL_CLIENT_DONE Convenience wrapper for the gui headers.
char login[128]
Login name.
int(* open)(struct Connection *conn)
Open a socket Connection - Implements Connection::open()
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
struct ConnAccount account
Account details: username, password, etc.
unsigned int ssf
Security strength factor, in bits (see below)
int(* read)(struct Connection *conn, char *buf, size_t count)
Read from a socket Connection.
static int mutt_sasl_cb_pass(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret)
SASL callback function to get password.
static size_t plen
Length of cached packet.
void * sockdata
Backend-specific socket data.
static int mutt_sasl_cb_authname(void *context, int id, const char **result, unsigned int *len)
callback to retrieve authname or user from ConnAccount
An open network connection (socket)
static int mutt_sasl_start(void)
Initialise SASL library.
int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
Wrapper for sasl_client_new()
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
Set up an SASL connection.
SASL authentication support.
void * sockdata
Underlying socket data.
#define mutt_get_field(field, buf, buflen, complete)
int(* open)(struct Connection *conn)
Note about ssf: in actuality, NeoMutt uses this as a boolean to determine if the connection is "secur...
char host[128]
Server to login to.
#define mutt_array_size(x)
Many unsorted constants and some structs.
static int mutt_sasl_conn_poll(struct Connection *conn, time_t wait_secs)
Check an SASL connection for data - Implements Connection::poll()
#define MUTT_COMP_NO_FLAGS
No flags are set.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
unsigned short port
Port to connect to.
int(* close)(struct Connection *conn)
Close a socket Connection.
static int mutt_sasl_conn_close(struct Connection *conn)
close SASL connection - Implements Connection::close()
int fd
Socket file descriptor.
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
static int mutt_sasl_conn_write(struct Connection *conn, const char *buf, size_t count)
Write to an SASL connection - Implements Connection::write()
static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out, unsigned int outlen)
Convert IP Address to string.
static sasl_secret_t * secret_ptr
int mutt_account_getlogin(struct ConnAccount *cac)
Retrieve login info into ConnAccount, if necessary.
const char * service
Name of the service, e.g. "imap".
Login details for a remote server.
static int mutt_sasl_conn_open(struct Connection *conn)
empty wrapper for underlying open function - Implements Connection::open()
int(* close)(struct Connection *conn)
Close a socket Connection - Implements Connection::close()
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
int(* poll)(struct Connection *conn, time_t wait_secs)
Check whether a socket read would block.
static int getnameinfo_err(int ret)
Convert a getaddrinfo() error code into an SASL error code.
void mutt_sasl_done(void)
Invoke when processing is complete.
int(* write)(struct Connection *conn, const char *buf, size_t count)
Write to a socket Connection.
int(* poll)(struct Connection *conn, time_t wait_secs)
Check whether a socket read would block - 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()
static const char *const sasl_authenticators[]
Authenticaion methods supported by Cyrus SASL.
Handling of global boolean variables.
#define mutt_debug(LEVEL,...)
int(* read)(struct Connection *conn, char *buf, size_t count)
Read from a socket Connection - Implements Connection::read()
Convenience wrapper for the library headers.
const unsigned int * pbufsize
int(* write)(struct Connection *conn, const char *buf, size_t count)
Write to a socket Connection - Implements Connection::write()
bool sasl_auth_validator(const char *authenticator)
Validate an auth method against Cyrus SASL methods.
static int mutt_sasl_cb_log(void *context, int priority, const char *message)
callback to log SASL messages
static unsigned char * pbuf
Cache PGP data packet.
static sasl_callback_t MuttSaslCallbacks[5]
static sasl_callback_t * mutt_sasl_get_callbacks(struct ConnAccount *cac)
Get the SASL callback functions.
int mutt_account_getpass(struct ConnAccount *cac)
Fetch password into ConnAccount, if necessary.
int mutt_sasl_interact(sasl_interact_t *interaction)
Perform an SASL interaction with the user.