summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2023-07-26 18:10:16 +0100
committerHugo Landau <hlandau@openssl.org>2023-08-10 18:19:45 +0100
commit40c8c756c86fc17751b989426aa66fb33319c4ca (patch)
tree77eae277108a725e7ea4d2b7c52cd4fb05f49d05 /ssl
parentd56b81ac9f02dd55ecf3281d16fdb156897b4d8d (diff)
QUIC APL/CHANNEL: Wire up connection closure reason
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/21565)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/quic/quic_channel.c47
-rw-r--r--ssl/quic/quic_impl.c7
-rw-r--r--ssl/quic/quic_tserver.c2
3 files changed, 48 insertions, 8 deletions
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c
index 6931f79d01..a4f451d6b9 100644
--- a/ssl/quic/quic_channel.c
+++ b/ssl/quic/quic_channel.c
@@ -371,6 +371,7 @@ static void ch_cleanup(QUIC_CHANNEL *ch)
ossl_qrx_free(ch->qrx);
ossl_quic_demux_free(ch->demux);
OPENSSL_free(ch->local_transport_params);
+ OPENSSL_free((char *)ch->terminate_cause.reason);
OSSL_ERR_STATE_free(ch->err_state);
}
@@ -2438,7 +2439,8 @@ int ossl_quic_channel_start(QUIC_CHANNEL *ch)
}
/* Start a locally initiated connection shutdown. */
-void ossl_quic_channel_local_close(QUIC_CHANNEL *ch, uint64_t app_error_code)
+void ossl_quic_channel_local_close(QUIC_CHANNEL *ch, uint64_t app_error_code,
+ const char *app_reason)
{
QUIC_TERMINATE_CAUSE tcause = {0};
@@ -2447,6 +2449,8 @@ void ossl_quic_channel_local_close(QUIC_CHANNEL *ch, uint64_t app_error_code)
tcause.app = 1;
tcause.error_code = app_error_code;
+ tcause.reason = app_reason;
+ tcause.reason_len = app_reason != NULL ? strlen(app_reason) : 0;
ch_start_terminating(ch, &tcause, 0);
}
@@ -2622,6 +2626,37 @@ int ossl_quic_channel_on_handshake_confirmed(QUIC_CHANNEL *ch)
* closing state and send a packet containing a CONNECTION_CLOSE
* frame in response to any UDP datagram that is received.
*/
+static void copy_tcause(QUIC_TERMINATE_CAUSE *dst,
+ const QUIC_TERMINATE_CAUSE *src)
+{
+ dst->error_code = src->error_code;
+ dst->frame_type = src->frame_type;
+ dst->app = src->app;
+ dst->remote = src->remote;
+
+ dst->reason = NULL;
+ dst->reason_len = 0;
+
+ if (src->reason != NULL && src->reason_len > 0) {
+ size_t l = src->reason_len;
+ char *r;
+
+ if (l >= SIZE_MAX)
+ --l;
+
+ /*
+ * If this fails, dst->reason becomes NULL and we simply do not use a
+ * reason. This ensures termination is infallible.
+ */
+ dst->reason = r = OPENSSL_memdup(src->reason, l + 1);
+ if (r == NULL)
+ return;
+
+ r[l] = '\0';
+ dst->reason_len = l;
+ }
+}
+
static void ch_start_terminating(QUIC_CHANNEL *ch,
const QUIC_TERMINATE_CAUSE *tcause,
int force_immediate)
@@ -2629,12 +2664,12 @@ static void ch_start_terminating(QUIC_CHANNEL *ch,
switch (ch->state) {
default:
case QUIC_CHANNEL_STATE_IDLE:
- ch->terminate_cause = *tcause;
+ copy_tcause(&ch->terminate_cause, tcause);
ch_on_terminating_timeout(ch);
break;
case QUIC_CHANNEL_STATE_ACTIVE:
- ch->terminate_cause = *tcause;
+ copy_tcause(&ch->terminate_cause, tcause);
if (!force_immediate) {
ch->state = tcause->remote ? QUIC_CHANNEL_STATE_TERMINATING_DRAINING
@@ -2656,6 +2691,8 @@ static void ch_start_terminating(QUIC_CHANNEL *ch,
f.error_code = ch->terminate_cause.error_code;
f.frame_type = ch->terminate_cause.frame_type;
f.is_app = ch->terminate_cause.app;
+ f.reason = (char *)ch->terminate_cause.reason;
+ f.reason_len = ch->terminate_cause.reason_len;
ossl_quic_tx_packetiser_schedule_conn_close(ch->txp, &f);
/*
* RFC 9000 s. 10.2.2 Draining Connection State:
@@ -2714,7 +2751,8 @@ void ossl_quic_channel_on_remote_conn_close(QUIC_CHANNEL *ch,
tcause.app = f->is_app;
tcause.error_code = f->error_code;
tcause.frame_type = f->frame_type;
-
+ tcause.reason = f->reason;
+ tcause.reason_len = f->reason_len;
ch_start_terminating(ch, &tcause, 0);
}
@@ -2967,6 +3005,7 @@ void ossl_quic_channel_raise_protocol_error_loc(QUIC_CHANNEL *ch,
tcause.error_code = error_code;
tcause.frame_type = frame_type;
+ tcause.reason = reason;
ch_start_terminating(ch, &tcause, 0);
}
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index ca00fcd476..ba5b27eeb4 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -1200,7 +1200,8 @@ int ossl_quic_conn_shutdown(SSL *s, uint64_t flags,
/* Phase 2: Connection Closure */
ossl_quic_channel_local_close(ctx.qc->ch,
- args != NULL ? args->quic_error_code : 0);
+ args != NULL ? args->quic_error_code : 0,
+ args != NULL ? args->quic_reason : NULL);
SSL_set_shutdown(ctx.qc->tls, SSL_SENT_SHUTDOWN);
@@ -3043,8 +3044,8 @@ int ossl_quic_get_conn_close_info(SSL *ssl,
return 0;
info->error_code = tc->error_code;
- info->reason = NULL; /* TODO(QUIC): Wire reason */
- info->reason_len = 0;
+ info->reason = tc->reason;
+ info->reason_len = tc->reason_len;
info->is_local = !tc->remote;
info->is_transport = !tc->app;
return 1;
diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c
index 15444ecc5b..b92b1de8da 100644
--- a/ssl/quic/quic_tserver.c
+++ b/ssl/quic/quic_tserver.c
@@ -488,7 +488,7 @@ OSSL_TIME ossl_quic_tserver_get_deadline(QUIC_TSERVER *srv)
int ossl_quic_tserver_shutdown(QUIC_TSERVER *srv)
{
- ossl_quic_channel_local_close(srv->ch, 0);
+ ossl_quic_channel_local_close(srv->ch, 0, NULL);
/* TODO(QUIC): !SSL_SHUTDOWN_FLAG_NO_STREAM_FLUSH */