@@ -281,7 +281,7 @@ public void Load()
281
281
282
282
// Compare to UseHttps(httpsOptions => { })
283
283
var httpsOptions = new HttpsConnectionAdapterOptions ( ) ;
284
- ServerOptionsSelectionCallback serverOptionsCallback = null ;
284
+ SniOptionsSelector sniOptionsSelector = null ;
285
285
286
286
if ( https )
287
287
{
@@ -318,8 +318,7 @@ public void Load()
318
318
}
319
319
else
320
320
{
321
- serverOptionsCallback = ( stream , clientHelloInfo , state , cancellationToken ) =>
322
- SniCallback ( httpsOptions , listenOptions . Protocols , endpoint , clientHelloInfo ) ;
321
+ sniOptionsSelector = new SniOptionsSelector ( this , endpoint , httpsOptions , listenOptions . Protocols ) ;
323
322
}
324
323
}
325
324
@@ -343,7 +342,7 @@ public void Load()
343
342
// EndpointDefaults or configureEndpoint may have added an https adapter.
344
343
if ( https && ! listenOptions . IsTls )
345
344
{
346
- if ( serverOptionsCallback is null )
345
+ if ( sniOptionsSelector is null )
347
346
{
348
347
if ( httpsOptions . ServerCertificate == null && httpsOptions . ServerCertificateSelector == null )
349
348
{
@@ -354,7 +353,7 @@ public void Load()
354
353
}
355
354
else
356
355
{
357
- listenOptions . UseHttps ( serverOptionsCallback ) ;
356
+ listenOptions . UseHttps ( ServerOptionsSelectionCallback , sniOptionsSelector ) ;
358
357
}
359
358
}
360
359
@@ -367,80 +366,11 @@ public void Load()
367
366
return ( endpointsToStop , endpointsToStart ) ;
368
367
}
369
368
370
- private ValueTask < SslServerAuthenticationOptions > SniCallback (
371
- HttpsConnectionAdapterOptions httpsOptions ,
372
- HttpProtocols endpointDefaultHttpProtocols ,
373
- EndpointConfig endpoint ,
374
- SslClientHelloInfo clientHelloInfo )
369
+ private static ValueTask < SslServerAuthenticationOptions > ServerOptionsSelectionCallback ( SslStream stream , SslClientHelloInfo clientHelloInfo , object state , CancellationToken cancellationToken )
375
370
{
376
- const string wildcardHost = "*" ;
377
- const string wildcardPrefix = "*." ;
378
-
379
- var sslServerOptions = new SslServerAuthenticationOptions ( ) ;
380
- var serverName = clientHelloInfo . ServerName ;
381
- SniConfig sniConfig = null ;
382
-
383
- if ( ! string . IsNullOrEmpty ( serverName ) )
384
- {
385
- foreach ( var ( name , sniConfigCandidate ) in endpoint . SNI )
386
- {
387
- if ( name . Equals ( serverName , StringComparison . OrdinalIgnoreCase ) )
388
- {
389
- sniConfig = sniConfigCandidate ;
390
- break ;
391
- }
392
- // Note that we only slice off the `*`. We want to match the leading `.` also.
393
- else if ( name . StartsWith ( wildcardPrefix , StringComparison . Ordinal )
394
- && serverName . EndsWith ( name . Substring ( wildcardHost . Length ) , StringComparison . OrdinalIgnoreCase )
395
- && name . Length > ( sniConfig ? . Name . Length ?? 0 ) )
396
- {
397
- sniConfig = sniConfigCandidate ;
398
- }
399
- else if ( name . Equals ( wildcardHost , StringComparison . Ordinal ) )
400
- {
401
- sniConfig ??= sniConfigCandidate ;
402
- }
403
- }
404
- }
405
-
406
- sslServerOptions . ServerCertificate = LoadCertificate ( sniConfig ? . Certificate , endpoint . Name ) ?? LoadEndpointOrDefaultCertificate ( httpsOptions , endpoint ) ;
407
-
408
- if ( sslServerOptions . ServerCertificate is null )
409
- {
410
- throw new InvalidOperationException ( CoreStrings . NoCertSpecifiedNoDevelopmentCertificateFound ) ;
411
- }
412
-
413
- sslServerOptions . EnabledSslProtocols = sniConfig ? . SslProtocols ?? httpsOptions . SslProtocols ;
414
- HttpsConnectionMiddleware . ConfigureAlpn ( sslServerOptions , sniConfig ? . Protocols ?? endpointDefaultHttpProtocols ) ;
415
-
416
- var clientCertificateMode = sniConfig ? . ClientCertificateMode ?? httpsOptions . ClientCertificateMode ;
417
-
418
- if ( clientCertificateMode != ClientCertificateMode . NoCertificate )
419
- {
420
- sslServerOptions . ClientCertificateRequired = true ;
421
- sslServerOptions . RemoteCertificateValidationCallback = ( sender , certificate , chain , sslPolicyErrors ) =>
422
- HttpsConnectionMiddleware . RemoteCertificateValidationCallback ( clientCertificateMode , httpsOptions . ClientCertificateValidation , certificate , chain , sslPolicyErrors ) ;
423
- }
424
-
425
- return new ValueTask < SslServerAuthenticationOptions > ( sslServerOptions ) ;
426
- }
427
-
428
- private X509Certificate2 LoadEndpointOrDefaultCertificate ( HttpsConnectionAdapterOptions httpsOptions , EndpointConfig endpoint )
429
- {
430
- // Specified
431
- httpsOptions . ServerCertificate = LoadCertificate ( endpoint . Certificate , endpoint . Name )
432
- ?? httpsOptions . ServerCertificate ;
433
-
434
- if ( httpsOptions . ServerCertificate == null && httpsOptions . ServerCertificateSelector == null )
435
- {
436
- // Fallback
437
- Options . ApplyDefaultCert ( httpsOptions ) ;
438
-
439
- // Ensure endpoint is reloaded if it used the default certificate and the certificate changed.
440
- endpoint . Certificate = DefaultCertificateConfig ;
441
- }
442
-
443
- return httpsOptions . ServerCertificate ;
371
+ var sniOptionsSelector = ( SniOptionsSelector ) state ;
372
+ var options = sniOptionsSelector . GetOptions ( clientHelloInfo . ServerName ) ;
373
+ return new ValueTask < SslServerAuthenticationOptions > ( options ) ;
444
374
}
445
375
446
376
private void LoadDefaultCert ( ConfigurationReader configReader )
@@ -531,7 +461,7 @@ private bool TryGetCertificatePath(out string path)
531
461
return path != null ;
532
462
}
533
463
534
- private X509Certificate2 LoadCertificate ( CertificateConfig certInfo , string endpointName )
464
+ internal X509Certificate2 LoadCertificate ( CertificateConfig certInfo , string endpointName )
535
465
{
536
466
if ( certInfo is null )
537
467
{
@@ -622,6 +552,24 @@ static X509Certificate2 GetCertificate(string certificatePath)
622
552
}
623
553
}
624
554
555
+ internal X509Certificate2 LoadEndpointOrDefaultCertificate ( HttpsConnectionAdapterOptions httpsOptions , EndpointConfig endpoint )
556
+ {
557
+ // Specified
558
+ httpsOptions . ServerCertificate = LoadCertificate ( endpoint . Certificate , endpoint . Name )
559
+ ?? httpsOptions . ServerCertificate ;
560
+
561
+ if ( httpsOptions . ServerCertificate == null && httpsOptions . ServerCertificateSelector == null )
562
+ {
563
+ // Fallback
564
+ Options . ApplyDefaultCert ( httpsOptions ) ;
565
+
566
+ // Ensure endpoint is reloaded if it used the default certificate and the certificate changed.
567
+ endpoint . Certificate = DefaultCertificateConfig ;
568
+ }
569
+
570
+ return httpsOptions . ServerCertificate ;
571
+ }
572
+
625
573
private static X509Certificate2 AttachPemRSAKey ( X509Certificate2 certificate , string keyText , string password )
626
574
{
627
575
using var rsa = RSA . Create ( ) ;
0 commit comments