summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorNeil Horman <nhorman@openssl.org>2024-09-05 21:49:14 +0200
committerNeil Horman <nhorman@openssl.org>2024-09-13 21:05:29 +0200
commitc8127df04cae8d6a0d913e6e5c760062817a202e (patch)
tree87c312d23f1840c3c12e15f06ef1a91b15737fac /ssl
parentdocs: Correct bad link to provider-keymgmt(7) in provider-signature(7) (diff)
downloadopenssl-c8127df04cae8d6a0d913e6e5c760062817a202e.tar.xz
openssl-c8127df04cae8d6a0d913e6e5c760062817a202e.zip
Detect fin state of a QUIC stream for streams which are completely read
SSL_poll indicates that a stream which has had the fin bit set on it, should generate SSL_POLL_EVENT_R events, so that applications can detect stream completion via SSL_read_ex and SSL_get_error returning SSL_ERROR_ZERO_RETURN. However, the quic polling code misses on this, as a client that completely reads a buffer after receipt has its underlying stream buffer freed, loosing the fin status We can however detect stream completion still, as a stream which has been finalized, and had all its data read will be in the QUIC_RSTREAM_STATE_DATA_READ state, iff the fin bit was set. Fix it by checking in test_poll_event_r for that state, and generating a SSL_POLL_EVENT_R if its found to be true, so as to stay in line with the docs. Fixes openssl/private#627 Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Sasa Nedvedicky <sashan@openssl.org> (Merged from https://github.com/openssl/openssl/pull/25399)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/quic/quic_impl.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index 539d6d9b78..6d6592e956 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -4023,6 +4023,22 @@ static int test_poll_event_r(QUIC_XSO *xso)
int fin = 0;
size_t avail = 0;
+ /*
+ * If a stream has had the fin bit set on the last packet
+ * received, then we need to return a 1 here to raise
+ * SSL_POLL_EVENT_R, so that the stream can have its completion
+ * detected and closed gracefully by an application.
+ * However, if the client reads the data via SSL_read[_ex], that api
+ * provides no stream status, and as a result the stream state moves to
+ * QUIC_RSTREAM_STATE_DATA_READ, and the receive buffer is freed, which
+ * stored the fin state, so its not directly know-able here. Instead
+ * check for the stream state being QUIC_RSTREAM_STATE_DATA_READ, which
+ * is only set if the last stream frame received had the fin bit set, and
+ * the client read the data. This catches our poll/read/poll case
+ */
+ if (xso->stream->recv_state == QUIC_RSTREAM_STATE_DATA_READ)
+ return 1;
+
return ossl_quic_stream_has_recv_buffer(xso->stream)
&& ossl_quic_rstream_available(xso->stream->rstream, &avail, &fin)
&& (avail > 0 || (fin && !xso->retired_fin));