mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-18 20:49:28 +00:00
99 lines
3.3 KiB
C
99 lines
3.3 KiB
C
/* Provenance: openssl/openssl tls_parse_stoc_alpn (fixed).
|
|||
|
|
* repo: openssl/openssl
|
||
|
|
* commit: 4b375b998798dd516d367036773073e1b88e6433
|
||
|
|
* parent: 189a7ed3e380e34ea38fe4190a7c9396bace0fb7
|
||
|
|
* commit_url: https://github.com/openssl/openssl/commit/4b375b998798dd516d367036773073e1b88e6433
|
||
|
|
* cve: CVE-2024-5535
|
||
|
|
* license: Apache-2.0
|
||
|
|
* function: tls_parse_stoc_alpn
|
||
|
|
* relpath: ssl/statem/extensions_clnt.c
|
||
|
|
*/
|
||
|
|
|
||
|
|
int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||
|
|
size_t chainidx)
|
||
|
|
{
|
||
|
|
size_t len;
|
||
|
|
PACKET confpkt, protpkt;
|
||
|
|
int valid = 0;
|
||
|
|
|
||
|
|
/* We must have requested it. */
|
||
|
|
if (!s->s3.alpn_sent) {
|
||
|
|
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_R_BAD_EXTENSION);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
/*-
|
||
|
|
* The extension data consists of:
|
||
|
|
* uint16 list_length
|
||
|
|
* uint8 proto_length;
|
||
|
|
* uint8 proto[proto_length];
|
||
|
|
*/
|
||
|
|
if (!PACKET_get_net_2_len(pkt, &len)
|
||
|
|
|| PACKET_remaining(pkt) != len || !PACKET_get_1_len(pkt, &len)
|
||
|
|
|| PACKET_remaining(pkt) != len) {
|
||
|
|
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* It must be a protocol that we sent */
|
||
|
|
if (!PACKET_buf_init(&confpkt, s->ext.alpn, s->ext.alpn_len)) {
|
||
|
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
while (PACKET_get_length_prefixed_1(&confpkt, &protpkt)) {
|
||
|
|
if (PACKET_remaining(&protpkt) != len)
|
||
|
|
continue;
|
||
|
|
if (memcmp(PACKET_data(pkt), PACKET_data(&protpkt), len) == 0) {
|
||
|
|
/* Valid protocol found */
|
||
|
|
valid = 1;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!valid) {
|
||
|
|
/* The protocol sent from the server does not match one we advertised */
|
||
|
|
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
OPENSSL_free(s->s3.alpn_selected);
|
||
|
|
s->s3.alpn_selected = OPENSSL_malloc(len);
|
||
|
|
if (s->s3.alpn_selected == NULL) {
|
||
|
|
s->s3.alpn_selected_len = 0;
|
||
|
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if (!PACKET_copy_bytes(pkt, s->s3.alpn_selected, len)) {
|
||
|
|
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
s->s3.alpn_selected_len = len;
|
||
|
|
|
||
|
|
if (s->session->ext.alpn_selected == NULL
|
||
|
|
|| s->session->ext.alpn_selected_len != len
|
||
|
|
|| memcmp(s->session->ext.alpn_selected, s->s3.alpn_selected, len)
|
||
|
|
!= 0) {
|
||
|
|
/* ALPN not consistent with the old session so cannot use early_data */
|
||
|
|
s->ext.early_data_ok = 0;
|
||
|
|
}
|
||
|
|
if (!s->hit) {
|
||
|
|
/*
|
||
|
|
* This is a new session and so alpn_selected should have been
|
||
|
|
* initialised to NULL. We should update it with the selected ALPN.
|
||
|
|
*/
|
||
|
|
if (!ossl_assert(s->session->ext.alpn_selected == NULL)) {
|
||
|
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
s->session->ext.alpn_selected =
|
||
|
|
OPENSSL_memdup(s->s3.alpn_selected, s->s3.alpn_selected_len);
|
||
|
|
if (s->session->ext.alpn_selected == NULL) {
|
||
|
|
s->session->ext.alpn_selected_len = 0;
|
||
|
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
s->session->ext.alpn_selected_len = s->s3.alpn_selected_len;
|
||
|
|
}
|
||
|
|
|
||
|
|
return 1;
|
||
|
|
}
|