flush CachedDirectoryStoreProvider on X509Store changes (#48149)
authorTomas Weinfurt <tweinfurt@yahoo.com>
Fri, 12 Feb 2021 04:38:30 +0000 (20:38 -0800)
committerGitHub <noreply@github.com>
Fri, 12 Feb 2021 04:38:30 +0000 (20:38 -0800)
* flush CachedDirectoryStoreProvider on X509Store changes

* reset _forceRefresh

src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs
src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs
src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedDirectoryStoreProvider.cs
src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ChainPal.cs
src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/DirectoryBasedStoreProvider.cs
src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509ChainProcessor.cs

index 445b68a..29039f5 100644 (file)
@@ -354,7 +354,7 @@ namespace System.Net.Security.Tests
         public async Task SslStream_ClientCertificate_SendsChain()
         {
             List<SslStream> streams = new List<SslStream>();
-            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 @@ namespace System.Net.Security.Tests
                 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 @@ namespace System.Net.Security.Tests
                 streams.Add(server);
             }
 
-            TestHelper.CleanupCertificates("SslStream_ClinetCertificate_SendsChain");
+            TestHelper.CleanupCertificates();
             clientCertificate.Dispose();
             foreach (X509Certificate c in clientChain)
             {
index 22ae213..200f8a8 100644 (file)
@@ -81,7 +81,7 @@ namespace System.Net.Security.Tests
 
         }
 
-        internal static void CleanupCertificates(string testName)
+        internal static void CleanupCertificates([CallerMemberName] string? testName = null)
         {
             string caName = $"O={testName}";
             try
index 5e46cfd..8c3727b 100644 (file)
@@ -22,6 +22,7 @@ namespace Internal.Cryptography.Pal
 
         private SafeX509StackHandle? _nativeCollection;
         private DateTime _loadLastWrite;
+        private bool _forceRefresh;
 
         internal CachedDirectoryStoreProvider(string storeName)
         {
@@ -29,13 +30,18 @@ namespace Internal.Cryptography.Pal
             _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 @@ namespace Internal.Cryptography.Pal
                     DirectoryInfo info = _storeDirectoryInfo;
 
                     if (ret == null ||
+                        _forceRefresh ||
                         elapsed >= s_assumeInvalidInterval ||
                         (info.Exists && info.LastWriteTimeUtc != _loadLastWrite))
                     {
@@ -65,6 +72,7 @@ namespace Internal.Cryptography.Pal
                         ret = newColl;
                         _nativeCollection = newColl;
                         _recheckStopwatch.Restart();
+                        _forceRefresh = false;
                     }
                 }
             }
index d32d8b5..29cdfa5 100644 (file)
@@ -23,6 +23,11 @@ namespace Internal.Cryptography.Pal
             return true;
         }
 
+        public static void FlushStores()
+        {
+            OpenSslX509ChainProcessor.FlushStores();
+        }
+
         public static IChainPal BuildChain(
             bool useMachineContext,
             ICertificatePal cert,
index b795622..0cf1cca 100644 (file)
@@ -118,6 +118,7 @@ namespace Internal.Cryptography.Pal
             try
             {
                 AddCertToStore(certPal);
+                ChainPal.FlushStores();
             }
             catch (CryptographicException)
             {
@@ -223,6 +224,7 @@ namespace Internal.Cryptography.Pal
                         }
 
                         File.Delete(currentFilename);
+                        ChainPal.FlushStores();
                     }
                 } while (currentFilename != null);
             }
index f43e6dd..345579e 100644 (file)
@@ -326,6 +326,13 @@ namespace Internal.Cryptography.Pal
             Interop.Crypto.X509StoreCtxCommitToChain(_storeCtx);
         }
 
+        internal static void FlushStores()
+        {
+            s_userRootStore.DoRefresh();
+            s_userPersonalStore.DoRefresh();
+            s_userIntermediateStore.DoRefresh();
+        }
+
         internal void ProcessRevocation(
             X509RevocationMode revocationMode,
             X509RevocationFlag revocationFlag)