diff options
-rw-r--r-- | net/base/net_util.cc | 17 | ||||
-rw-r--r-- | net/base/net_util.h | 8 | ||||
-rw-r--r-- | net/base/net_util_unittest.cc | 15 | ||||
-rw-r--r-- | net/proxy/proxy_bypass_rules.cc | 13 | ||||
-rw-r--r-- | net/proxy/proxy_server.cc | 10 |
5 files changed, 47 insertions, 16 deletions
diff --git a/net/base/net_util.cc b/net/base/net_util.cc index 704add2..d63dfe8 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -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; diff --git a/net/base/net_util.h b/net/base/net_util.h index 49780e8..8420cb3 100644 --- a/net/base/net_util.h +++ b/net/base/net_util.h @@ -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, diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc index 3bb518f..5ef1d49 100644 --- a/net/base/net_util_unittest.cc +++ b/net/base/net_util_unittest.cc @@ -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) { diff --git a/net/proxy/proxy_bypass_rules.cc b/net/proxy/proxy_bypass_rules.cc index 6bf1c61..239a2fe 100644 --- a/net/proxy/proxy_bypass_rules.cc +++ b/net/proxy/proxy_bypass_rules.cc @@ -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); } } diff --git a/net/proxy/proxy_server.cc b/net/proxy/proxy_server.cc index d74a89f0..0b9ba67 100644 --- a/net/proxy/proxy_server.cc +++ b/net/proxy/proxy_server.cc @@ -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); |