NeoMutt  2023-11-03-85-g512e01
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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 "editor/lib.h"
55#include "history/lib.h"
56#include "connaccount.h"
57#include "connection.h"
58#include "globals.h"
59
64{
65 sasl_conn_t *saslconn;
66 const sasl_ssf_t *ssf;
67 const unsigned int *pbufsize;
68
69 /* read buffer */
70 const char *buf;
71 unsigned int blen;
72 unsigned int bpos;
73
74 void *sockdata;
75
79 int (*open)(struct Connection *conn);
80
84 int (*read)(struct Connection *conn, char *buf, size_t count);
85
89 int (*write)(struct Connection *conn, const char *buf, size_t count);
90
94 int (*poll)(struct Connection *conn, time_t wait_secs);
95
99 int (*close)(struct Connection *conn);
100};
101
105static const char *const SaslAuthenticators[] = {
106 "ANONYMOUS", "CRAM-MD5", "DIGEST-MD5", "EXTERNAL",
107 "GS2-IAKERB", "GS2-KRB5", "GSS-SPNEGO", "GSSAPI",
108 "LOGIN", "NTLM", "OTP-MD4", "OTP-MD5",
109 "OTP-SHA1", "PASSDSS-3DES-1", "PLAIN", "SCRAM-SHA-1",
110 "SCRAM-SHA-224", "SCRAM-SHA-256", "SCRAM-SHA-384", "SCRAM-SHA-512",
111 "SRP",
112};
113
114/* arbitrary. SASL will probably use a smaller buffer anyway. OTOH it's
115 * been a while since I've had access to an SASL server which negotiated
116 * a protection buffer. */
117#define MUTT_SASL_MAXBUF 65536
118
119/* used to hold a string "host;port"
120 * where host is size NI_MAXHOST-1 and port is size NI_MAXSERV-1
121 * plus two bytes for the ';' and trailing \0 */
122#define IP_PORT_BUFLEN (NI_MAXHOST + NI_MAXSERV)
123
125static sasl_callback_t MuttSaslCallbacks[5];
126
128static sasl_secret_t *SecretPtr = NULL;
129
135bool sasl_auth_validator(const char *authenticator)
136{
137 for (size_t i = 0; i < mutt_array_size(SaslAuthenticators); i++)
138 {
139 const char *auth = SaslAuthenticators[i];
140 if (mutt_istr_equal(auth, authenticator))
141 return true;
142 }
143
144 return false;
145}
146
152static int getnameinfo_err(int rc)
153{
154 int err;
155 mutt_debug(LL_DEBUG1, "getnameinfo: ");
156 switch (rc)
157 {
158 case EAI_AGAIN:
159 mutt_debug(LL_DEBUG1, "The name could not be resolved at this time. Future attempts may succeed\n");
160 err = SASL_TRYAGAIN;
161 break;
162 case EAI_BADFLAGS:
163 mutt_debug(LL_DEBUG1, "The flags had an invalid value\n");
164 err = SASL_BADPARAM;
165 break;
166 case EAI_FAIL:
167 mutt_debug(LL_DEBUG1, "A non-recoverable error occurred\n");
168 err = SASL_FAIL;
169 break;
170 case EAI_FAMILY:
171 mutt_debug(LL_DEBUG1, "The address family was not recognized or the address length was invalid for the specified family\n");
172 err = SASL_BADPROT;
173 break;
174 case EAI_MEMORY:
175 mutt_debug(LL_DEBUG1, "There was a memory allocation failure\n");
176 err = SASL_NOMEM;
177 break;
178 case EAI_NONAME:
179 mutt_debug(LL_DEBUG1, "The name does not resolve for the supplied parameters. "
180 "NI_NAMEREQD is set and the host's name can't be located, or both nodename and servname were null.\n");
181 err = SASL_FAIL; /* no real equivalent */
182 break;
183 case EAI_SYSTEM:
184 mutt_debug(LL_DEBUG1, "A system error occurred. The error code can be found in 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", rc);
190 err = SASL_FAIL; /* no real equivalent */
191 break;
192 }
193 return err;
194}
195
206static 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 rc;
211
212 if (!addr || !out)
213 return SASL_BADPARAM;
214
215 rc = 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 (rc != 0)
222 return getnameinfo_err(rc);
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
239static 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
276static 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))(intptr_t) 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
316static 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
360static 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(&SecretPtr, sizeof(sasl_secret_t) + len);
376 memcpy((char *) SecretPtr->data, cac->pass, (size_t) len);
377 SecretPtr->len = len;
378 *psecret = SecretPtr;
379
380 return SASL_OK;
381}
382
388static 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))(intptr_t) mutt_sasl_cb_authname;
394 callback->context = cac;
395 callback++;
396
397 callback->id = SASL_CB_AUTHNAME;
398 callback->proc = (int (*)(void))(intptr_t) mutt_sasl_cb_authname;
399 callback->context = cac;
400 callback++;
401
402 callback->id = SASL_CB_PASS;
403 callback->proc = (int (*)(void))(intptr_t) 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
426static 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
442static 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
467static 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 {
521 rc = sasldata->read(conn, buf, count);
522 }
523
524out:
525 conn->sockdata = sasldata;
526
527 return rc;
528}
529
533static int mutt_sasl_conn_write(struct Connection *conn, const char *buf, size_t count)
534{
535 int rc;
536 const char *pbuf = NULL;
537 unsigned int olen, plen;
538
539 struct SaslSockData *sasldata = conn->sockdata;
540 conn->sockdata = sasldata->sockdata;
541
542 /* encode data, if necessary */
543 if (*sasldata->ssf != 0)
544 {
545 /* handle data larger than MAXOUTBUF */
546 do
547 {
548 olen = (count > *sasldata->pbufsize) ? *sasldata->pbufsize : count;
549
550 rc = sasl_encode(sasldata->saslconn, buf, olen, &pbuf, &plen);
551 if (rc != SASL_OK)
552 {
553 mutt_debug(LL_DEBUG1, "SASL encoding failed: %s\n", sasl_errstring(rc, NULL, NULL));
554 goto fail;
555 }
556
557 rc = sasldata->write(conn, pbuf, plen);
558 if (rc != plen)
559 goto fail;
560
561 count -= olen;
562 buf += olen;
563 } while (count > *sasldata->pbufsize);
564 }
565 else
566 {
567 /* just write using the underlying socket function */
568 rc = sasldata->write(conn, buf, count);
569 }
570
571 conn->sockdata = sasldata;
572
573 return rc;
574
575fail:
576 conn->sockdata = sasldata;
577 return -1;
578}
579
583static int mutt_sasl_conn_poll(struct Connection *conn, time_t wait_secs)
584{
585 struct SaslSockData *sasldata = conn->sockdata;
586 int rc;
587
588 conn->sockdata = sasldata->sockdata;
589 rc = sasldata->poll(conn, wait_secs);
590 conn->sockdata = sasldata;
591
592 return rc;
593}
594
605int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
606{
607 if (mutt_sasl_start() != SASL_OK)
608 return -1;
609
610 if (!conn->account.service)
611 {
612 mutt_error(_("Unknown SASL profile"));
613 return -1;
614 }
615
616 socklen_t size;
617
618 struct sockaddr_storage local = { 0 };
619 char iplocalport[IP_PORT_BUFLEN] = { 0 };
620 char *plp = NULL;
621 size = sizeof(local);
622 if (getsockname(conn->fd, (struct sockaddr *) &local, &size) == 0)
623 {
624 if (iptostring((struct sockaddr *) &local, size, iplocalport, IP_PORT_BUFLEN) == SASL_OK)
625 plp = iplocalport;
626 else
627 mutt_debug(LL_DEBUG2, "SASL failed to parse local IP address\n");
628 }
629 else
630 {
631 mutt_debug(LL_DEBUG2, "SASL failed to get local IP address\n");
632 }
633
634 struct sockaddr_storage remote = { 0 };
635 char ipremoteport[IP_PORT_BUFLEN] = { 0 };
636 char *prp = NULL;
637 size = sizeof(remote);
638 if (getpeername(conn->fd, (struct sockaddr *) &remote, &size) == 0)
639 {
640 if (iptostring((struct sockaddr *) &remote, size, ipremoteport, IP_PORT_BUFLEN) == SASL_OK)
641 prp = ipremoteport;
642 else
643 mutt_debug(LL_DEBUG2, "SASL failed to parse remote IP address\n");
644 }
645 else
646 {
647 mutt_debug(LL_DEBUG2, "SASL failed to get remote IP address\n");
648 }
649
650 mutt_debug(LL_DEBUG2, "SASL local ip: %s, remote ip:%s\n", NONULL(plp), NONULL(prp));
651
652 int rc = sasl_client_new(conn->account.service, conn->account.host, plp, prp,
653 mutt_sasl_get_callbacks(&conn->account), 0, saslconn);
654 if (rc != SASL_OK)
655 {
656 mutt_error(_("Error allocating SASL connection"));
657 return -1;
658 }
659
660 /* Work around a casting bug in the SASL krb4 module */
661 sasl_security_properties_t secprops = { 0 };
662 secprops.max_ssf = 0x7fff;
663 secprops.maxbufsize = MUTT_SASL_MAXBUF;
664 if (sasl_setprop(*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
665 {
666 mutt_error(_("Error setting SASL security properties"));
667 sasl_dispose(saslconn);
668 return -1;
669 }
670
671 if (conn->ssf != 0)
672 {
673 /* I'm not sure this actually has an effect, at least with SASLv2 */
674 mutt_debug(LL_DEBUG2, "External SSF: %d\n", conn->ssf);
675 if (sasl_setprop(*saslconn, SASL_SSF_EXTERNAL, &conn->ssf) != SASL_OK)
676 {
677 mutt_error(_("Error setting SASL external security strength"));
678 sasl_dispose(saslconn);
679 return -1;
680 }
681 }
682 if (conn->account.user[0])
683 {
684 mutt_debug(LL_DEBUG2, "External authentication name: %s\n", conn->account.user);
685 if (sasl_setprop(*saslconn, SASL_AUTH_EXTERNAL, conn->account.user) != SASL_OK)
686 {
687 mutt_error(_("Error setting SASL external user name"));
688 sasl_dispose(saslconn);
689 return -1;
690 }
691 }
692
693 return 0;
694}
695
703int mutt_sasl_interact(sasl_interact_t *interaction)
704{
705 int rc = SASL_OK;
706 char prompt[128] = { 0 };
707 struct Buffer *resp = buf_pool_get();
708
709 while (interaction->id != SASL_CB_LIST_END)
710 {
711 mutt_debug(LL_DEBUG2, "filling in SASL interaction %ld\n", interaction->id);
712
713 snprintf(prompt, sizeof(prompt), "%s: ", interaction->prompt);
714 buf_reset(resp);
715
716 if (OptNoCurses ||
717 (mw_get_field(prompt, resp, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0))
718 {
719 rc = SASL_FAIL;
720 break;
721 }
722
723 interaction->len = buf_len(resp) + 1;
724 interaction->result = buf_strdup(resp);
725 interaction++;
726 }
727
728 buf_pool_release(&resp);
729 return rc;
730}
731
740void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
741{
742 struct SaslSockData *sasldata = mutt_mem_malloc(sizeof(struct SaslSockData));
743 /* work around sasl_getprop aliasing issues */
744 const void *tmp = NULL;
745
746 sasldata->saslconn = saslconn;
747 /* get ssf so we know whether we have to (en|de)code read/write */
748 sasl_getprop(saslconn, SASL_SSF, &tmp);
749 sasldata->ssf = tmp;
750 mutt_debug(LL_DEBUG3, "SASL protection strength: %u\n", *sasldata->ssf);
751 /* Add SASL SSF to transport SSF */
752 conn->ssf += *sasldata->ssf;
753 sasl_getprop(saslconn, SASL_MAXOUTBUF, &tmp);
754 sasldata->pbufsize = tmp;
755 mutt_debug(LL_DEBUG3, "SASL protection buffer size: %u\n", *sasldata->pbufsize);
756
757 /* clear input buffer */
758 sasldata->buf = NULL;
759 sasldata->bpos = 0;
760 sasldata->blen = 0;
761
762 /* preserve old functions */
763 sasldata->sockdata = conn->sockdata;
764 sasldata->open = conn->open;
765 sasldata->read = conn->read;
766 sasldata->write = conn->write;
767 sasldata->poll = conn->poll;
768 sasldata->close = conn->close;
769
770 /* and set up new functions */
771 conn->sockdata = sasldata;
777}
778
786{
787 /* As we never use the server-side, the silently ignore the return value */
788 sasl_client_done();
789}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:466
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:542
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:50
int mutt_account_getlogin(struct ConnAccount *cac)
Retrieve login info into ConnAccount, if necessary.
Definition: connaccount.c:99
Connection Credentials.
An open network connection (socket)
Edit a string.
bool OptNoCurses
(pseudo) when sending in batch mode
Definition: globals.c:77
static int mutt_sasl_conn_close(struct Connection *conn)
Close SASL connection - Implements Connection::close() -.
Definition: sasl.c:442
int(* close)(struct Connection *conn)
Close a socket Connection - Implements Connection::close() -.
Definition: sasl.c:99
int(* open)(struct Connection *conn)
Open a socket Connection - Implements Connection::open() -.
Definition: sasl.c:79
static int mutt_sasl_conn_open(struct Connection *conn)
Empty wrapper for underlying open function - Implements Connection::open() -.
Definition: sasl.c:426
int(* poll)(struct Connection *conn, time_t wait_secs)
Check if any data is waiting on a socket - Implements Connection::poll() -.
Definition: sasl.c:94
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:583
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
int(* read)(struct Connection *conn, char *buf, size_t count)
Read from a socket Connection - Implements Connection::read() -.
Definition: sasl.c:84
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:533
int(* write)(struct Connection *conn, const char *buf, size_t count)
Write to a socket Connection - Implements Connection::write() -.
Definition: sasl.c:89
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:275
#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:810
Many unsorted constants and some structs.
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:55
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:360
#define MUTT_SASL_MAXBUF
Definition: sasl.c:117
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
void mutt_sasl_cleanup(void)
Invoke when processing is complete.
Definition: sasl.c:785
#define IP_PORT_BUFLEN
Definition: sasl.c:122
static int getnameinfo_err(int rc)
Convert a getaddrinfo() error code into an SASL error code.
Definition: sasl.c:152
int mutt_sasl_interact(sasl_interact_t *interaction)
Perform an SASL interaction with the user.
Definition: sasl.c:703
static int mutt_sasl_start(void)
Initialise SASL library.
Definition: sasl.c:276
static int mutt_sasl_cb_log(void *context, int priority, const char *message)
Callback to log SASL messages.
Definition: sasl.c:239
static sasl_callback_t * mutt_sasl_get_callbacks(struct ConnAccount *cac)
Get the SASL callback functions.
Definition: sasl.c:388
static const char *const SaslAuthenticators[]
Authenticaion methods supported by Cyrus SASL.
Definition: sasl.c:105
static sasl_callback_t MuttSaslCallbacks[5]
SASL callback functions, e.g. mutt_sasl_cb_authname(), mutt_sasl_cb_pass()
Definition: sasl.c:125
static int iptostring(const struct sockaddr *addr, socklen_t addrlen, char *out, unsigned int outlen)
Convert IP Address to string.
Definition: sasl.c:206
bool sasl_auth_validator(const char *authenticator)
Validate an auth method against Cyrus SASL methods.
Definition: sasl.c:135
int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
Wrapper for sasl_client_new()
Definition: sasl.c:605
void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
Set up an SASL connection.
Definition: sasl.c:740
static sasl_secret_t * SecretPtr
SASL secret, to store the password.
Definition: sasl.c:128
SASL authentication support.
#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:64
void * sockdata
Underlying socket data.
Definition: sasl.c:74
unsigned int blen
Size of the read buffer.
Definition: sasl.c:71
unsigned int bpos
Current read position.
Definition: sasl.c:72
const sasl_ssf_t * ssf
Definition: sasl.c:66
const unsigned int * pbufsize
Definition: sasl.c:67
const char * buf
Buffer for data read from the connection.
Definition: sasl.c:70
sasl_conn_t * saslconn
Definition: sasl.c:65