libtls: Send empty cert payload upon cert request
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.
This commit is contained in:
+33
-23
@@ -90,6 +90,11 @@ struct private_tls_peer_t {
|
|||||||
*/
|
*/
|
||||||
peer_state_t state;
|
peer_state_t state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Received a certificate request from server
|
||||||
|
*/
|
||||||
|
bool certreq_received;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLS version we offered in hello
|
* 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);
|
extensions->destroy(extensions);
|
||||||
}
|
}
|
||||||
|
this->certreq_received = TRUE;
|
||||||
this->state = STATE_CERTREQ_RECEIVED;
|
this->state = STATE_CERTREQ_RECEIVED;
|
||||||
return NEED_MORE;
|
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_min = this->tls->get_version_min(this->tls);
|
||||||
version_max = this->tls->get_version_max(this->tls);
|
version_max = this->tls->get_version_max(this->tls);
|
||||||
if (!this->hashsig.len)
|
|
||||||
|
if (this->peer)
|
||||||
{
|
{
|
||||||
convert_cert_types(this);
|
if (!this->hashsig.len)
|
||||||
}
|
|
||||||
enumerator = tls_create_private_key_enumerator(version_min, version_max,
|
|
||||||
this->hashsig, this->peer);
|
|
||||||
if (!enumerator || !enumerator->enumerate(enumerator, &key, &auth))
|
|
||||||
{
|
|
||||||
if (!enumerator)
|
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "no common signature algorithms found");
|
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 (!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
|
else
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "no usable TLS client certificate found for '%Y'",
|
this->private = key->get_ref(key);
|
||||||
this->peer);
|
this->peer_auth->merge(this->peer_auth, auth, FALSE);
|
||||||
}
|
}
|
||||||
this->peer->destroy(this->peer);
|
DESTROY_IF(enumerator);
|
||||||
this->peer = NULL;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
this->private = key->get_ref(key);
|
|
||||||
this->peer_auth->merge(this->peer_auth, auth, FALSE);
|
|
||||||
}
|
|
||||||
DESTROY_IF(enumerator);
|
|
||||||
|
|
||||||
/* certificate request context as described in RFC 8446, section 4.4.2 */
|
/* 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);
|
writer->write_uint8(writer, 0);
|
||||||
}
|
}
|
||||||
@@ -1524,7 +1534,7 @@ static status_t send_certificate(private_tls_peer_t *this,
|
|||||||
free(data.ptr);
|
free(data.ptr);
|
||||||
}
|
}
|
||||||
/* extensions see RFC 8446, section 4.4.2 */
|
/* 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);
|
certs->write_uint16(certs, 0);
|
||||||
}
|
}
|
||||||
@@ -1767,7 +1777,7 @@ METHOD(tls_handshake_t, build, status_t,
|
|||||||
case STATE_INIT:
|
case STATE_INIT:
|
||||||
return send_client_hello(this, type, writer);
|
return send_client_hello(this, type, writer);
|
||||||
case STATE_HELLO_DONE:
|
case STATE_HELLO_DONE:
|
||||||
if (this->peer)
|
if (this->peer || this->certreq_received)
|
||||||
{
|
{
|
||||||
return send_certificate(this, type, writer);
|
return send_certificate(this, type, writer);
|
||||||
}
|
}
|
||||||
@@ -1804,7 +1814,7 @@ METHOD(tls_handshake_t, build, status_t,
|
|||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
this->crypto->change_cipher(this->crypto, TRUE);
|
this->crypto->change_cipher(this->crypto, TRUE);
|
||||||
if (this->peer)
|
if (this->peer || this->certreq_received)
|
||||||
{
|
{
|
||||||
return send_certificate(this, type, writer);
|
return send_certificate(this, type, writer);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user