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