Folks,

OpenSSL 1.0.1 introduced support for TLSv1.1 and TLSv1.2.  These are not
used by mutt.  This patch fixes that.

Counter-intuitively, the OpenSSL folks have TLSv1_client_method()
negotiate *only* TLSv1.0, and SSLv23_client_method() remains the only
method which can negotiate different versions.  This is true at least as
of 1.0.1c (the latest release at time of writing).

The attached patch uses SSLv23_client_method() and SSL_CTX_set_options()
to then disable SSLv2 and SSLv3.

This mail is sent with such a patched mutt, and you should thus see that
the initial Received: header uses the cipher:
  TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256

Regards,
-Phil
--- mutt_ssl.c.old	2010-08-25 16:31:40.000000000 +0000
+++ mutt_ssl.c	2012-05-23 19:50:58.000000000 +0000
@@ -88,6 +88,7 @@ static int interactive_check_cert (X509 
 static void ssl_get_client_cert(sslsockdata *ssldata, CONNECTION *conn);
 static int ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata);
 static int ssl_negotiate (CONNECTION *conn, sslsockdata*);
+static const char * ssl_error (void);
 
 /* mutt_ssl_starttls: Negotiate TLS over an already opened connection.
  *   TODO: Merge this code better with ssl_socket_open. */
@@ -95,29 +96,53 @@ int mutt_ssl_starttls (CONNECTION* conn)
 {
   sslsockdata* ssldata;
   int maxbits;
+  long ssl_options;
 
   if (ssl_init())
     goto bail;
 
   ssldata = (sslsockdata*) safe_calloc (1, sizeof (sslsockdata));
-  /* the ssl_use_xxx protocol options don't apply. We must use TLS in TLS. */
-  if (! (ssldata->ctx = SSL_CTX_new (TLSv1_client_method ())))
+  /* the ssl_use_xxx protocol options don't apply. We must use TLS in TLS.
+   * However, we need to be able to negotiate amongst various TLS versions,
+   * which at present can only be done with the SSLv23_client_method;
+   * TLSv1_client_method gives us explicitly TLSv1.0, not 1.1 or 1.2
+   * (True as of OpenSSL 1.0.1c)
+   */
+  if (! (ssldata->ctx = SSL_CTX_new (SSLv23_client_method ())))
   {
-    dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL_CTX\n"));
+    dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL_CTX: %s\n",
+       ssl_error()));
     goto bail_ssldata;
   }
 
+  /* now fix it to disable SSL, leaving just TLS */
+  ssl_options = 0
+#ifdef SSL_OP_NO_SSLv2
+          | SSL_OP_NO_SSLv2
+#endif
+#ifdef SSL_OP_NO_SSLv3
+          | SSL_OP_NO_SSLv3
+#endif
+    ;
+  if (! (SSL_CTX_set_options (ssldata->ctx, ssl_options)))
+  {
+    dprint (1, (debugfile, "mutt_ssl_starttls: Error setting SSL options: %s\n",
+       ssl_error()));
+  }
+
   ssl_get_client_cert(ssldata, conn);
 
   if (! (ssldata->ssl = SSL_new (ssldata->ctx)))
   {
-    dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL\n"));
+    dprint (1, (debugfile, "mutt_ssl_starttls: Error allocating SSL: %s\n",
+       ssl_error()));
     goto bail_ctx;
   }
 
   if (SSL_set_fd (ssldata->ssl, conn->fd) != 1)
   {
-    dprint (1, (debugfile, "mutt_ssl_starttls: Error setting fd\n"));
+    dprint (1, (debugfile, "mutt_ssl_starttls: Error setting fd: %s\n",
+       ssl_error()));
     goto bail_ssl;
   }
 
@@ -1061,3 +1086,13 @@ static int ssl_passwd_cb(char *buf, int 
 
   return snprintf(buf, size, "%s", account->pass);
 }
+
+static const char * ssl_error (void)
+{
+  /* OpenSSL documents buffer must be at least 120 characters; allocate some
+   * more to allow for growth */
+  static char ssl_errbuf[256];
+
+  ERR_error_string_n(ERR_get_error(), ssl_errbuf, sizeof(ssl_errbuf));
+  return ssl_errbuf;
+}

Attachment: pgpf5KpBbOKiG.pgp
Description: PGP signature

Reply via email to