11using System . Diagnostics ;
22using System . Net ;
33using System . Net . Security ;
4- using System . Runtime . InteropServices ;
4+ using System . Reflection ;
55using System . Security . Authentication ;
66using System . Security . Cryptography . X509Certificates ;
7- using Microsoft . AspNetCore . Authentication . Certificate ;
87using Microsoft . AspNetCore . Connections . Features ;
98using Microsoft . AspNetCore . Http . Features ;
109using Microsoft . AspNetCore . Server . HttpSys ;
2120var tlsRenegotiationEnabled = bool . TryParse ( builder . Configuration [ "tlsRenegotiation" ] , out var tlsRenegotiationEnabledConfig ) && tlsRenegotiationEnabledConfig ;
2221var certPublicKeySpecified = int . TryParse ( builder . Configuration [ "certPublicKeyLength" ] , out var certPublicKeyConfig ) ;
2322var certPublicKeyLength = certPublicKeySpecified ? certPublicKeyConfig : 2048 ;
23+ var enableHostHeaderValidation = bool . TryParse ( builder . Configuration [ "enableHostHeaderValidation" ] , out var enableHostHeaderValidationConfig ) && enableHostHeaderValidationConfig ;
2424
2525// endpoints
2626var listeningEndpoints = builder . Configuration [ "urls" ] ?? "https://localhost:5000/" ;
3939var connectionIds = new HashSet < string > ( ) ;
4040var fetchedCertsCounter = 0 ;
4141
42+ if ( enableHostHeaderValidation )
43+ {
44+ builder . Services . Configure < Microsoft . AspNetCore . HostFiltering . HostFilteringOptions > ( options =>
45+ {
46+ var allowedHosts = new HashSet < string > ( ) ;
47+ foreach ( var endpoint in listeningEndpoints . Split ( [ ';' ] , StringSplitOptions . RemoveEmptyEntries ) )
48+ {
49+ var urlPrefix = UrlPrefix . Create ( endpoint ) ;
50+ allowedHosts . Add ( urlPrefix . Host ) ;
51+ }
52+
53+ Console . WriteLine ( "Configured HostFilteringOptions. Hosts: " + string . Join ( ';' , allowedHosts ) ) ;
54+ options . AllowedHosts = allowedHosts . ToArray ( ) ;
55+ options . IncludeFailureMessage = true ; // Suppresses the failure message in response body. It should be `true` to match http.sys behavior.
56+ options . AllowEmptyHosts = true ;
57+ } ) ;
58+ }
59+
4260builder . WebHost . UseKestrel ( options =>
4361{
4462 foreach ( var value in listeningEndpoints . Split ( [ ';' ] , StringSplitOptions . RemoveEmptyEntries ) )
@@ -56,8 +74,15 @@ void ConfigureListen(KestrelServerOptions serverOptions, IConfigurationRoot conf
5674 var certificatePath = Path . Combine ( "certificates" , $ "testCert-{ certPublicKeyLength } .pfx") ;
5775 Console . WriteLine ( $ "Using certificate: { certificatePath } ") ;
5876
77+ var certPath =
78+ #if DEBUG
79+ Path . Combine ( Path . GetDirectoryName ( Assembly . GetEntryAssembly ( ) ! . Location ) ! , certificatePath ) ; // exe location
80+ #else
81+ certificatePath ;
82+ #endif
83+
5984 // [SuppressMessage("Microsoft.Security", "CSCAN0220.DefaultPasswordContexts", Justification="Benchmark code, not a secret")]
60- listenOptions . UseHttps ( certificatePath , "testPassword" , options =>
85+ listenOptions. UseHttps ( certPath , "testPassword" , options =>
6186 {
6287 if ( supportedTlsVersions is not null )
6388 {
@@ -98,6 +123,12 @@ void ConfigureListen(KestrelServerOptions serverOptions, IConfigurationRoot conf
98123
99124var app = builder . Build ( ) ;
100125
126+ if ( enableHostHeaderValidation )
127+ {
128+ Console . WriteLine ( "Enabled host header filtering middleware." ) ;
129+ app . UseHostFiltering ( ) ;
130+ }
131+
101132bool AllowAnyCertificateValidationWithLogging ( X509Certificate2 certificate , X509Chain ? chain , SslPolicyErrors errors )
102133{
103134 fetchedCertsCounter ++ ;
0 commit comments