From: Arran Cudbard-Bell Date: Thu, 7 Sep 2017 05:07:02 +0000 (+0700) Subject: Use SSL_CTX_set_max_proto_version/SSL_CTX_set_min_proto_version where available X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d7ab215cd6ec6e37df39ae7cfd31a2fbd47c422d;p=thirdparty%2Ffreeradius-server.git Use SSL_CTX_set_max_proto_version/SSL_CTX_set_min_proto_version where available Debian OpenSSL may disable TLS < 1.2 by default. See here for details: https://lists.debian.org/debian-devel-announce/2017/08/msg00004.html Kurt Roeckx (author of the patch) stated that the original patch was modified so that the version could still be changed with SSL_CTX_set_max_proto_version and SSL_CTX_set_min_proto_version. But we still needed to add support for those functions. --- diff --git a/raddb/mods-available/eap b/raddb/mods-available/eap index 53cf4aad939..d7200515148 100644 --- a/raddb/mods-available/eap +++ b/raddb/mods-available/eap @@ -340,9 +340,23 @@ eap { # not calculate the EAP keys correctly. The fix is to upgrade # OpenSSL, or disable TLS 1.2 here. # - # For EAP-FAST, this MUST be set to "yes". + # For EAP-FAST, this MUST be set to 1.1 # - disable_tlsv1_2 = no + # SSLv2 and SSLv3 are permanently disabled due to security + # issues. + # +# tls_max_version = 1.1 + + # + # Prevents versions < tls_min_version from being negotiated. + # In general the higher the tls_min_version the more secure + # the protocol, but the narrower the range of supported TLS + # clients. + # + # SSLv2 and SSLv3 are permanently disabled due to security + # issues. + # +# tls_min_version = 1.0 # # Elliptical cryptography configuration diff --git a/src/include/tls-h b/src/include/tls-h index 34f01b5d696..75b2f9ba62a 100644 --- a/src/include/tls-h +++ b/src/include/tls-h @@ -232,9 +232,9 @@ struct fr_tls_conf_t { //!< If false, the complete chain must be provided in //!< certificate file. bool disable_single_dh_use; - bool disable_tlsv1; //!< Prevent TLSv1 being negotiated. - bool disable_tlsv1_1; //!< Prevent TLSv1.1 being negotiated. - bool disable_tlsv1_2; //!< Prevent TLSv1.2 being negotiated. + + float tls_max_version; //!< Maximum TLS version allowed. + float tls_min_version; //!< Minimum TLS version allowed. uint32_t fragment_size; //!< Maximum record fragment, or record size. bool check_crl; //!< Check certificate revocation lists. diff --git a/src/main/tls/conf.c b/src/main/tls/conf.c index 58dff83f6f5..9b4ca2bd6b2 100644 --- a/src/main/tls/conf.c +++ b/src/main/tls/conf.c @@ -119,17 +119,21 @@ CONF_PARSER tls_server_config[] = { #endif #ifdef SSL_OP_NO_TLSv1 - { FR_CONF_OFFSET("disable_tlsv1", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1) }, + { FR_CONF_DEPRECATED("disable_tlsv1", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1) }, #endif #ifdef SSL_OP_NO_TLSv1_1 - { FR_CONF_OFFSET("disable_tlsv1_1", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1_1) }, + { FR_CONF_DEPRECATED("disable_tlsv1_1", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1_1) }, #endif #ifdef SSL_OP_NO_TLSv1_2 - { FR_CONF_OFFSET("disable_tlsv1_2", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1_2) }, + { FR_CONF_DEPRECATED("disable_tlsv1_2", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1_2) }, #endif + { FR_CONF_OFFSET("tls_max_version", FR_TYPE_FLOAT32, fr_tls_conf_t, tls_max_version) }, + + { FR_CONF_OFFSET("tls_min_version", FR_TYPE_FLOAT32, fr_tls_conf_t, tls_min_version), .dflt = "1.0" }, + { FR_CONF_POINTER("cache", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) cache_config }, { FR_CONF_POINTER("verify", FR_TYPE_SUBSECTION, NULL), .subcs = (void const *) verify_config }, @@ -165,16 +169,20 @@ CONF_PARSER tls_client_config[] = { #endif #ifdef SSL_OP_NO_TLSv1 - { FR_CONF_OFFSET("disable_tlsv1", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1) }, + { FR_CONF_DEPRECATED("disable_tlsv1", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1) }, #endif #ifdef SSL_OP_NO_TLSv1_1 - { FR_CONF_OFFSET("disable_tlsv1_1", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1_1) }, + { FR_CONF_DEPRECATED("disable_tlsv1_1", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1_1) }, #endif #ifdef SSL_OP_NO_TLSv1_2 - { FR_CONF_OFFSET("disable_tlsv1_2", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1_2) }, + { FR_CONF_DEPRECATED("disable_tlsv1_2", FR_TYPE_BOOL, fr_tls_conf_t, disable_tlsv1_2) }, #endif + { FR_CONF_OFFSET("tls_max_version", FR_TYPE_FLOAT32, fr_tls_conf_t, tls_max_version) }, + + { FR_CONF_OFFSET("tls_min_version", FR_TYPE_FLOAT32, fr_tls_conf_t, tls_min_version), .dflt = "1.0" }, + CONF_PARSER_TERMINATOR }; @@ -411,7 +419,7 @@ fr_tls_conf_t *tls_conf_parse_server(CONF_SECTION *cs) * OpenSSL 1.0.1f and 1.0.1g get the MS-MPPE keys wrong. */ #if (OPENSSL_VERSION_NUMBER >= 0x10010060L) && (OPENSSL_VERSION_NUMBER < 0x10010060L) - conf->disable_tlsv1_2 = true; + conf->max_tls_version = 1.1; WARN("OpenSSL version in range 1.0.1f-1.0.1g. " "TLSv1.2 disabled to workaround broken keying material export"); #endif diff --git a/src/main/tls/ctx.c b/src/main/tls/ctx.c index c49ab404989..7f67676cb6d 100644 --- a/src/main/tls/ctx.c +++ b/src/main/tls/ctx.c @@ -121,7 +121,6 @@ SSL_CTX *tls_ctx_alloc(fr_tls_conf_t const *conf, bool client) X509_STORE *cert_vpstore; int verify_mode = SSL_VERIFY_NONE; int ctx_options = 0; - int ctx_tls_versions = 0; int type; void *app_data_index; @@ -287,36 +286,116 @@ load_ca: post_ca: #endif +#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* - * We never want SSLv2 or SSLv3. + * SSL_CTX_set_(min|max)_proto_version was included in OpenSSL 1.1.0 + * + * This version already defines macros for TLS1_2_VERSION and + * below, so we don't need to check for them explicitly. + * + * TLS1_3_VERSION is available in OpenSSL 1.1.1. + * + * TLS1_4_VERSION in speculative. */ - ctx_options |= SSL_OP_NO_SSLv2; - ctx_options |= SSL_OP_NO_SSLv3; + if (conf->tls_max_version > 0.0) { + int max_version = 0; - /* - * As of 3.0.5, we always allow TLSv1.1 and TLSv1.2. - * Though they can be *globally* disabled if necessary.x - */ -#ifdef SSL_OP_NO_TLSv1 - if (conf->disable_tlsv1) ctx_options |= SSL_OP_NO_TLSv1; + if (conf->tls_min_version > conf->tls_max_version) { + ERROR("tls_min_version (%f) must be <= tls_max_version (%f)", + conf->tls_min_version, conf->tls_max_version); + return NULL; + } - ctx_tls_versions |= SSL_OP_NO_TLSv1; -#endif -#ifdef SSL_OP_NO_TLSv1_1 - if (conf->disable_tlsv1_1) ctx_options |= SSL_OP_NO_TLSv1_1; + if (conf->tls_max_version < 1.0) { + ERROR("tls_max_version must be >= 1.0 as SSLv2 and SSLv3 are permanently disabled"); + return NULL; + } - ctx_tls_versions |= SSL_OP_NO_TLSv1_1; -#endif -#ifdef SSL_OP_NO_TLSv1_2 - if (conf->disable_tlsv1_2) ctx_options |= SSL_OP_NO_TLSv1_2; +# ifdef TLS1_4_VERSION + else if (conf->tls_max_version >= 1.4) max_version = TLS1_4_VERSION; +# endif +# ifdef TLS1_3_VERSION + else if (conf->tls_max_version >= 1.3) max_version = TLS1_3_VERSION; +# endif + else if (conf->tls_max_version >= 1.2) max_version = TLS1_2_VERSION; + else if (conf->tls_max_version >= 1.1) max_version = TLS1_1_VERSION; + else max_version = TLS1_VERSION; - ctx_tls_versions |= SSL_OP_NO_TLSv1_2; -#endif + if (!SSL_CTX_set_max_proto_version(ctx, max_version)) { + tls_log_error(NULL, "Failed setting TLS maximum version"); + return NULL; + } + } - if ((ctx_options & ctx_tls_versions) == ctx_tls_versions) { - ERROR("You have disabled all available TLS versions. EAP will not work"); - return NULL; + { + int min_version = TLS1_VERSION; + + if (conf->tls_min_version < 1.0) { + ERROR("tls_min_version must be >= 1.0 as SSLv2 and SSLv3 are permanently disabled"); + return NULL; + } +# ifdef TLS1_4_VERSION + else if (conf->tls_min_version >= 1.4) min_version = TLS1_4_VERSION; +# endif +# ifdef TLS1_3_VERSION + else if (conf->tls_min_version >= 1.3) min_version = TLS1_3_VERSION; +# endif + else if (conf->tls_min_version >= 1.2) min_version = TLS1_2_VERSION; + else if (conf->tls_min_version >= 1.1) min_version = TLS1_1_VERSION; + else min_version = TLS1_VERSION; + + if (!SSL_CTX_set_min_proto_version(ctx, min_version)) { + tls_log_error(NULL, "Failed setting TLS minimum version"); + return NULL; + } + } +#else + { + int ctx_tls_versions = 0; + + /* + * We never want SSLv2 or SSLv3. + */ + ctx_options |= SSL_OP_NO_SSLv2; + ctx_options |= SSL_OP_NO_SSLv3; + + if (conf->tls_min_version < 1.0) { + ERROR("SSLv2 and SSLv3 are permanently disabled due to critical security issues"); + return NULL; + } + + /* + * As of 3.0.5, we always allow TLSv1.1 and TLSv1.2. + * Though they can be *globally* disabled if necessary.x + */ +# ifdef SSL_OP_NO_TLSv1 + if (conf->tls_min_version > 1.0) ctx_options |= SSL_OP_NO_TLSv1; + if ((conf->tls_max_version != 0.0) && (conf->tls_max_version < 1.0)) { + ctx_options |= SSL_OP_NO_TLSv1; + } + ctx_tls_versions |= SSL_OP_NO_TLSv1; +# endif +# ifdef SSL_OP_NO_TLSv1_1 + if (conf->tls_min_version > 1.1) ctx_options |= SSL_OP_NO_TLSv1_1; + if ((conf->tls_max_version != 0.0) && (conf->tls_max_version < 1.1)) { + ctx_options |= SSL_OP_NO_TLSv1_1; + } + ctx_tls_versions |= SSL_OP_NO_TLSv1_1; +# endif +# ifdef SSL_OP_NO_TLSv1_2 + if (conf->tls_min_version > 1.2) ctx_options |= SSL_OP_NO_TLSv1_2; + if ((conf->tls_max_version != 0.0) && (conf->tls_max_version < 1.2)) { + ctx_options |= SSL_OP_NO_TLSv1_2; + } + ctx_tls_versions |= SSL_OP_NO_TLSv1_2; +# endif + + if ((ctx_options & ctx_tls_versions) == ctx_tls_versions) { + ERROR("You have disabled all available TLS versions. EAP will not work"); + return NULL; + } } +#endif #ifdef SSL_OP_NO_TICKET ctx_options |= SSL_OP_NO_TICKET; diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c index 588e2035641..51730d95c1a 100644 --- a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c +++ b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c @@ -107,8 +107,8 @@ static int mod_instantiate(void *instance, CONF_SECTION *cs) } // FIXME TLSv1.2 uses a different PRF and SSL_export_keying_material("key expansion") is forbidden - if (!inst->tls_conf->disable_tlsv1_2) { - cf_log_err_by_name(cs, "disable_tlsv1_2", "require disable_tlsv1_2=yes"); + if ((inst->tls_conf->tls_max_version > 1.1) || (inst->tls_conf->tls_max_version == 0.0)) { + cf_log_err_by_name(cs, "tls_max_version", "require tls_max_version <= 1.1"); return -1; }