Commit ff374b7f authored by eroman's avatar eroman Committed by Commit bot

Change ParseHostAndPort() to not include brackets around IPv6 literals.

There were several consumers assuming that the returned hosts had no brackets.

BUG=417417

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

Cr-Commit-Position: refs/heads/master@{#296569}
parent 94f23092
......@@ -376,6 +376,23 @@ bool ParseHostAndPort(std::string::const_iterator host_and_port_begin,
if (port_component.len == 0)
return false; // Reject inputs like "foo:"
unsigned char tmp_ipv6_addr[16];
// If the hostname starts with a bracket, it is either an IPv6 literal or
// invalid. If it is an IPv6 literal then strip the brackets.
if (hostname_component.len > 0 &&
auth_begin[hostname_component.begin] == '[') {
if (auth_begin[hostname_component.end() - 1] == ']' &&
url::IPv6AddressToNumber(
auth_begin, hostname_component, tmp_ipv6_addr)) {
// Strip the brackets.
hostname_component.begin++;
hostname_component.len -= 2;
} else {
return false;
}
}
// Pass results back to caller.
host->assign(auth_begin + hostname_component.begin, hostname_component.len);
*port = parsed_port_number;
......
......@@ -81,8 +81,12 @@ NET_EXPORT_PRIVATE extern size_t GetCountOfExplicitlyAllowedPorts();
// Saves the result into |*host| and |*port|. If the input did not have
// the optional port, sets |*port| to -1.
// Returns true if the parsing was successful, false otherwise.
// The returned host is NOT canonicalized, and may be invalid. If <host> is
// an IPv6 literal address, the returned host includes the square brackets.
// The returned host is NOT canonicalized, and may be invalid.
//
// IPv6 literals must be specified in a bracketed form, for instance:
// [::1]:90 and [::1]
//
// The resultant |*host| in both cases will be "::1" (not bracketed).
NET_EXPORT bool ParseHostAndPort(
std::string::const_iterator host_and_port_begin,
std::string::const_iterator host_and_port_end,
......
......@@ -246,9 +246,20 @@ TEST(NetUtilTest, ParseHostAndPort) {
{
"[1080:0:0:0:8:800:200C:4171]:11",
true,
"1080:0:0:0:8:800:200C:4171",
11
},
{
"[1080:0:0:0:8:800:200C:4171]",
11,
true,
"1080:0:0:0:8:800:200C:4171",
-1
},
// Because no validation is done on the host, the following are accepted,
// even though they are invalid names.
{"]", true, "]", -1},
{"::1", true, ":", 1},
// Invalid inputs:
{"foo:bar", false, "", -1},
{"foo:", false, "", -1},
......@@ -262,6 +273,8 @@ TEST(NetUtilTest, ParseHostAndPort) {
{":password@host:80", false, "", -1},
{":password@host", false, "", -1},
{"@host", false, "", -1},
{"[", false, "", -1},
{"[]", false, "", -1},
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
......
......@@ -6,10 +6,11 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_util.h"
namespace net {
......@@ -131,6 +132,7 @@ class BypassIPBlockRule : public ProxyBypassRules::Rule {
};
// Returns true if the given string represents an IP address.
// IPv6 addresses are expected to be bracketed.
bool IsIPAddress(const std::string& domain) {
// From GURL::HostIsIPAddress()
url::RawCanonOutputT<char, 128> ignored_output;
......@@ -305,9 +307,12 @@ bool ProxyBypassRules::AddRuleFromStringInternal(
std::string host;
int port;
if (ParseHostAndPort(raw, &host, &port)) {
if (IsIPAddress(host)) {
// Note that HostPortPair is used to merely to convert any IPv6 literals to
// a URL-safe format that can be used by canonicalization below.
std::string bracketed_host = HostPortPair(host, 80).HostForURL();
if (IsIPAddress(bracketed_host)) {
// Canonicalize the IP literal before adding it as a string pattern.
GURL tmp_url("http://" + host);
GURL tmp_url("http://" + bracketed_host);
return AddRuleForHostname(scheme, tmp_url.host(), port);
}
}
......
......@@ -64,14 +64,6 @@ ProxyServer::Scheme GetSchemeFromURIInternal(std::string::const_iterator begin,
return ProxyServer::SCHEME_INVALID;
}
std::string HostNoBrackets(const std::string& host) {
// Remove brackets from an RFC 2732-style IPv6 literal address.
const std::string::size_type len = host.size();
if (len >= 2 && host[0] == '[' && host[len - 1] == ']')
return host.substr(1, len - 2);
return host;
}
} // namespace
ProxyServer::ProxyServer(Scheme scheme, const HostPortPair& host_port_pair)
......@@ -246,7 +238,7 @@ ProxyServer ProxyServer::FromSchemeHostAndPort(
if (port == -1)
port = GetDefaultPortForScheme(scheme);
host_port_pair = HostPortPair(HostNoBrackets(host), port);
host_port_pair = HostPortPair(host, port);
}
return ProxyServer(scheme, host_port_pair);
......
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