mirror of
https://github.com/openssl/openssl.git
synced 2025-01-18 13:44:20 +08:00
Fix SSL_select_next_proto
Ensure that the provided client list is non-NULL and starts with a valid entry. When called from the ALPN callback the client list should already have been validated by OpenSSL so this should not cause a problem. When called from the NPN callback the client list is locally configured and will not have already been validated. Therefore SSL_select_next_proto should not assume that it is correctly formatted. We implement stricter checking of the client protocol list. We also do the same for the server list while we are about it. CVE-2024-5535 Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Neil Horman <nhorman@openssl.org> (Merged from https://github.com/openssl/openssl/pull/24716)
This commit is contained in:
parent
b76a6c26a2
commit
2ebbe2d7ca
@ -3535,37 +3535,54 @@ int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
|
|||||||
unsigned int server_len,
|
unsigned int server_len,
|
||||||
const unsigned char *client, unsigned int client_len)
|
const unsigned char *client, unsigned int client_len)
|
||||||
{
|
{
|
||||||
unsigned int i, j;
|
PACKET cpkt, csubpkt, spkt, ssubpkt;
|
||||||
const unsigned char *result;
|
|
||||||
int status = OPENSSL_NPN_UNSUPPORTED;
|
if (!PACKET_buf_init(&cpkt, client, client_len)
|
||||||
|
|| !PACKET_get_length_prefixed_1(&cpkt, &csubpkt)
|
||||||
|
|| PACKET_remaining(&csubpkt) == 0) {
|
||||||
|
*out = NULL;
|
||||||
|
*outlen = 0;
|
||||||
|
return OPENSSL_NPN_NO_OVERLAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the default opportunistic protocol. Will be overwritten if we find
|
||||||
|
* a match.
|
||||||
|
*/
|
||||||
|
*out = (unsigned char *)PACKET_data(&csubpkt);
|
||||||
|
*outlen = (unsigned char)PACKET_remaining(&csubpkt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For each protocol in server preference order, see if we support it.
|
* For each protocol in server preference order, see if we support it.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < server_len;) {
|
if (PACKET_buf_init(&spkt, server, server_len)) {
|
||||||
for (j = 0; j < client_len;) {
|
while (PACKET_get_length_prefixed_1(&spkt, &ssubpkt)) {
|
||||||
if (server[i] == client[j] &&
|
if (PACKET_remaining(&ssubpkt) == 0)
|
||||||
memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) {
|
continue; /* Invalid - ignore it */
|
||||||
/* We found a match */
|
if (PACKET_buf_init(&cpkt, client, client_len)) {
|
||||||
result = &server[i];
|
while (PACKET_get_length_prefixed_1(&cpkt, &csubpkt)) {
|
||||||
status = OPENSSL_NPN_NEGOTIATED;
|
if (PACKET_equal(&csubpkt, PACKET_data(&ssubpkt),
|
||||||
goto found;
|
PACKET_remaining(&ssubpkt))) {
|
||||||
|
/* We found a match */
|
||||||
|
*out = (unsigned char *)PACKET_data(&ssubpkt);
|
||||||
|
*outlen = (unsigned char)PACKET_remaining(&ssubpkt);
|
||||||
|
return OPENSSL_NPN_NEGOTIATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Ignore spurious trailing bytes in the client list */
|
||||||
|
} else {
|
||||||
|
/* This should never happen */
|
||||||
|
return OPENSSL_NPN_NO_OVERLAP;
|
||||||
}
|
}
|
||||||
j += client[j];
|
|
||||||
j++;
|
|
||||||
}
|
}
|
||||||
i += server[i];
|
/* Ignore spurious trailing bytes in the server list */
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There's no overlap between our protocols and the server's list. */
|
/*
|
||||||
result = client;
|
* There's no overlap between our protocols and the server's list. We use
|
||||||
status = OPENSSL_NPN_NO_OVERLAP;
|
* the default opportunistic protocol selected earlier
|
||||||
|
*/
|
||||||
found:
|
return OPENSSL_NPN_NO_OVERLAP;
|
||||||
*out = (unsigned char *)result + 1;
|
|
||||||
*outlen = result[0];
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
|
Loading…
Reference in New Issue
Block a user