Commit 2e7009c0 authored by Irem Uguz's avatar Irem Uguz Committed by Chromium LUCI CQ

Cert Provisioning: Refresh certificate manager on updates.

Add Observer to net::CertDatabase in certificate_manager_model CertsSourcePlatformNSS to observe the changes in the CertDatabase and Refresh whenever there is a change in the database to solve the bug. Update the tests accordingly.

Bug: 1146607
Change-Id: I3b9ba7f64cf47333cb79430c6a060620290e8f30
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2601748Reviewed-by: default avatarMatt Mueller <mattm@chromium.org>
Reviewed-by: default avatarPavol Marko <pmarko@chromium.org>
Commit-Queue: Irem Uğuz <iremuguz@google.com>
Cr-Commit-Position: refs/heads/master@{#843463}
parent 398eae2c
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/i18n/time_formatting.h" #include "base/i18n/time_formatting.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
...@@ -26,6 +27,7 @@ ...@@ -26,6 +27,7 @@
#include "content/public/browser/resource_context.h" #include "content/public/browser/resource_context.h"
#include "crypto/nss_util.h" #include "crypto/nss_util.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/cert/cert_database.h"
#include "net/cert/x509_certificate.h" #include "net/cert/x509_certificate.h"
#include "net/cert/x509_util_nss.h" #include "net/cert/x509_util_nss.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
...@@ -178,14 +180,24 @@ class CertificateManagerModel::CertsSource { ...@@ -178,14 +180,24 @@ class CertificateManagerModel::CertsSource {
namespace { namespace {
// Provides certificates enumerable from a NSSCertDatabase. // Provides certificates enumerable from a NSSCertDatabase.
class CertsSourcePlatformNSS : public CertificateManagerModel::CertsSource { class CertsSourcePlatformNSS : public CertificateManagerModel::CertsSource,
net::CertDatabase::Observer {
public: public:
CertsSourcePlatformNSS(base::RepeatingClosure certs_source_updated_callback, CertsSourcePlatformNSS(base::RepeatingClosure certs_source_updated_callback,
net::NSSCertDatabase* nss_cert_database) net::NSSCertDatabase* nss_cert_database)
: CertsSource(certs_source_updated_callback), : CertsSource(certs_source_updated_callback),
cert_db_(nss_cert_database) {} cert_db_(nss_cert_database) {
// Observe CertDatabase changes to refresh when it's updated.
cert_database_observation_.Observe(net::CertDatabase::GetInstance());
}
~CertsSourcePlatformNSS() override = default; ~CertsSourcePlatformNSS() override = default;
// net::CertDatabase::Observer
void OnCertDBChanged() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Refresh();
}
void Refresh() override { void Refresh() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
SetHoldBackUpdates(true); SetHoldBackUpdates(true);
...@@ -210,10 +222,7 @@ class CertsSourcePlatformNSS : public CertificateManagerModel::CertsSource { ...@@ -210,10 +222,7 @@ class CertsSourcePlatformNSS : public CertificateManagerModel::CertsSource {
bool Delete(CERTCertificate* cert) override { bool Delete(CERTCertificate* cert) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool result = cert_db_->DeleteCertAndKey(cert); return cert_db_->DeleteCertAndKey(cert);
if (result)
Refresh();
return result;
} }
private: private:
...@@ -264,6 +273,10 @@ class CertsSourcePlatformNSS : public CertificateManagerModel::CertsSource { ...@@ -264,6 +273,10 @@ class CertsSourcePlatformNSS : public CertificateManagerModel::CertsSource {
// The source NSSCertDatabase used for listing certificates. // The source NSSCertDatabase used for listing certificates.
net::NSSCertDatabase* cert_db_; net::NSSCertDatabase* cert_db_;
// ScopedObservation to keep track of the observer for net::CertDatabase.
base::ScopedObservation<net::CertDatabase, net::CertDatabase::Observer>
cert_database_observation_{this};
base::WeakPtrFactory<CertsSourcePlatformNSS> weak_ptr_factory_{this}; base::WeakPtrFactory<CertsSourcePlatformNSS> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(CertsSourcePlatformNSS); DISALLOW_COPY_AND_ASSIGN(CertsSourcePlatformNSS);
...@@ -615,29 +628,19 @@ int CertificateManagerModel::ImportFromPKCS12(PK11SlotInfo* slot_info, ...@@ -615,29 +628,19 @@ int CertificateManagerModel::ImportFromPKCS12(PK11SlotInfo* slot_info,
const std::string& data, const std::string& data,
const base::string16& password, const base::string16& password,
bool is_extractable) { bool is_extractable) {
int result = cert_db_->ImportFromPKCS12(slot_info, data, password, return cert_db_->ImportFromPKCS12(slot_info, data, password, is_extractable,
is_extractable, nullptr); nullptr);
if (result == net::OK)
Refresh();
return result;
} }
int CertificateManagerModel::ImportUserCert(const std::string& data) { int CertificateManagerModel::ImportUserCert(const std::string& data) {
int result = cert_db_->ImportUserCert(data); return cert_db_->ImportUserCert(data);
if (result == net::OK)
Refresh();
return result;
} }
bool CertificateManagerModel::ImportCACerts( bool CertificateManagerModel::ImportCACerts(
const net::ScopedCERTCertificateList& certificates, const net::ScopedCERTCertificateList& certificates,
net::NSSCertDatabase::TrustBits trust_bits, net::NSSCertDatabase::TrustBits trust_bits,
net::NSSCertDatabase::ImportCertFailureList* not_imported) { net::NSSCertDatabase::ImportCertFailureList* not_imported) {
const size_t num_certs = certificates.size(); return cert_db_->ImportCACerts(certificates, trust_bits, not_imported);
bool result = cert_db_->ImportCACerts(certificates, trust_bits, not_imported);
if (result && not_imported->size() != num_certs)
Refresh();
return result;
} }
bool CertificateManagerModel::ImportServerCert( bool CertificateManagerModel::ImportServerCert(
......
...@@ -95,11 +95,14 @@ class CertificateManagerModelTest : public testing::Test { ...@@ -95,11 +95,14 @@ class CertificateManagerModelTest : public testing::Test {
} }
protected: protected:
// Invoke an explicit Refresh and wait until the observer has been notified. // Invoke an explicit Refresh if the refresh is triggered and wait until the
void RefreshAndWait() { // observer has been notified.
void WaitForRefresh(bool trigger_refresh) {
base::RunLoop run_loop; base::RunLoop run_loop;
fake_observer_->RunOnNextRefresh(run_loop.QuitClosure()); fake_observer_->RunOnNextRefresh(run_loop.QuitClosure());
certificate_manager_model_->Refresh(); if (trigger_refresh) {
certificate_manager_model_->Refresh();
}
run_loop.Run(); run_loop.Run();
} }
...@@ -132,7 +135,7 @@ TEST_F(CertificateManagerModelTest, ListsCertsFromPlatform) { ...@@ -132,7 +135,7 @@ TEST_F(CertificateManagerModelTest, ListsCertsFromPlatform) {
ASSERT_EQ(SECSuccess, ASSERT_EQ(SECSuccess,
PK11_ImportCert(test_nssdb_.slot(), cert.get(), CK_INVALID_HANDLE, PK11_ImportCert(test_nssdb_.slot(), cert.get(), CK_INVALID_HANDLE,
"cert", PR_FALSE /* includeTrust (unused) */)); "cert", PR_FALSE /* includeTrust (unused) */));
RefreshAndWait(); WaitForRefresh(true /*tigger_for_refresh*/);
{ {
CertificateManagerModel::OrgGroupingMap org_grouping_map; CertificateManagerModel::OrgGroupingMap org_grouping_map;
...@@ -156,7 +159,9 @@ TEST_F(CertificateManagerModelTest, ListsCertsFromPlatform) { ...@@ -156,7 +159,9 @@ TEST_F(CertificateManagerModelTest, ListsCertsFromPlatform) {
certificate_manager_model_->SetCertTrust(cert.get(), net::CertType::CA_CERT, certificate_manager_model_->SetCertTrust(cert.get(), net::CertType::CA_CERT,
net::NSSCertDatabase::TRUSTED_SSL); net::NSSCertDatabase::TRUSTED_SSL);
RefreshAndWait(); // Wait for refresh without triggering because observer should be notified by
// net::CertDatabase and refresh automatically.
WaitForRefresh(false /*tigger_for_refresh*/);
{ {
CertificateManagerModel::OrgGroupingMap org_grouping_map; CertificateManagerModel::OrgGroupingMap org_grouping_map;
certificate_manager_model_->FilterAndBuildOrgGroupingMap( certificate_manager_model_->FilterAndBuildOrgGroupingMap(
...@@ -178,7 +183,7 @@ TEST_F(CertificateManagerModelTest, ListsClientCertsFromPlatform) { ...@@ -178,7 +183,7 @@ TEST_F(CertificateManagerModelTest, ListsClientCertsFromPlatform) {
net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8", net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8",
test_nssdb_.slot(), &platform_client_cert); test_nssdb_.slot(), &platform_client_cert);
RefreshAndWait(); WaitForRefresh(true /*tigger_for_refresh*/);
CertificateManagerModel::OrgGroupingMap org_grouping_map; CertificateManagerModel::OrgGroupingMap org_grouping_map;
certificate_manager_model_->FilterAndBuildOrgGroupingMap( certificate_manager_model_->FilterAndBuildOrgGroupingMap(
...@@ -418,7 +423,7 @@ TEST_F(CertificateManagerModelChromeOSTest, ...@@ -418,7 +423,7 @@ TEST_F(CertificateManagerModelChromeOSTest,
ASSERT_TRUE(policy_cert.get()); ASSERT_TRUE(policy_cert.get());
policy_certs_provider_.SetPolicyProvidedCertificates({policy_cert}, {}); policy_certs_provider_.SetPolicyProvidedCertificates({policy_cert}, {});
RefreshAndWait(); WaitForRefresh(true /*tigger_for_refresh*/);
{ {
CertificateManagerModel::OrgGroupingMap org_grouping_map; CertificateManagerModel::OrgGroupingMap org_grouping_map;
...@@ -486,7 +491,7 @@ TEST_F(CertificateManagerModelChromeOSTest, ...@@ -486,7 +491,7 @@ TEST_F(CertificateManagerModelChromeOSTest,
ASSERT_TRUE(policy_cert.get()); ASSERT_TRUE(policy_cert.get());
policy_certs_provider_.SetPolicyProvidedCertificates({}, {policy_cert}); policy_certs_provider_.SetPolicyProvidedCertificates({}, {policy_cert});
RefreshAndWait(); WaitForRefresh(true /*tigger_for_refresh*/);
{ {
CertificateManagerModel::OrgGroupingMap org_grouping_map; CertificateManagerModel::OrgGroupingMap org_grouping_map;
...@@ -557,7 +562,7 @@ TEST_F(CertificateManagerModelChromeOSTest, ...@@ -557,7 +562,7 @@ TEST_F(CertificateManagerModelChromeOSTest,
ASSERT_TRUE(policy_cert.get()); ASSERT_TRUE(policy_cert.get());
policy_certs_provider_.SetPolicyProvidedCertificates({policy_cert}, {}); policy_certs_provider_.SetPolicyProvidedCertificates({policy_cert}, {});
RefreshAndWait(); WaitForRefresh(true /*tigger_for_refresh*/);
CertificateManagerModel::OrgGroupingMap org_grouping_map; CertificateManagerModel::OrgGroupingMap org_grouping_map;
certificate_manager_model_->FilterAndBuildOrgGroupingMap( certificate_manager_model_->FilterAndBuildOrgGroupingMap(
...@@ -579,7 +584,7 @@ TEST_F(CertificateManagerModelChromeOSTest, ListsExtensionCerts) { ...@@ -579,7 +584,7 @@ TEST_F(CertificateManagerModelChromeOSTest, ListsExtensionCerts) {
ASSERT_TRUE(extension_cert.get()); ASSERT_TRUE(extension_cert.get());
extension_client_certs_.push_back(extension_cert); extension_client_certs_.push_back(extension_cert);
RefreshAndWait(); WaitForRefresh(true /*tigger_for_refresh*/);
CertificateManagerModel::OrgGroupingMap org_grouping_map; CertificateManagerModel::OrgGroupingMap org_grouping_map;
certificate_manager_model_->FilterAndBuildOrgGroupingMap( certificate_manager_model_->FilterAndBuildOrgGroupingMap(
...@@ -610,7 +615,7 @@ TEST_F(CertificateManagerModelChromeOSTest, ...@@ -610,7 +615,7 @@ TEST_F(CertificateManagerModelChromeOSTest,
ASSERT_TRUE(extension_cert.get()); ASSERT_TRUE(extension_cert.get());
extension_client_certs_.push_back(extension_cert); extension_client_certs_.push_back(extension_cert);
RefreshAndWait(); WaitForRefresh(true /*tigger_for_refresh*/);
{ {
CertificateManagerModel::OrgGroupingMap org_grouping_map; CertificateManagerModel::OrgGroupingMap org_grouping_map;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment