NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
sasl.c
Go to the documentation of this file.
1 
40 #include "config.h"
41 #include <stddef.h>
42 #include <errno.h>
43 #include <netdb.h>
44 #include <sasl/sasl.h>
45 #include <stdbool.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <sys/socket.h>
49 #include <sys/types.h>
50 #include "mutt/lib.h"
51 #include "gui/lib.h"
52 #include "mutt.h"
53 #include "sasl.h"
54 #include "lib.h"
55 #include "options.h"
56 
61 {
62  sasl_conn_t *saslconn;
63  const sasl_ssf_t *ssf;
64  const unsigned int *pbufsize;
65 
66  /* read buffer */
67  const char *buf;
68  unsigned int blen;
69  unsigned int bpos;
70 
71  void *sockdata;
72 
76  int (*open)(struct Connection *conn);
77 
81  int (*read)(struct Connection *conn, char *buf, size_t count);
82 
86  int (*write)(struct Connection *conn, const char *buf, size_t count);
87 
91  int (*poll)(struct Connection *conn, time_t wait_secs);
92 
96  int (*close)(struct Connection *conn);
97 };
98 
102 static const char *const sasl_authenticators[] = {
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",
108  "SRP",
109 };
110 
111 /* arbitrary. SASL will probably use a smaller buffer anyway. OTOH it's
112  * been a while since I've had access to an SASL server which negotiated
113  * a protection buffer. */
114 #define MUTT_SASL_MAXBUF 65536
115 
116 #define IP_PORT_BUFLEN 1024
117 
118 static sasl_callback_t MuttSaslCallbacks[5];
119 
120 static sasl_secret_t *secret_ptr = NULL;
121 
127 bool sasl_auth_validator(const char *authenticator)
128 {
129  for (size_t i = 0; i < mutt_array_size(sasl_authenticators); i++)
130  {
131  const char *auth = sasl_authenticators[i];
132  if (mutt_istr_equal(auth, authenticator))
133  return true;
134  }
135 
136  return false;
137 }
138 
144 static int getnameinfo_err(int ret)
145 {
146  int err;
147  mutt_debug(LL_DEBUG1, "getnameinfo: ");
148  switch (ret)
149  {
150  case EAI_AGAIN:
152  "The name could not be resolved at this time. Future "
153  "attempts may succeed\n");
154  err = SASL_TRYAGAIN;
155  break;
156  case EAI_BADFLAGS:
157  mutt_debug(LL_DEBUG1, "The flags had an invalid value\n");
158  err = SASL_BADPARAM;
159  break;
160  case EAI_FAIL:
161  mutt_debug(LL_DEBUG1, "A non-recoverable error occurred\n");
162  err = SASL_FAIL;
163  break;
164  case EAI_FAMILY:
166  "The address family was not recognized or the address "
167  "length was invalid for the specified family\n");
168  err = SASL_BADPROT;
169  break;
170  case EAI_MEMORY:
171  mutt_debug(LL_DEBUG1, "There was a memory allocation failure\n");
172  err = SASL_NOMEM;
173  break;
174  case EAI_NONAME:
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");
179  err = SASL_FAIL; /* no real equivalent */
180  break;
181  case EAI_SYSTEM:
183  "A system error occurred. The error code can be found in "
184  "errno(%d,%s))\n",
185  errno, strerror(errno));
186  err = SASL_FAIL; /* no real equivalent */
187  break;
188  default:
189  mutt_debug(LL_DEBUG1, "Unknown error %d\n", ret);
190  err = SASL_FAIL; /* no real equivalent */
191  break;
192  }
193  return err;
194 }
195 
206 static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out,
207  unsigned int outlen)
208 {
209  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
210  int ret;
211 
212  if (!addr || !out)
213  return SASL_BADPARAM;
214 
215  ret = getnameinfo(addr, addrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
216  NI_NUMERICHOST |
217 #ifdef NI_WITHSCOPEID
218  NI_WITHSCOPEID |
219 #endif
220  NI_NUMERICSERV);
221  if (ret != 0)
222  return getnameinfo_err(ret);
223 
224  if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
225  return SASL_BUFOVER;
226 
227  snprintf(out, outlen, "%s;%s", hbuf, pbuf);
228 
229  return SASL_OK;
230 }
231 
239 static int mutt_sasl_cb_log(void *context, int priority, const char *message)
240 {
241  if (priority == SASL_LOG_NONE)
242  return SASL_OK;
243 
244  int mutt_priority = 0;
245  switch (priority)
246  {
247  case SASL_LOG_TRACE:
248  case SASL_LOG_PASS:
249  mutt_priority = 5;
250  break;
251  case SASL_LOG_DEBUG:
252  case SASL_LOG_NOTE:
253  mutt_priority = 3;
254  break;
255  case SASL_LOG_FAIL:
256  case SASL_LOG_WARN:
257  mutt_priority = 2;
258  break;
259  case SASL_LOG_ERR:
260  mutt_priority = 1;
261  break;
262  default:
263  mutt_debug(LL_DEBUG1, "SASL unknown log priority: %s\n", message);
264  return SASL_OK;
265  }
266  mutt_debug(mutt_priority, "SASL: %s\n", message);
267  return SASL_OK;
268 }
269 
276 static int mutt_sasl_start(void)
277 {
278  static bool sasl_init = false;
279 
280  static sasl_callback_t callbacks[2];
281  int rc;
282 
283  if (sasl_init)
284  return SASL_OK;
285 
286  /* set up default logging callback */
287  callbacks[0].id = SASL_CB_LOG;
288  callbacks[0].proc = (int (*)(void)) mutt_sasl_cb_log;
289  callbacks[0].context = NULL;
290 
291  callbacks[1].id = SASL_CB_LIST_END;
292  callbacks[1].proc = NULL;
293  callbacks[1].context = NULL;
294 
295  rc = sasl_client_init(callbacks);
296 
297  if (rc != SASL_OK)
298  {
299  mutt_debug(LL_DEBUG1, "libsasl initialisation failed\n");
300  return SASL_FAIL;
301  }
302 
303  sasl_init = true;
304 
305  return SASL_OK;
306 }
307 
316 static int mutt_sasl_cb_authname(void *context, int id, const char **result, unsigned int *len)
317 {
318  if (!result)
319  return SASL_FAIL;
320 
321  struct ConnAccount *cac = context;
322 
323  *result = NULL;
324  if (len)
325  *len = 0;
326 
327  if (!cac)
328  return SASL_BADPARAM;
329 
330  mutt_debug(LL_DEBUG2, "getting %s for %s:%u\n",
331  (id == SASL_CB_AUTHNAME) ? "authname" : "user", cac->host, cac->port);
332 
333  if (id == SASL_CB_AUTHNAME)
334  {
335  if (mutt_account_getlogin(cac) < 0)
336  return SASL_FAIL;
337  *result = cac->login;
338  }
339  else
340  {
341  if (mutt_account_getuser(cac) < 0)
342  return SASL_FAIL;
343  *result = cac->user;
344  }
345 
346  if (len)
347  *len = strlen(*result);
348 
349  return SASL_OK;
350 }
351 
360 static int mutt_sasl_cb_pass(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret)
361 {
362  struct ConnAccount *cac = context;
363  int len;
364 
365  if (!cac || !psecret)
366  return SASL_BADPARAM;
367 
368  mutt_debug(LL_DEBUG2, "getting password for %s@%s:%u\n", cac->login, cac->host, cac->port);
369 
370  if (mutt_account_getpass(cac) < 0)
371  return SASL_FAIL;
372 
373  len = strlen(cac->pass);
374 
375  mutt_mem_realloc(&secret_ptr, sizeof(sasl_secret_t) + len);
376  memcpy((char *) secret_ptr->data, cac->pass, (size_t) len);
377  secret_ptr->len = len;
378  *psecret = secret_ptr;
379 
380  return SASL_OK;
381 }
382 
388 static sasl_callback_t *mutt_sasl_get_callbacks(struct ConnAccount *cac)
389 {
390  sasl_callback_t *callback = MuttSaslCallbacks;
391 
392  callback->id = SASL_CB_USER;
393  callback->proc = (int (*)(void)) mutt_sasl_cb_authname;
394  callback->context = cac;
395  callback++;
396 
397  callback->id = SASL_CB_AUTHNAME;
398  callback->proc = (int (*)(void)) mutt_sasl_cb_authname;
399  callback->context = cac;
400  callback++;
401 
402  callback->id = SASL_CB_PASS;
403  callback->proc = (int (*)(void)) mutt_sasl_cb_pass;
404  callback->context = cac;
405  callback++;
406 
407  callback->id = SASL_CB_GETREALM;
408  callback->proc = NULL;
409  callback->context = NULL;
410  callback++;
411 
412  callback->id = SASL_CB_LIST_END;
413  callback->proc = NULL;
414  callback->context = NULL;
415 
416  return MuttSaslCallbacks;
417 }
418 
426 static int mutt_sasl_conn_open(struct Connection *conn)
427 {
428  struct SaslSockData *sasldata = conn->sockdata;
429  conn->sockdata = sasldata->sockdata;
430  int rc = sasldata->open(conn);
431  conn->sockdata = sasldata;
432 
433  return rc;
434 }
435 
442 static int mutt_sasl_conn_close(struct Connection *conn)
443 {
444  struct SaslSockData *sasldata = conn->sockdata;
445 
446  /* restore connection's underlying methods */
447  conn->sockdata = sasldata->sockdata;
448  conn->open = sasldata->open;
449  conn->read = sasldata->read;
450  conn->write = sasldata->write;
451  conn->poll = sasldata->poll;
452  conn->close = sasldata->close;
453 
454  /* release sasl resources */
455  sasl_dispose(&sasldata->saslconn);
456  FREE(&sasldata);
457 
458  /* call underlying close */
459  int rc = conn->close(conn);
460 
461  return rc;
462 }
463 
467 static int mutt_sasl_conn_read(struct Connection *conn, char *buf, size_t count)
468 {
469  int rc;
470  unsigned int olen;
471 
472  struct SaslSockData *sasldata = conn->sockdata;
473 
474  /* if we still have data in our read buffer, copy it into buf */
475  if (sasldata->blen > sasldata->bpos)
476  {
477  olen = ((sasldata->blen - sasldata->bpos) > count) ?
478  count :
479  sasldata->blen - sasldata->bpos;
480 
481  memcpy(buf, sasldata->buf + sasldata->bpos, olen);
482  sasldata->bpos += olen;
483 
484  return olen;
485  }
486 
487  conn->sockdata = sasldata->sockdata;
488 
489  sasldata->bpos = 0;
490  sasldata->blen = 0;
491 
492  /* and decode the result, if necessary */
493  if (*sasldata->ssf != 0)
494  {
495  do
496  {
497  /* call the underlying read function to fill the buffer */
498  rc = sasldata->read(conn, buf, count);
499  if (rc <= 0)
500  goto out;
501 
502  rc = sasl_decode(sasldata->saslconn, buf, rc, &sasldata->buf, &sasldata->blen);
503  if (rc != SASL_OK)
504  {
505  mutt_debug(LL_DEBUG1, "SASL decode failed: %s\n", sasl_errstring(rc, NULL, NULL));
506  goto out;
507  }
508  } while (sasldata->blen == 0);
509 
510  olen = ((sasldata->blen - sasldata->bpos) > count) ?
511  count :
512  sasldata->blen - sasldata->bpos;
513 
514  memcpy(buf, sasldata->buf, olen);
515  sasldata->bpos += olen;
516 
517  rc = olen;
518  }
519  else
520  rc = sasldata->read(conn, buf, count);
521 
522 out:
523  conn->sockdata = sasldata;
524 
525  return rc;
526 }
527 
531 static int mutt_sasl_conn_write(struct Connection *conn, const char *buf, size_t count)
532 {
533  int rc;
534  const char *pbuf = NULL;
535  unsigned int olen, plen;
536 
537  struct SaslSockData *sasldata = conn->sockdata;
538  conn->sockdata = sasldata->sockdata;
539 
540  /* encode data, if necessary */
541  if (*sasldata->ssf != 0)
542  {
543  /* handle data larger than MAXOUTBUF */
544  do
545  {
546  olen = (count > *sasldata->pbufsize) ? *sasldata->pbufsize : count;
547 
548  rc = sasl_encode(sasldata->saslconn, buf, olen, &pbuf, &plen);
549  if (rc != SASL_OK)
550  {
551  mutt_debug(LL_DEBUG1, "SASL encoding failed: %s\n", sasl_errstring(rc, NULL, NULL));
552  goto fail;
553  }
554 
555  rc = sasldata->write(conn, pbuf, plen);
556  if (rc != plen)
557  goto fail;
558 
559  count -= olen;
560  buf += olen;
561  } while (count > *sasldata->pbufsize);
562  }
563  else
564  {
565  /* just write using the underlying socket function */
566  rc = sasldata->write(conn, buf, count);
567  }
568 
569  conn->sockdata = sasldata;
570 
571  return rc;
572 
573 fail:
574  conn->sockdata = sasldata;
575  return -1;
576 }
577 
581 static int mutt_sasl_conn_poll(struct Connection *conn, time_t wait_secs)
582 {
583  struct SaslSockData *sasldata = conn->sockdata;
584  int rc;
585 
586  conn->sockdata = sasldata->sockdata;
587  rc = sasldata->poll(conn, wait_secs);
588  conn->sockdata = sasldata;
589 
590  return rc;
591 }
592 
603 int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
604 {
605  sasl_security_properties_t secprops;
606  struct sockaddr_storage local, remote;
607  socklen_t size;
608  char iplocalport[IP_PORT_BUFLEN], ipremoteport[IP_PORT_BUFLEN];
609  char *plp = NULL;
610  char *prp = NULL;
611  int rc;
612 
613  if (mutt_sasl_start() != SASL_OK)
614  return -1;
615 
616  if (!conn->account.service)
617  {
618  mutt_error(_("Unknown SASL profile"));
619  return -1;
620  }
621 
622  size = sizeof(local);
623  if (getsockname(conn->fd, (struct sockaddr *) &local, &size) == 0)
624  {
625  if (iptostring((struct sockaddr *) &local, size, iplocalport, IP_PORT_BUFLEN) == SASL_OK)
626  plp = iplocalport;
627  else
628  mutt_debug(LL_DEBUG2, "SASL failed to parse local IP address\n");
629  }
630  else
631  mutt_debug(LL_DEBUG2, "SASL failed to get local IP address\n");
632 
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  mutt_debug(LL_DEBUG2, "SASL failed to get remote IP address\n");
643 
644  mutt_debug(LL_DEBUG2, "SASL local ip: %s, remote ip:%s\n", NONULL(plp), NONULL(prp));
645 
646  rc = sasl_client_new(conn->account.service, conn->account.host, plp, prp,
647  mutt_sasl_get_callbacks(&conn->account), 0, saslconn);
648 
649  if (rc != SASL_OK)
650  {
651  mutt_error(_("Error allocating SASL connection"));
652  return -1;
653  }
654 
655  memset(&secprops, 0, sizeof(secprops));
656  /* Work around a casting bug in the SASL krb4 module */
657  secprops.max_ssf = 0x7fff;
658  secprops.maxbufsize = MUTT_SASL_MAXBUF;
659  if (sasl_setprop(*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
660  {
661  mutt_error(_("Error setting SASL security properties"));
662  sasl_dispose(saslconn);
663  return -1;
664  }
665 
666  if (conn->ssf != 0)
667  {
668  /* I'm not sure this actually has an effect, at least with SASLv2 */
669  mutt_debug(LL_DEBUG2, "External SSF: %d\n", conn->ssf);
670  if (sasl_setprop(*saslconn, SASL_SSF_EXTERNAL, &conn->ssf) != SASL_OK)
671  {
672  mutt_error(_("Error setting SASL external security strength"));
673  sasl_dispose(saslconn);
674  return -1;
675  }
676  }
677  if (conn->account.user[0])
678  {
679  mutt_debug(LL_DEBUG2, "External authentication name: %s\n", conn->account.user);
680  if (sasl_setprop(*saslconn, SASL_AUTH_EXTERNAL, conn->account.user) != SASL_OK)
681  {
682  mutt_error(_("Error setting SASL external user name"));
683  sasl_dispose(saslconn);
684  return -1;
685  }
686  }
687 
688  return 0;
689 }
690 
698 int mutt_sasl_interact(sasl_interact_t *interaction)
699 {
700  char prompt[128];
701  char resp[128];
702 
703  while (interaction->id != SASL_CB_LIST_END)
704  {
705  mutt_debug(LL_DEBUG2, "filling in SASL interaction %ld\n", interaction->id);
706 
707  snprintf(prompt, sizeof(prompt), "%s: ", interaction->prompt);
708  resp[0] = '\0';
709  if (OptNoCurses || mutt_get_field(prompt, resp, sizeof(resp), MUTT_COMP_NO_FLAGS))
710  return SASL_FAIL;
711 
712  interaction->len = mutt_str_len(resp) + 1;
713  char *result = mutt_mem_malloc(interaction->len);
714  memcpy(result, resp, interaction->len);
715  interaction->result = result;
716 
717  interaction++;
718  }
719 
720  return SASL_OK;
721 }
722 
731 void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
732 {
733  struct SaslSockData *sasldata = mutt_mem_malloc(sizeof(struct SaslSockData));
734  /* work around sasl_getprop aliasing issues */
735  const void *tmp = NULL;
736 
737  sasldata->saslconn = saslconn;
738  /* get ssf so we know whether we have to (en|de)code read/write */
739  sasl_getprop(saslconn, SASL_SSF, &tmp);
740  sasldata->ssf = tmp;
741  mutt_debug(LL_DEBUG3, "SASL protection strength: %u\n", *sasldata->ssf);
742  /* Add SASL SSF to transport SSF */
743  conn->ssf += *sasldata->ssf;
744  sasl_getprop(saslconn, SASL_MAXOUTBUF, &tmp);
745  sasldata->pbufsize = tmp;
746  mutt_debug(LL_DEBUG3, "SASL protection buffer size: %u\n", *sasldata->pbufsize);
747 
748  /* clear input buffer */
749  sasldata->buf = NULL;
750  sasldata->bpos = 0;
751  sasldata->blen = 0;
752 
753  /* preserve old functions */
754  sasldata->sockdata = conn->sockdata;
755  sasldata->open = conn->open;
756  sasldata->read = conn->read;
757  sasldata->write = conn->write;
758  sasldata->poll = conn->poll;
759  sasldata->close = conn->close;
760 
761  /* and set up new functions */
762  conn->sockdata = sasldata;
763  conn->open = mutt_sasl_conn_open;
764  conn->read = mutt_sasl_conn_read;
765  conn->write = mutt_sasl_conn_write;
766  conn->poll = mutt_sasl_conn_poll;
767  conn->close = mutt_sasl_conn_close;
768 }
769 
776 void mutt_sasl_done(void)
777 {
778 #ifdef HAVE_SASL_CLIENT_DONE
779  /* As we never use the server-side, the silently ignore the return value */
780  sasl_client_done();
781 #else
782  sasl_done();
783 #endif
784 }
Convenience wrapper for the gui headers.
#define MUTT_SASL_MAXBUF
Definition: sasl.c:114
#define NONULL(x)
Definition: string2.h:37
char login[128]
Login name.
Definition: connaccount.h:54
int(* open)(struct Connection *conn)
Open a socket Connection - Implements Connection::open()
Definition: sasl.c:76
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
Definition: connaccount.c:48
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
unsigned int ssf
Security strength factor, in bits (see below)
Definition: connection.h:37
int(* read)(struct Connection *conn, char *buf, size_t count)
Read from a socket Connection.
Definition: connection.h:72
static int mutt_sasl_cb_pass(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret)
SASL callback function to get password.
Definition: sasl.c:360
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
SASL authentication API.
Definition: sasl.c:60
void * sockdata
Backend-specific socket data.
Definition: connection.h:42
static int mutt_sasl_cb_authname(void *context, int id, const char **result, unsigned int *len)
callback to retrieve authname or user from ConnAccount
Definition: sasl.c:316
An open network connection (socket)
Definition: connection.h:34
char user[128]
Username.
Definition: connaccount.h:55
static int mutt_sasl_start(void)
Initialise SASL library.
Definition: sasl.c:276
#define _(a)
Definition: message.h:28
int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
Wrapper for sasl_client_new()
Definition: sasl.c:603
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:48
sasl_conn_t * saslconn
Definition: sasl.c:62
void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
Set up an SASL connection.
Definition: sasl.c:731
unsigned int bpos
Definition: sasl.c:69
SASL authentication support.
void * sockdata
Underlying socket data.
Definition: sasl.c:71
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
int(* open)(struct Connection *conn)
Note about ssf: in actuality, NeoMutt uses this as a boolean to determine if the connection is "secur...
Definition: connection.h:62
char host[128]
Server to login to.
Definition: connaccount.h:53
#define mutt_array_size(x)
Definition: memory.h:33
Many unsorted constants and some structs.
Log at debug level 2.
Definition: logging.h:41
static int mutt_sasl_conn_poll(struct Connection *conn, time_t wait_secs)
Check an SASL connection for data - Implements Connection::poll()
Definition: sasl.c:581
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
char pass[256]
Password.
Definition: connaccount.h:56
#define IP_PORT_BUFLEN
Definition: sasl.c:116
unsigned int blen
Definition: sasl.c:68
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
unsigned short port
Port to connect to.
Definition: connaccount.h:57
int(* close)(struct Connection *conn)
Close a socket Connection.
Definition: connection.h:100
const sasl_ssf_t * ssf
Definition: sasl.c:63
static int mutt_sasl_conn_close(struct Connection *conn)
close SASL connection - Implements Connection::close()
Definition: sasl.c:442
int fd
Socket file descriptor.
Definition: connection.h:40
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
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:531
static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out, unsigned int outlen)
Convert IP Address to string.
Definition: sasl.c:206
static sasl_secret_t * secret_ptr
Definition: sasl.c:120
int mutt_account_getlogin(struct ConnAccount *cac)
Retrieve login info into ConnAccount, if necessary.
Definition: connaccount.c:81
const char * service
Name of the service, e.g. "imap".
Definition: connaccount.h:60
Login details for a remote server.
Definition: connaccount.h:51
static int mutt_sasl_conn_open(struct Connection *conn)
empty wrapper for underlying open function - Implements Connection::open()
Definition: sasl.c:426
int(* close)(struct Connection *conn)
Close a socket Connection - Implements Connection::close()
Definition: sasl.c:96
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
int(* poll)(struct Connection *conn, time_t wait_secs)
Check whether a socket read would block.
Definition: connection.h:92
static int getnameinfo_err(int ret)
Convert a getaddrinfo() error code into an SASL error code.
Definition: sasl.c:144
Log at debug level 1.
Definition: logging.h:40
void mutt_sasl_done(void)
Invoke when processing is complete.
Definition: sasl.c:776
#define mutt_error(...)
Definition: logging.h:84
int(* write)(struct Connection *conn, const char *buf, size_t count)
Write to a socket Connection.
Definition: connection.h:82
Connection Library.
int(* poll)(struct Connection *conn, time_t wait_secs)
Check whether a socket read would block - Implements Connection::poll()
Definition: sasl.c:91
#define FREE(x)
Definition: memory.h:40
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:467
static const char *const sasl_authenticators[]
Authenticaion methods supported by Cyrus SASL.
Definition: sasl.c:102
Handling of global boolean variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int(* read)(struct Connection *conn, char *buf, size_t count)
Read from a socket Connection - Implements Connection::read()
Definition: sasl.c:81
const char * buf
Definition: sasl.c:67
Convenience wrapper for the library headers.
const unsigned int * pbufsize
Definition: sasl.c:64
int(* write)(struct Connection *conn, const char *buf, size_t count)
Write to a socket Connection - Implements Connection::write()
Definition: sasl.c:86
bool sasl_auth_validator(const char *authenticator)
Validate an auth method against Cyrus SASL methods.
Definition: sasl.c:127
static int mutt_sasl_cb_log(void *context, int priority, const char *message)
callback to log SASL messages
Definition: sasl.c:239
static unsigned char * pbuf
Cache PGP data packet.
Definition: pgppacket.c:38
Log at debug level 3.
Definition: logging.h:42
static sasl_callback_t MuttSaslCallbacks[5]
Definition: sasl.c:118
static sasl_callback_t * mutt_sasl_get_callbacks(struct ConnAccount *cac)
Get the SASL callback functions.
Definition: sasl.c:388
int mutt_account_getpass(struct ConnAccount *cac)
Fetch password into ConnAccount, if necessary.
Definition: connaccount.c:111
int mutt_sasl_interact(sasl_interact_t *interaction)
Perform an SASL interaction with the user.
Definition: sasl.c:698