Commit 3ad1745a authored by tfarina's avatar tfarina Committed by Commit bot

net: move IsHostnameNonUnique() into url_util.h

This patch moves this free function from generic net_util.h header,
into url_util.h, because it operates on a URL part (hostname), so it
seems more appropriate there than in the soon-to-go-way net_util.h.

BUG=488531
TEST=net_unittests --gtest_filter=UrlUtil*
R=eroman@chromium.org
TBR=felt@chromium.org

Review URL: https://codereview.chromium.org/1629733002

Cr-Commit-Position: refs/heads/master@{#371768}
parent f3fdb386
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "net/base/net_util.h" #include "net/base/net_util.h"
#include "net/base/network_change_notifier.h" #include "net/base/network_change_notifier.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/url_util.h"
#include "net/cert/x509_cert_types.h" #include "net/cert/x509_cert_types.h"
#include "net/cert/x509_certificate.h" #include "net/cert/x509_certificate.h"
#include "url/gurl.h" #include "url/gurl.h"
......
...@@ -14,9 +14,6 @@ ...@@ -14,9 +14,6 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "net/base/address_list.h" #include "net/base/address_list.h"
#include "net/base/ip_address_number.h" #include "net/base/ip_address_number.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/url_util.h"
#include "url/url_canon_ip.h"
#if defined(OS_WIN) #if defined(OS_WIN)
#include "net/base/winsock_init.h" #include "net/base/winsock_init.h"
...@@ -50,52 +47,6 @@ bool IsLocal6Hostname(const std::string& host) { ...@@ -50,52 +47,6 @@ bool IsLocal6Hostname(const std::string& host) {
} // namespace } // namespace
bool IsHostnameNonUnique(const std::string& hostname) {
// CanonicalizeHost requires surrounding brackets to parse an IPv6 address.
const std::string host_or_ip = hostname.find(':') != std::string::npos ?
"[" + hostname + "]" : hostname;
url::CanonHostInfo host_info;
std::string canonical_name = CanonicalizeHost(host_or_ip, &host_info);
// If canonicalization fails, then the input is truly malformed. However,
// to avoid mis-reporting bad inputs as "non-unique", treat them as unique.
if (canonical_name.empty())
return false;
// If |hostname| is an IP address, check to see if it's in an IANA-reserved
// range.
if (host_info.IsIPAddress()) {
IPAddressNumber host_addr;
if (!ParseIPLiteralToNumber(hostname.substr(host_info.out_host.begin,
host_info.out_host.len),
&host_addr)) {
return false;
}
switch (host_info.family) {
case url::CanonHostInfo::IPV4:
case url::CanonHostInfo::IPV6:
return IsIPAddressReserved(host_addr);
case url::CanonHostInfo::NEUTRAL:
case url::CanonHostInfo::BROKEN:
return false;
}
}
// Check for a registry controlled portion of |hostname|, ignoring private
// registries, as they already chain to ICANN-administered registries,
// and explicitly ignoring unknown registries.
//
// Note: This means that as new gTLDs are introduced on the Internet, they
// will be treated as non-unique until the registry controlled domain list
// is updated. However, because gTLDs are expected to provide significant
// advance notice to deprecate older versions of this code, this an
// acceptable tradeoff.
return 0 == registry_controlled_domains::GetRegistryLength(
canonical_name,
registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
}
std::string GetHostName() { std::string GetHostName() {
#if defined(OS_NACL) #if defined(OS_NACL)
NOTIMPLEMENTED(); NOTIMPLEMENTED();
......
...@@ -16,11 +16,6 @@ namespace net { ...@@ -16,11 +16,6 @@ namespace net {
class AddressList; class AddressList;
// Returns true if |hostname| contains a non-registerable or non-assignable
// domain name (eg: a gTLD that has not been assigned by IANA) or an IP address
// that falls in an IANA-reserved range.
NET_EXPORT bool IsHostnameNonUnique(const std::string& hostname);
// Returns the hostname of the current system. Returns empty string on failure. // Returns the hostname of the current system. Returns empty string on failure.
NET_EXPORT std::string GetHostName(); NET_EXPORT std::string GetHostName();
......
...@@ -4,31 +4,10 @@ ...@@ -4,31 +4,10 @@
#include "net/base/net_util.h" #include "net/base/net_util.h"
#include <ostream>
#include "base/format_macros.h" #include "base/format_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/address_list.h" #include "net/base/address_list.h"
#include "net/base/ip_endpoint.h" #include "net/base/ip_endpoint.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#if !defined(OS_NACL) && !defined(OS_WIN)
#include <net/if.h>
#include <netinet/in.h>
#if defined(OS_MACOSX)
#include <ifaddrs.h>
#if !defined(OS_IOS)
#include <netinet/in_var.h>
#endif // !OS_IOS
#endif // OS_MACOSX
#endif // !OS_NACL && !OS_WIN
#if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_WIN)
#include "net/base/address_tracker_linux.h"
#endif // !OS_MACOSX && !OS_NACL && !OS_WIN
namespace net { namespace net {
...@@ -188,83 +167,4 @@ TEST(NetUtilTest, ResolveLocalHostname) { ...@@ -188,83 +167,4 @@ TEST(NetUtilTest, ResolveLocalHostname) {
ResolveLocalHostname("foo.localhoste", kLocalhostLookupPort, &addresses)); ResolveLocalHostname("foo.localhoste", kLocalhostLookupPort, &addresses));
} }
struct NonUniqueNameTestData {
bool is_unique;
const char* const hostname;
};
// Google Test pretty-printer.
void PrintTo(const NonUniqueNameTestData& data, std::ostream* os) {
ASSERT_TRUE(data.hostname);
*os << " hostname: " << testing::PrintToString(data.hostname)
<< "; is_unique: " << testing::PrintToString(data.is_unique);
}
const NonUniqueNameTestData kNonUniqueNameTestData[] = {
// Domains under ICANN-assigned domains.
{ true, "google.com" },
{ true, "google.co.uk" },
// Domains under private registries.
{ true, "appspot.com" },
{ true, "test.appspot.com" },
// Unreserved IPv4 addresses (in various forms).
{ true, "8.8.8.8" },
{ true, "99.64.0.0" },
{ true, "212.15.0.0" },
{ true, "212.15" },
{ true, "212.15.0" },
{ true, "3557752832" },
// Reserved IPv4 addresses (in various forms).
{ false, "192.168.0.0" },
{ false, "192.168.0.6" },
{ false, "10.0.0.5" },
{ false, "10.0" },
{ false, "10.0.0" },
{ false, "3232235526" },
// Unreserved IPv6 addresses.
{ true, "FFC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
{ true, "2000:ba98:7654:2301:EFCD:BA98:7654:3210" },
// Reserved IPv6 addresses.
{ false, "::192.9.5.5" },
{ false, "FEED::BEEF" },
{ false, "FEC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
// 'internal'/non-IANA assigned domains.
{ false, "intranet" },
{ false, "intranet." },
{ false, "intranet.example" },
{ false, "host.intranet.example" },
// gTLDs under discussion, but not yet assigned.
{ false, "intranet.corp" },
{ false, "intranet.internal" },
// Invalid host names are treated as unique - but expected to be
// filtered out before then.
{ true, "junk)(£)$*!@~#" },
{ true, "w$w.example.com" },
{ true, "nocolonsallowed:example" },
{ true, "[::4.5.6.9]" },
};
class NetUtilNonUniqueNameTest
: public testing::TestWithParam<NonUniqueNameTestData> {
public:
virtual ~NetUtilNonUniqueNameTest() {}
protected:
bool IsUnique(const std::string& hostname) {
return !IsHostnameNonUnique(hostname);
}
};
// Test that internal/non-unique names are properly identified as such, but
// that IP addresses and hosts beneath registry-controlled domains are flagged
// as unique names.
TEST_P(NetUtilNonUniqueNameTest, IsHostnameNonUnique) {
const NonUniqueNameTestData& test_data = GetParam();
EXPECT_EQ(test_data.is_unique, IsUnique(test_data.hostname));
}
INSTANTIATE_TEST_CASE_P(, NetUtilNonUniqueNameTest,
testing::ValuesIn(kNonUniqueNameTestData));
} // namespace net } // namespace net
...@@ -8,8 +8,9 @@ ...@@ -8,8 +8,9 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "net/base/escape.h" #include "net/base/escape.h"
#include "net/base/ip_address_number.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "url/gurl.h" #include "url/gurl.h"
#include "url/third_party/mozilla/url_parse.h"
#include "url/url_canon.h" #include "url/url_canon.h"
#include "url/url_canon_ip.h" #include "url/url_canon_ip.h"
...@@ -292,6 +293,52 @@ bool IsCanonicalizedHostCompliant(const std::string& host) { ...@@ -292,6 +293,52 @@ bool IsCanonicalizedHostCompliant(const std::string& host) {
return most_recent_component_started_alphanumeric; return most_recent_component_started_alphanumeric;
} }
bool IsHostnameNonUnique(const std::string& hostname) {
// CanonicalizeHost requires surrounding brackets to parse an IPv6 address.
const std::string host_or_ip = hostname.find(':') != std::string::npos ?
"[" + hostname + "]" : hostname;
url::CanonHostInfo host_info;
std::string canonical_name = CanonicalizeHost(host_or_ip, &host_info);
// If canonicalization fails, then the input is truly malformed. However,
// to avoid mis-reporting bad inputs as "non-unique", treat them as unique.
if (canonical_name.empty())
return false;
// If |hostname| is an IP address, check to see if it's in an IANA-reserved
// range.
if (host_info.IsIPAddress()) {
IPAddressNumber host_addr;
if (!ParseIPLiteralToNumber(hostname.substr(host_info.out_host.begin,
host_info.out_host.len),
&host_addr)) {
return false;
}
switch (host_info.family) {
case url::CanonHostInfo::IPV4:
case url::CanonHostInfo::IPV6:
return IsIPAddressReserved(host_addr);
case url::CanonHostInfo::NEUTRAL:
case url::CanonHostInfo::BROKEN:
return false;
}
}
// Check for a registry controlled portion of |hostname|, ignoring private
// registries, as they already chain to ICANN-administered registries,
// and explicitly ignoring unknown registries.
//
// Note: This means that as new gTLDs are introduced on the Internet, they
// will be treated as non-unique until the registry controlled domain list
// is updated. However, because gTLDs are expected to provide significant
// advance notice to deprecate older versions of this code, this an
// acceptable tradeoff.
return 0 == registry_controlled_domains::GetRegistryLength(
canonical_name,
registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
}
GURL SimplifyUrlForRequest(const GURL& url) { GURL SimplifyUrlForRequest(const GURL& url) {
DCHECK(url.is_valid()); DCHECK(url.is_valid());
GURL::Replacements replacements; GURL::Replacements replacements;
......
...@@ -132,6 +132,11 @@ NET_EXPORT std::string CanonicalizeHost(base::StringPiece host, ...@@ -132,6 +132,11 @@ NET_EXPORT std::string CanonicalizeHost(base::StringPiece host,
// CanonicalizeHost(), or you may not get accurate results. // CanonicalizeHost(), or you may not get accurate results.
NET_EXPORT bool IsCanonicalizedHostCompliant(const std::string& host); NET_EXPORT bool IsCanonicalizedHostCompliant(const std::string& host);
// Returns true if |hostname| contains a non-registerable or non-assignable
// domain name (eg: a gTLD that has not been assigned by IANA) or an IP address
// that falls in an IANA-reserved range.
NET_EXPORT bool IsHostnameNonUnique(const std::string& hostname);
// Strip the portions of |url| that aren't core to the network request. // Strip the portions of |url| that aren't core to the network request.
// - user name / password // - user name / password
// - reference section // - reference section
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "net/base/url_util.h" #include "net/base/url_util.h"
#include <ostream>
#include "base/format_macros.h" #include "base/format_macros.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
...@@ -306,6 +308,85 @@ TEST(UrlUtilTest, CompliantHost) { ...@@ -306,6 +308,85 @@ TEST(UrlUtilTest, CompliantHost) {
} }
} }
struct NonUniqueNameTestData {
bool is_unique;
const char* const hostname;
};
// Google Test pretty-printer.
void PrintTo(const NonUniqueNameTestData& data, std::ostream* os) {
ASSERT_TRUE(data.hostname);
*os << " hostname: " << testing::PrintToString(data.hostname)
<< "; is_unique: " << testing::PrintToString(data.is_unique);
}
const NonUniqueNameTestData kNonUniqueNameTestData[] = {
// Domains under ICANN-assigned domains.
{ true, "google.com" },
{ true, "google.co.uk" },
// Domains under private registries.
{ true, "appspot.com" },
{ true, "test.appspot.com" },
// Unreserved IPv4 addresses (in various forms).
{ true, "8.8.8.8" },
{ true, "99.64.0.0" },
{ true, "212.15.0.0" },
{ true, "212.15" },
{ true, "212.15.0" },
{ true, "3557752832" },
// Reserved IPv4 addresses (in various forms).
{ false, "192.168.0.0" },
{ false, "192.168.0.6" },
{ false, "10.0.0.5" },
{ false, "10.0" },
{ false, "10.0.0" },
{ false, "3232235526" },
// Unreserved IPv6 addresses.
{ true, "FFC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
{ true, "2000:ba98:7654:2301:EFCD:BA98:7654:3210" },
// Reserved IPv6 addresses.
{ false, "::192.9.5.5" },
{ false, "FEED::BEEF" },
{ false, "FEC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
// 'internal'/non-IANA assigned domains.
{ false, "intranet" },
{ false, "intranet." },
{ false, "intranet.example" },
{ false, "host.intranet.example" },
// gTLDs under discussion, but not yet assigned.
{ false, "intranet.corp" },
{ false, "intranet.internal" },
// Invalid host names are treated as unique - but expected to be
// filtered out before then.
{ true, "junk)(£)$*!@~#" },
{ true, "w$w.example.com" },
{ true, "nocolonsallowed:example" },
{ true, "[::4.5.6.9]" },
};
class UrlUtilNonUniqueNameTest
: public testing::TestWithParam<NonUniqueNameTestData> {
public:
virtual ~UrlUtilNonUniqueNameTest() {}
protected:
bool IsUnique(const std::string& hostname) {
return !IsHostnameNonUnique(hostname);
}
};
// Test that internal/non-unique names are properly identified as such, but
// that IP addresses and hosts beneath registry-controlled domains are flagged
// as unique names.
TEST_P(UrlUtilNonUniqueNameTest, IsHostnameNonUnique) {
const NonUniqueNameTestData& test_data = GetParam();
EXPECT_EQ(test_data.is_unique, IsUnique(test_data.hostname));
}
INSTANTIATE_TEST_CASE_P(, UrlUtilNonUniqueNameTest,
testing::ValuesIn(kNonUniqueNameTestData));
TEST(UrlUtilTest, SimplifyUrlForRequest) { TEST(UrlUtilTest, SimplifyUrlForRequest) {
struct { struct {
const char* const input_url; const char* const input_url;
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/url_util.h" #include "net/base/url_util.h"
#include "net/cert/cert_status_flags.h" #include "net/cert/cert_status_flags.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment