NeoMutt  2023-03-22-27-g3cb248
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 <stdint.h>
47#include <stdio.h>
48#include <string.h>
49#include <sys/socket.h>
50#include <sys/types.h>
51#include "mutt/lib.h"
52#include "mutt.h"
53#include "sasl.h"
54#include "lib.h"
55#include "enter/lib.h"
56#include "globals.h"
57
62{
63 sasl_conn_t *saslconn;
64 const sasl_ssf_t *ssf;
65 const unsigned int *pbufsize;
66
67 /* read buffer */
68 const char *buf;
69 unsigned int blen;
70 unsigned int bpos;
71
72 void *sockdata;
73
77 int (*open)(struct Connection *conn);
78
82 int (*read)(struct Connection *conn, char *buf, size_t count);
83
87 int (*write)(struct Connection *conn, const char *buf, size_t count);
88
92 int (*poll)(struct Connection *conn, time_t wait_secs);
93
97 int (*close)(struct Connection *conn);
98};
99
103static const char *const SaslAuthenticators[] = {
104 "ANONYMOUS", "CRAM-MD5", "DIGEST-MD5", "EXTERNAL",
105 "GS2-IAKERB", "GS2-KRB5", "GSS-SPNEGO", "GSSAPI",
106 "LOGIN", "NTLM", "OTP-MD4", "OTP-MD5",
107 "OTP-SHA1", "PASSDSS-3DES-1", "PLAIN", "SCRAM-SHA-1",
108 "SCRAM-SHA-224", "SCRAM-SHA-256", "SCRAM-SHA-384", "SCRAM-SHA-512",
109 "SRP",
110};
111
112/* arbitrary. SASL will probably use a smaller buffer anyway. OTOH it's
113 * been a while since I've had access to an SASL server which negotiated
114 * a protection buffer. */
115#define MUTT_SASL_MAXBUF 65536
116
117/* used to hold a string "host;port"
118 * where host is size NI_MAXHOST-1 and port is size NI_MAXSERV-1
119 * plus two bytes for the ';' and trailing \0 */
120#define IP_PORT_BUFLEN (NI_MAXHOST + NI_MAXSERV)
121
122static sasl_callback_t MuttSaslCallbacks[5];
123
124static sasl_secret_t *secret_ptr = NULL;
125
131bool sasl_auth_validator(const char *authenticator)
132{
133 for (size_t i = 0; i < mutt_array_size(SaslAuthenticators); i++)
134 {
135 const char *auth = SaslAuthenticators[i];
136 if (mutt_istr_equal(auth, authenticator))
137 return true;
138 }
139
140 return false;
141}
142
148static int getnameinfo_err(int rc)
149{
150 int err;
151 mutt_debug(LL_DEBUG1, "getnameinfo: ");
152 switch (rc)
153 {
154 case EAI_AGAIN:
155 mutt_debug(LL_DEBUG1, "The name could not be resolved at this time. Future attempts may succeed\n");
156 err = SASL_TRYAGAIN;
157 break;
158 case EAI_BADFLAGS:
159 mutt_debug(LL_DEBUG1, "The flags had an invalid value\n");
160 err = SASL_BADPARAM;
161 break;
162 case EAI_FAIL:
163 mutt_debug(LL_DEBUG1, "A non-recoverable error occurred\n");
164 err = SASL_FAIL;
165 break;
166 case EAI_FAMILY:
167 mutt_debug(LL_DEBUG1, "The address family was not recognized or the address 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:
175 mutt_debug(LL_DEBUG1, "The name does not resolve for the supplied parameters. "
176 "NI_NAMEREQD is set and the host's name can't be located, or both nodename and servname were null.\n");
177 err = SASL_FAIL; /* no real equivalent */
178 break;
179 case EAI_SYSTEM:
180 mutt_debug(LL_DEBUG1, "A system error occurred. The error code can be found in errno(%d,%s))\n",
181 errno, strerror(errno));
182 err = SASL_FAIL; /* no real equivalent */
183 break;
184 default:
185 mutt_debug(LL_DEBUG1, "Unknown error %d\n", rc);
186 err = SASL_FAIL; /* no real equivalent */
187 break;
188 }
189 return err;
190}
191
202static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out,
203 unsigned int outlen)
204{
205 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
206 int rc;
207
208 if (!addr || !out)
209 return SASL_BADPARAM;
210
211 rc = getnameinfo(addr, addrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
212 NI_NUMERICHOST |
213#ifdef NI_WITHSCOPEID
214 NI_WITHSCOPEID |
215#endif
216 NI_NUMERICSERV);
217 if (rc != 0)
218 return getnameinfo_err(rc);
219
220 if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
221 return SASL_BUFOVER;
222
223 snprintf(out, outlen, "%s;%s", hbuf, pbuf);
224
225 return SASL_OK;
226}
227
235static int mutt_sasl_cb_log(void *context, int priority, const char *message)
236{
237 if (priority == SASL_LOG_NONE)
238 return SASL_OK;
239
240 int mutt_priority = 0;
241 switch (priority)
242 {
243 case SASL_LOG_TRACE:
244 case SASL_LOG_PASS:
245 mutt_priority = 5;
246 break;
247 case SASL_LOG_DEBUG:
248 case SASL_LOG_NOTE:
249 mutt_priority = 3;
250 break;
251 case SASL_LOG_FAIL:
252 case SASL_LOG_WARN:
253 mutt_priority = 2;
254 break;
255 case SASL_LOG_ERR:
256 mutt_priority = 1;
257 break;
258 default:
259 mutt_debug(LL_DEBUG1, "SASL unknown log priority: %s\n", message);
260 return SASL_OK;
261 }
262 mutt_debug(mutt_priority, "SASL: %s\n", message);
263 return SASL_OK;
264}
265
272static int mutt_sasl_start(void)
273{
274 static bool sasl_init = false;
275
276 static sasl_callback_t callbacks[2];
277 int rc;
278
279 if (sasl_init)
280 return SASL_OK;
281
282 /* set up default logging callback */
283 callbacks[0].id = SASL_CB_LOG;
284 callbacks[0].proc = (int (*)(void))(intptr_t) mutt_sasl_cb_log;
285 callbacks[0].context = NULL;
286
287 callbacks[1].id = SASL_CB_LIST_END;
288 callbacks[1].proc = NULL;
289 callbacks[1].context = NULL;
290
291 rc = sasl_client_init(callbacks);
292
293 if (rc != SASL_OK)
294 {
295 mutt_debug(LL_DEBUG1, "libsasl initialisation failed\n");
296 return SASL_FAIL;
297 }
298
299 sasl_init = true;
300
301 return SASL_OK;
302}
303
312static int mutt_sasl_cb_authname(void *context, int id, const char **result, unsigned int *len)
313{
314 if (!result)
315 return SASL_FAIL;
316
317 struct ConnAccount *cac = context;
318
319 *result = NULL;
320 if (len)
321 *len = 0;
322
323 if (!cac)
324 return SASL_BADPARAM;
325
326 mutt_debug(LL_DEBUG2, "getting %s for %s:%u\n",
327 (id == SASL_CB_AUTHNAME) ? "authname" : "user", cac->host, cac->port);
328
329 if (id == SASL_CB_AUTHNAME)
330 {
331 if (mutt_account_getlogin(cac) < 0)
332 return SASL_FAIL;
333 *result = cac->login;
334 }
335 else
336 {
337 if (mutt_account_getuser(cac) < 0)
338 return SASL_FAIL;
339 *result = cac->user;
340 }
341
342 if (len)
343 *len = strlen(*result);
344
345 return SASL_OK;
346}
347
356static int mutt_sasl_cb_pass(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret)
357{
358 struct ConnAccount *cac = context;
359 int len;
360
361 if (!cac || !psecret)
362 return SASL_BADPARAM;
363
364 mutt_debug(LL_DEBUG2, "getting password for %s@%s:%u\n", cac->login, cac->host, cac->port);
365
366 if (mutt_account_getpass(cac) < 0)
367 return SASL_FAIL;
368
369 len = strlen(cac->pass);
370
371 mutt_mem_realloc(&secret_ptr, sizeof(sasl_secret_t) + len);
372 memcpy((char *) secret_ptr->data, cac->pass, (size_t) len);
373 secret_ptr->len = len;
374 *psecret = secret_ptr;
375
376 return SASL_OK;
377}
378
384static sasl_callback_t *mutt_sasl_get_callbacks(struct ConnAccount *cac)
385{
386 sasl_callback_t *callback = MuttSaslCallbacks;
387
388 callback->id = SASL_CB_USER;
389 callback->proc = (int (*)(void))(intptr_t) mutt_sasl_cb_authname;
390 callback->context = cac;
391 callback++;
392
393 callback->id = SASL_CB_AUTHNAME;
394 callback->proc = (int (*)(void))(intptr_t) mutt_sasl_cb_authname;
395 callback->context = cac;
396 callback++;
397
398 callback->id = SASL_CB_PASS;
399 callback->proc = (int (*)(void))(intptr_t) mutt_sasl_cb_pass;
400 callback->context = cac;
401 callback++;
402
403 callback->id = SASL_CB_GETREALM;
404 callback->proc = NULL;
405 callback->context = NULL;
406 callback++;
407
408 callback->id = SASL_CB_LIST_END;
409 callback->proc = NULL;
410 callback->context = NULL;
411
412 return MuttSaslCallbacks;
413}
414
422static int mutt_sasl_conn_open(struct Connection *conn)
423{
424 struct SaslSockData *sasldata = conn->sockdata;
425 conn->sockdata = sasldata->sockdata;
426 int rc = sasldata->open(conn);
427 conn->sockdata = sasldata;
428
429 return rc;
430}
431
438static int mutt_sasl_conn_close(struct Connection *conn)
439{
440 struct SaslSockData *sasldata = conn->sockdata;
441
442 /* restore connection's underlying methods */
443 conn->sockdata = sasldata->sockdata;
444 conn->open = sasldata->open;
445 conn->read = sasldata->read;
446 conn->write = sasldata->write;
447 conn->poll = sasldata->poll;
448 conn->close = sasldata->close;
449
450 /* release sasl resources */
451 sasl_dispose(&sasldata->saslconn);
452 FREE(&sasldata);
453
454 /* call underlying close */
455 int rc = conn->close(conn);
456
457 return rc;
458}
459
463static int mutt_sasl_conn_read(struct Connection *conn, char *buf, size_t count)
464{
465 int rc;
466 unsigned int olen;
467
468 struct SaslSockData *sasldata = conn->sockdata;
469
470 /* if we still have data in our read buffer, copy it into buf */
471 if (sasldata->blen > sasldata->bpos)
472 {
473 olen = ((sasldata->blen - sasldata->bpos) > count) ?
474 count :
475 sasldata->blen - sasldata->bpos;
476
477 memcpy(buf, sasldata->buf + sasldata->bpos, olen);
478 sasldata->bpos += olen;
479
480 return olen;
481 }
482
483 conn->sockdata = sasldata->sockdata;
484
485 sasldata->bpos = 0;
486 sasldata->blen = 0;
487
488 /* and decode the result, if necessary */
489 if (*sasldata->ssf != 0)
490 {
491 do
492 {
493 /* call the underlying read function to fill the buffer */
494 rc = sasldata->read(conn, buf, count);
495 if (rc <= 0)
496 goto out;
497
498 rc = sasl_decode(sasldata->saslconn, buf, rc, &sasldata->buf, &sasldata->blen);
499 if (rc != SASL_OK)
500 {
501 mutt_debug(LL_DEBUG1, "SASL decode failed: %s\n", sasl_errstring(rc, NULL, NULL));
502 goto out;
503 }
504 } while (sasldata->blen == 0);
505
506 olen = ((sasldata->blen - sasldata->bpos) > count) ?
507 count :
508 sasldata->blen - sasldata->bpos;
509
510 memcpy(buf, sasldata->buf, olen);
511 sasldata->bpos += olen;
512
513 rc = olen;
514 }
515 else
516 {
517 rc = sasldata->read(conn, buf, count);
518 }
519
520out:
521 conn->sockdata = sasldata;
522
523 return rc;
524}
525
529static int mutt_sasl_conn_write(struct Connection *conn, const char *buf, size_t count)
530{
531 int rc;
532 const char *pbuf = NULL;
533 unsigned int olen, plen;
534
535 struct SaslSockData *sasldata = conn->sockdata;
536 conn->sockdata = sasldata->sockdata;
537
538 /* encode data, if necessary */
539 if (*sasldata->ssf != 0)
540 {
541 /* handle data larger than MAXOUTBUF */
542 do
543 {
544 olen = (count > *sasldata->pbufsize) ? *sasldata->pbufsize : count;
545
546 rc = sasl_encode(sasldata->saslconn, buf, olen, &pbuf, &plen);
547 if (rc != SASL_OK)
548 {
549 mutt_debug(LL_DEBUG1, "SASL encoding failed: %s\n", sasl_errstring(rc, NULL, NULL));
550 goto fail;
551 }
552
553 rc = sasldata->write(conn, pbuf, plen);
554 if (rc != plen)
555 goto fail;
556
557 count -= olen;
558 buf += olen;
559 } while (count > *sasldata->pbufsize);
560 }
561 else
562 {
563 /* just write using the underlying socket function */
564 rc = sasldata->write(conn, buf, count);
565 }
566
567 conn->sockdata = sasldata;
568
569 return rc;
570
571fail:
572 conn->sockdata = sasldata;
573 return -1;
574}
575
579static int mutt_sasl_conn_poll(struct Connection *conn, time_t wait_secs)
580{
581 struct SaslSockData *sasldata = conn->sockdata;
582 int rc;
583
584 conn->sockdata = sasldata->sockdata;
585 rc = sasldata->poll(conn, wait_secs);
586 conn->sockdata = sasldata;
587
588 return rc;
589}
590
601int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
602{
603 sasl_security_properties_t secprops;
604 struct sockaddr_storage local, remote;
605 socklen_t size;
606 char iplocalport[IP_PORT_BUFLEN], ipremoteport[IP_PORT_BUFLEN];
607 char *plp = NULL;
608 char *prp = NULL;
609 int rc;
610
611 if (mutt_sasl_start() != SASL_OK)
612 return -1;
613
614 if (!conn->account.service)
615 {
616 mutt_error(_("Unknown SASL profile"));
617 return -1;
618 }
619
620 size = sizeof(local);
621 if (getsockname(conn->fd, (struct sockaddr *) &local, &size) == 0)
622 {
623 if (iptostring((struct sockaddr *) &local, size, iplocalport, IP_PORT_BUFLEN) == SASL_OK)
624 plp = iplocalport;
625 else
626 mutt_debug(LL_DEBUG2, "SASL failed to parse local IP address\n");
627 }
628 else
629 {
630 mutt_debug(LL_DEBUG2, "SASL failed to get local IP address\n");
631 }
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 {
643 mutt_debug(LL_DEBUG2, "SASL failed to get remote IP address\n");
644 }
645
646 mutt_debug(LL_DEBUG2, "SASL local ip: %s, remote ip:%s\n", NONULL(plp), NONULL(prp));
647
648 rc = sasl_client_new(conn->account.service, conn->account.host, plp, prp,
649 mutt_sasl_get_callbacks(&conn->account), 0, saslconn);
650
651 if (rc != SASL_OK)
652 {
653 mutt_error(_("Error allocating SASL connection"));
654 return -1;
655 }
656
657 memset(&secprops, 0, sizeof(secprops));
658 /* Work around a casting bug in the SASL krb4 module */
659 secprops.max_ssf = 0x7fff;
660 secprops.maxbufsize = MUTT_SASL_MAXBUF;
661 if (sasl_setprop(*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
662 {
663 mutt_error(_("Error setting SASL security properties"));
664 sasl_dispose(saslconn);
665 return -1;
666 }
667
668 if (conn->ssf != 0)
669 {
670 /* I'm not sure this actually has an effect, at least with SASLv2 */
671 mutt_debug(LL_DEBUG2, "External SSF: %d\n", conn->ssf);
672 if (sasl_setprop(*saslconn, SASL_SSF_EXTERNAL, &conn->ssf) != SASL_OK)
673 {
674 mutt_error(_("Error setting SASL external security strength"));
675 sasl_dispose(saslconn);
676 return -1;
677 }
678 }
679 if (conn->account.user[0])
680 {
681 mutt_debug(LL_DEBUG2, "External authentication name: %s\n", conn->account.user);
682 if (sasl_setprop(*saslconn, SASL_AUTH_EXTERNAL, conn->account.user) != SASL_OK)
683 {
684 mutt_error(_("Error setting SASL external user name"));
685 sasl_dispose(saslconn);
686 return -1;
687 }
688 }
689
690 return 0;
691}
692
700int mutt_sasl_interact(sasl_interact_t *interaction)
701{
702 int rc = SASL_OK;
703 char prompt[128] = { 0 };
704 struct Buffer *resp = mutt_buffer_pool_get();
705
706 while (interaction->id != SASL_CB_LIST_END)
707 {
708 mutt_debug(LL_DEBUG2, "filling in SASL interaction %ld\n", interaction->id);
709
710 snprintf(prompt, sizeof(prompt), "%s: ", interaction->prompt);
711 mutt_buffer_reset(resp);
712
714 false, NULL, NULL, NULL) != 0))
715 {
716 rc = SASL_FAIL;
717 break;
718 }
719
720 interaction->len = mutt_buffer_len(resp) + 1;
721 interaction->result = mutt_buffer_strdup(resp);
722 interaction++;
723 }
724
726 return rc;
727}
728
737void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
738{
739 struct SaslSockData *sasldata = mutt_mem_malloc(sizeof(struct SaslSockData));
740 /* work around sasl_getprop aliasing issues */
741 const void *tmp = NULL;
742
743 sasldata->saslconn = saslconn;
744 /* get ssf so we know whether we have to (en|de)code read/write */
745 sasl_getprop(saslconn, SASL_SSF, &tmp);
746 sasldata->ssf = tmp;
747 mutt_debug(LL_DEBUG3, "SASL protection strength: %u\n", *sasldata->ssf);
748 /* Add SASL SSF to transport SSF */
749 conn->ssf += *sasldata->ssf;
750 sasl_getprop(saslconn, SASL_MAXOUTBUF, &tmp);
751 sasldata->pbufsize = tmp;
752 mutt_debug(LL_DEBUG3, "SASL protection buffer size: %u\n", *sasldata->pbufsize);
753
754 /* clear input buffer */
755 sasldata->buf = NULL;
756 sasldata->bpos = 0;
757 sasldata->blen = 0;
758
759 /* preserve old functions */
760 sasldata->sockdata = conn->sockdata;
761 sasldata->open = conn->open;
762 sasldata->read = conn->read;
763 sasldata->write = conn->write;
764 sasldata->poll = conn->poll;
765 sasldata->close = conn->close;
766
767 /* and set up new functions */
768 conn->sockdata = sasldata;
774}
775
783{
784 /* As we never use the server-side, the silently ignore the return value */
785 sasl_client_done();
786}
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:409
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:485
int mutt_account_getpass(struct ConnAccount *cac)
Fetch password into ConnAccount, if necessary.
Definition: connaccount.c:129
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
Definition: connaccount.c:49
int mutt_account_getlogin(struct ConnAccount *cac)
Retrieve login info into ConnAccount, if necessary.
Definition: connaccount.c:99
Enter a string.
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: window.c:180
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:81
static int mutt_sasl_conn_close(struct Connection *conn)
Close SASL connection - Implements Connection::close() -.
Definition: sasl.c:438
int(* close)(struct Connection *conn)
Close a socket Connection - Implements Connection::close() -.
Definition: sasl.c:97
int(* open)(struct Connection *conn)
Open a socket Connection - Implements Connection::open() -.
Definition: sasl.c:77
static int mutt_sasl_conn_open(struct Connection *conn)
Empty wrapper for underlying open function - Implements Connection::open() -.
Definition: sasl.c:422
int(* poll)(struct Connection *conn, time_t wait_secs)
Check whether a socket read would block - Implements Connection::poll() -.
Definition: sasl.c:92
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:579
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:463
int(* read)(struct Connection *conn, char *buf, size_t count)
Read from a socket Connection - Implements Connection::read() -.
Definition: sasl.c:82
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:529
int(* write)(struct Connection *conn, const char *buf, size_t count)
Write to a socket Connection - Implements Connection::write() -.
Definition: sasl.c:87
#define mutt_error(...)
Definition: logging.h:87
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define FREE(x)
Definition: memory.h:43
#define mutt_array_size(x)
Definition: memory.h:36
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
Many unsorted constants and some structs.
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:55
static unsigned char * pbuf
Cached PGP data packet.
Definition: pgppacket.c:38
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
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:356
#define MUTT_SASL_MAXBUF
Definition: sasl.c:115
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:312
static sasl_secret_t * secret_ptr
Definition: sasl.c:124
#define IP_PORT_BUFLEN
Definition: sasl.c:120
static int getnameinfo_err(int rc)
Convert a getaddrinfo() error code into an SASL error code.
Definition: sasl.c:148
int mutt_sasl_interact(sasl_interact_t *interaction)
Perform an SASL interaction with the user.
Definition: sasl.c:700
static int mutt_sasl_start(void)
Initialise SASL library.
Definition: sasl.c:272
static int mutt_sasl_cb_log(void *context, int priority, const char *message)
Callback to log SASL messages.
Definition: sasl.c:235
void mutt_sasl_done(void)
Invoke when processing is complete.
Definition: sasl.c:782
static sasl_callback_t * mutt_sasl_get_callbacks(struct ConnAccount *cac)
Get the SASL callback functions.
Definition: sasl.c:384
static const char *const SaslAuthenticators[]
Authenticaion methods supported by Cyrus SASL.
Definition: sasl.c:103
static sasl_callback_t MuttSaslCallbacks[5]
Definition: sasl.c:122
static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out, unsigned int outlen)
Convert IP Address to string.
Definition: sasl.c:202
bool sasl_auth_validator(const char *authenticator)
Validate an auth method against Cyrus SASL methods.
Definition: sasl.c:131
int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
Wrapper for sasl_client_new()
Definition: sasl.c:601
void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
Set up an SASL connection.
Definition: sasl.c:737
SASL authentication support.
Key value store.
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:34
Login details for a remote server.
Definition: connaccount.h:53
char login[128]
Login name.
Definition: connaccount.h:55
char user[128]
Username.
Definition: connaccount.h:56
char pass[256]
Password.
Definition: connaccount.h:57
const char * service
Name of the service, e.g. "imap".
Definition: connaccount.h:61
char host[128]
Server to login to.
Definition: connaccount.h:54
unsigned short port
Port to connect to.
Definition: connaccount.h:58
void * sockdata
Backend-specific socket data.
Definition: connection.h:56
int(* poll)(struct Connection *conn, time_t wait_secs)
Definition: connection.h:106
int(* write)(struct Connection *conn, const char *buf, size_t count)
Definition: connection.h:93
unsigned int ssf
Security strength factor, in bits (see notes)
Definition: connection.h:51
int(* close)(struct Connection *conn)
Definition: connection.h:117
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:50
int(* open)(struct Connection *conn)
Definition: connection.h:67
int fd
Socket file descriptor.
Definition: connection.h:54
int(* read)(struct Connection *conn, char *buf, size_t count)
Definition: connection.h:80
SASL authentication API -.
Definition: sasl.c:62
void * sockdata
Underlying socket data.
Definition: sasl.c:72
unsigned int blen
Size of the read buffer.
Definition: sasl.c:69
unsigned int bpos
Current read position.
Definition: sasl.c:70
const sasl_ssf_t * ssf
Definition: sasl.c:64
const unsigned int * pbufsize
Definition: sasl.c:65
const char * buf
Buffer for data read from the connection.
Definition: sasl.c:68
sasl_conn_t * saslconn
Definition: sasl.c:63