Commit a57ac5d324 for openssl.org
commit a57ac5d3243a915f1579d723105274163e144009
Author: Matt Caswell <matt@openssl.org>
Date: Fri Feb 27 11:50:15 2026 +0000
Remove further remnants of SSLv2 ClientHello handling
We recently removed support for SSLv2 ClientHello messages - but some
remnants were still remaining in the record layer. We remove those too.
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
MergeDate: Fri Mar 13 15:12:39 2026
(Merged from https://github.com/openssl/openssl/pull/30204)
diff --git a/ssl/record/methods/tls_common.c b/ssl/record/methods/tls_common.c
index aa43dba6a4..64a53b0cb0 100644
--- a/ssl/record/methods/tls_common.c
+++ b/ssl/record/methods/tls_common.c
@@ -553,7 +553,7 @@ int tls_get_more_records(OSSL_RECORD_LAYER *rl)
size_t mac_size = 0;
int imac_size;
size_t num_recs = 0, max_recs, j;
- PACKET pkt, sslv2pkt;
+ PACKET pkt;
SSL_MAC_BUF *macbufs = NULL;
int ret = OSSL_RECORD_RETURN_FATAL;
@@ -576,7 +576,6 @@ int tls_get_more_records(OSSL_RECORD_LAYER *rl)
/* check if we have the header */
if ((rl->rstate != SSL_ST_READ_BODY) || (rl->packet_length < SSL3_RT_HEADER_LENGTH)) {
- size_t sslv2len;
unsigned int type;
rret = rl->funcs->read_n(rl, SSL3_RT_HEADER_LENGTH,
@@ -593,74 +592,26 @@ int tls_get_more_records(OSSL_RECORD_LAYER *rl)
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return OSSL_RECORD_RETURN_FATAL;
}
- sslv2pkt = pkt;
- if (!PACKET_get_net_2_len(&sslv2pkt, &sslv2len)
- || !PACKET_get_1(&sslv2pkt, &type)) {
+
+ /* Pull apart the header into the TLS_RL_RECORD */
+ if (!PACKET_get_1(&pkt, &type)
+ || !PACKET_get_net_2(&pkt, &version)
+ || !PACKET_get_net_2_len(&pkt, &thisrr->length)) {
+ if (rl->msg_callback != NULL)
+ rl->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, rl->cbarg);
RLAYERfatal(rl, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
return OSSL_RECORD_RETURN_FATAL;
}
- /*
- * The first record received by the server may be a V2ClientHello.
- */
- if (rl->role == OSSL_RECORD_ROLE_SERVER
- && rl->is_first_record
- && (sslv2len & 0x8000) != 0
- && (type == SSL2_MT_CLIENT_HELLO)) {
- /*
- * SSLv2 style record
- *
- * |num_recs| here will actually always be 0 because
- * |num_recs > 0| only ever occurs when we are processing
- * multiple app data records - which we know isn't the case here
- * because it is an SSLv2ClientHello. We keep it using
- * |num_recs| for the sake of consistency
- */
- thisrr->type = SSL3_RT_HANDSHAKE;
- thisrr->rec_version = SSL2_VERSION;
-
- thisrr->length = sslv2len & 0x7fff;
-
- if (thisrr->length > TLS_BUFFER_get_len(rbuf)
- - SSL2_RT_HEADER_LENGTH) {
- RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
- SSL_R_PACKET_LENGTH_TOO_LONG);
- return OSSL_RECORD_RETURN_FATAL;
- }
- } else {
- /* SSLv3+ style record */
-
- /* Pull apart the header into the TLS_RL_RECORD */
- if (!PACKET_get_1(&pkt, &type)
- || !PACKET_get_net_2(&pkt, &version)
- || !PACKET_get_net_2_len(&pkt, &thisrr->length)) {
- if (rl->msg_callback != NULL)
- rl->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, rl->cbarg);
- RLAYERfatal(rl, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
- return OSSL_RECORD_RETURN_FATAL;
- }
- thisrr->type = type;
- thisrr->rec_version = version;
+ thisrr->type = type;
+ thisrr->rec_version = version;
- /*
- * When we call validate_record_header() only records actually
- * received in SSLv2 format should have the record version set
- * to SSL2_VERSION. This way validate_record_header() can know
- * what format the record was in based on the version.
- */
- if (thisrr->rec_version == SSL2_VERSION) {
- RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
- SSL_R_WRONG_VERSION_NUMBER);
- return OSSL_RECORD_RETURN_FATAL;
- }
+ if (rl->msg_callback != NULL)
+ rl->msg_callback(0, version, SSL3_RT_HEADER, p, 5, rl->cbarg);
- if (rl->msg_callback != NULL)
- rl->msg_callback(0, version, SSL3_RT_HEADER, p, 5, rl->cbarg);
-
- if (thisrr->length > TLS_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) {
- RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
- SSL_R_PACKET_LENGTH_TOO_LONG);
- return OSSL_RECORD_RETURN_FATAL;
- }
+ if (thisrr->length > TLS_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) {
+ RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
+ SSL_R_PACKET_LENGTH_TOO_LONG);
+ return OSSL_RECORD_RETURN_FATAL;
}
if (!rl->funcs->validate_record_header(rl, thisrr)) {
diff --git a/ssl/record/methods/tlsany_meth.c b/ssl/record/methods/tlsany_meth.c
index 9961725439..2b9a02146e 100644
--- a/ssl/record/methods/tlsany_meth.c
+++ b/ssl/record/methods/tlsany_meth.c
@@ -43,75 +43,64 @@ static int tls_any_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
static int tls_validate_record_header(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *rec)
{
- if (rec->rec_version == SSL2_VERSION) {
- /* SSLv2 format ClientHello */
- if (!ossl_assert(rl->version == TLS_ANY_VERSION)) {
- RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (rec->length < MIN_SSL2_RECORD_LEN) {
- RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
- return 0;
- }
- } else {
- if (rl->version == TLS_ANY_VERSION) {
- if ((rec->rec_version >> 8) != SSL3_VERSION_MAJOR) {
- if (rl->is_first_record) {
- unsigned char *p;
-
- /*
- * Go back to start of packet, look at the five bytes that
- * we have.
- */
- p = rl->packet;
- if (HAS_PREFIX((char *)p, "GET ") || HAS_PREFIX((char *)p, "POST ") || HAS_PREFIX((char *)p, "HEAD ") || HAS_PREFIX((char *)p, "PATCH") || HAS_PREFIX((char *)p, "OPTIO") || HAS_PREFIX((char *)p, "DELET") || HAS_PREFIX((char *)p, "TRACE") || HAS_PREFIX((char *)p, "PUT ")) {
- RLAYERfatal(rl, SSL_AD_NO_ALERT, SSL_R_HTTP_REQUEST);
- return 0;
- } else if (HAS_PREFIX((char *)p, "CONNE")) {
- RLAYERfatal(rl, SSL_AD_NO_ALERT,
- SSL_R_HTTPS_PROXY_REQUEST);
- return 0;
- }
-
- /* Doesn't look like TLS - don't send an alert */
- RLAYERfatal(rl, SSL_AD_NO_ALERT,
- SSL_R_WRONG_VERSION_NUMBER);
- return 0;
- } else {
- RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
- SSL_R_WRONG_VERSION_NUMBER);
+ if (rl->version == TLS_ANY_VERSION) {
+ if ((rec->rec_version >> 8) != SSL3_VERSION_MAJOR) {
+ if (rl->is_first_record) {
+ unsigned char *p;
+
+ /*
+ * Go back to start of packet, look at the five bytes that
+ * we have.
+ */
+ p = rl->packet;
+ if (HAS_PREFIX((char *)p, "GET ") || HAS_PREFIX((char *)p, "POST ") || HAS_PREFIX((char *)p, "HEAD ") || HAS_PREFIX((char *)p, "PATCH") || HAS_PREFIX((char *)p, "OPTIO") || HAS_PREFIX((char *)p, "DELET") || HAS_PREFIX((char *)p, "TRACE") || HAS_PREFIX((char *)p, "PUT ")) {
+ RLAYERfatal(rl, SSL_AD_NO_ALERT, SSL_R_HTTP_REQUEST);
return 0;
- }
- }
- } else if (rl->version == TLS1_3_VERSION) {
- /*
- * In this case we know we are going to negotiate TLSv1.3, but we've
- * had an HRR, so we haven't actually done so yet. In TLSv1.3 we
- * must ignore the legacy record version in plaintext records.
- */
- } else if (rec->rec_version != rl->version) {
- if ((rl->version & 0xFF00) == (rec->rec_version & 0xFF00)) {
- if (rec->type == SSL3_RT_ALERT) {
- /*
- * The record is using an incorrect version number,
- * but what we've got appears to be an alert. We
- * haven't read the body yet to check whether its a
- * fatal or not - but chances are it is. We probably
- * shouldn't send a fatal alert back. We'll just
- * end.
- */
+ } else if (HAS_PREFIX((char *)p, "CONNE")) {
RLAYERfatal(rl, SSL_AD_NO_ALERT,
- SSL_R_WRONG_VERSION_NUMBER);
+ SSL_R_HTTPS_PROXY_REQUEST);
return 0;
}
- /* Send back error using their minor version number */
- rl->version = (unsigned short)rec->rec_version;
+
+ /* Doesn't look like TLS - don't send an alert */
+ RLAYERfatal(rl, SSL_AD_NO_ALERT,
+ SSL_R_WRONG_VERSION_NUMBER);
+ return 0;
+ } else {
+ RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
+ SSL_R_WRONG_VERSION_NUMBER);
+ return 0;
}
- RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
- SSL_R_WRONG_VERSION_NUMBER);
- return 0;
}
+ } else if (rl->version == TLS1_3_VERSION) {
+ /*
+ * In this case we know we are going to negotiate TLSv1.3, but we've
+ * had an HRR, so we haven't actually done so yet. In TLSv1.3 we
+ * must ignore the legacy record version in plaintext records.
+ */
+ } else if (rec->rec_version != rl->version) {
+ if ((rl->version & 0xFF00) == (rec->rec_version & 0xFF00)) {
+ if (rec->type == SSL3_RT_ALERT) {
+ /*
+ * The record is using an incorrect version number,
+ * but what we've got appears to be an alert. We
+ * haven't read the body yet to check whether its a
+ * fatal or not - but chances are it is. We probably
+ * shouldn't send a fatal alert back. We'll just
+ * end.
+ */
+ RLAYERfatal(rl, SSL_AD_NO_ALERT,
+ SSL_R_WRONG_VERSION_NUMBER);
+ return 0;
+ }
+ /* Send back error using their minor version number */
+ rl->version = (unsigned short)rec->rec_version;
+ }
+ RLAYERfatal(rl, SSL_AD_PROTOCOL_VERSION,
+ SSL_R_WRONG_VERSION_NUMBER);
+ return 0;
}
+
if (rec->length > SSL3_RT_MAX_PLAIN_LENGTH) {
/*
* We use SSL_R_DATA_LENGTH_TOO_LONG instead of