| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7652bd9 commit b68f8ea
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5133,6 +5133,11 @@ function processSessionOptions(options, config = kEmptyObject) { | |||
| 5133 | 5133 | // client SSL_CTX. For 'auto' and 'manual' modes, the handshake | |
| 5134 | 5134 | // completes regardless and the result is handled in JS. | |
| 5135 | 5135 | verifyPeerStrict: verifyPeer === 'strict', | |
| 5136 | + // Enable hostname verification for 'strict' and 'auto' modes. | ||
| 5137 | + // SSL_set1_host tells OpenSSL to verify the server certificate's | ||
| 5138 | + // SAN/CN matches the servername. Without this, a valid cert for | ||
| 5139 | + // any domain would be accepted. | ||
| 5140 | + verifyHostname: verifyPeer !== 'manual', | ||
| 5136 | 5141 | }, | |
| 5137 | 5142 | verifyPeer, | |
| 5138 | 5143 | qlog, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -169,6 +169,7 @@ class SessionManager; | |||
| 169 | 169 | V(unacknowledged_packet_threshold, "unacknowledgedPacketThreshold") \ | |
| 170 | 170 | V(validate_address, "validateAddress") \ | |
| 171 | 171 | V(verify_client, "verifyClient") \ | |
| 172 | + V(verify_hostname, "verifyHostname") \ | ||
| 172 | 173 | V(verify_peer_strict, "verifyPeerStrict") \ | |
| 173 | 174 | V(verify_private_key, "verifyPrivateKey") \ | |
| 174 | 175 | V(version, "version") | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -618,8 +618,7 @@ Maybe<Session::Options> Session::Options::From(Environment* env, | |||
| 618 | 618 | !SET(keep_alive_timeout) || !SET(max_stream_window) || !SET(max_window) || | |
| 619 | 619 | !SET(max_payload_size) || !SET(unacknowledged_packet_threshold) || | |
| 620 | 620 | !SET(cc_algorithm) || !SET(draining_period_multiplier) || | |
| 621 | - !SET(max_datagram_send_attempts) || | ||
| 622 | - !SET(stream_idle_timeout)) { | ||
| 621 | + !SET(max_datagram_send_attempts) || !SET(stream_idle_timeout)) { | ||
| 623 | 622 | return Nothing<Options>(); | |
| 624 | 623 | } | |
| 625 | 624 | ||
@@ -2839,8 +2838,8 @@ void Session::ShutdownStream(stream_id id, QuicError error) { | |||
| 2839 | 2838 | ||
| 2840 | 2839 | void Session::ShutdownStreamWrite(stream_id id, QuicError error) { | |
| 2841 | 2840 | DCHECK(!is_destroyed()); | |
| 2842 | - Debug(this, "Shutting down stream %" PRIi64 " write with error %s", | ||
| 2843 | - id, error); | ||
| 2841 | + Debug( | ||
| 2842 | + this, "Shutting down stream %" PRIi64 " write with error %s", id, error); | ||
| 2844 | 2843 | SendPendingDataScope send_scope(this); | |
| 2845 | 2844 | error_code code; | |
| 2846 | 2845 | if (error.type() == QuicError::Type::APPLICATION) { | |
@@ -3066,17 +3065,15 @@ void Session::CheckStreamIdleTimeout(uint64_t now) { | |||
| 3066 | 3065 | ||
| 3067 | 3066 | uint64_t last_activity = stream->last_activity_timestamp(); | |
| 3068 | 3067 | if (last_activity > 0 && (now - last_activity) > timeout_ns) { | |
| 3069 | - Debug(this, | ||
| 3070 | - "Stream %" PRId64 " idle timeout exceeded, destroying", | ||
| 3071 | - id); | ||
| 3068 | + Debug(this, "Stream %" PRId64 " idle timeout exceeded, destroying", id); | ||
| 3072 | 3069 | // Notify the peer before destroying. ShutdownStream sends both | |
| 3073 | 3070 | // STOP_SENDING and RESET_STREAM as appropriate, using the | |
| 3074 | 3071 | // application's no-error code for non-APPLICATION errors (since | |
| 3075 | 3072 | // these frames carry application-level error codes per RFC 9000). | |
| 3076 | 3073 | // Without this, the peer's stream sits orphaned until the | |
| 3077 | 3074 | // session closes. | |
| 3078 | - auto error = QuicError::ForTransport(NGTCP2_ERR_PROTO, | ||
| 3079 | - "stream idle timeout"); | ||
| 3075 | + auto error = | ||
| 3076 | + QuicError::ForTransport(NGTCP2_ERR_PROTO, "stream idle timeout"); | ||
| 3080 | 3077 | ShutdownStream(id, error); | |
| 3081 | 3078 | stream->Destroy(error); | |
| 3082 | 3079 | STAT_INCREMENT(Stats, streams_idle_timed_out); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1891,6 +1891,7 @@ void Stream::EmitClose(const QuicError& error) { | |||
| 1891 | 1891 | } | |
| 1892 | 1892 | ||
| 1893 | 1893 | void Stream::EmitHeaders() { | |
| 1894 | + STAT_RECORD_TIMESTAMP(Stats, received_at); | ||
| 1894 | 1895 | // state()->wants_headers will be set from the javascript side if the | |
| 1895 | 1896 | // stream object has a handler for the headers event. | |
| 1896 | 1897 | if (!env()->can_call_into_js() || !state()->wants_headers) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -261,6 +261,18 @@ bool OSSLContext::set_hostname(std::string_view hostname) const { | |||
| 261 | 261 | const_cast<char*>(name.c_str())) == 1; | |
| 262 | 262 | } | |
| 263 | 263 | ||
| 264 | + bool OSSLContext::set_verify_hostname(std::string_view hostname) const { | ||
| 265 | + // SSL_set1_host tells OpenSSL to verify the peer certificate's | ||
| 266 | + // subject name (SAN/CN) matches this hostname. This is separate | ||
| 267 | + // from SSL_set_tlsext_host_name which only sets the SNI extension. | ||
| 268 | + static const char* kDefaultHostname = "localhost"; | ||
| 269 | + if (hostname.empty()) { | ||
| 270 | + return SSL_set1_host(*this, kDefaultHostname) == 1; | ||
| 271 | + } else { | ||
| 272 | + return SSL_set1_host(*this, hostname.data()) == 1; | ||
| 273 | + } | ||
| 274 | + } | ||
| 275 | + | ||
| 264 | 276 | bool OSSLContext::set_early_data_enabled() const { | |
| 265 | 277 | return SSL_set_quic_tls_early_data_enabled(*this, 1) == 1; | |
| 266 | 278 | } | |
@@ -714,12 +726,13 @@ Maybe<TLSContext::Options> TLSContext::Options::From(Environment* env, | |||
| 714 | 726 | env, &options, params, state.name##_string()) | |
| 715 | 727 | ||
| 716 | 728 | if (!SET(verify_client) || !SET(reject_unauthorized) || | |
| 717 | - !SET(verify_peer_strict) || !SET(enable_early_data) || | ||
| 718 | - !SET(enable_tls_trace) || !SET(alpn) || !SET(servername) || | ||
| 719 | - !SET(ciphers) || !SET(groups) || !SET(verify_private_key) || | ||
| 720 | - !SET(keylog) || !SET(port) || !SET(authoritative) || | ||
| 721 | - !SET_VECTOR(crypto::KeyObjectData, keys) || !SET_VECTOR(Store, certs) || | ||
| 722 | - !SET_VECTOR(Store, ca) || !SET_VECTOR(Store, crl)) { | ||
| 729 | + !SET(verify_hostname) || !SET(verify_peer_strict) || | ||
| 730 | + !SET(enable_early_data) || !SET(enable_tls_trace) || !SET(alpn) || | ||
| 731 | + !SET(servername) || !SET(ciphers) || !SET(groups) || | ||
| 732 | + !SET(verify_private_key) || !SET(keylog) || !SET(port) || | ||
| 733 | + !SET(authoritative) || !SET_VECTOR(crypto::KeyObjectData, keys) || | ||
| 734 | + !SET_VECTOR(Store, certs) || !SET_VECTOR(Store, ca) || | ||
| 735 | + !SET_VECTOR(Store, crl)) { | ||
| 723 | 736 | return Nothing<Options>(); | |
| 724 | 737 | } | |
| 725 | 738 | ||
@@ -854,6 +867,14 @@ void TLSSession::Initialize( | |||
| 854 | 867 | return; | |
| 855 | 868 | } | |
| 856 | 869 | ||
| 870 | + if (options.verify_hostname) { | ||
| 871 | + if (!ossl_context_.set_verify_hostname(options.servername)) { | ||
| 872 | + validation_error_ = "Failed to set verify hostname"; | ||
| 873 | + ossl_context_.reset(); | ||
| 874 | + return; | ||
| 875 | + } | ||
| 876 | + } | ||
| 877 | + | ||
| 857 | 878 | if (maybeSessionTicket.has_value()) { | |
| 858 | 879 | const auto& sessionTicket = *maybeSessionTicket; | |
| 859 | 880 | uv_buf_t buf = sessionTicket.ticket(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -51,6 +51,7 @@ class OSSLContext final { | |||
| 51 | 51 | ||
| 52 | 52 | bool set_alpn_protocols(std::string_view protocols) const; | |
| 53 | 53 | bool set_hostname(std::string_view hostname) const; | |
| 54 | + bool set_verify_hostname(std::string_view hostname) const; | ||
| 54 | 55 | bool set_early_data_enabled() const; | |
| 55 | 56 | bool set_transport_params(const ngtcp2_vec& tp) const; | |
| 56 | 57 | ||
@@ -215,6 +216,13 @@ class TLSContext final : public MemoryRetainer, | |||
| 215 | 216 | // by the client side. | |
| 216 | 217 | bool verify_peer_strict = false; | |
| 217 | 218 | ||
| 219 | + // When true, OpenSSL verifies that the server's certificate matches | ||
| 220 | + // the servername (hostname verification via SSL_set1_host). Should | ||
| 221 | + // be true for 'strict' and 'auto' verifyPeer modes, false for | ||
| 222 | + // 'manual'. Without this, a valid certificate for any domain would | ||
| 223 | + // be accepted. This option is only used by the client side. | ||
| 224 | + bool verify_hostname = false; | ||
| 225 | + | ||
| 218 | 226 | // When true (the default), the server accepts 0-RTT early data | |
| 219 | 227 | // from clients with valid session tickets. When false, early data | |
| 220 | 228 | // is disabled and clients must complete a full handshake before | |
| Back | FazBrowse Home | New Git URL |
0 commit comments