mirror of
https://github.com/Alex313031/thorium.git
synced 2025-01-10 11:57:48 -03:00
Add files via upload
This commit is contained in:
parent
c1f9373e36
commit
8dfa33cf9c
1 changed files with 341 additions and 0 deletions
341
src/net/dns/dns_client.cc
Normal file
341
src/net/dns/dns_client.cc
Normal file
|
@ -0,0 +1,341 @@
|
||||||
|
// Copyright (c) 2022 The Chromium Authors and Alex313031. All rights reserved.
|
||||||
|
// 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 <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "base/bind.h"
|
||||||
|
#include "base/memory/raw_ptr.h"
|
||||||
|
#include "base/metrics/histogram_macros.h"
|
||||||
|
#include "base/rand_util.h"
|
||||||
|
#include "base/ranges/algorithm.h"
|
||||||
|
#include "base/values.h"
|
||||||
|
#include "net/base/ip_address.h"
|
||||||
|
#include "net/base/ip_endpoint.h"
|
||||||
|
#include "net/dns/address_sorter.h"
|
||||||
|
#include "net/dns/dns_session.h"
|
||||||
|
#include "net/dns/dns_transaction.h"
|
||||||
|
#include "net/dns/dns_util.h"
|
||||||
|
#include "net/dns/public/dns_over_https_config.h"
|
||||||
|
#include "net/dns/public/secure_dns_mode.h"
|
||||||
|
#include "net/dns/resolve_context.h"
|
||||||
|
#include "net/log/net_log.h"
|
||||||
|
#include "net/log/net_log_event_type.h"
|
||||||
|
#include "net/socket/client_socket_factory.h"
|
||||||
|
#include "net/third_party/uri_template/uri_template.h"
|
||||||
|
#include "url/gurl.h"
|
||||||
|
#include "url/scheme_host_port.h"
|
||||||
|
|
||||||
|
namespace net {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool IsEqual(const absl::optional<DnsConfig>& c1, const DnsConfig* c2) {
|
||||||
|
if (!c1.has_value() && c2 == nullptr)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!c1.has_value() || c2 == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return c1.value() == *c2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateConfigForDohUpgrade(DnsConfig* config) {
|
||||||
|
bool has_doh_servers = !config->doh_config.servers().empty();
|
||||||
|
// Do not attempt upgrade when there are already DoH servers specified or
|
||||||
|
// when there are aspects of the system DNS config that are unhandled.
|
||||||
|
if (!config->unhandled_options && config->allow_dns_over_https_upgrade &&
|
||||||
|
!has_doh_servers &&
|
||||||
|
config->secure_dns_mode == SecureDnsMode::kAutomatic) {
|
||||||
|
// If we're in strict mode on Android, only attempt to upgrade the
|
||||||
|
// specified DoT hostname.
|
||||||
|
if (!config->dns_over_tls_hostname.empty()) {
|
||||||
|
config->doh_config = DnsOverHttpsConfig(
|
||||||
|
GetDohUpgradeServersFromDotHostname(config->dns_over_tls_hostname));
|
||||||
|
has_doh_servers = !config->doh_config.servers().empty();
|
||||||
|
UMA_HISTOGRAM_BOOLEAN("Net.DNS.UpgradeConfig.DotUpgradeSucceeded",
|
||||||
|
has_doh_servers);
|
||||||
|
} else {
|
||||||
|
bool all_local = true;
|
||||||
|
for (const auto& server : config->nameservers) {
|
||||||
|
if (server.address().IsPubliclyRoutable()) {
|
||||||
|
all_local = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UMA_HISTOGRAM_BOOLEAN("Net.DNS.UpgradeConfig.HasPublicInsecureNameserver",
|
||||||
|
!all_local);
|
||||||
|
|
||||||
|
config->doh_config = DnsOverHttpsConfig(
|
||||||
|
GetDohUpgradeServersFromNameservers(config->nameservers));
|
||||||
|
has_doh_servers = !config->doh_config.servers().empty();
|
||||||
|
UMA_HISTOGRAM_BOOLEAN("Net.DNS.UpgradeConfig.InsecureUpgradeSucceeded",
|
||||||
|
has_doh_servers);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
UMA_HISTOGRAM_BOOLEAN("Net.DNS.UpgradeConfig.Ineligible.DohSpecified",
|
||||||
|
has_doh_servers);
|
||||||
|
UMA_HISTOGRAM_BOOLEAN("Net.DNS.UpgradeConfig.Ineligible.UnhandledOptions",
|
||||||
|
config->unhandled_options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DnsClientImpl : public DnsClient {
|
||||||
|
public:
|
||||||
|
DnsClientImpl(NetLog* net_log, const RandIntCallback& rand_int_callback)
|
||||||
|
: net_log_(net_log), rand_int_callback_(rand_int_callback) {}
|
||||||
|
|
||||||
|
DnsClientImpl(const DnsClientImpl&) = delete;
|
||||||
|
DnsClientImpl& operator=(const DnsClientImpl&) = delete;
|
||||||
|
|
||||||
|
~DnsClientImpl() override = default;
|
||||||
|
|
||||||
|
bool CanUseSecureDnsTransactions() const override {
|
||||||
|
const DnsConfig* config = GetEffectiveConfig();
|
||||||
|
return config && !config->doh_config.servers().empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanUseInsecureDnsTransactions() const override {
|
||||||
|
const DnsConfig* config = GetEffectiveConfig();
|
||||||
|
return config && config->nameservers.size() > 0 && insecure_enabled_ &&
|
||||||
|
!config->unhandled_options && !config->dns_over_tls_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanQueryAdditionalTypesViaInsecureDns() const override {
|
||||||
|
// Only useful information if insecure DNS is usable, so expect this to
|
||||||
|
// never be called if that is not the case.
|
||||||
|
DCHECK(CanUseInsecureDnsTransactions());
|
||||||
|
|
||||||
|
return can_query_additional_types_via_insecure_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetInsecureEnabled(bool enabled,
|
||||||
|
bool additional_types_enabled) override {
|
||||||
|
insecure_enabled_ = enabled;
|
||||||
|
can_query_additional_types_via_insecure_ = additional_types_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FallbackFromSecureTransactionPreferred(
|
||||||
|
ResolveContext* context) const override {
|
||||||
|
if (!CanUseSecureDnsTransactions())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
DCHECK(session_); // Should be true if CanUseSecureDnsTransactions() true.
|
||||||
|
return context->NumAvailableDohServers(session_.get()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FallbackFromInsecureTransactionPreferred() const override {
|
||||||
|
return !CanUseInsecureDnsTransactions() ||
|
||||||
|
insecure_fallback_failures_ >= kMaxInsecureFallbackFailures;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetSystemConfig(absl::optional<DnsConfig> system_config) override {
|
||||||
|
if (system_config == system_config_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
system_config_ = std::move(system_config);
|
||||||
|
|
||||||
|
return UpdateDnsConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetConfigOverrides(DnsConfigOverrides config_overrides) override {
|
||||||
|
if (config_overrides == config_overrides_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
config_overrides_ = std::move(config_overrides);
|
||||||
|
|
||||||
|
return UpdateDnsConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplaceCurrentSession() override {
|
||||||
|
if (!session_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UpdateSession(session_->config());
|
||||||
|
}
|
||||||
|
|
||||||
|
DnsSession* GetCurrentSession() override { return session_.get(); }
|
||||||
|
|
||||||
|
const DnsConfig* GetEffectiveConfig() const override {
|
||||||
|
if (!session_)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
DCHECK(session_->config().IsValid());
|
||||||
|
return &session_->config();
|
||||||
|
}
|
||||||
|
|
||||||
|
const DnsHosts* GetHosts() const override {
|
||||||
|
const DnsConfig* config = GetEffectiveConfig();
|
||||||
|
if (!config)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return &config->hosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::optional<std::vector<IPEndPoint>> GetPresetAddrs(
|
||||||
|
const url::SchemeHostPort& endpoint) const override {
|
||||||
|
DCHECK(endpoint.IsValid());
|
||||||
|
if (!session_)
|
||||||
|
return absl::nullopt;
|
||||||
|
const auto& servers = session_->config().doh_config.servers();
|
||||||
|
auto it = base::ranges::find_if(servers, [&](const auto& server) {
|
||||||
|
std::string uri;
|
||||||
|
bool valid = uri_template::Expand(server.server_template(), {}, &uri);
|
||||||
|
// Server templates are validated before being allowed into the config.
|
||||||
|
DCHECK(valid);
|
||||||
|
GURL gurl(uri);
|
||||||
|
return url::SchemeHostPort(gurl) == endpoint;
|
||||||
|
});
|
||||||
|
if (it == servers.end())
|
||||||
|
return absl::nullopt;
|
||||||
|
std::vector<IPEndPoint> combined;
|
||||||
|
for (const IPAddressList& ips : it->endpoints()) {
|
||||||
|
for (const IPAddress& ip : ips) {
|
||||||
|
combined.emplace_back(ip, endpoint.port());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return combined;
|
||||||
|
}
|
||||||
|
|
||||||
|
DnsTransactionFactory* GetTransactionFactory() override {
|
||||||
|
return session_.get() ? factory_.get() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressSorter* GetAddressSorter() override { return address_sorter_.get(); }
|
||||||
|
|
||||||
|
void IncrementInsecureFallbackFailures() override {
|
||||||
|
++insecure_fallback_failures_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearInsecureFallbackFailures() override {
|
||||||
|
insecure_fallback_failures_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
base::Value GetDnsConfigAsValueForNetLog() const override {
|
||||||
|
const DnsConfig* config = GetEffectiveConfig();
|
||||||
|
if (config == nullptr)
|
||||||
|
return base::Value(base::Value::Dict());
|
||||||
|
base::Value value = config->ToValue();
|
||||||
|
DCHECK(value.is_dict());
|
||||||
|
base::Value::Dict& dict = value.GetDict();
|
||||||
|
dict.Set("can_use_secure_dns_transactions", CanUseSecureDnsTransactions());
|
||||||
|
dict.Set("can_use_insecure_dns_transactions",
|
||||||
|
CanUseInsecureDnsTransactions());
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::optional<DnsConfig> GetSystemConfigForTesting() const override {
|
||||||
|
return system_config_;
|
||||||
|
}
|
||||||
|
|
||||||
|
DnsConfigOverrides GetConfigOverridesForTesting() const override {
|
||||||
|
return config_overrides_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTransactionFactoryForTesting(
|
||||||
|
std::unique_ptr<DnsTransactionFactory> factory) override {
|
||||||
|
factory_ = std::move(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
absl::optional<DnsConfig> BuildEffectiveConfig() const {
|
||||||
|
DnsConfig config;
|
||||||
|
// in Bromite it is sufficient to have secure DoH enabled to give the overrides priority
|
||||||
|
if (config_overrides_.dns_over_https_config && config_overrides_.secure_dns_mode) {
|
||||||
|
config = config_overrides_.ApplyOverrides(DnsConfig());
|
||||||
|
} else {
|
||||||
|
if (!system_config_) {
|
||||||
|
LOG(WARNING) << "BuildEffectiveConfig(): no system configuration";
|
||||||
|
return absl::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
config = config_overrides_.ApplyOverrides(system_config_.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateConfigForDohUpgrade(&config);
|
||||||
|
|
||||||
|
// TODO(ericorth): Consider keeping a separate DnsConfig for pure Chrome-
|
||||||
|
// produced configs to allow respecting all fields like |unhandled_options|
|
||||||
|
// while still being able to fallback to system config for DoH.
|
||||||
|
// For now, clear the nameservers for extra security if parts of the system
|
||||||
|
// config are unhandled.
|
||||||
|
if (config.unhandled_options)
|
||||||
|
config.nameservers.clear();
|
||||||
|
|
||||||
|
if (!config.IsValid()) {
|
||||||
|
LOG(WARNING) << "BuildEffectiveConfig(): invalid configuration";
|
||||||
|
return absl::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UpdateDnsConfig() {
|
||||||
|
absl::optional<DnsConfig> new_effective_config = BuildEffectiveConfig();
|
||||||
|
|
||||||
|
if (IsEqual(new_effective_config, GetEffectiveConfig()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
insecure_fallback_failures_ = 0;
|
||||||
|
UpdateSession(std::move(new_effective_config));
|
||||||
|
|
||||||
|
if (net_log_) {
|
||||||
|
net_log_->AddGlobalEntry(NetLogEventType::DNS_CONFIG_CHANGED, [this] {
|
||||||
|
return GetDnsConfigAsValueForNetLog();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateSession(absl::optional<DnsConfig> new_effective_config) {
|
||||||
|
factory_.reset();
|
||||||
|
session_ = nullptr;
|
||||||
|
|
||||||
|
if (new_effective_config) {
|
||||||
|
DCHECK(new_effective_config.value().IsValid());
|
||||||
|
|
||||||
|
session_ = base::MakeRefCounted<DnsSession>(
|
||||||
|
std::move(new_effective_config).value(), rand_int_callback_,
|
||||||
|
net_log_);
|
||||||
|
factory_ = DnsTransactionFactory::CreateFactory(session_.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insecure_enabled_ = false;
|
||||||
|
bool can_query_additional_types_via_insecure_ = false;
|
||||||
|
int insecure_fallback_failures_ = 0;
|
||||||
|
|
||||||
|
absl::optional<DnsConfig> system_config_;
|
||||||
|
DnsConfigOverrides config_overrides_;
|
||||||
|
|
||||||
|
scoped_refptr<DnsSession> session_;
|
||||||
|
std::unique_ptr<DnsTransactionFactory> factory_;
|
||||||
|
std::unique_ptr<AddressSorter> address_sorter_ =
|
||||||
|
AddressSorter::CreateAddressSorter();
|
||||||
|
|
||||||
|
raw_ptr<NetLog> net_log_;
|
||||||
|
|
||||||
|
const RandIntCallback rand_int_callback_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::unique_ptr<DnsClient> DnsClient::CreateClient(NetLog* net_log) {
|
||||||
|
return std::make_unique<DnsClientImpl>(net_log,
|
||||||
|
base::BindRepeating(&base::RandInt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::unique_ptr<DnsClient> DnsClient::CreateClientForTesting(
|
||||||
|
NetLog* net_log,
|
||||||
|
const RandIntCallback& rand_int_callback) {
|
||||||
|
return std::make_unique<DnsClientImpl>(net_log, rand_int_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace net
|
Loading…
Reference in a new issue