Commit 91dd3606 authored by eroman's avatar eroman Committed by Commit bot

Fail DNS resolution if the result contains 127.0.53.53.

ICANN designated the IPv4 address 127.0.53.53 as meaning a name collision occurred during resolution (as a way to discover real world conflicts around the new gTLDs).

This change makes such resolutions now fail with:
  ICANN_NAME_COLLISION.

IP literals are exempt from the policy and will continue to work as before (meaning you can still navigate to http://127.0.53.53).

This only affects IPv4 results.

BUG=470704

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

Cr-Commit-Position: refs/heads/master@{#322309}
parent 9ac40f44
...@@ -340,6 +340,12 @@ NET_ERROR(SSL_CLIENT_AUTH_CERT_BAD_FORMAT, -164) ...@@ -340,6 +340,12 @@ NET_ERROR(SSL_CLIENT_AUTH_CERT_BAD_FORMAT, -164)
// minimum fallback version, and thus fallback failed. // minimum fallback version, and thus fallback failed.
NET_ERROR(SSL_FALLBACK_BEYOND_MINIMUM_VERSION, -165) NET_ERROR(SSL_FALLBACK_BEYOND_MINIMUM_VERSION, -165)
// Resolving a hostname to an IP address list included the IPv4 address
// "127.0.53.53". This is a special IP address which ICANN has recommended to
// indicate there was a name collision, and alert admins to a potential
// problem.
NET_ERROR(ICANN_NAME_COLLISION, -166)
// Certificate error codes // Certificate error codes
// //
// The values of certificate error codes must be consecutive. // The values of certificate error codes must be consecutive.
......
...@@ -144,6 +144,17 @@ enum DnsResolveStatus { ...@@ -144,6 +144,17 @@ enum DnsResolveStatus {
RESOLVE_STATUS_MAX RESOLVE_STATUS_MAX
}; };
// ICANN uses this localhost address to indicate a name collision.
//
// The policy in Chromium is to fail host resolving if it resolves to
// this special address.
//
// Not however that IP literals are exempt from this policy, so it is still
// possible to navigate to http://127.0.53.53/ directly.
//
// For more details: https://www.icann.org/news/announcement-2-2014-08-01-en
const unsigned char kIcanNameCollisionIp[] = {127, 0, 53, 53};
void UmaAsyncDnsResolveStatus(DnsResolveStatus result) { void UmaAsyncDnsResolveStatus(DnsResolveStatus result) {
UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ResolveStatus", UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ResolveStatus",
result, result,
...@@ -663,6 +674,17 @@ class HostResolverImpl::ProcTask ...@@ -663,6 +674,17 @@ class HostResolverImpl::ProcTask
&results, &results,
&os_error); &os_error);
// Fail the resolution if the result contains 127.0.53.53. See the comment
// block of kIcanNameCollisionIp for details on why.
for (const auto& it : results) {
const IPAddressNumber& cur = it.address();
if (cur.size() == arraysize(kIcanNameCollisionIp) &&
0 == memcmp(&cur.front(), kIcanNameCollisionIp, cur.size())) {
error = ERR_ICANN_NAME_COLLISION;
break;
}
}
origin_loop_->PostTask( origin_loop_->PostTask(
FROM_HERE, FROM_HERE,
base::Bind(&ProcTask::OnLookupComplete, this, results, start_time, base::Bind(&ProcTask::OnLookupComplete, this, results, start_time,
......
...@@ -1319,6 +1319,53 @@ TEST_F(HostResolverImplTest, MultipleAttempts) { ...@@ -1319,6 +1319,53 @@ TEST_F(HostResolverImplTest, MultipleAttempts) {
EXPECT_EQ(resolver_proc->resolved_attempt_number(), kAttemptNumberToResolve); EXPECT_EQ(resolver_proc->resolved_attempt_number(), kAttemptNumberToResolve);
} }
// If a host resolves to a list that includes 127.0.53.53, this is treated as
// an error. 127.0.53.53 is a localhost address, however it has been given a
// special significance by ICANN to help surfance name collision resulting from
// the new gTLDs.
TEST_F(HostResolverImplTest, NameCollision127_0_53_53) {
proc_->AddRuleForAllFamilies("single", "127.0.53.53");
proc_->AddRuleForAllFamilies("multiple", "127.0.0.1,127.0.53.53");
proc_->AddRuleForAllFamilies("ipv6", "::127.0.53.53");
proc_->AddRuleForAllFamilies("not_reserved1", "53.53.0.127");
proc_->AddRuleForAllFamilies("not_reserved2", "127.0.53.54");
proc_->AddRuleForAllFamilies("not_reserved3", "10.0.53.53");
proc_->SignalMultiple(6u);
Request* request;
request = CreateRequest("single");
EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
EXPECT_EQ(ERR_ICANN_NAME_COLLISION, request->WaitForResult());
request = CreateRequest("multiple");
EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
EXPECT_EQ(ERR_ICANN_NAME_COLLISION, request->WaitForResult());
// Resolving an IP literal of 127.0.53.53 however is allowed.
EXPECT_EQ(OK, CreateRequest("127.0.53.53")->Resolve());
// Moreover the address should not be recognized when embedded in an IPv6
// address.
request = CreateRequest("ipv6");
EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
EXPECT_EQ(OK, request->WaitForResult());
// Try some other IPs which are similar, but NOT an exact match on
// 127.0.53.53.
request = CreateRequest("not_reserved1");
EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
EXPECT_EQ(OK, request->WaitForResult());
request = CreateRequest("not_reserved2");
EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
EXPECT_EQ(OK, request->WaitForResult());
request = CreateRequest("not_reserved3");
EXPECT_EQ(ERR_IO_PENDING, request->Resolve());
EXPECT_EQ(OK, request->WaitForResult());
}
DnsConfig CreateValidDnsConfig() { DnsConfig CreateValidDnsConfig() {
IPAddressNumber dns_ip; IPAddressNumber dns_ip;
bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip); bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip);
......
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