OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/cert/internal/cert_issuer_source_aia.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "net/cert/internal/parsed_certificate.h" | |
9 #include "net/cert/internal/test_helpers.h" | |
10 #include "testing/gmock/include/gmock/gmock.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 #include "url/gurl.h" | |
13 | |
14 namespace net { | |
15 | |
16 namespace { | |
17 | |
18 using ::testing::Mock; | |
19 using ::testing::StrictMock; | |
20 | |
21 ::testing::AssertionResult ReadTestPem(const std::string& file_name, | |
22 const std::string& block_name, | |
23 std::string* result) { | |
24 const PemBlockMapping mappings[] = { | |
25 {block_name.c_str(), result}, | |
26 }; | |
27 | |
28 return ReadTestDataFromPemFile(file_name, mappings); | |
29 } | |
30 | |
31 ::testing::AssertionResult ReadTestCert( | |
32 const std::string& file_name, | |
33 scoped_refptr<ParsedCertificate>* result) { | |
34 std::string der; | |
35 ::testing::AssertionResult r = | |
36 ReadTestPem("net/data/cert_issuer_source_aia_unittest/" + file_name, | |
37 "CERTIFICATE", &der); | |
38 if (!r) | |
39 return r; | |
40 *result = ParsedCertificate::CreateFromCertificateCopy(der); | |
41 if (!*result) | |
42 return ::testing::AssertionFailure() << "CreateFromCertificateCopy failed"; | |
43 return ::testing::AssertionSuccess(); | |
44 } | |
45 | |
46 std::vector<uint8_t> CertDataVector(const ParsedCertificate* cert) { | |
47 std::vector<uint8_t> data( | |
48 cert->der_cert().UnsafeData(), | |
49 cert->der_cert().UnsafeData() + cert->der_cert().Length()); | |
50 return data; | |
51 } | |
52 | |
53 class RequestManager { | |
54 public: | |
55 class Request : public CertNetFetcher::Request { | |
56 public: | |
57 explicit Request(RequestManager* manager, | |
eroman
2016/06/03 16:28:52
nit: no need for explicit
mattm
2016/06/03 21:27:27
Done.
| |
58 const CertNetFetcher::FetchCallback& callback) | |
59 : manager_(manager), callback_(callback) {} | |
60 ~Request() override { manager_->RequestWasDestroyed(); } | |
61 CertNetFetcher::FetchCallback get_callback() const { return callback_; } | |
62 | |
63 private: | |
64 RequestManager* manager_; | |
65 CertNetFetcher::FetchCallback callback_; | |
66 }; | |
67 | |
68 ~RequestManager() { CHECK_EQ(nullptr, request_); } | |
69 | |
70 std::unique_ptr<Request> CreateRequest( | |
71 const CertNetFetcher::FetchCallback& callback) { | |
72 CHECK_EQ(nullptr, request_); | |
73 std::unique_ptr<Request> request(new Request(this, callback)); | |
74 request_ = request.get(); | |
75 return request; | |
76 } | |
77 | |
78 bool is_request_alive() const { return request_; } | |
79 | |
80 CertNetFetcher::FetchCallback get_callback() const { | |
81 CHECK(is_request_alive()); | |
82 return request_->get_callback(); | |
83 } | |
84 | |
85 private: | |
86 void RequestWasDestroyed() { | |
87 CHECK_NE(nullptr, request_); | |
88 request_ = nullptr; | |
89 } | |
90 | |
91 Request* request_; | |
92 }; | |
93 | |
94 // MockCertNetFetcherImpl is an implementation of CertNetFetcher for testing. | |
95 class MockCertNetFetcherImpl : public CertNetFetcher { | |
96 public: | |
97 MockCertNetFetcherImpl() = default; | |
98 ~MockCertNetFetcherImpl() override = default; | |
99 | |
100 RequestManager* GetRequestManagerForURL(const GURL& url) { | |
101 auto it = request_map_.find(url); | |
102 if (it == request_map_.end()) | |
103 return nullptr; | |
104 return it->second.get(); | |
105 } | |
106 | |
107 WARN_UNUSED_RESULT std::unique_ptr<Request> FetchCaIssuers( | |
108 const GURL& url, | |
109 int timeout_milliseconds, | |
110 int max_response_bytes, | |
111 const FetchCallback& callback) override { | |
112 CHECK(request_map_.find(url) == request_map_.end()); | |
113 | |
114 std::unique_ptr<RequestManager> request_manager(new RequestManager()); | |
115 | |
116 std::unique_ptr<Request> request = request_manager->CreateRequest(callback); | |
117 | |
118 request_map_[url] = std::move(request_manager); | |
119 | |
120 return request; | |
121 } | |
122 | |
123 WARN_UNUSED_RESULT std::unique_ptr<Request> FetchCrl( | |
124 const GURL& url, | |
125 int timeout_milliseconds, | |
126 int max_response_bytes, | |
127 const FetchCallback& callback) override { | |
128 NOTREACHED(); | |
129 return nullptr; | |
130 } | |
131 | |
132 WARN_UNUSED_RESULT std::unique_ptr<Request> FetchOcsp( | |
133 const GURL& url, | |
134 int timeout_milliseconds, | |
135 int max_response_bytes, | |
136 const FetchCallback& callback) override { | |
137 NOTREACHED(); | |
138 return nullptr; | |
139 } | |
140 | |
141 private: | |
142 // std::map<GURL, RequestImpl*> request_map_; | |
143 std::map<GURL, std::unique_ptr<RequestManager>> request_map_; | |
144 | |
145 DISALLOW_COPY_AND_ASSIGN(MockCertNetFetcherImpl); | |
146 }; | |
147 | |
148 class MockIssuerCallback { | |
149 public: | |
150 MOCK_METHOD1(Callback, void(CertIssuerSource::Request*)); | |
151 }; | |
152 | |
153 void NotCalled(CertIssuerSource::Request* request) { | |
154 ADD_FAILURE() << "NotCalled was called"; | |
155 } | |
156 | |
157 // CertIssuerSourceAia does not return results for SyncGetIssuersOf. | |
158 TEST(CertIssuerSourceAiaUnittest, NoSyncResults) { | |
159 scoped_refptr<ParsedCertificate> cert; | |
160 ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert)); | |
161 | |
162 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
163 CertIssuerSourceAia aia_source(&mock_fetcher); | |
164 std::vector<scoped_refptr<ParsedCertificate>> issuers; | |
165 aia_source.SyncGetIssuersOf(cert.get(), &issuers); | |
166 EXPECT_EQ(0U, issuers.size()); | |
167 } | |
168 | |
169 // If the AuthorityInfoAccess extension is not present, AsyncGetIssuersOf should | |
170 // synchronously indicate no results. | |
171 TEST(CertIssuerSourceAiaUnittest, NoAia) { | |
172 scoped_refptr<ParsedCertificate> cert; | |
173 ASSERT_TRUE(ReadTestCert("target_no_aia.pem", &cert)); | |
174 | |
175 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
176 CertIssuerSourceAia aia_source(&mock_fetcher); | |
177 std::unique_ptr<CertIssuerSource::Request> request; | |
178 aia_source.AsyncGetIssuersOf(cert.get(), base::Bind(&NotCalled), &request); | |
179 EXPECT_EQ(nullptr, request); | |
180 } | |
181 | |
182 // If the AuthorityInfoAccess extension only contains non-http URIs, | |
183 // AsyncGetIssuersOf should synchronously indicate no results. | |
184 TEST(CertIssuerSourceAiaUnittest, FileAia) { | |
185 scoped_refptr<ParsedCertificate> cert; | |
186 ASSERT_TRUE(ReadTestCert("target_file_aia.pem", &cert)); | |
187 | |
188 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
189 CertIssuerSourceAia aia_source(&mock_fetcher); | |
190 std::unique_ptr<CertIssuerSource::Request> request; | |
191 aia_source.AsyncGetIssuersOf(cert.get(), base::Bind(&NotCalled), &request); | |
192 EXPECT_EQ(nullptr, request); | |
193 } | |
194 | |
195 // AuthorityInfoAccess with a single HTTP url pointing to a single DER cert. | |
196 TEST(CertIssuerSourceAiaUnittest, OneAia) { | |
197 scoped_refptr<ParsedCertificate> cert; | |
198 ASSERT_TRUE(ReadTestCert("target_one_aia.pem", &cert)); | |
199 scoped_refptr<ParsedCertificate> intermediate_cert; | |
200 ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert)); | |
201 | |
202 StrictMock<MockIssuerCallback> mock_callback; | |
203 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
204 CertIssuerSourceAia aia_source(&mock_fetcher); | |
205 std::unique_ptr<CertIssuerSource::Request> cert_source_request; | |
206 aia_source.AsyncGetIssuersOf(cert.get(), | |
207 base::Bind(&MockIssuerCallback::Callback, | |
208 base::Unretained(&mock_callback)), | |
209 &cert_source_request); | |
210 ASSERT_NE(nullptr, cert_source_request); | |
211 | |
212 RequestManager* req_manager = | |
213 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia/I.cer")); | |
214 ASSERT_TRUE(req_manager); | |
215 ASSERT_TRUE(req_manager->is_request_alive()); | |
216 | |
217 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
218 req_manager->get_callback().Run(OK, CertDataVector(intermediate_cert.get())); | |
219 Mock::VerifyAndClearExpectations(&mock_callback); | |
220 | |
221 scoped_refptr<ParsedCertificate> result_cert; | |
222 CompletionStatus status = cert_source_request->GetNext(&result_cert); | |
223 EXPECT_EQ(CompletionStatus::SYNC, status); | |
224 ASSERT_TRUE(result_cert.get()); | |
225 ASSERT_EQ(result_cert->der_cert(), intermediate_cert->der_cert()); | |
226 | |
227 status = cert_source_request->GetNext(&result_cert); | |
228 EXPECT_EQ(CompletionStatus::SYNC, status); | |
229 EXPECT_FALSE(result_cert.get()); | |
230 | |
231 EXPECT_TRUE(req_manager->is_request_alive()); | |
232 cert_source_request.reset(); | |
233 EXPECT_FALSE(req_manager->is_request_alive()); | |
234 } | |
235 | |
236 // AuthorityInfoAccess with a two URIs, one a FILE, the other a HTTP. | |
237 TEST(CertIssuerSourceAiaUnittest, OneFileOneHttpAia) { | |
238 scoped_refptr<ParsedCertificate> cert; | |
239 ASSERT_TRUE(ReadTestCert("target_file_and_http_aia.pem", &cert)); | |
240 scoped_refptr<ParsedCertificate> intermediate_cert; | |
241 ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert)); | |
242 | |
243 StrictMock<MockIssuerCallback> mock_callback; | |
244 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
245 CertIssuerSourceAia aia_source(&mock_fetcher); | |
246 std::unique_ptr<CertIssuerSource::Request> cert_source_request; | |
247 aia_source.AsyncGetIssuersOf(cert.get(), | |
248 base::Bind(&MockIssuerCallback::Callback, | |
249 base::Unretained(&mock_callback)), | |
250 &cert_source_request); | |
251 ASSERT_NE(nullptr, cert_source_request); | |
252 | |
253 RequestManager* req_manager = | |
254 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia2/I2.foo")); | |
255 ASSERT_TRUE(req_manager); | |
256 ASSERT_TRUE(req_manager->is_request_alive()); | |
257 | |
258 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
259 req_manager->get_callback().Run(OK, CertDataVector(intermediate_cert.get())); | |
260 Mock::VerifyAndClearExpectations(&mock_callback); | |
261 | |
262 scoped_refptr<ParsedCertificate> result_cert; | |
263 CompletionStatus status = cert_source_request->GetNext(&result_cert); | |
264 EXPECT_EQ(CompletionStatus::SYNC, status); | |
265 ASSERT_TRUE(result_cert.get()); | |
266 ASSERT_EQ(result_cert->der_cert(), intermediate_cert->der_cert()); | |
267 | |
268 status = cert_source_request->GetNext(&result_cert); | |
269 EXPECT_EQ(CompletionStatus::SYNC, status); | |
270 EXPECT_FALSE(result_cert.get()); | |
271 | |
272 EXPECT_TRUE(req_manager->is_request_alive()); | |
273 cert_source_request.reset(); | |
274 EXPECT_FALSE(req_manager->is_request_alive()); | |
275 } | |
276 | |
277 // AuthorityInfoAccess with two HTTP urls, each pointing to a single DER cert. | |
278 // One request completes, results are retrieved, then the next request completes | |
279 // and the results are retrieved. | |
280 TEST(CertIssuerSourceAiaUnittest, TwoAiaCompletedInSeries) { | |
281 scoped_refptr<ParsedCertificate> cert; | |
282 ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert)); | |
283 scoped_refptr<ParsedCertificate> intermediate_cert; | |
284 ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert)); | |
285 scoped_refptr<ParsedCertificate> intermediate_cert2; | |
286 ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert2)); | |
287 | |
288 StrictMock<MockIssuerCallback> mock_callback; | |
289 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
290 CertIssuerSourceAia aia_source(&mock_fetcher); | |
291 std::unique_ptr<CertIssuerSource::Request> cert_source_request; | |
292 aia_source.AsyncGetIssuersOf(cert.get(), | |
293 base::Bind(&MockIssuerCallback::Callback, | |
294 base::Unretained(&mock_callback)), | |
295 &cert_source_request); | |
296 ASSERT_NE(nullptr, cert_source_request); | |
297 | |
298 RequestManager* req_manager = | |
299 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia/I.cer")); | |
300 ASSERT_TRUE(req_manager); | |
301 ASSERT_TRUE(req_manager->is_request_alive()); | |
302 | |
303 RequestManager* req_manager2 = | |
304 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia2/I2.foo")); | |
305 ASSERT_TRUE(req_manager2); | |
306 ASSERT_TRUE(req_manager2->is_request_alive()); | |
307 | |
308 // Request for I.cer completes first. | |
309 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
310 req_manager->get_callback().Run(OK, CertDataVector(intermediate_cert.get())); | |
311 Mock::VerifyAndClearExpectations(&mock_callback); | |
312 | |
313 // Results are retrieved before the other request completes. | |
314 scoped_refptr<ParsedCertificate> result_cert; | |
315 CompletionStatus status = cert_source_request->GetNext(&result_cert); | |
316 EXPECT_EQ(CompletionStatus::SYNC, status); | |
317 ASSERT_TRUE(result_cert.get()); | |
318 ASSERT_EQ(result_cert->der_cert(), intermediate_cert->der_cert()); | |
319 | |
320 status = cert_source_request->GetNext(&result_cert); | |
321 // The other http request is still pending, status should be ASYNC to signify | |
322 // the need to wait for another callback. | |
323 ASSERT_EQ(CompletionStatus::ASYNC, status); | |
324 EXPECT_FALSE(result_cert.get()); | |
325 | |
326 // Request for I2.foo completes. | |
327 ASSERT_TRUE(req_manager2->is_request_alive()); | |
328 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
329 req_manager2->get_callback().Run(OK, | |
330 CertDataVector(intermediate_cert2.get())); | |
331 Mock::VerifyAndClearExpectations(&mock_callback); | |
332 | |
333 // Results from the second http request are retrieved. | |
334 status = cert_source_request->GetNext(&result_cert); | |
335 EXPECT_EQ(CompletionStatus::SYNC, status); | |
336 ASSERT_TRUE(result_cert.get()); | |
337 ASSERT_EQ(result_cert->der_cert(), intermediate_cert2->der_cert()); | |
338 | |
339 // No more results. | |
340 status = cert_source_request->GetNext(&result_cert); | |
341 ASSERT_EQ(CompletionStatus::SYNC, status); | |
342 EXPECT_FALSE(result_cert.get()); | |
343 | |
344 EXPECT_TRUE(req_manager->is_request_alive()); | |
345 EXPECT_TRUE(req_manager2->is_request_alive()); | |
346 cert_source_request.reset(); | |
347 EXPECT_FALSE(req_manager->is_request_alive()); | |
348 EXPECT_FALSE(req_manager2->is_request_alive()); | |
349 } | |
350 | |
351 // AuthorityInfoAccess with two HTTP urls, each pointing to a single DER cert. | |
352 // Both HTTP requests complete before the results are retrieved from the | |
353 // CertIssuerSourceAia. There should only be a single callback since the 2nd | |
354 // HTTP request completed before GetNext was called, so both requests can be | |
355 // supplied to the caller in the same batch. | |
356 TEST(CertIssuerSourceAiaUnittest, TwoAiaCompletedBeforeGetNext) { | |
357 scoped_refptr<ParsedCertificate> cert; | |
358 ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert)); | |
359 scoped_refptr<ParsedCertificate> intermediate_cert; | |
360 ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert)); | |
361 scoped_refptr<ParsedCertificate> intermediate_cert2; | |
362 ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert2)); | |
363 | |
364 StrictMock<MockIssuerCallback> mock_callback; | |
365 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
366 CertIssuerSourceAia aia_source(&mock_fetcher); | |
367 std::unique_ptr<CertIssuerSource::Request> cert_source_request; | |
368 aia_source.AsyncGetIssuersOf(cert.get(), | |
369 base::Bind(&MockIssuerCallback::Callback, | |
370 base::Unretained(&mock_callback)), | |
371 &cert_source_request); | |
372 ASSERT_NE(nullptr, cert_source_request); | |
373 | |
374 RequestManager* req_manager = | |
375 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia/I.cer")); | |
376 ASSERT_TRUE(req_manager); | |
377 ASSERT_TRUE(req_manager->is_request_alive()); | |
378 | |
379 RequestManager* req_manager2 = | |
380 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia2/I2.foo")); | |
381 ASSERT_TRUE(req_manager2); | |
382 ASSERT_TRUE(req_manager2->is_request_alive()); | |
383 | |
384 // First HTTP request completes. Callback is called as soon as the first | |
385 // request completes. | |
386 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
387 req_manager->get_callback().Run(OK, CertDataVector(intermediate_cert.get())); | |
388 Mock::VerifyAndClearExpectations(&mock_callback); | |
389 | |
390 // Second HTTP request completes before any results were retrieved from the | |
391 // CertIssuerSourceAia. The callback should not be called again. | |
392 ASSERT_TRUE(req_manager2->is_request_alive()); | |
393 req_manager2->get_callback().Run(OK, | |
394 CertDataVector(intermediate_cert2.get())); | |
395 | |
396 // Caller retrieves results. Both certs should be supplied. | |
397 scoped_refptr<ParsedCertificate> result_cert; | |
398 CompletionStatus status = cert_source_request->GetNext(&result_cert); | |
399 EXPECT_EQ(CompletionStatus::SYNC, status); | |
400 ASSERT_TRUE(result_cert.get()); | |
401 ASSERT_EQ(result_cert->der_cert(), intermediate_cert->der_cert()); | |
402 | |
403 // 2nd cert is retrieved. | |
404 status = cert_source_request->GetNext(&result_cert); | |
405 EXPECT_EQ(CompletionStatus::SYNC, status); | |
406 ASSERT_TRUE(result_cert.get()); | |
407 ASSERT_EQ(result_cert->der_cert(), intermediate_cert2->der_cert()); | |
408 | |
409 // All results are done, SYNC signals completion. | |
410 status = cert_source_request->GetNext(&result_cert); | |
411 ASSERT_EQ(CompletionStatus::SYNC, status); | |
412 EXPECT_FALSE(result_cert.get()); | |
413 } | |
414 | |
415 // AuthorityInfoAccess with three HTTP urls, each pointing to a single DER cert. | |
416 // | |
417 // 1) Two HTTP requests complete before the results are retrieved from the | |
418 // CertIssuerSourceAia. | |
419 // 2) A single cert result is retrieved via GetNext. | |
420 // 3) The third HTTP request completes. | |
421 // 4) The remaining two certs are retrieved. | |
422 // | |
423 // Only one callback should occur (after the first HTTP request completed), | |
424 // since the pending cert results weren't exhausted before the 3rd request | |
425 // completed. | |
426 TEST(CertIssuerSourceAiaUnittest, AiaRequestCompletesDuringGetNextSequence) { | |
427 scoped_refptr<ParsedCertificate> cert; | |
428 ASSERT_TRUE(ReadTestCert("target_three_aia.pem", &cert)); | |
429 scoped_refptr<ParsedCertificate> intermediate_cert; | |
430 ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert)); | |
431 scoped_refptr<ParsedCertificate> intermediate_cert2; | |
432 ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert2)); | |
433 scoped_refptr<ParsedCertificate> intermediate_cert3; | |
434 ASSERT_TRUE(ReadTestCert("i3.pem", &intermediate_cert3)); | |
435 | |
436 StrictMock<MockIssuerCallback> mock_callback; | |
437 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
438 CertIssuerSourceAia aia_source(&mock_fetcher); | |
439 std::unique_ptr<CertIssuerSource::Request> cert_source_request; | |
440 aia_source.AsyncGetIssuersOf(cert.get(), | |
441 base::Bind(&MockIssuerCallback::Callback, | |
442 base::Unretained(&mock_callback)), | |
443 &cert_source_request); | |
444 ASSERT_NE(nullptr, cert_source_request); | |
445 | |
446 RequestManager* req_manager = | |
447 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia/I.cer")); | |
448 ASSERT_TRUE(req_manager); | |
449 ASSERT_TRUE(req_manager->is_request_alive()); | |
450 | |
451 RequestManager* req_manager2 = | |
452 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia2/I2.foo")); | |
453 ASSERT_TRUE(req_manager2); | |
454 ASSERT_TRUE(req_manager2->is_request_alive()); | |
455 | |
456 RequestManager* req_manager3 = | |
457 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia3/I3.foo")); | |
458 ASSERT_TRUE(req_manager3); | |
459 ASSERT_TRUE(req_manager3->is_request_alive()); | |
460 | |
461 // First HTTP request completes. Callback is called as soon as the first | |
462 // request completes. | |
463 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
464 req_manager->get_callback().Run(OK, CertDataVector(intermediate_cert.get())); | |
465 Mock::VerifyAndClearExpectations(&mock_callback); | |
466 | |
467 // Second HTTP request completes before any results were retrieved from the | |
468 // CertIssuerSourceAia. The callback should not be called again. | |
469 ASSERT_TRUE(req_manager2->is_request_alive()); | |
470 req_manager2->get_callback().Run(OK, | |
471 CertDataVector(intermediate_cert2.get())); | |
472 | |
473 // Caller retrieves a single result. | |
474 scoped_refptr<ParsedCertificate> result_cert; | |
475 CompletionStatus status = cert_source_request->GetNext(&result_cert); | |
476 EXPECT_EQ(CompletionStatus::SYNC, status); | |
477 ASSERT_TRUE(result_cert.get()); | |
478 ASSERT_EQ(result_cert->der_cert(), intermediate_cert->der_cert()); | |
479 | |
480 // Third HTTP request completes. | |
481 // The callback should not be called again, since the last GetNext call had | |
482 // indicated more results were pending still. | |
483 ASSERT_TRUE(req_manager3->is_request_alive()); | |
484 req_manager3->get_callback().Run(OK, | |
485 CertDataVector(intermediate_cert3.get())); | |
486 | |
487 // 2nd cert is retrieved. | |
488 status = cert_source_request->GetNext(&result_cert); | |
489 EXPECT_EQ(CompletionStatus::SYNC, status); | |
490 ASSERT_TRUE(result_cert.get()); | |
491 ASSERT_EQ(result_cert->der_cert(), intermediate_cert2->der_cert()); | |
492 | |
493 // 3rd cert is retrieved. | |
494 status = cert_source_request->GetNext(&result_cert); | |
495 EXPECT_EQ(CompletionStatus::SYNC, status); | |
496 ASSERT_TRUE(result_cert.get()); | |
497 ASSERT_EQ(result_cert->der_cert(), intermediate_cert3->der_cert()); | |
498 | |
499 // All results are done, SYNC signals completion. | |
500 status = cert_source_request->GetNext(&result_cert); | |
501 ASSERT_EQ(CompletionStatus::SYNC, status); | |
502 EXPECT_FALSE(result_cert.get()); | |
503 } | |
504 | |
505 // AuthorityInfoAccess with a single HTTP url pointing to a single DER cert, | |
506 // CertNetFetcher request fails. The callback should be called to indicate the | |
507 // request is complete, but no results should be provided. | |
508 TEST(CertIssuerSourceAiaUnittest, OneAiaHttpError) { | |
509 scoped_refptr<ParsedCertificate> cert; | |
510 ASSERT_TRUE(ReadTestCert("target_one_aia.pem", &cert)); | |
511 scoped_refptr<ParsedCertificate> intermediate_cert; | |
512 ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert)); | |
513 | |
514 StrictMock<MockIssuerCallback> mock_callback; | |
515 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
516 CertIssuerSourceAia aia_source(&mock_fetcher); | |
517 std::unique_ptr<CertIssuerSource::Request> cert_source_request; | |
518 aia_source.AsyncGetIssuersOf(cert.get(), | |
519 base::Bind(&MockIssuerCallback::Callback, | |
520 base::Unretained(&mock_callback)), | |
521 &cert_source_request); | |
522 ASSERT_NE(nullptr, cert_source_request); | |
523 | |
524 RequestManager* req_manager = | |
525 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia/I.cer")); | |
526 ASSERT_TRUE(req_manager); | |
527 ASSERT_TRUE(req_manager->is_request_alive()); | |
528 | |
529 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
530 // HTTP request returns with an error. | |
531 req_manager->get_callback().Run(ERR_FAILED, std::vector<uint8_t>()); | |
532 Mock::VerifyAndClearExpectations(&mock_callback); | |
533 | |
534 scoped_refptr<ParsedCertificate> result_cert; | |
535 CompletionStatus status = cert_source_request->GetNext(&result_cert); | |
536 EXPECT_EQ(CompletionStatus::SYNC, status); | |
537 EXPECT_FALSE(result_cert.get()); | |
538 } | |
539 | |
540 // AuthorityInfoAccess with a single HTTP url pointing to a single DER cert, | |
541 // CertNetFetcher request completes, but the DER cert fails to parse. The | |
542 // callback should be called to indicate the request is complete, but no results | |
543 // should be provided. | |
544 TEST(CertIssuerSourceAiaUnittest, OneAiaParseError) { | |
545 scoped_refptr<ParsedCertificate> cert; | |
546 ASSERT_TRUE(ReadTestCert("target_one_aia.pem", &cert)); | |
547 | |
548 StrictMock<MockIssuerCallback> mock_callback; | |
549 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
550 CertIssuerSourceAia aia_source(&mock_fetcher); | |
551 std::unique_ptr<CertIssuerSource::Request> cert_source_request; | |
552 aia_source.AsyncGetIssuersOf(cert.get(), | |
553 base::Bind(&MockIssuerCallback::Callback, | |
554 base::Unretained(&mock_callback)), | |
555 &cert_source_request); | |
556 ASSERT_NE(nullptr, cert_source_request); | |
557 | |
558 RequestManager* req_manager = | |
559 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia/I.cer")); | |
560 ASSERT_TRUE(req_manager); | |
561 ASSERT_TRUE(req_manager->is_request_alive()); | |
562 | |
563 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
564 // HTTP request returns with an error. | |
565 uint8_t data[] = {1, 2, 3, 4, 5}; | |
566 req_manager->get_callback().Run( | |
567 OK, std::vector<uint8_t>(data, data + arraysize(data))); | |
568 Mock::VerifyAndClearExpectations(&mock_callback); | |
569 | |
570 scoped_refptr<ParsedCertificate> result_cert; | |
571 CompletionStatus status = cert_source_request->GetNext(&result_cert); | |
572 EXPECT_EQ(CompletionStatus::SYNC, status); | |
573 EXPECT_FALSE(result_cert.get()); | |
574 } | |
575 | |
576 // AuthorityInfoAccess with two HTTP urls, each pointing to a single DER cert. | |
577 // One request fails. No callback should be generated yet. Once the second | |
578 // request completes, the callback should occur. | |
579 TEST(CertIssuerSourceAiaUnittest, TwoAiaCompletedInSeriesFirstFails) { | |
580 scoped_refptr<ParsedCertificate> cert; | |
581 ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert)); | |
582 scoped_refptr<ParsedCertificate> intermediate_cert2; | |
583 ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert2)); | |
584 | |
585 StrictMock<MockIssuerCallback> mock_callback; | |
586 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
587 CertIssuerSourceAia aia_source(&mock_fetcher); | |
588 std::unique_ptr<CertIssuerSource::Request> cert_source_request; | |
589 aia_source.AsyncGetIssuersOf(cert.get(), | |
590 base::Bind(&MockIssuerCallback::Callback, | |
591 base::Unretained(&mock_callback)), | |
592 &cert_source_request); | |
593 ASSERT_NE(nullptr, cert_source_request); | |
594 | |
595 RequestManager* req_manager = | |
596 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia/I.cer")); | |
597 ASSERT_TRUE(req_manager); | |
598 ASSERT_TRUE(req_manager->is_request_alive()); | |
599 | |
600 RequestManager* req_manager2 = | |
601 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia2/I2.foo")); | |
602 ASSERT_TRUE(req_manager2); | |
603 ASSERT_TRUE(req_manager2->is_request_alive()); | |
604 | |
605 // Request for I.cer completes first, but fails. Callback is NOT called. | |
606 req_manager->get_callback().Run(ERR_INVALID_RESPONSE, std::vector<uint8_t>()); | |
607 Mock::VerifyAndClearExpectations(&mock_callback); | |
608 | |
609 // Request for I2.foo completes. Callback should be called now. | |
610 ASSERT_TRUE(req_manager2->is_request_alive()); | |
611 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
612 req_manager2->get_callback().Run(OK, | |
613 CertDataVector(intermediate_cert2.get())); | |
614 Mock::VerifyAndClearExpectations(&mock_callback); | |
615 | |
616 // Results from the second http request are retrieved. | |
617 scoped_refptr<ParsedCertificate> result_cert; | |
618 CompletionStatus status = cert_source_request->GetNext(&result_cert); | |
619 EXPECT_EQ(CompletionStatus::SYNC, status); | |
620 ASSERT_TRUE(result_cert.get()); | |
621 ASSERT_EQ(result_cert->der_cert(), intermediate_cert2->der_cert()); | |
622 | |
623 // No more results. | |
624 status = cert_source_request->GetNext(&result_cert); | |
625 ASSERT_EQ(CompletionStatus::SYNC, status); | |
626 EXPECT_FALSE(result_cert.get()); | |
627 } | |
628 | |
629 // AuthorityInfoAccess with two HTTP urls, each pointing to a single DER cert. | |
630 // First request completes, result is retrieved, then the second request fails. | |
631 // The second callback should occur to indicate that the results are exhausted, | |
632 // even though no more results are available. | |
633 TEST(CertIssuerSourceAiaUnittest, TwoAiaCompletedInSeriesSecondFails) { | |
634 scoped_refptr<ParsedCertificate> cert; | |
635 ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert)); | |
636 scoped_refptr<ParsedCertificate> intermediate_cert; | |
637 ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert)); | |
638 | |
639 StrictMock<MockIssuerCallback> mock_callback; | |
640 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
641 CertIssuerSourceAia aia_source(&mock_fetcher); | |
642 std::unique_ptr<CertIssuerSource::Request> cert_source_request; | |
643 aia_source.AsyncGetIssuersOf(cert.get(), | |
644 base::Bind(&MockIssuerCallback::Callback, | |
645 base::Unretained(&mock_callback)), | |
646 &cert_source_request); | |
647 ASSERT_NE(nullptr, cert_source_request); | |
648 | |
649 RequestManager* req_manager = | |
650 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia/I.cer")); | |
651 ASSERT_TRUE(req_manager); | |
652 ASSERT_TRUE(req_manager->is_request_alive()); | |
653 | |
654 RequestManager* req_manager2 = | |
655 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia2/I2.foo")); | |
656 ASSERT_TRUE(req_manager2); | |
657 ASSERT_TRUE(req_manager2->is_request_alive()); | |
658 | |
659 // Request for I.cer completes first. | |
660 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
661 req_manager->get_callback().Run(OK, CertDataVector(intermediate_cert.get())); | |
662 Mock::VerifyAndClearExpectations(&mock_callback); | |
663 | |
664 // Results are retrieved before the other request completes. | |
665 scoped_refptr<ParsedCertificate> result_cert; | |
666 CompletionStatus status = cert_source_request->GetNext(&result_cert); | |
667 EXPECT_EQ(CompletionStatus::SYNC, status); | |
668 ASSERT_TRUE(result_cert.get()); | |
669 ASSERT_EQ(result_cert->der_cert(), intermediate_cert->der_cert()); | |
670 | |
671 status = cert_source_request->GetNext(&result_cert); | |
672 // The other http request is still pending, status should be ASYNC to signify | |
673 // the need to wait for another callback. | |
674 ASSERT_EQ(CompletionStatus::ASYNC, status); | |
675 EXPECT_FALSE(result_cert.get()); | |
676 | |
677 // Request for I2.foo fails. Callback should be called to indicate that | |
678 // results are exhausted. | |
679 ASSERT_TRUE(req_manager2->is_request_alive()); | |
680 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
681 req_manager2->get_callback().Run(ERR_INVALID_RESPONSE, | |
682 std::vector<uint8_t>()); | |
683 Mock::VerifyAndClearExpectations(&mock_callback); | |
684 | |
685 // GetNext has no more results. | |
686 status = cert_source_request->GetNext(&result_cert); | |
687 ASSERT_EQ(CompletionStatus::SYNC, status); | |
688 EXPECT_FALSE(result_cert.get()); | |
689 } | |
690 | |
691 // AuthorityInfoAccess with two HTTP urls. Request is cancelled before any HTTP | |
692 // requests finish. | |
693 TEST(CertIssuerSourceAiaUnittest, CertSourceRequestCancelled) { | |
694 scoped_refptr<ParsedCertificate> cert; | |
695 ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert)); | |
696 | |
697 StrictMock<MockIssuerCallback> mock_callback; | |
698 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
699 CertIssuerSourceAia aia_source(&mock_fetcher); | |
700 std::unique_ptr<CertIssuerSource::Request> cert_source_request; | |
701 aia_source.AsyncGetIssuersOf(cert.get(), | |
702 base::Bind(&MockIssuerCallback::Callback, | |
703 base::Unretained(&mock_callback)), | |
704 &cert_source_request); | |
705 ASSERT_NE(nullptr, cert_source_request); | |
706 | |
707 RequestManager* req_manager = | |
708 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia/I.cer")); | |
709 ASSERT_TRUE(req_manager); | |
710 ASSERT_TRUE(req_manager->is_request_alive()); | |
711 | |
712 RequestManager* req_manager2 = | |
713 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia2/I2.foo")); | |
714 ASSERT_TRUE(req_manager2); | |
715 ASSERT_TRUE(req_manager2->is_request_alive()); | |
716 | |
717 // Delete The CertIssuerSource::Request, cancelling it. | |
718 cert_source_request.reset(); | |
719 // Both CertNetFetcher::Requests should be cancelled. | |
720 EXPECT_FALSE(req_manager->is_request_alive()); | |
721 EXPECT_FALSE(req_manager2->is_request_alive()); | |
722 } | |
723 | |
724 // AuthorityInfoAccess with two HTTP urls, each pointing to a single DER cert. | |
725 // One request completes, results are retrieved, then request is cancelled | |
726 // before the second HTTP request completes. | |
727 TEST(CertIssuerSourceAiaUnittest, TwoAiaOneCompletedThenRequestCancelled) { | |
728 scoped_refptr<ParsedCertificate> cert; | |
729 ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert)); | |
730 scoped_refptr<ParsedCertificate> intermediate_cert; | |
731 ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert)); | |
732 | |
733 StrictMock<MockIssuerCallback> mock_callback; | |
734 StrictMock<MockCertNetFetcherImpl> mock_fetcher; | |
735 CertIssuerSourceAia aia_source(&mock_fetcher); | |
736 std::unique_ptr<CertIssuerSource::Request> cert_source_request; | |
737 aia_source.AsyncGetIssuersOf(cert.get(), | |
738 base::Bind(&MockIssuerCallback::Callback, | |
739 base::Unretained(&mock_callback)), | |
740 &cert_source_request); | |
741 ASSERT_NE(nullptr, cert_source_request); | |
742 | |
743 RequestManager* req_manager = | |
744 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia/I.cer")); | |
745 ASSERT_TRUE(req_manager); | |
746 ASSERT_TRUE(req_manager->is_request_alive()); | |
747 | |
748 RequestManager* req_manager2 = | |
749 mock_fetcher.GetRequestManagerForURL(GURL("http://url-for-aia2/I2.foo")); | |
750 ASSERT_TRUE(req_manager2); | |
751 ASSERT_TRUE(req_manager2->is_request_alive()); | |
752 | |
753 // Request for I.cer completes first. | |
754 EXPECT_CALL(mock_callback, Callback(cert_source_request.get())); | |
755 req_manager->get_callback().Run(OK, CertDataVector(intermediate_cert.get())); | |
756 Mock::VerifyAndClearExpectations(&mock_callback); | |
757 | |
758 // Results are retrieved before the other request completes. | |
759 scoped_refptr<ParsedCertificate> result_cert; | |
760 CompletionStatus status = cert_source_request->GetNext(&result_cert); | |
761 EXPECT_EQ(CompletionStatus::SYNC, status); | |
762 ASSERT_TRUE(result_cert.get()); | |
763 ASSERT_EQ(result_cert->der_cert(), intermediate_cert->der_cert()); | |
764 | |
765 status = cert_source_request->GetNext(&result_cert); | |
766 // The other http request is still pending, status should be ASYNC to signify | |
767 // the need to wait for another callback. | |
768 ASSERT_EQ(CompletionStatus::ASYNC, status); | |
769 EXPECT_FALSE(result_cert.get()); | |
770 | |
771 // Delete The CertIssuerSource::Request, cancelling it. | |
772 cert_source_request.reset(); | |
773 // Both CertNetFetcher::Requests should be cancelled. | |
774 EXPECT_FALSE(req_manager->is_request_alive()); | |
775 EXPECT_FALSE(req_manager2->is_request_alive()); | |
776 } | |
777 | |
778 } // namespace | |
779 | |
780 } // namespace net | |
OLD | NEW |