3131#include <openssl/pem.h>
3232#include <openssl/ssl.h>
3333#include <openssl/err.h>
34+ #include <openssl/x509v3.h>
3435#endif
3536#ifdef MD5AUTH
3637#include "md5auth/hmac_md5.h"
@@ -52,6 +53,9 @@ bool_t use_tls = False; /* Use SSL to transfer mail to HUB */
5253bool_t use_starttls = False ; /* SSL only after STARTTLS (RFC2487) */
5354bool_t use_cert = False ; /* Use a certificate to transfer SSL mail */
5455bool_t use_oldauth = False ; /* use old AUTH LOGIN username style */
56+ bool_t verify_peer = True ; /* Verify peer certificate. */
57+ bool_t verify_peer_name = True ; /* Verify hostname in the certificate match server connected */
58+ bool_t allow_self_signed = True ; /* Accept self signed certificates. */
5559
5660#define ARPADATE_LENGTH 32 /* Current date in RFC format */
5761char arpadate [ARPADATE_LENGTH ];
@@ -68,6 +72,9 @@ char *gecos;
6872char * prog = NULL ;
6973char * root = NULL ;
7074char * tls_cert = "/etc/ssl/certs/ssmtp.pem" ; /* Default Certificate */
75+ char * tls_key = "/etc/ssl/certs/ssmtp.pem" ; /* Default Private Key */
76+ char * tls_ca_file = NULL ; /* Trusted Certificate file */
77+ char * tls_ca_dir = NULL ; /* Trusted Certificate directory */
7178char * uad = NULL ;
7279char * config_file = NULL ; /* alternate configuration file */
7380
@@ -1014,6 +1021,45 @@ bool_t read_config()
10141021 "Set UseSTARTTLS=\"%s\"\n" , use_tls ? "True" : "False" );
10151022 }
10161023 }
1024+ else if (strcasecmp (p , "VerifyPeer ") == 0 ) {
1025+ if (strcasecmp (q , "YES" ) == 0 ) {
1026+ verify_peer = True ;
1027+ }
1028+ else {
1029+ verify_peer = False ;
1030+ }
1031+
1032+ if (log_level > 0 ) {
1033+ log_event (LOG_INFO ,
1034+ "Set VerifyPeer=\"%s\"\n" , verify_peer ? "True" : "False" );
1035+ }
1036+ }
1037+ else if (strcasecmp (p , "VerifyPeerName ") == 0 ) {
1038+ if (strcasecmp (q , "YES" ) == 0 ) {
1039+ verify_peer_name = True ;
1040+ }
1041+ else {
1042+ verify_peer_name = False ;
1043+ }
1044+
1045+ if (log_level > 0 ) {
1046+ log_event (LOG_INFO ,
1047+ "Set VerifyPeerName=\"%s\"\n" , verify_peer_name ? "True" : "False" );
1048+ }
1049+ }
1050+ else if (strcasecmp (p , "AllowSelfSigned ") == 0 ) {
1051+ if (strcasecmp (q , "YES" ) == 0 ) {
1052+ allow_self_signed = True ;
1053+ }
1054+ else {
1055+ allow_self_signed = False ;
1056+ }
1057+
1058+ if (log_level > 0 ) {
1059+ log_event (LOG_INFO ,
1060+ "Set AllowSelfSigned=\"%s\"\n" , allow_self_signed ? "True" : "False" );
1061+ }
1062+ }
10171063 else if (strcasecmp (p , "UseTLSCert ") == 0 ) {
10181064 if (strcasecmp (q , "YES" ) == 0 ) {
10191065 use_cert = True ;
@@ -1037,6 +1083,33 @@ bool_t read_config()
10371083 log_event (LOG_INFO , "Set TLSCert=\"%s\"\n" , tls_cert );
10381084 }
10391085 }
1086+ else if (strcasecmp (p , "TLSKey ") == 0 ) {
1087+ if ((tls_key = strdup (q )) == (char * )NULL ) {
1088+ die ("parse_config() -- strdup() failed" );
1089+ }
1090+
1091+ if (log_level > 0 ) {
1092+ log_event (LOG_INFO , "Set TLSKey=\"%s\"\n" , tls_key );
1093+ }
1094+ }
1095+ else if (strcasecmp (p , "TLS_CA_File ") == 0 ) {
1096+ if ((tls_ca_file = strdup (q )) == (char * )NULL ) {
1097+ die ("parse_config() -- strdup() failed" );
1098+ }
1099+
1100+ if (log_level > 0 ) {
1101+ log_event (LOG_INFO , "Set TLS_CA_File=\"%s\"\n" , tls_ca_file );
1102+ }
1103+ }
1104+ else if (strcasecmp (p , "TLS_CA_Dir ") == 0 ) {
1105+ if ((tls_ca_dir = strdup (q )) == (char * )NULL ) {
1106+ die ("parse_config() -- strdup() failed" );
1107+ }
1108+
1109+ if (log_level > 0 ) {
1110+ log_event (LOG_INFO , "Set TLS_CA_Dir=\"%s\"\n" , tls_ca_dir );
1111+ }
1112+ }
10401113#endif
10411114 /* Command-line overrides these */
10421115 else if (strcasecmp (p , "AuthUser ") == 0 && !auth_user ) {
@@ -1129,29 +1202,66 @@ int smtp_open(char *host, int port)
11291202
11301203 SSL_load_error_strings ();
11311204 SSLeay_add_ssl_algorithms ();
1132- meth = SSLv23_client_method ();
1205+ meth = TLS_client_method ();
11331206 ctx = SSL_CTX_new (meth );
11341207 if (!ctx ) {
11351208 log_event (LOG_ERR , "No SSL support initiated\n" );
1209+ SSL_CTX_free (ctx );
11361210 return (-1 );
11371211 }
11381212
11391213 if (use_cert == True ) {
11401214 if (SSL_CTX_use_certificate_chain_file (ctx , tls_cert ) <= 0 ) {
11411215 perror ("Use certfile" );
1216+ SSL_CTX_free (ctx );
11421217 return (-1 );
11431218 }
11441219
1145- if (SSL_CTX_use_PrivateKey_file (ctx , tls_cert , SSL_FILETYPE_PEM ) <= 0 ) {
1220+ if (SSL_CTX_use_PrivateKey_file (ctx , tls_key , SSL_FILETYPE_PEM ) <= 0 ) {
11461221 perror ("Use PrivateKey" );
1222+ SSL_CTX_free (ctx );
11471223 return (-1 );
11481224 }
11491225
11501226 if (!SSL_CTX_check_private_key (ctx )) {
11511227 log_event (LOG_ERR , "Private key does not match the certificate public key\n" );
1228+ SSL_CTX_free (ctx );
11521229 return (-1 );
11531230 }
11541231 }
1232+
1233+ if (verify_peer == True ) {
1234+ long lerr ;
1235+ unsigned long ulerr ;
1236+
1237+ if (log_level > 0 ) {
1238+ log_event (LOG_INFO , "verifying peer" );
1239+ }
1240+ if (tls_ca_file != NULL || tls_ca_dir != NULL ) {
1241+ if (!SSL_CTX_load_verify_locations (ctx , tls_ca_file , tls_ca_dir )) {
1242+ ulerr = ERR_get_error ();
1243+ log_event (LOG_ERR , "Error setting verify location: %s" ,
1244+ ERR_reason_error_string (ulerr ));
1245+ SSL_CTX_free (ctx );
1246+ return (-1 );
1247+ }
1248+ }
1249+ else {
1250+ if (SSL_CTX_set_default_verify_paths (ctx ) != 1 ) {
1251+ ulerr = ERR_get_error ();
1252+ log_event (LOG_ERR , "Error setting default verify location: %s" ,
1253+ ERR_reason_error_string (ulerr ));
1254+ SSL_CTX_free (ctx );
1255+ return (-1 );
1256+ }
1257+ if (log_level > 0 ) {
1258+ log_event (LOG_INFO , "set default verify path" );
1259+ }
1260+ }
1261+ if (allow_self_signed == False ) {
1262+ SSL_CTX_set_verify (ctx , SSL_VERIFY_PEER , NULL );
1263+ }
1264+ }
11551265#endif
11561266
11571267#ifdef INET6
@@ -1163,7 +1273,7 @@ int smtp_open(char *host, int port)
11631273 /* Check we can reach the host */
11641274 if (getaddrinfo (host , servname , & hints , & ai0 )) {
11651275 log_event (LOG_ERR , "Unable to locate %s" , host );
1166- return ( -1 ) ;
1276+ goto tcp_err ;
11671277 }
11681278
11691279 for (ai = ai0 ; ai ; ai = ai -> ai_next ) {
@@ -1183,31 +1293,31 @@ int smtp_open(char *host, int port)
11831293 if (s < 0 ) {
11841294 log_event (LOG_ERR ,
11851295 "Unable to connect to \"%s\" port %d.\n" , host , port );
1186-
1187- return (-1 );
1296+ goto tcp_err ;
11881297 }
1298+ goto tcp_ok ;
11891299#else
11901300 /* Check we can reach the host */
11911301 if ((hent = gethostbyname (host )) == (struct hostent * )NULL ) {
11921302 log_event (LOG_ERR , "Unable to locate %s" , host );
1193- return ( -1 ) ;
1303+ goto tcp_err ;
11941304 }
11951305
11961306 if (hent -> h_length > sizeof (hent -> h_addr )) {
11971307 log_event (LOG_ERR , "Buffer overflow in gethostbyname()" );
1198- return ( -1 ) ;
1308+ goto tcp_err ;
11991309 }
12001310
12011311 /* Create a socket for the connection */
12021312 if ((s = socket (PF_INET , SOCK_STREAM , IPPROTO_TCP )) < 0 ) {
12031313 log_event (LOG_ERR , "Unable to create a socket" );
1204- return ( -1 ) ;
1314+ goto tcp_err ;
12051315 }
12061316
12071317 for (i = 0 ; ; ++ i ) {
12081318 if (!hent -> h_addr_list [i ]) {
12091319 log_event (LOG_ERR , "Unable to connect to %s:%d" , host , port );
1210- return ( -1 ) ;
1320+ goto tcp_err ;
12111321 }
12121322
12131323 /* This SHOULD already be in Network Byte Order from gethostbyname() */
@@ -1220,10 +1330,17 @@ int smtp_open(char *host, int port)
12201330 continue ;
12211331 break ;
12221332 }
1333+ goto tcp_ok ;
12231334#endif
1224-
1335+ tcp_err :
1336+ #ifdef HAVE_SSL
1337+ SSL_CTX_free (ctx );
1338+ #endif
1339+ return (-1 );
1340+ tcp_ok :
12251341#ifdef HAVE_SSL
12261342 if (use_tls == True ) {
1343+ long status ;
12271344 log_event (LOG_INFO , "Creating SSL connection to host" );
12281345
12291346 if (use_starttls == True )
@@ -1237,6 +1354,7 @@ int smtp_open(char *host, int port)
12371354 smtp_write (s , "STARTTLS" ); /* assume STARTTLS regardless */
12381355 if (!smtp_okay (s , buf )) {
12391356 log_event (LOG_ERR , "STARTTLS not working" );
1357+ SSL_CTX_free (ctx );
12401358 return (-1 );
12411359 }
12421360 }
@@ -1248,6 +1366,7 @@ int smtp_open(char *host, int port)
12481366 else
12491367 {
12501368 log_event (LOG_ERR , "Invalid response SMTP Server (STARTTLS)" );
1369+ SSL_CTX_free (ctx );
12511370 return (-1 );
12521371 }
12531372 use_tls = True ; /* now continue as normal for SSL */
@@ -1256,13 +1375,27 @@ int smtp_open(char *host, int port)
12561375 ssl = SSL_new (ctx );
12571376 if (!ssl ) {
12581377 log_event (LOG_ERR , "SSL not working" );
1378+ SSL_free (ssl );
1379+ SSL_CTX_free (ctx );
12591380 return (-1 );
12601381 }
1261- SSL_set_fd (ssl , s );
12621382
1383+ if (verify_peer == True && verify_peer_name == True ) {
1384+ SSL_set_hostflags (ssl , X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS );
1385+ if (!SSL_set1_host (ssl , host )) {
1386+ log_event (LOG_ERR , "Unable to set peer host name" );
1387+ SSL_free (ssl );
1388+ SSL_CTX_free (ctx );
1389+ return (-1 );
1390+ }
1391+ }
1392+
1393+ SSL_set_fd (ssl , s );
12631394 err = SSL_connect (ssl );
12641395 if (err < 0 ) {
12651396 perror ("SSL_connect" );
1397+ SSL_free (ssl );
1398+ SSL_CTX_free (ctx );
12661399 return (-1 );
12671400 }
12681401
@@ -1273,11 +1406,37 @@ int smtp_open(char *host, int port)
12731406
12741407 server_cert = SSL_get_peer_certificate (ssl );
12751408 if (!server_cert ) {
1409+ SSL_free (ssl );
1410+ SSL_CTX_free (ctx );
12761411 return (-1 );
12771412 }
1278- X509_free (server_cert );
12791413
1280- /* TODO: Check server cert if changed! */
1414+ if (verify_peer == True ) {
1415+ status = SSL_get_verify_result (ssl );
1416+ if (log_level > 0 ) {
1417+ log_event (LOG_INFO ,"%d %s" , status , X509_verify_cert_error_string (status ) );
1418+ }
1419+ if (status != X509_V_OK ) {
1420+ if (allow_self_signed == True
1421+ && status != X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
1422+ && status != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
1423+ && status != X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ) {
1424+ log_event (LOG_ERR , "%d %s" , status , X509_verify_cert_error_string (status ));
1425+ X509_free (server_cert );
1426+ SSL_free (ssl );
1427+ SSL_CTX_free (ctx );
1428+ return (-1 );
1429+ }
1430+ else if (allow_self_signed == False ) {
1431+ log_event (LOG_ERR , "%d %s" , status , X509_verify_cert_error_string (status ));
1432+ X509_free (server_cert );
1433+ SSL_free (ssl );
1434+ SSL_CTX_free (ctx );
1435+ return (-1 );
1436+ }
1437+ }
1438+ }
1439+ X509_free (server_cert );
12811440 }
12821441#endif
12831442
0 commit comments