From: Tobias Brunner Date: Wed, 13 Jan 2021 13:40:40 +0000 (+0100) Subject: libtls: Make min/max TLS version configurable X-Git-Tag: 5.9.2rc1~23^2~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=663969ddf7856f7f92c27ed78accc5bdeb303215;p=thirdparty%2Fstrongswan.git libtls: Make min/max TLS version configurable Except for the tls_test tool, the versions now default to those configured in strongswan.conf. --- diff --git a/conf/options/charon.opt b/conf/options/charon.opt index d57fb4cedf..eb835e88e4 100644 --- a/conf/options/charon.opt +++ b/conf/options/charon.opt @@ -473,6 +473,12 @@ charon.tls.mac charon.tls.suites List of TLS cipher suites. +charon.tls.version_min = 1.0 + Minimum TLS version to negotiate. + +charon.tls.version_max = 1.3 + Maximum TLS version to negotiate. + charon.user Name of the user the daemon changes to after startup. diff --git a/scripts/tls_test.c b/scripts/tls_test.c index 0040e23a3e..5ee7e37142 100644 --- a/scripts/tls_test.c +++ b/scripts/tls_test.c @@ -294,22 +294,13 @@ static void init() atexit(cleanup); } -/** - * Used to parse TLS versions - */ -ENUM(numeric_version_names, TLS_1_0, TLS_1_3, - "1.0", - "1.1", - "1.2", - "1.3"); - int main(int argc, char *argv[]) { char *address = NULL; bool listen = FALSE; int port = 0, times = -1, res, family = AF_UNSPEC; identification_t *server, *client = NULL; - tls_version_t min_version = TLS_1_0, max_version = TLS_1_3; + tls_version_t min_version = TLS_SUPPORTED_MIN, max_version = TLS_SUPPORTED_MAX; tls_cache_t *cache; host_t *host; @@ -387,21 +378,24 @@ int main(int argc, char *argv[]) family = AF_INET6; continue; case 'm': - if (!enum_from_name(numeric_version_names, optarg, &min_version)) + if (!enum_from_name(tls_numeric_version_names, optarg, + &min_version)) { fprintf(stderr, "unknown minimum TLS version: %s\n", optarg); return 1; } continue; case 'M': - if (!enum_from_name(numeric_version_names, optarg, &max_version)) + if (!enum_from_name(tls_numeric_version_names, optarg, + &max_version)) { fprintf(stderr, "unknown maximum TLS version: %s\n", optarg); return 1; } continue; case 'v': - if (!enum_from_name(numeric_version_names, optarg, &min_version)) + if (!enum_from_name(tls_numeric_version_names, optarg, + &min_version)) { fprintf(stderr, "unknown TLS version: %s\n", optarg); return 1; diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c index ab8c7273b4..4937f32a2a 100644 --- a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c @@ -877,7 +877,7 @@ static bool soap_init(private_tnc_ifmap_soap_t *this) /* open TLS socket */ this->tls = tls_socket_create(FALSE, server_id, client_id, this->fd, - NULL, TLS_1_0, TLS_1_2, FALSE); + NULL, TLS_UNSPEC, TLS_UNSPEC, FALSE); if (!this->tls) { DBG1(DBG_TNC, "creating TLS socket failed"); diff --git a/src/libpttls/pt_tls_client.c b/src/libpttls/pt_tls_client.c index 59842368f9..b7fc4c70d5 100644 --- a/src/libpttls/pt_tls_client.c +++ b/src/libpttls/pt_tls_client.c @@ -85,7 +85,7 @@ static bool make_connection(private_pt_tls_client_t *this) } this->tls = tls_socket_create(FALSE, this->server, this->client, fd, - NULL, TLS_1_0, TLS_1_2, FALSE); + NULL, TLS_UNSPEC, TLS_UNSPEC, FALSE); if (!this->tls) { close(fd); diff --git a/src/libpttls/pt_tls_server.c b/src/libpttls/pt_tls_server.c index 4c484fbb8e..1ad6165f6c 100644 --- a/src/libpttls/pt_tls_server.c +++ b/src/libpttls/pt_tls_server.c @@ -532,8 +532,8 @@ pt_tls_server_t *pt_tls_server_create(identification_t *server, int fd, .destroy = _destroy, }, .state = PT_TLS_SERVER_VERSION, - .tls = tls_socket_create(TRUE, server, NULL, fd, NULL, TLS_1_0, TLS_1_2, - FALSE), + .tls = tls_socket_create(TRUE, server, NULL, fd, NULL, TLS_UNSPEC, + TLS_UNSPEC, FALSE), .tnccs = (tls_t*)tnccs, .auth = auth, ); diff --git a/src/libtls/tests/suites/test_socket.c b/src/libtls/tests/suites/test_socket.c index de1b516821..ee470e2805 100644 --- a/src/libtls/tests/suites/test_socket.c +++ b/src/libtls/tests/suites/test_socket.c @@ -401,7 +401,7 @@ static job_requeue_t serve_echo(echo_server_config_t *config) } tls = tls_socket_create(TRUE, server, client, cfd, NULL, - TLS_1_0, config->version, TRUE); + TLS_SUPPORTED_MIN, config->version, TRUE); ck_assert(tls != NULL); while (TRUE) @@ -477,7 +477,7 @@ static void run_echo_client(echo_server_config_t *config) ck_assert(connect(fd, host->get_sockaddr(host), *host->get_sockaddr_len(host)) != -1); tls = tls_socket_create(FALSE, server, client, fd, NULL, - TLS_1_0, config->version, TRUE); + TLS_SUPPORTED_MIN, config->version, TRUE); ck_assert(tls != NULL); wr = rd = 0; diff --git a/src/libtls/tls.c b/src/libtls/tls.c index 52e06a446e..4cb68ba298 100644 --- a/src/libtls/tls.c +++ b/src/libtls/tls.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2021 Tobias Brunner * Copyright (C) 2020 Pascal Knecht * HSR Hochschule fuer Technik Rapperswil * @@ -27,7 +28,9 @@ #include "tls_server.h" #include "tls_peer.h" -ENUM_BEGIN(tls_version_names, SSL_2_0, SSL_2_0, +ENUM_BEGIN(tls_version_names, TLS_UNSPEC, TLS_UNSPEC, + "TLS UNSPEC"); +ENUM_NEXT(tls_version_names, SSL_2_0, SSL_2_0, TLS_UNSPEC, "SSLv2"); ENUM_NEXT(tls_version_names, SSL_3_0, TLS_1_3, SSL_2_0, "SSLv3", @@ -37,6 +40,15 @@ ENUM_NEXT(tls_version_names, SSL_3_0, TLS_1_3, SSL_2_0, "TLS 1.3"); ENUM_END(tls_version_names, TLS_1_3); +/** + * Only supported versions are mapped + */ +ENUM(tls_numeric_version_names, TLS_SUPPORTED_MIN, TLS_SUPPORTED_MAX, + "1.0", + "1.1", + "1.2", + "1.3"); + ENUM(tls_content_type_names, TLS_CHANGE_CIPHER_SPEC, TLS_APPLICATION_DATA, "ChangeCipherSpec", "Alert", @@ -435,25 +447,74 @@ METHOD(tls_t, get_peer_id, identification_t*, return this->handshake->get_peer_id(this->handshake); } +/** + * Determine the min/max versions + */ +static void determine_versions(private_tls_t *this) +{ + tls_version_t version; + char *version_str; + + if (this->version_min == TLS_UNSPEC) + { + this->version_min = TLS_SUPPORTED_MIN; + + version_str = lib->settings->get_str(lib->settings, "%s.tls.version_min", + NULL, lib->ns); + if (version_str && + enum_from_name(tls_numeric_version_names, version_str, &version)) + { + this->version_min = version; + } + } + if (this->version_max == TLS_UNSPEC) + { + this->version_max = TLS_SUPPORTED_MAX; + + version_str = lib->settings->get_str(lib->settings, "%s.tls.version_max", + NULL, lib->ns); + if (version_str && + enum_from_name(tls_numeric_version_names, version_str, &version)) + { + this->version_max = version; + } + } + if (this->version_max < this->version_min) + { + this->version_min = this->version_max; + } +} + METHOD(tls_t, get_version_max, tls_version_t, private_tls_t *this) { + determine_versions(this); return this->version_max; } METHOD(tls_t, get_version_min, tls_version_t, private_tls_t *this) { + determine_versions(this); return this->version_min; } METHOD(tls_t, set_version, bool, private_tls_t *this, tls_version_t min_version, tls_version_t max_version) { - if (min_version < this->version_min || - max_version > this->version_max || - min_version > max_version || - min_version < TLS_1_0) + if (min_version == TLS_UNSPEC) + { + min_version = this->version_min; + } + if (max_version == TLS_UNSPEC) + { + max_version = this->version_max; + } + if ((this->version_min != TLS_UNSPEC && min_version < this->version_min) || + (this->version_max != TLS_UNSPEC && max_version > this->version_max) || + (min_version != TLS_UNSPEC && min_version < TLS_SUPPORTED_MIN) || + (max_version != TLS_UNSPEC && max_version > TLS_SUPPORTED_MAX) || + min_version > max_version) { return FALSE; } @@ -461,7 +522,7 @@ METHOD(tls_t, set_version, bool, this->version_min = min_version; this->version_max = max_version; - if (min_version == max_version) + if (min_version != TLS_UNSPEC && min_version == max_version) { this->protection->set_version(this->protection, max_version); } @@ -555,8 +616,6 @@ tls_t *tls_create(bool is_server, identification_t *server, .destroy = _destroy, }, .is_server = is_server, - .version_min = TLS_1_0, - .version_max = TLS_1_3, .application = application, .purpose = purpose, ); diff --git a/src/libtls/tls.h b/src/libtls/tls.h index c85c9c452c..5a11f703dd 100644 --- a/src/libtls/tls.h +++ b/src/libtls/tls.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2021 Tobias Brunner * Copyright (C) 2020 Pascal Knecht * HSR Hochschule fuer Technik Rapperswil * @@ -50,12 +51,15 @@ typedef struct tls_t tls_t; * TLS/SSL version numbers */ enum tls_version_t { + TLS_UNSPEC = 0, SSL_2_0 = 0x0200, SSL_3_0 = 0x0300, TLS_1_0 = 0x0301, + TLS_SUPPORTED_MIN = TLS_1_0, TLS_1_1 = 0x0302, TLS_1_2 = 0x0303, TLS_1_3 = 0x0304, + TLS_SUPPORTED_MAX = TLS_1_3, }; /** @@ -63,6 +67,11 @@ enum tls_version_t { */ extern enum_name_t *tls_version_names; +/** + * Simple, numeric enum names for tls_version_t (only supported versions) + */ +extern enum_name_t *tls_numeric_version_names; + /** * TLS higher level content type */ diff --git a/src/libtls/tls_socket.h b/src/libtls/tls_socket.h index 2026cba415..08ccbd287a 100644 --- a/src/libtls/tls_socket.h +++ b/src/libtls/tls_socket.h @@ -99,13 +99,15 @@ struct tls_socket_t { /** * Create a tls_socket instance. * + * Use TLS_UNSPEC to default to the configured min/max version. + * * @param is_server TRUE to act as TLS server * @param server server identity * @param peer client identity, NULL for no client authentication * @param fd socket to read/write from * @param cache session cache to use, or NULL - * @param min_version minimum TLS version to negotiate - * @param max_version maximum TLS version to negotiate + * @param min_version minimum TLS version to negotiate or TLS_UNSPEC + * @param max_version maximum TLS version to negotiate or TLS_UNSPEC * @param nullok accept NULL encryption ciphers * @return TLS socket wrapper */