Save This Page
Home » openjdk-7 » java » security » [javadoc | source]
    1   /*
    2    * Copyright 1997-2006 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.security;
   27   
   28   import java.util.Enumeration;
   29   import java.util.List;
   30   import java.util.ArrayList;
   31   import sun.security.util.Debug;
   32   import sun.security.util.SecurityConstants;
   33   
   34   /**
   35    *
   36    *<p>
   37    * This ProtectionDomain class encapsulates the characteristics of a domain,
   38    * which encloses a set of classes whose instances are granted a set
   39    * of permissions when being executed on behalf of a given set of Principals.
   40    * <p>
   41    * A static set of permissions can be bound to a ProtectionDomain when it is
   42    * constructed; such permissions are granted to the domain regardless of the
   43    * Policy in force. However, to support dynamic security policies, a
   44    * ProtectionDomain can also be constructed such that it is dynamically
   45    * mapped to a set of permissions by the current Policy whenever a permission
   46    * is checked.
   47    * <p>
   48    *
   49    * @author Li Gong
   50    * @author Roland Schemers
   51    * @author Gary Ellison
   52    */
   53   
   54   public class ProtectionDomain {
   55   
   56       /* CodeSource */
   57       private CodeSource codesource ;
   58   
   59       /* ClassLoader the protection domain was consed from */
   60       private ClassLoader classloader;
   61   
   62       /* Principals running-as within this protection domain */
   63       private Principal[] principals;
   64   
   65       /* the rights this protection domain is granted */
   66       private PermissionCollection permissions;
   67   
   68       /* if the permissions object has AllPermission */
   69       private boolean hasAllPerm = false;
   70   
   71       /* the PermissionCollection is static (pre 1.4 constructor)
   72          or dynamic (via a policy refresh) */
   73       private boolean staticPermissions;
   74   
   75       private static final Debug debug = Debug.getInstance("domain");
   76   
   77       /**
   78        * Creates a new ProtectionDomain with the given CodeSource and
   79        * Permissions. If the permissions object is not null, then
   80        *  <code>setReadOnly())</code> will be called on the passed in
   81        * Permissions object. The only permissions granted to this domain
   82        * are the ones specified; the current Policy will not be consulted.
   83        *
   84        * @param codesource the codesource associated with this domain
   85        * @param permissions the permissions granted to this domain
   86        */
   87       public ProtectionDomain(CodeSource codesource,
   88                               PermissionCollection permissions) {
   89           this.codesource = codesource;
   90           if (permissions != null) {
   91               this.permissions = permissions;
   92               this.permissions.setReadOnly();
   93               if (permissions instanceof Permissions &&
   94                   ((Permissions)permissions).allPermission != null) {
   95                   hasAllPerm = true;
   96               }
   97           }
   98           this.classloader = null;
   99           this.principals = new Principal[0];
  100           staticPermissions = true;
  101       }
  102   
  103       /**
  104        * Creates a new ProtectionDomain qualified by the given CodeSource,
  105        * Permissions, ClassLoader and array of Principals. If the
  106        * permissions object is not null, then <code>setReadOnly()</code>
  107        * will be called on the passed in Permissions object.
  108        * The permissions granted to this domain are dynamic; they include
  109        * both the static permissions passed to this constructor, and any
  110        * permissions granted to this domain by the current Policy at the
  111        * time a permission is checked.
  112        * <p>
  113        * This constructor is typically used by
  114        * {@link SecureClassLoader ClassLoaders}
  115        * and {@link DomainCombiner DomainCombiners} which delegate to
  116        * <code>Policy</code> to actively associate the permissions granted to
  117        * this domain. This constructor affords the
  118        * Policy provider the opportunity to augment the supplied
  119        * PermissionCollection to reflect policy changes.
  120        * <p>
  121        *
  122        * @param codesource the CodeSource associated with this domain
  123        * @param permissions the permissions granted to this domain
  124        * @param classloader the ClassLoader associated with this domain
  125        * @param principals the array of Principals associated with this
  126        * domain. The contents of the array are copied to protect against
  127        * subsequent modification.
  128        * @see Policy#refresh
  129        * @see Policy#getPermissions(ProtectionDomain)
  130        * @since 1.4
  131        */
  132       public ProtectionDomain(CodeSource codesource,
  133                               PermissionCollection permissions,
  134                               ClassLoader classloader,
  135                               Principal[] principals) {
  136           this.codesource = codesource;
  137           if (permissions != null) {
  138               this.permissions = permissions;
  139               this.permissions.setReadOnly();
  140               if (permissions instanceof Permissions &&
  141                   ((Permissions)permissions).allPermission != null) {
  142                   hasAllPerm = true;
  143               }
  144           }
  145           this.classloader = classloader;
  146           this.principals = (principals != null ? principals.clone():
  147                              new Principal[0]);
  148           staticPermissions = false;
  149       }
  150   
  151       /**
  152        * Returns the CodeSource of this domain.
  153        * @return the CodeSource of this domain which may be null.
  154        * @since 1.2
  155        */
  156       public final CodeSource getCodeSource() {
  157           return this.codesource;
  158       }
  159   
  160   
  161       /**
  162        * Returns the ClassLoader of this domain.
  163        * @return the ClassLoader of this domain which may be null.
  164        *
  165        * @since 1.4
  166        */
  167       public final ClassLoader getClassLoader() {
  168           return this.classloader;
  169       }
  170   
  171   
  172       /**
  173        * Returns an array of principals for this domain.
  174        * @return a non-null array of principals for this domain.
  175        * Returns a new array each time this method is called.
  176        *
  177        * @since 1.4
  178        */
  179       public final Principal[] getPrincipals() {
  180           return this.principals.clone();
  181       }
  182   
  183       /**
  184        * Returns the static permissions granted to this domain.
  185        *
  186        * @return the static set of permissions for this domain which may be null.
  187        * @see Policy#refresh
  188        * @see Policy#getPermissions(ProtectionDomain)
  189        */
  190       public final PermissionCollection getPermissions() {
  191           return permissions;
  192       }
  193   
  194       /**
  195        * Check and see if this ProtectionDomain implies the permissions
  196        * expressed in the Permission object.
  197        * <p>
  198        * The set of permissions evaluated is a function of whether the
  199        * ProtectionDomain was constructed with a static set of permissions
  200        * or it was bound to a dynamically mapped set of permissions.
  201        * <p>
  202        * If the ProtectionDomain was constructed to a
  203        * {@link #ProtectionDomain(CodeSource, PermissionCollection)
  204        * statically bound} PermissionCollection then the permission will
  205        * only be checked against the PermissionCollection supplied at
  206        * construction.
  207        * <p>
  208        * However, if the ProtectionDomain was constructed with
  209        * the constructor variant which supports
  210        * {@link #ProtectionDomain(CodeSource, PermissionCollection,
  211        * ClassLoader, java.security.Principal[]) dynamically binding}
  212        * permissions, then the permission will be checked against the
  213        * combination of the PermissionCollection supplied at construction and
  214        * the current Policy binding.
  215        * <p>
  216        *
  217        * @param permission the Permission object to check.
  218        *
  219        * @return true if "permission" is implicit to this ProtectionDomain.
  220        */
  221       public boolean implies(Permission permission) {
  222   
  223           if (hasAllPerm) {
  224               // internal permission collection already has AllPermission -
  225               // no need to go to policy
  226               return true;
  227           }
  228   
  229           if (!staticPermissions &&
  230               Policy.getPolicyNoCheck().implies(this, permission))
  231               return true;
  232           if (permissions != null)
  233               return permissions.implies(permission);
  234   
  235           return false;
  236       }
  237   
  238       /**
  239        * Convert a ProtectionDomain to a String.
  240        */
  241       public String toString() {
  242           String pals = "<no principals>";
  243           if (principals != null && principals.length > 0) {
  244               StringBuilder palBuf = new StringBuilder("(principals ");
  245   
  246               for (int i = 0; i < principals.length; i++) {
  247                   palBuf.append(principals[i].getClass().getName() +
  248                               " \"" + principals[i].getName() +
  249                               "\"");
  250                   if (i < principals.length-1)
  251                       palBuf.append(",\n");
  252                   else
  253                       palBuf.append(")\n");
  254               }
  255               pals = palBuf.toString();
  256           }
  257   
  258           // Check if policy is set; we don't want to load
  259           // the policy prematurely here
  260           PermissionCollection pc = Policy.isSet() && seeAllp() ?
  261                                         mergePermissions():
  262                                         getPermissions();
  263   
  264           return "ProtectionDomain "+
  265               " "+codesource+"\n"+
  266               " "+classloader+"\n"+
  267               " "+pals+"\n"+
  268               " "+pc+"\n";
  269       }
  270   
  271       /**
  272        * Return true (merge policy permissions) in the following cases:
  273        *
  274        * . SecurityManager is null
  275        *
  276        * . SecurityManager is not null,
  277        *          debug is not null,
  278        *          SecurityManager impelmentation is in bootclasspath,
  279        *          Policy implementation is in bootclasspath
  280        *          (the bootclasspath restrictions avoid recursion)
  281        *
  282        * . SecurityManager is not null,
  283        *          debug is null,
  284        *          caller has Policy.getPolicy permission
  285        */
  286       private static boolean seeAllp() {
  287           SecurityManager sm = System.getSecurityManager();
  288   
  289           if (sm == null) {
  290               return true;
  291           } else {
  292               if (debug != null) {
  293                   if (sm.getClass().getClassLoader() == null &&
  294                       Policy.getPolicyNoCheck().getClass().getClassLoader()
  295                                                                   == null) {
  296                       return true;
  297                   }
  298               } else {
  299                   try {
  300                       sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
  301                       return true;
  302                   } catch (SecurityException se) {
  303                       // fall thru and return false
  304                   }
  305               }
  306           }
  307   
  308           return false;
  309       }
  310   
  311       private PermissionCollection mergePermissions() {
  312           if (staticPermissions)
  313               return permissions;
  314   
  315           PermissionCollection perms =
  316               java.security.AccessController.doPrivileged
  317               (new java.security.PrivilegedAction<PermissionCollection>() {
  318                       public PermissionCollection run() {
  319                           Policy p = Policy.getPolicyNoCheck();
  320                           return p.getPermissions(ProtectionDomain.this);
  321                       }
  322                   });
  323   
  324           Permissions mergedPerms = new Permissions();
  325           int swag = 32;
  326           int vcap = 8;
  327           Enumeration<Permission> e;
  328           List<Permission> pdVector = new ArrayList<Permission>(vcap);
  329           List<Permission> plVector = new ArrayList<Permission>(swag);
  330   
  331           //
  332           // Build a vector of domain permissions for subsequent merge
  333           if (permissions != null) {
  334               synchronized (permissions) {
  335                   e = permissions.elements();
  336                   while (e.hasMoreElements()) {
  337                       pdVector.add(e.nextElement());
  338                   }
  339               }
  340           }
  341   
  342           //
  343           // Build a vector of Policy permissions for subsequent merge
  344           if (perms != null) {
  345               synchronized (perms) {
  346                   e = perms.elements();
  347                   while (e.hasMoreElements()) {
  348                       plVector.add(e.nextElement());
  349                       vcap++;
  350                   }
  351               }
  352           }
  353   
  354           if (perms != null && permissions != null) {
  355               //
  356               // Weed out the duplicates from the policy. Unless a refresh
  357               // has occured since the pd was consed this should result in
  358               // an empty vector.
  359               synchronized (permissions) {
  360                   e = permissions.elements();   // domain vs policy
  361                   while (e.hasMoreElements()) {
  362                       Permission pdp = e.nextElement();
  363                       Class pdpClass = pdp.getClass();
  364                       String pdpActions = pdp.getActions();
  365                       String pdpName = pdp.getName();
  366                       for (int i = 0; i < plVector.size(); i++) {
  367                           Permission pp = plVector.get(i);
  368                           if (pdpClass.isInstance(pp)) {
  369                               // The equals() method on some permissions
  370                               // have some side effects so this manual
  371                               // comparison is sufficient.
  372                               if (pdpName.equals(pp.getName()) &&
  373                                   pdpActions.equals(pp.getActions())) {
  374                                   plVector.remove(i);
  375                                   break;
  376                               }
  377                           }
  378                       }
  379                   }
  380               }
  381           }
  382   
  383           if (perms !=null) {
  384               // the order of adding to merged perms and permissions
  385               // needs to preserve the bugfix 4301064
  386   
  387               for (int i = plVector.size()-1; i >= 0; i--) {
  388                   mergedPerms.add(plVector.get(i));
  389               }
  390           }
  391           if (permissions != null) {
  392               for (int i = pdVector.size()-1; i >= 0; i--) {
  393                   mergedPerms.add(pdVector.get(i));
  394               }
  395           }
  396   
  397           return mergedPerms;
  398       }
  399   }

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