libtls: Make min/max TLS version configurable

Except for the tls_test tool, the versions now default to those
configured in strongswan.conf.
This commit is contained in:
Tobias Brunner 2021-01-13 14:40:40 +01:00
parent 9389fef78a
commit 663969ddf7
9 changed files with 99 additions and 29 deletions

View 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.

View 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;

View 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");

View 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);

View 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,
);

View 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;

View 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,
);

View 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,
};
/**
@ -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
*/

View 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
*/