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