@@ -539,7 +539,6 @@ void ConfigureListenOptions(ListenOptions listenOptions)
539
539
listenOptions . UseHttps ( options =>
540
540
{
541
541
options . ServerCertificate = _x509Certificate2 ;
542
- options . SslProtocols = SslProtocols . Tls12 ; // Linux doesn't support renegotiate on TLS1.3 yet. https://github.com/dotnet/runtime/issues/55757
543
542
options . ClientCertificateMode = ClientCertificateMode . DelayCertificate ;
544
543
options . AllowAnyClientCertificate ( ) ;
545
544
} ) ;
@@ -626,7 +625,6 @@ void ConfigureListenOptions(ListenOptions listenOptions)
626
625
return ValueTask . FromResult ( new SslServerAuthenticationOptions ( )
627
626
{
628
627
ServerCertificate = _x509Certificate2 ,
629
- EnabledSslProtocols = SslProtocols . Tls12 , // Linux doesn't support renegotiate on TLS1.3 yet. https://github.com/dotnet/runtime/issues/55757
630
628
ClientCertificateRequired = false ,
631
629
RemoteCertificateValidationCallback = ( _ , _ , _ , _ ) => true ,
632
630
} ) ;
@@ -670,7 +668,6 @@ void ConfigureListenOptions(ListenOptions listenOptions)
670
668
listenOptions . UseHttps ( options =>
671
669
{
672
670
options . ServerCertificate = _x509Certificate2 ;
673
- options . SslProtocols = SslProtocols . Tls12 ; // Linux doesn't support renegotiate on TLS1.3 yet. https://github.com/dotnet/runtime/issues/55757
674
671
options . ClientCertificateMode = ClientCertificateMode . DelayCertificate ;
675
672
options . AllowAnyClientCertificate ( ) ;
676
673
} ) ;
@@ -786,60 +783,13 @@ void ConfigureListenOptions(ListenOptions listenOptions)
786
783
// then the connection is aborted.
787
784
[ OSSkipCondition ( OperatingSystems . MacOSX , SkipReason = "Missing platform support." ) ]
788
785
[ SkipOnHelix ( "https://github.com/dotnet/aspnetcore/issues/33566#issuecomment-892031659" , Queues = HelixConstants . RedhatAmd64 ) ] // Outdated OpenSSL client
789
- public async Task RenegotiateForClientCertificateOnPostWithoutBufferingThrows_TLS12 ( )
786
+ public async Task RenegotiateForClientCertificateOnPostWithoutBufferingThrows ( )
790
787
{
791
788
void ConfigureListenOptions ( ListenOptions listenOptions )
792
789
{
793
790
listenOptions . Protocols = HttpProtocols . Http1 ;
794
791
listenOptions . UseHttps ( options =>
795
792
{
796
- options . SslProtocols = SslProtocols . Tls12 ;
797
- options . ServerCertificate = _x509Certificate2 ;
798
- options . ClientCertificateMode = ClientCertificateMode . DelayCertificate ;
799
- options . AllowAnyClientCertificate ( ) ;
800
- } ) ;
801
- }
802
-
803
- // Under 4kb can sometimes work because it fits into Kestrel's header parsing buffer.
804
- var expectedBody = new string ( 'a' , 1024 * 4 ) ;
805
-
806
- await using var server = new TestServer ( async context =>
807
- {
808
- var tlsFeature = context . Features . Get < ITlsConnectionFeature > ( ) ;
809
- Assert . NotNull ( tlsFeature ) ;
810
- Assert . Null ( tlsFeature . ClientCertificate ) ;
811
- Assert . Null ( context . Connection . ClientCertificate ) ;
812
-
813
- var ex = await Assert . ThrowsAsync < InvalidOperationException > ( ( ) => context . Connection . GetClientCertificateAsync ( ) ) ;
814
- Assert . Equal ( "Client stream needs to be drained before renegotiation." , ex . Message ) ;
815
- Assert . Null ( tlsFeature . ClientCertificate ) ;
816
- Assert . Null ( context . Connection . ClientCertificate ) ;
817
- } , new TestServiceContext ( LoggerFactory ) , ConfigureListenOptions ) ;
818
-
819
- using var connection = server . CreateConnection ( ) ;
820
- // SslStream is used to ensure the certificate is actually passed to the server
821
- // HttpClient might not send the certificate because it is invalid or it doesn't match any
822
- // of the certificate authorities sent by the server in the SSL handshake.
823
- // Use a random host name to avoid the TLS session resumption cache.
824
- var stream = OpenSslStreamWithCert ( connection . Stream ) ;
825
- await stream . AuthenticateAsClientAsync ( Guid . NewGuid ( ) . ToString ( ) ) ;
826
- await AssertConnectionResult ( stream , true , expectedBody ) ;
827
- }
828
-
829
- [ ConditionalFact ]
830
- // TLS 1.3 uses a new client cert negotiation extension that doesn't cause the connection to abort
831
- // for this error.
832
- [ MinimumOSVersion ( OperatingSystems . Windows , "10.0.20145" ) ] // Needs a preview version with TLS 1.3 enabled.
833
- [ OSSkipCondition ( OperatingSystems . MacOSX | OperatingSystems . Linux , SkipReason = "https://github.com/dotnet/runtime/issues/55757" ) ]
834
- [ SkipOnHelix ( "https://github.com/dotnet/aspnetcore/issues/33566#issuecomment-892031659" , Queues = HelixConstants . RedhatAmd64 ) ] // Outdated OpenSSL client
835
- public async Task RenegotiateForClientCertificateOnPostWithoutBufferingThrows_TLS13 ( )
836
- {
837
- void ConfigureListenOptions ( ListenOptions listenOptions )
838
- {
839
- listenOptions . Protocols = HttpProtocols . Http1 ;
840
- listenOptions . UseHttps ( options =>
841
- {
842
- options . SslProtocols = SslProtocols . Tls13 ;
843
793
options . ServerCertificate = _x509Certificate2 ;
844
794
options . ClientCertificateMode = ClientCertificateMode . DelayCertificate ;
845
795
options . AllowAnyClientCertificate ( ) ;
@@ -977,7 +927,6 @@ void ConfigureListenOptions(ListenOptions listenOptions)
977
927
listenOptions . UseHttps ( options =>
978
928
{
979
929
options . ServerCertificate = _x509Certificate2 ;
980
- options . SslProtocols = SslProtocols . Tls12 ; // Linux doesn't support renegotiate on TLS1.3 yet. https://github.com/dotnet/runtime/issues/55757
981
930
options . ClientCertificateMode = ClientCertificateMode . DelayCertificate ;
982
931
options . AllowAnyClientCertificate ( ) ;
983
932
} ) ;
@@ -1013,6 +962,60 @@ void ConfigureListenOptions(ListenOptions listenOptions)
1013
962
await AssertConnectionResult ( stream , true , expectedBody ) ;
1014
963
}
1015
964
965
+ [ ConditionalFact ]
966
+ [ OSSkipCondition ( OperatingSystems . MacOSX , SkipReason = "Missing platform support." ) ]
967
+ [ SkipOnHelix ( "https://github.com/dotnet/aspnetcore/issues/33566#issuecomment-892031659" , Queues = HelixConstants . RedhatAmd64 ) ] // Outdated OpenSSL client
968
+ public async Task RenegotationFailureCausesConnectionClose ( )
969
+ {
970
+ void ConfigureListenOptions ( ListenOptions listenOptions )
971
+ {
972
+ listenOptions . Protocols = HttpProtocols . Http1 ;
973
+ listenOptions . UseHttps ( options =>
974
+ {
975
+ options . ServerCertificate = _x509Certificate2 ;
976
+ options . ClientCertificateMode = ClientCertificateMode . DelayCertificate ;
977
+ options . AllowAnyClientCertificate ( ) ;
978
+ } ) ;
979
+ }
980
+
981
+ var expectedBody = new string ( 'a' , 1024 * 4 ) ;
982
+
983
+ await using var server = new TestServer ( async context =>
984
+ {
985
+ var tlsFeature = context . Features . Get < ITlsConnectionFeature > ( ) ;
986
+ Assert . NotNull ( tlsFeature ) ;
987
+ Assert . Null ( tlsFeature . ClientCertificate ) ;
988
+ Assert . Null ( context . Connection . ClientCertificate ) ;
989
+
990
+ // Request the client cert while there's still body data in the buffers
991
+ var ioe = await Assert . ThrowsAsync < InvalidOperationException > ( ( ) => context . Connection . GetClientCertificateAsync ( ) ) ;
992
+ Assert . Equal ( "Client stream needs to be drained before renegotiation." , ioe . Message ) ;
993
+
994
+ context . Response . ContentLength = 11 ;
995
+ await context . Response . WriteAsync ( "hello world" ) ;
996
+
997
+ } , new TestServiceContext ( LoggerFactory ) , ConfigureListenOptions ) ;
998
+
999
+ using var connection = server . CreateConnection ( ) ;
1000
+ // SslStream is used to ensure the certificate is actually passed to the server
1001
+ // HttpClient might not send the certificate because it is invalid or it doesn't match any
1002
+ // of the certificate authorities sent by the server in the SSL handshake.
1003
+ // Use a random host name to avoid the TLS session resumption cache.
1004
+ var stream = OpenSslStreamWithCert ( connection . Stream ) ;
1005
+ await stream . AuthenticateAsClientAsync ( Guid . NewGuid ( ) . ToString ( ) ) ;
1006
+
1007
+ var request = Encoding . UTF8 . GetBytes ( $ "POST / HTTP/1.1\r \n Host: localhost\r \n Content-Length: { expectedBody . Length } \r \n \r \n { expectedBody } ") ;
1008
+ await stream . WriteAsync ( request , 0 , request . Length ) . DefaultTimeout ( ) ;
1009
+ var reader = new StreamReader ( stream ) ;
1010
+ Assert . Equal ( "HTTP/1.1 200 OK" , await reader . ReadLineAsync ( ) . DefaultTimeout ( ) ) ;
1011
+ Assert . Equal ( "Content-Length: 11" , await reader . ReadLineAsync ( ) . DefaultTimeout ( ) ) ;
1012
+ Assert . Equal ( "Connection: close" , await reader . ReadLineAsync ( ) . DefaultTimeout ( ) ) ;
1013
+ Assert . StartsWith ( "Date: " , await reader . ReadLineAsync ( ) . DefaultTimeout ( ) ) ;
1014
+ Assert . Equal ( "" , await reader . ReadLineAsync ( ) . DefaultTimeout ( ) ) ;
1015
+ Assert . Equal ( "hello world" , await reader . ReadLineAsync ( ) . DefaultTimeout ( ) ) ;
1016
+ Assert . Null ( await reader . ReadLineAsync ( ) . DefaultTimeout ( ) ) ;
1017
+ }
1018
+
1016
1019
[ Fact ]
1017
1020
public async Task HttpsSchemePassedToRequestFeature ( )
1018
1021
{
0 commit comments