This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
java.security.Policy and java.security.ProtectionDomain
- From: "Raif S. Naffah" <raif at fl dot net dot au>
- To: GCC libjava patches <java-patches at gcc dot gnu dot org>
- Date: Mon, 3 Mar 2003 05:50:02 +1100
- Subject: java.security.Policy and java.security.ProtectionDomain
- Reply-to: raif at fl dot net dot au
hello there,
this patch addresses JDK 1.4 compatibility.
cheers;
rsn
in ChangeLog (in libjava), add:
2003-03-03 Raif S. Naffah <raif at fl dot net dot au>
* java.security.Policy: formatting.
(pd2pc): new field.
(setPolicy()): ensure instance is loaded.
(setup(Policy)): new method.
(getCurrentPolicy()): new package-private method; contains code
previously in static initialiser.
(isLoaded()): new method.
(getPermissions(ProtectionDomain)): new method.
(implies(ProtectionDomain, Permission)): new method.
* java.security.ProtectionDomain:
(classloader, principals, staticBinding): new fields.
(<ctor>(CodeSource, PermissionCollection)): use new ctor.
(<ctor>(CodeSource, PermissionCollection, ClassLoader,
Principal[])): new ctor.
(getClassLoader(), getPrincipals(), implies(Permission)): new
methods.
(toString()): added representation of new fields.
cvs -z9 diff -u -wb -B Policy.java (in directory /data/workspace/cvs/gcc/libjava/java/security/)
Index: Policy.java
===================================================================
RCS file: /cvsroot/gcc/gcc/libjava/java/security/Policy.java,v
retrieving revision 1.3
diff -u -w -b -B -r1.3 Policy.java
--- Policy.java 24 May 2002 11:57:20 -0000 1.3
+++ Policy.java 2 Mar 2003 18:27:17 -0000
@@ -36,6 +36,10 @@
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
@@ -77,30 +81,14 @@
to the correct Policy implementation class.
@author Mark Benvenuto
-
- @since JDK 1.2
+ @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();
- }
+ private static Policy currentPolicy = null;
+
+ /** Map of ProtectionDomains to PermissionCollections for this instance. */
+ private Map pd2pc = null;
/**
Constructs a new Policy class.
@@ -117,8 +105,7 @@
if the caller has Permission to get the current Policy.
@return the current Policy
-
- @throws SecurityException if the security manager exists
+ @throws SecurityException if the security manager exists and
the caller does not have permission to
<code>getPolicy</code>.
*/
@@ -128,7 +115,7 @@
if (sm != null)
sm.checkPermission(new SecurityPermission("getPolicy"));
- return currentPolicy;
+ return getCurrentPolicy();
}
/**
@@ -149,9 +135,64 @@
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
+ }
+ }
+
+ // ensures/forces loading of the configured policy provider, while bypassing
+ // the SecurityManager checks for "getPolicy" security permission.
+ // needed by ProtectionDomain.
+ //
+ // 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 Policy getCurrentPolicy()
+ {
+ if (currentPolicy == null)
+ {
+ String pp = System.getProperty ("policy.provider");
+ if (pp != null)
+ try
+ {
+ currentPolicy = (Policy) Class.forName(pp).newInstance();
+ }
+ catch (Exception ignored)
+ {
+ }
+ if (currentPolicy == null)
+ currentPolicy = new gnu.java.security.provider.DefaultPolicy();
+ }
+ return currentPolicy;
+ }
+
+ // tests if currentPolicy is not null, thus allowing clients to not force
+ // loading of any policy provider. needed by ProtectionDomain.
+ static boolean isLoaded()
+ {
+ return currentPolicy != null;
+ }
/**
Evalutes the global policy and returns a set of Permissions
@@ -168,6 +207,79 @@
public abstract PermissionCollection getPermissions(CodeSource codesource);
/**
+ * Evaluates the global policy and returns a PermissionCollection object
+ * specifying the set of permissions allowed given the characteristics of the
+ * protection domain.
+ *
+ * @param domain the ProtectionDomain associated with the caller.
+ * @return the set of permissions allowed for the <i>domain</i> according to
+ * the policy. The returned set of permissions must be a new mutable instance
+ * and it must support heterogeneous Permission types.
+ * @since 1.4
+ * @see { at link ProtectionDomain}
+ * @see { at link 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
+ * ProtectionDomain and tests whether the permission is granted.
+ *
+ * @param domain the ProtectionDomain to test.
+ * @param permission the Permission object to be tested for implication.
+ * @return true if "permission" is a proper subset of a permission granted to
+ * this ProtectionDomain.
+ * @since 1.4
+ * @see { at link 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 and/or reloads the current Policy. The actual
behavior of this method depends on the implementation.
*/
cvs -z9 diff -u -wb -B ProtectionDomain.java (in directory /data/workspace/cvs/gcc/libjava/java/security/)
Index: ProtectionDomain.java
===================================================================
RCS file: /cvsroot/gcc/gcc/libjava/java/security/ProtectionDomain.java,v
retrieving revision 1.4
diff -u -w -b -B -r1.4 ProtectionDomain.java
--- ProtectionDomain.java 4 Oct 2002 20:15:07 -0000 1.4
+++ ProtectionDomain.java 2 Mar 2003 18:29:51 -0000
@@ -62,6 +62,12 @@
* This is the set of permissions granted to this domain
*/
private PermissionCollection perms;
+ /** The { at link ClassLoader} associated with this domain. */
+ private ClassLoader classloader;
+ /** The array of Principals associated with this domain.. */
+ private Principal[] principals;
+ /** Post 1.4 the policy may be refreshed! use false for pre 1.4. */
+ private boolean staticBinding;
/**
* This method initializes a new instance of <code>ProtectionDomain</code>
@@ -72,16 +78,61 @@
*
* @param code_source The <code>CodeSource</code> for this domain
* @param perms The permission set for this domain
- *
* @see java.security.PermissionCollection#setReadOnly()
*/
public ProtectionDomain(CodeSource code_source, PermissionCollection perms)
{
- this.code_source = code_source;
- this.perms = perms;
- if (perms != null)
+ this(code_source, perms, null, null, false);
+ }
+
+ /**
+ * <p>Creates a new ProtectionDomain qualified by the given CodeSource,
+ * Permissions, ClassLoader and array of Principals. If the permissions
+ * object is not null, then <code>setReadOnly()</code> will be called on the
+ * passed in Permissions object. The permissions granted to this domain are
+ * dynamic; they include both the static permissions passed to this
+ * constructor, and any permissions granted to this domain by the current
+ * Policy at the time a permission is checked.</p>
+ *
+ * <p>This constructor is typically used by { at link ClassLoader}s and { at link
+ * DomainCombiner}s which delegate to <code>Policy</code> to actively
+ * associate the permissions granted to this domain. This constructor affords
+ * the Policy provider the opportunity to augment the supplied
+ * PermissionCollection to reflect policy changes.</p>
+ *
+ * @param codesource the CodeSource associated with this domain.
+ * @param permissions the permissions granted to this domain.
+ * @param classloader the ClassLoader associated with this domain.
+ * @param principals the array of Principals associated with this domain.
+ * @since 1.4
+ * @see Policy#refresh()
+ * @see Policy#getPermissions(ProtectionDomain)
+ */
+ public ProtectionDomain(CodeSource codesource,
+ PermissionCollection permissions,
+ ClassLoader classloader, Principal[] principals)
+ {
+ this(codesource, permissions, classloader, principals, false);
+ }
+
+ private ProtectionDomain(CodeSource codesource,
+ PermissionCollection permissions,
+ ClassLoader classloader, Principal[] principals,
+ boolean staticBinding)
+ {
+ super();
+
+ code_source = codesource;
+ if (permissions != null)
+ {
+ perms = permissions;
perms.setReadOnly();
}
+ this.classloader = classloader;
+ this.principals =
+ (principals != null ? (Principal[]) principals.clone() : new Principal[0]);
+ this.staticBinding = staticBinding;
+ }
/**
* This method returns the <code>CodeSource</code> for this domain.
@@ -104,20 +155,59 @@
}
/**
- * This method tests whether or not the specified <code>Permission</code> is
- * implied by the set of permissions granted to this domain.
+ * Returns the ClassLoader of this domain.
*
- * @param perm The <code>Permission</code> to test.
+ * @return the ClassLoader of this domain which may be null.
+ * @since 1.4
+ */
+ public final ClassLoader getClassLoader()
+ {
+ return classloader;
+ }
+
+ /**
+ * Returns an array of principals for this domain.
*
- * @return <code>true</code> if the specified <code>Permission</code> is implied for this domain, <code>false</code> otherwise.
+ * @return a non-null array of principals for this domain. Changes to this
+ * array will have no impact on the ProtectionDomain.
+ * @since 1.4
*/
- public boolean implies(Permission perm)
+ public final Principal[] getPrincipals()
{
- PermissionCollection pc = getPermissions();
- if (pc == null)
- return (false);
+ return (Principal[]) principals.clone();
+ }
- return (pc.implies(perm));
+ /**
+ * <p>Check and see if this ProtectionDomain implies the permissions
+ * expressed in the Permission object.</p>
+ *
+ * <p>The set of permissions evaluated is a function of whether the
+ * ProtectionDomain was constructed with a static set of permissions or it
+ * was bound to a dynamically mapped set of permissions.</p>
+ *
+ * <p>If the ProtectionDomain was constructed to a { at link
+ * #ProtectionDomain(CodeSource, PermissionCollection) statically bound}
+ * PermissionCollection then the permission will only be checked against the
+ * PermissionCollection supplied at construction.</p>
+ *
+ * <p>However, if the ProtectionDomain was constructed with the constructor
+ * variant which supports { at link
+ * #ProtectionDomain(CodeSource, PermissionCollection, ClassLoader, Principal[]) dynamically binding}
+ * permissions, then the permission will be checked against the combination
+ * of the PermissionCollection supplied at construction and the current
+ * Policy binding.</p>
+ *
+ * @param perm the Permission object to check.
+ * @return <code>true</code> if "permission" is implicit to this
+ * ProtectionDomain.
+ */
+ public boolean implies(Permission perm)
+ {
+ if (staticBinding)
+ return (perms == null ? false : perms.implies(perm));
+ // else dynamically bound. do we have it?
+ // NOTE: this will force loading of Policy.currentPolicy
+ return Policy.getCurrentPolicy().implies(this, perm);
}
/**
@@ -130,15 +220,49 @@
public String toString()
{
String linesep = System.getProperty("line.separator");
- StringBuffer sb = new StringBuffer("");
- sb.append("ProtectionDomain (" + linesep);
+ StringBuffer sb = new StringBuffer("ProtectionDomain (").append(linesep);
+
if (code_source == null)
- sb.append("CodeSource:null" + linesep);
+ sb.append("CodeSource:null");
+ else
+ sb.append(code_source);
+
+ sb.append(linesep);
+ if (classloader == null)
+ sb.append("ClassLoader:null");
+ else
+ sb.append(classloader);
+
+ sb.append(linesep);
+ sb.append("Principals:");
+ if (principals != null && principals.length > 0)
+ {
+ sb.append("[");
+ Principal pal;
+ for (int i = 0; i < principals.length; i++)
+ {
+ pal = principals[i];
+ sb.append("'").append(pal.getName())
+ .append("' of type ").append(pal.getClass().getName());
+ if (i < principals.length-1)
+ sb.append(", ");
+ }
+ sb.append("]");
+ }
+ else
+ sb.append("none");
+
+ sb.append(linesep);
+ if (!staticBinding) // include all but dont force loading Policy.currentPolicy
+ {
+ if (Policy.isLoaded())
+ sb.append(Policy.getCurrentPolicy().getPermissions(this));
+ else // fallback on this one's permissions
+ sb.append(perms);
+ }
else
- sb.append(code_source + linesep);
sb.append(perms);
- sb.append(linesep + ")" + linesep);
- return sb.toString();
+ return sb.append(linesep).append(")").append(linesep).toString();
}
}