tls-server: Optionally omit CAs in CertificateRequest messages
authorShmulik Ladkani <shmulik@metanetworks.com>
Fri, 15 Jan 2021 13:45:34 +0000 (14:45 +0100)
committerTobias Brunner <tobias@strongswan.org>
Fri, 12 Feb 2021 13:35:23 +0000 (14:35 +0100)
Usually, the DNs of all loaded CA certificates are included in the
CertificateRequest messages sent by the server.

Alas, certain EAP-TLS clients fail to process this message if the
list is too long, returning the fatal TLS alert 'illegal parameter'.

This new option allows configuring whether CAs are included or an
empty list is sent (TLS 1.2), or the certificate_authorities extension
is omitted (TLS 1.3).  The list only serves as hint/constraint
for clients during certificate selection, they still have to provide
a certificate but are free to select any one they have available.

Closes strongswan/strongswan#187.

conf/options/charon.opt
src/libtls/tls_server.c

index fb69bd7..dd97264 100644 (file)
@@ -473,6 +473,12 @@ charon.tls.mac
 charon.tls.suites
        List of TLS cipher suites.
 
+charon.tls.send_certreq_authorities = yes
+       Whether to include CAs in a server's CertificateRequest message.
+
+       Whether to include CAs in a server's CertificateRequest message. May be
+       disabled if clients can't handle a long list of CAs.
+
 charon.tls.version_min = 1.0
        Minimum TLS version to negotiate.
 
index 50051c1..eb3edf8 100644 (file)
@@ -163,6 +163,11 @@ struct private_tls_server_t {
         * Did we receive the curves from the client?
         */
        bool curves_received;
+
+       /**
+        * Whether to include CAs in CertificateRequest messages
+        */
+       bool send_certreq_authorities;
 };
 
 /**
@@ -1372,7 +1377,14 @@ static status_t send_certificate_request(private_tls_server_t *this,
                        this->crypto->get_signature_algorithms(this->crypto, writer, TRUE);
                }
 
-               write_certificate_authorities(writer);
+               if (this->send_certreq_authorities)
+               {
+                       write_certificate_authorities(writer);
+               }
+               else
+               {
+                       writer->write_data16(writer, chunk_empty);
+               }
        }
        else
        {
@@ -1380,13 +1392,17 @@ static status_t send_certificate_request(private_tls_server_t *this,
                writer->write_uint8(writer, 0);
 
                extensions = bio_writer_create(32);
-               DBG2(DBG_TLS, "sending extension: %N",
-                        tls_extension_names, TLS_EXT_CERTIFICATE_AUTHORITIES);
-               authorities = bio_writer_create(64);
-               write_certificate_authorities(authorities);
-               extensions->write_uint16(extensions, TLS_EXT_CERTIFICATE_AUTHORITIES);
-               extensions->write_data16(extensions, authorities->get_buf(authorities));
-               authorities->destroy(authorities);
+
+               if (this->send_certreq_authorities)
+               {
+                       DBG2(DBG_TLS, "sending extension: %N",
+                                tls_extension_names, TLS_EXT_CERTIFICATE_AUTHORITIES);
+                       authorities = bio_writer_create(64);
+                       write_certificate_authorities(authorities);
+                       extensions->write_uint16(extensions, TLS_EXT_CERTIFICATE_AUTHORITIES);
+                       extensions->write_data16(extensions, authorities->get_buf(authorities));
+                       authorities->destroy(authorities);
+               }
 
                DBG2(DBG_TLS, "sending extension: %N",
                         tls_extension_names, TLS_EXT_SIGNATURE_ALGORITHMS);
@@ -1808,6 +1824,9 @@ tls_server_t *tls_server_create(tls_t *tls,
                .state = STATE_INIT,
                .peer_auth = auth_cfg_create(),
                .server_auth = auth_cfg_create(),
+               .send_certreq_authorities = lib->settings->get_bool(lib->settings,
+                                                                                       "%s.tls.send_certreq_authorities",
+                                                                                       TRUE, lib->ns),
        );
 
        return &this->public;