Save This Page
Home » openjdk-7 » sun.security » provider » [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 sun.security.provider;
   27   
   28   import java.io;
   29   import java.lang.RuntimePermission;
   30   import java.lang.reflect;
   31   import java.lang.ref;
   32   import java.net.MalformedURLException;
   33   import java.net.URL;
   34   import java.net.URI;
   35   import java.util;
   36   import java.util.Enumeration;
   37   import java.util.Hashtable;
   38   import java.util.List;
   39   import java.util.StringTokenizer;
   40   import java.util.PropertyPermission;
   41   import java.util.ArrayList;
   42   import java.util.ListIterator;
   43   import java.util.WeakHashMap;
   44   import java.text.MessageFormat;
   45   import com.sun.security.auth.PrincipalComparator;
   46   import java.security;
   47   import java.security.cert.Certificate;
   48   import java.security.cert.X509Certificate;
   49   import javax.security.auth.PrivateCredentialPermission;
   50   import javax.security.auth.Subject;
   51   import javax.security.auth.x500.X500Principal;
   52   import java.io.FilePermission;
   53   import java.net.SocketPermission;
   54   import java.net.NetPermission;
   55   import java.util.PropertyPermission;
   56   import java.util.concurrent.atomic.AtomicReference;
   57   import java.awt.AWTPermission;
   58   /*
   59   import javax.security.auth.AuthPermission;
   60   import javax.security.auth.kerberos.ServicePermission;
   61   import javax.security.auth.kerberos.DelegationPermission;
   62   import java.io.SerializablePermission;
   63   import java.util.logging.LoggingPermission;
   64   import java.sql.SQLPermission;
   65   import java.lang.reflect.ReflectPermission;
   66   import javax.sound.sampled.AudioPermission;
   67   import javax.net.ssl.SSLPermission;
   68   */
   69   import sun.security.util.Password;
   70   import sun.security.util.PolicyUtil;
   71   import sun.security.util.PropertyExpander;
   72   import sun.security.util.Debug;
   73   import sun.security.util.ResourcesMgr;
   74   import sun.security.util.SecurityConstants;
   75   import sun.net.www.ParseUtil;
   76   
   77   /**
   78    * This class represents a default implementation for
   79    * <code>java.security.Policy</code>.
   80    *
   81    * Note:
   82    * For backward compatibility with JAAS 1.0 it loads
   83    * both java.auth.policy and java.policy. However it
   84    * is recommended that java.auth.policy be not used
   85    * and the java.policy contain all grant entries including
   86    * that contain principal-based entries.
   87    *
   88    *
   89    * <p> This object stores the policy for entire Java runtime,
   90    * and is the amalgamation of multiple static policy
   91    * configurations that resides in files.
   92    * The algorithm for locating the policy file(s) and reading their
   93    * information into this <code>Policy</code> object is:
   94    *
   95    * <ol>
   96    * <li>
   97    *   Loop through the <code>java.security.Security</code> properties,
   98    *   <i>policy.url.1</i>, <i>policy.url.2</i>, ...,
   99    *   <i>policy.url.X</i>" and
  100    *   <i>auth.policy.url.1</i>, <i>auth.policy.url.2</i>, ...,
  101    *   <i>auth.policy.url.X</i>".  These properties are set
  102    *   in the Java security properties file, which is located in the file named
  103    *   &lt;JAVA_HOME&gt;/lib/security/java.security.
  104    *   &lt;JAVA_HOME&gt; refers to the value of the java.home system property,
  105    *   and specifies the directory where the JRE is installed.
  106    *   Each property value specifies a <code>URL</code> pointing to a
  107    *   policy file to be loaded.  Read in and load each policy.
  108    *
  109    *   <i>auth.policy.url</i> is supported only for backward compatibility.
  110    *
  111    * <li>
  112    *   The <code>java.lang.System</code> property <i>java.security.policy</i>
  113    *   may also be set to a <code>URL</code> pointing to another policy file
  114    *   (which is the case when a user uses the -D switch at runtime).
  115    *   If this property is defined, and its use is allowed by the
  116    *   security property file (the Security property,
  117    *   <i>policy.allowSystemProperty</i> is set to <i>true</i>),
  118    *   also load that policy.
  119    *
  120    * <li>
  121    *   The <code>java.lang.System</code> property
  122    *   <i>java.security.auth.policy</i> may also be set to a
  123    *   <code>URL</code> pointing to another policy file
  124    *   (which is the case when a user uses the -D switch at runtime).
  125    *   If this property is defined, and its use is allowed by the
  126    *   security property file (the Security property,
  127    *   <i>policy.allowSystemProperty</i> is set to <i>true</i>),
  128    *   also load that policy.
  129    *
  130    *   <i>java.security.auth.policy</i> is supported only for backward
  131    *   compatibility.
  132    *
  133    *   If the  <i>java.security.policy</i> or
  134    *   <i>java.security.auth.policy</i> property is defined using
  135    *   "==" (rather than "="), then ignore all other specified
  136    *   policies and only load this policy.
  137    * </ol>
  138    *
  139    * Each policy file consists of one or more grant entries, each of
  140    * which consists of a number of permission entries.
  141    *
  142    * <pre>
  143    *   grant signedBy "<b>alias</b>", codeBase "<b>URL</b>",
  144    *         principal <b>principalClass</b> "<b>principalName</b>",
  145    *         principal <b>principalClass</b> "<b>principalName</b>",
  146    *         ... {
  147    *
  148    *     permission <b>Type</b> "<b>name</b> "<b>action</b>",
  149    *         signedBy "<b>alias</b>";
  150    *     permission <b>Type</b> "<b>name</b> "<b>action</b>",
  151    *         signedBy "<b>alias</b>";
  152    *     ....
  153    *   };
  154    * </pre>
  155    *
  156    * All non-bold items above must appear as is (although case
  157    * doesn't matter and some are optional, as noted below).
  158    * principal entries are optional and need not be present.
  159    * Italicized items represent variable values.
  160    *
  161    * <p> A grant entry must begin with the word <code>grant</code>.
  162    * The <code>signedBy</code>,<code>codeBase</code> and <code>principal</code>
  163    * name/value pairs are optional.
  164    * If they are not present, then any signer (including unsigned code)
  165    * will match, and any codeBase will match.
  166    * Note that the <i>principalClass</i>
  167    * may be set to the wildcard value, *, which allows it to match
  168    * any <code>Principal</code> class.  In addition, the <i>principalName</i>
  169    * may also be set to the wildcard value, *, allowing it to match
  170    * any <code>Principal</code> name.  When setting the <i>principalName</i>
  171    * to the *, do not surround the * with quotes.
  172    *
  173    * <p> A permission entry must begin with the word <code>permission</code>.
  174    * The word <code><i>Type</i></code> in the template above is
  175    * a specific permission type, such as <code>java.io.FilePermission</code>
  176    * or <code>java.lang.RuntimePermission</code>.
  177    *
  178    * <p> The "<i>action</i>" is required for
  179    * many permission types, such as <code>java.io.FilePermission</code>
  180    * (where it specifies what type of file access that is permitted).
  181    * It is not required for categories such as
  182    * <code>java.lang.RuntimePermission</code>
  183    * where it is not necessary - you either have the
  184    * permission specified by the <code>"<i>name</i>"</code>
  185    * value following the type name or you don't.
  186    *
  187    * <p> The <code>signedBy</code> name/value pair for a permission entry
  188    * is optional. If present, it indicates a signed permission. That is,
  189    * the permission class itself must be signed by the given alias in
  190    * order for it to be granted. For example,
  191    * suppose you have the following grant entry:
  192    *
  193    * <pre>
  194    *   grant principal foo.com.Principal "Duke" {
  195    *     permission Foo "foobar", signedBy "FooSoft";
  196    *   }
  197    * </pre>
  198    *
  199    * <p> Then this permission of type <i>Foo</i> is granted if the
  200    * <code>Foo.class</code> permission has been signed by the
  201    * "FooSoft" alias, or if XXX <code>Foo.class</code> is a
  202    * system class (i.e., is found on the CLASSPATH).
  203    *
  204    *
  205    * <p> Items that appear in an entry must appear in the specified order
  206    * (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
  207    * "<i>action</i>"). An entry is terminated with a semicolon.
  208    *
  209    * <p> Case is unimportant for the identifiers (<code>permission</code>,
  210    * <code>signedBy</code>, <code>codeBase</code>, etc.) but is
  211    * significant for the <i>Type</i>
  212    * or for any string that is passed in as a value. <p>
  213    *
  214    * <p> An example of two entries in a policy configuration file is
  215    * <pre>
  216    *   // if the code is comes from "foo.com" and is running as "Duke",
  217    *   // grant it read/write to all files in /tmp.
  218    *
  219    *   grant codeBase "foo.com", principal foo.com.Principal "Duke" {
  220    *              permission java.io.FilePermission "/tmp/*", "read,write";
  221    *   };
  222    *
  223    *   // grant any code running as "Duke" permission to read
  224    *   // the "java.vendor" Property.
  225    *
  226    *   grant principal foo.com.Principal "Duke" {
  227    *         permission java.util.PropertyPermission "java.vendor";
  228    *
  229    *
  230    * </pre>
  231    *  This Policy implementation supports special handling of any
  232    *  permission that contains the string, "<b>${{self}}</b>", as part of
  233    *  its target name.  When such a permission is evaluated
  234    *  (such as during a security check), <b>${{self}}</b> is replaced
  235    *  with one or more Principal class/name pairs.  The exact
  236    *  replacement performed depends upon the contents of the
  237    *  grant clause to which the permission belongs.
  238    *<p>
  239    *
  240    *  If the grant clause does not contain any principal information,
  241    *  the permission will be ignored (permissions containing
  242    *  <b>${{self}}</b> in their target names are only valid in the context
  243    *  of a principal-based grant clause).  For example, BarPermission
  244    *  will always be ignored in the following grant clause:
  245    *
  246    *<pre>
  247    *    grant codebase "www.foo.com", signedby "duke" {
  248    *      permission BarPermission "... ${{self}} ...";
  249    *    };
  250    *</pre>
  251    *
  252    *  If the grant clause contains principal information, <b>${{self}}</b>
  253    *  will be replaced with that same principal information.
  254    *  For example, <b>${{self}}</b> in BarPermission will be replaced by
  255    *  <b>javax.security.auth.x500.X500Principal "cn=Duke"</b>
  256    *  in the following grant clause:
  257    *
  258    *  <pre>
  259    *    grant principal javax.security.auth.x500.X500Principal "cn=Duke" {
  260    *      permission BarPermission "... ${{self}} ...";
  261    *    };
  262    *  </pre>
  263    *
  264    *  If there is a comma-separated list of principals in the grant
  265    *  clause, then <b>${{self}}</b> will be replaced by the same
  266    *  comma-separated list or principals.
  267    *  In the case where both the principal class and name are
  268    *  wildcarded in the grant clause, <b>${{self}}</b> is replaced
  269    *  with all the principals associated with the <code>Subject</code>
  270    *  in the current <code>AccessControlContext</code>.
  271    *
  272    *
  273    * <p> For PrivateCredentialPermissions, you can also use "<b>self</b>"
  274    * instead of "<b>${{self}}</b>". However the use of "<b>self</b>" is
  275    * deprecated in favour of "<b>${{self}}</b>".
  276    *
  277    * @see java.security.CodeSource
  278    * @see java.security.Permissions
  279    * @see java.security.ProtectionDomain
  280    */
  281   public class PolicyFile extends java.security.Policy {
  282   
  283       private static final Debug debug = Debug.getInstance("policy");
  284   
  285       private static final String NONE = "NONE";
  286       private static final String P11KEYSTORE = "PKCS11";
  287   
  288       private static final String SELF = "${{self}}";
  289       private static final String X500PRINCIPAL =
  290                           "javax.security.auth.x500.X500Principal";
  291       private static final String POLICY = "java.security.policy";
  292       private static final String SECURITY_MANAGER = "java.security.manager";
  293       private static final String POLICY_URL = "policy.url.";
  294       private static final String AUTH_POLICY = "java.security.auth.policy";
  295       private static final String AUTH_POLICY_URL = "auth.policy.url.";
  296   
  297       private static final int DEFAULT_CACHE_SIZE = 1;
  298   
  299       /** the scope to check */
  300       private static IdentityScope scope = null;
  301   
  302       // contains the policy grant entries, PD cache, and alias mapping
  303       private AtomicReference<PolicyInfo> policyInfo =
  304           new AtomicReference<PolicyInfo>();
  305       private boolean constructed = false;
  306   
  307       private boolean expandProperties = true;
  308       private boolean ignoreIdentityScope = false;
  309       private boolean allowSystemProperties = true;
  310       private boolean notUtf8 = false;
  311       private URL url;
  312   
  313       // for use with the reflection API
  314   
  315       private static final Class[] PARAMS0 = { };
  316       private static final Class[] PARAMS1 = { String.class };
  317       private static final Class[] PARAMS2 = { String.class, String.class };
  318   
  319       /**
  320        * Initializes the Policy object and reads the default policy
  321        * configuration file(s) into the Policy object.
  322        */
  323       public PolicyFile() {
  324           init((URL)null);
  325       }
  326   
  327       /**
  328        * Initializes the Policy object and reads the default policy
  329        * from the specified URL only.
  330        */
  331       public PolicyFile(URL url) {
  332           this.url = url;
  333           init(url);
  334       }
  335   
  336       /**
  337        * Initializes the Policy object and reads the default policy
  338        * configuration file(s) into the Policy object.
  339        *
  340        * The algorithm for locating the policy file(s) and reading their
  341        * information into the Policy object is:
  342        * <pre>
  343        *   loop through the Security Properties named "policy.url.1",
  344        *  ""policy.url.2", "auth.policy.url.1",  "auth.policy.url.2" etc, until
  345        *   you don't find one. Each of these specify a policy file.
  346        *
  347        *   if none of these could be loaded, use a builtin static policy
  348        *      equivalent to the default lib/security/java.policy file.
  349        *
  350        *   if the system property "java.policy" or "java.auth.policy" is defined
  351        * (which is the
  352        *      case when the user uses the -D switch at runtime), and
  353        *     its use is allowed by the security property file,
  354        *     also load it.
  355        * </pre>
  356        *
  357        * Each policy file consists of one or more grant entries, each of
  358        * which consists of a number of permission entries.
  359        * <pre>
  360        *   grant signedBy "<i>alias</i>", codeBase "<i>URL</i>" {
  361        *     permission <i>Type</i> "<i>name</i>", "<i>action</i>",
  362        *         signedBy "<i>alias</i>";
  363        *     ....
  364        *     permission <i>Type</i> "<i>name</i>", "<i>action</i>",
  365        *         signedBy "<i>alias</i>";
  366        *   };
  367        *
  368        * </pre>
  369        *
  370        * All non-italicized items above must appear as is (although case
  371        * doesn't matter and some are optional, as noted below).
  372        * Italicized items represent variable values.
  373        *
  374        * <p> A grant entry must begin with the word <code>grant</code>.
  375        * The <code>signedBy</code> and <code>codeBase</code> name/value
  376        * pairs are optional.
  377        * If they are not present, then any signer (including unsigned code)
  378        * will match, and any codeBase will match.
  379        *
  380        * <p> A permission entry must begin with the word <code>permission</code>.
  381        * The word <code><i>Type</i></code> in the template above would actually
  382        * be a specific permission type, such as
  383        * <code>java.io.FilePermission</code> or
  384        * <code>java.lang.RuntimePermission</code>.
  385        *
  386        * <p>The "<i>action</i>" is required for
  387        * many permission types, such as <code>java.io.FilePermission</code>
  388        * (where it specifies what type of file access is permitted).
  389        * It is not required for categories such as
  390        * <code>java.lang.RuntimePermission</code>
  391        * where it is not necessary - you either have the
  392        * permission specified by the <code>"<i>name</i>"</code>
  393        * value following the type name or you don't.
  394        *
  395        * <p>The <code>signedBy</code> name/value pair for a permission entry
  396        * is optional. If present, it indicates a signed permission. That is,
  397        * the permission class itself must be signed by the given alias in
  398        * order for it to be granted. For example,
  399        * suppose you have the following grant entry:
  400        *
  401        * <pre>
  402        *   grant {
  403        *     permission Foo "foobar", signedBy "FooSoft";
  404        *   }
  405        * </pre>
  406        *
  407        * <p>Then this permission of type <i>Foo</i> is granted if the
  408        * <code>Foo.class</code> permission has been signed by the
  409        * "FooSoft" alias, or if <code>Foo.class</code> is a
  410        * system class (i.e., is found on the CLASSPATH).
  411        *
  412        * <p>Items that appear in an entry must appear in the specified order
  413        * (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
  414        * "<i>action</i>"). An entry is terminated with a semicolon.
  415        *
  416        * <p>Case is unimportant for the identifiers (<code>permission</code>,
  417        * <code>signedBy</code>, <code>codeBase</code>, etc.) but is
  418        * significant for the <i>Type</i>
  419        * or for any string that is passed in as a value. <p>
  420        *
  421        * <p>An example of two entries in a policy configuration file is
  422        * <pre>
  423        *   //  if the code is signed by "Duke", grant it read/write to all
  424        *   // files in /tmp.
  425        *
  426        *   grant signedBy "Duke" {
  427        *          permission java.io.FilePermission "/tmp/*", "read,write";
  428        *   };
  429        * <p>
  430        *   // grant everyone the following permission
  431        *
  432        *   grant {
  433        *     permission java.util.PropertyPermission "java.vendor";
  434        *   };
  435        *  </pre>
  436        */
  437       private void init(URL url) {
  438           // Properties are set once for each init(); ignore changes between
  439           // between diff invocations of initPolicyFile(policy, url, info).
  440           String numCacheStr =
  441             AccessController.doPrivileged(new PrivilegedAction<String>() {
  442               public String run() {
  443                   expandProperties = "true".equalsIgnoreCase
  444                       (Security.getProperty("policy.expandProperties"));
  445                   ignoreIdentityScope = "true".equalsIgnoreCase
  446                       (Security.getProperty("policy.ignoreIdentityScope"));
  447                   allowSystemProperties = "true".equalsIgnoreCase
  448                       (Security.getProperty("policy.allowSystemProperty"));
  449                   notUtf8 = "false".equalsIgnoreCase
  450                       (System.getProperty("sun.security.policy.utf8"));
  451                   return System.getProperty("sun.security.policy.numcaches");
  452               }});
  453   
  454           int numCaches;
  455           if (numCacheStr != null) {
  456               try {
  457                   numCaches = Integer.parseInt(numCacheStr);
  458               } catch (NumberFormatException e) {
  459                   numCaches = DEFAULT_CACHE_SIZE;
  460               }
  461           } else {
  462               numCaches = DEFAULT_CACHE_SIZE;
  463           }
  464           // System.out.println("number caches=" + numCaches);
  465           PolicyInfo newInfo = new PolicyInfo(numCaches);
  466           initPolicyFile(newInfo, url);
  467           policyInfo.set(newInfo);
  468       }
  469   
  470       private void initPolicyFile(final PolicyInfo newInfo, final URL url) {
  471   
  472           if (url != null) {
  473   
  474               /**
  475                * If the caller specified a URL via Policy.getInstance,
  476                * we only read from that URL
  477                */
  478   
  479               if (debug != null) {
  480                   debug.println("reading "+url);
  481               }
  482               AccessController.doPrivileged(new PrivilegedAction<Void>() {
  483                   public Void run() {
  484                       if (init(url, newInfo) == false) {
  485                           // use static policy if all else fails
  486                           initStaticPolicy(newInfo);
  487                       }
  488                       return null;
  489                   }
  490               });
  491   
  492           } else {
  493   
  494               /**
  495                * Caller did not specify URL via Policy.getInstance.
  496                * Read from URLs listed in the java.security properties file.
  497                *
  498                * We call initPolicyFile with POLICY , POLICY_URL and then
  499                * call it with AUTH_POLICY and AUTH_POLICY_URL
  500                * So first we will process the JAVA standard policy
  501                * and then process the JAVA AUTH Policy.
  502                * This is for backward compatibility as well as to handle
  503                * cases where the user has a single unified policyfile
  504                * with both java policy entries and auth entries
  505                */
  506   
  507               boolean loaded_one = initPolicyFile(POLICY, POLICY_URL, newInfo);
  508               // To maintain strict backward compatibility
  509               // we load the static policy only if POLICY load failed
  510               if (!loaded_one) {
  511                   // use static policy if all else fails
  512                   initStaticPolicy(newInfo);
  513               }
  514   
  515               initPolicyFile(AUTH_POLICY, AUTH_POLICY_URL, newInfo);
  516           }
  517       }
  518   
  519       private boolean initPolicyFile(final String propname, final String urlname,
  520                                   final PolicyInfo newInfo) {
  521           Boolean loadedPolicy =
  522               AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
  523               public Boolean run() {
  524                   boolean loaded_policy = false;
  525   
  526                   if (allowSystemProperties) {
  527                       String extra_policy = System.getProperty(propname);
  528                       if (extra_policy != null) {
  529                           boolean overrideAll = false;
  530                           if (extra_policy.startsWith("=")) {
  531                               overrideAll = true;
  532                               extra_policy = extra_policy.substring(1);
  533                           }
  534                           try {
  535                               extra_policy =
  536                                   PropertyExpander.expand(extra_policy);
  537                               URL policyURL;
  538   
  539                               File policyFile = new File(extra_policy);
  540                               if (policyFile.exists()) {
  541                                   policyURL = ParseUtil.fileToEncodedURL
  542                                       (new File(policyFile.getCanonicalPath()));
  543                               } else {
  544                                   policyURL = new URL(extra_policy);
  545                               }
  546                               if (debug != null)
  547                                   debug.println("reading "+policyURL);
  548                               if (init(policyURL, newInfo))
  549                                   loaded_policy = true;
  550                           } catch (Exception e) {
  551                               // ignore.
  552                               if (debug != null) {
  553                                   debug.println("caught exception: "+e);
  554                               }
  555                           }
  556                           if (overrideAll) {
  557                               if (debug != null) {
  558                                   debug.println("overriding other policies!");
  559                               }
  560                               return Boolean.valueOf(loaded_policy);
  561                           }
  562                       }
  563                   }
  564   
  565                   int n = 1;
  566                   String policy_uri;
  567   
  568                   while ((policy_uri = Security.getProperty(urlname+n)) != null) {
  569                       try {
  570                           URL policy_url = null;
  571                           String expanded_uri = PropertyExpander.expand
  572                                   (policy_uri).replace(File.separatorChar, '/');
  573   
  574                           if (policy_uri.startsWith("file:${java.home}/") ||
  575                               policy_uri.startsWith("file:${user.home}/")) {
  576   
  577                               // this special case accommodates
  578                               // the situation java.home/user.home
  579                               // expand to a single slash, resulting in
  580                               // a file://foo URI
  581                               policy_url = new File
  582                                   (expanded_uri.substring(5)).toURI().toURL();
  583                           } else {
  584                               policy_url = new URI(expanded_uri).toURL();
  585                           }
  586   
  587                           if (debug != null)
  588                               debug.println("reading "+policy_url);
  589                           if (init(policy_url, newInfo))
  590                               loaded_policy = true;
  591                       } catch (Exception e) {
  592                           if (debug != null) {
  593                               debug.println("error reading policy "+e);
  594                               e.printStackTrace();
  595                           }
  596                           // ignore that policy
  597                       }
  598                       n++;
  599                   }
  600                   return Boolean.valueOf(loaded_policy);
  601               }
  602           });
  603   
  604           return loadedPolicy.booleanValue();
  605       }
  606   
  607       /**
  608        * Reads a policy configuration into the Policy object using a
  609        * Reader object.
  610        *
  611        * @param policyFile the policy Reader object.
  612        */
  613       private boolean init(URL policy, PolicyInfo newInfo) {
  614           boolean success = false;
  615           PolicyParser pp = new PolicyParser(expandProperties);
  616           InputStreamReader isr = null;
  617           try {
  618   
  619               // read in policy using UTF-8 by default
  620               //
  621               // check non-standard system property to see if
  622               // the default encoding should be used instead
  623   
  624               if (notUtf8) {
  625                   isr = new InputStreamReader
  626                                   (PolicyUtil.getInputStream(policy));
  627               } else {
  628                   isr = new InputStreamReader
  629                                   (PolicyUtil.getInputStream(policy), "UTF-8");
  630               }
  631   
  632               pp.read(isr);
  633   
  634               KeyStore keyStore = null;
  635               try {
  636                   keyStore = PolicyUtil.getKeyStore
  637                                   (policy,
  638                                   pp.getKeyStoreUrl(),
  639                                   pp.getKeyStoreType(),
  640                                   pp.getKeyStoreProvider(),
  641                                   pp.getStorePassURL(),
  642                                   debug);
  643               } catch (Exception e) {
  644                   // ignore, treat it like we have no keystore
  645                   if (debug != null) {
  646                       e.printStackTrace();
  647                   }
  648               }
  649   
  650               Enumeration<PolicyParser.GrantEntry> enum_ = pp.grantElements();
  651               while (enum_.hasMoreElements()) {
  652                   PolicyParser.GrantEntry ge = enum_.nextElement();
  653                   addGrantEntry(ge, keyStore, newInfo);
  654               }
  655           } catch (PolicyParser.ParsingException pe) {
  656               MessageFormat form = new MessageFormat(ResourcesMgr.getString
  657                   (POLICY + ": error parsing policy:\n\tmessage"));
  658               Object[] source = {policy, pe.getLocalizedMessage()};
  659               System.err.println(form.format(source));
  660               if (debug != null)
  661                   pe.printStackTrace();
  662   
  663           } catch (Exception e) {
  664               if (debug != null) {
  665                   debug.println("error parsing "+policy);
  666                   debug.println(e.toString());
  667                   e.printStackTrace();
  668               }
  669           } finally {
  670               if (isr != null) {
  671                   try {
  672                       isr.close();
  673                       success = true;
  674                   } catch (IOException e) {
  675                       // ignore the exception
  676                   }
  677               } else {
  678                   success = true;
  679               }
  680           }
  681   
  682           return success;
  683       }
  684   
  685       private void initStaticPolicy(final PolicyInfo newInfo) {
  686           AccessController.doPrivileged(new PrivilegedAction<Void>() {
  687               public Void run() {
  688                   PolicyEntry pe = new PolicyEntry(new CodeSource(null,
  689                       (Certificate[]) null));
  690                   pe.add(SecurityConstants.LOCAL_LISTEN_PERMISSION);
  691                   pe.add(new PropertyPermission("java.version",
  692                       SecurityConstants.PROPERTY_READ_ACTION));
  693                   pe.add(new PropertyPermission("java.vendor",
  694                       SecurityConstants.PROPERTY_READ_ACTION));
  695                   pe.add(new PropertyPermission("java.vendor.url",
  696                       SecurityConstants.PROPERTY_READ_ACTION));
  697                   pe.add(new PropertyPermission("java.class.version",
  698                       SecurityConstants.PROPERTY_READ_ACTION));
  699                   pe.add(new PropertyPermission("os.name",
  700                       SecurityConstants.PROPERTY_READ_ACTION));
  701                   pe.add(new PropertyPermission("os.version",
  702                       SecurityConstants.PROPERTY_READ_ACTION));
  703                   pe.add(new PropertyPermission("os.arch",
  704                       SecurityConstants.PROPERTY_READ_ACTION));
  705                   pe.add(new PropertyPermission("file.separator",
  706                       SecurityConstants.PROPERTY_READ_ACTION));
  707                   pe.add(new PropertyPermission("path.separator",
  708                       SecurityConstants.PROPERTY_READ_ACTION));
  709                   pe.add(new PropertyPermission("line.separator",
  710                       SecurityConstants.PROPERTY_READ_ACTION));
  711                   pe.add(new PropertyPermission
  712                                   ("java.specification.version",
  713                                       SecurityConstants.PROPERTY_READ_ACTION));
  714                   pe.add(new PropertyPermission
  715                                   ("java.specification.vendor",
  716                                       SecurityConstants.PROPERTY_READ_ACTION));
  717                   pe.add(new PropertyPermission
  718                                   ("java.specification.name",
  719                                       SecurityConstants.PROPERTY_READ_ACTION));
  720                   pe.add(new PropertyPermission
  721                                   ("java.vm.specification.version",
  722                                       SecurityConstants.PROPERTY_READ_ACTION));
  723                   pe.add(new PropertyPermission
  724                                   ("java.vm.specification.vendor",
  725                                       SecurityConstants.PROPERTY_READ_ACTION));
  726                   pe.add(new PropertyPermission
  727                                   ("java.vm.specification.name",
  728                                       SecurityConstants.PROPERTY_READ_ACTION));
  729                   pe.add(new PropertyPermission("java.vm.version",
  730                       SecurityConstants.PROPERTY_READ_ACTION));
  731                   pe.add(new PropertyPermission("java.vm.vendor",
  732                       SecurityConstants.PROPERTY_READ_ACTION));
  733                   pe.add(new PropertyPermission("java.vm.name",
  734                       SecurityConstants.PROPERTY_READ_ACTION));
  735   
  736                   // No need to sync because noone has access to newInfo yet
  737                   newInfo.policyEntries.add(pe);
  738   
  739                   // Add AllPermissions for standard extensions
  740                   String[] extCodebases = PolicyParser.parseExtDirs(
  741                       PolicyParser.EXTDIRS_EXPANSION, 0);
  742                   if (extCodebases != null && extCodebases.length > 0) {
  743                       for (int i = 0; i < extCodebases.length; i++) {
  744                           try {
  745                               pe = new PolicyEntry(canonicalizeCodebase(
  746                                   new CodeSource(new URL(extCodebases[i]),
  747                                       (Certificate[]) null), false ));
  748                               pe.add(SecurityConstants.ALL_PERMISSION);
  749   
  750                               // No need to sync because noone has access to
  751                               // newInfo yet
  752                               newInfo.policyEntries.add(pe);
  753                           } catch (Exception e) {
  754                               // this is probably bad (though not dangerous).
  755                               // What should we do?
  756                           }
  757                       }
  758                   }
  759                   return null;
  760               }
  761           });
  762       }
  763   
  764       /**
  765        * Given a GrantEntry, create a codeSource.
  766        *
  767        * @return null if signedBy alias is not recognized
  768        */
  769       private CodeSource getCodeSource(PolicyParser.GrantEntry ge, KeyStore keyStore,
  770           PolicyInfo newInfo) throws java.net.MalformedURLException
  771       {
  772           Certificate[] certs = null;
  773           if (ge.signedBy != null) {
  774               certs = getCertificates(keyStore, ge.signedBy, newInfo);
  775               if (certs == null) {
  776                   // we don't have a key for this alias,
  777                   // just return
  778                   if (debug != null) {
  779                       debug.println("  -- No certs for alias '" +
  780                                          ge.signedBy + "' - ignoring entry");
  781                   }
  782                   return null;
  783               }
  784           }
  785   
  786           URL location;
  787   
  788           if (ge.codeBase != null)
  789               location = new URL(ge.codeBase);
  790           else
  791               location = null;
  792   
  793           return (canonicalizeCodebase(new CodeSource(location, certs),false));
  794       }
  795   
  796       /**
  797        * Add one policy entry to the list.
  798        */
  799       private void addGrantEntry(PolicyParser.GrantEntry ge,
  800                                  KeyStore keyStore, PolicyInfo newInfo) {
  801   
  802           if (debug != null) {
  803               debug.println("Adding policy entry: ");
  804               debug.println("  signedBy " + ge.signedBy);
  805               debug.println("  codeBase " + ge.codeBase);
  806               if (ge.principals != null && ge.principals.size() > 0) {
  807                   ListIterator<PolicyParser.PrincipalEntry> li =
  808                                                   ge.principals.listIterator();
  809                   while (li.hasNext()) {
  810                       PolicyParser.PrincipalEntry pppe = li.next();
  811                   debug.println("  " + pppe.toString());
  812                   }
  813               }
  814           }
  815   
  816           try {
  817               CodeSource codesource = getCodeSource(ge, keyStore, newInfo);
  818               // skip if signedBy alias was unknown...
  819               if (codesource == null) return;
  820   
  821               // perform keystore alias principal replacement.
  822               // for example, if alias resolves to X509 certificate,
  823               // replace principal with:  <X500Principal class>  <SubjectDN>
  824               // -- skip if alias is unknown
  825               if (replacePrincipals(ge.principals, keyStore) == false)
  826                   return;
  827               PolicyEntry entry = new PolicyEntry(codesource, ge.principals);
  828               Enumeration<PolicyParser.PermissionEntry> enum_ =
  829                                                   ge.permissionElements();
  830               while (enum_.hasMoreElements()) {
  831                   PolicyParser.PermissionEntry pe = enum_.nextElement();
  832   
  833                   try {
  834                       // perform ${{ ... }} expansions within permission name
  835                       expandPermissionName(pe, keyStore);
  836   
  837                       // XXX special case PrivateCredentialPermission-SELF
  838                       Permission perm;
  839                       if (pe.permission.equals
  840                           ("javax.security.auth.PrivateCredentialPermission") &&
  841                           pe.name.endsWith(" self")) {
  842                           pe.name = pe.name.substring(0, pe.name.indexOf("self"))
  843                                   + SELF;
  844                       }
  845                       // check for self
  846                       if (pe.name != null && pe.name.indexOf(SELF) != -1) {
  847                           // Create a "SelfPermission" , it could be an
  848                           // an unresolved permission which will be resolved
  849                           // when implies is called
  850                           // Add it to entry
  851                           Certificate certs[];
  852                           if (pe.signedBy != null) {
  853                               certs = getCertificates(keyStore,
  854                                                       pe.signedBy,
  855                                                       newInfo);
  856                           } else {
  857                               certs = null;
  858                           }
  859                           perm = new SelfPermission(pe.permission,
  860                                                     pe.name,
  861                                                     pe.action,
  862                                                     certs);
  863                       } else {
  864                           perm = getInstance(pe.permission,
  865                                              pe.name,
  866                                              pe.action);
  867                       }
  868                       entry.add(perm);
  869                       if (debug != null) {
  870                           debug.println("  "+perm);
  871                       }
  872                   } catch (ClassNotFoundException cnfe) {
  873                       Certificate certs[];
  874                       if (pe.signedBy != null) {
  875                           certs = getCertificates(keyStore,
  876                                                   pe.signedBy,
  877                                                   newInfo);
  878                       } else {
  879                           certs = null;
  880                       }
  881   
  882                       // only add if we had no signer or we had a
  883                       // a signer and found the keys for it.
  884                       if (certs != null || pe.signedBy == null) {
  885                           Permission perm = new UnresolvedPermission(
  886                                                     pe.permission,
  887                                                     pe.name,
  888                                                     pe.action,
  889                                                     certs);
  890                           entry.add(perm);
  891                           if (debug != null) {
  892                               debug.println("  "+perm);
  893                           }
  894                       }
  895                   } catch (java.lang.reflect.InvocationTargetException ite) {
  896                       MessageFormat form = new MessageFormat
  897                           (ResourcesMgr.getString
  898                            (POLICY +
  899                             ": error adding Permission, perm:\n\tmessage"));
  900                       Object[] source = {pe.permission,
  901                                          ite.getTargetException().toString()};
  902                       System.err.println(form.format(source));
  903                   } catch (Exception e) {
  904                       MessageFormat form = new MessageFormat
  905                           (ResourcesMgr.getString
  906                            (POLICY +
  907                             ": error adding Permission, perm:\n\tmessage"));
  908                       Object[] source = {pe.permission,
  909                                          e.toString()};
  910                       System.err.println(form.format(source));
  911                   }
  912               }
  913   
  914               // No need to sync because noone has access to newInfo yet
  915               newInfo.policyEntries.add(entry);
  916           } catch (Exception e) {
  917               MessageFormat form = new MessageFormat(ResourcesMgr.getString
  918                                            (POLICY
  919                                            + ": error adding Entry:\n\tmessage"));
  920               Object[] source = {e.toString()};
  921               System.err.println(form.format(source));
  922           }
  923           if (debug != null)
  924               debug.println();
  925       }
  926   
  927       /**
  928        * Returns a new Permission object of the given Type. The Permission is
  929        * created by getting the
  930        * Class object using the <code>Class.forName</code> method, and using
  931        * the reflection API to invoke the (String name, String actions)
  932        * constructor on the
  933        * object.
  934        *
  935        * @param type the type of Permission being created.
  936        * @param name the name of the Permission being created.
  937        * @param actions the actions of the Permission being created.
  938        *
  939        * @exception  ClassNotFoundException  if the particular Permission
  940        *             class could not be found.
  941        *
  942        * @exception  IllegalAccessException  if the class or initializer is
  943        *               not accessible.
  944        *
  945        * @exception  InstantiationException  if getInstance tries to
  946        *               instantiate an abstract class or an interface, or if the
  947        *               instantiation fails for some other reason.
  948        *
  949        * @exception  NoSuchMethodException if the (String, String) constructor
  950        *               is not found.
  951        *
  952        * @exception  InvocationTargetException if the underlying Permission
  953        *               constructor throws an exception.
  954        *
  955        */
  956   
  957       private static final Permission getInstance(String type,
  958                                       String name,
  959                                       String actions)
  960           throws ClassNotFoundException,
  961                  InstantiationException,
  962                  IllegalAccessException,
  963                  NoSuchMethodException,
  964                  InvocationTargetException
  965       {
  966           //XXX we might want to keep a hash of created factories...
  967           Class<?> pc = Class.forName(type);
  968           Permission answer = getKnownInstance(pc, name, actions);
  969           if (answer != null) {
  970               return answer;
  971           }
  972   
  973           if (name == null && actions == null) {
  974               try {
  975                   Constructor<?> c = pc.getConstructor(PARAMS0);
  976                   return (Permission) c.newInstance(new Object[] {});
  977               } catch (NoSuchMethodException ne) {
  978                   try {
  979                       Constructor<?> c = pc.getConstructor(PARAMS1);
  980                       return (Permission) c.newInstance(
  981                                 new Object[] { name});
  982                   } catch (NoSuchMethodException ne1 ) {
  983                       Constructor<?> c = pc.getConstructor(PARAMS2);
  984                       return (Permission) c.newInstance(
  985                           new Object[] { name, actions });
  986                   }
  987               }
  988           } else {
  989               if (name != null && actions == null) {
  990                   try {
  991                       Constructor<?> c = pc.getConstructor(PARAMS1);
  992                       return (Permission) c.newInstance(new Object[] { name});
  993                   } catch (NoSuchMethodException ne) {
  994                       Constructor<?> c = pc.getConstructor(PARAMS2);
  995                       return (Permission) c.newInstance(
  996                             new Object[] { name, actions });
  997                   }
  998               } else {
  999                   Constructor<?> c = pc.getConstructor(PARAMS2);
 1000                   return (Permission) c.newInstance(
 1001                         new Object[] { name, actions });
 1002                }
 1003           }
 1004       }
 1005   
 1006       /**
 1007        * Creates one of the well-known permissions directly instead of
 1008        * via reflection. Keep list short to not penalize non-JDK-defined
 1009        * permissions.
 1010        */
 1011       private static final Permission getKnownInstance(Class claz,
 1012           String name, String actions) {
 1013           // XXX shorten list to most popular ones?
 1014           if (claz.equals(FilePermission.class)) {
 1015               return new FilePermission(name, actions);
 1016           } else if (claz.equals(SocketPermission.class)) {
 1017               return new SocketPermission(name, actions);
 1018           } else if (claz.equals(RuntimePermission.class)) {
 1019               return new RuntimePermission(name, actions);
 1020           } else if (claz.equals(PropertyPermission.class)) {
 1021               return new PropertyPermission(name, actions);
 1022           } else if (claz.equals(NetPermission.class)) {
 1023               return new NetPermission(name, actions);
 1024           } else if (claz.equals(AllPermission.class)) {
 1025               return SecurityConstants.ALL_PERMISSION;
 1026           } else if (claz.equals(AWTPermission.class)) {
 1027               return new AWTPermission(name, actions);
 1028   /*
 1029           } else if (claz.equals(ReflectPermission.class)) {
 1030               return new ReflectPermission(name, actions);
 1031           } else if (claz.equals(SecurityPermission.class)) {
 1032               return new SecurityPermission(name, actions);
 1033           } else if (claz.equals(PrivateCredentialPermission.class)) {
 1034               return new PrivateCredentialPermission(name, actions);
 1035           } else if (claz.equals(AuthPermission.class)) {
 1036               return new AuthPermission(name, actions);
 1037           } else if (claz.equals(ServicePermission.class)) {
 1038               return new ServicePermission(name, actions);
 1039           } else if (claz.equals(DelegationPermission.class)) {
 1040               return new DelegationPermission(name, actions);
 1041           } else if (claz.equals(SerializablePermission.class)) {
 1042               return new SerializablePermission(name, actions);
 1043           } else if (claz.equals(AudioPermission.class)) {
 1044               return new AudioPermission(name, actions);
 1045           } else if (claz.equals(SSLPermission.class)) {
 1046               return new SSLPermission(name, actions);
 1047           } else if (claz.equals(LoggingPermission.class)) {
 1048               return new LoggingPermission(name, actions);
 1049           } else if (claz.equals(SQLPermission.class)) {
 1050               return new SQLPermission(name, actions);
 1051   */
 1052           } else {
 1053               return null;
 1054           }
 1055       }
 1056   
 1057       /**
 1058        * Fetch all certs associated with this alias.
 1059        */
 1060       private Certificate[] getCertificates
 1061                   (KeyStore keyStore, String aliases, PolicyInfo newInfo) {
 1062   
 1063           List<Certificate> vcerts = null;
 1064   
 1065           StringTokenizer st = new StringTokenizer(aliases, ",");
 1066           int n = 0;
 1067   
 1068           while (st.hasMoreTokens()) {
 1069               String alias = st.nextToken().trim();
 1070               n++;
 1071               Certificate cert = null;
 1072               // See if this alias's cert has already been cached
 1073               synchronized (newInfo.aliasMapping) {
 1074                   cert = (Certificate)newInfo.aliasMapping.get(alias);
 1075   
 1076                   if (cert == null && keyStore != null) {
 1077   
 1078                       try {
 1079                           cert = keyStore.getCertificate(alias);
 1080                       } catch (KeyStoreException kse) {
 1081                           // never happens, because keystore has already been loaded
 1082                           // when we call this
 1083                       }
 1084                       if (cert != null) {
 1085                           newInfo.aliasMapping.put(alias, cert);
 1086                           newInfo.aliasMapping.put(cert, alias);
 1087                       }
 1088                   }
 1089               }
 1090   
 1091               if (cert != null) {
 1092                   if (vcerts == null)
 1093                       vcerts = new ArrayList<Certificate>();
 1094                   vcerts.add(cert);
 1095               }
 1096           }
 1097   
 1098           // make sure n == vcerts.size, since we are doing a logical *and*
 1099           if (vcerts != null && n == vcerts.size()) {
 1100               Certificate[] certs = new Certificate[vcerts.size()];
 1101               vcerts.toArray(certs);
 1102               return certs;
 1103           } else {
 1104               return null;
 1105           }
 1106       }
 1107   
 1108       /**
 1109        * Refreshes the policy object by re-reading all the policy files.
 1110        */
 1111       public void refresh() {
 1112           init(url);
 1113       }
 1114   
 1115       /**
 1116        * Evaluates the the global policy for the permissions granted to
 1117        * the ProtectionDomain and tests whether the permission is
 1118        * granted.
 1119        *
 1120        * @param domain the ProtectionDomain to test
 1121        * @param permission the Permission object to be tested for implication.
 1122        *
 1123        * @return true if "permission" is a proper subset of a permission
 1124        * granted to this ProtectionDomain.
 1125        *
 1126        * @see java.security.ProtectionDomain
 1127        */
 1128       public boolean implies(ProtectionDomain pd, Permission p) {
 1129           PolicyInfo pi = policyInfo.get();
 1130           Map<ProtectionDomain, PermissionCollection> pdMap = pi.getPdMapping();
 1131   
 1132           PermissionCollection pc = pdMap.get(pd);
 1133   
 1134           if (pc != null) {
 1135               return pc.implies(p);
 1136           }
 1137   
 1138           pc = getPermissions(pd);
 1139           if (pc == null) {
 1140               return false;
 1141           }
 1142   
 1143           // cache mapping of protection domain to its PermissionCollection
 1144           pdMap.put(pd, pc);
 1145           return pc.implies(p);
 1146       }
 1147   
 1148       /**
 1149        * Examines this <code>Policy</code> and returns the permissions granted
 1150        * to the specified <code>ProtectionDomain</code>.  This includes
 1151        * the permissions currently associated with the domain as well
 1152        * as the policy permissions granted to the domain's
 1153        * CodeSource, ClassLoader, and Principals.
 1154        *
 1155        * <p> Note that this <code>Policy</code> implementation has
 1156        * special handling for PrivateCredentialPermissions.
 1157        * When this method encounters a <code>PrivateCredentialPermission</code>
 1158        * which specifies "self" as the <code>Principal</code> class and name,
 1159        * it does not add that <code>Permission</code> to the returned
 1160        * <code>PermissionCollection</code>.  Instead, it builds
 1161        * a new <code>PrivateCredentialPermission</code>
 1162        * for each <code>Principal</code> associated with the provided
 1163        * <code>Subject</code>.  Each new <code>PrivateCredentialPermission</code>
 1164        * contains the same Credential class as specified in the
 1165        * originally granted permission, as well as the Class and name
 1166        * for the respective <code>Principal</code>.
 1167        *
 1168        * <p>
 1169        *
 1170        * @param domain the Permissions granted to this
 1171        *          <code>ProtectionDomain</code> are returned.
 1172        *
 1173        * @return the Permissions granted to the provided
 1174        *          <code>ProtectionDomain</code>.
 1175        */
 1176       public PermissionCollection getPermissions(ProtectionDomain domain) {
 1177           Permissions perms = new Permissions();
 1178   
 1179           if (domain == null)
 1180              return perms;
 1181   
 1182           // first get policy perms
 1183           getPermissions(perms, domain);
 1184   
 1185           // add static perms
 1186           //      - adding static perms after policy perms is necessary
 1187           //        to avoid a regression for 4301064
 1188           PermissionCollection pc = domain.getPermissions();
 1189           if (pc != null) {
 1190               synchronized (pc) {
 1191                   Enumeration<Permission> e = pc.elements();
 1192                   while (e.hasMoreElements()) {
 1193                       perms.add(e.nextElement());
 1194                   }
 1195               }
 1196           }
 1197   
 1198           return perms;
 1199       }
 1200   
 1201       /**
 1202        * Examines this Policy and creates a PermissionCollection object with
 1203        * the set of permissions for the specified CodeSource.
 1204        *
 1205        * @param CodeSource the codesource associated with the caller.
 1206        * This encapsulates the original location of the code (where the code
 1207        * came from) and the public key(s) of its signer.
 1208        *
 1209        * @return the set of permissions according to the policy.
 1210        */
 1211       public PermissionCollection getPermissions(CodeSource codesource) {
 1212           return getPermissions(new Permissions(), codesource);
 1213       }
 1214   
 1215       /**
 1216        * Examines the global policy and returns the provided Permissions
 1217        * object with additional permissions granted to the specified
 1218        * ProtectionDomain.
 1219        *
 1220        * @param perm the Permissions to populate
 1221        * @param pd the ProtectionDomain associated with the caller.
 1222        *
 1223        * @return the set of Permissions according to the policy.
 1224        */
 1225       private PermissionCollection getPermissions(Permissions perms,
 1226                                           ProtectionDomain pd ) {
 1227           if (debug != null) {
 1228               debug.println("getPermissions:\n\t" + printPD(pd));
 1229           }
 1230   
 1231           final CodeSource cs = pd.getCodeSource();
 1232           if (cs == null)
 1233               return perms;
 1234   
 1235           CodeSource canonCodeSource = AccessController.doPrivileged(
 1236               new java.security.PrivilegedAction<CodeSource>(){
 1237                   public CodeSource run() {
 1238                       return canonicalizeCodebase(cs, true);
 1239                   }
 1240               });
 1241           return getPermissions(perms, canonCodeSource, pd.getPrincipals());
 1242       }
 1243   
 1244       /**
 1245        * Examines the global policy and returns the provided Permissions
 1246        * object with additional permissions granted to the specified
 1247        * CodeSource.
 1248        *
 1249        * @param permissions the permissions to populate
 1250        * @param codesource the codesource associated with the caller.
 1251        * This encapsulates the original location of the code (where the code
 1252        * came from) and the public key(s) of its signer.
 1253        *
 1254        * @return the set of permissions according to the policy.
 1255        */
 1256       private PermissionCollection getPermissions(Permissions perms,
 1257                                  final CodeSource cs) {
 1258   
 1259           CodeSource canonCodeSource = AccessController.doPrivileged(
 1260               new java.security.PrivilegedAction<CodeSource>(){
 1261                   public CodeSource run() {
 1262                       return canonicalizeCodebase(cs, true);
 1263                   }
 1264               });
 1265   
 1266           return getPermissions(perms, canonCodeSource, null);
 1267       }
 1268   
 1269       private Permissions getPermissions(Permissions perms,
 1270                                          final CodeSource cs,
 1271                                          Principal[] principals) {
 1272           PolicyInfo pi = policyInfo.get();
 1273   
 1274           for (PolicyEntry entry : pi.policyEntries) {
 1275               addPermissions(perms, cs, principals, entry);
 1276           }
 1277   
 1278           // Go through policyEntries gotten from identity db; sync required
 1279           // because checkForTrustedIdentity (below) might update list
 1280           synchronized (pi.identityPolicyEntries) {
 1281               for (PolicyEntry entry : pi.identityPolicyEntries) {
 1282                   addPermissions(perms, cs, principals, entry);
 1283               }
 1284           }
 1285   
 1286           // now see if any of the keys are trusted ids.
 1287           if (!ignoreIdentityScope) {
 1288               Certificate certs[] = cs.getCertificates();
 1289               if (certs != null) {
 1290                   for (int k=0; k < certs.length; k++) {
 1291                       Object idMap = pi.aliasMapping.get(certs[k]);
 1292                       if (idMap == null &&
 1293                           checkForTrustedIdentity(certs[k], pi)) {
 1294                           // checkForTrustedIdentity added it
 1295                           // to the policy for us. next time
 1296                           // around we'll find it. This time
 1297                           // around we need to add it.
 1298                           perms.add(SecurityConstants.ALL_PERMISSION);
 1299                       }
 1300                   }
 1301               }
 1302           }
 1303           return perms;
 1304       }
 1305   
 1306       private void addPermissions(Permissions perms,
 1307           final CodeSource cs,
 1308           Principal[] principals,
 1309           final PolicyEntry entry) {
 1310   
 1311           if (debug != null) {
 1312               debug.println("evaluate codesources:\n" +
 1313                   "\tPolicy CodeSource: " + entry.getCodeSource() + "\n" +
 1314                   "\tActive CodeSource: " + cs);
 1315           }
 1316   
 1317           // check to see if the CodeSource implies
 1318           Boolean imp = AccessController.doPrivileged
 1319               (new PrivilegedAction<Boolean>() {
 1320               public Boolean run() {
 1321                   return new Boolean(entry.getCodeSource().implies(cs));
 1322               }
 1323           });
 1324           if (!imp.booleanValue()) {
 1325               if (debug != null) {
 1326                   debug.println("evaluation (codesource) failed");
 1327               }
 1328   
 1329               // CodeSource does not imply - return and try next policy entry
 1330               return;
 1331           }
 1332   
 1333           // check to see if the Principals imply
 1334   
 1335           List<PolicyParser.PrincipalEntry> entryPs = entry.getPrincipals();
 1336           if (debug != null) {
 1337               ArrayList<PolicyParser.PrincipalEntry> accPs =
 1338                           new ArrayList<PolicyParser.PrincipalEntry>();
 1339               if (principals != null) {
 1340                   for (int i = 0; i < principals.length; i++) {
 1341                       accPs.add(new PolicyParser.PrincipalEntry
 1342                                           (principals[i].getClass().getName(),
 1343                                           principals[i].getName()));
 1344                   }
 1345               }
 1346               debug.println("evaluate principals:\n" +
 1347                   "\tPolicy Principals: " + entryPs + "\n" +
 1348                   "\tActive Principals: " + accPs);
 1349           }
 1350   
 1351           if (entryPs == null || entryPs.size() == 0) {
 1352   
 1353               // policy entry has no principals -
 1354               // add perms regardless of principals in current ACC
 1355   
 1356               addPerms(perms, principals, entry);
 1357               if (debug != null) {
 1358                   debug.println("evaluation (codesource/principals) passed");
 1359               }
 1360               return;
 1361   
 1362           } else if (principals == null || principals.length == 0) {
 1363   
 1364               // current thread has no principals but this policy entry
 1365               // has principals - perms are not added
 1366   
 1367               if (debug != null) {
 1368                   debug.println("evaluation (principals) failed");
 1369               }
 1370               return;
 1371           }
 1372   
 1373           // current thread has principals and this policy entry
 1374           // has principals.  see if policy entry principals match
 1375           // principals in current ACC
 1376   
 1377           for (int i = 0; i < entryPs.size(); i++) {
 1378               PolicyParser.PrincipalEntry pppe = entryPs.get(i);
 1379   
 1380               // see if principal entry is a PrincipalComparator
 1381   
 1382               try {
 1383                   Class<?> pClass = Class.forName
 1384                                   (pppe.principalClass,
 1385                                   true,
 1386                                   Thread.currentThread().getContextClassLoader());
 1387   
 1388                   if (!PrincipalComparator.class.isAssignableFrom(pClass)) {
 1389   
 1390                       // common case - dealing with regular Principal class.
 1391                       // see if policy entry principal is in current ACC
 1392   
 1393                       if (!checkEntryPs(principals, pppe)) {
 1394                           if (debug != null) {
 1395                               debug.println("evaluation (principals) failed");
 1396                           }
 1397   
 1398                           // policy entry principal not in current ACC -
 1399                           // immediately return and go to next policy entry
 1400                           return;
 1401                       }
 1402   
 1403                   } else {
 1404   
 1405                       // dealing with a PrincipalComparator
 1406   
 1407                       Constructor<?> c = pClass.getConstructor(PARAMS1);
 1408                       PrincipalComparator pc = (PrincipalComparator)c.newInstance
 1409                                           (new Object[] { pppe.principalName });
 1410   
 1411                       if (debug != null) {
 1412                           debug.println("found PrincipalComparator " +
 1413                                           pc.getClass().getName());
 1414                       }
 1415   
 1416                       // check if the PrincipalComparator
 1417                       // implies the current thread's principals
 1418   
 1419                       Set<Principal> pSet =
 1420                                   new HashSet<Principal>(principals.length);
 1421                       for (int j = 0; j < principals.length; j++) {
 1422                           pSet.add(principals[j]);
 1423                       }
 1424                       Subject subject = new Subject(true,
 1425                                                   pSet,
 1426                                                   Collections.EMPTY_SET,
 1427                                                   Collections.EMPTY_SET);
 1428   
 1429                       if (!pc.implies(subject)) {
 1430                           if (debug != null) {
 1431                               debug.println
 1432                                   ("evaluation (principal comparator) failed");
 1433                           }
 1434   
 1435                           // policy principal does not imply the current Subject -
 1436                           // immediately return and go to next policy entry
 1437                           return;
 1438                       }
 1439                   }
 1440               } catch (Exception e) {
 1441                   // fall back to regular principal comparison.
 1442                   // see if policy entry principal is in current ACC
 1443   
 1444                   if (debug != null) {
 1445                       e.printStackTrace();
 1446                   }
 1447   
 1448                   if (!checkEntryPs(principals, pppe)) {
 1449                       if (debug != null) {
 1450                           debug.println("evaluation (principals) failed");
 1451                       }
 1452   
 1453                       // policy entry principal not in current ACC -
 1454                       // immediately return and go to next policy entry
 1455                       return;
 1456                   }
 1457               }
 1458   
 1459               // either the principal information matched,
 1460               // or the PrincipalComparator.implies succeeded.
 1461               // continue loop and test the next policy principal
 1462           }
 1463   
 1464           // all policy entry principals were found in the current ACC -
 1465           // grant the policy permissions
 1466   
 1467           if (debug != null) {
 1468               debug.println("evaluation (codesource/principals) passed");
 1469           }
 1470           addPerms(perms, principals, entry);
 1471       }
 1472   
 1473       private void addPerms(Permissions perms,
 1474                           Principal[] accPs,
 1475                           PolicyEntry entry) {
 1476           for (int i = 0; i < entry.permissions.size(); i++) {
 1477               Permission p = entry.permissions.get(i);
 1478               if (debug != null) {
 1479                   debug.println("  granting " + p);
 1480               }
 1481   
 1482               if (p instanceof SelfPermission) {
 1483                   // handle "SELF" permissions
 1484                   expandSelf((SelfPermission)p,
 1485                           entry.getPrincipals(),
 1486                           accPs,
 1487                           perms);
 1488               } else {
 1489                   perms.add(p);
 1490               }
 1491           }
 1492       }
 1493   
 1494       /**
 1495        * This method returns, true, if the principal in the policy entry,
 1496        * pppe, is part of the current thread's principal array, pList.
 1497        * This method also returns, true, if the policy entry's principal
 1498        * is appropriately wildcarded.
 1499        *
 1500        * Note that the provided <i>pppe</i> argument may have
 1501        * wildcards (*) for both the <code>Principal</code> class and name.
 1502        *
 1503        * @param pList an array of principals from the current thread's
 1504        *          AccessControlContext.
 1505        *
 1506        * @param pppe a Principal specified in a policy grant entry.
 1507        *
 1508        * @return true if the current thread's pList "contains" the
 1509        *          principal in the policy entry, pppe.  This method
 1510        *          also returns true if the policy entry's principal
 1511        *          appropriately wildcarded.
 1512        */
 1513       private boolean checkEntryPs(Principal[] pList,
 1514                                   PolicyParser.PrincipalEntry pppe) {
 1515   
 1516           for (int i = 0; i < pList.length; i++) {
 1517   
 1518               if (pppe.principalClass.equals
 1519                           (PolicyParser.PrincipalEntry.WILDCARD_CLASS) ||
 1520                   pppe.principalClass.equals
 1521                           (pList[i].getClass().getName())) {
 1522   
 1523                   if (pppe.principalName.equals
 1524                           (PolicyParser.PrincipalEntry.WILDCARD_NAME) ||
 1525                       pppe.principalName.equals
 1526                           (pList[i].getName())) {
 1527   
 1528                       return true;
 1529                   }
 1530               }
 1531           }
 1532           return false;
 1533       }
 1534   
 1535       /**
 1536        * <p>
 1537        *
 1538        * @param sp the SelfPermission that needs to be expanded <p>
 1539        *
 1540        * @param entryPs list of principals for the Policy entry.
 1541        *
 1542        * @param pdp Principal array from the current ProtectionDomain.
 1543        *
 1544        * @param perms the PermissionCollection where the individual
 1545        *                  Permissions will be added after expansion.
 1546        */
 1547   
 1548       private void expandSelf(SelfPermission sp,
 1549                               List<PolicyParser.PrincipalEntry> entryPs,
 1550                               Principal[] pdp,
 1551                               Permissions perms) {
 1552   
 1553           if (entryPs == null || entryPs.size() == 0) {
 1554               // No principals in the grant to substitute
 1555               if (debug != null) {
 1556                   debug.println("Ignoring permission "
 1557                                   + sp.getSelfType()
 1558                                   + " with target name ("
 1559                                   + sp.getSelfName() + ").  "
 1560                                   + "No Principal(s) specified "
 1561                                   + "in the grant clause.  "
 1562                                   + "SELF-based target names are "
 1563                                   + "only valid in the context "
 1564                                   + "of a Principal-based grant entry."
 1565                                );
 1566               }
 1567               return;
 1568           }
 1569           int startIndex = 0;
 1570           int v;
 1571           StringBuilder sb = new StringBuilder();
 1572           while ((v = sp.getSelfName().indexOf(SELF, startIndex)) != -1) {
 1573   
 1574               // add non-SELF string
 1575               sb.append(sp.getSelfName().substring(startIndex, v));
 1576   
 1577               // expand SELF
 1578               ListIterator<PolicyParser.PrincipalEntry> pli =
 1579                                                   entryPs.listIterator();
 1580               while (pli.hasNext()) {
 1581                   PolicyParser.PrincipalEntry pppe = pli.next();
 1582                   String[][] principalInfo = getPrincipalInfo(pppe,pdp);
 1583                   for (int i = 0; i < principalInfo.length; i++) {
 1584                       if (i != 0) {
 1585                           sb.append(", ");
 1586                       }
 1587                       sb.append(principalInfo[i][0] + " " +
 1588                           "\"" + principalInfo[i][1] + "\"");
 1589                   }
 1590                   if (pli.hasNext()) {
 1591                       sb.append(", ");
 1592                   }
 1593               }
 1594               startIndex = v + SELF.length();
 1595           }
 1596           // add remaining string (might be the entire string)
 1597           sb.append(sp.getSelfName().substring(startIndex));
 1598   
 1599           if (debug != null) {
 1600               debug.println("  expanded:\n\t" + sp.getSelfName()
 1601                           + "\n  into:\n\t" + sb.toString());
 1602           }
 1603           try {
 1604               // first try to instantiate the permission
 1605               perms.add(getInstance(sp.getSelfType(),
 1606                                   sb.toString(),
 1607                                   sp.getSelfActions()));
 1608           } catch (ClassNotFoundException cnfe) {
 1609               // ok, the permission is not in the bootclasspath.
 1610               // before we add an UnresolvedPermission, check to see
 1611               // whether this perm already belongs to the collection.
 1612               // if so, use that perm's ClassLoader to create a new
 1613               // one.
 1614               Class<?> pc = null;
 1615               synchronized (perms) {
 1616                   Enumeration<Permission> e = perms.elements();
 1617                   while (e.hasMoreElements()) {
 1618                       Permission pElement = e.nextElement();
 1619                       if (pElement.getClass().getName().equals(sp.getSelfType())) {
 1620                           pc = pElement.getClass();
 1621                           break;
 1622                       }
 1623                   }
 1624               }
 1625               if (pc == null) {
 1626                   // create an UnresolvedPermission
 1627                   perms.add(new UnresolvedPermission(sp.getSelfType(),
 1628                                                           sb.toString(),
 1629                                                           sp.getSelfActions(),
 1630                                                           sp.getCerts()));
 1631               } else {
 1632                   try {
 1633                       // we found an instantiated permission.
 1634                       // use its class loader to instantiate a new permission.
 1635                       Constructor<?> c;
 1636                       // name parameter can not be null
 1637                       if (sp.getSelfActions() == null) {
 1638                           try {
 1639                               c = pc.getConstructor(PARAMS1);
 1640                               perms.add((Permission)c.newInstance
 1641                                    (new Object[] {sb.toString()}));
 1642                           } catch (NoSuchMethodException ne) {
 1643                               c = pc.getConstructor(PARAMS2);
 1644                               perms.add((Permission)c.newInstance
 1645                                    (new Object[] {sb.toString(),
 1646                                                   sp.getSelfActions() }));
 1647                           }
 1648                       } else {
 1649                           c = pc.getConstructor(PARAMS2);
 1650                           perms.add((Permission)c.newInstance
 1651                              (new Object[] {sb.toString(),
 1652                                             sp.getSelfActions()}));
 1653                       }
 1654                   } catch (Exception nme) {
 1655                       if (debug != null) {
 1656                           debug.println("self entry expansion " +
 1657                           " instantiation failed: "
 1658                           +  nme.toString());
 1659                       }
 1660                   }
 1661               }
 1662           } catch (Exception e) {
 1663               if (debug != null) {
 1664                   debug.println(e.toString());
 1665               }
 1666           }
 1667       }
 1668   
 1669       /**
 1670        * return the principal class/name pair in the 2D array.
 1671        * array[x][y]:     x corresponds to the array length.
 1672        *                  if (y == 0), it's the principal class.
 1673        *                  if (y == 1), it's the principal name.
 1674        */
 1675       private String[][] getPrincipalInfo
 1676           (PolicyParser.PrincipalEntry pe, Principal[] pdp) {
 1677   
 1678           // there are 3 possibilities:
 1679           // 1) the entry's Principal class and name are not wildcarded
 1680           // 2) the entry's Principal name is wildcarded only
 1681           // 3) the entry's Principal class and name are wildcarded
 1682   
 1683           if (!pe.principalClass.equals
 1684               (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
 1685               !pe.principalName.equals
 1686               (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
 1687   
 1688               // build an info array for the principal
 1689               // from the Policy entry
 1690               String[][] info = new String[1][2];
 1691               info[0][0] = pe.principalClass;
 1692               info[0][1] = pe.principalName;
 1693               return info;
 1694   
 1695           } else if (!pe.principalClass.equals
 1696                      (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
 1697                      pe.principalName.equals
 1698                      (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
 1699   
 1700               // build an info array for every principal
 1701               // in the current domain which has a principal class
 1702               // that is equal to policy entry principal class name
 1703               List<Principal> plist = new ArrayList<Principal>();
 1704               for (int i = 0; i < pdp.length; i++) {
 1705                   if(pe.principalClass.equals(pdp[i].getClass().getName()))
 1706                       plist.add(pdp[i]);
 1707               }
 1708               String[][] info = new String[plist.size()][2];
 1709               int i = 0;
 1710               java.util.Iterator<Principal> pIterator = plist.iterator();
 1711               while (pIterator.hasNext()) {
 1712                   Principal p = pIterator.next();
 1713                   info[i][0] = p.getClass().getName();
 1714                   info[i][1] = p.getName();
 1715                   i++;
 1716               }
 1717               return info;
 1718   
 1719           } else {
 1720   
 1721               // build an info array for every
 1722               // one of the current Domain's principals
 1723   
 1724               String[][] info = new String[pdp.length][2];
 1725   
 1726               for (int i = 0; i < pdp.length; i++) {
 1727                   info[i][0] = pdp[i].getClass().getName();
 1728                   info[i][1] = pdp[i].getName();
 1729               }
 1730               return info;
 1731           }
 1732       }
 1733   
 1734       /*
 1735        * Returns the signer certificates from the list of certificates
 1736        * associated with the given code source.
 1737        *
 1738        * The signer certificates are those certificates that were used
 1739        * to verifysigned code originating from the codesource location.
 1740        *
 1741        * This method assumes that in the given code source, each signer
 1742        * certificate is followed by its supporting certificate chain
 1743        * (which may be empty), and that the signer certificate and its
 1744        * supporting certificate chain are ordered bottom-to-top
 1745        * (i.e., with the signer certificate first and the (root) certificate
 1746        * authority last).
 1747        */
 1748       protected Certificate[] getSignerCertificates(CodeSource cs) {
 1749           Certificate[] certs = null;
 1750           if ((certs = cs.getCertificates()) == null)
 1751               return null;
 1752           for (int i=0; i<certs.length; i++) {
 1753               if (!(certs[i] instanceof X509Certificate))
 1754                   return cs.getCertificates();
 1755           }
 1756   
 1757           // Do we have to do anything?
 1758           int i = 0;
 1759           int count = 0;
 1760           while (i < certs.length) {
 1761               count++;
 1762               while (((i+1) < certs.length)
 1763                      && ((X509Certificate)certs[i]).getIssuerDN().equals(
 1764                              ((X509Certificate)certs[i+1]).getSubjectDN())) {
 1765                   i++;
 1766               }
 1767               i++;
 1768           }
 1769           if (count == certs.length)
 1770               // Done
 1771               return certs;
 1772   
 1773           ArrayList<Certificate> userCertList = new ArrayList<Certificate>();
 1774           i = 0;
 1775           while (i < certs.length) {
 1776               userCertList.add(certs[i]);
 1777               while (((i+1) < certs.length)
 1778                      && ((X509Certificate)certs[i]).getIssuerDN().equals(
 1779                              ((X509Certificate)certs[i+1]).getSubjectDN())) {
 1780                   i++;
 1781               }
 1782               i++;
 1783           }
 1784           Certificate[] userCerts = new Certificate[userCertList.size()];
 1785           userCertList.toArray(userCerts);
 1786           return userCerts;
 1787       }
 1788   
 1789       private CodeSource canonicalizeCodebase(CodeSource cs,
 1790                                               boolean extractSignerCerts) {
 1791   
 1792           String path = null;
 1793   
 1794           CodeSource canonCs = cs;
 1795           URL u = cs.getLocation();
 1796           if (u != null && u.getProtocol().equals("file")) {
 1797               boolean isLocalFile = false;
 1798               String host = u.getHost();
 1799               isLocalFile = (host == null || host.equals("") ||
 1800                   host.equals("~") || host.equalsIgnoreCase("localhost"));
 1801   
 1802               if (isLocalFile) {
 1803                   path = u.getFile().replace('/', File.separatorChar);
 1804                   path = ParseUtil.decode(path);
 1805               }
 1806           }
 1807   
 1808           if (path != null) {
 1809               try {
 1810                   URL csUrl = null;
 1811                   path = canonPath(path);
 1812                   csUrl = ParseUtil.fileToEncodedURL(new File(path));
 1813   
 1814                   if (extractSignerCerts) {
 1815                       canonCs = new CodeSource(csUrl,
 1816                                                getSignerCertificates(cs));
 1817                   } else {
 1818                       canonCs = new CodeSource(csUrl,
 1819                                                cs.getCertificates());
 1820                   }
 1821               } catch (IOException ioe) {
 1822                   // leave codesource as it is, unless we have to extract its
 1823                   // signer certificates
 1824                   if (extractSignerCerts) {
 1825                       canonCs = new CodeSource(cs.getLocation(),
 1826                                                getSignerCertificates(cs));
 1827                   }
 1828               }
 1829           } else {
 1830               if (extractSignerCerts) {
 1831                   canonCs = new CodeSource(cs.getLocation(),
 1832                                            getSignerCertificates(cs));
 1833               }
 1834           }
 1835           return canonCs;
 1836       }
 1837   
 1838       // public for java.io.FilePermission
 1839       public static String canonPath(String path) throws IOException {
 1840           if (path.endsWith("*")) {
 1841               path = path.substring(0, path.length()-1) + "-";
 1842               path = new File(path).getCanonicalPath();
 1843               return path.substring(0, path.length()-1) + "*";
 1844           } else {
 1845               return new File(path).getCanonicalPath();
 1846           }
 1847       }
 1848   
 1849       private String printPD(ProtectionDomain pd) {
 1850           Principal[] principals = pd.getPrincipals();
 1851           String pals = "<no principals>";
 1852           if (principals != null && principals.length > 0) {
 1853               StringBuilder palBuf = new StringBuilder("(principals ");
 1854               for (int i = 0; i < principals.length; i++) {
 1855                   palBuf.append(principals[i].getClass().getName() +
 1856                                 " \"" + principals[i].getName() +
 1857                                 "\"");
 1858                   if (i < principals.length-1)
 1859                       palBuf.append(", ");
 1860                   else
 1861                       palBuf.append(")");
 1862               }
 1863               pals = palBuf.toString();
 1864           }
 1865           return "PD CodeSource: "
 1866                   + pd.getCodeSource()
 1867                   +"\n\t" + "PD ClassLoader: "
 1868                   + pd.getClassLoader()
 1869                   +"\n\t" + "PD Principals: "
 1870                   + pals;
 1871       }
 1872   
 1873       /**
 1874        * return true if no replacement was performed,
 1875        * or if replacement succeeded.
 1876        */
 1877       private boolean replacePrincipals(
 1878           List<PolicyParser.PrincipalEntry> principals, KeyStore keystore) {
 1879   
 1880           if (principals == null || principals.size() == 0 || keystore == null)
 1881               return true;
 1882   
 1883           ListIterator<PolicyParser.PrincipalEntry> i = principals.listIterator();
 1884           while (i.hasNext()) {
 1885               PolicyParser.PrincipalEntry pppe = i.next();
 1886               if (pppe.principalClass.equals(PolicyParser.REPLACE_NAME)) {
 1887   
 1888                   // perform replacement
 1889                   // (only X509 replacement is possible now)
 1890                   String name;
 1891                   if ((name = getDN(pppe.principalName, keystore)) == null) {
 1892                       return false;
 1893                   }
 1894   
 1895                   if (debug != null) {
 1896                       debug.println("  Replacing \"" +
 1897                           pppe.principalName +
 1898                           "\" with " +
 1899                           X500PRINCIPAL + "/\"" +
 1900                           name +
 1901                           "\"");
 1902                   }
 1903   
 1904                   pppe.principalClass = X500PRINCIPAL;
 1905                   pppe.principalName = name;
 1906               }
 1907           }
 1908           // return true if no replacement was performed,
 1909           // or if replacement succeeded
 1910           return true;
 1911       }
 1912   
 1913       private void expandPermissionName(PolicyParser.PermissionEntry pe,
 1914                                           KeyStore keystore) throws Exception {
 1915           // short cut the common case
 1916           if (pe.name == null || pe.name.indexOf("${{", 0) == -1) {
 1917               return;
 1918           }
 1919   
 1920           int startIndex = 0;
 1921           int b, e;
 1922           StringBuilder sb = new StringBuilder();
 1923           while ((b = pe.name.indexOf("${{", startIndex)) != -1) {
 1924               e = pe.name.indexOf("}}", b);
 1925               if (e < 1) {
 1926                   break;
 1927               }
 1928               sb.append(pe.name.substring(startIndex, b));
 1929   
 1930               // get the value in ${{...}}
 1931               String value = pe.name.substring(b+3, e);
 1932   
 1933               // parse up to the first ':'
 1934               int colonIndex;
 1935               String prefix = value;
 1936               String suffix;
 1937               if ((colonIndex = value.indexOf(":")) != -1) {
 1938                   prefix = value.substring(0, colonIndex);
 1939               }
 1940   
 1941               // handle different prefix possibilities
 1942               if (prefix.equalsIgnoreCase("self")) {
 1943                   // do nothing - handled later
 1944                   sb.append(pe.name.substring(b, e+2));
 1945                   startIndex = e+2;
 1946                   continue;
 1947               } else if (prefix.equalsIgnoreCase("alias")) {
 1948                   // get the suffix and perform keystore alias replacement
 1949                   if (colonIndex == -1) {
 1950                       MessageFormat form = new MessageFormat
 1951                           (ResourcesMgr.getString
 1952                           ("alias name not provided (pe.name)"));
 1953                       Object[] source = {pe.name};
 1954                       throw new Exception(form.format(source));
 1955                   }
 1956                   suffix = value.substring(colonIndex+1);
 1957                   if ((suffix = getDN(suffix, keystore)) == null) {
 1958                       MessageFormat form = new MessageFormat
 1959                           (ResourcesMgr.getString
 1960                           ("unable to perform substitution on alias, suffix"));
 1961                       Object[] source = {value.substring(colonIndex+1)};
 1962                       throw new Exception(form.format(source));
 1963                   }
 1964   
 1965                   sb.append(X500PRINCIPAL + " \"" + suffix + "\"");
 1966                   startIndex = e+2;
 1967               } else {
 1968                   MessageFormat form = new MessageFormat
 1969                           (ResourcesMgr.getString
 1970                           ("substitution value, prefix, unsupported"));
 1971                   Object[] source = {prefix};
 1972                   throw new Exception(form.format(source));
 1973               }
 1974           }
 1975   
 1976           // copy the rest of the value
 1977           sb.append(pe.name.substring(startIndex));
 1978   
 1979           // replace the name with expanded value
 1980           if (debug != null) {
 1981               debug.println("  Permission name expanded from:\n\t" +
 1982                           pe.name + "\nto\n\t" + sb.toString());
 1983           }
 1984           pe.name = sb.toString();
 1985       }
 1986   
 1987       private String getDN(String alias, KeyStore keystore) {
 1988           Certificate cert = null;
 1989           try {
 1990               cert = keystore.getCertificate(alias);
 1991           } catch (Exception e) {
 1992               if (debug != null) {
 1993                   debug.println("  Error retrieving certificate for '" +
 1994                                   alias +
 1995                                   "': " +
 1996                                   e.toString());
 1997               }
 1998               return null;
 1999           }
 2000   
 2001           if (cert == null || !(cert instanceof X509Certificate)) {
 2002               if (debug != null) {
 2003                   debug.println("  -- No certificate for '" +
 2004                                   alias +
 2005                                   "' - ignoring entry");
 2006               }
 2007               return null;
 2008           } else {
 2009               X509Certificate x509Cert = (X509Certificate)cert;
 2010   
 2011               // 4702543:  X500 names with an EmailAddress
 2012               // were encoded incorrectly.  create new
 2013               // X500Principal name with correct encoding
 2014   
 2015               X500Principal p = new X500Principal
 2016                   (x509Cert.getSubjectX500Principal().toString());
 2017               return p.getName();
 2018           }
 2019       }
 2020   
 2021       /**
 2022        * Checks public key. If it is marked as trusted in
 2023        * the identity database, add it to the policy
 2024        * with the AllPermission.
 2025        */
 2026       private boolean checkForTrustedIdentity(final Certificate cert,
 2027           PolicyInfo myInfo)
 2028       {
 2029           if (cert == null)
 2030               return false;
 2031   
 2032           // see if we are ignoring the identity scope or not
 2033           if (ignoreIdentityScope)
 2034               return false;
 2035   
 2036           // try to initialize scope
 2037           synchronized(PolicyFile.class) {
 2038               if (scope == null) {
 2039                   IdentityScope is = IdentityScope.getSystemScope();
 2040   
 2041                   if (is instanceof sun.security.provider.IdentityDatabase) {
 2042                       scope = is;
 2043                   } else {
 2044                       // leave scope null
 2045                   }
 2046               }
 2047           }
 2048   
 2049           if (scope == null) {
 2050               ignoreIdentityScope = true;
 2051               return false;
 2052           }
 2053   
 2054           // need privileged block for getIdentity in case we are trying
 2055           // to get a signer
 2056           final Identity id = AccessController.doPrivileged(
 2057                                 new java.security.PrivilegedAction<Identity>() {
 2058               public Identity run() {
 2059                   return scope.getIdentity(cert.getPublicKey());
 2060               }
 2061           });
 2062   
 2063           if (isTrusted(id)) {
 2064               if (debug != null) {
 2065                   debug.println("Adding policy entry for trusted Identity: ");
 2066                   //needed for identity toString!
 2067                   AccessController.doPrivileged(
 2068                         new java.security.PrivilegedAction<Void>() {
 2069                       public Void run() {
 2070                           debug.println("  identity = " + id);
 2071                           return null;
 2072                       }
 2073                   });
 2074                   debug.println("");
 2075               }
 2076   
 2077               // add it to the policy for future reference
 2078               Certificate certs[] = new Certificate[] {cert};
 2079               PolicyEntry pe = new PolicyEntry(new CodeSource(null, certs));
 2080               pe.add(SecurityConstants.ALL_PERMISSION);
 2081   
 2082               myInfo.identityPolicyEntries.add(pe);
 2083   
 2084               // add it to the mapping as well so
 2085               // we don't have to go through this again
 2086               myInfo.aliasMapping.put(cert, id.getName());
 2087   
 2088               return true;
 2089           }
 2090           return false;
 2091       }
 2092   
 2093       private static boolean isTrusted(Identity id) {
 2094               if (id instanceof SystemIdentity) {
 2095                   SystemIdentity sysid = (SystemIdentity)id;
 2096                   if (sysid.isTrusted()) {
 2097                       return true;
 2098                   }
 2099               } else if (id instanceof SystemSigner) {
 2100                   SystemSigner sysid = (SystemSigner)id;
 2101                   if (sysid.isTrusted()) {
 2102                       return true;
 2103                   }
 2104               }
 2105               return false;
 2106       }
 2107   
 2108       /**
 2109        * Each entry in the policy configuration file is represented by a
 2110        * PolicyEntry object.  <p>
 2111        *
 2112        * A PolicyEntry is a (CodeSource,Permission) pair.  The
 2113        * CodeSource contains the (URL, PublicKey) that together identify
 2114        * where the Java bytecodes come from and who (if anyone) signed
 2115        * them.  The URL could refer to localhost.  The URL could also be
 2116        * null, meaning that this policy entry is given to all comers, as
 2117        * long as they match the signer field.  The signer could be null,
 2118        * meaning the code is not signed. <p>
 2119        *
 2120        * The Permission contains the (Type, Name, Action) triplet. <p>
 2121        *
 2122        * For now, the Policy object retrieves the public key from the
 2123        * X.509 certificate on disk that corresponds to the signedBy
 2124        * alias specified in the Policy config file.  For reasons of
 2125        * efficiency, the Policy object keeps a hashtable of certs already
 2126        * read in.  This could be replaced by a secure internal key
 2127        * store.
 2128        *
 2129        * <p>
 2130        * For example, the entry
 2131        * <pre>
 2132        *          permission java.io.File "/tmp", "read,write",
 2133        *          signedBy "Duke";
 2134        * </pre>
 2135        * is represented internally
 2136        * <pre>
 2137        *
 2138        * FilePermission f = new FilePermission("/tmp", "read,write");
 2139        * PublicKey p = publickeys.get("Duke");
 2140        * URL u = InetAddress.getLocalHost();
 2141        * CodeBase c = new CodeBase( p, u );
 2142        * pe = new PolicyEntry(f, c);
 2143        * </pre>
 2144        *
 2145        * @author Marianne Mueller
 2146        * @author Roland Schemers
 2147        * @see java.security.CodeSource
 2148        * @see java.security.Policy
 2149        * @see java.security.Permissions
 2150        * @see java.security.ProtectionDomain
 2151        */
 2152       private static class PolicyEntry {
 2153   
 2154           private final CodeSource codesource;
 2155           final List<Permission> permissions;
 2156           private final List<PolicyParser.PrincipalEntry> principals;
 2157   
 2158           /**
 2159            * Given a Permission and a CodeSource, create a policy entry.
 2160            *
 2161            * XXX Decide if/how to add validity fields and "purpose" fields to
 2162            * XXX policy entries
 2163            *
 2164            * @param cs the CodeSource, which encapsulates the URL and the
 2165            *        public key
 2166            *        attributes from the policy config file. Validity checks
 2167            *        are performed on the public key before PolicyEntry is
 2168            *        called.
 2169            *
 2170            */
 2171           PolicyEntry(CodeSource cs, List<PolicyParser.PrincipalEntry> principals)
 2172           {
 2173               this.codesource = cs;
 2174               this.permissions = new ArrayList<Permission>();
 2175               this.principals = principals; // can be null
 2176           }
 2177   
 2178           PolicyEntry(CodeSource cs)
 2179           {
 2180               this(cs, null);
 2181           }
 2182   
 2183           List<PolicyParser.PrincipalEntry> getPrincipals() {
 2184               return principals; // can be null
 2185           }
 2186   
 2187           /**
 2188            * add a Permission object to this entry.
 2189            * No need to sync add op because perms are added to entry only
 2190            * while entry is being initialized
 2191            */
 2192           void add(Permission p) {
 2193               permissions.add(p);
 2194           }
 2195   
 2196           /**
 2197            * Return the CodeSource for this policy entry
 2198            */
 2199           CodeSource getCodeSource() {
 2200               return codesource;
 2201           }
 2202   
 2203           public String toString(){
 2204               StringBuilder sb = new StringBuilder();
 2205               sb.append(ResourcesMgr.getString("("));
 2206               sb.append(getCodeSource());
 2207               sb.append("\n");
 2208               for (int j = 0; j < permissions.size(); j++) {
 2209                   Permission p = permissions.get(j);
 2210                   sb.append(ResourcesMgr.getString(" "));
 2211                   sb.append(ResourcesMgr.getString(" "));
 2212                   sb.append(p);
 2213                   sb.append(ResourcesMgr.getString("\n"));
 2214               }
 2215               sb.append(ResourcesMgr.getString(")"));
 2216               sb.append(ResourcesMgr.getString("\n"));
 2217               return sb.toString();
 2218           }
 2219       }
 2220   
 2221       private static class SelfPermission extends Permission {
 2222   
 2223           private static final long serialVersionUID = -8315562579967246806L;
 2224   
 2225           /**
 2226            * The class name of the Permission class that will be
 2227            * created when this self permission is expanded .
 2228            *
 2229            * @serial
 2230            */
 2231           private String type;
 2232   
 2233           /**
 2234            * The permission name.
 2235            *
 2236            * @serial
 2237            */
 2238           private String name;
 2239   
 2240           /**
 2241            * The actions of the permission.
 2242            *
 2243            * @serial
 2244            */
 2245           private String actions;
 2246   
 2247           /**
 2248            * The certs of the permission.
 2249            *
 2250            * @serial
 2251            */
 2252           private Certificate certs[];
 2253   
 2254           /**
 2255            * Creates a new SelfPermission containing the permission
 2256            * information needed later to expand the self
 2257            * @param type the class name of the Permission class that will be
 2258            * created when this permission is expanded and if necessary resolved.
 2259            * @param name the name of the permission.
 2260            * @param actions the actions of the permission.
 2261            * @param certs the certificates the permission's class was signed with.
 2262            * This is a list of certificate chains, where each chain is composed of
 2263            * a signer certificate and optionally its supporting certificate chain.
 2264            * Each chain is ordered bottom-to-top (i.e., with the signer
 2265            * certificate first and the (root) certificate authority last).
 2266            */
 2267           public SelfPermission(String type, String name, String actions,
 2268                                 Certificate certs[])
 2269           {
 2270               super(type);
 2271               if (type == null) {
 2272                   throw new NullPointerException
 2273                       (ResourcesMgr.getString("type can't be null"));
 2274               }
 2275               this.type = type;
 2276               this.name = name;
 2277               this.actions = actions;
 2278               if (certs != null) {
 2279                   // Extract the signer certs from the list of certificates.
 2280                   for (int i=0; i<certs.length; i++) {
 2281                       if (!(certs[i] instanceof X509Certificate)) {
 2282                           // there is no concept of signer certs, so we store the
 2283                           // entire cert array
 2284                           this.certs = certs.clone();
 2285                           break;
 2286                       }
 2287                   }
 2288   
 2289                   if (this.certs == null) {
 2290                       // Go through the list of certs and see if all the certs are
 2291                       // signer certs.
 2292                       int i = 0;
 2293                       int count = 0;
 2294                       while (i < certs.length) {
 2295                           count++;
 2296                           while (((i+1) < certs.length) &&
 2297                               ((X509Certificate)certs[i]).getIssuerDN().equals(
 2298                               ((X509Certificate)certs[i+1]).getSubjectDN())) {
 2299                               i++;
 2300                           }
 2301                           i++;
 2302                       }
 2303                       if (count == certs.length) {
 2304                           // All the certs are signer certs, so we store the
 2305                           // entire array
 2306                           this.certs = certs.clone();
 2307                       }
 2308   
 2309                       if (this.certs == null) {
 2310                           // extract the signer certs
 2311                           ArrayList<Certificate> signerCerts =
 2312                               new ArrayList<Certificate>();
 2313                           i = 0;
 2314                           while (i < certs.length) {
 2315                               signerCerts.add(certs[i]);
 2316                               while (((i+1) < certs.length) &&
 2317                                   ((X509Certificate)certs[i]).getIssuerDN().equals(
 2318                                   ((X509Certificate)certs[i+1]).getSubjectDN())) {
 2319                                   i++;
 2320                               }
 2321                               i++;
 2322                           }
 2323                           this.certs = new Certificate[signerCerts.size()];
 2324                           signerCerts.toArray(this.certs);
 2325                       }
 2326                   }
 2327               }
 2328           }
 2329   
 2330           /**
 2331            * This method always returns false for SelfPermission permissions.
 2332            * That is, an SelfPermission never considered to
 2333            * imply another permission.
 2334            *
 2335            * @param p the permission to check against.
 2336            *
 2337            * @return false.
 2338            */
 2339           public boolean implies(Permission p) {
 2340               return false;
 2341           }
 2342   
 2343           /**
 2344            * Checks two SelfPermission objects for equality.
 2345            *
 2346            * Checks that <i>obj</i> is an SelfPermission, and has
 2347            * the same type (class) name, permission name, actions, and
 2348            * certificates as this object.
 2349            *
 2350            * @param obj the object we are testing for equality with this object.
 2351            *
 2352            * @return true if obj is an SelfPermission, and has the same
 2353            * type (class) name, permission name, actions, and
 2354            * certificates as this object.
 2355            */
 2356           public boolean equals(Object obj) {
 2357               if (obj == this)
 2358                   return true;
 2359   
 2360               if (! (obj instanceof SelfPermission))
 2361                   return false;
 2362               SelfPermission that = (SelfPermission) obj;
 2363   
 2364               if (!(this.type.equals(that.type) &&
 2365                   this.name.equals(that.name) &&
 2366                   this.actions.equals(that.actions)))
 2367                   return false;
 2368   
 2369               if (this.certs.length != that.certs.length)
 2370                   return false;
 2371   
 2372               int i,j;
 2373               boolean match;
 2374   
 2375               for (i = 0; i < this.certs.length; i++) {
 2376                   match = false;
 2377                   for (j = 0; j < that.certs.length; j++) {
 2378                       if (this.certs[i].equals(that.certs[j])) {
 2379                           match = true;
 2380                           break;
 2381                       }
 2382                   }
 2383                   if (!match) return false;
 2384               }
 2385   
 2386               for (i = 0; i < that.certs.length; i++) {
 2387                   match = false;
 2388                   for (j = 0; j < this.certs.length; j++) {
 2389                       if (that.certs[i].equals(this.certs[j])) {
 2390                           match = true;
 2391                           break;
 2392                       }
 2393                   }
 2394                   if (!match) return false;
 2395               }
 2396               return true;
 2397           }
 2398   
 2399           /**
 2400            * Returns the hash code value for this object.
 2401            *
 2402            * @return a hash code value for this object.
 2403            */
 2404           public int hashCode() {
 2405               int hash = type.hashCode();
 2406               if (name != null)
 2407                   hash ^= name.hashCode();
 2408               if (actions != null)
 2409                   hash ^= actions.hashCode();
 2410               return hash;
 2411           }
 2412   
 2413           /**
 2414            * Returns the canonical string representation of the actions,
 2415            * which currently is the empty string "", since there are no actions
 2416            * for an SelfPermission. That is, the actions for the
 2417            * permission that will be created when this SelfPermission
 2418            * is resolved may be non-null, but an SelfPermission
 2419            * itself is never considered to have any actions.
 2420            *
 2421            * @return the empty string "".
 2422            */
 2423           public String getActions() {
 2424               return "";
 2425           }
 2426   
 2427           public String getSelfType() {
 2428               return type;
 2429           }
 2430   
 2431           public String getSelfName() {
 2432               return name;
 2433           }
 2434   
 2435           public String getSelfActions() {
 2436               return actions;
 2437           }
 2438   
 2439           public Certificate[] getCerts() {
 2440               return certs;
 2441           }
 2442   
 2443           /**
 2444            * Returns a string describing this SelfPermission.  The convention
 2445            * is to specify the class name, the permission name, and the actions,
 2446            * in the following format: '(unresolved "ClassName" "name" "actions")'.
 2447            *
 2448            * @return information about this SelfPermission.
 2449            */
 2450           public String toString() {
 2451               return "(SelfPermission " + type + " " + name + " " + actions + ")";
 2452           }
 2453       }
 2454   
 2455       /**
 2456        * holds policy information that we need to synch on
 2457        */
 2458       private static class PolicyInfo {
 2459           private static final boolean verbose = false;
 2460   
 2461           // Stores grant entries in the policy
 2462           final List<PolicyEntry> policyEntries;
 2463   
 2464           // Stores grant entries gotten from identity database
 2465           // Use separate lists to avoid sync on policyEntries
 2466           final List<PolicyEntry> identityPolicyEntries;
 2467   
 2468           // Maps aliases to certs
 2469           final Map aliasMapping;
 2470   
 2471           // Maps ProtectionDomain to PermissionCollection
 2472           private final Map<ProtectionDomain, PermissionCollection>[] pdMapping;
 2473           private java.util.Random random;
 2474   
 2475           PolicyInfo(int numCaches) {
 2476               policyEntries = new ArrayList<PolicyEntry>();
 2477               identityPolicyEntries =
 2478                   Collections.synchronizedList(new ArrayList<PolicyEntry>(2));
 2479               aliasMapping = Collections.synchronizedMap(new HashMap(11));
 2480   
 2481               pdMapping = new Map[numCaches];
 2482               for (int i = 0; i < numCaches; i++) {
 2483                   pdMapping[i] = Collections.synchronizedMap
 2484                       (new WeakHashMap<ProtectionDomain, PermissionCollection>());
 2485               }
 2486               if (numCaches > 1) {
 2487                   random = new java.util.Random();
 2488               }
 2489           }
 2490           Map<ProtectionDomain, PermissionCollection> getPdMapping() {
 2491               if (pdMapping.length == 1) {
 2492                   return pdMapping[0];
 2493               } else {
 2494                   int i = java.lang.Math.abs(random.nextInt() % pdMapping.length);
 2495                   return pdMapping[i];
 2496               }
 2497           }
 2498       }
 2499   }

Save This Page
Home » openjdk-7 » sun.security » provider » [javadoc | source]