From e8043229ead9b44e2883a80ce256c219a1171cbb Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Tue, 13 Dec 2022 12:27:05 +0000 Subject: [PATCH] QUIC: Refine SSL_shutdown and begin to implement SSL_shutdown_ex Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/19897) --- include/internal/quic_channel.h | 2 +- include/internal/quic_ssl.h | 5 +++- include/openssl/ssl.h.in | 12 ++++++++ ssl/quic/quic_channel.c | 5 ++-- ssl/quic/quic_impl.c | 52 ++++++++++++++++++++++++--------- ssl/quic/quic_local.h | 2 +- ssl/ssl_lib.c | 26 +++++++++++++++-- util/libssl.num | 1 + 8 files changed, 85 insertions(+), 20 deletions(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index 4d96ab63dfd..83eb90a6625 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -92,7 +92,7 @@ void ossl_quic_channel_free(QUIC_CHANNEL *ch); int ossl_quic_channel_start(QUIC_CHANNEL *ch); /* Start a locally initiated connection shutdown. */ -void ossl_quic_channel_local_close(QUIC_CHANNEL *ch); +void ossl_quic_channel_local_close(QUIC_CHANNEL *ch, uint64_t app_error_code); /* * Called when the handshake is confirmed. diff --git a/include/internal/quic_ssl.h b/include/internal/quic_ssl.h index d319faef515..8846877a4a2 100644 --- a/include/internal/quic_ssl.h +++ b/include/internal/quic_ssl.h @@ -28,7 +28,6 @@ __owur int ossl_quic_connect(SSL *s); __owur int ossl_quic_read(SSL *s, void *buf, size_t len, size_t *readbytes); __owur int ossl_quic_peek(SSL *s, void *buf, size_t len, size_t *readbytes); __owur int ossl_quic_write(SSL *s, const void *buf, size_t len, size_t *written); -__owur int ossl_quic_shutdown(SSL *s); __owur long ossl_quic_ctrl(SSL *s, int cmd, long larg, void *parg); __owur long ossl_quic_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg); __owur long ossl_quic_callback_ctrl(SSL *s, int cmd, void (*fp) (void)); @@ -53,6 +52,10 @@ __owur int ossl_quic_get_net_write_desired(QUIC_CONNECTION *qc); __owur int ossl_quic_get_error(const QUIC_CONNECTION *qc, int i); __owur int ossl_quic_conn_get_blocking_mode(const QUIC_CONNECTION *qc); __owur int ossl_quic_conn_set_blocking_mode(QUIC_CONNECTION *qc, int blocking); +__owur int ossl_quic_conn_shutdown(QUIC_CONNECTION *qc, uint64_t flags, + const SSL_SHUTDOWN_EX_ARGS *args, + size_t args_len); +__owur int ossl_quic_conn_stream_conclude(QUIC_CONNECTION *qc); void ossl_quic_conn_set0_net_rbio(QUIC_CONNECTION *qc, BIO *net_wbio); void ossl_quic_conn_set0_net_wbio(QUIC_CONNECTION *qc, BIO *net_wbio); BIO *ossl_quic_conn_get_net_rbio(const QUIC_CONNECTION *qc); diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in index 0a449684444..095698ea9db 100644 --- a/include/openssl/ssl.h.in +++ b/include/openssl/ssl.h.in @@ -2258,6 +2258,18 @@ __owur int SSL_set_blocking_mode(SSL *s, int blocking); __owur int SSL_get_blocking_mode(SSL *s); __owur int SSL_set_initial_peer_addr(SSL *s, const BIO_ADDR *peer_addr); +typedef struct ssl_shutdown_ex_args_st { + uint64_t quic_error_code; + const char *quic_reason; +} SSL_SHUTDOWN_EX_ARGS; + +#define SSL_SHUTDOWN_FLAG_RAPID (1U << 0) +#define SSL_SHUTDOWN_FLAG_IMMEDIATE (1U << 1) + +__owur int SSL_shutdown_ex(SSL *ssl, uint64_t flags, + const SSL_SHUTDOWN_EX_ARGS *args, + size_t args_len); + # ifndef OPENSSL_NO_DEPRECATED_1_1_0 # define SSL_cache_hit(s) SSL_session_reused(s) # endif diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 3701d93e1cf..bffd0d3244e 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -1712,14 +1712,15 @@ int ossl_quic_channel_start(QUIC_CHANNEL *ch) } /* Start a locally initiated connection shutdown. */ -void ossl_quic_channel_local_close(QUIC_CHANNEL *ch) +void ossl_quic_channel_local_close(QUIC_CHANNEL *ch, uint64_t app_error_code) { QUIC_TERMINATE_CAUSE tcause = {0}; if (ossl_quic_channel_is_term_any(ch)) return; - tcause.app = 1; + tcause.app = 1; + tcause.error_code = app_error_code; ch_start_terminating(ch, &tcause, 0); } diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 6fb868a0045..e869e97ef54 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -18,6 +18,7 @@ #include "internal/time.h" static void aon_write_finish(QUIC_CONNECTION *qc); +static int ensure_channel(QUIC_CONNECTION *qc); /* * QUIC Front-End I/O API: Common Utilities @@ -486,17 +487,34 @@ int ossl_quic_get_net_write_desired(QUIC_CONNECTION *qc) */ /* SSL_shutdown */ -int ossl_quic_shutdown(SSL *s) +static int quic_shutdown_wait(void *arg) { - QUIC_CONNECTION *qc = QUIC_CONNECTION_FROM_SSL(s); + QUIC_CONNECTION *qc = arg; - if (!expect_quic_conn(qc)) - return 0; + return qc->ch == NULL || ossl_quic_channel_is_terminated(qc->ch); +} - if (qc->ch != NULL) - ossl_quic_channel_local_close(qc->ch); +int ossl_quic_conn_shutdown(QUIC_CONNECTION *qc, uint64_t flags, + const SSL_SHUTDOWN_EX_ARGS *args, + size_t args_len) +{ + if (!ensure_channel(qc)) + return -1; - return 1; + ossl_quic_channel_local_close(qc->ch, + args != NULL ? args->quic_error_code : 0); + + /* TODO(QUIC): !SSL_SHUTDOWN_FLAG_IMMEDIATE */ + + if (ossl_quic_channel_is_terminated(qc->ch)) + return 1; + + if (blocking_mode(qc) && (flags & SSL_SHUTDOWN_FLAG_RAPID) == 0) + block_until_pred(qc, quic_shutdown_wait, NULL, 0); + else + ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch)); + + return ossl_quic_channel_is_terminated(qc->ch); } /* SSL_ctrl */ @@ -573,12 +591,7 @@ static int configure_channel(QUIC_CONNECTION *qc) return 1; } -/* - * Creates a channel and configures it with the information we have accumulated - * via calls made to us from the application prior to starting a handshake - * attempt. - */ -static int ensure_channel_and_start(QUIC_CONNECTION *qc) +static int ensure_channel(QUIC_CONNECTION *qc) { QUIC_CHANNEL_ARGS args = {0}; @@ -594,6 +607,19 @@ static int ensure_channel_and_start(QUIC_CONNECTION *qc) if (qc->ch == NULL) return 0; + return 1; +} + +/* + * Creates a channel and configures it with the information we have accumulated + * via calls made to us from the application prior to starting a handshake + * attempt. + */ +static int ensure_channel_and_start(QUIC_CONNECTION *qc) +{ + if (!ensure_channel(qc)) + return 0; + if (!configure_channel(qc) || !ossl_quic_channel_start(qc->ch)) { ossl_quic_channel_free(qc->ch); diff --git a/ssl/quic/quic_local.h b/ssl/quic/quic_local.h index 83cce376fb8..f4397447dd5 100644 --- a/ssl/quic/quic_local.h +++ b/ssl/quic/quic_local.h @@ -198,7 +198,7 @@ const SSL_METHOD *func_name(void) \ ossl_quic_read, \ ossl_quic_peek, \ ossl_quic_write, \ - ossl_quic_shutdown, \ + NULL /* shutdown */, \ NULL /* renegotiate */, \ ossl_quic_renegotiate_check, \ NULL /* read_bytes */, \ diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 1e23ec55e55..b927e283fee 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -2638,6 +2638,12 @@ int SSL_shutdown(SSL *s) * (see ssl3_shutdown). */ SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s); +#ifndef OPENSSL_NO_QUIC + QUIC_CONNECTION *qc = QUIC_CONNECTION_FROM_SSL(s); + + if (qc != NULL) + return ossl_quic_conn_shutdown(qc, 0, NULL, 0); +#endif if (sc == NULL) return -1; @@ -7168,10 +7174,26 @@ int SSL_set_initial_peer_addr(SSL *s, const BIO_ADDR *peer_addr) QUIC_CONNECTION *qc = QUIC_CONNECTION_FROM_SSL(s); if (qc == NULL) - return -1; + return 0; return ossl_quic_conn_set_initial_peer_addr(qc, peer_addr); #else - return -1; + return 0; +#endif +} + +int SSL_shutdown_ex(SSL *ssl, uint64_t flags, + const SSL_SHUTDOWN_EX_ARGS *args, + size_t args_len) +{ +#ifndef OPENSSL_NO_QUIC + QUIC_CONNECTION *qc = QUIC_CONNECTION_FROM_SSL(ssl); + + if (qc == NULL) + return SSL_shutdown(ssl); + + return ossl_quic_conn_shutdown(qc, flags, args, args_len); +#else + return SSL_shutdown(ssl); #endif } diff --git a/util/libssl.num b/util/libssl.num index 38535b11b00..16b4609c078 100644 --- a/util/libssl.num +++ b/util/libssl.num @@ -541,3 +541,4 @@ SSL_get_blocking_mode ? 3_2_0 EXIST::FUNCTION: SSL_set_initial_peer_addr ? 3_2_0 EXIST::FUNCTION: SSL_net_read_desired ? 3_2_0 EXIST::FUNCTION: SSL_net_write_desired ? 3_2_0 EXIST::FUNCTION: +SSL_shutdown_ex ? 3_2_0 EXIST::FUNCTION: -- 2.47.2