GNU Classpath (0.20) | |
Frames | No Frames |
1: /* SocketPermission.java -- Class modeling permissions for socket operations 2: Copyright (C) 1998, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package java.net; 39: 40: import java.io.Serializable; 41: import java.security.Permission; 42: import java.security.PermissionCollection; 43: 44: 45: /** 46: * This class models a specific set of permssions for connecting to a 47: * host. There are two elements to this, the host/port combination and 48: * the permission list. 49: * <p> 50: * The host/port combination is specified as followed 51: * <p> 52: * <pre> 53: * hostname[:[-]port[-[port]]] 54: * </pre> 55: * <p> 56: * The hostname portion can be either a hostname or IP address. If it is 57: * a hostname, a wildcard is allowed in hostnames. This wildcard is a "*" 58: * and matches one or more characters. Only one "*" may appear in the 59: * host and it must be the leftmost character. For example, 60: * "*.urbanophile.com" matches all hosts in the "urbanophile.com" domain. 61: * <p> 62: * The port portion can be either a single value, or a range of values 63: * treated as inclusive. The first or the last port value in the range 64: * can be omitted in which case either the minimum or maximum legal 65: * value for a port (respectively) is used by default. Here are some 66: * examples: 67: * <p><ul> 68: * <li>8080 - Represents port 8080 only</li> 69: * <li>2000-3000 - Represents ports 2000 through 3000 inclusive</li> 70: * <li>-4000 - Represents ports 0 through 4000 inclusive</li> 71: * <li>1024- - Represents ports 1024 through 65535 inclusive</li> 72: * </ul><p> 73: * The permission list is a comma separated list of individual permissions. 74: * These individual permissions are: 75: * <p> 76: * <pre> 77: * accept 78: * connect 79: * listen 80: * resolve 81: * </pre> 82: * <p> 83: * The "listen" permission is only relevant if the host is localhost. If 84: * any permission at all is specified, then resolve permission is implied to 85: * exist. 86: * <p> 87: * Here are a variety of examples of how to create SocketPermission's 88: * <p><pre> 89: * SocketPermission("www.urbanophile.com", "connect"); 90: * Can connect to any port on www.urbanophile.com 91: * SocketPermission("www.urbanophile.com:80", "connect,accept"); 92: * Can connect to or accept connections from www.urbanophile.com on port 80 93: * SocketPermission("localhost:1024-", "listen,accept,connect"); 94: * Can connect to, accept from, an listen on any local port number 1024 95: * and up. 96: * SocketPermission("*.edu", "connect"); 97: * Can connect to any host in the edu domain 98: * SocketPermission("197.197.20.1", "accept"); 99: * Can accept connections from 197.197.20.1 100: * </pre><p> 101: * 102: * This class also supports IPv6 addresses. These should be specified 103: * in either RFC 2732 format or in full uncompressed form. 104: * 105: * @since 1.2 106: * 107: * @author Aaron M. Renn (arenn@urbanophile.com) 108: */ 109: public final class SocketPermission extends Permission implements Serializable 110: { 111: static final long serialVersionUID = -7204263841984476862L; 112: 113: // FIXME: Needs serialization work, including readObject/writeObject methods. 114: 115: /** 116: * A hostname/port combination as described above 117: */ 118: private transient String hostport; 119: 120: /** 121: * A comma separated list of actions for which we have permission 122: */ 123: private String actions; 124: 125: /** 126: * Initializes a new instance of <code>SocketPermission</code> with the 127: * specified host/port combination and actions string. 128: * 129: * @param hostport The hostname/port number combination 130: * @param actions The actions string 131: */ 132: public SocketPermission(String hostport, String actions) 133: { 134: super(hostport); 135: 136: this.hostport = hostport; 137: this.actions = actions; 138: } 139: 140: /** 141: * Tests this object for equality against another. This will be true if 142: * and only if the passed object is an instance of 143: * <code>SocketPermission</code> and both its hostname/port combination 144: * and permissions string are identical. 145: * 146: * @param obj The object to test against for equality 147: * 148: * @return <code>true</code> if object is equal to this object, 149: * <code>false</code> otherwise. 150: */ 151: public boolean equals(Object obj) 152: { 153: if (! (obj instanceof SocketPermission)) 154: return false; 155: 156: if (((SocketPermission) obj).hostport.equals(hostport)) 157: if (((SocketPermission) obj).actions.equals(actions)) 158: return true; 159: 160: return false; 161: } 162: 163: /** 164: * Returns a hash code value for this object. Overrides the 165: * <code>Permission.hashCode()</code>. 166: * 167: * @return A hash code 168: */ 169: public int hashCode() 170: { 171: int hash = 100; 172: if (hostport != null) 173: hash += hostport.hashCode(); 174: if (actions != null) 175: hash += actions.hashCode(); 176: return hash; 177: } 178: 179: /** 180: * Returns the list of permission actions in this object in canonical 181: * order. The canonical order is "connect,listen,accept,resolve" 182: * 183: * @return The permitted action string. 184: */ 185: public String getActions() 186: { 187: boolean found = false; 188: StringBuffer sb = new StringBuffer(""); 189: 190: if (actions.indexOf("connect") != -1) 191: { 192: sb.append("connect"); 193: found = true; 194: } 195: 196: if (actions.indexOf("listen") != -1) 197: if (found) 198: sb.append(",listen"); 199: else 200: { 201: sb.append("listen"); 202: found = true; 203: } 204: 205: if (actions.indexOf("accept") != -1) 206: if (found) 207: sb.append(",accept"); 208: else 209: { 210: sb.append("accept"); 211: found = true; 212: } 213: 214: if (found) 215: sb.append(",resolve"); 216: else if (actions.indexOf("resolve") != -1) 217: sb.append("resolve"); 218: 219: return sb.toString(); 220: } 221: 222: /** 223: * Returns a new <code>PermissionCollection</code> object that can hold 224: * <code>SocketPermission</code>'s. 225: * 226: * @return A new <code>PermissionCollection</code>. 227: */ 228: public PermissionCollection newPermissionCollection() 229: { 230: // FIXME: Implement 231: 232: return null; 233: } 234: 235: /** 236: * Returns true if the permission object passed it is implied by the 237: * this permission. This will be true if: 238: * 239: * <ul> 240: * <li>The argument is of type <code>SocketPermission</code></li> 241: * <li>The actions list of the argument are in this object's actions</li> 242: * <li>The port range of the argument is within this objects port range</li> 243: * <li>The hostname is equal to or a subset of this objects hostname</li> 244: * </ul> 245: * 246: * <p>The argument's hostname will be a subset of this object's hostname if:</p> 247: * 248: * <ul> 249: * <li>The argument's hostname or IP address is equal to this object's.</li> 250: * <li>The argument's canonical hostname is equal to this object's.</li> 251: * <li>The argument's canonical name matches this domains hostname with 252: * wildcards</li> 253: * </ul> 254: * 255: * @param perm The <code>Permission</code> to check against 256: * 257: * @return <code>true</code> if the <code>Permission</code> is implied by 258: * this object, <code>false</code> otherwise. 259: */ 260: public boolean implies(Permission perm) 261: { 262: SocketPermission p; 263: 264: // First make sure we are the right object type 265: if (perm instanceof SocketPermission) 266: p = (SocketPermission) perm; 267: else 268: return false; 269: 270: // Next check the actions 271: String ourlist = getActions(); 272: String theirlist = p.getActions(); 273: 274: if (! ourlist.startsWith(theirlist)) 275: return false; 276: 277: // Now check ports 278: int ourfirstport = 0; 279: 280: // Now check ports 281: int ourlastport = 0; 282: 283: // Now check ports 284: int theirfirstport = 0; 285: 286: // Now check ports 287: int theirlastport = 0; 288: 289: // Get ours 290: if (hostport.indexOf(":") == -1) 291: { 292: ourfirstport = 0; 293: ourlastport = 65535; 294: } 295: else 296: { 297: // FIXME: Needs bulletproofing. 298: // This will dump if hostport if all sorts of bad data was passed to 299: // the constructor 300: String range = hostport.substring(hostport.indexOf(":") + 1); 301: if (range.startsWith("-")) 302: ourfirstport = 0; 303: else if (range.indexOf("-") == -1) 304: ourfirstport = Integer.parseInt(range); 305: else 306: ourfirstport = 307: Integer.parseInt(range.substring(0, range.indexOf("-"))); 308: 309: if (range.endsWith("-")) 310: ourlastport = 65535; 311: else if (range.indexOf("-") == -1) 312: ourlastport = Integer.parseInt(range); 313: else 314: ourlastport = 315: Integer.parseInt(range.substring(range.indexOf("-") + 1, 316: range.length())); 317: } 318: 319: // Get theirs 320: if (p.hostport.indexOf(":") == -1) 321: { 322: theirfirstport = 0; 323: ourlastport = 65535; 324: } 325: else 326: { 327: // This will dump if hostport if all sorts of bad data was passed to 328: // the constructor 329: String range = p.hostport.substring(hostport.indexOf(":") + 1); 330: if (range.startsWith("-")) 331: theirfirstport = 0; 332: else if (range.indexOf("-") == -1) 333: theirfirstport = Integer.parseInt(range); 334: else 335: theirfirstport = 336: Integer.parseInt(range.substring(0, range.indexOf("-"))); 337: 338: if (range.endsWith("-")) 339: theirlastport = 65535; 340: else if (range.indexOf("-") == -1) 341: theirlastport = Integer.parseInt(range); 342: else 343: theirlastport = 344: Integer.parseInt(range.substring(range.indexOf("-") + 1, 345: range.length())); 346: } 347: 348: // Now check them 349: if ((theirfirstport < ourfirstport) || (theirlastport > ourlastport)) 350: return false; 351: 352: // Finally we can check the hosts 353: String ourhost; 354: 355: // Finally we can check the hosts 356: String theirhost; 357: 358: // Get ours 359: if (hostport.indexOf(":") == -1) 360: ourhost = hostport; 361: else 362: ourhost = hostport.substring(0, hostport.indexOf(":")); 363: 364: // Get theirs 365: if (p.hostport.indexOf(":") == -1) 366: theirhost = p.hostport; 367: else 368: theirhost = p.hostport.substring(0, p.hostport.indexOf(":")); 369: 370: // Are they equal? 371: if (ourhost.equals(theirhost)) 372: return true; 373: 374: // Try the canonical names 375: String ourcanonical = null; 376: 377: // Try the canonical names 378: String theircanonical = null; 379: try 380: { 381: ourcanonical = InetAddress.getByName(ourhost).getHostName(); 382: theircanonical = InetAddress.getByName(theirhost).getHostName(); 383: } 384: catch (UnknownHostException e) 385: { 386: // Who didn't resolve? Just assume current address is canonical enough 387: // Is this ok to do? 388: if (ourcanonical == null) 389: ourcanonical = ourhost; 390: if (theircanonical == null) 391: theircanonical = theirhost; 392: } 393: 394: if (ourcanonical.equals(theircanonical)) 395: return true; 396: 397: // Well, last chance. Try for a wildcard 398: if (ourhost.indexOf("*.") != -1) 399: { 400: String wild_domain = ourhost.substring(ourhost.indexOf("*" + 1)); 401: if (theircanonical.endsWith(wild_domain)) 402: return true; 403: } 404: 405: // Didn't make it 406: return false; 407: } 408: }
GNU Classpath (0.20) |