039bf80
From aa85f127d31346a28c619ee426090f1f23fd2249 Mon Sep 17 00:00:00 2001
039bf80
From: TJ Saunders <tj@castaglia.org>
039bf80
Date: Fri, 5 May 2017 09:24:10 -0700
039bf80
Subject: [PATCH] Improve detection of badly configured ciphersuites (e.g.
039bf80
 unsupported/misspelled cipher suites) at startup time.
039bf80
039bf80
---
039bf80
 contrib/mod_tls.c                            | 21 +++++++++++-
039bf80
 doc/contrib/mod_tls.html                     | 21 +++++++++++-
039bf80
 tests/t/lib/ProFTPD/Tests/Modules/mod_tls.pm | 50 ++++++++++++++++++++++++++++
039bf80
 3 files changed, 90 insertions(+), 2 deletions(-)
039bf80
039bf80
diff --git a/contrib/mod_tls.c b/contrib/mod_tls.c
039bf80
index 7a2a74f..3ff8ee2 100644
039bf80
--- a/contrib/mod_tls.c
039bf80
+++ b/contrib/mod_tls.c
039bf80
@@ -11976,6 +11976,7 @@ MODRET set_tlscertchain(cmd_rec *cmd) {
039bf80
 MODRET set_tlsciphersuite(cmd_rec *cmd) {
039bf80
   config_rec *c = NULL;
039bf80
   char *ciphersuite = NULL;
039bf80
+  SSL_CTX *ctx;
039bf80
 
039bf80
   CHECK_ARGS(cmd, 1);
039bf80
   CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
039bf80
@@ -11984,8 +11985,26 @@ MODRET set_tlsciphersuite(cmd_rec *cmd) {
039bf80
   c = add_config_param(cmd->argv[0], 1, NULL);
039bf80
 
039bf80
   /* Make sure that EXPORT ciphers cannot be used, per Bug#4163. */
039bf80
-  c->argv[0] = pstrcat(c->pool, "!EXPORT:", ciphersuite, NULL);
039bf80
+  ciphersuite = pstrcat(c->pool, "!EXPORT:", ciphersuite, NULL);
039bf80
+
039bf80
+  /* Check that our construct ciphersuite is acceptable. */
039bf80
+  ctx = SSL_CTX_new(SSLv23_server_method());
039bf80
+  if (ctx != NULL) {
039bf80
+    if (SSL_CTX_set_cipher_list(ctx, ciphersuite) != 1) {
039bf80
+      /* Note: tls_get_errors() relies on session.pool, so temporarily set
039bf80
+       * it to our temporary pool.
039bf80
+       */
039bf80
+      session.pool = cmd->tmp_pool;
039bf80
+
039bf80
+      CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
039bf80
+        "unable to use configured TLSCipherSuite '", ciphersuite, "': ",
039bf80
+        tls_get_errors(), NULL));
039bf80
+    }
039bf80
+
039bf80
+    SSL_CTX_free(ctx);
039bf80
+  }
039bf80
 
039bf80
+  c->argv[0] = ciphersuite;
039bf80
   return PR_HANDLED(cmd);
039bf80
 }
039bf80
 
039bf80
diff --git a/doc/contrib/mod_tls.html b/doc/contrib/mod_tls.html
039bf80
index c1d3f2d..cc88946 100644
039bf80
--- a/doc/contrib/mod_tls.html
039bf80
+++ b/doc/contrib/mod_tls.html
039bf80
@@ -295,7 +295,13 @@
039bf80
 Compatibility: 1.2.7rc1 and later
039bf80
 
039bf80
 

039bf80
-Default cipher list is "DEFAULT:!ADH:!EXPORT:!DES".
039bf80
+Sets the list of SSL/TLS ciphersuites for use.  Default cipher list is
039bf80
+"DEFAULT:!ADH:!EXPORT:!DES".
039bf80
+
039bf80
+

039bf80
+Note that mod_tls will automatically prepend the
039bf80
+configured cipher-list with "!EXPORT", in order to prevent the
039bf80
+use of the insecure "export grade" ciphers.
039bf80
 
039bf80
 

039bf80
 How to put together a cipher list parameter:
039bf80
@@ -2215,6 +2221,19 @@
039bf80
   TLSDHParamFile /path/to/dh1024.pem
039bf80
 
039bf80
 
039bf80
+

039bf80
+<font color=red>Question</font>: I tried to configure a specific ciphersuite
039bf80
+using TLSCipherSuite, but ProFTPD fails on startup with this error:
039bf80
+
039bf80
+  fatal: TLSCipherSuite: unable to use configured TLSCipherSuite '!EXPORT:MYCIPHER':
039bf80
+  (1) error:1410D0B9:SSL routines:SSL_CTX_set_cipher_list:no cipher match on line 16 of '/etc/proftpd/tls.conf'
039bf80
+
039bf80
+<font color=blue>Answer</font>: This error indicates that the version of OpenSSL
039bf80
+does not recognize/support one of the ciphers that you configured in your
039bf80
+TLSCipherSuite list.  Unfortunately the OpenSSL error reporting
039bf80
+does not pinpoint which is the offending ciphersuite; experimenting
039bf80
+with your cipher list will reveal which ones are problematic.
039bf80
+
039bf80
 

039bf80
 
039bf80
 

Installation

039bf80
diff --git a/tests/t/lib/ProFTPD/Tests/Modules/mod_tls.pm b/tests/t/lib/ProFTPD/Tests/Modules/mod_tls.pm
039bf80
index f7cd171..226d47c 100644
039bf80
--- a/tests/t/lib/ProFTPD/Tests/Modules/mod_tls.pm
039bf80
+++ b/tests/t/lib/ProFTPD/Tests/Modules/mod_tls.pm
039bf80
@@ -299,6 +299,11 @@ my $TESTS = {
039bf80
     test_class => [qw(bug forking)],
039bf80
   },
039bf80
 
039bf80
+  tls_config_tlsciphersuite_bad_cipher => {
039bf80
+    order => ++$order,
039bf80
+    test_class => [qw(forking)],
039bf80
+  },
039bf80
+
039bf80
   tls_session_cache_off_bug3869 => {
039bf80
     order => ++$order,
039bf80
     test_class => [qw(bug forking)],
039bf80
@@ -8983,6 +8988,51 @@ sub tls_config_tlsdhparamfile_bug3868 {
039bf80
   unlink($log_file);
039bf80
 }
039bf80
 
039bf80
+sub tls_config_tlsciphersuite_bad_cipher {
039bf80
+  my $self = shift;
039bf80
+  my $tmpdir = $self->{tmpdir};
039bf80
+  my $setup = test_setup($tmpdir, 'tls');
039bf80
+
039bf80
+  my $cert_file = File::Spec->rel2abs('t/etc/modules/mod_tls/server-cert.pem');
039bf80
+  my $ca_file = File::Spec->rel2abs('t/etc/modules/mod_tls/ca-cert.pem');
039bf80
+
039bf80
+  my $config = {
039bf80
+    PidFile => $setup->{pid_file},
039bf80
+    ScoreboardFile => $setup->{scoreboard_file},
039bf80
+    SystemLog => $setup->{log_file},
039bf80
+
039bf80
+    IfModules => {
039bf80
+      'mod_delay.c' => {
039bf80
+        DelayEngine => 'off',
039bf80
+      },
039bf80
+
039bf80
+      'mod_tls.c' => {
039bf80
+        TLSEngine => 'on',
039bf80
+        TLSLog => $setup->{log_file},
039bf80
+        TLSRSACertificateFile => $cert_file,
039bf80
+        TLSCACertificateFile => $ca_file,
039bf80
+        TLSCipherSuite => 'FOOBAR',
039bf80
+      },
039bf80
+    },
039bf80
+  };
039bf80
+
039bf80
+  my ($port, $config_user, $config_group) = config_write($setup->{config_file},
039bf80
+    $config);
039bf80
+
039bf80
+  my $ex;
039bf80
+
039bf80
+  # This should silently fail.
039bf80
+  server_start($setup->{config_file});
039bf80
+
039bf80
+  # This is where we detect the actual problem.
039bf80
+  eval { server_stop($setup->{pid_file}) };
039bf80
+  unless ($@) {
039bf80
+    $ex = "Server start with bad config unexpectedly";
039bf80
+  }
039bf80
+
039bf80
+  test_cleanup($setup->{log_file}, $ex);
039bf80
+}
039bf80
+
039bf80
 sub tls_session_cache_off_bug3869 {
039bf80
   my $self = shift;
039bf80
   my $tmpdir = $self->{tmpdir};