@@ -104,6 +104,12 @@ SSL_SESSION* GetSessionCallback(
104104 return w->ReleaseSession ();
105105}
106106
107+ // The server name is handled in EarlyClientHelloCallback, so this only
108+ // acknowledges it, which also has the TLS library store it in new sessions.
109+ int AcknowledgeServerName (SSL * s, int * ad, void * arg) {
110+ return SSL_TLSEXT_ERR_OK ;
111+ }
112+
107113// Reads a 16-bit length prefixed vector from the front of data. Returns
108114// nothing if the length does not fit within data.
109115std::optional<std::span<const uint8_t >> ReadVector16 (
@@ -158,10 +164,7 @@ ssl_select_cert_result_t EarlyClientHelloCallback(const SSL_CLIENT_HELLO* ch) {
158164 // If we can't parse the hello SNI, reject it explicitly:
159165 if (!servername.has_value ()) return ssl_select_cert_error;
160166
161- // Session resumption must only be allowed for sessions with exactly the same
162- // SNI. We use the SNI to derive the session id, so no handshake can resume
163- // from a mismatched SNI value. Mismatches fall back to full handshakes:
164- if (!w->BindSessionsToServerName (*servername)) return ssl_select_cert_error;
167+ if (!w->PinServerName (*servername)) return ssl_select_cert_error;
165168
166169 if (!w->should_suspend_for_client_hello ()) return ssl_select_cert_success;
167170
@@ -191,10 +194,10 @@ int EarlyClientHelloCallback(SSL* s, int* al, void* arg) {
191194 return SSL_CLIENT_HELLO_ERROR ;
192195 }
193196
194- // Session resumption must only be allowed for sessions with exactly the same
195- // SNI. We use the SNI to derive the session id, so no handshake can resume
196- // from a mismatched SNI value. Mismatches fall back to full handshakes:
197- if (!w-> BindSessionsToServerName (*servername)) return SSL_CLIENT_HELLO_ERROR ;
197+ if (!w-> PinServerName (*servername)) {
198+ *al = SSL_AD_ILLEGAL_PARAMETER ;
199+ return SSL_CLIENT_HELLO_ERROR ;
200+ }
198201
199202 if (!w->should_suspend_for_client_hello ()) return SSL_CLIENT_HELLO_SUCCESS ;
200203
@@ -655,8 +658,7 @@ void TLSWrap::InitSSL() {
655658 // https://github.com/openssl/openssl/issues/7199#issuecomment-420670544
656659 SSL_set_info_callback (ssl_.get (), SSLInfoCallback);
657660
658- if (is_server ())
659- sc_->SetSelectSNIContextCallback (SelectSNIContextCallback);
661+ if (is_server ()) sc_->SetSelectSNIContextCallback (AcknowledgeServerName);
660662
661663 ConfigureSecureContext (sc_.get ());
662664
@@ -1592,39 +1594,34 @@ void TLSWrap::SetServername(const FunctionCallbackInfo<Value>& args) {
15921594 SSL_set_tlsext_host_name (wrap->ssl_ .get (), *servername);
15931595}
15941596
1595- int TLSWrap::SelectSNIContextCallback (SSL * s, int * ad, void * arg) {
1596- TLSWrap* p = static_cast <TLSWrap*>(SSL_get_app_data (s));
1597- Environment* env = p->env ();
1598- HandleScope handle_scope (env->isolate ());
1599- Context::Scope context_scope (env->context ());
1600-
1601- auto servername = SSLPointer::GetServerName (s);
1602- if (!servername.has_value () ||
1603- !Set (env, p->GetOwner (), env->servername_string (), servername.value ()))
1604- return SSL_TLSEXT_ERR_NOACK ;
1605-
1606- Local<Value> ctx = p->object ()->Get (env->context (), env->sni_context_string ())
1607- .FromMaybe (Local<Value>());
1608-
1609- // Acknowlege the name so it's correctly stored on the session:
1610- if (ctx.IsEmpty () || !ctx->IsObject ()) return SSL_TLSEXT_ERR_OK ;
1611-
1612- if (!env->secure_context_constructor_template ()->HasInstance (ctx)) {
1613- // Failure: incorrect SNI context object
1614- Local<Value> err = Exception::TypeError (env->sni_context_err_string ());
1615- p->MakeCallback (env->onerror_string (), 1 , &err);
1616- return SSL_TLSEXT_ERR_NOACK ;
1597+ // The connection's server name is fixed by its first ClientHello: later ones (a
1598+ // renegotiation, or the second of a HelloRetryRequest) must ask for exactly the
1599+ // same, as the connection's secure context was chosen for it.
1600+ bool TLSWrap::PinServerName (std::string_view servername) {
1601+ if (flags_.servername_pinned ) {
1602+ if (servername == servername_) return true ;
1603+ Debug (this ,
1604+ " ClientHello asked for server name '%s', connection pinned to '%s'" ,
1605+ servername,
1606+ servername_);
1607+ return false ;
16171608 }
1609+ flags_.servername_pinned = true ;
1610+ servername_ = servername;
16181611
1619- SecureContext* sc = Unwrap<SecureContext>(ctx. As <Object> ());
1620- CHECK_NOT_NULL (sc );
1621- p-> sni_context_ = BaseObjectPtr<SecureContext>(sc );
1622-
1623- ConfigureSecureContext (sc) ;
1624- CHECK_EQ ( SSL_set_SSL_CTX (p-> ssl_ . get (), sc-> ctx (). get ()), sc-> ctx (). get ());
1625- p-> SetCACerts (sc);
1612+ if (!servername. empty ()) {
1613+ HandleScope handle_scope ( env ()-> isolate () );
1614+ Context::Scope context_scope ( env ()-> context () );
1615+ if (! Set ( env (), GetOwner (), env ()-> servername_string (), servername_)) {
1616+ return false ;
1617+ }
1618+ }
16261619
1627- return SSL_TLSEXT_ERR_OK ;
1620+ // Session resumption must only be allowed for sessions with exactly the same
1621+ // SNI. We use the SNI to derive the session id context, so no handshake can
1622+ // resume from a mismatched SNI value. Mismatches fall back to full
1623+ // handshakes:
1624+ return BindSessionsToServerName (servername);
16281625}
16291626
16301627bool TLSWrap::BindSessionsToServerName (std::string_view servername) {
@@ -1803,6 +1800,7 @@ void TLSWrap::MemoryInfo(MemoryTracker* tracker) const {
18031800 tracker->TrackField (" ocsp_response" , ocsp_response_);
18041801 tracker->TrackField (" sni_context" , sni_context_);
18051802 tracker->TrackField (" error" , error_);
1803+ tracker->TrackField (" servername" , servername_);
18061804 if (pending_cleartext_input_)
18071805 tracker->TrackField (" pending_cleartext_input" , pending_cleartext_input_);
18081806 if (enc_in_ != nullptr )
0 commit comments