For OpenSSL, this means to use TLSv1_(client|server)_method rather
than SSLv23_(client|server)_method combined with SSL_OP_NO_x flags
for specific TLS versions to disable.

For PolarSSL, this means to avoid calling ssl_set_min_version and
instead implicitly control the TLS version via allowed ciphersuites.

Signed-off-by: James Yonan <ja...@openvpn.net>
---
 src/openvpn/ssl.c          |  4 ++--
 src/openvpn/ssl_backend.h  | 15 +++++++++------
 src/openvpn/ssl_openssl.c  | 31 ++++++++++++++++++++++---------
 src/openvpn/ssl_polarssl.c | 43 +++++++++++++++++++++++--------------------
 4 files changed, 56 insertions(+), 37 deletions(-)

diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index b09e52b..af30641 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -486,12 +486,12 @@ init_ssl (const struct options *options, struct 
tls_root_ctx *new_ctx)

   if (options->tls_server)
     {
-      tls_ctx_server_new(new_ctx);
+      tls_ctx_server_new(new_ctx, options->ssl_flags);
       tls_ctx_load_dh_params(new_ctx, options->dh_file, 
options->dh_file_inline);
     }
   else                         /* if client */
     {
-      tls_ctx_client_new(new_ctx);
+      tls_ctx_client_new(new_ctx, options->ssl_flags);
     }

   tls_ctx_set_options(new_ctx, options->ssl_flags);
diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h
index 57b03df..0b41ff2 100644
--- a/src/openvpn/ssl_backend.h
+++ b/src/openvpn/ssl_backend.h
@@ -109,10 +109,11 @@ void tls_clear_error();
  * @return             One of the TLS_VER_x constants or TLS_VER_BAD
  *                      if a parse error should be flagged.
  */
-#define TLS_VER_BAD   -1
-#define TLS_VER_1_0    0 /* default */
-#define TLS_VER_1_1    1
-#define TLS_VER_1_2    2
+#define TLS_VER_BAD    -1
+#define TLS_VER_UNSPEC  0
+#define TLS_VER_1_0     1 /* default */
+#define TLS_VER_1_1     2
+#define TLS_VER_1_2     3
 int tls_version_min_parse(const char *vstr, const char *extra);

 /**
@@ -127,15 +128,17 @@ int tls_version_max(void);
  * Initialise a library-specific TLS context for a server.
  *
  * @param ctx          TLS context to initialise
+ * @param ssl_flags     SSLF_x flags from ssl_common.h
  */
-void tls_ctx_server_new(struct tls_root_ctx *ctx);
+void tls_ctx_server_new(struct tls_root_ctx *ctx, unsigned int ssl_flags);

 /**
  * Initialises a library-specific TLS context for a client.
  *
  * @param ctx          TLS context to initialise
+ * @param ssl_flags     SSLF_x flags from ssl_common.h
  */
-void tls_ctx_client_new(struct tls_root_ctx *ctx);
+void tls_ctx_client_new(struct tls_root_ctx *ctx, unsigned int ssl_flags);

 /**
  * Frees the library-specific TLSv1 context
diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c
index 1923230..abf39ac 100644
--- a/src/openvpn/ssl_openssl.c
+++ b/src/openvpn/ssl_openssl.c
@@ -94,22 +94,32 @@ tls_clear_error()
 }

 void
-tls_ctx_server_new(struct tls_root_ctx *ctx)
+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;
+
   ASSERT(NULL != ctx);

-  ctx->ctx = SSL_CTX_new (SSLv23_server_method ());
+  if (tls_version_min > TLS_VER_UNSPEC)
+    ctx->ctx = SSL_CTX_new (SSLv23_server_method ());
+  else
+    ctx->ctx = SSL_CTX_new (TLSv1_server_method ());

   if (ctx->ctx == NULL)
     msg (M_SSLERR, "SSL_CTX_new SSLv23_server_method");
 }

 void
-tls_ctx_client_new(struct tls_root_ctx *ctx)
+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;
+
   ASSERT(NULL != ctx);

-  ctx->ctx = SSL_CTX_new (SSLv23_client_method ());
+  if (tls_version_min > TLS_VER_UNSPEC)
+    ctx->ctx = SSL_CTX_new (SSLv23_client_method ());
+  else
+    ctx->ctx = SSL_CTX_new (TLSv1_client_method ());

   if (ctx->ctx == NULL)
     msg (M_SSLERR, "SSL_CTX_new SSLv23_client_method");
@@ -182,16 +192,19 @@ tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned 
int ssl_flags)
   {
     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)
-      sslopt |= SSL_OP_NO_TLSv1;
+    if (tls_version_min > TLS_VER_UNSPEC)
+      {
+       if (tls_version_min > TLS_VER_1_0)
+         sslopt |= SSL_OP_NO_TLSv1;
 #ifdef SSL_OP_NO_TLSv1_1
-    if (tls_version_min > TLS_VER_1_1)
-      sslopt |= SSL_OP_NO_TLSv1_1;
+       if (tls_version_min > 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)
-      sslopt |= SSL_OP_NO_TLSv1_2;
+       sslopt |= SSL_OP_NO_TLSv1_2;
 #endif
+      }
     SSL_CTX_set_options (ctx->ctx, sslopt);
   }

diff --git a/src/openvpn/ssl_polarssl.c b/src/openvpn/ssl_polarssl.c
index c110d0d..15450ff 100644
--- a/src/openvpn/ssl_polarssl.c
+++ b/src/openvpn/ssl_polarssl.c
@@ -68,7 +68,7 @@ tls_clear_error()
 }

 void
-tls_ctx_server_new(struct tls_root_ctx *ctx)
+tls_ctx_server_new(struct tls_root_ctx *ctx, unsigned int ssl_flags)
 {
   ASSERT(NULL != ctx);
   CLEAR(*ctx);
@@ -85,7 +85,7 @@ tls_ctx_server_new(struct tls_root_ctx *ctx)
 }

 void
-tls_ctx_client_new(struct tls_root_ctx *ctx)
+tls_ctx_client_new(struct tls_root_ctx *ctx, unsigned int ssl_flags)
 {
   ASSERT(NULL != ctx);
   CLEAR(*ctx);
@@ -715,29 +715,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)
+       if (tls_version_min > TLS_VER_UNSPEC)
          {
-         case TLS_VER_1_0:
-         default:
-           polar_major = SSL_MAJOR_VERSION_3;
-           polar_minor = SSL_MINOR_VERSION_1;
-           break;
+           int polar_major;
+           int polar_minor;
+           switch (tls_version_min)
+             {
+             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;
+             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;
+             case TLS_VER_1_2:
+               polar_major = SSL_MAJOR_VERSION_3;
+               polar_minor = SSL_MINOR_VERSION_3;
+               break;
 #endif
+             }
+           ssl_set_min_version(ks_ssl->ctx, polar_major, polar_minor);
          }
-       ssl_set_min_version(ks_ssl->ctx, polar_major, polar_minor);
       }

       /* Initialise BIOs */
@@ -1046,7 +1049,7 @@ show_available_tls_ciphers (const char *cipher_list)
   struct tls_root_ctx tls_ctx;
   const int *ciphers = ssl_list_ciphersuites();

-  tls_ctx_server_new(&tls_ctx);
+  tls_ctx_server_new(&tls_ctx, 0);
   tls_ctx_restrict_ciphers(&tls_ctx, cipher_list);

   if (tls_ctx.allowed_ciphers)
-- 
1.8.5.5


Reply via email to