Source file
src/crypto/x509/root_unix_test.go
1
2
3
4
5
6
7 package x509
8
9 import (
10 "bytes"
11 "fmt"
12 "os"
13 "path/filepath"
14 "slices"
15 "strings"
16 "testing"
17 )
18
19 const (
20 testDirCN = "test-dir"
21 testFile = "test-file.crt"
22 testFileCN = "test-file"
23 testMissing = "missing"
24 )
25
26 func TestEnvVars(t *testing.T) {
27 tmpDir := t.TempDir()
28 testCert, err := os.ReadFile("testdata/test-dir.crt")
29 if err != nil {
30 t.Fatalf("failed to read test cert: %s", err)
31 }
32 if err := os.WriteFile(filepath.Join(tmpDir, testFile), testCert, 0644); err != nil {
33 if err != nil {
34 t.Fatalf("failed to write test cert: %s", err)
35 }
36 }
37
38 testCases := []struct {
39 name string
40 fileEnv string
41 dirEnv string
42 files []string
43 dirs []string
44 cns []string
45 }{
46 {
47
48 name: "override-defaults",
49 fileEnv: testMissing,
50 dirEnv: testMissing,
51 files: []string{testFile},
52 dirs: []string{tmpDir},
53 cns: nil,
54 },
55 {
56
57 name: "file",
58 fileEnv: testFile,
59 dirEnv: "",
60 files: nil,
61 dirs: nil,
62 cns: []string{testFileCN},
63 },
64 {
65
66 name: "dir",
67 fileEnv: "",
68 dirEnv: tmpDir,
69 files: nil,
70 dirs: nil,
71 cns: []string{testDirCN},
72 },
73 {
74
75 name: "file+dir",
76 fileEnv: testFile,
77 dirEnv: tmpDir,
78 files: nil,
79 dirs: nil,
80 cns: []string{testFileCN, testDirCN},
81 },
82 {
83
84 name: "empty-fall-through",
85 fileEnv: "",
86 dirEnv: "",
87 files: []string{testFile},
88 dirs: []string{tmpDir},
89 cns: []string{testFileCN, testDirCN},
90 },
91 }
92
93
94 origCertFiles, origCertDirectories := certFiles, certDirectories
95 origFile, origDir := os.Getenv(certFileEnv), os.Getenv(certDirEnv)
96 defer func() {
97 certFiles = origCertFiles
98 certDirectories = origCertDirectories
99 os.Setenv(certFileEnv, origFile)
100 os.Setenv(certDirEnv, origDir)
101 }()
102
103 for _, tc := range testCases {
104 t.Run(tc.name, func(t *testing.T) {
105 if err := os.Setenv(certFileEnv, tc.fileEnv); err != nil {
106 t.Fatalf("setenv %q failed: %v", certFileEnv, err)
107 }
108 if err := os.Setenv(certDirEnv, tc.dirEnv); err != nil {
109 t.Fatalf("setenv %q failed: %v", certDirEnv, err)
110 }
111
112 certFiles, certDirectories = tc.files, tc.dirs
113
114 r, err := loadSystemRoots()
115 if err != nil {
116 t.Fatal("unexpected failure:", err)
117 }
118
119 if r == nil {
120 t.Fatal("nil roots")
121 }
122
123
124 for i, cn := range tc.cns {
125 if i >= r.len() {
126 t.Errorf("missing cert %v @ %v", cn, i)
127 } else if r.mustCert(t, i).Subject.CommonName != cn {
128 fmt.Printf("%#v\n", r.mustCert(t, 0).Subject)
129 t.Errorf("unexpected cert common name %q, want %q", r.mustCert(t, i).Subject.CommonName, cn)
130 }
131 }
132 if r.len() > len(tc.cns) {
133 t.Errorf("got %v certs, which is more than %v wanted", r.len(), len(tc.cns))
134 }
135 })
136 }
137 }
138
139
140
141
142
143 func TestLoadSystemCertsLoadColonSeparatedDirs(t *testing.T) {
144 origFile, origDir := os.Getenv(certFileEnv), os.Getenv(certDirEnv)
145 origCertFiles := certFiles[:]
146
147
148
149
150 certFiles = certFiles[:0]
151 os.Setenv(certFileEnv, "")
152
153 defer func() {
154 certFiles = origCertFiles[:]
155 os.Setenv(certDirEnv, origDir)
156 os.Setenv(certFileEnv, origFile)
157 }()
158
159 tmpDir := t.TempDir()
160
161 rootPEMs := []string{
162 gtsRoot,
163 googleLeaf,
164 }
165
166 var certDirs []string
167 for i, certPEM := range rootPEMs {
168 certDir := filepath.Join(tmpDir, fmt.Sprintf("cert-%d", i))
169 if err := os.MkdirAll(certDir, 0755); err != nil {
170 t.Fatalf("Failed to create certificate dir: %v", err)
171 }
172 certOutFile := filepath.Join(certDir, "cert.crt")
173 if err := os.WriteFile(certOutFile, []byte(certPEM), 0655); err != nil {
174 t.Fatalf("Failed to write certificate to file: %v", err)
175 }
176 certDirs = append(certDirs, certDir)
177 }
178
179
180 if g, w := len(certDirs), len(rootPEMs); g != w {
181 t.Fatalf("Failed sanity check: len(certsDir)=%d is not equal to len(rootsPEMS)=%d", g, w)
182 }
183
184
185 colonConcatCertDirs := strings.Join(certDirs, ":")
186 os.Setenv(certDirEnv, colonConcatCertDirs)
187 gotPool, err := loadSystemRoots()
188 if err != nil {
189 t.Fatalf("Failed to load system roots: %v", err)
190 }
191 subjects := gotPool.Subjects()
192
193 if g, w := len(subjects), len(rootPEMs); g != w {
194 t.Fatalf("Invalid number of subjects: got %d want %d", g, w)
195 }
196
197 wantPool := NewCertPool()
198 for _, certPEM := range rootPEMs {
199 wantPool.AppendCertsFromPEM([]byte(certPEM))
200 }
201 strCertPool := func(p *CertPool) string {
202 return string(bytes.Join(p.Subjects(), []byte("\n")))
203 }
204
205 if !certPoolEqual(gotPool, wantPool) {
206 g, w := strCertPool(gotPool), strCertPool(wantPool)
207 t.Fatalf("Mismatched certPools\nGot:\n%s\n\nWant:\n%s", g, w)
208 }
209 }
210
211 func TestReadUniqueDirectoryEntries(t *testing.T) {
212 tmp := t.TempDir()
213 temp := func(base string) string { return filepath.Join(tmp, base) }
214 if f, err := os.Create(temp("file")); err != nil {
215 t.Fatal(err)
216 } else {
217 f.Close()
218 }
219 if err := os.Symlink("target-in", temp("link-in")); err != nil {
220 t.Fatal(err)
221 }
222 if err := os.Symlink("../target-out", temp("link-out")); err != nil {
223 t.Fatal(err)
224 }
225 got, err := readUniqueDirectoryEntries(tmp)
226 if err != nil {
227 t.Fatal(err)
228 }
229 gotNames := []string{}
230 for _, fi := range got {
231 gotNames = append(gotNames, fi.Name())
232 }
233 wantNames := []string{"file", "link-out"}
234 if !slices.Equal(gotNames, wantNames) {
235 t.Errorf("got %q; want %q", gotNames, wantNames)
236 }
237 }
238
View as plain text