1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package fixchain
16
17 import (
18 "context"
19 "net/http"
20 "strings"
21 "sync"
22 "testing"
23
24 "github.com/google/certificate-transparency-go/client"
25 "github.com/google/certificate-transparency-go/jsonclient"
26 "github.com/google/certificate-transparency-go/x509"
27 )
28
29 var newFixAndLogTests = []fixAndLogTest{
30
31 {
32 url: "https://ct.googleapis.com/pilot",
33 chain: []string{googleLeaf, thawteIntermediate, verisignRoot},
34
35 function: "QueueChain",
36 expLoggedChains: [][]string{
37 {"Google", "Thawte", "VeriSign"},
38 },
39 },
40 {
41 url: "https://ct.googleapis.com/pilot",
42 chain: []string{googleLeaf, thawteIntermediate},
43
44 function: "QueueChain",
45 expLoggedChains: [][]string{
46 {"Google", "Thawte", "VeriSign"},
47 },
48 },
49 {
50 url: "https://ct.googleapis.com/pilot",
51 chain: []string{megaLeaf, comodoIntermediate, comodoRoot},
52
53 function: "QueueChain",
54 expectedErrs: []errorType{VerifyFailed, FixFailed},
55 },
56 {
57 url: "https://ct.googleapis.com/pilot",
58 chain: []string{testC, testB, testA},
59
60 function: "QueueChain",
61 expectedErrs: []errorType{VerifyFailed, FixFailed},
62 },
63 {
64 url: "https://ct.googleapis.com/pilot",
65 chain: []string{googleLeaf},
66
67 function: "QueueChain",
68 expLoggedChains: [][]string{
69 {"Google", "Thawte", "VeriSign"},
70 },
71 expectedErrs: []errorType{VerifyFailed},
72 },
73 {
74 url: "https://ct.googleapis.com/pilot",
75 chain: []string{testLeaf},
76
77 function: "QueueChain",
78 expLoggedChains: [][]string{
79 {"Leaf", "Intermediate2", "Intermediate1", "CA"},
80 },
81 expectedErrs: []errorType{VerifyFailed},
82 },
83 {
84 url: "https://ct.googleapis.com/pilot",
85 chain: []string{megaLeaf, googleLeaf, thawteIntermediate, verisignRoot},
86
87 function: "QueueChain",
88 expectedErrs: []errorType{VerifyFailed, FixFailed},
89 },
90 {
91 url: "https://ct.googleapis.com/pilot",
92 chain: []string{testLeaf, megaLeaf, googleLeaf, thawteIntermediate, comodoRoot},
93
94 function: "QueueChain",
95 expLoggedChains: [][]string{
96 {"Leaf", "Intermediate2", "Intermediate1", "CA"},
97 },
98 expectedErrs: []errorType{VerifyFailed},
99 },
100
101 {
102 url: "https://ct.googleapis.com/pilot",
103 chain: []string{googleLeaf, thawteIntermediate, verisignRoot},
104
105 function: "QueueAllCertsInChain",
106 expLoggedChains: [][]string{
107 {"Google", "Thawte", "VeriSign"},
108 {"Thawte", "VeriSign"},
109 {"VeriSign"},
110 },
111 },
112 {
113 url: "https://ct.googleapis.com/pilot",
114 chain: []string{googleLeaf, thawteIntermediate},
115
116 function: "QueueAllCertsInChain",
117 expLoggedChains: [][]string{
118 {"Google", "Thawte", "VeriSign"},
119 {"Thawte", "VeriSign"},
120 },
121 },
122 {
123 url: "https://ct.googleapis.com/pilot",
124 chain: []string{megaLeaf, comodoIntermediate, comodoRoot},
125
126 function: "QueueAllCertsInChain",
127 expectedErrs: []errorType{
128 VerifyFailed, FixFailed,
129 VerifyFailed, FixFailed,
130 VerifyFailed, FixFailed,
131 },
132 },
133 {
134 url: "https://ct.googleapis.com/pilot",
135 chain: []string{testC, testB, testA},
136
137 function: "QueueAllCertsInChain",
138 expectedErrs: []errorType{
139 VerifyFailed, FixFailed,
140 VerifyFailed, FixFailed,
141 VerifyFailed, FixFailed,
142 },
143 },
144 {
145 url: "https://ct.googleapis.com/pilot",
146 chain: []string{googleLeaf},
147
148 function: "QueueAllCertsInChain",
149 expLoggedChains: [][]string{
150 {"Google", "Thawte", "VeriSign"},
151 },
152 expectedErrs: []errorType{VerifyFailed},
153 },
154 {
155 url: "https://ct.googleapis.com/pilot",
156 chain: []string{testLeaf},
157
158 function: "QueueAllCertsInChain",
159 expLoggedChains: [][]string{
160 {"Leaf", "Intermediate2", "Intermediate1", "CA"},
161 },
162 expectedErrs: []errorType{VerifyFailed},
163 },
164 {
165 url: "https://ct.googleapis.com/pilot",
166 chain: []string{megaLeaf, googleLeaf, thawteIntermediate, verisignRoot},
167
168 function: "QueueAllCertsInChain",
169 expLoggedChains: [][]string{
170 {"Google", "Thawte", "VeriSign"},
171 {"Thawte", "VeriSign"},
172 {"VeriSign"},
173 },
174 expectedErrs: []errorType{
175 VerifyFailed, FixFailed,
176 },
177 },
178 {
179 url: "https://ct.googleapis.com/pilot",
180 chain: []string{testLeaf, megaLeaf, googleLeaf, thawteIntermediate, comodoRoot},
181
182 function: "QueueAllCertsInChain",
183 expLoggedChains: [][]string{
184 {"Leaf", "Intermediate2", "Intermediate1", "CA"},
185 {"Google", "Thawte", "VeriSign"},
186 {"Thawte", "VeriSign"},
187 },
188 expectedErrs: []errorType{
189 VerifyFailed,
190 VerifyFailed, FixFailed,
191 VerifyFailed, FixFailed,
192 },
193 },
194 }
195
196 func TestNewFixAndLog(t *testing.T) {
197
198 ctx := context.Background()
199 for i, test := range newFixAndLogTests {
200 seen := make([]bool, len(test.expLoggedChains))
201 errors := make(chan *FixError)
202 c := &http.Client{Transport: &testRoundTripper{t: t, test: &test, testIndex: i, seen: seen}}
203 logClient, err := client.New(test.url, c, jsonclient.Options{})
204 if err != nil {
205 t.Fatalf("failed to create LogClient: %v", err)
206 }
207 fl := NewFixAndLog(ctx, 1, 1, errors, c, logClient, newNilLimiter(), false)
208
209 var wg sync.WaitGroup
210 wg.Add(1)
211 go func() {
212 defer wg.Done()
213 testErrors(t, i, test.expectedErrs, errors)
214 }()
215 switch test.function {
216 case "QueueChain":
217 fl.QueueChain(extractTestChain(t, i, test.chain))
218 case "QueueAllCertsInChain":
219 fl.QueueAllCertsInChain(extractTestChain(t, i, test.chain))
220 }
221 fl.Wait()
222 close(errors)
223 wg.Wait()
224
225
226 for j, val := range seen {
227 if !val {
228 t.Errorf("#%d: Expected chain was not logged: %s", i, strings.Join(test.expLoggedChains[j], " -> "))
229 }
230 }
231 }
232 }
233
234 var fixAndLogQueueTests = []fixAndLogTest{
235 {
236 url: "https://ct.googleapis.com/pilot",
237 chain: []string{googleLeaf, thawteIntermediate, verisignRoot},
238
239 expectedCert: "Google",
240 expectedChain: []string{"Google", "Thawte", "VeriSign"},
241 expectedRoots: []string{verisignRoot, testRoot},
242 },
243 {
244 url: "https://ct.googleapis.com/pilot",
245 chain: []string{googleLeaf, googleLeaf, thawteIntermediate, verisignRoot},
246
247 expectedCert: "Google",
248 expectedChain: []string{"Google", "Thawte", "VeriSign"},
249 expectedRoots: []string{verisignRoot, testRoot},
250 },
251 {
252 url: "https://ct.googleapis.com/pilot",
253 },
254 }
255
256 func testQueueAllCertsInChain(t *testing.T, i int, test *fixAndLogTest, fl *FixAndLog) {
257 defer fl.wg.Done()
258 seen := make([]bool, len(test.expectedChain))
259 NextToFix:
260 for fix := range fl.fixer.toFix {
261
262 matchTestChain(t, i, test.expectedChain, fix.chain.certs)
263
264 matchTestRoots(t, i, test.expectedRoots, fix.roots)
265 for j, expCert := range test.expectedChain {
266 if seen[j] {
267 continue
268 }
269 if strings.Contains(nameToKey(&fix.cert.Subject), expCert) {
270 seen[j] = true
271 continue NextToFix
272 }
273 }
274 t.Errorf("#%d: Queued certificate %s was not expected", i, nameToKey(&fix.cert.Subject))
275 }
276 for j, val := range seen {
277 if !val {
278 t.Errorf("#%d: Expected certificate %s was not queued", i, test.expectedChain[j])
279 }
280 }
281 }
282
283 func TestQueueAllCertsInChain(t *testing.T) {
284 ctx := context.Background()
285 for i, test := range fixAndLogQueueTests {
286 f := &Fixer{toFix: make(chan *toFix)}
287 c := &http.Client{Transport: &testRoundTripper{}}
288 logClient, err := client.New(test.url, c, jsonclient.Options{})
289 if err != nil {
290 t.Fatalf("failed to create LogClient: %v", err)
291 }
292 l := &Logger{
293 ctx: ctx,
294 client: logClient,
295 postCertCache: newLockedMap(),
296 }
297 fl := &FixAndLog{fixer: f, chains: make(chan []*x509.Certificate), logger: l, done: newLockedMap()}
298
299 fl.wg.Add(1)
300 go testQueueAllCertsInChain(t, i, &test, fl)
301 fl.QueueAllCertsInChain(extractTestChain(t, i, test.chain))
302 fl.Wait()
303 }
304 }
305
306 func testFixAndLogQueueChain(t *testing.T, i int, test *fixAndLogTest, fl *FixAndLog) {
307 defer fl.wg.Done()
308
309 fix, ok := <-fl.fixer.toFix
310 if ok {
311
312 if !strings.Contains(nameToKey(&fix.cert.Subject), test.expectedCert) {
313 t.Errorf("#%d: Expected cert does not match queued cert", i)
314 }
315
316
317 matchTestChain(t, i, test.expectedChain, fix.chain.certs)
318
319
320 matchTestRoots(t, i, test.expectedRoots, fix.roots)
321 }
322 }
323
324 func TestFixAndLogQueueChain(t *testing.T) {
325 ctx := context.Background()
326 for i, test := range fixAndLogQueueTests {
327 f := &Fixer{toFix: make(chan *toFix)}
328 c := &http.Client{Transport: &testRoundTripper{}}
329 logClient, err := client.New(test.url, c, jsonclient.Options{})
330 if err != nil {
331 t.Fatalf("failed to create LogClient: %v", err)
332 }
333 l := &Logger{
334 ctx: ctx,
335 client: logClient,
336 postCertCache: newLockedMap(),
337 }
338 fl := &FixAndLog{fixer: f, chains: make(chan []*x509.Certificate), logger: l, done: newLockedMap()}
339
340 fl.wg.Add(1)
341 go testFixAndLogQueueChain(t, i, &test, fl)
342 fl.QueueChain(extractTestChain(t, i, test.chain))
343 fl.Wait()
344 }
345 }
346
View as plain text