get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/ocsp.go (about)

     1  // Copyright 2021-2023 The NATS Authors
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package server
    15  
    16  import (
    17  	"bytes"
    18  	"crypto/sha256"
    19  	"crypto/tls"
    20  	"crypto/x509"
    21  	"encoding/asn1"
    22  	"encoding/base64"
    23  	"encoding/pem"
    24  	"errors"
    25  	"fmt"
    26  	"io"
    27  	"net/http"
    28  	"os"
    29  	"path/filepath"
    30  	"strings"
    31  	"sync"
    32  	"time"
    33  
    34  	"golang.org/x/crypto/ocsp"
    35  
    36  	"get.pme.sh/pnats/server/certidp"
    37  	"get.pme.sh/pnats/server/certstore"
    38  )
    39  
    40  const (
    41  	defaultOCSPStoreDir      = "ocsp"
    42  	defaultOCSPCheckInterval = 24 * time.Hour
    43  	minOCSPCheckInterval     = 2 * time.Minute
    44  )
    45  
    46  type OCSPMode uint8
    47  
    48  const (
    49  	// OCSPModeAuto staples a status, only if "status_request" is set in cert.
    50  	OCSPModeAuto OCSPMode = iota
    51  
    52  	// OCSPModeAlways enforces OCSP stapling for certs and shuts down the server in
    53  	// case a server is revoked or cannot get OCSP staples.
    54  	OCSPModeAlways
    55  
    56  	// OCSPModeNever disables OCSP stapling even if cert has Must-Staple flag.
    57  	OCSPModeNever
    58  
    59  	// OCSPModeMust honors the Must-Staple flag from a certificate but also causing shutdown
    60  	// in case the certificate has been revoked.
    61  	OCSPModeMust
    62  )
    63  
    64  // OCSPMonitor monitors the state of a staple per certificate.
    65  type OCSPMonitor struct {
    66  	kind     string
    67  	mu       sync.Mutex
    68  	raw      []byte
    69  	srv      *Server
    70  	certFile string
    71  	resp     *ocsp.Response
    72  	hc       *http.Client
    73  	stopCh   chan struct{}
    74  	Leaf     *x509.Certificate
    75  	Issuer   *x509.Certificate
    76  
    77  	shutdownOnRevoke bool
    78  }
    79  
    80  func (oc *OCSPMonitor) getNextRun() time.Duration {
    81  	oc.mu.Lock()
    82  	nextUpdate := oc.resp.NextUpdate
    83  	oc.mu.Unlock()
    84  
    85  	now := time.Now()
    86  	if nextUpdate.IsZero() {
    87  		// If response is missing NextUpdate, we check the day after.
    88  		// Technically, if NextUpdate is missing, we can try whenever.
    89  		// https://tools.ietf.org/html/rfc6960#section-4.2.2.1
    90  		return defaultOCSPCheckInterval
    91  	}
    92  	dur := nextUpdate.Sub(now) / 2
    93  
    94  	// If negative, then wait a couple of minutes before getting another staple.
    95  	if dur < 0 {
    96  		return minOCSPCheckInterval
    97  	}
    98  
    99  	return dur
   100  }
   101  
   102  func (oc *OCSPMonitor) getStatus() ([]byte, *ocsp.Response, error) {
   103  	raw, resp := oc.getCacheStatus()
   104  	if len(raw) > 0 && resp != nil {
   105  		// Check if the OCSP is still valid.
   106  		if err := validOCSPResponse(resp); err == nil {
   107  			return raw, resp, nil
   108  		}
   109  	}
   110  	var err error
   111  	raw, resp, err = oc.getLocalStatus()
   112  	if err == nil {
   113  		return raw, resp, nil
   114  	}
   115  
   116  	return oc.getRemoteStatus()
   117  }
   118  
   119  func (oc *OCSPMonitor) getCacheStatus() ([]byte, *ocsp.Response) {
   120  	oc.mu.Lock()
   121  	defer oc.mu.Unlock()
   122  	return oc.raw, oc.resp
   123  }
   124  
   125  func (oc *OCSPMonitor) getLocalStatus() ([]byte, *ocsp.Response, error) {
   126  	opts := oc.srv.getOpts()
   127  	storeDir := opts.StoreDir
   128  	if storeDir == _EMPTY_ {
   129  		return nil, nil, fmt.Errorf("store_dir not set")
   130  	}
   131  
   132  	// This key must be based upon the current full certificate, not the public key,
   133  	// so MUST be on the full raw certificate and not an SPKI or other reduced form.
   134  	key := fmt.Sprintf("%x", sha256.Sum256(oc.Leaf.Raw))
   135  
   136  	oc.mu.Lock()
   137  	raw, err := os.ReadFile(filepath.Join(storeDir, defaultOCSPStoreDir, key))
   138  	oc.mu.Unlock()
   139  	if err != nil {
   140  		return nil, nil, err
   141  	}
   142  
   143  	resp, err := ocsp.ParseResponse(raw, oc.Issuer)
   144  	if err != nil {
   145  		return nil, nil, fmt.Errorf("failed to get local status: %w", err)
   146  	}
   147  	if err := validOCSPResponse(resp); err != nil {
   148  		return nil, nil, err
   149  	}
   150  
   151  	// Cache the response.
   152  	oc.mu.Lock()
   153  	oc.raw = raw
   154  	oc.resp = resp
   155  	oc.mu.Unlock()
   156  
   157  	return raw, resp, nil
   158  }
   159  
   160  func (oc *OCSPMonitor) getRemoteStatus() ([]byte, *ocsp.Response, error) {
   161  	opts := oc.srv.getOpts()
   162  	var overrideURLs []string
   163  	if config := opts.OCSPConfig; config != nil {
   164  		overrideURLs = config.OverrideURLs
   165  	}
   166  	getRequestBytes := func(u string, reqDER []byte, hc *http.Client) ([]byte, error) {
   167  		reqEnc := base64.StdEncoding.EncodeToString(reqDER)
   168  		u = fmt.Sprintf("%s/%s", u, reqEnc)
   169  		start := time.Now()
   170  		resp, err := hc.Get(u)
   171  		if err != nil {
   172  			return nil, err
   173  		}
   174  		defer resp.Body.Close()
   175  
   176  		oc.srv.Debugf("Received OCSP response (method=GET, status=%v, url=%s, duration=%.3fs)",
   177  			resp.StatusCode, u, time.Since(start).Seconds())
   178  		if resp.StatusCode > 299 {
   179  			return nil, fmt.Errorf("non-ok http status on GET request (reqlen=%d): %d", len(reqEnc), resp.StatusCode)
   180  		}
   181  		return io.ReadAll(resp.Body)
   182  	}
   183  	postRequestBytes := func(u string, body []byte, hc *http.Client) ([]byte, error) {
   184  		hreq, err := http.NewRequest("POST", u, bytes.NewReader(body))
   185  		if err != nil {
   186  			return nil, err
   187  		}
   188  		hreq.Header.Add("Content-Type", "application/ocsp-request")
   189  		hreq.Header.Add("Accept", "application/ocsp-response")
   190  
   191  		start := time.Now()
   192  		resp, err := hc.Do(hreq)
   193  		if err != nil {
   194  			return nil, err
   195  		}
   196  		defer resp.Body.Close()
   197  
   198  		oc.srv.Debugf("Received OCSP response (method=POST, status=%v, url=%s, duration=%.3fs)",
   199  			resp.StatusCode, u, time.Since(start).Seconds())
   200  		if resp.StatusCode > 299 {
   201  			return nil, fmt.Errorf("non-ok http status on POST request (reqlen=%d): %d", len(body), resp.StatusCode)
   202  		}
   203  		return io.ReadAll(resp.Body)
   204  	}
   205  
   206  	// Request documentation:
   207  	// https://tools.ietf.org/html/rfc6960#appendix-A.1
   208  
   209  	reqDER, err := ocsp.CreateRequest(oc.Leaf, oc.Issuer, nil)
   210  	if err != nil {
   211  		return nil, nil, err
   212  	}
   213  
   214  	responders := oc.Leaf.OCSPServer
   215  	if len(overrideURLs) > 0 {
   216  		responders = overrideURLs
   217  	}
   218  	if len(responders) == 0 {
   219  		return nil, nil, fmt.Errorf("no available ocsp servers")
   220  	}
   221  
   222  	oc.mu.Lock()
   223  	hc := oc.hc
   224  	oc.mu.Unlock()
   225  
   226  	var raw []byte
   227  	for _, u := range responders {
   228  		var postErr, getErr error
   229  		u = strings.TrimSuffix(u, "/")
   230  		// Prefer to make POST requests first.
   231  		raw, postErr = postRequestBytes(u, reqDER, hc)
   232  		if postErr == nil {
   233  			err = nil
   234  			break
   235  		} else {
   236  			// Fallback to use a GET request.
   237  			raw, getErr = getRequestBytes(u, reqDER, hc)
   238  			if getErr == nil {
   239  				err = nil
   240  				break
   241  			} else {
   242  				err = errors.Join(postErr, getErr)
   243  			}
   244  		}
   245  	}
   246  	if err != nil {
   247  		return nil, nil, fmt.Errorf("exhausted ocsp servers: %w", err)
   248  	}
   249  	resp, err := ocsp.ParseResponse(raw, oc.Issuer)
   250  	if err != nil {
   251  		return nil, nil, fmt.Errorf("failed to get remote status: %w", err)
   252  	}
   253  	if err := validOCSPResponse(resp); err != nil {
   254  		return nil, nil, err
   255  	}
   256  
   257  	if storeDir := opts.StoreDir; storeDir != _EMPTY_ {
   258  		key := fmt.Sprintf("%x", sha256.Sum256(oc.Leaf.Raw))
   259  		if err := oc.writeOCSPStatus(storeDir, key, raw); err != nil {
   260  			return nil, nil, fmt.Errorf("failed to write ocsp status: %w", err)
   261  		}
   262  	}
   263  
   264  	oc.mu.Lock()
   265  	oc.raw = raw
   266  	oc.resp = resp
   267  	oc.mu.Unlock()
   268  
   269  	return raw, resp, nil
   270  }
   271  
   272  func (oc *OCSPMonitor) run() {
   273  	s := oc.srv
   274  	s.mu.Lock()
   275  	quitCh := s.quitCh
   276  	s.mu.Unlock()
   277  
   278  	var doShutdown bool
   279  	defer func() {
   280  		// Need to decrement before shuting down, otherwise shutdown
   281  		// would be stuck waiting on grWG to go down to 0.
   282  		s.grWG.Done()
   283  		if doShutdown {
   284  			s.Shutdown()
   285  		}
   286  	}()
   287  
   288  	oc.mu.Lock()
   289  	shutdownOnRevoke := oc.shutdownOnRevoke
   290  	certFile := oc.certFile
   291  	stopCh := oc.stopCh
   292  	kind := oc.kind
   293  	oc.mu.Unlock()
   294  
   295  	var nextRun time.Duration
   296  	_, resp, err := oc.getStatus()
   297  	if err == nil && resp.Status == ocsp.Good {
   298  		nextRun = oc.getNextRun()
   299  		t := resp.NextUpdate.Format(time.RFC3339Nano)
   300  		s.Noticef(
   301  			"Found OCSP status for %s certificate at '%s': good, next update %s, checking again in %s",
   302  			kind, certFile, t, nextRun,
   303  		)
   304  	} else if err == nil && shutdownOnRevoke {
   305  		// If resp.Status is ocsp.Revoked, ocsp.Unknown, or any other value.
   306  		s.Errorf("Found OCSP status for %s certificate at '%s': %s", kind, certFile, ocspStatusString(resp.Status))
   307  		doShutdown = true
   308  		return
   309  	}
   310  
   311  	for {
   312  		// On reload, if the certificate changes then need to stop this monitor.
   313  		select {
   314  		case <-time.After(nextRun):
   315  		case <-stopCh:
   316  			// In case of reload and have to restart the OCSP stapling monitoring.
   317  			return
   318  		case <-quitCh:
   319  			// Server quit channel.
   320  			return
   321  		}
   322  		_, resp, err := oc.getRemoteStatus()
   323  		if err != nil {
   324  			nextRun = oc.getNextRun()
   325  			s.Errorf("Bad OCSP status update for certificate '%s': %s, trying again in %v", certFile, err, nextRun)
   326  			continue
   327  		}
   328  
   329  		switch n := resp.Status; n {
   330  		case ocsp.Good:
   331  			nextRun = oc.getNextRun()
   332  			t := resp.NextUpdate.Format(time.RFC3339Nano)
   333  			s.Noticef(
   334  				"Received OCSP status for %s certificate '%s': good, next update %s, checking again in %s",
   335  				kind, certFile, t, nextRun,
   336  			)
   337  			continue
   338  		default:
   339  			s.Errorf("Received OCSP status for %s certificate '%s': %s", kind, certFile, ocspStatusString(n))
   340  			if shutdownOnRevoke {
   341  				doShutdown = true
   342  			}
   343  			return
   344  		}
   345  	}
   346  }
   347  
   348  func (oc *OCSPMonitor) stop() {
   349  	oc.mu.Lock()
   350  	stopCh := oc.stopCh
   351  	oc.mu.Unlock()
   352  	stopCh <- struct{}{}
   353  }
   354  
   355  // NewOCSPMonitor takes a TLS configuration then wraps it with the callbacks set for OCSP verification
   356  // along with a monitor that will periodically fetch OCSP staples.
   357  func (srv *Server) NewOCSPMonitor(config *tlsConfigKind) (*tls.Config, *OCSPMonitor, error) {
   358  	kind := config.kind
   359  	tc := config.tlsConfig
   360  	tcOpts := config.tlsOpts
   361  	opts := srv.getOpts()
   362  	oc := opts.OCSPConfig
   363  
   364  	// We need to track the CA certificate in case the CA is not present
   365  	// in the chain to be able to verify the signature of the OCSP staple.
   366  	var (
   367  		certFile string
   368  		caFile   string
   369  	)
   370  	if kind == kindStringMap[CLIENT] {
   371  		tcOpts = opts.tlsConfigOpts
   372  		if opts.TLSCert != _EMPTY_ {
   373  			certFile = opts.TLSCert
   374  		}
   375  		if opts.TLSCaCert != _EMPTY_ {
   376  			caFile = opts.TLSCaCert
   377  		}
   378  	}
   379  	if tcOpts != nil {
   380  		certFile = tcOpts.CertFile
   381  		caFile = tcOpts.CaFile
   382  	}
   383  
   384  	// NOTE: Currently OCSP Stapling is enabled only for the first certificate found.
   385  	var mon *OCSPMonitor
   386  	for _, currentCert := range tc.Certificates {
   387  		// Create local copy since this will be used in the GetCertificate callback.
   388  		cert := currentCert
   389  
   390  		// This is normally non-nil, but can still be nil here when in tests
   391  		// or in some embedded scenarios.
   392  		if cert.Leaf == nil {
   393  			if len(cert.Certificate) <= 0 {
   394  				return nil, nil, fmt.Errorf("no certificate found")
   395  			}
   396  			var err error
   397  			cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
   398  			if err != nil {
   399  				return nil, nil, fmt.Errorf("error parsing certificate: %v", err)
   400  			}
   401  		}
   402  		var shutdownOnRevoke bool
   403  		mustStaple := hasOCSPStatusRequest(cert.Leaf)
   404  		if oc != nil {
   405  			switch {
   406  			case oc.Mode == OCSPModeNever:
   407  				if mustStaple {
   408  					srv.Warnf("Certificate at '%s' has MustStaple but OCSP is disabled", certFile)
   409  				}
   410  				return tc, nil, nil
   411  			case oc.Mode == OCSPModeAlways:
   412  				// Start the monitor for this cert even if it does not have
   413  				// the MustStaple flag and shutdown the server in case the
   414  				// staple ever gets revoked.
   415  				mustStaple = true
   416  				shutdownOnRevoke = true
   417  			case oc.Mode == OCSPModeMust && mustStaple:
   418  				shutdownOnRevoke = true
   419  			case oc.Mode == OCSPModeAuto && !mustStaple:
   420  				// "status_request" MustStaple flag not set in certificate. No need to do anything.
   421  				return tc, nil, nil
   422  			}
   423  		}
   424  		if !mustStaple {
   425  			// No explicit OCSP config and cert does not have MustStaple flag either.
   426  			return tc, nil, nil
   427  		}
   428  
   429  		if err := srv.setupOCSPStapleStoreDir(); err != nil {
   430  			return nil, nil, err
   431  		}
   432  
   433  		// TODO: Add OCSP 'responder_cert' option in case CA cert not available.
   434  		issuer, err := getOCSPIssuer(caFile, cert.Certificate)
   435  		if err != nil {
   436  			return nil, nil, err
   437  		}
   438  
   439  		mon = &OCSPMonitor{
   440  			kind:             kind,
   441  			srv:              srv,
   442  			hc:               &http.Client{Timeout: 30 * time.Second},
   443  			shutdownOnRevoke: shutdownOnRevoke,
   444  			certFile:         certFile,
   445  			stopCh:           make(chan struct{}, 1),
   446  			Leaf:             cert.Leaf,
   447  			Issuer:           issuer,
   448  		}
   449  
   450  		// Get the certificate status from the memory, then remote OCSP responder.
   451  		if _, resp, err := mon.getStatus(); err != nil {
   452  			return nil, nil, fmt.Errorf("bad OCSP status update for certificate at '%s': %s", certFile, err)
   453  		} else if err == nil && resp != nil && resp.Status != ocsp.Good && shutdownOnRevoke {
   454  			return nil, nil, fmt.Errorf("found existing OCSP status for certificate at '%s': %s", certFile, ocspStatusString(resp.Status))
   455  		}
   456  
   457  		// Callbacks below will be in charge of returning the certificate instead,
   458  		// so this has to be nil.
   459  		tc.Certificates = nil
   460  
   461  		// GetCertificate returns a certificate that's presented to a client.
   462  		tc.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
   463  			raw, _, err := mon.getStatus()
   464  			if err != nil {
   465  				return nil, err
   466  			}
   467  
   468  			return &tls.Certificate{
   469  				OCSPStaple:                   raw,
   470  				Certificate:                  cert.Certificate,
   471  				PrivateKey:                   cert.PrivateKey,
   472  				SupportedSignatureAlgorithms: cert.SupportedSignatureAlgorithms,
   473  				SignedCertificateTimestamps:  cert.SignedCertificateTimestamps,
   474  				Leaf:                         cert.Leaf,
   475  			}, nil
   476  		}
   477  
   478  		// Check whether need to verify staples from a peer router or gateway connection.
   479  		switch kind {
   480  		case kindStringMap[ROUTER], kindStringMap[GATEWAY]:
   481  			tc.VerifyConnection = func(s tls.ConnectionState) error {
   482  				oresp := s.OCSPResponse
   483  				if oresp == nil {
   484  					return fmt.Errorf("%s peer missing OCSP Staple", kind)
   485  				}
   486  
   487  				// Peer connections will verify the response of the staple.
   488  				if len(s.VerifiedChains) == 0 {
   489  					return fmt.Errorf("%s peer missing TLS verified chains", kind)
   490  				}
   491  
   492  				chain := s.VerifiedChains[0]
   493  				peerLeaf := chain[0]
   494  				peerIssuer := certidp.GetLeafIssuerCert(chain, 0)
   495  				if peerIssuer == nil {
   496  					return fmt.Errorf("failed to get issuer certificate for %s peer", kind)
   497  				}
   498  
   499  				// Response signature of issuer or issuer delegate is checked in the library parse
   500  				resp, err := ocsp.ParseResponseForCert(oresp, peerLeaf, peerIssuer)
   501  				if err != nil {
   502  					return fmt.Errorf("failed to parse OCSP response from %s peer: %w", kind, err)
   503  				}
   504  
   505  				// If signer was issuer delegate double-check issuer delegate authorization
   506  				if resp.Certificate != nil {
   507  					ok := false
   508  					for _, eku := range resp.Certificate.ExtKeyUsage {
   509  						if eku == x509.ExtKeyUsageOCSPSigning {
   510  							ok = true
   511  							break
   512  						}
   513  					}
   514  					if !ok {
   515  						return fmt.Errorf("OCSP staple's signer missing authorization by CA to act as OCSP signer")
   516  					}
   517  				}
   518  
   519  				// Check that the OCSP response is effective, take defaults for clockskew and default validity
   520  				peerOpts := certidp.OCSPPeerConfig{ClockSkew: -1, TTLUnsetNextUpdate: -1}
   521  				sLog := certidp.Log{Debugf: srv.Debugf}
   522  				if !certidp.OCSPResponseCurrent(resp, &peerOpts, &sLog) {
   523  					return fmt.Errorf("OCSP staple from %s peer not current", kind)
   524  				}
   525  
   526  				if resp.Status != ocsp.Good {
   527  					return fmt.Errorf("bad status for OCSP Staple from %s peer: %s", kind, ocspStatusString(resp.Status))
   528  				}
   529  
   530  				return nil
   531  			}
   532  
   533  			// When server makes a peer connection, need to also present an OCSP Staple.
   534  			tc.GetClientCertificate = func(info *tls.CertificateRequestInfo) (*tls.Certificate, error) {
   535  				raw, _, err := mon.getStatus()
   536  				if err != nil {
   537  					return nil, err
   538  				}
   539  				cert.OCSPStaple = raw
   540  
   541  				return &cert, nil
   542  			}
   543  		default:
   544  			// GetClientCertificate returns a certificate that's presented to a server.
   545  			tc.GetClientCertificate = func(info *tls.CertificateRequestInfo) (*tls.Certificate, error) {
   546  				return &cert, nil
   547  			}
   548  		}
   549  
   550  	}
   551  	return tc, mon, nil
   552  }
   553  
   554  func (s *Server) setupOCSPStapleStoreDir() error {
   555  	opts := s.getOpts()
   556  	storeDir := opts.StoreDir
   557  	if storeDir == _EMPTY_ {
   558  		return nil
   559  	}
   560  	storeDir = filepath.Join(storeDir, defaultOCSPStoreDir)
   561  	if stat, err := os.Stat(storeDir); os.IsNotExist(err) {
   562  		if err := os.MkdirAll(storeDir, defaultDirPerms); err != nil {
   563  			return fmt.Errorf("could not create OCSP storage directory - %v", err)
   564  		}
   565  	} else if stat == nil || !stat.IsDir() {
   566  		return fmt.Errorf("OCSP storage directory is not a directory")
   567  	}
   568  	return nil
   569  }
   570  
   571  type tlsConfigKind struct {
   572  	tlsConfig   *tls.Config
   573  	tlsOpts     *TLSConfigOpts
   574  	kind        string
   575  	isLeafSpoke bool
   576  	apply       func(*tls.Config)
   577  }
   578  
   579  func (s *Server) configureOCSP() []*tlsConfigKind {
   580  	sopts := s.getOpts()
   581  
   582  	configs := make([]*tlsConfigKind, 0)
   583  
   584  	if config := sopts.TLSConfig; config != nil {
   585  		opts := sopts.tlsConfigOpts
   586  		o := &tlsConfigKind{
   587  			kind:      kindStringMap[CLIENT],
   588  			tlsConfig: config,
   589  			tlsOpts:   opts,
   590  			apply:     func(tc *tls.Config) { sopts.TLSConfig = tc },
   591  		}
   592  		configs = append(configs, o)
   593  	}
   594  	if config := sopts.Websocket.TLSConfig; config != nil {
   595  		opts := sopts.Websocket.tlsConfigOpts
   596  		o := &tlsConfigKind{
   597  			kind:      kindStringMap[CLIENT],
   598  			tlsConfig: config,
   599  			tlsOpts:   opts,
   600  			apply:     func(tc *tls.Config) { sopts.Websocket.TLSConfig = tc },
   601  		}
   602  		configs = append(configs, o)
   603  	}
   604  	if config := sopts.MQTT.TLSConfig; config != nil {
   605  		opts := sopts.tlsConfigOpts
   606  		o := &tlsConfigKind{
   607  			kind:      kindStringMap[CLIENT],
   608  			tlsConfig: config,
   609  			tlsOpts:   opts,
   610  			apply:     func(tc *tls.Config) { sopts.MQTT.TLSConfig = tc },
   611  		}
   612  		configs = append(configs, o)
   613  	}
   614  	if config := sopts.Cluster.TLSConfig; config != nil {
   615  		opts := sopts.Cluster.tlsConfigOpts
   616  		o := &tlsConfigKind{
   617  			kind:      kindStringMap[ROUTER],
   618  			tlsConfig: config,
   619  			tlsOpts:   opts,
   620  			apply:     func(tc *tls.Config) { sopts.Cluster.TLSConfig = tc },
   621  		}
   622  		configs = append(configs, o)
   623  	}
   624  	if config := sopts.LeafNode.TLSConfig; config != nil {
   625  		opts := sopts.LeafNode.tlsConfigOpts
   626  		o := &tlsConfigKind{
   627  			kind:      kindStringMap[LEAF],
   628  			tlsConfig: config,
   629  			tlsOpts:   opts,
   630  			apply:     func(tc *tls.Config) { sopts.LeafNode.TLSConfig = tc },
   631  		}
   632  		configs = append(configs, o)
   633  	}
   634  	for _, remote := range sopts.LeafNode.Remotes {
   635  		if config := remote.TLSConfig; config != nil {
   636  			// Use a copy of the remote here since will be used
   637  			// in the apply func callback below.
   638  			r, opts := remote, remote.tlsConfigOpts
   639  			o := &tlsConfigKind{
   640  				kind:        kindStringMap[LEAF],
   641  				tlsConfig:   config,
   642  				tlsOpts:     opts,
   643  				isLeafSpoke: true,
   644  				apply:       func(tc *tls.Config) { r.TLSConfig = tc },
   645  			}
   646  			configs = append(configs, o)
   647  		}
   648  	}
   649  	if config := sopts.Gateway.TLSConfig; config != nil {
   650  		opts := sopts.Gateway.tlsConfigOpts
   651  		o := &tlsConfigKind{
   652  			kind:      kindStringMap[GATEWAY],
   653  			tlsConfig: config,
   654  			tlsOpts:   opts,
   655  			apply:     func(tc *tls.Config) { sopts.Gateway.TLSConfig = tc },
   656  		}
   657  		configs = append(configs, o)
   658  	}
   659  	for _, remote := range sopts.Gateway.Gateways {
   660  		if config := remote.TLSConfig; config != nil {
   661  			gw, opts := remote, remote.tlsConfigOpts
   662  			o := &tlsConfigKind{
   663  				kind:      kindStringMap[GATEWAY],
   664  				tlsConfig: config,
   665  				tlsOpts:   opts,
   666  				apply:     func(tc *tls.Config) { gw.TLSConfig = tc },
   667  			}
   668  			configs = append(configs, o)
   669  		}
   670  	}
   671  	return configs
   672  }
   673  
   674  func (s *Server) enableOCSP() error {
   675  	configs := s.configureOCSP()
   676  
   677  	for _, config := range configs {
   678  
   679  		// We do not staple Leaf Hub and Leaf Spokes, use ocsp_peer
   680  		if config.kind != kindStringMap[LEAF] {
   681  			// OCSP Stapling feature, will also enable tls server peer check for gateway and route peers
   682  			tc, mon, err := s.NewOCSPMonitor(config)
   683  			if err != nil {
   684  				return err
   685  			}
   686  			// Check if an OCSP stapling monitor is required for this certificate.
   687  			if mon != nil {
   688  				s.ocsps = append(s.ocsps, mon)
   689  
   690  				// Override the TLS config with one that follows OCSP stapling
   691  				config.apply(tc)
   692  			}
   693  		}
   694  
   695  		// OCSP peer check (client mTLS, leaf mTLS, leaf remote TLS)
   696  		if config.kind == kindStringMap[CLIENT] || config.kind == kindStringMap[LEAF] {
   697  			tc, plugged, err := s.plugTLSOCSPPeer(config)
   698  			if err != nil {
   699  				return err
   700  			}
   701  			if plugged && tc != nil {
   702  				s.ocspPeerVerify = true
   703  				config.apply(tc)
   704  			}
   705  		}
   706  	}
   707  
   708  	return nil
   709  }
   710  
   711  func (s *Server) startOCSPMonitoring() {
   712  	s.mu.Lock()
   713  	ocsps := s.ocsps
   714  	s.mu.Unlock()
   715  	if ocsps == nil {
   716  		return
   717  	}
   718  	for _, mon := range ocsps {
   719  		m := mon
   720  		m.mu.Lock()
   721  		kind := m.kind
   722  		m.mu.Unlock()
   723  		s.Noticef("OCSP Stapling enabled for %s connections", kind)
   724  		s.startGoRoutine(func() { m.run() })
   725  	}
   726  }
   727  
   728  func (s *Server) reloadOCSP() error {
   729  	if err := s.setupOCSPStapleStoreDir(); err != nil {
   730  		return err
   731  	}
   732  
   733  	s.mu.Lock()
   734  	ocsps := s.ocsps
   735  	s.mu.Unlock()
   736  
   737  	// Stop all OCSP Stapling monitors in case there were any running.
   738  	for _, oc := range ocsps {
   739  		oc.stop()
   740  	}
   741  
   742  	configs := s.configureOCSP()
   743  
   744  	// Restart the monitors under the new configuration.
   745  	ocspm := make([]*OCSPMonitor, 0)
   746  
   747  	// Reset server's ocspPeerVerify flag to re-detect at least one plugged OCSP peer
   748  	s.mu.Lock()
   749  	s.ocspPeerVerify = false
   750  	s.mu.Unlock()
   751  	s.stopOCSPResponseCache()
   752  
   753  	for _, config := range configs {
   754  		// We do not staple Leaf Hub and Leaf Spokes, use ocsp_peer
   755  		if config.kind != kindStringMap[LEAF] {
   756  			tc, mon, err := s.NewOCSPMonitor(config)
   757  			if err != nil {
   758  				return err
   759  			}
   760  			// Check if an OCSP stapling monitor is required for this certificate.
   761  			if mon != nil {
   762  				ocspm = append(ocspm, mon)
   763  
   764  				// Apply latest TLS configuration.
   765  				config.apply(tc)
   766  			}
   767  		}
   768  
   769  		// OCSP peer check (client mTLS, leaf mTLS, leaf remote TLS)
   770  		if config.kind == kindStringMap[CLIENT] || config.kind == kindStringMap[LEAF] {
   771  			tc, plugged, err := s.plugTLSOCSPPeer(config)
   772  			if err != nil {
   773  				return err
   774  			}
   775  			if plugged && tc != nil {
   776  				s.ocspPeerVerify = true
   777  				config.apply(tc)
   778  			}
   779  		}
   780  	}
   781  
   782  	// Replace stopped monitors with the new ones.
   783  	s.mu.Lock()
   784  	s.ocsps = ocspm
   785  	s.mu.Unlock()
   786  
   787  	// Dispatch all goroutines once again.
   788  	s.startOCSPMonitoring()
   789  
   790  	// Init and restart OCSP responder cache
   791  	s.stopOCSPResponseCache()
   792  	s.initOCSPResponseCache()
   793  	s.startOCSPResponseCache()
   794  
   795  	return nil
   796  }
   797  
   798  func hasOCSPStatusRequest(cert *x509.Certificate) bool {
   799  	// OID for id-pe-tlsfeature defined in RFC here:
   800  	// https://datatracker.ietf.org/doc/html/rfc7633
   801  	tlsFeatures := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 24}
   802  	const statusRequestExt = 5
   803  
   804  	// Example values:
   805  	// * [48 3 2 1 5] - seen when creating own certs locally
   806  	// * [30 3 2 1 5] - seen in the wild
   807  	// Documentation:
   808  	// https://tools.ietf.org/html/rfc6066
   809  
   810  	for _, ext := range cert.Extensions {
   811  		if !ext.Id.Equal(tlsFeatures) {
   812  			continue
   813  		}
   814  
   815  		var val []int
   816  		rest, err := asn1.Unmarshal(ext.Value, &val)
   817  		if err != nil || len(rest) > 0 {
   818  			return false
   819  		}
   820  
   821  		for _, n := range val {
   822  			if n == statusRequestExt {
   823  				return true
   824  			}
   825  		}
   826  		break
   827  	}
   828  
   829  	return false
   830  }
   831  
   832  // writeOCSPStatus writes an OCSP status to a temporary file then moves it to a
   833  // new path, in an attempt to avoid corrupting existing data.
   834  func (oc *OCSPMonitor) writeOCSPStatus(storeDir, file string, data []byte) error {
   835  	storeDir = filepath.Join(storeDir, defaultOCSPStoreDir)
   836  	tmp, err := os.CreateTemp(storeDir, "tmp-cert-status")
   837  	if err != nil {
   838  		return err
   839  	}
   840  
   841  	if _, err := tmp.Write(data); err != nil {
   842  		tmp.Close()
   843  		os.Remove(tmp.Name())
   844  		return err
   845  	}
   846  	if err := tmp.Close(); err != nil {
   847  		return err
   848  	}
   849  
   850  	oc.mu.Lock()
   851  	err = os.Rename(tmp.Name(), filepath.Join(storeDir, file))
   852  	oc.mu.Unlock()
   853  	if err != nil {
   854  		os.Remove(tmp.Name())
   855  		return err
   856  	}
   857  
   858  	return nil
   859  }
   860  
   861  func parseCertPEM(name string) ([]*x509.Certificate, error) {
   862  	data, err := os.ReadFile(name)
   863  	if err != nil {
   864  		return nil, err
   865  	}
   866  
   867  	var pemBytes []byte
   868  
   869  	var block *pem.Block
   870  	for len(data) != 0 {
   871  		block, data = pem.Decode(data)
   872  		if block == nil {
   873  			break
   874  		}
   875  		if block.Type != "CERTIFICATE" {
   876  			return nil, fmt.Errorf("unexpected PEM certificate type: %s", block.Type)
   877  		}
   878  
   879  		pemBytes = append(pemBytes, block.Bytes...)
   880  	}
   881  
   882  	return x509.ParseCertificates(pemBytes)
   883  }
   884  
   885  // getOCSPIssuerLocally determines a leaf's issuer from locally configured certificates
   886  func getOCSPIssuerLocally(trustedCAs []*x509.Certificate, certBundle []*x509.Certificate) (*x509.Certificate, error) {
   887  	var vOpts x509.VerifyOptions
   888  	var leaf *x509.Certificate
   889  	trustedCAPool := x509.NewCertPool()
   890  
   891  	// Require Leaf as first cert in bundle
   892  	if len(certBundle) > 0 {
   893  		leaf = certBundle[0]
   894  	} else {
   895  		return nil, fmt.Errorf("invalid ocsp ca configuration")
   896  	}
   897  
   898  	// Allow Issuer to be configured as second cert in bundle
   899  	if len(certBundle) > 1 {
   900  		// The operator may have misconfigured the cert bundle
   901  		issuerCandidate := certBundle[1]
   902  		err := issuerCandidate.CheckSignature(leaf.SignatureAlgorithm, leaf.RawTBSCertificate, leaf.Signature)
   903  		if err != nil {
   904  			return nil, fmt.Errorf("invalid issuer configuration: %w", err)
   905  		} else {
   906  			return issuerCandidate, nil
   907  		}
   908  	}
   909  
   910  	// Operator did not provide the Leaf Issuer in cert bundle second position
   911  	// so we will attempt to create at least one ordered verified chain from the
   912  	// trusted CA pool.
   913  
   914  	// Specify CA trust store to validator; if unset, system trust store used
   915  	if len(trustedCAs) > 0 {
   916  		for _, ca := range trustedCAs {
   917  			trustedCAPool.AddCert(ca)
   918  		}
   919  		vOpts.Roots = trustedCAPool
   920  	}
   921  
   922  	return certstore.GetLeafIssuer(leaf, vOpts), nil
   923  }
   924  
   925  // getOCSPIssuer determines an issuer certificate from the cert (bundle) or the file-based CA trust store
   926  func getOCSPIssuer(caFile string, chain [][]byte) (*x509.Certificate, error) {
   927  	var issuer *x509.Certificate
   928  	var trustedCAs []*x509.Certificate
   929  	var certBundle []*x509.Certificate
   930  	var err error
   931  
   932  	// FIXME(tgb): extend if pluggable CA store provider added to NATS (i.e. other than PEM file)
   933  
   934  	// Non-system default CA trust store passed
   935  	if caFile != _EMPTY_ {
   936  		trustedCAs, err = parseCertPEM(caFile)
   937  		if err != nil {
   938  			return nil, fmt.Errorf("failed to parse ca_file: %v", err)
   939  		}
   940  	}
   941  
   942  	// Specify bundled intermediate CA store
   943  	for _, certBytes := range chain {
   944  		cert, err := x509.ParseCertificate(certBytes)
   945  		if err != nil {
   946  			return nil, fmt.Errorf("failed to parse cert: %v", err)
   947  		}
   948  		certBundle = append(certBundle, cert)
   949  	}
   950  
   951  	issuer, err = getOCSPIssuerLocally(trustedCAs, certBundle)
   952  	if err != nil || issuer == nil {
   953  		return nil, fmt.Errorf("no issuers found")
   954  	}
   955  
   956  	if !issuer.IsCA {
   957  		return nil, fmt.Errorf("%s invalid ca basic constraints: is not ca", issuer.Subject)
   958  	}
   959  	return issuer, nil
   960  }
   961  
   962  func ocspStatusString(n int) string {
   963  	switch n {
   964  	case ocsp.Good:
   965  		return "good"
   966  	case ocsp.Revoked:
   967  		return "revoked"
   968  	default:
   969  		return "unknown"
   970  	}
   971  }
   972  
   973  func validOCSPResponse(r *ocsp.Response) error {
   974  	// Time validation not handled by ParseResponse.
   975  	// https://tools.ietf.org/html/rfc6960#section-4.2.2.1
   976  	if !r.NextUpdate.IsZero() && r.NextUpdate.Before(time.Now()) {
   977  		t := r.NextUpdate.Format(time.RFC3339Nano)
   978  		return fmt.Errorf("invalid ocsp NextUpdate, is past time: %s", t)
   979  	}
   980  	if r.ThisUpdate.After(time.Now()) {
   981  		t := r.ThisUpdate.Format(time.RFC3339Nano)
   982  		return fmt.Errorf("invalid ocsp ThisUpdate, is future time: %s", t)
   983  	}
   984  
   985  	return nil
   986  }