@@ -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"
@@ -516,6 +518,34 @@ func matchDomainConstraint(domain, constraint string) (bool, error) {
516
518
return true , nil
517
519
}
518
520
521
+ func matchDirNameConstraint (dirname pkix.RDNSequence , constraint pkix.RDNSequence ) (bool , error ) {
522
+
523
+ if len (constraint ) > len (dirname ) {
524
+ return false , nil
525
+ }
526
+ for i , rdn := range constraint {
527
+ if len (rdn ) > len (dirname [i ]) {
528
+ return false , nil
529
+ }
530
+ for j , const_tv := range rdn {
531
+ dirname_tv := dirname [i ][j ]
532
+ if len (const_tv .Type ) != len (dirname_tv .Type ) {
533
+ return false , nil
534
+ }
535
+ for k , _ := range const_tv .Type {
536
+ if const_tv .Type [k ] != dirname_tv .Type [k ] {
537
+ return false , nil
538
+ }
539
+ }
540
+ if const_tv .Value != dirname_tv .Value {
541
+ return false , nil
542
+ }
543
+ }
544
+ }
545
+
546
+ return true , nil
547
+ }
548
+
519
549
// checkNameConstraints checks that c permits a child certificate to claim the
520
550
// given name, of type nameType. The argument parsedName contains the parsed
521
551
// form of name, suitable for passing to the match function. The total number
@@ -623,6 +653,26 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
623
653
}
624
654
625
655
checkNameConstraints := (certType == intermediateCertificate || certType == rootCertificate ) && c .hasNameConstraints ()
656
+ if checkNameConstraints {
657
+ for _ , cert := range currentChain {
658
+ var subject pkix.RDNSequence
659
+
660
+ // cert.Subject.ToRDNSequence cannot be used as it ignores unknown RDN
661
+ if rest , err := asn1 .Unmarshal (cert .RawSubject , & subject ); err != nil {
662
+ return err
663
+ } else if len (rest ) != 0 {
664
+ return errors .New ("x509: trailing data after X.509 subject" )
665
+ }
666
+
667
+ if err := c .checkNameConstraints (& comparisonCount , maxConstraintComparisons , "directory Name" , cert .Subject .String (), subject ,
668
+ func (parsedName , constraint interface {}) (bool , error ) {
669
+ return matchDirNameConstraint (parsedName .(pkix.RDNSequence ), constraint .(pkix.RDNSequence ))
670
+ }, c .PermittedDirNames , c .ExcludedDirNames ); err != nil {
671
+ return err
672
+ }
673
+ }
674
+ }
675
+
626
676
if checkNameConstraints && leaf .commonNameAsHostname () {
627
677
// This is the deprecated, legacy case of depending on the commonName as
628
678
// a hostname. We don't enforce name constraints against the CN, but
0 commit comments