GNU Classpath (0.20) | |
Frames | No Frames |
1: /* Policy.java --- Policy Manager Class 2: Copyright (C) 1999, 2003, 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.security; 39: 40: import java.util.Collections; 41: import java.util.Enumeration; 42: import java.util.LinkedHashMap; 43: import java.util.Map; 44: 45: /** 46: * <p>This is an abstract class for representing the system security policy for 47: * a Java application environment (specifying which permissions are available 48: * for code from various sources). That is, the security policy is represented 49: * by a <code>Policy</code> subclass providing an implementation of the abstract 50: * methods in this <code>Policy</code> class.</p> 51: * 52: * <p>There is only one <code>Policy</code> object in effect at any given time. 53: * </p> 54: * 55: * <p>The source location for the policy information utilized by the 56: * <code>Policy</code> object is up to the <code>Policy</code> implementation. 57: * The policy configuration may be stored, for example, as a flat ASCII file, as 58: * a serialized binary file of the <code>Policy</code> class, or as a database. 59: * </p> 60: * 61: * <p>The currently-installed <code>Policy</code> object can be obtained by 62: * calling the <code>getPolicy()</code> method, and it can be changed by a call 63: * to the <code>setPolicy()</code> method (by code with permission to reset the 64: * <code>Policy</code>).</p> 65: * 66: * <p>The <code>refresh()</code> method causes the policy object to refresh / 67: * reload its current configuration.</p> 68: * 69: * <p>This is implementation-dependent. For example, if the policy object stores 70: * its policy in configuration files, calling <code>refresh()</code> will cause 71: * it to re-read the configuration policy files. The refreshed policy may not 72: * have an effect on classes in a particular {@link ProtectionDomain}. This is 73: * dependent on the <code>Policy</code> provider's implementation of the 74: * <code>implies()</code> method and the {@link PermissionCollection} caching 75: * strategy.</p> 76: * 77: * <p>The default <code>Policy</code> implementation can be changed by setting 78: * the value of the <code>"policy.provider"</code> security property (in the 79: * Java security properties file) to the fully qualified name of the desired 80: * <code>Policy</code> implementation class. The Java security properties file 81: * is located in the file named <code><JAVA_HOME>/lib/security/java.security 82: * </code>, where <code><JAVA_HOME></code> refers to the directory where the 83: * SDK was installed.</p> 84: * 85: * <p><b>IMPLEMENTATION NOTE:</b> This implementation attempts to read the 86: * System property named <code>policy.provider</code> to find the concrete 87: * implementation of the <code>Policy</code>. If/when this fails, it falls back 88: * to a default implementation, which <b>allows everything</b>. 89: * 90: * @author Mark Benvenuto 91: * @see CodeSource 92: * @see PermissionCollection 93: * @see SecureClassLoader 94: * @since 1.2 95: */ 96: public abstract class Policy 97: { 98: private static Policy currentPolicy; 99: 100: /** Map of ProtectionDomains to PermissionCollections for this instance. */ 101: private Map pd2pc = null; 102: 103: /** Constructs a new <code>Policy</code> object. */ 104: public Policy() 105: { 106: } 107: 108: /** 109: * Returns the installed <code>Policy</code> object. This value should not be 110: * cached, as it may be changed by a call to <code>setPolicy()</code>. This 111: * method first calls {@link SecurityManager#checkPermission(Permission)} with 112: * a <code>SecurityPermission("getPolicy")</code> permission to ensure it's ok 113: * to get the <code>Policy</code> object. 114: * 115: * @return the installed <code>Policy</code>. 116: * @throws SecurityException if a security manager exists and its 117: * <code>checkPermission()</code> method doesn't allow getting the 118: * <code>Policy</code> object. 119: * @see SecurityManager#checkPermission(Permission) 120: * @see #setPolicy(Policy) 121: */ 122: public static Policy getPolicy() 123: { 124: SecurityManager sm = System.getSecurityManager(); 125: if (sm != null) 126: sm.checkPermission(new SecurityPermission("getPolicy")); 127: 128: return getCurrentPolicy(); 129: } 130: 131: /** 132: * Sets the system-wide <code>Policy</code> object. This method first calls 133: * {@link SecurityManager#checkPermission(Permission)} with a 134: * <code>SecurityPermission("setPolicy")</code> permission to ensure it's ok 135: * to set the <code>Policy</code>. 136: * 137: * @param policy the new system <code>Policy</code> object. 138: * @throws SecurityException if a security manager exists and its 139: * <code>checkPermission()</code> method doesn't allow setting the 140: * <code>Policy</code>. 141: * @see SecurityManager#checkPermission(Permission) 142: * @see #getPolicy() 143: */ 144: public static void setPolicy(Policy policy) 145: { 146: SecurityManager sm = System.getSecurityManager(); 147: if (sm != null) 148: sm.checkPermission(new SecurityPermission("setPolicy")); 149: 150: setup(policy); 151: currentPolicy = policy; 152: } 153: 154: private static void setup(final Policy policy) 155: { 156: if (policy.pd2pc == null) 157: policy.pd2pc = Collections.synchronizedMap(new LinkedHashMap()); 158: 159: ProtectionDomain pd = policy.getClass().getProtectionDomain(); 160: if (pd.getCodeSource() != null) 161: { 162: PermissionCollection pc = null; 163: if (currentPolicy != null) 164: pc = currentPolicy.getPermissions(pd); 165: 166: if (pc == null) // assume it has all 167: { 168: pc = new Permissions(); 169: pc.add(new AllPermission()); 170: } 171: 172: policy.pd2pc.put(pd, pc); // add the mapping pd -> pc 173: } 174: } 175: 176: /** 177: * Ensures/forces loading of the configured policy provider, while bypassing 178: * the {@link SecurityManager} checks for <code>"getPolicy"</code> security 179: * permission. Needed by {@link ProtectionDomain}. 180: */ 181: static Policy getCurrentPolicy() 182: { 183: // FIXME: The class name of the Policy provider should really be sourced 184: // from the "java.security" configuration file. For now, just hard-code 185: // a stub implementation. 186: if (currentPolicy == null) 187: { 188: String pp = System.getProperty ("policy.provider"); 189: if (pp != null) 190: try 191: { 192: currentPolicy = (Policy) Class.forName(pp).newInstance(); 193: } 194: catch (Exception e) 195: { 196: // Ignored. 197: } 198: 199: if (currentPolicy == null) 200: currentPolicy = new gnu.java.security.provider.DefaultPolicy(); 201: } 202: return currentPolicy; 203: } 204: 205: /** 206: * Tests if <code>currentPolicy</code> is not <code>null</code>, 207: * thus allowing clients to not force loading of any policy 208: * provider; needed by {@link ProtectionDomain}. 209: */ 210: static boolean isLoaded() 211: { 212: return currentPolicy != null; 213: } 214: 215: /** 216: * Evaluates the global policy and returns a {@link PermissionCollection} 217: * object specifying the set of permissions allowed for code from the 218: * specified code source. 219: * 220: * @param codesource the {@link CodeSource} associated with the caller. This 221: * encapsulates the original location of the code (where the code came from) 222: * and the public key(s) of its signer. 223: * @return the set of permissions allowed for code from codesource according 224: * to the policy. The returned set of permissions must be a new mutable 225: * instance and it must support heterogeneous {@link Permission} types. 226: */ 227: public abstract PermissionCollection getPermissions(CodeSource codesource); 228: 229: /** 230: * Evaluates the global policy and returns a {@link PermissionCollection} 231: * object specifying the set of permissions allowed given the characteristics 232: * of the protection domain. 233: * 234: * @param domain the {@link ProtectionDomain} associated with the caller. 235: * @return the set of permissions allowed for the domain according to the 236: * policy. The returned set of permissions must be a new mutable instance and 237: * it must support heterogeneous {@link Permission} types. 238: * @since 1.4 239: * @see ProtectionDomain 240: * @see SecureClassLoader 241: */ 242: public PermissionCollection getPermissions(ProtectionDomain domain) 243: { 244: if (domain == null) 245: return new Permissions(); 246: 247: if (pd2pc == null) 248: setup(this); 249: 250: PermissionCollection result = (PermissionCollection) pd2pc.get(domain); 251: if (result != null) 252: { 253: Permissions realResult = new Permissions(); 254: for (Enumeration e = result.elements(); e.hasMoreElements(); ) 255: realResult.add((Permission) e.nextElement()); 256: 257: return realResult; 258: } 259: 260: result = getPermissions(domain.getCodeSource()); 261: if (result == null) 262: result = new Permissions(); 263: 264: PermissionCollection pc = domain.getPermissions(); 265: if (pc != null) 266: for (Enumeration e = pc.elements(); e.hasMoreElements(); ) 267: result.add((Permission) e.nextElement()); 268: 269: return result; 270: } 271: 272: /** 273: * Evaluates the global policy for the permissions granted to the {@link 274: * ProtectionDomain} and tests whether the <code>permission</code> is granted. 275: * 276: * @param domain the {@link ProtectionDomain} to test. 277: * @param permission the {@link Permission} object to be tested for 278: * implication. 279: * @return <code>true</code> if <code>permission</code> is a proper subset of 280: * a permission granted to this {@link ProtectionDomain}. 281: * @since 1.4 282: * @see ProtectionDomain 283: */ 284: public boolean implies(ProtectionDomain domain, Permission permission) 285: { 286: if (pd2pc == null) 287: setup(this); 288: 289: PermissionCollection pc = (PermissionCollection) pd2pc.get(domain); 290: if (pc != null) 291: return pc.implies(permission); 292: 293: boolean result = false; 294: pc = getPermissions(domain); 295: if (pc != null) 296: { 297: result = pc.implies(permission); 298: pd2pc.put(domain, pc); 299: } 300: 301: return result; 302: } 303: 304: /** 305: * Refreshes/reloads the policy configuration. The behavior of this method 306: * depends on the implementation. For example, calling refresh on a file-based 307: * policy will cause the file to be re-read. 308: */ 309: public abstract void refresh(); 310: }
GNU Classpath (0.20) |