public static void AiaFetchDelayed() { CertificateAuthority.BuildPrivatePki( PkiOptions.OcspEverywhere, out RevocationResponder responder, out CertificateAuthority rootAuthority, out CertificateAuthority intermediateAuthority, out X509Certificate2 endEntityCert, nameof(AiaFetchDelayed)); using (responder) using (rootAuthority) using (intermediateAuthority) using (endEntityCert) using (ChainHolder holder = new ChainHolder()) using (X509Certificate2 rootCert = rootAuthority.CloneIssuerCert()) using (X509Certificate2 intermediateCert = intermediateAuthority.CloneIssuerCert()) { TimeSpan delay = TimeSpan.FromSeconds(1); X509Chain chain = holder.Chain; responder.ResponseDelay = delay; responder.DelayedActions = RevocationResponder.DelayedActionsFlag.All; chain.ChainPolicy.UrlRetrievalTimeout = TimeSpan.FromSeconds(15); chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; chain.ChainPolicy.CustomTrustStore.Add(rootCert); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; Stopwatch watch = Stopwatch.StartNew(); Assert.True( Retry(() => { watch.Restart(); return(chain.Build(endEntityCert)); }), GetFlags(chain, endEntityCert.Thumbprint).ToString()); watch.Stop(); Assert.True(watch.Elapsed >= delay, $"watch.Elapsed: {watch.Elapsed}"); } }
public static void RevocationCheckingNegativeTimeout(PkiOptions pkiOptions) { RetryHelper.Execute(() => { CertificateAuthority.BuildPrivatePki( pkiOptions, out RevocationResponder responder, out CertificateAuthority rootAuthority, out CertificateAuthority intermediateAuthority, out X509Certificate2 endEntityCert, nameof(RevocationCheckingNegativeTimeout)); using (responder) using (rootAuthority) using (intermediateAuthority) using (endEntityCert) using (ChainHolder holder = new ChainHolder()) using (X509Certificate2 rootCert = rootAuthority.CloneIssuerCert()) using (X509Certificate2 intermediateCert = intermediateAuthority.CloneIssuerCert()) { // Delay is more than the 15 second default. TimeSpan delay = TimeSpan.FromSeconds(25); X509Chain chain = holder.Chain; responder.ResponseDelay = delay; responder.DelayedActions = DelayedActionsFlag.All; chain.ChainPolicy.UrlRetrievalTimeout = TimeSpan.FromMinutes(-1); chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; chain.ChainPolicy.CustomTrustStore.Add(rootCert); chain.ChainPolicy.ExtraStore.Add(intermediateCert); chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EndCertificateOnly; chain.ChainPolicy.DisableCertificateDownloads = true; Assert.True(chain.Build(endEntityCert), $"chain.Build; Chain status: {chain.AllStatusFlags()}"); } }); }
public static void AiaFetchTimeout() { CertificateAuthority.BuildPrivatePki( PkiOptions.AllRevocation, out RevocationResponder responder, out CertificateAuthority rootAuthority, out CertificateAuthority intermediateAuthority, out X509Certificate2 endEntityCert, nameof(AiaFetchTimeout)); using (responder) using (rootAuthority) using (intermediateAuthority) using (endEntityCert) using (ChainHolder holder = new ChainHolder()) using (X509Certificate2 rootCert = rootAuthority.CloneIssuerCert()) using (X509Certificate2 intermediateCert = intermediateAuthority.CloneIssuerCert()) { TimeSpan delay = TimeSpan.FromSeconds(10); X509Chain chain = holder.Chain; responder.ResponseDelay = delay; responder.DelayedActions = DelayedActionsFlag.All; chain.ChainPolicy.UrlRetrievalTimeout = TimeSpan.FromSeconds(2); chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; chain.ChainPolicy.CustomTrustStore.Add(rootCert); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; Assert.False(chain.Build(endEntityCert), "chain.Build"); const X509ChainStatusFlags ExpectedFlags = X509ChainStatusFlags.PartialChain; X509ChainStatusFlags eeFlags = GetFlags(chain, endEntityCert.Thumbprint); Assert.Equal(ExpectedFlags, eeFlags); } }
public static void RevocationCheckingTimeoutFallbackToOther(DelayedActionsFlag delayFlags) { RetryHelper.Execute(() => { CertificateAuthority.BuildPrivatePki( PkiOptions.AllRevocation, out RevocationResponder responder, out CertificateAuthority rootAuthority, out CertificateAuthority intermediateAuthority, out X509Certificate2 endEntityCert, nameof(RevocationCheckingTimeoutFallbackToOther)); using (responder) using (rootAuthority) using (intermediateAuthority) using (endEntityCert) using (ChainHolder holder = new ChainHolder()) using (X509Certificate2 rootCert = rootAuthority.CloneIssuerCert()) using (X509Certificate2 intermediateCert = intermediateAuthority.CloneIssuerCert()) { X509Chain chain = holder.Chain; responder.ResponseDelay = TimeSpan.FromSeconds(8); responder.DelayedActions = delayFlags; chain.ChainPolicy.UrlRetrievalTimeout = TimeSpan.FromSeconds(4); chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; chain.ChainPolicy.CustomTrustStore.Add(rootCert); chain.ChainPolicy.ExtraStore.Add(intermediateCert); chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EndCertificateOnly; chain.ChainPolicy.DisableCertificateDownloads = true; Assert.True(chain.Build(endEntityCert), $"chain.Build; Chain status: {chain.AllStatusFlags()}"); } }); }
public static void DisableAiaOptionWorks() { CertificateAuthority.BuildPrivatePki( PkiOptions.AllRevocation, out RevocationResponder responder, out CertificateAuthority root, out CertificateAuthority intermediate, out X509Certificate2 endEntity, pkiOptionsInSubject: false); using (responder) using (root) using (intermediate) using (endEntity) using (ChainHolder holder = new ChainHolder()) using (X509Certificate2 rootCert = root.CloneIssuerCert()) using (X509Certificate2 intermediateCert = intermediate.CloneIssuerCert()) using (var cuCaStore = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser)) { cuCaStore.Open(OpenFlags.ReadWrite); X509Chain chain = holder.Chain; chain.ChainPolicy.DisableCertificateDownloads = true; chain.ChainPolicy.CustomTrustStore.Add(rootCert); chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; chain.ChainPolicy.VerificationTime = endEntity.NotBefore.AddMinutes(1); chain.ChainPolicy.UrlRetrievalTimeout = DynamicRevocationTests.s_urlRetrievalLimit; Assert.False(chain.Build(endEntity), "Chain build with no intermediate, AIA disabled"); // If a previous run of this test leaves contamination in the CU\CA store on Windows // the Windows chain engine will match the bad issuer and report NotSignatureValid instead // of PartialChain. X509ChainStatusFlags chainFlags = chain.AllStatusFlags(); if (chainFlags.HasFlag(X509ChainStatusFlags.NotSignatureValid)) { Assert.Equal(3, chain.ChainElements.Count); foreach (X509Certificate2 storeCert in cuCaStore.Certificates) { if (storeCert.Subject.Equals(intermediateCert.Subject)) { cuCaStore.Remove(storeCert); } storeCert.Dispose(); } holder.DisposeChainElements(); // Try again, with no caching side effect. Assert.False(chain.Build(endEntity), "Chain build 2 with no intermediate, AIA disabled"); } Assert.Equal(1, chain.ChainElements.Count); Assert.Contains(X509ChainStatusFlags.PartialChain, chain.ChainStatus.Select(s => s.Status)); holder.DisposeChainElements(); // macOS doesn't like our revocation responder, so disable revocation checks there. if (PlatformDetection.IsOSX) { chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; } chain.ChainPolicy.ExtraStore.Add(intermediateCert); Assert.True(chain.Build(endEntity), "Chain build with intermediate, AIA disabled"); Assert.Equal(3, chain.ChainElements.Count); Assert.Equal(X509ChainStatusFlags.NoError, chain.AllStatusFlags()); holder.DisposeChainElements(); chain.ChainPolicy.DisableCertificateDownloads = false; chain.ChainPolicy.ExtraStore.Clear(); Assert.True(chain.Build(endEntity), "Chain build with no intermediate, AIA enabled"); Assert.Equal(3, chain.ChainElements.Count); Assert.Equal(X509ChainStatusFlags.NoError, chain.AllStatusFlags()); cuCaStore.Remove(intermediateCert); } }