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);
> 

Attachment: signature.asc
Description: Digital signature

Reply via email to