Thanks to visit codestin.com
Credit goes to github.com

Skip to content

SslStream RemoteCertificateValidationCallback has regressed to being unable to access protocol/cipher info #114351

Closed
@dlstucki

Description

@dlstucki

Description

This scenario was enabled, including a unit test in .NET 5. It is broken again since .NET 7. I've observed this issue on .NET 8 Windows x64, but looking over the source it appears the issue is still present in higher versions.

The desired capability is being able to call Stream.SslProtocol/CipherAlogrithm from the SslStream's RemoteCertificateValidationCallback as described here: #919.

Original fix was #37580. It included a unit test named ClientAsyncAuthenticate_ConnectionInfoInCallback_DoesNotThrow.

Later #68678 changed the implementation of SslStream.ThrowIfExceptionalOrNotHandshake. This broke the property access scenario, but at some point the test method ClientAsyncAuthenticateTest.ClientAsyncSslHelper was refactored a bit and the ClientAsyncAuthenticate_ConnectionInfoInCallback_DoesNotThrow unit test was no longer using its special remote certificate validation callback to verify property access.

Reproduction Steps

Either of:

  1. This could easily be reproduced by fixing the ClientAsyncAuthenticate_ConnectionInfoInCallback_DoesNotThrow unit test and running that. That update would be to change ClientAsyncSslHelper(EncryptionPolicy, SslProtocols, SslProtocols, RemoteCertificateValidationCallback) to honor the RemoteCertificateValidationCallback parameter. AllowAnyServerCertificateAndVerifyConnectionInfo would then attempt to access the properties and the test would fail.

  2. The desired capability is being able to call Stream.SslProtocol/CipherAlogrithm from the SslStream's RemoteCertificateValidationCallback as described here: SslStream RemoteCertificateValidationCallback cannot access protocol/cipher info #919:

static bool ValidateRemoteCertificate(object Sender, X509Certificate Certificate, X509Chain Chain, SslPolicyErrors PolicyErrors)
{
    var stream = (SslStream)Sender;

    // The linked docs imply that these properties should be accessible at this point but
    // they throw InvalidOperationException when accessed
    return stream.CipherAlgorithm != CipherAlgorithmType.Rc4 &&
        stream.HashAlgorithm != HashAlgorithmType.Md5 &&
        stream.SslProtocol != SslProtocols.Tls13;
}

Expected behavior

SslStream.SslProtocol should be accessible from the RemoteCertificateValidationCallback

Actual behavior

System.InvalidOperationException: This operation is only allowed using a successfully authenticated context.
   at System.Net.Security.SslStream.ThrowNotAuthenticated()
   at System.Net.Security.SslStream.get_CipherAlgorithm()
   at Microsoft.Azure.SomeProcduct.RemoteServerValidationCallback(Object, X509Certificate, X509Chain, SslPolicyErrors)

Regression?

Crypto properties were accessible at RemoteCertificateValidationCallback time in .NET 5 and 6. Since .NET 7 that scenario has been broken.

Known Workarounds

I couldn't quickly come up with anything.

Configuration

.NET 7+ is broken. I tested with .NET 8, Windows 11, x64.

Other information

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions