Skip to content

SslStream.IsMutuallyAuthenticated returns wrong value when cached creds are used #65563

Description

Description

We use SslStream to connect with a device which allows to be configured for mutual authentication with client certificates. For that we use AuthenticateAsClientAsync. After calling this method we check the IsMutuallyAuthenticated property the way it is mentioned in the docs:

...Check the IsMutuallyAuthenticated property to determine whether mutual authentication occurred.

see Remarks section

This works fine so far. But subsequent connect with authenticate to the same device (server) now results in that the property IsMutuallyAuthenticated returns true even when this is not correct anymore.

This wrong behavior comes from the caching which is done by the SslStream as it is mentioned in the docs:

Note:
The Framework caches SSL sessions as they are created and attempts to reuse a cached session for a new request, if possible. When attempting to reuse an SSL session, the Framework uses the first element of ClientCertificates (if there is one), or tries to reuse an anonymous sessions if ClientCertificates is empty.

see Remarks section

Reproduction Steps

  1. Connect to a server via SslStream which requires mutual authentication via client certificate.
  2. Call AuthenticateAsClientAsync and provide the client certificate
  3. Verify that IsMutuallyAuthenticated returns true
  4. Disconnect
  • Note: Keep the client running
  1. Restart and reconfigure the server so that it does not require a mutual authentication anymore
  2. Connect to a server via SslStream
  3. Call AuthenticateAsClientAsync and provide the client certificate
  4. Verify what IsMutuallyAuthenticated returns now (see Expected and Actual behavior)

Expected behavior

In step 8:
8. IsMutuallyAuthenticated should return false

Actual behavior

In step 8:
8. IsMutuallyAuthenticated returns true

Although a TLS 1.2 connection was established without mutual authentication.

Regression?

I can reproduce this issue with:

  • .NET 6
  • .NET 5
  • .NET Framework 4.8

Known Workarounds

This not-recommended workaround solves the issue:

  • Call the following method before starting connecting to the server.
private static void ClearCache()
{
    var sslAssembly = Assembly.GetAssembly(typeof(SslStream));
    var sslSessionCacheClass = sslAssembly.GetType("System.Net.Security.SslSessionsCache");
    var cachedCredsInfo = sslSessionCacheClass.GetField("s_cachedCreds", BindingFlags.NonPublic | BindingFlags.Static);
    var cachedCreds = cachedCredsInfo.GetValue(null);
    cachedCreds.GetType().GetMethod("Clear", BindingFlags.Public | BindingFlags.Instance).Invoke(cachedCreds, null);
}

Configuration

  • Windows 10 20H2

Other information

Maybe this is related: #65539

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions