--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Cryptography.X509Certificates.Tests
+{
+ /// <summary>
+ /// A type to extend the Dispose on X509Chain to also dispose all of the X509Certificate objects
+ /// in the ChainElements structure.
+ /// </summary>
+ internal sealed class ChainHolder : IDisposable
+ {
+ public X509Chain Chain { get; } = new X509Chain();
+
+ public void Dispose()
+ {
+ DisposeChainElements();
+
+ Chain.Dispose();
+ }
+
+ public void DisposeChainElements()
+ {
+ int count = Chain.ChainElements.Count;
+
+ for (int i = 0; i < count; i++)
+ {
+ Chain.ChainElements[i].Certificate.Dispose();
+ }
+ }
+ }
+}
using System.Collections.Generic;
using System.IO;
-using System.Linq;
-using Microsoft.Win32.SafeHandles;
using Xunit;
namespace System.Security.Cryptography.X509Certificates.Tests
using (var microsoftDotComIssuer = new X509Certificate2(TestData.MicrosoftDotComIssuerBytes))
using (var microsoftDotComRoot = new X509Certificate2(TestData.MicrosoftDotComRootBytes))
using (var unrelated = new X509Certificate2(TestData.DssCer))
+ using (var chainHolder = new ChainHolder())
{
- X509Chain chain = new X509Chain();
+ X509Chain chain = chainHolder.Chain;
chain.ChainPolicy.ExtraStore.Add(unrelated);
chain.ChainPolicy.ExtraStore.Add(microsoftDotComRoot);
public static void BuildChainExtraStoreUntrustedRoot()
{
using (var testCert = new X509Certificate2(Path.Combine("TestData", "test.pfx"), TestData.ChainPfxPassword))
+ using (ImportedCollection ic = Cert.Import(Path.Combine("TestData", "test.pfx"), TestData.ChainPfxPassword, X509KeyStorageFlags.DefaultKeySet))
+ using (var chainHolder = new ChainHolder())
{
- using (ImportedCollection ic = Cert.Import(Path.Combine("TestData", "test.pfx"), TestData.ChainPfxPassword, X509KeyStorageFlags.DefaultKeySet))
- {
- X509Certificate2Collection collection = ic.Collection;
+ X509Certificate2Collection collection = ic.Collection;
- X509Chain chain = new X509Chain();
- chain.ChainPolicy.ExtraStore.AddRange(collection);
- chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
- chain.ChainPolicy.VerificationTime = new DateTime(2015, 9, 22, 12, 25, 0);
+ X509Chain chain = chainHolder.Chain;
+ chain.ChainPolicy.ExtraStore.AddRange(collection);
+ chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
+ chain.ChainPolicy.VerificationTime = new DateTime(2015, 9, 22, 12, 25, 0);
- bool valid = chain.Build(testCert);
+ bool valid = chain.Build(testCert);
- Assert.False(valid);
- Assert.Contains(chain.ChainStatus, s => s.Status == X509ChainStatusFlags.UntrustedRoot);
- }
+ Assert.False(valid);
+ Assert.Contains(chain.ChainStatus, s => s.Status == X509ChainStatusFlags.UntrustedRoot);
}
}
using (var microsoftDotCom = new X509Certificate2(TestData.MicrosoftDotComSslCertBytes))
using (var microsoftDotComIssuer = new X509Certificate2(TestData.MicrosoftDotComIssuerBytes))
using (var microsoftDotComRoot = new X509Certificate2(TestData.MicrosoftDotComRootBytes))
+ using (var chainHolder = new ChainHolder())
{
- X509Chain chain = new X509Chain();
+ X509Chain chain = chainHolder.Chain;
chain.ChainPolicy.ExtraStore.Add(microsoftDotComIssuer);
chain.ChainPolicy.ExtraStore.Add(microsoftDotComRoot);
public static void BuildChain_WithApplicationPolicy_Match()
{
using (var msCer = new X509Certificate2(TestData.MsCertificate))
- using (X509Chain chain = new X509Chain())
+ using (var chainHolder = new ChainHolder())
{
+ X509Chain chain = chainHolder.Chain;
+
// Code Signing
chain.ChainPolicy.ApplicationPolicy.Add(new Oid("1.3.6.1.5.5.7.3.3"));
chain.ChainPolicy.VerificationTime = msCer.NotBefore.AddHours(2);
public static void BuildChain_WithApplicationPolicy_NoMatch()
{
using (var cert = new X509Certificate2(TestData.MsCertificate))
- using (X509Chain chain = new X509Chain())
+ using (var chainHolder = new ChainHolder())
{
+ X509Chain chain = chainHolder.Chain;
+
// Gibberish. (Code Signing + ".1")
chain.ChainPolicy.ApplicationPolicy.Add(new Oid("1.3.6.1.5.5.7.3.3.1"));
chain.ChainPolicy.VerificationFlags =
public static void BuildChain_WithCertificatePolicy_Match()
{
using (var cert = new X509Certificate2(TestData.CertWithPolicies))
- using (X509Chain chain = new X509Chain())
+ using (var chainHolder = new ChainHolder())
{
+ X509Chain chain = chainHolder.Chain;
+
// Code Signing
chain.ChainPolicy.CertificatePolicy.Add(new Oid("2.18.19"));
chain.ChainPolicy.VerificationFlags =
public static void BuildChain_WithCertificatePolicy_NoMatch()
{
using (var cert = new X509Certificate2(TestData.CertWithPolicies))
- using (X509Chain chain = new X509Chain())
+ using (var chainHolder = new ChainHolder())
{
+ X509Chain chain = chainHolder.Chain;
+
chain.ChainPolicy.CertificatePolicy.Add(new Oid("2.999"));
chain.ChainPolicy.VerificationFlags =
X509VerificationFlags.AllowUnknownCertificateAuthority;
public static void VerifyWithRevocation()
{
using (var cert = new X509Certificate2(Path.Combine("TestData", "MS.cer")))
- using (var onlineChain = new X509Chain())
- using (var offlineChain = new X509Chain())
+ using (var onlineChainHolder = new ChainHolder())
+ using (var offlineChainHolder = new ChainHolder())
{
+ X509Chain onlineChain = onlineChainHolder.Chain;
+ X509Chain offlineChain = offlineChainHolder.Chain;
+
onlineChain.ChainPolicy.VerificationFlags =
X509VerificationFlags.AllowUnknownCertificateAuthority;
using (var microsoftDotCom = new X509Certificate2(TestData.MicrosoftDotComSslCertBytes))
using (var microsoftDotComIssuer = new X509Certificate2(TestData.MicrosoftDotComIssuerBytes))
using (var microsoftDotComRoot = new X509Certificate2(TestData.MicrosoftDotComRootBytes))
- using (X509Chain chain = new X509Chain())
+ using (var chainHolder = new ChainHolder())
{
+ X509Chain chain = chainHolder.Chain;
+
chain.ChainPolicy.ExtraStore.Add(microsoftDotComRoot);
chain.ChainPolicy.ExtraStore.Add(microsoftDotComIssuer);
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
using (var microsoftDotCom = new X509Certificate2(TestData.MicrosoftDotComSslCertBytes))
using (var microsoftDotComIssuer = new X509Certificate2(TestData.MicrosoftDotComIssuerBytes))
using (var microsoftDotComRoot = new X509Certificate2(TestData.MicrosoftDotComRootBytes))
- using (X509Chain chain = new X509Chain())
+ using (var chainHolder = new ChainHolder())
{
+ X509Chain chain = chainHolder.Chain;
+
chain.ChainPolicy.ExtraStore.Add(microsoftDotComRoot);
chain.ChainPolicy.ExtraStore.Add(microsoftDotComIssuer);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
[Fact]
public static void SubjectKeyIdentifierExtension_PublicKey()
{
- PublicKey pk = new X509Certificate2(TestData.MsCertificate).PublicKey;
+ PublicKey pk;
+
+ using (var cert = new X509Certificate2(TestData.MsCertificate))
+ {
+ pk = cert.PublicKey;
+ }
+
X509SubjectKeyIdentifierExtension e = new X509SubjectKeyIdentifierExtension(pk, false);
byte[] rawData = e.RawData;
byte[] expectedDer,
string expectedIdentifier)
{
- PublicKey pk = new X509Certificate2(certBytes).PublicKey;
+ PublicKey pk;
+
+ using (var cert = new X509Certificate2(certBytes))
+ {
+ pk = cert.PublicKey;
+ }
X509SubjectKeyIdentifierExtension ext =
new X509SubjectKeyIdentifierExtension(pk, algorithm, critical);
{
X509Certificate2Collection col2 = col1.Find(findType, findValue, validOnly: false);
- Assert.Equal(0, col2.Count);
+ using (new ImportedCollection(col2))
+ {
+ Assert.Equal(0, col2.Count);
+ }
});
}
X509Certificate2Collection col2 =
col1.Find(findType, findValue, validOnly: false);
- Assert.Equal(1, col2.Count);
-
- byte[] serialNumber;
-
- using (X509Certificate2 match = col2[0])
+ using (new ImportedCollection(col2))
{
- Assert.Equal(expected, match);
- Assert.NotSame(expected, match);
+ Assert.Equal(1, col2.Count);
- // FriendlyName is Windows-only.
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ byte[] serialNumber;
+
+ using (X509Certificate2 match = col2[0])
{
- // Verify that the find result and original are linked, not just equal.
- match.FriendlyName = "HAHA";
- Assert.Equal("HAHA", expected.FriendlyName);
+ Assert.Equal(expected, match);
+ Assert.NotSame(expected, match);
+
+ // FriendlyName is Windows-only.
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ // Verify that the find result and original are linked, not just equal.
+ match.FriendlyName = "HAHA";
+ Assert.Equal("HAHA", expected.FriendlyName);
+ }
+
+ serialNumber = match.GetSerialNumber();
}
- serialNumber = match.GetSerialNumber();
+ // Check that disposing match didn't dispose expected
+ Assert.Equal(serialNumber, expected.GetSerialNumber());
}
-
- // Check that disposing match didn't dispose expected
- Assert.Equal(serialNumber, expected.GetSerialNumber());
}
[Theory]
X509Certificate2Collection col2 =
col1.Find(X509FindType.FindByThumbprint, msCer.Thumbprint, validOnly);
- // The certificate is expired. Unless we invent time travel
- // (or roll the computer clock back significantly), the validOnly
- // criteria should filter it out.
- //
- // This test runs both ways to make sure that the precondition of
- // "would match otherwise" is met (in the validOnly=false case it is
- // effectively the same as FindByValidThumbprint, but does less inspection)
- int expectedMatchCount = validOnly ? 0 : 1;
-
- Assert.Equal(expectedMatchCount, col2.Count);
-
- if (!validOnly)
+ using (new ImportedCollection(col2))
{
- // Double check that turning on validOnly doesn't prevent the cloning
- // behavior of Find.
- using (X509Certificate2 match = col2[0])
+ // The certificate is expired. Unless we invent time travel
+ // (or roll the computer clock back significantly), the validOnly
+ // criteria should filter it out.
+ //
+ // This test runs both ways to make sure that the precondition of
+ // "would match otherwise" is met (in the validOnly=false case it is
+ // effectively the same as FindByValidThumbprint, but does less inspection)
+ int expectedMatchCount = validOnly ? 0 : 1;
+
+ Assert.Equal(expectedMatchCount, col2.Count);
+
+ if (!validOnly)
{
- Assert.Equal(msCer, match);
- Assert.NotSame(msCer, match);
+ // Double check that turning on validOnly doesn't prevent the cloning
+ // behavior of Find.
+ using (X509Certificate2 match = col2[0])
+ {
+ Assert.Equal(msCer, match);
+ Assert.NotSame(msCer, match);
+ }
}
}
}
earliest - TimeSpan.FromSeconds(1),
validOnly: false);
- Assert.Equal(0, col2.Count);
+ using (new ImportedCollection(col2))
+ {
+ Assert.Equal(0, col2.Count);
+ }
});
}
latest + TimeSpan.FromSeconds(1),
validOnly: false);
- Assert.Equal(0, col2.Count);
+ using (new ImportedCollection(col2))
+ {
+ Assert.Equal(0, col2.Count);
+ }
});
}
noMatchTime,
validOnly: false);
- Assert.Equal(0, col2.Count);
+ using (new ImportedCollection(col2))
+ {
+ Assert.Equal(0, col2.Count);
+ }
});
}
matchTime,
validOnly: false);
- Assert.Equal(1, col2.Count);
+ using (new ImportedCollection(col2))
+ {
+ Assert.Equal(1, col2.Count);
+ }
});
}
noMatchTime,
validOnly: false);
- Assert.Equal(0, col2.Count);
+ using (new ImportedCollection(col2))
+ {
+ Assert.Equal(0, col2.Count);
+ }
});
}
matchTime,
validOnly: false);
- Assert.Equal(1, col2.Count);
+ using (new ImportedCollection(col2))
+ {
+ Assert.Equal(1, col2.Count);
+ }
});
}
noMatchTime,
validOnly: false);
- Assert.Equal(0, col2.Count);
+ using (new ImportedCollection(col2))
+ {
+ Assert.Equal(0, col2.Count);
+ }
});
}
X509Certificate2Collection results =
col1.Find(X509FindType.FindByApplicationPolicy, "1.3.6.1.5.5.7.3.3", false);
- Assert.Equal(2, results.Count);
-
- Assert.True(results.Contains(msCer));
- Assert.True(results.Contains(pfxCer));
-
- foreach (X509Certificate2 match in results)
+ using (new ImportedCollection(results))
{
- match.Dispose();
+ Assert.Equal(2, results.Count);
+
+ Assert.True(results.Contains(msCer));
+ Assert.True(results.Contains(pfxCer));
}
});
}
X509Certificate2Collection results =
col1.Find(X509FindType.FindByApplicationPolicy, "2.2", false);
- Assert.Equal(0, results.Count);
+ using (new ImportedCollection(results))
+ {
+ Assert.Equal(0, results.Count);
+ }
});
}
X509Certificate2Collection col1 = new X509Certificate2Collection(policyCert);
X509Certificate2Collection results = col1.Find(X509FindType.FindByCertificatePolicy, "2.999", false);
- Assert.Equal(0, results.Count);
+
+ using (new ImportedCollection(results))
+ {
+ Assert.Equal(0, results.Count);
+ }
}
}
X509Certificate2Collection col1 = new X509Certificate2Collection(templatedCert);
X509Certificate2Collection results = col1.Find(X509FindType.FindByTemplateName, "2.999", false);
- Assert.Equal(0, results.Count);
+
+ using (new ImportedCollection(results))
+ {
+ Assert.Equal(0, results.Count);
+ }
}
}
var coll = new X509Certificate2Collection { noKeyUsages, noKeyUsages2, keyUsages, };
X509Certificate2Collection results = coll.Find(X509FindType.FindByKeyUsage, matchCriteria, false);
- // The two certificates with no KeyUsages extension will always match, the real question is about the third.
- int matchCount = shouldMatch ? 3 : 2;
- Assert.Equal(matchCount, results.Count);
-
- if (shouldMatch)
+ using (new ImportedCollection(results))
{
- bool found = false;
+ // The two certificates with no KeyUsages extension will always match,
+ // the real question is about the third.
+ int matchCount = shouldMatch ? 3 : 2;
+ Assert.Equal(matchCount, results.Count);
- foreach (X509Certificate2 cert in results)
+ if (shouldMatch)
{
- if (keyUsages.Equals(cert))
+ bool found = false;
+
+ foreach (X509Certificate2 cert in results)
{
- Assert.NotSame(cert, keyUsages);
- found = true;
- break;
+ if (keyUsages.Equals(cert))
+ {
+ Assert.NotSame(cert, keyUsages);
+ found = true;
+ break;
+ }
}
- }
- Assert.True(found, "Certificate with key usages was found in the collection");
- }
- else
- {
- Assert.False(results.Contains(keyUsages), "KeyUsages certificate is not present in the collection");
+ Assert.True(found, "Certificate with key usages was found in the collection");
+ }
+ else
+ {
+ Assert.False(
+ results.Contains(keyUsages),
+ "KeyUsages certificate is not present in the collection");
+ }
}
}
}
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition="'$(Configuration)'==''">Windows_Debug</Configuration>
<ItemGroup>
<Compile Include="Cert.cs" />
<Compile Include="CertTests.cs" />
+ <Compile Include="ChainHolder.cs" />
<Compile Include="ChainTests.cs" />
<Compile Include="CollectionImportTests.cs" />
<Compile Include="CollectionTests.cs" />
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using (var microsoftDotComIssuer = new X509Certificate2(TestData.MicrosoftDotComIssuerBytes))
using (var microsoftDotComRoot = new X509Certificate2(TestData.MicrosoftDotComRootBytes))
using (var unrelated = new X509Certificate2(TestData.DssCer))
+ using (var chainHolder = new ChainHolder())
{
- X509Chain chain = new X509Chain();
+ X509Chain chain = chainHolder.Chain;
chain.ChainPolicy.ExtraStore.Add(unrelated);
chain.ChainPolicy.ExtraStore.Add(microsoftDotComRoot);
Assert.Equal(X509ChainStatusFlags.UntrustedRoot, chain.ChainStatus[0].Status);
}
+ chainHolder.DisposeChainElements();
+
chain.ChainPolicy.RevocationMode = X509RevocationMode.Offline;
valid = chain.Build(microsoftDotComIssuer);
File.WriteAllText(crlFile, MicrosoftDotComRootCrlPem, Encoding.ASCII);
+ chainHolder.DisposeChainElements();
+
valid = chain.Build(microsoftDotComIssuer);
Assert.True(valid, "Chain should build validly now");
Assert.Equal(initialErrorCount, chain.ChainStatus.Length);
using (X509Store storeClone = new X509Store(newName, store.Location))
{
storeClone.Open(OpenFlags.ReadWrite);
-
- X509Certificate2Collection storeCerts = store.Certificates;
- X509Certificate2Collection storeCloneCerts = storeClone.Certificates;
-
- Assert.Equal(
- storeCerts.OfType<X509Certificate2>(),
- storeCloneCerts.OfType<X509Certificate2>());
+ AssertEqualContents(store, storeClone);
store.Add(certC);
// The object was added to store, but should show up in both objects
// after re-reading the Certificates property
- storeCerts = store.Certificates;
- storeCloneCerts = storeClone.Certificates;
-
- Assert.Equal(
- storeCerts.OfType<X509Certificate2>(),
- storeCloneCerts.OfType<X509Certificate2>());
+ AssertEqualContents(store, storeClone);
// Now add one to storeClone to prove bidirectionality.
storeClone.Add(certD);
- storeCerts = store.Certificates;
- storeCloneCerts = storeClone.Certificates;
-
- Assert.Equal(
- storeCerts.OfType<X509Certificate2>(),
- storeCloneCerts.OfType<X509Certificate2>());
+ AssertEqualContents(store, storeClone);
}
}
});
}
-
+
+ private static void AssertEqualContents(X509Store storeA, X509Store storeB)
+ {
+ Assert.NotSame(storeA, storeB);
+
+ using (var storeATracker = new ImportedCollection(storeA.Certificates))
+ using (var storeBTracker = new ImportedCollection(storeB.Certificates))
+ {
+ X509Certificate2Collection storeACerts = storeATracker.Collection;
+ X509Certificate2Collection storeBCerts = storeBTracker.Collection;
+
+ Assert.Equal(storeACerts.OfType<X509Certificate2>(), storeBCerts.OfType<X509Certificate2>());
+ }
+ }
+
private static void RunX509StoreTest(Action<X509Store, string> testAction)
{
string certStoresFeaturePath = PersistedFiles.GetUserFeatureDirectory("cryptography", "x509stores");
{
store.Open(OpenFlags.ReadOnly);
- int certCount = store.Certificates.Count;
- Assert.InRange(certCount, MinimumThreshold, int.MaxValue);
+ using (var storeCerts = new ImportedCollection(store.Certificates))
+ {
+ int certCount = storeCerts.Collection.Count;
+ Assert.InRange(certCount, MinimumThreshold, int.MaxValue);
+ }
}
}
}