From 482aa518a6c915d128f957265f7d5fbcfdb3da2c Mon Sep 17 00:00:00 2001 From: jccollet Date: Fri, 18 Sep 2009 10:51:44 +0200 Subject: [PATCH] 6737819: sun.misc.net.DefaultProxySelector doesn't use proxy setting to localhost Summary: Move default nonProxyHosts from hardcoded to property default value Reviewed-by: chegar --- .../java/net/doc-files/net-properties.html | 10 +- .../sun/net/spi/DefaultProxySelector.java | 144 +++--------------- src/share/lib/net.properties | 4 +- test/java/net/ProxySelector/B6737819.java | 63 ++++++++ 4 files changed, 90 insertions(+), 131 deletions(-) create mode 100644 test/java/net/ProxySelector/B6737819.java diff --git a/src/share/classes/java/net/doc-files/net-properties.html b/src/share/classes/java/net/doc-files/net-properties.html index e6b6330ba..384abd8d9 100644 --- a/src/share/classes/java/net/doc-files/net-properties.html +++ b/src/share/classes/java/net/doc-files/net-properties.html @@ -71,12 +71,12 @@ of proxies.

  • HTTP

    The following proxy settings are used by the HTTP protocol handler.

    +

    The default value excludes all common variations of the loopback address.

    +
  • HTTPS
    This is HTTP over SSL, a secure version of HTTP mainly used when confidentiality (like on payment sites) is needed.

    The following proxy settings are used by the HTTPS protocol handler.

    @@ -107,7 +108,7 @@ of proxies.

  • ftp.proxyPort (default: 80)
    The port number of the proxy server.

    -
  • ftp.nonProxyHosts (default: <none>)
    +

  • ftp.nonProxyHosts (default: localhost|127.*|[::1])
    Indicates the hosts that should be accessed without going through the proxy. Typically this defines internal hosts. The value of this property is a list of hosts, separated by @@ -117,6 +118,7 @@ of proxies.

    will indicate that every hosts in the foo.com domain and the localhost should be accessed directly even if a proxy server is specified.

    +

    The default value excludes all common variations of the loopback address.

  • SOCKS
    This is another type of proxy. It allows for lower level type of tunneling since it works at the TCP level. In effect, diff --git a/src/share/classes/sun/net/spi/DefaultProxySelector.java b/src/share/classes/sun/net/spi/DefaultProxySelector.java index 714dc4ce5..af34ada8c 100644 --- a/src/share/classes/sun/net/spi/DefaultProxySelector.java +++ b/src/share/classes/sun/net/spi/DefaultProxySelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,9 @@ package sun.net.spi; -import sun.net.www.http.*; import sun.net.NetProperties; import java.net.*; import java.util.*; -import java.util.regex.*; import java.io.*; import sun.misc.RegexpPool; import java.security.AccessController; @@ -102,17 +100,22 @@ public class DefaultProxySelector extends ProxySelector { */ static class NonProxyInfo { + // Default value for nonProxyHosts, this provides backward compatibility + // by excluding localhost and its litteral notations. + static final String defStringVal = "localhost|127.*|[::1]"; + String hostsSource; RegexpPool hostsPool; - String property; - - static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null); - static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null); + final String property; + final String defaultVal; + static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null, defStringVal); + static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null, defStringVal); - NonProxyInfo(String p, String s, RegexpPool pool) { + NonProxyInfo(String p, String s, RegexpPool pool, String d) { property = p; hostsSource = s; hostsPool = pool; + defaultVal = d; } } @@ -130,7 +133,6 @@ public class DefaultProxySelector extends ProxySelector { } String protocol = uri.getScheme(); String host = uri.getHost(); - int port = uri.getPort(); if (host == null) { // This is a hack to ensure backward compatibility in two @@ -149,11 +151,6 @@ public class DefaultProxySelector extends ProxySelector { } i = auth.lastIndexOf(':'); if (i >= 0) { - try { - port = Integer.parseInt(auth.substring(i+1)); - } catch (NumberFormatException e) { - port = -1; - } auth = auth.substring(0,i); } host = auth; @@ -165,13 +162,6 @@ public class DefaultProxySelector extends ProxySelector { } List proxyl = new ArrayList(1); - // special case localhost and loopback addresses to - // not go through proxy - if (isLoopback(host)) { - proxyl.add(Proxy.NO_PROXY); - return proxyl; - } - NonProxyInfo pinfo = null; if ("http".equalsIgnoreCase(protocol)) { @@ -244,9 +234,14 @@ public class DefaultProxySelector extends ProxySelector { nphosts = NetProperties.get(nprop.property); synchronized (nprop) { if (nphosts == null) { - nprop.hostsSource = null; - nprop.hostsPool = null; - } else { + if (nprop.defaultVal != null) { + nphosts = nprop.defaultVal; + } else { + nprop.hostsSource = null; + nprop.hostsPool = null; + } + } + if (nphosts != null) { if (!nphosts.equals(nprop.hostsSource)) { RegexpPool pool = new RegexpPool(); StringTokenizer st = new StringTokenizer(nphosts, "|", false); @@ -334,107 +329,6 @@ public class DefaultProxySelector extends ProxySelector { } } - private boolean isLoopback(String host) { - if (host == null || host.length() == 0) - return false; - - if (host.equalsIgnoreCase("localhost")) - return true; - - /* The string could represent a numerical IP address. - * For IPv4 addresses, check whether it starts with 127. - * For IPv6 addresses, check whether it is ::1 or its equivalent. - * Don't check IPv4-mapped or IPv4-compatible addresses - */ - - if (host.startsWith("127.")) { - // possible IPv4 loopback address - int p = 4; - int q; - int n = host.length(); - // Per RFC2732: At most three digits per byte - // Further constraint: Each element fits in a byte - if ((q = scanByte(host, p, n)) <= p) return false; p = q; - if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0; p = q; - if ((q = scanByte(host, p, n)) <= p) return false; p = q; - if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0; p = q; - if ((q = scanByte(host, p, n)) <= p) return false; - return q == n && number > 0; - } - - if (host.endsWith(":1")) { - final Pattern p6 = Pattern.compile("::1|(0:){7}1|(0:){1,6}:1"); - return p6.matcher(host).matches(); - } - return false; - } - - // Character-class masks, in reverse order from RFC2396 because - // initializers for static fields cannot make forward references. - - // Compute a low-order mask for the characters - // between first and last, inclusive - private static long lowMask(char first, char last) { - long m = 0; - int f = Math.max(Math.min(first, 63), 0); - int l = Math.max(Math.min(last, 63), 0); - for (int i = f; i <= l; i++) - m |= 1L << i; - return m; - } - // digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | - // "8" | "9" - private static final long L_DIGIT = lowMask('0', '9'); - private static final long H_DIGIT = 0L; - - // Scan a string of decimal digits whose value fits in a byte - // - private int number; - private int scanByte(String input, int start, int n) - { - int p = start; - int q = scan(input, p, n, L_DIGIT, H_DIGIT); - if (q <= p) return q; - number = Integer.parseInt(input.substring(p, q)); - if (number > 255) return p; - return q; - } - - // Scan a specific char: If the char at the given start position is - // equal to c, return the index of the next char; otherwise, return the - // start position. - // - private int scan(String input, int start, int end, char c) { - if ((start < end) && (input.charAt(start) == c)) - return start + 1; - return start; - } - - // Scan chars that match the given mask pair - // - private int scan(String input, int start, int n, long lowMask, long highMask) - { - int p = start; - while (p < n) { - char c = input.charAt(p); - if (match(c, lowMask, highMask)) { - p++; - continue; - } - break; - } - return p; - } - - // Tell whether the given character is permitted by the given mask pair - private boolean match(char c, long lowMask, long highMask) { - if (c < 64) - return ((1L << c) & lowMask) != 0; - if (c < 128) - return ((1L << (c - 64)) & highMask) != 0; - return false; - } - private native static boolean init(); private native Proxy getSystemProxy(String protocol, String host); } diff --git a/src/share/lib/net.properties b/src/share/lib/net.properties index e941d50e3..da78a84d5 100644 --- a/src/share/lib/net.properties +++ b/src/share/lib/net.properties @@ -32,7 +32,7 @@ java.net.useSystemProxies=false # # http.proxyHost= # http.proxyPort=80 -# http.nonProxyHosts=localhost|127.0.0.1 +http.nonProxyHosts=localhost|127.*|[::1] # # HTTPS Proxy Settings. proxyHost is the name of the proxy server # (e.g. proxy.mydomain.com), proxyPort is the port number to use (default @@ -49,7 +49,7 @@ java.net.useSystemProxies=false # # ftp.proxyHost= # ftp.proxyPort=80 -# ftp.nonProxyHosts=localhost|127.0.0.1 +ftp.nonProxyHosts=localhost|127.*|[::1] # # Gopher Proxy settings. proxyHost is the name of the proxy server # (e.g. proxy.mydomain.com), proxyPort is the port number to use (default diff --git a/test/java/net/ProxySelector/B6737819.java b/test/java/net/ProxySelector/B6737819.java new file mode 100644 index 000000000..360f1ae4a --- /dev/null +++ b/test/java/net/ProxySelector/B6737819.java @@ -0,0 +1,63 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @test + * @bug 6737819 + * @summary sun.misc.net.DefaultProxySelector doesn't use proxy setting to localhost + */ + +import java.net.ProxySelector; +import java.net.Proxy; +import java.net.URI; + +public class B6737819 { + private static String[] uris = { + "http://localhost/index.html", + "http://127.0.0.1/index.html", + "http://127.2/index.html", + "http://[::1]/index.html" + }; + public static void main(String[] args) throws Exception { + System.setProperty("http.proxyHost", "myproxy"); + System.setProperty("http.proxyPort", "8080"); + ProxySelector sel = ProxySelector.getDefault(); + java.util.List l; + // Default value for http.nonProxyHots should exclude all this uris + // from going through the HTTP proxy + for (String s : uris) { + l = sel.select(new URI(s)); + if (l.size() == 1 && l.get(0).type() != Proxy.Type.DIRECT) { + throw new RuntimeException("ProxySelector returned the wrong proxy for " + s); + } + } + // Let's override the default nonProxyHosts and make sure we now get a + // HTTP proxy + System.setProperty("http.nonProxyHosts", ""); + for (String s : uris) { + l = sel.select(new URI(s)); + if (l.size() == 1 && l.get(0).type() != Proxy.Type.HTTP) { + throw new RuntimeException("ProxySelector returned the wrong proxy for " + s); + } + } + } +} -- GitLab