github.com/nats-io/nats-server/v2@v2.11.0-preview.2/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  	"github.com/nats-io/nats-server/v2/server/certidp"
    37  	"github.com/nats-io/nats-server/v2/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 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  			ccert := cert
   464  			raw, _, err := mon.getStatus()
   465  			if err != nil {
   466  				return nil, err
   467  			}
   468  			return &tls.Certificate{
   469  				OCSPStaple:                   raw,
   470  				Certificate:                  ccert.Certificate,
   471  				PrivateKey:                   ccert.PrivateKey,
   472  				SupportedSignatureAlgorithms: ccert.SupportedSignatureAlgorithms,
   473  				SignedCertificateTimestamps:  ccert.SignedCertificateTimestamps,
   474  				Leaf:                         ccert.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  				ccert := cert
   536  				raw, _, err := mon.getStatus()
   537  				if err != nil {
   538  					return nil, err
   539  				}
   540  				// NOTE: crypto/tls.sendClientCertificate internally also calls getClientCertificate
   541  				// so if for some reason these callbacks are triggered concurrently during a reconnect
   542  				// there can be a race. To avoid that, the OCSP monitor lock is used to serialize access
   543  				// to the staple which could also change inflight during an update.
   544  				mon.mu.Lock()
   545  				ccert.OCSPStaple = raw
   546  				mon.mu.Unlock()
   547  
   548  				return &ccert, nil
   549  			}
   550  		default:
   551  			// GetClientCertificate returns a certificate that's presented to a server.
   552  			tc.GetClientCertificate = func(info *tls.CertificateRequestInfo) (*tls.Certificate, error) {
   553  				return &cert, nil
   554  			}
   555  		}
   556  	}
   557  	return tc, mon, nil
   558  }
   559  
   560  func (s *Server) setupOCSPStapleStoreDir() error {
   561  	opts := s.getOpts()
   562  	storeDir := opts.StoreDir
   563  	if storeDir == _EMPTY_ {
   564  		return nil
   565  	}
   566  	storeDir = filepath.Join(storeDir, defaultOCSPStoreDir)
   567  	if stat, err := os.Stat(storeDir); os.IsNotExist(err) {
   568  		if err := os.MkdirAll(storeDir, defaultDirPerms); err != nil {
   569  			return fmt.Errorf("could not create OCSP storage directory - %v", err)
   570  		}
   571  	} else if stat == nil || !stat.IsDir() {
   572  		return fmt.Errorf("OCSP storage directory is not a directory")
   573  	}
   574  	return nil
   575  }
   576  
   577  type tlsConfigKind struct {
   578  	tlsConfig   *tls.Config
   579  	tlsOpts     *TLSConfigOpts
   580  	kind        string
   581  	isLeafSpoke bool
   582  	apply       func(*tls.Config)
   583  }
   584  
   585  func (s *Server) configureOCSP() []*tlsConfigKind {
   586  	sopts := s.getOpts()
   587  
   588  	configs := make([]*tlsConfigKind, 0)
   589  
   590  	if config := sopts.TLSConfig; config != nil {
   591  		opts := sopts.tlsConfigOpts
   592  		o := &tlsConfigKind{
   593  			kind:      kindStringMap[CLIENT],
   594  			tlsConfig: config,
   595  			tlsOpts:   opts,
   596  			apply:     func(tc *tls.Config) { sopts.TLSConfig = tc },
   597  		}
   598  		configs = append(configs, o)
   599  	}
   600  	if config := sopts.Websocket.TLSConfig; config != nil {
   601  		opts := sopts.Websocket.tlsConfigOpts
   602  		o := &tlsConfigKind{
   603  			kind:      kindStringMap[CLIENT],
   604  			tlsConfig: config,
   605  			tlsOpts:   opts,
   606  			apply:     func(tc *tls.Config) { sopts.Websocket.TLSConfig = tc },
   607  		}
   608  		configs = append(configs, o)
   609  	}
   610  	if config := sopts.MQTT.TLSConfig; config != nil {
   611  		opts := sopts.tlsConfigOpts
   612  		o := &tlsConfigKind{
   613  			kind:      kindStringMap[CLIENT],
   614  			tlsConfig: config,
   615  			tlsOpts:   opts,
   616  			apply:     func(tc *tls.Config) { sopts.MQTT.TLSConfig = tc },
   617  		}
   618  		configs = append(configs, o)
   619  	}
   620  	if config := sopts.Cluster.TLSConfig; config != nil {
   621  		opts := sopts.Cluster.tlsConfigOpts
   622  		o := &tlsConfigKind{
   623  			kind:      kindStringMap[ROUTER],
   624  			tlsConfig: config,
   625  			tlsOpts:   opts,
   626  			apply:     func(tc *tls.Config) { sopts.Cluster.TLSConfig = tc },
   627  		}
   628  		configs = append(configs, o)
   629  	}
   630  	if config := sopts.LeafNode.TLSConfig; config != nil {
   631  		opts := sopts.LeafNode.tlsConfigOpts
   632  		o := &tlsConfigKind{
   633  			kind:      kindStringMap[LEAF],
   634  			tlsConfig: config,
   635  			tlsOpts:   opts,
   636  			apply:     func(tc *tls.Config) { sopts.LeafNode.TLSConfig = tc },
   637  		}
   638  		configs = append(configs, o)
   639  	}
   640  	for _, remote := range sopts.LeafNode.Remotes {
   641  		if config := remote.TLSConfig; config != nil {
   642  			// Use a copy of the remote here since will be used
   643  			// in the apply func callback below.
   644  			r, opts := remote, remote.tlsConfigOpts
   645  			o := &tlsConfigKind{
   646  				kind:        kindStringMap[LEAF],
   647  				tlsConfig:   config,
   648  				tlsOpts:     opts,
   649  				isLeafSpoke: true,
   650  				apply:       func(tc *tls.Config) { r.TLSConfig = tc },
   651  			}
   652  			configs = append(configs, o)
   653  		}
   654  	}
   655  	if config := sopts.Gateway.TLSConfig; config != nil {
   656  		opts := sopts.Gateway.tlsConfigOpts
   657  		o := &tlsConfigKind{
   658  			kind:      kindStringMap[GATEWAY],
   659  			tlsConfig: config,
   660  			tlsOpts:   opts,
   661  			apply:     func(tc *tls.Config) { sopts.Gateway.TLSConfig = tc },
   662  		}
   663  		configs = append(configs, o)
   664  	}
   665  	for _, remote := range sopts.Gateway.Gateways {
   666  		if config := remote.TLSConfig; config != nil {
   667  			gw, opts := remote, remote.tlsConfigOpts
   668  			o := &tlsConfigKind{
   669  				kind:      kindStringMap[GATEWAY],
   670  				tlsConfig: config,
   671  				tlsOpts:   opts,
   672  				apply:     func(tc *tls.Config) { gw.TLSConfig = tc },
   673  			}
   674  			configs = append(configs, o)
   675  		}
   676  	}
   677  	return configs
   678  }
   679  
   680  func (s *Server) enableOCSP() error {
   681  	configs := s.configureOCSP()
   682  
   683  	for _, config := range configs {
   684  
   685  		// We do not staple Leaf Hub and Leaf Spokes, use ocsp_peer
   686  		if config.kind != kindStringMap[LEAF] {
   687  			// OCSP Stapling feature, will also enable tls server peer check for gateway and route peers
   688  			tc, mon, err := s.NewOCSPMonitor(config)
   689  			if err != nil {
   690  				return err
   691  			}
   692  			// Check if an OCSP stapling monitor is required for this certificate.
   693  			if mon != nil {
   694  				s.ocsps = append(s.ocsps, mon)
   695  
   696  				// Override the TLS config with one that follows OCSP stapling
   697  				config.apply(tc)
   698  			}
   699  		}
   700  
   701  		// OCSP peer check (client mTLS, leaf mTLS, leaf remote TLS)
   702  		if config.kind == kindStringMap[CLIENT] || config.kind == kindStringMap[LEAF] {
   703  			tc, plugged, err := s.plugTLSOCSPPeer(config)
   704  			if err != nil {
   705  				return err
   706  			}
   707  			if plugged && tc != nil {
   708  				s.ocspPeerVerify = true
   709  				config.apply(tc)
   710  			}
   711  		}
   712  	}
   713  
   714  	return nil
   715  }
   716  
   717  func (s *Server) startOCSPMonitoring() {
   718  	s.mu.Lock()
   719  	ocsps := s.ocsps
   720  	s.mu.Unlock()
   721  	if ocsps == nil {
   722  		return
   723  	}
   724  	for _, mon := range ocsps {
   725  		m := mon
   726  		m.mu.Lock()
   727  		kind := m.kind
   728  		m.mu.Unlock()
   729  		s.Noticef("OCSP Stapling enabled for %s connections", kind)
   730  		s.startGoRoutine(func() { m.run() })
   731  	}
   732  }
   733  
   734  func (s *Server) reloadOCSP() error {
   735  	if err := s.setupOCSPStapleStoreDir(); err != nil {
   736  		return err
   737  	}
   738  
   739  	s.mu.Lock()
   740  	ocsps := s.ocsps
   741  	s.mu.Unlock()
   742  
   743  	// Stop all OCSP Stapling monitors in case there were any running.
   744  	for _, oc := range ocsps {
   745  		oc.stop()
   746  	}
   747  
   748  	configs := s.configureOCSP()
   749  
   750  	// Restart the monitors under the new configuration.
   751  	ocspm := make([]*OCSPMonitor, 0)
   752  
   753  	// Reset server's ocspPeerVerify flag to re-detect at least one plugged OCSP peer
   754  	s.mu.Lock()
   755  	s.ocspPeerVerify = false
   756  	s.mu.Unlock()
   757  	s.stopOCSPResponseCache()
   758  
   759  	for _, config := range configs {
   760  		// We do not staple Leaf Hub and Leaf Spokes, use ocsp_peer
   761  		if config.kind != kindStringMap[LEAF] {
   762  			tc, mon, err := s.NewOCSPMonitor(config)
   763  			if err != nil {
   764  				return err
   765  			}
   766  			// Check if an OCSP stapling monitor is required for this certificate.
   767  			if mon != nil {
   768  				ocspm = append(ocspm, mon)
   769  
   770  				// Apply latest TLS configuration after OCSP monitors have started.
   771  				defer config.apply(tc)
   772  			}
   773  		}
   774  
   775  		// OCSP peer check (client mTLS, leaf mTLS, leaf remote TLS)
   776  		if config.kind == kindStringMap[CLIENT] || config.kind == kindStringMap[LEAF] {
   777  			tc, plugged, err := s.plugTLSOCSPPeer(config)
   778  			if err != nil {
   779  				return err
   780  			}
   781  			if plugged && tc != nil {
   782  				s.ocspPeerVerify = true
   783  				defer config.apply(tc)
   784  			}
   785  		}
   786  	}
   787  
   788  	// Replace stopped monitors with the new ones.
   789  	s.mu.Lock()
   790  	s.ocsps = ocspm
   791  	s.mu.Unlock()
   792  
   793  	// Dispatch all goroutines once again.
   794  	s.startOCSPMonitoring()
   795  
   796  	// Init and restart OCSP responder cache
   797  	s.stopOCSPResponseCache()
   798  	s.initOCSPResponseCache()
   799  	s.startOCSPResponseCache()
   800  
   801  	return nil
   802  }
   803  
   804  func hasOCSPStatusRequest(cert *x509.Certificate) bool {
   805  	// OID for id-pe-tlsfeature defined in RFC here:
   806  	// https://datatracker.ietf.org/doc/html/rfc7633
   807  	tlsFeatures := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 24}
   808  	const statusRequestExt = 5
   809  
   810  	// Example values:
   811  	// * [48 3 2 1 5] - seen when creating own certs locally
   812  	// * [30 3 2 1 5] - seen in the wild
   813  	// Documentation:
   814  	// https://tools.ietf.org/html/rfc6066
   815  
   816  	for _, ext := range cert.Extensions {
   817  		if !ext.Id.Equal(tlsFeatures) {
   818  			continue
   819  		}
   820  
   821  		var val []int
   822  		rest, err := asn1.Unmarshal(ext.Value, &val)
   823  		if err != nil || len(rest) > 0 {
   824  			return false
   825  		}
   826  
   827  		for _, n := range val {
   828  			if n == statusRequestExt {
   829  				return true
   830  			}
   831  		}
   832  		break
   833  	}
   834  
   835  	return false
   836  }
   837  
   838  // writeOCSPStatus writes an OCSP status to a temporary file then moves it to a
   839  // new path, in an attempt to avoid corrupting existing data.
   840  func (oc *OCSPMonitor) writeOCSPStatus(storeDir, file string, data []byte) error {
   841  	storeDir = filepath.Join(storeDir, defaultOCSPStoreDir)
   842  	tmp, err := os.CreateTemp(storeDir, "tmp-cert-status")
   843  	if err != nil {
   844  		return err
   845  	}
   846  
   847  	if _, err := tmp.Write(data); err != nil {
   848  		tmp.Close()
   849  		os.Remove(tmp.Name())
   850  		return err
   851  	}
   852  	if err := tmp.Close(); err != nil {
   853  		return err
   854  	}
   855  
   856  	oc.mu.Lock()
   857  	err = os.Rename(tmp.Name(), filepath.Join(storeDir, file))
   858  	oc.mu.Unlock()
   859  	if err != nil {
   860  		os.Remove(tmp.Name())
   861  		return err
   862  	}
   863  
   864  	return nil
   865  }
   866  
   867  func parseCertPEM(name string) ([]*x509.Certificate, error) {
   868  	data, err := os.ReadFile(name)
   869  	if err != nil {
   870  		return nil, err
   871  	}
   872  
   873  	var pemBytes []byte
   874  
   875  	var block *pem.Block
   876  	for len(data) != 0 {
   877  		block, data = pem.Decode(data)
   878  		if block == nil {
   879  			break
   880  		}
   881  		if block.Type != "CERTIFICATE" {
   882  			return nil, fmt.Errorf("unexpected PEM certificate type: %s", block.Type)
   883  		}
   884  
   885  		pemBytes = append(pemBytes, block.Bytes...)
   886  	}
   887  
   888  	return x509.ParseCertificates(pemBytes)
   889  }
   890  
   891  // getOCSPIssuerLocally determines a leaf's issuer from locally configured certificates
   892  func getOCSPIssuerLocally(trustedCAs []*x509.Certificate, certBundle []*x509.Certificate) (*x509.Certificate, error) {
   893  	var vOpts x509.VerifyOptions
   894  	var leaf *x509.Certificate
   895  	trustedCAPool := x509.NewCertPool()
   896  
   897  	// Require Leaf as first cert in bundle
   898  	if len(certBundle) > 0 {
   899  		leaf = certBundle[0]
   900  	} else {
   901  		return nil, fmt.Errorf("invalid ocsp ca configuration")
   902  	}
   903  
   904  	// Allow Issuer to be configured as second cert in bundle
   905  	if len(certBundle) > 1 {
   906  		// The operator may have misconfigured the cert bundle
   907  		issuerCandidate := certBundle[1]
   908  		err := issuerCandidate.CheckSignature(leaf.SignatureAlgorithm, leaf.RawTBSCertificate, leaf.Signature)
   909  		if err != nil {
   910  			return nil, fmt.Errorf("invalid issuer configuration: %w", err)
   911  		} else {
   912  			return issuerCandidate, nil
   913  		}
   914  	}
   915  
   916  	// Operator did not provide the Leaf Issuer in cert bundle second position
   917  	// so we will attempt to create at least one ordered verified chain from the
   918  	// trusted CA pool.
   919  
   920  	// Specify CA trust store to validator; if unset, system trust store used
   921  	if len(trustedCAs) > 0 {
   922  		for _, ca := range trustedCAs {
   923  			trustedCAPool.AddCert(ca)
   924  		}
   925  		vOpts.Roots = trustedCAPool
   926  	}
   927  
   928  	return certstore.GetLeafIssuer(leaf, vOpts), nil
   929  }
   930  
   931  // getOCSPIssuer determines an issuer certificate from the cert (bundle) or the file-based CA trust store
   932  func getOCSPIssuer(caFile string, chain [][]byte) (*x509.Certificate, error) {
   933  	var issuer *x509.Certificate
   934  	var trustedCAs []*x509.Certificate
   935  	var certBundle []*x509.Certificate
   936  	var err error
   937  
   938  	// FIXME(tgb): extend if pluggable CA store provider added to NATS (i.e. other than PEM file)
   939  
   940  	// Non-system default CA trust store passed
   941  	if caFile != _EMPTY_ {
   942  		trustedCAs, err = parseCertPEM(caFile)
   943  		if err != nil {
   944  			return nil, fmt.Errorf("failed to parse ca_file: %v", err)
   945  		}
   946  	}
   947  
   948  	// Specify bundled intermediate CA store
   949  	for _, certBytes := range chain {
   950  		cert, err := x509.ParseCertificate(certBytes)
   951  		if err != nil {
   952  			return nil, fmt.Errorf("failed to parse cert: %v", err)
   953  		}
   954  		certBundle = append(certBundle, cert)
   955  	}
   956  
   957  	issuer, err = getOCSPIssuerLocally(trustedCAs, certBundle)
   958  	if err != nil || issuer == nil {
   959  		return nil, fmt.Errorf("no issuers found")
   960  	}
   961  
   962  	if !issuer.IsCA {
   963  		return nil, fmt.Errorf("%s invalid ca basic constraints: is not ca", issuer.Subject)
   964  	}
   965  	return issuer, nil
   966  }
   967  
   968  func ocspStatusString(n int) string {
   969  	switch n {
   970  	case ocsp.Good:
   971  		return "good"
   972  	case ocsp.Revoked:
   973  		return "revoked"
   974  	default:
   975  		return "unknown"
   976  	}
   977  }
   978  
   979  func validOCSPResponse(r *ocsp.Response) error {
   980  	// Time validation not handled by ParseResponse.
   981  	// https://tools.ietf.org/html/rfc6960#section-4.2.2.1
   982  	if !r.NextUpdate.IsZero() && r.NextUpdate.Before(time.Now()) {
   983  		t := r.NextUpdate.Format(time.RFC3339Nano)
   984  		return fmt.Errorf("invalid ocsp NextUpdate, is past time: %s", t)
   985  	}
   986  	if r.ThisUpdate.After(time.Now()) {
   987  		t := r.ThisUpdate.Format(time.RFC3339Nano)
   988  		return fmt.Errorf("invalid ocsp ThisUpdate, is future time: %s", t)
   989  	}
   990  
   991  	return nil
   992  }