1
0
mirror of https://github.com/golang/go synced 2024-11-22 03:44:39 -07:00

crypto/x509: enforce path length constraint.

An X.509 path length constrains the number of certificate that may
follow in the chain. This is a little simplistic for a first pass as it
doesn't check self-signed certificates (which don't count towards the
length), but it's conservatively simplistic.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5727057
This commit is contained in:
Adam Langley 2012-03-05 12:08:42 -05:00
parent 52d6ca2f86
commit ed35d5e0fb
2 changed files with 17 additions and 5 deletions

View File

@ -23,6 +23,9 @@ const (
// certificate has a name constraint which doesn't include the name // certificate has a name constraint which doesn't include the name
// being checked. // being checked.
CANotAuthorizedForThisName CANotAuthorizedForThisName
// TooManyIntermediates results when a path length constraint is
// violated.
TooManyIntermediates
) )
// CertificateInvalidError results when an odd error occurs. Users of this // CertificateInvalidError results when an odd error occurs. Users of this
@ -40,6 +43,8 @@ func (e CertificateInvalidError) Error() string {
return "x509: certificate has expired or is not yet valid" return "x509: certificate has expired or is not yet valid"
case CANotAuthorizedForThisName: case CANotAuthorizedForThisName:
return "x509: a root or intermediate certificate is not authorized to sign in this domain" return "x509: a root or intermediate certificate is not authorized to sign in this domain"
case TooManyIntermediates:
return "x509: too many intermediates for path length constraint"
} }
return "x509: unknown error" return "x509: unknown error"
} }
@ -87,7 +92,7 @@ const (
) )
// isValid performs validity checks on the c. // isValid performs validity checks on the c.
func (c *Certificate) isValid(certType int, opts *VerifyOptions) error { func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
now := opts.CurrentTime now := opts.CurrentTime
if now.IsZero() { if now.IsZero() {
now = time.Now() now = time.Now()
@ -130,6 +135,13 @@ func (c *Certificate) isValid(certType int, opts *VerifyOptions) error {
return CertificateInvalidError{c, NotAuthorizedToSign} return CertificateInvalidError{c, NotAuthorizedToSign}
} }
if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
numIntermediates := len(currentChain) - 1
if numIntermediates > c.MaxPathLen {
return CertificateInvalidError{c, TooManyIntermediates}
}
}
return nil return nil
} }
@ -140,7 +152,7 @@ func (c *Certificate) isValid(certType int, opts *VerifyOptions) error {
// //
// WARNING: this doesn't do any revocation checking. // WARNING: this doesn't do any revocation checking.
func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) { func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
err = c.isValid(leafCertificate, &opts) err = c.isValid(leafCertificate, nil, &opts)
if err != nil { if err != nil {
return return
} }
@ -163,7 +175,7 @@ func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate
func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) { func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) {
for _, rootNum := range opts.Roots.findVerifiedParents(c) { for _, rootNum := range opts.Roots.findVerifiedParents(c) {
root := opts.Roots.certs[rootNum] root := opts.Roots.certs[rootNum]
err = root.isValid(rootCertificate, opts) err = root.isValid(rootCertificate, currentChain, opts)
if err != nil { if err != nil {
continue continue
} }
@ -178,7 +190,7 @@ nextIntermediate:
continue nextIntermediate continue nextIntermediate
} }
} }
err = intermediate.isValid(intermediateCertificate, opts) err = intermediate.isValid(intermediateCertificate, currentChain, opts)
if err != nil { if err != nil {
continue continue
} }

View File

@ -429,7 +429,7 @@ func (h UnhandledCriticalExtension) Error() string {
type basicConstraints struct { type basicConstraints struct {
IsCA bool `asn1:"optional"` IsCA bool `asn1:"optional"`
MaxPathLen int `asn1:"optional"` MaxPathLen int `asn1:"optional,default:-1"`
} }
// RFC 5280 4.2.1.4 // RFC 5280 4.2.1.4