NeoMutt  2020-06-26-89-g172cd3
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 
99 /* arbitrary. SASL will probably use a smaller buffer anyway. OTOH it's
100  * been a while since I've had access to an SASL server which negotiated
101  * a protection buffer. */
102 #define MUTT_SASL_MAXBUF 65536
103 
104 #define IP_PORT_BUFLEN 1024
105 
106 static sasl_callback_t MuttSaslCallbacks[5];
107 
108 static sasl_secret_t *secret_ptr = NULL;
109 
115 static int getnameinfo_err(int ret)
116 {
117  int err;
118  mutt_debug(LL_DEBUG1, "getnameinfo: ");
119  switch (ret)
120  {
121  case EAI_AGAIN:
123  "The name could not be resolved at this time. Future "
124  "attempts may succeed\n");
125  err = SASL_TRYAGAIN;
126  break;
127  case EAI_BADFLAGS:
128  mutt_debug(LL_DEBUG1, "The flags had an invalid value\n");
129  err = SASL_BADPARAM;
130  break;
131  case EAI_FAIL:
132  mutt_debug(LL_DEBUG1, "A non-recoverable error occurred\n");
133  err = SASL_FAIL;
134  break;
135  case EAI_FAMILY:
137  "The address family was not recognized or the address "
138  "length was invalid for the specified family\n");
139  err = SASL_BADPROT;
140  break;
141  case EAI_MEMORY:
142  mutt_debug(LL_DEBUG1, "There was a memory allocation failure\n");
143  err = SASL_NOMEM;
144  break;
145  case EAI_NONAME:
147  "The name does not resolve for the supplied parameters. "
148  "NI_NAMEREQD is set and the host's name can't be located, "
149  "or both nodename and servname were null.\n");
150  err = SASL_FAIL; /* no real equivalent */
151  break;
152  case EAI_SYSTEM:
154  "A system error occurred. The error code can be found in "
155  "errno(%d,%s))\n",
156  errno, strerror(errno));
157  err = SASL_FAIL; /* no real equivalent */
158  break;
159  default:
160  mutt_debug(LL_DEBUG1, "Unknown error %d\n", ret);
161  err = SASL_FAIL; /* no real equivalent */
162  break;
163  }
164  return err;
165 }
166 
177 static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out,
178  unsigned int outlen)
179 {
180  char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
181  int ret;
182 
183  if (!addr || !out)
184  return SASL_BADPARAM;
185 
186  ret = getnameinfo(addr, addrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
187  NI_NUMERICHOST |
188 #ifdef NI_WITHSCOPEID
189  NI_WITHSCOPEID |
190 #endif
191  NI_NUMERICSERV);
192  if (ret != 0)
193  return getnameinfo_err(ret);
194 
195  if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
196  return SASL_BUFOVER;
197 
198  snprintf(out, outlen, "%s;%s", hbuf, pbuf);
199 
200  return SASL_OK;
201 }
202 
210 static int mutt_sasl_cb_log(void *context, int priority, const char *message)
211 {
212  if (priority == SASL_LOG_NONE)
213  return SASL_OK;
214 
215  int mutt_priority = 0;
216  switch (priority)
217  {
218  case SASL_LOG_TRACE:
219  case SASL_LOG_PASS:
220  mutt_priority = 5;
221  break;
222  case SASL_LOG_DEBUG:
223  case SASL_LOG_NOTE:
224  mutt_priority = 3;
225  break;
226  case SASL_LOG_FAIL:
227  case SASL_LOG_WARN:
228  mutt_priority = 2;
229  break;
230  case SASL_LOG_ERR:
231  mutt_priority = 1;
232  break;
233  default:
234  mutt_debug(LL_DEBUG1, "SASL unknown log priority: %s\n", message);
235  return SASL_OK;
236  }
237  mutt_debug(mutt_priority, "SASL: %s\n", message);
238  return SASL_OK;
239 }
240 
247 static int mutt_sasl_start(void)
248 {
249  static bool sasl_init = false;
250 
251  static sasl_callback_t callbacks[2];
252  int rc;
253 
254  if (sasl_init)
255  return SASL_OK;
256 
257  /* set up default logging callback */
258  callbacks[0].id = SASL_CB_LOG;
259  callbacks[0].proc = (int (*)(void)) mutt_sasl_cb_log;
260  callbacks[0].context = NULL;
261 
262  callbacks[1].id = SASL_CB_LIST_END;
263  callbacks[1].proc = NULL;
264  callbacks[1].context = NULL;
265 
266  rc = sasl_client_init(callbacks);
267 
268  if (rc != SASL_OK)
269  {
270  mutt_debug(LL_DEBUG1, "libsasl initialisation failed\n");
271  return SASL_FAIL;
272  }
273 
274  sasl_init = true;
275 
276  return SASL_OK;
277 }
278 
287 static int mutt_sasl_cb_authname(void *context, int id, const char **result, unsigned int *len)
288 {
289  if (!result)
290  return SASL_FAIL;
291 
292  struct ConnAccount *cac = context;
293 
294  *result = NULL;
295  if (len)
296  *len = 0;
297 
298  if (!cac)
299  return SASL_BADPARAM;
300 
301  mutt_debug(LL_DEBUG2, "getting %s for %s:%u\n",
302  (id == SASL_CB_AUTHNAME) ? "authname" : "user", cac->host, cac->port);
303 
304  if (id == SASL_CB_AUTHNAME)
305  {
306  if (mutt_account_getlogin(cac) < 0)
307  return SASL_FAIL;
308  *result = cac->login;
309  }
310  else
311  {
312  if (mutt_account_getuser(cac) < 0)
313  return SASL_FAIL;
314  *result = cac->user;
315  }
316 
317  if (len)
318  *len = strlen(*result);
319 
320  return SASL_OK;
321 }
322 
331 static int mutt_sasl_cb_pass(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret)
332 {
333  struct ConnAccount *cac = context;
334  int len;
335 
336  if (!cac || !psecret)
337  return SASL_BADPARAM;
338 
339  mutt_debug(LL_DEBUG2, "getting password for %s@%s:%u\n", cac->login, cac->host, cac->port);
340 
341  if (mutt_account_getpass(cac) < 0)
342  return SASL_FAIL;
343 
344  len = strlen(cac->pass);
345 
346  mutt_mem_realloc(&secret_ptr, sizeof(sasl_secret_t) + len);
347  memcpy((char *) secret_ptr->data, cac->pass, (size_t) len);
348  secret_ptr->len = len;
349  *psecret = secret_ptr;
350 
351  return SASL_OK;
352 }
353 
359 static sasl_callback_t *mutt_sasl_get_callbacks(struct ConnAccount *cac)
360 {
361  sasl_callback_t *callback = MuttSaslCallbacks;
362 
363  callback->id = SASL_CB_USER;
364  callback->proc = (int (*)(void)) mutt_sasl_cb_authname;
365  callback->context = cac;
366  callback++;
367 
368  callback->id = SASL_CB_AUTHNAME;
369  callback->proc = (int (*)(void)) mutt_sasl_cb_authname;
370  callback->context = cac;
371  callback++;
372 
373  callback->id = SASL_CB_PASS;
374  callback->proc = (int (*)(void)) mutt_sasl_cb_pass;
375  callback->context = cac;
376  callback++;
377 
378  callback->id = SASL_CB_GETREALM;
379  callback->proc = NULL;
380  callback->context = NULL;
381  callback++;
382 
383  callback->id = SASL_CB_LIST_END;
384  callback->proc = NULL;
385  callback->context = NULL;
386 
387  return MuttSaslCallbacks;
388 }
389 
397 static int mutt_sasl_conn_open(struct Connection *conn)
398 {
399  struct SaslSockData *sasldata = conn->sockdata;
400  conn->sockdata = sasldata->sockdata;
401  int rc = sasldata->open(conn);
402  conn->sockdata = sasldata;
403 
404  return rc;
405 }
406 
413 static int mutt_sasl_conn_close(struct Connection *conn)
414 {
415  struct SaslSockData *sasldata = conn->sockdata;
416 
417  /* restore connection's underlying methods */
418  conn->sockdata = sasldata->sockdata;
419  conn->open = sasldata->open;
420  conn->read = sasldata->read;
421  conn->write = sasldata->write;
422  conn->poll = sasldata->poll;
423  conn->close = sasldata->close;
424 
425  /* release sasl resources */
426  sasl_dispose(&sasldata->saslconn);
427  FREE(&sasldata);
428 
429  /* call underlying close */
430  int rc = conn->close(conn);
431 
432  return rc;
433 }
434 
438 static int mutt_sasl_conn_read(struct Connection *conn, char *buf, size_t count)
439 {
440  int rc;
441  unsigned int olen;
442 
443  struct SaslSockData *sasldata = conn->sockdata;
444 
445  /* if we still have data in our read buffer, copy it into buf */
446  if (sasldata->blen > sasldata->bpos)
447  {
448  olen = ((sasldata->blen - sasldata->bpos) > count) ?
449  count :
450  sasldata->blen - sasldata->bpos;
451 
452  memcpy(buf, sasldata->buf + sasldata->bpos, olen);
453  sasldata->bpos += olen;
454 
455  return olen;
456  }
457 
458  conn->sockdata = sasldata->sockdata;
459 
460  sasldata->bpos = 0;
461  sasldata->blen = 0;
462 
463  /* and decode the result, if necessary */
464  if (*sasldata->ssf != 0)
465  {
466  do
467  {
468  /* call the underlying read function to fill the buffer */
469  rc = sasldata->read(conn, buf, count);
470  if (rc <= 0)
471  goto out;
472 
473  rc = sasl_decode(sasldata->saslconn, buf, rc, &sasldata->buf, &sasldata->blen);
474  if (rc != SASL_OK)
475  {
476  mutt_debug(LL_DEBUG1, "SASL decode failed: %s\n", sasl_errstring(rc, NULL, NULL));
477  goto out;
478  }
479  } while (sasldata->blen == 0);
480 
481  olen = ((sasldata->blen - sasldata->bpos) > count) ?
482  count :
483  sasldata->blen - sasldata->bpos;
484 
485  memcpy(buf, sasldata->buf, olen);
486  sasldata->bpos += olen;
487 
488  rc = olen;
489  }
490  else
491  rc = sasldata->read(conn, buf, count);
492 
493 out:
494  conn->sockdata = sasldata;
495 
496  return rc;
497 }
498 
502 static int mutt_sasl_conn_write(struct Connection *conn, const char *buf, size_t count)
503 {
504  int rc;
505  const char *pbuf = NULL;
506  unsigned int olen, plen;
507 
508  struct SaslSockData *sasldata = conn->sockdata;
509  conn->sockdata = sasldata->sockdata;
510 
511  /* encode data, if necessary */
512  if (*sasldata->ssf != 0)
513  {
514  /* handle data larger than MAXOUTBUF */
515  do
516  {
517  olen = (count > *sasldata->pbufsize) ? *sasldata->pbufsize : count;
518 
519  rc = sasl_encode(sasldata->saslconn, buf, olen, &pbuf, &plen);
520  if (rc != SASL_OK)
521  {
522  mutt_debug(LL_DEBUG1, "SASL encoding failed: %s\n", sasl_errstring(rc, NULL, NULL));
523  goto fail;
524  }
525 
526  rc = sasldata->write(conn, pbuf, plen);
527  if (rc != plen)
528  goto fail;
529 
530  count -= olen;
531  buf += olen;
532  } while (count > *sasldata->pbufsize);
533  }
534  else
535  {
536  /* just write using the underlying socket function */
537  rc = sasldata->write(conn, buf, count);
538  }
539 
540  conn->sockdata = sasldata;
541 
542  return rc;
543 
544 fail:
545  conn->sockdata = sasldata;
546  return -1;
547 }
548 
552 static int mutt_sasl_conn_poll(struct Connection *conn, time_t wait_secs)
553 {
554  struct SaslSockData *sasldata = conn->sockdata;
555  int rc;
556 
557  conn->sockdata = sasldata->sockdata;
558  rc = sasldata->poll(conn, wait_secs);
559  conn->sockdata = sasldata;
560 
561  return rc;
562 }
563 
574 int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
575 {
576  sasl_security_properties_t secprops;
577  struct sockaddr_storage local, remote;
578  socklen_t size;
579  char iplocalport[IP_PORT_BUFLEN], ipremoteport[IP_PORT_BUFLEN];
580  char *plp = NULL;
581  char *prp = NULL;
582  int rc;
583 
584  if (mutt_sasl_start() != SASL_OK)
585  return -1;
586 
587  if (!conn->account.service)
588  {
589  mutt_error(_("Unknown SASL profile"));
590  return -1;
591  }
592 
593  size = sizeof(local);
594  if (getsockname(conn->fd, (struct sockaddr *) &local, &size) == 0)
595  {
596  if (iptostring((struct sockaddr *) &local, size, iplocalport, IP_PORT_BUFLEN) == SASL_OK)
597  plp = iplocalport;
598  else
599  mutt_debug(LL_DEBUG2, "SASL failed to parse local IP address\n");
600  }
601  else
602  mutt_debug(LL_DEBUG2, "SASL failed to get local IP address\n");
603 
604  size = sizeof(remote);
605  if (getpeername(conn->fd, (struct sockaddr *) &remote, &size) == 0)
606  {
607  if (iptostring((struct sockaddr *) &remote, size, ipremoteport, IP_PORT_BUFLEN) == SASL_OK)
608  prp = ipremoteport;
609  else
610  mutt_debug(LL_DEBUG2, "SASL failed to parse remote IP address\n");
611  }
612  else
613  mutt_debug(LL_DEBUG2, "SASL failed to get remote IP address\n");
614 
615  mutt_debug(LL_DEBUG2, "SASL local ip: %s, remote ip:%s\n", NONULL(plp), NONULL(prp));
616 
617  rc = sasl_client_new(conn->account.service, conn->account.host, plp, prp,
618  mutt_sasl_get_callbacks(&conn->account), 0, saslconn);
619 
620  if (rc != SASL_OK)
621  {
622  mutt_error(_("Error allocating SASL connection"));
623  return -1;
624  }
625 
626  memset(&secprops, 0, sizeof(secprops));
627  /* Work around a casting bug in the SASL krb4 module */
628  secprops.max_ssf = 0x7fff;
629  secprops.maxbufsize = MUTT_SASL_MAXBUF;
630  if (sasl_setprop(*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
631  {
632  mutt_error(_("Error setting SASL security properties"));
633  sasl_dispose(saslconn);
634  return -1;
635  }
636 
637  if (conn->ssf != 0)
638  {
639  /* I'm not sure this actually has an effect, at least with SASLv2 */
640  mutt_debug(LL_DEBUG2, "External SSF: %d\n", conn->ssf);
641  if (sasl_setprop(*saslconn, SASL_SSF_EXTERNAL, &conn->ssf) != SASL_OK)
642  {
643  mutt_error(_("Error setting SASL external security strength"));
644  sasl_dispose(saslconn);
645  return -1;
646  }
647  }
648  if (conn->account.user[0])
649  {
650  mutt_debug(LL_DEBUG2, "External authentication name: %s\n", conn->account.user);
651  if (sasl_setprop(*saslconn, SASL_AUTH_EXTERNAL, conn->account.user) != SASL_OK)
652  {
653  mutt_error(_("Error setting SASL external user name"));
654  sasl_dispose(saslconn);
655  return -1;
656  }
657  }
658 
659  return 0;
660 }
661 
669 int mutt_sasl_interact(sasl_interact_t *interaction)
670 {
671  char prompt[128];
672  char resp[128];
673 
674  while (interaction->id != SASL_CB_LIST_END)
675  {
676  mutt_debug(LL_DEBUG2, "filling in SASL interaction %ld\n", interaction->id);
677 
678  snprintf(prompt, sizeof(prompt), "%s: ", interaction->prompt);
679  resp[0] = '\0';
680  if (OptNoCurses || mutt_get_field(prompt, resp, sizeof(resp), MUTT_COMP_NO_FLAGS))
681  return SASL_FAIL;
682 
683  interaction->len = mutt_str_len(resp) + 1;
684  char *result = mutt_mem_malloc(interaction->len);
685  memcpy(result, resp, interaction->len);
686  interaction->result = result;
687 
688  interaction++;
689  }
690 
691  return SASL_OK;
692 }
693 
702 void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
703 {
704  struct SaslSockData *sasldata = mutt_mem_malloc(sizeof(struct SaslSockData));
705  /* work around sasl_getprop aliasing issues */
706  const void *tmp = NULL;
707 
708  sasldata->saslconn = saslconn;
709  /* get ssf so we know whether we have to (en|de)code read/write */
710  sasl_getprop(saslconn, SASL_SSF, &tmp);
711  sasldata->ssf = tmp;
712  mutt_debug(LL_DEBUG3, "SASL protection strength: %u\n", *sasldata->ssf);
713  /* Add SASL SSF to transport SSF */
714  conn->ssf += *sasldata->ssf;
715  sasl_getprop(saslconn, SASL_MAXOUTBUF, &tmp);
716  sasldata->pbufsize = tmp;
717  mutt_debug(LL_DEBUG3, "SASL protection buffer size: %u\n", *sasldata->pbufsize);
718 
719  /* clear input buffer */
720  sasldata->buf = NULL;
721  sasldata->bpos = 0;
722  sasldata->blen = 0;
723 
724  /* preserve old functions */
725  sasldata->sockdata = conn->sockdata;
726  sasldata->open = conn->open;
727  sasldata->read = conn->read;
728  sasldata->write = conn->write;
729  sasldata->poll = conn->poll;
730  sasldata->close = conn->close;
731 
732  /* and set up new functions */
733  conn->sockdata = sasldata;
734  conn->open = mutt_sasl_conn_open;
735  conn->read = mutt_sasl_conn_read;
736  conn->write = mutt_sasl_conn_write;
737  conn->poll = mutt_sasl_conn_poll;
738  conn->close = mutt_sasl_conn_close;
739 }
740 
747 void mutt_sasl_done(void)
748 {
749 #ifdef HAVE_SASL_CLIENT_DONE
750  /* As we never use the server-side, the silently ignore the return value */
751  sasl_client_done();
752 #else
753  sasl_done();
754 #endif
755 }
Convenience wrapper for the gui headers.
#define MUTT_SASL_MAXBUF
Definition: sasl.c:102
#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:331
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:287
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:247
#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:574
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:702
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
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:552
#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:104
unsigned int blen
Definition: sasl.c:68
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:413
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:502
static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out, unsigned int outlen)
Convert IP Address to string.
Definition: sasl.c:177
static sasl_secret_t * secret_ptr
Definition: sasl.c:108
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:397
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:636
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:115
Log at debug level 1.
Definition: logging.h:40
void mutt_sasl_done(void)
Invoke when processing is complete.
Definition: sasl.c:747
#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:438
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
static int mutt_sasl_cb_log(void *context, int priority, const char *message)
callback to log SASL messages
Definition: sasl.c:210
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:106
static sasl_callback_t * mutt_sasl_get_callbacks(struct ConnAccount *cac)
Get the SASL callback functions.
Definition: sasl.c:359
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:669