summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2023-04-18 19:30:55 +0100
committerHugo Landau <hlandau@openssl.org>2023-05-12 14:47:12 +0100
commitcb68ce9fa7e2312afd8e5346a799d32024b67d02 (patch)
tree08174897813e28d600f9da0144ab761061bc8b8c
parent8a90df343edb194920b7a01c8b5e47d8b6e952c5 (diff)
downloadopenssl-new-cb68ce9fa7e2312afd8e5346a799d32024b67d02.tar.gz
QUIC DISPATCH/APL: SSL_accept_stream, SSL_get_accept_queue_len
Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20765)
-rw-r--r--include/internal/quic_ssl.h2
-rw-r--r--include/openssl/ssl.h.in4
-rw-r--r--ssl/quic/quic_impl.c129
-rw-r--r--ssl/ssl_lib.c24
-rw-r--r--util/libssl.num2
5 files changed, 161 insertions, 0 deletions
diff --git a/include/internal/quic_ssl.h b/include/internal/quic_ssl.h
index d307a9e196..ed17005843 100644
--- a/include/internal/quic_ssl.h
+++ b/include/internal/quic_ssl.h
@@ -74,6 +74,8 @@ __owur SSL *ossl_quic_detach_stream(SSL *s);
__owur int ossl_quic_attach_stream(SSL *conn, SSL *stream);
__owur int ossl_quic_set_incoming_stream_reject_policy(SSL *s, int policy,
uint64_t aec);
+__owur SSL *ossl_quic_accept_stream(SSL *s, uint64_t flags);
+__owur size_t ossl_quic_get_accept_stream_queue_len(SSL *s);
/*
* Used to override ossl_time_now() for debug purposes. Must be called before
diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in
index d29ad85ece..dcc7cfdb3a 100644
--- a/include/openssl/ssl.h.in
+++ b/include/openssl/ssl.h.in
@@ -2293,6 +2293,10 @@ __owur SSL *SSL_new_stream(SSL *s, uint64_t flags);
#define SSL_INCOMING_STREAM_REJECT_POLICY_REJECT 2
__owur int SSL_set_incoming_stream_reject_policy(SSL *s, int policy, uint64_t aec);
+#define SSL_ACCEPT_STREAM_NO_BLOCK (1U << 0)
+__owur SSL *SSL_accept_stream(SSL *s, uint64_t flags);
+__owur size_t SSL_get_accept_stream_queue_len(SSL *s);
+
# ifndef OPENSSL_NO_QUIC
__owur int SSL_inject_net_dgram(SSL *s, const unsigned char *buf,
size_t buf_len,
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index e76526a1b9..840dcfed96 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -1991,6 +1991,7 @@ int ossl_quic_get_stream_type(SSL *s)
* SSL_get_stream_id
* -----------------
*/
+QUIC_TAKES_LOCK
uint64_t ossl_quic_get_stream_id(SSL *s)
{
QCTX ctx;
@@ -2009,6 +2010,7 @@ uint64_t ossl_quic_get_stream_id(SSL *s)
* SSL_set_default_stream_mode
* ---------------------------
*/
+QUIC_TAKES_LOCK
int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode)
{
QCTX ctx;
@@ -2042,6 +2044,7 @@ int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode)
* SSL_detach_stream
* -----------------
*/
+QUIC_TAKES_LOCK
SSL *ossl_quic_detach_stream(SSL *s)
{
QCTX ctx;
@@ -2067,6 +2070,7 @@ SSL *ossl_quic_detach_stream(SSL *s)
* SSL_attach_stream
* -----------------
*/
+QUIC_TAKES_LOCK
int ossl_quic_attach_stream(SSL *conn, SSL *stream)
{
QCTX ctx;
@@ -2099,6 +2103,7 @@ int ossl_quic_attach_stream(SSL *conn, SSL *stream)
* SSL_set_incoming_stream_reject_policy
* -------------------------------------
*/
+QUIC_TAKES_LOCK
int ossl_quic_set_incoming_stream_reject_policy(SSL *s, int policy,
uint64_t aec)
{
@@ -2128,6 +2133,130 @@ int ossl_quic_set_incoming_stream_reject_policy(SSL *s, int policy,
}
/*
+ * SSL_accept_stream
+ * -----------------
+ */
+QUIC_NEEDS_LOCK
+static int qc_get_effective_incoming_stream_reject_policy(QUIC_CONNECTION *qc)
+{
+ switch (qc->incoming_stream_reject_policy) {
+ case SSL_INCOMING_STREAM_REJECT_POLICY_AUTO:
+ if ((qc->default_xso == NULL && qc->default_xso_created)
+ || qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_NONE)
+ return SSL_INCOMING_STREAM_REJECT_POLICY_ACCEPT;
+ else
+ return SSL_INCOMING_STREAM_REJECT_POLICY_REJECT;
+
+ default:
+ return qc->incoming_stream_reject_policy;
+ }
+}
+
+struct wait_for_incoming_stream_args {
+ QUIC_CONNECTION *qc;
+ QUIC_STREAM *qs;
+};
+
+QUIC_NEEDS_LOCK
+static int wait_for_incoming_stream(void *arg)
+{
+ struct wait_for_incoming_stream_args *args = arg;
+ QUIC_STREAM_MAP *qsm = ossl_quic_channel_get_qsm(args->qc->ch);
+
+ if (!ossl_quic_channel_is_active(args->qc->ch)) {
+ /* If connection is torn down due to an error while blocking, stop. */
+ QUIC_RAISE_NON_NORMAL_ERROR(args->qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
+ return -1;
+ }
+
+ args->qs = ossl_quic_stream_map_peek_accept_queue(qsm);
+ if (args->qs != NULL)
+ return 1; /* got a stream */
+
+ return 0; /* did not get a stream, keep trying */
+}
+
+QUIC_TAKES_LOCK
+SSL *ossl_quic_accept_stream(SSL *s, uint64_t flags)
+{
+ QCTX ctx;
+ int ret;
+ SSL *new_s = NULL;
+ QUIC_STREAM_MAP *qsm;
+ QUIC_STREAM *qs;
+ QUIC_XSO *xso;
+
+ if (!expect_quic_conn_only(s, &ctx))
+ return NULL;
+
+ quic_lock(ctx.qc);
+
+ if (qc_get_effective_incoming_stream_reject_policy(ctx.qc)
+ == SSL_INCOMING_STREAM_REJECT_POLICY_REJECT)
+ goto out;
+
+ qsm = ossl_quic_channel_get_qsm(ctx.qc->ch);
+
+ qs = ossl_quic_stream_map_peek_accept_queue(qsm);
+ if (qs == NULL) {
+ if (qc_blocking_mode(ctx.qc)
+ && (flags & SSL_ACCEPT_STREAM_NO_BLOCK) == 0) {
+ struct wait_for_incoming_stream_args args;
+
+ args.qc = ctx.qc;
+ args.qs = NULL;
+
+ ret = block_until_pred(ctx.qc, wait_for_incoming_stream, &args, 0);
+ if (ret == 0) {
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_INTERNAL_ERROR, NULL);
+ goto out;
+ } else if (ret < 0 || args.qs == NULL) {
+ goto out;
+ }
+
+ qs = args.qs;
+ } else {
+ goto out;
+ }
+ }
+
+ xso = create_xso_from_stream(ctx.qc, qs);
+ if (xso == NULL)
+ goto out;
+
+ ossl_quic_stream_map_remove_from_accept_queue(qsm, qs);
+ new_s = &xso->ssl;
+
+ /* Calling this function inhibits default XSO autocreation. */
+ ctx.qc->default_xso_created = 1;
+
+out:
+ quic_unlock(ctx.qc);
+ return new_s;
+}
+
+/*
+ * SSL_get_accept_stream_queue_len
+ * -------------------------------
+ */
+QUIC_TAKES_LOCK
+size_t ossl_quic_get_accept_stream_queue_len(SSL *s)
+{
+ QCTX ctx;
+ size_t v;
+
+ if (!expect_quic_conn_only(s, &ctx))
+ return 0;
+
+ quic_lock(ctx.qc);
+
+ v = ossl_quic_stream_map_get_accept_queue_len(ossl_quic_channel_get_qsm(ctx.qc->ch));
+
+ quic_unlock(ctx.qc);
+ return v;
+}
+
+/*
* QUIC Front-End I/O API: SSL_CTX Management
* ==========================================
*/
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 6e3ef08376..1d84ac39dc 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -7400,6 +7400,30 @@ int SSL_set_incoming_stream_reject_policy(SSL *s, int policy, uint64_t aec)
#endif
}
+SSL *SSL_accept_stream(SSL *s, uint64_t flags)
+{
+#ifndef OPENSSL_NO_QUIC
+ if (!IS_QUIC(s))
+ return NULL;
+
+ return ossl_quic_accept_stream(s, flags);
+#else
+ return NULL;
+#endif
+}
+
+size_t SSL_get_accept_stream_queue_len(SSL *s)
+{
+#ifndef OPENSSL_NO_QUIC
+ if (!IS_QUIC(s))
+ return 0;
+
+ return ossl_quic_get_accept_stream_queue_len(s);
+#else
+ return 0;
+#endif
+}
+
int SSL_add_expected_rpk(SSL *s, EVP_PKEY *rpk)
{
unsigned char *data = NULL;
diff --git a/util/libssl.num b/util/libssl.num
index ab28742a81..b99ed33a9e 100644
--- a/util/libssl.num
+++ b/util/libssl.num
@@ -569,3 +569,5 @@ SSL_set_default_stream_mode ? 3_2_0 EXIST::FUNCTION:
SSL_detach_stream ? 3_2_0 EXIST::FUNCTION:
SSL_attach_stream ? 3_2_0 EXIST::FUNCTION:
SSL_set_incoming_stream_reject_policy ? 3_2_0 EXIST::FUNCTION:
+SSL_accept_stream ? 3_2_0 EXIST::FUNCTION:
+SSL_get_accept_stream_queue_len ? 3_2_0 EXIST::FUNCTION: