1
1
using System . Diagnostics ;
2
2
using System . Net ;
3
3
using System . Net . Security ;
4
+ using System . Security . Authentication ;
4
5
using System . Security . Cryptography . X509Certificates ;
6
+ using Microsoft . AspNetCore . Authentication . Certificate ;
7
+ using Microsoft . AspNetCore . Connections . Features ;
8
+ using Microsoft . AspNetCore . Http . Features ;
5
9
using Microsoft . AspNetCore . Server . HttpSys ;
6
10
using Microsoft . AspNetCore . Server . Kestrel . Core ;
7
11
using Microsoft . AspNetCore . Server . Kestrel . Https ;
11
15
var builder = WebApplication . CreateBuilder ( args ) ;
12
16
builder . Logging . ClearProviders ( ) ;
13
17
14
- var writeCertValidationEventsToConsole = bool . TryParse ( builder . Configuration [ "certValidationConsoleEnabled" ] , out var certValidationConsoleEnabled ) && certValidationConsoleEnabled ;
18
+ // behavioral
15
19
var mTlsEnabled = bool . TryParse ( builder . Configuration [ "mTLS" ] , out var mTlsEnabledConfig ) && mTlsEnabledConfig ;
16
20
var tlsRenegotiationEnabled = bool . TryParse ( builder . Configuration [ "tlsRenegotiation" ] , out var tlsRenegotiationEnabledConfig ) && tlsRenegotiationEnabledConfig ;
17
- var statsEnabled = bool . TryParse ( builder . Configuration [ "statsEnabled" ] , out var connectionStatsEnabledConfig ) && connectionStatsEnabledConfig ;
18
21
var listeningEndpoints = builder . Configuration [ "urls" ] ?? "https://localhost:5000/" ;
22
+ var supportedTlsVersions = ParseSslProtocols ( builder . Configuration [ "tlsProtocols" ] ) ;
23
+
24
+ // debug
25
+ var writeCertValidationEventsToConsole = bool . TryParse ( builder . Configuration [ "certValidationConsoleEnabled" ] , out var certValidationConsoleEnabled ) && certValidationConsoleEnabled ;
26
+ var statsEnabled = bool . TryParse ( builder . Configuration [ "statsEnabled" ] , out var connectionStatsEnabledConfig ) && connectionStatsEnabledConfig ;
27
+ var logRequestDetails = bool . TryParse ( builder . Configuration [ "logRequestDetails" ] , out var logRequestDetailsConfig ) && logRequestDetailsConfig ;
19
28
20
29
if ( mTlsEnabled && tlsRenegotiationEnabled )
21
30
{
@@ -42,6 +51,11 @@ void ConfigureListen(KestrelServerOptions serverOptions, IConfigurationRoot conf
42
51
// [SuppressMessage("Microsoft.Security", "CSCAN0220.DefaultPasswordContexts", Justification="Benchmark code, not a secret")]
43
52
listenOptions . UseHttps ( "testCert.pfx" , "testPassword" , options =>
44
53
{
54
+ if ( supportedTlsVersions is not null )
55
+ {
56
+ options . SslProtocols = supportedTlsVersions . Value ;
57
+ }
58
+
45
59
if ( mTlsEnabled )
46
60
{
47
61
options . ClientCertificateMode = ClientCertificateMode . RequireCertificate ;
@@ -83,6 +97,28 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
83
97
return true ;
84
98
}
85
99
100
+ if ( logRequestDetails )
101
+ {
102
+ var logged = false ;
103
+ Console . WriteLine ( "Registered request details logging middleware" ) ;
104
+ app . Use ( async ( context , next ) =>
105
+ {
106
+ if ( ! logged )
107
+ {
108
+ logged = true ;
109
+
110
+ var tlsHandshakeFeature = context . Features . GetRequiredFeature < ITlsHandshakeFeature > ( ) ;
111
+
112
+ Console . WriteLine ( "Request details:" ) ;
113
+ Console . WriteLine ( "-----" ) ;
114
+ Console . WriteLine ( "TLS: " + tlsHandshakeFeature . Protocol ) ;
115
+ Console . WriteLine ( "-----" ) ;
116
+ }
117
+
118
+ await next ( context ) ;
119
+ } ) ;
120
+ }
121
+
86
122
if ( statsEnabled )
87
123
{
88
124
Console . WriteLine ( "Registered stats middleware" ) ;
@@ -91,7 +127,7 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
91
127
connectionIds . Add ( context . Connection . Id ) ;
92
128
Console . WriteLine ( $ "[stats] unique connections established: { connectionIds . Count } ; fetched certificates: { fetchedCertsCounter } ") ;
93
129
94
- await next ( ) ;
130
+ await next ( context ) ;
95
131
} ) ;
96
132
}
97
133
@@ -111,7 +147,7 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
111
147
Console . WriteLine ( $ "client certificate ({ clientCert . Thumbprint } ) already exists on the connection { context . Connection . Id } ") ;
112
148
}
113
149
114
- await next ( ) ;
150
+ await next ( context ) ;
115
151
} ) ;
116
152
}
117
153
@@ -140,6 +176,7 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
140
176
{
141
177
Console . WriteLine ( $ "\t enabled logging stats to console") ;
142
178
}
179
+ Console . WriteLine ( $ "\t supported TLS versions: { supportedTlsVersions } ") ;
143
180
Console . WriteLine ( $ "\t listening endpoints: { listeningEndpoints } ") ;
144
181
Console . WriteLine ( "--------------------------------" ) ;
145
182
@@ -162,6 +199,33 @@ static IPEndPoint CreateIPEndPoint(UrlPrefix urlPrefix)
162
199
return new IPEndPoint ( ip , urlPrefix . PortValue ) ;
163
200
}
164
201
202
+ static SslProtocols ? ParseSslProtocols ( string ? supportedTlsVersions )
203
+ {
204
+ var protocols = SslProtocols . None ;
205
+ if ( string . IsNullOrEmpty ( supportedTlsVersions ) || supportedTlsVersions == "any" )
206
+ {
207
+ return null ;
208
+ }
209
+
210
+ foreach ( var version in supportedTlsVersions . Split ( ',' ) )
211
+ {
212
+ switch ( version . Trim ( ) . ToLower ( ) )
213
+ {
214
+ case "tls12" :
215
+ protocols |= SslProtocols . Tls12 ;
216
+ break ;
217
+ case "tls13" :
218
+ protocols |= SslProtocols . Tls13 ;
219
+ break ;
220
+ default :
221
+ throw new ArgumentException ( $ "Unsupported TLS version: { version } ") ;
222
+ }
223
+ }
224
+
225
+ return protocols ;
226
+ }
227
+ }
228
+
165
229
static void LogOpenSSLVersion ( )
166
230
{
167
231
using var process = new Process ( )
0 commit comments