Policy.java 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /* Policy.java --- Policy Manager Class
  2. Copyright (C) 1999, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 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.security;
  32. import java.util.Collections;
  33. import java.util.Enumeration;
  34. import java.util.LinkedHashMap;
  35. import java.util.Map;
  36. /**
  37. * <code>Policy</code> is an abstract class for managing the system security
  38. * policy for the Java application environment. It specifies which permissions
  39. * are available for code from various sources. The security policy is
  40. * represented through a subclass of <code>Policy</code>.
  41. *
  42. * <p>Only one <code>Policy</code> is in effect at any time. A
  43. * {@link ProtectionDomain} initializes itself with information from this class
  44. * on the set of permssions to grant.</p>
  45. *
  46. * <p>The location for the actual <code>Policy</code> could be anywhere in any
  47. * form because it depends on the Policy implementation. The default system is
  48. * in a flat ASCII file or it could be in a database.</p>
  49. *
  50. * <p>The current installed <code>Policy</code> can be accessed with
  51. * {@link #getPolicy()} and changed with {@link #setPolicy(Policy)} if the code
  52. * has the correct permissions.</p>
  53. *
  54. * <p>The {@link #refresh()} method causes the <code>Policy</code> instance to
  55. * refresh/reload its configuration. The method used to refresh depends on the
  56. * <code>Policy</code> implementation.</p>
  57. *
  58. * <p>When a protection domain initializes its permissions, it uses code like
  59. * the following:</p>
  60. *
  61. * <code>
  62. * policy = Policy.getPolicy();
  63. * PermissionCollection perms = policy.getPermissions(myCodeSource);
  64. * </code>
  65. *
  66. * <p>The protection domain passes the <code>Policy</code> handler a
  67. * {@link CodeSource} instance which contains the codebase URL and a public key.
  68. * The <code>Policy</code> implementation then returns the proper set of
  69. * permissions for that {@link CodeSource}.</p>
  70. *
  71. * <p>The default <code>Policy</code> implementation can be changed by setting
  72. * the "policy.provider" security provider in the "java.security" file to the
  73. * correct <code>Policy</code> implementation class.</p>
  74. *
  75. * @author Mark Benvenuto
  76. * @see CodeSource
  77. * @see PermissionCollection
  78. * @see SecureClassLoader
  79. * @since 1.2
  80. */
  81. public abstract class Policy
  82. {
  83. private static Policy currentPolicy;
  84. /** Map of ProtectionDomains to PermissionCollections for this instance. */
  85. private Map pd2pc = null;
  86. /** Constructs a new <code>Policy</code> object. */
  87. public Policy()
  88. {
  89. }
  90. /**
  91. * Returns the currently installed <code>Policy</code> handler. The value
  92. * should not be cached as it can be changed any time by
  93. * {@link #setPolicy(Policy)}.
  94. *
  95. * @return the current <code>Policy</code>.
  96. * @throws SecurityException
  97. * if a {@link SecurityManager} is installed which disallows this
  98. * operation.
  99. */
  100. public static Policy getPolicy()
  101. {
  102. SecurityManager sm = System.getSecurityManager();
  103. if (sm != null)
  104. sm.checkPermission(new SecurityPermission("getPolicy"));
  105. return getCurrentPolicy();
  106. }
  107. /**
  108. * Sets the <code>Policy</code> handler to a new value.
  109. *
  110. * @param policy
  111. * the new <code>Policy</code> to use.
  112. * @throws SecurityException
  113. * if a {@link SecurityManager} is installed which disallows this
  114. * operation.
  115. */
  116. public static void setPolicy(Policy policy)
  117. {
  118. SecurityManager sm = System.getSecurityManager();
  119. if (sm != null)
  120. sm.checkPermission(new SecurityPermission("setPolicy"));
  121. setup(policy);
  122. currentPolicy = policy;
  123. }
  124. private static void setup(final Policy policy)
  125. {
  126. if (policy.pd2pc == null)
  127. policy.pd2pc = Collections.synchronizedMap(new LinkedHashMap());
  128. ProtectionDomain pd = policy.getClass().getProtectionDomain();
  129. if (pd.getCodeSource() != null)
  130. {
  131. PermissionCollection pc = null;
  132. if (currentPolicy != null)
  133. pc = currentPolicy.getPermissions(pd);
  134. if (pc == null) // assume it has all
  135. {
  136. pc = new Permissions();
  137. pc.add(new AllPermission());
  138. }
  139. policy.pd2pc.put(pd, pc); // add the mapping pd -> pc
  140. }
  141. }
  142. /**
  143. * Ensures/forces loading of the configured policy provider, while bypassing
  144. * the {@link SecurityManager} checks for <code>"getPolicy"</code> security
  145. * permission. Needed by {@link ProtectionDomain}.
  146. */
  147. static Policy getCurrentPolicy()
  148. {
  149. // FIXME: The class name of the Policy provider should really be sourced
  150. // from the "java.security" configuration file. For now, just hard-code
  151. // a stub implementation.
  152. if (currentPolicy == null)
  153. {
  154. String pp = System.getProperty ("policy.provider");
  155. if (pp != null)
  156. try
  157. {
  158. currentPolicy = (Policy) Class.forName(pp).newInstance();
  159. }
  160. catch (Exception e)
  161. {
  162. // Ignored.
  163. }
  164. if (currentPolicy == null)
  165. currentPolicy = new gnu.java.security.provider.DefaultPolicy();
  166. }
  167. return currentPolicy;
  168. }
  169. /**
  170. * Tests if <code>currentPolicy</code> is not <code>null</code>,
  171. * thus allowing clients to not force loading of any policy
  172. * provider; needed by {@link ProtectionDomain}.
  173. */
  174. static boolean isLoaded()
  175. {
  176. return currentPolicy != null;
  177. }
  178. /**
  179. * Returns the set of Permissions allowed for a given {@link CodeSource}.
  180. *
  181. * @param codesource
  182. * the {@link CodeSource} for which, the caller needs to find the
  183. * set of granted permissions.
  184. * @return a set of permissions for {@link CodeSource} specified by the
  185. * current <code>Policy</code>.
  186. * @throws SecurityException
  187. * if a {@link SecurityManager} is installed which disallows this
  188. * operation.
  189. */
  190. public abstract PermissionCollection getPermissions(CodeSource codesource);
  191. /**
  192. * Returns the set of Permissions allowed for a given {@link ProtectionDomain}.
  193. *
  194. * @param domain
  195. * the {@link ProtectionDomain} for which, the caller needs to find
  196. * the set of granted permissions.
  197. * @return a set of permissions for {@link ProtectionDomain} specified by the
  198. * current <code>Policy.</code>.
  199. * @since 1.4
  200. * @see ProtectionDomain
  201. * @see SecureClassLoader
  202. */
  203. public PermissionCollection getPermissions(ProtectionDomain domain)
  204. {
  205. if (domain == null)
  206. return new Permissions();
  207. if (pd2pc == null)
  208. setup(this);
  209. PermissionCollection result = (PermissionCollection) pd2pc.get(domain);
  210. if (result != null)
  211. {
  212. Permissions realResult = new Permissions();
  213. for (Enumeration e = result.elements(); e.hasMoreElements(); )
  214. realResult.add((Permission) e.nextElement());
  215. return realResult;
  216. }
  217. result = getPermissions(domain.getCodeSource());
  218. if (result == null)
  219. result = new Permissions();
  220. PermissionCollection pc = domain.getPermissions();
  221. if (pc != null)
  222. for (Enumeration e = pc.elements(); e.hasMoreElements(); )
  223. result.add((Permission) e.nextElement());
  224. return result;
  225. }
  226. /**
  227. * Checks if the designated {@link Permission} is granted to a designated
  228. * {@link ProtectionDomain}.
  229. *
  230. * @param domain
  231. * the {@link ProtectionDomain} to test.
  232. * @param permission
  233. * the {@link Permission} to check.
  234. * @return <code>true</code> if <code>permission</code> is implied by a
  235. * permission granted to this {@link ProtectionDomain}. Returns
  236. * <code>false</code> otherwise.
  237. * @since 1.4
  238. * @see ProtectionDomain
  239. */
  240. public boolean implies(ProtectionDomain domain, Permission permission)
  241. {
  242. if (pd2pc == null)
  243. setup(this);
  244. PermissionCollection pc = (PermissionCollection) pd2pc.get(domain);
  245. if (pc != null)
  246. return pc.implies(permission);
  247. boolean result = false;
  248. pc = getPermissions(domain);
  249. if (pc != null)
  250. {
  251. result = pc.implies(permission);
  252. pd2pc.put(domain, pc);
  253. }
  254. return result;
  255. }
  256. /**
  257. * Causes this <code>Policy</code> instance to refresh / reload its
  258. * configuration. The method used to refresh depends on the concrete
  259. * implementation.
  260. */
  261. public abstract void refresh();
  262. }