Skip to content

Commit

Permalink
Ignore 0-byte responses from AIA fetch.
Browse files Browse the repository at this point in the history
When fetching a certificate with AIA, we should ignore responses that
are zero bytes in length. A zero-byte value passed to X509Certificate2
will create a default certificate with a null PAL. This was being
passed in to the OpenSSL chain builder, and would pass in a null handle
for the certificate.
  • Loading branch information
vcsjones authored Jul 6, 2020
1 parent c8a9942 commit ac8fe0d
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ private readonly Dictionary<string, CertificateAuthority> _crlPaths

public string UriPrefix { get; }

public bool RespondEmpty { get; set; }

private RevocationResponder(HttpListener listener, string uriPrefix)
{
_listener = listener;
Expand Down Expand Up @@ -133,7 +135,7 @@ internal void HandleRequest(HttpListenerContext context)
catch (Exception)
{
}

return;
}

Expand All @@ -159,7 +161,7 @@ private void HandleRequest(HttpListenerContext context, ref bool responded)

if (_aiaPaths.TryGetValue(url, out authority))
{
byte[] certData = authority.GetCertData();
byte[] certData = RespondEmpty ? Array.Empty<byte>() : authority.GetCertData();

responded = true;
context.Response.StatusCode = 200;
Expand All @@ -171,7 +173,7 @@ private void HandleRequest(HttpListenerContext context, ref bool responded)

if (_crlPaths.TryGetValue(url, out authority))
{
byte[] crl = authority.GetCrl();
byte[] crl = RespondEmpty ? Array.Empty<byte>() : authority.GetCrl();

responded = true;
context.Response.StatusCode = 200;
Expand Down Expand Up @@ -208,7 +210,7 @@ private void HandleRequest(HttpListenerContext context, ref bool responded)
return;
}

byte[] ocspResponse = authority.BuildOcspResponse(certId, nonce);
byte[] ocspResponse = RespondEmpty ? Array.Empty<byte>() : authority.BuildOcspResponse(certId, nonce);

responded = true;
context.Response.StatusCode = 200;
Expand All @@ -234,7 +236,7 @@ private void HandleRequest(HttpListenerContext context, ref bool responded)
internal static RevocationResponder CreateAndListen()
{
HttpListener listener = OpenListener(out string uriPrefix);

RevocationResponder responder = new RevocationResponder(listener, uriPrefix);
responder.HandleRequests();
return responder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ internal static class CertificateAssetDownloader
{
byte[]? data = DownloadAsset(uri, ref remainingDownloadTime);

if (data == null)
if (data == null || data.Length == 0)
{
return null;
}

try
{
return new X509Certificate2(data);
X509Certificate2 certificate = new X509Certificate2(data);
certificate.ThrowIfInvalid();
return certificate;
}
catch (CryptographicException)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,38 @@ namespace System.Security.Cryptography.X509Certificates.Tests.RevocationTests
{
public static class AiaTests
{
[Fact]
public static void EmptyAiaResponseIsIgnored()
{
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())
{
responder.RespondEmpty = true;

X509Chain chain = holder.Chain;
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
chain.ChainPolicy.VerificationTime = endEntity.NotBefore.AddMinutes(1);
chain.ChainPolicy.UrlRetrievalTimeout = DynamicRevocationTests.s_urlRetrievalLimit;
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;

Assert.False(chain.Build(endEntity));
Assert.True(chain.AllStatusFlags().HasFlag(X509ChainStatusFlags.PartialChain), "expected partial chain");
}
}

[Fact]
public static void DisableAiaOptionWorks()
{
Expand Down

0 comments on commit ac8fe0d

Please sign in to comment.