Black Lives Matter. Support the Equal Justice Initiative.

Source file src/crypto/x509/root_unix.go

Documentation: crypto/x509

     1  // Copyright 2011 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  // +build aix dragonfly freebsd js,wasm linux netbsd openbsd solaris
     6  
     7  package x509
     8  
     9  import (
    10  	"io/ioutil"
    11  	"os"
    12  	"path/filepath"
    13  	"strings"
    14  )
    15  
    16  // Possible directories with certificate files; stop after successfully
    17  // reading at least one file from a directory.
    18  var certDirectories = []string{
    19  	"/etc/ssl/certs",               // SLES10/SLES11, https://golang.org/issue/12139
    20  	"/system/etc/security/cacerts", // Android
    21  	"/usr/local/share/certs",       // FreeBSD
    22  	"/etc/pki/tls/certs",           // Fedora/RHEL
    23  	"/etc/openssl/certs",           // NetBSD
    24  	"/var/ssl/certs",               // AIX
    25  }
    26  
    27  const (
    28  	// certFileEnv is the environment variable which identifies where to locate
    29  	// the SSL certificate file. If set this overrides the system default.
    30  	certFileEnv = "SSL_CERT_FILE"
    31  
    32  	// certDirEnv is the environment variable which identifies which directory
    33  	// to check for SSL certificate files. If set this overrides the system default.
    34  	// It is a colon separated list of directories.
    35  	// See https://www.openssl.org/docs/man1.0.2/man1/c_rehash.html.
    36  	certDirEnv = "SSL_CERT_DIR"
    37  )
    38  
    39  func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
    40  	return nil, nil
    41  }
    42  
    43  func loadSystemRoots() (*CertPool, error) {
    44  	roots := NewCertPool()
    45  
    46  	files := certFiles
    47  	if f := os.Getenv(certFileEnv); f != "" {
    48  		files = []string{f}
    49  	}
    50  
    51  	var firstErr error
    52  	for _, file := range files {
    53  		data, err := ioutil.ReadFile(file)
    54  		if err == nil {
    55  			roots.AppendCertsFromPEM(data)
    56  			break
    57  		}
    58  		if firstErr == nil && !os.IsNotExist(err) {
    59  			firstErr = err
    60  		}
    61  	}
    62  
    63  	dirs := certDirectories
    64  	if d := os.Getenv(certDirEnv); d != "" {
    65  		// OpenSSL and BoringSSL both use ":" as the SSL_CERT_DIR separator.
    66  		// See:
    67  		//  * https://golang.org/issue/35325
    68  		//  * https://www.openssl.org/docs/man1.0.2/man1/c_rehash.html
    69  		dirs = strings.Split(d, ":")
    70  	}
    71  
    72  	for _, directory := range dirs {
    73  		fis, err := readUniqueDirectoryEntries(directory)
    74  		if err != nil {
    75  			if firstErr == nil && !os.IsNotExist(err) {
    76  				firstErr = err
    77  			}
    78  			continue
    79  		}
    80  		for _, fi := range fis {
    81  			data, err := ioutil.ReadFile(directory + "/" + fi.Name())
    82  			if err == nil {
    83  				roots.AppendCertsFromPEM(data)
    84  			}
    85  		}
    86  	}
    87  
    88  	if len(roots.certs) > 0 || firstErr == nil {
    89  		return roots, nil
    90  	}
    91  
    92  	return nil, firstErr
    93  }
    94  
    95  // readUniqueDirectoryEntries is like ioutil.ReadDir but omits
    96  // symlinks that point within the directory.
    97  func readUniqueDirectoryEntries(dir string) ([]os.FileInfo, error) {
    98  	fis, err := ioutil.ReadDir(dir)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	uniq := fis[:0]
   103  	for _, fi := range fis {
   104  		if !isSameDirSymlink(fi, dir) {
   105  			uniq = append(uniq, fi)
   106  		}
   107  	}
   108  	return uniq, nil
   109  }
   110  
   111  // isSameDirSymlink reports whether fi in dir is a symlink with a
   112  // target not containing a slash.
   113  func isSameDirSymlink(fi os.FileInfo, dir string) bool {
   114  	if fi.Mode()&os.ModeSymlink == 0 {
   115  		return false
   116  	}
   117  	target, err := os.Readlink(filepath.Join(dir, fi.Name()))
   118  	return err == nil && !strings.Contains(target, "/")
   119  }
   120  

View as plain text