summaryrefslogtreecommitdiff
path: root/java/net/SocketPermission.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/net/SocketPermission.java')
-rw-r--r--java/net/SocketPermission.java171
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;
}