diff options
-rw-r--r-- | net/proxy/proxy_config.h | 2 | ||||
-rw-r--r-- | net/proxy/proxy_service.cc | 33 | ||||
-rw-r--r-- | net/proxy/proxy_service_unittest.cc | 206 |
3 files changed, 188 insertions, 53 deletions
diff --git a/net/proxy/proxy_config.h b/net/proxy/proxy_config.h index ec6c1fc..50d9497 100644 --- a/net/proxy/proxy_config.h +++ b/net/proxy/proxy_config.h @@ -92,6 +92,8 @@ class ProxyConfig { // Indicates a list of hosts that should bypass any proxy configuration. For // these hosts, a direct connection should always be used. + // The form <host>:<port> is also supported, meaning that only + // connections on the specified port should be direct. std::vector<std::string> proxy_bypass; // Indicates whether local names (no dots) bypass proxies. diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index bc4378e..4657ec9 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc @@ -578,6 +578,9 @@ bool ProxyService::ShouldBypassProxyForURL(const GURL& url) { // percent-encoded characters. StringToLowerASCII(&url_domain); + std::string url_domain_and_port = url_domain + ":" + + IntToString(url.EffectiveIntPort()); + if (config_.proxy_bypass_local_names) { if (url.host().find('.') == std::string::npos) return true; @@ -591,24 +594,48 @@ bool ProxyService::ShouldBypassProxyForURL(const GURL& url) { // If no scheme is specified then it indicates that all schemes are // allowed for the current entry. For matching this we just use // the protocol scheme of the url passed in. - if (bypass_url_domain.find("://") == std::string::npos) { + size_t scheme_colon = bypass_url_domain.find("://"); + if (scheme_colon == std::string::npos) { std::string bypass_url_domain_with_scheme = url.scheme(); + scheme_colon = bypass_url_domain_with_scheme.length(); bypass_url_domain_with_scheme += "://"; bypass_url_domain_with_scheme += bypass_url_domain; bypass_url_domain = bypass_url_domain_with_scheme; } + std::string* url_compare_reference = &url_domain; + size_t port_colon = bypass_url_domain.rfind(":"); + if (port_colon > scheme_colon) { + // If our match pattern includes a colon followed by a digit, + // and either it's preceded by ']' (IPv6 with port) + // or has no other colon (IPv4), + // then match against <domain>:<port>. + // TODO(sdoyon): straighten this out, in particular the IPv6 brackets, + // and do the parsing in ProxyConfig when we do the CIDR matching + // mentioned below. + std::string::const_iterator domain_begin = + bypass_url_domain.begin() + scheme_colon + 3; // after :// + std::string::const_iterator port_iter = + bypass_url_domain.begin() + port_colon; + std::string::const_iterator end = bypass_url_domain.end(); + if ((port_iter + 1) < end && IsAsciiDigit(*(port_iter + 1)) && + (*(port_iter - 1) == ']' || + std::find(domain_begin, port_iter, ':') == port_iter)) + url_compare_reference = &url_domain_and_port; + } StringToLowerASCII(&bypass_url_domain); - if (MatchPattern(url_domain, bypass_url_domain)) + if (MatchPattern(*url_compare_reference, bypass_url_domain)) return true; // Some systems (the Mac, for example) allow CIDR-style specification of // proxy bypass for IP-specified hosts (e.g. "10.0.0.0/8"; see // http://www.tcd.ie/iss/internet/osx_proxy.php for a real-world example). // That's kinda cool so we'll provide that for everyone. - // TODO(avi): implement here + // TODO(avi): implement here. See: http://crbug.com/9835. + // IP addresses ought to be canonicalized for comparison (whether + // with CIDR, port, or IP address alone). } return false; diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc index 68d4be5..a2b33d4 100644 --- a/net/proxy/proxy_service_unittest.cc +++ b/net/proxy/proxy_service_unittest.cc @@ -686,83 +686,189 @@ TEST(ProxyServiceTest, ProxyFallback_BadConfig) { TEST(ProxyServiceTest, ProxyBypassList) { // Test what happens when a proxy bypass list is specified. + net::ProxyInfo info; net::ProxyConfig config; config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); config.auto_detect = false; config.proxy_bypass_local_names = true; - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver()); - GURL url("http://www.google.com/"); - // Get the proxy information. - net::ProxyInfo info; - int rv = service.ResolveProxy(url, &info); - EXPECT_EQ(rv, net::OK); - EXPECT_FALSE(info.is_direct()); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver()); + GURL url("http://www.google.com/"); + // Get the proxy information. + int rv = service.ResolveProxy(url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_FALSE(info.is_direct()); + } - SyncProxyService service1(new MockProxyConfigService(config), - new MockProxyResolver()); - GURL test_url1("local"); - net::ProxyInfo info1; - rv = service1.ResolveProxy(test_url1, &info1); - EXPECT_EQ(rv, net::OK); - EXPECT_TRUE(info1.is_direct()); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver()); + GURL test_url("local"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(info.is_direct()); + } config.proxy_bypass.clear(); config.proxy_bypass.push_back("*.org"); config.proxy_bypass_local_names = true; - SyncProxyService service2(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url2("http://www.webkit.org"); - net::ProxyInfo info2; - rv = service2.ResolveProxy(test_url2, &info2); - EXPECT_EQ(rv, net::OK); - EXPECT_TRUE(info2.is_direct()); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver); + GURL test_url("http://www.webkit.org"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(info.is_direct()); + } config.proxy_bypass.clear(); config.proxy_bypass.push_back("*.org"); config.proxy_bypass.push_back("7*"); config.proxy_bypass_local_names = true; - SyncProxyService service3(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url3("http://74.125.19.147"); - net::ProxyInfo info3; - rv = service3.ResolveProxy(test_url3, &info3); - EXPECT_EQ(rv, net::OK); - EXPECT_TRUE(info3.is_direct()); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver); + GURL test_url("http://74.125.19.147"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(info.is_direct()); + } config.proxy_bypass.clear(); config.proxy_bypass.push_back("*.org"); config.proxy_bypass_local_names = true; - SyncProxyService service4(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url4("http://www.msn.com"); - net::ProxyInfo info4; - rv = service4.ResolveProxy(test_url4, &info4); - EXPECT_EQ(rv, net::OK); - EXPECT_FALSE(info4.is_direct()); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver); + GURL test_url("http://www.msn.com"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_FALSE(info.is_direct()); + } config.proxy_bypass.clear(); config.proxy_bypass.push_back("*.MSN.COM"); config.proxy_bypass_local_names = true; - SyncProxyService service5(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url5("http://www.msnbc.msn.com"); - net::ProxyInfo info5; - rv = service5.ResolveProxy(test_url5, &info5); - EXPECT_EQ(rv, net::OK); - EXPECT_TRUE(info5.is_direct()); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver); + GURL test_url("http://www.msnbc.msn.com"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(info.is_direct()); + } config.proxy_bypass.clear(); config.proxy_bypass.push_back("*.msn.com"); config.proxy_bypass_local_names = true; - SyncProxyService service6(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url6("HTTP://WWW.MSNBC.MSN.COM"); - net::ProxyInfo info6; - rv = service6.ResolveProxy(test_url6, &info6); - EXPECT_EQ(rv, net::OK); - EXPECT_TRUE(info6.is_direct()); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver); + GURL test_url("HTTP://WWW.MSNBC.MSN.COM"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(info.is_direct()); + } +} + +TEST(ProxyServiceTest, ProxyBypassListWithPorts) { + // Test port specification in bypass list entries. + net::ProxyInfo info; + net::ProxyConfig config; + config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); + config.auto_detect = false; + config.proxy_bypass_local_names = false; + + config.proxy_bypass.clear(); + config.proxy_bypass.push_back("*.example.com:99"); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver); + { + GURL test_url("http://www.example.com:99"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(info.is_direct()); + } + { + GURL test_url("http://www.example.com:100"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_FALSE(info.is_direct()); + } + { + GURL test_url("http://www.example.com"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_FALSE(info.is_direct()); + } + } + + config.proxy_bypass.clear(); + config.proxy_bypass.push_back("*.example.com:80"); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver); + GURL test_url("http://www.example.com"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(info.is_direct()); + } + + config.proxy_bypass.clear(); + config.proxy_bypass.push_back("*.example.com"); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver); + GURL test_url("http://www.example.com:99"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(info.is_direct()); + } + + // IPv6 with port. + config.proxy_bypass.clear(); + config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]:99"); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver); + { + GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(info.is_direct()); + } + { + GURL test_url("http://[3ffe:2a00:100:7031::1]/"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_FALSE(info.is_direct()); + } + } + + // IPv6 without port. The bypass entry ought to work without the + // brackets, but the bypass matching logic in ProxyService is + // currently limited. + config.proxy_bypass.clear(); + config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]"); + { + SyncProxyService service(new MockProxyConfigService(config), + new MockProxyResolver); + { + GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(info.is_direct()); + } + { + GURL test_url("http://[3ffe:2a00:100:7031::1]/"); + int rv = service.ResolveProxy(test_url, &info); + EXPECT_EQ(rv, net::OK); + EXPECT_TRUE(info.is_direct()); + } + } } TEST(ProxyServiceTest, PerProtocolProxyTests) { |