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  )
    11  
    12  var (
    13  	once           sync.Once
    14  	systemRootsMu  sync.RWMutex
    15  	systemRoots    *CertPool
    16  	systemRootsErr error
    17  	fallbacksSet   bool
    18  )
    19  
    20  func systemRootsPool() *CertPool {
    21  	once.Do(initSystemRoots)
    22  	systemRootsMu.RLock()
    23  	defer systemRootsMu.RUnlock()
    24  	return systemRoots
    25  }
    26  
    27  func initSystemRoots() {
    28  	systemRootsMu.Lock()
    29  	defer systemRootsMu.Unlock()
    30  	systemRoots, systemRootsErr = loadSystemRoots()
    31  	if systemRootsErr != nil {
    32  		systemRoots = nil
    33  	}
    34  }
    35  
    36  var x509usefallbackroots = godebug.New("x509usefallbackroots")
    37  
    38  // SetFallbackRoots sets the roots to use during certificate verification, if no
    39  // custom roots are specified and a platform verifier or a system certificate
    40  // pool is not available (for instance in a container which does not have a root
    41  // certificate bundle). SetFallbackRoots will panic if roots is nil.
    42  //
    43  // SetFallbackRoots may only be called once, if called multiple times it will
    44  // panic.
    45  //
    46  // The fallback behavior can be forced on all platforms, even when there is a
    47  // system certificate pool, by setting GODEBUG=x509usefallbackroots=1 (note that
    48  // on Windows and macOS this will disable usage of the platform verification
    49  // APIs and cause the pure Go verifier to be used). Setting
    50  // x509usefallbackroots=1 without calling SetFallbackRoots has no effect.
    51  func SetFallbackRoots(roots *CertPool) {
    52  	if roots == nil {
    53  		panic("roots must be non-nil")
    54  	}
    55  
    56  	// trigger initSystemRoots if it hasn't already been called before we
    57  	// take the lock
    58  	_ = systemRootsPool()
    59  
    60  	systemRootsMu.Lock()
    61  	defer systemRootsMu.Unlock()
    62  
    63  	if fallbacksSet {
    64  		panic("SetFallbackRoots has already been called")
    65  	}
    66  	fallbacksSet = true
    67  
    68  	if systemRoots != nil && (systemRoots.len() > 0 || systemRoots.systemPool) {
    69  		if x509usefallbackroots.Value() != "1" {
    70  			return
    71  		}
    72  		x509usefallbackroots.IncNonDefault()
    73  	}
    74  	systemRoots, systemRootsErr = roots, nil
    75  }
    76  

View as plain text