1 // Copyright 2019 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/cert_verify_proc_builtin.h"
6 
7 #include "base/run_loop.h"
8 #include "base/task/post_task.h"
9 #include "base/task/thread_pool.h"
10 #include "base/test/task_environment.h"
11 #include "net/base/test_completion_callback.h"
12 #include "net/cert/cert_verify_proc.h"
13 #include "net/cert/crl_set.h"
14 #include "net/cert/ev_root_ca_metadata.h"
15 #include "net/cert/internal/system_trust_store.h"
16 #include "net/cert_net/cert_net_fetcher_url_request.h"
17 #include "net/der/encode_values.h"
18 #include "net/log/net_log_with_source.h"
19 #include "net/log/test_net_log.h"
20 #include "net/test/cert_builder.h"
21 #include "net/test/cert_test_util.h"
22 #include "net/test/embedded_test_server/embedded_test_server.h"
23 #include "net/test/embedded_test_server/http_request.h"
24 #include "net/test/embedded_test_server/http_response.h"
25 #include "net/test/embedded_test_server/request_handler_util.h"
26 #include "net/test/gtest_util.h"
27 #include "net/url_request/url_request_test_util.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 
30 using net::test::IsError;
31 using net::test::IsOk;
32 
33 namespace net {
34 
35 namespace {
36 
37 class DummySystemTrustStoreProvider : public SystemTrustStoreProvider {
38  public:
CreateSystemTrustStore()39   std::unique_ptr<SystemTrustStore> CreateSystemTrustStore() override {
40     return CreateEmptySystemTrustStore();
41   }
42 };
43 
HangRequestAndCallback(base::OnceClosure callback,const test_server::HttpRequest & request)44 std::unique_ptr<test_server::HttpResponse> HangRequestAndCallback(
45     base::OnceClosure callback,
46     const test_server::HttpRequest& request) {
47   std::move(callback).Run();
48   return std::make_unique<test_server::HungResponse>();
49 }
50 
FailTest(const std::string & message)51 void FailTest(const std::string& message) {
52   ADD_FAILURE() << message;
53 }
54 
FailRequestAndFailTest(const std::string & message,scoped_refptr<base::TaskRunner> main_task_runner,const test_server::HttpRequest & request)55 std::unique_ptr<test_server::HttpResponse> FailRequestAndFailTest(
56     const std::string& message,
57     scoped_refptr<base::TaskRunner> main_task_runner,
58     const test_server::HttpRequest& request) {
59   main_task_runner->PostTask(FROM_HERE, base::BindOnce(FailTest, message));
60   auto response = std::make_unique<test_server::BasicHttpResponse>();
61   response->set_code(HTTP_NOT_ACCEPTABLE);
62   return response;
63 }
64 
VerifyOnWorkerThread(const scoped_refptr<CertVerifyProc> & verify_proc,scoped_refptr<X509Certificate> cert,const std::string & hostname,int flags,const CertificateList & additional_trust_anchors,CertVerifyResult * verify_result,NetLogSource * out_source)65 int VerifyOnWorkerThread(const scoped_refptr<CertVerifyProc>& verify_proc,
66                          scoped_refptr<X509Certificate> cert,
67                          const std::string& hostname,
68                          int flags,
69                          const CertificateList& additional_trust_anchors,
70                          CertVerifyResult* verify_result,
71                          NetLogSource* out_source) {
72   base::ScopedAllowBaseSyncPrimitivesForTesting scoped_allow_blocking;
73   scoped_refptr<CRLSet> crl_set = CRLSet::EmptyCRLSetForTesting();
74   NetLogWithSource net_log(NetLogWithSource::Make(
75       net::NetLog::Get(), net::NetLogSourceType::CERT_VERIFIER_TASK));
76   int error =
77       verify_proc->Verify(cert.get(), hostname,
78                           /*ocsp_response=*/std::string(),
79                           /*sct_list=*/std::string(), flags, crl_set.get(),
80                           additional_trust_anchors, verify_result, net_log);
81   verify_result->DetachFromSequence();
82   *out_source = net_log.source();
83   return error;
84 }
85 
86 }  // namespace
87 
88 class CertVerifyProcBuiltinTest : public ::testing::Test {
89  public:
90   // CertVerifyProcBuiltinTest() {}
91 
SetUp()92   void SetUp() override {
93     cert_net_fetcher_ = base::MakeRefCounted<CertNetFetcherURLRequest>();
94     verify_proc_ = CreateCertVerifyProcBuiltin(
95         cert_net_fetcher_, std::make_unique<DummySystemTrustStoreProvider>());
96 
97     context_ = std::make_unique<net::TestURLRequestContext>();
98 
99     cert_net_fetcher_->SetURLRequestContext(context_.get());
100   }
101 
TearDown()102   void TearDown() override { cert_net_fetcher_->Shutdown(); }
103 
Verify(scoped_refptr<X509Certificate> cert,const std::string & hostname,int flags,const CertificateList & additional_trust_anchors,CertVerifyResult * verify_result,NetLogSource * out_source,CompletionOnceCallback callback)104   void Verify(scoped_refptr<X509Certificate> cert,
105               const std::string& hostname,
106               int flags,
107               const CertificateList& additional_trust_anchors,
108               CertVerifyResult* verify_result,
109               NetLogSource* out_source,
110               CompletionOnceCallback callback) {
111     verify_result->DetachFromSequence();
112     base::ThreadPool::PostTaskAndReplyWithResult(
113         FROM_HERE,
114         {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
115         base::BindOnce(&VerifyOnWorkerThread, verify_proc_, std::move(cert),
116                        hostname, flags, additional_trust_anchors, verify_result,
117                        out_source),
118         std::move(callback));
119   }
120 
task_environment()121   base::test::TaskEnvironment& task_environment() { return task_environment_; }
122 
CreateChain(std::unique_ptr<CertBuilder> * out_leaf,std::unique_ptr<CertBuilder> * out_intermediate,std::unique_ptr<CertBuilder> * out_root)123   void CreateChain(std::unique_ptr<CertBuilder>* out_leaf,
124                    std::unique_ptr<CertBuilder>* out_intermediate,
125                    std::unique_ptr<CertBuilder>* out_root) {
126     CertBuilder::CreateSimpleChain(out_leaf, out_intermediate, out_root);
127     ASSERT_TRUE(*out_leaf && *out_intermediate && *out_root);
128     // This test uses MOCK_TIME, so need to set the cert validity dates based
129     // on whatever the mock time happens to start at.
130     base::Time not_before = base::Time::Now() - base::TimeDelta::FromDays(1);
131     base::Time not_after = base::Time::Now() + base::TimeDelta::FromDays(10);
132     (*out_leaf)->SetValidity(not_before, not_after);
133     (*out_intermediate)->SetValidity(not_before, not_after);
134     (*out_root)->SetValidity(not_before, not_after);
135   }
136 
137  private:
138   base::test::TaskEnvironment task_environment_{
139       base::test::TaskEnvironment::TimeSource::MOCK_TIME,
140       base::test::TaskEnvironment::MainThreadType::IO,
141   };
142 
143   CertVerifier::Config config_;
144   std::unique_ptr<net::TestURLRequestContext> context_;
145   scoped_refptr<CertVerifyProc> verify_proc_;
146   scoped_refptr<CertNetFetcherURLRequest> cert_net_fetcher_;
147 };
148 
TEST_F(CertVerifyProcBuiltinTest,SimpleSuccess)149 TEST_F(CertVerifyProcBuiltinTest, SimpleSuccess) {
150   std::unique_ptr<CertBuilder> leaf, intermediate, root;
151   CreateChain(&leaf, &intermediate, &root);
152   ASSERT_TRUE(leaf && intermediate && root);
153 
154   scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
155   ASSERT_TRUE(chain.get());
156 
157   CertVerifyResult verify_result;
158   NetLogSource verify_net_log_source;
159   TestCompletionCallback callback;
160   Verify(chain.get(), "www.example.com", /*flags=*/0,
161          /*additional_trust_anchors=*/{root->GetX509Certificate()},
162          &verify_result, &verify_net_log_source, callback.callback());
163 
164   int error = callback.WaitForResult();
165   EXPECT_THAT(error, IsOk());
166 }
167 
168 // Tests that if the verification deadline is exceeded during revocation
169 // checking, additional CRL fetches will not be attempted.
TEST_F(CertVerifyProcBuiltinTest,RevocationCheckDeadlineCRL)170 TEST_F(CertVerifyProcBuiltinTest, RevocationCheckDeadlineCRL) {
171   std::unique_ptr<CertBuilder> leaf, intermediate, root;
172   CreateChain(&leaf, &intermediate, &root);
173   ASSERT_TRUE(leaf && intermediate && root);
174 
175   const base::TimeDelta timeout_increment =
176       CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
177       base::TimeDelta::FromMilliseconds(1);
178   const int expected_request_count =
179       GetCertVerifyProcBuiltinTimeLimitForTesting() / timeout_increment + 1;
180 
181   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
182   ASSERT_TRUE(test_server.InitializeAndListen());
183 
184   // Set up the test cert to have enough crlDistributionPoint urls that if the
185   // first N-1 requests hang the deadline will be exceeded before the Nth
186   // request is made.
187   std::vector<GURL> crl_urls;
188   std::vector<base::RunLoop> runloops(expected_request_count);
189   for (int i = 0; i < expected_request_count; ++i) {
190     std::string path = base::StringPrintf("/hung/%i", i);
191     crl_urls.emplace_back(test_server.GetURL(path));
192     test_server.RegisterRequestHandler(
193         base::BindRepeating(&test_server::HandlePrefixedRequest, path,
194                             base::BindRepeating(&HangRequestAndCallback,
195                                                 runloops[i].QuitClosure())));
196   }
197   // Add CRL URLs and handlers that will add test failures if requested.
198   for (int i = expected_request_count; i < expected_request_count + 1; ++i) {
199     std::string path = base::StringPrintf("/failtest/%i", i);
200     crl_urls.emplace_back(test_server.GetURL(path));
201     test_server.RegisterRequestHandler(base::BindRepeating(
202         &test_server::HandlePrefixedRequest, path,
203         base::BindRepeating(FailRequestAndFailTest,
204                             "additional request made after deadline exceeded",
205                             base::SequencedTaskRunnerHandle::Get())));
206   }
207   leaf->SetCrlDistributionPointUrls(crl_urls);
208 
209   test_server.StartAcceptingConnections();
210 
211   scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
212   ASSERT_TRUE(chain.get());
213 
214   CertVerifyResult verify_result;
215   NetLogSource verify_net_log_source;
216   TestCompletionCallback verify_callback;
217   Verify(chain.get(), "www.example.com",
218          CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
219          /*additional_trust_anchors=*/{root->GetX509Certificate()},
220          &verify_result, &verify_net_log_source, verify_callback.callback());
221 
222   for (int i = 0; i < expected_request_count; i++) {
223     // Wait for request #|i| to be made.
224     runloops[i].Run();
225     // Advance virtual time to cause the timeout task to become runnable.
226     task_environment().AdvanceClock(timeout_increment);
227   }
228 
229   // Once |expected_request_count| requests have been made and timed out, the
230   // overall deadline should be reached, and no more requests should have been
231   // made. (If they were, the test will fail due to the ADD_FAILURE callback in
232   // the request handlers.)
233   int error = verify_callback.WaitForResult();
234   // Soft-fail revocation checking was used, therefore verification result
235   // should be OK even though none of the CRLs could be retrieved.
236   EXPECT_THAT(error, IsOk());
237 }
238 
239 // Tests that if the verification deadline is exceeded during revocation
240 // checking, additional OCSP fetches will not be attempted.
TEST_F(CertVerifyProcBuiltinTest,RevocationCheckDeadlineOCSP)241 TEST_F(CertVerifyProcBuiltinTest, RevocationCheckDeadlineOCSP) {
242   std::unique_ptr<CertBuilder> leaf, intermediate, root;
243   CreateChain(&leaf, &intermediate, &root);
244   ASSERT_TRUE(leaf && intermediate && root);
245 
246   const base::TimeDelta timeout_increment =
247       CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
248       base::TimeDelta::FromMilliseconds(1);
249   const int expected_request_count =
250       GetCertVerifyProcBuiltinTimeLimitForTesting() / timeout_increment + 1;
251 
252   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
253   ASSERT_TRUE(test_server.InitializeAndListen());
254 
255   // Set up the test cert to have enough OCSP urls that if the
256   // first N-1 requests hang the deadline will be exceeded before the Nth
257   // request is made.
258   std::vector<GURL> ocsp_urls;
259   std::vector<base::RunLoop> runloops(expected_request_count);
260   for (int i = 0; i < expected_request_count; ++i) {
261     std::string path = base::StringPrintf("/hung/%i", i);
262     ocsp_urls.emplace_back(test_server.GetURL(path));
263     test_server.RegisterRequestHandler(
264         base::BindRepeating(&test_server::HandlePrefixedRequest, path,
265                             base::BindRepeating(&HangRequestAndCallback,
266                                                 runloops[i].QuitClosure())));
267   }
268   // Add OCSP URLs and handlers that will add test failures if requested.
269   for (int i = expected_request_count; i < expected_request_count + 1; ++i) {
270     std::string path = base::StringPrintf("/failtest/%i", i);
271     ocsp_urls.emplace_back(test_server.GetURL(path));
272     test_server.RegisterRequestHandler(base::BindRepeating(
273         &test_server::HandlePrefixedRequest, path,
274         base::BindRepeating(FailRequestAndFailTest,
275                             "additional request made after deadline exceeded",
276                             base::SequencedTaskRunnerHandle::Get())));
277   }
278   leaf->SetCaIssuersAndOCSPUrls({}, ocsp_urls);
279 
280   test_server.StartAcceptingConnections();
281 
282   scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
283   ASSERT_TRUE(chain.get());
284 
285   CertVerifyResult verify_result;
286   NetLogSource verify_net_log_source;
287   TestCompletionCallback verify_callback;
288   Verify(chain.get(), "www.example.com",
289          CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
290          /*additional_trust_anchors=*/{root->GetX509Certificate()},
291          &verify_result, &verify_net_log_source, verify_callback.callback());
292 
293   for (int i = 0; i < expected_request_count; i++) {
294     // Wait for request #|i| to be made.
295     runloops[i].Run();
296     // Advance virtual time to cause the timeout task to become runnable.
297     task_environment().AdvanceClock(timeout_increment);
298   }
299 
300   // Once |expected_request_count| requests have been made and timed out, the
301   // overall deadline should be reached, and no more requests should have been
302   // made. (If they were, the test will fail due to the ADD_FAILURE callback in
303   // the request handlers.)
304   int error = verify_callback.WaitForResult();
305   // Soft-fail revocation checking was used, therefore verification result
306   // should be OK even though none of the OCSP responses could be retrieved.
307   EXPECT_THAT(error, IsOk());
308 }
309 
310 #if defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
311 // Tests that if the verification deadline is exceeded during EV revocation
312 // checking, the certificate is verified as non-EV.
TEST_F(CertVerifyProcBuiltinTest,EVRevocationCheckDeadline)313 TEST_F(CertVerifyProcBuiltinTest, EVRevocationCheckDeadline) {
314   std::unique_ptr<CertBuilder> leaf, intermediate, root;
315   CreateChain(&leaf, &intermediate, &root);
316   ASSERT_TRUE(leaf && intermediate && root);
317 
318   // Add test EV policy to leaf and intermediate.
319   static const char kEVTestCertPolicy[] = "1.2.3.4";
320   leaf->SetCertificatePolicies({kEVTestCertPolicy});
321   intermediate->SetCertificatePolicies({kEVTestCertPolicy});
322 
323   const base::TimeDelta timeout_increment =
324       CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
325       base::TimeDelta::FromMilliseconds(1);
326   const int expected_request_count =
327       GetCertVerifyProcBuiltinTimeLimitForTesting() / timeout_increment + 1;
328 
329   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
330   ASSERT_TRUE(test_server.InitializeAndListen());
331 
332   // Set up the test intermediate to have enough OCSP urls that if all the
333   // requests hang the deadline will be exceeded.
334   std::vector<GURL> ocsp_urls;
335   std::vector<base::RunLoop> runloops(expected_request_count);
336   for (int i = 0; i < expected_request_count; ++i) {
337     std::string path = base::StringPrintf("/hung/%i", i);
338     ocsp_urls.emplace_back(test_server.GetURL(path));
339     test_server.RegisterRequestHandler(
340         base::BindRepeating(&test_server::HandlePrefixedRequest, path,
341                             base::BindRepeating(&HangRequestAndCallback,
342                                                 runloops[i].QuitClosure())));
343   }
344   intermediate->SetCaIssuersAndOCSPUrls({}, ocsp_urls);
345 
346   test_server.StartAcceptingConnections();
347 
348   // Consider the root of the test chain a valid EV root for the test policy.
349   ScopedTestEVPolicy scoped_test_ev_policy(
350       EVRootCAMetadata::GetInstance(),
351       X509Certificate::CalculateFingerprint256(root->GetCertBuffer()),
352       kEVTestCertPolicy);
353 
354   scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
355   ASSERT_TRUE(chain.get());
356 
357   RecordingNetLogObserver net_log_observer(NetLogCaptureMode::kDefault);
358   CertVerifyResult verify_result;
359   NetLogSource verify_net_log_source;
360   TestCompletionCallback verify_callback;
361   Verify(chain.get(), "www.example.com",
362          /*flags=*/0,
363          /*additional_trust_anchors=*/{root->GetX509Certificate()},
364          &verify_result, &verify_net_log_source, verify_callback.callback());
365 
366   for (int i = 0; i < expected_request_count; i++) {
367     // Wait for request #|i| to be made.
368     runloops[i].Run();
369     // Advance virtual time to cause the timeout task to become runnable.
370     task_environment().AdvanceClock(timeout_increment);
371   }
372 
373   // Once |expected_request_count| requests have been made and timed out, the
374   // overall deadline should be reached, causing the EV verification attempt to
375   // fail.
376   int error = verify_callback.WaitForResult();
377   // EV uses soft-fail revocation checking, therefore verification result
378   // should be OK but not EV.
379   EXPECT_THAT(error, IsOk());
380   EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_IS_EV);
381   EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
382 
383   auto events = net_log_observer.GetEntriesForSource(verify_net_log_source);
384 
385   auto event = std::find_if(events.begin(), events.end(), [](const auto& e) {
386     return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT;
387   });
388   ASSERT_NE(event, events.end());
389   EXPECT_EQ(net::NetLogEventPhase::BEGIN, event->phase);
390   ASSERT_TRUE(event->params.is_dict());
391   EXPECT_EQ(true, event->params.FindBoolKey("is_ev_attempt"));
392 
393   event = std::find_if(++event, events.end(), [](const auto& e) {
394     return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILT;
395   });
396   ASSERT_NE(event, events.end());
397   EXPECT_EQ(net::NetLogEventPhase::NONE, event->phase);
398   ASSERT_TRUE(event->params.is_dict());
399   const std::string* errors = event->params.FindStringKey("errors");
400   ASSERT_TRUE(errors);
401   EXPECT_EQ("----- Certificate i=1 (CN=" +
402                 intermediate->GetX509Certificate()->subject().common_name +
403                 ") -----\nERROR: Unable to check revocation\n\n",
404             *errors);
405 
406   event = std::find_if(++event, events.end(), [](const auto& e) {
407     return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT;
408   });
409   ASSERT_NE(event, events.end());
410   EXPECT_EQ(net::NetLogEventPhase::END, event->phase);
411   ASSERT_TRUE(event->params.is_dict());
412   EXPECT_EQ(false, event->params.FindBoolKey("has_valid_path"));
413 
414   event = std::find_if(++event, events.end(), [](const auto& e) {
415     return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT;
416   });
417   ASSERT_NE(event, events.end());
418   EXPECT_EQ(net::NetLogEventPhase::BEGIN, event->phase);
419   ASSERT_TRUE(event->params.is_dict());
420   EXPECT_EQ(base::nullopt, event->params.FindBoolKey("is_ev_attempt"));
421 
422   event = std::find_if(++event, events.end(), [](const auto& e) {
423     return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILT;
424   });
425   ASSERT_NE(event, events.end());
426   EXPECT_EQ(net::NetLogEventPhase::NONE, event->phase);
427   ASSERT_TRUE(event->params.is_dict());
428   EXPECT_FALSE(event->params.FindStringKey("errors"));
429 
430   event = std::find_if(++event, events.end(), [](const auto& e) {
431     return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT;
432   });
433   ASSERT_NE(event, events.end());
434   EXPECT_EQ(net::NetLogEventPhase::END, event->phase);
435   ASSERT_TRUE(event->params.is_dict());
436   EXPECT_EQ(true, event->params.FindBoolKey("has_valid_path"));
437 }
438 #endif  // defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
439 
TEST_F(CertVerifyProcBuiltinTest,DebugData)440 TEST_F(CertVerifyProcBuiltinTest, DebugData) {
441   std::unique_ptr<CertBuilder> leaf, intermediate, root;
442   CreateChain(&leaf, &intermediate, &root);
443   ASSERT_TRUE(leaf && intermediate && root);
444 
445   scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
446   ASSERT_TRUE(chain.get());
447 
448   base::Time time = base::Time::Now();
449 
450   CertVerifyResult verify_result;
451   NetLogSource verify_net_log_source;
452   TestCompletionCallback callback;
453   Verify(chain.get(), "www.example.com", /*flags=*/0,
454          /*additional_trust_anchors=*/{root->GetX509Certificate()},
455          &verify_result, &verify_net_log_source, callback.callback());
456 
457   int error = callback.WaitForResult();
458   EXPECT_THAT(error, IsOk());
459 
460   auto* debug_data = CertVerifyProcBuiltinResultDebugData::Get(&verify_result);
461   ASSERT_TRUE(debug_data);
462   // No delayed tasks involved, so the mock time should not have advanced.
463   EXPECT_EQ(time, debug_data->verification_time());
464 
465   base::Time der_verification_time_converted_back_to_base_time;
466   EXPECT_TRUE(net::der::GeneralizedTimeToTime(
467       debug_data->der_verification_time(),
468       &der_verification_time_converted_back_to_base_time));
469   // GeneralizedTime only has seconds precision.
470   EXPECT_EQ(
471       0,
472       (time - der_verification_time_converted_back_to_base_time).InSeconds());
473 }
474 
475 }  // namespace net
476