@@ -6,6 +6,8 @@ package x509
6
6
7
7
import (
8
8
"bytes"
9
+ "crypto/x509/pkix"
10
+ "encoding/asn1"
9
11
"errors"
10
12
"fmt"
11
13
"net"
@@ -512,6 +514,34 @@ func matchDomainConstraint(domain, constraint string) (bool, error) {
512
514
return true , nil
513
515
}
514
516
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
+
515
545
// checkNameConstraints checks that c permits a child certificate to claim the
516
546
// given name, of type nameType. The argument parsedName contains the parsed
517
547
// 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
619
649
}
620
650
621
651
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
+
622
672
if checkNameConstraints && leaf .commonNameAsHostname () {
623
673
// This is the deprecated, legacy case of depending on the commonName as
624
674
// a hostname. We don't enforce name constraints against the CN, but
0 commit comments