TLS fixes for OpenSSL.
authorPhil Pennock <pdp@exim.org>
Sat, 28 Apr 2012 13:21:02 +0000 (06:21 -0700)
committerPhil Pennock <pdp@exim.org>
Sat, 28 Apr 2012 13:21:02 +0000 (06:21 -0700)
Support TLS 1.1 & 1.2
New "openssl_options" values (all now documented).

Set SSL_MODE_AUTO_RETRY so that OpenSSL will retry a read or write after
TLS renegotiation, which otherwise led to messages "Got SSL error 2".

doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
src/README.UPDATING
src/src/tls-openssl.c

index c1f845eafef6824aecacdb45e76f5662606284c4..e719855f8e0dc6e1ff9aac7717d491aa84808ec7 100644 (file)
@@ -14362,6 +14362,61 @@ An example:
 openssl_options = -all +microsoft_big_sslv3_buffer
 .endd
 
+Possible options may include:
+.ilist
+&`all`&
+.ilist
+&`allow_unsafe_legacy_renegotiation`&
+.ilist
+&`cipher_server_preference`&
+.ilist
+&`dont_insert_empty_fragments`&
+.ilist
+&`ephemeral_rsa`&
+.ilist
+&`legacy_server_connect`&
+.ilist
+&`microsoft_big_sslv3_buffer`&
+.ilist
+&`microsoft_sess_id_bug`&
+.ilist
+&`msie_sslv2_rsa_padding`&
+.ilist
+&`netscape_challenge_bug`&
+.ilist
+&`netscape_reuse_cipher_change_bug`&
+.ilist
+&`no_compression`&
+.ilist
+&`no_session_resumption_on_renegotiation`&
+.ilist
+&`no_sslv2`&
+.ilist
+&`no_sslv3`&
+.ilist
+&`no_ticket`&
+.ilist
+&`no_tlsv1`&
+.ilist
+&`no_tlsv1_1`&
+.ilist
+&`no_tlsv1_2`&
+.ilist
+&`single_dh_use`&
+.ilist
+&`single_ecdh_use`&
+.ilist
+&`ssleay_080_client_dh_bug`&
+.ilist
+&`sslref2_reuse_cert_type_bug`&
+.ilist
+&`tls_block_padding_bug`&
+.ilist
+&`tls_d5_bug`&
+.ilist
+&`tls_rollback_bug`&
+.endlist
+
 
 .option oracle_servers main "string list" unset
 .cindex "Oracle" "server list"
index 03f4469af217587cdfcb519ce4ed72eecc9e1bb8..1d313879a84fb7a1e140ba04aebe4696228cf803 100644 (file)
@@ -53,6 +53,11 @@ PP/13 tls_peerdn now print-escaped for spool files.
       Observed some $tls_peerdn in wild which contained \n, which resulted
       in spool file corruption.
 
+PP/14 TLS fixes for OpenSSL: support TLS 1.1 & 1.2; new "openssl_options"
+      values; set SSL_MODE_AUTO_RETRY so that OpenSSL will retry a read
+      or write after TLS renegotiation, which otherwise led to messages
+      "Got SSL error 2".
+
 
 Exim version 4.77
 -----------------
index 1eb36277e39acb936350d0621514707aff57e6f4..9e3689d84d505a92cb9acf599c35053cd3813dd7 100644 (file)
@@ -39,6 +39,15 @@ Exim version 4.78
    the message.  No tool has been provided as we believe this is a rare
    occurence.
 
+ * With OpenSSL 1.0.1+, Exim now supports TLS 1.1 and TLS 1.2.  If built
+   against 1.0.1a then you will get a warning message and the
+   "openssl_options" value will not parse "no_tlsv1_1": the value changes
+   incompatibly between 1.0.1a and 1.0.1b, because the value chosen for 1.0.1a
+   is infelicitous.  We advise avoiding 1.0.1a.
+
+   "openssl_options" gains "no_tlsv1_1", "no_tlsv1_2" and "no_compression".
+
+
 
 Exim version 4.77
 -----------------
index 2104711bb96230013a2c27948abd6ded697c6533..e2e150c0a139c9ca4cec7f25c4ba3e16c03a8bf4 100644 (file)
@@ -347,6 +347,9 @@ level. */
 
 SSL_CTX_set_info_callback(ctx, (void (*)())info_callback);
 
+/* Automatically re-try reads/writes after renegotiation. */
+(void) SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+
 /* Apply administrator-supplied work-arounds.
 Historically we applied just one requested option,
 SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS, but when bug 994 requested a second, we
@@ -456,6 +459,18 @@ switch (ssl->session->ssl_version)
   ver = US"TLSv1";
   break;
 
+#ifdef TLS1_1_VERSION
+  case TLS1_1_VERSION:
+  ver = US"TLSv1.1";
+  break;
+#endif
+
+#ifdef TLS1_2_VERSION
+  case TLS1_2_VERSION:
+  ver = US"TLSv1.2";
+  break;
+#endif
+
   default:
   ver = US"UNKNOWN";
   }
@@ -873,8 +888,8 @@ if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm)
   int error;
   int inbytes;
 
-  DEBUG(D_tls) debug_printf("Calling SSL_read(%lx, %lx, %u)\n", (long)ssl,
-    (long)ssl_xfer_buffer, ssl_xfer_buffer_size);
+  DEBUG(D_tls) debug_printf("Calling SSL_read(%p, %p, %u)\n", ssl,
+    ssl_xfer_buffer, ssl_xfer_buffer_size);
 
   if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout);
   inbytes = SSL_read(ssl, CS ssl_xfer_buffer, ssl_xfer_buffer_size);
@@ -920,6 +935,7 @@ if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm)
     ssl_xfer_error = 1;
     return EOF;
     }
+
 #ifndef DISABLE_DKIM
   dkim_exim_verify_feed(ssl_xfer_buffer, inbytes);
 #endif
@@ -953,8 +969,8 @@ tls_read(uschar *buff, size_t len)
 int inbytes;
 int error;
 
-DEBUG(D_tls) debug_printf("Calling SSL_read(%lx, %lx, %u)\n", (long)ssl,
-  (long)buff, (unsigned int)len);
+DEBUG(D_tls) debug_printf("Calling SSL_read(%p, %p, %u)\n", ssl,
+  buff, (unsigned int)len);
 
 inbytes = SSL_read(ssl, CS buff, len);
 error = SSL_get_error(ssl, inbytes);
@@ -996,10 +1012,10 @@ int outbytes;
 int error;
 int left = len;
 
-DEBUG(D_tls) debug_printf("tls_do_write(%lx, %d)\n", (long)buff, left);
+DEBUG(D_tls) debug_printf("tls_do_write(%p, %d)\n", buff, left);
 while (left > 0)
   {
-  DEBUG(D_tls) debug_printf("SSL_write(SSL, %lx, %d)\n", (long)buff, left);
+  DEBUG(D_tls) debug_printf("SSL_write(SSL, %p, %d)\n", buff, left);
   outbytes = SSL_write(ssl, CS buff, left);
   error = SSL_get_error(ssl, outbytes);
   DEBUG(D_tls) debug_printf("outbytes=%d error=%d\n", outbytes, error);
@@ -1177,7 +1193,7 @@ all options unless explicitly for DTLS, let the administrator choose which
 to apply.
 
 This list is current as of:
-  ==>  1.0.0c  <==  */
+  ==>  1.0.1b  <==  */
 static struct exim_openssl_option exim_openssl_options[] = {
 /* KEEP SORTED ALPHABETICALLY! */
 #ifdef SSL_OP_ALL
@@ -1213,6 +1229,9 @@ static struct exim_openssl_option exim_openssl_options[] = {
 #ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
   { US"netscape_reuse_cipher_change_bug", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG },
 #endif
+#ifdef SSL_OP_NO_COMPRESSION
+  { US"no_compression", SSL_OP_NO_COMPRESSION },
+#endif
 #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
   { US"no_session_resumption_on_renegotiation", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION },
 #endif
@@ -1228,6 +1247,17 @@ static struct exim_openssl_option exim_openssl_options[] = {
 #ifdef SSL_OP_NO_TLSv1
   { US"no_tlsv1", SSL_OP_NO_TLSv1 },
 #endif
+#ifdef SSL_OP_NO_TLSv1_1
+#if SSL_OP_NO_TLSv1_1 == 0x00000400L
+  /* Error in chosen value in 1.0.1a; see first item in CHANGES for 1.0.1b */
+#warning OpenSSL 1.0.1a uses a bad value for SSL_OP_NO_TLSv1_1, ignoring
+#else
+  { US"no_tlsv1_1", SSL_OP_NO_TLSv1_1 },
+#endif
+#endif
+#ifdef SSL_OP_NO_TLSv1_2
+  { US"no_tlsv1_2", SSL_OP_NO_TLSv1_2 },
+#endif
 #ifdef SSL_OP_SINGLE_DH_USE
   { US"single_dh_use", SSL_OP_SINGLE_DH_USE },
 #endif
@@ -1253,6 +1283,7 @@ static struct exim_openssl_option exim_openssl_options[] = {
 static int exim_openssl_options_size =
   sizeof(exim_openssl_options)/sizeof(struct exim_openssl_option);
 
+
 static BOOL
 tls_openssl_one_option_parse(uschar *name, long *value)
 {