]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add "prefer-server-ciphers" options to the "tls" clause
authorArtem Boldariev <artem@boldariev.com>
Mon, 20 Sep 2021 13:53:27 +0000 (16:53 +0300)
committerArtem Boldariev <artem@boldariev.com>
Fri, 1 Oct 2021 12:50:43 +0000 (15:50 +0300)
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.

14 files changed:
bin/named/named.conf.rst
bin/named/server.c
bin/tests/system/checkconf/good-doh-tlsopts.conf
bin/tests/system/checkconf/good-dot-tlsopts.conf
doc/arm/reference.rst
doc/man/named.conf.5in
doc/misc/options
doc/misc/options.active
doc/misc/tls.grammar.rst
lib/isc/include/isc/tls.h
lib/isc/tls.c
lib/isccfg/namedconf.c
lib/ns/include/ns/listenlist.h
lib/ns/listenlist.c

index d1818a7ef6ba0443861950e0e3a5c4cc447f4754..ff9e7de0f88b029e07adb702fdfb0f87cd01e6f7 100644 (file)
@@ -567,6 +567,7 @@ TLS
        dhparam-file quoted_string;
        hostname quoted_string;
        key-file quoted_string;
+       prefer-server-ciphers boolean;
        protocols { string; ... };
   };
 
index d3e8d802d6218adfc20461af8cb850e2af77f872..3c3ebd7b4830f45b8f2d07cdc299d5a742698466 100644 (file)
@@ -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)) {
index 7583c70cd503f14bf5586ce12d5fec7de884fdc5..f6cafa342f7ad317b304a09d15c0a06c5687daf9 100644 (file)
@@ -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 {
index 1a0029d22013464dd260fa4daace4da3d20af746..8912646f65a098ad263d025f55b2312e71dda168 100644 (file)
@@ -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 {
index 46f24ec5366b2995962059e2ff13ad18891b41fb..b6a7c14e273126242eabdbdf68e8f7f12f9799ff 100644 (file)
@@ -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
index eb7cf4c5606f890426760f572b004d5ff8af2fab..036d5899495d5a06d72b94b9f8afb6c6c20be60e 100644 (file)
@@ -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
index 1a708a616360700235072ec2f06627778058bb5d..da7fcceb311636993a642bec30981eea1f646c32 100644 (file)
@@ -463,6 +463,7 @@ tls <string> {
         dhparam-file <quoted_string>;
         hostname <quoted_string>;
         key-file <quoted_string>;
+        prefer-server-ciphers <boolean>;
         protocols { <string>; ... };
 }; // may occur multiple times
 
index 91a555f5a52a0481e41c77f1469bb95b5b889005..f579cc2835e408b95f8885c00950e738abffe8cb 100644 (file)
@@ -460,6 +460,7 @@ tls <string> {
         dhparam-file <quoted_string>;
         hostname <quoted_string>;
         key-file <quoted_string>;
+        prefer-server-ciphers <boolean>;
         protocols { <string>; ... };
 }; // may occur multiple times
 
index 17c0c36bac11a9ca214dfedc434294a35dcd73fc..4cb078da9478b64a1370371a0b3078ca8929b3c6 100644 (file)
@@ -7,5 +7,6 @@
        dhparam-file <quoted_string>;
        hostname <quoted_string>;
        key-file <quoted_string>;
+       prefer-server-ciphers <boolean>;
        protocols { <string>; ... };
   };
index 90f185e825c95dfec0724e650b405d03e9b09a55..5c32053df32c60795ddf8c55154fe47c104f6528 100644 (file)
@@ -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);
 /*%<
index cec6c5ff43365ec7c443012ab13379daf1ab6d29..f2dcbf187bc355bd23dc749e86e0d26ab56bfb01 100644 (file)
@@ -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;
index ceea97480a60ae3ccf7bda2b7fe3f7f7b68e8182..0f8329f26ad60d282b941184d5c5de74a1117622 100644 (file)
@@ -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 }
 };
 
index 5b8d68edb9e920c1e956530a183e3d3962303cfe..207c1f6ab384d6b60ab5752dd35a8115378d1c59 100644 (file)
@@ -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;
 
 /***
index 68aab57cfa39650c8ce8d48cf33290cac650e6a6..600ee64ceb7e159671e9e0724e86977ca7587d34 100644 (file)
@@ -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));