This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

java.security.Policy and java.security.ProtectionDomain


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();
   }
 }



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]