aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/security/Policy.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/security/Policy.java')
-rw-r--r--libjava/java/security/Policy.java322
1 files changed, 227 insertions, 95 deletions
diff --git a/libjava/java/security/Policy.java b/libjava/java/security/Policy.java
index 126c084..47171cf 100644
--- a/libjava/java/security/Policy.java
+++ b/libjava/java/security/Policy.java
@@ -1,5 +1,5 @@
/* Policy.java --- Policy Manager Class
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2003, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,90 +37,87 @@ exception statement from your version. */
package java.security;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
/**
- Policy is an abstract class for managing the system security
- policy for the Java application environment. It specifies
- which permissions are available for code from various
- sources. The security policy is represented through a
- subclass of Policy.
-
- Only one Policy is in effect at any time. ProtectionDomain
- initializes itself with information from this class on the
- set of permssions to grant.
-
- The location for the actual Policy could be anywhere in any
- form because it depends on the Policy implementation. The
- default system is in a flat ASCII file or it could be in a
- database.
-
- The current installed Policy can be accessed with getPolicy
- and changed with setPolicy if the code has the correct
- permissions.
-
- The refresh method causes the Policy class to refresh/reload
- its configuration. The method used to refresh depends on the
- Policy implementation.
-
- When a protection domain initializes its permissions it uses
- code like:
- <code>
- policy = Policy.getPolicy();
- permissionCollection perms = policy.getPermissions(MyCodeSource)
- </code>
- The protection domain passes the Policy handler a CodeSource
- object which contains the codebase URL and public key. The
- Policy implementation then returns the proper set of
- permissions for the CodeSource.
-
- The default Policy implementation can be changed by setting
- the "policy.provider" security provider in java.security
- to the correct Policy implementation class.
-
- @author Mark Benvenuto
-
- @since JDK 1.2
+ * <p>This is an abstract class for representing the system security policy for
+ * a Java application environment (specifying which permissions are available
+ * for code from various sources). That is, the security policy is represented
+ * by a <code>Policy</code> subclass providing an implementation of the abstract
+ * methods in this <code>Policy</code> class.</p>
+ *
+ * <p>There is only one <code>Policy</code> object in effect at any given time.
+ * </p>
+ *
+ * <p>The source location for the policy information utilized by the
+ * <code>Policy</code> object is up to the <code>Policy</code> implementation.
+ * The policy configuration may be stored, for example, as a flat ASCII file, as
+ * a serialized binary file of the <code>Policy</code> class, or as a database.
+ * </p>
+ *
+ * <p>The currently-installed <code>Policy</code> object can be obtained by
+ * calling the <code>getPolicy()</code> method, and it can be changed by a call
+ * to the <code>setPolicy()</code> method (by code with permission to reset the
+ * <code>Policy</code>).</p>
+ *
+ * <p>The <code>refresh()</code> method causes the policy object to refresh /
+ * reload its current configuration.</p>
+ *
+ * <p>This is implementation-dependent. For example, if the policy object stores
+ * its policy in configuration files, calling <code>refresh()</code> will cause
+ * it to re-read the configuration policy files. The refreshed policy may not
+ * have an effect on classes in a particular {@link ProtectionDomain}. This is
+ * dependent on the <code>Policy</code> provider's implementation of the
+ * <code>implies()</code> method and the {@link PermissionCollection} caching
+ * strategy.</p>
+ *
+ * <p>The default <code>Policy</code> implementation can be changed by setting
+ * the value of the <code>"policy.provider"</code> security property (in the
+ * Java security properties file) to the fully qualified name of the desired
+ * <code>Policy</code> implementation class. The Java security properties file
+ * is located in the file named <code>&lt;JAVA_HOME>/lib/security/java.security
+ * </code>, where <code>&lt;JAVA_HOME></code> refers to the directory where the
+ * SDK was installed.</p>
+ *
+ * <p><b>IMPLEMENTATION NOTE:</b> This implementation attempts to read the
+ * System property named <code>policy.provider</code> to find the concrete
+ * implementation of the <code>Policy</code>. If/when this fails, it falls back
+ * to a default implementation, which <b>allows everything</b>.
+ *
+ * @author Mark Benvenuto
+ * @see CodeSource
+ * @see PermissionCollection
+ * @see SecureClassLoader
+ * @since 1.2
*/
public abstract class Policy
{
- // FIXME: The class name of the Policy provider should really be sourced
- // from the "java.security" configuration file. For now, just hard-code
- // a stub implementation.
static private Policy currentPolicy = null;
- static
- {
- String pp = System.getProperty ("policy.provider");
- if (pp != null)
- try
- {
- currentPolicy = (Policy)Class.forName(pp).newInstance();
- }
- catch (Exception _)
- {
- currentPolicy = null;
- }
- if (currentPolicy == null)
- currentPolicy = new gnu.java.security.provider.DefaultPolicy();
- }
-
- /**
- Constructs a new Policy class.
- */
+
+ /** Map of ProtectionDomains to PermissionCollections for this instance. */
+ private Map pd2pc = null;
+
+ /** Constructs a new <code>Policy</code> object. */
public Policy()
{
}
/**
- Gets the currently installed Policy handler. The value should
- not be cached as it can be changed by setPolicy. This
- function first calls <code>SecurityManager.checkPermission</code>
- with <code>SecurityPermission("getPolicy")</code> to check
- if the caller has Permission to get the current Policy.
-
- @return the current Policy
-
- @throws SecurityException if the security manager exists
- the caller does not have permission to
- <code>getPolicy</code>.
+ * Returns the installed <code>Policy</code> object. This value should not be
+ * cached, as it may be changed by a call to <code>setPolicy()</code>. This
+ * method first calls {@link SecurityManager#checkPermission(Permission)} with
+ * a <code>SecurityPermission("getPolicy")</code> permission to ensure it's ok
+ * to get the <code>Policy</code> object.
+ *
+ * @return the installed <code>Policy</code>.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkPermission()</code> method doesn't allow getting the
+ * <code>Policy</code> object.
+ * @see SecurityManager#checkPermission(Permission)
+ * @see #setPolicy(Policy)
*/
public static Policy getPolicy()
{
@@ -128,20 +125,21 @@ public abstract class Policy
if (sm != null)
sm.checkPermission(new SecurityPermission("getPolicy"));
- return currentPolicy;
+ return getCurrentPolicy();
}
/**
- Sets the currently installed Policy handler. This
- function first calls <code>SecurityManager.checkPermission</code>
- with <code>SecurityPermission("setPolicy")</code> to check
- if the caller has Permission to get the current Policy.
-
- @param policy the new Policy to use
-
- @throws SecurityException if the security manager exists
- the caller does not have permission to
- <code>getPolicy</code>.
+ * Sets the system-wide <code>Policy</code> object. This method first calls
+ * {@link SecurityManager#checkPermission(Permission)} with a
+ * <code>SecurityPermission("setPolicy")</code> permission to ensure it's ok
+ * to set the <code>Policy</code>.
+ *
+ * @param policy the new system <code>Policy</code> object.
+ * @throws SecurityException if a security manager exists and its
+ * <code>checkPermission()</code> method doesn't allow setting the
+ * <code>Policy</code>.
+ * @see SecurityManager#checkPermission(Permission)
+ * @see #getPolicy()
*/
public static void setPolicy(Policy policy)
{
@@ -149,27 +147,161 @@ public abstract class Policy
if (sm != null)
sm.checkPermission(new SecurityPermission("setPolicy"));
+ setup(policy);
currentPolicy = policy;
}
+ private static void setup(final Policy policy)
+ {
+ if (policy.pd2pc == null)
+ policy.pd2pc = Collections.synchronizedMap(new LinkedHashMap());
+
+ ProtectionDomain pd = policy.getClass().getProtectionDomain();
+ if (pd.getCodeSource() != null)
+ {
+ PermissionCollection pc = null;
+ if (currentPolicy != null)
+ pc = currentPolicy.getPermissions(pd);
+
+ if (pc == null) // assume it has all
+ {
+ pc = new Permissions();
+ pc.add(new AllPermission());
+ }
+
+ policy.pd2pc.put(pd, pc); // add the mapping pd -> pc
+ }
+ }
/**
- Evalutes the global policy and returns a set of Permissions
- allowed for the specified CodeSource.
+ * Ensures/forces loading of the configured policy provider, while bypassing
+ * the {@link SecurityManager} checks for <code>"getPolicy"</code> security
+ * permission. Needed by {@link ProtectionDomain}.
+ */
+ static Policy getCurrentPolicy()
+ {
+ // FIXME: The class name of the Policy provider should really be sourced
+ // from the "java.security" configuration file. For now, just hard-code
+ // a stub implementation.
+ if (currentPolicy == null)
+ {
+ String pp = System.getProperty ("policy.provider");
+ if (pp != null)
+ try
+ {
+ currentPolicy = (Policy) Class.forName(pp).newInstance();
+ }
+ catch (Exception ignored) {}
- @param codesource The CodeSource to get Permission for
+ if (currentPolicy == null)
+ currentPolicy = new gnu.java.security.provider.DefaultPolicy();
+ }
+ return currentPolicy;
+ }
- @return a set of permissions for codesource specified by
- the current policy
+ /**
+ * Tests if <code>currentPolicy</code> is not <code>null</code>,
+ * thus allowing clients to not force loading of any policy
+ * provider; needed by {@link ProtectionDomain}.
+ */
+ static boolean isLoaded()
+ {
+ return currentPolicy != null;
+ }
- @throws SecurityException if the current thread does not
- have permission to call <code>getPermissions</code>
+ /**
+ * Evaluates the global policy and returns a {@link PermissionCollection}
+ * object specifying the set of permissions allowed for code from the
+ * specified code source.
+ *
+ * @param codesource the {@link CodeSource} associated with the caller. This
+ * encapsulates the original location of the code (where the code came from)
+ * and the public key(s) of its signer.
+ * @return the set of permissions allowed for code from codesource according
+ * to the policy. The returned set of permissions must be a new mutable
+ * instance and it must support heterogeneous {@link Permission} types.
*/
public abstract PermissionCollection getPermissions(CodeSource codesource);
/**
- Refreshes and/or reloads the current Policy. The actual
- behavior of this method depends on the implementation.
+ * Evaluates the global policy and returns a {@link PermissionCollection}
+ * object specifying the set of permissions allowed given the characteristics
+ * of the protection domain.
+ *
+ * @param domain the {@link ProtectionDomain} associated with the caller.
+ * @return the set of permissions allowed for the domain according to the
+ * policy. The returned set of permissions must be a new mutable instance and
+ * it must support heterogeneous {@link Permission} types.
+ * @since 1.4
+ * @see ProtectionDomain
+ * @see SecureClassLoader
+ */
+ public PermissionCollection getPermissions(ProtectionDomain domain)
+ {
+ if (domain == null)
+ return new Permissions();
+
+ if (pd2pc == null)
+ setup(this);
+
+ PermissionCollection result = (PermissionCollection) pd2pc.get(domain);
+ if (result != null)
+ {
+ Permissions realResult = new Permissions();
+ for (Enumeration e = result.elements(); e.hasMoreElements(); )
+ realResult.add((Permission) e.nextElement());
+
+ return realResult;
+ }
+
+ result = getPermissions(domain.getCodeSource());
+ if (result == null)
+ result = new Permissions();
+
+ PermissionCollection pc = domain.getPermissions();
+ if (pc != null)
+ for (Enumeration e = pc.elements(); e.hasMoreElements(); )
+ result.add((Permission) e.nextElement());
+
+ return result;
+ }
+
+ /**
+ * Evaluates the global policy for the permissions granted to the {@link
+ * ProtectionDomain} and tests whether the <code>permission</code> is granted.
+ *
+ * @param domain the {@link ProtectionDomain} to test.
+ * @param permission the {@link Permission} object to be tested for
+ * implication.
+ * @return <code>true</code> if <code>permission</code> is a proper subset of
+ * a permission granted to this {@link ProtectionDomain}.
+ * @since 1.4
+ * @see ProtectionDomain
+ */
+ public boolean implies(ProtectionDomain domain, Permission permission)
+ {
+ if (pd2pc == null)
+ setup(this);
+
+ PermissionCollection pc = (PermissionCollection) pd2pc.get(domain);
+ if (pc != null)
+ return pc.implies(permission);
+
+ boolean result = false;
+ pc = getPermissions(domain);
+ if (pc != null)
+ {
+ result = pc.implies(permission);
+ pd2pc.put(domain, pc);
+ }
+
+ return result;
+ }
+
+ /**
+ * Refreshes/reloads the policy configuration. The behavior of this method
+ * depends on the implementation. For example, calling refresh on a file-based
+ * policy will cause the file to be re-read.
*/
public abstract void refresh();
}