diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b6b381aa..898ceb19 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -119,7 +119,7 @@ jobs: - name: Build nghttp3 if: matrix.http3 == 'http3' run: | - git clone --depth 1 -b v0.4.1 https://github.com/ngtcp2/nghttp3 + git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/nghttp3 cd nghttp3 autoreconf -i ./configure --prefix=$PWD/build --enable-lib-only @@ -128,7 +128,7 @@ jobs: - name: Build ngtcp2 if: matrix.http3 == 'http3' run: | - git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/ngtcp2 + git clone --depth 1 -b v0.6.0 https://github.com/ngtcp2/ngtcp2 cd ngtcp2 autoreconf -i ./configure --prefix=$PWD/build --enable-lib-only PKG_CONFIG_PATH="../openssl/build/lib/pkgconfig" diff --git a/README.rst b/README.rst index ece02ebb..205d1da1 100644 --- a/README.rst +++ b/README.rst @@ -154,7 +154,7 @@ following libraries are required: `_; or `BoringSSL `_ (commit 36a41bf0bf2dd3176f8780e09c03585351f29963) -* `ngtcp2 `_ >= 0.5.0 +* `ngtcp2 `_ >= 0.6.0 * `nghttp3 `_ >= 0.4.0 Use ``--enable-http3`` configure option to enable HTTP/3 feature for @@ -366,7 +366,7 @@ Build nghttp3: .. code-block:: text - $ git clone --depth 1 -b v0.4.1 https://github.com/ngtcp2/nghttp3 + $ git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/nghttp3 $ cd nghttp3 $ autoreconf -i $ ./configure --prefix=$PWD/build --enable-lib-only @@ -378,7 +378,7 @@ Build ngtcp2: .. code-block:: text - $ git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/ngtcp2 + $ git clone --depth 1 -b v0.6.0 https://github.com/ngtcp2/ngtcp2 $ cd ngtcp2 $ autoreconf -i $ ./configure --prefix=$PWD/build --enable-lib-only \ diff --git a/configure.ac b/configure.ac index f6c935d8..ec3ad444 100644 --- a/configure.ac +++ b/configure.ac @@ -540,7 +540,7 @@ fi # ngtcp2 (for src) have_libngtcp2=no if test "x${request_libngtcp2}" != "xno"; then - PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 0.5.0], [have_libngtcp2=yes], + PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 0.6.0], [have_libngtcp2=yes], [have_libngtcp2=no]) if test "x${have_libngtcp2}" = "xno"; then AC_MSG_NOTICE($LIBNGTCP2_PKG_ERRORS) @@ -557,7 +557,7 @@ have_libngtcp2_crypto_openssl=no if test "x${have_ssl_is_quic}" = "xyes" && test "x${request_libngtcp2}" != "xno"; then PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_OPENSSL], - [libngtcp2_crypto_openssl >= 0.5.0], + [libngtcp2_crypto_openssl >= 0.6.0], [have_libngtcp2_crypto_openssl=yes], [have_libngtcp2_crypto_openssl=no]) if test "x${have_libngtcp2_crypto_openssl}" = "xno"; then diff --git a/docker/Dockerfile b/docker/Dockerfile index ab676cc9..bdd39054 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -15,7 +15,7 @@ RUN git clone --depth 1 -b OpenSSL_1_1_1o+quic https://github.com/quictls/openss cd .. && \ rm -rf openssl -RUN git clone --depth 1 -b v0.4.1 https://github.com/ngtcp2/nghttp3 && \ +RUN git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/nghttp3 && \ cd nghttp3 && \ autoreconf -i && \ ./configure --enable-lib-only && \ @@ -24,7 +24,7 @@ RUN git clone --depth 1 -b v0.4.1 https://github.com/ngtcp2/nghttp3 && \ cd .. && \ rm -rf nghttp3 -RUN git clone --depth 1 -b v0.5.0 https://github.com/ngtcp2/ngtcp2 && \ +RUN git clone --depth 1 -b v0.6.0 https://github.com/ngtcp2/ngtcp2 && \ cd ngtcp2 && \ autoreconf -i && \ ./configure --enable-lib-only \ diff --git a/src/h2load.cc b/src/h2load.cc index bf3ba523..7d03286f 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -51,8 +51,13 @@ #include #ifdef ENABLE_HTTP3 -# include -#endif // ENABLE_HTTP3 +# ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL +# include +# endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL +# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL +# include +# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL +#endif // ENABLE_HTTP3 #include "url-parser/url_parser.h" @@ -724,12 +729,17 @@ void Client::disconnect() { ev_io_stop(worker->loop, &wev); ev_io_stop(worker->loop, &rev); if (ssl) { - SSL_set_shutdown(ssl, SSL_get_shutdown(ssl) | SSL_RECEIVED_SHUTDOWN); - ERR_clear_error(); - - if (SSL_shutdown(ssl) != 1) { + if (config.is_quic()) { SSL_free(ssl); ssl = nullptr; + } else { + SSL_set_shutdown(ssl, SSL_get_shutdown(ssl) | SSL_RECEIVED_SHUTDOWN); + ERR_clear_error(); + + if (SSL_shutdown(ssl) != 1) { + SSL_free(ssl); + ssl = nullptr; + } } } if (fd != -1) { @@ -2878,9 +2888,21 @@ int main(int argc, char **argv) { if (config.is_quic()) { #ifdef ENABLE_HTTP3 - SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION); - SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION); -#endif // ENABLE_HTTP3 +# ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL + if (ngtcp2_crypto_openssl_configure_client_context(ssl_ctx) != 0) { + std::cerr << "ngtcp2_crypto_openssl_configure_client_context failed" + << std::endl; + exit(EXIT_FAILURE); + } +# endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL +# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL + if (ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) { + std::cerr << "ngtcp2_crypto_boringssl_configure_client_context failed" + << std::endl; + exit(EXIT_FAILURE); + } +# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL +#endif // ENABLE_HTTP3 } else if (nghttp2::tls::ssl_ctx_set_proto_versions( ssl_ctx, nghttp2::tls::NGHTTP2_TLS_MIN_VERSION, nghttp2::tls::NGHTTP2_TLS_MAX_VERSION) != 0) { diff --git a/src/h2load.h b/src/h2load.h index 087ee8cd..18d6cb8f 100644 --- a/src/h2load.h +++ b/src/h2load.h @@ -339,10 +339,10 @@ struct Client { SSL *ssl; #ifdef ENABLE_HTTP3 struct { + ngtcp2_crypto_conn_ref conn_ref; ev_timer pkt_timer; ngtcp2_conn *conn; ngtcp2_connection_close_error last_error; - uint8_t tls_alert; bool close_requested; FILE *qlog_file; @@ -495,17 +495,12 @@ struct Client { int quic_stream_stop_sending(int64_t stream_id, uint64_t app_error_code); int quic_extend_max_local_streams(); - int quic_on_rx_secret(ngtcp2_crypto_level level, const uint8_t *secret, - size_t secretlen); - int quic_on_tx_secret(ngtcp2_crypto_level level, const uint8_t *secret, - size_t secretlen); - void quic_set_tls_alert(uint8_t alert); - int quic_write_client_handshake(ngtcp2_crypto_level level, const uint8_t *data, size_t datalen); int quic_pkt_timeout(); void quic_restart_pkt_timer(); void quic_write_qlog(const void *data, size_t datalen); + int quic_make_http3_session(); #endif // ENABLE_HTTP3 }; diff --git a/src/h2load_quic.cc b/src/h2load_quic.cc index 0e9a210c..0c4a8dfd 100644 --- a/src/h2load_quic.cc +++ b/src/h2load_quic.cc @@ -243,127 +243,6 @@ ngtcp2_tstamp timestamp(struct ev_loop *loop) { } } // namespace -#ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL -namespace { -int set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, - const uint8_t *rx_secret, const uint8_t *tx_secret, - size_t secret_len) { - auto c = static_cast(SSL_get_app_data(ssl)); - auto level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level); - - if (c->quic_on_rx_secret(level, rx_secret, secret_len) != 0) { - return 0; - } - - if (c->quic_on_tx_secret(level, tx_secret, secret_len) != 0) { - return 0; - } - - return 1; -} -} // namespace - -namespace { -int add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, - const uint8_t *data, size_t len) { - auto c = static_cast(SSL_get_app_data(ssl)); - if (c->quic_write_client_handshake( - ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level), data, - len) != 0) { - return 0; - } - return 1; -} -} // namespace - -namespace { -int flush_flight(SSL *ssl) { return 1; } -} // namespace - -namespace { -int send_alert(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert) { - auto c = static_cast(SSL_get_app_data(ssl)); - c->quic_set_tls_alert(alert); - return 1; -} -} // namespace - -namespace { -auto quic_method = SSL_QUIC_METHOD{ - set_encryption_secrets, - add_handshake_data, - flush_flight, - send_alert, -}; -} // namespace -#endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL - -#ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL -namespace { -int set_read_secret(SSL *ssl, ssl_encryption_level_t ssl_level, - const SSL_CIPHER *cipher, const uint8_t *secret, - size_t secretlen) { - auto c = static_cast(SSL_get_app_data(ssl)); - - if (c->quic_on_rx_secret( - ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level), secret, - secretlen) != 0) { - return 0; - } - - return 1; -} -} // namespace - -namespace { -int set_write_secret(SSL *ssl, ssl_encryption_level_t ssl_level, - const SSL_CIPHER *cipher, const uint8_t *secret, - size_t secretlen) { - auto c = static_cast(SSL_get_app_data(ssl)); - - if (c->quic_on_tx_secret( - ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level), secret, - secretlen) != 0) { - return 0; - } - - return 1; -} -} // namespace - -namespace { -int add_handshake_data(SSL *ssl, ssl_encryption_level_t ssl_level, - const uint8_t *data, size_t len) { - auto c = static_cast(SSL_get_app_data(ssl)); - if (c->quic_write_client_handshake( - ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level), data, - len) != 0) { - return 0; - } - return 1; -} -} // namespace - -namespace { -int flush_flight(SSL *ssl) { return 1; } -} // namespace - -namespace { -int send_alert(SSL *ssl, ssl_encryption_level_t level, uint8_t alert) { - auto c = static_cast(SSL_get_app_data(ssl)); - c->quic_set_tls_alert(alert); - return 1; -} -} // namespace - -namespace { -auto quic_method = SSL_QUIC_METHOD{ - set_read_secret, set_write_secret, add_handshake_data, - flush_flight, send_alert, -}; -} // namespace -#endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL - // qlog write callback -- excerpted from ngtcp2/examples/client_base.cc namespace { void qlog_write_cb(void *user_data, uint32_t flags, const void *data, @@ -385,6 +264,39 @@ void rand(uint8_t *dest, size_t destlen, const ngtcp2_rand_ctx *rand_ctx) { } } // namespace +namespace { +int recv_rx_key(ngtcp2_conn *conn, ngtcp2_crypto_level level, void *user_data) { + if (level != NGTCP2_CRYPTO_LEVEL_APPLICATION) { + return 0; + } + + auto c = static_cast(user_data); + + if (c->quic_make_http3_session() != 0) { + return NGTCP2_ERR_CALLBACK_FAILURE; + } + + return 0; +} +} // namespace + +int Client::quic_make_http3_session() { + auto s = std::make_unique(this); + if (s->init_conn() == -1) { + return -1; + } + session = std::move(s); + + return 0; +} + +namespace { +ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref) { + auto c = static_cast(conn_ref->user_data); + return c->quic.conn; +} +} // namespace + int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen, const sockaddr *remote_addr, socklen_t remote_addrlen) { int rv; @@ -392,9 +304,11 @@ int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen, if (!ssl) { ssl = SSL_new(worker->ssl_ctx); - SSL_set_app_data(ssl, this); + quic.conn_ref.get_conn = get_conn; + quic.conn_ref.user_data = this; + + SSL_set_app_data(ssl, &quic.conn_ref); SSL_set_connect_state(ssl); - SSL_set_quic_method(ssl, &quic_method); SSL_set_quic_use_legacy_codepoint(ssl, 0); } @@ -435,6 +349,9 @@ int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen, nullptr, // lost_datagram ngtcp2_crypto_get_path_challenge_data_cb, h2load::stream_stop_sending, + nullptr, // version_negotiation + h2load::recv_rx_key, + nullptr, // recv_tx_key }; ngtcp2_cid scid, dcid; @@ -546,42 +463,6 @@ void Client::quic_close_connection() { ps.path.remote.addrlen, buf.data(), nwrite, 0); } -int Client::quic_on_rx_secret(ngtcp2_crypto_level level, const uint8_t *secret, - size_t secretlen) { - if (ngtcp2_crypto_derive_and_install_rx_key(quic.conn, nullptr, nullptr, - nullptr, level, secret, - secretlen) != 0) { - std::cerr << "ngtcp2_crypto_derive_and_install_rx_key() failed" - << std::endl; - return -1; - } - - if (level == NGTCP2_CRYPTO_LEVEL_APPLICATION) { - auto s = std::make_unique(this); - if (s->init_conn() == -1) { - return -1; - } - session = std::move(s); - } - - return 0; -} - -int Client::quic_on_tx_secret(ngtcp2_crypto_level level, const uint8_t *secret, - size_t secretlen) { - if (ngtcp2_crypto_derive_and_install_tx_key(quic.conn, nullptr, nullptr, - nullptr, level, secret, - secretlen) != 0) { - std::cerr << "ngtcp2_crypto_derive_and_install_tx_key() failed" - << std::endl; - return -1; - } - - return 0; -} - -void Client::quic_set_tls_alert(uint8_t alert) { quic.tls_alert = alert; } - int Client::quic_write_client_handshake(ngtcp2_crypto_level level, const uint8_t *data, size_t datalen) { int rv; @@ -670,7 +551,8 @@ int Client::read_quic() { if (!quic.last_error.error_code) { if (rv == NGTCP2_ERR_CRYPTO) { ngtcp2_connection_close_error_set_transport_error_tls_alert( - &quic.last_error, quic.tls_alert, nullptr, 0); + &quic.last_error, ngtcp2_conn_get_tls_alert(quic.conn), nullptr, + 0); } else { ngtcp2_connection_close_error_set_transport_error_liberr( &quic.last_error, rv, nullptr, 0); diff --git a/src/shrpx_connection.cc b/src/shrpx_connection.cc index a0fcab76..2bb23459 100644 --- a/src/shrpx_connection.cc +++ b/src/shrpx_connection.cc @@ -60,7 +60,11 @@ Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl, IOCb readcb, TimerCb timeoutcb, void *data, size_t tls_dyn_rec_warmup_threshold, ev_tstamp tls_dyn_rec_idle_timeout, Proto proto) - : tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool), + : +#ifdef ENABLE_HTTP3 + conn_ref{nullptr, this}, +#endif // ENABLE_HTTP3 + tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool), DefaultMemchunks(mcpool)}, wlimit(loop, &wev, write_limit.rate, write_limit.burst), rlimit(loop, &rev, read_limit.rate, read_limit.burst, this), @@ -97,21 +101,24 @@ Connection::~Connection() { disconnect(); } void Connection::disconnect() { if (tls.ssl) { - SSL_set_shutdown(tls.ssl, - SSL_get_shutdown(tls.ssl) | SSL_RECEIVED_SHUTDOWN); - ERR_clear_error(); + if (proto != Proto::HTTP3) { + SSL_set_shutdown(tls.ssl, + SSL_get_shutdown(tls.ssl) | SSL_RECEIVED_SHUTDOWN); + ERR_clear_error(); - if (tls.cached_session) { - SSL_SESSION_free(tls.cached_session); - tls.cached_session = nullptr; + if (tls.cached_session) { + SSL_SESSION_free(tls.cached_session); + tls.cached_session = nullptr; + } + + if (tls.cached_session_lookup_req) { + tls.cached_session_lookup_req->canceled = true; + tls.cached_session_lookup_req = nullptr; + } + + SSL_shutdown(tls.ssl); } - if (tls.cached_session_lookup_req) { - tls.cached_session_lookup_req->canceled = true; - tls.cached_session_lookup_req = nullptr; - } - - SSL_shutdown(tls.ssl); SSL_free(tls.ssl); tls.ssl = nullptr; diff --git a/src/shrpx_connection.h b/src/shrpx_connection.h index 9aed671f..52245689 100644 --- a/src/shrpx_connection.h +++ b/src/shrpx_connection.h @@ -33,6 +33,10 @@ #include +#ifdef ENABLE_HTTP3 +# include +#endif // ENABLE_HTTP3 + #include "shrpx_rate_limit.h" #include "shrpx_error.h" #include "memchunk.h" @@ -155,6 +159,10 @@ struct Connection { // Returns true if read timer expired. bool expired_rt(); +#ifdef ENABLE_HTTP3 + // This must be the first member of Connection. + ngtcp2_crypto_conn_ref conn_ref; +#endif // ENABLE_HTTP3 TLSConnection tls; ev_io wev; ev_io rev; @@ -178,6 +186,11 @@ struct Connection { ev_tstamp read_timeout; }; +#ifdef ENABLE_HTTP3 +static_assert(std::is_standard_layout::value, + "Conneciton is not standard layout"); +#endif // ENABLE_HTTP3 + // Creates BIO_method shared by all SSL objects. BIO_METHOD *create_bio_method(); diff --git a/src/shrpx_http3_upstream.cc b/src/shrpx_http3_upstream.cc index 0232728b..359898de 100644 --- a/src/shrpx_http3_upstream.cc +++ b/src/shrpx_http3_upstream.cc @@ -100,12 +100,20 @@ size_t downstream_queue_size(Worker *worker) { } } // namespace +namespace { +ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref) { + auto conn = static_cast(conn_ref->user_data); + auto handler = static_cast(conn->data); + auto upstream = static_cast(handler->get_upstream()); + return upstream->get_conn(); +} +} // namespace + Http3Upstream::Http3Upstream(ClientHandler *handler) : handler_{handler}, qlog_fd_{-1}, hashed_scid_{}, conn_{nullptr}, - tls_alert_{0}, httpconn_{nullptr}, downstream_queue_{downstream_queue_size(handler->get_worker()), !get_config()->http2_proxy}, @@ -113,6 +121,9 @@ Http3Upstream::Http3Upstream(ClientHandler *handler) tx_{ .data = std::unique_ptr(new uint8_t[64_k]), } { + auto conn = handler_->get_connection(); + conn->conn_ref.get_conn = shrpx::get_conn; + ev_timer_init(&timer_, timeoutcb, 0., 0.); timer_.data = this; @@ -493,6 +504,21 @@ int Http3Upstream::handshake_completed() { return 0; } +namespace { +int recv_tx_key(ngtcp2_conn *conn, ngtcp2_crypto_level level, void *user_data) { + if (level != NGTCP2_CRYPTO_LEVEL_APPLICATION) { + return 0; + } + + auto upstream = static_cast(user_data); + if (upstream->setup_httpconn() != 0) { + return NGTCP2_ERR_CALLBACK_FAILURE; + } + + return 0; +} +} // namespace + int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_hd &initial_hd, @@ -540,6 +566,9 @@ int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr, nullptr, // lost_datagram ngtcp2_crypto_get_path_challenge_data_cb, shrpx::stream_stop_sending, + nullptr, // version_negotiation + nullptr, // recv_rx_key + shrpx::recv_tx_key, }; auto config = get_config(); @@ -1795,7 +1824,7 @@ int Http3Upstream::on_read(const UpstreamAddr *faddr, case NGTCP2_ERR_CRYPTO: if (!last_error_.error_code) { ngtcp2_connection_close_error_set_transport_error_tls_alert( - &last_error_, tls_alert_, nullptr, 0); + &last_error_, ngtcp2_conn_get_tls_alert(conn_), nullptr, 0); } break; case NGTCP2_ERR_DROP_CONN: @@ -1944,47 +1973,6 @@ int Http3Upstream::handle_error() { return -1; } -int Http3Upstream::on_rx_secret(ngtcp2_crypto_level level, - const uint8_t *secret, size_t secretlen) { - if (ngtcp2_crypto_derive_and_install_rx_key(conn_, nullptr, nullptr, nullptr, - level, secret, secretlen) != 0) { - ULOG(ERROR, this) << "ngtcp2_crypto_derive_and_install_rx_key failed"; - return -1; - } - - return 0; -} - -int Http3Upstream::on_tx_secret(ngtcp2_crypto_level level, - const uint8_t *secret, size_t secretlen) { - if (ngtcp2_crypto_derive_and_install_tx_key(conn_, nullptr, nullptr, nullptr, - level, secret, secretlen) != 0) { - ULOG(ERROR, this) << "ngtcp2_crypto_derive_and_install_tx_key failed"; - return -1; - } - - if (level == NGTCP2_CRYPTO_LEVEL_APPLICATION && setup_httpconn() != 0) { - return -1; - } - - return 0; -} - -int Http3Upstream::add_crypto_data(ngtcp2_crypto_level level, - const uint8_t *data, size_t datalen) { - int rv = ngtcp2_conn_submit_crypto_data(conn_, level, data, datalen); - - if (rv != 0) { - ULOG(ERROR, this) << "ngtcp2_conn_submit_crypto_data: " - << ngtcp2_strerror(rv); - return -1; - } - - return 0; -} - -void Http3Upstream::set_tls_alert(uint8_t alert) { tls_alert_ = alert; } - int Http3Upstream::handle_expiry() { int rv; @@ -2646,11 +2634,10 @@ int Http3Upstream::setup_httpconn() { return -1; } - ngtcp2_transport_params params; - ngtcp2_conn_get_local_transport_params(conn_, ¶ms); + auto params = ngtcp2_conn_get_local_transport_params(conn_); nghttp3_conn_set_max_client_streams_bidi(httpconn_, - params.initial_max_streams_bidi); + params->initial_max_streams_bidi); int64_t ctrl_stream_id; @@ -2933,4 +2920,6 @@ int Http3Upstream::open_qlog_file(const StringRef &dir, return fd; } +ngtcp2_conn *Http3Upstream::get_conn() const { return conn_; } + } // namespace shrpx diff --git a/src/shrpx_http3_upstream.h b/src/shrpx_http3_upstream.h index 4b190d6e..23874850 100644 --- a/src/shrpx_http3_upstream.h +++ b/src/shrpx_http3_upstream.h @@ -97,16 +97,6 @@ public: int write_streams(); - int on_rx_secret(ngtcp2_crypto_level level, const uint8_t *secret, - size_t secretlen); - int on_tx_secret(ngtcp2_crypto_level level, const uint8_t *secret, - size_t secretlen); - - int add_crypto_data(ngtcp2_crypto_level level, const uint8_t *data, - size_t datalen); - - void set_tls_alert(uint8_t alert); - int handle_error(); int handle_expiry(); @@ -162,6 +152,8 @@ public: int send_blocked_packet(); void signal_write_upstream_addr(const UpstreamAddr *faddr); + ngtcp2_conn *get_conn() const; + private: ClientHandler *handler_; ev_timer timer_; @@ -171,7 +163,6 @@ private: ngtcp2_cid hashed_scid_; ngtcp2_conn *conn_; ngtcp2_connection_close_error last_error_; - uint8_t tls_alert_; nghttp3_conn *httpconn_; DownstreamQueue downstream_queue_; bool retry_close_; diff --git a/src/shrpx_tls.cc b/src/shrpx_tls.cc index 7a53f8d9..653dd58e 100644 --- a/src/shrpx_tls.cc +++ b/src/shrpx_tls.cc @@ -1219,149 +1219,6 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file, } #ifdef ENABLE_HTTP3 -# ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL -namespace { -int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, - const uint8_t *rx_secret, - const uint8_t *tx_secret, size_t secretlen) { - auto conn = static_cast(SSL_get_app_data(ssl)); - auto handler = static_cast(conn->data); - auto upstream = static_cast(handler->get_upstream()); - auto level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level); - - if (upstream->on_rx_secret(level, rx_secret, secretlen) != 0) { - return 0; - } - - if (tx_secret && upstream->on_tx_secret(level, tx_secret, secretlen) != 0) { - return 0; - } - - return 1; -} -} // namespace - -namespace { -int quic_add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, - const uint8_t *data, size_t len) { - auto conn = static_cast(SSL_get_app_data(ssl)); - auto handler = static_cast(conn->data); - auto upstream = static_cast(handler->get_upstream()); - auto level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level); - - upstream->add_crypto_data(level, data, len); - - return 1; -} -} // namespace - -namespace { -int quic_flush_flight(SSL *ssl) { return 1; } -} // namespace - -namespace { -int quic_send_alert(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, uint8_t alert) { - auto conn = static_cast(SSL_get_app_data(ssl)); - auto handler = static_cast(conn->data); - auto upstream = static_cast(handler->get_upstream()); - - if (!upstream) { - return 1; - } - - upstream->set_tls_alert(alert); - - return 1; -} -} // namespace - -namespace { -auto quic_method = SSL_QUIC_METHOD{ - quic_set_encryption_secrets, - quic_add_handshake_data, - quic_flush_flight, - quic_send_alert, -}; -} // namespace -# endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL - -# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL -namespace { -int quic_set_read_secret(SSL *ssl, ssl_encryption_level_t ssl_level, - const SSL_CIPHER *cipher, const uint8_t *secret, - size_t secretlen) { - auto conn = static_cast(SSL_get_app_data(ssl)); - auto handler = static_cast(conn->data); - auto upstream = static_cast(handler->get_upstream()); - auto level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level); - - if (upstream->on_rx_secret(level, secret, secretlen) != 0) { - return 0; - } - - return 1; -} -} // namespace - -namespace { -int quic_set_write_secret(SSL *ssl, ssl_encryption_level_t ssl_level, - const SSL_CIPHER *cipher, const uint8_t *secret, - size_t secretlen) { - auto conn = static_cast(SSL_get_app_data(ssl)); - auto handler = static_cast(conn->data); - auto upstream = static_cast(handler->get_upstream()); - auto level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level); - - if (upstream->on_tx_secret(level, secret, secretlen) != 0) { - return 0; - } - - return 1; -} -} // namespace - -namespace { -int quic_add_handshake_data(SSL *ssl, ssl_encryption_level_t ssl_level, - const uint8_t *data, size_t len) { - auto conn = static_cast(SSL_get_app_data(ssl)); - auto handler = static_cast(conn->data); - auto upstream = static_cast(handler->get_upstream()); - auto level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level); - - upstream->add_crypto_data(level, data, len); - - return 1; -} -} // namespace - -namespace { -int quic_flush_flight(SSL *ssl) { return 1; } -} // namespace - -namespace { -int quic_send_alert(SSL *ssl, ssl_encryption_level_t level, uint8_t alert) { - auto conn = static_cast(SSL_get_app_data(ssl)); - auto handler = static_cast(conn->data); - auto upstream = static_cast(handler->get_upstream()); - - if (!upstream) { - return 1; - } - - upstream->set_tls_alert(alert); - - return 1; -} -} // namespace - -namespace { -auto quic_method = SSL_QUIC_METHOD{ - quic_set_read_secret, quic_set_write_secret, quic_add_handshake_data, - quic_flush_flight, quic_send_alert, -}; -} // namespace -# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL - SSL_CTX *create_quic_ssl_context(const char *private_key_file, const char *cert_file, const std::vector &sct_data @@ -1396,8 +1253,18 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file, SSL_CTX_set_options(ssl_ctx, ssl_opts); - SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION); - SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION); +# ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL + if (ngtcp2_crypto_openssl_configure_server_context(ssl_ctx) != 0) { + LOG(FATAL) << "ngtcp2_crypto_openssl_configure_server_context failed"; + DIE(); + } +# endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL +# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL + if (ngtcp2_crypto_boringssl_configure_server_context(ssl_ctx) != 0) { + LOG(FATAL) << "ngtcp2_crypto_boringssl_configure_server_context failed"; + DIE(); + } +# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL const unsigned char sid_ctx[] = "shrpx"; SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1); @@ -1638,8 +1505,6 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file, SSL_CTX_set_psk_server_callback(ssl_ctx, psk_server_cb); # endif // !LIBRESSL_NO_PSK - SSL_CTX_set_quic_method(ssl_ctx, &quic_method); - return ssl_ctx; } #endif // ENABLE_HTTP3