Skip to content

Commit

Permalink
crypto/x509: implement policy validation
Browse files Browse the repository at this point in the history
Implement support for parsing the various policy related extensions,
and for validating the policy graph for chains.

Policy validation is only run if VerifyOptions.CertificatePolicies is
set. Policy validation is run after chains are built. If the computed
policy graph for a chain is invalid, the chain is removed from the set
of returned chains.

This implements the RFC 5280 algorithm as updated by
RFC 9618 [0].

Fixes #68484

[0] https://www.rfc-editor.org/rfc/rfc9618.html

Change-Id: I576432a47ddc404cba966c2b1995365944b8bd26
Reviewed-on: https://go-review.googlesource.com/c/go/+/628616
Auto-Submit: Roland Shoemaker <[email protected]>
Reviewed-by: Filippo Valsorda <[email protected]>
Reviewed-by: Damien Neil <[email protected]>
Reviewed-by: Daniel McCarney <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
rolandshoemaker authored and gopherbot committed Nov 22, 2024
1 parent e06e29b commit e8d9561
Show file tree
Hide file tree
Showing 37 changed files with 1,386 additions and 53 deletions.
13 changes: 13 additions & 0 deletions api/next/68484.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pkg crypto/x509, type Certificate struct, InhibitAnyPolicy int #68484
pkg crypto/x509, type Certificate struct, InhibitAnyPolicyZero bool #68484
pkg crypto/x509, type Certificate struct, InhibitPolicyMapping int #68484
pkg crypto/x509, type Certificate struct, InhibitPolicyMappingZero bool #68484
pkg crypto/x509, type Certificate struct, PolicyMappings []PolicyMapping #68484
pkg crypto/x509, type Certificate struct, RequireExplicitPolicy int #68484
pkg crypto/x509, type Certificate struct, RequireExplicitPolicyZero bool #68484
pkg crypto/x509, type PolicyMapping struct #68484
pkg crypto/x509, type PolicyMapping struct, IssuerDomainPolicy OID #68484
pkg crypto/x509, type PolicyMapping struct, SubjectDomainPolicy OID #68484
pkg crypto/x509, type VerifyOptions struct, CertificatePolicies []OID #68484
pkg crypto/x509, const NoValidChains = 10 #68484
pkg crypto/x509, const NoValidChains InvalidReason #68484
5 changes: 5 additions & 0 deletions doc/next/6-stdlib/99-minor/crypto/x509/68484.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[Certificate.Verify] now supports policy validation, as defined by RFC 5280 and
RFC 9618. In order to enable policy validation,
[VerifyOptions.CertificatePolicies] must be set to an acceptable set of policy
[OIDs]. When enabled, only certificate chains with valid policy graphs will be
returned from [Certificate.Verify].
63 changes: 27 additions & 36 deletions src/crypto/x509/oid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,12 @@ func TestOIDEqual(t *testing.T) {
oid2 OID
eq bool
}{
{oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: mustNewOIDFromInts(t, []uint64{1, 2, 3}), eq: true},
{oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: mustNewOIDFromInts(t, []uint64{1, 2, 4}), eq: false},
{oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: mustNewOIDFromInts(t, []uint64{1, 2, 3, 4}), eq: false},
{oid: mustNewOIDFromInts(t, []uint64{2, 33, 22}), oid2: mustNewOIDFromInts(t, []uint64{2, 33, 23}), eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: mustNewOIDFromInts([]uint64{1, 2, 3}), eq: true},
{oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: mustNewOIDFromInts([]uint64{1, 2, 4}), eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: mustNewOIDFromInts([]uint64{1, 2, 3, 4}), eq: false},
{oid: mustNewOIDFromInts([]uint64{2, 33, 22}), oid2: mustNewOIDFromInts([]uint64{2, 33, 23}), eq: false},
{oid: OID{}, oid2: OID{}, eq: true},
{oid: OID{}, oid2: mustNewOIDFromInts(t, []uint64{2, 33, 23}), eq: false},
{oid: OID{}, oid2: mustNewOIDFromInts([]uint64{2, 33, 23}), eq: false},
}

for _, tt := range cases {
Expand Down Expand Up @@ -277,32 +277,32 @@ func TestOIDEqualASN1OID(t *testing.T) {
oid2 asn1.ObjectIdentifier
eq bool
}{
{oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 3}, eq: true},
{oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 4}, eq: false},
{oid: mustNewOIDFromInts(t, []uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 3, 4}, eq: false},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, 22}), oid2: asn1.ObjectIdentifier{1, 33, 23}, eq: false},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, 23}), oid2: asn1.ObjectIdentifier{1, 33, 22}, eq: false},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, 127}), oid2: asn1.ObjectIdentifier{1, 33, 127}, eq: true},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 127}, eq: false},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 128}, eq: true},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, 129}), oid2: asn1.ObjectIdentifier{1, 33, 129}, eq: true},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 129}, eq: false},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, 129}), oid2: asn1.ObjectIdentifier{1, 33, 128}, eq: false},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, 255}), oid2: asn1.ObjectIdentifier{1, 33, 255}, eq: true},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, 256}), oid2: asn1.ObjectIdentifier{1, 33, 256}, eq: true},
{oid: mustNewOIDFromInts(t, []uint64{2, 33, 257}), oid2: asn1.ObjectIdentifier{2, 33, 256}, eq: false},
{oid: mustNewOIDFromInts(t, []uint64{2, 33, 256}), oid2: asn1.ObjectIdentifier{2, 33, 257}, eq: false},

{oid: mustNewOIDFromInts(t, []uint64{1, 33}), oid2: asn1.ObjectIdentifier{1, 33, math.MaxInt32}, eq: false},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, math.MaxInt32}), oid2: asn1.ObjectIdentifier{1, 33}, eq: false},
{oid: mustNewOIDFromInts(t, []uint64{1, 33, math.MaxInt32}), oid2: asn1.ObjectIdentifier{1, 33, math.MaxInt32}, eq: true},
{oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 3}, eq: true},
{oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 4}, eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 2, 3}), oid2: asn1.ObjectIdentifier{1, 2, 3, 4}, eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 33, 22}), oid2: asn1.ObjectIdentifier{1, 33, 23}, eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 33, 23}), oid2: asn1.ObjectIdentifier{1, 33, 22}, eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 33, 127}), oid2: asn1.ObjectIdentifier{1, 33, 127}, eq: true},
{oid: mustNewOIDFromInts([]uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 127}, eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 128}, eq: true},
{oid: mustNewOIDFromInts([]uint64{1, 33, 129}), oid2: asn1.ObjectIdentifier{1, 33, 129}, eq: true},
{oid: mustNewOIDFromInts([]uint64{1, 33, 128}), oid2: asn1.ObjectIdentifier{1, 33, 129}, eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 33, 129}), oid2: asn1.ObjectIdentifier{1, 33, 128}, eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 33, 255}), oid2: asn1.ObjectIdentifier{1, 33, 255}, eq: true},
{oid: mustNewOIDFromInts([]uint64{1, 33, 256}), oid2: asn1.ObjectIdentifier{1, 33, 256}, eq: true},
{oid: mustNewOIDFromInts([]uint64{2, 33, 257}), oid2: asn1.ObjectIdentifier{2, 33, 256}, eq: false},
{oid: mustNewOIDFromInts([]uint64{2, 33, 256}), oid2: asn1.ObjectIdentifier{2, 33, 257}, eq: false},

{oid: mustNewOIDFromInts([]uint64{1, 33}), oid2: asn1.ObjectIdentifier{1, 33, math.MaxInt32}, eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 33, math.MaxInt32}), oid2: asn1.ObjectIdentifier{1, 33}, eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 33, math.MaxInt32}), oid2: asn1.ObjectIdentifier{1, 33, math.MaxInt32}, eq: true},
{
oid: mustNewOIDFromInts(t, []uint64{1, 33, math.MaxInt32 + 1}),
oid: mustNewOIDFromInts([]uint64{1, 33, math.MaxInt32 + 1}),
oid2: asn1.ObjectIdentifier{1, 33 /*convert to int, so that it compiles on 32bit*/, int(maxInt32PlusOne)},
eq: false,
},

{oid: mustNewOIDFromInts(t, []uint64{1, 33, 256}), oid2: asn1.ObjectIdentifier{}, eq: false},
{oid: mustNewOIDFromInts([]uint64{1, 33, 256}), oid2: asn1.ObjectIdentifier{}, eq: false},
{oid: OID{}, oid2: asn1.ObjectIdentifier{1, 33, 256}, eq: false},
{oid: OID{}, oid2: asn1.ObjectIdentifier{}, eq: false},
}
Expand Down Expand Up @@ -331,7 +331,7 @@ func TestOIDUnmarshalBinary(t *testing.T) {
}

func BenchmarkOIDMarshalUnmarshalText(b *testing.B) {
oid := mustNewOIDFromInts(b, []uint64{1, 2, 3, 9999, 1024})
oid := mustNewOIDFromInts([]uint64{1, 2, 3, 9999, 1024})
for range b.N {
text, err := oid.MarshalText()
if err != nil {
Expand All @@ -343,12 +343,3 @@ func BenchmarkOIDMarshalUnmarshalText(b *testing.B) {
}
}
}

func mustNewOIDFromInts(t testing.TB, ints []uint64) OID {
t.Helper()
oid, err := OIDFromInts(ints)
if err != nil {
t.Fatalf("OIDFromInts(%v) unexpected error: %v", ints, err)
}
return oid
}
58 changes: 56 additions & 2 deletions src/crypto/x509/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ func parseExtKeyUsageExtension(der cryptobyte.String) ([]ExtKeyUsage, []asn1.Obj

func parseCertificatePoliciesExtension(der cryptobyte.String) ([]OID, error) {
var oids []OID
seenOIDs := map[string]bool{}
if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) {
return nil, errors.New("x509: invalid certificate policies")
}
Expand All @@ -467,6 +468,10 @@ func parseCertificatePoliciesExtension(der cryptobyte.String) ([]OID, error) {
if !der.ReadASN1(&cp, cryptobyte_asn1.SEQUENCE) || !cp.ReadASN1(&OIDBytes, cryptobyte_asn1.OBJECT_IDENTIFIER) {
return nil, errors.New("x509: invalid certificate policies")
}
if seenOIDs[string(OIDBytes)] {
return nil, errors.New("x509: invalid certificate policies")
}
seenOIDs[string(OIDBytes)] = true
oid, ok := newOIDFromDER(OIDBytes)
if !ok {
return nil, errors.New("x509: invalid certificate policies")
Expand Down Expand Up @@ -747,13 +752,41 @@ func processExtensions(out *Certificate) error {
if err != nil {
return err
}
case 36:
val := cryptobyte.String(e.Value)
if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) {
return errors.New("x509: invalid policy constraints extension")
}
if val.PeekASN1Tag(cryptobyte_asn1.Tag(0).ContextSpecific()) {
var v int64
if !val.ReadASN1Int64WithTag(&v, cryptobyte_asn1.Tag(0).ContextSpecific()) {
return errors.New("x509: invalid policy constraints extension")
}
out.RequireExplicitPolicy = int(v)
// Check for overflow.
if int64(out.RequireExplicitPolicy) != v {
return errors.New("x509: policy constraints requireExplicitPolicy field overflows int")
}
out.RequireExplicitPolicyZero = out.RequireExplicitPolicy == 0
}
if val.PeekASN1Tag(cryptobyte_asn1.Tag(1).ContextSpecific()) {
var v int64
if !val.ReadASN1Int64WithTag(&v, cryptobyte_asn1.Tag(1).ContextSpecific()) {
return errors.New("x509: invalid policy constraints extension")
}
out.InhibitPolicyMapping = int(v)
// Check for overflow.
if int64(out.InhibitPolicyMapping) != v {
return errors.New("x509: policy constraints inhibitPolicyMapping field overflows int")
}
out.InhibitPolicyMappingZero = out.InhibitPolicyMapping == 0
}
case 37:
out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value)
if err != nil {
return err
}
case 14:
// RFC 5280, 4.2.1.2
case 14: // RFC 5280, 4.2.1.2
if e.Critical {
// Conforming CAs MUST mark this extension as non-critical
return errors.New("x509: subject key identifier incorrectly marked critical")
Expand All @@ -775,6 +808,27 @@ func processExtensions(out *Certificate) error {
out.PolicyIdentifiers = append(out.PolicyIdentifiers, oid)
}
}
case 33:
val := cryptobyte.String(e.Value)
if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) {
return errors.New("x509: invalid policy mappings extension")
}
for !val.Empty() {
var s cryptobyte.String
var issuer, subject cryptobyte.String
if !val.ReadASN1(&s, cryptobyte_asn1.SEQUENCE) ||
!s.ReadASN1(&issuer, cryptobyte_asn1.OBJECT_IDENTIFIER) ||
!s.ReadASN1(&subject, cryptobyte_asn1.OBJECT_IDENTIFIER) {
return errors.New("x509: invalid policy mappings extension")
}
out.PolicyMappings = append(out.PolicyMappings, PolicyMapping{OID{issuer}, OID{subject}})
}
case 54:
val := cryptobyte.String(e.Value)
if !val.ReadASN1Integer(&out.InhibitAnyPolicy) {
return errors.New("x509: invalid inhibit any policy extension")
}
out.InhibitAnyPolicyZero = out.InhibitAnyPolicy == 0
default:
// Unknown extensions are recorded if critical.
unhandled = true
Expand Down
83 changes: 83 additions & 0 deletions src/crypto/x509/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package x509

import (
"encoding/asn1"
"encoding/pem"
"os"
"testing"

cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
Expand Down Expand Up @@ -101,3 +103,84 @@ func TestParseASN1String(t *testing.T) {
})
}
}

const policyPEM = `-----BEGIN CERTIFICATE-----
MIIGeDCCBWCgAwIBAgIUED9KQBi0ScBDoufB2mgAJ63G5uIwDQYJKoZIhvcNAQEL
BQAwVTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDENMAsG
A1UECxMERlBLSTEdMBsGA1UEAxMURmVkZXJhbCBCcmlkZ2UgQ0EgRzQwHhcNMjAx
MDIyMTcwNDE5WhcNMjMxMDIyMTcwNDE5WjCBgTELMAkGA1UEBhMCVVMxHTAbBgNV
BAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVz
dCBOZXR3b3JrMTIwMAYDVQQDEylTeW1hbnRlYyBDbGFzcyAzIFNTUCBJbnRlcm1l
ZGlhdGUgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2p
75cMpx86sS2aH4r+0o8r+m/KTrPrknWP0RA9Kp6sewAzkNa7BVwg0jOhyamiv1iP
Cns10usoH93nxYbXLWF54vOLRdYU/53KEPNmgkj2ipMaTLuaReBghNibikWSnAmy
S8RItaDMs8tdF2goKPI4xWiamNwqe92VC+pic2tq0Nva3Y4kvMDJjtyje3uduTtL
oyoaaHkrX7i7gE67psnMKj1THUtre1JV1ohl9+oOuyot4p3eSxVlrMWiiwb11bnk
CakecOz/mP2DHMGg6pZ/BeJ+ThaLUylAXECARIqHc9UwRPKC9BfLaCX4edIoeYiB
loRs4KdqLdg/I9eTwKkCAwEAAaOCAxEwggMNMB0GA1UdDgQWBBQ1Jn1QleGhwb0F
1cOdd0LHDBOWjDAfBgNVHSMEGDAWgBR58ABJ6393wl1BAmU0ipAjmx4HbzAOBgNV
HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zCBiAYDVR0gBIGAMH4wDAYKYIZI
AWUDAgEDAzAMBgpghkgBZQMCAQMMMAwGCmCGSAFlAwIBAw4wDAYKYIZIAWUDAgED
DzAMBgpghkgBZQMCAQMSMAwGCmCGSAFlAwIBAxMwDAYKYIZIAWUDAgEDFDAMBgpg
hkgBZQMCAQMlMAwGCmCGSAFlAwIBAyYwggESBgNVHSEEggEJMIIBBTAbBgpghkgB
ZQMCAQMDBg1ghkgBhvhFAQcXAwEGMBsGCmCGSAFlAwIBAwwGDWCGSAGG+EUBBxcD
AQcwGwYKYIZIAWUDAgEDDgYNYIZIAYb4RQEHFwMBDjAbBgpghkgBZQMCAQMPBg1g
hkgBhvhFAQcXAwEPMBsGCmCGSAFlAwIBAxIGDWCGSAGG+EUBBxcDARIwGwYKYIZI
AWUDAgEDEwYNYIZIAYb4RQEHFwMBETAbBgpghkgBZQMCAQMUBg1ghkgBhvhFAQcX
AwEUMBsGCmCGSAFlAwIBAyUGDWCGSAGG+EUBBxcDAQgwGwYKYIZIAWUDAgEDJgYN
YIZIAYb4RQEHFwMBJDBgBggrBgEFBQcBCwRUMFIwUAYIKwYBBQUHMAWGRGh0dHA6
Ly9zc3Atc2lhLnN5bWF1dGguY29tL1NUTlNTUC9DZXJ0c19Jc3N1ZWRfYnlfQ2xh
c3MzU1NQQ0EtRzMucDdjMA8GA1UdJAQIMAaAAQCBAQAwCgYDVR02BAMCAQAwUQYI
KwYBBQUHAQEERTBDMEEGCCsGAQUFBzAChjVodHRwOi8vcmVwby5mcGtpLmdvdi9i
cmlkZ2UvY2FDZXJ0c0lzc3VlZFRvZmJjYWc0LnA3YzA3BgNVHR8EMDAuMCygKqAo
hiZodHRwOi8vcmVwby5mcGtpLmdvdi9icmlkZ2UvZmJjYWc0LmNybDANBgkqhkiG
9w0BAQsFAAOCAQEAA751TycC1f/WTkHmedF9ZWxP58Jstmwvkyo8bKueJ0eF7LTG
BgQlzE2B9vke4sFhd4V+BdgOPGE1dsGzllYKCWg0BhkCBs5kIJ7F6Ay6G1TBuGU1
Ie8247GL+P9pcC5TVvXHC/62R2w3DuD/vAPLbYEbSQjobXlsqt8Kmtd6yK/jVuDV
BTZMdZmvoNtjemqmgcBXHsf0ctVm0m6tH5uYqyVxu8tfyUis6Cf303PHj+spWP1k
gc5PYnVF0ot7qAmNFENIpbKg3BdusBkF9rGxLaDSUBvSc7+s9iQz9d/iRuAebrYu
+eqUlJ2lsjS1U8qyPmlH+spfPNbAEQEsuP32Aw==
-----END CERTIFICATE-----
`

func TestPolicyParse(t *testing.T) {
b, _ := pem.Decode([]byte(policyPEM))
c, err := ParseCertificate(b.Bytes)
if err != nil {
t.Fatal(err)
}
if len(c.Policies) != 9 {
t.Errorf("unexpected number of policies: got %d, want %d", len(c.Policies), 9)
}
if len(c.PolicyMappings) != 9 {
t.Errorf("unexpected number of policy mappings: got %d, want %d", len(c.PolicyMappings), 9)
}
if !c.RequireExplicitPolicyZero {
t.Error("expected RequireExplicitPolicyZero to be set")
}
if !c.InhibitPolicyMappingZero {
t.Error("expected InhibitPolicyMappingZero to be set")
}
if !c.InhibitAnyPolicyZero {
t.Error("expected InhibitAnyPolicyZero to be set")
}
}

func TestParsePolicies(t *testing.T) {
for _, tc := range []string{
"testdata/policy_leaf_duplicate.pem",
"testdata/policy_leaf_invalid.pem",
} {
t.Run(tc, func(t *testing.T) {
b, err := os.ReadFile(tc)
if err != nil {
t.Fatal(err)
}
p, _ := pem.Decode(b)
_, err = ParseCertificate(p.Bytes)
if err == nil {
t.Error("parsing should've failed")
}
})
}
}
20 changes: 15 additions & 5 deletions src/crypto/x509/root_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,24 @@ import (
)

const (
testDir = "testdata"
testDirCN = "test-dir"
testFile = "test-file.crt"
testFileCN = "test-file"
testMissing = "missing"
)

func TestEnvVars(t *testing.T) {
tmpDir := t.TempDir()
testCert, err := os.ReadFile("testdata/test-dir.crt")
if err != nil {
t.Fatalf("failed to read test cert: %s", err)
}
if err := os.WriteFile(filepath.Join(tmpDir, testFile), testCert, 0644); err != nil {
if err != nil {
t.Fatalf("failed to write test cert: %s", err)
}
}

testCases := []struct {
name string
fileEnv string
Expand All @@ -39,7 +49,7 @@ func TestEnvVars(t *testing.T) {
fileEnv: testMissing,
dirEnv: testMissing,
files: []string{testFile},
dirs: []string{testDir},
dirs: []string{tmpDir},
cns: nil,
},
{
Expand All @@ -55,7 +65,7 @@ func TestEnvVars(t *testing.T) {
// Directory environment overrides default directory locations.
name: "dir",
fileEnv: "",
dirEnv: testDir,
dirEnv: tmpDir,
files: nil,
dirs: nil,
cns: []string{testDirCN},
Expand All @@ -64,7 +74,7 @@ func TestEnvVars(t *testing.T) {
// File & directory environment overrides both default locations.
name: "file+dir",
fileEnv: testFile,
dirEnv: testDir,
dirEnv: tmpDir,
files: nil,
dirs: nil,
cns: []string{testFileCN, testDirCN},
Expand All @@ -75,7 +85,7 @@ func TestEnvVars(t *testing.T) {
fileEnv: "",
dirEnv: "",
files: []string{testFile},
dirs: []string{testDir},
dirs: []string{tmpDir},
cns: []string{testFileCN, testDirCN},
},
}
Expand Down
11 changes: 11 additions & 0 deletions src/crypto/x509/testdata/policy_intermediate.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBqjCCAVGgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg
Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE
AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia
jQ6Dg7CTpVZVVH+bguT7JTCjgYUwgYIwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM
MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr
CIRhwsXrPVBagG2uMCsGA1UdIAQkMCIwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG
9xIEAYS3CQICMAoGCCqGSM49BAMCA0cAMEQCIFN2ZtknXQ9vz23qD1ecprC9iIo7
j/SI42Ub64qZQaraAiA+CRCWJz/l+NQ1+TPWYDDWY6Wh2L9Wbddh1Nj5KJEkhQ==
-----END CERTIFICATE-----
11 changes: 11 additions & 0 deletions src/crypto/x509/testdata/policy_intermediate_any.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBkDCCATWgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg
Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE
AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia
jQ6Dg7CTpVZVVH+bguT7JTCjajBoMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK
BggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQ0vf+Du6oawiE
YcLF6z1QWoBtrjARBgNVHSAECjAIMAYGBFUdIAAwCgYIKoZIzj0EAwIDSQAwRgIh
AJbyXshUwjsFCiqrJkg91GzJdhZZ+3WXOekCJgi8uEESAiEAhv4sEE0wRRqgHDjl
vIt26IELfFE2Z/FBF3ihGmi6NoI=
-----END CERTIFICATE-----
12 changes: 12 additions & 0 deletions src/crypto/x509/testdata/policy_intermediate_duplicate.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIBvDCCAWKgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg
Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE
AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia
jQ6Dg7CTpVZVVH+bguT7JTCjgZYwgZMwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM
MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr
CIRhwsXrPVBagG2uMDwGA1UdIAQ1MDMwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG
9xIEAYS3CQICMA8GDSqGSIb3EgQBhLcJAgIwCgYIKoZIzj0EAwIDSAAwRQIgUpG6
FUeWrC62BtTPHiSlWBdnLWUYH0llS6uYUkpJFJECIQCWfhoZYXvHdMhgBDSI/vzY
Sw4uNdcMxrC2kP6lIioUSw==
-----END CERTIFICATE-----
Loading

0 comments on commit e8d9561

Please sign in to comment.