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 }