SocketPermission.java 12 KB

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