@@ -95,6 +95,73 @@ void ConfigureListenOptions(ListenOptions listenOptions)
95
95
}
96
96
}
97
97
98
+ [ ConditionalFact ]
99
+ [ OSSkipCondition ( OperatingSystems . MacOSX , SkipReason = "Missing SslStream ALPN support: https://github.com/dotnet/corefx/issues/30492" ) ]
100
+ [ MinimumOSVersion ( OperatingSystems . Windows , WindowsVersions . Win81 ) ]
101
+ public async Task CanUseDefaultSniConfiguration ( )
102
+ {
103
+ var configuration = new ConfigurationBuilder ( ) . AddInMemoryCollection ( new Dictionary < string , string >
104
+ {
105
+ [ "EndpointDefaults:Sni:*.example.org:Protocols" ] = "Http1" ,
106
+ [ "EndpointDefaults:Sni:dot.net:Protocols" ] = "None" ,
107
+ } ) . Build ( ) ;
108
+
109
+ var options = new KestrelServerOptions ( ) ;
110
+ var env = new Mock < IHostEnvironment > ( ) ;
111
+ env . SetupGet ( e => e . ContentRootPath ) . Returns ( Directory . GetCurrentDirectory ( ) ) ;
112
+
113
+ options . ApplicationServices = new ServiceCollection ( )
114
+ . AddLogging ( )
115
+ . AddSingleton ( env . Object )
116
+ . BuildServiceProvider ( ) ;
117
+
118
+ options . Configure ( configuration ) . Load ( ) ;
119
+
120
+ void ConfigureListenOptions ( ListenOptions listenOptions )
121
+ {
122
+ listenOptions . KestrelServerOptions = options ;
123
+ listenOptions . UseHttps ( _x509Certificate2 ) ;
124
+ // We don't need to set listenOptions.Protocols since it will be flowed through the HttpProtocolsFeature
125
+ } ;
126
+
127
+ await using var server = new TestServer ( context => Task . CompletedTask , new TestServiceContext ( LoggerFactory ) , ConfigureListenOptions ) ;
128
+
129
+ using var exampleConnection = server . CreateConnection ( ) ;
130
+ var exampleSslOptions = new SslClientAuthenticationOptions
131
+ {
132
+ TargetHost = "a.example.org" ,
133
+ ApplicationProtocols = new List < SslApplicationProtocol > { SslApplicationProtocol . Http11 , SslApplicationProtocol . Http2 } ,
134
+ } ;
135
+
136
+ using var exampleStream = OpenSslStream ( exampleConnection . Stream ) ;
137
+ await exampleStream . AuthenticateAsClientAsync ( exampleSslOptions ) ;
138
+
139
+ Assert . Equal ( SslApplicationProtocol . Http11 , exampleStream . NegotiatedApplicationProtocol ) ;
140
+
141
+ using var dotnetConnection = server . CreateConnection ( ) ;
142
+ var dotnetSslOptions = new SslClientAuthenticationOptions
143
+ {
144
+ TargetHost = "dot.net" ,
145
+ ApplicationProtocols = new List < SslApplicationProtocol > { SslApplicationProtocol . Http11 , SslApplicationProtocol . Http2 } ,
146
+ } ;
147
+
148
+ using var dotnetStream = OpenSslStream ( dotnetConnection . Stream ) ;
149
+ await dotnetStream . AuthenticateAsClientAsync ( dotnetSslOptions ) ;
150
+
151
+ // HttpProtocols.None was configured, so there is no negotiated protocol
152
+ Assert . True ( dotnetStream . NegotiatedApplicationProtocol . Protocol . IsEmpty ) ;
153
+
154
+ using var emptyNameConnection = server . CreateConnection ( ) ;
155
+ var emptyNameSslOptions = new SslClientAuthenticationOptions
156
+ {
157
+ TargetHost = "" ,
158
+ } ;
159
+
160
+ using var refusedStream = OpenSslStream ( emptyNameConnection . Stream ) ;
161
+ // We expect the handshake to throw here because Kestrel refuses the connection due to there being no TargetHost and now wildcard config.
162
+ await Assert . ThrowsAsync < IOException > ( async ( ) => await refusedStream . AuthenticateAsClientAsync ( emptyNameSslOptions ) ) ;
163
+ }
164
+
98
165
[ Fact ]
99
166
public async Task HandshakeDetailsAreAvailable ( )
100
167
{
0 commit comments