1 // Copyright 2018 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 "services/network/ssl_config_service_mojo.h"
6
7 #include "base/feature_list.h"
8 #include "base/files/file_util.h"
9 #include "base/run_loop.h"
10 #include "base/stl_util.h"
11 #include "base/test/task_environment.h"
12 #include "build/build_config.h"
13 #include "crypto/sha2.h"
14 #include "mojo/public/cpp/bindings/remote.h"
15 #include "net/base/test_completion_callback.h"
16 #include "net/cert/asn1_util.h"
17 #include "net/cert/cert_verifier.h"
18 #include "net/cert/cert_verify_result.h"
19 #include "net/cert/crl_set.h"
20 #include "net/cert/test_root_certs.h"
21 #include "net/cert/x509_certificate.h"
22 #include "net/cert/x509_util.h"
23 #include "net/log/net_log_with_source.h"
24 #include "net/ssl/ssl_config.h"
25 #include "net/ssl/ssl_config_service.h"
26 #include "net/test/cert_test_util.h"
27 #include "net/test/gtest_util.h"
28 #include "net/test/test_data_directory.h"
29 #include "net/url_request/url_request_context.h"
30 #include "services/network/network_context.h"
31 #include "services/network/network_service.h"
32 #include "services/network/public/cpp/features.h"
33 #include "services/network/public/mojom/network_service.mojom.h"
34 #include "services/network/public/mojom/ssl_config.mojom.h"
35 #include "services/network/test/fake_test_cert_verifier_params_factory.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38
39 namespace network {
40 namespace {
41
42 class TestSSLConfigServiceObserver : public net::SSLConfigService::Observer {
43 public:
TestSSLConfigServiceObserver(net::SSLConfigService * ssl_config_service)44 explicit TestSSLConfigServiceObserver(
45 net::SSLConfigService* ssl_config_service)
46 : ssl_config_service_(ssl_config_service) {
47 ssl_config_service_->AddObserver(this);
48 }
49
~TestSSLConfigServiceObserver()50 ~TestSSLConfigServiceObserver() override {
51 EXPECT_EQ(observed_changes_, changes_to_wait_for_);
52 ssl_config_service_->RemoveObserver(this);
53 }
54
55 // net::SSLConfigService::Observer implementation:
OnSSLContextConfigChanged()56 void OnSSLContextConfigChanged() override {
57 ++observed_changes_;
58 ssl_context_config_during_change_ =
59 ssl_config_service_->GetSSLContextConfig();
60 if (run_loop_)
61 run_loop_->Quit();
62 }
63
64 // Waits for a SSLContextConfig change. The first time it's called, waits for
65 // the first change, if one hasn't been observed already, the second time,
66 // waits for the second, etc. Must be called once for each change that
67 // happens, and fails if more than once change happens between calls, or
68 // during a call.
WaitForChange()69 void WaitForChange() {
70 EXPECT_FALSE(run_loop_);
71 ++changes_to_wait_for_;
72 if (changes_to_wait_for_ == observed_changes_)
73 return;
74 EXPECT_LT(observed_changes_, changes_to_wait_for_);
75
76 run_loop_ = std::make_unique<base::RunLoop>();
77 run_loop_->Run();
78 run_loop_.reset();
79 EXPECT_EQ(observed_changes_, changes_to_wait_for_);
80 }
81
ssl_context_config_during_change() const82 const net::SSLContextConfig& ssl_context_config_during_change() const {
83 return ssl_context_config_during_change_;
84 }
85
observed_changes() const86 int observed_changes() const { return observed_changes_; }
87
88 private:
89 net::SSLConfigService* const ssl_config_service_;
90 int observed_changes_ = 0;
91 int changes_to_wait_for_ = 0;
92 net::SSLContextConfig ssl_context_config_during_change_;
93 std::unique_ptr<base::RunLoop> run_loop_;
94 };
95
96 class TestCertVerifierConfigObserver : public net::CertVerifier {
97 public:
98 TestCertVerifierConfigObserver() = default;
~TestCertVerifierConfigObserver()99 ~TestCertVerifierConfigObserver() override {
100 EXPECT_EQ(observed_changes_, changes_to_wait_for_);
101 }
102
103 // CertVerifier implementation:
Verify(const net::CertVerifier::RequestParams & params,net::CertVerifyResult * verify_result,net::CompletionOnceCallback callback,std::unique_ptr<net::CertVerifier::Request> * out_req,const net::NetLogWithSource & net_log)104 int Verify(const net::CertVerifier::RequestParams& params,
105 net::CertVerifyResult* verify_result,
106 net::CompletionOnceCallback callback,
107 std::unique_ptr<net::CertVerifier::Request>* out_req,
108 const net::NetLogWithSource& net_log) override {
109 ADD_FAILURE() << "Verify should not be called by tests";
110 return net::ERR_FAILED;
111 }
SetConfig(const Config & config)112 void SetConfig(const Config& config) override {
113 ++observed_changes_;
114 verifier_config_during_change_ = config;
115 if (run_loop_)
116 run_loop_->Quit();
117 }
118
119 // Waits for a SSLConfig change. The first time it's called, waits for the
120 // first change, if one hasn't been observed already, the second time, waits
121 // for the second, etc. Must be called once for each change that happens, and
122 // fails it more than once change happens between calls, or during a call.
WaitForChange()123 void WaitForChange() {
124 EXPECT_FALSE(run_loop_);
125 ++changes_to_wait_for_;
126 if (changes_to_wait_for_ == observed_changes_)
127 return;
128 EXPECT_LT(observed_changes_, changes_to_wait_for_);
129
130 run_loop_ = std::make_unique<base::RunLoop>();
131 run_loop_->Run();
132 run_loop_.reset();
133 EXPECT_EQ(observed_changes_, changes_to_wait_for_);
134 }
135
verifier_config_during_change() const136 const net::CertVerifier::Config& verifier_config_during_change() const {
137 return verifier_config_during_change_;
138 }
139
observed_changes() const140 int observed_changes() const { return observed_changes_; }
141
142 private:
143 int observed_changes_ = 0;
144 int changes_to_wait_for_ = 0;
145 net::CertVerifier::Config verifier_config_during_change_;
146 std::unique_ptr<base::RunLoop> run_loop_;
147 };
148
149 class NetworkServiceSSLConfigServiceTest : public testing::Test {
150 public:
NetworkServiceSSLConfigServiceTest()151 NetworkServiceSSLConfigServiceTest()
152 : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
153 network_service_(NetworkService::CreateForTesting()) {}
~NetworkServiceSSLConfigServiceTest()154 ~NetworkServiceSSLConfigServiceTest() override {
155 NetworkContext::SetCertVerifierForTesting(nullptr);
156 }
157
158 // Creates a NetworkContext using the specified NetworkContextParams, and
159 // stores it in |network_context_|.
SetUpNetworkContext(mojom::NetworkContextParamsPtr network_context_params)160 void SetUpNetworkContext(
161 mojom::NetworkContextParamsPtr network_context_params) {
162 // Use a dummy CertVerifier that always passes cert verification, since
163 // these unittests don't need to test the behavior of a real CertVerifier.
164 // There are a parallel set of tests in services/cert_verifier/ that *do*
165 // test CertVerifier behavior.
166 network_context_params->cert_verifier_params =
167 FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
168 ssl_config_client_.reset();
169 network_context_params->ssl_config_client_receiver =
170 ssl_config_client_.BindNewPipeAndPassReceiver();
171 network_context_remote_.reset();
172 network_context_ = std::make_unique<NetworkContext>(
173 network_service_.get(),
174 network_context_remote_.BindNewPipeAndPassReceiver(),
175 std::move(network_context_params));
176 }
177
178 // Returns the current SSLContextConfig for |network_context_|.
GetSSLContextConfig()179 net::SSLContextConfig GetSSLContextConfig() {
180 return network_context_->url_request_context()
181 ->ssl_config_service()
182 ->GetSSLContextConfig();
183 }
184
185 // Runs two conversion tests for |mojo_config|. Uses it as a initial
186 // SSLConfig for a NetworkContext, making sure it matches
187 // |expected_net_config|. Then switches to the default configuration and then
188 // back to |mojo_config|, to make sure it works as a new configuration. The
189 // expected configuration must not be the default configuration.
RunConversionTests(const mojom::SSLConfig & mojo_config,const net::SSLContextConfig & expected_net_config)190 void RunConversionTests(const mojom::SSLConfig& mojo_config,
191 const net::SSLContextConfig& expected_net_config) {
192 // The expected configuration must not be the default configuration, or the
193 // change test won't send an event.
194 EXPECT_FALSE(net::SSLConfigService::SSLContextConfigsAreEqualForTesting(
195 net::SSLContextConfig(), expected_net_config));
196
197 // Set up |mojo_config| as the initial configuration of a NetworkContext.
198 mojom::NetworkContextParamsPtr network_context_params =
199 mojom::NetworkContextParams::New();
200 network_context_params->initial_ssl_config = mojo_config.Clone();
201 SetUpNetworkContext(std::move(network_context_params));
202 EXPECT_TRUE(net::SSLConfigService::SSLContextConfigsAreEqualForTesting(
203 GetSSLContextConfig(), expected_net_config));
204 // Sanity check.
205 EXPECT_FALSE(net::SSLConfigService::SSLContextConfigsAreEqualForTesting(
206 GetSSLContextConfig(), net::SSLContextConfig()));
207
208 // Reset the configuration to the default ones, and check the results.
209 TestSSLConfigServiceObserver observer(
210 network_context_->url_request_context()->ssl_config_service());
211 ssl_config_client_->OnSSLConfigUpdated(mojom::SSLConfig::New());
212 observer.WaitForChange();
213 EXPECT_TRUE(net::SSLConfigService::SSLContextConfigsAreEqualForTesting(
214 GetSSLContextConfig(), net::SSLContextConfig()));
215 EXPECT_TRUE(net::SSLConfigService::SSLContextConfigsAreEqualForTesting(
216 observer.ssl_context_config_during_change(), net::SSLContextConfig()));
217 // Sanity check.
218 EXPECT_FALSE(net::SSLConfigService::SSLContextConfigsAreEqualForTesting(
219 GetSSLContextConfig(), expected_net_config));
220
221 // Set the configuration to |mojo_config| again, and check the results.
222 ssl_config_client_->OnSSLConfigUpdated(mojo_config.Clone());
223 observer.WaitForChange();
224 EXPECT_TRUE(net::SSLConfigService::SSLContextConfigsAreEqualForTesting(
225 GetSSLContextConfig(), expected_net_config));
226 EXPECT_TRUE(net::SSLConfigService::SSLContextConfigsAreEqualForTesting(
227 observer.ssl_context_config_during_change(), expected_net_config));
228 }
229
230 // Runs two conversion tests for |mojo_config|. Uses it as an initial
231 // net::CertVerifier::Config for a NetworkContext, making sure it matches
232 // |expected_net_config|. Then switches to the default configuration and then
233 // back to |mojo_config|, to make sure it works as a new configuration. The
234 // expected configuration must not be the default configuration.
RunCertConversionTests(const mojom::SSLConfig & mojo_config,const net::CertVerifier::Config & expected_net_config)235 void RunCertConversionTests(
236 const mojom::SSLConfig& mojo_config,
237 const net::CertVerifier::Config& expected_net_config) {
238 TestCertVerifierConfigObserver observer;
239 NetworkContext::SetCertVerifierForTesting(&observer);
240
241 EXPECT_NE(net::CertVerifier::Config(), expected_net_config);
242
243 // Set up |mojo_config| as the initial configuration of a NetworkContext.
244 mojom::NetworkContextParamsPtr network_context_params =
245 mojom::NetworkContextParams::New();
246 network_context_params->initial_ssl_config = mojo_config.Clone();
247 SetUpNetworkContext(std::move(network_context_params));
248
249 // Make sure the initial configuration is set.
250 observer.WaitForChange();
251 EXPECT_EQ(observer.verifier_config_during_change(), expected_net_config);
252 // Sanity check.
253 EXPECT_NE(observer.verifier_config_during_change(),
254 net::CertVerifier::Config());
255
256 // Reset the configuration to the default ones, and check the results.
257 ssl_config_client_->OnSSLConfigUpdated(mojom::SSLConfig::New());
258 observer.WaitForChange();
259 EXPECT_EQ(observer.verifier_config_during_change(),
260 net::CertVerifier::Config());
261 // Sanity check.
262 EXPECT_NE(observer.verifier_config_during_change(), expected_net_config);
263
264 // Set the configuration to |mojo_config| again, and check the results.
265 ssl_config_client_->OnSSLConfigUpdated(mojo_config.Clone());
266 observer.WaitForChange();
267 EXPECT_EQ(observer.verifier_config_during_change(), expected_net_config);
268
269 // Reset the CertVerifier for subsequent invocations.
270 NetworkContext::SetCertVerifierForTesting(nullptr);
271 }
272
273 protected:
274 base::test::TaskEnvironment task_environment_;
275 std::unique_ptr<NetworkService> network_service_;
276 mojo::Remote<mojom::SSLConfigClient> ssl_config_client_;
277 mojo::Remote<mojom::NetworkContext> network_context_remote_;
278 std::unique_ptr<NetworkContext> network_context_;
279 };
280
281 // Check that passing in a no mojom::SSLConfig matches the default
282 // net::SSLConfig.
TEST_F(NetworkServiceSSLConfigServiceTest,NoSSLConfig)283 TEST_F(NetworkServiceSSLConfigServiceTest, NoSSLConfig) {
284 SetUpNetworkContext(mojom::NetworkContextParams::New());
285 EXPECT_TRUE(net::SSLConfigService::SSLContextConfigsAreEqualForTesting(
286 GetSSLContextConfig(), net::SSLContextConfig()));
287
288 // Make sure the default TLS version range is as expected.
289 EXPECT_EQ(net::kDefaultSSLVersionMin, GetSSLContextConfig().version_min);
290 EXPECT_EQ(net::kDefaultSSLVersionMax, GetSSLContextConfig().version_max);
291 }
292
293 // Check that passing in the default mojom::SSLConfig matches the default
294 // net::SSLConfig.
TEST_F(NetworkServiceSSLConfigServiceTest,Default)295 TEST_F(NetworkServiceSSLConfigServiceTest, Default) {
296 mojom::NetworkContextParamsPtr network_context_params =
297 mojom::NetworkContextParams::New();
298 network_context_params->initial_ssl_config = mojom::SSLConfig::New();
299 SetUpNetworkContext(std::move(network_context_params));
300 EXPECT_TRUE(net::SSLConfigService::SSLContextConfigsAreEqualForTesting(
301 GetSSLContextConfig(), net::SSLContextConfig()));
302
303 // Make sure the default TLS version range is as expected.
304 EXPECT_EQ(net::kDefaultSSLVersionMin, GetSSLContextConfig().version_min);
305 EXPECT_EQ(net::kDefaultSSLVersionMax, GetSSLContextConfig().version_max);
306 }
307
308 // Check that passing in the default mojom::SSLConfig matches the default
309 // net::CertVerifier::Config.
TEST_F(NetworkServiceSSLConfigServiceTest,DefaultCertConfig)310 TEST_F(NetworkServiceSSLConfigServiceTest, DefaultCertConfig) {
311 TestCertVerifierConfigObserver observer;
312 NetworkContext::SetCertVerifierForTesting(&observer);
313
314 mojom::NetworkContextParamsPtr network_context_params =
315 mojom::NetworkContextParams::New();
316 network_context_params->initial_ssl_config = mojom::SSLConfig::New();
317 SetUpNetworkContext(std::move(network_context_params));
318
319 observer.WaitForChange();
320
321 net::CertVerifier::Config default_config;
322 EXPECT_EQ(observer.verifier_config_during_change(), default_config);
323
324 NetworkContext::SetCertVerifierForTesting(nullptr);
325 }
326
TEST_F(NetworkServiceSSLConfigServiceTest,RevCheckingEnabled)327 TEST_F(NetworkServiceSSLConfigServiceTest, RevCheckingEnabled) {
328 net::CertVerifier::Config expected_net_config;
329 // Use the opposite of the default value.
330 expected_net_config.enable_rev_checking =
331 !expected_net_config.enable_rev_checking;
332
333 mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New();
334 mojo_config->rev_checking_enabled = expected_net_config.enable_rev_checking;
335
336 RunCertConversionTests(*mojo_config, expected_net_config);
337 }
338
TEST_F(NetworkServiceSSLConfigServiceTest,RevCheckingRequiredLocalTrustAnchors)339 TEST_F(NetworkServiceSSLConfigServiceTest,
340 RevCheckingRequiredLocalTrustAnchors) {
341 net::CertVerifier::Config expected_net_config;
342 // Use the opposite of the default value.
343 expected_net_config.require_rev_checking_local_anchors =
344 !expected_net_config.require_rev_checking_local_anchors;
345
346 mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New();
347 mojo_config->rev_checking_required_local_anchors =
348 expected_net_config.require_rev_checking_local_anchors;
349
350 RunCertConversionTests(*mojo_config, expected_net_config);
351 }
352
TEST_F(NetworkServiceSSLConfigServiceTest,Sha1LocalAnchorsEnabled)353 TEST_F(NetworkServiceSSLConfigServiceTest, Sha1LocalAnchorsEnabled) {
354 net::CertVerifier::Config expected_net_config;
355 // Use the opposite of the default value.
356 expected_net_config.enable_sha1_local_anchors =
357 !expected_net_config.enable_sha1_local_anchors;
358
359 mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New();
360 mojo_config->sha1_local_anchors_enabled =
361 expected_net_config.enable_sha1_local_anchors;
362
363 RunCertConversionTests(*mojo_config, expected_net_config);
364 }
365
TEST_F(NetworkServiceSSLConfigServiceTest,SymantecEnforcementDisabled)366 TEST_F(NetworkServiceSSLConfigServiceTest, SymantecEnforcementDisabled) {
367 net::CertVerifier::Config expected_net_config;
368 // Use the opposite of the default value.
369 expected_net_config.disable_symantec_enforcement =
370 !expected_net_config.disable_symantec_enforcement;
371
372 mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New();
373 mojo_config->symantec_enforcement_disabled =
374 expected_net_config.disable_symantec_enforcement;
375
376 RunCertConversionTests(*mojo_config, expected_net_config);
377 }
378
TEST_F(NetworkServiceSSLConfigServiceTest,SSLVersion)379 TEST_F(NetworkServiceSSLConfigServiceTest, SSLVersion) {
380 const struct {
381 mojom::SSLVersion mojo_ssl_version;
382 int net_ssl_version;
383 } kVersionTable[] = {
384 {mojom::SSLVersion::kTLS1, net::SSL_PROTOCOL_VERSION_TLS1},
385 {mojom::SSLVersion::kTLS11, net::SSL_PROTOCOL_VERSION_TLS1_1},
386 {mojom::SSLVersion::kTLS12, net::SSL_PROTOCOL_VERSION_TLS1_2},
387 {mojom::SSLVersion::kTLS13, net::SSL_PROTOCOL_VERSION_TLS1_3},
388 };
389
390 for (size_t min_index = 0; min_index < base::size(kVersionTable);
391 ++min_index) {
392 for (size_t max_index = min_index; max_index < base::size(kVersionTable);
393 ++max_index) {
394 // If the versions match the default values, skip this value in the table.
395 // The defaults will get plenty of testing anyways, when switching back to
396 // the default values in RunConversionTests().
397 if (kVersionTable[min_index].net_ssl_version ==
398 net::SSLContextConfig().version_min &&
399 kVersionTable[max_index].net_ssl_version ==
400 net::SSLContextConfig().version_max) {
401 continue;
402 }
403 net::SSLContextConfig expected_net_config;
404 expected_net_config.version_min =
405 kVersionTable[min_index].net_ssl_version;
406 expected_net_config.version_max =
407 kVersionTable[max_index].net_ssl_version;
408
409 mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New();
410 mojo_config->version_min = kVersionTable[min_index].mojo_ssl_version;
411 mojo_config->version_max = kVersionTable[max_index].mojo_ssl_version;
412
413 RunConversionTests(*mojo_config, expected_net_config);
414 }
415 }
416 }
417
TEST_F(NetworkServiceSSLConfigServiceTest,InitialConfigDisableCipherSuite)418 TEST_F(NetworkServiceSSLConfigServiceTest, InitialConfigDisableCipherSuite) {
419 net::SSLContextConfig expected_net_config;
420 expected_net_config.disabled_cipher_suites.push_back(0x0004);
421
422 mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New();
423 mojo_config->disabled_cipher_suites =
424 expected_net_config.disabled_cipher_suites;
425
426 RunConversionTests(*mojo_config, expected_net_config);
427 }
428
TEST_F(NetworkServiceSSLConfigServiceTest,InitialConfigDisableTwoCipherSuites)429 TEST_F(NetworkServiceSSLConfigServiceTest,
430 InitialConfigDisableTwoCipherSuites) {
431 net::SSLContextConfig expected_net_config;
432 expected_net_config.disabled_cipher_suites.push_back(0x0004);
433 expected_net_config.disabled_cipher_suites.push_back(0x0005);
434
435 mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New();
436 mojo_config->disabled_cipher_suites =
437 expected_net_config.disabled_cipher_suites;
438
439 RunConversionTests(*mojo_config, expected_net_config);
440 }
441
TEST_F(NetworkServiceSSLConfigServiceTest,CanShareConnectionWithClientCerts)442 TEST_F(NetworkServiceSSLConfigServiceTest, CanShareConnectionWithClientCerts) {
443 // Create a default NetworkContext and test that
444 // CanShareConnectionWithClientCerts returns false.
445 SetUpNetworkContext(mojom::NetworkContextParams::New());
446
447 net::SSLConfigService* config_service =
448 network_context_->url_request_context()->ssl_config_service();
449
450 EXPECT_FALSE(
451 config_service->CanShareConnectionWithClientCerts("example.com"));
452 EXPECT_FALSE(
453 config_service->CanShareConnectionWithClientCerts("example.net"));
454
455 // Configure policy to allow example.com (but no subdomains), and example.net
456 // (including subdomains), update the config, and test that pooling is allowed
457 // with this policy.
458 mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New();
459 mojo_config->client_cert_pooling_policy = {".example.com", "example.net"};
460
461 TestSSLConfigServiceObserver observer(config_service);
462 ssl_config_client_->OnSSLConfigUpdated(std::move(mojo_config));
463 observer.WaitForChange();
464
465 EXPECT_TRUE(config_service->CanShareConnectionWithClientCerts("example.com"));
466 EXPECT_FALSE(
467 config_service->CanShareConnectionWithClientCerts("sub.example.com"));
468
469 EXPECT_TRUE(config_service->CanShareConnectionWithClientCerts("example.net"));
470 EXPECT_TRUE(
471 config_service->CanShareConnectionWithClientCerts("sub.example.net"));
472 EXPECT_TRUE(
473 config_service->CanShareConnectionWithClientCerts("sub.sub.example.net"));
474 EXPECT_FALSE(
475 config_service->CanShareConnectionWithClientCerts("notexample.net"));
476
477 EXPECT_FALSE(
478 config_service->CanShareConnectionWithClientCerts("example.org"));
479
480 // Reset the configuration to the default and check that pooling is no longer
481 // allowed.
482 ssl_config_client_->OnSSLConfigUpdated(mojom::SSLConfig::New());
483 observer.WaitForChange();
484
485 EXPECT_FALSE(
486 config_service->CanShareConnectionWithClientCerts("example.com"));
487 EXPECT_FALSE(
488 config_service->CanShareConnectionWithClientCerts("example.net"));
489 }
490
491 } // namespace
492 } // namespace network
493