903f6e
Some servers have problem when connection uses TLS 1.0 or SSL 3.0.
903f6e
Since openssl offers TLS 1.1 and 1.2, we would like to use these
903f6e
when connecting to server, while having ability to disable these
903f6e
protocols if needed.
903f6e
903f6e
https://bugzilla.redhat.com/show_bug.cgi?id=957840
903f6e
903f6e
Upstream related bug report:
903f6e
http://dev.mutt.org/trac/ticket/3571
903f6e
903f6e
diff -up mutt-1.5.21/init.h.tlsv1v2 mutt-1.5.21/init.h
903f6e
--- mutt-1.5.21/init.h.tlsv1v2	2013-06-27 12:46:14.120389035 +0200
903f6e
+++ mutt-1.5.21/init.h	2013-06-27 12:47:28.020387743 +0200
903f6e
@@ -2970,6 +2970,18 @@ struct option_t MuttVars[] = {
903f6e
   ** This variable specifies whether to attempt to use TLSv1 in the
903f6e
   ** SSL authentication process.
903f6e
   */
903f6e
+  { "ssl_use_tlsv1_1", DT_BOOL, R_NONE, OPTTLSV1_1, 1 },
903f6e
+  /*
903f6e
+  ** .pp
903f6e
+  ** This variable specifies whether to attempt to use TLSv1.1 in the
903f6e
+  ** SSL authentication process.
903f6e
+  */
903f6e
+  { "ssl_use_tlsv1_2", DT_BOOL, R_NONE, OPTTLSV1_2, 1 },
903f6e
+  /*
903f6e
+  ** .pp
903f6e
+  ** This variable specifies whether to attempt to use TLSv1.2 in the
903f6e
+  ** SSL authentication process.
903f6e
+  */
903f6e
 #ifdef USE_SSL_OPENSSL
903f6e
   { "ssl_usesystemcerts", DT_BOOL, R_NONE, OPTSSLSYSTEMCERTS, 1 },
903f6e
   /*
903f6e
diff -up mutt-1.5.21/mutt.h.tlsv1v2 mutt-1.5.21/mutt.h
903f6e
--- mutt-1.5.21/mutt.h.tlsv1v2	2010-09-13 19:19:55.000000000 +0200
903f6e
+++ mutt-1.5.21/mutt.h	2013-06-27 12:47:28.020387743 +0200
903f6e
@@ -376,6 +376,8 @@ enum
903f6e
 # endif /* USE_SSL_GNUTLS */
903f6e
   OPTSSLV3,
903f6e
   OPTTLSV1,
903f6e
+  OPTTLSV1_1,
903f6e
+  OPTTLSV1_2,
903f6e
   OPTSSLFORCETLS,
903f6e
   OPTSSLVERIFYDATES,
903f6e
   OPTSSLVERIFYHOST,
903f6e
diff -up mutt-1.5.21/mutt_ssl.c.tlsv1v2 mutt-1.5.21/mutt_ssl.c
903f6e
--- mutt-1.5.21/mutt_ssl.c.tlsv1v2	2010-08-25 18:31:40.000000000 +0200
903f6e
+++ mutt-1.5.21/mutt_ssl.c	2013-06-27 12:47:28.021387743 +0200
903f6e
@@ -106,6 +106,18 @@ int mutt_ssl_starttls (CONNECTION* conn)
903f6e
     dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL_CTX\n"));
903f6e
     goto bail_ssldata;
903f6e
   }
903f6e
+#ifdef SSL_OP_NO_TLSv1_1
903f6e
+  if (!option(OPTTLSV1_1))
903f6e
+  {
903f6e
+    SSL_CTX_set_options(ssldata->ctx, SSL_OP_NO_TLSv1_1);
903f6e
+  }
903f6e
+#endif
903f6e
+#ifdef SSL_OP_NO_TLSv1_2
903f6e
+  if (!option(OPTTLSV1_2))
903f6e
+  {
903f6e
+    SSL_CTX_set_options(ssldata->ctx, SSL_OP_NO_TLSv1_2);
903f6e
+  }
903f6e
+#endif
903f6e
 
903f6e
   ssl_get_client_cert(ssldata, conn);
903f6e
 
903f6e
@@ -303,6 +315,21 @@ static int ssl_socket_open (CONNECTION *
903f6e
   {
903f6e
     SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1);
903f6e
   }
903f6e
+  /* TLSv1.1/1.2 support was added in OpenSSL 1.0.1, but some OS distros such
903f6e
+   * as Fedora 17 are on OpenSSL 1.0.0.
903f6e
+   */
903f6e
+#ifdef SSL_OP_NO_TLSv1_1
903f6e
+  if (!option(OPTTLSV1_1))
903f6e
+  {
903f6e
+    SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_1);
903f6e
+  }
903f6e
+#endif
903f6e
+#ifdef SSL_OP_NO_TLSv1_2
903f6e
+  if (!option(OPTTLSV1_2))
903f6e
+  {
903f6e
+    SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_2);
903f6e
+  }
903f6e
+#endif
903f6e
   if (!option(OPTSSLV2))
903f6e
   {
903f6e
     SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv2);
903f6e
diff -up mutt-1.5.21/mutt_ssl_gnutls.c.tlsv1v2 mutt-1.5.21/mutt_ssl_gnutls.c
903f6e
--- mutt-1.5.21/mutt_ssl_gnutls.c.tlsv1v2	2013-06-27 12:46:14.123389035 +0200
903f6e
+++ mutt-1.5.21/mutt_ssl_gnutls.c	2013-06-27 12:47:28.018387743 +0200
903f6e
@@ -238,7 +238,11 @@ err_crt:
903f6e
   gnutls_x509_crt_deinit (clientcrt);
903f6e
 }
903f6e
 
903f6e
-static int protocol_priority[] = {GNUTLS_TLS1, GNUTLS_SSL3, 0};
903f6e
+/* This array needs to be large enough to hold all the possible values support
903f6e
+ * by Mutt.  The initialized values are just placeholders--the array gets
903f6e
+ * overwrriten in tls_negotiate() depending on the $ssl_use_* options.
903f6e
+ */
903f6e
+static int protocol_priority[] = {GNUTLS_TLS1_2, GNUTLS_TLS1_1, GNUTLS_TLS1, GNUTLS_SSL3, 0};
903f6e
 
903f6e
 /* tls_negotiate: After TLS state has been initialised, attempt to negotiate
903f6e
  *   TLS over the wire, including certificate checks. */
903f6e
@@ -246,6 +250,7 @@ static int tls_negotiate (CONNECTION * c
903f6e
 {
903f6e
   tlssockdata *data;
903f6e
   int err;
903f6e
+  size_t nproto = 0; /* number of tls/ssl protocols */
903f6e
 
903f6e
   data = (tlssockdata *) safe_calloc (1, sizeof (tlssockdata));
903f6e
   conn->sockdata = data;
903f6e
@@ -286,22 +291,22 @@ static int tls_negotiate (CONNECTION * c
903f6e
   /* set socket */
903f6e
   gnutls_transport_set_ptr (data->state, (gnutls_transport_ptr)conn->fd);
903f6e
 
903f6e
+  if (option(OPTTLSV1_2))
903f6e
+    protocol_priority[nproto++] = GNUTLS_TLS1_2;
903f6e
+  if (option(OPTTLSV1_1))
903f6e
+    protocol_priority[nproto++] = GNUTLS_TLS1_1;
903f6e
+  if (option(OPTTLSV1))
903f6e
+    protocol_priority[nproto++] = GNUTLS_TLS1;
903f6e
+  if (option(OPTSSLV3))
903f6e
+    protocol_priority[nproto++] = GNUTLS_SSL3;
903f6e
+  protocol_priority[nproto] = 0;
903f6e
+
903f6e
   /* disable TLS/SSL protocols as needed */
903f6e
-  if (!option(OPTTLSV1) && !option(OPTSSLV3))
903f6e
+  if (nproto == 0)
903f6e
   {
903f6e
     mutt_error (_("All available protocols for TLS/SSL connection disabled"));
903f6e
     goto fail;
903f6e
   }
903f6e
-  else if (!option(OPTTLSV1))
903f6e
-  {
903f6e
-    protocol_priority[0] = GNUTLS_SSL3;
903f6e
-    protocol_priority[1] = 0;
903f6e
-  }
903f6e
-  else if (!option(OPTSSLV3))
903f6e
-  {
903f6e
-    protocol_priority[0] = GNUTLS_TLS1;
903f6e
-    protocol_priority[1] = 0;
903f6e
-  }
903f6e
   /*
903f6e
   else
903f6e
     use the list set above