@@ -295,62 +295,24 @@ private string[] GetRequestCertificateAuthorities()
295295 return issuers ;
296296 }
297297
298- /*++
299- AcquireCredentials - Attempts to find Client Credential
300- Information, that can be sent to the server. In our case,
301- this is only Client Certificates, that we have Credential Info.
302-
303- How it works:
304- case 0: Cert Selection delegate is present
305- Always use its result as the client cert answer.
306- Try to use cached credential handle whenever feasible.
307- Do not use cached anonymous creds if the delegate has returned null
308- and the collection is not empty (allow responding with the cert later).
309-
310- case 1: Certs collection is empty
311- Always use the same statically acquired anonymous SSL Credential
312-
313- case 2: Before our Connection with the Server
314- If we have a cached credential handle keyed by first X509Certificate
315- **content** in the passed collection, then we use that cached
316- credential and hoping to restart a session.
317-
318- Otherwise create a new anonymous (allow responding with the cert later).
319-
320- case 3: After our Connection with the Server (i.e. during handshake or re-handshake)
321- The server has requested that we send it a Certificate then
322- we Enumerate a list of server sent Issuers trying to match against
323- our list of Certificates, the first match is sent to the server.
324-
325- Once we got a cert we again try to match cached credential handle if possible.
326- This will not restart a session but helps minimizing the number of handles we create.
327-
328- In the case of an error getting a Certificate or checking its private Key we fall back
329- to the behavior of having no certs, case 1.
330-
331- Returns: True if cached creds were used, false otherwise.
332-
333- --*/
334-
335- private bool AcquireClientCredentials ( ref byte [ ] ? thumbPrint )
298+ internal X509Certificate2 ? SelectClientCertificate ( out bool sessionRestartAttempt )
336299 {
337- // Acquire possible Client Certificate information and set it on the handle.
338- X509Certificate ? clientCertificate = null ; // This is a candidate that can come from the user callback or be guessed when targeting a session restart.
339- List < X509Certificate > ? filteredCerts = null ; // This is an intermediate client certs collection that try to use if no selectedCert is available yet.
340- string [ ] issuers ; // This is a list of issuers sent by the server, only valid is we do know what the server cert is.
300+ sessionRestartAttempt = false ;
341301
342- bool sessionRestartAttempt = false ; // If true and no cached creds we will use anonymous creds.
302+ X509Certificate ? clientCertificate = null ; // candidate certificate that can come from the user callback or be guessed when targeting a session restart.
303+ X509Certificate2 ? selectedCert = null ; // final selected cert (ensured that it does have private key with it).
304+ List < X509Certificate > ? filteredCerts = null ; // This is an intermediate client certs collection that try to use if no selectedCert is available yet.
305+ string [ ] issuers ; // This is a list of issuers sent by the server, only valid if we do know what the server cert is.
343306
344307 if ( _sslAuthenticationOptions . CertSelectionDelegate != null )
345308 {
346- issuers = GetRequestCertificateAuthorities ( ) ;
347-
348309 if ( NetEventSource . Log . IsEnabled ( ) )
349310 NetEventSource . Info ( this , "Calling CertificateSelectionCallback" ) ;
350311
351312 X509Certificate2 ? remoteCert = null ;
352313 try
353314 {
315+ issuers = GetRequestCertificateAuthorities ( ) ;
354316 remoteCert = CertificateValidationPal . GetRemoteCertificate ( _securityContext ! ) ;
355317 if ( _sslAuthenticationOptions . ClientCertificates == null )
356318 {
@@ -363,7 +325,6 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint)
363325 remoteCert ? . Dispose ( ) ;
364326 }
365327
366-
367328 if ( clientCertificate != null )
368329 {
369330 if ( _credentialsHandle == null )
@@ -505,9 +466,6 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint)
505466 }
506467 }
507468
508- bool cachedCred = false ; // This is a return result from this method.
509- X509Certificate2 ? selectedCert = null ; // This is a final selected cert (ensured that it does have private key with it).
510-
511469 clientCertificate = null ;
512470
513471 if ( NetEventSource . Log . IsEnabled ( ) )
@@ -550,6 +508,56 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint)
550508
551509 if ( NetEventSource . Log . IsEnabled ( ) ) NetEventSource . Info ( this , $ "Selected cert = { selectedCert } ") ;
552510
511+ _selectedClientCertificate = clientCertificate ;
512+ return selectedCert ;
513+ }
514+
515+ /*++
516+ AcquireCredentials - Attempts to find Client Credential
517+ Information, that can be sent to the server. In our case,
518+ this is only Client Certificates, that we have Credential Info.
519+
520+ How it works:
521+ case 0: Cert Selection delegate is present
522+ Always use its result as the client cert answer.
523+ Try to use cached credential handle whenever feasible.
524+ Do not use cached anonymous creds if the delegate has returned null
525+ and the collection is not empty (allow responding with the cert later).
526+
527+ case 1: Certs collection is empty
528+ Always use the same statically acquired anonymous SSL Credential
529+
530+ case 2: Before our Connection with the Server
531+ If we have a cached credential handle keyed by first X509Certificate
532+ **content** in the passed collection, then we use that cached
533+ credential and hoping to restart a session.
534+
535+ Otherwise create a new anonymous (allow responding with the cert later).
536+
537+ case 3: After our Connection with the Server (i.e. during handshake or re-handshake)
538+ The server has requested that we send it a Certificate then
539+ we Enumerate a list of server sent Issuers trying to match against
540+ our list of Certificates, the first match is sent to the server.
541+
542+ Once we got a cert we again try to match cached credential handle if possible.
543+ This will not restart a session but helps minimizing the number of handles we create.
544+
545+ In the case of an error getting a Certificate or checking its private Key we fall back
546+ to the behavior of having no certs, case 1.
547+
548+ Returns: True if cached creds were used, false otherwise.
549+
550+ --*/
551+
552+ private bool AcquireClientCredentials ( ref byte [ ] ? thumbPrint )
553+ {
554+ // Acquire possible Client Certificate information and set it on the handle.
555+
556+ bool sessionRestartAttempt ; // If true and no cached creds we will use anonymous creds.
557+ bool cachedCred = false ; // this is a return result from this method.
558+
559+ X509Certificate2 ? selectedCert = SelectClientCertificate ( out sessionRestartAttempt ) ;
560+
553561 try
554562 {
555563 // Try to locate cached creds first.
@@ -574,22 +582,21 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint)
574582 // So we don't want to reuse **anonymous** cached credential for a new SSL connection if the client has passed some certificate.
575583 // The following block happens if client did specify a certificate but no cached creds were found in the cache.
576584 // Since we don't restart a session the server side can still challenge for a client cert.
577- if ( ( object ? ) clientCertificate != ( object ? ) selectedCert )
585+ if ( ( object ? ) _selectedClientCertificate != ( object ? ) selectedCert )
578586 {
579587 selectedCert . Dispose ( ) ;
580588 }
581589
582590 guessedThumbPrint = null ;
583591 selectedCert = null ;
584- clientCertificate = null ;
592+ _selectedClientCertificate = null ;
585593 }
586594
587595 if ( cachedCredentialHandle != null )
588596 {
589597 if ( NetEventSource . Log . IsEnabled ( ) )
590598 NetEventSource . Log . UsingCachedCredential ( this ) ;
591599 _credentialsHandle = cachedCredentialHandle ;
592- _selectedClientCertificate = clientCertificate ;
593600 cachedCred = true ;
594601 if ( selectedCert != null )
595602 {
@@ -607,7 +614,6 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint)
607614 _sslAuthenticationOptions . EnabledSslProtocols , _sslAuthenticationOptions . EncryptionPolicy , _sslAuthenticationOptions . IsServer ) ;
608615
609616 thumbPrint = guessedThumbPrint ; // Delay until here in case something above threw.
610- _selectedClientCertificate = clientCertificate ;
611617 }
612618 }
613619 finally
@@ -792,6 +798,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan<byte> inputBuffer, ref byte
792798 if ( _sslAuthenticationOptions . IsServer )
793799 {
794800 status = SslStreamPal . AcceptSecurityContext (
801+ this ,
795802 ref _credentialsHandle ! ,
796803 ref _securityContext ,
797804 inputBuffer ,
@@ -801,6 +808,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan<byte> inputBuffer, ref byte
801808 else
802809 {
803810 status = SslStreamPal . InitializeSecurityContext (
811+ this ,
804812 ref _credentialsHandle ! ,
805813 ref _securityContext ,
806814 _sslAuthenticationOptions . TargetHost ,
@@ -841,6 +849,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan<byte> inputBuffer, ref byte
841849 internal SecurityStatusPal Renegotiate ( out byte [ ] ? output )
842850 {
843851 return SslStreamPal . Renegotiate (
852+ this ,
844853 ref _credentialsHandle ! ,
845854 ref _securityContext ,
846855 _sslAuthenticationOptions ,
0 commit comments