]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Add --tls-version-max
authorSteffan Karger <steffan.karger@fox-it.com>
Fri, 5 Sep 2014 10:38:04 +0000 (12:38 +0200)
committerGert Doering <gert@greenie.muc.de>
Fri, 14 Nov 2014 14:12:08 +0000 (15:12 +0100)
Because using TLS 1.2 breaks certain setups, a user might want to enforce
a maximum TLS version to use. This patch adds that option.

This patch removes a number of #ifdefs from ssl_polarssl.c, because the
polarssl versions we currently support (polar 1.2 for openvpn 2.3, and
polar 1.3 for openvpn-master) have all versions unconditionally enabled.

Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <544EC052.3080809@fox-it.com>
URL: http://article.gmane.org/gmane.network.openvpn.devel/9210
Signed-off-by: Gert Doering <gert@greenie.muc.de>
doc/openvpn.8
src/openvpn/options.c
src/openvpn/ssl.c
src/openvpn/ssl_backend.h
src/openvpn/ssl_common.h
src/openvpn/ssl_openssl.c
src/openvpn/ssl_polarssl.c

index 39b128ff2aa2fd0b06470486001739f6b2ebf034..d75bb764c7abee26674be6df0e09ba082333d513 100644 (file)
@@ -4292,6 +4292,11 @@ out that TLS version negotiation can lead to handshake problems due
 to new signature algorithms in TLS 1.2.
 .\"*********************************************************
 .TP
+.B \-\-tls-version-max version
+Set the maximum TLS version we will use (default is the highest version
+supported).  Examples for version include "1.0", "1.1", or "1.2".
+.\"*********************************************************
+.TP
 .B \-\-pkcs12 file
 Specify a PKCS #12 file containing local private key,
 local certificate, and root CA certificate.
index fa53a1779a3b1870a34d201181bc2ca27e6c43df..d91bb63d6c317d1a10f08134dfc37f8a45c48e5e 100644 (file)
@@ -572,6 +572,7 @@ static const char usage_message[] =
   "--tls-version-min <version> ['or-highest'] : sets the minimum TLS version we\n"
   "    will accept from the peer.  If version is unrecognized and 'or-highest'\n"
   "    is specified, require max TLS version supported by SSL implementation.\n"
+  "--tls-version-max <version> : sets the maximum TLS version we will use.\n"
 #ifndef ENABLE_CRYPTO_POLARSSL
   "--pkcs12 file   : PKCS#12 file containing local private key, local certificate\n"
   "                  and optionally the root CA certificate.\n"
@@ -6570,14 +6571,29 @@ add_option (struct options *options,
     {
       int ver;
       VERIFY_PERMISSION (OPT_P_GENERAL);
-      ver = tls_version_min_parse(p[1], p[2]);
+      ver = tls_version_parse(p[1], p[2]);
       if (ver == TLS_VER_BAD)
        {
          msg (msglevel, "unknown tls-version-min parameter: %s", p[1]);
           goto err;
        }
-      options->ssl_flags &= ~(SSLF_TLS_VERSION_MASK << SSLF_TLS_VERSION_SHIFT);
-      options->ssl_flags |= (ver << SSLF_TLS_VERSION_SHIFT);
+      options->ssl_flags &=
+         ~(SSLF_TLS_VERSION_MIN_MASK << SSLF_TLS_VERSION_MIN_SHIFT);
+      options->ssl_flags |= (ver << SSLF_TLS_VERSION_MIN_SHIFT);
+    }
+  else if (streq (p[0], "tls-version-max") && p[1])
+    {
+      int ver;
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      ver = tls_version_parse(p[1], NULL);
+      if (ver == TLS_VER_BAD)
+       {
+         msg (msglevel, "unknown tls-version-max parameter: %s", p[1]);
+          goto err;
+       }
+      options->ssl_flags &=
+         ~(SSLF_TLS_VERSION_MAX_MASK << SSLF_TLS_VERSION_MAX_SHIFT);
+      options->ssl_flags |= (ver << SSLF_TLS_VERSION_MAX_SHIFT);
     }
 #ifndef ENABLE_CRYPTO_POLARSSL
   else if (streq (p[0], "pkcs12") && p[1])
index ac6818ef405f3dcd0219c0c7dc7589dc8f83bfa5..281176e8a58651d2ca876ea764b5bf3e770676d5 100644 (file)
@@ -458,7 +458,7 @@ ssl_put_auth_challenge (const char *cr_str)
  * return tls_version_max().
  */
 int
-tls_version_min_parse(const char *vstr, const char *extra)
+tls_version_parse(const char *vstr, const char *extra)
 {
   const int max_version = tls_version_max();
   if (!strcmp(vstr, "1.0") && TLS_VER_1_0 <= max_version)
index fc23175a2969bc0131bbfb38ec80f730a35fae98..6d47bd044b6d43aa45c526004f47419c1b0c8a09 100644 (file)
@@ -114,7 +114,7 @@ void tls_clear_error();
 #define TLS_VER_1_0     1
 #define TLS_VER_1_1     2
 #define TLS_VER_1_2     3
-int tls_version_min_parse(const char *vstr, const char *extra);
+int tls_version_parse(const char *vstr, const char *extra);
 
 /**
  * Return the maximum TLS version (as a TLS_VER_x constant)
index 66b6492c0723ff938b67ee90fda15c62b352f777..ba104590b2d5f9aeaabcd993a6a6b17540f89de3 100644 (file)
@@ -291,8 +291,10 @@ struct tls_options
 # define SSLF_AUTH_USER_PASS_OPTIONAL  (1<<2)
 # define SSLF_OPT_VERIFY               (1<<4)
 # define SSLF_CRL_VERIFY_DIR           (1<<5)
-# define SSLF_TLS_VERSION_SHIFT        6
-# define SSLF_TLS_VERSION_MASK         0xF /* (uses bit positions 6 to 9) */
+# define SSLF_TLS_VERSION_MIN_SHIFT    6
+# define SSLF_TLS_VERSION_MIN_MASK     0xF /* (uses bit positions 6 to 9) */
+# define SSLF_TLS_VERSION_MAX_SHIFT    10
+# define SSLF_TLS_VERSION_MAX_MASK     0xF /* (uses bit positions 10 to 13) */
   unsigned int ssl_flags;
 
 #ifdef MANAGEMENT_DEF_AUTH
index e77b73657e5930cef4a423a0bbb11de1df1c1c7f..a769b2a4d95efbef9f95f5d7279fe2c8956198f3 100644 (file)
@@ -121,7 +121,8 @@ tmp_rsa_cb (SSL * s, int is_export, int keylength)
 void
 tls_ctx_server_new(struct tls_root_ctx *ctx, unsigned int ssl_flags)
 {
-  const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK;
+  const int tls_version_min =
+      (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK;
 
   ASSERT(NULL != ctx);
 
@@ -139,7 +140,8 @@ tls_ctx_server_new(struct tls_root_ctx *ctx, unsigned int ssl_flags)
 void
 tls_ctx_client_new(struct tls_root_ctx *ctx, unsigned int ssl_flags)
 {
-  const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK;
+  const int tls_version_min =
+      (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK;
 
   ASSERT(NULL != ctx);
 
@@ -218,15 +220,22 @@ tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags)
   /* process SSL options including minimum TLS version we will accept from peer */
   {
     long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
-    const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK;
-    if (tls_version_min > TLS_VER_1_0)
+    const int tls_ver_min =
+       (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK;
+    int tls_ver_max =
+       (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK;
+
+    if (tls_ver_max <= TLS_VER_UNSPEC)
+       tls_ver_max = tls_version_max();
+
+    if (tls_ver_min > TLS_VER_1_0 || tls_ver_max < TLS_VER_1_0)
       sslopt |= SSL_OP_NO_TLSv1;
 #ifdef SSL_OP_NO_TLSv1_1
-    if (tls_version_min > TLS_VER_1_1)
+    if (tls_ver_min > TLS_VER_1_1 || tls_ver_max < TLS_VER_1_1)
       sslopt |= SSL_OP_NO_TLSv1_1;
 #endif
 #ifdef SSL_OP_NO_TLSv1_2
-    if (tls_version_min > TLS_VER_1_2)
+    if (tls_ver_min > TLS_VER_1_2 || tls_ver_max < TLS_VER_1_2)
       sslopt |= SSL_OP_NO_TLSv1_2;
 #endif
     SSL_CTX_set_options (ctx->ctx, sslopt);
index 5718c8cc8a7e108cee5b560ef7a761ab8b080e44..189bf7158eeb0b96cecd4c14f3ebb9b4403c537e 100644 (file)
@@ -654,6 +654,40 @@ tls_version_max(void)
 #endif
 }
 
+/**
+ * Convert an OpenVPN tls-version variable to PolarSSl format (i.e. a major and
+ * minor ssl version number).
+ *
+ * @param tls_ver      The tls-version variable to convert.
+ * @param major                Returns the TLS major version in polarssl format.
+ *                     Must be a valid pointer.
+ * @param minor                Returns the TLS minor version in polarssl format.
+ *                     Must be a valid pointer.
+ */
+static void tls_version_to_major_minor(int tls_ver, int *major, int *minor) {
+  ASSERT(major);
+  ASSERT(minor);
+
+  switch (tls_ver)
+  {
+    case TLS_VER_1_0:
+      *major = SSL_MAJOR_VERSION_3;
+      *minor = SSL_MINOR_VERSION_1;
+      break;
+    case TLS_VER_1_1:
+      *major = SSL_MAJOR_VERSION_3;
+      *minor = SSL_MINOR_VERSION_2;
+      break;
+    case TLS_VER_1_2:
+      *major = SSL_MAJOR_VERSION_3;
+      *minor = SSL_MINOR_VERSION_3;
+      break;
+    default:
+      msg(M_FATAL, "%s: invalid TLS version %d", __func__, tls_ver);
+      break;
+  }
+}
+
 void key_state_ssl_init(struct key_state_ssl *ks_ssl,
     const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session)
 {
@@ -712,30 +746,32 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl,
 
       /* Initialize minimum TLS version */
       {
-       const int tls_version_min = (session->opt->ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK;
-       int polar_major;
-       int polar_minor;
-       switch (tls_version_min)
+       const int tls_version_min =
+           (session->opt->ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) &
+           SSLF_TLS_VERSION_MIN_MASK;
+
+       /* default to TLS 1.0 */
+       int major = SSL_MAJOR_VERSION_3;
+       int minor = SSL_MINOR_VERSION_1;
+
+       if (tls_version_min > TLS_VER_UNSPEC)
+         tls_version_to_major_minor(tls_version_min, &major, &minor);
+
+       ssl_set_min_version(ks_ssl->ctx, major, minor);
+      }
+
+      /* Initialize maximum TLS version */
+      {
+       const int tls_version_max =
+           (session->opt->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) &
+           SSLF_TLS_VERSION_MAX_MASK;
+
+       if (tls_version_max > TLS_VER_UNSPEC)
          {
-         case TLS_VER_1_0:
-         default:
-           polar_major = SSL_MAJOR_VERSION_3;
-           polar_minor = SSL_MINOR_VERSION_1;
-           break;
-#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_2)
-         case TLS_VER_1_1:
-           polar_major = SSL_MAJOR_VERSION_3;
-           polar_minor = SSL_MINOR_VERSION_2;
-           break;
-#endif
-#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_3)
-         case TLS_VER_1_2:
-           polar_major = SSL_MAJOR_VERSION_3;
-           polar_minor = SSL_MINOR_VERSION_3;
-           break;
-#endif
+           int major, minor;
+           tls_version_to_major_minor(tls_version_max, &major, &minor);
+           ssl_set_max_version(ks_ssl->ctx, major, minor);
          }
-       ssl_set_min_version(ks_ssl->ctx, polar_major, polar_minor);
       }
 
       /* Initialise BIOs */