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