libtls: Make min/max TLS version configurable
authorTobias Brunner <tobias@strongswan.org>
Wed, 13 Jan 2021 13:40:40 +0000 (14:40 +0100)
committerTobias Brunner <tobias@strongswan.org>
Fri, 12 Feb 2021 13:35:23 +0000 (14:35 +0100)
Except for the tls_test tool, the versions now default to those
configured in strongswan.conf.

conf/options/charon.opt
scripts/tls_test.c
src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c
src/libpttls/pt_tls_client.c
src/libpttls/pt_tls_server.c
src/libtls/tests/suites/test_socket.c
src/libtls/tls.c
src/libtls/tls.h
src/libtls/tls_socket.h

index d57fb4c..eb835e8 100644 (file)
@@ -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.
 
index 0040e23..5ee7e37 100644 (file)
@@ -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;
index ab8c727..4937f32 100644 (file)
@@ -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");
index 5984236..b7fc4c7 100644 (file)
@@ -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);
index 4c484fb..1ad6165 100644 (file)
@@ -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,
        );
index de1b516..ee470e2 100644 (file)
@@ -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;
index 52e06a4..4cb68ba 100644 (file)
@@ -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,
        );
index c85c9c4..5a11f70 100644 (file)
@@ -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,
 };
 
 /**
@@ -64,6 +68,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
  */
 enum tls_content_type_t {
index 2026cba..08ccbd2 100644 (file)
@@ -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
  */