-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Client certs with HttpClient on Windows prevents X509Certificate2 cleanup #101090
Comments
Tagging subscribers to this area: @dotnet/ncl |
Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones |
In this specific case, the certificate seems to be rooted in the SslSessions cache
The same thing can be reproduced with plain SslStream. However, client.badssl.com sends trusted issuers list which we use to filter out certificates provided by the stream.AuthenticateAsClient(new SslClientAuthenticationOptions
{
- ClientCertificates = new X509CertificateCollection { cert },
+ LocalCertificateSelectionCallback = delegate { return cert; },
TargetHost = TargetHost,
}); That being said, the certificate instance is rooted because of runtime/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs Lines 229 to 238 in ae184d5
which was part of #79898 |
The only place where runtime/src/libraries/System.Net.Security/src/System/Net/CertificateValidationPal.Windows.cs Lines 93 to 109 in d64c653
since the actual value is not used anywhere, I think we might just switch to a cc @wfurt. |
Aside from the specific issue, is there some good way how to cleanup the stranded keys @bartonjs ? |
There is no universal way to clean up the keys. Keys can exist independent of certificates (this example makes a bare key... then matches it to a certificate); so it's not possible to prove whether deleting any of the files would break some later use of them.
Yep. It's a "well-known" (by at least a few people) problem that can occur when EphemeralKeySet isn't a viable loading option (which is mostly just with SslStream). But the occasional file getting left behind is less bad than all of them. |
Reopening for backport, the issue exists in .NET 6.0+ releases since this February (as it was caused partly by a fix to |
Possible workaround should be cleaning the Type type = Type.GetType("System.Net.Security.SslSessionsCache, System.Net.Security");
FieldInfo field = type.GetField("s_cachedCreds", BindingFlags.NonPublic | BindingFlags.Static);
IDictionary cache = (IDictionary)field.GetValue(null);
foreach (IDisposable value in cache.Values)
{
value.Dispose();
}
cache.Clear(); |
Closing since fixes were backported to 6.0 and 8.0 (to be released mid June) |
Due to Windows S/Channel requirements, TLS server and TLS client certificates have to have key files on disk for SslStream to make use of them. Because filling the key storage directories with discarded data is bad, a certificate imported from a PFX blob/file will delete the "temporary" key file when the SafeHandle that powers it is released.
This cleanup works on certificates used without networking, and works with direct usage of SslStream; but when used in conjunction with HttpClient the certificate's SafeHandle ends up in state 6 (Disposed, but has an outstanding reference count of 1). In my debugging I was able to track this back to a SafeFreeCredentials_SECURITY instance that was also in state 6; but I wasn't able to go back farther.
This function demonstrates that HttpClient is involved in the minimal repro. It must, of course, be run on Windows.
When run on my machine just now, it prints:
Ignoring the HTTP 400 failure, what the test shows is:
GC.Collect()
andGC.WaitForPendingFinalizers()
, run after the repro function has exited, does not result in successful cleanup. So either there's an unbalanced AddRef/Release, or the release is pending on a rooted object somewhere.This state of affairs is causing trouble for hosted program models that execute with a very small user profile directory quota... it is filling up the key storage drive and preventing further program executions.
The text was updated successfully, but these errors were encountered: