blob: 283c40f028f8d01747f7b3ab0100dd06235fd03a [file] [log] [blame]
// Copyright 2018 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 "chrome/browser/net/system_network_context_manager.h"
#include <string>
#include <vector>
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/component_updater/first_party_sets_component_installer.h"
#include "chrome/browser/net/stub_resolver_config_reader.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#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/network_service_util.h"
#include "content/public/common/user_agent.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
#include "net/dns/public/dns_over_https_server_config.h"
#include "net/net_buildflags.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"
#include "services/network/public/mojom/network_service_test.mojom.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/features.h"
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
#include "chrome/browser/policy/policy_test_utils.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "net/base/features.h"
#endif
namespace {
int64_t GetFirstPartySetEntriesCountFromNetworkService() {
// The test interface isn't supported in the in-process case.
DCHECK(!content::IsInProcessNetworkService());
mojo::Remote<network::mojom::NetworkServiceTest> network_service_test;
content::GetNetworkService()->BindTestInterface(
network_service_test.BindNewPipeAndPassReceiver());
network_service_test.FlushForTesting();
mojo::ScopedAllowSyncCallForTesting allow_sync_call;
int64_t count = 0;
EXPECT_TRUE(network_service_test->GetFirstPartySetEntriesCount(&count));
return count;
}
void Sleep(base::TimeDelta duration) {
base::RunLoop run_loop;
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), duration);
run_loop.Run();
}
// Calls a predicate periodically until it becomes true, or until a timeout
// elapses. The predicate is expected to be monotonic (i.e. once it becomes
// true, it will remain true until the next time `predicate` is invoked).
// Returns true if the predicate became true; false otherwise.
bool PollWithTimeout(base::TimeDelta timeout,
base::RepeatingCallback<bool()> predicate) {
base::TimeTicks deadline = base::TimeTicks::Now() + timeout;
while (base::TimeTicks::Now() <= deadline) {
if (predicate.Run())
return true;
Sleep(base::Milliseconds(5));
}
return false;
}
void PollForFirstPartySetEntryCount(base::TimeDelta timeout,
int64_t expected_count) {
if (!PollWithTimeout(
timeout, base::BindLambdaForTesting([expected_count]() {
return GetFirstPartySetEntriesCountFromNetworkService() ==
expected_count;
}))) {
FAIL() << "Polled for " << timeout << " but never found exactly "
<< expected_count << " First-Party Set entries.";
}
}
} // namespace
using SystemNetworkContextManagerBrowsertest = InProcessBrowserTest;
IN_PROC_BROWSER_TEST_F(SystemNetworkContextManagerBrowsertest,
StaticAuthParams) {
// Test defaults.
network::mojom::HttpAuthStaticParamsPtr static_params =
SystemNetworkContextManager::GetHttpAuthStaticParamsForTesting();
EXPECT_THAT(static_params->supported_schemes,
testing::ElementsAre("basic", "digest", "ntlm", "negotiate"));
EXPECT_EQ("", static_params->gssapi_library_name);
// Test that prefs are reflected in params.
PrefService* local_state = g_browser_process->local_state();
local_state->SetString(prefs::kAuthSchemes, "basic");
static_params =
SystemNetworkContextManager::GetHttpAuthStaticParamsForTesting();
EXPECT_THAT(static_params->supported_schemes, testing::ElementsAre("basic"));
#if defined(OS_POSIX) && !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
const char dev_null[] = "/dev/null";
local_state->SetString(prefs::kGSSAPILibraryName, dev_null);
static_params =
SystemNetworkContextManager::GetHttpAuthStaticParamsForTesting();
EXPECT_EQ(dev_null, static_params->gssapi_library_name);
#endif
}
IN_PROC_BROWSER_TEST_F(SystemNetworkContextManagerBrowsertest, AuthParams) {
// Test defaults.
network::mojom::HttpAuthDynamicParamsPtr dynamic_params =
SystemNetworkContextManager::GetHttpAuthDynamicParamsForTesting();
EXPECT_FALSE(dynamic_params->negotiate_disable_cname_lookup);
EXPECT_FALSE(dynamic_params->enable_negotiate_port);
EXPECT_TRUE(dynamic_params->basic_over_http_enabled);
EXPECT_EQ("", dynamic_params->server_allowlist);
EXPECT_EQ("", dynamic_params->delegate_allowlist);
EXPECT_FALSE(dynamic_params->delegate_by_kdc_policy);
PrefService* local_state = g_browser_process->local_state();
local_state->SetBoolean(prefs::kDisableAuthNegotiateCnameLookup, true);
dynamic_params =
SystemNetworkContextManager::GetHttpAuthDynamicParamsForTesting();
EXPECT_TRUE(dynamic_params->negotiate_disable_cname_lookup);
EXPECT_FALSE(dynamic_params->enable_negotiate_port);
EXPECT_TRUE(dynamic_params->basic_over_http_enabled);
EXPECT_EQ("", dynamic_params->server_allowlist);
EXPECT_EQ("", dynamic_params->delegate_allowlist);
EXPECT_FALSE(dynamic_params->delegate_by_kdc_policy);
local_state->SetBoolean(prefs::kEnableAuthNegotiatePort, true);
dynamic_params =
SystemNetworkContextManager::GetHttpAuthDynamicParamsForTesting();
EXPECT_TRUE(dynamic_params->negotiate_disable_cname_lookup);
EXPECT_TRUE(dynamic_params->enable_negotiate_port);
EXPECT_TRUE(dynamic_params->basic_over_http_enabled);
EXPECT_EQ("", dynamic_params->server_allowlist);
EXPECT_EQ("", dynamic_params->delegate_allowlist);
EXPECT_FALSE(dynamic_params->delegate_by_kdc_policy);
local_state->SetBoolean(prefs::kBasicAuthOverHttpEnabled, false);
dynamic_params =
SystemNetworkContextManager::GetHttpAuthDynamicParamsForTesting();
EXPECT_TRUE(dynamic_params->negotiate_disable_cname_lookup);
EXPECT_TRUE(dynamic_params->enable_negotiate_port);
EXPECT_FALSE(dynamic_params->basic_over_http_enabled);
EXPECT_EQ("", dynamic_params->server_allowlist);
EXPECT_EQ("", dynamic_params->delegate_allowlist);
EXPECT_FALSE(dynamic_params->delegate_by_kdc_policy);
const char kServerAllowList[] = "foo";
local_state->SetString(prefs::kAuthServerAllowlist, kServerAllowList);
dynamic_params =
SystemNetworkContextManager::GetHttpAuthDynamicParamsForTesting();
EXPECT_TRUE(dynamic_params->negotiate_disable_cname_lookup);
EXPECT_TRUE(dynamic_params->enable_negotiate_port);
EXPECT_FALSE(dynamic_params->basic_over_http_enabled);
EXPECT_EQ(kServerAllowList, dynamic_params->server_allowlist);
EXPECT_EQ("", dynamic_params->delegate_allowlist);
const char kDelegateAllowList[] = "bar, baz";
local_state->SetString(prefs::kAuthNegotiateDelegateAllowlist,
kDelegateAllowList);
dynamic_params =
SystemNetworkContextManager::GetHttpAuthDynamicParamsForTesting();
EXPECT_TRUE(dynamic_params->negotiate_disable_cname_lookup);
EXPECT_TRUE(dynamic_params->enable_negotiate_port);
EXPECT_EQ(kServerAllowList, dynamic_params->server_allowlist);
EXPECT_FALSE(dynamic_params->basic_over_http_enabled);
EXPECT_EQ(kDelegateAllowList, dynamic_params->delegate_allowlist);
EXPECT_FALSE(dynamic_params->delegate_by_kdc_policy);
#if defined(OS_LINUX) || defined(OS_MAC) || defined(OS_CHROMEOS)
local_state->SetBoolean(prefs::kAuthNegotiateDelegateByKdcPolicy, true);
dynamic_params =
SystemNetworkContextManager::GetHttpAuthDynamicParamsForTesting();
EXPECT_TRUE(dynamic_params->negotiate_disable_cname_lookup);
EXPECT_TRUE(dynamic_params->enable_negotiate_port);
EXPECT_FALSE(dynamic_params->basic_over_http_enabled);
EXPECT_EQ(kServerAllowList, dynamic_params->server_allowlist);
EXPECT_EQ(kDelegateAllowList, dynamic_params->delegate_allowlist);
EXPECT_TRUE(dynamic_params->delegate_by_kdc_policy);
#endif // defined(OS_LINUX) || defined(OS_MAC) || defined(OS_CHROMEOS)
#if BUILDFLAG(IS_CHROMEOS_ASH)
// The kerberos.enabled pref is false and the device is not Active Directory
// managed by default.
EXPECT_FALSE(dynamic_params->allow_gssapi_library_load);
local_state->SetBoolean(prefs::kKerberosEnabled, true);
dynamic_params =
SystemNetworkContextManager::GetHttpAuthDynamicParamsForTesting();
EXPECT_TRUE(dynamic_params->allow_gssapi_library_load);
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
}
class SystemNetworkContextManagerWithFirstPartySetComponentBrowserTest
: public SystemNetworkContextManagerBrowsertest {
public:
SystemNetworkContextManagerWithFirstPartySetComponentBrowserTest() = default;
void SetUpInProcessBrowserTestFixture() override {
SystemNetworkContextManagerBrowsertest::SetUpInProcessBrowserTestFixture();
feature_list_.InitAndEnableFeature(net::features::kFirstPartySets);
CHECK(component_dir_.CreateUniqueTempDir());
base::ScopedAllowBlockingForTesting allow_blocking;
component_updater::FirstPartySetsComponentInstallerPolicy::
WriteComponentForTesting(component_dir_.GetPath(), R"([{
"owner": "https://example.test",
"members": [
"https://member1.test",
"https://member2.test"
]
}])");
}
private:
base::test::ScopedFeatureList feature_list_;
base::ScopedTempDir component_dir_;
};
IN_PROC_BROWSER_TEST_F(
SystemNetworkContextManagerWithFirstPartySetComponentBrowserTest,
ReloadsFirstPartySetsAfterCrash) {
// Network service is not running out of process, so cannot be crashed.
if (!content::IsOutOfProcessNetworkService())
return;
PollForFirstPartySetEntryCount(base::Seconds(5),
/*expected_count=*/3);
SimulateNetworkServiceCrash();
PollForFirstPartySetEntryCount(base::Seconds(5),
/*expected_count=*/3);
}
class SystemNetworkContextManagerReferrersFeatureBrowsertest
: public SystemNetworkContextManagerBrowsertest,
public testing::WithParamInterface<bool> {
public:
SystemNetworkContextManagerReferrersFeatureBrowsertest() {
scoped_feature_list_.InitWithFeatureState(features::kNoReferrers,
GetParam());
}
~SystemNetworkContextManagerReferrersFeatureBrowsertest() override {}
void SetUpOnMainThread() override {}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
// Tests that toggling the kNoReferrers feature correctly changes the default
// value of the kEnableReferrers pref.
IN_PROC_BROWSER_TEST_P(SystemNetworkContextManagerReferrersFeatureBrowsertest,
TestDefaultReferrerReflectsFeatureValue) {
ASSERT_TRUE(g_browser_process);
PrefService* local_state = g_browser_process->local_state();
ASSERT_TRUE(local_state);
EXPECT_NE(local_state->GetBoolean(prefs::kEnableReferrers), GetParam());
}
INSTANTIATE_TEST_SUITE_P(All,
SystemNetworkContextManagerReferrersFeatureBrowsertest,
::testing::Bool());
class SystemNetworkContextManagerFreezeQUICUaBrowsertest
: public SystemNetworkContextManagerBrowsertest,
public testing::WithParamInterface<bool> {
public:
SystemNetworkContextManagerFreezeQUICUaBrowsertest() {
scoped_feature_list_.InitWithFeatureState(blink::features::kReduceUserAgent,
GetParam());
}
~SystemNetworkContextManagerFreezeQUICUaBrowsertest() override {}
void SetUpOnMainThread() override {}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_P(SystemNetworkContextManagerFreezeQUICUaBrowsertest,
QUICUaConfig) {
network::mojom::NetworkContextParamsPtr network_context_params =
g_browser_process->system_network_context_manager()
->CreateDefaultNetworkContextParams();
std::string quic_ua = network_context_params->quic_user_agent_id;
if (GetParam()) { // if the UA Freeze feature is turned on
EXPECT_EQ("", quic_ua);
} else {
EXPECT_THAT(quic_ua, testing::HasSubstr(chrome::GetChannelName(
chrome::WithExtendedStable(false))));
EXPECT_THAT(quic_ua,
testing::HasSubstr(
version_info::GetProductNameAndVersionForUserAgent()));
EXPECT_THAT(quic_ua, testing::HasSubstr(content::BuildOSCpuInfo(
content::IncludeAndroidBuildNumber::Exclude,
content::IncludeAndroidModel::Include)));
}
}
INSTANTIATE_TEST_SUITE_P(All,
SystemNetworkContextManagerFreezeQUICUaBrowsertest,
::testing::Bool());
class SystemNetworkContextManagerWPADQuickCheckBrowsertest
: public SystemNetworkContextManagerBrowsertest,
public testing::WithParamInterface<bool> {
public:
SystemNetworkContextManagerWPADQuickCheckBrowsertest() = default;
~SystemNetworkContextManagerWPADQuickCheckBrowsertest() override = default;
};
IN_PROC_BROWSER_TEST_P(SystemNetworkContextManagerWPADQuickCheckBrowsertest,
WPADQuickCheckPref) {
PrefService* local_state = g_browser_process->local_state();
local_state->SetBoolean(prefs::kQuickCheckEnabled, GetParam());
network::mojom::NetworkContextParamsPtr network_context_params =
g_browser_process->system_network_context_manager()
->CreateDefaultNetworkContextParams();
EXPECT_EQ(GetParam(), network_context_params->pac_quick_check_enabled);
}
INSTANTIATE_TEST_SUITE_P(All,
SystemNetworkContextManagerWPADQuickCheckBrowsertest,
::testing::Bool());
class SystemNetworkContextManagerCertificateTransparencyBrowsertest
: public SystemNetworkContextManagerBrowsertest,
public testing::WithParamInterface<absl::optional<bool>> {
public:
SystemNetworkContextManagerCertificateTransparencyBrowsertest() {
SystemNetworkContextManager::SetEnableCertificateTransparencyForTesting(
GetParam());
}
~SystemNetworkContextManagerCertificateTransparencyBrowsertest() override {
SystemNetworkContextManager::SetEnableCertificateTransparencyForTesting(
absl::nullopt);
}
};
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
class SystemNetworkContextServiceCertVerifierBuiltinPermissionsPolicyTest
: public policy::PolicyTest,
public testing::WithParamInterface<bool> {
public:
SystemNetworkContextServiceCertVerifierBuiltinPermissionsPolicyTest() {
bool use_builtin_cert_verifier = GetParam();
cert_verifier_impl_ =
use_builtin_cert_verifier
? cert_verifier::mojom::CertVerifierCreationParams::
CertVerifierImpl::kBuiltin
: cert_verifier::mojom::CertVerifierCreationParams::
CertVerifierImpl::kSystem;
}
void SetUpInProcessBrowserTestFixture() override {
scoped_feature_list_.InitWithFeatureState(
net::features::kCertVerifierBuiltinFeature,
cert_verifier_impl_ ==
cert_verifier::mojom::CertVerifierCreationParams::CertVerifierImpl::
kBuiltin);
content::SetCertVerifierServiceFactoryForTesting(
&test_cert_verifier_service_factory_);
policy::PolicyTest::SetUpInProcessBrowserTestFixture();
}
void TearDownInProcessBrowserTestFixture() override {
content::SetCertVerifierServiceFactoryForTesting(nullptr);
}
void SetUpOnMainThread() override {
test_cert_verifier_service_factory_.ReleaseAllCertVerifierParams();
}
void ExpectUseBuiltinCertVerifierCorrect(
network::mojom::NetworkContextParamsPtr& network_context_params_ptr,
cert_verifier::mojom::CertVerifierCreationParams::CertVerifierImpl
use_builtin_cert_verifier) {
ASSERT_TRUE(network_context_params_ptr);
ASSERT_TRUE(network_context_params_ptr->cert_verifier_params);
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();
}
cert_verifier::mojom::CertVerifierCreationParams::CertVerifierImpl
cert_verifier_impl() const {
return cert_verifier_impl_;
}
private:
cert_verifier::mojom::CertVerifierCreationParams::CertVerifierImpl
cert_verifier_impl_;
base::test::ScopedFeatureList scoped_feature_list_;
cert_verifier::TestCertVerifierServiceFactoryImpl
test_cert_verifier_service_factory_;
};
IN_PROC_BROWSER_TEST_P(
SystemNetworkContextServiceCertVerifierBuiltinPermissionsPolicyTest,
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.
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.
policy::PolicyMap policies;
SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
base::Value(true));
UpdateProviderPolicy(policies);
network_context_params_ptr =
g_browser_process->system_network_context_manager()
->CreateDefaultNetworkContextParams();
ExpectUseBuiltinCertVerifierCorrect(
network_context_params_ptr,
cert_verifier::mojom::CertVerifierCreationParams::CertVerifierImpl::
kBuiltin);
SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
base::Value(false));
UpdateProviderPolicy(policies);
network_context_params_ptr =
g_browser_process->system_network_context_manager()
->CreateDefaultNetworkContextParams();
ExpectUseBuiltinCertVerifierCorrect(
network_context_params_ptr,
cert_verifier::mojom::CertVerifierCreationParams::CertVerifierImpl::
kSystem);
#endif // BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
}
INSTANTIATE_TEST_SUITE_P(
All,
SystemNetworkContextServiceCertVerifierBuiltinPermissionsPolicyTest,
::testing::Bool());
#endif // BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)