@@ -40,6 +40,19 @@ public enum ClientCertSource
40
40
CertificateContext
41
41
}
42
42
43
+ public static TheoryData < ClientCertSource > CertSourceData ( )
44
+ {
45
+ TheoryData < ClientCertSource > data = new ( ) ;
46
+
47
+ foreach ( var source in Enum . GetValues < ClientCertSource > ( ) )
48
+ {
49
+ data . Add ( source ) ;
50
+ }
51
+
52
+ return data ;
53
+ }
54
+
55
+
43
56
public static TheoryData < bool , ClientCertSource > BoolAndCertSourceData ( )
44
57
{
45
58
TheoryData < bool , ClientCertSource > data = new ( ) ;
@@ -143,6 +156,72 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout(
143
156
}
144
157
}
145
158
159
+ [ ConditionalTheory ( typeof ( TestConfiguration ) , nameof ( TestConfiguration . SupportsRenegotiation ) ) ]
160
+ [ MemberData ( nameof ( CertSourceData ) ) ]
161
+ [ PlatformSpecific ( TestPlatforms . Windows | TestPlatforms . Linux ) ]
162
+ public async Task SslStream_NegotiateClientCertificate_IsMutuallyAuthenticatedCorrect ( ClientCertSource certSource )
163
+ {
164
+ SslStreamCertificateContext context = SslStreamCertificateContext . Create ( _serverCertificate , null ) ;
165
+ var clientOptions = new SslClientAuthenticationOptions
166
+ {
167
+ TargetHost = Guid . NewGuid ( ) . ToString ( "N" )
168
+ } ;
169
+
170
+ for ( int round = 0 ; round < 3 ; round ++ )
171
+ {
172
+ ( Stream stream1 , Stream stream2 ) = TestHelper . GetConnectedStreams ( ) ;
173
+ using ( var client = new SslStream ( stream1 , false , AllowAnyCertificate ) )
174
+ using ( var server = new SslStream ( stream2 , false , AllowAnyCertificate ) )
175
+ {
176
+
177
+ switch ( certSource )
178
+ {
179
+ case ClientCertSource . ClientCertificate :
180
+ clientOptions . ClientCertificates = new X509CertificateCollection ( ) { _clientCertificate } ;
181
+ break ;
182
+ case ClientCertSource . SelectionCallback :
183
+ clientOptions . LocalCertificateSelectionCallback = ClientCertSelectionCallback ;
184
+ break ;
185
+ case ClientCertSource . CertificateContext :
186
+ clientOptions . ClientCertificateContext = SslStreamCertificateContext . Create ( _clientCertificate , new ( ) ) ;
187
+ break ;
188
+ }
189
+
190
+ Task t2 = client . AuthenticateAsClientAsync ( clientOptions ) ;
191
+ Task t1 = server . AuthenticateAsServerAsync ( new SslServerAuthenticationOptions
192
+ {
193
+ ServerCertificateContext = context ,
194
+ ClientCertificateRequired = false ,
195
+ EnabledSslProtocols = SslProtocols . Tls12 ,
196
+
197
+ } ) ;
198
+
199
+ await TestConfiguration . WhenAllOrAnyFailedWithTimeout ( t1 , t2 ) ;
200
+
201
+ if ( round >= 0 && server . RemoteCertificate != null )
202
+ {
203
+ // TLS resumed
204
+ Assert . True ( client . IsMutuallyAuthenticated , "client.IsMutuallyAuthenticated" ) ;
205
+ Assert . True ( server . IsMutuallyAuthenticated , "server.IsMutuallyAuthenticated" ) ;
206
+ continue ;
207
+ }
208
+
209
+ Assert . False ( client . IsMutuallyAuthenticated , "client.IsMutuallyAuthenticated" ) ;
210
+ Assert . False ( server . IsMutuallyAuthenticated , "server.IsMutuallyAuthenticated" ) ;
211
+
212
+ var t = client . ReadAsync ( new byte [ 1 ] ) ;
213
+ await server . NegotiateClientCertificateAsync ( ) ;
214
+ Assert . NotNull ( server . RemoteCertificate ) ;
215
+ await server . WriteAsync ( new byte [ 1 ] ) ;
216
+ await t ;
217
+
218
+ Assert . NotNull ( server . RemoteCertificate ) ;
219
+ Assert . True ( client . IsMutuallyAuthenticated , "client.IsMutuallyAuthenticated" ) ;
220
+ Assert . True ( server . IsMutuallyAuthenticated , "server.IsMutuallyAuthenticated" ) ;
221
+ }
222
+ }
223
+ }
224
+
146
225
[ ConditionalTheory ( typeof ( PlatformDetection ) , nameof ( PlatformDetection . IsNotWindows7 ) ) ]
147
226
[ ClassData ( typeof ( SslProtocolSupport . SupportedSslProtocolsTestData ) ) ]
148
227
public async Task SslStream_ResumedSessionsClientCollection_IsMutuallyAuthenticatedCorrect (
0 commit comments