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