// Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package x509 import ( "internal/godebug" "sync" _ "unsafe" // for linkname ) // systemRoots should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - github.com/breml/rootcerts // // Do not remove or change the type signature. // See go.dev/issue/67401. // //go:linkname systemRoots var ( once sync.Once systemRootsMu sync.RWMutex systemRoots *CertPool systemRootsErr error fallbacksSet bool ) func systemRootsPool() *CertPool { once.Do(initSystemRoots) systemRootsMu.RLock() defer systemRootsMu.RUnlock() return systemRoots } func initSystemRoots() { systemRootsMu.Lock() defer systemRootsMu.Unlock() systemRoots, systemRootsErr = loadSystemRoots() if systemRootsErr != nil { systemRoots = nil } } var x509usefallbackroots = godebug.New("x509usefallbackroots") // SetFallbackRoots sets the roots to use during certificate verification, if no // custom roots are specified and a platform verifier or a system certificate // pool is not available (for instance in a container which does not have a root // certificate bundle). SetFallbackRoots will panic if roots is nil. // // SetFallbackRoots may only be called once, if called multiple times it will // panic. // // The fallback behavior can be forced on all platforms, even when there is a // system certificate pool, by setting GODEBUG=x509usefallbackroots=1 (note that // on Windows and macOS this will disable usage of the platform verification // APIs and cause the pure Go verifier to be used). Setting // x509usefallbackroots=1 without calling SetFallbackRoots has no effect. func SetFallbackRoots(roots *CertPool) { if roots == nil { panic("roots must be non-nil") } // trigger initSystemRoots if it hasn't already been called before we // take the lock _ = systemRootsPool() systemRootsMu.Lock() defer systemRootsMu.Unlock() if fallbacksSet { panic("SetFallbackRoots has already been called") } fallbacksSet = true if systemRoots != nil && (systemRoots.len() > 0 || systemRoots.systemPool) { if x509usefallbackroots.Value() != "1" { return } x509usefallbackroots.IncNonDefault() } systemRoots, systemRootsErr = roots, nil }