Package: ssmtp Version: 2.62-1 Tags: patch Owner Andrew Wansink <[EMAIL PROTECTED]>
On Fri, Apr 11, 2008 at 11:58:33PM +1000, Andrew Wansink wrote: >Hi, I've done a bit of work to incorporate SASL into sSMTP so that >I can authenticate with our mail servers. This will allow many >different authentication methods to work without any further code >updates. > >I'm sending this to you using the SASL patched sSMTP program >doing DIGEST-MD5 authentication. > >Attached is the patch which implements SASL. > >Andrew Wansink >--- ssmtp-2.61/configure.in 2004-07-23 14:40:29.000000000 +1000 >+++ ssmtp-2.61.sasl/configure.in 2008-04-11 09:47:59.000000000 +1000 >@@ -52,7 +52,15 @@ > [ --enable-ssl support for secure connection to mail server]) > if test x$enableval = xyes ; then > AC_DEFINE(HAVE_SSL) >- LIBS="$LIBS -lssl" >+ LIBS="$LIBS -lssl -lcrypto" >+fi >+enableval="" >+ >+AC_ARG_ENABLE(sasl, >+[ --enable-sasl support for SASL authentication]) >+if test x$enableval = xyes ; then >+ AC_DEFINE(HAVE_SASL) >+ LIBS="$LIBS -lsasl2" > fi > enableval="" > >@@ -63,6 +71,12 @@ > fi > enableval="" > >+AC_ARG_ENABLE(debug, [ --enable-debug debug mode]) >+if test x$enablevar = xyes ; then >+ AC_DEFINE(DEBUG) >+fi >+enablevar="" >+ > AC_ARG_ENABLE(md5auth, > [ --enable-md5auth support for MD5 authentication]) > if test x$enableval = xyes ; then >--- ssmtp-2.61/ssmtp.c 2004-07-23 15:58:48.000000000 +1000 >+++ ssmtp-2.61.sasl/ssmtp.c 2008-04-11 23:16:56.000000000 +1000 >@@ -14,6 +14,7 @@ > */ > #define VERSION "2.60.4" > >+#include <sys/types.h> > #include <sys/socket.h> > #include <netinet/in.h> > #include <sys/param.h> >@@ -38,6 +39,10 @@ > #endif > #include "ssmtp.h" > >+#ifdef HAVE_SASL >+#include <sasl/sasl.h> >+#include <sasl/saslutil.h> >+#endif > > bool_t have_date = False; > bool_t have_from = False; >@@ -71,6 +76,7 @@ > > headers_t headers, *ht; > >+#define DEBUG > #ifdef DEBUG > int log_level = 1; > #else >@@ -606,12 +612,13 @@ > > memset (secret,0,sizeof(secret)); > memset (challenge,0,sizeof(challenge)); >- strncpy (secret, password, sizeof(secret)); >+ strncpy ((char *) secret, password, sizeof(secret)); > if (!challengeb64 || strlen(challengeb64) > sizeof(challenge) * 3 / 4) > return 0; >- from64tobits(challenge, challengeb64); >+ from64tobits((char *) challenge, challengeb64); > >- hmac_md5(challenge, strlen(challenge), secret, strlen(secret), digest); >+ hmac_md5(challenge, strlen((char *) challenge), secret, >+ strlen((char *) secret), digest); > > for (i = 0; i < MD5_DIGEST_LEN; i++) { > digascii[2 * i] = hextab[digest[i] >> 4]; >@@ -622,10 +629,10 @@ > if (sizeof(response) <= strlen(username) + sizeof(digascii)) > return 0; > >- strncpy (response, username, sizeof(response) - sizeof(digascii) - 2); >- strcat (response, " "); >- strcat (response, digascii); >- to64frombits(responseb64, response, strlen(response)); >+ strncpy ((char *) response, username, sizeof(response) - >sizeof(digascii) - 2); >+ strcat ((char *) response, " "); >+ strcat ((char *) response, (char *) digascii); >+ to64frombits((unsigned char *) responseb64, response, strlen((char *) >response)); > > return 1; > } >@@ -1193,6 +1200,10 @@ > if(fd_gets(response, BUF_SZ, fd) == NULL) { > return(0); > } >+ >+ if (strstr(response, "AUTH")) { >+ auth_method = strdup(&response[9]); >+ } > } > while(response[3] == '-'); > >@@ -1255,6 +1266,61 @@ > (void)fd_puts(fd, buf, strlen(buf)); > } > >+#ifdef HAVE_SASL >+int use_context(void *context, int id, const char **result, >+ unsigned *len) >+{ >+ if (log_level) { >+ log_event(LOG_INFO, "use_context: id %d", id); >+ } >+ >+ if (id != SASL_CB_USER && id != SASL_CB_AUTHNAME) { >+ return SASL_BADPARAM; >+ } >+ >+ *result = NULL; >+ >+ if (context) { >+ *result = strdup(context); >+ } >+ >+ if (len) *len = strlen(*result); >+ >+ if (log_level) { >+ log_event(LOG_INFO, "use_context: %s %d%s", *result, len ? *len >: 0, >+ len ? "" : " (null)"); >+ } >+ >+ return SASL_OK; >+} >+ >+static int get_realm(void *context, int id, >+ const char **availrealms __attribute__((unused)), >+ const char **result) >+{ >+ log_event(LOG_INFO, "get_realm"); >+ *result = strdup(context); >+ return SASL_OK; >+} >+ >+static int get_secret(sasl_conn_t *conn, void *context >__attribute__((unused)), >+ int id, sasl_secret_t **psecret) >+{ >+ unsigned int len = (unsigned) strlen(auth_pass); >+ >+ log_event(LOG_INFO, "get_secret"); >+ *psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len); >+ (*psecret)->len = len; >+ strcpy((char *) (*psecret)->data, auth_pass); >+ >+ if (log_level) { >+ log_event(LOG_INFO, "get_secret: password is '%s'", >(*psecret)->data); >+ } >+ >+ return SASL_OK; >+} >+#endif >+ > /* > handler() -- A "normal" non-portable version of an alarm handler > Alas, setting a flag and returning is not fully > functional in >@@ -1275,9 +1341,10 @@ > int ssmtp(char *argv[]) > { > char buf[(BUF_SZ + 1)], *p, *q; >-#ifdef MD5AUTH >+#if defined MD5AUTH || defined HAVE_SASL > char challenge[(BUF_SZ + 1)]; > #endif >+ > struct passwd *pw; > int i, sock; > uid_t uid; >@@ -1348,7 +1415,93 @@ > > /* Try to log in if username was supplied */ > if(auth_user) { >-#ifdef MD5AUTH >+#ifdef HAVE_SASL >+ sasl_conn_t *pconn; >+ char *mech = NULL, *result, *clientout; >+ int ret, pcount; >+ unsigned int resultlen, clientoutlen; >+ >+ sasl_callback_t cb[] = { >+ { SASL_CB_GETREALM, &get_realm, NULL }, >+ { SASL_CB_USER, &use_context, NULL }, >+ { SASL_CB_AUTHNAME, &use_context, auth_user }, >+ { SASL_CB_PASS, &get_secret, auth_pass }, >+ { SASL_CB_LIST_END, NULL, NULL } >+ }; >+ >+ ret = sasl_client_init(cb); >+ >+ if (ret != SASL_OK) { >+ die("sasl_client_init: SASL init failed %d", ret); >+ } >+ >+ ret = sasl_client_new("smtp", mailhost, NULL, NULL, cb, 0, >&pconn); >+ >+ if (ret != SASL_OK) { >+ die("sasl_client_new: SASL setup failed %d", ret); >+ } >+ >+ if (log_level > 0) { >+ log_event(LOG_INFO, "Server mechanisms '%s' %s", >auth_method, >+ mailhost); >+ } >+ >+ if (log_level) { >+ sasl_listmech(pconn, NULL, "", ",", "", (const char **) >&result, >+ &resultlen, &pcount); >+ >+ log_event(LOG_INFO, "Client mechanisms '%s'", result); >+ } >+ >+ ret = sasl_client_start(pconn, auth_method, NULL, >+ (const char **) &clientout, &clientoutlen, >+ (const char **) &mech); >+ >+ log_event(LOG_INFO, "start client out is '%s' %d", clientout, >clientoutlen); >+ >+ if (ret != SASL_CONTINUE) { >+ die("sasl_client_start: failed %d", ret); >+ } >+ >+ if (log_level) { >+ log_event(LOG_INFO, "Supported mechanism '%s'", mech); >+ } >+ >+ sprintf(buf, "AUTH %s", mech); >+ >+ do { >+ char buf_decode[1024]; >+ int blen; >+ >+ smtp_write(sock, "%s", buf); >+ smtp_read(sock, buf); >+ >+ sasl_decode64(&buf[4], strlen(buf) - 4, buf_decode, >+ sizeof(buf_decode), (unsigned *) &blen); >+ >+ if (log_level) { >+ log_event(LOG_INFO, "decoded '%s' (%d)", >buf_decode, blen); >+ } >+ >+ ret = sasl_client_step(pconn, buf_decode, blen, >+ NULL, (const char **) &clientout, >&clientoutlen); >+ >+ if (log_level) { >+ log_event(LOG_INFO, "response '%s'", clientout); >+ } >+ >+ sasl_encode64(clientout, clientoutlen, buf, sizeof(buf), >+ (unsigned *) &blen); >+ } while (ret == SASL_CONTINUE); >+ >+ if (ret != SASL_OK) { >+ die("SASL failed"); >+ } >+ >+ goto authorised; >+ >+#elif defined MD5AUTH >+ > if(auth_pass == (char *)NULL) { > auth_pass = strdup(""); > } >@@ -1364,11 +1517,13 @@ > > memset(buf, 0, sizeof(buf)); > crammd5(challenge, auth_user, auth_pass, buf); >+ >+ goto authorised; > } >- else { > #endif > memset(buf, 0, sizeof(buf)); >- to64frombits(buf, auth_user, strlen(auth_user)); >+ to64frombits((unsigned char *) buf, (unsigned char *) auth_user, >+ strlen(auth_user)); > smtp_write(sock, "AUTH LOGIN %s", buf); > > (void)alarm((unsigned) MEDWAIT); >@@ -1377,10 +1532,11 @@ > } > memset(buf, 0, sizeof(buf)); > >- to64frombits(buf, auth_pass, strlen(auth_pass)); >-#ifdef MD5AUTH >- } >-#endif >+ to64frombits((unsigned char *) buf, (unsigned char *) auth_pass, >+ strlen(auth_pass)); >+ >+authorised: >+ > smtp_write(sock, "%s", buf); > (void)alarm((unsigned) MEDWAIT); >
signature.asc
Description: Digital signature