mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 20:26:19 +08:00
properly apply name constrains to roots and intermediates #125
This commit is contained in:
parent
36a92eff46
commit
f3a5d48ed8
@ -481,22 +481,19 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
|
|||||||
}
|
}
|
||||||
comparisonCount := 0
|
comparisonCount := 0
|
||||||
|
|
||||||
var leaf *Certificate
|
|
||||||
if certType == intermediateCertificate || certType == rootCertificate {
|
if certType == intermediateCertificate || certType == rootCertificate {
|
||||||
if len(currentChain) == 0 {
|
if len(currentChain) == 0 {
|
||||||
return errors.New("x509: internal error: empty chain when appending CA cert")
|
return errors.New("x509: internal error: empty chain when appending CA cert")
|
||||||
}
|
}
|
||||||
leaf = currentChain[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (certType == intermediateCertificate || certType == rootCertificate) &&
|
if (certType == intermediateCertificate || certType == rootCertificate) &&
|
||||||
c.hasNameConstraints() {
|
c.hasNameConstraints() {
|
||||||
toCheck := []*Certificate{}
|
toCheck := []*Certificate{}
|
||||||
if leaf.hasSANExtension() {
|
for _, c := range currentChain {
|
||||||
toCheck = append(toCheck, leaf)
|
if c.hasSANExtension() {
|
||||||
}
|
toCheck = append(toCheck, c)
|
||||||
if c.hasSANExtension() {
|
}
|
||||||
toCheck = append(toCheck, c)
|
|
||||||
}
|
}
|
||||||
for _, sanCert := range toCheck {
|
for _, sanCert := range toCheck {
|
||||||
err := forEachSAN(sanCert.getSANExtension(), func(tag int, data []byte) error {
|
err := forEachSAN(sanCert.getSANExtension(), func(tag int, data []byte) error {
|
||||||
|
@ -1918,8 +1918,13 @@ type trustGraphEdge struct {
|
|||||||
MutateTemplate func(*Certificate)
|
MutateTemplate func(*Certificate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type rootDescription struct {
|
||||||
|
Subject string
|
||||||
|
MutateTemplate func(*Certificate)
|
||||||
|
}
|
||||||
|
|
||||||
type trustGraphDescription struct {
|
type trustGraphDescription struct {
|
||||||
Roots []string
|
Roots []rootDescription
|
||||||
Leaf string
|
Leaf string
|
||||||
Graph []trustGraphEdge
|
Graph []trustGraphEdge
|
||||||
}
|
}
|
||||||
@ -1974,10 +1979,10 @@ func buildTrustGraph(t *testing.T, d trustGraphDescription) (*CertPool, *CertPoo
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to generate test key: %s", err)
|
t.Fatalf("failed to generate test key: %s", err)
|
||||||
}
|
}
|
||||||
root := genCertEdge(t, r, k, nil, rootCertificate, nil, nil)
|
root := genCertEdge(t, r.Subject, k, r.MutateTemplate, rootCertificate, nil, nil)
|
||||||
roots = append(roots, root)
|
roots = append(roots, root)
|
||||||
certs[r] = root
|
certs[r.Subject] = root
|
||||||
keys[r] = k
|
keys[r.Subject] = k
|
||||||
}
|
}
|
||||||
|
|
||||||
intermediates := []*Certificate{}
|
intermediates := []*Certificate{}
|
||||||
@ -2069,7 +2074,7 @@ func TestPathBuilding(t *testing.T) {
|
|||||||
// +----+
|
// +----+
|
||||||
name: "bad EKU 1",
|
name: "bad EKU 1",
|
||||||
graph: trustGraphDescription{
|
graph: trustGraphDescription{
|
||||||
Roots: []string{"root"},
|
Roots: []rootDescription{{Subject: "root"}},
|
||||||
Leaf: "leaf",
|
Leaf: "leaf",
|
||||||
Graph: []trustGraphEdge{
|
Graph: []trustGraphEdge{
|
||||||
{
|
{
|
||||||
@ -2145,7 +2150,7 @@ func TestPathBuilding(t *testing.T) {
|
|||||||
// +----+
|
// +----+
|
||||||
name: "bad EKU 2",
|
name: "bad EKU 2",
|
||||||
graph: trustGraphDescription{
|
graph: trustGraphDescription{
|
||||||
Roots: []string{"root"},
|
Roots: []rootDescription{{Subject: "root"}},
|
||||||
Leaf: "leaf",
|
Leaf: "leaf",
|
||||||
Graph: []trustGraphEdge{
|
Graph: []trustGraphEdge{
|
||||||
{
|
{
|
||||||
@ -2227,7 +2232,7 @@ func TestPathBuilding(t *testing.T) {
|
|||||||
// +----+
|
// +----+
|
||||||
name: "all paths",
|
name: "all paths",
|
||||||
graph: trustGraphDescription{
|
graph: trustGraphDescription{
|
||||||
Roots: []string{"root"},
|
Roots: []rootDescription{{Subject: "root"}},
|
||||||
Leaf: "leaf",
|
Leaf: "leaf",
|
||||||
Graph: []trustGraphEdge{
|
Graph: []trustGraphEdge{
|
||||||
{
|
{
|
||||||
@ -2291,7 +2296,7 @@ func TestPathBuilding(t *testing.T) {
|
|||||||
// +----+
|
// +----+
|
||||||
name: "ignore cross-sig loops",
|
name: "ignore cross-sig loops",
|
||||||
graph: trustGraphDescription{
|
graph: trustGraphDescription{
|
||||||
Roots: []string{"root"},
|
Roots: []rootDescription{{Subject: "root"}},
|
||||||
Leaf: "leaf",
|
Leaf: "leaf",
|
||||||
Graph: []trustGraphEdge{
|
Graph: []trustGraphEdge{
|
||||||
{
|
{
|
||||||
@ -2344,7 +2349,7 @@ func TestPathBuilding(t *testing.T) {
|
|||||||
// the leaf has SANs.
|
// the leaf has SANs.
|
||||||
name: "leaf with same subject, key, as parent but with SAN",
|
name: "leaf with same subject, key, as parent but with SAN",
|
||||||
graph: trustGraphDescription{
|
graph: trustGraphDescription{
|
||||||
Roots: []string{"root"},
|
Roots: []rootDescription{{Subject: "root"}},
|
||||||
Leaf: "root",
|
Leaf: "root",
|
||||||
Graph: []trustGraphEdge{
|
Graph: []trustGraphEdge{
|
||||||
{
|
{
|
||||||
@ -2366,7 +2371,7 @@ func TestPathBuilding(t *testing.T) {
|
|||||||
// through C should be ignored, because it has invalid EKU nesting.
|
// through C should be ignored, because it has invalid EKU nesting.
|
||||||
name: "ignore invalid EKU path",
|
name: "ignore invalid EKU path",
|
||||||
graph: trustGraphDescription{
|
graph: trustGraphDescription{
|
||||||
Roots: []string{"root"},
|
Roots: []rootDescription{{Subject: "root"}},
|
||||||
Leaf: "leaf",
|
Leaf: "leaf",
|
||||||
Graph: []trustGraphEdge{
|
Graph: []trustGraphEdge{
|
||||||
{
|
{
|
||||||
@ -2409,6 +2414,70 @@ func TestPathBuilding(t *testing.T) {
|
|||||||
"CN=leaf -> CN=inter b -> CN=inter a -> CN=root",
|
"CN=leaf -> CN=inter b -> CN=inter a -> CN=root",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// A name constraint on the root should apply to any names that appear
|
||||||
|
// on the intermediate, meaning there is no valid chain.
|
||||||
|
name: "contrained root, invalid intermediate",
|
||||||
|
graph: trustGraphDescription{
|
||||||
|
Roots: []rootDescription{
|
||||||
|
{
|
||||||
|
Subject: "root",
|
||||||
|
MutateTemplate: func(t *Certificate) {
|
||||||
|
t.PermittedDNSDomains = []string{"example.com"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Leaf: "leaf",
|
||||||
|
Graph: []trustGraphEdge{
|
||||||
|
{
|
||||||
|
Issuer: "root",
|
||||||
|
Subject: "inter",
|
||||||
|
Type: intermediateCertificate,
|
||||||
|
MutateTemplate: func(t *Certificate) {
|
||||||
|
t.DNSNames = []string{"beep.com"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Issuer: "inter",
|
||||||
|
Subject: "leaf",
|
||||||
|
Type: leafCertificate,
|
||||||
|
MutateTemplate: func(t *Certificate) {
|
||||||
|
t.DNSNames = []string{"www.example.com"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedErr: "x509: a root or intermediate certificate is not authorized to sign for this name: DNS name \"beep.com\" is not permitted by any constraint",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// A name constraint on the intermediate does not apply to the intermediate
|
||||||
|
// itself, so this is a valid chain.
|
||||||
|
name: "contrained intermediate, non-matching SAN",
|
||||||
|
graph: trustGraphDescription{
|
||||||
|
Roots: []rootDescription{{Subject: "root"}},
|
||||||
|
Leaf: "leaf",
|
||||||
|
Graph: []trustGraphEdge{
|
||||||
|
{
|
||||||
|
Issuer: "root",
|
||||||
|
Subject: "inter",
|
||||||
|
Type: intermediateCertificate,
|
||||||
|
MutateTemplate: func(t *Certificate) {
|
||||||
|
t.DNSNames = []string{"beep.com"}
|
||||||
|
t.PermittedDNSDomains = []string{"example.com"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Issuer: "inter",
|
||||||
|
Subject: "leaf",
|
||||||
|
Type: leafCertificate,
|
||||||
|
MutateTemplate: func(t *Certificate) {
|
||||||
|
t.DNSNames = []string{"www.example.com"}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedChains: []string{"CN=leaf -> CN=inter -> CN=root"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
@ -2421,9 +2490,12 @@ func TestPathBuilding(t *testing.T) {
|
|||||||
if err != nil && err.Error() != tc.expectedErr {
|
if err != nil && err.Error() != tc.expectedErr {
|
||||||
t.Fatalf("unexpected error: got %q, want %q", err, tc.expectedErr)
|
t.Fatalf("unexpected error: got %q, want %q", err, tc.expectedErr)
|
||||||
}
|
}
|
||||||
|
if len(tc.expectedChains) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
gotChains := chainsToStrings(chains)
|
gotChains := chainsToStrings(chains)
|
||||||
if !reflect.DeepEqual(gotChains, tc.expectedChains) {
|
if !reflect.DeepEqual(gotChains, tc.expectedChains) {
|
||||||
t.Errorf("unexpected chains returned:\ngot:\n\t%s\nwant:\n\t%s", strings.Join(gotChains, "\n\t"), strings.Join(tc.expectedChains, "\n\t"))
|
t.Errorf("%s unexpected chains returned:\ngot:\n\t%s\nwant:\n\t%s", tc.name, strings.Join(gotChains, "\n\t"), strings.Join(tc.expectedChains, "\n\t"))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user