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
commit995ff282103d444844a476ae6aba4a05936284fa (patch)
tree44af5e5bcfe7c2ce829eb9bd9cef612fd8615bcc
parentcb68ce9fa7e2312afd8e5346a799d32024b67d02 (diff)
downloadopenssl-new-995ff282103d444844a476ae6aba4a05936284fa.tar.gz
QUIC CHANNEL, APL: Reject policy handling
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_channel.h17
-rw-r--r--ssl/quic/quic_channel.c24
-rw-r--r--ssl/quic/quic_channel_local.h9
-rw-r--r--ssl/quic/quic_impl.c87
4 files changed, 107 insertions, 30 deletions
diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h
index 74b3473782..32e5a57fd9 100644
--- a/include/internal/quic_channel.h
+++ b/include/internal/quic_channel.h
@@ -299,6 +299,23 @@ QUIC_STREAM *ossl_quic_channel_new_stream_local(QUIC_CHANNEL *ch, int is_uni);
QUIC_STREAM *ossl_quic_channel_new_stream_remote(QUIC_CHANNEL *ch,
uint64_t stream_id);
+/*
+ * Configures incoming stream auto-reject. If enabled, incoming streams have
+ * both their sending and receiving parts automatically rejected using
+ * STOP_SENDING and STREAM_RESET frames. aec is the application error
+ * code to be used for those frames.
+ */
+void ossl_quic_channel_set_incoming_stream_auto_reject(QUIC_CHANNEL *ch,
+ int enable,
+ uint64_t aec);
+
+/*
+ * Causes the channel to reject the sending and receiving parts of a stream,
+ * as though autorejected. Can be used if a stream has already been
+ * accepted.
+ */
+void ossl_quic_channel_reject_stream(QUIC_CHANNEL *ch, QUIC_STREAM *qs);
+
# endif
#endif
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c
index f11139132f..3e099e9d93 100644
--- a/ssl/quic/quic_channel.c
+++ b/ssl/quic/quic_channel.c
@@ -2342,10 +2342,32 @@ QUIC_STREAM *ossl_quic_channel_new_stream_remote(QUIC_CHANNEL *ch,
if (!ch_init_new_stream(ch, qs, /*can_send=*/!is_uni, /*can_recv=*/1))
goto err;
- ossl_quic_stream_map_push_accept_queue(&ch->qsm, qs);
+ if (ch->incoming_stream_auto_reject)
+ ossl_quic_channel_reject_stream(ch, qs);
+ else
+ ossl_quic_stream_map_push_accept_queue(&ch->qsm, qs);
+
return qs;
err:
ossl_quic_stream_map_release(&ch->qsm, qs);
return NULL;
}
+
+void ossl_quic_channel_set_incoming_stream_auto_reject(QUIC_CHANNEL *ch,
+ int enable,
+ uint64_t aec)
+{
+ ch->incoming_stream_auto_reject = (enable != 0);
+ ch->incoming_stream_auto_reject_aec = aec;
+}
+
+void ossl_quic_channel_reject_stream(QUIC_CHANNEL *ch, QUIC_STREAM *qs)
+{
+ ossl_quic_stream_stop_sending(qs, ch->incoming_stream_auto_reject_aec);
+ ossl_quic_stream_reset(qs, ch->incoming_stream_auto_reject_aec);
+
+ qs->deleted = 1;
+
+ ossl_quic_stream_map_update_state(&ch->qsm, qs);
+}
diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h
index 3645c277dd..a1ce833f56 100644
--- a/ssl/quic/quic_channel_local.h
+++ b/ssl/quic/quic_channel_local.h
@@ -167,6 +167,12 @@ struct quic_channel_st {
uint64_t next_local_stream_ordinal_bidi;
uint64_t next_local_stream_ordinal_uni;
+ /*
+ * Application error code to be used for STOP_SENDING/RESET_STREAM frames
+ * used to autoreject incoming streams.
+ */
+ uint64_t incoming_stream_auto_reject_aec;
+
/* Valid if we are in the TERMINATING or TERMINATED states. */
QUIC_TERMINATE_CAUSE terminate_cause;
@@ -290,6 +296,9 @@ struct quic_channel_st {
* 10.1).
*/
unsigned int have_sent_ack_eliciting_since_rx : 1;
+
+ /* Should incoming streams automatically be rejected? */
+ unsigned int incoming_stream_auto_reject : 1;
};
# endif
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index 840dcfed96..2dd5a4f91f 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -25,6 +25,9 @@ static int qc_wait_for_default_xso_for_read(QUIC_CONNECTION *qc);
static void quic_lock(QUIC_CONNECTION *qc);
static void quic_unlock(QUIC_CONNECTION *qc);
static int quic_do_handshake(QUIC_CONNECTION *qc);
+static void qc_update_reject_policy(QUIC_CONNECTION *qc);
+static void qc_touch_default_xso(QUIC_CONNECTION *qc);
+static void qc_set_default_xso(QUIC_CONNECTION *qc, QUIC_XSO *xso, int touch);
/*
* QUIC Front-End I/O API: Common Utilities
@@ -303,6 +306,8 @@ SSL *ossl_quic_new(SSL_CTX *ctx)
if (!create_channel(qc))
goto err;
+ qc_update_reject_policy(qc);
+
/*
* We do not create the default XSO yet. The reason for this is that the
* stream ID of the default XSO will depend on whether the stream is client
@@ -458,6 +463,21 @@ void ossl_quic_conn_force_assist_thread_wake(SSL *s)
ossl_quic_thread_assist_notify_deadline_changed(&ctx.qc->thread_assist);
}
+QUIC_NEEDS_LOCK
+static void qc_touch_default_xso(QUIC_CONNECTION *qc)
+{
+ qc->default_xso_created = 1;
+ qc_update_reject_policy(qc);
+}
+
+QUIC_NEEDS_LOCK
+static void qc_set_default_xso(QUIC_CONNECTION *qc, QUIC_XSO *xso, int touch)
+{
+ qc->default_xso = xso;
+ if (touch)
+ qc_touch_default_xso(qc);
+}
+
/*
* QUIC Front-End I/O API: Network BIO Configuration
* =================================================
@@ -1170,11 +1190,12 @@ static int qc_try_create_default_xso_for_write(QUIC_CONNECTION *qc)
if (qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_AUTO_UNI)
flags |= SSL_STREAM_FLAG_UNI;
- qc->default_xso = (QUIC_XSO *)ossl_quic_conn_stream_new(&qc->ssl, flags);
+ qc_set_default_xso(qc, (QUIC_XSO *)ossl_quic_conn_stream_new(&qc->ssl, flags),
+ /*touch=*/0);
if (qc->default_xso == NULL)
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
- qc->default_xso_created = 1;
+ qc_touch_default_xso(qc);
return 1;
}
@@ -1267,11 +1288,11 @@ static int qc_wait_for_default_xso_for_read(QUIC_CONNECTION *qc)
* We now have qs != NULL. Make it the default stream, creating the
* necessary XSO.
*/
- qc->default_xso = create_xso_from_stream(qc, qs);
+ qc_set_default_xso(qc, create_xso_from_stream(qc, qs), /*touch=*/0);
if (qc->default_xso == NULL)
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
- qc->default_xso_created = 1;
+ qc_touch_default_xso(qc); /* inhibits default XSO */
return 1;
}
@@ -1326,7 +1347,7 @@ SSL *ossl_quic_conn_stream_new(SSL *s, uint64_t flags)
if (xso == NULL)
goto err;
- ctx.qc->default_xso_created = 1; /* inhibits default XSO */
+ qc_touch_default_xso(ctx.qc); /* inhibits default XSO */
quic_unlock(ctx.qc);
return &xso->ssl;
@@ -2055,11 +2076,9 @@ SSL *ossl_quic_detach_stream(SSL *s)
quic_lock(ctx.qc);
- xso = ctx.qc->default_xso;
- ctx.qc->default_xso = NULL;
-
/* Calling this function inhibits default XSO autocreation. */
- ctx.qc->default_xso_created = 1;
+ xso = ctx.qc->default_xso;
+ qc_set_default_xso(ctx.qc, NULL, /*touch=*/1);
quic_unlock(ctx.qc);
@@ -2090,10 +2109,8 @@ int ossl_quic_attach_stream(SSL *conn, SSL *stream)
"connection already has a default stream");
}
- ctx.qc->default_xso = (QUIC_XSO *)stream;
-
/* Calling this function inhibits default XSO autocreation. */
- ctx.qc->default_xso_created = 1;
+ qc_set_default_xso(ctx.qc, (QUIC_XSO *)stream, /*touch=*/1);
quic_unlock(ctx.qc);
return 1;
@@ -2103,6 +2120,33 @@ int ossl_quic_attach_stream(SSL *conn, SSL *stream)
* SSL_set_incoming_stream_reject_policy
* -------------------------------------
*/
+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;
+ }
+}
+
+QUIC_NEEDS_LOCK
+static void qc_update_reject_policy(QUIC_CONNECTION *qc)
+{
+ int policy = qc_get_effective_incoming_stream_reject_policy(qc);
+ int enable_reject = (policy == SSL_INCOMING_STREAM_REJECT_POLICY_REJECT);
+
+ ossl_quic_channel_set_incoming_stream_auto_reject(qc->ch,
+ enable_reject,
+ qc->incoming_stream_reject_aec);
+}
+
QUIC_TAKES_LOCK
int ossl_quic_set_incoming_stream_reject_policy(SSL *s, int policy,
uint64_t aec)
@@ -2128,6 +2172,7 @@ int ossl_quic_set_incoming_stream_reject_policy(SSL *s, int policy,
break;
}
+ qc_update_reject_policy(ctx.qc);
quic_unlock(ctx.qc);
return ret;
}
@@ -2136,22 +2181,6 @@ 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;
@@ -2228,7 +2257,7 @@ SSL *ossl_quic_accept_stream(SSL *s, uint64_t flags)
new_s = &xso->ssl;
/* Calling this function inhibits default XSO autocreation. */
- ctx.qc->default_xso_created = 1;
+ qc_touch_default_xso(ctx.qc); /* inhibits default XSO */
out:
quic_unlock(ctx.qc);