NeoMutt  2024-03-23-147-g885fbc
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
sasl.c
Go to the documentation of this file.
1
41#include "config.h"
42#include <stddef.h>
43#include <errno.h>
44#include <netdb.h>
45#include <sasl/sasl.h>
46#include <stdbool.h>
47#include <stdint.h>
48#include <stdio.h>
49#include <string.h>
50#include <sys/socket.h>
51#include <sys/types.h>
52#include "mutt/lib.h"
53#include "mutt.h"
54#include "sasl.h"
55#include "editor/lib.h"
56#include "history/lib.h"
57#include "connaccount.h"
58#include "connection.h"
59#include "globals.h"
60
65{
66 sasl_conn_t *saslconn;
67 const sasl_ssf_t *ssf;
68 const unsigned int *pbufsize;
69
70 /* read buffer */
71 const char *buf;
72 unsigned int blen;
73 unsigned int bpos;
74
75 void *sockdata;
76
80 int (*open)(struct Connection *conn);
81
85 int (*read)(struct Connection *conn, char *buf, size_t count);
86
90 int (*write)(struct Connection *conn, const char *buf, size_t count);
91
95 int (*poll)(struct Connection *conn, time_t wait_secs);
96
100 int (*close)(struct Connection *conn);
101};
102
106static const char *const SaslAuthenticators[] = {
107 "ANONYMOUS", "CRAM-MD5", "DIGEST-MD5", "EXTERNAL",
108 "GS2-IAKERB", "GS2-KRB5", "GSS-SPNEGO", "GSSAPI",
109 "LOGIN", "NTLM", "OTP-MD4", "OTP-MD5",
110 "OTP-SHA1", "PASSDSS-3DES-1", "PLAIN", "SCRAM-SHA-1",
111 "SCRAM-SHA-224", "SCRAM-SHA-256", "SCRAM-SHA-384", "SCRAM-SHA-512",
112 "SRP",
113};
114
115/* arbitrary. SASL will probably use a smaller buffer anyway. OTOH it's
116 * been a while since I've had access to an SASL server which negotiated
117 * a protection buffer. */
118#define MUTT_SASL_MAXBUF 65536
119
120/* used to hold a string "host;port"
121 * where host is size NI_MAXHOST-1 and port is size NI_MAXSERV-1
122 * plus two bytes for the ';' and trailing \0 */
123#define IP_PORT_BUFLEN (NI_MAXHOST + NI_MAXSERV)
124
126static sasl_callback_t MuttSaslCallbacks[5];
127
129static sasl_secret_t *SecretPtr = NULL;
130
136bool sasl_auth_validator(const char *authenticator)
137{
138 for (size_t i = 0; i < mutt_array_size(SaslAuthenticators); i++)
139 {
140 const char *auth = SaslAuthenticators[i];
141 if (mutt_istr_equal(auth, authenticator))
142 return true;
143 }
144
145 return false;
146}
147
153static int getnameinfo_err(int rc)
154{
155 int err;
156 mutt_debug(LL_DEBUG1, "getnameinfo: ");
157 switch (rc)
158 {
159 case EAI_AGAIN:
160 mutt_debug(LL_DEBUG1, "The name could not be resolved at this time. Future attempts may succeed\n");
161 err = SASL_TRYAGAIN;
162 break;
163 case EAI_BADFLAGS:
164 mutt_debug(LL_DEBUG1, "The flags had an invalid value\n");
165 err = SASL_BADPARAM;
166 break;
167 case EAI_FAIL:
168 mutt_debug(LL_DEBUG1, "A non-recoverable error occurred\n");
169 err = SASL_FAIL;
170 break;
171 case EAI_FAMILY:
172 mutt_debug(LL_DEBUG1, "The address family was not recognized or the address length was invalid for the specified family\n");
173 err = SASL_BADPROT;
174 break;
175 case EAI_MEMORY:
176 mutt_debug(LL_DEBUG1, "There was a memory allocation failure\n");
177 err = SASL_NOMEM;
178 break;
179 case EAI_NONAME:
180 mutt_debug(LL_DEBUG1, "The name does not resolve for the supplied parameters. "
181 "NI_NAMEREQD is set and the host's name can't be located, or both nodename and servname were null.\n");
182 err = SASL_FAIL; /* no real equivalent */
183 break;
184 case EAI_SYSTEM:
185 mutt_debug(LL_DEBUG1, "A system error occurred. The error code can be found in errno(%d,%s))\n",
186 errno, strerror(errno));
187 err = SASL_FAIL; /* no real equivalent */
188 break;
189 default:
190 mutt_debug(LL_DEBUG1, "Unknown error %d\n", rc);
191 err = SASL_FAIL; /* no real equivalent */
192 break;
193 }
194 return err;
195}
196
207static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out,
208 unsigned int outlen)
209{
210 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
211 int rc;
212
213 if (!addr || !out)
214 return SASL_BADPARAM;
215
216 rc = getnameinfo(addr, addrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
217 NI_NUMERICHOST |
218#ifdef NI_WITHSCOPEID
219 NI_WITHSCOPEID |
220#endif
221 NI_NUMERICSERV);
222 if (rc != 0)
223 return getnameinfo_err(rc);
224
225 if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
226 return SASL_BUFOVER;
227
228 snprintf(out, outlen, "%s;%s", hbuf, pbuf);
229
230 return SASL_OK;
231}
232
240static int mutt_sasl_cb_log(void *context, int priority, const char *message)
241{
242 if (priority == SASL_LOG_NONE)
243 return SASL_OK;
244
245 int mutt_priority = 0;
246 switch (priority)
247 {
248 case SASL_LOG_TRACE:
249 case SASL_LOG_PASS:
250 mutt_priority = 5;
251 break;
252 case SASL_LOG_DEBUG:
253 case SASL_LOG_NOTE:
254 mutt_priority = 3;
255 break;
256 case SASL_LOG_FAIL:
257 case SASL_LOG_WARN:
258 mutt_priority = 2;
259 break;
260 case SASL_LOG_ERR:
261 mutt_priority = 1;
262 break;
263 default:
264 mutt_debug(LL_DEBUG1, "SASL unknown log priority: %s\n", message);
265 return SASL_OK;
266 }
267 mutt_debug(mutt_priority, "SASL: %s\n", message);
268 return SASL_OK;
269}
270
278{
279 static bool sasl_init = false;
280
281 static sasl_callback_t callbacks[2];
282 int rc;
283
284 if (sasl_init)
285 return SASL_OK;
286
287 /* set up default logging callback */
288 callbacks[0].id = SASL_CB_LOG;
289 callbacks[0].proc = (int (*)(void))(intptr_t) mutt_sasl_cb_log;
290 callbacks[0].context = NULL;
291
292 callbacks[1].id = SASL_CB_LIST_END;
293 callbacks[1].proc = NULL;
294 callbacks[1].context = NULL;
295
296 rc = sasl_client_init(callbacks);
297
298 if (rc != SASL_OK)
299 {
300 mutt_debug(LL_DEBUG1, "libsasl initialisation failed\n");
301 return SASL_FAIL;
302 }
303
304 sasl_init = true;
305
306 return SASL_OK;
307}
308
317static int mutt_sasl_cb_authname(void *context, int id, const char **result, unsigned int *len)
318{
319 if (!result)
320 return SASL_FAIL;
321
322 struct ConnAccount *cac = context;
323
324 *result = NULL;
325 if (len)
326 *len = 0;
327
328 if (!cac)
329 return SASL_BADPARAM;
330
331 mutt_debug(LL_DEBUG2, "getting %s for %s:%u\n",
332 (id == SASL_CB_AUTHNAME) ? "authname" : "user", cac->host, cac->port);
333
334 if (id == SASL_CB_AUTHNAME)
335 {
336 if (mutt_account_getlogin(cac) < 0)
337 return SASL_FAIL;
338 *result = cac->login;
339 }
340 else
341 {
342 if (mutt_account_getuser(cac) < 0)
343 return SASL_FAIL;
344 *result = cac->user;
345 }
346
347 if (len)
348 *len = strlen(*result);
349
350 return SASL_OK;
351}
352
361static int mutt_sasl_cb_pass(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret)
362{
363 struct ConnAccount *cac = context;
364 int len;
365
366 if (!cac || !psecret)
367 return SASL_BADPARAM;
368
369 mutt_debug(LL_DEBUG2, "getting password for %s@%s:%u\n", cac->login, cac->host, cac->port);
370
371 if (mutt_account_getpass(cac) < 0)
372 return SASL_FAIL;
373
374 len = strlen(cac->pass);
375
376 mutt_mem_realloc(&SecretPtr, sizeof(sasl_secret_t) + len);
377 memcpy((char *) SecretPtr->data, cac->pass, (size_t) len);
378 SecretPtr->len = len;
379 *psecret = SecretPtr;
380
381 return SASL_OK;
382}
383
389static sasl_callback_t *mutt_sasl_get_callbacks(struct ConnAccount *cac)
390{
391 sasl_callback_t *callback = MuttSaslCallbacks;
392
393 callback->id = SASL_CB_USER;
394 callback->proc = (int (*)(void))(intptr_t) mutt_sasl_cb_authname;
395 callback->context = cac;
396 callback++;
397
398 callback->id = SASL_CB_AUTHNAME;
399 callback->proc = (int (*)(void))(intptr_t) mutt_sasl_cb_authname;
400 callback->context = cac;
401 callback++;
402
403 callback->id = SASL_CB_PASS;
404 callback->proc = (int (*)(void))(intptr_t) mutt_sasl_cb_pass;
405 callback->context = cac;
406 callback++;
407
408 callback->id = SASL_CB_GETREALM;
409 callback->proc = NULL;
410 callback->context = NULL;
411 callback++;
412
413 callback->id = SASL_CB_LIST_END;
414 callback->proc = NULL;
415 callback->context = NULL;
416
417 return MuttSaslCallbacks;
418}
419
427static int mutt_sasl_conn_open(struct Connection *conn)
428{
429 struct SaslSockData *sasldata = conn->sockdata;
430 conn->sockdata = sasldata->sockdata;
431 int rc = sasldata->open(conn);
432 conn->sockdata = sasldata;
433
434 return rc;
435}
436
443static int mutt_sasl_conn_close(struct Connection *conn)
444{
445 struct SaslSockData *sasldata = conn->sockdata;
446
447 /* restore connection's underlying methods */
448 conn->sockdata = sasldata->sockdata;
449 conn->open = sasldata->open;
450 conn->read = sasldata->read;
451 conn->write = sasldata->write;
452 conn->poll = sasldata->poll;
453 conn->close = sasldata->close;
454
455 /* release sasl resources */
456 sasl_dispose(&sasldata->saslconn);
457 FREE(&sasldata);
458
459 /* call underlying close */
460 int rc = conn->close(conn);
461
462 return rc;
463}
464
468static int mutt_sasl_conn_read(struct Connection *conn, char *buf, size_t count)
469{
470 int rc;
471 unsigned int olen;
472
473 struct SaslSockData *sasldata = conn->sockdata;
474
475 /* if we still have data in our read buffer, copy it into buf */
476 if (sasldata->blen > sasldata->bpos)
477 {
478 olen = ((sasldata->blen - sasldata->bpos) > count) ?
479 count :
480 sasldata->blen - sasldata->bpos;
481
482 memcpy(buf, sasldata->buf + sasldata->bpos, olen);
483 sasldata->bpos += olen;
484
485 return olen;
486 }
487
488 conn->sockdata = sasldata->sockdata;
489
490 sasldata->bpos = 0;
491 sasldata->blen = 0;
492
493 /* and decode the result, if necessary */
494 if (*sasldata->ssf != 0)
495 {
496 do
497 {
498 /* call the underlying read function to fill the buffer */
499 rc = sasldata->read(conn, buf, count);
500 if (rc <= 0)
501 goto out;
502
503 rc = sasl_decode(sasldata->saslconn, buf, rc, &sasldata->buf, &sasldata->blen);
504 if (rc != SASL_OK)
505 {
506 mutt_debug(LL_DEBUG1, "SASL decode failed: %s\n", sasl_errstring(rc, NULL, NULL));
507 goto out;
508 }
509 } while (sasldata->blen == 0);
510
511 olen = ((sasldata->blen - sasldata->bpos) > count) ?
512 count :
513 sasldata->blen - sasldata->bpos;
514
515 memcpy(buf, sasldata->buf, olen);
516 sasldata->bpos += olen;
517
518 rc = olen;
519 }
520 else
521 {
522 rc = sasldata->read(conn, buf, count);
523 }
524
525out:
526 conn->sockdata = sasldata;
527
528 return rc;
529}
530
534static int mutt_sasl_conn_write(struct Connection *conn, const char *buf, size_t count)
535{
536 int rc;
537 const char *pbuf = NULL;
538 unsigned int olen, plen;
539
540 struct SaslSockData *sasldata = conn->sockdata;
541 conn->sockdata = sasldata->sockdata;
542
543 /* encode data, if necessary */
544 if (*sasldata->ssf != 0)
545 {
546 /* handle data larger than MAXOUTBUF */
547 do
548 {
549 olen = (count > *sasldata->pbufsize) ? *sasldata->pbufsize : count;
550
551 rc = sasl_encode(sasldata->saslconn, buf, olen, &pbuf, &plen);
552 if (rc != SASL_OK)
553 {
554 mutt_debug(LL_DEBUG1, "SASL encoding failed: %s\n", sasl_errstring(rc, NULL, NULL));
555 goto fail;
556 }
557
558 rc = sasldata->write(conn, pbuf, plen);
559 if (rc != plen)
560 goto fail;
561
562 count -= olen;
563 buf += olen;
564 } while (count > *sasldata->pbufsize);
565 }
566 else
567 {
568 /* just write using the underlying socket function */
569 rc = sasldata->write(conn, buf, count);
570 }
571
572 conn->sockdata = sasldata;
573
574 return rc;
575
576fail:
577 conn->sockdata = sasldata;
578 return -1;
579}
580
584static int mutt_sasl_conn_poll(struct Connection *conn, time_t wait_secs)
585{
586 struct SaslSockData *sasldata = conn->sockdata;
587 int rc;
588
589 conn->sockdata = sasldata->sockdata;
590 rc = sasldata->poll(conn, wait_secs);
591 conn->sockdata = sasldata;
592
593 return rc;
594}
595
606int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
607{
608 if (mutt_sasl_start() != SASL_OK)
609 return -1;
610
611 if (!conn->account.service)
612 {
613 mutt_error(_("Unknown SASL profile"));
614 return -1;
615 }
616
617 socklen_t size;
618
619 struct sockaddr_storage local = { 0 };
620 char iplocalport[IP_PORT_BUFLEN] = { 0 };
621 char *plp = NULL;
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 {
632 mutt_debug(LL_DEBUG2, "SASL failed to get local IP address\n");
633 }
634
635 struct sockaddr_storage remote = { 0 };
636 char ipremoteport[IP_PORT_BUFLEN] = { 0 };
637 char *prp = NULL;
638 size = sizeof(remote);
639 if (getpeername(conn->fd, (struct sockaddr *) &remote, &size) == 0)
640 {
641 if (iptostring((struct sockaddr *) &remote, size, ipremoteport, IP_PORT_BUFLEN) == SASL_OK)
642 prp = ipremoteport;
643 else
644 mutt_debug(LL_DEBUG2, "SASL failed to parse remote IP address\n");
645 }
646 else
647 {
648 mutt_debug(LL_DEBUG2, "SASL failed to get remote IP address\n");
649 }
650
651 mutt_debug(LL_DEBUG2, "SASL local ip: %s, remote ip:%s\n", NONULL(plp), NONULL(prp));
652
653 int rc = sasl_client_new(conn->account.service, conn->account.host, plp, prp,
654 mutt_sasl_get_callbacks(&conn->account), 0, saslconn);
655 if (rc != SASL_OK)
656 {
657 mutt_error(_("Error allocating SASL connection"));
658 return -1;
659 }
660
661 /* Work around a casting bug in the SASL krb4 module */
662 sasl_security_properties_t secprops = { 0 };
663 secprops.max_ssf = 0x7fff;
664 secprops.maxbufsize = MUTT_SASL_MAXBUF;
665 if (sasl_setprop(*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
666 {
667 mutt_error(_("Error setting SASL security properties"));
668 sasl_dispose(saslconn);
669 return -1;
670 }
671
672 if (conn->ssf != 0)
673 {
674 /* I'm not sure this actually has an effect, at least with SASLv2 */
675 mutt_debug(LL_DEBUG2, "External SSF: %d\n", conn->ssf);
676 if (sasl_setprop(*saslconn, SASL_SSF_EXTERNAL, &conn->ssf) != SASL_OK)
677 {
678 mutt_error(_("Error setting SASL external security strength"));
679 sasl_dispose(saslconn);
680 return -1;
681 }
682 }
683 if (conn->account.user[0])
684 {
685 mutt_debug(LL_DEBUG2, "External authentication name: %s\n", conn->account.user);
686 if (sasl_setprop(*saslconn, SASL_AUTH_EXTERNAL, conn->account.user) != SASL_OK)
687 {
688 mutt_error(_("Error setting SASL external user name"));
689 sasl_dispose(saslconn);
690 return -1;
691 }
692 }
693
694 return 0;
695}
696
704int mutt_sasl_interact(sasl_interact_t *interaction)
705{
706 int rc = SASL_OK;
707 char prompt[128] = { 0 };
708 struct Buffer *resp = buf_pool_get();
709
710 while (interaction->id != SASL_CB_LIST_END)
711 {
712 mutt_debug(LL_DEBUG2, "filling in SASL interaction %ld\n", interaction->id);
713
714 snprintf(prompt, sizeof(prompt), "%s: ", interaction->prompt);
715 buf_reset(resp);
716
717 if (OptNoCurses ||
718 (mw_get_field(prompt, resp, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0))
719 {
720 rc = SASL_FAIL;
721 break;
722 }
723
724 interaction->len = buf_len(resp) + 1;
725 interaction->result = buf_strdup(resp);
726 interaction++;
727 }
728
729 buf_pool_release(&resp);
730 return rc;
731}
732
741void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
742{
743 struct SaslSockData *sasldata = mutt_mem_malloc(sizeof(struct SaslSockData));
744 /* work around sasl_getprop aliasing issues */
745 const void *tmp = NULL;
746
747 sasldata->saslconn = saslconn;
748 /* get ssf so we know whether we have to (en|de)code read/write */
749 sasl_getprop(saslconn, SASL_SSF, &tmp);
750 sasldata->ssf = tmp;
751 mutt_debug(LL_DEBUG3, "SASL protection strength: %u\n", *sasldata->ssf);
752 /* Add SASL SSF to transport SSF */
753 conn->ssf += *sasldata->ssf;
754 sasl_getprop(saslconn, SASL_MAXOUTBUF, &tmp);
755 sasldata->pbufsize = tmp;
756 mutt_debug(LL_DEBUG3, "SASL protection buffer size: %u\n", *sasldata->pbufsize);
757
758 /* clear input buffer */
759 sasldata->buf = NULL;
760 sasldata->bpos = 0;
761 sasldata->blen = 0;
762
763 /* preserve old functions */
764 sasldata->sockdata = conn->sockdata;
765 sasldata->open = conn->open;
766 sasldata->read = conn->read;
767 sasldata->write = conn->write;
768 sasldata->poll = conn->poll;
769 sasldata->close = conn->close;
770
771 /* and set up new functions */
772 conn->sockdata = sasldata;
778}
779
787{
788 /* As we never use the server-side, the silently ignore the return value */
789 sasl_client_done();
790}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:490
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:75
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:570
int mutt_account_getpass(struct ConnAccount *cac)
Fetch password into ConnAccount, if necessary.
Definition: connaccount.c:131
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
Definition: connaccount.c:52
int mutt_account_getlogin(struct ConnAccount *cac)
Retrieve login info into ConnAccount, if necessary.
Definition: connaccount.c:101
Connection Credentials.
An open network connection (socket)
Edit a string.
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:72
static int mutt_sasl_conn_close(struct Connection *conn)
Close SASL connection - Implements Connection::close() -.
Definition: sasl.c:443
int(* close)(struct Connection *conn)
Close a socket Connection - Implements Connection::close() -.
Definition: sasl.c:100
int(* open)(struct Connection *conn)
Open a socket Connection - Implements Connection::open() -.
Definition: sasl.c:80
static int mutt_sasl_conn_open(struct Connection *conn)
Empty wrapper for underlying open function - Implements Connection::open() -.
Definition: sasl.c:427
int(* poll)(struct Connection *conn, time_t wait_secs)
Check if any data is waiting on a socket - Implements Connection::poll() -.
Definition: sasl.c:95
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() -.
Definition: sasl.c:584
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:468
int(* read)(struct Connection *conn, char *buf, size_t count)
Read from a socket Connection - Implements Connection::read() -.
Definition: sasl.c:85
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:534
int(* write)(struct Connection *conn, const char *buf, size_t count)
Write to a socket Connection - Implements Connection::write() -.
Definition: sasl.c:90
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 -.
Definition: window.c:274
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
Read/write command history from/to a file.
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:56
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
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:45
#define mutt_array_size(x)
Definition: memory.h:38
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:721
Many unsorted constants and some structs.
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
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:361
#define MUTT_SASL_MAXBUF
Definition: sasl.c:118
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:317
void mutt_sasl_cleanup(void)
Invoke when processing is complete.
Definition: sasl.c:786
#define IP_PORT_BUFLEN
Definition: sasl.c:123
int mutt_sasl_start(void)
Initialise SASL library.
Definition: sasl.c:277
static int getnameinfo_err(int rc)
Convert a getaddrinfo() error code into an SASL error code.
Definition: sasl.c:153
int mutt_sasl_interact(sasl_interact_t *interaction)
Perform an SASL interaction with the user.
Definition: sasl.c:704
static int mutt_sasl_cb_log(void *context, int priority, const char *message)
Callback to log SASL messages.
Definition: sasl.c:240
static sasl_callback_t * mutt_sasl_get_callbacks(struct ConnAccount *cac)
Get the SASL callback functions.
Definition: sasl.c:389
static const char *const SaslAuthenticators[]
Authenticaion methods supported by Cyrus SASL.
Definition: sasl.c:106
static sasl_callback_t MuttSaslCallbacks[5]
SASL callback functions, e.g. mutt_sasl_cb_authname(), mutt_sasl_cb_pass()
Definition: sasl.c:126
static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out, unsigned int outlen)
Convert IP Address to string.
Definition: sasl.c:207
bool sasl_auth_validator(const char *authenticator)
Validate an auth method against Cyrus SASL methods.
Definition: sasl.c:136
int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
Wrapper for sasl_client_new()
Definition: sasl.c:606
void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
Set up an SASL connection.
Definition: sasl.c:741
static sasl_secret_t * SecretPtr
SASL secret, to store the password.
Definition: sasl.c:129
SASL authentication support.
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:36
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:55
int(* poll)(struct Connection *conn, time_t wait_secs)
Definition: connection.h:105
int(* write)(struct Connection *conn, const char *buf, size_t count)
Definition: connection.h:92
unsigned int ssf
Security strength factor, in bits (see notes)
Definition: connection.h:50
int(* close)(struct Connection *conn)
Definition: connection.h:116
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:49
int(* open)(struct Connection *conn)
Definition: connection.h:66
int fd
Socket file descriptor.
Definition: connection.h:53
int(* read)(struct Connection *conn, char *buf, size_t count)
Definition: connection.h:79
SASL authentication API -.
Definition: sasl.c:65
void * sockdata
Underlying socket data.
Definition: sasl.c:75
unsigned int blen
Size of the read buffer.
Definition: sasl.c:72
unsigned int bpos
Current read position.
Definition: sasl.c:73
const sasl_ssf_t * ssf
Definition: sasl.c:67
const unsigned int * pbufsize
Definition: sasl.c:68
const char * buf
Buffer for data read from the connection.
Definition: sasl.c:71
sasl_conn_t * saslconn
Definition: sasl.c:66