| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <memory> |
| #include <string> |
| |
| #include "ash/constants/ash_features.h" |
| #include "ash/constants/ash_switches.h" |
| #include "base/command_line.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/functional/bind.h" |
| #include "base/json/json_writer.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/path_service.h" |
| #include "base/run_loop.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/test_future.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/ash/login/lock/screen_locker_tester.h" |
| #include "chrome/browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.h" |
| #include "chrome/browser/ash/profiles/profile_helper.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/net/nss_service.h" |
| #include "chrome/browser/net/nss_service_factory.h" |
| #include "chrome/browser/policy/networking/user_network_configuration_updater_ash.h" |
| #include "chrome/browser/policy/networking/user_network_configuration_updater_factory.h" |
| #include "chrome/browser/policy/profile_policy_connector_builder.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/profiles/profile_test_util.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_list.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chromeos/ash/components/network/network_cert_loader.h" |
| #include "chromeos/ash/components/network/onc/onc_certificate_importer.h" |
| #include "chromeos/ash/components/network/onc/onc_certificate_importer_impl.h" |
| #include "chromeos/components/onc/onc_test_utils.h" |
| #include "chromeos/test/chromeos_test_utils.h" |
| #include "components/onc/onc_constants.h" |
| #include "components/policy/core/browser/browser_policy_connector.h" |
| #include "components/policy/core/common/cloud/cloud_policy_constants.h" |
| #include "components/policy/core/common/mock_configuration_policy_provider.h" |
| #include "components/policy/core/common/policy_switches.h" |
| #include "components/policy/policy_constants.h" |
| #include "components/policy/proto/cloud_policy.pb.h" |
| #include "components/session_manager/core/session_manager.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "content/public/test/browser_test.h" |
| #include "content/public/test/test_utils.h" |
| #include "crypto/scoped_test_nss_db.h" |
| #include "net/cert/cert_database.h" |
| #include "net/cert/nss_cert_database.h" |
| #include "net/cert/test_root_certs.h" |
| #include "net/cert/x509_util_nss.h" |
| #include "net/test/cert_test_util.h" |
| #include "services/network/public/cpp/features.h" |
| #include "services/network/public/mojom/network_context.mojom.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| static_assert(BUILDFLAG(IS_CHROMEOS)); |
| |
| using ::testing::NotNull; |
| |
| namespace em = enterprise_management; |
| |
| namespace policy { |
| namespace { |
| |
| // Test data file storing an ONC blob with an Authority certificate. |
| constexpr char kRootCaCertOnc[] = "root-ca-cert.onc"; |
| constexpr char kRootAndIntermediateCaCertsOnc[] = |
| "root-and-intermediate-ca-certs.onc"; |
| // A PEM-encoded certificate which was signed by the Authority specified in |
| // |kRootCaCertOnc|. |
| constexpr char kServerCert[] = "ok_cert.pem"; |
| // A PEM-encoded certificate which was signed by the intermediate Authority |
| // specified in |kRootAndIntermediateCaCertsOnc|. |
| constexpr char kServerCertByIntermediate[] = "ok_cert_by_intermediate.pem"; |
| // The PEM-encoded Authority certificate specified by |kRootCaCertOnc|. |
| constexpr char kRootCaCert[] = "root_ca_cert.pem"; |
| |
| // Allows waiting until the list of policy-pushed web-trusted certificates |
| // changes. |
| class WebTrustedCertsChangedObserver |
| : public ash::PolicyCertificateProvider::Observer { |
| public: |
| WebTrustedCertsChangedObserver() = default; |
| |
| WebTrustedCertsChangedObserver(const WebTrustedCertsChangedObserver&) = |
| delete; |
| WebTrustedCertsChangedObserver& operator=( |
| const WebTrustedCertsChangedObserver&) = delete; |
| |
| // ash::PolicyCertificateProvider::Observer |
| void OnPolicyProvidedCertsChanged() override { run_loop_.Quit(); } |
| |
| void Wait() { run_loop_.Run(); } |
| |
| private: |
| base::RunLoop run_loop_; |
| }; |
| |
| // Allows waiting until |NetworkCertLoader| updates its list of certificates. |
| class NetworkCertLoaderTestObserver : public ash::NetworkCertLoader::Observer { |
| public: |
| explicit NetworkCertLoaderTestObserver( |
| ash::NetworkCertLoader* network_cert_loader) |
| : network_cert_loader_(network_cert_loader) { |
| network_cert_loader_->AddObserver(this); |
| } |
| |
| NetworkCertLoaderTestObserver(const NetworkCertLoaderTestObserver&) = delete; |
| NetworkCertLoaderTestObserver& operator=( |
| const NetworkCertLoaderTestObserver&) = delete; |
| |
| ~NetworkCertLoaderTestObserver() override { |
| network_cert_loader_->RemoveObserver(this); |
| } |
| |
| // ash::NetworkCertLoader::Observer |
| void OnCertificatesLoaded() override { run_loop_.Quit(); } |
| |
| void Wait() { run_loop_.Run(); } |
| |
| private: |
| raw_ptr<ash::NetworkCertLoader> network_cert_loader_; |
| base::RunLoop run_loop_; |
| }; |
| |
| // Retrieves the path to the directory containing certificates designated for |
| // testing of policy-provided certificates into *|out_test_certs_path|. |
| base::FilePath GetTestCertsPath() { |
| base::FilePath test_data_dir; |
| EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)); |
| |
| base::FilePath test_certs_path = |
| test_data_dir.AppendASCII("policy").AppendASCII("test_certs"); |
| base::ScopedAllowBlockingForTesting allow_io; |
| EXPECT_TRUE(base::DirectoryExists(test_certs_path)); |
| return test_certs_path; |
| } |
| |
| // Reads the contents of the file with name |file_name| in the directory |
| // returned by GetTestCertsPath into *|out_file_contents|. |
| std::string GetTestCertsFileContents(const std::string& file_name) { |
| base::FilePath test_certs_path = GetTestCertsPath(); |
| |
| base::ScopedAllowBlockingForTesting allow_io; |
| std::string file_contents; |
| EXPECT_TRUE(base::ReadFileToString(test_certs_path.AppendASCII(file_name), |
| &file_contents)); |
| return file_contents; |
| } |
| |
| // Allows setting user policy to assign trust to the CA certificate specified by |
| // |kRootCaCert|. |
| class UserPolicyCertsHelper { |
| public: |
| UserPolicyCertsHelper() = default; |
| ~UserPolicyCertsHelper() = default; |
| |
| UserPolicyCertsHelper(const UserPolicyCertsHelper& other) = delete; |
| UserPolicyCertsHelper& operator=(const UserPolicyCertsHelper& other) = delete; |
| |
| // Reads in testing certificates. |
| // Run in ASSERT_NO_FATAL_FAILURE. |
| void Initialize() { |
| base::ScopedAllowBlockingForTesting allow_io; |
| base::FilePath test_certs_path = GetTestCertsPath(); |
| |
| base::FilePath server_cert_path = test_certs_path.AppendASCII(kServerCert); |
| server_cert_ = net::ImportCertFromFile(server_cert_path.DirName(), |
| server_cert_path.BaseName().value()); |
| ASSERT_TRUE(server_cert_); |
| |
| base::FilePath root_cert_path = test_certs_path.AppendASCII(kRootCaCert); |
| root_cert_ = net::ImportCertFromFile(root_cert_path.DirName(), |
| root_cert_path.BaseName().value()); |
| ASSERT_TRUE(root_cert_); |
| |
| base::FilePath server_cert_by_intermediate_path = |
| test_certs_path.AppendASCII(kServerCertByIntermediate); |
| server_cert_by_intermediate_ = net::ImportCertFromFile( |
| server_cert_path.DirName(), |
| server_cert_by_intermediate_path.BaseName().value()); |
| ASSERT_TRUE(server_cert_by_intermediate_); |
| } |
| |
| // Sets the ONC-policy to the blob defined by |kRootCaCertOnc| and waits until |
| // the notification that policy-provided trust roots have changed is sent from |
| // |profile|'s UserNetworkConfigurationUpdater. |
| void SetRootCertONCUserPolicy( |
| Profile* profile, |
| MockConfigurationPolicyProvider* mock_policy_provider) { |
| std::string onc_policy_data = GetTestCertsFileContents(kRootCaCertOnc); |
| SetONCUserPolicy(profile, mock_policy_provider, onc_policy_data); |
| } |
| |
| // Sets the ONC-policy to the blob defined by |kRootCaCertOnc| and waits until |
| // the notification that policy-provided trust roots have changed is sent from |
| // |profile|'s UserNetworkConfigurationUpdater. |
| void SetRootAndIntermediateCertsONCUserPolicy( |
| Profile* profile, |
| MockConfigurationPolicyProvider* mock_policy_provider) { |
| std::string onc_policy_data = |
| GetTestCertsFileContents(kRootAndIntermediateCaCertsOnc); |
| SetONCUserPolicy(profile, mock_policy_provider, onc_policy_data); |
| } |
| |
| const scoped_refptr<net::X509Certificate>& server_cert() { |
| return server_cert_; |
| } |
| |
| const scoped_refptr<net::X509Certificate>& root_cert() { return root_cert_; } |
| |
| const scoped_refptr<net::X509Certificate>& server_cert_by_intermediate() { |
| return server_cert_by_intermediate_; |
| } |
| |
| private: |
| void SetONCUserPolicy(Profile* profile, |
| MockConfigurationPolicyProvider* mock_policy_provider, |
| const std::string& onc_policy_data) { |
| NetworkConfigurationUpdater* user_network_configuration_updater = |
| UserNetworkConfigurationUpdaterFactory::GetForBrowserContext(profile); |
| if (!user_network_configuration_updater) { |
| return; |
| } |
| |
| WebTrustedCertsChangedObserver trust_roots_changed_observer; |
| user_network_configuration_updater->AddPolicyProvidedCertsObserver( |
| &trust_roots_changed_observer); |
| |
| policy::PolicyMap policy; |
| policy.Set(key::kOpenNetworkConfiguration, policy::POLICY_LEVEL_MANDATORY, |
| policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, |
| base::Value(onc_policy_data), nullptr); |
| mock_policy_provider->UpdateChromePolicy(policy); |
| |
| // Note that this relies on the implementation detail that the notification |
| // is sent even if the trust roots effectively remain the same. |
| trust_roots_changed_observer.Wait(); |
| user_network_configuration_updater->RemovePolicyProvidedCertsObserver( |
| &trust_roots_changed_observer); |
| |
| // The above `trust_roots_changed_observer` only ensures that the |
| // UpdateAdditionalCertificates message has been sent, but not that the |
| // CertVerifierService has received it. Do a FlushForTesting on the loaded |
| // CertVerifierServiceUpdaters for `profile`, to ensure any earlier |
| // messages on the mojo pipes have been processed. |
| profile->ForEachLoadedStoragePartition( |
| &content::StoragePartition::FlushCertVerifierInterfaceForTesting); |
| } |
| |
| // Server Certificate which is signed by authority specified in |kRootCaCert|. |
| scoped_refptr<net::X509Certificate> server_cert_; |
| // Authority Certificate specified in |kRootCaCert|. |
| scoped_refptr<net::X509Certificate> root_cert_; |
| // Server Certificate which is signed by an intermediate authority, which |
| // itself is signed by the authority specified in |kRootCaCert|. |
| // |kRootCaCertOnc| does not know this intermediate authority. |
| // |kRootCaAndIntermediateCertsOnc| does know this intermediate authority, but |
| // does not request web trust for it. Instead, trust should be delegate from |
| // the root authrotiy. |
| scoped_refptr<net::X509Certificate> server_cert_by_intermediate_; |
| }; |
| |
| // A class that allows testing multiple profiles in a browsertest, each having |
| // its own MockConfigurationPolicyProvider. |
| // TODO(crbug.com/40718963): Transform this into a general-purpose mixin. |
| class MultiProfilePolicyProviderHelper { |
| public: |
| MultiProfilePolicyProviderHelper() = default; |
| ~MultiProfilePolicyProviderHelper() = default; |
| |
| MultiProfilePolicyProviderHelper( |
| const MultiProfilePolicyProviderHelper& other) = delete; |
| MultiProfilePolicyProviderHelper& operator=( |
| const MultiProfilePolicyProviderHelper& other) = delete; |
| |
| void SetUpCommandLine(base::CommandLine* command_line) { |
| command_line->AppendSwitch( |
| ash::switches::kIgnoreUserProfileMappingForTests); |
| } |
| |
| // The test should call this before the initial profile is created by chrome. |
| void BeforeInitialProfileCreated() { |
| // Set the overridden policy provider for the first Profile (|profile_1_|). |
| // Note that the first ptofile will be created automatically by the |
| // browser initialization. |
| policy_for_profile_1_.SetDefaultReturns( |
| /*is_initialization_complete_return=*/true, |
| /*is_first_policy_load_complete_return=*/true); |
| policy::PushProfilePolicyConnectorProviderForTesting( |
| &policy_for_profile_1_); |
| } |
| |
| // The test should call this after the initial profile is created by chrome. |
| void AfterInitialProfileCreated() { |
| // Mimics what InProcessBrowserTest does to get the first created Profile. |
| const BrowserList* browser_list = BrowserList::GetInstance(); |
| ASSERT_FALSE(browser_list->empty()); |
| Browser* first_browser = browser_list->get(0); |
| profile_1_ = first_browser->profile(); |
| ASSERT_TRUE(profile_1_); |
| } |
| |
| // Creates a additional profile. The Profile can then be accessed by |
| // profile_2() and its policy by policy_for_profile_2(). Should be wrapped in |
| // ASSERT_NO_FATAL_FAILURE. |
| void CreateSecondProfile() { |
| ASSERT_FALSE(profile_2_); |
| |
| // Prepare policy provider for second profile. |
| policy_for_profile_2_.SetDefaultReturns( |
| /*is_initialization_complete_return=*/true, |
| /*is_first_policy_load_complete_return=*/true); |
| policy::PushProfilePolicyConnectorProviderForTesting( |
| &policy_for_profile_2_); |
| |
| ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| base::FilePath path_profile = |
| profile_manager->GenerateNextProfileDirectoryPath(); |
| // Create an additional profile. |
| profile_2_ = |
| &profiles::testing::CreateProfileSync(profile_manager, path_profile); |
| |
| // Make sure second profile creation does what we think it does. |
| ASSERT_TRUE(profile_1() != profile_2()); |
| } |
| |
| Profile* profile_1() { return profile_1_; } |
| Profile* profile_2() { return profile_2_; } |
| |
| // Returns the MockConfigurationPolicyProvider for profile_1. |
| MockConfigurationPolicyProvider* policy_for_profile_1() { |
| return &policy_for_profile_1_; |
| } |
| |
| // Returns the MockConfigurationPolicyProvider for profile_2. |
| MockConfigurationPolicyProvider* policy_for_profile_2() { |
| return &policy_for_profile_2_; |
| } |
| |
| private: |
| raw_ptr<Profile, DanglingUntriaged> profile_1_ = nullptr; |
| raw_ptr<Profile, DanglingUntriaged> profile_2_ = nullptr; |
| |
| testing::NiceMock<MockConfigurationPolicyProvider> policy_for_profile_1_; |
| testing::NiceMock<MockConfigurationPolicyProvider> policy_for_profile_2_; |
| }; |
| |
| // Verifies |certificate| with |storage_partition|'s CertVerifier and returns |
| // the result. |
| int VerifyTestServerCertInStoragePartition( |
| content::StoragePartition* storage_partition, |
| const scoped_refptr<net::X509Certificate>& certificate) { |
| base::test::TestFuture<int> future; |
| storage_partition->GetNetworkContext()->VerifyCertificateForTesting( |
| certificate, "127.0.0.1", /*ocsp_response=*/std::string(), |
| /*sct_list=*/std::string(), future.GetCallback()); |
| return future.Get(); |
| } |
| |
| // Verifies |certificate| with the CertVerifier for |profile|'s default |
| // StoragePartition and returns the result. |
| int VerifyTestServerCert( |
| Profile* profile, |
| const scoped_refptr<net::X509Certificate>& certificate) { |
| return VerifyTestServerCertInStoragePartition( |
| profile->GetDefaultStoragePartition(), certificate); |
| } |
| |
| // Allows testing if user policy provided trust roots take effect, without |
| // having device policy. |
| // The parameter specifies whether the CertVerifierService is enabled. |
| class PolicyProvidedCertsRegularUserTest : public InProcessBrowserTest { |
| protected: |
| PolicyProvidedCertsRegularUserTest() = default; |
| ~PolicyProvidedCertsRegularUserTest() override = default; |
| |
| void SetUpCommandLine(base::CommandLine* command_line) override { |
| multi_profile_policy_helper_.SetUpCommandLine(command_line); |
| } |
| |
| void SetUpInProcessBrowserTestFixture() override { |
| InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); |
| |
| ASSERT_NO_FATAL_FAILURE( |
| multi_profile_policy_helper_.BeforeInitialProfileCreated()); |
| } |
| |
| void SetUpOnMainThread() override { |
| InProcessBrowserTest::SetUpOnMainThread(); |
| |
| ASSERT_NO_FATAL_FAILURE( |
| multi_profile_policy_helper_.AfterInitialProfileCreated()); |
| |
| ASSERT_NO_FATAL_FAILURE(user_policy_certs_helper_.Initialize()); |
| |
| // Use the same testing slot as private and public slot for testing. |
| test_nss_cert_db_ = std::make_unique<net::NSSCertDatabase>( |
| crypto::ScopedPK11Slot( |
| PK11_ReferenceSlot(test_nssdb_.slot())) /* public slot */, |
| crypto::ScopedPK11Slot( |
| PK11_ReferenceSlot(test_nssdb_.slot())) /* private slot */); |
| } |
| |
| MultiProfilePolicyProviderHelper multi_profile_policy_helper_; |
| |
| UserPolicyCertsHelper user_policy_certs_helper_; |
| |
| // A NSSCertDatabase is needed for the tests that do something with |
| // NetworkCertLoader. |
| crypto::ScopedTestNSSDB test_nssdb_; |
| std::unique_ptr<net::NSSCertDatabase> test_nss_cert_db_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(PolicyProvidedCertsRegularUserTest, NoTrustAnchor) { |
| ASSERT_NO_FATAL_FAILURE(multi_profile_policy_helper_.CreateSecondProfile()); |
| |
| EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, |
| VerifyTestServerCert(multi_profile_policy_helper_.profile_1(), |
| user_policy_certs_helper_.server_cert())); |
| EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, |
| VerifyTestServerCert(multi_profile_policy_helper_.profile_2(), |
| user_policy_certs_helper_.server_cert())); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(PolicyProvidedCertsRegularUserTest, TrustAnchorApplied) { |
| user_policy_certs_helper_.SetRootCertONCUserPolicy( |
| multi_profile_policy_helper_.profile_1(), |
| multi_profile_policy_helper_.policy_for_profile_1()); |
| EXPECT_EQ(net::OK, |
| VerifyTestServerCert(multi_profile_policy_helper_.profile_1(), |
| user_policy_certs_helper_.server_cert())); |
| } |
| |
| // Test that policy provided trust anchors are available in Incognito mode. |
| IN_PROC_BROWSER_TEST_F(PolicyProvidedCertsRegularUserTest, |
| TrustAnchorAppliedInIncognito) { |
| user_policy_certs_helper_.SetRootCertONCUserPolicy( |
| multi_profile_policy_helper_.profile_1(), |
| multi_profile_policy_helper_.policy_for_profile_1()); |
| |
| Profile* otr_profile = |
| multi_profile_policy_helper_.profile_1()->GetPrimaryOTRProfile( |
| /*create_if_needed=*/true); |
| |
| EXPECT_EQ(net::OK, VerifyTestServerCert( |
| otr_profile, user_policy_certs_helper_.server_cert())); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(PolicyProvidedCertsRegularUserTest, |
| PrimaryProfileTrustAnchorDoesNotLeak) { |
| ASSERT_NO_FATAL_FAILURE(multi_profile_policy_helper_.CreateSecondProfile()); |
| |
| user_policy_certs_helper_.SetRootCertONCUserPolicy( |
| multi_profile_policy_helper_.profile_1(), |
| multi_profile_policy_helper_.policy_for_profile_1()); |
| EXPECT_EQ(net::OK, |
| VerifyTestServerCert(multi_profile_policy_helper_.profile_1(), |
| user_policy_certs_helper_.server_cert())); |
| EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, |
| VerifyTestServerCert(multi_profile_policy_helper_.profile_2(), |
| user_policy_certs_helper_.server_cert())); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(PolicyProvidedCertsRegularUserTest, |
| SecondaryProfileTrustAnchorDoesNotLeakOrIgnored) { |
| ASSERT_NO_FATAL_FAILURE(multi_profile_policy_helper_.CreateSecondProfile()); |
| |
| user_policy_certs_helper_.SetRootCertONCUserPolicy( |
| multi_profile_policy_helper_.profile_2(), |
| multi_profile_policy_helper_.policy_for_profile_2()); |
| EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, |
| VerifyTestServerCert(multi_profile_policy_helper_.profile_1(), |
| user_policy_certs_helper_.server_cert())); |
| // TODO(crbug.com/40718963): That the cert from a secondary user's |
| // policy is used at all is currently an artifact of the test, which reuses |
| // the primary user_manager::User for the secondary Profile. |
| // Fix that and then expect ERR_CERT_AUTHORITY_INVALID here too, and rename |
| // the test to SecondaryProfileTrustAnchorIgnored. |
| // Or, allow secondary Profile ONC policy to set trust anchors for the |
| // secondary Profile. |
| EXPECT_EQ(net::OK, |
| VerifyTestServerCert(multi_profile_policy_helper_.profile_2(), |
| user_policy_certs_helper_.server_cert())); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(PolicyProvidedCertsRegularUserTest, |
| UntrustedIntermediateAuthorityApplied) { |
| // Sanity check: Apply ONC policy which does not mention the intermediate |
| // authority. |
| user_policy_certs_helper_.SetRootCertONCUserPolicy( |
| multi_profile_policy_helper_.profile_1(), |
| multi_profile_policy_helper_.policy_for_profile_1()); |
| EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, |
| VerifyTestServerCert( |
| multi_profile_policy_helper_.profile_1(), |
| user_policy_certs_helper_.server_cert_by_intermediate())); |
| |
| // Now apply ONC policy which mentions the intermediate authority (but does |
| // not assign trust to it). |
| user_policy_certs_helper_.SetRootAndIntermediateCertsONCUserPolicy( |
| multi_profile_policy_helper_.profile_1(), |
| multi_profile_policy_helper_.policy_for_profile_1()); |
| EXPECT_EQ(net::OK, |
| VerifyTestServerCert( |
| multi_profile_policy_helper_.profile_1(), |
| user_policy_certs_helper_.server_cert_by_intermediate())); |
| } |
| |
| bool IsCertInCertificateList( |
| const net::X509Certificate* cert, |
| const ash::NetworkCertLoader::NetworkCertList& network_cert_list) { |
| for (const auto& network_cert : network_cert_list) { |
| if (net::x509_util::IsSameCertificate(network_cert.cert(), cert)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(PolicyProvidedCertsRegularUserTest, |
| AuthorityAvailableThroughNetworkCertLoader) { |
| // Set |NetworkCertLoader| to use a test NSS database - otherwise, it is not |
| // properly initialized because |UserSessionManager| only sets the primary |
| // user's NSS Database in |NetworkCertLoader| if running on ChromeOS according |
| // to |base::SysInfo|. |
| ASSERT_TRUE(ash::NetworkCertLoader::IsInitialized()); |
| ash::NetworkCertLoader::Get()->SetUserNSSDB(test_nss_cert_db_.get()); |
| |
| EXPECT_FALSE(IsCertInCertificateList( |
| user_policy_certs_helper_.root_cert().get(), |
| ash::NetworkCertLoader::Get()->authority_certs())); |
| NetworkCertLoaderTestObserver network_cert_loader_observer( |
| ash::NetworkCertLoader::Get()); |
| user_policy_certs_helper_.SetRootCertONCUserPolicy( |
| multi_profile_policy_helper_.profile_1(), |
| multi_profile_policy_helper_.policy_for_profile_1()); |
| network_cert_loader_observer.Wait(); |
| |
| // Check that |NetworkCertLoader| is aware of the authority certificate. |
| // (Web Trust does not matter for the NetworkCertLoader, but we currently only |
| // set a policy with a certificate requesting Web Trust here). |
| EXPECT_TRUE(IsCertInCertificateList( |
| user_policy_certs_helper_.root_cert().get(), |
| ash::NetworkCertLoader::Get()->authority_certs())); |
| } |
| |
| // Test that the lock screen profile uses the policy provided custom trusted |
| // anchors of the primary profile . |
| IN_PROC_BROWSER_TEST_F(PolicyProvidedCertsRegularUserTest, |
| LockScreenPrimaryProfileCerts) { |
| ash::ScreenLockerTester locker; |
| locker.Lock(); |
| // Showing the reauth dialog will create the lock screen profile. |
| ash::LockScreenReauthDialogTestHelper::ShowDialogAndWait(); |
| ASSERT_THAT(ash::ProfileHelper::GetLockScreenProfile(), NotNull()); |
| |
| // Set policy provided trusted anchors on the primary profile. |
| user_policy_certs_helper_.SetRootCertONCUserPolicy( |
| browser()->profile(), |
| multi_profile_policy_helper_.policy_for_profile_1()); |
| |
| EXPECT_EQ(net::OK, |
| VerifyTestServerCert(browser()->profile(), |
| user_policy_certs_helper_.server_cert())); |
| // Verify that the lock screen can access the policy provided certs. |
| EXPECT_EQ(net::OK, |
| VerifyTestServerCert(ash::ProfileHelper::GetLockScreenProfile(), |
| user_policy_certs_helper_.server_cert())); |
| } |
| |
| // Test that the lock screen profile doesn't use the policy provided custom |
| // trusted anchors of a secondary profile. |
| IN_PROC_BROWSER_TEST_F(PolicyProvidedCertsRegularUserTest, |
| LockScreenSecondaryProfileCerts) { |
| ash::ScreenLockerTester locker; |
| locker.Lock(); |
| // Showing the reauth dialog will create the lock screen profile. |
| ash::LockScreenReauthDialogTestHelper::ShowDialogAndWait(); |
| ASSERT_THAT(ash::ProfileHelper::GetLockScreenProfile(), NotNull()); |
| |
| ASSERT_NO_FATAL_FAILURE(multi_profile_policy_helper_.CreateSecondProfile()); |
| user_policy_certs_helper_.SetRootCertONCUserPolicy( |
| multi_profile_policy_helper_.profile_2(), |
| multi_profile_policy_helper_.policy_for_profile_2()); |
| |
| EXPECT_EQ(net::OK, |
| VerifyTestServerCert(multi_profile_policy_helper_.profile_2(), |
| user_policy_certs_helper_.server_cert())); |
| EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, |
| VerifyTestServerCert(ash::ProfileHelper::GetLockScreenProfile(), |
| user_policy_certs_helper_.server_cert())); |
| } |
| |
| } // namespace |
| } // namespace policy |