Package: ssmtp
Version: 2.64-5
Severity: wishlist
Tags: patch

The current versions of sSMTP doesn't attempt to validate the server
certificate when using TLS.  Without this, users authenticating over
encrypted connections might unknowingly be sending their
authentication information to a man in the middle.

The attached patch allows the user to configure a set of trusted
authorities which can be used to validate the server (`TLS_CA_File`
and `TLS_CA_Dir`).  If neither configuration option is given, the
current behavious (no validation) is preserved.

The attached patch should be applied after my patch for bug #662959
(http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=662959).

Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy
From d4f02531856d842cea082cd22babe9cf7e78003e Mon Sep 17 00:00:00 2001
From: W. Trevor King <wk...@drexel.edu>
Date: Wed, 7 Mar 2012 10:12:43 -0500
Subject: [PATCH 3/3] Validate the server certificate when using TLS.

---
 TLS          |    7 +++++--
 ssmtp.c      |   45 +++++++++++++++++++++++++++++++++++++++++----
 ssmtp.conf.5 |    6 ++++++
 3 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/TLS b/TLS
index 74404a3..844bbd8 100644
--- a/TLS
+++ b/TLS
@@ -30,5 +30,8 @@ TLSKey=<file>
 Specify which key file should be used (can be the same as the
 certificate file).
 
-TODO:
-* Check server certificate for changes and notify about it.
+TLS_CA_File=<file>
+Optional file of trusted certificates for validating the server.
+
+TLS_CA_Dir=<file>
+Optional directory of trusted certificates for validating the server.
diff --git a/ssmtp.c b/ssmtp.c
index c491cd4..85f5950 100644
--- a/ssmtp.c
+++ b/ssmtp.c
@@ -69,6 +69,8 @@ char *prog = (char)NULL;
 char *root = NULL;
 char *tls_cert = "/etc/ssl/certs/ssmtp.pem";   /* Default Certificate */
 char *tls_key = "/etc/ssl/certs/ssmtp.pem";    /* Default private key */
+char *tls_ca_file = NULL;      /* Trusted Certificate file */
+char *tls_ca_dir = NULL;       /* Trusted Certificate directory */
 char *uad = (char)NULL;
 char *config_file = (char)NULL;                /* alternate configuration file 
*/
 
@@ -1043,6 +1045,24 @@ bool_t read_config()
                                        log_event(LOG_INFO, "Set 
TLSKey=\"%s\"", tls_key);
                                }
                        }
+                       else if(strcasecmp(p, "TLS_CA_File") == 0) {
+                               if((tls_ca_file = strdup(q)) == (char *)NULL) {
+                                       die("parse_config() -- strdup() 
failed");
+                               }
+
+                               if(log_level > 0) {
+                                       log_event(LOG_INFO, "Set 
TLS_CA_File=\"%s\"\n", tls_ca_file);
+                               }
+                       }
+                       else if(strcasecmp(p, "TLS_CA_Dir") == 0) {
+                               if((tls_ca_dir = strdup(q)) == (char *)NULL) {
+                                       die("parse_config() -- strdup() 
failed");
+                               }
+
+                               if(log_level > 0) {
+                                       log_event(LOG_INFO, "Set 
TLS_CA_Dir=\"%s\"\n", tls_ca_dir);
+                               }
+                       }
 #endif
                        /* Command-line overrides these */
                        else if(strcasecmp(p, "AuthUser") == 0 && !auth_user) {
@@ -1126,6 +1146,8 @@ int smtp_open(char *host, int port)
 
 #ifdef HAVE_SSL
        int err;
+       long lerr;
+       unsigned long ulerr;
        char buf[(BUF_SZ + 1)];
 
        /* Init SSL stuff */
@@ -1157,6 +1179,17 @@ int smtp_open(char *host, int port)
                        log_event(LOG_ERR, "Private key does not match the 
certificate public key");
                        return(-1);
                }
+
+               if (tls_ca_file || tls_ca_dir) {
+                       if(!SSL_CTX_load_verify_locations(ctx, tls_ca_file, 
tls_ca_dir)) {
+                               ulerr = ERR_get_error();
+                               log_event(LOG_ERR, "Error setting verify 
location: %s",
+                                                                       
ERR_reason_error_string(ulerr));
+                               return(-1);
+                       }
+               }
+
+               SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
        }
 #endif
 
@@ -1261,14 +1294,20 @@ int smtp_open(char *host, int port)
 
                ssl = SSL_new(ctx);
                if(!ssl) {
-                       log_event(LOG_ERR, "SSL not working");
+                       ulerr = ERR_get_error();
+                       log_event(LOG_ERR, "SSL not working: %s",
+                                 ERR_reason_error_string(ulerr));
                        return(-1);
                }
                SSL_set_fd(ssl, s);
 
                err = SSL_connect(ssl);
                if(err < 0) { 
-                       perror("SSL_connect");
+                       ulerr = ERR_get_error();
+                       lerr = SSL_get_verify_result(ssl);
+                       log_event(LOG_ERR, "SSL not working: %s (%ld)",
+                                 ERR_reason_error_string(ulerr), lerr);
+
                        return(-1);
                }
 
@@ -1282,8 +1321,6 @@ int smtp_open(char *host, int port)
                        return(-1);
                }
                X509_free(server_cert);
-
-               /* TODO: Check server cert if changed! */
        }
 #endif
 
diff --git a/ssmtp.conf.5 b/ssmtp.conf.5
index d80a24a..d8479bc 100644
--- a/ssmtp.conf.5
+++ b/ssmtp.conf.5
@@ -57,6 +57,12 @@ The file name of an RSA certificate to use for TLS, if 
required.
 .It Cm TLSKey
 The file name of an RSA key to use for TLS, if required.
 .Pp
+.It Cm TLS_CA_File
+A file of trusted certificates for validating the server, if required.
+.Pp
+.It Cm TLS_CA_Dir
+A directory of trusted certificates for validating the server, if required.
+.Pp
 .It Cm AuthUser
 The user name to use for SMTP AUTH.
 The default is blank, in which case SMTP AUTH is not used.
-- 
1.7.3.4

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to