405 lines
15 KiB
C++
405 lines
15 KiB
C++
// Copyright 2019 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "net/dns/dns_client.h"
|
|
|
|
#include <utility>
|
|
|
|
#include "base/functional/bind.h"
|
|
#include "base/rand_util.h"
|
|
#include "base/test/task_environment.h"
|
|
#include "net/base/ip_address.h"
|
|
#include "net/base/ip_endpoint.h"
|
|
#include "net/dns/dns_config.h"
|
|
#include "net/dns/dns_session.h"
|
|
#include "net/dns/dns_test_util.h"
|
|
#include "net/dns/public/dns_over_https_config.h"
|
|
#include "net/dns/resolve_context.h"
|
|
#include "net/socket/socket_test_util.h"
|
|
#include "net/test/test_with_task_environment.h"
|
|
#include "net/url_request/url_request_context.h"
|
|
#include "net/url_request/url_request_context_builder.h"
|
|
#include "net/url_request/url_request_test_util.h"
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
#include "url/scheme_host_port.h"
|
|
|
|
namespace net {
|
|
|
|
class ClientSocketFactory;
|
|
|
|
namespace {
|
|
|
|
class AlwaysFailSocketFactory : public MockClientSocketFactory {
|
|
public:
|
|
std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
|
|
DatagramSocket::BindType bind_type,
|
|
NetLog* net_log,
|
|
const NetLogSource& source) override {
|
|
return std::make_unique<MockUDPClientSocket>();
|
|
}
|
|
};
|
|
|
|
class DnsClientTest : public TestWithTaskEnvironment {
|
|
protected:
|
|
DnsClientTest()
|
|
: TestWithTaskEnvironment(
|
|
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
|
|
|
|
void SetUp() override {
|
|
client_ = DnsClient::CreateClient(nullptr /* net_log */);
|
|
auto context_builder = CreateTestURLRequestContextBuilder();
|
|
context_builder->set_client_socket_factory_for_testing(&socket_factory_);
|
|
request_context_ = context_builder->Build();
|
|
resolve_context_ = std::make_unique<ResolveContext>(
|
|
request_context_.get(), false /* enable_caching */);
|
|
}
|
|
|
|
DnsConfig BasicValidConfig() {
|
|
DnsConfig config;
|
|
config.nameservers = {IPEndPoint(IPAddress(2, 3, 4, 5), 123)};
|
|
return config;
|
|
}
|
|
|
|
DnsConfig ValidConfigWithDoh(bool doh_only) {
|
|
DnsConfig config;
|
|
if (!doh_only) {
|
|
config = BasicValidConfig();
|
|
}
|
|
config.doh_config =
|
|
*net::DnsOverHttpsConfig::FromString("https://www.doh.com/");
|
|
return config;
|
|
}
|
|
|
|
DnsConfigOverrides BasicValidOverrides() {
|
|
DnsConfigOverrides config;
|
|
config.nameservers.emplace({IPEndPoint(IPAddress(1, 2, 3, 4), 123)});
|
|
return config;
|
|
}
|
|
|
|
std::unique_ptr<URLRequestContext> request_context_;
|
|
std::unique_ptr<ResolveContext> resolve_context_;
|
|
std::unique_ptr<DnsClient> client_;
|
|
AlwaysFailSocketFactory socket_factory_;
|
|
};
|
|
|
|
TEST_F(DnsClientTest, NoConfig) {
|
|
client_->SetInsecureEnabled(/*enabled=*/true,
|
|
/*additional_types_enabled=*/true);
|
|
|
|
EXPECT_FALSE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_TRUE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
EXPECT_FALSE(client_->CanUseInsecureDnsTransactions());
|
|
EXPECT_TRUE(client_->FallbackFromInsecureTransactionPreferred());
|
|
|
|
EXPECT_FALSE(client_->GetEffectiveConfig());
|
|
EXPECT_FALSE(client_->GetHosts());
|
|
EXPECT_FALSE(client_->GetTransactionFactory());
|
|
EXPECT_FALSE(client_->GetCurrentSession());
|
|
}
|
|
|
|
TEST_F(DnsClientTest, InvalidConfig) {
|
|
client_->SetInsecureEnabled(/*enabled=*/true,
|
|
/*additional_types_enabled=*/true);
|
|
client_->SetSystemConfig(DnsConfig());
|
|
|
|
EXPECT_FALSE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_TRUE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
EXPECT_FALSE(client_->CanUseInsecureDnsTransactions());
|
|
EXPECT_TRUE(client_->FallbackFromInsecureTransactionPreferred());
|
|
|
|
EXPECT_FALSE(client_->GetEffectiveConfig());
|
|
EXPECT_FALSE(client_->GetHosts());
|
|
EXPECT_FALSE(client_->GetTransactionFactory());
|
|
EXPECT_FALSE(client_->GetCurrentSession());
|
|
}
|
|
|
|
TEST_F(DnsClientTest, CanUseSecureDnsTransactions_NoDohServers) {
|
|
client_->SetInsecureEnabled(/*enabled=*/true,
|
|
/*additional_types_enabled=*/true);
|
|
client_->SetSystemConfig(BasicValidConfig());
|
|
|
|
EXPECT_FALSE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_TRUE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
EXPECT_TRUE(client_->CanUseInsecureDnsTransactions());
|
|
EXPECT_TRUE(client_->CanQueryAdditionalTypesViaInsecureDns());
|
|
EXPECT_FALSE(client_->FallbackFromInsecureTransactionPreferred());
|
|
|
|
EXPECT_THAT(client_->GetEffectiveConfig(),
|
|
testing::Pointee(BasicValidConfig()));
|
|
EXPECT_TRUE(client_->GetHosts());
|
|
EXPECT_TRUE(client_->GetTransactionFactory());
|
|
EXPECT_EQ(client_->GetCurrentSession()->config(), BasicValidConfig());
|
|
}
|
|
|
|
TEST_F(DnsClientTest, InsecureNotEnabled) {
|
|
client_->SetInsecureEnabled(/*enabled=*/false,
|
|
/*additional_types_enabled=*/false);
|
|
client_->SetSystemConfig(ValidConfigWithDoh(false /* doh_only */));
|
|
|
|
EXPECT_TRUE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_TRUE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
EXPECT_FALSE(client_->CanUseInsecureDnsTransactions());
|
|
EXPECT_TRUE(client_->FallbackFromInsecureTransactionPreferred());
|
|
|
|
EXPECT_THAT(client_->GetEffectiveConfig(),
|
|
testing::Pointee(ValidConfigWithDoh(false /* doh_only */)));
|
|
EXPECT_TRUE(client_->GetHosts());
|
|
EXPECT_TRUE(client_->GetTransactionFactory());
|
|
EXPECT_EQ(client_->GetCurrentSession()->config(),
|
|
ValidConfigWithDoh(false /* doh_only */));
|
|
}
|
|
|
|
TEST_F(DnsClientTest, RespectsAdditionalTypesDisabled) {
|
|
client_->SetInsecureEnabled(/*enabled=*/true,
|
|
/*additional_types_enabled=*/false);
|
|
client_->SetSystemConfig(BasicValidConfig());
|
|
|
|
EXPECT_FALSE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_TRUE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
EXPECT_TRUE(client_->CanUseInsecureDnsTransactions());
|
|
EXPECT_FALSE(client_->CanQueryAdditionalTypesViaInsecureDns());
|
|
EXPECT_FALSE(client_->FallbackFromInsecureTransactionPreferred());
|
|
}
|
|
|
|
TEST_F(DnsClientTest, UnhandledOptions) {
|
|
client_->SetInsecureEnabled(/*enabled=*/true,
|
|
/*additional_types_enabled=*/true);
|
|
DnsConfig config = ValidConfigWithDoh(false /* doh_only */);
|
|
config.unhandled_options = true;
|
|
client_->SetSystemConfig(config);
|
|
|
|
EXPECT_TRUE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_TRUE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
EXPECT_FALSE(client_->CanUseInsecureDnsTransactions());
|
|
EXPECT_TRUE(client_->FallbackFromInsecureTransactionPreferred());
|
|
|
|
DnsConfig expected_config = config;
|
|
expected_config.nameservers.clear();
|
|
EXPECT_THAT(client_->GetEffectiveConfig(), testing::Pointee(expected_config));
|
|
EXPECT_TRUE(client_->GetHosts());
|
|
EXPECT_TRUE(client_->GetTransactionFactory());
|
|
EXPECT_EQ(client_->GetCurrentSession()->config(), expected_config);
|
|
}
|
|
|
|
TEST_F(DnsClientTest, CanUseSecureDnsTransactions_ProbeSuccess) {
|
|
client_->SetSystemConfig(ValidConfigWithDoh(true /* doh_only */));
|
|
resolve_context_->InvalidateCachesAndPerSessionData(
|
|
client_->GetCurrentSession(), true /* network_change */);
|
|
|
|
EXPECT_TRUE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_TRUE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
|
|
resolve_context_->RecordServerSuccess(0u /* server_index */,
|
|
true /* is_doh_server */,
|
|
client_->GetCurrentSession());
|
|
EXPECT_TRUE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_FALSE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
}
|
|
|
|
TEST_F(DnsClientTest, DnsOverTlsActive) {
|
|
client_->SetInsecureEnabled(/*enabled=*/true,
|
|
/*additional_types_enabled=*/true);
|
|
DnsConfig config = ValidConfigWithDoh(false /* doh_only */);
|
|
config.dns_over_tls_active = true;
|
|
client_->SetSystemConfig(config);
|
|
|
|
EXPECT_TRUE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_TRUE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
EXPECT_FALSE(client_->CanUseInsecureDnsTransactions());
|
|
EXPECT_TRUE(client_->FallbackFromInsecureTransactionPreferred());
|
|
|
|
EXPECT_THAT(client_->GetEffectiveConfig(), testing::Pointee(config));
|
|
EXPECT_TRUE(client_->GetHosts());
|
|
EXPECT_TRUE(client_->GetTransactionFactory());
|
|
EXPECT_EQ(client_->GetCurrentSession()->config(), config);
|
|
}
|
|
|
|
TEST_F(DnsClientTest, AllAllowed) {
|
|
client_->SetInsecureEnabled(/*enabled=*/true,
|
|
/*additional_types_enabled=*/true);
|
|
client_->SetSystemConfig(ValidConfigWithDoh(false /* doh_only */));
|
|
resolve_context_->InvalidateCachesAndPerSessionData(
|
|
client_->GetCurrentSession(), false /* network_change */);
|
|
resolve_context_->RecordServerSuccess(0u /* server_index */,
|
|
true /* is_doh_server */,
|
|
client_->GetCurrentSession());
|
|
|
|
EXPECT_TRUE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_FALSE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
EXPECT_TRUE(client_->CanUseInsecureDnsTransactions());
|
|
EXPECT_TRUE(client_->CanQueryAdditionalTypesViaInsecureDns());
|
|
EXPECT_FALSE(client_->FallbackFromInsecureTransactionPreferred());
|
|
|
|
EXPECT_THAT(client_->GetEffectiveConfig(),
|
|
testing::Pointee(ValidConfigWithDoh(false /* doh_only */)));
|
|
EXPECT_TRUE(client_->GetHosts());
|
|
EXPECT_TRUE(client_->GetTransactionFactory());
|
|
EXPECT_EQ(client_->GetCurrentSession()->config(),
|
|
ValidConfigWithDoh(false /* doh_only */));
|
|
}
|
|
|
|
TEST_F(DnsClientTest, FallbackFromInsecureTransactionPreferred_Failures) {
|
|
client_->SetInsecureEnabled(/*enabled=*/true,
|
|
/*additional_types_enabled=*/true);
|
|
client_->SetSystemConfig(ValidConfigWithDoh(false /* doh_only */));
|
|
|
|
for (int i = 0; i < DnsClient::kMaxInsecureFallbackFailures; ++i) {
|
|
EXPECT_TRUE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_TRUE(client_->FallbackFromSecureTransactionPreferred(
|
|
resolve_context_.get()));
|
|
EXPECT_TRUE(client_->CanUseInsecureDnsTransactions());
|
|
EXPECT_TRUE(client_->CanQueryAdditionalTypesViaInsecureDns());
|
|
EXPECT_FALSE(client_->FallbackFromInsecureTransactionPreferred());
|
|
|
|
client_->IncrementInsecureFallbackFailures();
|
|
}
|
|
|
|
EXPECT_TRUE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_TRUE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
EXPECT_TRUE(client_->CanUseInsecureDnsTransactions());
|
|
EXPECT_TRUE(client_->CanQueryAdditionalTypesViaInsecureDns());
|
|
EXPECT_TRUE(client_->FallbackFromInsecureTransactionPreferred());
|
|
|
|
client_->ClearInsecureFallbackFailures();
|
|
|
|
EXPECT_TRUE(client_->CanUseSecureDnsTransactions());
|
|
EXPECT_TRUE(
|
|
client_->FallbackFromSecureTransactionPreferred(resolve_context_.get()));
|
|
EXPECT_TRUE(client_->CanUseInsecureDnsTransactions());
|
|
EXPECT_TRUE(client_->CanQueryAdditionalTypesViaInsecureDns());
|
|
EXPECT_FALSE(client_->FallbackFromInsecureTransactionPreferred());
|
|
}
|
|
|
|
TEST_F(DnsClientTest, GetPresetAddrs) {
|
|
DnsConfig config;
|
|
config.doh_config = *net::DnsOverHttpsConfig::FromString(R"(
|
|
{
|
|
"servers": [{
|
|
"template": "https://www.doh.com/",
|
|
"endpoints": [{
|
|
"ips": ["4.3.2.1"]
|
|
}, {
|
|
"ips": ["4.3.2.2"]
|
|
}]
|
|
}]
|
|
}
|
|
)");
|
|
client_->SetSystemConfig(config);
|
|
|
|
EXPECT_FALSE(client_->GetPresetAddrs(
|
|
url::SchemeHostPort("https", "otherdomain.com", 443)));
|
|
EXPECT_FALSE(
|
|
client_->GetPresetAddrs(url::SchemeHostPort("http", "www.doh.com", 443)));
|
|
EXPECT_FALSE(client_->GetPresetAddrs(
|
|
url::SchemeHostPort("https", "www.doh.com", 9999)));
|
|
|
|
std::vector<IPEndPoint> expected({{{4, 3, 2, 1}, 443}, {{4, 3, 2, 2}, 443}});
|
|
|
|
EXPECT_THAT(
|
|
client_->GetPresetAddrs(url::SchemeHostPort("https", "www.doh.com", 443)),
|
|
testing::Optional(expected));
|
|
}
|
|
|
|
TEST_F(DnsClientTest, Override) {
|
|
client_->SetSystemConfig(BasicValidConfig());
|
|
EXPECT_THAT(client_->GetEffectiveConfig(),
|
|
testing::Pointee(BasicValidConfig()));
|
|
EXPECT_EQ(client_->GetCurrentSession()->config(), BasicValidConfig());
|
|
|
|
client_->SetConfigOverrides(BasicValidOverrides());
|
|
EXPECT_THAT(client_->GetEffectiveConfig(),
|
|
testing::Pointee(
|
|
BasicValidOverrides().ApplyOverrides(BasicValidConfig())));
|
|
EXPECT_EQ(client_->GetCurrentSession()->config(),
|
|
BasicValidOverrides().ApplyOverrides(BasicValidConfig()));
|
|
|
|
client_->SetConfigOverrides(DnsConfigOverrides());
|
|
EXPECT_THAT(client_->GetEffectiveConfig(),
|
|
testing::Pointee(BasicValidConfig()));
|
|
EXPECT_EQ(client_->GetCurrentSession()->config(), BasicValidConfig());
|
|
}
|
|
|
|
// Cannot apply overrides without a system config unless everything is
|
|
// overridden
|
|
TEST_F(DnsClientTest, OverrideNoConfig) {
|
|
client_->SetConfigOverrides(BasicValidOverrides());
|
|
EXPECT_FALSE(client_->GetEffectiveConfig());
|
|
EXPECT_FALSE(client_->GetCurrentSession());
|
|
|
|
auto override_everything =
|
|
DnsConfigOverrides::CreateOverridingEverythingWithDefaults();
|
|
override_everything.nameservers.emplace(
|
|
{IPEndPoint(IPAddress(1, 2, 3, 4), 123)});
|
|
client_->SetConfigOverrides(override_everything);
|
|
EXPECT_THAT(
|
|
client_->GetEffectiveConfig(),
|
|
testing::Pointee(override_everything.ApplyOverrides(DnsConfig())));
|
|
EXPECT_EQ(client_->GetCurrentSession()->config(),
|
|
override_everything.ApplyOverrides(DnsConfig()));
|
|
}
|
|
|
|
TEST_F(DnsClientTest, OverrideInvalidConfig) {
|
|
client_->SetSystemConfig(DnsConfig());
|
|
EXPECT_FALSE(client_->GetEffectiveConfig());
|
|
EXPECT_FALSE(client_->GetCurrentSession());
|
|
|
|
client_->SetConfigOverrides(BasicValidOverrides());
|
|
EXPECT_THAT(client_->GetEffectiveConfig(),
|
|
testing::Pointee(
|
|
BasicValidOverrides().ApplyOverrides(BasicValidConfig())));
|
|
EXPECT_EQ(client_->GetCurrentSession()->config(),
|
|
BasicValidOverrides().ApplyOverrides(DnsConfig()));
|
|
}
|
|
|
|
TEST_F(DnsClientTest, OverrideToInvalid) {
|
|
client_->SetSystemConfig(BasicValidConfig());
|
|
EXPECT_THAT(client_->GetEffectiveConfig(),
|
|
testing::Pointee(BasicValidConfig()));
|
|
EXPECT_EQ(client_->GetCurrentSession()->config(), BasicValidConfig());
|
|
|
|
DnsConfigOverrides overrides;
|
|
overrides.nameservers.emplace();
|
|
client_->SetConfigOverrides(std::move(overrides));
|
|
|
|
EXPECT_FALSE(client_->GetEffectiveConfig());
|
|
EXPECT_FALSE(client_->GetCurrentSession());
|
|
}
|
|
|
|
TEST_F(DnsClientTest, ReplaceCurrentSession) {
|
|
client_->SetSystemConfig(BasicValidConfig());
|
|
|
|
base::WeakPtr<DnsSession> session_before =
|
|
client_->GetCurrentSession()->GetWeakPtr();
|
|
ASSERT_TRUE(session_before);
|
|
|
|
client_->ReplaceCurrentSession();
|
|
|
|
EXPECT_FALSE(session_before);
|
|
EXPECT_TRUE(client_->GetCurrentSession());
|
|
}
|
|
|
|
TEST_F(DnsClientTest, ReplaceCurrentSession_NoSession) {
|
|
ASSERT_FALSE(client_->GetCurrentSession());
|
|
|
|
client_->ReplaceCurrentSession();
|
|
|
|
EXPECT_FALSE(client_->GetCurrentSession());
|
|
}
|
|
|
|
} // namespace
|
|
|
|
} // namespace net
|