提交 135c8a01 编写于 作者: M michaelm

8014719: HttpClient/ProxyTest.java failing with IAE HttpURLPermission.parseURI

Reviewed-by: alanb, chegar
上级 a6cdba21
/*
* Copyright (c) 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.net.*;
import java.util.Formatter;
import java.util.Locale;
import sun.net.util.IPAddressUtil;
/**
* Parses a string containing a host/domain name and port range
*/
class HostPortrange {
String hostname;
String scheme;
int[] portrange;
boolean wildcard;
boolean literal;
boolean ipv6, ipv4;
static final int PORT_MIN = 0;
static final int PORT_MAX = (1 << 16) -1;
boolean equals(HostPortrange that) {
return this.hostname.equals(that.hostname)
&& this.portrange[0] == that.portrange[0]
&& this.portrange[1] == that.portrange[1]
&& this.wildcard == that.wildcard
&& this.literal == that.literal;
}
public int hashCode() {
return hostname.hashCode() + portrange[0] + portrange[1];
}
HostPortrange(String scheme, String str) {
// Parse the host name. A name has up to three components, the
// hostname, a port number, or two numbers representing a port
// range. "www.sun.com:8080-9090" is a valid host name.
// With IPv6 an address can be 2010:836B:4179::836B:4179
// An IPv6 address needs to be enclose in []
// For ex: [2010:836B:4179::836B:4179]:8080-9090
// Refer to RFC 2732 for more information.
// first separate string into two fields: hoststr, portstr
String hoststr, portstr = null;
this.scheme = scheme;
// check for IPv6 address
if (str.charAt(0) == '[') {
ipv6 = literal = true;
int rb = str.indexOf(']');
if (rb != -1) {
hoststr = str.substring(1, rb);
} else {
throw new IllegalArgumentException("invalid IPv6 address: " + str);
}
int sep = str.indexOf(':', rb + 1);
if (sep != -1 && str.length() > sep) {
portstr = str.substring(sep + 1);
}
// need to normalize hoststr now
byte[] ip = IPAddressUtil.textToNumericFormatV6(hoststr);
if (ip == null) {
throw new IllegalArgumentException("illegal IPv6 address");
}
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb, Locale.US);
formatter.format("%02x%02x:%02x%02x:%02x%02x:%02x"
+ "%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8],
ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]);
hostname = sb.toString();
} else {
// not IPv6 therefore ':' is the port separator
int sep = str.indexOf(':');
if (sep != -1 && str.length() > sep) {
hoststr = str.substring(0, sep);
portstr = str.substring(sep + 1);
} else {
hoststr = sep == -1 ? str : str.substring(0, sep);
}
// is this a domain wildcard specification?
if (hoststr.lastIndexOf('*') > 0) {
throw new IllegalArgumentException("invalid host wildcard specification");
} else if (hoststr.startsWith("*")) {
wildcard = true;
if (hoststr.equals("*")) {
hoststr = "";
} else if (hoststr.startsWith("*.")) {
hoststr = hoststr.substring(1).toLowerCase(); // leave the '.' ?
} else {
throw new IllegalArgumentException("invalid host wildcard specification");
}
} else {
// check if ipv4 (if rightmost label a number)
// The normal way to specify ipv4 is 4 decimal labels
// but actually three, two or single label formats valid also
// So, we recognise ipv4 by just testing the rightmost label
// being a number.
int lastdot = hoststr.lastIndexOf('.');
if (lastdot != -1 && (hoststr.length() > 1)) {
boolean ipv4 = true;
for (int i = lastdot + 1, len = hoststr.length(); i < len; i++) {
char c = hoststr.charAt(i);
if (c < '0' || c > '9') {
ipv4 = false;
break;
}
}
this.ipv4 = this.literal = ipv4;
if (ipv4) {
byte[] ip = IPAddressUtil.textToNumericFormatV4(hoststr);
if (ip == null) {
throw new IllegalArgumentException("illegal IPv4 address");
}
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb, Locale.US);
formatter.format("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
hoststr = sb.toString();
} else {
// regular domain name
hoststr = hoststr.toLowerCase();
}
}
}
hostname = hoststr;
}
try {
portrange = parsePort(portstr);
} catch (Exception e) {
throw new IllegalArgumentException("invalid port range: " + portstr);
}
}
public boolean literal() {
return literal;
}
public boolean ipv4Literal() {
return ipv4;
}
public boolean ipv6Literal() {
return ipv6;
}
public String hostname() {
return hostname;
}
public int[] portrange() {
return portrange;
}
/**
* returns true if the hostname part started with *
* hostname returns the remaining part of the host component
* eg "*.foo.com" -> ".foo.com" or "*" -> ""
*
* @return
*/
public boolean wildcard() {
return wildcard;
}
// these shouldn't leak outside the implementation
final static int[] HTTP_PORT = {80, 80};
final static int[] HTTPS_PORT = {443, 443};
final static int[] NO_PORT = {-1, -1};
int[] defaultPort() {
if (scheme.equals("http")) {
return HTTP_PORT;
} else if (scheme.equals("https")) {
return HTTPS_PORT;
}
return NO_PORT;
}
int[] parsePort(String port)
{
if (port == null || port.equals("")) {
return defaultPort();
}
if (port.equals("*")) {
return new int[] {PORT_MIN, PORT_MAX};
}
try {
int dash = port.indexOf('-');
if (dash == -1) {
int p = Integer.parseInt(port);
return new int[] {p, p};
} else {
String low = port.substring(0, dash);
String high = port.substring(dash+1);
int l,h;
if (low.equals("")) {
l = PORT_MIN;
} else {
l = Integer.parseInt(low);
}
if (high.equals("")) {
h = PORT_MAX;
} else {
h = Integer.parseInt(high);
}
if (l < 0 || h < 0 || h<l) {
return defaultPort();
}
return new int[] {l, h};
}
} catch (IllegalArgumentException e) {
return defaultPort();
}
}
}
......@@ -57,7 +57,7 @@ import java.util.Date;
* attempt to open a connection, the caller must possess either:-
* <ul><li>a "connect" {@link SocketPermission} to the host/port combination of the
* destination URL or</li>
* <li>a {@link HttpURLPermission} that permits this request.</li>
* <li>a {@link URLPermission} that permits this request.</li>
* </ul><p>
* If automatic redirection is enabled, and this request is redirected to another
* destination, then the caller must also have permission to connect to the
......
......@@ -34,18 +34,41 @@ import java.security.Permission;
/**
* Represents permission to access a resource or set of resources defined by a
* given http or https url, and for a given set of user-settable request methods
* given url, and for a given set of user-settable request methods
* and request headers. The <i>name</i> of the permission is the url string.
* The <i>actions</i> string is a concatenation of the request methods and headers.
* The range of method and header names is not restricted by this class.
* <p><b>The url</b><p>
* The url string is also used to instantiate a {@link URI} object which is
* used for comparison with other HttpURLPermission instances. Therefore, any
* references in this specification to url, mean this URI object.
* The path component of the url comprises a sequence of path segments, separated
* by '/' characters. The path is specified in a similar way to the path
* in {@link java.io.FilePermission}. There are three different ways
* as the following examples show:
* The url string has the following expected structure.
* <pre>
* scheme : // authority [ / path ]
* </pre>
* <i>scheme</i> will typically be http or https, but is not restricted by this
* class.
* <i>authority</i> is specified as:<p>
* <pre>
* authority = hostrange [ : portrange ]
* portrange = portnumber | -portnumber | portnumber-[portnumber] | *
* hostrange = ([*.] dnsname) | IPv4address | IPv6address
* </pre>
* <i>dnsname</i> is a standard DNS host or domain name, ie. one or more labels
* separated by ".". <i>IPv4address</i> is a standard literal IPv4 address and
* <i>IPv6address</i> is as defined in <a href="http://www.ietf.org/rfc/rfc2732.txt">
* RFC 2732</a>. Literal IPv6 addresses must however, be enclosed in '[]' characters.
* The <i>dnsname</i> specification can be preceded by "*." which means
* the name will match any hostname whose right-most domain labels are the same as
* this name. For example, "*.oracle.com" matches "foo.bar.oracle.com"
* <p>
* <i>portrange</i> is used to specify a port number, or a bounded or unbounded range of ports
* that this permission applies to. If portrange is absent or invalid, then a default
* port number is assumed if the scheme is {@code http} (default 80) or {@code https}
* (default 443). No default is assumed for other schemes. A wildcard may be specified
* which means all ports.
* <p>
* The <i>path</i> component comprises a sequence of path segments,
* separated by '/' characters. <i>path</i> may also be empty. The path is specified
* in a similar way to the path in {@link java.io.FilePermission}. There are
* three different ways as the following examples show:
* <table border>
* <caption>URL Examples</caption>
* <tr><th>Example url</th><th>Description</th></tr>
......@@ -68,13 +91,19 @@ import java.security.Permission;
* <p>
* The '*' and '-' may only be specified in the final segment of a path and must be
* the only character in that segment. Any query or fragment components of the
* url are ignored when constructing HttpURLPermissions.
* url are ignored when constructing URLPermissions.
* <p>
* As a special case, urls of the form, "http:*" or "https:*" are accepted to
* As a special case, urls of the form, "scheme:*" are accepted to
* mean any url of the given scheme.
* <p>
* The <i>scheme</i> and <i>authority</i> components of the url string are handled
* without regard to case. This means {@link #equals(Object)},
* {@link #hashCode()} and {@link #implies(Permission)} are case insensitive with respect
* to these components. If the <i>authority</i> contains a literal IP address,
* then the address is normalized for comparison. The path component is case sensitive.
* <p><b>The actions string</b><p>
* The actions string of a HttpURLPermission is a concatenation of the <i>method list</i>
* and the <i>request headers list</i>. These are lists of the permitted HTTP request
* The actions string of a URLPermission is a concatenation of the <i>method list</i>
* and the <i>request headers list</i>. These are lists of the permitted request
* methods and permitted request headers of the permission (respectively). The two lists
* are separated by a colon ':' character and elements of each list are comma separated.
* Some examples are:
......@@ -89,7 +118,7 @@ import java.security.Permission;
* <p>
* The colon separator need not be present if the request headers list is empty.
* No white-space is permitted in the actions string. The action strings supplied to
* the HttpURLPermission constructors are case-insensitive and are normalized by converting
* the URLPermission constructors are case-insensitive and are normalized by converting
* method names to upper-case and header names to the form defines in RFC2616 (lower case
* with initial letter of each word capitalized). Either list can contain a wild-card '*'
* character which signifies all request methods or headers respectively.
......@@ -102,38 +131,40 @@ import java.security.Permission;
*
* @since 1.8
*/
public final class HttpURLPermission extends Permission {
public final class URLPermission extends Permission {
private static final long serialVersionUID = -2702463814894478682L;
private transient URI uri;
private transient String scheme;
private transient String ssp; // scheme specific part
private transient String path;
private transient List<String> methods;
private transient List<String> requestHeaders;
private transient Authority authority;
// serialized field
private String actions;
/**
* Creates a new HttpURLPermission from a url string and which permits the given
* Creates a new URLPermission from a url string and which permits the given
* request methods and user-settable request headers.
* The name of the permission is its url string. Only the scheme, authority
* and path components of the url are used. Any fragment or query
* The name of the permission is the url string it was created with. Only the scheme,
* authority and path components of the url are used internally. Any fragment or query
* components are ignored. The permissions action string is as specified above.
*
* @param url the url string
*
* @param actions the actions string
*
* @throws IllegalArgumentException if url does not result in a valid {@link URI},
* its scheme is not http or https, or if actions contains white-space.
* @exception IllegalArgumentException if url is invalid or if actions contains white-space.
*/
public HttpURLPermission(String url, String actions) {
public URLPermission(String url, String actions) {
super(url);
init(actions);
}
private void init(String actions) {
URI uri = parseURI(getName());
parseURI(getName());
int colon = actions.indexOf(':');
if (actions.lastIndexOf(':') != colon) {
throw new IllegalArgumentException("invalid actions string");
......@@ -157,19 +188,18 @@ public final class HttpURLPermission extends Permission {
this.requestHeaders = Collections.unmodifiableList(l);
this.actions = actions();
this.uri = uri;
}
/**
* Creates a HttpURLPermission with the given url string and unrestricted
* Creates a URLPermission with the given url string and unrestricted
* methods and request headers by invoking the two argument
* constructor as follows: HttpURLPermission(url, "*:*")
* constructor as follows: URLPermission(url, "*:*")
*
* @param url the url string
*
* @throws IllegalArgumentException if url does not result in a valid {@link URI}
*/
public HttpURLPermission(String url) {
public URLPermission(String url) {
this(url, "*:*");
}
......@@ -190,20 +220,23 @@ public final class HttpURLPermission extends Permission {
}
/**
* Checks if this HttpURLPermission implies the given permission.
* Checks if this URLPermission implies the given permission.
* Specifically, the following checks are done as if in the
* following sequence:
* <p><ul>
* <li>if 'p' is not an instance of HttpURLPermission return false</li>
* <li>if 'p' is not an instance of URLPermission return false</li>
* <li>if any of p's methods are not in this's method list, and if
* this's method list is not equal to "*", then return false.</li>
* <li>if any of p's headers are not in this's request header list, and if
* this's request header list is not equal to "*", then return false.</li>
* <li>if this's url is equal to p's url , then return true</li>
* <li>if this's url scheme is not equal to p's url scheme return false</li>
* <li>if the scheme specific part of this's url is '*' return true</li>
* <li>if this's url authority is not equal to p's url authority
* return false</li>
* <li>if the set of hosts defined by p's url hostrange is not a subset of
* this's url hostrange then return false. For example, "*.foo.oracle.com"
* is a subset of "*.oracle.com". "foo.bar.oracle.com" is not
* a subset of "*.foo.oracle.com"</li>
* <li>if the portrange defined by p's url is not a subset of the
* portrange defined by this's url then return false.
* <li>if the path or paths specified by p's url are contained in the
* set of paths specified by this's url, then return true
* <li>otherwise, return false</li>
......@@ -222,11 +255,11 @@ public final class HttpURLPermission extends Permission {
* </table>
*/
public boolean implies(Permission p) {
if (! (p instanceof HttpURLPermission)) {
if (! (p instanceof URLPermission)) {
return false;
}
HttpURLPermission that = (HttpURLPermission)p;
URLPermission that = (URLPermission)p;
if (!this.methods.get(0).equals("*") &&
Collections.indexOfSubList(this.methods, that.methods) == -1) {
......@@ -244,39 +277,36 @@ public final class HttpURLPermission extends Permission {
return false;
}
if (this.uri.equals(that.uri)) {
return true;
}
if (!this.uri.getScheme().equals(that.uri.getScheme())) {
if (!this.scheme.equals(that.scheme)) {
return false;
}
if (this.uri.getSchemeSpecificPart().equals("*")) {
if (this.ssp.equals("*")) {
return true;
}
String thisAuthority = this.uri.getAuthority();
if (thisAuthority != null &&
!thisAuthority.equals(that.uri.getAuthority())) {
if (!this.authority.implies(that.authority)) {
return false;
}
String thispath = this.uri.getPath();
String thatpath = that.uri.getPath();
if (this.path == null) {
return that.path == null;
}
if (that.path == null) {
return false;
}
if (thispath.endsWith("/-")) {
String thisprefix = thispath.substring(0, thispath.length() - 1);
return thatpath.startsWith(thisprefix);
if (this.path.endsWith("/-")) {
String thisprefix = this.path.substring(0, this.path.length() - 1);
return that.path.startsWith(thisprefix);
}
if (thispath.endsWith("/*")) {
String thisprefix = thispath.substring(0, thispath.length() - 1);
if (!thatpath.startsWith(thisprefix)) {
if (this.path.endsWith("/*")) {
String thisprefix = this.path.substring(0, this.path.length() - 1);
if (!that.path.startsWith(thisprefix)) {
return false;
}
String thatsuffix = thatpath.substring(thisprefix.length());
String thatsuffix = that.path.substring(thisprefix.length());
// suffix must not contain '/' chars
if (thatsuffix.indexOf('/') != -1) {
return false;
......@@ -286,7 +316,7 @@ public final class HttpURLPermission extends Permission {
}
return true;
}
return false;
return this.path.equals(that.path);
}
......@@ -295,20 +325,35 @@ public final class HttpURLPermission extends Permission {
* and p's url equals this's url. Returns false otherwise.
*/
public boolean equals(Object p) {
if (!(p instanceof HttpURLPermission)) {
if (!(p instanceof URLPermission)) {
return false;
}
URLPermission that = (URLPermission)p;
if (!this.scheme.equals(that.scheme)) {
return false;
}
HttpURLPermission that = (HttpURLPermission)p;
return this.getActions().equals(that.getActions()) &&
this.uri.equals(that.uri);
if (!this.getActions().equals(that.getActions())) {
return false;
}
if (!this.authority.equals(that.authority)) {
return false;
}
if (this.path != null) {
return this.path.equals(that.path);
} else {
return that.path == null;
}
}
/**
* Returns a hashcode calculated from the hashcode of the
* actions String and the url
* actions String and the url string.
*/
public int hashCode() {
return getActions().hashCode() + uri.hashCode();
return getActions().hashCode()
+ scheme.hashCode()
+ authority.hashCode()
+ path == null ? 0 : path.hashCode();
}
......@@ -371,17 +416,31 @@ public final class HttpURLPermission extends Permission {
return l;
}
private URI parseURI(String url) {
URI u = URI.create(url);
String scheme = u.getScheme();
if (!(scheme.equalsIgnoreCase("http") ||
scheme.equalsIgnoreCase("https"))) {
throw new IllegalArgumentException ("unexpected URL scheme");
private void parseURI(String url) {
int len = url.length();
int delim = url.indexOf(':');
if (delim == -1 || delim + 1 == len) {
throw new IllegalArgumentException("invalid URL string");
}
scheme = url.substring(0, delim).toLowerCase();
this.ssp = url.substring(delim + 1);
if (!ssp.startsWith("//")) {
this.authority = new Authority(scheme, ssp.toLowerCase());
return;
}
if (!u.getSchemeSpecificPart().equals("*")) {
u = URI.create(scheme + "://" + u.getRawAuthority() + u.getRawPath());
String authpath = ssp.substring(2);
delim = authpath.indexOf('/');
String auth;
if (delim == -1) {
this.path = "";
auth = authpath;
} else {
auth = authpath.substring(0, delim);
this.path = authpath.substring(delim);
}
return u;
this.authority = new Authority(scheme, auth.toLowerCase());
}
private String actions() {
......@@ -395,6 +454,7 @@ public final class HttpURLPermission extends Permission {
}
return b.toString();
}
/**
* restore the state of this object from stream
*/
......@@ -405,4 +465,59 @@ public final class HttpURLPermission extends Permission {
init(actions);
}
static class Authority {
HostPortrange p;
Authority(String scheme, String authority) {
p = new HostPortrange(scheme, authority);
}
boolean implies(Authority other) {
return impliesHostrange(other) && impliesPortrange(other);
}
private boolean impliesHostrange(Authority that) {
String thishost = this.p.hostname();
String thathost = that.p.hostname();
if (p.wildcard() && thishost.equals("")) {
// this "*" implies all others
return true;
}
if (that.p.wildcard() && thathost.equals("")) {
// that "*" can only be implied by this "*"
return false;
}
if (thishost.equals(thathost)) {
// covers all cases of literal IP addresses and fixed
// domain names.
return true;
}
if (this.p.wildcard()) {
// this "*.foo.com" implies "bub.bar.foo.com"
return thathost.endsWith(thishost);
}
return false;
}
private boolean impliesPortrange(Authority that) {
int[] thisrange = this.p.portrange();
int[] thatrange = that.p.portrange();
if (thisrange[0] == -1) {
/* port not specified non http/s URL */
return true;
}
return thisrange[0] <= thatrange[0] &&
thisrange[1] >= thatrange[1];
}
boolean equals(Authority that) {
return this.p.equals(that.p);
}
public int hashCode() {
return p.hashCode();
}
}
}
......@@ -46,7 +46,7 @@ import java.net.ResponseCache;
import java.net.CacheResponse;
import java.net.SecureCacheResponse;
import java.net.CacheRequest;
import java.net.HttpURLPermission;
import java.net.URLPermission;
import java.net.Authenticator.RequestorType;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
......@@ -389,7 +389,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
private int connectTimeout = NetworkClient.DEFAULT_CONNECT_TIMEOUT;
private int readTimeout = NetworkClient.DEFAULT_READ_TIMEOUT;
/* A permission converted from a HttpURLPermission */
/* A permission converted from a URLPermission */
private SocketPermission socketPermission;
/* Logging support */
......@@ -930,8 +930,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
plainConnect0();
return null;
}
}
// }, null, p -- replace line above, when limited doPriv ready
}, null, p
);
} catch (PrivilegedActionException e) {
throw (IOException) e.getException();
......@@ -943,7 +942,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
}
/**
* if the caller has a HttpURLPermission for connecting to the
* if the caller has a URLPermission for connecting to the
* given URL, then return a SocketPermission which permits
* access to that destination. Return null otherwise. The permission
* is cached in a field (which can only be changed by redirects)
......@@ -969,7 +968,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
String actions = getRequestMethod()+":" +
getUserSetHeaders().getHeaderNamesInList();
HttpURLPermission p = new HttpURLPermission(url.toString(), actions);
String urlstring = url.getProtocol() + "://" + url.getAuthority()
+ url.getPath();
URLPermission p = new URLPermission(urlstring, actions);
try {
sm.checkPermission(p);
socketPermission = newPerm;
......@@ -1188,8 +1190,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
public OutputStream run() throws IOException {
return getOutputStream0();
}
}
// }, null, p -- replace line above, when limited doPriv ready
}, null, p
);
} catch (PrivilegedActionException e) {
throw (IOException) e.getException();
......@@ -1372,8 +1373,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
public InputStream run() throws IOException {
return getInputStream0();
}
}
// }, null, p -- replace line above, when limited doPriv ready
}, null, p
);
} catch (PrivilegedActionException e) {
throw (IOException) e.getException();
......@@ -2507,8 +2507,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
public Boolean run() throws IOException {
return followRedirect0(loc, stat, locUrl0);
}
}
// }, null, p -- replace line above, when limited doPriv ready
}, null, p
);
} catch (PrivilegedActionException e) {
throw (IOException) e.getException();
......
......@@ -1447,7 +1447,7 @@ class ToolDialog extends Dialog {
PERM_ARRAY.add(new AWTPerm());
PERM_ARRAY.add(new DelegationPerm());
PERM_ARRAY.add(new FilePerm());
PERM_ARRAY.add(new HttpURLPerm());
PERM_ARRAY.add(new URLPerm());
PERM_ARRAY.add(new InqSecContextPerm());
PERM_ARRAY.add(new LogPerm());
PERM_ARRAY.add(new MgmtPerm());
......@@ -3843,10 +3843,10 @@ class FilePerm extends Perm {
}
}
class HttpURLPerm extends Perm {
public HttpURLPerm() {
super("HttpURLPermission",
"java.net.HttpURLPermission",
class URLPerm extends Perm {
public URLPerm() {
super("URLPermission",
"java.net.URLPermission",
new String[] {
"<"+ PolicyTool.rb.getString("url") + ">",
},
......
......@@ -21,7 +21,7 @@
* questions.
*/
import java.net.HttpURLPermission;
import java.net.URLPermission;
import java.io.*;
/**
......@@ -29,7 +29,7 @@ import java.io.*;
* @bug 8010464
*/
public class HttpURLPermissionTest {
public class URLPermissionTest {
// super class for all test types
abstract static class Test {
......@@ -37,6 +37,28 @@ public class HttpURLPermissionTest {
abstract boolean execute();
};
// Should throw an IAE on construction
static class ExTest extends Test {
String arg;
ExTest(String arg) {
this.arg = arg;
}
@Override
boolean execute() {
try {
URLPermission p = new URLPermission(arg);
return false;
} catch (IllegalArgumentException e) {
return true;
}
}
};
static ExTest extest(String arg) {
return new ExTest(arg);
}
// Tests URL part of implies() method. This is the main test.
static class URLImpliesTest extends Test {
String arg1, arg2;
......@@ -48,9 +70,13 @@ public class HttpURLPermissionTest {
}
boolean execute() {
HttpURLPermission p1 = new HttpURLPermission (arg1, "GET:*");
HttpURLPermission p2 = new HttpURLPermission (arg2, "GET:*");
URLPermission p1 = new URLPermission (arg1, "GET:*");
URLPermission p2 = new URLPermission (arg2, "GET:*");
boolean result = p1.implies(p2);
if (result != expected) {
System.out.println("p1 = " + p1);
System.out.println("p2 = " + p2);
}
return result == expected;
}
};
......@@ -68,12 +94,14 @@ public class HttpURLPermissionTest {
this.expected = expected;
}
@Override
boolean execute() {
String url1 = "http://www.foo.com/-";
String url2 = "http://www.foo.com/a/b";
HttpURLPermission p1 = new HttpURLPermission(url1, arg1);
HttpURLPermission p2 = new HttpURLPermission(url2, arg2);
URLPermission p1 = new URLPermission(url1, arg1);
URLPermission p2 = new URLPermission(url2, arg2);
boolean result = p1.implies(p2);
return result == expected;
}
}
......@@ -82,6 +110,29 @@ public class HttpURLPermissionTest {
return new ActionImpliesTest(arg1, arg2, expected);
}
static class URLEqualityTest extends Test {
String arg1, arg2;
URLEqualityTest(String arg1, String arg2, boolean expected) {
this.arg1 = arg1;
this.arg2 = arg2;
this.expected = expected;
}
@Override
boolean execute() {
URLPermission p1 = new URLPermission(arg1);
URLPermission p2 = new URLPermission(arg2);
boolean result = p1.equals(p2);
return result == expected;
}
}
static URLEqualityTest eqtest(String arg1, String arg2, boolean expected) {
return new URLEqualityTest(arg1, arg2, expected);
}
static Test[] pathImplies = {
// single
imtest("http://www.foo.com/", "http://www.foo.com/", true),
......@@ -116,6 +167,69 @@ public class HttpURLPermissionTest {
imtest("http://foo/bar", "https://foo/bar", false)
};
// new functionality
static Test[] exceptionTests = {
extest("http://1.2.3.4.5/a/b/c"),
extest("http://www.*.com"),
//extest("http://www.foo.com:1-X"),
extest("http://[foo.com]:99"),
extest("http://[fec0::X]:99"),
extest("http:")
};
static Test[] pathImplies2 = {
imtest("http://[FE80::]:99", "http://[fe80:0::]:99", true),
// hostnames
imtest("http://*.foo.com/a/b/-", "http://www.foo.com/a/b/c/d", true),
imtest("http://*.foo.com/a/b/-", "http://www.bar.com/a/b/c/d", false),
imtest("http://*.foo.com/a/b/-", "http://www.biz.bar.foo.com/a/b/c/d", true),
imtest("http://*.foo.com/a/b/-", "http://www.biz.bar.foo.como/a/b/c/d", false),
imtest("http://*/a/b/-", "http://www.biz.bar.foo.fuzz/a/b/c/d", true),
imtest("http://*/a/b/-", "http://*/a/b/c/d", true),
imtest("http://*.foo.com/a/b/-", "http://*/a/b/c/d", false),
imtest("http:*", "http://*/a/b/c/d", true),
// literal IPv4 addresses
imtest("http://1.2.3.4/a/b/-", "http://www.biz.bar.foo.com/a/b/c/d", false),
imtest("http://1.2.3.4/a/b/-", "http://1.2.3.4/a/b/c/d", true),
imtest("http://1.2.3.4/a/b/-", "http://1.2.88.4/a/b/c/d", false),
imtest("http:*", "http://1.2.88.4/a/b/c/d", true),
// literal IPv6 addresses
imtest("http://[fe80::]/a/b/-", "http://[fe80::0]/a/b/c", true),
imtest("http://[fe80::]/a/b/-", "http://[fe80::3]/a/b/c", false),
imtest("http://[1:2:3:4:5:6:7:8]/a/b/-","http://[1:002:03:4:0005:6:07:8]/a/b/c", true),
imtest("http://[1:2:3:4:5:6:7:8]/a/b/-","http://[1:002:03:4:0033:6:07:8]/a/b/c", false),
imtest("http://[1::2]/a/b/-", "http://[1:0:0:0::2]/a/b/c", true),
imtest("http://[1::2]/a/b/-", "http://[1:0:0:0::3]/a/b/c", false),
imtest("http://[FE80::]:99", "http://[fe80:0::]:99", true),
imtest("http:*", "http://[fe80:0::]:99", true),
// portranges
imtest("http://*.foo.com:1-2/a/b/-", "http://www.foo.com:1/a/b/c/d", true),
imtest("http://*.foo.com:1-2/a/b/-", "http://www.foo.com:3/a/b/c/d", false),
imtest("http://*.foo.com:3-/a/b/-", "http://www.foo.com:1/a/b/c/d", false),
imtest("http://*.foo.com:3-/a/b/-", "http://www.foo.com:4-5/a/b/c/d", true),
imtest("http://*.foo.com:3-/a/b/-", "http://www.foo.com:3-3/a/b/c/d", true),
imtest("http://*.foo.com:3-99/a/b/-", "http://www.foo.com:55-100/a/b/c/d", false),
imtest("http://*.foo.com:-44/a/b/-", "http://www.foo.com:1/a/b/c/d", true),
imtest("http://*.foo.com:-44/a/b/-", "http://www.foo.com:1-10/a/b/c/d", true),
imtest("http://*.foo.com:-44/a/b/-", "http://www.foo.com:44/a/b/c/d", true),
imtest("http://*.foo.com:-44/a/b/-", "http://www.foo.com:45/a/b/c/d", false),
imtest("http://www.foo.com:70-90/a/b", "http://www.foo.com/a/b", true),
imtest("https://www.foo.com/a/b", "https://www.foo.com:80/a/b", false),
imtest("https://www.foo.com:70-90/a/b", "https://www.foo.com/a/b", false),
imtest("https://www.foo.com/a/b", "https://www.foo.com:443/a/b", true),
imtest("https://www.foo.com:200-500/a/b", "https://www.foo.com/a/b", true),
imtest("http://www.foo.com:*/a/b", "http://www.foo.com:1-12345/a/b", true),
// misc
imtest("https:*", "http://www.foo.com", false),
imtest("https:*", "http:*", false)
};
static Test[] actionImplies = {
actest("GET", "GET", true),
actest("GET", "POST", false),
......@@ -132,6 +246,21 @@ public class HttpURLPermissionTest {
actest("*:*", "GET:x-bar,x-foo", true)
};
static Test[] equalityTests = {
eqtest("http://www.foo.com", "http://www.FOO.CoM", true),
eqtest("http://[fe80:0:0::]:1-2", "HTTP://[FE80::]:1-2", true),
eqtest("HTTP://1.2.3.5/A/B/C", "http://1.2.3.5/A/b/C", false),
eqtest("HTTP://1.2.3.5/A/B/C", "HTTP://1.2.3.5/A/b/C", false),
eqtest("http:*", "http:*", true),
eqtest("http://www.foo.com/a/b", "https://www.foo.com/a/b", false),
eqtest("http://w.foo.com", "http://w.foo.com/", false),
eqtest("http://*.foo.com", "http://*.foo.com", true),
eqtest("http://www.foo.com/a/b", "http://www.foo.com:80/a/b", true),
eqtest("http://www.foo.com/a/b", "http://www.foo.com:82/a/b", false),
eqtest("https://www.foo.com/a/b", "https://www.foo.com:443/a/b", true),
eqtest("https://www.foo.com/a/b", "https://www.foo.com:444/a/b", false),
};
static boolean failed = false;
public static void main(String args[]) throws Exception {
......@@ -147,12 +276,67 @@ public class HttpURLPermissionTest {
}
if (!result) {
failed = true;
System.out.println ("test failed: " + test.arg1 + ": " +
test.arg2 + " Exception: " + caught);
}
System.out.printf("path test %d failed: %s : %s\n", i, test.arg1,
test.arg2);
} else {
System.out.println ("path test " + i + " OK");
}
}
// new tests for functionality added in revision of API
for (int i=0; i<pathImplies2.length ; i++) {
URLImpliesTest test = (URLImpliesTest)pathImplies2[i];
Exception caught = null;
boolean result = false;
try {
result = test.execute();
} catch (Exception e) {
caught = e;
e.printStackTrace();
}
if (!result) {
failed = true;
System.out.printf("path2 test %d failed: %s : %s\n", i, test.arg1,
test.arg2);
} else {
System.out.println ("path2 test " + i + " OK");
}
}
for (int i=0; i<equalityTests.length ; i++) {
URLEqualityTest test = (URLEqualityTest)equalityTests[i];
Exception caught = null;
boolean result = false;
try {
result = test.execute();
} catch (Exception e) {
caught = e;
e.printStackTrace();
}
if (!result) {
failed = true;
System.out.printf("equality test %d failed: %s : %s\n", i, test.arg1,
test.arg2);
} else {
System.out.println ("equality test " + i + " OK");
}
}
for (int i=0; i<exceptionTests.length; i++) {
ExTest test = (ExTest)exceptionTests[i];
boolean result = test.execute();
if (!result) {
System.out.println ("test failed: " + test.arg);
failed = true;
} else {
System.out.println ("exception test " + i + " OK");
}
}
for (int i=0; i<actionImplies.length ; i++) {
ActionImpliesTest test = (ActionImpliesTest)actionImplies[i];
Exception caught = null;
......@@ -186,14 +370,14 @@ public class HttpURLPermissionTest {
static void serializationTest(String name, String actions)
throws Exception {
HttpURLPermission out = new HttpURLPermission(name, actions);
URLPermission out = new URLPermission(name, actions);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(baos);
o.writeObject(out);
ByteArrayInputStream bain = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream i = new ObjectInputStream(bain);
HttpURLPermission in = (HttpURLPermission)i.readObject();
URLPermission in = (URLPermission)i.readObject();
if (!in.equals(out)) {
System.out.println ("FAIL");
System.out.println ("in = " + in);
......
......@@ -21,7 +21,7 @@
* questions.
*/
import java.net.HttpURLPermission;
import java.net.URLPermission;
/*
* Run the tests once without security manager and once with
*
......
......@@ -22,8 +22,8 @@
//
grant {
permission java.net.HttpURLPermission "http://127.0.0.1:12567/foo.html", "GET:X-Foo,Z-Bar";
permission java.net.HttpURLPermission "https://127.0.0.1:12568/foo.html", "POST:X-Fob,T-Bar";
permission java.net.URLPermission "http://127.0.0.1:12567/foo.html", "GET:X-Foo,Z-Bar";
permission java.net.URLPermission "https://127.0.0.1:12568/foo.html", "POST:X-Fob,T-Bar";
// needed for HttpServer
permission "java.net.SocketPermission" "localhost:1024-", "listen,resolve,accept";
......
......@@ -22,8 +22,8 @@
//
grant {
permission java.net.HttpURLPermission "http://127.0.0.1:12567/*", "GET:X-Foo";
permission java.net.HttpURLPermission "https://127.0.0.1:12568/*", "POST:X-Fob";
permission java.net.URLPermission "http://127.0.0.1:12567/*", "GET:X-Foo";
permission java.net.URLPermission "https://127.0.0.1:12568/*", "POST:X-Fob";
// needed for HttpServer
permission "java.net.SocketPermission" "localhost:1024-", "listen,resolve,accept";
......
......@@ -22,8 +22,8 @@
//
grant {
permission java.net.HttpURLPermission "http://127.0.0.1:12567/a/b/-", "DELETE,GET:X-Foo,Y-Foo";
permission java.net.HttpURLPermission "https://127.0.0.1:12568/a/c/-", "POST:*";
permission java.net.URLPermission "http://127.0.0.1:12567/a/b/-", "DELETE,GET:X-Foo,Y-Foo";
permission java.net.URLPermission "https://127.0.0.1:12568/a/c/-", "POST:*";
// needed for HttpServer
permission "java.net.SocketPermission" "localhost:1024-", "listen,resolve,accept";
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册