1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
// Copyright 2021 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/enterprise/signals/client_certificate_fetcher.h"
#include <memory>
#include <utility>
#include "chrome/browser/enterprise/util/managed_browser_utils.h"
#include "chrome/browser/net/profile_network_context_service.h"
#include "chrome/browser/net/profile_network_context_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "net/cert/cert_database.h"
#include "net/ssl/client_cert_identity.h"
#include "net/ssl/client_cert_store.h"
#include "net/ssl/ssl_cert_request_info.h"
namespace enterprise_signals {
class ProfileNetworkContextServiceWrapperImpl
: public ProfileNetworkContextServiceWrapper {
public:
explicit ProfileNetworkContextServiceWrapperImpl(
ProfileNetworkContextService* profile_network_context_service)
: profile_network_context_service_(profile_network_context_service) {
CHECK(profile_network_context_service_);
}
~ProfileNetworkContextServiceWrapperImpl() override = default;
// ProfileNetworkContextServiceWrapper:
std::unique_ptr<net::ClientCertStore> CreateClientCertStore() override {
return profile_network_context_service_->CreateClientCertStore();
}
void FlushCachedClientCertIfNeeded(
const net::HostPortPair& host,
const scoped_refptr<net::X509Certificate>& certificate) override {
profile_network_context_service_->FlushCachedClientCertIfNeeded(
host, certificate);
}
private:
raw_ptr<ProfileNetworkContextService> profile_network_context_service_;
};
ClientCertificateFetcher::ClientCertificateFetcher(
std::unique_ptr<ProfileNetworkContextServiceWrapper>
profile_network_context_service_wrapper,
Profile* profile)
: profile_network_context_service_wrapper_(
std::move(profile_network_context_service_wrapper)),
profile_(profile) {
CHECK(profile_network_context_service_wrapper_);
CHECK(profile_);
client_cert_store_ =
profile_network_context_service_wrapper_->CreateClientCertStore();
}
ClientCertificateFetcher::~ClientCertificateFetcher() = default;
// static
std::unique_ptr<ClientCertificateFetcher> ClientCertificateFetcher::Create(
content::BrowserContext* browser_context) {
auto* profile_network_context_service =
ProfileNetworkContextServiceFactory::GetForContext(browser_context);
if (!profile_network_context_service) {
return nullptr;
}
return std::make_unique<ClientCertificateFetcher>(
std::make_unique<ProfileNetworkContextServiceWrapperImpl>(
profile_network_context_service),
Profile::FromBrowserContext(browser_context));
}
void ClientCertificateFetcher::FetchAutoSelectedCertificateForUrl(
const GURL& url,
FetchAutoSelectedCertificateForUrlCallback callback) {
if (!url.is_valid() || !client_cert_store_) {
std::move(callback).Run(nullptr);
return;
}
fetch_callback_ = std::move(callback);
cert_request_info_ = base::MakeRefCounted<net::SSLCertRequestInfo>();
client_cert_store_->GetClientCerts(
cert_request_info_,
base::BindOnce(&ClientCertificateFetcher::OnGetClientCertsComplete,
weak_ptr_factory_.GetWeakPtr(), url));
}
void ClientCertificateFetcher::OnGetClientCertsComplete(
const GURL& url,
net::ClientCertIdentityList client_certs) {
net::ClientCertIdentityList matching_certificates, nonmatching_certificates;
enterprise_util::AutoSelectCertificates(
profile_, url, std::move(client_certs), &matching_certificates,
&nonmatching_certificates);
std::unique_ptr<net::ClientCertIdentity> selected_cert;
if (!matching_certificates.empty()) {
// In case of multiple matching certificates simply take the first one,
// given the lack of other criteria here.
selected_cert = std::move(matching_certificates[0]);
}
// Make sure the network stack's cached client certificate matches with the
// one that is about to be returned (or not).
profile_network_context_service_wrapper_->FlushCachedClientCertIfNeeded(
net::HostPortPair::FromURL(url),
selected_cert ? selected_cert->certificate() : nullptr);
std::move(fetch_callback_).Run(std::move(selected_cert));
}
} // namespace enterprise_signals
|