#include "chrome/browser/certificate_manager_model.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/i18n/time_formatting.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/sequence_checker.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/net/nss_service.h"
#include "chrome/browser/net/nss_service_factory.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/ui/crypto_module_password_dialog_nss.h"
#include "chrome/common/net/x509_certificate_model_nss.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "crypto/scoped_nss_types.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_database.h"
#include "net/cert/nss_cert_database.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util_nss.h"
#include "net/net_buildflags.h"
#include "ui/base/l10n/l10n_util.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/certificate_provider/certificate_provider.h"
#include "chrome/browser/certificate_provider/certificate_provider_service.h"
#include "chrome/browser/certificate_provider/certificate_provider_service_factory.h"
#include "chrome/browser/policy/networking/user_network_configuration_updater.h"
#include "chrome/browser/policy/networking/user_network_configuration_updater_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/ash/components/network/policy_certificate_provider.h"
#include "chromeos/constants/chromeos_features.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/kcer/kcer_factory_ash.h"
#include "chrome/browser/policy/networking/user_network_configuration_updater_ash.h"
#include "chromeos/components/kcer/kcer.h"
#include "chromeos/components/kcer/kcer_histograms.h"
#include "chromeos/components/onc/certificate_scope.h"
#endif
BrowserThread;
namespace {
std::string GetCertificateOrg(CERTCertificate* cert) { … }
#if BUILDFLAG(IS_CHROMEOS)
constexpr char kOperationNotPermitted[] =
"Operation not permitted on a certificate. Source: ";
#endif
}
class CertificateManagerModel::CertsSource { … };
namespace {
class CertsSourcePlatformNSS : public CertificateManagerModel::CertsSource,
net::CertDatabase::Observer { … };
#if BUILDFLAG(IS_CHROMEOS)
class CertsSourcePolicy : public CertificateManagerModel::CertsSource,
ash::PolicyCertificateProvider::Observer {
public:
enum class Mode {
kPolicyCertsWithoutWebTrust,
kPolicyCertsWithWebTrust
};
CertsSourcePolicy(base::RepeatingClosure certs_source_updated_callback,
ash::PolicyCertificateProvider* policy_certs_provider,
Mode mode)
: CertsSource(certs_source_updated_callback),
policy_certs_provider_(policy_certs_provider),
mode_(mode) {
policy_certs_provider_->AddPolicyProvidedCertsObserver(this);
}
CertsSourcePolicy(const CertsSourcePolicy&) = delete;
CertsSourcePolicy& operator=(const CertsSourcePolicy&) = delete;
~CertsSourcePolicy() override {
policy_certs_provider_->RemovePolicyProvidedCertsObserver(this);
}
void OnPolicyProvidedCertsChanged() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Refresh();
}
void Refresh() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
switch (mode_) {
case Mode::kPolicyCertsWithoutWebTrust:
RefreshImpl(policy_certs_provider_->GetCertificatesWithoutWebTrust(
chromeos::onc::CertificateScope::Default()),
false );
break;
case Mode::kPolicyCertsWithWebTrust:
RefreshImpl(policy_certs_provider_->GetWebTrustedCertificates(
chromeos::onc::CertificateScope::Default()),
true );
break;
default:
NOTREACHED_IN_MIGRATION();
}
}
bool SetCertTrust(CERTCertificate* cert,
net::CertType type,
net::NSSCertDatabase::TrustBits trust_bits) override {
LOG(WARNING) << kOperationNotPermitted << "Policy";
return false;
}
void RemoveFromDatabase(net::ScopedCERTCertificate cert,
base::OnceCallback<void(bool)> callback) override {
LOG(WARNING) << kOperationNotPermitted << "Policy";
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), false));
}
private:
void RefreshImpl(const net::CertificateList& certificates,
bool policy_web_trusted) {
std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>> cert_infos;
cert_infos.reserve(certificates.size());
for (const auto& policy_cert : certificates) {
net::ScopedCERTCertificate nss_cert(
net::x509_util::CreateCERTCertificateFromX509Certificate(
policy_cert.get()));
if (!nss_cert)
continue;
net::CertType type = x509_certificate_model::GetType(nss_cert.get());
std::u16string cert_name = base::UTF8ToUTF16(
x509_certificate_model::GetCertNameOrNickname(nss_cert.get()));
cert_infos.push_back(std::make_unique<CertificateManagerModel::CertInfo>(
std::move(nss_cert), type, std::move(cert_name),
false , false ,
CertificateManagerModel::CertInfo::Source::kPolicy,
policy_web_trusted ,
false , false ));
}
SetCertInfos(std::move(cert_infos));
}
raw_ptr<ash::PolicyCertificateProvider> policy_certs_provider_;
Mode mode_;
};
class CertsSourceExtensions : public CertificateManagerModel::CertsSource {
public:
CertsSourceExtensions(base::RepeatingClosure certs_source_updated_callback,
std::unique_ptr<chromeos::CertificateProvider>
certificate_provider_service)
: CertsSource(certs_source_updated_callback),
certificate_provider_service_(std::move(certificate_provider_service)) {
}
CertsSourceExtensions(const CertsSourceExtensions&) = delete;
CertsSourceExtensions& operator=(const CertsSourceExtensions&) = delete;
void Refresh() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
certificate_provider_service_->GetCertificates(base::BindOnce(
&CertsSourceExtensions::DidGetCerts, weak_ptr_factory_.GetWeakPtr()));
}
bool SetCertTrust(CERTCertificate* cert,
net::CertType type,
net::NSSCertDatabase::TrustBits trust_bits) override {
LOG(WARNING) << kOperationNotPermitted << "Extension";
return false;
}
void RemoveFromDatabase(net::ScopedCERTCertificate cert,
base::OnceCallback<void(bool)> callback) override {
LOG(WARNING) << kOperationNotPermitted << "Extension";
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), false));
}
private:
void DidGetCerts(net::ClientCertIdentityList cert_identities) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>> cert_infos;
cert_infos.reserve(cert_identities.size());
for (const auto& identity : cert_identities) {
net::ScopedCERTCertificate nss_cert(
net::x509_util::CreateCERTCertificateFromX509Certificate(
identity->certificate()));
if (!nss_cert)
continue;
std::u16string cert_name = base::UTF8ToUTF16(
x509_certificate_model::GetCertNameOrNickname(nss_cert.get()));
std::u16string display_name = l10n_util::GetStringFUTF16(
IDS_CERT_MANAGER_EXTENSION_PROVIDED_FORMAT, std::move(cert_name));
cert_infos.push_back(std::make_unique<CertificateManagerModel::CertInfo>(
std::move(nss_cert), net::CertType::USER_CERT ,
display_name, false , false ,
CertificateManagerModel::CertInfo::Source::kExtension,
false , false ,
false ));
}
SetCertInfos(std::move(cert_infos));
}
std::unique_ptr<chromeos::CertificateProvider> certificate_provider_service_;
base::WeakPtrFactory<CertsSourceExtensions> weak_ptr_factory_{this};
};
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
void RecordImportFromPKCS12KcerResult(
int nss_import_result,
base::OnceCallback<void(int nss_import_result)> callback,
base::expected<void, kcer::Error> kcer_import_result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (kcer_import_result.has_value()) {
kcer::RecordPkcs12MigrationUmaEvent(
kcer::Pkcs12MigrationUmaEvent::kPkcs12ImportKcerSuccess);
} else {
kcer::RecordPkcs12MigrationUmaEvent(
kcer::Pkcs12MigrationUmaEvent::kPkcs12ImportKcerFailed);
kcer::RecordKcerError(kcer_import_result.error());
}
return std::move(callback).Run(nss_import_result);
}
#endif
}
CertificateManagerModel::CertInfo::CertInfo(net::ScopedCERTCertificate cert,
net::CertType type,
std::u16string name,
bool can_be_deleted,
bool untrusted,
Source source,
bool web_trust_anchor,
bool hardware_backed,
bool device_wide)
: … { … }
CertificateManagerModel::CertInfo::~CertInfo() { … }
std::unique_ptr<CertificateManagerModel::CertInfo>
CertificateManagerModel::CertInfo::Clone(const CertInfo* cert_info) { … }
CertificateManagerModel::Params::Params() = default;
CertificateManagerModel::Params::~Params() = default;
CertificateManagerModel::Params::Params(Params&& other) = default;
void CertificateManagerModel::Create(
content::BrowserContext* browser_context,
CertificateManagerModel::Observer* observer,
CreationCallback callback) { … }
CertificateManagerModel::CertificateManagerModel(
std::unique_ptr<Params> params,
Observer* observer,
net::NSSCertDatabase* nss_cert_database)
: … { … }
CertificateManagerModel::~CertificateManagerModel() { … }
void CertificateManagerModel::OnCertsSourceUpdated() { … }
CertificateManagerModel::CertsSource*
CertificateManagerModel::FindCertsSourceForCert(CERTCertificate* cert) { … }
void CertificateManagerModel::Refresh() { … }
void CertificateManagerModel::FilterAndBuildOrgGroupingMap(
net::CertType filter_type,
CertificateManagerModel::OrgGroupingMap* out_org_grouping_map) const { … }
void CertificateManagerModel::ImportFromPKCS12(
PK11SlotInfo* slot_info,
const std::string& data,
const std::u16string& password,
bool is_extractable,
base::OnceCallback<void(int nss_import_result)> callback) { … }
int CertificateManagerModel::ImportUserCert(const std::string& data) { … }
bool CertificateManagerModel::ImportCACerts(
const net::ScopedCERTCertificateList& certificates,
net::NSSCertDatabase::TrustBits trust_bits,
net::NSSCertDatabase::ImportCertFailureList* not_imported) { … }
bool CertificateManagerModel::ImportServerCert(
const net::ScopedCERTCertificateList& certificates,
net::NSSCertDatabase::TrustBits trust_bits,
net::NSSCertDatabase::ImportCertFailureList* not_imported) { … }
bool CertificateManagerModel::SetCertTrust(
CERTCertificate* cert,
net::CertType type,
net::NSSCertDatabase::TrustBits trust_bits) { … }
void CertificateManagerModel::RemoveFromDatabase(
net::ScopedCERTCertificate cert,
base::OnceCallback<void(bool)> callback) { … }
void CertificateManagerModel::DidGetCertDBOnUIThread(
std::unique_ptr<Params> params,
CertificateManagerModel::Observer* observer,
CreationCallback callback,
net::NSSCertDatabase* cert_db) { … }
void CertificateManagerModel::DidGetCertDBOnIOThread(
std::unique_ptr<Params> params,
CertificateManagerModel::Observer* observer,
CreationCallback callback,
net::NSSCertDatabase* cert_db) { … }
void CertificateManagerModel::GetCertDBOnIOThread(
std::unique_ptr<Params> params,
NssCertDatabaseGetter database_getter,
CertificateManagerModel::Observer* observer,
CreationCallback callback) { … }