Source File
verify.go
Belonging Package
crypto/x509
package x509
import (
)
type CertificateInvalidError struct {
Cert *Certificate
Reason InvalidReason
Detail string
}
func ( CertificateInvalidError) () string {
switch .Reason {
case NotAuthorizedToSign:
return "x509: certificate is not authorized to sign other certificates"
case Expired:
return "x509: certificate has expired or is not yet valid: " + .Detail
case CANotAuthorizedForThisName:
return "x509: a root or intermediate certificate is not authorized to sign for this name: " + .Detail
case CANotAuthorizedForExtKeyUsage:
return "x509: a root or intermediate certificate is not authorized for an extended key usage: " + .Detail
case TooManyIntermediates:
return "x509: too many intermediates for path length constraint"
case IncompatibleUsage:
return "x509: certificate specifies an incompatible key usage"
case NameMismatch:
return "x509: issuer name does not match subject from issuing certificate"
case NameConstraintsWithoutSANs:
return "x509: issuer has name constraints but leaf doesn't have a SAN extension"
case UnconstrainedName:
return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + .Detail
}
return "x509: unknown error"
}
type HostnameError struct {
Certificate *Certificate
Host string
}
func ( HostnameError) () string {
:= .Certificate
if !.hasSANExtension() && matchHostnames(.Subject.CommonName, .Host) {
return "x509: Common Name is not a valid hostname: " + .Subject.CommonName
}
return "x509: certificate relies on legacy Common Name field, " +
"use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0"
}
}
var string
if len(.IPAddresses) == 0 {
return "x509: cannot validate certificate for " + .Host + " because it doesn't contain any IP SANs"
}
for , := range .IPAddresses {
if len() > 0 {
+= ", "
}
+= .String()
}
} else {
if .commonNameAsHostname() {
= .Subject.CommonName
} else {
= strings.Join(.DNSNames, ", ")
}
}
if len() == 0 {
return "x509: certificate is not valid for any names, but wanted to match " + .Host
}
return "x509: certificate is valid for " + + ", not " + .Host
}
type UnknownAuthorityError struct {
hintCert *Certificate
}
func ( UnknownAuthorityError) () string {
:= "x509: certificate signed by unknown authority"
if .hintErr != nil {
:= .hintCert.Subject.CommonName
if len() == 0 {
if len(.hintCert.Subject.Organization) > 0 {
= .hintCert.Subject.Organization[0]
} else {
= "serial:" + .hintCert.SerialNumber.String()
}
}
+= fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", .hintErr, )
}
return
}
type SystemRootsError struct {
Err error
}
func ( SystemRootsError) () string {
:= "x509: failed to load system roots and no roots provided"
if .Err != nil {
return + "; " + .Err.Error()
}
return
}
func ( SystemRootsError) () error { return .Err }
var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate")
type rfc2821Mailbox struct {
local, domain string
}
== 32 ||
== 33 ||
== 127 ||
(1 <= && <= 8) ||
(14 <= && <= 31) ||
(35 <= && <= 91) ||
:
:= [0]
switch {
= [1:]
if len() == 0 {
return , false
}
fallthrough
case ('0' <= && <= '9') ||
('a' <= && <= 'z') ||
('A' <= && <= 'Z') ||
== '!' || == '#' || == '$' || == '%' ||
== '&' || == '\'' || == '*' || == '+' ||
== '-' || == '/' || == '=' || == '?' ||
== '^' || == '_' || == '`' || == '{' ||
== '|' || == '}' || == '~' || == '.':
= append(, [0])
= [1:]
default:
break
}
}
if len() == 0 {
return , false
}
return matchDomainConstraint(.domain, )
}
:= .Host
if len() == 0 {
return false, fmt.Errorf("URI with empty host (%q) cannot be matched against constraints", .String())
}
if strings.Contains(, ":") && !strings.HasSuffix(, "]") {
var error
, _, = net.SplitHostPort(.Host)
if != nil {
return false,
}
}
if strings.HasPrefix(, "[") && strings.HasSuffix(, "]") ||
net.ParseIP() != nil {
return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", .String())
}
return matchDomainConstraint(, )
}
func ( net.IP, *net.IPNet) (bool, error) {
if len() != len(.IP) {
return false, nil
}
for := range {
if := .Mask[]; []& != .IP[]& {
return false, nil
}
}
return true, nil
}
:= false
if [0] == '.' {
= true
= [1:]
}
, := domainToReverseLabels()
if ! {
return false, fmt.Errorf("x509: internal error: cannot parse domain %q", )
}
if len() < len() ||
( && len() == len()) {
return false, nil
}
for , := range {
if !strings.EqualFold(, []) {
return false, nil
}
}
return true, nil
}
func ( *Certificate) ( *int,
int,
string,
string,
interface{},
func(, interface{}) ( bool, error),
, interface{}) error {
:= reflect.ValueOf()
* += .Len()
if * > {
return CertificateInvalidError{, TooManyConstraints, ""}
}
for := 0; < .Len(); ++ {
:= .Index().Interface()
, := (, )
if != nil {
return CertificateInvalidError{, CANotAuthorizedForThisName, .Error()}
}
if {
return CertificateInvalidError{, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is excluded by constraint %q", , , )}
}
}
:= reflect.ValueOf()
* += .Len()
if * > {
return CertificateInvalidError{, TooManyConstraints, ""}
}
:= true
for := 0; < .Len(); ++ {
:= .Index().Interface()
var error
if , = (, ); != nil {
return CertificateInvalidError{, CANotAuthorizedForThisName, .Error()}
}
if {
break
}
}
if ! {
return CertificateInvalidError{, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is not permitted by any constraint", , )}
}
return nil
}
func ( *Certificate) ( int, []*Certificate, *VerifyOptions) error {
if len(.UnhandledCriticalExtensions) > 0 {
return UnhandledCriticalExtension{}
}
if len() > 0 {
:= [len()-1]
if !bytes.Equal(.RawIssuer, .RawSubject) {
return CertificateInvalidError{, NameMismatch, ""}
}
}
:= .CurrentTime
if .IsZero() {
= time.Now()
}
if .Before(.NotBefore) {
return CertificateInvalidError{
Cert: ,
Reason: Expired,
Detail: fmt.Sprintf("current time %s is before %s", .Format(time.RFC3339), .NotBefore.Format(time.RFC3339)),
}
} else if .After(.NotAfter) {
return CertificateInvalidError{
Cert: ,
Reason: Expired,
Detail: fmt.Sprintf("current time %s is after %s", .Format(time.RFC3339), .NotAfter.Format(time.RFC3339)),
}
}
:= .MaxConstraintComparisions
if == 0 {
= 250000
}
:= 0
var *Certificate
if == intermediateCertificate || == rootCertificate {
if len() == 0 {
return errors.New("x509: internal error: empty chain when appending CA cert")
}
= [0]
}
:= ( == intermediateCertificate || == rootCertificate) && .hasNameConstraints()
return CertificateInvalidError{, NameConstraintsWithoutSANs, ""}
} else if && .hasSANExtension() {
:= forEachSAN(.getSANExtension(), func( int, []byte) error {
switch {
case nameTypeEmail:
:= string()
, := parseRFC2821Mailbox()
if ! {
return fmt.Errorf("x509: cannot parse rfc822Name %q", )
}
if := .checkNameConstraints(&, , "email address", , ,
func(, interface{}) (bool, error) {
return matchEmailConstraint(.(rfc2821Mailbox), .(string))
}, .PermittedEmailAddresses, .ExcludedEmailAddresses); != nil {
return
}
case nameTypeDNS:
:= string()
if , := domainToReverseLabels(); ! {
return fmt.Errorf("x509: cannot parse dnsName %q", )
}
if := .checkNameConstraints(&, , "DNS name", , ,
func(, interface{}) (bool, error) {
return matchDomainConstraint(.(string), .(string))
}, .PermittedDNSDomains, .ExcludedDNSDomains); != nil {
return
}
case nameTypeURI:
:= string()
, := url.Parse()
if != nil {
return fmt.Errorf("x509: internal error: URI SAN %q failed to parse", )
}
if := .checkNameConstraints(&, , "URI", , ,
func(, interface{}) (bool, error) {
return matchURIConstraint(.(*url.URL), .(string))
}, .PermittedURIDomains, .ExcludedURIDomains); != nil {
return
}
case nameTypeIP:
:= net.IP()
if := len(); != net.IPv4len && != net.IPv6len {
return fmt.Errorf("x509: internal error: IP SAN %x failed to parse", )
}
if := .checkNameConstraints(&, , "IP address", .String(), ,
func(, interface{}) (bool, error) {
return matchIPConstraint(.(net.IP), .(*net.IPNet))
}, .PermittedIPRanges, .ExcludedIPRanges); != nil {
return
}
if == intermediateCertificate && (!.BasicConstraintsValid || !.IsCA) {
return CertificateInvalidError{, NotAuthorizedToSign, ""}
}
if .BasicConstraintsValid && .MaxPathLen >= 0 {
:= len() - 1
if > .MaxPathLen {
return CertificateInvalidError{, TooManyIntermediates, ""}
}
}
return nil
}
if len(.Raw) == 0 {
return nil, errNotParsed
}
for := 0; < .Intermediates.len(); ++ {
, := .Intermediates.cert()
if != nil {
return nil, fmt.Errorf("crypto/x509: error fetching intermediate: %w", )
}
if len(.Raw) == 0 {
return nil, errNotParsed
}
}
if .Roots == nil && runtime.GOOS == "windows" {
return .systemVerify(&)
}
if .Roots == nil {
.Roots = systemRootsPool()
if .Roots == nil {
return nil, SystemRootsError{systemRootsErr}
}
}
= .isValid(leafCertificate, nil, &)
if != nil {
return
}
if len(.DNSName) > 0 {
= .VerifyHostname(.DNSName)
if != nil {
return
}
}
var [][]*Certificate
if .Roots.contains() {
= append(, []*Certificate{})
} else {
if , = .buildChains(nil, []*Certificate{}, nil, &); != nil {
return nil,
}
}
:= .KeyUsages
if len() == 0 {
= []ExtKeyUsage{ExtKeyUsageServerAuth}
}
for , := range {
if == ExtKeyUsageAny {
return , nil
}
}
for , := range {
if checkChainForKeyUsage(, ) {
= append(, )
}
}
if len() == 0 {
return nil, CertificateInvalidError{, IncompatibleUsage, ""}
}
return , nil
}
func ( []*Certificate, *Certificate) []*Certificate {
:= make([]*Certificate, len()+1)
copy(, )
[len()] =
return
}
const maxChainSignatureChecks = 100
func ( *Certificate) ( map[*Certificate][][]*Certificate, []*Certificate, *int, *VerifyOptions) ( [][]*Certificate, error) {
var (
error
*Certificate
)
:= func( int, *Certificate) {
for , := range {
if .Equal() {
return
}
}
if == nil {
= new(int)
}
*++
if * > maxChainSignatureChecks {
= errors.New("x509: signature check attempts limit reached while verifying certificate chain")
return
}
if := .CheckSignatureFrom(); != nil {
if == nil {
=
=
}
return
}
= .isValid(, , )
if != nil {
return
}
switch {
case rootCertificate:
= append(, appendToFreshChain(, ))
case intermediateCertificate:
if == nil {
= make(map[*Certificate][][]*Certificate)
}
, := []
if ! {
, = .(, appendToFreshChain(, ), , )
[] =
}
= append(, ...)
}
}
for , := range .Roots.findPotentialParents() {
(rootCertificate, )
}
for , := range .Intermediates.findPotentialParents() {
(intermediateCertificate, )
}
if len() > 0 {
= nil
}
if len() == 0 && == nil {
= UnknownAuthorityError{, , }
}
return
}
func ( string) bool { return validHostname(, true) }
func ( string) bool { return validHostname(, false) }
return false
}
continue
}
for , := range {
if 'a' <= && <= 'z' {
continue
}
if '0' <= && <= '9' {
continue
}
if 'A' <= && <= 'Z' {
continue
}
if == '-' && != 0 {
continue
}
func ( *Certificate) () bool {
return !ignoreCN && !.hasSANExtension() && validHostnamePattern(.Subject.CommonName)
}
func (, string) bool {
if == "" || == "." || == "" || == "." {
return false
}
return toLowerCaseASCII() == toLowerCaseASCII()
}
func (, string) bool {
= toLowerCaseASCII()
= toLowerCaseASCII(strings.TrimSuffix(, "."))
if len() == 0 || len() == 0 {
return false
}
:= strings.Split(, ".")
:= strings.Split(, ".")
if len() != len() {
return false
}
for , := range {
if == 0 && == "*" {
continue
}
if != [] {
return false
}
}
return true
}
:= true
for , := range {
for , := range .IPAddresses {
if .Equal() {
return nil
}
}
return HostnameError{, }
}
:= .DNSNames
if .commonNameAsHostname() {
= []string{.Subject.CommonName}
}
:= toLowerCaseASCII() // Save allocations inside the loop.
:= validHostnameInput()
if && validHostnamePattern() {
if matchHostnames(, ) {
return nil
}
} else {
if matchExactly(, ) {
return nil
}
}
}
return HostnameError{, }
}
func ( []*Certificate, []ExtKeyUsage) bool {
:= make([]ExtKeyUsage, len())
copy(, )
if len() == 0 {
return false
}
:= len()
:
for := len() - 1; >= 0; -- {
:= []
continue
}
for , := range .ExtKeyUsage {
continue
}
}
const ExtKeyUsage = -1
:
for , := range {
if == {
continue
}
for , := range .ExtKeyUsage {
if == {
continue
} else if == ExtKeyUsageServerAuth &&
( == ExtKeyUsageNetscapeServerGatedCrypto ||
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |