diff options
Diffstat (limited to 'java/net/SocketPermission.java')
-rw-r--r-- | java/net/SocketPermission.java | 171 |
1 files changed, 138 insertions, 33 deletions
diff --git a/java/net/SocketPermission.java b/java/net/SocketPermission.java index 97e93dcbb..64885438a 100644 --- a/java/net/SocketPermission.java +++ b/java/net/SocketPermission.java @@ -117,11 +117,18 @@ public final class SocketPermission extends Permission implements Serializable static final long serialVersionUID = -7204263841984476862L; /** - * A hostname (possibly wildcarded) or IP address (IPv4 or IPv6). + * A hostname (possibly wildcarded). Will be set if and only if + * this object was initialized with a hostname. */ - private transient String host; + private transient String hostname = null; /** + * An IP address (IPv4 or IPv6). Will be set if and only if this + * object was initialized with a single literal IP address. + */ + private transient InetAddress address = null; + + /** * A range of ports. */ private transient int minport; @@ -186,16 +193,19 @@ public final class SocketPermission extends Permission implements Serializable if (hostport.charAt(0) == '[') return hostport; - int colons = 0, last_colon = 0; + int colons = 0; + boolean colon_allowed = true; for (int i = 0; i < hostport.length(); i++) { if (hostport.charAt(i) == ':') { - if (i - last_colon == 1) + if (!colon_allowed) throw new IllegalArgumentException("Ambiguous hostport part"); colons++; - last_colon = i; + colon_allowed = false; } + else + colon_allowed = true; } switch (colons) @@ -211,6 +221,7 @@ public final class SocketPermission extends Permission implements Serializable case 8: // an IPv6 address with ports + int last_colon = hostport.lastIndexOf(':'); return "[" + hostport.substring(0, last_colon) + "]" + hostport.substring(last_colon); @@ -225,7 +236,7 @@ public final class SocketPermission extends Permission implements Serializable private void setHostPort(String hostport) { // Split into host and ports - String ports; + String host, ports; if (hostport.charAt(0) == '[') { // host is a bracketed IPv6 address @@ -234,6 +245,10 @@ public final class SocketPermission extends Permission implements Serializable throw new IllegalArgumentException("Unmatched '['"); host = hostport.substring(1, end); + address = InetAddress.getByLiteral(host); + if (address == null) + throw new IllegalArgumentException("Bad IPv6 address"); + if (end == hostport.length() - 1) ports = ""; else if (hostport.charAt(end + 1) == ':') @@ -255,6 +270,15 @@ public final class SocketPermission extends Permission implements Serializable host = hostport.substring(0, sep); ports = hostport.substring(sep + 1); } + + address = InetAddress.getByLiteral(host); + if (address == null) + { + if (host.lastIndexOf('*') > 0) + throw new IllegalArgumentException("Bad hostname"); + + hostname = host; + } } // Parse and validate the ports @@ -362,10 +386,25 @@ public final class SocketPermission extends Permission implements Serializable else return false; - return p.actionmask == actionmask && - p.minport == minport && - p.maxport == maxport && - p.host.equals(host); + if (p.actionmask != actionmask || + p.minport != minport || + p.maxport != maxport) + return false; + + if (address != null) + { + if (p.address == null) + return false; + else + return p.address.equals(address); + } + else + { + if (p.hostname == null) + return false; + else + return p.hostname.equals(hostname); + } } /** @@ -376,7 +415,12 @@ public final class SocketPermission extends Permission implements Serializable */ public int hashCode() { - return actionmask + minport + maxport + host.hashCode(); + int code = actionmask + minport + maxport; + if (address != null) + code += address.hashCode(); + else + code += hostname.hashCode(); + return code; } /** @@ -416,6 +460,44 @@ public final class SocketPermission extends Permission implements Serializable } /** + * Returns an array of all IP addresses represented by this object. + */ + private InetAddress[] getAddresses() + { + if (address != null) + return new InetAddress[] {address}; + + try + { + return InetAddress.getAllByName(hostname); + } + catch (UnknownHostException e) + { + return new InetAddress[0]; + } + } + + /** + * Returns the canonical hostname represented by this object, + * or null if this object represents a wildcarded domain. + */ + private String getCanonicalHostName() + { + if (address != null) + return address.internalGetCanonicalHostName(); + if (hostname.charAt(0) == '*') + return null; + try + { + return InetAddress.getByName(hostname).internalGetCanonicalHostName(); + } + catch (UnknownHostException e) + { + return null; + } + } + + /** * Returns true if the permission object passed it is implied by the * this permission. This will be true if: * @@ -450,6 +532,11 @@ public final class SocketPermission extends Permission implements Serializable else return false; + // If p was initialised with an empty hostname then we do not + // imply it. This is not part of the spec, but it seems necessary. + if (p.hostname != null && p.hostname.length() == 0) + return false; + // Next check the actions if ((p.actionmask & actionmask) != p.actionmask) return false; @@ -459,36 +546,54 @@ public final class SocketPermission extends Permission implements Serializable return false; // Finally check the hosts - if (host.equals(p.host)) - return true; + String p_canon = null; - // Try the canonical names - String ourcanonical = null; - String theircanonical = null; - try + // Return true if this object was initialized with a single + // IP address which one of p's IP addresses is equal to. + if (address != null) { - ourcanonical = InetAddress.getByName(host).getHostName(); - theircanonical = InetAddress.getByName(p.host).getHostName(); + InetAddress[] addrs = p.getAddresses(); + for (int i = 0; i < addrs.length; i++) + { + if (address.equals(addrs[i])) + return true; + } } - catch (UnknownHostException e) + + // Return true if this object is a wildcarded domain that + // p's canonical name matches. + if (hostname != null && hostname.charAt(0) == '*') { - // Who didn't resolve? Just assume current address is canonical enough - // Is this ok to do? - if (ourcanonical == null) - ourcanonical = host; - if (theircanonical == null) - theircanonical = p.host; + p_canon = p.getCanonicalHostName(); + if (p_canon != null && p_canon.endsWith(hostname.substring(1))) + return true; + } - if (ourcanonical.equals(theircanonical)) - return true; + // Return true if this one of this object's IP addresses + // is equal to one of p's. + if (address == null) + { + InetAddress[] addrs = p.getAddresses(); + InetAddress[] p_addrs = p.getAddresses(); + + for (int i = 0; i < addrs.length; i++) + { + for (int j = 0; j < p_addrs.length; j++) + { + if (addrs[i].equals(p_addrs[j])) + return true; + } + } + } - // Well, last chance. Try for a wildcard - if (host.indexOf("*.") != -1) + // Return true if this object's canonical name equals p's. + String canon = getCanonicalHostName(); + if (canon != null) { - String wild_domain = - host.substring(host.indexOf("*" + 1)); - if (theircanonical.endsWith(wild_domain)) + if (p_canon == null) + p_canon = p.getCanonicalHostName(); + if (p_canon != null && canon.equals(p_canon)) return true; } |