diff options
author | Gary Benson <gbenson@redhat.com> | 2006-09-14 13:43:39 +0000 |
---|---|---|
committer | Gary Benson <gbenson@redhat.com> | 2006-09-14 13:43:39 +0000 |
commit | 76074e7e82247a39031b9031396fdad9abd3ed98 (patch) | |
tree | 21b37702d808cfeef1bfe748bbd82f9e692b905c /java/net | |
parent | c09ef45dc0dbebcbbcd4ff6c4caf5db1f2dab4f5 (diff) | |
download | classpath-76074e7e82247a39031b9031396fdad9abd3ed98.tar.gz |
2006-09-14 Gary Benson <gbenson@redhat.com>
* java/net/InetAddress.java
(internalGetCanonicalHostName): New method.
(getCanonicalHostName): Use internalGetCanonicalHostName.
(getByLiteral): New method.
(getAllByName): Use getByLiteral.
* java/net/SocketPermission.java
(host): Replaced with...
(hostname, address): New fields.
(equals, hashcode): Reflect the above.
(setHostPort): Parse host into hostname or address.
(implies): Rewrite host checks.
Diffstat (limited to 'java/net')
-rw-r--r-- | java/net/InetAddress.java | 49 | ||||
-rw-r--r-- | java/net/SocketPermission.java | 161 |
2 files changed, 173 insertions, 37 deletions
diff --git a/java/net/InetAddress.java b/java/net/InetAddress.java index b5d66c285..a67358832 100644 --- a/java/net/InetAddress.java +++ b/java/net/InetAddress.java @@ -311,20 +311,27 @@ public class InetAddress implements Serializable /** * Returns the canonical hostname represented by this InetAddress - * - * @since 1.4 */ - public String getCanonicalHostName() + String internalGetCanonicalHostName() { - String hostname; try { - hostname = VMInetAddress.getHostByAddr(addr); + return VMInetAddress.getHostByAddr(addr); } catch (UnknownHostException e) { return getHostAddress(); } + } + + /** + * Returns the canonical hostname represented by this InetAddress + * + * @since 1.4 + */ + public String getCanonicalHostName() + { + String hostname = internalGetCanonicalHostName(); SecurityManager sm = System.getSecurityManager(); if (sm != null) @@ -492,6 +499,34 @@ public class InetAddress implements Serializable } /** + * Returns an InetAddress object representing the IP address of + * the given literal IP address in dotted decimal format such as + * "127.0.0.1". This is used by SocketPermission.setHostPort() + * to parse literal IP addresses without performing a DNS lookup. + * + * @param literal The literal IP address to create the InetAddress + * object from + * + * @return The address of the host as an InetAddress object, or + * null if the IP address is invalid. + */ + static InetAddress getByLiteral(String literal) + { + byte[] address = VMInetAddress.aton(literal); + if (address == null) + return null; + + try + { + return getByAddress(address); + } + catch (UnknownHostException e) + { + throw new RuntimeException("should never happen", e); + } + } + + /** * Returns an InetAddress object representing the IP address of the given * hostname. This name can be either a hostname such as "www.urbanophile.com" * or an IP address in dotted decimal format such as "127.0.0.1". If the @@ -542,9 +577,9 @@ public class InetAddress implements Serializable return new InetAddress[] {LOCALHOST}; // Check if hostname is an IP address - byte[] address = VMInetAddress.aton(hostname); + InetAddress address = getByLiteral(hostname); if (address != null) - return new InetAddress[] {getByAddress(address)}; + return new InetAddress[] {address}; // Perform security check before resolving SecurityManager sm = System.getSecurityManager(); diff --git a/java/net/SocketPermission.java b/java/net/SocketPermission.java index 97e93dcbb..2d6343dc5 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; @@ -225,7 +232,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 +241,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 +266,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 +382,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 +411,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 +456,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 +528,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 +542,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; } |