11using System . Diagnostics ;
22using System . Net ;
33using System . Net . Security ;
4+ using System . Security . Authentication ;
45using System . Security . Cryptography . X509Certificates ;
6+ using Microsoft . AspNetCore . Authentication . Certificate ;
7+ using Microsoft . AspNetCore . Connections . Features ;
8+ using Microsoft . AspNetCore . Http . Features ;
59using Microsoft . AspNetCore . Server . HttpSys ;
610using Microsoft . AspNetCore . Server . Kestrel . Core ;
711using Microsoft . AspNetCore . Server . Kestrel . Https ;
1115var builder = WebApplication . CreateBuilder ( args ) ;
1216builder . Logging . ClearProviders ( ) ;
1317
14- var writeCertValidationEventsToConsole = bool . TryParse ( builder . Configuration [ "certValidationConsoleEnabled" ] , out var certValidationConsoleEnabled ) && certValidationConsoleEnabled ;
18+ // behavioral
1519var mTlsEnabled = bool . TryParse ( builder . Configuration [ "mTLS" ] , out var mTlsEnabledConfig ) && mTlsEnabledConfig ;
1620var tlsRenegotiationEnabled = bool . TryParse ( builder . Configuration [ "tlsRenegotiation" ] , out var tlsRenegotiationEnabledConfig ) && tlsRenegotiationEnabledConfig ;
17- var statsEnabled = bool . TryParse ( builder . Configuration [ "statsEnabled" ] , out var connectionStatsEnabledConfig ) && connectionStatsEnabledConfig ;
1821var 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 ;
1928
2029if ( mTlsEnabled && tlsRenegotiationEnabled )
2130{
@@ -42,6 +51,11 @@ void ConfigureListen(KestrelServerOptions serverOptions, IConfigurationRoot conf
4251 // [SuppressMessage("Microsoft.Security", "CSCAN0220.DefaultPasswordContexts", Justification="Benchmark code, not a secret")]
4352 listenOptions . UseHttps ( "testCert.pfx" , "testPassword" , options =>
4453 {
54+ if ( supportedTlsVersions is not null )
55+ {
56+ options . SslProtocols = supportedTlsVersions . Value ;
57+ }
58+
4559 if ( mTlsEnabled )
4660 {
4761 options . ClientCertificateMode = ClientCertificateMode . RequireCertificate ;
@@ -83,6 +97,28 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
8397 return true ;
8498}
8599
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+
86122if ( statsEnabled )
87123{
88124 Console . WriteLine ( "Registered stats middleware" ) ;
@@ -91,7 +127,7 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
91127 connectionIds . Add ( context . Connection . Id ) ;
92128 Console . WriteLine ( $ "[stats] unique connections established: { connectionIds . Count } ; fetched certificates: { fetchedCertsCounter } ") ;
93129
94- await next ( ) ;
130+ await next ( context ) ;
95131 } ) ;
96132}
97133
@@ -111,7 +147,7 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
111147 Console . WriteLine ( $ "client certificate ({ clientCert . Thumbprint } ) already exists on the connection { context . Connection . Id } ") ;
112148 }
113149
114- await next ( ) ;
150+ await next ( context ) ;
115151 } ) ;
116152}
117153
@@ -140,6 +176,7 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
140176{
141177 Console . WriteLine ( $ "\t enabled logging stats to console") ;
142178}
179+ Console . WriteLine ( $ "\t supported TLS versions: { supportedTlsVersions } ") ;
143180Console . WriteLine ( $ "\t listening endpoints: { listeningEndpoints } ") ;
144181Console . WriteLine ( "--------------------------------" ) ;
145182
@@ -162,6 +199,33 @@ static IPEndPoint CreateIPEndPoint(UrlPrefix urlPrefix)
162199 return new IPEndPoint ( ip , urlPrefix . PortValue ) ;
163200}
164201
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+
165229static void LogOpenSSLVersion ( )
166230{
167231 using var process = new Process ( )
0 commit comments