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