1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Diagnostics; 6 using System.IO; 7 using System.Runtime.InteropServices; 8 using System.Security.Authentication; 9 using System.Security.Cryptography.X509Certificates; 10 using System.Threading; 11 using Xunit; 12 13 namespace System.Net.Test.Common 14 { 15 public static partial class Configuration 16 { 17 public static partial class Certificates 18 { 19 private const string CertificatePassword = "testcertificate"; 20 private const string TestDataFolder = "TestData"; 21 22 private static Mutex m; 23 private const int MutexTimeout = 120 * 1000; 24 Certificates()25 static Certificates() 26 { 27 if (PlatformDetection.IsUap) 28 { 29 // UWP doesn't support Global mutexes. 30 m = new Mutex(false, "Local\\CoreFXTest.Configuration.Certificates.LoadPfxCertificate"); 31 } 32 else 33 { 34 m = new Mutex(false, "Global\\CoreFXTest.Configuration.Certificates.LoadPfxCertificate"); 35 } 36 } 37 GetServerCertificate()38 public static X509Certificate2 GetServerCertificate() => GetCertWithPrivateKey(GetServerCertificateCollection()); 39 GetClientCertificate()40 public static X509Certificate2 GetClientCertificate() => GetCertWithPrivateKey(GetClientCertificateCollection()); 41 GetNoEKUCertificate()42 public static X509Certificate2 GetNoEKUCertificate() => GetCertWithPrivateKey(GetNoEKUCertificateCollection()); 43 GetSelfSignedServerCertificate()44 public static X509Certificate2 GetSelfSignedServerCertificate() => GetCertWithPrivateKey(GetSelfSignedServerCertificateCollection()); 45 GetSelfSignedClientCertificate()46 public static X509Certificate2 GetSelfSignedClientCertificate() => GetCertWithPrivateKey(GetSelfSignedClientCertificateCollection()); 47 GetServerCertificateCollection()48 public static X509Certificate2Collection GetServerCertificateCollection() => GetCertificateCollection("testservereku.contoso.com.pfx"); 49 GetClientCertificateCollection()50 public static X509Certificate2Collection GetClientCertificateCollection() => GetCertificateCollection("testclienteku.contoso.com.pfx"); 51 GetNoEKUCertificateCollection()52 public static X509Certificate2Collection GetNoEKUCertificateCollection() => GetCertificateCollection("testnoeku.contoso.com.pfx"); 53 GetSelfSignedServerCertificateCollection()54 public static X509Certificate2Collection GetSelfSignedServerCertificateCollection() => GetCertificateCollection("testselfsignedservereku.contoso.com.pfx"); 55 GetSelfSignedClientCertificateCollection()56 public static X509Certificate2Collection GetSelfSignedClientCertificateCollection() => GetCertificateCollection("testselfsignedclienteku.contoso.com.pfx"); 57 GetCertificateCollection(string certificateFileName)58 private static X509Certificate2Collection GetCertificateCollection(string certificateFileName) 59 { 60 // On Windows, .Net Core applications should not import PFX files in parallel to avoid a known system-level race condition. 61 // This bug results in corrupting the X509Certificate2 certificate state. 62 try 63 { 64 Assert.True(m.WaitOne(MutexTimeout), "Cannot acquire the global certificate mutex."); 65 66 var certCollection = new X509Certificate2Collection(); 67 certCollection.Import(Path.Combine(TestDataFolder, certificateFileName), CertificatePassword, X509KeyStorageFlags.DefaultKeySet); 68 69 return certCollection; 70 } 71 catch (Exception ex) 72 { 73 Debug.Fail(nameof(Configuration.Certificates.GetCertificateCollection) + " threw " + ex.ToString()); 74 throw; 75 } 76 finally 77 { 78 m.ReleaseMutex(); 79 } 80 } 81 GetCertWithPrivateKey(X509Certificate2Collection certCollection)82 private static X509Certificate2 GetCertWithPrivateKey(X509Certificate2Collection certCollection) 83 { 84 X509Certificate2 certificate = null; 85 86 foreach (X509Certificate2 c in certCollection) 87 { 88 if (certificate == null && c.HasPrivateKey) 89 { 90 certificate = c; 91 } 92 else 93 { 94 c.Dispose(); 95 } 96 } 97 98 Assert.NotNull(certificate); 99 return certificate; 100 } 101 } 102 } 103 } 104