0

Integrate Cert Verifier Service into Network Service and Chrome

Bug: 1015134
Change-Id: I7cf982dae2f62be1987c24f0a8c822a4733cb7bd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2155824
Commit-Queue: Matthew Denton <mpdenton@chromium.org>
Reviewed-by: Matt Falkenhagen <falken@chromium.org>
Reviewed-by: John Abd-El-Malek <jam@chromium.org>
Reviewed-by: Ryan Sleevi <rsleevi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#773901}
This commit is contained in:
Matthew Denton
2020-06-01 23:40:48 +00:00
committed by Commit Bot
parent 8621cf2a3a
commit 03c45a2667
73 changed files with 2130 additions and 767 deletions
android_webview/browser/safe_browsing
chrome
components/net_log
content
headless/lib/browser
services
weblayer/browser

@ -26,6 +26,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/network_service_instance.h"
#include "services/network/public/mojom/network_service.mojom.h"
using content::BrowserThread;
@ -48,6 +49,8 @@ void RecordIsWebViewViewable(bool isViewable) {
network::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams() {
network::mojom::NetworkContextParamsPtr network_context_params =
network::mojom::NetworkContextParams::New();
network_context_params->cert_verifier_params = content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
network_context_params->user_agent = GetUserAgent();
return network_context_params;
}

@ -2241,6 +2241,7 @@ static_library("browser") {
"//printing/buildflags",
"//rlz/buildflags",
"//services/audio/public/cpp",
"//services/cert_verifier:lib",
"//services/data_decoder/public/cpp",
"//services/device/public/cpp:device_features",
"//services/device/public/cpp/usb",

@ -335,6 +335,7 @@ include_rules = [
"+rlz",
"+sandbox/win/src", # The path doesn't say it, but this is the Windows sandbox.
"+services/audio/public",
"+services/cert_verifier",
"+services/data_decoder/public",
"+services/device/public",
"+services/image_annotation/public",

@ -117,6 +117,7 @@
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/favicon_size.h"
@ -1124,11 +1125,15 @@ class ChromeBrowsingDataRemoverDelegateTest : public testing::Test {
content::GetNetworkService();
task_environment_.RunUntilIdle();
auto network_context_params = network::mojom::NetworkContextParams::New();
network_context_params->cert_verifier_params =
content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
mojo::PendingRemote<network::mojom::NetworkContext> network_context_remote;
network_context_ = std::make_unique<network::NetworkContext>(
network::NetworkService::GetNetworkServiceForTesting(),
network_context_remote.InitWithNewPipeAndPassReceiver(),
network::mojom::NetworkContextParams::New());
std::move(network_context_params));
content::BrowserContext::GetDefaultStoragePartition(profile_.get())
->SetNetworkContextForTesting(std::move(network_context_remote));

@ -17,6 +17,7 @@
#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/network_service_instance.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
@ -89,10 +90,16 @@ class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness {
signin_ui_web_contents_ = content::WebContentsTester::CreateTestWebContents(
GetSigninProfile(), content::SiteInstance::Create(GetSigninProfile()));
auto system_network_context_params =
network::mojom::NetworkContextParams::New();
system_network_context_params->cert_verifier_params =
content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
system_network_context_ = std::make_unique<network::NetworkContext>(
network::NetworkService::GetNetworkServiceForTesting(),
system_network_context_remote_.BindNewPipeAndPassReceiver(),
network::mojom::NetworkContextParams::New());
std::move(system_network_context_params));
GURL url(kEmbedderUrl);
content::WebContentsTester::For(signin_ui_web_contents())
@ -186,10 +193,17 @@ class SigninPartitionManagerTest : public ChromeRenderViewHostTestHarness {
// Bind the NetworkContext for the new StoragePartition.
mojo::PendingRemote<network::mojom::NetworkContext>
signin_network_context_remote;
auto signin_network_context_params =
network::mojom::NetworkContextParams::New();
signin_network_context_params->cert_verifier_params =
content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
signin_network_context_ = std::make_unique<network::NetworkContext>(
network::NetworkService::GetNetworkServiceForTesting(),
signin_network_context_remote.InitWithNewPipeAndPassReceiver(),
network::mojom::NetworkContextParams::New());
std::move(signin_network_context_params));
storage_partition->SetNetworkContextForTesting(
std::move(signin_network_context_remote));
}

@ -9,6 +9,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/test/browser_task_environment.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@ -82,6 +83,13 @@ class CRLSetComponentInstallerTest : public PlatformTest {
task_environment_.RunUntilIdle();
}
network::mojom::NetworkContextParamsPtr CreateNetworkContextParams() {
auto params = network::mojom::NetworkContextParams::New();
params->cert_verifier_params = content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
return params;
}
protected:
content::BrowserTaskEnvironment task_environment_;
net::EmbeddedTestServer test_server_;
@ -100,7 +108,7 @@ class CRLSetComponentInstallerTest : public PlatformTest {
TEST_F(CRLSetComponentInstallerTest, ConfiguresOnInstall) {
network_service_->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(),
network::mojom::NetworkContextParams::New());
CreateNetworkContextParams());
// Ensure the test server can load by default.
LoadURL(test_server_.GetURL("/empty.html"));
@ -122,7 +130,7 @@ TEST_F(CRLSetComponentInstallerTest, ConfiguresOnInstall) {
TEST_F(CRLSetComponentInstallerTest, ReconfiguresAfterRestartWithCRLSet) {
network_service_->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(),
network::mojom::NetworkContextParams::New());
CreateNetworkContextParams());
// Ensure the test server can load by default.
LoadURL(test_server_.GetURL("/empty.html"));
@ -148,7 +156,7 @@ TEST_F(CRLSetComponentInstallerTest, ReconfiguresAfterRestartWithCRLSet) {
network_context_.reset();
network_service_->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(),
network::mojom::NetworkContextParams::New());
CreateNetworkContextParams());
// Ensure the test server is still flagged even with a new context and
// service.
@ -162,7 +170,7 @@ TEST_F(CRLSetComponentInstallerTest, ReconfiguresAfterRestartWithCRLSet) {
TEST_F(CRLSetComponentInstallerTest, ReconfiguresAfterRestartWithNoCRLSet) {
network_service_->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(),
network::mojom::NetworkContextParams::New());
CreateNetworkContextParams());
// Ensure the test server can load by default.
LoadURL(test_server_.GetURL("/empty.html"));
@ -176,7 +184,7 @@ TEST_F(CRLSetComponentInstallerTest, ReconfiguresAfterRestartWithNoCRLSet) {
network_context_.reset();
network_service_->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(),
network::mojom::NetworkContextParams::New());
CreateNetworkContextParams());
// Ensure the test server can still load.
LoadURL(test_server_.GetURL("/empty.html"));

@ -7,12 +7,14 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/json/json_reader.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/test/base/chrome_test_utils.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/test/browser_test.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#if defined(OS_ANDROID)
@ -83,8 +85,26 @@ class NetLogPlatformBrowserTestBase : public PlatformBrowserTest {
// This is an integration test to ensure that CertVerifyProc netlog events
// continue to be logged once cert verification is moved out of the network
// service process. (See crbug.com/1015134 and crbug.com/1040681.)
class CertVerifyProcNetLogBrowserTest : public NetLogPlatformBrowserTestBase {
class CertVerifyProcNetLogBrowserTest
: public NetLogPlatformBrowserTestBase,
public testing::WithParamInterface<bool> {
public:
void SetUpInProcessBrowserTestFixture() override {
if (GetParam()) {
#if defined(OS_CHROMEOS)
// TODO(crbug.com/1085379): remove this GTEST_SKIP().
GTEST_SKIP() << "Skipping test, CertVerifierService feature not yet "
"available on ChromeOS.";
#else
scoped_feature_list_.InitAndEnableFeature(
network::features::kCertVerifierService);
#endif
} else {
scoped_feature_list_.InitAndDisableFeature(
network::features::kCertVerifierService);
}
}
void SetUpOnMainThread() override {
PlatformBrowserTest::SetUpOnMainThread();
@ -129,10 +149,11 @@ class CertVerifyProcNetLogBrowserTest : public NetLogPlatformBrowserTestBase {
const std::string kTestHost = "netlog-example.a.test";
protected:
base::test::ScopedFeatureList scoped_feature_list_;
net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
};
IN_PROC_BROWSER_TEST_F(CertVerifyProcNetLogBrowserTest, Test) {
IN_PROC_BROWSER_TEST_P(CertVerifyProcNetLogBrowserTest, Test) {
ASSERT_TRUE(https_server_.Start());
// Request using a unique host name to ensure that the cert verification wont
@ -150,3 +171,7 @@ IN_PROC_BROWSER_TEST_F(CertVerifyProcNetLogBrowserTest, Test) {
base::RunLoop().RunUntilIdle();
content::FlushNetworkServiceInstanceForTesting();
}
INSTANTIATE_TEST_SUITE_P(CertVerifierService,
CertVerifyProcNetLogBrowserTest,
::testing::Bool());

@ -88,6 +88,8 @@ class ChromeNetworkServiceBrowserTest
context_params->enable_encrypted_cookies = enable_encrypted_cookies;
context_params->cookie_path =
browser()->profile()->GetPath().Append(FILE_PATH_LITERAL("cookies"));
context_params->cert_verifier_params = content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
GetNetworkService()->CreateNetworkContext(
network_context.InitWithNewPipeAndPassReceiver(),
std::move(context_params));

@ -195,6 +195,8 @@ IN_PROC_BROWSER_TEST_F(NetworkQualityEstimatorPrefsBrowserTest,
mojo::PendingRemote<network::mojom::NetworkContext> network_context;
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
context_params->cert_verifier_params = content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
context_params->http_server_properties_path =
browser()->profile()->GetPath().Append(
FILE_PATH_LITERAL("Temp Network Persistent State"));

@ -3,12 +3,16 @@
// found in the LICENSE file.
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
@ -25,8 +29,10 @@
#include "chrome/browser/net/profile_network_context_service.h"
#include "chrome/browser/net/profile_network_context_service_factory.h"
#include "chrome/browser/net/profile_network_context_service_test_utils.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/policy/policy_test_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_features.h"
@ -38,10 +44,12 @@
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/simple_url_loader_test_helper.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
#include "net/base/features.h"
#include "net/base/load_flags.h"
@ -51,6 +59,8 @@
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/embedded_test_server/request_handler_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/cert_verifier/test_cert_verifier_service_factory.h"
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/network_context.mojom.h"
@ -444,19 +454,94 @@ IN_PROC_BROWSER_TEST_F(ProfileNetworkContextServiceDiskCacheBrowsertest,
}
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
namespace {
void UnblockOnProfileCreation(base::RunLoop* run_loop,
Profile* profile,
Profile::CreateStatus status) {
if (status == Profile::CREATE_STATUS_INITIALIZED)
run_loop->Quit();
}
} // namespace
class ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest
: public policy::PolicyTest,
public testing::WithParamInterface<bool> {
public:
void SetUpInProcessBrowserTestFixture() override {
scoped_feature_list_.InitWithFeatureState(
net::features::kCertVerifierBuiltinFeature,
/*enabled=*/GetParam());
std::vector<base::Feature> enabled_features, disabled_features;
if (use_builtin_cert_verifier()) {
enabled_features.push_back(net::features::kCertVerifierBuiltinFeature);
} else {
disabled_features.push_back(net::features::kCertVerifierBuiltinFeature);
}
if (enable_cert_verifier_service()) {
#if defined(OS_CHROMEOS)
// TODO(crbug.com/1085379): remove this GTEST_SKIP().
GTEST_SKIP() << "Skipping test, CertVerifierService feature not yet "
"available on ChromeOS.";
#else
enabled_features.push_back(network::features::kCertVerifierService);
test_cert_verifier_service_factory_.emplace();
content::SetCertVerifierServiceFactoryForTesting(
&test_cert_verifier_service_factory_.value());
#endif
} else {
disabled_features.push_back(network::features::kCertVerifierService);
}
scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
policy::PolicyTest::SetUpInProcessBrowserTestFixture();
}
void TearDownInProcessBrowserTestFixture() override {
content::SetCertVerifierServiceFactoryForTesting(nullptr);
}
void SetUpOnMainThread() override {
if (enable_cert_verifier_service()) {
test_cert_verifier_service_factory_->ReleaseAllCertVerifierParams();
}
}
void ExpectUseBuiltinCertVerifierCorrectUsingCertVerifierService(
network::mojom::CertVerifierCreationParams::CertVerifierImpl
use_builtin_cert_verifier) {
ASSERT_TRUE(enable_cert_verifier_service());
ASSERT_TRUE(test_cert_verifier_service_factory_);
EXPECT_EQ(1ul, test_cert_verifier_service_factory_->num_captured_params());
EXPECT_EQ(use_builtin_cert_verifier,
test_cert_verifier_service_factory_->GetParamsAtIndex(0)
->creation_params->use_builtin_cert_verifier);
// Send it to the actual CertVerifierServiceFactory.
test_cert_verifier_service_factory_->ReleaseNextCertVerifierParams();
}
Profile* CreateNewProfile() {
ProfileManager* profile_manager = g_browser_process->profile_manager();
base::FilePath new_path =
profile_manager->GenerateNextProfileDirectoryPath();
base::RunLoop run_loop;
profile_manager->CreateProfileAsync(
new_path, base::BindRepeating(&UnblockOnProfileCreation, &run_loop),
base::string16(), std::string());
run_loop.Run();
return profile_manager->GetProfileByPath(new_path);
}
bool use_builtin_cert_verifier() const { return GetParam(); }
bool enable_cert_verifier_service() const {
return enable_cert_verifier_service_;
}
void set_enable_cert_verifier_service(bool enable_cv_service) {
enable_cert_verifier_service_ = enable_cv_service;
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
bool enable_cert_verifier_service_ = false;
// Used if enable_cert_verifier_service() returns true.
base::Optional<cert_verifier::TestCertVerifierServiceFactoryImpl>
test_cert_verifier_service_factory_;
};
IN_PROC_BROWSER_TEST_P(
@ -472,10 +557,11 @@ IN_PROC_BROWSER_TEST_P(
/*in_memory=*/false, empty_relative_partition_path,
&network_context_params, &cert_verifier_creation_params);
EXPECT_EQ(GetParam() ? network::mojom::CertVerifierCreationParams::
CertVerifierImpl::kBuiltin
: network::mojom::CertVerifierCreationParams::
CertVerifierImpl::kSystem,
EXPECT_EQ(use_builtin_cert_verifier()
? network::mojom::CertVerifierCreationParams::
CertVerifierImpl::kBuiltin
: network::mojom::CertVerifierCreationParams::
CertVerifierImpl::kSystem,
cert_verifier_creation_params.use_builtin_cert_verifier);
}
@ -519,6 +605,68 @@ INSTANTIATE_TEST_SUITE_P(
All,
ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest,
::testing::Bool());
class
ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTestWithService
: public ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest {
public:
ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTestWithService() {
set_enable_cert_verifier_service(true);
}
~ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTestWithService()
override = default;
};
IN_PROC_BROWSER_TEST_P(
ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTestWithService,
Test) {
{
content::BrowserContext::GetDefaultStoragePartition(CreateNewProfile())
->GetNetworkContext();
ExpectUseBuiltinCertVerifierCorrectUsingCertVerifierService(
use_builtin_cert_verifier()
? network::mojom::CertVerifierCreationParams::CertVerifierImpl::
kBuiltin
: network::mojom::CertVerifierCreationParams::CertVerifierImpl::
kSystem);
}
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
// If the BuiltinCertificateVerifierEnabled policy is set it should override
// the feature flag.
policy::PolicyMap policies;
SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
std::make_unique<base::Value>(true));
UpdateProviderPolicy(policies);
{
content::BrowserContext::GetDefaultStoragePartition(CreateNewProfile())
->GetNetworkContext();
ExpectUseBuiltinCertVerifierCorrectUsingCertVerifierService(
network::mojom::CertVerifierCreationParams::CertVerifierImpl::kBuiltin);
}
SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
std::make_unique<base::Value>(false));
UpdateProviderPolicy(policies);
{
content::BrowserContext::GetDefaultStoragePartition(CreateNewProfile())
->GetNetworkContext();
ExpectUseBuiltinCertVerifierCorrectUsingCertVerifierService(
network::mojom::CertVerifierCreationParams::CertVerifierImpl::kSystem);
}
#endif // BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
}
INSTANTIATE_TEST_SUITE_P(
All,
ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTestWithService,
::testing::Bool());
#endif // BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
enum class CorsTestMode {

@ -55,14 +55,17 @@
#include "content/public/common/user_agent.h"
#include "crypto/sha2.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/features.h"
#include "net/net_buildflags.h"
#include "net/third_party/uri_template/uri_template.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
#include "third_party/blink/public/common/features.h"
@ -272,6 +275,7 @@ SystemNetworkContextManager::GetURLLoaderFactory() {
params->process_id = network::mojom::kBrowserProcessId;
params->is_corb_enabled = false;
params->is_trusted = true;
url_loader_factory_.reset();
GetContext()->CreateURLLoaderFactory(
url_loader_factory_.BindNewPipeAndPassReceiver(), std::move(params));
@ -644,8 +648,8 @@ SystemNetworkContextManager::CreateDefaultNetworkContextParams() {
network::mojom::CertVerifierCreationParams::New();
ConfigureDefaultNetworkContextParams(network_context_params.get(),
cert_verifier_creation_params.get());
network_context_params->cert_verifier_creation_params =
std::move(cert_verifier_creation_params);
network_context_params->cert_verifier_params =
content::GetCertVerifierParams(std::move(cert_verifier_creation_params));
return network_context_params;
}

@ -9,6 +9,7 @@
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
@ -123,9 +124,12 @@ class SystemNetworkContextManager {
network::mojom::CertVerifierCreationParams*
cert_verifier_creation_params);
// Same as ConfigureDefaultNetworkContextParams() but returns a newly
// allocated network::mojom::NetworkContextParams with the
// CertVerifierCreationParams already placed into the NetworkContextParams.
// Performs the same function as ConfigureDefaultNetworkContextParams(), and
// then returns a newly allocated network::mojom::NetworkContextParams with
// some modifications: if the CertVerifierService is enabled, the new
// NetworkContextParams will contain a CertVerifierServiceRemoteParams.
// Otherwise the newly configured CertVerifierCreationParams is placed
// directly into the NetworkContextParams.
network::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams();
// Returns a shared global NetExportFileWriter instance, used by net-export.
@ -160,6 +164,10 @@ class SystemNetworkContextManager {
}
private:
FRIEND_TEST_ALL_PREFIXES(
SystemNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest,
Test);
class URLLoaderFactoryForSystem;
// Constructor. |pref_service| must out live this object.

@ -21,8 +21,11 @@
#include "chrome/test/base/in_process_browser_test.h"
#include "components/prefs/pref_service.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/common/user_agent.h"
#include "content/public/test/browser_test.h"
#include "services/cert_verifier/test_cert_verifier_service_factory.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_service_buildflags.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
@ -458,57 +461,142 @@ INSTANTIATE_TEST_SUITE_P(
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
class SystemNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest
: public policy::PolicyTest,
public testing::WithParamInterface<bool> {
public testing::WithParamInterface<std::tuple<bool, bool>> {
public:
SystemNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest() {
bool use_builtin_cert_verifier;
std::tie(use_builtin_cert_verifier, enable_cert_verification_service_) =
GetParam();
cert_verifier_impl_ = use_builtin_cert_verifier
? network::mojom::CertVerifierCreationParams::
CertVerifierImpl::kBuiltin
: network::mojom::CertVerifierCreationParams::
CertVerifierImpl::kSystem;
}
void SetUpInProcessBrowserTestFixture() override {
scoped_feature_list_.InitWithFeatureState(
net::features::kCertVerifierBuiltinFeature,
/*enabled=*/GetParam());
std::vector<base::Feature> enabled_features, disabled_features;
if (cert_verifier_impl_ == network::mojom::CertVerifierCreationParams::
CertVerifierImpl::kBuiltin) {
enabled_features.push_back(net::features::kCertVerifierBuiltinFeature);
} else {
disabled_features.push_back(net::features::kCertVerifierBuiltinFeature);
}
if (enable_cert_verification_service_) {
#if defined(OS_CHROMEOS)
// TODO(crbug.com/1085379): remove this GTEST_SKIP().
GTEST_SKIP() << "Skipping test, CertVerifierService feature not yet "
"available on ChromeOS.";
#else
enabled_features.push_back(network::features::kCertVerifierService);
test_cert_verifier_service_factory_.emplace();
content::SetCertVerifierServiceFactoryForTesting(
&test_cert_verifier_service_factory_.value());
#endif
} else {
disabled_features.push_back(network::features::kCertVerifierService);
}
scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
policy::PolicyTest::SetUpInProcessBrowserTestFixture();
}
void TearDownInProcessBrowserTestFixture() override {
content::SetCertVerifierServiceFactoryForTesting(nullptr);
}
void SetUpOnMainThread() override {
if (enable_cert_verification_service_) {
test_cert_verifier_service_factory_->ReleaseAllCertVerifierParams();
}
}
void ExpectUseBuiltinCertVerifierCorrect(
network::mojom::NetworkContextParamsPtr& network_context_params_ptr,
network::mojom::CertVerifierCreationParams::CertVerifierImpl
use_builtin_cert_verifier) {
ASSERT_TRUE(network_context_params_ptr);
ASSERT_TRUE(network_context_params_ptr->cert_verifier_params);
if (enable_cert_verification_service_) {
EXPECT_TRUE(
network_context_params_ptr->cert_verifier_params->is_remote_params());
ASSERT_TRUE(test_cert_verifier_service_factory_);
ASSERT_EQ(1ul,
test_cert_verifier_service_factory_->num_captured_params());
ASSERT_TRUE(test_cert_verifier_service_factory_->GetParamsAtIndex(0)
->creation_params);
EXPECT_EQ(use_builtin_cert_verifier,
test_cert_verifier_service_factory_->GetParamsAtIndex(0)
->creation_params->use_builtin_cert_verifier);
// Send it to the actual CertVerifierServiceFactory.
test_cert_verifier_service_factory_->ReleaseNextCertVerifierParams();
} else {
ASSERT_TRUE(network_context_params_ptr->cert_verifier_params
->is_creation_params());
EXPECT_EQ(use_builtin_cert_verifier,
network_context_params_ptr->cert_verifier_params
->get_creation_params()
->use_builtin_cert_verifier);
}
}
network::mojom::CertVerifierCreationParams::CertVerifierImpl
cert_verifier_impl() const {
return cert_verifier_impl_;
}
private:
network::mojom::CertVerifierCreationParams::CertVerifierImpl
cert_verifier_impl_;
bool enable_cert_verification_service_;
base::test::ScopedFeatureList scoped_feature_list_;
// Used if |enable_cert_verification_service_| set to true.
base::Optional<cert_verifier::TestCertVerifierServiceFactoryImpl>
test_cert_verifier_service_factory_;
};
IN_PROC_BROWSER_TEST_P(
SystemNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest,
Test) {
network::mojom::NetworkContextParamsPtr network_context_params_ptr;
// If no BuiltinCertificateVerifierEnabled policy is set, the
// use_builtin_cert_verifier param should be set from the feature flag.
EXPECT_EQ(GetParam() ? network::mojom::CertVerifierCreationParams::
CertVerifierImpl::kBuiltin
: network::mojom::CertVerifierCreationParams::
CertVerifierImpl::kSystem,
g_browser_process->system_network_context_manager()
->CreateDefaultNetworkContextParams()
->cert_verifier_creation_params->use_builtin_cert_verifier);
network_context_params_ptr =
g_browser_process->system_network_context_manager()
->CreateDefaultNetworkContextParams();
ExpectUseBuiltinCertVerifierCorrect(network_context_params_ptr,
cert_verifier_impl());
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
// If the BuiltinCertificateVerifierEnabled policy is set it should override
// the feature flag.
// If the BuiltinCertificateVerifierEnabled policy is set it should
// override the feature flag.
policy::PolicyMap policies;
SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
std::make_unique<base::Value>(true));
UpdateProviderPolicy(policies);
EXPECT_EQ(
network::mojom::CertVerifierCreationParams::CertVerifierImpl::kBuiltin,
network_context_params_ptr =
g_browser_process->system_network_context_manager()
->CreateDefaultNetworkContextParams()
->cert_verifier_creation_params->use_builtin_cert_verifier);
->CreateDefaultNetworkContextParams();
ExpectUseBuiltinCertVerifierCorrect(
network_context_params_ptr,
network::mojom::CertVerifierCreationParams::CertVerifierImpl::kBuiltin);
SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
std::make_unique<base::Value>(false));
UpdateProviderPolicy(policies);
EXPECT_EQ(
network::mojom::CertVerifierCreationParams::CertVerifierImpl::kSystem,
network_context_params_ptr =
g_browser_process->system_network_context_manager()
->CreateDefaultNetworkContextParams()
->cert_verifier_creation_params->use_builtin_cert_verifier);
->CreateDefaultNetworkContextParams();
ExpectUseBuiltinCertVerifierCorrect(
network_context_params_ptr,
network::mojom::CertVerifierCreationParams::CertVerifierImpl::kSystem);
#endif // BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
}
INSTANTIATE_TEST_SUITE_P(
All,
SystemNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest,
::testing::Bool());
::testing::Combine(::testing::Bool(), ::testing::Bool()));
#endif // BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)

@ -13,6 +13,7 @@
#include "components/prefs/pref_service.h"
#include "components/prefs/testing_pref_store.h"
#include "components/sync_preferences/pref_service_mock_factory.h"
#include "content/public/browser/network_service_instance.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/ssl_config.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -43,6 +44,8 @@ TEST_F(CommandLinePrefStoreSSLManagerTest, CommandLinePrefs) {
SSLConfigServiceManager::RegisterPrefs(registry.get());
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
context_params->cert_verifier_params = content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
std::unique_ptr<SSLConfigServiceManager> config_manager(
SSLConfigServiceManager::CreateDefaultManager(local_state.get()));
config_manager->AddToNetworkContextParams(context_params.get());

@ -49,6 +49,7 @@
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "url/origin.h"
@ -795,6 +796,8 @@ void IsolatedPrerenderTabHelper::CreateIsolatedURLLoaderFactory() {
context_params->initial_custom_proxy_config =
isolated_prerender_service->proxy_configurator()
->CreateCustomProxyConfig();
context_params->cert_verifier_params = content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
// Also register a client config receiver so that updates to the set of proxy
// hosts or proxy headers will be updated.

@ -21,6 +21,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/p2p.mojom.h"
#include "services/network/public/mojom/p2p_trusted.mojom.h"
@ -321,6 +322,8 @@ network::mojom::NetworkContext* SharingServiceHost::GetNetworkContext() {
network::mojom::NetworkContextParams::New();
context_params->user_agent = "";
context_params->accept_language = "en-us,en";
context_params->cert_verifier_params = content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
content::GetNetworkService()->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(), std::move(context_params));

@ -17,6 +17,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/browser/network_service_instance.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/cert/cert_verifier.h"
#include "net/ssl/ssl_config.h"
@ -46,6 +47,9 @@ class SSLConfigServiceManagerPrefTest : public testing::Test,
// steal the only two params that the |config_manager| populates.
network::mojom::NetworkContextParamsPtr network_context_params =
network::mojom::NetworkContextParams::New();
network_context_params->cert_verifier_params =
content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
config_manager->AddToNetworkContextParams(network_context_params.get());
EXPECT_TRUE(network_context_params->initial_ssl_config);
initial_config_ = std::move(network_context_params->initial_ssl_config);

@ -220,6 +220,7 @@ static_library("test_support") {
"//pdf",
"//ppapi/buildflags",
"//printing/buildflags",
"//services/cert_verifier:test_support",
"//skia",
"//sql",
"//sql:test_support",

@ -36,6 +36,7 @@
#include "services/network/network_service.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_network_context.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -294,6 +295,10 @@ class NetExportFileWriterTest : public ::testing::Test {
ASSERT_TRUE(log_temp_dir_.CreateUniqueTempDir());
network::mojom::NetworkContextParamsPtr params =
network::mojom::NetworkContextParams::New();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
params->cert_verifier_params =
network::FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
params->initial_proxy_config =

@ -148,6 +148,7 @@ jumbo_source_set("browser") {
"//services/audio",
"//services/audio/public/cpp",
"//services/audio/public/mojom",
"//services/cert_verifier:lib",
"//services/content:impl",
"//services/content/public/cpp",
"//services/content/public/mojom",

@ -72,6 +72,9 @@ include_rules = [
"-services/network",
"+services/network/public/cpp",
"+services/network/public/mojom",
"-services/cert_verifier",
"+services/cert_verifier/public/cpp",
"+services/cert_verifier/public/mojom",
# In general, //content shouldn't depend on //device.
# This is the an exception.
@ -152,6 +155,8 @@ specific_include_rules = {
"+services/network/url_request_context_owner.h",
],
"network_service_instance_impl\.cc": [
# Used to instantiate a CertVerifierServiceFactory in the browser process.
"+services/cert_verifier/cert_verifier_service_factory.h",
# TODO(crbug.com/1049894): Remove.
"+services/network/network_service.h",
],

@ -255,6 +255,8 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
mojo::Remote<network::mojom::NetworkContext> network_context;
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
context_params->cert_verifier_params =
GetCertVerifierParams(network::mojom::CertVerifierCreationParams::New());
context_params->http_cache_path = GetCacheDirectory();
GetNetworkService()->CreateNetworkContext(
network_context.BindNewPipeAndPassReceiver(), std::move(context_params));

@ -37,6 +37,7 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/log/net_log_util.h"
#include "services/cert_verifier/cert_verifier_service_factory.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
@ -481,4 +482,95 @@ void PingNetworkService(base::OnceClosure closure) {
base::Passed(std::move(closure))));
}
namespace {
mojo::PendingRemote<cert_verifier::mojom::CertVerifierService>
GetNewCertVerifierServiceRemote(
cert_verifier::mojom::CertVerifierServiceFactory*
cert_verifier_service_factory,
network::mojom::CertVerifierCreationParamsPtr creation_params) {
mojo::PendingRemote<cert_verifier::mojom::CertVerifierService>
cert_verifier_remote;
cert_verifier_service_factory->GetNewCertVerifier(
cert_verifier_remote.InitWithNewPipeAndPassReceiver(),
std::move(creation_params));
return cert_verifier_remote;
}
// Owns the CertVerifierServiceFactory used by the browser.
// Lives on the UI thread.
class CertVerifierServiceFactoryOwner {
public:
CertVerifierServiceFactoryOwner() = default;
CertVerifierServiceFactoryOwner(const CertVerifierServiceFactoryOwner&) =
delete;
CertVerifierServiceFactoryOwner& operator=(
const CertVerifierServiceFactoryOwner&) = delete;
~CertVerifierServiceFactoryOwner() = delete;
static CertVerifierServiceFactoryOwner* Get() {
static base::NoDestructor<CertVerifierServiceFactoryOwner>
cert_verifier_service_factory_owner;
return &*cert_verifier_service_factory_owner;
}
// Passing nullptr will reset the current remote.
void SetCertVerifierServiceFactoryForTesting(
cert_verifier::mojom::CertVerifierServiceFactory* service_factory) {
if (service_factory) {
DCHECK(!service_factory_);
}
service_factory_ = service_factory;
service_factory_remote_.reset();
}
// Returns a pointer to a CertVerifierServiceFactory usable on the UI thread.
cert_verifier::mojom::CertVerifierServiceFactory*
GetCertVerifierServiceFactory() {
if (!service_factory_) {
// Except in tests, our CertVerifierServiceFactoryImpl is a singleton.
static base::NoDestructor<cert_verifier::CertVerifierServiceFactoryImpl>
cv_service_factory(
service_factory_remote_.BindNewPipeAndPassReceiver());
service_factory_ = service_factory_remote_.get();
}
return service_factory_;
}
private:
// Bound to UI thread.
mojo::Remote<cert_verifier::mojom::CertVerifierServiceFactory>
service_factory_remote_;
cert_verifier::mojom::CertVerifierServiceFactory* service_factory_ = nullptr;
};
} // namespace
network::mojom::CertVerifierParamsPtr GetCertVerifierParams(
network::mojom::CertVerifierCreationParamsPtr
cert_verifier_creation_params) {
if (!base::FeatureList::IsEnabled(network::features::kCertVerifierService)) {
return network::mojom::CertVerifierParams::NewCreationParams(
std::move(cert_verifier_creation_params));
}
auto cv_service_remote_params =
network::mojom::CertVerifierServiceRemoteParams::New();
// Create a cert verifier service.
cv_service_remote_params
->cert_verifier_service = GetNewCertVerifierServiceRemote(
CertVerifierServiceFactoryOwner::Get()->GetCertVerifierServiceFactory(),
std::move(cert_verifier_creation_params));
return network::mojom::CertVerifierParams::NewRemoteParams(
std::move(cv_service_remote_params));
}
void SetCertVerifierServiceFactoryForTesting(
cert_verifier::mojom::CertVerifierServiceFactory* service_factory) {
CertVerifierServiceFactoryOwner::Get()
->SetCertVerifierServiceFactoryForTesting(service_factory);
}
} // namespace content

@ -69,6 +69,8 @@ mojo::PendingRemote<network::mojom::NetworkContext> CreateNetworkContext() {
mojo::PendingRemote<network::mojom::NetworkContext> network_context;
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
context_params->cert_verifier_params =
GetCertVerifierParams(network::mojom::CertVerifierCreationParams::New());
GetNetworkService()->CreateNetworkContext(
network_context.InitWithNewPipeAndPassReceiver(),
std::move(context_params));

@ -7,6 +7,7 @@
#include <stdint.h>
#include <functional>
#include <memory>
#include <set>
#include <utility>
#include <vector>
@ -95,6 +96,7 @@
#include "net/ssl/client_cert_store.h"
#include "net/url_request/url_request_context.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h"
#include "services/network/public/cpp/features.h"
@ -2369,13 +2371,14 @@ void StoragePartitionImpl::InitNetworkContext() {
GetContentClient()->browser()->ConfigureNetworkContextParams(
browser_context_, is_in_memory_, relative_partition_path_,
context_params.get(), cert_verifier_creation_params.get());
DCHECK(!context_params->cert_verifier_creation_params)
<< "|cert_verifier_creation_params| should not be set in the "
"NetworkContextParams, as they will eventually be removed when the "
"CertVerifierService ships.";
DCHECK(!context_params->cert_verifier_params)
<< "|cert_verifier_params| should not be set in the NetworkContextParams,"
"as they will be replaced with either the newly configured "
"|cert_verifier_creation_params| or with a new pipe to the "
"CertVerifierService.";
context_params->cert_verifier_creation_params =
std::move(cert_verifier_creation_params);
context_params->cert_verifier_params =
GetCertVerifierParams(std::move(cert_verifier_creation_params));
// This mechanisms should be used only for legacy internal headers. You can
// find a recommended alternative approach on URLRequest::cors_exempt_headers

@ -1,6 +1,7 @@
include_rules = [
"-content",
"+services/cert_verifier/public/mojom",
"+services/network/public/mojom",
"+services/service_manager/public",
"+services/service_manager/sandbox",

@ -435,6 +435,7 @@ jumbo_source_set("browser_sources") {
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//services/audio/public/mojom",
"//services/cert_verifier/public/mojom",
"//services/content/public/mojom",
"//services/data_decoder/public/mojom",
"//services/device/public/mojom:device_service",

@ -1472,6 +1472,12 @@ class CONTENT_EXPORT ContentBrowserClient {
// BrowserContext's StoragePartition. StoragePartition will use the
// NetworkService to create a new NetworkContext using these params.
//
// If the CertVerifierService is enabled, the CertVerifierCreationParams will
// be used to create a new CertVerifierService, which will be passed to the
// network service in NetworkContextParams. Otherwise, the
// CertVerifierCreationParams will be placed in the NetworkContextParams and
// sent directly to the NetworkService for in-process CertVerifier creation.
//
// If |in_memory| is true, |relative_partition_path| is still a path that
// uniquely identifies the storage partition, though nothing should be written
// to it.

@ -11,7 +11,9 @@
#include "base/callback_list.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom-forward.h"
#include "services/network/public/cpp/network_connection_tracker.h"
#include "services/network/public/mojom/network_context.mojom-forward.h"
namespace base {
class SequencedTaskRunner;
@ -77,6 +79,25 @@ CONTENT_EXPORT void SetNetworkConnectionTrackerForTesting(
CONTENT_EXPORT const scoped_refptr<base::SequencedTaskRunner>&
GetNetworkTaskRunner();
// Returns a CertVerifierParams that can be placed into a new
// network::mojom::NetworkContextParams.
//
// If the CertVerifierService feature is enabled, the
// |cert_verifier_creation_params| will be used to configure a new
// CertVerifierService, and a pipe to the new CertVerifierService will be placed
// in the CertVerifierParams.
//
// Otherwise, |cert_verifier_creation_params| will just be placed directly into
// the CertVerifierParams to configure an in-network-service CertVerifier.
CONTENT_EXPORT network::mojom::CertVerifierParamsPtr GetCertVerifierParams(
network::mojom::CertVerifierCreationParamsPtr
cert_verifier_creation_params);
// Sets the CertVerifierServiceFactory used to instantiate
// CertVerifierServices.
CONTENT_EXPORT void SetCertVerifierServiceFactoryForTesting(
cert_verifier::mojom::CertVerifierServiceFactory* service_factory);
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_NETWORK_SERVICE_INSTANCE_H_

@ -12,6 +12,7 @@
#include "base/test/test_suite.h"
#include "build/build_config.h"
#include "content/browser/network_service_instance_impl.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/test/test_host_resolver.h"
#include "content/test/test_blink_web_unit_test_support.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -54,6 +55,21 @@ class ResetNetworkServiceBetweenTests : public testing::EmptyTestEventListener {
DISALLOW_COPY_AND_ASSIGN(ResetNetworkServiceBetweenTests);
};
// Similarly to the above, the global CertVerifierServiceFactory object needs
// to be destructed in between tests.
class ResetCertVerifierServiceFactoryBetweenTests
: public testing::EmptyTestEventListener {
public:
ResetCertVerifierServiceFactoryBetweenTests() = default;
void OnTestEnd(const testing::TestInfo& test_info) override {
SetCertVerifierServiceFactoryForTesting(nullptr);
}
private:
DISALLOW_COPY_AND_ASSIGN(ResetCertVerifierServiceFactoryBetweenTests);
};
} // namespace
UnitTestTestSuite::UnitTestTestSuite(base::TestSuite* test_suite)
@ -69,6 +85,7 @@ UnitTestTestSuite::UnitTestTestSuite(base::TestSuite* test_suite)
testing::TestEventListeners& listeners =
testing::UnitTest::GetInstance()->listeners();
listeners.Append(new ResetNetworkServiceBetweenTests);
listeners.Append(new ResetCertVerifierServiceFactoryBetweenTests);
// The ThreadPool created by the test launcher is never destroyed.
// Similarly, the FeatureList created here is never destroyed so it

@ -179,8 +179,8 @@ HeadlessRequestContextManager::CreateSystemContext(
::network::mojom::CertVerifierCreationParams::New();
manager->ConfigureNetworkContextParamsInternal(
network_context_params.get(), cert_verifier_creation_params.get());
network_context_params->cert_verifier_creation_params =
std::move(cert_verifier_creation_params);
network_context_params->cert_verifier_params =
content::GetCertVerifierParams(std::move(cert_verifier_creation_params));
network_service->CreateNetworkContext(
manager->system_context_.InitWithNewPipeAndPassReceiver(),
std::move(network_context_params));

@ -29,6 +29,9 @@ source_set("tests") {
sources = [
"cert_verifier_service_factory_unittest.cc",
"cert_verifier_service_unittest.cc",
"integration_tests/network_context_unittest.cc",
"integration_tests/network_service_unittest.cc",
"integration_tests/ssl_config_service_mojo_unittest.cc",
]
deps = [
@ -37,8 +40,11 @@ source_set("tests") {
"//base/test:test_support",
"//net",
"//net:test_support",
"//services/cert_verifier/cert_net_url_loader:cert_net_url_loader",
"//services/cert_verifier/public/mojom",
"//services/network:network_service",
"//services/network:test_support",
"//services/network/public/cpp/cert_verifier:mojo_cert_verifier",
"//services/network/public/mojom",
"//testing/gtest",
]

@ -17,7 +17,8 @@ CertNetFetcherTestUtil::CertNetFetcherTestUtil() {
pending_receiver_ =
pending_remote_url_loader_factory.InitWithNewPipeAndPassReceiver();
fetcher_ = base::MakeRefCounted<CertNetFetcherURLLoader>(
fetcher_ = base::MakeRefCounted<CertNetFetcherURLLoader>();
fetcher_->SetURLLoaderFactoryAndReconnector(
std::move(pending_remote_url_loader_factory),
base::BindRepeating(
&CertNetFetcherTestUtil::RebindURLLoaderFactoryTrampoline,

@ -75,6 +75,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/timer/timer.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/load_flags.h"
#include "net/cert/cert_net_fetcher.h"
#include "net/http/http_request_headers.h"
@ -142,6 +143,10 @@ class CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader {
// requests have completed or Shutdown() is called.
~AsyncCertNetFetcherURLLoader();
// Disconnects |factory_|, and calls FlushForTesting() in order to
// synchronously disconnect.
void DisconnectURLLoaderFactoryForTesting();
// Starts an asynchronous request to fetch the given URL. On completion
// request->OnJobCompleted() will be invoked.
void Fetch(std::unique_ptr<RequestParams> request_params,
@ -156,8 +161,8 @@ class CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader {
void Shutdown();
private:
// Callback for disconnection of |factory_|. Attempts to use
// |bind_new_url_loader_factory_cb_| to reconnect.
// Attempts to use |bind_new_url_loader_factory_cb_| to reconnect |factory_|.
// There's no guarantee that |bind_new_url_loader_factory_cb_| will succeed.
void RebindURLLoaderFactory();
// Finds a job with a matching RequestPararms or returns nullptr if there was
@ -592,15 +597,7 @@ CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
BindNewURLLoaderFactoryCallback bind_new_url_loader_factory_cb)
: factory_(std::move(factory_pending_remote)),
bind_new_url_loader_factory_cb_(
std::move(bind_new_url_loader_factory_cb)) {
// If the URLLoaderFactory disconnects, try to rebind immediately in case this
// was a deliberate disconnection to force a restart. Safe to use
// base::Unretained(this) because |this| owns |factory_|.
factory_.set_disconnect_handler(
base::BindOnce(&CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
RebindURLLoaderFactory,
base::Unretained(this)));
}
std::move(bind_new_url_loader_factory_cb)) {}
CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
~AsyncCertNetFetcherURLLoader() {
@ -611,6 +608,16 @@ CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
DCHECK(jobs_.empty());
}
void CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
DisconnectURLLoaderFactoryForTesting() {
// Sadly, there's no good way to disconnect a Mojo remote other than resetting
// it, binding it to a new pipe, and dropping the PendingReceiver on the
// floor.
factory_.reset();
ignore_result(factory_.BindNewPipeAndPassReceiver());
factory_.FlushForTesting();
}
bool JobComparator::operator()(const Job* job1, const Job* job2) const {
return job1->request_params() < job2->request_params();
}
@ -628,6 +635,10 @@ void CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::Fetch(
return;
}
if (!factory_.is_connected()) {
RebindURLLoaderFactory();
}
job = new Job(std::move(request_params), this);
jobs_[job] = base::WrapUnique(job);
// Attach the request before calling |StartURLLoader()|; this ensures that the
@ -655,12 +666,12 @@ void CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
// trying to reconnect a URLLoaderFactory.
DCHECK(factory_);
if (!bind_new_url_loader_factory_cb_) {
return;
}
factory_.reset();
bind_new_url_loader_factory_cb_.Run(factory_.BindNewPipeAndPassReceiver());
factory_.set_disconnect_handler(
base::BindOnce(&CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
RebindURLLoaderFactory,
base::Unretained(this)));
}
namespace {
@ -726,21 +737,30 @@ class CertNetFetcherRequestImpl : public net::CertNetFetcher::Request {
} // namespace
CertNetFetcherURLLoader::CertNetFetcherURLLoader(
mojo::PendingRemote<network::mojom::URLLoaderFactory> factory,
BindNewURLLoaderFactoryCallback bind_new_url_loader_factory_cb)
: task_runner_(base::SequencedTaskRunnerHandle::Get()),
impl_(std::make_unique<AsyncCertNetFetcherURLLoader>(
std::move(factory),
std::move(bind_new_url_loader_factory_cb))) {}
CertNetFetcherURLLoader::CertNetFetcherURLLoader()
: task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
CertNetFetcherURLLoader::~CertNetFetcherURLLoader() = default;
void CertNetFetcherURLLoader::SetURLLoaderFactoryAndReconnector(
mojo::PendingRemote<network::mojom::URLLoaderFactory> factory,
base::RepeatingCallback<
void(mojo::PendingReceiver<network::mojom::URLLoaderFactory>)>
bind_new_url_loader_factory_cb) {
DCHECK(!impl_);
impl_ = std::make_unique<AsyncCertNetFetcherURLLoader>(
std::move(factory), std::move(bind_new_url_loader_factory_cb));
}
// static
base::TimeDelta CertNetFetcherURLLoader::GetDefaultTimeoutForTesting() {
return GetTimeout(CertNetFetcher::DEFAULT);
}
void CertNetFetcherURLLoader::DisconnectURLLoaderFactoryForTesting() {
impl_->DisconnectURLLoaderFactoryForTesting();
}
void CertNetFetcherURLLoader::Shutdown() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (impl_) {
@ -800,9 +820,10 @@ void CertNetFetcherURLLoader::DoFetchOnTaskRunner(
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (!impl_) {
// The fetcher might have been shutdown (which resets |impl_|) between when
// this task was posted and when it is running. In this case, signal the
// request and do not start a network request.
// |SetURLLoaderFactoryAndReconnector| may not have been called yet, or the
// fetcher might have been shutdown between when this task was posted and
// when it is running. In this case, signal the request and do not start a
// network request.
request->SignalImmediateError();
return;
}

@ -30,10 +30,17 @@ class COMPONENT_EXPORT(CERT_VERIFIER_CPP) CertNetFetcherURLLoader
class RequestCore;
struct RequestParams;
// Creates the CertNetFetcherURLLoader, using the provided URLLoaderFactory.
// If the other side of the remote disconnects, the CertNetFetcherURLLoader
// will attempt that reconnect using |bind_new_url_loader_factory_cb|.
explicit CertNetFetcherURLLoader(
// The CertNetFetcherURLLoader will immediately fail all requests until
// SetURLLoaderFactoryAndReconnector() is called.
CertNetFetcherURLLoader();
// Enables this CertNetFetcher to load URLs using |factory|.
// If the other side of the |factory| remote disconnects, the
// CertNetFetcherURLLoader will attempt to reconnect using
// |bind_new_url_loader_factory_cb|. This must be called before ever
// performing a fetch. It is recommended, but not required, to provide a
// functional |bind_new_url_loader_factory_cb|.
void SetURLLoaderFactoryAndReconnector(
mojo::PendingRemote<network::mojom::URLLoaderFactory> factory,
base::RepeatingCallback<
void(mojo::PendingReceiver<network::mojom::URLLoaderFactory>)>
@ -42,6 +49,9 @@ class COMPONENT_EXPORT(CERT_VERIFIER_CPP) CertNetFetcherURLLoader
// Returns the default timeout value. Intended for test use only.
static base::TimeDelta GetDefaultTimeoutForTesting();
// Disconnects the URLLoaderFactory used for fetches.
void DisconnectURLLoaderFactoryForTesting();
// CertNetFetcher impl:
void Shutdown() override;
std::unique_ptr<Request> FetchCaIssuers(const GURL& url,

@ -4,9 +4,12 @@
#include "services/cert_verifier/cert_verifier_service.h"
#include "base/bind.h"
#include "base/logging.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/completion_once_callback.h"
#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
namespace cert_verifier {
namespace internal {
@ -65,12 +68,18 @@ class CertVerifyResultHelper {
std::unique_ptr<net::CertVerifier::Request> local_request_;
};
void ReconnectURLLoaderFactory(
mojo::Remote<mojom::URLLoaderFactoryConnector>* reconnector,
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {
(*reconnector)->CreateURLLoaderFactory(std::move(receiver));
}
} // namespace
CertVerifierServiceImpl::CertVerifierServiceImpl(
std::unique_ptr<net::CertVerifier> verifier,
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
scoped_refptr<net::CertNetFetcher> cert_net_fetcher)
scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher)
: verifier_(std::move(verifier)),
receiver_(this, std::move(receiver)),
cert_net_fetcher_(std::move(cert_net_fetcher)) {
@ -95,6 +104,20 @@ void CertVerifierServiceImpl::SetConfig(
verifier_->SetConfig(config);
}
void CertVerifierServiceImpl::EnableNetworkAccess(
mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
mojo::PendingRemote<mojom::URLLoaderFactoryConnector> reconnector) {
if (cert_net_fetcher_) {
auto reconnect_cb =
std::make_unique<mojo::Remote<mojom::URLLoaderFactoryConnector>>(
std::move(reconnector));
cert_net_fetcher_->SetURLLoaderFactoryAndReconnector(
std::move(url_loader_factory),
base::BindRepeating(&ReconnectURLLoaderFactory,
base::Owned(std::move(reconnect_cb))));
}
}
void CertVerifierServiceImpl::Verify(
const net::CertVerifier::RequestParams& params,
mojo::PendingRemote<mojom::CertVerifierRequest> cert_verifier_request) {
@ -115,9 +138,11 @@ void CertVerifierServiceImpl::Verify(
base::BindOnce(&CertVerifyResultHelper::CompleteCertVerifierRequest,
std::move(result_helper));
int net_err =
verifier_->Verify(params, result.get(), std::move(callback),
result_helper_ptr->local_request(), null_net_log_);
int net_err = verifier_->Verify(
params, result.get(), std::move(callback),
result_helper_ptr->local_request(),
net::NetLogWithSource::Make(net::NetLog::Get(),
net::NetLogSourceType::CERT_VERIFIER_JOB));
if (net_err == net::ERR_IO_PENDING) {
// If this request is to be completely asynchronously, give the callback
// ownership of our mojom::CertVerifierRequest and net::CertVerifyResult.

@ -13,7 +13,9 @@
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "net/cert/cert_net_fetcher.h"
#include "net/log/net_log_with_source.h"
#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
// Defines an implementation of a Cert Verifier Service to be queried by network
// service or others.
@ -26,13 +28,17 @@ class CertVerifierServiceImpl : public mojom::CertVerifierService {
explicit CertVerifierServiceImpl(
std::unique_ptr<net::CertVerifier> verifier,
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
scoped_refptr<net::CertNetFetcher> cert_net_fetcher);
scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher);
// mojom::CertVerifierService implementation:
void Verify(const net::CertVerifier::RequestParams& params,
mojo::PendingRemote<mojom::CertVerifierRequest>
cert_verifier_request) override;
void SetConfig(const net::CertVerifier::Config& config) override;
void EnableNetworkAccess(
mojo::PendingRemote<network::mojom::URLLoaderFactory>,
mojo::PendingRemote<mojom::URLLoaderFactoryConnector> reconnector)
override;
private:
~CertVerifierServiceImpl() override;
@ -41,11 +47,7 @@ class CertVerifierServiceImpl : public mojom::CertVerifierService {
std::unique_ptr<net::CertVerifier> verifier_;
mojo::Receiver<mojom::CertVerifierService> receiver_;
scoped_refptr<net::CertNetFetcher> cert_net_fetcher_;
// A null NetLog for |verifier_->Verify()|. Initialized with a non-capturing
// NetLog.
const net::NetLogWithSource null_net_log_;
scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher_;
};
} // namespace internal

@ -20,58 +20,19 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace cert_verifier {
namespace {
void ReconnectCertNetFetcher(
mojo::Remote<mojom::URLLoaderFactoryConnector>* connector,
mojo::PendingReceiver<network::mojom::URLLoaderFactory>
url_loader_factory) {
(*connector)->CreateURLLoaderFactory(std::move(url_loader_factory));
}
} // namespace
CertVerifierServiceFactoryImpl::CertVerifierServiceFactoryImpl(
mojo::PendingReceiver<mojom::CertVerifierServiceFactory> receiver)
: receiver_(this, std::move(receiver)) {}
CertVerifierServiceFactoryImpl::~CertVerifierServiceFactoryImpl() = default;
// static
scoped_refptr<CertNetFetcherURLLoader>
CertVerifierServiceFactoryImpl::CreateCertNetFetcher(
mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
cert_net_fetcher_url_loader_factory_connector) {
auto connector =
std::make_unique<mojo::Remote<mojom::URLLoaderFactoryConnector>>(
std::move(cert_net_fetcher_url_loader_factory_connector));
// The callback will own the CertNetFetcherReconnector, and the callback
// will be owned by the CertNetFetcherURLLoader. Only the
// CertNetFetcherURLLoader uses the CertNetFetcherReconnector.
auto reconnector_cb = base::BindRepeating(&ReconnectCertNetFetcher,
base::Owned(std::move(connector)));
return base::MakeRefCounted<CertNetFetcherURLLoader>(
std::move(url_loader_factory), std::move(reconnector_cb));
}
void CertVerifierServiceFactoryImpl::GetNewCertVerifier(
void GetNewCertVerifierImpl(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
cert_net_fetcher_url_loader_factory_connector,
network::mojom::CertVerifierCreationParamsPtr creation_params) {
network::mojom::CertVerifierCreationParamsPtr creation_params,
scoped_refptr<CertNetFetcherURLLoader>* cert_net_fetcher_ptr) {
scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher;
// Sometimes the cert_net_fetcher isn't used by CreateCertVerifier.
// But losing the last ref without calling Shutdown() will cause a CHECK
// failure, so keep a ref.
if (network::IsUsingCertNetFetcher()) {
DCHECK(url_loader_factory.is_valid());
DCHECK(cert_net_fetcher_url_loader_factory_connector.is_valid());
cert_net_fetcher = CreateCertNetFetcher(
std::move(url_loader_factory),
std::move(cert_net_fetcher_url_loader_factory_connector));
}
if (network::IsUsingCertNetFetcher())
cert_net_fetcher = base::MakeRefCounted<CertNetFetcherURLLoader>();
// Create a new CertVerifier to back our service. This will be instantiated
// without the coalescing or caching layers, because those layers will work
@ -87,10 +48,36 @@ void CertVerifierServiceFactoryImpl::GetNewCertVerifier(
cert_net_fetcher.reset();
}
if (cert_net_fetcher_ptr)
*cert_net_fetcher_ptr = cert_net_fetcher;
// The service will delete itself upon disconnection.
new internal::CertVerifierServiceImpl(std::move(cert_verifier),
std::move(receiver),
std::move(cert_net_fetcher));
}
} // namespace
CertVerifierServiceFactoryImpl::CertVerifierServiceFactoryImpl(
mojo::PendingReceiver<mojom::CertVerifierServiceFactory> receiver)
: receiver_(this, std::move(receiver)) {}
CertVerifierServiceFactoryImpl::~CertVerifierServiceFactoryImpl() = default;
void CertVerifierServiceFactoryImpl::GetNewCertVerifier(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
network::mojom::CertVerifierCreationParamsPtr creation_params) {
GetNewCertVerifierImpl(std::move(receiver), std::move(creation_params),
nullptr);
}
void CertVerifierServiceFactoryImpl::GetNewCertVerifierForTesting(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
network::mojom::CertVerifierCreationParamsPtr creation_params,
scoped_refptr<CertNetFetcherURLLoader>* cert_net_fetcher_ptr) {
GetNewCertVerifierImpl(std::move(receiver), std::move(creation_params),
cert_net_fetcher_ptr);
}
} // namespace cert_verifier

@ -8,6 +8,7 @@
#include <memory>
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
@ -28,23 +29,19 @@ class CertVerifierServiceFactoryImpl
mojo::PendingReceiver<mojom::CertVerifierServiceFactory> receiver);
~CertVerifierServiceFactoryImpl() override;
// Creates a CertNetFetcherURLLoader using the given URLLoaderFactory, that
// will try to reconnect its URLLoaderFactory using the
// URLLoaderFactoryConnector in case the original URLLoaderFactory
// disconnects.
static scoped_refptr<CertNetFetcherURLLoader> CreateCertNetFetcher(
mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
cert_net_fetcher_url_loader_factory_connector);
// mojom::CertVerifierServiceFactory implementation:
void GetNewCertVerifier(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
cert_net_fetcher_url_loader_factory_connector,
network::mojom::CertVerifierCreationParamsPtr creation_params) override;
// Performs the same function as above, but stores a ref to the new
// CertNetFetcherURLLoader in |*cert_net_fetcher_ptr|, if the
// CertNetFetcherURLLoader is in use.
void GetNewCertVerifierForTesting(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
network::mojom::CertVerifierCreationParamsPtr creation_params,
scoped_refptr<CertNetFetcherURLLoader>* cert_net_fetcher_ptr);
private:
mojo::Receiver<mojom::CertVerifierServiceFactory> receiver_;
};

@ -13,113 +13,25 @@
#include "base/check_op.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_net_fetcher.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
namespace cert_verifier {
namespace {
const char kMockURL[] = "http://mock.invalid/";
class TestReconnector : public mojom::URLLoaderFactoryConnector {
public:
explicit TestReconnector(
network::TestURLLoaderFactory* test_url_loader_factory)
: test_url_loader_factory_(test_url_loader_factory) {}
void CreateURLLoaderFactory(
mojo::PendingReceiver<network::mojom::URLLoaderFactory>
url_loader_factory_receiver) override {
num_connects_++;
receiver_set_.Add(test_url_loader_factory_,
std::move(url_loader_factory_receiver));
}
void DisconnectAll() { receiver_set_.Clear(); }
size_t num_connects() const { return num_connects_; }
private:
network::TestURLLoaderFactory* test_url_loader_factory_;
mojo::ReceiverSet<network::mojom::URLLoaderFactory> receiver_set_;
size_t num_connects_ = 0;
};
std::unique_ptr<net::CertNetFetcher::Request>
PerformCertNetFetcherRequestOnTaskRunner(
scoped_refptr<base::SequencedTaskRunner> runner,
scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher) {
std::unique_ptr<net::CertNetFetcher::Request> request;
base::RunLoop run_loop;
runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() {
request = cert_net_fetcher->FetchCaIssuers(
GURL(kMockURL), net::CertNetFetcher::DEFAULT,
net::CertNetFetcher::DEFAULT);
run_loop.QuitWhenIdle();
}));
run_loop.Run();
return request;
}
class CertVerifierServiceFactoryTest : public PlatformTest {
public:
CertVerifierServiceFactoryTest()
: test_reconnector_(&test_url_loader_factory_),
test_reconnector_receiver_(&test_reconnector_) {
test_reconnector_.CreateURLLoaderFactory(
test_url_loader_factory_remote_.InitWithNewPipeAndPassReceiver());
EXPECT_EQ(test_reconnector_.num_connects(), 1ul);
}
TestReconnector* test_reconnector() { return &test_reconnector_; }
mojo::PendingRemote<network::mojom::URLLoaderFactory>
TakeURLLoaderFactoryPendingRemote() {
return std::move(test_url_loader_factory_remote_);
}
mojo::Receiver<mojom::URLLoaderFactoryConnector>&
test_reconnector_receiver() {
return test_reconnector_receiver_;
}
network::TestURLLoaderFactory* test_url_loader_factory() {
return &test_url_loader_factory_;
}
private:
base::test::TaskEnvironment task_environment_;
// Instantiate a TestURLLoaderFactory which we can use to respond and unpause
// network requests.
network::TestURLLoaderFactory test_url_loader_factory_;
mojo::PendingRemote<network::mojom::URLLoaderFactory>
test_url_loader_factory_remote_;
// Instantiate a dummy URLLoaderFactoryConnector that can disconnect at will
// and will automatically reconnect to the |test_url_loader_factory| above.
TestReconnector test_reconnector_;
mojo::Receiver<mojom::URLLoaderFactoryConnector> test_reconnector_receiver_;
};
struct DummyCVServiceRequest : public mojom::CertVerifierRequest {
explicit DummyCVServiceRequest(base::RepeatingClosure on_finish)
: on_finish_(std::move(on_finish)) {}
@ -138,83 +50,9 @@ struct DummyCVServiceRequest : public mojom::CertVerifierRequest {
};
} // namespace
// Test that the CertNetFetcherURLLoader handed to the CertVerifierService
// successfully tries to reconnect after URLLoaderFactory disconnection.
TEST_F(CertVerifierServiceFactoryTest,
CertNetFetcherReconnectAfterURLLoaderFactoryReset) {
scoped_refptr<base::SequencedTaskRunner> caller_task_runner =
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
TEST(CertVerifierServiceFactoryTest, GetNewCertVerifier) {
base::test::TaskEnvironment task_environment;
// Pass mojo::Remote's for |test_url_loader_factory| and
// |test_reconnector| to the CertNetFetcherURLLoader
// created by the CertVerifierServiceFactoryImpl.
scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher =
CertVerifierServiceFactoryImpl::CreateCertNetFetcher(
TakeURLLoaderFactoryPendingRemote(),
test_reconnector_receiver().BindNewPipeAndPassRemote());
// Now run the test.
auto request1 = PerformCertNetFetcherRequestOnTaskRunner(caller_task_runner,
cert_net_fetcher);
EXPECT_EQ(test_url_loader_factory()->NumPending(), 1);
EXPECT_TRUE(test_url_loader_factory()->IsPending(kMockURL));
EXPECT_TRUE(test_url_loader_factory()->SimulateResponseForPendingRequest(
kMockURL, "", net::HTTP_NOT_FOUND));
EXPECT_EQ(test_url_loader_factory()->NumPending(), 0);
// Disconnect the test_url_loader_factory to test reconnection.
test_reconnector()->DisconnectAll();
// Now run the test.
auto request2 = PerformCertNetFetcherRequestOnTaskRunner(caller_task_runner,
cert_net_fetcher);
EXPECT_EQ(test_url_loader_factory()->NumPending(), 1);
EXPECT_TRUE(test_url_loader_factory()->IsPending(kMockURL));
EXPECT_TRUE(test_url_loader_factory()->SimulateResponseForPendingRequest(
kMockURL, "", net::HTTP_NOT_FOUND));
EXPECT_EQ(test_reconnector()->num_connects(), 2ul);
// Disconnect the test_url_loader_factory to test reconnection one more time.
test_reconnector()->DisconnectAll();
// Now run the test.
auto request3 = PerformCertNetFetcherRequestOnTaskRunner(caller_task_runner,
cert_net_fetcher);
EXPECT_EQ(test_url_loader_factory()->NumPending(), 1);
EXPECT_TRUE(test_url_loader_factory()->IsPending(kMockURL));
EXPECT_EQ(test_reconnector()->num_connects(), 3ul);
// The test simulated responses for at least the first two requests, so they
// should complete without hanging. The response content is not important, but
// the test sent error responses, so check that net::OK wasn't returned.
// The third request may have attached to a previous job, but cancelling it
// should not cause problems.
{
net::Error error1, error2;
std::vector<uint8_t> bytes1, bytes2;
base::RunLoop run_loop;
caller_task_runner->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
base::ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync;
request1->WaitForResult(&error1, &bytes1);
request2->WaitForResult(&error2, &bytes2);
request3.reset();
run_loop.Quit();
}));
run_loop.Run();
EXPECT_NE(error1, net::OK);
EXPECT_NE(error2, net::OK);
}
cert_net_fetcher->Shutdown();
}
TEST_F(CertVerifierServiceFactoryTest, GetNewCertVerifier) {
base::FilePath certs_dir = net::GetTestCertsDirectory();
scoped_refptr<net::X509Certificate> test_cert(
net::ImportCertFromFile(certs_dir, "ok_cert.pem"));
@ -230,8 +68,6 @@ TEST_F(CertVerifierServiceFactoryTest, GetNewCertVerifier) {
cv_service_factory_remote->GetNewCertVerifier(
cv_service_remote.BindNewPipeAndPassReceiver(),
TakeURLLoaderFactoryPendingRemote(),
test_reconnector_receiver().BindNewPipeAndPassRemote(),
std::move(cv_creation_params));
base::RunLoop request_completed_run_loop;

@ -0,0 +1,3 @@
include_rules = [
"+services/network"
]

@ -0,0 +1,299 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include "base/feature_list.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "net/base/features.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/cert_verifier/cert_verifier_service_factory.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cert_verifier {
namespace {
mojo::PendingRemote<mojom::CertVerifierService> GetNewCertVerifierServiceRemote(
mojom::CertVerifierServiceFactory* cert_verifier_service_factory,
network::mojom::CertVerifierCreationParamsPtr creation_params) {
mojo::PendingRemote<mojom::CertVerifierService> cert_verifier_remote;
cert_verifier_service_factory->GetNewCertVerifier(
cert_verifier_remote.InitWithNewPipeAndPassReceiver(),
std::move(creation_params));
return cert_verifier_remote;
}
} // namespace
class NetworkContextTest : public testing::Test {
public:
explicit NetworkContextTest(
base::test::TaskEnvironment::TimeSource time_source =
base::test::TaskEnvironment::TimeSource::DEFAULT)
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO,
time_source),
network_change_notifier_(
net::NetworkChangeNotifier::CreateMockIfNeeded()),
network_service_(network::NetworkService::CreateForTesting()) {}
~NetworkContextTest() override = default;
std::unique_ptr<network::NetworkContext> CreateContextWithParams(
network::mojom::NetworkContextParamsPtr context_params) {
network_context_remote_.reset();
return std::make_unique<network::NetworkContext>(
network_service_.get(),
network_context_remote_.BindNewPipeAndPassReceiver(),
std::move(context_params));
}
network::mojom::CertVerifierParamsPtr GetCertVerifierParams(
network::mojom::CertVerifierCreationParamsPtr
cert_verifier_creation_params =
network::mojom::CertVerifierCreationParams::New()) {
if (!base::FeatureList::IsEnabled(
network::features::kCertVerifierService)) {
return network::mojom::CertVerifierParams::NewCreationParams(
std::move(cert_verifier_creation_params));
}
if (!cert_verifier_service_factory_) {
cert_verifier_service_factory_ =
std::make_unique<CertVerifierServiceFactoryImpl>(
cert_verifier_service_factory_remote_
.BindNewPipeAndPassReceiver());
}
auto cv_service_remote_params =
network::mojom::CertVerifierServiceRemoteParams::New();
// Create a cert verifier service.
cv_service_remote_params->cert_verifier_service =
GetNewCertVerifierServiceRemote(
cert_verifier_service_factory_.get(),
std::move(cert_verifier_creation_params));
return network::mojom::CertVerifierParams::NewRemoteParams(
std::move(cv_service_remote_params));
}
network::mojom::NetworkService* network_service() const {
return network_service_.get();
}
private:
base::test::TaskEnvironment task_environment_;
std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
std::unique_ptr<network::NetworkService> network_service_;
// Stores the mojo::Remote<NetworkContext> of the most recently created
// NetworkContext. Not strictly needed, but seems best to mimic real-world
// usage.
mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
mojo::Remote<mojom::CertVerifierServiceFactory>
cert_verifier_service_factory_remote_;
std::unique_ptr<mojom::CertVerifierServiceFactory>
cert_verifier_service_factory_;
};
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
namespace {
network::mojom::NetworkContextParamsPtr CreateContextParams() {
network::mojom::NetworkContextParamsPtr params =
network::mojom::NetworkContextParams::New();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
params->initial_proxy_config = net::ProxyConfigWithAnnotation::CreateDirect();
return params;
}
std::unique_ptr<network::TestURLLoaderClient> FetchRequest(
const network::ResourceRequest& request,
network::NetworkContext* network_context,
int url_loader_options = network::mojom::kURLLoadOptionNone,
int process_id = network::mojom::kBrowserProcessId,
network::mojom::URLLoaderFactoryParamsPtr params = nullptr) {
mojo::Remote<network::mojom::URLLoaderFactory> loader_factory;
if (!params)
params = network::mojom::URLLoaderFactoryParams::New();
params->process_id = process_id;
params->is_corb_enabled = false;
// If |site_for_cookies| is null, any non-empty NIK is fine. Otherwise, the
// NIK must be consistent with |site_for_cookies|.
if (request.site_for_cookies.IsNull()) {
params->isolation_info = net::IsolationInfo::Create(
net::IsolationInfo::RedirectMode::kUpdateNothing,
url::Origin::Create(GURL("https://abc.invalid")),
url::Origin::Create(GURL("https://xyz.invalid")),
request.site_for_cookies);
} else {
params->isolation_info = net::IsolationInfo::CreateForInternalRequest(
url::Origin::Create(request.site_for_cookies.RepresentativeUrl()));
}
network_context->CreateURLLoaderFactory(
loader_factory.BindNewPipeAndPassReceiver(), std::move(params));
auto client = std::make_unique<network::TestURLLoaderClient>();
mojo::PendingRemote<network::mojom::URLLoader> loader;
loader_factory->CreateLoaderAndStart(
loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
0 /* request_id */, url_loader_options, request, client->CreateRemote(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
client->RunUntilComplete();
return client;
}
} // namespace
class UseCertVerifierBuiltinTest : public NetworkContextTest,
public testing::WithParamInterface<bool> {
public:
UseCertVerifierBuiltinTest() = default;
~UseCertVerifierBuiltinTest() override = default;
void SetUp() override {
if (GetParam()) {
#if defined(OS_CHROMEOS)
// TODO(crbug.com/1085379): remove this GTEST_SKIP().
GTEST_SKIP() << "Skipping test, CertVerifierService feature not yet "
"available on ChromeOS.";
#else
scoped_feature_list_.InitAndEnableFeature(
network::features::kCertVerifierService);
#endif
} else {
scoped_feature_list_.InitAndDisableFeature(
network::features::kCertVerifierService);
}
NetworkContextTest::SetUp();
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_P(UseCertVerifierBuiltinTest, UseCertVerifierBuiltin) {
net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::test_server::RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
// This just happens to be the only histogram that directly records which
// verifier was used.
const char kBuiltinVerifierHistogram[] =
"Net.CertVerifier.NameNormalizationPrivateRoots.Builtin";
for (bool builtin_verifier_enabled : {false, true}) {
SCOPED_TRACE(builtin_verifier_enabled);
network::mojom::NetworkContextParamsPtr params = CreateContextParams();
auto creation_params = network::mojom::CertVerifierCreationParams::New();
creation_params->use_builtin_cert_verifier =
builtin_verifier_enabled ? network::mojom::CertVerifierCreationParams::
CertVerifierImpl::kBuiltin
: network::mojom::CertVerifierCreationParams::
CertVerifierImpl::kSystem;
params->cert_verifier_params =
GetCertVerifierParams(std::move(creation_params));
std::unique_ptr<network::NetworkContext> network_context =
CreateContextWithParams(std::move(params));
network::ResourceRequest request;
request.url = test_server.GetURL("/nocontent");
base::HistogramTester histogram_tester;
std::unique_ptr<network::TestURLLoaderClient> client =
FetchRequest(request, network_context.get());
EXPECT_EQ(net::OK, client->completion_status().error_code);
histogram_tester.ExpectTotalCount(kBuiltinVerifierHistogram,
builtin_verifier_enabled ? 1 : 0);
}
}
INSTANTIATE_TEST_SUITE_P(All, UseCertVerifierBuiltinTest, ::testing::Bool());
class NetworkContextCertVerifierBuiltinFeatureFlagTest
: public NetworkContextTest,
public testing::WithParamInterface<std::tuple<bool, bool>> {
public:
NetworkContextCertVerifierBuiltinFeatureFlagTest()
: use_builtin_cert_verifier_feature_(std::get<0>(GetParam())),
use_cert_verifier_service_feature_(std::get<1>(GetParam())) {
std::vector<base::Feature> enabled_features, disabled_features;
if (use_builtin_cert_verifier_feature_) {
enabled_features.push_back(net::features::kCertVerifierBuiltinFeature);
} else {
disabled_features.push_back(net::features::kCertVerifierBuiltinFeature);
}
if (use_cert_verifier_service_feature_) {
#if defined(OS_CHROMEOS)
// TODO(crbug.com/1085379): remove this GTEST_SKIP().
GTEST_SKIP() << "Skipping test, CertVerifierService feature not yet "
"available on ChromeOS.";
#else
enabled_features.push_back(network::features::kCertVerifierService);
#endif
} else {
disabled_features.push_back(network::features::kCertVerifierService);
}
scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
}
bool use_builtin_cert_verifier_feature() const {
return use_builtin_cert_verifier_feature_;
}
private:
const bool use_builtin_cert_verifier_feature_;
const bool use_cert_verifier_service_feature_;
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_P(NetworkContextCertVerifierBuiltinFeatureFlagTest,
DefaultNetworkContextParamsUsesCorrectVerifier) {
net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::test_server::RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
// This just happens to be the only histogram that directly records which
// verifier was used.
const char kBuiltinVerifierHistogram[] =
"Net.CertVerifier.NameNormalizationPrivateRoots.Builtin";
// Test creating a NetworkContextParams without specifying a value for
// use_builtin_cert_verifier. Should use whatever the default cert verifier
// implementation is according to the feature flag.
network::mojom::NetworkContextParamsPtr params = CreateContextParams();
params->cert_verifier_params = GetCertVerifierParams();
std::unique_ptr<network::NetworkContext> network_context =
CreateContextWithParams(std::move(params));
network::ResourceRequest request;
request.url = test_server.GetURL("/nocontent");
base::HistogramTester histogram_tester;
std::unique_ptr<network::TestURLLoaderClient> client =
FetchRequest(request, network_context.get());
EXPECT_EQ(net::OK, client->completion_status().error_code);
histogram_tester.ExpectTotalCount(
kBuiltinVerifierHistogram, use_builtin_cert_verifier_feature() ? 1 : 0);
}
INSTANTIATE_TEST_SUITE_P(All,
NetworkContextCertVerifierBuiltinFeatureFlagTest,
::testing::Combine(::testing::Bool(),
::testing::Bool()));
#endif // BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
} // namespace cert_verifier

@ -0,0 +1,485 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/asn1_util.h"
#include "net/cert/test_root_certs.h"
#include "net/cert/x509_util.h"
#include "net/test/cert_test_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/gtest_util.h"
#include "net/test/test_data_directory.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_context.h"
#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"
#include "services/cert_verifier/cert_verifier_service_factory.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/cert_verifier/mojo_cert_verifier.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/ssl_config_service_mojo.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace cert_verifier {
namespace {
const base::FilePath::CharType kServicesTestData[] =
FILE_PATH_LITERAL("services/test/data");
} // namespace
// Base class for any tests that just need a NetworkService and a
// TaskEnvironment, and to create NetworkContexts using the NetworkService.
// Parametrized on whether or not the CertVerifierService feature is enabled.
class NetworkServiceIntegrationTest : public testing::TestWithParam<bool> {
public:
NetworkServiceIntegrationTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
service_(network::NetworkService::CreateForTesting()),
cert_verifier_service_impl_(
cert_verifier_service_remote_.BindNewPipeAndPassReceiver()) {}
~NetworkServiceIntegrationTest() override = default;
void SetUp() override {
if (GetParam()) {
#if defined(OS_CHROMEOS)
// TODO(crbug.com/1085379): remove this GTEST_SKIP().
GTEST_SKIP() << "Skipping test, CertVerifierService feature not yet "
"available on ChromeOS.";
#else
scoped_feature_list_.InitAndEnableFeature(
network::features::kCertVerifierService);
#endif
} else {
scoped_feature_list_.InitAndDisableFeature(
network::features::kCertVerifierService);
}
}
void DestroyService() { service_.reset(); }
network::mojom::NetworkContextParamsPtr CreateNetworkContextParams() {
network::mojom::CertVerifierCreationParamsPtr
cert_verifier_creation_params =
network::mojom::CertVerifierCreationParams::New();
network::mojom::CertVerifierParamsPtr cert_verifier_params;
if (base::FeatureList::IsEnabled(network::features::kCertVerifierService)) {
mojo::PendingRemote<mojom::CertVerifierService> cv_service_remote;
auto cv_service_remote_params =
network::mojom::CertVerifierServiceRemoteParams::New();
// Create a cert verifier service.
cert_verifier_service_impl_.GetNewCertVerifierForTesting(
cv_service_remote.InitWithNewPipeAndPassReceiver(),
std::move(cert_verifier_creation_params),
&cert_net_fetcher_url_loader_);
cv_service_remote_params->cert_verifier_service =
std::move(cv_service_remote);
cert_verifier_params =
network::mojom::CertVerifierParams::NewRemoteParams(
std::move(cv_service_remote_params));
} else {
cert_verifier_params =
network::mojom::CertVerifierParams::NewCreationParams(
std::move(cert_verifier_creation_params));
}
network::mojom::NetworkContextParamsPtr params =
network::mojom::NetworkContextParams::New();
params->cert_verifier_params = std::move(cert_verifier_params);
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
params->initial_proxy_config =
net::ProxyConfigWithAnnotation::CreateDirect();
return params;
}
void CreateNetworkContext(network::mojom::NetworkContextParamsPtr params) {
network_context_ = std::make_unique<network::NetworkContext>(
service_.get(), network_context_remote_.BindNewPipeAndPassReceiver(),
std::move(params));
}
void LoadURL(const GURL& url,
int options = network::mojom::kURLLoadOptionNone) {
network::ResourceRequest request;
request.url = url;
request.method = "GET";
request.request_initiator = url::Origin();
StartLoadingURL(request, 0 /* process_id */, options);
client_->RunUntilComplete();
}
void StartLoadingURL(const network::ResourceRequest& request,
uint32_t process_id,
int options = network::mojom::kURLLoadOptionNone) {
client_ = std::make_unique<network::TestURLLoaderClient>();
mojo::Remote<network::mojom::URLLoaderFactory> loader_factory;
network::mojom::URLLoaderFactoryParamsPtr params =
network::mojom::URLLoaderFactoryParams::New();
params->process_id = process_id;
params->is_corb_enabled = false;
network_context_->CreateURLLoaderFactory(
loader_factory.BindNewPipeAndPassReceiver(), std::move(params));
loader_.reset();
loader_factory->CreateLoaderAndStart(
loader_.BindNewPipeAndPassReceiver(), 1, 1, options, request,
client_->CreateRemote(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
}
network::TestURLLoaderClient* client() { return client_.get(); }
base::test::TaskEnvironment* task_environment() { return &task_environment_; }
network::NetworkService* service() const { return service_.get(); }
network::NetworkContext* network_context() { return network_context_.get(); }
mojo::Remote<network::mojom::NetworkContext>& network_context_remote() {
return network_context_remote_;
}
CertNetFetcherURLLoader* cert_net_fetcher_url_loader() {
return cert_net_fetcher_url_loader_.get();
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
base::test::TaskEnvironment task_environment_;
std::unique_ptr<network::NetworkService> service_;
mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
std::unique_ptr<network::NetworkContext> network_context_;
mojo::Remote<mojom::CertVerifierServiceFactory> cert_verifier_service_remote_;
CertVerifierServiceFactoryImpl cert_verifier_service_impl_;
scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher_url_loader_;
std::unique_ptr<network::TestURLLoaderClient> client_;
mojo::Remote<network::mojom::URLLoader> loader_;
};
// CRLSets are not supported on iOS and Android system verifiers.
#if !defined(OS_IOS) && !defined(OS_ANDROID)
class NetworkServiceCRLSetTest : public NetworkServiceIntegrationTest {
public:
NetworkServiceCRLSetTest()
: test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
~NetworkServiceCRLSetTest() override = default;
void SetUp() override {
NetworkServiceIntegrationTest::SetUp();
test_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
test_server_.AddDefaultHandlers(base::FilePath(kServicesTestData));
ASSERT_TRUE(test_server_.Start());
}
GURL GetURL(std::string url) { return test_server_.GetURL(std::move(url)); }
private:
net::EmbeddedTestServer test_server_;
};
// Verifies CRLSets take effect if configured on the service.
TEST_P(NetworkServiceCRLSetTest, CRLSetIsApplied) {
CreateNetworkContext(CreateNetworkContextParams());
uint32_t options =
network::mojom::kURLLoadOptionSendSSLInfoWithResponse |
network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
// Make sure the test server loads fine with no CRLSet.
LoadURL(GetURL("/echo"), options);
ASSERT_EQ(net::OK, client()->completion_status().error_code);
// Send a CRLSet that blocks the leaf cert.
std::string crl_set_bytes;
EXPECT_TRUE(base::ReadFileToString(
net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
&crl_set_bytes));
{
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
}
// Flush all connections in the context, to force a new connection. A new
// verification should be attempted, due to the configuration having
// changed, thus forcing the CRLSet to be checked.
{
base::RunLoop run_loop;
network_context()->CloseAllConnections(run_loop.QuitClosure());
run_loop.Run();
}
// Make sure the connection fails, due to the certificate being revoked.
LoadURL(GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
}
// Verifies CRLSets configured before creating a new network context are
// applied to that network context.
TEST_P(NetworkServiceCRLSetTest, CRLSetIsPassedToNewContexts) {
// Send a CRLSet that blocks the leaf cert, even while no NetworkContexts
// exist.
std::string crl_set_bytes;
EXPECT_TRUE(base::ReadFileToString(
net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
&crl_set_bytes));
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
// Configure a new NetworkContext.
CreateNetworkContext(CreateNetworkContextParams());
uint32_t options =
network::mojom::kURLLoadOptionSendSSLInfoWithResponse |
network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
// Make sure the connection fails, due to the certificate being revoked.
LoadURL(GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
}
// Verifies newer CRLSets (by sequence number) are applied.
TEST_P(NetworkServiceCRLSetTest, CRLSetIsUpdatedIfNewer) {
// Send a CRLSet that only allows the root cert if it matches a known SPKI
// hash (that matches the test server chain)
std::string crl_set_bytes;
ASSERT_TRUE(base::ReadFileToString(
net::GetTestCertsDirectory().AppendASCII("crlset_by_root_subject.raw"),
&crl_set_bytes));
{
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
}
CreateNetworkContext(CreateNetworkContextParams());
uint32_t options =
network::mojom::kURLLoadOptionSendSSLInfoWithResponse |
network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
// Make sure the connection loads, due to the root being permitted.
LoadURL(GetURL("/echo"), options);
ASSERT_EQ(net::OK, client()->completion_status().error_code);
// Send a new CRLSet that removes trust in the root.
ASSERT_TRUE(base::ReadFileToString(net::GetTestCertsDirectory().AppendASCII(
"crlset_by_root_subject_no_spki.raw"),
&crl_set_bytes));
{
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
}
// Flush all connections in the context, to force a new connection. A new
// verification should be attempted, due to the configuration having
// changed, thus forcing the CRLSet to be checked.
{
base::RunLoop run_loop;
network_context()->CloseAllConnections(run_loop.QuitClosure());
run_loop.Run();
}
// Make sure the connection fails, due to the certificate being revoked.
LoadURL(GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
}
// Verifies that attempting to send an older CRLSet (by sequence number)
// does not apply to existing or new contexts.
TEST_P(NetworkServiceCRLSetTest, CRLSetDoesNotDowngrade) {
// Send a CRLSet that blocks the root certificate by subject name.
std::string crl_set_bytes;
ASSERT_TRUE(base::ReadFileToString(net::GetTestCertsDirectory().AppendASCII(
"crlset_by_root_subject_no_spki.raw"),
&crl_set_bytes));
{
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
}
CreateNetworkContext(CreateNetworkContextParams());
uint32_t options =
network::mojom::kURLLoadOptionSendSSLInfoWithResponse |
network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
// Make sure the connection fails, due to the certificate being revoked.
LoadURL(GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
// Attempt to configure an older CRLSet that allowed trust in the root.
ASSERT_TRUE(base::ReadFileToString(
net::GetTestCertsDirectory().AppendASCII("crlset_by_root_subject.raw"),
&crl_set_bytes));
{
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
}
// Flush all connections in the context, to force a new connection. A new
// verification should be attempted, due to the configuration having
// changed, thus forcing the CRLSet to be checked.
{
base::RunLoop run_loop;
network_context()->CloseAllConnections(run_loop.QuitClosure());
run_loop.Run();
}
// Make sure the connection still fails, due to the newer CRLSet still
// applying.
LoadURL(GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
// Create a new NetworkContext and ensure the latest CRLSet is still
// applied.
network_context_remote().reset();
CreateNetworkContext(CreateNetworkContextParams());
// The newer CRLSet that blocks the connection should still apply, even to
// new NetworkContexts.
LoadURL(GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
}
INSTANTIATE_TEST_SUITE_P(All, NetworkServiceCRLSetTest, ::testing::Bool());
#endif // !defined(OS_IOS) && !defined(OS_ANDROID)
// TODO(crbug.com/860189): AIA tests fail on iOS
#if defined(OS_IOS)
#define MAYBE(test_name) DISABLED_##test_name
#else
#define MAYBE(test_name) test_name
#endif
class NetworkServiceAIATest : public NetworkServiceIntegrationTest {
public:
NetworkServiceAIATest() : test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
~NetworkServiceAIATest() override = default;
void SetUp() override {
NetworkServiceIntegrationTest::SetUp();
network::mojom::NetworkContextParamsPtr context_params =
CreateNetworkContextParams();
CreateNetworkContext(std::move(context_params));
net::EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.intermediate =
net::EmbeddedTestServer::IntermediateType::kByAIA;
test_server_.SetSSLConfig(cert_config);
test_server_.AddDefaultHandlers(base::FilePath(kServicesTestData));
ASSERT_TRUE(test_server_.Start());
}
void PerformAIATest() {
LoadURL(test_server_.GetURL("/echo"),
network::mojom::kURLLoadOptionSendSSLInfoWithResponse);
EXPECT_EQ(net::OK, client()->completion_status().error_code);
ASSERT_TRUE(client()->response_head());
EXPECT_EQ(0u, client()->response_head()->cert_status &
net::CERT_STATUS_ALL_ERRORS);
ASSERT_TRUE(client()->ssl_info());
ASSERT_TRUE(client()->ssl_info()->cert);
EXPECT_EQ(2u, client()->ssl_info()->cert->intermediate_buffers().size());
ASSERT_TRUE(client()->ssl_info()->unverified_cert);
EXPECT_EQ(
0u,
client()->ssl_info()->unverified_cert->intermediate_buffers().size());
}
private:
net::EmbeddedTestServer test_server_;
};
TEST_P(NetworkServiceAIATest, MAYBE(AIAFetching)) {
PerformAIATest();
}
// Check that AIA fetching still succeeds even after the URLLoaderFactory
// backing the CertNetFetcherURLLoader disconnects.
// Only relevant if testing with the CertVerifierService, and the underlying
// CertVerifier uses the CertNetFetcher.
TEST_P(NetworkServiceAIATest,
MAYBE(AIAFetchingWithURLLoaderFactoryDisconnect)) {
if (!base::FeatureList::IsEnabled(network::features::kCertVerifierService) ||
!cert_net_fetcher_url_loader()) {
// TODO(crbug.com/1015706): Switch to GTEST_SKIP().
LOG(WARNING) << "Skipping AIA reconnection test because the underlying "
"cert verifier does not use a CertNetFetcherURLLoader.";
return;
}
PerformAIATest();
// Disconnect the URLLoaderFactory used by the CertNetFetcherURLLoader.
cert_net_fetcher_url_loader()->DisconnectURLLoaderFactoryForTesting();
// Try running the test again to test reconnection of the
// CertNetFetcherURLLoader.
PerformAIATest();
// Repeat one more time to be sure.
cert_net_fetcher_url_loader()->DisconnectURLLoaderFactoryForTesting();
PerformAIATest();
}
INSTANTIATE_TEST_SUITE_P(All, NetworkServiceAIATest, ::testing::Bool());
} // namespace cert_verifier

@ -0,0 +1,207 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include "base/files/file_util.h"
#include "base/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/test_root_certs.h"
#include "net/cert/x509_util.h"
#include "net/test/cert_test_util.h"
#include "net/test/gtest_util.h"
#include "net/test/test_data_directory.h"
#include "net/url_request/url_request_context.h"
#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"
#include "services/cert_verifier/cert_verifier_service_factory.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/ssl_config_service_mojo.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cert_verifier {
// Base class for any tests that just need a NetworkService and a
// TaskEnvironment, and to create NetworkContexts using the NetworkService.
class SSLConfigServiceMojoTestWithCertVerifier
: public testing::TestWithParam<bool> {
public:
SSLConfigServiceMojoTestWithCertVerifier()
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
service_(network::NetworkService::CreateForTesting()),
cert_verifier_service_impl_(
cert_verifier_service_remote_.BindNewPipeAndPassReceiver()) {}
~SSLConfigServiceMojoTestWithCertVerifier() override = default;
void SetUp() override {
if (GetParam()) {
#if defined(OS_CHROMEOS)
// TODO(crbug.com/1085379): remove this GTEST_SKIP().
GTEST_SKIP() << "Skipping test, CertVerifierService feature not yet "
"available on ChromeOS.";
#else
scoped_feature_list_.InitAndEnableFeature(
network::features::kCertVerifierService);
#endif
} else {
scoped_feature_list_.InitAndDisableFeature(
network::features::kCertVerifierService);
}
}
void DestroyService() { service_.reset(); }
network::mojom::NetworkContextParamsPtr CreateNetworkContextParams() {
network::mojom::CertVerifierCreationParamsPtr
cert_verifier_creation_params =
network::mojom::CertVerifierCreationParams::New();
network::mojom::CertVerifierParamsPtr cert_verifier_params;
if (base::FeatureList::IsEnabled(network::features::kCertVerifierService)) {
mojo::PendingRemote<mojom::CertVerifierService> cv_service_remote;
auto cv_service_remote_params =
network::mojom::CertVerifierServiceRemoteParams::New();
// Create a cert verifier service.
cert_verifier_service_impl_.GetNewCertVerifierForTesting(
cv_service_remote.InitWithNewPipeAndPassReceiver(),
std::move(cert_verifier_creation_params),
&cert_net_fetcher_url_loader_);
cv_service_remote_params->cert_verifier_service =
std::move(cv_service_remote);
cert_verifier_params =
network::mojom::CertVerifierParams::NewRemoteParams(
std::move(cv_service_remote_params));
} else {
cert_verifier_params =
network::mojom::CertVerifierParams::NewCreationParams(
std::move(cert_verifier_creation_params));
}
network::mojom::NetworkContextParamsPtr params =
network::mojom::NetworkContextParams::New();
params->cert_verifier_params = std::move(cert_verifier_params);
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
params->initial_proxy_config =
net::ProxyConfigWithAnnotation::CreateDirect();
return params;
}
void CreateNetworkContext(network::mojom::NetworkContextParamsPtr params) {
network_context_ = std::make_unique<network::NetworkContext>(
service_.get(), network_context_remote_.BindNewPipeAndPassReceiver(),
std::move(params));
}
base::test::TaskEnvironment* task_environment() { return &task_environment_; }
network::NetworkService* service() const { return service_.get(); }
network::NetworkContext* network_context() { return network_context_.get(); }
mojo::Remote<network::mojom::NetworkContext>& network_context_remote() {
return network_context_remote_;
}
CertNetFetcherURLLoader* cert_net_fetcher_url_loader() {
return cert_net_fetcher_url_loader_.get();
}
private:
base::test::TaskEnvironment task_environment_;
std::unique_ptr<network::NetworkService> service_;
base::test::ScopedFeatureList scoped_feature_list_;
mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
std::unique_ptr<network::NetworkContext> network_context_;
mojo::Remote<mojom::CertVerifierServiceFactory> cert_verifier_service_remote_;
CertVerifierServiceFactoryImpl cert_verifier_service_impl_;
scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher_url_loader_;
};
#if !defined(OS_IOS) && !defined(OS_ANDROID)
TEST_P(SSLConfigServiceMojoTestWithCertVerifier, CRLSetIsApplied) {
mojo::Remote<network::mojom::SSLConfigClient> ssl_config_client;
network::mojom::NetworkContextParamsPtr context_params =
CreateNetworkContextParams();
context_params->ssl_config_client_receiver =
ssl_config_client.BindNewPipeAndPassReceiver();
CreateNetworkContext(std::move(context_params));
network::SSLConfigServiceMojo* config_service =
static_cast<network::SSLConfigServiceMojo*>(
network_context()->url_request_context()->ssl_config_service());
scoped_refptr<net::X509Certificate> root_cert =
net::CreateCertificateChainFromFile(
net::GetTestCertsDirectory(), "root_ca_cert.pem",
net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
ASSERT_TRUE(root_cert);
net::ScopedTestRoot test_root(root_cert.get());
scoped_refptr<net::X509Certificate> leaf_cert =
net::CreateCertificateChainFromFile(
net::GetTestCertsDirectory(), "ok_cert.pem",
net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
ASSERT_TRUE(leaf_cert);
// Ensure that |leaf_cert| is trusted without any CRLSet explicitly
// configured.
net::TestCompletionCallback callback1;
net::CertVerifyResult cert_verify_result1;
std::unique_ptr<net::CertVerifier::Request> request1;
int result =
network_context()->url_request_context()->cert_verifier()->Verify(
net::CertVerifier::RequestParams(leaf_cert, "127.0.0.1",
/*flags=*/0,
/*ocsp_response=*/std::string(),
/*sct_list=*/std::string()),
&cert_verify_result1, callback1.callback(), &request1,
net::NetLogWithSource());
ASSERT_THAT(callback1.GetResult(result), net::test::IsOk());
// Load a CRLSet that removes trust in |leaf_cert| by SPKI.
scoped_refptr<net::CRLSet> crl_set;
std::string crl_set_bytes;
ASSERT_TRUE(base::ReadFileToString(
net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
&crl_set_bytes));
ASSERT_TRUE(net::CRLSet::ParseAndStoreUnparsedData(crl_set_bytes, &crl_set));
config_service->OnNewCRLSet(crl_set);
// Ensure that |leaf_cert| is revoked, due to the CRLSet being applied.
net::TestCompletionCallback callback2;
net::CertVerifyResult cert_verify_result2;
std::unique_ptr<net::CertVerifier::Request> request2;
result = network_context()->url_request_context()->cert_verifier()->Verify(
net::CertVerifier::RequestParams(leaf_cert, "127.0.0.1",
/*flags=*/0,
/*ocsp_response=*/std::string(),
/*sct_list=*/std::string()),
&cert_verify_result2, callback2.callback(), &request2,
net::NetLogWithSource());
ASSERT_THAT(callback2.GetResult(result),
net::test::IsError(net::ERR_CERT_REVOKED));
}
INSTANTIATE_TEST_SUITE_P(All,
SSLConfigServiceMojoTestWithCertVerifier,
::testing::Bool());
#endif // !defined(OS_IOS) && !defined(OS_ANDROID)
} // namespace cert_verifier

@ -15,19 +15,5 @@ interface CertVerifierServiceFactory {
// Gets a new CertVerifierFactory, which //net code can interface with using
// cert_verifier::MojoCertVerifier.
GetNewCertVerifier(pending_receiver<CertVerifierService> receiver,
pending_remote<network.mojom.URLLoaderFactory>?
cert_net_fetcher_url_loader_factory,
pending_remote<URLLoaderFactoryConnector>?
cert_net_fetcher_url_loader_factory_connector,
network.mojom.CertVerifierCreationParams? creation_params);
};
// Allows the CertVerifierService to connect a new URLLoaderFactory if its
// existing URLLoaderFactory is disconnected. The CertVerifierService uses the
// URLLoaderFactory for AIA and OCSP fetching.
interface URLLoaderFactoryConnector {
// Binds a URLLoaderFactory. The implementer of this interface is in charge
// of choosing the URLLoaderFactoryParams.
CreateURLLoaderFactory(
pending_receiver<network.mojom.URLLoaderFactory> url_loader_factory);
};

@ -32,9 +32,6 @@ TestCertVerifierServiceFactoryImpl::~TestCertVerifierServiceFactoryImpl() =
void TestCertVerifierServiceFactoryImpl::GetNewCertVerifier(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
cert_net_fetcher_url_loader_factory_connector,
network::mojom::CertVerifierCreationParamsPtr creation_params) {
if (!delegate_) {
InitDelegate();
@ -42,9 +39,6 @@ void TestCertVerifierServiceFactoryImpl::GetNewCertVerifier(
GetNewCertVerifierParams params;
params.receiver = std::move(receiver);
params.url_loader_factory = std::move(url_loader_factory);
params.cert_net_fetcher_url_loader_factory_connector =
std::move(cert_net_fetcher_url_loader_factory_connector);
params.creation_params = std::move(creation_params);
captured_params_.push_front(std::move(params));
@ -60,10 +54,8 @@ void TestCertVerifierServiceFactoryImpl::ReleaseNextCertVerifierParams() {
DCHECK(delegate_);
GetNewCertVerifierParams params = std::move(captured_params_.back());
captured_params_.pop_back();
delegate_remote_->GetNewCertVerifier(
std::move(params.receiver), std::move(params.url_loader_factory),
std::move(params.cert_net_fetcher_url_loader_factory_connector),
std::move(params.creation_params));
delegate_remote_->GetNewCertVerifier(std::move(params.receiver),
std::move(params.creation_params));
}
void TestCertVerifierServiceFactoryImpl::InitDelegate() {

@ -38,18 +38,12 @@ class TestCertVerifierServiceFactoryImpl
~GetNewCertVerifierParams();
mojo::PendingReceiver<mojom::CertVerifierService> receiver;
mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory;
mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
cert_net_fetcher_url_loader_factory_connector;
network::mojom::CertVerifierCreationParamsPtr creation_params;
};
// mojom::CertVerifierServiceFactory implementation:
void GetNewCertVerifier(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
cert_net_fetcher_url_loader_factory_connector,
network::mojom::CertVerifierCreationParamsPtr creation_params) override;
// Pops the first request off the back of the list and forwards it to the

@ -417,6 +417,8 @@ jumbo_source_set("test_support") {
sources = [
"mojo_socket_test_util.cc",
"mojo_socket_test_util.h",
"test/fake_test_cert_verifier_params_factory.cc",
"test/fake_test_cert_verifier_params_factory.h",
"test/test_cookie_manager.cc",
"test/test_cookie_manager.h",
"test/test_data_pipe_getter.cc",

@ -21,6 +21,7 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/resource_scheduler/resource_scheduler.h"
#include "services/network/resource_scheduler/resource_scheduler_client.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@ -54,6 +55,10 @@ class CorsURLLoaderFactoryTest : public testing::Test {
network_service_ = NetworkService::CreateForTesting();
auto context_params = mojom::NetworkContextParams::New();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
context_params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
context_params->initial_proxy_config =

@ -39,6 +39,7 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/resource_scheduler/resource_scheduler.h"
#include "services/network/resource_scheduler/resource_scheduler_client.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_url_loader_client.h"
#include "services/network/url_loader.h"
#include "testing/gmock/include/gmock/gmock.h"
@ -162,6 +163,12 @@ class CorsURLLoaderTest : public testing::Test {
network_service_ = NetworkService::CreateForTesting();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
context_params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
context_params->initial_proxy_config =
net::ProxyConfigWithAnnotation::CreateDirect();
context_params->cors_exempt_header_list.push_back(kTestCorsExemptHeader);

@ -21,8 +21,10 @@
#include "services/network/cors/cors_url_loader_factory.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_network_service_client.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -347,9 +349,14 @@ class PreflightControllerTest : public testing::Test {
network_service_ = NetworkService::Create(
network_service_remote.BindNewPipeAndPassReceiver());
auto context_params = mojom::NetworkContextParams::New();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
context_params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
network_service_remote->CreateNetworkContext(
network_context_remote_.BindNewPipeAndPassReceiver(),
mojom::NetworkContextParams::New());
std::move(context_params));
network::mojom::URLLoaderFactoryParamsPtr params =
network::mojom::URLLoaderFactoryParams::New();

@ -8,10 +8,12 @@
#include "base/bind.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/location.h"
#include "base/strings/string_piece.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "services/network/public/cpp/features.h"
namespace network {
@ -21,8 +23,13 @@ namespace {
// CRLSet.
scoped_refptr<net::CRLSet> ParseCRLSet(std::string crl_set) {
scoped_refptr<net::CRLSet> result;
if (!net::CRLSet::Parse(crl_set, &result))
return nullptr;
if (base::FeatureList::IsEnabled(network::features::kCertVerifierService)) {
if (!net::CRLSet::ParseAndStoreUnparsedData(std::move(crl_set), &result))
return nullptr;
} else {
if (!net::CRLSet::Parse(std::move(crl_set), &result))
return nullptr;
}
return result;
}

@ -30,6 +30,7 @@
#include "net/url_request/url_request_context.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
@ -54,6 +55,10 @@ constexpr CacheTestEntry kCacheEntries[] = {
mojom::NetworkContextParamsPtr CreateContextParams() {
mojom::NetworkContextParamsPtr params = mojom::NetworkContextParams::New();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
params->initial_proxy_config = net::ProxyConfigWithAnnotation::CreateDirect();

@ -29,6 +29,7 @@
#include "net/url_request/url_request_context_builder.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
@ -61,6 +62,10 @@ constexpr CacheTestEntry kCacheEntries[] = {
mojom::NetworkContextParamsPtr CreateContextParams() {
mojom::NetworkContextParamsPtr params = mojom::NetworkContextParams::New();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
params->initial_proxy_config = net::ProxyConfigWithAnnotation::CreateDirect();

@ -39,6 +39,7 @@
#include "components/prefs/pref_service.h"
#include "components/prefs/pref_service_factory.h"
#include "crypto/sha2.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/network_delegate.h"
@ -86,11 +87,14 @@
#include "services/network/proxy_lookup_request.h"
#include "services/network/proxy_resolving_socket_factory_mojo.h"
#include "services/network/public/cpp/cert_verifier/cert_verifier_creation.h"
#include "services/network/public/cpp/cert_verifier/mojo_cert_verifier.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/cpp/parsed_headers.h"
#include "services/network/public/mojom/network_context.mojom-forward.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/quic_transport.h"
#include "services/network/resolve_host_request.h"
#include "services/network/resource_scheduler/resource_scheduler_client.h"
@ -345,7 +349,15 @@ NetworkContext::NetworkContext(
cors_preflight_controller_(
params_->cors_extra_safelisted_request_header_names,
network_service) {
url_request_context_owner_ = MakeURLRequestContext();
mojo::PendingRemote<mojom::URLLoaderFactory>
url_loader_factory_for_cert_net_fetcher;
mojo::PendingReceiver<mojom::URLLoaderFactory>
url_loader_factory_for_cert_net_fetcher_receiver =
url_loader_factory_for_cert_net_fetcher
.InitWithNewPipeAndPassReceiver();
url_request_context_owner_ =
MakeURLRequestContext(std::move(url_loader_factory_for_cert_net_fetcher));
url_request_context_ = url_request_context_owner_.url_request_context.get();
network_service_->RegisterNetworkContext(this);
@ -383,6 +395,9 @@ NetworkContext::NetworkContext(
if (params_->cookie_manager)
GetCookieManager(std::move(params_->cookie_manager));
#endif
CreateURLLoaderFactoryForCertNetFetcher(
std::move(url_loader_factory_for_cert_net_fetcher_receiver));
}
NetworkContext::NetworkContext(
@ -463,6 +478,7 @@ NetworkContext::~NetworkContext() {
}
}
// static
void NetworkContext::SetCertVerifierForTesting(
net::CertVerifier* cert_verifier) {
g_cert_verifier_for_testing = cert_verifier;
@ -477,6 +493,18 @@ void NetworkContext::CreateURLLoaderFactory(
std::move(receiver), &cors_origin_access_list_));
}
void NetworkContext::CreateURLLoaderFactoryForCertNetFetcher(
mojo::PendingReceiver<mojom::URLLoaderFactory> factory_receiver) {
// TODO(crbug.com/1087790): investigate changing these params.
auto url_loader_factory_params = mojom::URLLoaderFactoryParams::New();
url_loader_factory_params->is_trusted = true;
url_loader_factory_params->process_id = mojom::kBrowserProcessId;
url_loader_factory_params->automatically_assign_isolation_info = true;
url_loader_factory_params->is_corb_enabled = false;
CreateURLLoaderFactory(std::move(factory_receiver),
std::move(url_loader_factory_params));
}
void NetworkContext::ActivateDohProbes() {
DCHECK(url_request_context_->host_resolver());
@ -942,8 +970,12 @@ void NetworkContext::SetEnableReferrers(bool enable_referrers) {
void NetworkContext::UpdateAdditionalCertificates(
mojom::AdditionalCertificatesPtr additional_certificates) {
if (!cert_verifier_with_trust_anchors_) {
CHECK(g_cert_verifier_for_testing ||
params_->cert_verifier_creation_params->username_hash.empty());
// TODO(crbug.com/1085379): include this CHECK somewhere in the
// CertVerifierService when it's launched on ChromeOS.
CHECK(g_cert_verifier_for_testing || !params_->cert_verifier_params ||
params_->cert_verifier_params->is_remote_params() ||
params_->cert_verifier_params->get_creation_params()
->username_hash.empty());
return;
}
if (!additional_certificates) {
@ -1674,26 +1706,61 @@ void NetworkContext::OnHttpAuthDynamicParamsChanged(
#endif
}
URLRequestContextOwner NetworkContext::MakeURLRequestContext() {
URLRequestContextOwner NetworkContext::MakeURLRequestContext(
mojo::PendingRemote<mojom::URLLoaderFactory>
url_loader_factory_for_cert_net_fetcher) {
URLRequestContextBuilderMojo builder;
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
DCHECK(
g_cert_verifier_for_testing ||
!base::FeatureList::IsEnabled(network::features::kCertVerifierService) ||
(params_->cert_verifier_params &&
params_->cert_verifier_params->is_remote_params()))
<< "If cert verification service is on, the creator of the "
"NetworkContext should pass CertVerifierServiceRemoteParams.";
std::unique_ptr<net::CertVerifier> cert_verifier;
if (g_cert_verifier_for_testing) {
cert_verifier = std::make_unique<WrappedTestingCertVerifier>();
} else {
mojom::CertVerifierCreationParams* creation_params = nullptr;
if (params_->cert_verifier_creation_params)
creation_params = params_->cert_verifier_creation_params.get();
if (params_->cert_verifier_params &&
params_->cert_verifier_params->is_remote_params()) {
#if defined(OS_CHROMEOS)
DLOG(FATAL) << "Servicified cert verifier not yet supported on ChromeOS.";
CHECK(false);
#endif
if (IsUsingCertNetFetcher())
cert_net_fetcher_ = base::MakeRefCounted<net::CertNetFetcherURLRequest>();
// base::Unretained() is safe below because |this| will own
// |cert_verifier|.
// TODO(https://crbug.com/1085233): this cert verifier should deal with
// disconnections if the CertVerifierService is run outside of the browser
// process.
cert_verifier = std::make_unique<cert_verifier::MojoCertVerifier>(
std::move(params_->cert_verifier_params->get_remote_params()
->cert_verifier_service),
std::move(url_loader_factory_for_cert_net_fetcher),
base::BindRepeating(
&NetworkContext::CreateURLLoaderFactoryForCertNetFetcher,
base::Unretained(this)));
} else {
mojom::CertVerifierCreationParams* creation_params = nullptr;
if (params_->cert_verifier_params &&
params_->cert_verifier_params->is_creation_params()) {
creation_params =
params_->cert_verifier_params->get_creation_params().get();
}
cert_verifier = CreateCertVerifier(creation_params, cert_net_fetcher_);
if (IsUsingCertNetFetcher())
cert_net_fetcher_ =
base::MakeRefCounted<net::CertNetFetcherURLRequest>();
// Wrap the cert verifier in caching and coalescing layers to avoid extra
// verifications.
cert_verifier = CreateCertVerifier(creation_params, cert_net_fetcher_);
}
// Whether the cert verifier is remote or in-process, we should wrap it in
// caching and coalescing layers to avoid extra verifications and IPCs.
cert_verifier = std::make_unique<net::CachingCertVerifier>(
std::make_unique<net::CoalescingCertVerifier>(
std::move(cert_verifier)));

@ -172,6 +172,14 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
mojom::URLLoaderFactoryParamsPtr params,
scoped_refptr<ResourceSchedulerClient> resource_scheduler_client);
// Creates a URLLoaderFactory with params specific to the
// CertVerifierService. A URLLoaderFactory created by this function will be
// used by a CertNetFetcherURLLoader to perform AIA and OCSP fetching.
// These URLLoaderFactories should only ever be used by the
// CertVerifierService, and should never be passed to a renderer.
void CreateURLLoaderFactoryForCertNetFetcher(
mojo::PendingReceiver<mojom::URLLoaderFactory> factory_receiver);
// Enables DoH probes to be sent using this context whenever the DNS
// configuration contains DoH servers.
void ActivateDohProbes();
@ -484,7 +492,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
}
private:
URLRequestContextOwner MakeURLRequestContext();
URLRequestContextOwner MakeURLRequestContext(
mojo::PendingRemote<mojom::URLLoaderFactory>
url_loader_factory_for_cert_net_fetcher);
// Invoked when the HTTP cache was cleared. Invokes |callback|.
void OnHttpCacheCleared(ClearHttpCacheCallback callback,
@ -644,7 +654,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
#endif
// CertNetFetcher used by the context's CertVerifier. May be nullptr if
// CertNetFetcher is not used by the current platform.
// CertNetFetcher is not used by the current platform, or if the actual
// net::CertVerifier is instantiated outside of the network service.
scoped_refptr<net::CertNetFetcherURLRequest> cert_net_fetcher_;
// Created on-demand. Null if unused.

@ -118,6 +118,7 @@
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/proxy_config.mojom.h"
#include "services/network/public/mojom/url_loader.mojom-shared.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_url_loader_client.h"
#include "services/network/trust_tokens/pending_trust_token_store.h"
#include "services/network/trust_tokens/trust_token_parameterization.h"
@ -392,6 +393,11 @@ class NetworkContextTest : public testing::Test {
std::unique_ptr<NetworkContext> CreateContextWithParams(
mojom::NetworkContextParamsPtr context_params) {
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
DCHECK(!context_params->cert_verifier_params);
context_params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
network_context_remote_.reset();
return std::make_unique<NetworkContext>(
network_service_.get(),
@ -6144,87 +6150,6 @@ TEST_F(NetworkContextTest, FactoriesDeletedWhenBindingsCleared) {
EXPECT_EQ(network_context->num_url_loader_factories_for_testing(), 0u);
}
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
TEST_F(NetworkContextTest, UseCertVerifierBuiltin) {
net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::test_server::RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
// This just happens to be the only histogram that directly records which
// verifier was used.
const char kBuiltinVerifierHistogram[] =
"Net.CertVerifier.NameNormalizationPrivateRoots.Builtin";
for (bool builtin_verifier_enabled : {false, true}) {
SCOPED_TRACE(builtin_verifier_enabled);
mojom::NetworkContextParamsPtr params = CreateContextParams();
auto creation_params = mojom::CertVerifierCreationParams::New();
creation_params->use_builtin_cert_verifier =
builtin_verifier_enabled
? mojom::CertVerifierCreationParams::CertVerifierImpl::kBuiltin
: mojom::CertVerifierCreationParams::CertVerifierImpl::kSystem;
params->cert_verifier_creation_params = std::move(creation_params);
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(params));
ResourceRequest request;
request.url = test_server.GetURL("/nocontent");
base::HistogramTester histogram_tester;
std::unique_ptr<TestURLLoaderClient> client =
FetchRequest(request, network_context.get());
EXPECT_EQ(net::OK, client->completion_status().error_code);
histogram_tester.ExpectTotalCount(kBuiltinVerifierHistogram,
builtin_verifier_enabled ? 1 : 0);
}
}
class NetworkContextCertVerifierBuiltinFeatureFlagTest
: public NetworkContextTest,
public testing::WithParamInterface<bool> {
public:
NetworkContextCertVerifierBuiltinFeatureFlagTest() {
scoped_feature_list_.InitWithFeatureState(
net::features::kCertVerifierBuiltinFeature,
/*enabled=*/GetParam());
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_P(NetworkContextCertVerifierBuiltinFeatureFlagTest,
DefaultNetworkContextParamsUsesCorrectVerifier) {
net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::test_server::RegisterDefaultHandlers(&test_server);
ASSERT_TRUE(test_server.Start());
// This just happens to be the only histogram that directly records which
// verifier was used.
const char kBuiltinVerifierHistogram[] =
"Net.CertVerifier.NameNormalizationPrivateRoots.Builtin";
// Test creating a NetworkContextParams without specifying a value for
// use_builtin_cert_verifier. Should use whatever the default cert verifier
// implementation is according to the feature flag.
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(CreateContextParams());
ResourceRequest request;
request.url = test_server.GetURL("/nocontent");
base::HistogramTester histogram_tester;
std::unique_ptr<TestURLLoaderClient> client =
FetchRequest(request, network_context.get());
EXPECT_EQ(net::OK, client->completion_status().error_code);
histogram_tester.ExpectTotalCount(kBuiltinVerifierHistogram,
GetParam() ? 1 : 0);
}
INSTANTIATE_TEST_SUITE_P(All,
NetworkContextCertVerifierBuiltinFeatureFlagTest,
::testing::Bool());
#endif // BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
static ResourceRequest CreateResourceRequest(const char* method,
const GURL& url) {
ResourceRequest request;

@ -56,6 +56,7 @@
#include "services/network/public/mojom/network_change_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_network_context_client.h"
#include "services/network/test/test_network_service_client.h"
#include "services/network/test/test_url_loader_client.h"
@ -83,6 +84,10 @@ GURL AddQuery(const GURL& url,
mojom::NetworkContextParamsPtr CreateContextParams() {
mojom::NetworkContextParamsPtr params = mojom::NetworkContextParams::New();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
params->initial_proxy_config = net::ProxyConfigWithAnnotation::CreateDirect();
@ -904,6 +909,10 @@ class NetworkServiceTestWithService : public testing::Test {
void CreateNetworkContext() {
mojom::NetworkContextParamsPtr context_params =
mojom::NetworkContextParams::New();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
context_params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
network_service_->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(),
std::move(context_params));
@ -1230,261 +1239,6 @@ TEST_F(NetworkServiceTestWithService, SetsTrustTokenKeyCommitments) {
EXPECT_TRUE(result.Equals(expectation));
}
// CRLSets are not supported on iOS and Android system verifiers.
#if !defined(OS_IOS) && !defined(OS_ANDROID)
// Verifies CRLSets take effect if configured on the service.
TEST_F(NetworkServiceTestWithService, CRLSetIsApplied) {
net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
test_server.AddDefaultHandlers(base::FilePath(kServicesTestData));
ASSERT_TRUE(test_server.Start());
CreateNetworkContext();
uint32_t options = mojom::kURLLoadOptionSendSSLInfoWithResponse |
mojom::kURLLoadOptionSendSSLInfoForCertificateError;
// Make sure the test server loads fine with no CRLSet.
LoadURL(test_server.GetURL("/echo"), options);
ASSERT_EQ(net::OK, client()->completion_status().error_code);
// Send a CRLSet that blocks the leaf cert.
std::string crl_set_bytes;
EXPECT_TRUE(base::ReadFileToString(
net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
&crl_set_bytes));
{
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
}
// Flush all connections in the context, to force a new connection. A new
// verification should be attempted, due to the configuration having
// changed, thus forcing the CRLSet to be checked.
{
base::RunLoop run_loop;
context()->CloseAllConnections(run_loop.QuitClosure());
run_loop.Run();
}
// Make sure the connection fails, due to the certificate being revoked.
LoadURL(test_server.GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
}
// Verifies CRLSets configured before creating a new network context are
// applied to that network context.
TEST_F(NetworkServiceTestWithService, CRLSetIsPassedToNewContexts) {
net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
test_server.AddDefaultHandlers(base::FilePath(kServicesTestData));
ASSERT_TRUE(test_server.Start());
// Send a CRLSet that blocks the leaf cert, even while no NetworkContexts
// exist.
std::string crl_set_bytes;
EXPECT_TRUE(base::ReadFileToString(
net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
&crl_set_bytes));
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
// Configure a new NetworkContext.
CreateNetworkContext();
uint32_t options = mojom::kURLLoadOptionSendSSLInfoWithResponse |
mojom::kURLLoadOptionSendSSLInfoForCertificateError;
// Make sure the connection fails, due to the certificate being revoked.
LoadURL(test_server.GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
}
// Verifies newer CRLSets (by sequence number) are applied.
TEST_F(NetworkServiceTestWithService, CRLSetIsUpdatedIfNewer) {
net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
test_server.AddDefaultHandlers(base::FilePath(kServicesTestData));
ASSERT_TRUE(test_server.Start());
// Send a CRLSet that only allows the root cert if it matches a known SPKI
// hash (that matches the test server chain)
std::string crl_set_bytes;
ASSERT_TRUE(base::ReadFileToString(
net::GetTestCertsDirectory().AppendASCII("crlset_by_root_subject.raw"),
&crl_set_bytes));
{
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
}
CreateNetworkContext();
uint32_t options = mojom::kURLLoadOptionSendSSLInfoWithResponse |
mojom::kURLLoadOptionSendSSLInfoForCertificateError;
// Make sure the connection loads, due to the root being permitted.
LoadURL(test_server.GetURL("/echo"), options);
ASSERT_EQ(net::OK, client()->completion_status().error_code);
// Send a new CRLSet that removes trust in the root.
ASSERT_TRUE(base::ReadFileToString(net::GetTestCertsDirectory().AppendASCII(
"crlset_by_root_subject_no_spki.raw"),
&crl_set_bytes));
{
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
}
// Flush all connections in the context, to force a new connection. A new
// verification should be attempted, due to the configuration having
// changed, thus forcing the CRLSet to be checked.
{
base::RunLoop run_loop;
context()->CloseAllConnections(run_loop.QuitClosure());
run_loop.Run();
}
// Make sure the connection fails, due to the certificate being revoked.
LoadURL(test_server.GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
}
// Verifies that attempting to send an older CRLSet (by sequence number)
// does not apply to existing or new contexts.
TEST_F(NetworkServiceTestWithService, CRLSetDoesNotDowngrade) {
net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
test_server.AddDefaultHandlers(base::FilePath(kServicesTestData));
ASSERT_TRUE(test_server.Start());
// Send a CRLSet that blocks the root certificate by subject name.
std::string crl_set_bytes;
ASSERT_TRUE(base::ReadFileToString(net::GetTestCertsDirectory().AppendASCII(
"crlset_by_root_subject_no_spki.raw"),
&crl_set_bytes));
{
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
}
CreateNetworkContext();
uint32_t options = mojom::kURLLoadOptionSendSSLInfoWithResponse |
mojom::kURLLoadOptionSendSSLInfoForCertificateError;
// Make sure the connection fails, due to the certificate being revoked.
LoadURL(test_server.GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
// Attempt to configure an older CRLSet that allowed trust in the root.
ASSERT_TRUE(base::ReadFileToString(
net::GetTestCertsDirectory().AppendASCII("crlset_by_root_subject.raw"),
&crl_set_bytes));
{
base::RunLoop run_loop;
service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
run_loop.QuitClosure());
run_loop.Run();
}
// Flush all connections in the context, to force a new connection. A new
// verification should be attempted, due to the configuration having
// changed, thus forcing the CRLSet to be checked.
{
base::RunLoop run_loop;
context()->CloseAllConnections(run_loop.QuitClosure());
run_loop.Run();
}
// Make sure the connection still fails, due to the newer CRLSet still
// applying.
LoadURL(test_server.GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
// Create a new NetworkContext and ensure the latest CRLSet is still
// applied.
network_context_.reset();
CreateNetworkContext();
// The newer CRLSet that blocks the connection should still apply, even to
// new NetworkContexts.
LoadURL(test_server.GetURL("/echo"), options);
EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
client()->completion_status().error_code);
ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
net::CERT_STATUS_REVOKED);
}
#endif // !defined(OS_IOS) && !defined(OS_ANDROID)
// TODO(crbug.com/860189): AIA tests fail on iOS
#if defined(OS_IOS)
#define MAYBE_AIAFetching DISABLED_AIAFetching
#else
#define MAYBE_AIAFetching AIAFetching
#endif
TEST_F(NetworkServiceTestWithService, MAYBE_AIAFetching) {
mojom::NetworkContextParamsPtr context_params = CreateContextParams();
network_service_->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(), std::move(context_params));
net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.intermediate = net::EmbeddedTestServer::IntermediateType::kByAIA;
test_server.SetSSLConfig(cert_config);
test_server.AddDefaultHandlers(base::FilePath(kServicesTestData));
ASSERT_TRUE(test_server.Start());
LoadURL(test_server.GetURL("/echo"),
mojom::kURLLoadOptionSendSSLInfoWithResponse);
EXPECT_EQ(net::OK, client()->completion_status().error_code);
ASSERT_TRUE(client()->response_head());
EXPECT_EQ(
0u, client()->response_head()->cert_status & net::CERT_STATUS_ALL_ERRORS);
ASSERT_TRUE(client()->ssl_info());
ASSERT_TRUE(client()->ssl_info()->cert);
EXPECT_EQ(2u, client()->ssl_info()->cert->intermediate_buffers().size());
ASSERT_TRUE(client()->ssl_info()->unverified_cert);
EXPECT_EQ(
0u, client()->ssl_info()->unverified_cert->intermediate_buffers().size());
}
TEST_F(NetworkServiceTestWithService, GetDnsConfigChangeManager) {
mojo::Remote<mojom::DnsConfigChangeManager> remote;
ASSERT_FALSE(remote.is_bound());
@ -1641,6 +1395,10 @@ class NetworkServiceNetworkDelegateTest : public NetworkServiceTest {
void CreateNetworkContext() {
mojom::NetworkContextParamsPtr context_params =
mojom::NetworkContextParams::New();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
context_params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
service()->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(),
std::move(context_params));

@ -12,6 +12,7 @@
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/origin_policy.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
@ -30,6 +31,10 @@ class OriginPolicyManagerTest : public testing::Test {
network_service_ = NetworkService::CreateForTesting();
auto context_params = mojom::NetworkContextParams::New();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
context_params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
context_params->initial_proxy_config =

@ -3,6 +3,9 @@
// found in the LICENSE file.
#include "services/network/public/cpp/cert_verifier/mojo_cert_verifier.h"
#include <memory>
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/base/net_errors.h"
@ -62,9 +65,44 @@ class CertVerifierRequestImpl : public mojom::CertVerifierRequest,
};
} // namespace
class MojoCertVerifier::MojoReconnector
: public mojom::URLLoaderFactoryConnector {
public:
MojoReconnector(
mojo::PendingReceiver<mojom::URLLoaderFactoryConnector> receiver,
base::RepeatingCallback<void(
mojo::PendingReceiver<network::mojom::URLLoaderFactory>)> reconnector)
: receiver_(this, std::move(receiver)),
reconnector_(std::move(reconnector)) {}
// mojom::URLLoaderFactoryConnector implementation:
void CreateURLLoaderFactory(
mojo::PendingReceiver<network::mojom::URLLoaderFactory>
url_loader_factory) override {
reconnector_.Run(std::move(url_loader_factory));
}
private:
mojo::Receiver<mojom::URLLoaderFactoryConnector> receiver_;
base::RepeatingCallback<void(
mojo::PendingReceiver<network::mojom::URLLoaderFactory>)>
reconnector_;
};
MojoCertVerifier::MojoCertVerifier(
mojo::PendingRemote<mojom::CertVerifierService> mojo_cert_verifier)
: mojo_cert_verifier_(std::move(mojo_cert_verifier)) {}
mojo::PendingRemote<mojom::CertVerifierService> mojo_cert_verifier,
mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
base::RepeatingCallback<void(
mojo::PendingReceiver<network::mojom::URLLoaderFactory>)> reconnector)
: mojo_cert_verifier_(std::move(mojo_cert_verifier)) {
mojo::PendingRemote<mojom::URLLoaderFactoryConnector> reconnector_remote;
reconnector_ = std::make_unique<MojoReconnector>(
reconnector_remote.InitWithNewPipeAndPassReceiver(),
std::move(reconnector));
mojo_cert_verifier_->EnableNetworkAccess(std::move(url_loader_factory),
std::move(reconnector_remote));
}
MojoCertVerifier::~MojoCertVerifier() = default;
@ -90,4 +128,8 @@ int MojoCertVerifier::Verify(
void MojoCertVerifier::SetConfig(const net::CertVerifier::Config& config) {
mojo_cert_verifier_->SetConfig(config);
}
void MojoCertVerifier::FlushForTesting() {
mojo_cert_verifier_.FlushForTesting();
}
} // namespace cert_verifier

@ -5,6 +5,8 @@
#ifndef SERVICES_NETWORK_PUBLIC_CPP_CERT_VERIFIER_MOJO_CERT_VERIFIER_H_
#define SERVICES_NETWORK_PUBLIC_CPP_CERT_VERIFIER_MOJO_CERT_VERIFIER_H_
#include "base/callback_forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_export.h"
@ -12,6 +14,7 @@
#include "net/cert/cert_verify_result.h"
#include "net/log/net_log_with_source.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
namespace cert_verifier {
@ -19,8 +22,16 @@ namespace cert_verifier {
// verify certificates.
class MojoCertVerifier : public net::CertVerifier {
public:
explicit MojoCertVerifier(
mojo::PendingRemote<mojom::CertVerifierService> mojo_cert_verifier);
using ReconnectURLLoaderFactory = base::RepeatingCallback<void(
mojo::PendingReceiver<network::mojom::URLLoaderFactory>)>;
// The remote CertNetFetcher will use |url_loader_factory| for fetches. If
// |url_loader_factory| disconnects it will use |reconnector| to try to
// connect a new URLLoaderFactory.
MojoCertVerifier(
mojo::PendingRemote<mojom::CertVerifierService> mojo_cert_verifier,
mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
ReconnectURLLoaderFactory reconnector);
~MojoCertVerifier() override;
// net::CertVerifier implementation:
@ -31,8 +42,14 @@ class MojoCertVerifier : public net::CertVerifier {
const net::NetLogWithSource& net_log) override;
void SetConfig(const net::CertVerifier::Config& config) override;
// Flushes the underlying Mojo pipe.
void FlushForTesting();
private:
class MojoReconnector;
mojo::Remote<mojom::CertVerifierService> mojo_cert_verifier_;
std::unique_ptr<MojoReconnector> reconnector_;
};
} // namespace cert_verifier

@ -7,9 +7,11 @@
#include <map>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
@ -36,12 +38,27 @@ net::CertVerifier::RequestParams GetDummyParams() {
/*sct_list=*/std::string());
}
mojo::PendingRemote<network::mojom::URLLoaderFactory>
CreateUnconnectedURLLoaderFactory() {
mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory;
// Bind the factory, but don't bother connecting it.
ignore_result(url_loader_factory.InitWithNewPipeAndPassReceiver());
return url_loader_factory;
}
class MojoCertVerifierTest : public PlatformTest {
public:
MojoCertVerifierTest()
: dummy_cv_service_(this),
cv_service_receiver_(&dummy_cv_service_),
mojo_cert_verifier_(cv_service_receiver_.BindNewPipeAndPassRemote()) {}
mojo_cert_verifier_(
cv_service_receiver_.BindNewPipeAndPassRemote(),
CreateUnconnectedURLLoaderFactory(),
base::BindRepeating(&MojoCertVerifierTest::ReconnectCb,
base::Unretained(this))) {
// Any Mojo requests in the MojoCertVerifier constructor should run here.
mojo_cert_verifier_.FlushForTesting();
}
class DummyCVService final : public mojom::CertVerifierService {
public:
@ -57,12 +74,24 @@ class MojoCertVerifierTest : public PlatformTest {
config_ = config;
}
void EnableNetworkAccess(
mojo::PendingRemote<network::mojom::URLLoaderFactory>
url_loader_factory,
mojo::PendingRemote<mojom::URLLoaderFactoryConnector> reconnector)
override {
reconnector_.Bind(std::move(reconnector));
}
const net::CertVerifier::Config* config() const { return &config_; }
mojom::URLLoaderFactoryConnector* reconnector() {
return reconnector_.get();
}
private:
MojoCertVerifierTest* test_;
net::CertVerifier::Config config_;
mojo::Remote<mojom::URLLoaderFactoryConnector> reconnector_;
};
base::test::TaskEnvironment* task_environment() { return &task_environment_; }
@ -97,6 +126,16 @@ class MojoCertVerifierTest : public PlatformTest {
void SimulateCVServiceDisconnect() { cv_service_receiver_.reset(); }
void ReconnectCb(mojo::PendingReceiver<network::mojom::URLLoaderFactory>
mojo_cert_verifier) {
if (reconnect_cb_)
reconnect_cb_.Run(std::move(mojo_cert_verifier));
}
void SetReconnectCb(MojoCertVerifier::ReconnectURLLoaderFactory cb) {
reconnect_cb_ = std::move(cb);
}
private:
std::map<net::CertVerifier::RequestParams,
mojo::Remote<mojom::CertVerifierRequest>>
@ -109,6 +148,8 @@ class MojoCertVerifierTest : public PlatformTest {
MojoCertVerifier mojo_cert_verifier_;
MojoCertVerifier::ReconnectURLLoaderFactory reconnect_cb_;
net::NetLogWithSource empty_net_log_with_source_;
};
} // namespace
@ -244,4 +285,22 @@ TEST_F(MojoCertVerifierTest, SendsConfig) {
ASSERT_TRUE(dummy_cv_service()->config()->disable_symantec_enforcement);
}
TEST_F(MojoCertVerifierTest, ReconnectorCallsCb) {
base::RunLoop run_loop;
SetReconnectCb(base::BindLambdaForTesting(
[&](mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {
run_loop.Quit();
}));
mojo::PendingRemote<network::mojom::URLLoaderFactory>
dummy_url_loader_factory_remote;
// Simulate a remote CertVerifierService trying to reconnect after
// disconnection. This should call the callback given to the MojoCertVerifier
// on construction.
dummy_cv_service()->reconnector()->CreateURLLoaderFactory(
dummy_url_loader_factory_remote.InitWithNewPipeAndPassReceiver());
run_loop.Run();
}
} // namespace cert_verifier

@ -194,6 +194,12 @@ const char kCorbAllowlistAlsoAppliesToOorCorsParamName[] =
const base::Feature kStrictAccessControlAllowListCheck = {
"StrictAccessControlAllowListCheck", base::FEATURE_ENABLED_BY_DEFAULT};
// When the CertVerifierService is enabled, certificate verification will not be
// performed in the network service, but will instead be brokered to a separate
// cert verification service potentially running in a different process.
const base::Feature kCertVerifierService{"CertVerifierService",
base::FEATURE_DISABLED_BY_DEFAULT};
// Enables preprocessing requests with the Trust Tokens API Fetch flags set,
// and handling their responses, according to the protocol.
// (See https://github.com/WICG/trust-token-api.)

@ -73,6 +73,8 @@ COMPONENT_EXPORT(NETWORK_CPP)
extern const char kCorbAllowlistAlsoAppliesToOorCorsParamName[];
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kStrictAccessControlAllowListCheck;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kCertVerifierService;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kTrustTokens;

@ -54,6 +54,7 @@
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_network_context_client.h"
#include "services/network/test/test_network_service_client.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -592,6 +593,12 @@ class SimpleURLLoaderTestBase {
network_service_remote.BindNewPipeAndPassReceiver());
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
context_params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
network_service_remote->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(),
std::move(context_params));

@ -6,6 +6,7 @@ module cert_verifier.mojom;
import "mojo/public/mojom/base/big_buffer.mojom";
import "services/network/public/mojom/network_param.mojom";
import "services/network/public/mojom/url_loader_factory.mojom";
// Mojo version of net::CertVerifier::RequestParams.
struct RequestParams {
@ -27,10 +28,27 @@ struct CertVerifierConfig {
array<network.mojom.X509Certificate> additional_trust_anchors;
};
// Allows the CertVerifierService to connect a new URLLoaderFactory if its
// existing URLLoaderFactory is disconnected. The CertVerifierService uses the
// URLLoaderFactory for AIA and OCSP fetching.
interface URLLoaderFactoryConnector {
// Binds a URLLoaderFactory.
CreateURLLoaderFactory(
pending_receiver<network.mojom.URLLoaderFactory> url_loader_factory);
};
// An interface that verifies a certificate based on the |params|, and calls the
// |Complete| method on the returned CertVerifierRequest when the result is
// available.
interface CertVerifierService {
// |url_loader_factory| allows the CertVerifierService to connect to the
// network for things like AIA or OCSP. |reconnector| allows the CertVerifier
// to reconnect its URLLoaderFactory in case the network service disconnects
// its URLLoaderFactories without crashing. Must be called before Verify() to
// have an effect.
EnableNetworkAccess(
pending_remote<network.mojom.URLLoaderFactory> url_loader_factory,
pending_remote<URLLoaderFactoryConnector>? reconnector);
// Mojo IPC used to verify a certificate. Sends results to the
// |cert_verifier_request| interface when verification is complete.
Verify(RequestParams params,

@ -11,7 +11,7 @@ import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "mojo/public/mojom/base/values.mojom";
import "services/network/public/mojom/address_list.mojom";
import "services/network/public/mojom/parsed_headers.mojom";
import "services/network/public/mojom/cert_verifier_service.mojom";
import "services/network/public/mojom/cookie_access_observer.mojom";
import "services/network/public/mojom/cookie_manager.mojom";
import "services/network/public/mojom/default_credentials.mojom";
@ -29,6 +29,7 @@ import "services/network/public/mojom/network_isolation_key.mojom";
import "services/network/public/mojom/isolation_info.mojom";
import "services/network/public/mojom/network_param.mojom";
import "services/network/public/mojom/origin_policy_manager.mojom";
import "services/network/public/mojom/parsed_headers.mojom";
import "services/network/public/mojom/p2p.mojom";
import "services/network/public/mojom/p2p_trusted.mojom";
import "services/network/public/mojom/proxy_config.mojom";
@ -123,6 +124,21 @@ struct CertVerifierCreationParams {
TrialComparisonCertVerifierParams? trial_comparison_cert_verifier_params;
};
// Includes a pipe to a CertVerifierService for usage by the
// NetworkContext.
struct CertVerifierServiceRemoteParams {
// A pipe to the CertVerifierService.
pending_remote<cert_verifier.mojom.CertVerifierService>?
cert_verifier_service;
};
// Contains the parameters necessary to either connect to a CertVerifierService
// or create a net::CertVerifier in the network service itself.
union CertVerifierParams {
CertVerifierServiceRemoteParams remote_params;
CertVerifierCreationParams creation_params;
};
// Client to update the custom proxy config.
interface CustomProxyConfigClient {
OnCustomProxyConfigUpdated(CustomProxyConfig proxy_config);
@ -373,8 +389,9 @@ struct NetworkContextParams {
[EnableIf=is_ct_supported]
mojo_base.mojom.Time ct_log_update_time;
// Contains the parameters used to instantiate a net::CertVerifier in-process.
CertVerifierCreationParams? cert_verifier_creation_params;
// Contains either a pipe to a CertVerifierService, or parameters used to
// instantiate a net::CertVerifier in-process.
CertVerifierParams? cert_verifier_params;
// Initial additional certificates that will be used for certificate
// validation.

@ -18,11 +18,22 @@
#include "net/url_request/url_request_context.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
namespace {
mojom::NetworkContextParamsPtr CreateNetworkContextParams() {
auto context_params = mojom::NetworkContextParams::New();
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test CertVerifier behavior.
context_params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
return context_params;
}
// We don't use mojo::BlockingCopyToString because it leads to deadlocks.
std::string Read(mojo::ScopedDataPipeConsumerHandle readable) {
std::string output;
@ -194,7 +205,7 @@ class QuicTransportTest : public testing::Test {
network_context_remote_(mojo::NullRemote()),
network_context_(network_service_.get(),
network_context_remote_.BindNewPipeAndPassReceiver(),
mojom::NetworkContextParams::New()),
CreateNetworkContextParams()),
server_(/* port= */ 0,
{origin_},
quic::test::crypto_test_utils::ProofSourceForTesting()) {

@ -4,6 +4,7 @@
#include "services/network/ssl_config_service_mojo.h"
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
@ -28,8 +29,10 @@
#include "net/url_request/url_request_context.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/ssl_config.mojom.h"
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -156,6 +159,12 @@ class NetworkServiceSSLConfigServiceTest : public testing::Test {
// stores it in |network_context_|.
void SetUpNetworkContext(
mojom::NetworkContextParamsPtr network_context_params) {
// Use a dummy CertVerifier that always passes cert verification, since
// these unittests don't need to test the behavior of a real CertVerifier.
// There are a parallel set of tests in services/cert_verifier/ that *do*
// test CertVerifier behavior.
network_context_params->cert_verifier_params =
FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
ssl_config_client_.reset();
network_context_params->ssl_config_client_receiver =
ssl_config_client_.BindNewPipeAndPassReceiver();
@ -489,66 +498,5 @@ TEST_F(NetworkServiceSSLConfigServiceTest, CanShareConnectionWithClientCerts) {
config_service->CanShareConnectionWithClientCerts("example.net"));
}
#if !defined(OS_IOS) && !defined(OS_ANDROID)
TEST_F(NetworkServiceSSLConfigServiceTest, CRLSetIsApplied) {
SetUpNetworkContext(mojom::NetworkContextParams::New());
SSLConfigServiceMojo* config_service = static_cast<SSLConfigServiceMojo*>(
network_context_->url_request_context()->ssl_config_service());
scoped_refptr<net::X509Certificate> root_cert =
net::CreateCertificateChainFromFile(
net::GetTestCertsDirectory(), "root_ca_cert.pem",
net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
ASSERT_TRUE(root_cert);
net::ScopedTestRoot test_root(root_cert.get());
scoped_refptr<net::X509Certificate> cert =
net::CreateCertificateChainFromFile(
net::GetTestCertsDirectory(), "ok_cert.pem",
net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
ASSERT_TRUE(cert);
// Ensure that |cert| is trusted without any CRLSet explicitly configured.
net::TestCompletionCallback callback1;
net::CertVerifyResult cert_verify_result1;
std::unique_ptr<net::CertVerifier::Request> request1;
int result = network_context_->url_request_context()->cert_verifier()->Verify(
net::CertVerifier::RequestParams(cert, "127.0.0.1",
/*flags=*/0,
/*ocsp_response=*/std::string(),
/*sct_list=*/std::string()),
&cert_verify_result1, callback1.callback(), &request1,
net::NetLogWithSource());
ASSERT_THAT(callback1.GetResult(result), net::test::IsOk());
// Configure an explicit CRLSet that removes trust in |leaf_cert| by SPKI.
base::StringPiece spki;
ASSERT_TRUE(net::asn1::ExtractSPKIFromDERCert(
net::x509_util::CryptoBufferAsStringPiece(root_cert->cert_buffer()),
&spki));
net::SHA256HashValue spki_sha256;
crypto::SHA256HashString(spki, spki_sha256.data, sizeof(spki_sha256.data));
config_service->OnNewCRLSet(net::CRLSet::ForTesting(
false, &spki_sha256, cert->serial_number(), "", {}));
// Ensure that |cert| is revoked, due to the CRLSet being applied.
net::TestCompletionCallback callback2;
net::CertVerifyResult cert_verify_result2;
std::unique_ptr<net::CertVerifier::Request> request2;
result = network_context_->url_request_context()->cert_verifier()->Verify(
net::CertVerifier::RequestParams(cert, "127.0.0.1",
/*flags=*/0,
/*ocsp_response=*/std::string(),
/*sct_list=*/std::string()),
&cert_verify_result2, callback2.callback(), &request2,
net::NetLogWithSource());
ASSERT_THAT(callback2.GetResult(result),
net::test::IsError(net::ERR_CERT_REVOKED));
}
#endif // !defined(OS_IOS) && !defined(OS_ANDROID)
} // namespace
} // namespace network

@ -0,0 +1,53 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include <memory>
#include "base/feature_list.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_verify_result.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace network {
FakeTestCertVerifierParamsFactory::FakeTestCertVerifierParamsFactory() =
default;
FakeTestCertVerifierParamsFactory::~FakeTestCertVerifierParamsFactory() =
default;
// static
mojom::CertVerifierParamsPtr
FakeTestCertVerifierParamsFactory::GetCertVerifierParams() {
if (!base::FeatureList::IsEnabled(network::features::kCertVerifierService)) {
return mojom::CertVerifierParams::NewCreationParams(
mojom::CertVerifierCreationParams::New());
}
auto remote_params = mojom::CertVerifierServiceRemoteParams::New();
mojo::PendingRemote<cert_verifier::mojom::CertVerifierService> cv_remote;
mojo::MakeSelfOwnedReceiver(
std::make_unique<FakeTestCertVerifierParamsFactory>(),
cv_remote.InitWithNewPipeAndPassReceiver());
remote_params->cert_verifier_service = std::move(cv_remote);
return mojom::CertVerifierParams::NewRemoteParams(std::move(remote_params));
}
void FakeTestCertVerifierParamsFactory::Verify(
const ::net::CertVerifier::RequestParams& params,
mojo::PendingRemote<cert_verifier::mojom::CertVerifierRequest>
cert_verifier_request) {
mojo::Remote<cert_verifier::mojom::CertVerifierRequest> request(
std::move(cert_verifier_request));
net::CertVerifyResult result;
result.verified_cert = params.certificate();
request->Complete(std::move(result), net::OK);
}
} // namespace network

@ -0,0 +1,43 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_NETWORK_TEST_FAKE_TEST_CERT_VERIFIER_PARAMS_FACTORY_H_
#define SERVICES_NETWORK_TEST_FAKE_TEST_CERT_VERIFIER_PARAMS_FACTORY_H_
#include "net/cert/cert_verifier.h"
#include "services/network/public/mojom/cert_verifier_service.mojom-forward.h"
#include "services/network/public/mojom/network_context.mojom-forward.h"
namespace network {
// FakeTestCertVerifierParamsFactory::GetCertVerifierParams returns a
// mojom::CertVerifierParamsPtr, which either contains the parameters for a real
// in-network-service CertVerifier, or contains a pipe to a fake
// CertVerifierService that successfully verifies every certificate, even
// invalid ones. This is useful for tests that need to set up a NetworkContext,
// which requires CertVerifierParams, but the test doesn't actually need to test
// cert verifier behavior.
class FakeTestCertVerifierParamsFactory
: public cert_verifier::mojom::CertVerifierService {
public:
FakeTestCertVerifierParamsFactory();
~FakeTestCertVerifierParamsFactory() override;
static mojom::CertVerifierParamsPtr GetCertVerifierParams();
private:
// cert_verifier::mojom::CertVerifierService implementation:
void Verify(const net::CertVerifier::RequestParams& params,
mojo::PendingRemote<cert_verifier::mojom::CertVerifierRequest>
cert_verifier_request) override;
void SetConfig(const net::CertVerifier::Config& config) override {}
void EnableNetworkAccess(
mojo::PendingRemote<mojom::URLLoaderFactory>,
mojo::PendingRemote<cert_verifier::mojom::URLLoaderFactoryConnector>
reconnector) override {}
};
} // namespace network
#endif // SERVICES_NETWORK_TEST_FAKE_TEST_CERT_VERIFIER_PARAMS_FACTORY_H_

@ -14,8 +14,10 @@
#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/network_service_instance.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_context.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
#include "weblayer/browser/safe_browsing/safe_browsing_navigation_throttle.h"
@ -29,6 +31,8 @@ network::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams(
const std::string& user_agent) {
network::mojom::NetworkContextParamsPtr network_context_params =
network::mojom::NetworkContextParams::New();
network_context_params->cert_verifier_params = content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
network_context_params->user_agent = user_agent;
return network_context_params;
}

@ -51,6 +51,8 @@ SystemNetworkContextManager::CreateDefaultNetworkContextParams(
const std::string& user_agent) {
network::mojom::NetworkContextParamsPtr network_context_params =
network::mojom::NetworkContextParams::New();
network_context_params->cert_verifier_params = content::GetCertVerifierParams(
network::mojom::CertVerifierCreationParams::New());
ConfigureDefaultNetworkContextParams(network_context_params.get(),
user_agent);
variations::UpdateCorsExemptHeaderForVariations(network_context_params.get());