blob: d8262b5054a5833371038ecc7acc6049b228c7a3 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ssl/ssl_config_service_manager.h"
#include <memory>
#include <utility>
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/values.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/test/browser_task_environment.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/cert/cert_verifier.h"
#include "net/ssl/ssl_config.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/ssl_config.mojom.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
class SSLConfigServiceManagerTest : public testing::Test,
public network::mojom::SSLConfigClient {
public:
SSLConfigServiceManagerTest() = default;
~SSLConfigServiceManagerTest() override {
EXPECT_EQ(updates_waited_for_, observed_configs_.size());
}
std::unique_ptr<SSLConfigServiceManager> SetUpConfigServiceManager(
TestingPrefServiceSimple* local_state) {
auto config_manager =
std::make_unique<SSLConfigServiceManager>(local_state);
// Create NetworkContextParams, pass it to the |config_manager|, and then
// steal the only two params that the |config_manager| populates.
network::mojom::NetworkContextParamsPtr network_context_params =
network::mojom::NetworkContextParams::New();
network_context_params->cert_verifier_params =
content::GetCertVerifierParams(
cert_verifier::mojom::CertVerifierCreationParams::New());
config_manager->AddToNetworkContextParams(network_context_params.get());
EXPECT_TRUE(network_context_params->initial_ssl_config);
initial_config_ = std::move(network_context_params->initial_ssl_config);
EXPECT_TRUE(network_context_params->ssl_config_client_receiver);
// It's safe to destroy the SSLConfigServiceManager before |receiver_|.
receiver_.Bind(
std::move(network_context_params->ssl_config_client_receiver));
return config_manager;
}
// Waits for a single SSLConfigUpdate call. Expected to be called once for
// every update, and does not support multple updates occuring between calls.
void WaitForUpdate() {
ASSERT_FALSE(run_loop_);
++updates_waited_for_;
if (observed_configs_.size() == updates_waited_for_)
return;
// Fail if there was more than one update since the last call to
// WaitForUpdate.
ASSERT_EQ(updates_waited_for_, observed_configs_.size() + 1);
// Not going to have much luck waiting for an update if this isn't bound to
// anything.
ASSERT_TRUE(receiver_.is_bound());
run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
run_loop_.reset();
// Fail if there was more than one update while spinning the message loop.
ASSERT_EQ(updates_waited_for_, observed_configs_.size());
}
// network::mojom::SSLConfigClient implementation:
void OnSSLConfigUpdated(network::mojom::SSLConfigPtr ssl_config) override {
observed_configs_.emplace_back(std::move(ssl_config));
if (run_loop_)
run_loop_->Quit();
}
protected:
content::BrowserTaskEnvironment task_environment_;
TestingPrefServiceSimple local_state_;
mojo::Receiver<network::mojom::SSLConfigClient> receiver_{this};
network::mojom::SSLConfigPtr initial_config_;
std::vector<network::mojom::SSLConfigPtr> observed_configs_;
size_t updates_waited_for_ = 0;
std::unique_ptr<base::RunLoop> run_loop_;
};
// Test that cipher suites can be disabled. "Good" refers to the fact that
// every value is expected to be successfully parsed into a cipher suite.
TEST_F(SSLConfigServiceManagerTest, GoodDisabledCipherSuites) {
TestingPrefServiceSimple local_state;
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager =
SetUpConfigServiceManager(&local_state);
EXPECT_TRUE(initial_config_->disabled_cipher_suites.empty());
base::Value::List list;
list.Append("0x0004");
list.Append("0x0005");
local_state.SetUserPref(prefs::kCipherSuiteBlacklist, std::move(list));
// Wait for the SSLConfigServiceManagerPref to be notified of the preferences
// being changed, and for it to notify the test fixture of the change.
ASSERT_NO_FATAL_FAILURE(WaitForUpdate());
EXPECT_NE(initial_config_->disabled_cipher_suites,
observed_configs_[0]->disabled_cipher_suites);
ASSERT_EQ(2u, observed_configs_[0]->disabled_cipher_suites.size());
EXPECT_EQ(0x0004, observed_configs_[0]->disabled_cipher_suites[0]);
EXPECT_EQ(0x0005, observed_configs_[0]->disabled_cipher_suites[1]);
}
// Test that cipher suites can be disabled. "Bad" refers to the fact that
// there are one or more non-cipher suite strings in the preference. They
// should be ignored.
TEST_F(SSLConfigServiceManagerTest, BadDisabledCipherSuites) {
TestingPrefServiceSimple local_state;
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager =
SetUpConfigServiceManager(&local_state);
EXPECT_TRUE(initial_config_->disabled_cipher_suites.empty());
base::Value::List list;
list.Append("0x0004");
list.Append("TLS_NOT_WITH_A_CIPHER_SUITE");
list.Append("0x0005");
list.Append("0xBEEFY");
local_state.SetUserPref(prefs::kCipherSuiteBlacklist, std::move(list));
// Wait for the SSLConfigServiceManagerPref to be notified of the preferences
// being changed, and for it to notify the test fixture of the change.
ASSERT_NO_FATAL_FAILURE(WaitForUpdate());
EXPECT_NE(initial_config_->disabled_cipher_suites,
observed_configs_[0]->disabled_cipher_suites);
ASSERT_EQ(2u, observed_configs_[0]->disabled_cipher_suites.size());
EXPECT_EQ(0x0004, observed_configs_[0]->disabled_cipher_suites[0]);
EXPECT_EQ(0x0005, observed_configs_[0]->disabled_cipher_suites[1]);
}
// Test that without command-line settings for minimum and maximum SSL versions,
// TLS versions from 1.2 are enabled.
TEST_F(SSLConfigServiceManagerTest, NoCommandLinePrefs) {
scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
TestingPrefServiceSimple local_state;
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager =
SetUpConfigServiceManager(&local_state);
// The settings should not be added to the local_state.
EXPECT_FALSE(local_state.HasPrefPath(prefs::kSSLVersionMin));
EXPECT_FALSE(local_state.HasPrefPath(prefs::kSSLVersionMax));
// Explicitly double-check the settings are not in the preference store.
std::string version_min_str;
std::string version_max_str;
EXPECT_FALSE(
local_state_store->GetString(prefs::kSSLVersionMin, &version_min_str));
EXPECT_FALSE(
local_state_store->GetString(prefs::kSSLVersionMax, &version_max_str));
}
// Tests that SSLVersionMin correctly sets the minimum version.
TEST_F(SSLConfigServiceManagerTest, SSLVersionMin) {
scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
TestingPrefServiceSimple local_state;
local_state.SetUserPref(prefs::kSSLVersionMin,
std::make_unique<base::Value>("tls1.3"));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager =
SetUpConfigServiceManager(&local_state);
EXPECT_EQ(network::mojom::SSLVersion::kTLS13, initial_config_->version_min);
}
// Tests that SSL max version correctly sets the maximum version.
TEST_F(SSLConfigServiceManagerTest, SSLVersionMax) {
scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
TestingPrefServiceSimple local_state;
local_state.SetUserPref(prefs::kSSLVersionMax,
std::make_unique<base::Value>("tls1.2"));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager =
SetUpConfigServiceManager(&local_state);
EXPECT_EQ(network::mojom::SSLVersion::kTLS12, initial_config_->version_max);
}
// Tests that SSL max version can not be set below TLS 1.2.
TEST_F(SSLConfigServiceManagerTest, NoTLS11Max) {
scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
TestingPrefServiceSimple local_state;
local_state.SetUserPref(prefs::kSSLVersionMax,
std::make_unique<base::Value>("tls1.1"));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager =
SetUpConfigServiceManager(&local_state);
// The command-line option must not have been honored.
EXPECT_LE(network::mojom::SSLVersion::kTLS12, initial_config_->version_max);
}
TEST_F(SSLConfigServiceManagerTest, H2ClientCertCoalescingPref) {
scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
TestingPrefServiceSimple local_state;
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager =
SetUpConfigServiceManager(&local_state);
base::Value::List patterns;
// Patterns expected to be canonicalized.
patterns.Append("canon.example");
patterns.Append(".NonCanon.example");
patterns.Append("Non-Canon.example");
patterns.Append("127.0.0.1");
patterns.Append("2147614986");
// Patterns expected to be skipped.
patterns.Append("???");
patterns.Append("example.com/");
patterns.Append("xn--hellö.com");
local_state.SetUserPref(prefs::kH2ClientCertCoalescingHosts,
std::move(patterns));
// Wait for the SSLConfigServiceManagerPref to be notified of the preferences
// being changed, and for it to notify the test fixture of the change.
ASSERT_NO_FATAL_FAILURE(WaitForUpdate());
auto observed_patterns = observed_configs_[0]->client_cert_pooling_policy;
ASSERT_EQ(5u, observed_patterns.size());
EXPECT_EQ("canon.example", observed_patterns[0]);
EXPECT_EQ(".noncanon.example", observed_patterns[1]);
EXPECT_EQ("non-canon.example", observed_patterns[2]);
EXPECT_EQ("127.0.0.1", observed_patterns[3]);
EXPECT_EQ("128.2.1.10", observed_patterns[4]);
}
// Tests that the cert revocation checking pref correctly sets the corresponding
// value in SSL configs.
TEST_F(SSLConfigServiceManagerTest,
RequireOnlineRevocationChecksForLocalAnchors) {
scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
TestingPrefServiceSimple local_state;
local_state.SetUserPref(prefs::kCertRevocationCheckingRequiredLocalAnchors,
std::make_unique<base::Value>(false));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager =
SetUpConfigServiceManager(&local_state);
EXPECT_FALSE(initial_config_->rev_checking_required_local_anchors);
local_state.SetUserPref(prefs::kCertRevocationCheckingRequiredLocalAnchors,
std::make_unique<base::Value>(true));
// Wait for the SSLConfigServiceManagerPref to be notified of the preferences
// being changed, and for it to notify the test fixture of the change.
ASSERT_NO_FATAL_FAILURE(WaitForUpdate());
EXPECT_TRUE(observed_configs_[0]->rev_checking_required_local_anchors);
}
// Tests that Trust Anchor IDs are populated correctly on newly created network
// context params: initially from compiled-in root store data, and then from
// dynamically-configured Trust Anchor IDs when present.
TEST_F(SSLConfigServiceManagerTest, InitialTrustAnchorIDs) {
TestingPrefServiceSimple local_state;
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager =
SetUpConfigServiceManager(&local_state);
EXPECT_THAT(
initial_config_->trust_anchor_ids,
testing::UnorderedElementsAreArray(
net::TrustStoreChrome::GetTrustAnchorIDsFromCompiledInRootStore()));
// Simulate an update that has an empty set of Trust Anchor IDs.
config_manager->UpdateTrustAnchorIDs({});
// Wait for the SSLConfigServiceManagerPref to be notified of the Trust Anchor
// IDs being changed, and for it to notify the test fixture of the change.
ASSERT_NO_FATAL_FAILURE(WaitForUpdate());
EXPECT_TRUE(observed_configs_[0]->trust_anchor_ids.empty());
// New network context params should use the latest Trust Anchor IDs (i.e.,
// empty set).
{
network::mojom::NetworkContextParamsPtr network_context_params =
network::mojom::NetworkContextParams::New();
network_context_params->cert_verifier_params =
content::GetCertVerifierParams(
cert_verifier::mojom::CertVerifierCreationParams::New());
config_manager->AddToNetworkContextParams(network_context_params.get());
ASSERT_TRUE(network_context_params->initial_ssl_config);
EXPECT_TRUE(
network_context_params->initial_ssl_config->trust_anchor_ids.empty());
}
// Simulate an update that has a non-empty set of Trust Anchor IDs.
config_manager->UpdateTrustAnchorIDs({{0x01, 0x02}, {0x03, 0x04}});
// Wait for the SSLConfigServiceManagerPref to be notified of the Trust Anchor
// IDs being changed, and for it to notify the test fixture of the change.
ASSERT_NO_FATAL_FAILURE(WaitForUpdate());
EXPECT_THAT(
observed_configs_[1]->trust_anchor_ids,
testing::UnorderedElementsAre(std::vector<uint8_t>({0x01, 0x02}),
std::vector<uint8_t>({0x03, 0x04})));
// New network context params should use the latest Trust Anchor IDs.
{
network::mojom::NetworkContextParamsPtr network_context_params =
network::mojom::NetworkContextParams::New();
network_context_params->cert_verifier_params =
content::GetCertVerifierParams(
cert_verifier::mojom::CertVerifierCreationParams::New());
config_manager->AddToNetworkContextParams(network_context_params.get());
ASSERT_TRUE(network_context_params->initial_ssl_config);
EXPECT_THAT(
network_context_params->initial_ssl_config->trust_anchor_ids,
testing::UnorderedElementsAre(std::vector<uint8_t>({0x01, 0x02}),
std::vector<uint8_t>({0x03, 0x04})));
}
}
// Tests that Trust Anchor IDs are properly set in new SSLConfigs after pref
// changes.
TEST_F(SSLConfigServiceManagerTest, TrustAnchorIDsAfterPrefChange) {
TestingPrefServiceSimple local_state;
local_state.SetUserPref(prefs::kCertRevocationCheckingRequiredLocalAnchors,
std::make_unique<base::Value>(false));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager =
SetUpConfigServiceManager(&local_state);
EXPECT_FALSE(initial_config_->rev_checking_required_local_anchors);
config_manager->UpdateTrustAnchorIDs({{0x01, 0x01}});
ASSERT_NO_FATAL_FAILURE(WaitForUpdate());
EXPECT_THAT(
observed_configs_[0]->trust_anchor_ids,
testing::UnorderedElementsAre(std::vector<uint8_t>({0x01, 0x01})));
EXPECT_FALSE(observed_configs_[0]->rev_checking_required_local_anchors);
// Change a pref and check that both the new pref and the existing Trust
// Anchor IDs are reflected in the new config.
local_state.SetUserPref(prefs::kCertRevocationCheckingRequiredLocalAnchors,
std::make_unique<base::Value>(true));
// Wait for the SSLConfigServiceManagerPref to be notified of the preferences
// being changed, and for it to notify the test fixture of the change.
ASSERT_NO_FATAL_FAILURE(WaitForUpdate());
EXPECT_TRUE(observed_configs_[1]->rev_checking_required_local_anchors);
EXPECT_THAT(
observed_configs_[1]->trust_anchor_ids,
testing::UnorderedElementsAre(std::vector<uint8_t>({0x01, 0x01})));
}
// Tests that prefs are preserved in new SSLConfigs after Trust Anchor IDs are
// set.
TEST_F(SSLConfigServiceManagerTest, PrefsPreservedAfterTrustAnchorIDsUpdated) {
TestingPrefServiceSimple local_state;
local_state.SetUserPref(prefs::kCertRevocationCheckingRequiredLocalAnchors,
std::make_unique<base::Value>(true));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager =
SetUpConfigServiceManager(&local_state);
EXPECT_TRUE(initial_config_->rev_checking_required_local_anchors);
// Update Trust Anchor IDs and check that both the existing pref and the new
// Trust Anchor IDs are reflected in the new config.
config_manager->UpdateTrustAnchorIDs({{0x01, 0x01}});
ASSERT_NO_FATAL_FAILURE(WaitForUpdate());
EXPECT_THAT(
observed_configs_[0]->trust_anchor_ids,
testing::UnorderedElementsAre(std::vector<uint8_t>({0x01, 0x01})));
EXPECT_TRUE(observed_configs_[0]->rev_checking_required_local_anchors);
}