github.com/hashicorp/vault/sdk@v0.13.0/helper/ocsp/client.go (about)

     1  // Copyright (c) 2017-2022 Snowflake Computing Inc. All rights reserved.
     2  
     3  package ocsp
     4  
     5  import (
     6  	"bytes"
     7  	"context"
     8  	"crypto"
     9  	"crypto/tls"
    10  	"crypto/x509"
    11  	"crypto/x509/pkix"
    12  	"encoding/asn1"
    13  	"encoding/base64"
    14  	"errors"
    15  	"fmt"
    16  	"io"
    17  	"math/big"
    18  	"net"
    19  	"net/http"
    20  	"net/url"
    21  	"strconv"
    22  	"strings"
    23  	"sync"
    24  	"time"
    25  
    26  	"github.com/hashicorp/go-hclog"
    27  	"github.com/hashicorp/go-multierror"
    28  	"github.com/hashicorp/go-retryablehttp"
    29  	lru "github.com/hashicorp/golang-lru"
    30  	"github.com/hashicorp/vault/sdk/helper/certutil"
    31  	"golang.org/x/crypto/ocsp"
    32  )
    33  
    34  //go:generate enumer -type=FailOpenMode -trimprefix=FailOpen
    35  
    36  // FailOpenMode is OCSP fail open mode. FailOpenTrue by default and may
    37  // set to ocspModeFailClosed for fail closed mode
    38  type FailOpenMode uint32
    39  
    40  type requestFunc func(method, urlStr string, body interface{}) (*retryablehttp.Request, error)
    41  
    42  type clientInterface interface {
    43  	Do(req *retryablehttp.Request) (*http.Response, error)
    44  }
    45  
    46  const (
    47  	httpHeaderContentType   = "Content-Type"
    48  	httpHeaderAccept        = "accept"
    49  	httpHeaderContentLength = "Content-Length"
    50  	httpHeaderHost          = "Host"
    51  	ocspRequestContentType  = "application/ocsp-request"
    52  	ocspResponseContentType = "application/ocsp-response"
    53  )
    54  
    55  const (
    56  	ocspFailOpenNotSet FailOpenMode = iota
    57  	// FailOpenTrue represents OCSP fail open mode.
    58  	FailOpenTrue
    59  	// FailOpenFalse represents OCSP fail closed mode.
    60  	FailOpenFalse
    61  )
    62  
    63  const (
    64  	ocspModeFailOpen   = "FAIL_OPEN"
    65  	ocspModeFailClosed = "FAIL_CLOSED"
    66  	ocspModeInsecure   = "INSECURE"
    67  )
    68  
    69  const ocspCacheKey = "ocsp_cache"
    70  
    71  const (
    72  	// defaultOCSPResponderTimeout is the total timeout for OCSP responder.
    73  	defaultOCSPResponderTimeout = 10 * time.Second
    74  )
    75  
    76  const (
    77  	// cacheExpire specifies cache data expiration time in seconds.
    78  	cacheExpire = float64(24 * 60 * 60)
    79  )
    80  
    81  // ErrOcspIssuerVerification indicates an error verifying the identity of an OCSP response occurred
    82  type ErrOcspIssuerVerification struct {
    83  	Err error
    84  }
    85  
    86  func (e *ErrOcspIssuerVerification) Error() string {
    87  	return fmt.Sprintf("ocsp response verification error: %v", e.Err)
    88  }
    89  
    90  type ocspCachedResponse struct {
    91  	time       float64
    92  	producedAt float64
    93  	thisUpdate float64
    94  	nextUpdate float64
    95  	status     ocspStatusCode
    96  }
    97  
    98  type Client struct {
    99  	// caRoot includes the CA certificates.
   100  	caRoot map[string]*x509.Certificate
   101  	// certPool includes the CA certificates.
   102  	certPool              *x509.CertPool
   103  	ocspResponseCache     *lru.TwoQueueCache
   104  	ocspResponseCacheLock sync.RWMutex
   105  	// cacheUpdated is true if the memory cache is updated
   106  	cacheUpdated bool
   107  	logFactory   func() hclog.Logger
   108  }
   109  
   110  type ocspStatusCode int
   111  
   112  type ocspStatus struct {
   113  	code ocspStatusCode
   114  	err  error
   115  }
   116  
   117  const (
   118  	ocspSuccess                ocspStatusCode = 0
   119  	ocspStatusGood             ocspStatusCode = -1
   120  	ocspStatusRevoked          ocspStatusCode = -2
   121  	ocspStatusUnknown          ocspStatusCode = -3
   122  	ocspStatusOthers           ocspStatusCode = -4
   123  	ocspFailedDecomposeRequest ocspStatusCode = -5
   124  	ocspInvalidValidity        ocspStatusCode = -6
   125  	ocspMissedCache            ocspStatusCode = -7
   126  	ocspCacheExpired           ocspStatusCode = -8
   127  )
   128  
   129  // copied from crypto/ocsp.go
   130  type certID struct {
   131  	HashAlgorithm pkix.AlgorithmIdentifier
   132  	NameHash      []byte
   133  	IssuerKeyHash []byte
   134  	SerialNumber  *big.Int
   135  }
   136  
   137  // cache key
   138  type certIDKey struct {
   139  	NameHash      string
   140  	IssuerKeyHash string
   141  	SerialNumber  string
   142  }
   143  
   144  // copied from crypto/ocsp
   145  var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{
   146  	crypto.SHA1:   asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}),
   147  	crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}),
   148  	crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}),
   149  	crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}),
   150  }
   151  
   152  // copied from crypto/ocsp
   153  func getOIDFromHashAlgorithm(target crypto.Hash) (asn1.ObjectIdentifier, error) {
   154  	for hash, oid := range hashOIDs {
   155  		if hash == target {
   156  			return oid, nil
   157  		}
   158  	}
   159  	return nil, fmt.Errorf("no valid OID is found for the hash algorithm: %v", target)
   160  }
   161  
   162  func (c *Client) ClearCache() {
   163  	c.ocspResponseCache.Purge()
   164  }
   165  
   166  func (c *Client) getHashAlgorithmFromOID(target pkix.AlgorithmIdentifier) crypto.Hash {
   167  	for hash, oid := range hashOIDs {
   168  		if oid.Equal(target.Algorithm) {
   169  			return hash
   170  		}
   171  	}
   172  	// no valid hash algorithm is found for the oid. Falling back to SHA1
   173  	return crypto.SHA1
   174  }
   175  
   176  // isInValidityRange checks the validity times of the OCSP response making sure
   177  // that thisUpdate and nextUpdate values are bounded within currTime
   178  func isInValidityRange(currTime time.Time, ocspRes *ocsp.Response) bool {
   179  	thisUpdate := ocspRes.ThisUpdate
   180  
   181  	// If the thisUpdate value in the OCSP response wasn't set or greater than current time fail this check
   182  	if thisUpdate.IsZero() || thisUpdate.After(currTime) {
   183  		return false
   184  	}
   185  
   186  	nextUpdate := ocspRes.NextUpdate
   187  	if nextUpdate.IsZero() {
   188  		// We don't have a nextUpdate field set, assume we are okay.
   189  		return true
   190  	}
   191  
   192  	if currTime.After(nextUpdate) || thisUpdate.After(nextUpdate) {
   193  		return false
   194  	}
   195  
   196  	return true
   197  }
   198  
   199  func extractCertIDKeyFromRequest(ocspReq []byte) (*certIDKey, *ocspStatus) {
   200  	r, err := ocsp.ParseRequest(ocspReq)
   201  	if err != nil {
   202  		return nil, &ocspStatus{
   203  			code: ocspFailedDecomposeRequest,
   204  			err:  err,
   205  		}
   206  	}
   207  
   208  	// encode CertID, used as a key in the cache
   209  	encodedCertID := &certIDKey{
   210  		base64.StdEncoding.EncodeToString(r.IssuerNameHash),
   211  		base64.StdEncoding.EncodeToString(r.IssuerKeyHash),
   212  		r.SerialNumber.String(),
   213  	}
   214  	return encodedCertID, &ocspStatus{
   215  		code: ocspSuccess,
   216  	}
   217  }
   218  
   219  func (c *Client) encodeCertIDKey(certIDKeyBase64 string) (*certIDKey, error) {
   220  	r, err := base64.StdEncoding.DecodeString(certIDKeyBase64)
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  	var cid certID
   225  	rest, err := asn1.Unmarshal(r, &cid)
   226  	if err != nil {
   227  		// error in parsing
   228  		return nil, err
   229  	}
   230  	if len(rest) > 0 {
   231  		// extra bytes to the end
   232  		return nil, err
   233  	}
   234  	return &certIDKey{
   235  		base64.StdEncoding.EncodeToString(cid.NameHash),
   236  		base64.StdEncoding.EncodeToString(cid.IssuerKeyHash),
   237  		cid.SerialNumber.String(),
   238  	}, nil
   239  }
   240  
   241  func (c *Client) checkOCSPResponseCache(encodedCertID *certIDKey, subject, issuer *x509.Certificate, config *VerifyConfig) (*ocspStatus, error) {
   242  	c.ocspResponseCacheLock.RLock()
   243  	var cacheValue *ocspCachedResponse
   244  	v, ok := c.ocspResponseCache.Get(*encodedCertID)
   245  	if ok {
   246  		cacheValue = v.(*ocspCachedResponse)
   247  	}
   248  	c.ocspResponseCacheLock.RUnlock()
   249  
   250  	status, err := c.extractOCSPCacheResponseValue(cacheValue, subject, issuer, config)
   251  	if err != nil {
   252  		return nil, err
   253  	}
   254  	if !isValidOCSPStatus(status.code) {
   255  		c.deleteOCSPCache(encodedCertID)
   256  	}
   257  	return status, err
   258  }
   259  
   260  func (c *Client) deleteOCSPCache(encodedCertID *certIDKey) {
   261  	c.ocspResponseCacheLock.Lock()
   262  	c.ocspResponseCache.Remove(*encodedCertID)
   263  	c.cacheUpdated = true
   264  	c.ocspResponseCacheLock.Unlock()
   265  }
   266  
   267  func validateOCSP(conf *VerifyConfig, ocspRes *ocsp.Response) (*ocspStatus, error) {
   268  	curTime := time.Now()
   269  
   270  	if ocspRes == nil {
   271  		return nil, errors.New("OCSP Response is nil")
   272  	}
   273  	if !isInValidityRange(curTime, ocspRes) {
   274  		return &ocspStatus{
   275  			code: ocspInvalidValidity,
   276  			err:  fmt.Errorf("invalid validity: producedAt: %v, thisUpdate: %v, nextUpdate: %v", ocspRes.ProducedAt, ocspRes.ThisUpdate, ocspRes.NextUpdate),
   277  		}, nil
   278  	}
   279  
   280  	if conf.OcspThisUpdateMaxAge > 0 && curTime.Sub(ocspRes.ThisUpdate) > conf.OcspThisUpdateMaxAge {
   281  		return &ocspStatus{
   282  			code: ocspInvalidValidity,
   283  			err:  fmt.Errorf("invalid validity: thisUpdate: %v is greater than max age: %s", ocspRes.ThisUpdate, conf.OcspThisUpdateMaxAge),
   284  		}, nil
   285  	}
   286  	return returnOCSPStatus(ocspRes), nil
   287  }
   288  
   289  func returnOCSPStatus(ocspRes *ocsp.Response) *ocspStatus {
   290  	switch ocspRes.Status {
   291  	case ocsp.Good:
   292  		return &ocspStatus{
   293  			code: ocspStatusGood,
   294  			err:  nil,
   295  		}
   296  	case ocsp.Revoked:
   297  		return &ocspStatus{
   298  			code: ocspStatusRevoked,
   299  		}
   300  	case ocsp.Unknown:
   301  		return &ocspStatus{
   302  			code: ocspStatusUnknown,
   303  			err:  errors.New("OCSP status unknown."),
   304  		}
   305  	default:
   306  		return &ocspStatus{
   307  			code: ocspStatusOthers,
   308  			err:  fmt.Errorf("OCSP others. %v", ocspRes.Status),
   309  		}
   310  	}
   311  }
   312  
   313  // retryOCSP is the second level of retry method if the returned contents are corrupted. It often happens with OCSP
   314  // serer and retry helps.
   315  func (c *Client) retryOCSP(
   316  	ctx context.Context,
   317  	client clientInterface,
   318  	req requestFunc,
   319  	ocspHost *url.URL,
   320  	headers map[string]string,
   321  	reqBody []byte,
   322  	subject,
   323  	issuer *x509.Certificate,
   324  ) (ocspRes *ocsp.Response, ocspResBytes []byte, ocspS *ocspStatus, retErr error) {
   325  	doRequest := func(request *retryablehttp.Request) (*http.Response, error) {
   326  		if request != nil {
   327  			request = request.WithContext(ctx)
   328  			for k, v := range headers {
   329  				request.Header[k] = append(request.Header[k], v)
   330  			}
   331  		}
   332  		res, err := client.Do(request)
   333  		if err != nil {
   334  			return nil, err
   335  		}
   336  		c.Logger().Debug("StatusCode from OCSP Server:", "statusCode", res.StatusCode)
   337  		return res, err
   338  	}
   339  
   340  	for _, method := range []string{"GET", "POST"} {
   341  		reqUrl := *ocspHost
   342  		var body []byte
   343  
   344  		switch method {
   345  		case "GET":
   346  			reqUrl.Path = reqUrl.Path + "/" + base64.StdEncoding.EncodeToString(reqBody)
   347  		case "POST":
   348  			body = reqBody
   349  		default:
   350  			// Programming error; all request/systems errors are multierror
   351  			// and appended.
   352  			return nil, nil, nil, fmt.Errorf("unknown request method: %v", method)
   353  		}
   354  
   355  		var res *http.Response
   356  		request, err := req(method, reqUrl.String(), bytes.NewBuffer(body))
   357  		if err != nil {
   358  			err = fmt.Errorf("error creating %v request: %w", method, err)
   359  			retErr = multierror.Append(retErr, err)
   360  			continue
   361  		}
   362  		if res, err = doRequest(request); err != nil {
   363  			err = fmt.Errorf("error doing %v request: %w", method, err)
   364  			retErr = multierror.Append(retErr, err)
   365  			continue
   366  		} else {
   367  			defer res.Body.Close()
   368  		}
   369  
   370  		if res.StatusCode != http.StatusOK {
   371  			err = fmt.Errorf("HTTP code is not OK on %v request. %v: %v", method, res.StatusCode, res.Status)
   372  			retErr = multierror.Append(retErr, err)
   373  			continue
   374  		}
   375  
   376  		ocspResBytes, err = io.ReadAll(res.Body)
   377  		if err != nil {
   378  			err = fmt.Errorf("error reading %v request body: %w", method, err)
   379  			retErr = multierror.Append(retErr, err)
   380  			continue
   381  		}
   382  
   383  		// Reading an OCSP response shouldn't be fatal. A misconfigured
   384  		// endpoint might return invalid results for e.g., GET but return
   385  		// valid results for POST on retry. This could happen if e.g., the
   386  		// server responds with JSON.
   387  		ocspRes, err = ocsp.ParseResponse(ocspResBytes /*issuer = */, nil /* !!unsafe!! */)
   388  		if err != nil {
   389  			err = fmt.Errorf("error parsing %v OCSP response: %w", method, err)
   390  			retErr = multierror.Append(retErr, err)
   391  			continue
   392  		}
   393  
   394  		if err := validateOCSPParsedResponse(ocspRes, subject, issuer); err != nil {
   395  			err = fmt.Errorf("error validating %v OCSP response: %w", method, err)
   396  
   397  			if IsOcspVerificationError(err) {
   398  				// We want to immediately give up on a verification error to a response
   399  				// and inform the user something isn't correct
   400  				return nil, nil, nil, err
   401  			}
   402  
   403  			retErr = multierror.Append(retErr, err)
   404  			// Clear the response out as we can't trust it.
   405  			ocspRes = nil
   406  			continue
   407  		}
   408  
   409  		// While we haven't validated the signature on the OCSP response, we
   410  		// got what we presume is a definitive answer and simply changing
   411  		// methods will likely not help us in that regard. Use this status
   412  		// to return without retrying another method, when it looks definitive.
   413  		//
   414  		// We don't accept ocsp.Unknown here: presumably, we could've hit a CDN
   415  		// with static mapping of request->responses, with a default "unknown"
   416  		// handler for everything else. By retrying here, we use POST, which
   417  		// could hit a live OCSP server with fresher data than the cached CDN.
   418  		if ocspRes.Status == ocsp.Good || ocspRes.Status == ocsp.Revoked {
   419  			break
   420  		}
   421  
   422  		// Here, we didn't have a valid response. Even though we didn't get an
   423  		// error, we should inform the user that this (valid-looking) response
   424  		// wasn't utilized.
   425  		err = fmt.Errorf("fetched %v OCSP response of status %v; wanted either good (%v) or revoked (%v)", method, ocspRes.Status, ocsp.Good, ocsp.Revoked)
   426  		retErr = multierror.Append(retErr, err)
   427  	}
   428  
   429  	if ocspRes != nil && ocspResBytes != nil {
   430  		// Clear retErr, because we have one parseable-but-maybe-not-quite-correct
   431  		// OCSP response.
   432  		retErr = nil
   433  		ocspS = &ocspStatus{
   434  			code: ocspSuccess,
   435  		}
   436  	}
   437  
   438  	return
   439  }
   440  
   441  func IsOcspVerificationError(err error) bool {
   442  	errOcspIssuer := &ErrOcspIssuerVerification{}
   443  	return errors.As(err, &errOcspIssuer)
   444  }
   445  
   446  func validateOCSPParsedResponse(ocspRes *ocsp.Response, subject, issuer *x509.Certificate) error {
   447  	// Above, we use the unsafe issuer=nil parameter to ocsp.ParseResponse
   448  	// because Go's library does the wrong thing.
   449  	//
   450  	// Here, we lack a full chain, but we know we trust the parent issuer,
   451  	// so if the Go library incorrectly discards useful certificates, we
   452  	// likely cannot verify this without passing through the full chain
   453  	// back to the root.
   454  	//
   455  	// Instead, take one of two paths: 1. if there is no certificate in
   456  	// the ocspRes, verify the OCSP response directly with our trusted
   457  	// issuer certificate, or 2. if there is a certificate, either verify
   458  	// it directly matches our trusted issuer certificate, or verify it
   459  	// is signed by our trusted issuer certificate.
   460  	//
   461  	// See also: https://github.com/golang/go/issues/59641
   462  	//
   463  	// This addresses the !!unsafe!! behavior above.
   464  	if ocspRes.Certificate == nil {
   465  		if err := ocspRes.CheckSignatureFrom(issuer); err != nil {
   466  			return &ErrOcspIssuerVerification{fmt.Errorf("error directly verifying signature: %w", err)}
   467  		}
   468  	} else {
   469  		// Because we have at least one certificate here, we know that
   470  		// Go's ocsp library verified the signature from this certificate
   471  		// onto the response and it was valid. Now we need to know we trust
   472  		// this certificate. There's two ways we can do this:
   473  		//
   474  		// 1. Via confirming issuer == ocspRes.Certificate, or
   475  		// 2. Via confirming ocspRes.Certificate.CheckSignatureFrom(issuer).
   476  		if !bytes.Equal(issuer.Raw, ocspRes.Raw) {
   477  			// 1 must not hold, so 2 holds; verify the signature.
   478  			if err := ocspRes.Certificate.CheckSignatureFrom(issuer); err != nil {
   479  				return &ErrOcspIssuerVerification{fmt.Errorf("error checking chain of trust %v failed: %w", issuer.Subject.String(), err)}
   480  			}
   481  
   482  			// Verify the OCSP responder certificate is still valid and
   483  			// contains the required EKU since it is a delegated OCSP
   484  			// responder certificate.
   485  			if ocspRes.Certificate.NotAfter.Before(time.Now()) {
   486  				return &ErrOcspIssuerVerification{fmt.Errorf("error checking delegated OCSP responder OCSP response: certificate has expired")}
   487  			}
   488  			haveEKU := false
   489  			for _, ku := range ocspRes.Certificate.ExtKeyUsage {
   490  				if ku == x509.ExtKeyUsageOCSPSigning {
   491  					haveEKU = true
   492  					break
   493  				}
   494  			}
   495  			if !haveEKU {
   496  				return &ErrOcspIssuerVerification{fmt.Errorf("error checking delegated OCSP responder: certificate lacks the OCSP Signing EKU")}
   497  			}
   498  		}
   499  	}
   500  
   501  	// Verify the response was for our original subject
   502  	if ocspRes.SerialNumber == nil || subject.SerialNumber == nil {
   503  		return &ErrOcspIssuerVerification{fmt.Errorf("OCSP response or cert did not contain a serial number")}
   504  	}
   505  	if ocspRes.SerialNumber.Cmp(subject.SerialNumber) != 0 {
   506  		return &ErrOcspIssuerVerification{fmt.Errorf(
   507  			"OCSP response serial number %s did not match the leaf certificate serial number %s",
   508  			certutil.GetHexFormatted(ocspRes.SerialNumber.Bytes(), ":"),
   509  			certutil.GetHexFormatted(subject.SerialNumber.Bytes(), ":"))}
   510  	}
   511  
   512  	return nil
   513  }
   514  
   515  // GetRevocationStatus checks the certificate revocation status for subject using issuer certificate.
   516  func (c *Client) GetRevocationStatus(ctx context.Context, subject, issuer *x509.Certificate, conf *VerifyConfig) (*ocspStatus, error) {
   517  	status, ocspReq, encodedCertID, err := c.validateWithCache(subject, issuer, conf)
   518  	if err != nil {
   519  		return nil, err
   520  	}
   521  	if isValidOCSPStatus(status.code) {
   522  		return status, nil
   523  	}
   524  	if ocspReq == nil || encodedCertID == nil {
   525  		return status, nil
   526  	}
   527  	c.Logger().Debug("cache missed", "server", subject.OCSPServer)
   528  	if len(subject.OCSPServer) == 0 && len(conf.OcspServersOverride) == 0 {
   529  		return nil, fmt.Errorf("no OCSP responder URL: subject: %v", subject.Subject)
   530  	}
   531  	ocspHosts := subject.OCSPServer
   532  	if len(conf.OcspServersOverride) > 0 {
   533  		ocspHosts = conf.OcspServersOverride
   534  	}
   535  
   536  	var wg sync.WaitGroup
   537  
   538  	ocspStatuses := make([]*ocspStatus, len(ocspHosts))
   539  	ocspResponses := make([]*ocsp.Response, len(ocspHosts))
   540  	errors := make([]error, len(ocspHosts))
   541  
   542  	for i, ocspHost := range ocspHosts {
   543  		u, err := url.Parse(ocspHost)
   544  		if err != nil {
   545  			return nil, err
   546  		}
   547  
   548  		hostname := u.Hostname()
   549  
   550  		headers := make(map[string]string)
   551  		headers[httpHeaderContentType] = ocspRequestContentType
   552  		headers[httpHeaderAccept] = ocspResponseContentType
   553  		headers[httpHeaderContentLength] = strconv.Itoa(len(ocspReq))
   554  		headers[httpHeaderHost] = hostname
   555  		timeout := defaultOCSPResponderTimeout
   556  
   557  		ocspClient := retryablehttp.NewClient()
   558  		ocspClient.RetryMax = conf.OcspMaxRetries
   559  		ocspClient.HTTPClient.Timeout = timeout
   560  		ocspClient.HTTPClient.Transport = newInsecureOcspTransport(conf.ExtraCas)
   561  
   562  		doRequest := func(i int) error {
   563  			if conf.QueryAllServers {
   564  				defer wg.Done()
   565  			}
   566  			ocspRes, _, ocspS, err := c.retryOCSP(
   567  				ctx, ocspClient, retryablehttp.NewRequest, u, headers, ocspReq, subject, issuer)
   568  			ocspResponses[i] = ocspRes
   569  			if err != nil {
   570  				errors[i] = err
   571  				return err
   572  			}
   573  			if ocspS.code != ocspSuccess {
   574  				ocspStatuses[i] = ocspS
   575  				return nil
   576  			}
   577  
   578  			ret, err := validateOCSP(conf, ocspRes)
   579  			if err != nil {
   580  				errors[i] = err
   581  				return err
   582  			}
   583  			if isValidOCSPStatus(ret.code) {
   584  				ocspStatuses[i] = ret
   585  			} else if ret.err != nil {
   586  				// This check needs to occur after the isValidOCSPStatus as the unknown
   587  				// status also sets an err value within ret.
   588  				errors[i] = ret.err
   589  				return ret.err
   590  			}
   591  			return nil
   592  		}
   593  		if conf.QueryAllServers {
   594  			wg.Add(1)
   595  			go doRequest(i)
   596  		} else {
   597  			err = doRequest(i)
   598  			if err == nil {
   599  				break
   600  			}
   601  		}
   602  	}
   603  	if conf.QueryAllServers {
   604  		wg.Wait()
   605  	}
   606  	// Good by default
   607  	var ret *ocspStatus
   608  	ocspRes := ocspResponses[0]
   609  	var firstError error
   610  	for i := range ocspHosts {
   611  		if errors[i] != nil {
   612  			if IsOcspVerificationError(errors[i]) {
   613  				return nil, errors[i]
   614  			}
   615  			if firstError == nil {
   616  				firstError = errors[i]
   617  			}
   618  		} else if ocspStatuses[i] != nil {
   619  			switch ocspStatuses[i].code {
   620  			case ocspStatusRevoked:
   621  				ret = ocspStatuses[i]
   622  				ocspRes = ocspResponses[i]
   623  				break
   624  			case ocspStatusGood:
   625  				// Use this response only if we don't have a status already, or if what we have was unknown
   626  				if ret == nil || ret.code == ocspStatusUnknown {
   627  					ret = ocspStatuses[i]
   628  					ocspRes = ocspResponses[i]
   629  				}
   630  			case ocspStatusUnknown:
   631  				if ret == nil {
   632  					// We may want to use this as the overall result
   633  					ret = ocspStatuses[i]
   634  					ocspRes = ocspResponses[i]
   635  				}
   636  			}
   637  		}
   638  	}
   639  
   640  	// If querying all servers is enabled, and we have an error from a host, we can't trust
   641  	// a good status from the other as we can't confirm the other server would have returned the
   642  	// same response, we do allow revoke responses through
   643  	if conf.QueryAllServers && firstError != nil && (ret != nil && ret.code == ocspStatusGood) {
   644  		return nil, fmt.Errorf("encountered an error on a server, "+
   645  			"ignoring good response status as ocsp_query_all_servers is set to true: %w", firstError)
   646  	}
   647  
   648  	// If no server reported the cert revoked, but we did have an error, report it
   649  	if (ret == nil || ret.code == ocspStatusUnknown) && firstError != nil {
   650  		return nil, firstError
   651  	}
   652  	// An extra safety in case ret and firstError are both nil
   653  	if ret == nil {
   654  		return nil, fmt.Errorf("failed to extract a known response code or error from the OCSP server")
   655  	}
   656  
   657  	// otherwise ret should contain a response for the overall request
   658  	if !isValidOCSPStatus(ret.code) {
   659  		return ret, nil
   660  	}
   661  
   662  	if ocspRes.NextUpdate.IsZero() {
   663  		// We should not cache values with no NextUpdate values
   664  		return ret, nil
   665  	}
   666  
   667  	v := ocspCachedResponse{
   668  		status:     ret.code,
   669  		time:       float64(time.Now().UTC().Unix()),
   670  		producedAt: float64(ocspRes.ProducedAt.UTC().Unix()),
   671  		thisUpdate: float64(ocspRes.ThisUpdate.UTC().Unix()),
   672  		nextUpdate: float64(ocspRes.NextUpdate.UTC().Unix()),
   673  	}
   674  
   675  	c.ocspResponseCacheLock.Lock()
   676  	c.ocspResponseCache.Add(*encodedCertID, &v)
   677  	c.cacheUpdated = true
   678  	c.ocspResponseCacheLock.Unlock()
   679  	return ret, nil
   680  }
   681  
   682  func isValidOCSPStatus(status ocspStatusCode) bool {
   683  	return status == ocspStatusGood || status == ocspStatusRevoked || status == ocspStatusUnknown
   684  }
   685  
   686  type VerifyConfig struct {
   687  	OcspEnabled          bool
   688  	ExtraCas             []*x509.Certificate
   689  	OcspServersOverride  []string
   690  	OcspFailureMode      FailOpenMode
   691  	QueryAllServers      bool
   692  	OcspThisUpdateMaxAge time.Duration
   693  	OcspMaxRetries       int
   694  }
   695  
   696  // VerifyLeafCertificate verifies just the subject against it's direct issuer
   697  func (c *Client) VerifyLeafCertificate(ctx context.Context, subject, issuer *x509.Certificate, conf *VerifyConfig) error {
   698  	results, err := c.GetRevocationStatus(ctx, subject, issuer, conf)
   699  	if err != nil {
   700  		return err
   701  	}
   702  	if results.code == ocspStatusGood {
   703  		return nil
   704  	} else {
   705  		serial := issuer.SerialNumber
   706  		serialHex := strings.TrimSpace(certutil.GetHexFormatted(serial.Bytes(), ":"))
   707  		if results.code == ocspStatusRevoked {
   708  			return fmt.Errorf("certificate with serial number %s has been revoked", serialHex)
   709  		} else if conf.OcspFailureMode == FailOpenFalse {
   710  			return fmt.Errorf("unknown OCSP status for cert with serial number %s", strings.TrimSpace(certutil.GetHexFormatted(serial.Bytes(), ":")))
   711  		} else {
   712  			c.Logger().Warn("could not validate OCSP status for cert, but continuing in fail open mode", "serial", serialHex)
   713  		}
   714  	}
   715  	return nil
   716  }
   717  
   718  // VerifyPeerCertificate verifies all of certificate revocation status
   719  func (c *Client) VerifyPeerCertificate(ctx context.Context, verifiedChains [][]*x509.Certificate, conf *VerifyConfig) error {
   720  	for i := 0; i < len(verifiedChains); i++ {
   721  		// Certificate signed by Root CA. This should be one before the last in the Certificate Chain
   722  		numberOfNoneRootCerts := len(verifiedChains[i]) - 1
   723  		if !verifiedChains[i][numberOfNoneRootCerts].IsCA || string(verifiedChains[i][numberOfNoneRootCerts].RawIssuer) != string(verifiedChains[i][numberOfNoneRootCerts].RawSubject) {
   724  			// Check if the last Non Root Cert is also a CA or is self signed.
   725  			// if the last certificate is not, add it to the list
   726  			rca := c.caRoot[string(verifiedChains[i][numberOfNoneRootCerts].RawIssuer)]
   727  			if rca == nil {
   728  				return fmt.Errorf("failed to find root CA. pkix.name: %v", verifiedChains[i][numberOfNoneRootCerts].Issuer)
   729  			}
   730  			verifiedChains[i] = append(verifiedChains[i], rca)
   731  			numberOfNoneRootCerts++
   732  		}
   733  		results, err := c.GetAllRevocationStatus(ctx, verifiedChains[i], conf)
   734  		if err != nil {
   735  			return err
   736  		}
   737  		if r := c.canEarlyExitForOCSP(results, numberOfNoneRootCerts, conf); r != nil {
   738  			return r.err
   739  		}
   740  	}
   741  
   742  	return nil
   743  }
   744  
   745  func (c *Client) canEarlyExitForOCSP(results []*ocspStatus, chainSize int, conf *VerifyConfig) *ocspStatus {
   746  	msg := ""
   747  	if conf.OcspFailureMode == FailOpenFalse {
   748  		// Fail closed. any error is returned to stop connection
   749  		for _, r := range results {
   750  			if r.err != nil {
   751  				return r
   752  			}
   753  		}
   754  	} else {
   755  		// Fail open and all results are valid.
   756  		allValid := len(results) == chainSize
   757  		for _, r := range results {
   758  			if !isValidOCSPStatus(r.code) {
   759  				allValid = false
   760  				break
   761  			}
   762  		}
   763  		for _, r := range results {
   764  			if allValid && r.code == ocspStatusRevoked {
   765  				return r
   766  			}
   767  			if r != nil && r.code != ocspStatusGood && r.err != nil {
   768  				msg += "" + r.err.Error()
   769  			}
   770  		}
   771  	}
   772  	if len(msg) > 0 {
   773  		c.Logger().Warn(
   774  			"OCSP is set to fail-open, and could not retrieve OCSP based revocation checking but proceeding.", "detail", msg)
   775  	}
   776  	return nil
   777  }
   778  
   779  func (c *Client) validateWithCacheForAllCertificates(verifiedChains []*x509.Certificate, config *VerifyConfig) (bool, error) {
   780  	n := len(verifiedChains) - 1
   781  	for j := 0; j < n; j++ {
   782  		subject := verifiedChains[j]
   783  		issuer := verifiedChains[j+1]
   784  		status, _, _, err := c.validateWithCache(subject, issuer, config)
   785  		if err != nil {
   786  			return false, err
   787  		}
   788  		if !isValidOCSPStatus(status.code) {
   789  			return false, nil
   790  		}
   791  	}
   792  	return true, nil
   793  }
   794  
   795  func (c *Client) validateWithCache(subject, issuer *x509.Certificate, config *VerifyConfig) (*ocspStatus, []byte, *certIDKey, error) {
   796  	ocspReq, err := ocsp.CreateRequest(subject, issuer, &ocsp.RequestOptions{})
   797  	if err != nil {
   798  		return nil, nil, nil, fmt.Errorf("failed to create OCSP request from the certificates: %v", err)
   799  	}
   800  	encodedCertID, ocspS := extractCertIDKeyFromRequest(ocspReq)
   801  	if ocspS.code != ocspSuccess {
   802  		return nil, nil, nil, fmt.Errorf("failed to extract CertID from OCSP Request: %v", err)
   803  	}
   804  	status, err := c.checkOCSPResponseCache(encodedCertID, subject, issuer, config)
   805  	if err != nil {
   806  		return nil, nil, nil, err
   807  	}
   808  	return status, ocspReq, encodedCertID, nil
   809  }
   810  
   811  func (c *Client) GetAllRevocationStatus(ctx context.Context, verifiedChains []*x509.Certificate, conf *VerifyConfig) ([]*ocspStatus, error) {
   812  	_, err := c.validateWithCacheForAllCertificates(verifiedChains, conf)
   813  	if err != nil {
   814  		return nil, err
   815  	}
   816  	n := len(verifiedChains) - 1
   817  	results := make([]*ocspStatus, n)
   818  	for j := 0; j < n; j++ {
   819  		results[j], err = c.GetRevocationStatus(ctx, verifiedChains[j], verifiedChains[j+1], conf)
   820  		if err != nil {
   821  			return nil, err
   822  		}
   823  		if !isValidOCSPStatus(results[j].code) {
   824  			return results, nil
   825  		}
   826  	}
   827  	return results, nil
   828  }
   829  
   830  // verifyPeerCertificateSerial verifies the certificate revocation status in serial.
   831  func (c *Client) verifyPeerCertificateSerial(conf *VerifyConfig) func(_ [][]byte, verifiedChains [][]*x509.Certificate) (err error) {
   832  	return func(_ [][]byte, verifiedChains [][]*x509.Certificate) error {
   833  		return c.VerifyPeerCertificate(context.TODO(), verifiedChains, conf)
   834  	}
   835  }
   836  
   837  func (c *Client) extractOCSPCacheResponseValueWithoutSubject(cacheValue ocspCachedResponse, conf *VerifyConfig) (*ocspStatus, error) {
   838  	return c.extractOCSPCacheResponseValue(&cacheValue, nil, nil, conf)
   839  }
   840  
   841  func (c *Client) extractOCSPCacheResponseValue(cacheValue *ocspCachedResponse, subject, issuer *x509.Certificate, conf *VerifyConfig) (*ocspStatus, error) {
   842  	subjectName := "Unknown"
   843  	if subject != nil {
   844  		subjectName = subject.Subject.CommonName
   845  	}
   846  
   847  	curTime := time.Now()
   848  	if cacheValue == nil {
   849  		return &ocspStatus{
   850  			code: ocspMissedCache,
   851  			err:  fmt.Errorf("miss cache data. subject: %v", subjectName),
   852  		}, nil
   853  	}
   854  	currentTime := float64(curTime.UTC().Unix())
   855  	if currentTime-cacheValue.time >= cacheExpire {
   856  		return &ocspStatus{
   857  			code: ocspCacheExpired,
   858  			err: fmt.Errorf("cache expired. current: %v, cache: %v",
   859  				time.Unix(int64(currentTime), 0).UTC(), time.Unix(int64(cacheValue.time), 0).UTC()),
   860  		}, nil
   861  	}
   862  
   863  	sdkOcspStatus := internalStatusCodeToSDK(cacheValue.status)
   864  
   865  	return validateOCSP(conf, &ocsp.Response{
   866  		ProducedAt: time.Unix(int64(cacheValue.producedAt), 0).UTC(),
   867  		ThisUpdate: time.Unix(int64(cacheValue.thisUpdate), 0).UTC(),
   868  		NextUpdate: time.Unix(int64(cacheValue.nextUpdate), 0).UTC(),
   869  		Status:     sdkOcspStatus,
   870  	})
   871  }
   872  
   873  func internalStatusCodeToSDK(internalStatusCode ocspStatusCode) int {
   874  	switch internalStatusCode {
   875  	case ocspStatusGood:
   876  		return ocsp.Good
   877  	case ocspStatusRevoked:
   878  		return ocsp.Revoked
   879  	case ocspStatusUnknown:
   880  		return ocsp.Unknown
   881  	default:
   882  		return int(internalStatusCode)
   883  	}
   884  }
   885  
   886  /*
   887  // writeOCSPCache writes a OCSP Response cache
   888  func (c *Client) writeOCSPCache(ctx context.Context, storage logical.Storage) error {
   889  	c.Logger().Debug("writing OCSP Response cache")
   890  	t := time.Now()
   891  	m := make(map[string][]interface{})
   892  	keys := c.ocspResponseCache.Keys()
   893  	if len(keys) > persistedCacheSize {
   894  		keys = keys[:persistedCacheSize]
   895  	}
   896  	for _, k := range keys {
   897  		e, ok := c.ocspResponseCache.Get(k)
   898  		if ok {
   899  			entry := e.(*ocspCachedResponse)
   900  			// Don't store if expired
   901  			if isInValidityRange(t, time.Unix(int64(entry.thisUpdate), 0), time.Unix(int64(entry.nextUpdate), 0)) {
   902  				key := k.(certIDKey)
   903  				cacheKeyInBase64, err := decodeCertIDKey(&key)
   904  				if err != nil {
   905  					return err
   906  				}
   907  				m[cacheKeyInBase64] = []interface{}{entry.status, entry.time, entry.producedAt, entry.thisUpdate, entry.nextUpdate}
   908  			}
   909  		}
   910  	}
   911  
   912  	v, err := jsonutil.EncodeJSONAndCompress(m, nil)
   913  	if err != nil {
   914  		return err
   915  	}
   916  	entry := logical.StorageEntry{
   917  		Key:   ocspCacheKey,
   918  		Value: v,
   919  	}
   920  	return storage.Put(ctx, &entry)
   921  }
   922  
   923  // readOCSPCache reads a OCSP Response cache from storage
   924  func (c *Client) readOCSPCache(ctx context.Context, storage logical.Storage) error {
   925  	c.Logger().Debug("reading OCSP Response cache")
   926  
   927  	entry, err := storage.Get(ctx, ocspCacheKey)
   928  	if err != nil {
   929  		return err
   930  	}
   931  	if entry == nil {
   932  		return nil
   933  	}
   934  	var untypedCache map[string][]interface{}
   935  
   936  	err = jsonutil.DecodeJSON(entry.Value, &untypedCache)
   937  	if err != nil {
   938  		return errors.New("failed to unmarshal OCSP cache")
   939  	}
   940  
   941  	for k, v := range untypedCache {
   942  		key, err := c.encodeCertIDKey(k)
   943  		if err != nil {
   944  			return err
   945  		}
   946  		var times [4]float64
   947  		for i, t := range v[1:] {
   948  			if jn, ok := t.(json.Number); ok {
   949  				times[i], err = jn.Float64()
   950  				if err != nil {
   951  					return err
   952  				}
   953  			} else {
   954  				times[i] = t.(float64)
   955  			}
   956  		}
   957  		var status int
   958  		if jn, ok := v[0].(json.Number); ok {
   959  			s, err := jn.Int64()
   960  			if err != nil {
   961  				return err
   962  			}
   963  			status = int(s)
   964  		} else {
   965  			status = v[0].(int)
   966  		}
   967  
   968  		c.ocspResponseCache.Add(*key, &ocspCachedResponse{
   969  			status:     ocspStatusCode(status),
   970  			time:       times[0],
   971  			producedAt: times[1],
   972  			thisUpdate: times[2],
   973  			nextUpdate: times[3],
   974  		})
   975  	}
   976  
   977  	return nil
   978  }
   979  */
   980  
   981  func New(logFactory func() hclog.Logger, cacheSize int) *Client {
   982  	if cacheSize < 100 {
   983  		cacheSize = 100
   984  	}
   985  	cache, _ := lru.New2Q(cacheSize)
   986  	c := Client{
   987  		caRoot:            make(map[string]*x509.Certificate),
   988  		ocspResponseCache: cache,
   989  		logFactory:        logFactory,
   990  	}
   991  
   992  	return &c
   993  }
   994  
   995  func (c *Client) Logger() hclog.Logger {
   996  	return c.logFactory()
   997  }
   998  
   999  // insecureOcspTransport is the transport object that doesn't do certificate revocation check.
  1000  func newInsecureOcspTransport(extraCas []*x509.Certificate) *http.Transport {
  1001  	// Get the SystemCertPool, continue with an empty pool on error
  1002  	rootCAs, _ := x509.SystemCertPool()
  1003  	if rootCAs == nil {
  1004  		rootCAs = x509.NewCertPool()
  1005  	}
  1006  	for _, c := range extraCas {
  1007  		rootCAs.AddCert(c)
  1008  	}
  1009  	config := &tls.Config{
  1010  		RootCAs: rootCAs,
  1011  	}
  1012  	return &http.Transport{
  1013  		MaxIdleConns:    10,
  1014  		IdleConnTimeout: 30 * time.Minute,
  1015  		Proxy:           http.ProxyFromEnvironment,
  1016  		DialContext: (&net.Dialer{
  1017  			Timeout:   30 * time.Second,
  1018  			KeepAlive: 30 * time.Second,
  1019  		}).DialContext,
  1020  		TLSClientConfig: config,
  1021  	}
  1022  }
  1023  
  1024  // NewTransport includes the certificate revocation check with OCSP in sequential.
  1025  func (c *Client) NewTransport(conf *VerifyConfig) *http.Transport {
  1026  	rootCAs := c.certPool
  1027  	if rootCAs == nil {
  1028  		rootCAs, _ = x509.SystemCertPool()
  1029  	}
  1030  	if rootCAs == nil {
  1031  		rootCAs = x509.NewCertPool()
  1032  	}
  1033  	for _, c := range conf.ExtraCas {
  1034  		rootCAs.AddCert(c)
  1035  	}
  1036  	return &http.Transport{
  1037  		TLSClientConfig: &tls.Config{
  1038  			RootCAs:               rootCAs,
  1039  			VerifyPeerCertificate: c.verifyPeerCertificateSerial(conf),
  1040  		},
  1041  		MaxIdleConns:    10,
  1042  		IdleConnTimeout: 30 * time.Minute,
  1043  		Proxy:           http.ProxyFromEnvironment,
  1044  		DialContext: (&net.Dialer{
  1045  			Timeout:   30 * time.Second,
  1046  			KeepAlive: 30 * time.Second,
  1047  		}).DialContext,
  1048  	}
  1049  }
  1050  
  1051  /*
  1052  func (c *Client) WriteCache(ctx context.Context, storage logical.Storage) error {
  1053  	c.ocspResponseCacheLock.Lock()
  1054  	defer c.ocspResponseCacheLock.Unlock()
  1055  	if c.cacheUpdated {
  1056  		err := c.writeOCSPCache(ctx, storage)
  1057  		if err == nil {
  1058  			c.cacheUpdated = false
  1059  		}
  1060  		return err
  1061  	}
  1062  	return nil
  1063  }
  1064  
  1065  func (c *Client) ReadCache(ctx context.Context, storage logical.Storage) error {
  1066  	c.ocspResponseCacheLock.Lock()
  1067  	defer c.ocspResponseCacheLock.Unlock()
  1068  	return c.readOCSPCache(ctx, storage)
  1069  }
  1070  */
  1071  /*
  1072                                   Apache License
  1073                             Version 2.0, January 2004
  1074                          http://www.apache.org/licenses/
  1075  
  1076     TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
  1077  
  1078     1. Definitions.
  1079  
  1080        "License" shall mean the terms and conditions for use, reproduction,
  1081        and distribution as defined by Sections 1 through 9 of this document.
  1082  
  1083        "Licensor" shall mean the copyright owner or entity authorized by
  1084        the copyright owner that is granting the License.
  1085  
  1086        "Legal Entity" shall mean the union of the acting entity and all
  1087        other entities that control, are controlled by, or are under common
  1088        control with that entity. For the purposes of this definition,
  1089        "control" means (i) the power, direct or indirect, to cause the
  1090        direction or management of such entity, whether by contract or
  1091        otherwise, or (ii) ownership of fifty percent (50%) or more of the
  1092        outstanding shares, or (iii) beneficial ownership of such entity.
  1093  
  1094        "You" (or "Your") shall mean an individual or Legal Entity
  1095        exercising permissions granted by this License.
  1096  
  1097        "Source" form shall mean the preferred form for making modifications,
  1098        including but not limited to software source code, documentation
  1099        source, and configuration files.
  1100  
  1101        "Object" form shall mean any form resulting from mechanical
  1102        transformation or translation of a Source form, including but
  1103        not limited to compiled object code, generated documentation,
  1104        and conversions to other media types.
  1105  
  1106        "Work" shall mean the work of authorship, whether in Source or
  1107        Object form, made available under the License, as indicated by a
  1108        copyright notice that is included in or attached to the work
  1109        (an example is provided in the Appendix below).
  1110  
  1111        "Derivative Works" shall mean any work, whether in Source or Object
  1112        form, that is based on (or derived from) the Work and for which the
  1113        editorial revisions, annotations, elaborations, or other modifications
  1114        represent, as a whole, an original work of authorship. For the purposes
  1115        of this License, Derivative Works shall not include works that remain
  1116        separable from, or merely link (or bind by name) to the interfaces of,
  1117        the Work and Derivative Works thereof.
  1118  
  1119        "Contribution" shall mean any work of authorship, including
  1120        the original version of the Work and any modifications or additions
  1121        to that Work or Derivative Works thereof, that is intentionally
  1122        submitted to Licensor for inclusion in the Work by the copyright owner
  1123        or by an individual or Legal Entity authorized to submit on behalf of
  1124        the copyright owner. For the purposes of this definition, "submitted"
  1125        means any form of electronic, verbal, or written communication sent
  1126        to the Licensor or its representatives, including but not limited to
  1127        communication on electronic mailing lists, source code control systems,
  1128        and issue tracking systems that are managed by, or on behalf of, the
  1129        Licensor for the purpose of discussing and improving the Work, but
  1130        excluding communication that is conspicuously marked or otherwise
  1131        designated in writing by the copyright owner as "Not a Contribution."
  1132  
  1133        "Contributor" shall mean Licensor and any individual or Legal Entity
  1134        on behalf of whom a Contribution has been received by Licensor and
  1135        subsequently incorporated within the Work.
  1136  
  1137     2. Grant of Copyright License. Subject to the terms and conditions of
  1138        this License, each Contributor hereby grants to You a perpetual,
  1139        worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  1140        copyright license to reproduce, prepare Derivative Works of,
  1141        publicly display, publicly perform, sublicense, and distribute the
  1142        Work and such Derivative Works in Source or Object form.
  1143  
  1144     3. Grant of Patent License. Subject to the terms and conditions of
  1145        this License, each Contributor hereby grants to You a perpetual,
  1146        worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  1147        (except as stated in this section) patent license to make, have made,
  1148        use, offer to sell, sell, import, and otherwise transfer the Work,
  1149        where such license applies only to those patent claims licensable
  1150        by such Contributor that are necessarily infringed by their
  1151        Contribution(s) alone or by combination of their Contribution(s)
  1152        with the Work to which such Contribution(s) was submitted. If You
  1153        institute patent litigation against any entity (including a
  1154        cross-claim or counterclaim in a lawsuit) alleging that the Work
  1155        or a Contribution incorporated within the Work constitutes direct
  1156        or contributory patent infringement, then any patent licenses
  1157        granted to You under this License for that Work shall terminate
  1158        as of the date such litigation is filed.
  1159  
  1160     4. Redistribution. You may reproduce and distribute copies of the
  1161        Work or Derivative Works thereof in any medium, with or without
  1162        modifications, and in Source or Object form, provided that You
  1163        meet the following conditions:
  1164  
  1165        (a) You must give any other recipients of the Work or
  1166            Derivative Works a copy of this License; and
  1167  
  1168        (b) You must cause any modified files to carry prominent notices
  1169            stating that You changed the files; and
  1170  
  1171        (c) You must retain, in the Source form of any Derivative Works
  1172            that You distribute, all copyright, patent, trademark, and
  1173            attribution notices from the Source form of the Work,
  1174            excluding those notices that do not pertain to any part of
  1175            the Derivative Works; and
  1176  
  1177        (d) If the Work includes a "NOTICE" text file as part of its
  1178            distribution, then any Derivative Works that You distribute must
  1179            include a readable copy of the attribution notices contained
  1180            within such NOTICE file, excluding those notices that do not
  1181            pertain to any part of the Derivative Works, in at least one
  1182            of the following places: within a NOTICE text file distributed
  1183            as part of the Derivative Works; within the Source form or
  1184            documentation, if provided along with the Derivative Works; or,
  1185            within a display generated by the Derivative Works, if and
  1186            wherever such third-party notices normally appear. The contents
  1187            of the NOTICE file are for informational purposes only and
  1188            do not modify the License. You may add Your own attribution
  1189            notices within Derivative Works that You distribute, alongside
  1190            or as an addendum to the NOTICE text from the Work, provided
  1191            that such additional attribution notices cannot be construed
  1192            as modifying the License.
  1193  
  1194        You may add Your own copyright statement to Your modifications and
  1195        may provide additional or different license terms and conditions
  1196        for use, reproduction, or distribution of Your modifications, or
  1197        for any such Derivative Works as a whole, provided Your use,
  1198        reproduction, and distribution of the Work otherwise complies with
  1199        the conditions stated in this License.
  1200  
  1201     5. Submission of Contributions. Unless You explicitly state otherwise,
  1202        any Contribution intentionally submitted for inclusion in the Work
  1203        by You to the Licensor shall be under the terms and conditions of
  1204        this License, without any additional terms or conditions.
  1205        Notwithstanding the above, nothing herein shall supersede or modify
  1206        the terms of any separate license agreement you may have executed
  1207        with Licensor regarding such Contributions.
  1208  
  1209     6. Trademarks. This License does not grant permission to use the trade
  1210        names, trademarks, service marks, or product names of the Licensor,
  1211        except as required for reasonable and customary use in describing the
  1212        origin of the Work and reproducing the content of the NOTICE file.
  1213  
  1214     7. Disclaimer of Warranty. Unless required by applicable law or
  1215        agreed to in writing, Licensor provides the Work (and each
  1216        Contributor provides its Contributions) on an "AS IS" BASIS,
  1217        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  1218        implied, including, without limitation, any warranties or conditions
  1219        of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
  1220        PARTICULAR PURPOSE. You are solely responsible for determining the
  1221        appropriateness of using or redistributing the Work and assume any
  1222        risks associated with Your exercise of permissions under this License.
  1223  
  1224     8. Limitation of Liability. In no event and under no legal theory,
  1225        whether in tort (including negligence), contract, or otherwise,
  1226        unless required by applicable law (such as deliberate and grossly
  1227        negligent acts) or agreed to in writing, shall any Contributor be
  1228        liable to You for damages, including any direct, indirect, special,
  1229        incidental, or consequential damages of any character arising as a
  1230        result of this License or out of the use or inability to use the
  1231        Work (including but not limited to damages for loss of goodwill,
  1232        work stoppage, computer failure or malfunction, or any and all
  1233        other commercial damages or losses), even if such Contributor
  1234        has been advised of the possibility of such damages.
  1235  
  1236     9. Accepting Warranty or Additional Liability. While redistributing
  1237        the Work or Derivative Works thereof, You may choose to offer,
  1238        and charge a fee for, acceptance of support, warranty, indemnity,
  1239        or other liability obligations and/or rights consistent with this
  1240        License. However, in accepting such obligations, You may act only
  1241        on Your own behalf and on Your sole responsibility, not on behalf
  1242        of any other Contributor, and only if You agree to indemnify,
  1243        defend, and hold each Contributor harmless for any liability
  1244        incurred by, or claims asserted against, such Contributor by reason
  1245        of your accepting any such warranty or additional liability.
  1246  
  1247     END OF TERMS AND CONDITIONS
  1248  
  1249     APPENDIX: How to apply the Apache License to your work.
  1250  
  1251        To apply the Apache License to your work, attach the following
  1252        boilerplate notice, with the fields enclosed by brackets "{}"
  1253        replaced with your own identifying information. (Don't include
  1254        the brackets!)  The text should be enclosed in the appropriate
  1255        comment syntax for the file format. We also recommend that a
  1256        file or class name and description of purpose be included on the
  1257        same "printed page" as the copyright notice for easier
  1258        identification within third-party archives.
  1259  
  1260     Copyright (c) 2017-2022 Snowflake Computing Inc. All rights reserved.
  1261  
  1262     Licensed under the Apache License, Version 2.0 (the "License");
  1263     you may not use this file except in compliance with the License.
  1264     You may obtain a copy of the License at
  1265  
  1266         http://www.apache.org/licenses/LICENSE-2.0
  1267  
  1268     Unless required by applicable law or agreed to in writing, software
  1269     distributed under the License is distributed on an "AS IS" BASIS,
  1270     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1271     See the License for the specific language governing permissions and
  1272     limitations under the License.
  1273  */