未验证 提交 d39232c0 编写于 作者: K Kevin Jones 提交者: GitHub

EmptyAiaResponseIsIgnored should use incomplete chain.

Since the certificate names were the same, different tests were
colliding with caches since they had the same certificate name.

In addition to the simple fix, this changes the test to build a partial
chain using two intermediates. The leaf's issuing intermediate is
added to the ExtraStore and the second intermediate is expected
to be fetched by AIA (and fail with an empty response).

This is to help coerce chain builders treat it as a partial chain,
and can actually make some progress, as opposed to the leaf being
treated as an invalid root.
上级 3473d30d
......@@ -820,8 +820,9 @@ private enum CertStatus
PkiOptions pkiOptions,
out RevocationResponder responder,
out CertificateAuthority rootAuthority,
out CertificateAuthority intermediateAuthority,
out CertificateAuthority[] intermediateAuthorities,
out X509Certificate2 endEntityCert,
int intermediateAuthorityCount,
string testName = null,
bool registerAuthorities = true,
bool pkiOptionsInSubject = false,
......@@ -841,14 +842,10 @@ private enum CertStatus
endEntityRevocationViaCrl || endEntityRevocationViaOcsp,
"At least one revocation mode is enabled");
if (extensions == null)
{
// default to client
extensions = new X509ExtensionCollection() { s_eeConstraints, s_eeKeyUsage, s_tlsClientEku };
}
extensions ??= new X509ExtensionCollection() { s_eeConstraints, s_eeKeyUsage, s_tlsClientEku };
using (RSA rootKey = RSA.Create(keySize))
using (RSA intermedKey = RSA.Create(keySize))
using (RSA eeKey = RSA.Create(keySize))
{
var rootReq = new CertificateRequest(
......@@ -882,15 +879,21 @@ private enum CertStatus
issuerRevocationViaCrl ? cdpUrl : null,
issuerRevocationViaOcsp ? ocspUrl : null);
CertificateAuthority issuingAuthority = rootAuthority;
intermediateAuthorities = new CertificateAuthority[intermediateAuthorityCount];
for (int intermediateIndex = 0; intermediateIndex < intermediateAuthorityCount; intermediateIndex++)
{
using RSA intermediateKey = RSA.Create(keySize);
// Don't dispose this, it's being transferred to the CertificateAuthority
X509Certificate2 intermedCert;
{
X509Certificate2 intermedPub = rootAuthority.CreateSubordinateCA(
BuildSubject("A Revocation Test CA", testName, pkiOptions, pkiOptionsInSubject),
intermedKey);
intermedCert = intermedPub.CopyWithPrivateKey(intermedKey);
X509Certificate2 intermedPub = issuingAuthority.CreateSubordinateCA(
BuildSubject($"A Revocation Test CA {intermediateIndex}", testName, pkiOptions, pkiOptionsInSubject),
intermediateKey);
intermedCert = intermedPub.CopyWithPrivateKey(intermediateKey);
intermedPub.Dispose();
}
......@@ -901,13 +904,17 @@ private enum CertStatus
cdpUrl = $"{responder.UriPrefix}crl/{intermedSkid.SubjectKeyIdentifier}.crl";
ocspUrl = $"{responder.UriPrefix}ocsp/{intermedSkid.SubjectKeyIdentifier}";
intermediateAuthority = new CertificateAuthority(
CertificateAuthority intermediateAuthority = new CertificateAuthority(
intermedCert,
issuerDistributionViaHttp ? certUrl : null,
endEntityRevocationViaCrl ? cdpUrl : null,
endEntityRevocationViaOcsp ? ocspUrl : null);
endEntityCert = intermediateAuthority.CreateEndEntity(
issuingAuthority = intermediateAuthority;
intermediateAuthorities[intermediateIndex] = intermediateAuthority;
}
endEntityCert = issuingAuthority.CreateEndEntity(
BuildSubject(subjectName ?? "A Revocation Test Cert", testName, pkiOptions, pkiOptionsInSubject),
eeKey,
extensions);
......@@ -918,9 +925,44 @@ private enum CertStatus
if (registerAuthorities)
{
responder.AddCertificateAuthority(rootAuthority);
responder.AddCertificateAuthority(intermediateAuthority);
foreach (CertificateAuthority authority in intermediateAuthorities)
{
responder.AddCertificateAuthority(authority);
}
}
}
internal static void BuildPrivatePki(
PkiOptions pkiOptions,
out RevocationResponder responder,
out CertificateAuthority rootAuthority,
out CertificateAuthority intermediateAuthority,
out X509Certificate2 endEntityCert,
string testName = null,
bool registerAuthorities = true,
bool pkiOptionsInSubject = false,
string subjectName = null,
int keySize = DefaultKeySize,
X509ExtensionCollection extensions = null)
{
BuildPrivatePki(
pkiOptions,
out responder,
out rootAuthority,
out CertificateAuthority[] intermediateAuthorities,
out endEntityCert,
intermediateAuthorityCount: 1,
testName: testName,
registerAuthorities: registerAuthorities,
pkiOptionsInSubject: pkiOptionsInSubject,
subjectName: subjectName,
keySize: keySize,
extensions: extensions);
intermediateAuthority = intermediateAuthorities.Single();
}
private static string BuildSubject(
string cn,
......
......@@ -16,21 +16,24 @@ public static void EmptyAiaResponseIsIgnored()
PkiOptions.AllRevocation,
out RevocationResponder responder,
out CertificateAuthority root,
out CertificateAuthority intermediate,
out CertificateAuthority[] intermediates,
out X509Certificate2 endEntity,
pkiOptionsInSubject: false);
intermediateAuthorityCount: 2,
pkiOptionsInSubject: false,
testName: nameof(EmptyAiaResponseIsIgnored));
using (responder)
using (root)
using (intermediate)
using (CertificateAuthority intermediate1 = intermediates[0])
using (CertificateAuthority intermediate2 = intermediates[1])
using (endEntity)
using (ChainHolder holder = new ChainHolder())
using (X509Certificate2 rootCert = root.CloneIssuerCert())
using (X509Certificate2 intermediateCert = intermediate.CloneIssuerCert())
using (X509Certificate2 intermediate2Cert = intermediate2.CloneIssuerCert())
{
responder.RespondEmpty = true;
X509Chain chain = holder.Chain;
chain.ChainPolicy.ExtraStore.Add(intermediate2Cert);
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
chain.ChainPolicy.VerificationTime = endEntity.NotBefore.AddMinutes(1);
chain.ChainPolicy.UrlRetrievalTimeout = DynamicRevocationTests.s_urlRetrievalLimit;
......@@ -39,6 +42,7 @@ public static void EmptyAiaResponseIsIgnored()
Assert.False(chain.Build(endEntity));
X509ChainStatusFlags chainFlags = chain.AllStatusFlags();
Assert.True(chainFlags.HasFlag(X509ChainStatusFlags.PartialChain), $"expected partial chain flags, got {chainFlags}");
Assert.Equal(2, chain.ChainElements.Count);
}
}
......@@ -51,7 +55,8 @@ public static void DisableAiaOptionWorks()
out CertificateAuthority root,
out CertificateAuthority intermediate,
out X509Certificate2 endEntity,
pkiOptionsInSubject: false);
pkiOptionsInSubject: false,
testName: nameof(DisableAiaOptionWorks));
using (responder)
using (root)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册