QUIC: Refine SSL_shutdown and begin to implement SSL_shutdown_ex
authorHugo Landau <hlandau@openssl.org>
Tue, 13 Dec 2022 12:27:05 +0000 (12:27 +0000)
committerHugo Landau <hlandau@openssl.org>
Fri, 27 Jan 2023 14:19:14 +0000 (14:19 +0000)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19897)

include/internal/quic_channel.h
include/internal/quic_ssl.h
include/openssl/ssl.h.in
ssl/quic/quic_channel.c
ssl/quic/quic_impl.c
ssl/quic/quic_local.h
ssl/ssl_lib.c
util/libssl.num

index 4d96ab63dfd87b229a2209e07914deeeacb9dafb..83eb90a66258b94483ba0e1f68735d9ef8f5f5ae 100644 (file)
@@ -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.
index d319faef515ec8d9c96a6780e454bc72b62b70f6..8846877a4a2ff407bd78a58add68519e9e5360e4 100644 (file)
@@ -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);
index 0a4496844447b34a74099a59244b20c8a759b1a0..095698ea9db704e526b92fa9f33d11aed4364c63 100644 (file)
@@ -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
index 3701d93e1cf2d8afca253b189fad020aa3ac3003..bffd0d3244ed6120d9c8168c8866331b44f69d91 100644 (file)
@@ -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);
 }
 
index 6fb868a00450519307016b899e0e65074a0c66b3..e869e97ef54825f8d8bd829669f5555d56b472c2 100644 (file)
@@ -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);
index 83cce376fb8420afdb1ac448e0180ef30cc9be73..f4397447dd5cae5e0e4770d5f7fe26958d9c7037 100644 (file)
@@ -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 */, \
index 1e23ec55e55ea932c2f794b7ac92cff9c91107de..b927e283fee8357b3900b2da478e19727c9a59a3 100644 (file)
@@ -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
 }
index 38535b11b00cf581f7b73b57963c47a31d6d2413..16b4609c078b406195e3b636c2dd7d19e84239a5 100644 (file)
@@ -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: