mirror of
https://github.com/openssl/openssl.git
synced 2025-01-30 14:01:55 +08:00
QUIC CONFORMANCE: Validate RESET_STREAM final sizes correctly
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Paul Dale <pauli@openssl.org> (Merged from https://github.com/openssl/openssl/pull/21135)
This commit is contained in:
parent
c407d5e568
commit
2cc0e2dddf
@ -720,7 +720,8 @@ int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm,
|
||||
/* RECV/SIZE_KNOWN/DATA_RECVD -> RESET_RECVD */
|
||||
int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm,
|
||||
QUIC_STREAM *qs,
|
||||
uint64_t app_error_code);
|
||||
uint64_t app_error_code,
|
||||
uint64_t final_size);
|
||||
|
||||
/* RESET_RECVD -> RESET_READ */
|
||||
int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm,
|
||||
|
@ -137,6 +137,7 @@ static int depack_do_frame_reset_stream(PACKET *pkt,
|
||||
{
|
||||
OSSL_QUIC_FRAME_RESET_STREAM frame_data;
|
||||
QUIC_STREAM *stream = NULL;
|
||||
uint64_t fce;
|
||||
|
||||
if (!ossl_quic_wire_decode_frame_reset_stream(pkt, &frame_data)) {
|
||||
ossl_quic_channel_raise_protocol_error(ch,
|
||||
@ -166,6 +167,35 @@ static int depack_do_frame_reset_stream(PACKET *pkt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The final size field of the RESET_STREAM frame must be used to determine
|
||||
* how much flow control credit the aborted stream was considered to have
|
||||
* consumed.
|
||||
*
|
||||
* We also need to ensure that if we already have a final size for the
|
||||
* stream, the RESET_STREAM frame's Final Size field matches this; we SHOULD
|
||||
* terminate the connection otherwise (RFC 9000 s. 4.5). The RXFC takes care
|
||||
* of this for us.
|
||||
*/
|
||||
if (!ossl_quic_rxfc_on_rx_stream_frame(&stream->rxfc,
|
||||
frame_data.final_size, /*is_fin=*/1)) {
|
||||
ossl_quic_channel_raise_protocol_error(ch,
|
||||
QUIC_ERR_INTERNAL_ERROR,
|
||||
OSSL_QUIC_FRAME_TYPE_RESET_STREAM,
|
||||
"internal error (flow control)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Has a flow control error occurred? */
|
||||
fce = ossl_quic_rxfc_get_error(&stream->rxfc, 0);
|
||||
if (fce != QUIC_ERR_NO_ERROR) {
|
||||
ossl_quic_channel_raise_protocol_error(ch,
|
||||
fce,
|
||||
OSSL_QUIC_FRAME_TYPE_RESET_STREAM,
|
||||
"flow control violation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Depending on the receive part state this is handled either as a reset
|
||||
* transition or a no-op (e.g. if a reset has already been received before,
|
||||
@ -173,7 +203,8 @@ static int depack_do_frame_reset_stream(PACKET *pkt,
|
||||
* protoocol error conditions we need to check for here.
|
||||
*/
|
||||
ossl_quic_stream_map_notify_reset_recv_part(&ch->qsm, stream,
|
||||
frame_data.app_error_code);
|
||||
frame_data.app_error_code,
|
||||
frame_data.final_size);
|
||||
|
||||
ossl_quic_stream_map_update_state(&ch->qsm, stream);
|
||||
return 1;
|
||||
|
@ -562,8 +562,11 @@ int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm,
|
||||
|
||||
int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm,
|
||||
QUIC_STREAM *qs,
|
||||
uint64_t app_error_code)
|
||||
uint64_t app_error_code,
|
||||
uint64_t final_size)
|
||||
{
|
||||
uint64_t prev_final_size;
|
||||
|
||||
switch (qs->recv_state) {
|
||||
default:
|
||||
case QUIC_RSTREAM_STATE_NONE:
|
||||
@ -573,6 +576,11 @@ int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm,
|
||||
case QUIC_RSTREAM_STATE_RECV:
|
||||
case QUIC_RSTREAM_STATE_SIZE_KNOWN:
|
||||
case QUIC_RSTREAM_STATE_DATA_RECVD:
|
||||
if (ossl_quic_stream_recv_get_final_size(qs, &prev_final_size)
|
||||
&& prev_final_size != final_size)
|
||||
/* Cannot change previous final size. */
|
||||
return 0;
|
||||
|
||||
qs->recv_state = QUIC_RSTREAM_STATE_RESET_RECVD;
|
||||
qs->peer_reset_stream_aec = app_error_code;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user