Save This Page
Home » openjdk-7 » java » security » [javadoc | source]
    1   /*
    2    * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.security;
   27   
   28   import java.util.ArrayList;
   29   import java.util.Collections;
   30   import java.util.Enumeration;
   31   import java.util.List;
   32   import java.util.Map;
   33   import java.util.WeakHashMap;
   34   import sun.misc.JavaSecurityProtectionDomainAccess;
   35   import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache;
   36   import sun.misc.SharedSecrets;
   37   import sun.security.util.Debug;
   38   import sun.security.util.SecurityConstants;
   39   import sun.misc.JavaSecurityAccess;
   40   import sun.misc.SharedSecrets;
   41   
   42   /**
   43    *
   44    *<p>
   45    * This ProtectionDomain class encapsulates the characteristics of a domain,
   46    * which encloses a set of classes whose instances are granted a set
   47    * of permissions when being executed on behalf of a given set of Principals.
   48    * <p>
   49    * A static set of permissions can be bound to a ProtectionDomain when it is
   50    * constructed; such permissions are granted to the domain regardless of the
   51    * Policy in force. However, to support dynamic security policies, a
   52    * ProtectionDomain can also be constructed such that it is dynamically
   53    * mapped to a set of permissions by the current Policy whenever a permission
   54    * is checked.
   55    * <p>
   56    *
   57    * @author Li Gong
   58    * @author Roland Schemers
   59    * @author Gary Ellison
   60    */
   61   
   62   public class ProtectionDomain {
   63   
   64       static {
   65           // Set up JavaSecurityAccess in SharedSecrets
   66           SharedSecrets.setJavaSecurityAccess(
   67               new JavaSecurityAccess() {
   68                   public <T> T doIntersectionPrivilege(
   69                       PrivilegedAction<T> action,
   70                       final AccessControlContext stack,
   71                       final AccessControlContext context)
   72                   {
   73                       if (action == null) {
   74                           throw new NullPointerException();
   75                       }
   76                       return AccessController.doPrivileged(
   77                           action,
   78                           new AccessControlContext(
   79                               stack.getContext(), context).optimize()
   80                       );
   81                   }
   82   
   83                   public <T> T doIntersectionPrivilege(
   84                       PrivilegedAction<T> action,
   85                       AccessControlContext context)
   86                   {
   87                       return doIntersectionPrivilege(action,
   88                           AccessController.getContext(), context);
   89                   }
   90               }
   91          );
   92       }
   93   
   94       /* CodeSource */
   95       private CodeSource codesource ;
   96   
   97       /* ClassLoader the protection domain was consed from */
   98       private ClassLoader classloader;
   99   
  100       /* Principals running-as within this protection domain */
  101       private Principal[] principals;
  102   
  103       /* the rights this protection domain is granted */
  104       private PermissionCollection permissions;
  105   
  106       /* if the permissions object has AllPermission */
  107       private boolean hasAllPerm = false;
  108   
  109       /* the PermissionCollection is static (pre 1.4 constructor)
  110          or dynamic (via a policy refresh) */
  111       private boolean staticPermissions;
  112   
  113       /*
  114        * An object used as a key when the ProtectionDomain is stored in a Map.
  115        */
  116       final Key key = new Key();
  117   
  118       private static final Debug debug = Debug.getInstance("domain");
  119   
  120       /**
  121        * Creates a new ProtectionDomain with the given CodeSource and
  122        * Permissions. If the permissions object is not null, then
  123        *  <code>setReadOnly())</code> will be called on the passed in
  124        * Permissions object. The only permissions granted to this domain
  125        * are the ones specified; the current Policy will not be consulted.
  126        *
  127        * @param codesource the codesource associated with this domain
  128        * @param permissions the permissions granted to this domain
  129        */
  130       public ProtectionDomain(CodeSource codesource,
  131                               PermissionCollection permissions) {
  132           this.codesource = codesource;
  133           if (permissions != null) {
  134               this.permissions = permissions;
  135               this.permissions.setReadOnly();
  136               if (permissions instanceof Permissions &&
  137                   ((Permissions)permissions).allPermission != null) {
  138                   hasAllPerm = true;
  139               }
  140           }
  141           this.classloader = null;
  142           this.principals = new Principal[0];
  143           staticPermissions = true;
  144       }
  145   
  146       /**
  147        * Creates a new ProtectionDomain qualified by the given CodeSource,
  148        * Permissions, ClassLoader and array of Principals. If the
  149        * permissions object is not null, then <code>setReadOnly()</code>
  150        * will be called on the passed in Permissions object.
  151        * The permissions granted to this domain are dynamic; they include
  152        * both the static permissions passed to this constructor, and any
  153        * permissions granted to this domain by the current Policy at the
  154        * time a permission is checked.
  155        * <p>
  156        * This constructor is typically used by
  157        * {@link SecureClassLoader ClassLoaders}
  158        * and {@link DomainCombiner DomainCombiners} which delegate to
  159        * <code>Policy</code> to actively associate the permissions granted to
  160        * this domain. This constructor affords the
  161        * Policy provider the opportunity to augment the supplied
  162        * PermissionCollection to reflect policy changes.
  163        * <p>
  164        *
  165        * @param codesource the CodeSource associated with this domain
  166        * @param permissions the permissions granted to this domain
  167        * @param classloader the ClassLoader associated with this domain
  168        * @param principals the array of Principals associated with this
  169        * domain. The contents of the array are copied to protect against
  170        * subsequent modification.
  171        * @see Policy#refresh
  172        * @see Policy#getPermissions(ProtectionDomain)
  173        * @since 1.4
  174        */
  175       public ProtectionDomain(CodeSource codesource,
  176                               PermissionCollection permissions,
  177                               ClassLoader classloader,
  178                               Principal[] principals) {
  179           this.codesource = codesource;
  180           if (permissions != null) {
  181               this.permissions = permissions;
  182               this.permissions.setReadOnly();
  183               if (permissions instanceof Permissions &&
  184                   ((Permissions)permissions).allPermission != null) {
  185                   hasAllPerm = true;
  186               }
  187           }
  188           this.classloader = classloader;
  189           this.principals = (principals != null ? principals.clone():
  190                              new Principal[0]);
  191           staticPermissions = false;
  192       }
  193   
  194       /**
  195        * Returns the CodeSource of this domain.
  196        * @return the CodeSource of this domain which may be null.
  197        * @since 1.2
  198        */
  199       public final CodeSource getCodeSource() {
  200           return this.codesource;
  201       }
  202   
  203   
  204       /**
  205        * Returns the ClassLoader of this domain.
  206        * @return the ClassLoader of this domain which may be null.
  207        *
  208        * @since 1.4
  209        */
  210       public final ClassLoader getClassLoader() {
  211           return this.classloader;
  212       }
  213   
  214   
  215       /**
  216        * Returns an array of principals for this domain.
  217        * @return a non-null array of principals for this domain.
  218        * Returns a new array each time this method is called.
  219        *
  220        * @since 1.4
  221        */
  222       public final Principal[] getPrincipals() {
  223           return this.principals.clone();
  224       }
  225   
  226       /**
  227        * Returns the static permissions granted to this domain.
  228        *
  229        * @return the static set of permissions for this domain which may be null.
  230        * @see Policy#refresh
  231        * @see Policy#getPermissions(ProtectionDomain)
  232        */
  233       public final PermissionCollection getPermissions() {
  234           return permissions;
  235       }
  236   
  237       /**
  238        * Check and see if this ProtectionDomain implies the permissions
  239        * expressed in the Permission object.
  240        * <p>
  241        * The set of permissions evaluated is a function of whether the
  242        * ProtectionDomain was constructed with a static set of permissions
  243        * or it was bound to a dynamically mapped set of permissions.
  244        * <p>
  245        * If the ProtectionDomain was constructed to a
  246        * {@link #ProtectionDomain(CodeSource, PermissionCollection)
  247        * statically bound} PermissionCollection then the permission will
  248        * only be checked against the PermissionCollection supplied at
  249        * construction.
  250        * <p>
  251        * However, if the ProtectionDomain was constructed with
  252        * the constructor variant which supports
  253        * {@link #ProtectionDomain(CodeSource, PermissionCollection,
  254        * ClassLoader, java.security.Principal[]) dynamically binding}
  255        * permissions, then the permission will be checked against the
  256        * combination of the PermissionCollection supplied at construction and
  257        * the current Policy binding.
  258        * <p>
  259        *
  260        * @param permission the Permission object to check.
  261        *
  262        * @return true if "permission" is implicit to this ProtectionDomain.
  263        */
  264       public boolean implies(Permission permission) {
  265   
  266           if (hasAllPerm) {
  267               // internal permission collection already has AllPermission -
  268               // no need to go to policy
  269               return true;
  270           }
  271   
  272           if (!staticPermissions &&
  273               Policy.getPolicyNoCheck().implies(this, permission))
  274               return true;
  275           if (permissions != null)
  276               return permissions.implies(permission);
  277   
  278           return false;
  279       }
  280   
  281       /**
  282        * Convert a ProtectionDomain to a String.
  283        */
  284       @Override public String toString() {
  285           String pals = "<no principals>";
  286           if (principals != null && principals.length > 0) {
  287               StringBuilder palBuf = new StringBuilder("(principals ");
  288   
  289               for (int i = 0; i < principals.length; i++) {
  290                   palBuf.append(principals[i].getClass().getName() +
  291                               " \"" + principals[i].getName() +
  292                               "\"");
  293                   if (i < principals.length-1)
  294                       palBuf.append(",\n");
  295                   else
  296                       palBuf.append(")\n");
  297               }
  298               pals = palBuf.toString();
  299           }
  300   
  301           // Check if policy is set; we don't want to load
  302           // the policy prematurely here
  303           PermissionCollection pc = Policy.isSet() && seeAllp() ?
  304                                         mergePermissions():
  305                                         getPermissions();
  306   
  307           return "ProtectionDomain "+
  308               " "+codesource+"\n"+
  309               " "+classloader+"\n"+
  310               " "+pals+"\n"+
  311               " "+pc+"\n";
  312       }
  313   
  314       /**
  315        * Return true (merge policy permissions) in the following cases:
  316        *
  317        * . SecurityManager is null
  318        *
  319        * . SecurityManager is not null,
  320        *          debug is not null,
  321        *          SecurityManager impelmentation is in bootclasspath,
  322        *          Policy implementation is in bootclasspath
  323        *          (the bootclasspath restrictions avoid recursion)
  324        *
  325        * . SecurityManager is not null,
  326        *          debug is null,
  327        *          caller has Policy.getPolicy permission
  328        */
  329       private static boolean seeAllp() {
  330           SecurityManager sm = System.getSecurityManager();
  331   
  332           if (sm == null) {
  333               return true;
  334           } else {
  335               if (debug != null) {
  336                   if (sm.getClass().getClassLoader() == null &&
  337                       Policy.getPolicyNoCheck().getClass().getClassLoader()
  338                                                                   == null) {
  339                       return true;
  340                   }
  341               } else {
  342                   try {
  343                       sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
  344                       return true;
  345                   } catch (SecurityException se) {
  346                       // fall thru and return false
  347                   }
  348               }
  349           }
  350   
  351           return false;
  352       }
  353   
  354       private PermissionCollection mergePermissions() {
  355           if (staticPermissions)
  356               return permissions;
  357   
  358           PermissionCollection perms =
  359               java.security.AccessController.doPrivileged
  360               (new java.security.PrivilegedAction<PermissionCollection>() {
  361                       public PermissionCollection run() {
  362                           Policy p = Policy.getPolicyNoCheck();
  363                           return p.getPermissions(ProtectionDomain.this);
  364                       }
  365                   });
  366   
  367           Permissions mergedPerms = new Permissions();
  368           int swag = 32;
  369           int vcap = 8;
  370           Enumeration<Permission> e;
  371           List<Permission> pdVector = new ArrayList<>(vcap);
  372           List<Permission> plVector = new ArrayList<>(swag);
  373   
  374           //
  375           // Build a vector of domain permissions for subsequent merge
  376           if (permissions != null) {
  377               synchronized (permissions) {
  378                   e = permissions.elements();
  379                   while (e.hasMoreElements()) {
  380                       pdVector.add(e.nextElement());
  381                   }
  382               }
  383           }
  384   
  385           //
  386           // Build a vector of Policy permissions for subsequent merge
  387           if (perms != null) {
  388               synchronized (perms) {
  389                   e = perms.elements();
  390                   while (e.hasMoreElements()) {
  391                       plVector.add(e.nextElement());
  392                       vcap++;
  393                   }
  394               }
  395           }
  396   
  397           if (perms != null && permissions != null) {
  398               //
  399               // Weed out the duplicates from the policy. Unless a refresh
  400               // has occured since the pd was consed this should result in
  401               // an empty vector.
  402               synchronized (permissions) {
  403                   e = permissions.elements();   // domain vs policy
  404                   while (e.hasMoreElements()) {
  405                       Permission pdp = e.nextElement();
  406                       Class pdpClass = pdp.getClass();
  407                       String pdpActions = pdp.getActions();
  408                       String pdpName = pdp.getName();
  409                       for (int i = 0; i < plVector.size(); i++) {
  410                           Permission pp = plVector.get(i);
  411                           if (pdpClass.isInstance(pp)) {
  412                               // The equals() method on some permissions
  413                               // have some side effects so this manual
  414                               // comparison is sufficient.
  415                               if (pdpName.equals(pp.getName()) &&
  416                                   pdpActions.equals(pp.getActions())) {
  417                                   plVector.remove(i);
  418                                   break;
  419                               }
  420                           }
  421                       }
  422                   }
  423               }
  424           }
  425   
  426           if (perms !=null) {
  427               // the order of adding to merged perms and permissions
  428               // needs to preserve the bugfix 4301064
  429   
  430               for (int i = plVector.size()-1; i >= 0; i--) {
  431                   mergedPerms.add(plVector.get(i));
  432               }
  433           }
  434           if (permissions != null) {
  435               for (int i = pdVector.size()-1; i >= 0; i--) {
  436                   mergedPerms.add(pdVector.get(i));
  437               }
  438           }
  439   
  440           return mergedPerms;
  441       }
  442   
  443       /**
  444        * Used for storing ProtectionDomains as keys in a Map.
  445        */
  446       final class Key {}
  447   
  448       static {
  449           SharedSecrets.setJavaSecurityProtectionDomainAccess(
  450               new JavaSecurityProtectionDomainAccess() {
  451                   public ProtectionDomainCache getProtectionDomainCache() {
  452                       return new ProtectionDomainCache() {
  453                           private final Map<Key, PermissionCollection> map =
  454                               Collections.synchronizedMap
  455                                   (new WeakHashMap<Key, PermissionCollection>());
  456                           public void put(ProtectionDomain pd,
  457                               PermissionCollection pc) {
  458                               map.put((pd == null ? null : pd.key), pc);
  459                           }
  460                           public PermissionCollection get(ProtectionDomain pd) {
  461                               return pd == null ? map.get(null) : map.get(pd.key);
  462                           }
  463                       };
  464                   }
  465               });
  466       }
  467   }

Save This Page
Home » openjdk-7 » java » security » [javadoc | source]