From 39ffe2cd8e4467633f229f23acdc39f8e7faa13a Mon Sep 17 00:00:00 2001 From: wfurt Date: Wed, 10 Feb 2021 19:40:12 -0800 Subject: [PATCH 1/2] flush CachedDirectoryStoreProvider on X509Store changes --- .../SslStreamNetworkStreamTest.cs | 16 +++------------- .../tests/FunctionalTests/TestHelper.cs | 2 +- .../Pal.Unix/CachedDirectoryStoreProvider.cs | 9 ++++++++- .../Internal/Cryptography/Pal.Unix/ChainPal.cs | 5 +++++ .../Pal.Unix/DirectoryBasedStoreProvider.cs | 2 ++ .../Pal.Unix/OpenSslX509ChainProcessor.cs | 7 +++++++ 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs index 445b68a67dcade..29039f5c76d0a7 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs @@ -354,7 +354,7 @@ public async Task SslStream_UntrustedCaWithCustomCallback_Throws(bool customCall public async Task SslStream_ClientCertificate_SendsChain() { List streams = new List(); - TestHelper.CleanupCertificates("SslStream_ClinetCertificate_SendsChain"); + TestHelper.CleanupCertificates(); (X509Certificate2 clientCertificate, X509Certificate2Collection clientChain) = TestHelper.GenerateCertificates("SslStream_ClinetCertificate_SendsChain", serverCertificate: false); using (X509Store store = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser)) { @@ -364,24 +364,14 @@ public async Task SslStream_ClientCertificate_SendsChain() store.Close(); } - // There is race between adding certificate to the store and building chain - // Make sure we can build chain before proceeding to ssl handshale using (var chain = new X509Chain()) { - int count = 25; chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.DisableCertificateDownloads = false; bool chainStatus = chain.Build(clientCertificate); - while (chain.ChainElements.Count != (clientChain.Count + 1) && count > 0) - { - Thread.Sleep(100); - count--; - chainStatus = chain.Build(clientCertificate); - } - // Verify we can construct full chain - Assert.True(chain.ChainElements.Count > clientChain.Count, "chain cannot be built"); + Assert.True(chain.ChainElements.Count >= clientChain.Count, "chain cannot be built"); } var clientOptions = new SslClientAuthenticationOptions() { TargetHost = "localhost", }; @@ -421,7 +411,7 @@ public async Task SslStream_ClientCertificate_SendsChain() streams.Add(server); } - TestHelper.CleanupCertificates("SslStream_ClinetCertificate_SendsChain"); + TestHelper.CleanupCertificates(); clientCertificate.Dispose(); foreach (X509Certificate c in clientChain) { diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs index 22ae213cf45347..200f8a8e4d68a1 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs @@ -81,7 +81,7 @@ internal static (NetworkStream ClientStream, NetworkStream ServerStream) GetConn } - internal static void CleanupCertificates(string testName) + internal static void CleanupCertificates([CallerMemberName] string? testName = null) { string caName = $"O={testName}"; try diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs index 5e46cfdf41498f..ccbd53274b43ce 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs @@ -22,6 +22,7 @@ internal sealed class CachedDirectoryStoreProvider private SafeX509StackHandle? _nativeCollection; private DateTime _loadLastWrite; + private bool _forceRefresh; internal CachedDirectoryStoreProvider(string storeName) { @@ -29,13 +30,18 @@ internal CachedDirectoryStoreProvider(string storeName) _storeDirectoryInfo = new DirectoryInfo(storePath); } + internal void DoRefresh() + { + _forceRefresh = true; + } + internal SafeX509StackHandle GetNativeCollection() { SafeX509StackHandle? ret = _nativeCollection; TimeSpan elapsed = _recheckStopwatch.Elapsed; - if (ret == null || elapsed >= s_lastWriteRecheckInterval) + if (ret == null || elapsed >= s_lastWriteRecheckInterval || _forceRefresh) { lock (_recheckStopwatch) { @@ -43,6 +49,7 @@ internal SafeX509StackHandle GetNativeCollection() DirectoryInfo info = _storeDirectoryInfo; if (ret == null || + _forceRefresh || elapsed >= s_assumeInvalidInterval || (info.Exists && info.LastWriteTimeUtc != _loadLastWrite)) { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainPal.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainPal.cs index d32d8b58c837da..29cdfa5f71cb72 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainPal.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainPal.cs @@ -23,6 +23,11 @@ public static bool ReleaseSafeX509ChainHandle(IntPtr handle) return true; } + public static void FlushStores() + { + OpenSslX509ChainProcessor.FlushStores(); + } + public static IChainPal BuildChain( bool useMachineContext, ICertificatePal cert, diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/DirectoryBasedStoreProvider.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/DirectoryBasedStoreProvider.cs index b795622eaa84c6..0cf1ccac56aec2 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/DirectoryBasedStoreProvider.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/DirectoryBasedStoreProvider.cs @@ -118,6 +118,7 @@ public void Add(ICertificatePal certPal) try { AddCertToStore(certPal); + ChainPal.FlushStores(); } catch (CryptographicException) { @@ -223,6 +224,7 @@ public void Remove(ICertificatePal certPal) } File.Delete(currentFilename); + ChainPal.FlushStores(); } } while (currentFilename != null); } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509ChainProcessor.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509ChainProcessor.cs index f43e6ddfdcda58..345579ea104c0b 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509ChainProcessor.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509ChainProcessor.cs @@ -326,6 +326,13 @@ internal void CommitToChain() Interop.Crypto.X509StoreCtxCommitToChain(_storeCtx); } + internal static void FlushStores() + { + s_userRootStore.DoRefresh(); + s_userPersonalStore.DoRefresh(); + s_userIntermediateStore.DoRefresh(); + } + internal void ProcessRevocation( X509RevocationMode revocationMode, X509RevocationFlag revocationFlag) From a2d36e860b826fe9ceacb3f665197cf51fe76244 Mon Sep 17 00:00:00 2001 From: wfurt Date: Wed, 10 Feb 2021 20:01:12 -0800 Subject: [PATCH 2/2] reset _forceRefresh --- .../Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs index ccbd53274b43ce..8c3727b98289d4 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs @@ -72,6 +72,7 @@ internal SafeX509StackHandle GetNativeCollection() ret = newColl; _nativeCollection = newColl; _recheckStopwatch.Restart(); + _forceRefresh = false; } } }