@@ -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"
@@ -498,6 +500,34 @@ func matchDomainConstraint(domain, constraint string) (bool, error) {
498
500
return true , nil
499
501
}
500
502
503
+ func matchDirNameConstraint (dirname pkix.RDNSequence , constraint pkix.RDNSequence ) (bool , error ) {
504
+
505
+ if len (constraint ) > len (dirname ) {
506
+ return false , nil
507
+ }
508
+ for i , rdn := range constraint {
509
+ if len (rdn ) > len (dirname [i ]) {
510
+ return false , nil
511
+ }
512
+ for j , const_tv := range rdn {
513
+ dirname_tv := dirname [i ][j ]
514
+ if len (const_tv .Type ) != len (dirname_tv .Type ) {
515
+ return false , nil
516
+ }
517
+ for k , _ := range const_tv .Type {
518
+ if const_tv .Type [k ] != dirname_tv .Type [k ] {
519
+ return false , nil
520
+ }
521
+ }
522
+ if const_tv .Value != dirname_tv .Value {
523
+ return false , nil
524
+ }
525
+ }
526
+ }
527
+
528
+ return true , nil
529
+ }
530
+
501
531
// checkNameConstraints checks that c permits a child certificate to claim the
502
532
// given name, of type nameType. The argument parsedName contains the parsed
503
533
// form of name, suitable for passing to the match function. The total number
@@ -605,6 +635,26 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
605
635
}
606
636
607
637
checkNameConstraints := (certType == intermediateCertificate || certType == rootCertificate ) && c .hasNameConstraints ()
638
+ if checkNameConstraints {
639
+ for _ , cert := range currentChain {
640
+ var subject pkix.RDNSequence
641
+
642
+ // cert.Subject.ToRDNSequence cannot be used as it ignores unknown RDN
643
+ if rest , err := asn1 .Unmarshal (cert .RawSubject , & subject ); err != nil {
644
+ return err
645
+ } else if len (rest ) != 0 {
646
+ return errors .New ("x509: trailing data after X.509 subject" )
647
+ }
648
+
649
+ if err := c .checkNameConstraints (& comparisonCount , maxConstraintComparisons , "directory Name" , cert .Subject .String (), subject ,
650
+ func (parsedName , constraint interface {}) (bool , error ) {
651
+ return matchDirNameConstraint (parsedName .(pkix.RDNSequence ), constraint .(pkix.RDNSequence ))
652
+ }, c .PermittedDirNames , c .ExcludedDirNames ); err != nil {
653
+ return err
654
+ }
655
+ }
656
+ }
657
+
608
658
if checkNameConstraints && leaf .commonNameAsHostname () {
609
659
// This is the deprecated, legacy case of depending on the commonName as
610
660
// a hostname. We don't enforce name constraints against the CN, but
0 commit comments