Source for java.security.Policy

   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>&lt;JAVA_HOME>/lib/security/java.security
  82:  * </code>, where <code>&lt;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: }