From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- libjava/classpath/java/net/SocketPermission.java | 636 +++++++++++++++++++++++ 1 file changed, 636 insertions(+) create mode 100644 libjava/classpath/java/net/SocketPermission.java (limited to 'libjava/classpath/java/net/SocketPermission.java') diff --git a/libjava/classpath/java/net/SocketPermission.java b/libjava/classpath/java/net/SocketPermission.java new file mode 100644 index 000000000..ce16a79a0 --- /dev/null +++ b/libjava/classpath/java/net/SocketPermission.java @@ -0,0 +1,636 @@ +/* SocketPermission.java -- Class modeling permissions for socket operations + Copyright (C) 1998, 2000, 2001, 2002, 2004, 2006 Free Software + Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.net; + +import gnu.java.lang.CPStringBuilder; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.security.Permission; +import java.security.PermissionCollection; +import java.util.StringTokenizer; + + +/** + * This class models a specific set of permssions for connecting to a + * host. There are two elements to this, the host/port combination and + * the permission list. + *

+ * The host/port combination is specified as followed + *

+ *

+ * hostname[:[-]port[-[port]]]
+ * 
+ *

+ * The hostname portion can be either a hostname or IP address. If it is + * a hostname, a wildcard is allowed in hostnames. This wildcard is a "*" + * and matches one or more characters. Only one "*" may appear in the + * host and it must be the leftmost character. For example, + * "*.urbanophile.com" matches all hosts in the "urbanophile.com" domain. + *

+ * The port portion can be either a single value, or a range of values + * treated as inclusive. The first or the last port value in the range + * can be omitted in which case either the minimum or maximum legal + * value for a port (respectively) is used by default. Here are some + * examples: + *

+ * The permission list is a comma separated list of individual permissions. + * These individual permissions are: + *

+ *

+ * accept
+ * connect
+ * listen
+ * resolve
+ * 
+ *

+ * The "listen" permission is only relevant if the host is localhost. If + * any permission at all is specified, then resolve permission is implied to + * exist. + *

+ * Here are a variety of examples of how to create SocketPermission's + *

+ * SocketPermission("www.urbanophile.com", "connect");
+ *   Can connect to any port on www.urbanophile.com
+ * SocketPermission("www.urbanophile.com:80", "connect,accept");
+ *   Can connect to or accept connections from www.urbanophile.com on port 80
+ * SocketPermission("localhost:1024-", "listen,accept,connect");
+ *   Can connect to, accept from, an listen on any local port number 1024
+ *   and up.
+ * SocketPermission("*.edu", "connect");
+ *   Can connect to any host in the edu domain
+ * SocketPermission("197.197.20.1", "accept");
+ *   Can accept connections from 197.197.20.1
+ * 

+ * + * This class also supports IPv6 addresses. These should be specified + * in either RFC 2732 format or in full uncompressed form. + * + * @since 1.2 + * + * @author Written by Aaron M. Renn (arenn@urbanophile.com) + * @author Extensively modified by Gary Benson (gbenson@redhat.com) + */ +public final class SocketPermission extends Permission implements Serializable +{ + static final long serialVersionUID = -7204263841984476862L; + + /** + * A hostname (possibly wildcarded). Will be set if and only if + * this object was initialized with a hostname. + */ + 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; + private transient int maxport; + + /** + * Values used for minimum and maximum ports when one or both bounds + * are omitted. This class is essentially independent of the + * networking code it describes, so we do not limit ports to the + * usual network limits of 1 and 65535. + */ + private static final int MIN_PORT = 0; + private static final int MAX_PORT = Integer.MAX_VALUE; + + /** + * The actions for which we have permission. This field is present + * to make the serialized form correct and should not be used by + * anything other than writeObject: everything else should use + * actionmask. + */ + private String actions; + + /** + * A bitmask representing the actions for which we have permission. + */ + private transient int actionmask; + + /** + * The available actions, in the canonical order required for getActions(). + */ + private static final String[] ACTIONS = new String[] { + "connect", "listen", "accept", "resolve"}; + + /** + * Initializes a new instance of SocketPermission with the + * specified host/port combination and actions string. + * + * @param hostport The hostname/port number combination + * @param actions The actions string + */ + public SocketPermission(String hostport, String actions) + { + super(processHostport(hostport)); + + setHostPort(getName()); + setActions(actions); + } + + /** + * There are two cases in which hostport needs rewriting before + * being passed to the superclass constructor. If hostport is an + * empty string then it is substituted with "localhost". And if + * the host part of hostport is a literal IPv6 address in the full + * uncompressed form not enclosed with "[" and "]" then we enclose + * it with them. + */ + private static String processHostport(String hostport) + { + if (hostport.length() == 0) + return "localhost"; + + if (hostport.charAt(0) == '[') + return hostport; + + int colons = 0; + boolean colon_allowed = true; + for (int i = 0; i < hostport.length(); i++) + { + if (hostport.charAt(i) == ':') + { + if (!colon_allowed) + throw new IllegalArgumentException("Ambiguous hostport part"); + colons++; + colon_allowed = false; + } + else + colon_allowed = true; + } + + switch (colons) + { + case 0: + case 1: + // a hostname or IPv4 address + return hostport; + + case 7: + // an IPv6 address with no ports + return "[" + hostport + "]"; + + case 8: + // an IPv6 address with ports + int last_colon = hostport.lastIndexOf(':'); + return "[" + hostport.substring(0, last_colon) + "]" + + hostport.substring(last_colon); + + default: + throw new IllegalArgumentException("Ambiguous hostport part"); + } + } + + /** + * Parse the hostport argument to the constructor. + */ + private void setHostPort(String hostport) + { + // Split into host and ports + String host, ports; + if (hostport.charAt(0) == '[') + { + // host is a bracketed IPv6 address + int end = hostport.indexOf("]"); + if (end == -1) + 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) == ':') + ports = hostport.substring(end + 2); + else + throw new IllegalArgumentException("Bad character after ']'"); + } + else + { + // host is a hostname or IPv4 address + int sep = hostport.indexOf(":"); + if (sep == -1) + { + host = hostport; + ports = ""; + } + else + { + 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 + if (ports.length() == 0) + { + minport = MIN_PORT; + maxport = MAX_PORT; + } + else + { + int sep = ports.indexOf("-"); + if (sep == -1) + { + // a single port + minport = maxport = Integer.parseInt(ports); + } + else + { + if (ports.indexOf("-", sep + 1) != -1) + throw new IllegalArgumentException("Unexpected '-'"); + + if (sep == 0) + { + // an upper bound + minport = MIN_PORT; + maxport = Integer.parseInt(ports.substring(1)); + } + else if (sep == ports.length() - 1) + { + // a lower bound + minport = + Integer.parseInt(ports.substring(0, ports.length() - 1)); + maxport = MAX_PORT; + } + else + { + // a range with two bounds + minport = Integer.parseInt(ports.substring(0, sep)); + maxport = Integer.parseInt(ports.substring(sep + 1)); + } + } + } + } + + /** + * Parse the actions argument to the constructor. + */ + private void setActions(String actionstring) + { + actionmask = 0; + + boolean resolve_needed = false; + boolean resolve_present = false; + + StringTokenizer t = new StringTokenizer(actionstring, ","); + while (t.hasMoreTokens()) + { + String action = t.nextToken(); + action = action.trim().toLowerCase(); + setAction(action); + + if (action.equals("resolve")) + resolve_present = true; + else + resolve_needed = true; + } + + if (resolve_needed && !resolve_present) + setAction("resolve"); + } + + /** + * Parse one element of the actions argument to the constructor. + */ + private void setAction(String action) + { + for (int i = 0; i < ACTIONS.length; i++) + { + if (action.equals(ACTIONS[i])) + { + actionmask |= 1 << i; + return; + } + } + throw new IllegalArgumentException("Unknown action " + action); + } + + /** + * Tests this object for equality against another. This will be true if + * and only if the passed object is an instance of + * SocketPermission and both its hostname/port combination + * and permissions string are identical. + * + * @param obj The object to test against for equality + * + * @return true if object is equal to this object, + * false otherwise. + */ + public boolean equals(Object obj) + { + SocketPermission p; + + if (obj instanceof SocketPermission) + p = (SocketPermission) obj; + else + return false; + + 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); + } + } + + /** + * Returns a hash code value for this object. Overrides the + * Permission.hashCode(). + * + * @return A hash code + */ + public int hashCode() + { + int code = actionmask + minport + maxport; + if (address != null) + code += address.hashCode(); + else + code += hostname.hashCode(); + return code; + } + + /** + * Returns the list of permission actions in this object in canonical + * order. The canonical order is "connect,listen,accept,resolve" + * + * @return The permitted action string. + */ + public String getActions() + { + CPStringBuilder sb = new CPStringBuilder(""); + + for (int i = 0; i < ACTIONS.length; i++) + { + if ((actionmask & (1 << i)) != 0) + { + if (sb.length() != 0) + sb.append(","); + sb.append(ACTIONS[i]); + } + } + + return sb.toString(); + } + + /** + * Returns a new PermissionCollection object that can hold + * SocketPermission's. + * + * @return A new PermissionCollection. + */ + public PermissionCollection newPermissionCollection() + { + // FIXME: Implement + + return null; + } + + /** + * 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: + * + *

+ * + *

The argument's hostname will be a subset of this object's hostname if:

+ * + * + * + * @param perm The Permission to check against + * + * @return true if the Permission is implied by + * this object, false otherwise. + */ + public boolean implies(Permission perm) + { + SocketPermission p; + + // First make sure we are the right object type + if (perm instanceof SocketPermission) + p = (SocketPermission) perm; + 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; + + // Then check the ports + if ((p.minport < minport) || (p.maxport > maxport)) + return false; + + // Finally check the hosts + String p_canon = null; + + // 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) + { + InetAddress[] addrs = p.getAddresses(); + for (int i = 0; i < addrs.length; i++) + { + if (address.equals(addrs[i])) + return true; + } + } + + // Return true if this object is a wildcarded domain that + // p's canonical name matches. + if (hostname != null && hostname.charAt(0) == '*') + { + p_canon = p.getCanonicalHostName(); + if (p_canon != null && p_canon.endsWith(hostname.substring(1))) + 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; + } + } + } + + // Return true if this object's canonical name equals p's. + String canon = getCanonicalHostName(); + if (canon != null) + { + if (p_canon == null) + p_canon = p.getCanonicalHostName(); + if (p_canon != null && canon.equals(p_canon)) + return true; + } + + // Didn't make it + return false; + } + + /** + * Deserializes a SocketPermission object from + * an input stream. + * + * @param input the input stream. + * @throws IOException if an I/O error occurs in the stream. + * @throws ClassNotFoundException if the class of the + * serialized object could not be found. + */ + private void readObject(ObjectInputStream input) + throws IOException, ClassNotFoundException + { + input.defaultReadObject(); + setHostPort(getName()); + setActions(actions); + } + + /** + * Serializes a SocketPermission object to an + * output stream. + * + * @param output the output stream. + * @throws IOException if an I/O error occurs in the stream. + */ + private void writeObject(ObjectOutputStream output) + throws IOException + { + actions = getActions(); + output.defaultWriteObject(); + } +} -- cgit v1.2.3