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:  * <code>Policy</code> is an abstract class for managing the system security
  47:  * policy for the Java application environment. It specifies which permissions
  48:  * are available for code from various sources. The security policy is
  49:  * represented through a subclass of <code>Policy</code>.
  50:  *
  51:  * <p>Only one <code>Policy</code> is in effect at any time. A
  52:  * {@link ProtectionDomain} initializes itself with information from this class
  53:  * on the set of permssions to grant.</p>
  54:  *
  55:  * <p>The location for the actual <code>Policy</code> could be anywhere in any
  56:  * form because it depends on the Policy implementation. The default system is
  57:  * in a flat ASCII file or it could be in a database.</p>
  58:  *
  59:  * <p>The current installed <code>Policy</code> can be accessed with
  60:  * {@link #getPolicy()} and changed with {@link #setPolicy(Policy)} if the code
  61:  * has the correct permissions.</p>
  62:  *
  63:  * <p>The {@link #refresh()} method causes the <code>Policy</code> instance to
  64:  * refresh/reload its configuration. The method used to refresh depends on the
  65:  * <code>Policy</code> implementation.</p>
  66:  *
  67:  * <p>When a protection domain initializes its permissions, it uses code like
  68:  * the following:</p>
  69:  *
  70:  * <code>
  71:  * policy = Policy.getPolicy();
  72:  * PermissionCollection perms = policy.getPermissions(myCodeSource);
  73:  * </code>
  74:  *
  75:  * <p>The protection domain passes the <code>Policy</code> handler a
  76:  * {@link CodeSource} instance which contains the codebase URL and a public key.
  77:  * The <code>Policy</code> implementation then returns the proper set of
  78:  * permissions for that {@link CodeSource}.</p>
  79:  *
  80:  * <p>The default <code>Policy</code> implementation can be changed by setting
  81:  * the "policy.provider" security provider in the "java.security" file to the
  82:  * correct <code>Policy</code> implementation class.</p>
  83:  *
  84:  * @author Mark Benvenuto
  85:  * @see CodeSource
  86:  * @see PermissionCollection
  87:  * @see SecureClassLoader
  88:  * @since 1.2
  89:  */
  90: public abstract class Policy
  91: {
  92:   private static Policy currentPolicy;
  93: 
  94:   /** Map of ProtectionDomains to PermissionCollections for this instance. */
  95:   private Map pd2pc = null;
  96: 
  97:   /** Constructs a new <code>Policy</code> object. */
  98:   public Policy()
  99:   {
 100:   }
 101: 
 102:   /**
 103:    * Returns the currently installed <code>Policy</code> handler. The value
 104:    * should not be cached as it can be changed any time by
 105:    * {@link #setPolicy(Policy)}.
 106:    *
 107:    * @return the current <code>Policy</code>.
 108:    * @throws SecurityException
 109:    *           if a {@link SecurityManager} is installed which disallows this
 110:    *           operation.
 111:    */
 112:   public static Policy getPolicy()
 113:   {
 114:     SecurityManager sm = System.getSecurityManager();
 115:     if (sm != null)
 116:       sm.checkPermission(new SecurityPermission("getPolicy"));
 117: 
 118:     return getCurrentPolicy();
 119:   }
 120: 
 121:   /**
 122:    * Sets the <code>Policy</code> handler to a new value.
 123:    *
 124:    * @param policy
 125:    *          the new <code>Policy</code> to use.
 126:    * @throws SecurityException
 127:    *           if a {@link SecurityManager} is installed which disallows this
 128:    *           operation.
 129:    */
 130:   public static void setPolicy(Policy policy)
 131:   {
 132:     SecurityManager sm = System.getSecurityManager();
 133:     if (sm != null)
 134:       sm.checkPermission(new SecurityPermission("setPolicy"));
 135: 
 136:     setup(policy);
 137:     currentPolicy = policy;
 138:   }
 139: 
 140:   private static void setup(final Policy policy)
 141:   {
 142:     if (policy.pd2pc == null)
 143:       policy.pd2pc = Collections.synchronizedMap(new LinkedHashMap());
 144: 
 145:     ProtectionDomain pd = policy.getClass().getProtectionDomain();
 146:     if (pd.getCodeSource() != null)
 147:       {
 148:         PermissionCollection pc = null;
 149:         if (currentPolicy != null)
 150:           pc = currentPolicy.getPermissions(pd);
 151: 
 152:         if (pc == null) // assume it has all
 153:           {
 154:             pc = new Permissions();
 155:             pc.add(new AllPermission());
 156:           }
 157: 
 158:         policy.pd2pc.put(pd, pc); // add the mapping pd -> pc
 159:       }
 160:   }
 161: 
 162:   /**
 163:    * Ensures/forces loading of the configured policy provider, while bypassing
 164:    * the {@link SecurityManager} checks for <code>"getPolicy"</code> security
 165:    * permission.  Needed by {@link ProtectionDomain}.
 166:    */
 167:   static Policy getCurrentPolicy()
 168:   {
 169:     // FIXME: The class name of the Policy provider should really be sourced
 170:     // from the "java.security" configuration file. For now, just hard-code
 171:     // a stub implementation.
 172:     if (currentPolicy == null)
 173:       {
 174:         String pp = System.getProperty ("policy.provider");
 175:         if (pp != null)
 176:           try
 177:             {
 178:               currentPolicy = (Policy) Class.forName(pp).newInstance();
 179:             }
 180:           catch (Exception e)
 181:             {
 182:               // Ignored.
 183:             }
 184: 
 185:         if (currentPolicy == null)
 186:           currentPolicy = new gnu.java.security.provider.DefaultPolicy();
 187:       }
 188:     return currentPolicy;
 189:   }
 190: 
 191:   /**
 192:    * Tests if <code>currentPolicy</code> is not <code>null</code>,
 193:    * thus allowing clients to not force loading of any policy
 194:    * provider; needed by {@link ProtectionDomain}.
 195:    */
 196:   static boolean isLoaded()
 197:   {
 198:     return currentPolicy != null;
 199:   }
 200: 
 201:   /**
 202:    * Returns the set of Permissions allowed for a given {@link CodeSource}.
 203:    *
 204:    * @param codesource
 205:    *          the {@link CodeSource} for which, the caller needs to find the
 206:    *          set of granted permissions.
 207:    * @return a set of permissions for {@link CodeSource} specified by the
 208:    *         current <code>Policy</code>.
 209:    * @throws SecurityException
 210:    *           if a {@link SecurityManager} is installed which disallows this
 211:    *           operation.
 212:    */
 213:   public abstract PermissionCollection getPermissions(CodeSource codesource);
 214: 
 215:   /**
 216:    * Returns the set of Permissions allowed for a given {@link ProtectionDomain}.
 217:    *
 218:    * @param domain
 219:    *          the {@link ProtectionDomain} for which, the caller needs to find
 220:    *          the set of granted permissions.
 221:    * @return a set of permissions for {@link ProtectionDomain} specified by the
 222:    *         current <code>Policy.</code>.
 223:    * @since 1.4
 224:    * @see ProtectionDomain
 225:    * @see SecureClassLoader
 226:    */
 227:   public PermissionCollection getPermissions(ProtectionDomain domain)
 228:   {
 229:     if (domain == null)
 230:       return new Permissions();
 231: 
 232:     if (pd2pc == null)
 233:       setup(this);
 234: 
 235:     PermissionCollection result = (PermissionCollection) pd2pc.get(domain);
 236:     if (result != null)
 237:       {
 238:         Permissions realResult = new Permissions();
 239:         for (Enumeration e = result.elements(); e.hasMoreElements(); )
 240:           realResult.add((Permission) e.nextElement());
 241: 
 242:         return realResult;
 243:       }
 244: 
 245:     result = getPermissions(domain.getCodeSource());
 246:     if (result == null)
 247:       result = new Permissions();
 248: 
 249:     PermissionCollection pc = domain.getPermissions();
 250:     if (pc != null)
 251:       for (Enumeration e = pc.elements(); e.hasMoreElements(); )
 252:         result.add((Permission) e.nextElement());
 253: 
 254:     return result;
 255:   }
 256: 
 257:   /**
 258:    * Checks if the designated {@link Permission} is granted to a designated
 259:    * {@link ProtectionDomain}.
 260:    *
 261:    * @param domain
 262:    *          the {@link ProtectionDomain} to test.
 263:    * @param permission
 264:    *          the {@link Permission} to check.
 265:    * @return <code>true</code> if <code>permission</code> is implied by a
 266:    *         permission granted to this {@link ProtectionDomain}. Returns
 267:    *         <code>false</code> otherwise.
 268:    * @since 1.4
 269:    * @see ProtectionDomain
 270:    */
 271:   public boolean implies(ProtectionDomain domain, Permission permission)
 272:   {
 273:     if (pd2pc == null)
 274:       setup(this);
 275: 
 276:     PermissionCollection pc = (PermissionCollection) pd2pc.get(domain);
 277:     if (pc != null)
 278:       return pc.implies(permission);
 279: 
 280:     boolean result = false;
 281:     pc = getPermissions(domain);
 282:     if (pc != null)
 283:       {
 284:         result = pc.implies(permission);
 285:         pd2pc.put(domain, pc);
 286:       }
 287: 
 288:     return result;
 289:   }
 290: 
 291:   /**
 292:    * Causes this <code>Policy</code> instance to refresh / reload its
 293:    * configuration. The method used to refresh depends on the concrete
 294:    * implementation.
 295:    */
 296:   public abstract void refresh();
 297: }