]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
libtls: Send empty cert payload upon cert request
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 19 Aug 2022 15:09:02 +0000 (17:09 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 25 Aug 2022 05:02:29 +0000 (07:02 +0200)
Currently when a TLS client doesn't have a certificate, it doesn't
send a certficiate payload upon receiving a certificate request
from the TLS server. According to the TLS 1.2 and 1.3 RFCs an
empty certificate payload must be sent.

src/libtls/tls_peer.c

index 04f4bcb37c43b97fee8496220b0fc7c3f8f42010..91f7efba82270b83ca299856d675d74c135ecf35 100644 (file)
@@ -90,6 +90,11 @@ struct private_tls_peer_t {
         */
        peer_state_t state;
 
+       /**
+        *  Received a certificate request from server
+        */
+        bool certreq_received;
+
        /**
         * TLS version we offered in hello
         */
@@ -982,6 +987,7 @@ static status_t process_certreq(private_tls_peer_t *this, bio_reader_t *reader)
                }
        extensions->destroy(extensions);
        }
+       this->certreq_received = TRUE;
        this->state = STATE_CERTREQ_RECEIVED;
        return NEED_MORE;
 }
@@ -1478,35 +1484,39 @@ static status_t send_certificate(private_tls_peer_t *this,
 
        version_min = this->tls->get_version_min(this->tls);
        version_max = this->tls->get_version_max(this->tls);
-       if (!this->hashsig.len)
-       {
-               convert_cert_types(this);
-       }
-       enumerator = tls_create_private_key_enumerator(version_min, version_max,
-                                                                                                  this->hashsig, this->peer);
-       if (!enumerator || !enumerator->enumerate(enumerator, &key, &auth))
+
+       if (this->peer)
        {
-               if (!enumerator)
+               if (!this->hashsig.len)
+               {
+                       convert_cert_types(this);
+               }
+               enumerator = tls_create_private_key_enumerator(version_min, version_max,
+                                                                                                          this->hashsig, this->peer);
+               if (!enumerator || !enumerator->enumerate(enumerator, &key, &auth))
                {
-                       DBG1(DBG_TLS, "no common signature algorithms found");
+                       if (!enumerator)
+                       {
+                               DBG1(DBG_TLS, "no common signature algorithms found");
+                       }
+                       else
+                       {
+                               DBG1(DBG_TLS, "no usable TLS client certificate found for '%Y'",
+                                        this->peer);
+                       }
+                       this->peer->destroy(this->peer);
+                       this->peer = NULL;
                }
                else
                {
-                       DBG1(DBG_TLS, "no usable TLS client certificate found for '%Y'",
-                                this->peer);
+                       this->private = key->get_ref(key);
+                       this->peer_auth->merge(this->peer_auth, auth, FALSE);
                }
-               this->peer->destroy(this->peer);
-               this->peer = NULL;
-       }
-       else
-       {
-               this->private = key->get_ref(key);
-               this->peer_auth->merge(this->peer_auth, auth, FALSE);
+               DESTROY_IF(enumerator);
        }
-       DESTROY_IF(enumerator);
 
        /* certificate request context as described in RFC 8446, section 4.4.2 */
-       if (this->tls->get_version_max(this->tls) > TLS_1_2)
+       if (version_max > TLS_1_2)
        {
                writer->write_uint8(writer, 0);
        }
@@ -1524,7 +1534,7 @@ static status_t send_certificate(private_tls_peer_t *this,
                        free(data.ptr);
                }
                /* extensions see RFC 8446, section 4.4.2 */
-               if (this->tls->get_version_max(this->tls) > TLS_1_2)
+               if (version_max > TLS_1_2)
                {
                        certs->write_uint16(certs, 0);
                }
@@ -1767,7 +1777,7 @@ METHOD(tls_handshake_t, build, status_t,
                        case STATE_INIT:
                                return send_client_hello(this, type, writer);
                        case STATE_HELLO_DONE:
-                               if (this->peer)
+                               if (this->peer || this->certreq_received)
                                {
                                        return send_certificate(this, type, writer);
                                }
@@ -1804,7 +1814,7 @@ METHOD(tls_handshake_t, build, status_t,
                                        return NEED_MORE;
                                }
                                this->crypto->change_cipher(this->crypto, TRUE);
-                               if (this->peer)
+                               if (this->peer || this->certreq_received)
                                {
                                        return send_certificate(this, type, writer);
                                }