From: Artem Boldariev Date: Mon, 20 Sep 2021 13:53:27 +0000 (+0300) Subject: Add "prefer-server-ciphers" options to the "tls" clause X-Git-Tag: v9.17.19~17^2~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=16c6e2be066d586ea37e37338550a40634a618f0;p=thirdparty%2Fbind9.git Add "prefer-server-ciphers" options to the "tls" clause This commit adds support for enforcing the preference of server ciphers over the client ones. This way, the server attains control over the ciphers priority and, thus, can choose more strong cyphers when a client prioritises less strong ciphers over the more strong ones, which is beneficial when trying to achieve Perfect Forward Secrecy. --- diff --git a/bin/named/named.conf.rst b/bin/named/named.conf.rst index d1818a7ef6b..ff9e7de0f88 100644 --- a/bin/named/named.conf.rst +++ b/bin/named/named.conf.rst @@ -567,6 +567,7 @@ TLS dhparam-file quoted_string; hostname quoted_string; key-file quoted_string; + prefer-server-ciphers boolean; protocols { string; ... }; }; diff --git a/bin/named/server.c b/bin/named/server.c index d3e8d802d62..3c3ebd7b483 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -11025,6 +11025,8 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, isc_dscp_t dscp = -1; const char *key = NULL, *cert = NULL, *dhparam_file = NULL, *ciphers = NULL; + bool tls_prefer_server_ciphers = false, + tls_prefer_server_ciphers_set = false; bool do_tls = false, no_tls = false, http = false; ns_listenelt_t *delt = NULL; uint32_t tls_protos = 0; @@ -11049,6 +11051,7 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, const cfg_obj_t *tlsmap = NULL; const cfg_obj_t *tls_proto_list = NULL; const cfg_obj_t *ciphers_obj = NULL; + const cfg_obj_t *prefer_server_ciphers_obj = NULL; do_tls = true; @@ -11097,14 +11100,27 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, ISC_R_SUCCESS) { ciphers = cfg_obj_asstring(ciphers_obj); } + + if (cfg_map_get(tlsmap, "prefer-server-ciphers", + &prefer_server_ciphers_obj) == + ISC_R_SUCCESS) + { + tls_prefer_server_ciphers = cfg_obj_asboolean( + prefer_server_ciphers_obj); + tls_prefer_server_ciphers_set = true; + } } } - tls_params = (ns_listen_tls_params_t){ .key = key, - .cert = cert, - .protocols = tls_protos, - .dhparam_file = dhparam_file, - .ciphers = ciphers }; + tls_params = (ns_listen_tls_params_t){ + .key = key, + .cert = cert, + .protocols = tls_protos, + .dhparam_file = dhparam_file, + .ciphers = ciphers, + .prefer_server_ciphers = tls_prefer_server_ciphers, + .prefer_server_ciphers_set = tls_prefer_server_ciphers_set, + }; httpobj = cfg_tuple_get(ltup, "http"); if (httpobj != NULL && cfg_obj_isstring(httpobj)) { diff --git a/bin/tests/system/checkconf/good-doh-tlsopts.conf b/bin/tests/system/checkconf/good-doh-tlsopts.conf index 7583c70cd50..f6cafa342f7 100644 --- a/bin/tests/system/checkconf/good-doh-tlsopts.conf +++ b/bin/tests/system/checkconf/good-doh-tlsopts.conf @@ -15,6 +15,7 @@ tls local-tls { cert-file "cert.pem"; dhparam-file "dhparam.pem"; ciphers "HIGH:!aNULL:!MD5:!RC4"; + prefer-server-ciphers yes; }; http local-http-server { diff --git a/bin/tests/system/checkconf/good-dot-tlsopts.conf b/bin/tests/system/checkconf/good-dot-tlsopts.conf index 1a0029d2201..8912646f65a 100644 --- a/bin/tests/system/checkconf/good-dot-tlsopts.conf +++ b/bin/tests/system/checkconf/good-dot-tlsopts.conf @@ -15,6 +15,7 @@ tls local-tls { cert-file "cert.pem"; dhparam-file "dhparam.pem"; ciphers "HIGH:!aNULL:!MD5:!RC4"; + prefer-server-ciphers yes; }; options { diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index 46f24ec5366..b6a7c14e273 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -293,7 +293,7 @@ The following statements are supported: Declares communication channels to get access to ``named`` statistics. ``tls`` - Specifies configuration information for a TLS connection, including a ``key-file``, ``cert-file``, ``ca-file``, ``dhparam-file``, ``hostname``, ``ciphers``, and ``protocols``. + Specifies configuration information for a TLS connection, including a ``key-file``, ``cert-file``, ``ca-file``, ``dhparam-file``, ``hostname``, ``ciphers``, ``protocols``, and ``prefer-server-ciphers``. ``http`` Specifies configuration information for an HTTP connection, including ``endponts``, ``listener-clients`` and ``streams-per-connection``. @@ -4792,6 +4792,9 @@ The following options can be specified in a ``tls`` statement: (see https://www.openssl.org/docs/man1.1.1/man1/ciphers.html for details). + ``prefer-server-ciphers`` + Specifies that server ciphers should be preferred over client ones. + There are two built-in TLS connection configurations: ``ephemeral``, uses a temporary key and certificate created for the current ``named`` session only, and ``none``, which can be used when setting up an HTTP diff --git a/doc/man/named.conf.5in b/doc/man/named.conf.5in index eb7cf4c5606..036d5899495 100644 --- a/doc/man/named.conf.5in +++ b/doc/man/named.conf.5in @@ -658,6 +658,7 @@ tls string { dhparam\-file quoted_string; hostname quoted_string; key\-file quoted_string; + prefer\-server\-ciphers boolean; protocols { string; ... }; }; .ft P diff --git a/doc/misc/options b/doc/misc/options index 1a708a61636..da7fcceb311 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -463,6 +463,7 @@ tls { dhparam-file ; hostname ; key-file ; + prefer-server-ciphers ; protocols { ; ... }; }; // may occur multiple times diff --git a/doc/misc/options.active b/doc/misc/options.active index 91a555f5a52..f579cc2835e 100644 --- a/doc/misc/options.active +++ b/doc/misc/options.active @@ -460,6 +460,7 @@ tls { dhparam-file ; hostname ; key-file ; + prefer-server-ciphers ; protocols { ; ... }; }; // may occur multiple times diff --git a/doc/misc/tls.grammar.rst b/doc/misc/tls.grammar.rst index 17c0c36bac1..4cb078da947 100644 --- a/doc/misc/tls.grammar.rst +++ b/doc/misc/tls.grammar.rst @@ -7,5 +7,6 @@ dhparam-file ; hostname ; key-file ; + prefer-server-ciphers ; protocols { ; ... }; }; diff --git a/lib/isc/include/isc/tls.h b/lib/isc/include/isc/tls.h index 90f185e825c..5c32053df32 100644 --- a/lib/isc/include/isc/tls.h +++ b/lib/isc/include/isc/tls.h @@ -114,6 +114,16 @@ isc_tlsctx_set_cipherlist(isc_tlsctx_t *ctx, const char *cipherlist); * \li 'cipherlist' a valid pointer to a non empty string. */ +void +isc_tlsctx_prefer_server_ciphers(isc_tlsctx_t *ctx, const bool prefer); +/*%< + * Make the given TLS context 'ctx' to prefer or to not prefer + * server side ciphers during the ciphers negotiation. + * + * Requires: + * \li 'ctx' != NULL. + */ + isc_tls_t * isc_tls_create(isc_tlsctx_t *ctx); /*%< diff --git a/lib/isc/tls.c b/lib/isc/tls.c index cec6c5ff433..f2dcbf187bc 100644 --- a/lib/isc/tls.c +++ b/lib/isc/tls.c @@ -562,6 +562,18 @@ isc_tlsctx_set_cipherlist(isc_tlsctx_t *ctx, const char *cipherlist) { RUNTIME_CHECK(SSL_CTX_set_cipher_list(ctx, cipherlist) == 1); } +void +isc_tlsctx_prefer_server_ciphers(isc_tlsctx_t *ctx, const bool prefer) { + REQUIRE(ctx != NULL); + + if (prefer) { + (void)SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + } else { + (void)SSL_CTX_clear_options(ctx, + SSL_OP_CIPHER_SERVER_PREFERENCE); + } +} + isc_tls_t * isc_tls_create(isc_tlsctx_t *ctx) { isc_tls_t *newctx = NULL; diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index ceea97480a6..0f8329f26ad 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -3890,6 +3890,7 @@ static cfg_clausedef_t tls_clauses[] = { { "dhparam-file", &cfg_type_qstring, 0 }, { "protocols", &cfg_type_tlsprotos, 0 }, { "ciphers", &cfg_type_astring, 0 }, + { "prefer-server-ciphers", &cfg_type_boolean, 0 }, { NULL, NULL, 0 } }; diff --git a/lib/ns/include/ns/listenlist.h b/lib/ns/include/ns/listenlist.h index 5b8d68edb9e..207c1f6ab38 100644 --- a/lib/ns/include/ns/listenlist.h +++ b/lib/ns/include/ns/listenlist.h @@ -65,6 +65,8 @@ typedef struct ns_listen_tls_params { uint32_t protocols; const char *dhparam_file; const char *ciphers; + bool prefer_server_ciphers; + bool prefer_server_ciphers_set; } ns_listen_tls_params_t; /*** diff --git a/lib/ns/listenlist.c b/lib/ns/listenlist.c index 68aab57cfa3..600ee64ceb7 100644 --- a/lib/ns/listenlist.c +++ b/lib/ns/listenlist.c @@ -59,6 +59,11 @@ ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, if (tls_params->ciphers != NULL) { isc_tlsctx_set_cipherlist(sslctx, tls_params->ciphers); } + + if (tls_params->prefer_server_ciphers_set) { + isc_tlsctx_prefer_server_ciphers( + sslctx, tls_params->prefer_server_ciphers); + } } elt = isc_mem_get(mctx, sizeof(*elt));