])
AM_CONDITIONAL(USE_SASL, test x$need_sasl = xyes)
+AC_ARG_WITH(sasl2, [ --with-sasl2[=PFX] Use Cyrus SASL library version 2 for POP/IMAP authentication],
+ [
+ if test "$need_socket" != "yes"
+ then
+ AC_MSG_ERROR([SASL support is only useful with POP or IMAP support])
+ fi
+
+ if test "$with_sasl2" != "no"
+ then
+ if test "$with_sasl2" != "yes"
+ then
+ CPPFLAGS="$CPPFLAGS -I$with_sasl2/include"
+ LDFLAGS="$LDFLAGS -L$with_sasl2/lib"
+ fi
+
+ saved_LIBS="$LIBS"
+
+ AC_CHECK_LIB(sasl2, sasl_client_init,,
+ AC_MSG_ERROR([could not find libsasl]),)
+
+ MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS mutt_sasl.o"
+ MUTTLIBS="$MUTTLIBS -lsasl2"
+ LIBS="$saved_LIBS"
+ AC_DEFINE(USE_SASL,1,
+ [ Define if want to use the Cyrus SASL library for POP/IMAP authentication. ])
+ AC_DEFINE(USE_SASL2,1,
+ [ Define if want to use version 2 of the Cyrus SASL library. ])
+ need_sasl=yes
+ need_md5=no
+ fi
+ ])
+AM_CONDITIONAL(USE_SASL, test x$need_sasl = xyes)
+
+AC_ARG_WITH(sasl2, [ --with-sasl2[=PFX] Use Cyrus SASL library version 2 for POP/IMAP authentication],
+ [
+ if test "$need_socket" != "yes"
+ then
+ AC_MSG_ERROR([SASL support is only useful with POP or IMAP support])
+ fi
+
+ if test "$with_sasl2" != "no"
+ then
+ if test "$with_sasl2" != "yes"
+ then
+ CPPFLAGS="$CPPFLAGS -I$with_sasl2/include"
+ LDFLAGS="$LDFLAGS -L$with_sasl2/lib"
+ fi
+
+ saved_LIBS="$LIBS"
+
+ AC_CHECK_LIB(sasl2, sasl_client_init,,
+ AC_MSG_ERROR([could not find libsasl]),)
+
+ MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS mutt_sasl.o"
+ MUTTLIBS="$MUTTLIBS -lsasl2"
+ LIBS="$saved_LIBS"
+ AC_DEFINE(USE_SASL,1,
+ [ Define if want to use the Cyrus SASL library for POP/IMAP authentication. ])
+ AC_DEFINE(USE_SASL2,1,
+ [ Define if want to use version 2 of the Cyrus SASL library. ])
+ need_sasl=yes
+ need_md5=no
+ fi
+ ])
+AM_CONDITIONAL(USE_SASL, test x$need_sasl = xyes)
+
if test "$need_md5" = "yes"
then
MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS md5c.o"
#include "imap_private.h"
#include "auth.h"
+#ifdef USE_SASL2
+#include <sasl/sasl.h>
+#include <sasl/saslutil.h>
+#else
#include <sasl.h>
#include <saslutil.h>
+#endif
/* imap_auth_sasl: Default authenticator if available. */
imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata, const char* method)
int rc, irc;
char buf[LONG_STRING];
const char* mech;
+#ifdef USE_SASL2
+ const char *pc = NULL;
+#else
char* pc = NULL;
+#endif
unsigned int len, olen;
unsigned char client_start;
if (mutt_bit_isset (idata->capabilities, AUTH_ANON) &&
(!idata->conn->account.user[0] ||
!ascii_strncmp (idata->conn->account.user, "anonymous", 9)))
+#ifdef USE_SASL2
+ rc = sasl_client_start (saslconn, "AUTH=ANONYMOUS", NULL, &pc, &olen,
+ &mech);
+#else
rc = sasl_client_start (saslconn, "AUTH=ANONYMOUS", NULL, NULL, &pc, &olen,
&mech);
+#endif
}
if (rc != SASL_OK && rc != SASL_CONTINUE)
do
{
+#ifdef USE_SASL2
+ rc = sasl_client_start (saslconn, method, &interaction,
+ &pc, &olen, &mech);
+#else
rc = sasl_client_start (saslconn, method, NULL, &interaction,
&pc, &olen, &mech);
+#endif
if (rc == SASL_INTERACT)
mutt_sasl_interact (interaction);
}
if (irc == IMAP_CMD_RESPOND)
{
+#ifdef USE_SASL2
+ if (sasl_decode64 (idata->cmd.buf+2, strlen (idata->cmd.buf+2), buf, LONG_STRING-1,
+#else
if (sasl_decode64 (idata->cmd.buf+2, strlen (idata->cmd.buf+2), buf,
+#endif
&len) != SASL_OK)
{
dprint (1, (debugfile, "imap_auth_sasl: error base64-decoding server response.\n"));
/* sasl_client_st(art|ep) allocate pc with malloc, expect me to
* free it */
+#ifndef USE_SASL2
FREE (&pc);
+#endif
}
if (olen || rc == SASL_CONTINUE)
#include "mutt_sasl.h"
#include "mutt_socket.h"
+#ifdef USE_SASL2
+#include <netdb.h>
+#include <sasl/sasl.h>
+#else
#include <sasl.h>
+#endif
#include <sys/socket.h>
#include <netinet/in.h>
* a protection buffer. */
#define M_SASL_MAXBUF 65536
+#ifdef USE_SASL2
+#define IP_PORT_BUFLEN 1024
+#endif
+
static sasl_callback_t mutt_sasl_callbacks[5];
static int mutt_sasl_start (void);
static int mutt_sasl_conn_write (CONNECTION* conn, const char* buf,
size_t count);
+#ifdef USE_SASL2
+/* utility function, stolen from sasl2 sample code */
+static int iptostring(const struct sockaddr *addr, socklen_t addrlen,
+ char *out, unsigned outlen) {
+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
+
+ if(!addr || !out) return SASL_BADPARAM;
+
+ getnameinfo(addr, addrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
+ NI_NUMERICHOST | NI_WITHSCOPEID | NI_NUMERICSERV);
+
+ if(outlen < strlen(hbuf) + strlen(pbuf) + 2)
+ return SASL_BUFOVER;
+
+ snprintf(out, outlen, "%s;%s", hbuf, pbuf);
+
+ return SASL_OK;
+}
+#endif
+
/* mutt_sasl_start: called before doing a SASL exchange - initialises library
* (if neccessary). */
int mutt_sasl_start (void)
int mutt_sasl_client_new (CONNECTION* conn, sasl_conn_t** saslconn)
{
sasl_security_properties_t secprops;
+#ifdef USE_SASL2
+ struct sockaddr local, remote;
+ socklen_t size;
+ char iplocalport[IP_PORT_BUFLEN], ipremoteport[IP_PORT_BUFLEN];
+#else
sasl_external_properties_t extprops;
+#endif
const char* service;
int rc;
dprint (1, (debugfile, "mutt_sasl_client_new: account type unset\n"));
return -1;
}
+
+#ifdef USE_SASL2
+ size = sizeof (local);
+ if (getsockname (conn->fd, &local, &size)){
+ dprint (1, (debugfile, "mutt_sasl_client_new: getsockname for local failed\n"));
+ return -1;
+ }
+ else
+ if (iptostring(&local, size, iplocalport, IP_PORT_BUFLEN) != SASL_OK){
+ dprint (1, (debugfile, "mutt_sasl_client_new: iptostring for local failed\n"));
+ return -1;
+ }
+ size = sizeof (remote);
+ if (getpeername (conn->fd, &remote, &size)){
+ dprint (1, (debugfile, "mutt_sasl_client_new: getsockname for remote failed\n"));
+ return -1;
+ }
+ else
+ if (iptostring(&remote, size, ipremoteport, IP_PORT_BUFLEN) != SASL_OK){
+ dprint (1, (debugfile, "mutt_sasl_client_new: iptostring for remote failed\n"));
+ return -1;
+ }
+
+dprint(1,(debugfile, "local ip: %s, remote ip:%s\n", iplocalport, ipremoteport));
+
+ rc = sasl_client_new (service, conn->account.host, iplocalport, ipremoteport,
+ mutt_sasl_get_callbacks (&conn->account), 0, saslconn);
+
+#else
rc = sasl_client_new (service, conn->account.host,
mutt_sasl_get_callbacks (&conn->account), SASL_SECURITY_LAYER, saslconn);
-
+#endif
+
if (rc != SASL_OK)
{
dprint (1, (debugfile,
/* Do we need to fail if this fails? I would assume having these unset
* would just disable KRB4. Who wrote this code? I'm not sure how this
* interacts with the NSS code either, since that mucks with the fd. */
+#ifndef USE_SASL2 /* with SASLv2 this all happens in sasl_client_new */
{
struct sockaddr_in local, remote;
socklen_t size;
}
#endif
}
+#endif
/* set security properties. We use NOPLAINTEXT globally, since we can
* just fall back to LOGIN in the IMAP case anyway. If that doesn't
#if defined(USE_SSL) && !defined(USE_NSS)
if (conn->account.flags & M_ACCT_SSL)
{
+#ifdef USE_SASL2 /* I'm not sure this actually has an effect, at least with SASLv2 */
+ dprint (2, (debugfile, "External SSF: %d\n", conn->ssf));
+ if (sasl_setprop (*saslconn, SASL_SSF_EXTERNAL, &(conn->ssf)) != SASL_OK)
+#else
memset (&extprops, 0, sizeof (extprops));
extprops.ssf = conn->ssf;
dprint (2, (debugfile, "External SSF: %d\n", extprops.ssf));
if (sasl_setprop (*saslconn, SASL_SSF_EXTERNAL, &extprops) != SASL_OK)
+#endif
{
dprint (1, (debugfile, "mutt_sasl_client_new: Error setting external properties\n"));
return -1;
}
+#ifdef USE_SASL2
+ dprint (2, (debugfile, "External authentication name: %s\n","NULL"));
+ if (sasl_setprop (*saslconn, SASL_AUTH_EXTERNAL, NULL) != SASL_OK)
+ {
+ dprint (1, (debugfile, "mutt_sasl_client_new: Error setting external properties\n"));
+ return -1;
+ }
+#endif
}
#endif
sasldata->saslconn = saslconn;
/* get ssf so we know whether we have to (en|de)code read/write */
+#ifdef USE_SASL2
+ sasl_getprop (saslconn, SASL_SSF, (const void**) &sasldata->ssf);
+#else
sasl_getprop (saslconn, SASL_SSF, (void**) &sasldata->ssf);
+#endif
dprint (3, (debugfile, "SASL protection strength: %u\n", *sasldata->ssf));
/* Add SASL SSF to transport SSF */
conn->ssf += *sasldata->ssf;
+#ifdef USE_SASL2
+ sasl_getprop (saslconn, SASL_MAXOUTBUF, (const void**) &sasldata->pbufsize);
+#else
sasl_getprop (saslconn, SASL_MAXOUTBUF, (void**) &sasldata->pbufsize);
+#endif
dprint (3, (debugfile, "SASL protection buffer size: %u\n", *sasldata->pbufsize));
/* clear input buffer */
/* release sasl resources */
sasl_dispose (&sasldata->saslconn);
+#ifndef USE_SASL2
FREE (&sasldata->buf);
+#endif
FREE (&sasldata);
/* call underlying close */
conn->sockdata = sasldata->sockdata;
+#ifndef USE_SASL2
FREE (&sasldata->buf);
+#endif
sasldata->bpos = 0;
sasldata->blen = 0;
SASL_DATA* sasldata;
int rc;
+#ifdef USE_SASL2
+ const char *pbuf;
+#else
char* pbuf;
+#endif
unsigned int olen, plen;
sasldata = (SASL_DATA*) conn->sockdata;
}
rc = (sasldata->write) (conn, pbuf, plen);
+#ifndef USE_SASL2
FREE (&pbuf);
+#endif
if (rc != plen)
goto fail;