Skip to content

Commit a3b93f5

Browse files
committed
crypto/x509: add directory name constraints
Fixes #15196
1 parent 606d4a3 commit a3b93f5

File tree

4 files changed

+1454
-23
lines changed

4 files changed

+1454
-23
lines changed

src/crypto/x509/verify.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package x509
66

77
import (
88
"bytes"
9+
"crypto/x509/pkix"
10+
"encoding/asn1"
911
"errors"
1012
"fmt"
1113
"net"
@@ -512,6 +514,34 @@ func matchDomainConstraint(domain, constraint string) (bool, error) {
512514
return true, nil
513515
}
514516

517+
func matchDirNameConstraint(dirname pkix.RDNSequence, constraint pkix.RDNSequence) (bool, error) {
518+
519+
if len(constraint) > len(dirname) {
520+
return false, nil
521+
}
522+
for i, rdn := range constraint {
523+
if len(rdn) > len(dirname[i]) {
524+
return false, nil
525+
}
526+
for j, const_tv := range rdn {
527+
dirname_tv := dirname[i][j]
528+
if len(const_tv.Type) != len(dirname_tv.Type) {
529+
return false, nil
530+
}
531+
for k, _ := range const_tv.Type {
532+
if const_tv.Type[k] != dirname_tv.Type[k] {
533+
return false, nil
534+
}
535+
}
536+
if const_tv.Value != dirname_tv.Value {
537+
return false, nil
538+
}
539+
}
540+
}
541+
542+
return true, nil
543+
}
544+
515545
// checkNameConstraints checks that c permits a child certificate to claim the
516546
// given name, of type nameType. The argument parsedName contains the parsed
517547
// form of name, suitable for passing to the match function. The total number
@@ -619,6 +649,26 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
619649
}
620650

621651
checkNameConstraints := (certType == intermediateCertificate || certType == rootCertificate) && c.hasNameConstraints()
652+
if checkNameConstraints {
653+
for _, cert := range currentChain {
654+
var subject pkix.RDNSequence
655+
656+
// cert.Subject.ToRDNSequence cannot be used as it ignores unknown RDN
657+
if rest, err := asn1.Unmarshal(cert.RawSubject, &subject); err != nil {
658+
return err
659+
} else if len(rest) != 0 {
660+
return errors.New("x509: trailing data after X.509 subject")
661+
}
662+
663+
if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "directory Name", cert.Subject.String(), subject,
664+
func(parsedName, constraint interface{}) (bool, error) {
665+
return matchDirNameConstraint(parsedName.(pkix.RDNSequence), constraint.(pkix.RDNSequence))
666+
}, c.PermittedDirNames, c.ExcludedDirNames); err != nil {
667+
return err
668+
}
669+
}
670+
}
671+
622672
if checkNameConstraints && leaf.commonNameAsHostname() {
623673
// This is the deprecated, legacy case of depending on the commonName as
624674
// a hostname. We don't enforce name constraints against the CN, but

0 commit comments

Comments
 (0)