| // Copyright 2024 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/certificate_manager_model.h" |
| |
| #include <string> |
| |
| #include "base/files/file_util.h" |
| #include "base/test/test_future.h" |
| #include "base/threading/thread_restrictions.h" |
| #include "chrome/browser/ash/crosapi/cert_database_ash.h" |
| #include "chrome/browser/ash/crosapi/crosapi_ash.h" |
| #include "chrome/browser/ash/crosapi/crosapi_manager.h" |
| #include "chrome/browser/ash/login/test/logged_in_user_mixin.h" |
| #include "chrome/browser/net/nss_service.h" |
| #include "chrome/browser/net/nss_service_factory.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/views/frame/browser_view.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/mixin_based_in_process_browser_test.h" |
| #include "chromeos/constants/chromeos_features.h" |
| #include "components/prefs/pref_service.h" |
| #include "content/public/test/browser_test.h" |
| #include "crypto/scoped_test_nss_db.h" |
| #include "net/test/test_data_directory.h" |
| |
| // The correct password for the client.p12 file. |
| const char16_t kPassword[] = u"12345"; |
| |
| struct FakeObserver : CertificateManagerModel::Observer { |
| void CertificatesRefreshed() override {} |
| }; |
| |
| class CertificateManagerModelBrowserTestBase |
| : public MixinBasedInProcessBrowserTest { |
| public: |
| void SetUpOnMainThread() override { |
| MixinBasedInProcessBrowserTest::SetUpOnMainThread(); |
| logged_in_user_mixin_.LogInUser(); |
| |
| base::test::TestFuture<std::unique_ptr<CertificateManagerModel>> |
| model_waiter; |
| CertificateManagerModel::Create(browser()->profile(), &fake_observer_, |
| model_waiter.GetCallback()); |
| certificate_manager_model_ = model_waiter.Take(); |
| } |
| |
| void TearDownOnMainThread() override { certificate_manager_model_.reset(); } |
| |
| std::string ReadTestFile(const std::string& file_name) { |
| base::ScopedAllowBlockingForTesting allow_blocking; |
| base::FilePath file_path = |
| net::GetTestCertsDirectory().AppendASCII(file_name); |
| std::string file_data; |
| if (!base::ReadFileToString(file_path, &file_data)) { |
| ADD_FAILURE() << "Couldn't read " << file_path; |
| return {}; |
| } |
| return file_data; |
| } |
| |
| const std::string& GetPkcs12() { |
| static const base::NoDestructor<std::string> pkcs12( |
| ReadTestFile("client.p12")); |
| return *pkcs12; |
| } |
| |
| protected: |
| ash::LoggedInUserMixin logged_in_user_mixin_{ |
| &mixin_host_, ash::LoggedInUserMixin::LogInType::kRegular, |
| embedded_test_server(), this}; |
| |
| FakeObserver fake_observer_; |
| base::test::ScopedFeatureList feature_list_; |
| std::unique_ptr<crypto::ScopedTestNSSDB> public_slot_ = |
| std::make_unique<crypto::ScopedTestNSSDB>(); |
| std::unique_ptr<CertificateManagerModel> certificate_manager_model_; |
| }; |
| |
| // Test that when OnPkcs12CertDualWritten() is called from Lacros, the |
| // kNssChapsDualWrittenCertsExist preference is stored. |
| IN_PROC_BROWSER_TEST_F(CertificateManagerModelBrowserTestBase, |
| LacrosCallStoresThePref) { |
| EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean( |
| prefs::kNssChapsDualWrittenCertsExist)); |
| |
| crosapi::CertDatabaseAsh* const cert_database_ash = |
| crosapi::CrosapiManager::Get()->crosapi_ash()->cert_database_ash(); |
| cert_database_ash->OnPkcs12CertDualWritten(); |
| |
| EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean( |
| prefs::kNssChapsDualWrittenCertsExist)); |
| } |
| |
| class CertificateManagerModelEnablePkcs12DualWrite |
| : public CertificateManagerModelBrowserTestBase { |
| public: |
| CertificateManagerModelEnablePkcs12DualWrite() { |
| feature_list_.InitAndEnableFeature( |
| chromeos::features::kEnablePkcs12ToChapsDualWrite); |
| } |
| }; |
| |
| // Test ImportFromPKCS12 with dual-write enabled. |
| IN_PROC_BROWSER_TEST_F(CertificateManagerModelEnablePkcs12DualWrite, |
| DualWriteIsEnabled) { |
| EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean( |
| prefs::kNssChapsDualWrittenCertsExist)); |
| |
| // Non-extractable certs should not be dual-written and should not set the |
| // related preference. |
| { |
| base::test::TestFuture<int> import_waiter; |
| certificate_manager_model_->ImportFromPKCS12( |
| public_slot_->slot(), GetPkcs12(), kPassword, |
| /*is_extractable=*/false, import_waiter.GetCallback()); |
| EXPECT_EQ(import_waiter.Get(), net::OK); |
| EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean( |
| prefs::kNssChapsDualWrittenCertsExist)); |
| } |
| |
| // Extractable certs should be dual-written and should set the related |
| // preference. |
| { |
| base::test::TestFuture<int> import_waiter; |
| certificate_manager_model_->ImportFromPKCS12( |
| public_slot_->slot(), GetPkcs12(), kPassword, |
| /*is_extractable=*/true, import_waiter.GetCallback()); |
| EXPECT_EQ(import_waiter.Get(), net::OK); |
| EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean( |
| prefs::kNssChapsDualWrittenCertsExist)); |
| } |
| } |
| |
| class CertificateManagerModelDisablePkcs12DualWrite |
| : public CertificateManagerModelBrowserTestBase { |
| public: |
| CertificateManagerModelDisablePkcs12DualWrite() { |
| feature_list_.InitAndDisableFeature( |
| chromeos::features::kEnablePkcs12ToChapsDualWrite); |
| } |
| }; |
| |
| // Test ImportFromPKCS12 with dual-write disabled. Everything should work as |
| // usual, kNssChapsDualWrittenCertsExist preference should not be set for all |
| // cases. |
| IN_PROC_BROWSER_TEST_F(CertificateManagerModelDisablePkcs12DualWrite, |
| DualWriteIsDisabled) { |
| EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean( |
| prefs::kNssChapsDualWrittenCertsExist)); |
| |
| { |
| base::test::TestFuture<int> import_waiter; |
| certificate_manager_model_->ImportFromPKCS12( |
| public_slot_->slot(), GetPkcs12(), kPassword, |
| /*is_extractable=*/false, import_waiter.GetCallback()); |
| EXPECT_EQ(import_waiter.Get(), net::OK); |
| EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean( |
| prefs::kNssChapsDualWrittenCertsExist)); |
| } |
| |
| { |
| base::test::TestFuture<int> import_waiter; |
| certificate_manager_model_->ImportFromPKCS12( |
| public_slot_->slot(), GetPkcs12(), kPassword, |
| /*is_extractable=*/true, import_waiter.GetCallback()); |
| EXPECT_EQ(import_waiter.Get(), net::OK); |
| EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean( |
| prefs::kNssChapsDualWrittenCertsExist)); |
| } |
| } |