Commit 4458a357 authored by Adam Langley's avatar Adam Langley

crypto/x509: parse multiple URLs in a single CRLDP.

Previously we would only extract a single URL from a given CRLDP, but
https://tools.ietf.org/html/rfc5280#section-4.2.1.13 permits multiple
URLs for a single distribution point.

Fixes #23403

Change-Id: I2eaed1537df02d0627db1b86bcd9c94506236bea
Reviewed-on: https://go-review.googlesource.com/87299
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 6631f227
......@@ -984,7 +984,7 @@ type distributionPoint struct {
}
type distributionPointName struct {
FullName asn1.RawValue `asn1:"optional,tag:0"`
FullName []asn1.RawValue `asn1:"optional,tag:0"`
RelativeName pkix.RDNSequence `asn1:"optional,tag:1"`
}
......@@ -1466,20 +1466,14 @@ func parseCertificate(in *certificate) (*Certificate, error) {
for _, dp := range cdp {
// Per RFC 5280, 4.2.1.13, one of distributionPoint or cRLIssuer may be empty.
if len(dp.DistributionPoint.FullName.Bytes) == 0 {
if len(dp.DistributionPoint.FullName) == 0 {
continue
}
var n asn1.RawValue
if _, err := asn1.Unmarshal(dp.DistributionPoint.FullName.Bytes, &n); err != nil {
return nil, err
}
// Trailing data after the fullName is
// allowed because other elements of
// the SEQUENCE can appear.
if n.Tag == 6 {
out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(n.Bytes))
for _, fullName := range dp.DistributionPoint.FullName {
if fullName.Tag == 6 {
out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(fullName.Bytes))
}
}
}
......@@ -1946,11 +1940,11 @@ func buildExtensions(template *Certificate, subjectIsEmpty bool, authorityKeyId
var crlDp []distributionPoint
for _, name := range template.CRLDistributionPoints {
rawFullName, _ := asn1.Marshal(asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)})
dp := distributionPoint{
DistributionPoint: distributionPointName{
FullName: asn1.RawValue{Tag: 0, Class: 2, IsCompound: true, Bytes: rawFullName},
FullName: []asn1.RawValue{
asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)},
},
},
}
crlDp = append(crlDp, dp)
......
......@@ -1891,3 +1891,58 @@ func TestEmptySubject(t *testing.T) {
t.Fatal("SAN extension is missing")
}
// multipleURLsInCRLDPPEM contains two URLs in a single CRL DistributionPoint
// structure. It is taken from https://crt.sh/?id=12721534.
const multipleURLsInCRLDPPEM = `
-----BEGIN CERTIFICATE-----
MIIF4TCCBMmgAwIBAgIQc+6uFePfrahUGpXs8lhiTzANBgkqhkiG9w0BAQsFADCB
8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy
dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1
YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3
dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh
IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD
LUFDQzAeFw0xNDA5MTgwODIxMDBaFw0zMDA5MTgwODIxMDBaMIGGMQswCQYDVQQG
EwJFUzEzMDEGA1UECgwqQ09OU09SQ0kgQURNSU5JU1RSQUNJTyBPQkVSVEEgREUg
Q0FUQUxVTllBMSowKAYDVQQLDCFTZXJ2ZWlzIFDDumJsaWNzIGRlIENlcnRpZmlj
YWNpw7MxFjAUBgNVBAMMDUVDLUNpdXRhZGFuaWEwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDFkHPRZPZlXTWZ5psJhbS/Gx+bxcTpGrlVQHHtIkgGz77y
TA7UZUFb2EQMncfbOhR0OkvQQn1aMvhObFJSR6nI+caf2D+h/m/InMl1MyH3S0Ak
YGZZsthnyC6KxqK2A/NApncrOreh70ULkQs45aOKsi1kR1W0zE+iFN+/P19P7AkL
Rl3bXBCVd8w+DLhcwRrkf1FCDw6cEqaFm3cGgf5cbBDMaVYAweWTxwBZAq2RbQAW
jE7mledcYghcZa4U6bUmCBPuLOnO8KMFAvH+aRzaf3ws5/ZoOVmryyLLJVZ54peZ
OwnP9EL4OuWzmXCjBifXR2IAblxs5JYj57tls45nAgMBAAGjggHaMIIB1jASBgNV
HRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUC2hZPofI
oxUa4ECCIl+fHbLFNxUwHwYDVR0jBBgwFoAUoMOLRKo3pUW/l4Ba0fF4opvpXY0w
gdYGA1UdIASBzjCByzCByAYEVR0gADCBvzAxBggrBgEFBQcCARYlaHR0cHM6Ly93
d3cuYW9jLmNhdC9DQVRDZXJ0L1JlZ3VsYWNpbzCBiQYIKwYBBQUHAgIwfQx7QXF1
ZXN0IGNlcnRpZmljYXQgw6lzIGVtw6hzIMO6bmljYSBpIGV4Y2x1c2l2YW1lbnQg
YSBFbnRpdGF0cyBkZSBDZXJ0aWZpY2FjacOzLiBWZWdldSBodHRwczovL3d3dy5h
b2MuY2F0L0NBVENlcnQvUmVndWxhY2lvMDMGCCsGAQUFBwEBBCcwJTAjBggrBgEF
BQcwAYYXaHR0cDovL29jc3AuY2F0Y2VydC5jYXQwYgYDVR0fBFswWTBXoFWgU4Yn
aHR0cDovL2Vwc2NkLmNhdGNlcnQubmV0L2NybC9lYy1hY2MuY3JshihodHRwOi8v
ZXBzY2QyLmNhdGNlcnQubmV0L2NybC9lYy1hY2MuY3JsMA0GCSqGSIb3DQEBCwUA
A4IBAQChqFTjlAH5PyIhLjLgEs68CyNNC1+vDuZXRhy22TI83JcvGmQrZosPvVIL
PsUXx+C06Pfqmh48Q9S89X9K8w1SdJxP/rZeGEoRiKpwvQzM4ArD9QxyC8jirxex
3Umg9Ai/sXQ+1lBf6xw4HfUUr1WIp7pNHj0ZWLo106urqktcdeAFWme+/klis5fu
labCSVPuT/QpwakPrtqOhRms8vgpKiXa/eLtL9ZiA28X/Mker0zlAeTA7Z7uAnp6
oPJTlZu1Gg1ZDJueTWWsLlO+P+Wzm3MRRIbcgdRzm4mdO7ubu26SzX/aQXDhuih+
eVxXDTCfs7GUlxnjOp5j559X/N0A
-----END CERTIFICATE-----
`
func TestMultipleURLsInCRLDP(t *testing.T) {
block, _ := pem.Decode([]byte(multipleURLsInCRLDPPEM))
cert, err := ParseCertificate(block.Bytes)
if err != nil {
t.Fatalf("failed to parse certificate: %s", err)
}
want := []string{
"http://epscd.catcert.net/crl/ec-acc.crl",
"http://epscd2.catcert.net/crl/ec-acc.crl",
}
if got := cert.CRLDistributionPoints; !reflect.DeepEqual(got, want) {
t.Errorf("CRL distribution points = %#v, want #%v", got, want)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment