Black Lives Matter. Support the Equal Justice Initiative.

Source file src/crypto/x509/verify.go

Documentation: crypto/x509

     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.
     4  
     5  package x509
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	"net"
    12  	"net/url"
    13  	"reflect"
    14  	"runtime"
    15  	"strings"
    16  	"time"
    17  	"unicode/utf8"
    18  )
    19  
    20  type InvalidReason int
    21  
    22  const (
    23  	// NotAuthorizedToSign results when a certificate is signed by another
    24  	// which isn't marked as a CA certificate.
    25  	NotAuthorizedToSign InvalidReason = iota
    26  	// Expired results when a certificate has expired, based on the time
    27  	// given in the VerifyOptions.
    28  	Expired
    29  	// CANotAuthorizedForThisName results when an intermediate or root
    30  	// certificate has a name constraint which doesn't permit a DNS or
    31  	// other name (including IP address) in the leaf certificate.
    32  	CANotAuthorizedForThisName
    33  	// TooManyIntermediates results when a path length constraint is
    34  	// violated.
    35  	TooManyIntermediates
    36  	// IncompatibleUsage results when the certificate's key usage indicates
    37  	// that it may only be used for a different purpose.
    38  	IncompatibleUsage
    39  	// NameMismatch results when the subject name of a parent certificate
    40  	// does not match the issuer name in the child.
    41  	NameMismatch
    42  	// NameConstraintsWithoutSANs is a legacy error and is no longer returned.
    43  	NameConstraintsWithoutSANs
    44  	// UnconstrainedName results when a CA certificate contains permitted
    45  	// name constraints, but leaf certificate contains a name of an
    46  	// unsupported or unconstrained type.
    47  	UnconstrainedName
    48  	// TooManyConstraints results when the number of comparison operations
    49  	// needed to check a certificate exceeds the limit set by
    50  	// VerifyOptions.MaxConstraintComparisions. This limit exists to
    51  	// prevent pathological certificates can consuming excessive amounts of
    52  	// CPU time to verify.
    53  	TooManyConstraints
    54  	// CANotAuthorizedForExtKeyUsage results when an intermediate or root
    55  	// certificate does not permit a requested extended key usage.
    56  	CANotAuthorizedForExtKeyUsage
    57  )
    58  
    59  // CertificateInvalidError results when an odd error occurs. Users of this
    60  // library probably want to handle all these errors uniformly.
    61  type CertificateInvalidError struct {
    62  	Cert   *Certificate
    63  	Reason InvalidReason
    64  	Detail string
    65  }
    66  
    67  func (e CertificateInvalidError) Error() string {
    68  	switch e.Reason {
    69  	case NotAuthorizedToSign:
    70  		return "x509: certificate is not authorized to sign other certificates"
    71  	case Expired:
    72  		return "x509: certificate has expired or is not yet valid: " + e.Detail
    73  	case CANotAuthorizedForThisName:
    74  		return "x509: a root or intermediate certificate is not authorized to sign for this name: " + e.Detail
    75  	case CANotAuthorizedForExtKeyUsage:
    76  		return "x509: a root or intermediate certificate is not authorized for an extended key usage: " + e.Detail
    77  	case TooManyIntermediates:
    78  		return "x509: too many intermediates for path length constraint"
    79  	case IncompatibleUsage:
    80  		return "x509: certificate specifies an incompatible key usage"
    81  	case NameMismatch:
    82  		return "x509: issuer name does not match subject from issuing certificate"
    83  	case NameConstraintsWithoutSANs:
    84  		return "x509: issuer has name constraints but leaf doesn't have a SAN extension"
    85  	case UnconstrainedName:
    86  		return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + e.Detail
    87  	}
    88  	return "x509: unknown error"
    89  }
    90  
    91  // HostnameError results when the set of authorized names doesn't match the
    92  // requested name.
    93  type HostnameError struct {
    94  	Certificate *Certificate
    95  	Host        string
    96  }
    97  
    98  func (h HostnameError) Error() string {
    99  	c := h.Certificate
   100  
   101  	if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) {
   102  		return "x509: certificate relies on legacy Common Name field, use SANs instead"
   103  	}
   104  
   105  	var valid 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"
   110  		}
   111  		for _, san := range c.IPAddresses {
   112  			if len(valid) > 0 {
   113  				valid += ", "
   114  			}
   115  			valid += san.String()
   116  		}
   117  	} else {
   118  		valid = strings.Join(c.DNSNames, ", ")
   119  	}
   120  
   121  	if len(valid) == 0 {
   122  		return "x509: certificate is not valid for any names, but wanted to match " + h.Host
   123  	}
   124  	return "x509: certificate is valid for " + valid + ", not " + h.Host
   125  }
   126  
   127  // UnknownAuthorityError results when the certificate issuer is unknown
   128  type UnknownAuthorityError struct {
   129  	Cert *Certificate
   130  	// hintErr contains an error that may be helpful in determining why an
   131  	// authority wasn't found.
   132  	hintErr error
   133  	// hintCert contains a possible authority certificate that was rejected
   134  	// because of the error in hintErr