1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
22 type InvalidReason
int
25 // NotAuthorizedToSign results when a certificate is signed by another
26 // which isn't marked as a CA certificate.
27 NotAuthorizedToSign InvalidReason
= iota
28 // Expired results when a certificate has expired, based on the time
29 // given in the VerifyOptions.
31 // CANotAuthorizedForThisName results when an intermediate or root
32 // certificate has a name constraint which doesn't permit a DNS or
33 // other name (including IP address) in the leaf certificate.
34 CANotAuthorizedForThisName
35 // TooManyIntermediates results when a path length constraint is
38 // IncompatibleUsage results when the certificate's key usage indicates
39 // that it may only be used for a different purpose.
41 // NameMismatch results when the subject name of a parent certificate
42 // does not match the issuer name in the child.
44 // NameConstraintsWithoutSANs results when a leaf certificate doesn't
45 // contain a Subject Alternative Name extension, but a CA certificate
46 // contains name constraints.
47 NameConstraintsWithoutSANs
48 // UnconstrainedName results when a CA certificate contains permitted
49 // name constraints, but leaf certificate contains a name of an
50 // unsupported or unconstrained type.
52 // TooManyConstraints results when the number of comparision operations
53 // needed to check a certificate exceeds the limit set by
54 // VerifyOptions.MaxConstraintComparisions. This limit exists to
55 // prevent pathological certificates can consuming excessive amounts of
56 // CPU time to verify.
58 // CANotAuthorizedForExtKeyUsage results when an intermediate or root
59 // certificate does not permit a requested extended key usage.
60 CANotAuthorizedForExtKeyUsage
63 // CertificateInvalidError results when an odd error occurs. Users of this
64 // library probably want to handle all these errors uniformly.
65 type CertificateInvalidError
struct {
71 func (e CertificateInvalidError
) Error() string {
73 case NotAuthorizedToSign
:
74 return "x509: certificate is not authorized to sign other certificates"
76 return "x509: certificate has expired or is not yet valid"
77 case CANotAuthorizedForThisName
:
78 return "x509: a root or intermediate certificate is not authorized to sign for this name: " + e
.Detail
79 case CANotAuthorizedForExtKeyUsage
:
80 return "x509: a root or intermediate certificate is not authorized for an extended key usage: " + e
.Detail
81 case TooManyIntermediates
:
82 return "x509: too many intermediates for path length constraint"
83 case IncompatibleUsage
:
84 return "x509: certificate specifies an incompatible key usage"
86 return "x509: issuer name does not match subject from issuing certificate"
87 case NameConstraintsWithoutSANs
:
88 return "x509: issuer has name constraints but leaf doesn't have a SAN extension"
89 case UnconstrainedName
:
90 return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + e
.Detail
92 return "x509: unknown error"
95 // HostnameError results when the set of authorized names doesn't match the
97 type HostnameError
struct {
98 Certificate
*Certificate
102 func (h HostnameError
) Error() string {
106 if ip
:= net
.ParseIP(h
.Host
); ip
!= nil {
107 // Trying to validate an IP
108 if len(c
.IPAddresses
) == 0 {
109 return "x509: cannot validate certificate for " + h
.Host
+ " because it doesn't contain any IP SANs"
111 for _
, san
:= range c
.IPAddresses
{
115 valid
+= san
.String()
118 if c
.hasSANExtension() {
119 valid
= strings
.Join(c
.DNSNames
, ", ")
121 valid
= c
.Subject
.CommonName
126 return "x509: certificate is not valid for any names, but wanted to match " + h
.Host
128 return "x509: certificate is valid for " + valid
+ ", not " + h
.Host
131 // UnknownAuthorityError results when the certificate issuer is unknown
132 type UnknownAuthorityError
struct {
134 // hintErr contains an error that may be helpful in determining why an
135 // authority wasn't found.
137 // hintCert contains a possible authority certificate that was rejected
138 // because of the error in hintErr.
139 hintCert
*Certificate
142 func (e UnknownAuthorityError
) Error() string {
143 s
:= "x509: certificate signed by unknown authority"
144 if e
.hintErr
!= nil {
145 certName
:= e
.hintCert
.Subject
.CommonName
146 if len(certName
) == 0 {
147 if len(e
.hintCert
.Subject
.Organization
) > 0 {
148 certName
= e
.hintCert
.Subject
.Organization
[0]
150 certName
= "serial:" + e
.hintCert
.SerialNumber
.String()
153 s
+= fmt
.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e
.hintErr
, certName
)
158 // SystemRootsError results when we fail to load the system root certificates.
159 type SystemRootsError
struct {
163 func (se SystemRootsError
) Error() string {
164 msg
:= "x509: failed to load system roots and no roots provided"
166 return msg
+ "; " + se
.Err
.Error()
171 // errNotParsed is returned when a certificate without ASN.1 contents is
172 // verified. Platform-specific verification needs the ASN.1 contents.
173 var errNotParsed
= errors
.New("x509: missing ASN.1 contents; use ParseCertificate")
175 // VerifyOptions contains parameters for Certificate.Verify. It's a structure
176 // because other PKIX verification APIs have ended up needing many options.
177 type VerifyOptions
struct {
179 Intermediates
*CertPool
180 Roots
*CertPool
// if nil, the system roots are used
181 CurrentTime time
.Time
// if zero, the current time is used
182 // KeyUsage specifies which Extended Key Usage values are acceptable. A leaf
183 // certificate is accepted if it contains any of the listed values. An empty
184 // list means ExtKeyUsageServerAuth. To accept any key usage, include
187 // Certificate chains are required to nest these extended key usage values.
188 // (This matches the Windows CryptoAPI behavior, but not the spec.)
189 KeyUsages
[]ExtKeyUsage
190 // MaxConstraintComparisions is the maximum number of comparisons to
191 // perform when checking a given certificate's name constraints. If
192 // zero, a sensible default is used. This limit prevents pathalogical
193 // certificates from consuming excessive amounts of CPU time when
195 MaxConstraintComparisions
int
199 leafCertificate
= iota
200 intermediateCertificate
204 // rfc2821Mailbox represents a “mailbox” (which is an email address to most
205 // people) by breaking it into the “local” (i.e. before the '@') and “domain”
207 type rfc2821Mailbox
struct {
211 // parseRFC2821Mailbox parses an email address into local and domain parts,
212 // based on the ABNF for a “Mailbox” from RFC 2821. According to
213 // https://tools.ietf.org/html/rfc5280#section-4.2.1.6 that's correct for an
214 // rfc822Name from a certificate: “The format of an rfc822Name is a "Mailbox"
215 // as defined in https://tools.ietf.org/html/rfc2821#section-4.1.2”.
216 func parseRFC2821Mailbox(in
string) (mailbox rfc2821Mailbox
, ok
bool) {
218 return mailbox
, false
221 localPartBytes
:= make([]byte, 0, len(in
)/2)
224 // Quoted-string = DQUOTE *qcontent DQUOTE
225 // non-whitespace-control = %d1-8 / %d11 / %d12 / %d14-31 / %d127
226 // qcontent = qtext / quoted-pair
227 // qtext = non-whitespace-control /
228 // %d33 / %d35-91 / %d93-126
229 // quoted-pair = ("\" text) / obs-qp
230 // text = %d1-9 / %d11 / %d12 / %d14-127 / obs-text
232 // (Names beginning with “obs-” are the obsolete syntax from
233 // https://tools.ietf.org/html/rfc2822#section-4. Since it has
234 // been 16 years, we no longer accept that.)
239 return mailbox
, false
251 return mailbox
, false
255 (1 <= in
[0] && in
[0] <= 9) ||
256 (14 <= in
[0] && in
[0] <= 127) {
257 localPartBytes
= append(localPartBytes
, in
[0])
260 return mailbox
, false
265 // Space (char 32) is not allowed based on the
266 // BNF, but RFC 3696 gives an example that
267 // assumes that it is. Several “verified”
268 // errata continue to argue about this point.
269 // We choose to accept it.
273 (1 <= c
&& c
<= 8) ||
274 (14 <= c
&& c
<= 31) ||
275 (35 <= c
&& c
<= 91) ||
276 (93 <= c
&& c
<= 126):
278 localPartBytes
= append(localPartBytes
, c
)
281 return mailbox
, false
288 // atext from https://tools.ietf.org/html/rfc2822#section-3.2.4
293 // Examples given in RFC 3696 suggest that
294 // escaped characters can appear outside of a
295 // quoted string. Several “verified” errata
296 // continue to argue the point. We choose to
300 return mailbox
, false
304 case ('0' <= c
&& c
<= '9') ||
305 ('a' <= c
&& c
<= 'z') ||
306 ('A' <= c
&& c
<= 'Z') ||
307 c
== '!' || c
== '#' || c
== '$' || c
== '%' ||
308 c
== '&' || c
== '\'' || c
== '*' || c
== '+' ||
309 c
== '-' || c
== '/' || c
== '=' || c
== '?' ||
310 c
== '^' || c
== '_' || c
== '`' || c
== '{' ||
311 c
== '|' || c
== '}' || c
== '~' || c
== '.':
312 localPartBytes
= append(localPartBytes
, in
[0])
320 if len(localPartBytes
) == 0 {
321 return mailbox
, false
324 // https://tools.ietf.org/html/rfc3696#section-3
325 // “period (".") may also appear, but may not be used to start
326 // or end the local part, nor may two or more consecutive
328 twoDots
:= []byte{'.', '.'}
329 if localPartBytes
[0] == '.' ||
330 localPartBytes
[len(localPartBytes
)-1] == '.' ||
331 bytes
.Contains(localPartBytes
, twoDots
) {
332 return mailbox
, false
336 if len(in
) == 0 || in
[0] != '@' {
337 return mailbox
, false
341 // The RFC species a format for domains, but that's known to be
342 // violated in practice so we accept that anything after an '@' is the
344 if _
, ok
:= domainToReverseLabels(in
); !ok
{
345 return mailbox
, false
348 mailbox
.local
= string(localPartBytes
)
353 // domainToReverseLabels converts a textual domain name like foo.example.com to
354 // the list of labels in reverse order, e.g. ["com", "example", "foo"].
355 func domainToReverseLabels(domain
string) (reverseLabels
[]string, ok
bool) {
356 for len(domain
) > 0 {
357 if i
:= strings
.LastIndexByte(domain
, '.'); i
== -1 {
358 reverseLabels
= append(reverseLabels
, domain
)
361 reverseLabels
= append(reverseLabels
, domain
[i
+1:len(domain
)])
366 if len(reverseLabels
) > 0 && len(reverseLabels
[0]) == 0 {
367 // An empty label at the end indicates an absolute value.
371 for _
, label
:= range reverseLabels
{
373 // Empty labels are otherwise invalid.
377 for _
, c
:= range label
{
378 if c
< 33 || c
> 126 {
379 // Invalid character.
385 return reverseLabels
, true
388 func matchEmailConstraint(mailbox rfc2821Mailbox
, constraint
string) (bool, error
) {
389 // If the constraint contains an @, then it specifies an exact mailbox
391 if strings
.Contains(constraint
, "@") {
392 constraintMailbox
, ok
:= parseRFC2821Mailbox(constraint
)
394 return false, fmt
.Errorf("x509: internal error: cannot parse constraint %q", constraint
)
396 return mailbox
.local
== constraintMailbox
.local
&& strings
.EqualFold(mailbox
.domain
, constraintMailbox
.domain
), nil
399 // Otherwise the constraint is like a DNS constraint of the domain part
401 return matchDomainConstraint(mailbox
.domain
, constraint
)
404 func matchURIConstraint(uri
*url
.URL
, constraint
string) (bool, error
) {
405 // https://tools.ietf.org/html/rfc5280#section-4.2.1.10
406 // “a uniformResourceIdentifier that does not include an authority
407 // component with a host name specified as a fully qualified domain
408 // name (e.g., if the URI either does not include an authority
409 // component or includes an authority component in which the host name
410 // is specified as an IP address), then the application MUST reject the
415 return false, fmt
.Errorf("URI with empty host (%q) cannot be matched against constraints", uri
.String())
418 if strings
.Contains(host
, ":") && !strings
.HasSuffix(host
, "]") {
420 host
, _
, err
= net
.SplitHostPort(uri
.Host
)
426 if strings
.HasPrefix(host
, "[") && strings
.HasSuffix(host
, "]") ||
427 net
.ParseIP(host
) != nil {
428 return false, fmt
.Errorf("URI with IP (%q) cannot be matched against constraints", uri
.String())
431 return matchDomainConstraint(host
, constraint
)
434 func matchIPConstraint(ip net
.IP
, constraint
*net
.IPNet
) (bool, error
) {
435 if len(ip
) != len(constraint
.IP
) {
440 if mask
:= constraint
.Mask
[i
]; ip
[i
]&mask
!= constraint
.IP
[i
]&mask
{
448 func matchDomainConstraint(domain
, constraint
string) (bool, error
) {
449 // The meaning of zero length constraints is not specified, but this
450 // code follows NSS and accepts them as matching everything.
451 if len(constraint
) == 0 {
455 domainLabels
, ok
:= domainToReverseLabels(domain
)
457 return false, fmt
.Errorf("x509: internal error: cannot parse domain %q", domain
)
460 // RFC 5280 says that a leading period in a domain name means that at
461 // least one label must be prepended, but only for URI and email
462 // constraints, not DNS constraints. The code also supports that
463 // behaviour for DNS constraints.
465 mustHaveSubdomains
:= false
466 if constraint
[0] == '.' {
467 mustHaveSubdomains
= true
468 constraint
= constraint
[1:]
471 constraintLabels
, ok
:= domainToReverseLabels(constraint
)
473 return false, fmt
.Errorf("x509: internal error: cannot parse domain %q", constraint
)
476 if len(domainLabels
) < len(constraintLabels
) ||
477 (mustHaveSubdomains
&& len(domainLabels
) == len(constraintLabels
)) {
481 for i
, constraintLabel
:= range constraintLabels
{
482 if !strings
.EqualFold(constraintLabel
, domainLabels
[i
]) {
490 // checkNameConstraints checks that c permits a child certificate to claim the
491 // given name, of type nameType. The argument parsedName contains the parsed
492 // form of name, suitable for passing to the match function. The total number
493 // of comparisons is tracked in the given count and should not exceed the given
495 func (c
*Certificate
) checkNameConstraints(count
*int,
496 maxConstraintComparisons
int,
499 parsedName
interface{},
500 match
func(parsedName
, constraint
interface{}) (match
bool, err error
),
501 permitted
, excluded
interface{}) error
{
503 excludedValue
:= reflect
.ValueOf(excluded
)
505 *count
+= excludedValue
.Len()
506 if *count
> maxConstraintComparisons
{
507 return CertificateInvalidError
{c
, TooManyConstraints
, ""}
510 for i
:= 0; i
< excludedValue
.Len(); i
++ {
511 constraint
:= excludedValue
.Index(i
).Interface()
512 match
, err
:= match(parsedName
, constraint
)
514 return CertificateInvalidError
{c
, CANotAuthorizedForThisName
, err
.Error()}
518 return CertificateInvalidError
{c
, CANotAuthorizedForThisName
, fmt
.Sprintf("%s %q is excluded by constraint %q", nameType
, name
, constraint
)}
522 permittedValue
:= reflect
.ValueOf(permitted
)
524 *count
+= permittedValue
.Len()
525 if *count
> maxConstraintComparisons
{
526 return CertificateInvalidError
{c
, TooManyConstraints
, ""}
530 for i
:= 0; i
< permittedValue
.Len(); i
++ {
531 constraint
:= permittedValue
.Index(i
).Interface()
534 if ok
, err
= match(parsedName
, constraint
); err
!= nil {
535 return CertificateInvalidError
{c
, CANotAuthorizedForThisName
, err
.Error()}
544 return CertificateInvalidError
{c
, CANotAuthorizedForThisName
, fmt
.Sprintf("%s %q is not permitted by any constraint", nameType
, name
)}
550 // isValid performs validity checks on c given that it is a candidate to append
551 // to the chain in currentChain.
552 func (c
*Certificate
) isValid(certType
int, currentChain
[]*Certificate
, opts
*VerifyOptions
) error
{
553 if len(c
.UnhandledCriticalExtensions
) > 0 {
554 return UnhandledCriticalExtension
{}
557 if len(currentChain
) > 0 {
558 child
:= currentChain
[len(currentChain
)-1]
559 if !bytes
.Equal(child
.RawIssuer
, c
.RawSubject
) {
560 return CertificateInvalidError
{c
, NameMismatch
, ""}
564 now
:= opts
.CurrentTime
568 if now
.Before(c
.NotBefore
) || now
.After(c
.NotAfter
) {
569 return CertificateInvalidError
{c
, Expired
, ""}
572 maxConstraintComparisons
:= opts
.MaxConstraintComparisions
573 if maxConstraintComparisons
== 0 {
574 maxConstraintComparisons
= 250000
578 var leaf
*Certificate
579 if certType
== intermediateCertificate || certType
== rootCertificate
{
580 if len(currentChain
) == 0 {
581 return errors
.New("x509: internal error: empty chain when appending CA cert")
583 leaf
= currentChain
[0]
586 if (certType
== intermediateCertificate || certType
== rootCertificate
) && c
.hasNameConstraints() {
587 sanExtension
, ok
:= leaf
.getSANExtension()
589 // This is the deprecated, legacy case of depending on
590 // the CN as a hostname. Chains modern enough to be
591 // using name constraints should not be depending on
593 return CertificateInvalidError
{c
, NameConstraintsWithoutSANs
, ""}
596 err
:= forEachSAN(sanExtension
, func(tag
int, data
[]byte) error
{
600 mailbox
, ok
:= parseRFC2821Mailbox(name
)
602 return fmt
.Errorf("x509: cannot parse rfc822Name %q", mailbox
)
605 if err
:= c
.checkNameConstraints(&comparisonCount
, maxConstraintComparisons
, "email address", name
, mailbox
,
606 func(parsedName
, constraint
interface{}) (bool, error
) {
607 return matchEmailConstraint(parsedName
.(rfc2821Mailbox
), constraint
.(string))
608 }, c
.PermittedEmailAddresses
, c
.ExcludedEmailAddresses
); err
!= nil {
614 if _
, ok
:= domainToReverseLabels(name
); !ok
{
615 return fmt
.Errorf("x509: cannot parse dnsName %q", name
)
618 if err
:= c
.checkNameConstraints(&comparisonCount
, maxConstraintComparisons
, "DNS name", name
, name
,
619 func(parsedName
, constraint
interface{}) (bool, error
) {
620 return matchDomainConstraint(parsedName
.(string), constraint
.(string))
621 }, c
.PermittedDNSDomains
, c
.ExcludedDNSDomains
); err
!= nil {
627 uri
, err
:= url
.Parse(name
)
629 return fmt
.Errorf("x509: internal error: URI SAN %q failed to parse", name
)
632 if err
:= c
.checkNameConstraints(&comparisonCount
, maxConstraintComparisons
, "URI", name
, uri
,
633 func(parsedName
, constraint
interface{}) (bool, error
) {
634 return matchURIConstraint(parsedName
.(*url
.URL
), constraint
.(string))
635 }, c
.PermittedURIDomains
, c
.ExcludedURIDomains
); err
!= nil {
641 if l
:= len(ip
); l
!= net
.IPv4len
&& l
!= net
.IPv6len
{
642 return fmt
.Errorf("x509: internal error: IP SAN %x failed to parse", data
)
645 if err
:= c
.checkNameConstraints(&comparisonCount
, maxConstraintComparisons
, "IP address", ip
.String(), ip
,
646 func(parsedName
, constraint
interface{}) (bool, error
) {
647 return matchIPConstraint(parsedName
.(net
.IP
), constraint
.(*net
.IPNet
))
648 }, c
.PermittedIPRanges
, c
.ExcludedIPRanges
); err
!= nil {
653 // Unknown SAN types are ignored.
664 // KeyUsage status flags are ignored. From Engineering Security, Peter
665 // Gutmann: A European government CA marked its signing certificates as
666 // being valid for encryption only, but no-one noticed. Another
667 // European CA marked its signature keys as not being valid for
668 // signatures. A different CA marked its own trusted root certificate
669 // as being invalid for certificate signing. Another national CA
670 // distributed a certificate to be used to encrypt data for the
671 // country’s tax authority that was marked as only being usable for
672 // digital signatures but not for encryption. Yet another CA reversed
673 // the order of the bit flags in the keyUsage due to confusion over
674 // encoding endianness, essentially setting a random keyUsage in
675 // certificates that it issued. Another CA created a self-invalidating
676 // certificate by adding a certificate policy statement stipulating
677 // that the certificate had to be used strictly as specified in the
678 // keyUsage, and a keyUsage containing a flag indicating that the RSA
679 // encryption key could only be used for Diffie-Hellman key agreement.
681 if certType
== intermediateCertificate
&& (!c
.BasicConstraintsValid ||
!c
.IsCA
) {
682 return CertificateInvalidError
{c
, NotAuthorizedToSign
, ""}
685 if c
.BasicConstraintsValid
&& c
.MaxPathLen
>= 0 {
686 numIntermediates
:= len(currentChain
) - 1
687 if numIntermediates
> c
.MaxPathLen
{
688 return CertificateInvalidError
{c
, TooManyIntermediates
, ""}
695 // formatOID formats an ASN.1 OBJECT IDENTIFER in the common, dotted style.
696 func formatOID(oid asn1
.ObjectIdentifier
) string {
698 for i
, v
:= range oid
{
702 ret
+= strconv
.Itoa(v
)
707 // Verify attempts to verify c by building one or more chains from c to a
708 // certificate in opts.Roots, using certificates in opts.Intermediates if
709 // needed. If successful, it returns one or more chains where the first
710 // element of the chain is c and the last element is from opts.Roots.
712 // If opts.Roots is nil and system roots are unavailable the returned error
713 // will be of type SystemRootsError.
715 // Name constraints in the intermediates will be applied to all names claimed
716 // in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim
717 // example.com if an intermediate doesn't permit it, even if example.com is not
718 // the name being validated. Note that DirectoryName constraints are not
721 // Extended Key Usage values are enforced down a chain, so an intermediate or
722 // root that enumerates EKUs prevents a leaf from asserting an EKU not in that
725 // WARNING: this function doesn't do any revocation checking.
726 func (c
*Certificate
) Verify(opts VerifyOptions
) (chains
[][]*Certificate
, err error
) {
727 // Platform-specific verification needs the ASN.1 contents so
728 // this makes the behavior consistent across platforms.
730 return nil, errNotParsed
732 if opts
.Intermediates
!= nil {
733 for _
, intermediate
:= range opts
.Intermediates
.certs
{
734 if len(intermediate
.Raw
) == 0 {
735 return nil, errNotParsed
740 // Use Windows's own verification and chain building.
741 if opts
.Roots
== nil && runtime
.GOOS
== "windows" {
742 return c
.systemVerify(&opts
)
745 if opts
.Roots
== nil {
746 opts
.Roots
= systemRootsPool()
747 if opts
.Roots
== nil {
748 return nil, SystemRootsError
{systemRootsErr
}
752 err
= c
.isValid(leafCertificate
, nil, &opts
)
757 if len(opts
.DNSName
) > 0 {
758 err
= c
.VerifyHostname(opts
.DNSName
)
764 var candidateChains
[][]*Certificate
765 if opts
.Roots
.contains(c
) {
766 candidateChains
= append(candidateChains
, []*Certificate
{c
})
768 if candidateChains
, err
= c
.buildChains(make(map[int][][]*Certificate
), []*Certificate
{c
}, &opts
); err
!= nil {
773 keyUsages
:= opts
.KeyUsages
774 if len(keyUsages
) == 0 {
775 keyUsages
= []ExtKeyUsage
{ExtKeyUsageServerAuth
}
778 // If any key usage is acceptable then we're done.
779 for _
, usage
:= range keyUsages
{
780 if usage
== ExtKeyUsageAny
{
781 return candidateChains
, nil
785 for _
, candidate
:= range candidateChains
{
786 if checkChainForKeyUsage(candidate
, keyUsages
) {
787 chains
= append(chains
, candidate
)
791 if len(chains
) == 0 {
792 return nil, CertificateInvalidError
{c
, IncompatibleUsage
, ""}
798 func appendToFreshChain(chain
[]*Certificate
, cert
*Certificate
) []*Certificate
{
799 n
:= make([]*Certificate
, len(chain
)+1)
805 func (c
*Certificate
) buildChains(cache
map[int][][]*Certificate
, currentChain
[]*Certificate
, opts
*VerifyOptions
) (chains
[][]*Certificate
, err error
) {
806 possibleRoots
, failedRoot
, rootErr
:= opts
.Roots
.findVerifiedParents(c
)
808 for _
, rootNum
:= range possibleRoots
{
809 root
:= opts
.Roots
.certs
[rootNum
]
811 for _
, cert
:= range currentChain
{
812 if cert
.Equal(root
) {
817 err
= root
.isValid(rootCertificate
, currentChain
, opts
)
821 chains
= append(chains
, appendToFreshChain(currentChain
, root
))
824 possibleIntermediates
, failedIntermediate
, intermediateErr
:= opts
.Intermediates
.findVerifiedParents(c
)
826 for _
, intermediateNum
:= range possibleIntermediates
{
827 intermediate
:= opts
.Intermediates
.certs
[intermediateNum
]
828 for _
, cert
:= range currentChain
{
829 if cert
.Equal(intermediate
) {
830 continue nextIntermediate
833 err
= intermediate
.isValid(intermediateCertificate
, currentChain
, opts
)
837 var childChains
[][]*Certificate
838 childChains
, ok
:= cache
[intermediateNum
]
840 childChains
, err
= intermediate
.buildChains(cache
, appendToFreshChain(currentChain
, intermediate
), opts
)
841 cache
[intermediateNum
] = childChains
843 chains
= append(chains
, childChains
...)
850 if len(chains
) == 0 && err
== nil {
852 hintCert
:= failedRoot
854 hintErr
= intermediateErr
855 hintCert
= failedIntermediate
857 err
= UnknownAuthorityError
{c
, hintErr
, hintCert
}
863 func matchHostnames(pattern
, host
string) bool {
864 host
= strings
.TrimSuffix(host
, ".")
865 pattern
= strings
.TrimSuffix(pattern
, ".")
867 if len(pattern
) == 0 ||
len(host
) == 0 {
871 patternParts
:= strings
.Split(pattern
, ".")
872 hostParts
:= strings
.Split(host
, ".")
874 if len(patternParts
) != len(hostParts
) {
878 for i
, patternPart
:= range patternParts
{
879 if i
== 0 && patternPart
== "*" {
882 if patternPart
!= hostParts
[i
] {
890 // toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use
891 // an explicitly ASCII function to avoid any sharp corners resulting from
892 // performing Unicode operations on DNS labels.
893 func toLowerCaseASCII(in
string) string {
894 // If the string is already lower-case then there's nothing to do.
895 isAlreadyLowerCase
:= true
896 for _
, c
:= range in
{
897 if c
== utf8
.RuneError
{
898 // If we get a UTF-8 error then there might be
899 // upper-case ASCII bytes in the invalid sequence.
900 isAlreadyLowerCase
= false
903 if 'A' <= c
&& c
<= 'Z' {
904 isAlreadyLowerCase
= false
909 if isAlreadyLowerCase
{
914 for i
, c
:= range out
{
915 if 'A' <= c
&& c
<= 'Z' {
922 // VerifyHostname returns nil if c is a valid certificate for the named host.
923 // Otherwise it returns an error describing the mismatch.
924 func (c
*Certificate
) VerifyHostname(h
string) error
{
925 // IP addresses may be written in [ ].
927 if len(h
) >= 3 && h
[0] == '[' && h
[len(h
)-1] == ']' {
928 candidateIP
= h
[1 : len(h
)-1]
930 if ip
:= net
.ParseIP(candidateIP
); ip
!= nil {
931 // We only match IP addresses against IP SANs.
932 // https://tools.ietf.org/html/rfc6125#appendix-B.2
933 for _
, candidate
:= range c
.IPAddresses
{
934 if ip
.Equal(candidate
) {
938 return HostnameError
{c
, candidateIP
}
941 lowered
:= toLowerCaseASCII(h
)
943 if c
.hasSANExtension() {
944 for _
, match
:= range c
.DNSNames
{
945 if matchHostnames(toLowerCaseASCII(match
), lowered
) {
949 // If Subject Alt Name is given, we ignore the common name.
950 } else if matchHostnames(toLowerCaseASCII(c
.Subject
.CommonName
), lowered
) {
954 return HostnameError
{c
, h
}
957 func checkChainForKeyUsage(chain
[]*Certificate
, keyUsages
[]ExtKeyUsage
) bool {
958 usages
:= make([]ExtKeyUsage
, len(keyUsages
))
959 copy(usages
, keyUsages
)
965 usagesRemaining
:= len(usages
)
967 // We walk down the list and cross out any usages that aren't supported
968 // by each certificate. If we cross out all the usages, then the chain
972 for i
:= len(chain
) - 1; i
>= 0; i
-- {
974 if len(cert
.ExtKeyUsage
) == 0 && len(cert
.UnknownExtKeyUsage
) == 0 {
975 // The certificate doesn't have any extended key usage specified.
979 for _
, usage
:= range cert
.ExtKeyUsage
{
980 if usage
== ExtKeyUsageAny
{
981 // The certificate is explicitly good for any usage.
986 const invalidUsage ExtKeyUsage
= -1
989 for i
, requestedUsage
:= range usages
{
990 if requestedUsage
== invalidUsage
{
994 for _
, usage
:= range cert
.ExtKeyUsage
{
995 if requestedUsage
== usage
{
996 continue NextRequestedUsage
997 } else if requestedUsage
== ExtKeyUsageServerAuth
&&
998 (usage
== ExtKeyUsageNetscapeServerGatedCrypto ||
999 usage
== ExtKeyUsageMicrosoftServerGatedCrypto
) {
1000 // In order to support COMODO
1001 // certificate chains, we have to
1002 // accept Netscape or Microsoft SGC
1003 // usages as equal to ServerAuth.
1004 continue NextRequestedUsage
1008 usages
[i
] = invalidUsage
1010 if usagesRemaining
== 0 {