diff --git a/CHANGES b/CHANGES index 7b37b4037a..0ee3ee6977 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,22 @@ +5729. [func] Allow finer control over the TLS protocol by + implementing more options within "tls" clauses, namely: + - Diffie-Hellman parameters via + 'dhparam-file "";' + - OpenSSL cipher list string via + 'ciphers "";' + - Server or client ciphers preference via + 'prefer-server-ciphers yes|no;' + - Ability to explicitly enable or disable stateless + TLS session tickets via 'session-tickets yes|no;' + The options are enough to implement perfect forward + secrecy in DNS-over-TLS, DNS-over-HTTPS transports. + Most of these options were no-op before this + change. [GL #2796] + +5728. [func] Allow specifying supported TLS protocol + versions within "tls" clauses + (e.g. protocols { TLSv1.2; TLSv1.3; };). [GL #2795] + 5727. [bug] Ignore the missing zones when doing a reload on a catalog zone, and make sure to restore them later on. [GL #2308] diff --git a/bin/named/named.conf.rst b/bin/named/named.conf.rst index d805ff65ad..7274c2044a 100644 --- a/bin/named/named.conf.rst +++ b/bin/named/named.conf.rst @@ -563,11 +563,13 @@ TLS tls string { ca-file quoted_string; cert-file quoted_string; - ciphers string; // experimental - dh-param quoted_string; // experimental + ciphers string; + dhparam-file quoted_string; hostname quoted_string; key-file quoted_string; - protocols sslprotos; // experimental + prefer-server-ciphers boolean; + protocols { string; ... }; + session-tickets boolean; }; TRUST-ANCHORS diff --git a/bin/named/server.c b/bin/named/server.c index 4183786f63..e9d3bdc59e 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -413,9 +413,9 @@ named_server_reload(isc_task_t *task, isc_event_t *event); #ifdef HAVE_LIBNGHTTP2 static isc_result_t -listenelt_http(const cfg_obj_t *http, bool tls, const char *key, - const char *cert, in_port_t port, isc_mem_t *mctx, - ns_listenelt_t **target); +listenelt_http(const cfg_obj_t *http, bool tls, + const ns_listen_tls_params_t *tls_params, in_port_t port, + isc_mem_t *mctx, ns_listenelt_t **target); #endif static isc_result_t @@ -11023,9 +11023,15 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, const cfg_obj_t *http_server = NULL; in_port_t port = 0; isc_dscp_t dscp = -1; - const char *key = NULL, *cert = NULL; + const char *key = NULL, *cert = NULL, *dhparam_file = NULL, + *ciphers = NULL; + bool tls_prefer_server_ciphers = false, + tls_prefer_server_ciphers_set = false; + bool tls_session_tickets = false, tls_session_tickets_set = false; bool do_tls = false, no_tls = false, http = false; ns_listenelt_t *delt = NULL; + uint32_t tls_protos = 0; + ns_listen_tls_params_t tls_params = { 0 }; REQUIRE(target != NULL && *target == NULL); @@ -11041,8 +11047,13 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, } else if (strcasecmp(tlsname, "ephemeral") == 0) { do_tls = true; } else { - const cfg_obj_t *keyobj = NULL, *certobj = NULL; + const cfg_obj_t *keyobj = NULL, *certobj = NULL, + *dhparam_obj = NULL; 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; + const cfg_obj_t *session_tickets_obj = NULL; do_tls = true; @@ -11059,9 +11070,70 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, CHECK(cfg_map_get(tlsmap, "cert-file", &certobj)); cert = cfg_obj_asstring(certobj); + + if (cfg_map_get(tlsmap, "protocols", &tls_proto_list) == + ISC_R_SUCCESS) { + const cfg_listelt_t *proto = NULL; + INSIST(tls_proto_list != NULL); + for (proto = cfg_list_first(tls_proto_list); + proto != 0; proto = cfg_list_next(proto)) + { + const cfg_obj_t *tls_proto_obj = + cfg_listelt_value(proto); + const char *tls_sver = + cfg_obj_asstring(tls_proto_obj); + const isc_tls_protocol_version_t ver = + isc_tls_protocol_name_to_version( + tls_sver); + + INSIST(ver != + ISC_TLS_PROTO_VER_UNDEFINED); + INSIST(isc_tls_protocol_supported(ver)); + tls_protos |= ver; + } + } + + if (cfg_map_get(tlsmap, "dhparam-file", &dhparam_obj) == + ISC_R_SUCCESS) { + dhparam_file = cfg_obj_asstring(dhparam_obj); + } + + if (cfg_map_get(tlsmap, "ciphers", &ciphers_obj) == + 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; + } + + if (cfg_map_get(tlsmap, "session-tickets", + &session_tickets_obj) == ISC_R_SUCCESS) + { + tls_session_tickets = + cfg_obj_asboolean(session_tickets_obj); + tls_session_tickets_set = true; + } } } + 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, + .session_tickets = tls_session_tickets, + .session_tickets_set = tls_session_tickets_set + }; + httpobj = cfg_tuple_get(ltup, "http"); if (httpobj != NULL && cfg_obj_isstring(httpobj)) { const char *httpname = cfg_obj_asstring(httpobj); @@ -11144,14 +11216,14 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, #ifdef HAVE_LIBNGHTTP2 if (http) { - CHECK(listenelt_http(http_server, do_tls, key, cert, port, mctx, - &delt)); + CHECK(listenelt_http(http_server, do_tls, &tls_params, port, + mctx, &delt)); } #endif /* HAVE_LIBNGHTTP2 */ if (!http) { - CHECK(ns_listenelt_create(mctx, port, dscp, NULL, do_tls, key, - cert, &delt)); + CHECK(ns_listenelt_create(mctx, port, dscp, NULL, do_tls, + &tls_params, &delt)); } result = cfg_acl_fromconfig2(cfg_tuple_get(listener, "acl"), config, @@ -11169,9 +11241,9 @@ cleanup: #ifdef HAVE_LIBNGHTTP2 static isc_result_t -listenelt_http(const cfg_obj_t *http, bool tls, const char *key, - const char *cert, in_port_t port, isc_mem_t *mctx, - ns_listenelt_t **target) { +listenelt_http(const cfg_obj_t *http, bool tls, + const ns_listen_tls_params_t *tls_params, in_port_t port, + isc_mem_t *mctx, ns_listenelt_t **target) { isc_result_t result = ISC_R_SUCCESS; ns_listenelt_t *delt = NULL; char **endpoints = NULL; @@ -11184,7 +11256,11 @@ listenelt_http(const cfg_obj_t *http, bool tls, const char *key, isc_quota_t *quota = NULL; REQUIRE(target != NULL && *target == NULL); - REQUIRE((key == NULL) == (cert == NULL)); + + if (tls) { + INSIST(tls_params != NULL); + INSIST((tls_params->key == NULL) == (tls_params->cert == NULL)); + } if (port == 0) { port = tls ? named_g_httpsport : named_g_httpport; @@ -11239,7 +11315,7 @@ listenelt_http(const cfg_obj_t *http, bool tls, const char *key, isc_quota_init(quota, max_clients); } result = ns_listenelt_create_http(mctx, port, named_g_dscp, NULL, tls, - key, cert, endpoints, len, quota, + tls_params, endpoints, len, quota, max_streams, &delt); if (result != ISC_R_SUCCESS) { goto error; diff --git a/bin/tests/system/checkconf/bad-dot-badciphers.conf b/bin/tests/system/checkconf/bad-dot-badciphers.conf new file mode 100644 index 0000000000..e4a0abca20 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-badciphers.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; + ciphers "$bad:ciphers"; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-badprotocol.conf b/bin/tests/system/checkconf/bad-dot-badprotocol.conf new file mode 100644 index 0000000000..da3b5edeb1 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-badprotocol.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; + protocols { unknown; TLSv1.2; }; # bad TLS protocol version name +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-duplicatetls.conf b/bin/tests/system/checkconf/bad-dot-duplicatetls.conf new file mode 100644 index 0000000000..63f5874e7e --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-duplicatetls.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-ephemeral.conf b/bin/tests/system/checkconf/bad-dot-ephemeral.conf new file mode 100644 index 0000000000..3f0273036f --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-ephemeral.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# ephemeral is reserved for internal use +tls ephemeral { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +options { + listen-on port 853 tls ephemeral { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-nocert.conf b/bin/tests/system/checkconf/bad-dot-nocert.conf new file mode 100644 index 0000000000..20c1eaf837 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-nocert.conf @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; +}; + +http local-http-server { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; + +options { + listen-on { 10.53.0.1; }; + http-port 80; + https-port 443; + http-listener-clients 100; + http-streams-per-connection 100; + listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; }; + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-nokey.conf b/bin/tests/system/checkconf/bad-dot-nokey.conf new file mode 100644 index 0000000000..a6798bafee --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-nokey.conf @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + cert-file "cert.pem"; +}; + +http local-http-server { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; + +options { + listen-on { 10.53.0.1; }; + http-port 80; + https-port 443; + http-listener-clients 100; + http-streams-per-connection 100; + listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; }; + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-none.conf b/bin/tests/system/checkconf/bad-dot-none.conf new file mode 100644 index 0000000000..1eebc253d3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-none.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# none is reserved for internal use +tls none { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +options { + listen-on port 853 tls none { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-doh-tlsopts.conf b/bin/tests/system/checkconf/good-doh-tlsopts.conf new file mode 100644 index 0000000000..0de934bfe4 --- /dev/null +++ b/bin/tests/system/checkconf/good-doh-tlsopts.conf @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.2; }; + key-file "key.pem"; + cert-file "cert.pem"; + dhparam-file "dhparam.pem"; + ciphers "HIGH:!aNULL:!MD5:!RC4"; + prefer-server-ciphers yes; + session-tickets no; +}; + +http local-http-server { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; + +options { + listen-on { 10.53.0.1; }; + http-port 80; + https-port 443; + http-listener-clients 100; + http-streams-per-connection 100; + listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; }; + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-dot-tlsopts.conf b/bin/tests/system/checkconf/good-dot-tlsopts.conf new file mode 100644 index 0000000000..e68e6211e3 --- /dev/null +++ b/bin/tests/system/checkconf/good-dot-tlsopts.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.2; }; + key-file "key.pem"; + cert-file "cert.pem"; + dhparam-file "dhparam.pem"; + ciphers "HIGH:!aNULL:!MD5:!RC4"; + prefer-server-ciphers yes; + session-tickets no; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/doth/ns2/dhparam3072.pem b/bin/tests/system/doth/ns2/dhparam3072.pem new file mode 100644 index 0000000000..9c2e0aa42b --- /dev/null +++ b/bin/tests/system/doth/ns2/dhparam3072.pem @@ -0,0 +1,11 @@ +-----BEGIN DH PARAMETERS----- +MIIBiAKCAYEA5D/Oioe+G+EMf/9RVxmcV4rZAtqZpVTFHcX0ZulvdiQGCQmopm6K +3+0uoU2J6WVMjhna5nHD2NO9miRDI/jIxX9g9k6PedSB4o3fSTtkAnGtUbB8S+Ab +EHtWfd7FTES8P1n16HN7BfPXVbP8zTcK+jO63KdQoxueYoETcrw0Myi9Lm8ri8os +O4oQ+XAH7GzZ60bcYV9jge0XIRUGVnYZDjWMlnwMvZyjLivxKXTC9HPNA6FF1/0H +0LPhsfjdoLNsVHFzfQz7QELMfHbTd0C8y0UMDQw9FqUp0esHZ5gsTlqnDHp2ZHoR +JDfNl4yVO5Gv4HiFJ0NSdggefhESU3FRAOhMmUkctOCxk5hyPqGMsvofOajY2MBp +eCffrKuAU6/dGUeq8inwrZlAMIZ20WyskHmbHnc4DXo2Uo6xSZo3xyEq1ofXXwTZ +vPw4e12so3RJAT2a8UsHf7DG1tH+9ke7HCAJQWxUizRFRsMi1Nl/7ikS4f3zgIbX +GKz9+uk5eS6jAgEC +-----END DH PARAMETERS----- diff --git a/bin/tests/system/doth/ns2/named.conf.in b/bin/tests/system/doth/ns2/named.conf.in index 0a77cf9952..9d747c9f6a 100644 --- a/bin/tests/system/doth/ns2/named.conf.in +++ b/bin/tests/system/doth/ns2/named.conf.in @@ -18,6 +18,7 @@ controls { tls local { key-file "key.pem"; cert-file "cert.pem"; + dhparam-file "dhparam3072.pem"; }; http local { diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index 0a4627bf40..6db12cc859 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`` and ``hostname``. + Specifies configuration information for a TLS connection, including a ``key-file``, ``cert-file``, ``ca-file``, ``dhparam-file``, ``hostname``, ``ciphers``, ``protocols``, ``prefer-server-ciphers``, and ``session-tickets``. ``http`` Specifies configuration information for an HTTP connection, including ``endponts``, ``listener-clients`` and ``streams-per-connection``. @@ -4769,9 +4769,72 @@ The following options can be specified in a ``tls`` statement: ``ca-file`` Path to a file containing trusted TLS certificates. + ``dhparam-file`` + Path to a file containing Diffie-Hellman parameters, + which is needed to enable the cipher suites depending on the + Diffie-Hellman ephemeral key exchange (DHE). Having these parameters + specified is essential for enabling perfect forward secrecy capable + ciphers in TLSv1.2. + ``hostname`` The hostname associated with the certificate. + ``protocols`` + Allowed versions of the TLS protocol. TLS version 1.2 and higher are + supported, depending on the cryptographic library in use. Multiple + versions might be specified (e.g. + ``protocols { TLSv1.2; TLSv1.3; };``). + + ``ciphers`` + Cipher list which defines allowed ciphers, such as + ``HIGH:!aNULL:!MD5:!SHA1:!SHA256:!SHA384``. The string must be + formed according to the rules specified in the OpenSSL documentation + (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. + + ``session-tickets`` + Enables or disables session resumption through TLS session tickets, + as defined in RFC5077. Disabling the stateless session tickets + might be required in the cases when forward secrecy is needed, + or the TLS certificate and key pair is planned to be used across + multiple BIND instances. + +The options described above are used to control different aspects of +TLS functioning. Thus, most of them have no well-defined default +values, as these depend on the cryptographic library version in use +and system-wide cryptographic policy. On the other hand, by specifying +the needed options one could have a uniform configuration deployable +across a range of platforms. + +An example of privacy-oriented, perfect forward secrecy enabled +configuration can be found below. It can be used as a +starting point. + +:: + + tls local-tls { + key-file "/path/to/key.pem"; + cert-file "/path/to/fullchain_cert.pem"; + dhparam-file "/path/to/dhparam.pem"; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + session-tickets no; + }; + +A Diffie-Hellman parameters file can be generated using e.g. OpenSSL, +like follows: + +:: + openssl dhparam -out /path/to/dhparam.pem <3072_or_4096> + +Ensure that it gets generated on a machine with enough entropy from +external sources (e.g. the computer you work on should be fine, +the remote virtual machine or server might be not). These files do +not contain any sensitive data and can be shared if required. + 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 d22ad8022d..30d73bab2f 100644 --- a/doc/man/named.conf.5in +++ b/doc/man/named.conf.5in @@ -654,11 +654,13 @@ statistics\-channels { tls string { ca\-file quoted_string; cert\-file quoted_string; - ciphers string; // experimental - dh\-param quoted_string; // experimental + ciphers string; + dhparam\-file quoted_string; hostname quoted_string; key\-file quoted_string; - protocols sslprotos; // experimental + prefer\-server\-ciphers boolean; + protocols { string; ... }; + session\-tickets boolean; }; .ft P .fi diff --git a/doc/misc/options b/doc/misc/options index 7b82fcec62..06fec355af 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -459,11 +459,13 @@ statistics-channels { tls { ca-file ; cert-file ; - ciphers ; // experimental - dh-param ; // experimental + ciphers ; + dhparam-file ; hostname ; key-file ; - protocols ; // experimental + prefer-server-ciphers ; + protocols { ; ... }; + session-tickets ; }; // may occur multiple times trust-anchors { ( static-key | diff --git a/doc/misc/options.active b/doc/misc/options.active index b76a310443..226e77da17 100644 --- a/doc/misc/options.active +++ b/doc/misc/options.active @@ -456,11 +456,13 @@ statistics-channels { tls { ca-file ; cert-file ; - ciphers ; // experimental - dh-param ; // experimental + ciphers ; + dhparam-file ; hostname ; key-file ; - protocols ; // experimental + prefer-server-ciphers ; + protocols { ; ... }; + session-tickets ; }; // may occur multiple times trust-anchors { ( static-key | diff --git a/doc/misc/tls.grammar.rst b/doc/misc/tls.grammar.rst index f610a77d59..98f724a6d8 100644 --- a/doc/misc/tls.grammar.rst +++ b/doc/misc/tls.grammar.rst @@ -3,9 +3,11 @@ tls { ca-file ; cert-file ; - ciphers ; // experimental - dh-param ; // experimental + ciphers ; + dhparam-file ; hostname ; key-file ; - protocols ; // experimental + prefer-server-ciphers ; + protocols { ; ... }; + session-tickets ; }; diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index 5bd4f71b0b..94a49630be 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -24,7 +24,17 @@ Known Issues New Features ~~~~~~~~~~~~ -- None. +- Ability to specify supported TLS protocol versions within ``tls`` + clauses (e.g. ``protocols { TLSv1.2; TLSv1.3; };``). :gl:`#2795` + +- New options within ``tls`` clauses were implemented, namely: + - ``dhparam-file "";`` to specify Diffie-Hellman parameters; + - ``ciphers "";`` to specify OpenSSL ciphers list; + - ``prefer-server-ciphers yes|no;`` to assert server or client ciphers preference; + - ``session-tickets yes|no;`` to explicitly enable or disable stateless TLS session tickets (see RFC5077). + These options allow finer control over TLS protocol features and make it + possible to achieve perfect forward secrecy for DNS-over-TLS and + DNS-over-HTTPS. :gl:`#2796` Removed Features ~~~~~~~~~~~~~~~~ diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 88dcc4d73c..84b899953a 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -16,6 +16,8 @@ #include #include +#include + #ifdef HAVE_DNSTAP #include #endif @@ -2116,6 +2118,163 @@ done: } #endif /* HAVE_LIBNGHTTP2 */ +static isc_result_t +bind9_check_tls_defintion(const cfg_obj_t *tlsobj, const char *name, + isc_log_t *logctx, isc_symtab_t *symtab) { + isc_result_t result, tresult; + const cfg_obj_t *tls_proto_list = NULL, *tls_key = NULL, + *tls_cert = NULL, *tls_ciphers = NULL; + uint32_t tls_protos = 0; + isc_symvalue_t symvalue; + + if (strcasecmp(name, "ephemeral") == 0 || strcasecmp(name, "none") == 0) + { + cfg_obj_log(tlsobj, logctx, ISC_LOG_ERROR, + "tls clause name '%s' is reserved for internal use", + name); + result = ISC_R_FAILURE; + } else { + /* Check for duplicates */ + symvalue.as_cpointer = tlsobj; + result = isc_symtab_define(symtab, name, 1, symvalue, + isc_symexists_reject); + if (result == ISC_R_EXISTS) { + const char *file = NULL; + unsigned int line; + + tresult = isc_symtab_lookup(symtab, name, 1, &symvalue); + RUNTIME_CHECK(tresult == ISC_R_SUCCESS); + + line = cfg_obj_line(symvalue.as_cpointer); + file = cfg_obj_file(symvalue.as_cpointer); + if (file == NULL) { + file = ""; + } + + cfg_obj_log(tlsobj, logctx, ISC_LOG_ERROR, + "tls clause '%s' is duplicated: " + "also defined at %s:%u", + name, file, line); + } + } + + if (cfg_map_get(tlsobj, "key-file", &tls_key) != ISC_R_SUCCESS) { + cfg_obj_log(tlsobj, logctx, ISC_LOG_ERROR, + "'key-file' is required in tls clause '%s'", name); + result = ISC_R_FAILURE; + } + + if (cfg_map_get(tlsobj, "cert-file", &tls_cert) != ISC_R_SUCCESS) { + cfg_obj_log(tlsobj, logctx, ISC_LOG_ERROR, + "'cert-file' is required in tls clause '%s'", name); + result = ISC_R_FAILURE; + } + + /* Check protocols are valid */ + tresult = cfg_map_get(tlsobj, "protocols", &tls_proto_list); + if (tresult == ISC_R_SUCCESS) { + const cfg_listelt_t *proto = NULL; + INSIST(tls_proto_list != NULL); + for (proto = cfg_list_first(tls_proto_list); proto != 0; + proto = cfg_list_next(proto)) + { + const cfg_obj_t *tls_proto_obj = + cfg_listelt_value(proto); + const char *tls_sver = cfg_obj_asstring(tls_proto_obj); + const isc_tls_protocol_version_t ver = + isc_tls_protocol_name_to_version(tls_sver); + + if (ver == ISC_TLS_PROTO_VER_UNDEFINED) { + cfg_obj_log(tls_proto_obj, logctx, + ISC_LOG_ERROR, + "'%s' is not a valid " + "TLS protocol version", + tls_sver); + result = ISC_R_FAILURE; + continue; + } else if (!isc_tls_protocol_supported(ver)) { + cfg_obj_log(tls_proto_obj, logctx, + ISC_LOG_ERROR, + "'%s' is not " + "supported by the " + "cryptographic library version in " + "use (%s)", + tls_sver, OPENSSL_VERSION_TEXT); + result = ISC_R_FAILURE; + } + + if ((tls_protos & ver) != 0) { + cfg_obj_log(tls_proto_obj, logctx, + ISC_LOG_WARNING, + "'%s' is specified more than once " + "in '%s'", + tls_sver, name); + result = ISC_R_FAILURE; + } + + tls_protos |= ver; + } + + if (tls_protos == 0) { + cfg_obj_log(tlsobj, logctx, ISC_LOG_ERROR, + "tls '%s' does not contain any valid " + "TLS protocol versions definitions", + name); + result = ISC_R_FAILURE; + } + } + + /* Check cipher list string is valid */ + tresult = cfg_map_get(tlsobj, "ciphers", &tls_ciphers); + if (tresult == ISC_R_SUCCESS) { + const char *ciphers = cfg_obj_asstring(tls_ciphers); + if (!isc_tls_cipherlist_valid(ciphers)) { + cfg_obj_log(tls_ciphers, logctx, ISC_LOG_ERROR, + "'ciphers' in the 'tls' clause '%s' is " + "not a " + "valid cipher list string", + name); + result = ISC_R_FAILURE; + } + } + + return (result); +} + +static isc_result_t +bind9_check_tls_definitions(const cfg_obj_t *config, isc_log_t *logctx, + isc_mem_t *mctx) { + isc_result_t result, tresult; + const cfg_obj_t *obj = NULL; + const cfg_listelt_t *elt = NULL; + isc_symtab_t *symtab = NULL; + + result = cfg_map_get(config, "tls", &obj); + if (result != ISC_R_SUCCESS) { + result = ISC_R_SUCCESS; + return (result); + } + + result = isc_symtab_create(mctx, 100, NULL, NULL, false, &symtab); + if (result != ISC_R_SUCCESS) { + return (result); + } + + for (elt = cfg_list_first(obj); elt != NULL; elt = cfg_list_next(elt)) { + const char *name; + obj = cfg_listelt_value(elt); + name = cfg_obj_asstring(cfg_map_getname(obj)); + tresult = bind9_check_tls_defintion(obj, name, logctx, symtab); + if (result == ISC_R_SUCCESS) { + result = tresult; + } + } + + isc_symtab_destroy(&symtab); + + return (result); +} + static isc_result_t get_remotes(const cfg_obj_t *cctx, const char *list, const char *name, const cfg_obj_t **ret) { @@ -5494,6 +5653,11 @@ bind9_check_namedconf(const cfg_obj_t *config, bool check_plugins, } #endif /* HAVE_LIBNGHTTP2 */ + if (bind9_check_tls_definitions(config, logctx, mctx) != ISC_R_SUCCESS) + { + result = ISC_R_FAILURE; + } + (void)cfg_map_get(config, "view", &views); if (views != NULL && options != NULL) { diff --git a/lib/isc/include/isc/tls.h b/lib/isc/include/isc/tls.h index 38c990648b..addc27ba5c 100644 --- a/lib/isc/include/isc/tls.h +++ b/lib/isc/include/isc/tls.h @@ -50,6 +50,90 @@ isc_tlsctx_createclient(isc_tlsctx_t **ctxp); *\li 'ctxp' != NULL and '*ctxp' == NULL. */ +typedef enum isc_tls_protocol_version { + /* these must be the powers of two */ + ISC_TLS_PROTO_VER_1_2 = 1 << 0, + ISC_TLS_PROTO_VER_1_3 = 1 << 1, + ISC_TLS_PROTO_VER_UNDEFINED, +} isc_tls_protocol_version_t; + +void +isc_tlsctx_set_protocols(isc_tlsctx_t *ctx, const uint32_t tls_versions); +/*%< + * Sets the supported TLS protocol versions via the 'tls_versions' bit + * set argument (see `isc_tls_protocol_version_t` enum for the + * expected values). + * + * Requires: + *\li 'ctx' != NULL; + *\li 'tls_versions' != 0. + */ + +bool +isc_tls_protocol_supported(const isc_tls_protocol_version_t tls_ver); +/*%< + * Check in runtime that the specified TLS protocol versions is supported. + */ + +isc_tls_protocol_version_t +isc_tls_protocol_name_to_version(const char *name); +/*%< + * Convert the protocol version string into the version of + * 'isc_tls_protocol_version_t' type. + * Requires: + *\li 'name' != NULL. + */ + +bool +isc_tlsctx_load_dhparams(isc_tlsctx_t *ctx, const char *dhparams_file); +/*%< + * Load Diffie-Hellman parameters file and apply it to the given TLS context + * 'ctx'. + * + * Requires: + * \li 'ctx' != NULL; + * \li 'dhaprams_file' a valid pointer to a non empty string. + */ + +bool +isc_tls_cipherlist_valid(const char *cipherlist); +/*%< + * Check if cipher list string is valid. + * + * Requires: + * \li 'cipherlist' a valid pointer to a non empty string. + */ + +void +isc_tlsctx_set_cipherlist(isc_tlsctx_t *ctx, const char *cipherlist); +/*%< + * Set cipher list string for on the given TLS context 'ctx'. + * + * Requires: + * \li 'ctx' != NULL; + * \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. + */ + +void +isc_tlsctx_session_tickets(isc_tlsctx_t *ctx, const bool use); +/*%< + * Enable/Disable stateless session resumptions tickets on the given + * TLS context 'ctx' (see RFC5077). + * + * 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 ad0cb74168..94d42b7e17 100644 --- a/lib/isc/tls.c +++ b/lib/isc/tls.c @@ -10,12 +10,14 @@ */ #include +#include #if HAVE_LIBNGHTTP2 #include #endif /* HAVE_LIBNGHTTP2 */ #include #include +#include #include #include #include @@ -33,6 +35,9 @@ #include "openssl_shim.h" #include "tls_p.h" +#define COMMON_SSL_OPTIONS \ + (SSL_OP_NO_COMPRESSION | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION) + static isc_once_t init_once = ISC_ONCE_INIT; static isc_once_t shut_once = ISC_ONCE_INIT; static atomic_bool init_done = ATOMIC_VAR_INIT(false); @@ -185,13 +190,13 @@ isc_tlsctx_createclient(isc_tlsctx_t **ctxp) { goto ssl_error; } + SSL_CTX_set_options(ctx, COMMON_SSL_OPTIONS); + #if HAVE_SSL_CTX_SET_MIN_PROTO_VERSION SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); #else - SSL_CTX_set_options( - ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | - SSL_OP_NO_TLSv1_1 | SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | + SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); #endif *ctxp = ctx; @@ -235,6 +240,8 @@ isc_tlsctx_createserver(const char *keyfile, const char *certfile, } RUNTIME_CHECK(ctx != NULL); + SSL_CTX_set_options(ctx, COMMON_SSL_OPTIONS); + #if HAVE_SSL_CTX_SET_MIN_PROTO_VERSION SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); #else @@ -359,6 +366,225 @@ ssl_error: return (ISC_R_TLSERROR); } +static long +get_tls_version_disable_bit(const isc_tls_protocol_version_t tls_ver) { + long bit = 0; + + switch (tls_ver) { + case ISC_TLS_PROTO_VER_1_2: +#ifdef SSL_OP_NO_TLSv1_2 + bit = SSL_OP_NO_TLSv1_2; +#else + bit = 0; +#endif + break; + case ISC_TLS_PROTO_VER_1_3: +#ifdef SSL_OP_NO_TLSv1_3 + bit = SSL_OP_NO_TLSv1_3; +#else + bit = 0; +#endif + break; + default: + INSIST(0); + ISC_UNREACHABLE(); + break; + }; + + return (bit); +} + +bool +isc_tls_protocol_supported(const isc_tls_protocol_version_t tls_ver) { + return (get_tls_version_disable_bit(tls_ver) != 0); +} + +isc_tls_protocol_version_t +isc_tls_protocol_name_to_version(const char *name) { + REQUIRE(name != NULL); + + if (strcasecmp(name, "TLSv1.2") == 0) { + return (ISC_TLS_PROTO_VER_1_2); + } else if (strcasecmp(name, "TLSv1.3") == 0) { + return (ISC_TLS_PROTO_VER_1_3); + } + + return (ISC_TLS_PROTO_VER_UNDEFINED); +} + +void +isc_tlsctx_set_protocols(isc_tlsctx_t *ctx, const uint32_t tls_versions) { + REQUIRE(ctx != NULL); + REQUIRE(tls_versions != 0); + long set_options = 0; + long clear_options = 0; + uint32_t versions = tls_versions; + + /* + * The code below might be initially hard to follow because of the + * double negation that OpenSSL enforces. + * + * Taking into account that OpenSSL provides bits to *disable* + * specific protocol versions, like SSL_OP_NO_TLSv1_2, + * SSL_OP_NO_TLSv1_3, etc., the code has the following logic: + * + * If a protocol version is not specified in the bitmask, get the + * bit that disables it and add it to the set of TLS options to + * set ('set_options'). Otherwise, if a protocol version is set, + * add the bit to the set of options to clear ('clear_options'). + */ + + /* TLS protocol versions are defined as powers of two. */ + for (uint32_t tls_ver = ISC_TLS_PROTO_VER_1_2; + tls_ver < ISC_TLS_PROTO_VER_UNDEFINED; tls_ver <<= 1) + { + /* Only supported versions should ever be passed to the + * function. The configuration file was not verified + * properly, if we are trying to enable an unsupported + * TLS version */ + INSIST(isc_tls_protocol_supported(tls_ver)); + if ((tls_versions & tls_ver) == 0) { + set_options |= get_tls_version_disable_bit(tls_ver); + } else { + clear_options |= get_tls_version_disable_bit(tls_ver); + } + versions &= ~(tls_ver); + } + + /* All versions should be processed at this point, thus the value + * must equal zero. If it is not, then some garbage has been + * passed to the function; this situation is worth + * investigation. */ + INSIST(versions == 0); + + (void)SSL_CTX_set_options(ctx, set_options); + (void)SSL_CTX_clear_options(ctx, clear_options); +} + +bool +isc_tlsctx_load_dhparams(isc_tlsctx_t *ctx, const char *dhparams_file) { + REQUIRE(ctx != NULL); + REQUIRE(dhparams_file != NULL); + REQUIRE(*dhparams_file != '\0'); + +#ifdef SSL_CTX_set_tmp_dh + /* OpenSSL < 3.0 */ + DH *dh = NULL; + FILE *paramfile; + + paramfile = fopen(dhparams_file, "r"); + + if (paramfile) { + int check = 0; + dh = PEM_read_DHparams(paramfile, NULL, NULL, NULL); + fclose(paramfile); + + if (dh == NULL) { + return (false); + } else if (DH_check(dh, &check) != 1 || check != 0) { + DH_free(dh); + return (false); + } + } else { + return (false); + } + + if (SSL_CTX_set_tmp_dh(ctx, dh) != 1) { + DH_free(dh); + return (false); + } + + DH_free(dh); +#else + /* OpenSSL >= 3.0: SSL_CTX_set_tmp_dh() is deprecated in OpenSSL 3.0 */ + EVP_PKEY *dh = NULL; + BIO *bio = NULL; + + bio = BIO_new_file(dhparams_file, "r"); + if (bio == NULL) { + return (false); + } + + dh = PEM_read_bio_Parameters(bio, NULL); + if (dh == NULL) { + BIO_free(bio); + return (false); + } + + if (SSL_CTX_set0_tmp_dh_pkey(ctx, dh) != 1) { + BIO_free(bio); + EVP_PKEY_free(dh); + return (false); + } + + /* No need to call EVP_PKEY_free(dh) as the "dh" is owned by the + * SSL context at this point. */ + + BIO_free(bio); +#endif + + return (true); +} + +bool +isc_tls_cipherlist_valid(const char *cipherlist) { + isc_tlsctx_t *tmp_ctx = NULL; + const SSL_METHOD *method = NULL; + bool result; + REQUIRE(cipherlist != NULL); + + if (*cipherlist == '\0') { + return (false); + } + + method = TLS_server_method(); + if (method == NULL) { + return (false); + } + tmp_ctx = SSL_CTX_new(method); + if (tmp_ctx == NULL) { + return (false); + } + + result = SSL_CTX_set_cipher_list(tmp_ctx, cipherlist) == 1; + + isc_tlsctx_free(&tmp_ctx); + + return (result); +} + +void +isc_tlsctx_set_cipherlist(isc_tlsctx_t *ctx, const char *cipherlist) { + REQUIRE(ctx != NULL); + REQUIRE(cipherlist != NULL); + REQUIRE(*cipherlist != '\0'); + + 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); + } +} + +void +isc_tlsctx_session_tickets(isc_tlsctx_t *ctx, const bool use) { + REQUIRE(ctx != NULL); + + if (!use) { + (void)SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET); + } else { + (void)SSL_CTX_clear_options(ctx, SSL_OP_NO_TICKET); + } +} + 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 8cd23814d0..7bff17d184 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -3875,19 +3875,23 @@ cfg_print_zonegrammar(const unsigned int zonetype, unsigned int flags, /*% * "tls" and related statement syntax. */ -static cfg_type_t cfg_type_sslprotos = { - "sslprotos", cfg_parse_spacelist, cfg_print_spacelist, - cfg_doc_terminal, &cfg_rep_list, &cfg_type_astring -}; +static cfg_type_t cfg_type_tlsprotos = { "tls_protocols", + cfg_parse_bracketed_list, + cfg_print_bracketed_list, + cfg_doc_bracketed_list, + &cfg_rep_list, + &cfg_type_astring }; static cfg_clausedef_t tls_clauses[] = { { "key-file", &cfg_type_qstring, 0 }, { "cert-file", &cfg_type_qstring, 0 }, { "ca-file", &cfg_type_qstring, 0 }, { "hostname", &cfg_type_qstring, 0 }, - { "dh-param", &cfg_type_qstring, CFG_CLAUSEFLAG_EXPERIMENTAL }, - { "protocols", &cfg_type_sslprotos, CFG_CLAUSEFLAG_EXPERIMENTAL }, - { "ciphers", &cfg_type_astring, CFG_CLAUSEFLAG_EXPERIMENTAL }, + { "dhparam-file", &cfg_type_qstring, 0 }, + { "protocols", &cfg_type_tlsprotos, 0 }, + { "ciphers", &cfg_type_astring, 0 }, + { "prefer-server-ciphers", &cfg_type_boolean, 0 }, + { "session-tickets", &cfg_type_boolean, 0 }, { NULL, NULL, 0 } }; diff --git a/lib/ns/include/ns/listenlist.h b/lib/ns/include/ns/listenlist.h index 348b1ca894..8119821b5b 100644 --- a/lib/ns/include/ns/listenlist.h +++ b/lib/ns/include/ns/listenlist.h @@ -59,22 +59,40 @@ struct ns_listenlist { ISC_LIST(ns_listenelt_t) elts; }; +typedef struct ns_listen_tls_params { + const char *key; + const char *cert; + uint32_t protocols; + const char *dhparam_file; + const char *ciphers; + bool prefer_server_ciphers; + bool prefer_server_ciphers_set; + bool session_tickets; + bool session_tickets_set; +} ns_listen_tls_params_t; + /*** *** Functions ***/ isc_result_t ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, - dns_acl_t *acl, bool tls, const char *key, const char *cert, - ns_listenelt_t **target); + dns_acl_t *acl, bool tls, + const ns_listen_tls_params_t *tls_params, + ns_listenelt_t ** target); /*%< * Create a listen-on list element. + * + * Requires: + * \li 'targetp' is a valid pointer to a pointer containing 'NULL'; + * \li 'tls_params' is a valid, non-'NULL' pointer if 'tls' equals 'true'. */ isc_result_t ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp, - dns_acl_t *acl, bool tls, const char *key, - const char *cert, char **endpoints, size_t nendpoints, + dns_acl_t *acl, bool tls, + const ns_listen_tls_params_t *tls_params, + char **endpoints, size_t nendpoints, isc_quota_t *quota, const uint32_t max_streams, ns_listenelt_t **target); /*%< diff --git a/lib/ns/listenlist.c b/lib/ns/listenlist.c index 9c445a710a..6aa67dbd2b 100644 --- a/lib/ns/listenlist.c +++ b/lib/ns/listenlist.c @@ -26,19 +26,49 @@ destroy(ns_listenlist_t *list); isc_result_t ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, - dns_acl_t *acl, bool tls, const char *key, const char *cert, + dns_acl_t *acl, bool tls, + const ns_listen_tls_params_t *tls_params, ns_listenelt_t **target) { ns_listenelt_t *elt = NULL; isc_result_t result = ISC_R_SUCCESS; isc_tlsctx_t *sslctx = NULL; REQUIRE(target != NULL && *target == NULL); + REQUIRE(!tls || tls_params != NULL); if (tls) { - result = isc_tlsctx_createserver(key, cert, &sslctx); + result = isc_tlsctx_createserver(tls_params->key, + tls_params->cert, &sslctx); if (result != ISC_R_SUCCESS) { return (result); } + + if (tls_params->protocols != 0) { + isc_tlsctx_set_protocols(sslctx, tls_params->protocols); + } + + if (tls_params->dhparam_file != NULL) { + if (!isc_tlsctx_load_dhparams(sslctx, + tls_params->dhparam_file)) + { + isc_tlsctx_free(&sslctx); + return (ISC_R_FAILURE); + } + } + + 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); + } + + if (tls_params->session_tickets_set) { + isc_tlsctx_session_tickets(sslctx, + tls_params->session_tickets); + } } elt = isc_mem_get(mctx, sizeof(*elt)); @@ -59,8 +89,9 @@ ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, isc_result_t ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp, - dns_acl_t *acl, bool tls, const char *key, - const char *cert, char **endpoints, size_t nendpoints, + dns_acl_t *acl, bool tls, + const ns_listen_tls_params_t *tls_params, + char **endpoints, size_t nendpoints, isc_quota_t *quota, const uint32_t max_streams, ns_listenelt_t **target) { isc_result_t result; @@ -69,8 +100,8 @@ ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp, REQUIRE(endpoints != NULL && *endpoints != NULL); REQUIRE(nendpoints > 0); - result = ns_listenelt_create(mctx, http_port, dscp, acl, tls, key, cert, - target); + result = ns_listenelt_create(mctx, http_port, dscp, acl, tls, + tls_params, target); if (result == ISC_R_SUCCESS) { (*target)->is_http = true; (*target)->http_endpoints = endpoints; @@ -164,8 +195,7 @@ ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, goto cleanup; } - result = ns_listenelt_create(mctx, port, dscp, acl, false, NULL, NULL, - &elt); + result = ns_listenelt_create(mctx, port, dscp, acl, false, NULL, &elt); if (result != ISC_R_SUCCESS) { goto cleanup_acl; } diff --git a/util/copyrights b/util/copyrights index 2d0d2faf53..0e24a2361d 100644 --- a/util/copyrights +++ b/util/copyrights @@ -276,6 +276,7 @@ ./bin/tests/system/doth/clean.sh SH 2020,2021 ./bin/tests/system/doth/example.axfr.good X 2021 ./bin/tests/system/doth/ns2/cert.pem X 2021 +./bin/tests/system/doth/ns2/dhparam3072.pem X 2021 ./bin/tests/system/doth/ns2/key.pem X 2021 ./bin/tests/system/doth/setup.sh SH 2021 ./bin/tests/system/doth/stress_http_quota.py PYTHON-BIN 2021