diff --git a/src/core/ddsi/include/ddsi/q_config.h b/src/core/ddsi/include/ddsi/q_config.h index 7810ea4..6f842b2 100644 --- a/src/core/ddsi/include/ddsi/q_config.h +++ b/src/core/ddsi/include/ddsi/q_config.h @@ -213,6 +213,13 @@ enum many_sockets_mode { MSM_MANY_UNICAST }; +#ifdef DDSI_INCLUDE_SSL +struct ssl_min_version { + int major; + int minor; +}; +#endif + struct config { int valid; @@ -301,6 +308,7 @@ struct config char * ssl_rand_file; char * ssl_key_pass; char * ssl_ciphers; + struct ssl_min_version ssl_min_version; #endif diff --git a/src/core/ddsi/src/ddsi_ssl.c b/src/core/ddsi/src/ddsi_ssl.c index 5ae6a19..ae99a2b 100644 --- a/src/core/ddsi/src/ddsi_ssl.c +++ b/src/core/ddsi/src/ddsi_ssl.c @@ -168,6 +168,7 @@ static int ddsi_ssl_password (char *buf, int num, int rwflag, void *udata) static SSL_CTX *ddsi_ssl_ctx_init (void) { SSL_CTX *ctx = SSL_CTX_new (SSLv23_method ()); + unsigned disallow_TLSv1_2; /* Load certificates */ if (! SSL_CTX_use_certificate_file (ctx, config.ssl_keystore, SSL_FILETYPE_PEM)) @@ -220,7 +221,32 @@ static SSL_CTX *ddsi_ssl_ctx_init (void) i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; SSL_CTX_set_verify (ctx, i, ddsi_ssl_verify); } - SSL_CTX_set_options (ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); + switch (config.ssl_min_version.major) + { + case 1: + switch (config.ssl_min_version.minor) + { + case 2: + disallow_TLSv1_2 = 0; + break; + case 3: +#ifdef SSL_OP_NO_TLSv1_2 + disallow_TLSv1_2 = SSL_OP_NO_TLSv1_2; +#else + DDS_LOG (DDS_LC_ERROR | DDS_LC_CONFIG, "tcp/ssl: openssl version does not support disabling TLSv1.2 as required by config\n"); + goto fail; +#endif + break; + default: + DDS_LOG (DDS_LC_ERROR | DDS_LC_CONFIG, "tcp/ssl: can't set minimum requested TLS version to %d.%d\n", config.ssl_min_version.major, config.ssl_min_version.minor); + goto fail; + } + break; + default: + DDS_LOG (DDS_LC_ERROR | DDS_LC_CONFIG, "tcp/ssl: can't set minimum requested TLS version to %d.%d\n", config.ssl_min_version.major, config.ssl_min_version.minor); + goto fail; + } + SSL_CTX_set_options (ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | disallow_TLSv1_2); return ctx; fail: diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 6cea54a..ecfbd53 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -165,6 +165,9 @@ DUPF(durability_cdr); DUPF(transport_selector); DUPF(many_sockets_mode); DU(deaf_mute); +#ifdef DDSI_INCLUDE_SSL +DUPF(min_tls_version); +#endif #undef DUPF #undef DU #undef PF @@ -691,6 +694,8 @@ static const struct cfgelem ssl_cfgelems[] = { "
The set of ciphers used by SSL/TLS
" }, { LEAF("EntropyFile"), 1, "", ABSOFF(ssl_rand_file), 0, uf_string, ff_free, pf_string, "The SSL/TLS random entropy file name.
" }, + { LEAF("MinimumTLSVersion"), 1, "1.3", ABSOFF(ssl_min_version), 0, uf_min_tls_version, 0, pf_min_tls_version, + "The minimum TLS version that may be negotiated, valid values are 1.2 and 1.3.
" }, END_MARKER }; #endif @@ -1408,6 +1413,30 @@ static void pf_besmode(struct cfgst *cfgst, void *parent, struct cfgelem const * cfg_log(cfgst, "%s%s", str, is_default ? " [def]" : ""); } +#ifdef DDSI_INCLUDE_SSL +static int uf_min_tls_version(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) +{ + static const char *vs[] = { + "1.2", "1.3", NULL + }; + static const struct ssl_min_version ms[] = { + {1,2}, {1,3}, {0,0} + }; + int idx = list_index(vs, value); + struct ssl_min_version *elem = cfg_address(cfgst, parent, cfgelem); + assert(sizeof(vs) / sizeof(*vs) == sizeof(ms) / sizeof(*ms)); + if ( idx < 0 ) + return cfg_error(cfgst, "'%s': undefined value", value); + *elem = ms[idx]; + return 1; +} + +static void pf_min_tls_version(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) +{ + struct ssl_min_version *p = cfg_address(cfgst, parent, cfgelem); + cfg_log(cfgst, "%d.%d%s", p->major, p->minor, is_default ? " [def]" : ""); +} +#endif static int uf_durability_cdr(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value) {