Source file src/crypto/x509/root.go

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package x509
     6  
     7  import (
     8  	"internal/godebug"
     9  	"sync"
    10  	_ "unsafe" // for linkname
    11  )
    12  
    13  // systemRoots should be an internal detail,
    14  // but widely used packages access it using linkname.
    15  // Notable members of the hall of shame include:
    16  //   - github.com/breml/rootcerts
    17  //
    18  // Do not remove or change the type signature.
    19  // See go.dev/issue/67401.
    20  //
    21  //go:linkname systemRoots
    22  var (
    23  	once           sync.Once
    24  	systemRootsMu  sync.RWMutex
    25  	systemRoots    *CertPool
    26  	systemRootsErr error
    27  	fallbacksSet   bool
    28  )
    29  
    30  func systemRootsPool() *CertPool {
    31  	once.Do(initSystemRoots)
    32  	systemRootsMu.RLock()
    33  	defer systemRootsMu.RUnlock()
    34  	return systemRoots
    35  }
    36  
    37  func initSystemRoots() {
    38  	systemRootsMu.Lock()
    39  	defer systemRootsMu.Unlock()
    40  	systemRoots, systemRootsErr = loadSystemRoots()
    41  	if systemRootsErr != nil {
    42  		systemRoots = nil
    43  	}
    44  }
    45  
    46  var x509usefallbackroots = godebug.New("x509usefallbackroots")
    47  
    48  // SetFallbackRoots sets the roots to use during certificate verification, if no
    49  // custom roots are specified and a platform verifier or a system certificate
    50  // pool is not available (for instance in a container which does not have a root
    51  // certificate bundle). SetFallbackRoots will panic if roots is nil.
    52  //
    53  // SetFallbackRoots may only be called once, if called multiple times it will
    54  // panic.
    55  //
    56  // The fallback behavior can be forced on all platforms, even when there is a
    57  // system certificate pool, by setting GODEBUG=x509usefallbackroots=1 (note that
    58  // on Windows and macOS this will disable usage of the platform verification
    59  // APIs and cause the pure Go verifier to be used). Setting
    60  // x509usefallbackroots=1 without calling SetFallbackRoots has no effect.
    61  func SetFallbackRoots(roots *CertPool) {
    62  	if roots == nil {
    63  		panic("roots must be non-nil")
    64  	}
    65  
    66  	// trigger initSystemRoots if it hasn't already been called before we
    67  	// take the lock
    68  	_ = systemRootsPool()
    69  
    70  	systemRootsMu.Lock()
    71  	defer systemRootsMu.Unlock()
    72  
    73  	if fallbacksSet {
    74  		panic("SetFallbackRoots has already been called")
    75  	}
    76  	fallbacksSet = true
    77  
    78  	if systemRoots != nil && (systemRoots.len() > 0 || systemRoots.systemPool) {
    79  		if x509usefallbackroots.Value() != "1" {
    80  			return
    81  		}
    82  		x509usefallbackroots.IncNonDefault()
    83  	}
    84  	systemRoots, systemRootsErr = roots, nil
    85  }
    86  

View as plain text