1
1
using System . Diagnostics ;
2
2
using System . Net ;
3
3
using System . Net . Security ;
4
- using System . Runtime . InteropServices ;
4
+ using System . Reflection ;
5
5
using System . Security . Authentication ;
6
6
using System . Security . Cryptography . X509Certificates ;
7
- using Microsoft . AspNetCore . Authentication . Certificate ;
8
7
using Microsoft . AspNetCore . Connections . Features ;
9
8
using Microsoft . AspNetCore . Http . Features ;
10
9
using Microsoft . AspNetCore . Server . HttpSys ;
21
20
var tlsRenegotiationEnabled = bool . TryParse ( builder . Configuration [ "tlsRenegotiation" ] , out var tlsRenegotiationEnabledConfig ) && tlsRenegotiationEnabledConfig ;
22
21
var certPublicKeySpecified = int . TryParse ( builder . Configuration [ "certPublicKeyLength" ] , out var certPublicKeyConfig ) ;
23
22
var certPublicKeyLength = certPublicKeySpecified ? certPublicKeyConfig : 2048 ;
23
+ var enableHostHeaderValidation = bool . TryParse ( builder . Configuration [ "enableHostHeaderValidation" ] , out var enableHostHeaderValidationConfig ) && enableHostHeaderValidationConfig ;
24
24
25
25
// endpoints
26
26
var listeningEndpoints = builder . Configuration [ "urls" ] ?? "https://localhost:5000/" ;
39
39
var connectionIds = new HashSet < string > ( ) ;
40
40
var fetchedCertsCounter = 0 ;
41
41
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
+
42
60
builder . WebHost . UseKestrel ( options =>
43
61
{
44
62
foreach ( var value in listeningEndpoints . Split ( [ ';' ] , StringSplitOptions . RemoveEmptyEntries ) )
@@ -56,8 +74,15 @@ void ConfigureListen(KestrelServerOptions serverOptions, IConfigurationRoot conf
56
74
var certificatePath = Path . Combine ( "certificates" , $ "testCert-{ certPublicKeyLength } .pfx") ;
57
75
Console . WriteLine ( $ "Using certificate: { certificatePath } ") ;
58
76
77
+ var certPath =
78
+ #if DEBUG
79
+ Path . Combine ( Path . GetDirectoryName ( Assembly . GetEntryAssembly ( ) ! . Location ) ! , certificatePath ) ; // exe location
80
+ #else
81
+ certificatePath ;
82
+ #endif
83
+
59
84
// [SuppressMessage("Microsoft.Security", "CSCAN0220.DefaultPasswordContexts", Justification="Benchmark code, not a secret")]
60
- listenOptions . UseHttps ( certificatePath , "testPassword" , options =>
85
+ listenOptions. UseHttps ( certPath , "testPassword" , options =>
61
86
{
62
87
if ( supportedTlsVersions is not null )
63
88
{
@@ -98,6 +123,12 @@ void ConfigureListen(KestrelServerOptions serverOptions, IConfigurationRoot conf
98
123
99
124
var app = builder . Build ( ) ;
100
125
126
+ if ( enableHostHeaderValidation )
127
+ {
128
+ Console . WriteLine ( "Enabled host header filtering middleware." ) ;
129
+ app . UseHostFiltering ( ) ;
130
+ }
131
+
101
132
bool AllowAnyCertificateValidationWithLogging ( X509Certificate2 certificate , X509Chain ? chain , SslPolicyErrors errors )
102
133
{
103
134
fetchedCertsCounter ++ ;
0 commit comments