summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSteffan Karger <steffan.karger@fox-it.com>2014-08-26 00:03:23 +0200
committerGert Doering <gert@greenie.muc.de>2014-11-14 15:03:21 +0100
commit6cb15b908a64b69b715fa8b2d60c71c6d9d3f9fc (patch)
tree6bf20802933b4689afecfc5165bd0674e25dd5d6 /src
parent4e93e6dc88f4d904a4f2eb90140472a8d8fd68d0 (diff)
downloadopenvpn-6cb15b908a64b69b715fa8b2d60c71c6d9d3f9fc.tar.gz
openvpn-6cb15b908a64b69b715fa8b2d60c71c6d9d3f9fc.tar.xz
openvpn-6cb15b908a64b69b715fa8b2d60c71c6d9d3f9fc.zip
Add --tls-version-max
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>
Diffstat (limited to 'src')
-rw-r--r--src/openvpn/options.c22
-rw-r--r--src/openvpn/ssl.c2
-rw-r--r--src/openvpn/ssl_backend.h11
-rw-r--r--src/openvpn/ssl_common.h6
-rw-r--r--src/openvpn/ssl_openssl.c16
-rw-r--r--src/openvpn/ssl_polarssl.c80
6 files changed, 100 insertions, 37 deletions
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 84eb6ed..64ded09 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -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"
@@ -6577,14 +6578,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])
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index 3ce1f60..c81659f 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -454,7 +454,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)
diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h
index bfd1549..b0777bf 100644
--- a/src/openvpn/ssl_backend.h
+++ b/src/openvpn/ssl_backend.h
@@ -109,11 +109,12 @@ 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
-int tls_version_min_parse(const char *vstr, const char *extra);
+#define TLS_VER_BAD -1
+#define TLS_VER_UNSPEC 0 /* default */
+#define TLS_VER_1_0 1
+#define TLS_VER_1_1 2
+#define TLS_VER_1_2 3
+int tls_version_parse(const char *vstr, const char *extra);
/**
* Return the maximum TLS version (as a TLS_VER_x constant)
diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
index 04ba789..2719b41 100644
--- a/src/openvpn/ssl_common.h
+++ b/src/openvpn/ssl_common.h
@@ -296,8 +296,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
diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c
index adf3ae6..6782a95 100644
--- a/src/openvpn/ssl_openssl.c
+++ b/src/openvpn/ssl_openssl.c
@@ -184,15 +184,23 @@ 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)
+ int tls_ver_max = TLS_VER_UNSPEC;
+ const int tls_ver_min =
+ (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK;
+
+ 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);
diff --git a/src/openvpn/ssl_polarssl.c b/src/openvpn/ssl_polarssl.c
index 387e636..b026a17 100644
--- a/src/openvpn/ssl_polarssl.c
+++ b/src/openvpn/ssl_polarssl.c
@@ -685,6 +685,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)
{
@@ -743,30 +777,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 */