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 26 package sun.security.provider; 27 28 import java.io.*; 29 import java.lang.reflect.*; 30 import java.net.MalformedURLException; 31 import java.net.URL; 32 import java.net.URI; 33 import java.util.*; 34 import java.text.MessageFormat; 35 import java.security.*; 36 import java.security.cert.Certificate; 37 import java.security.cert.X509Certificate; 38 import javax.security.auth.Subject; 39 import javax.security.auth.x500.X500Principal; 40 import java.io.FilePermission; 41 import java.net.SocketPermission; 42 import java.net.NetPermission; 43 import java.util.concurrent.atomic.AtomicReference; 44 import sun.misc.JavaSecurityProtectionDomainAccess; 45 import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache; 46 import sun.misc.SharedSecrets; 47 import sun.security.util.PolicyUtil; 48 import sun.security.util.PropertyExpander; 49 import sun.security.util.Debug; 50 import sun.security.util.ResourcesMgr; 51 import sun.security.util.SecurityConstants; 52 import 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 * <JAVA_HOME>/lib/security/java.security. 81 * <JAVA_HOME> 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 */ 258 public 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 lib/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 // Add AllPermissions for standard extensions 713 String[] extCodebases = PolicyParser.parseExtDirs( 714 PolicyParser.EXTDIRS_EXPANSION, 0); 715 if (extCodebases != null && extCodebases.length > 0) { 716 for (int i = 0; i < extCodebases.length; i++) { 717 try { 718 pe = new PolicyEntry(canonicalizeCodebase( 719 new CodeSource(new URL(extCodebases[i]), 720 (Certificate[]) null), false )); 721 pe.add(SecurityConstants.ALL_PERMISSION); 722 723 // No need to sync because noone has access to 724 // newInfo yet 725 newInfo.policyEntries.add(pe); 726 } catch (Exception e) { 727 // this is probably bad (though not dangerous). 728 // What should we do? 729 } 730 } 731 } 732 return null; 733 } 734 }); 735 } 736 737 /** 738 * Given a GrantEntry, create a codeSource. 739 * 740 * @return null if signedBy alias is not recognized 741 */ 742 private CodeSource getCodeSource(PolicyParser.GrantEntry ge, KeyStore keyStore, 743 PolicyInfo newInfo) throws java.net.MalformedURLException 744 { 745 Certificate[] certs = null; 746 if (ge.signedBy != null) { 747 certs = getCertificates(keyStore, ge.signedBy, newInfo); 748 if (certs == null) { 749 // we don't have a key for this alias, 750 // just return 751 if (debug != null) { 752 debug.println(" -- No certs for alias '" + 753 ge.signedBy + "' - ignoring entry"); 754 } 755 return null; 756 } 757 } 758 759 URL location; 760 761 if (ge.codeBase != null) 762 location = new URL(ge.codeBase); 763 else 764 location = null; 765 766 return (canonicalizeCodebase(new CodeSource(location, certs),false)); 767 } 768 769 /** 770 * Add one policy entry to the list. 771 */ 772 private void addGrantEntry(PolicyParser.GrantEntry ge, 773 KeyStore keyStore, PolicyInfo newInfo) { 774 775 if (debug != null) { 776 debug.println("Adding policy entry: "); 777 debug.println(" signedBy " + ge.signedBy); 778 debug.println(" codeBase " + ge.codeBase); 779 if (ge.principals != null) { 780 for (PolicyParser.PrincipalEntry pppe : ge.principals) { 781 debug.println(" " + pppe.toString()); 782 } 783 } 784 } 785 786 try { 787 CodeSource codesource = getCodeSource(ge, keyStore, newInfo); 788 // skip if signedBy alias was unknown... 789 if (codesource == null) return; 790 791 // perform keystore alias principal replacement. 792 // for example, if alias resolves to X509 certificate, 793 // replace principal with: <X500Principal class> <SubjectDN> 794 // -- skip if alias is unknown 795 if (replacePrincipals(ge.principals, keyStore) == false) 796 return; 797 PolicyEntry entry = new PolicyEntry(codesource, ge.principals); 798 Enumeration<PolicyParser.PermissionEntry> enum_ = 799 ge.permissionElements(); 800 while (enum_.hasMoreElements()) { 801 PolicyParser.PermissionEntry pe = enum_.nextElement(); 802 803 try { 804 // perform ${{ ... }} expansions within permission name 805 expandPermissionName(pe, keyStore); 806 807 // XXX special case PrivateCredentialPermission-SELF 808 Permission perm; 809 if (pe.permission.equals 810 ("javax.security.auth.PrivateCredentialPermission") && 811 pe.name.endsWith(" self")) { 812 pe.name = pe.name.substring(0, pe.name.indexOf("self")) 813 + SELF; 814 } 815 // check for self 816 if (pe.name != null && pe.name.indexOf(SELF) != -1) { 817 // Create a "SelfPermission" , it could be an 818 // an unresolved permission which will be resolved 819 // when implies is called 820 // Add it to entry 821 Certificate certs[]; 822 if (pe.signedBy != null) { 823 certs = getCertificates(keyStore, 824 pe.signedBy, 825 newInfo); 826 } else { 827 certs = null; 828 } 829 perm = new SelfPermission(pe.permission, 830 pe.name, 831 pe.action, 832 certs); 833 } else { 834 perm = getInstance(pe.permission, 835 pe.name, 836 pe.action); 837 } 838 entry.add(perm); 839 if (debug != null) { 840 debug.println(" "+perm); 841 } 842 } catch (ClassNotFoundException cnfe) { 843 Certificate certs[]; 844 if (pe.signedBy != null) { 845 certs = getCertificates(keyStore, 846 pe.signedBy, 847 newInfo); 848 } else { 849 certs = null; 850 } 851 852 // only add if we had no signer or we had a 853 // a signer and found the keys for it. 854 if (certs != null || pe.signedBy == null) { 855 Permission perm = new UnresolvedPermission( 856 pe.permission, 857 pe.name, 858 pe.action, 859 certs); 860 entry.add(perm); 861 if (debug != null) { 862 debug.println(" "+perm); 863 } 864 } 865 } catch (java.lang.reflect.InvocationTargetException ite) { 866 MessageFormat form = new MessageFormat 867 (ResourcesMgr.getString 868 (POLICY + 869 ".error.adding.Permission.perm.message")); 870 Object[] source = {pe.permission, 871 ite.getTargetException().toString()}; 872 System.err.println(form.format(source)); 873 } catch (Exception e) { 874 MessageFormat form = new MessageFormat 875 (ResourcesMgr.getString 876 (POLICY + 877 ".error.adding.Permission.perm.message")); 878 Object[] source = {pe.permission, 879 e.toString()}; 880 System.err.println(form.format(source)); 881 } 882 } 883 884 // No need to sync because noone has access to newInfo yet 885 newInfo.policyEntries.add(entry); 886 } catch (Exception e) { 887 MessageFormat form = new MessageFormat(ResourcesMgr.getString 888 (POLICY 889 + ".error.adding.Entry.message")); 890 Object[] source = {e.toString()}; 891 System.err.println(form.format(source)); 892 } 893 if (debug != null) 894 debug.println(); 895 } 896 897 /** 898 * Returns a new Permission object of the given Type. The Permission is 899 * created by getting the 900 * Class object using the <code>Class.forName</code> method, and using 901 * the reflection API to invoke the (String name, String actions) 902 * constructor on the 903 * object. 904 * 905 * @param type the type of Permission being created. 906 * @param name the name of the Permission being created. 907 * @param actions the actions of the Permission being created. 908 * 909 * @exception ClassNotFoundException if the particular Permission 910 * class could not be found. 911 * 912 * @exception IllegalAccessException if the class or initializer is 913 * not accessible. 914 * 915 * @exception InstantiationException if getInstance tries to 916 * instantiate an abstract class or an interface, or if the 917 * instantiation fails for some other reason. 918 * 919 * @exception NoSuchMethodException if the (String, String) constructor 920 * is not found. 921 * 922 * @exception InvocationTargetException if the underlying Permission 923 * constructor throws an exception. 924 * 925 */ 926 927 private static final Permission getInstance(String type, 928 String name, 929 String actions) 930 throws ClassNotFoundException, 931 InstantiationException, 932 IllegalAccessException, 933 NoSuchMethodException, 934 InvocationTargetException 935 { 936 //XXX we might want to keep a hash of created factories... 937 Class<?> pc = Class.forName(type, false, null); 938 Permission answer = getKnownInstance(pc, name, actions); 939 if (answer != null) { 940 return answer; 941 } 942 if (!Permission.class.isAssignableFrom(pc)) { 943 // not the right subtype 944 throw new ClassCastException(type + " is not a Permission"); 945 } 946 947 if (name == null && actions == null) { 948 try { 949 Constructor<?> c = pc.getConstructor(PARAMS0); 950 return (Permission) c.newInstance(new Object[] {}); 951 } catch (NoSuchMethodException ne) { 952 try { 953 Constructor<?> c = pc.getConstructor(PARAMS1); 954 return (Permission) c.newInstance( 955 new Object[] { name}); 956 } catch (NoSuchMethodException ne1 ) { 957 Constructor<?> c = pc.getConstructor(PARAMS2); 958 return (Permission) c.newInstance( 959 new Object[] { name, actions }); 960 } 961 } 962 } else { 963 if (name != null && actions == null) { 964 try { 965 Constructor<?> c = pc.getConstructor(PARAMS1); 966 return (Permission) c.newInstance(new Object[] { name}); 967 } catch (NoSuchMethodException ne) { 968 Constructor<?> c = pc.getConstructor(PARAMS2); 969 return (Permission) c.newInstance( 970 new Object[] { name, actions }); 971 } 972 } else { 973 Constructor<?> c = pc.getConstructor(PARAMS2); 974 return (Permission) c.newInstance( 975 new Object[] { name, actions }); 976 } 977 } 978 } 979 980 /** 981 * Creates one of the well-known permissions directly instead of 982 * via reflection. Keep list short to not penalize non-JDK-defined 983 * permissions. 984 */ 985 private static final Permission getKnownInstance(Class<?> claz, 986 String name, String actions) { 987 if (claz.equals(FilePermission.class)) { 988 return new FilePermission(name, actions); 989 } else if (claz.equals(SocketPermission.class)) { 990 return new SocketPermission(name, actions); 991 } else if (claz.equals(RuntimePermission.class)) { 992 return new RuntimePermission(name, actions); 993 } else if (claz.equals(PropertyPermission.class)) { 994 return new PropertyPermission(name, actions); 995 } else if (claz.equals(NetPermission.class)) { 996 return new NetPermission(name, actions); 997 } else if (claz.equals(AllPermission.class)) { 998 return SecurityConstants.ALL_PERMISSION; 999 } else { 1000 return null; 1001 } 1002 } 1003 1004 /** 1005 * Fetch all certs associated with this alias. 1006 */ 1007 private Certificate[] getCertificates 1008 (KeyStore keyStore, String aliases, PolicyInfo newInfo) { 1009 1010 List<Certificate> vcerts = null; 1011 1012 StringTokenizer st = new StringTokenizer(aliases, ","); 1013 int n = 0; 1014 1015 while (st.hasMoreTokens()) { 1016 String alias = st.nextToken().trim(); 1017 n++; 1018 Certificate cert = null; 1019 // See if this alias's cert has already been cached 1020 synchronized (newInfo.aliasMapping) { 1021 cert = (Certificate)newInfo.aliasMapping.get(alias); 1022 1023 if (cert == null && keyStore != null) { 1024 1025 try { 1026 cert = keyStore.getCertificate(alias); 1027 } catch (KeyStoreException kse) { 1028 // never happens, because keystore has already been loaded 1029 // when we call this 1030 } 1031 if (cert != null) { 1032 newInfo.aliasMapping.put(alias, cert); 1033 newInfo.aliasMapping.put(cert, alias); 1034 } 1035 } 1036 } 1037 1038 if (cert != null) { 1039 if (vcerts == null) 1040 vcerts = new ArrayList<>(); 1041 vcerts.add(cert); 1042 } 1043 } 1044 1045 // make sure n == vcerts.size, since we are doing a logical *and* 1046 if (vcerts != null && n == vcerts.size()) { 1047 Certificate[] certs = new Certificate[vcerts.size()]; 1048 vcerts.toArray(certs); 1049 return certs; 1050 } else { 1051 return null; 1052 } 1053 } 1054 1055 /** 1056 * Refreshes the policy object by re-reading all the policy files. 1057 */ 1058 @Override public void refresh() { 1059 init(url); 1060 } 1061 1062 /** 1063 * Evaluates the the global policy for the permissions granted to 1064 * the ProtectionDomain and tests whether the permission is 1065 * granted. 1066 * 1067 * @param domain the ProtectionDomain to test 1068 * @param permission the Permission object to be tested for implication. 1069 * 1070 * @return true if "permission" is a proper subset of a permission 1071 * granted to this ProtectionDomain. 1072 * 1073 * @see java.security.ProtectionDomain 1074 */ 1075 @Override 1076 public boolean implies(ProtectionDomain pd, Permission p) { 1077 PolicyInfo pi = policyInfo.get(); 1078 ProtectionDomainCache pdMap = pi.getPdMapping(); 1079 1080 PermissionCollection pc = pdMap.get(pd); 1081 1082 if (pc != null) { 1083 return pc.implies(p); 1084 } 1085 1086 pc = getPermissions(pd); 1087 if (pc == null) { 1088 return false; 1089 } 1090 1091 // cache mapping of protection domain to its PermissionCollection 1092 pdMap.put(pd, pc); 1093 return pc.implies(p); 1094 } 1095 1096 /** 1097 * Examines this <code>Policy</code> and returns the permissions granted 1098 * to the specified <code>ProtectionDomain</code>. This includes 1099 * the permissions currently associated with the domain as well 1100 * as the policy permissions granted to the domain's 1101 * CodeSource, ClassLoader, and Principals. 1102 * 1103 * <p> Note that this <code>Policy</code> implementation has 1104 * special handling for PrivateCredentialPermissions. 1105 * When this method encounters a <code>PrivateCredentialPermission</code> 1106 * which specifies "self" as the <code>Principal</code> class and name, 1107 * it does not add that <code>Permission</code> to the returned 1108 * <code>PermissionCollection</code>. Instead, it builds 1109 * a new <code>PrivateCredentialPermission</code> 1110 * for each <code>Principal</code> associated with the provided 1111 * <code>Subject</code>. Each new <code>PrivateCredentialPermission</code> 1112 * contains the same Credential class as specified in the 1113 * originally granted permission, as well as the Class and name 1114 * for the respective <code>Principal</code>. 1115 * 1116 * <p> 1117 * 1118 * @param domain the Permissions granted to this 1119 * <code>ProtectionDomain</code> are returned. 1120 * 1121 * @return the Permissions granted to the provided 1122 * <code>ProtectionDomain</code>. 1123 */ 1124 @Override 1125 public PermissionCollection getPermissions(ProtectionDomain domain) { 1126 Permissions perms = new Permissions(); 1127 1128 if (domain == null) 1129 return perms; 1130 1131 // first get policy perms 1132 getPermissions(perms, domain); 1133 1134 // add static perms 1135 // - adding static perms after policy perms is necessary 1136 // to avoid a regression for 4301064 1137 PermissionCollection pc = domain.getPermissions(); 1138 if (pc != null) { 1139 synchronized (pc) { 1140 Enumeration<Permission> e = pc.elements(); 1141 while (e.hasMoreElements()) { 1142 perms.add(e.nextElement()); 1143 } 1144 } 1145 } 1146 1147 return perms; 1148 } 1149 1150 /** 1151 * Examines this Policy and creates a PermissionCollection object with 1152 * the set of permissions for the specified CodeSource. 1153 * 1154 * @param CodeSource the codesource associated with the caller. 1155 * This encapsulates the original location of the code (where the code 1156 * came from) and the public key(s) of its signer. 1157 * 1158 * @return the set of permissions according to the policy. 1159 */ 1160 @Override 1161 public PermissionCollection getPermissions(CodeSource codesource) { 1162 return getPermissions(new Permissions(), codesource); 1163 } 1164 1165 /** 1166 * Examines the global policy and returns the provided Permissions 1167 * object with additional permissions granted to the specified 1168 * ProtectionDomain. 1169 * 1170 * @param perm the Permissions to populate 1171 * @param pd the ProtectionDomain associated with the caller. 1172 * 1173 * @return the set of Permissions according to the policy. 1174 */ 1175 private PermissionCollection getPermissions(Permissions perms, 1176 ProtectionDomain pd ) { 1177 if (debug != null) { 1178 debug.println("getPermissions:\n\t" + printPD(pd)); 1179 } 1180 1181 final CodeSource cs = pd.getCodeSource(); 1182 if (cs == null) 1183 return perms; 1184 1185 CodeSource canonCodeSource = AccessController.doPrivileged( 1186 new java.security.PrivilegedAction<CodeSource>(){ 1187 public CodeSource run() { 1188 return canonicalizeCodebase(cs, true); 1189 } 1190 }); 1191 return getPermissions(perms, canonCodeSource, pd.getPrincipals()); 1192 } 1193 1194 /** 1195 * Examines the global policy and returns the provided Permissions 1196 * object with additional permissions granted to the specified 1197 * CodeSource. 1198 * 1199 * @param permissions the permissions to populate 1200 * @param codesource the codesource associated with the caller. 1201 * This encapsulates the original location of the code (where the code 1202 * came from) and the public key(s) of its signer. 1203 * 1204 * @return the set of permissions according to the policy. 1205 */ 1206 private PermissionCollection getPermissions(Permissions perms, 1207 final CodeSource cs) { 1208 1209 if (cs == null) 1210 return perms; 1211 1212 CodeSource canonCodeSource = AccessController.doPrivileged( 1213 new java.security.PrivilegedAction<CodeSource>(){ 1214 public CodeSource run() { 1215 return canonicalizeCodebase(cs, true); 1216 } 1217 }); 1218 1219 return getPermissions(perms, canonCodeSource, null); 1220 } 1221 1222 private Permissions getPermissions(Permissions perms, 1223 final CodeSource cs, 1224 Principal[] principals) { 1225 PolicyInfo pi = policyInfo.get(); 1226 1227 for (PolicyEntry entry : pi.policyEntries) { 1228 addPermissions(perms, cs, principals, entry); 1229 } 1230 1231 // Go through policyEntries gotten from identity db; sync required 1232 // because checkForTrustedIdentity (below) might update list 1233 synchronized (pi.identityPolicyEntries) { 1234 for (PolicyEntry entry : pi.identityPolicyEntries) { 1235 addPermissions(perms, cs, principals, entry); 1236 } 1237 } 1238 1239 // now see if any of the keys are trusted ids. 1240 if (!ignoreIdentityScope) { 1241 Certificate certs[] = cs.getCertificates(); 1242 if (certs != null) { 1243 for (int k=0; k < certs.length; k++) { 1244 Object idMap = pi.aliasMapping.get(certs[k]); 1245 if (idMap == null && 1246 checkForTrustedIdentity(certs[k], pi)) { 1247 // checkForTrustedIdentity added it 1248 // to the policy for us. next time 1249 // around we'll find it. This time 1250 // around we need to add it. 1251 perms.add(SecurityConstants.ALL_PERMISSION); 1252 } 1253 } 1254 } 1255 } 1256 return perms; 1257 } 1258 1259 private void addPermissions(Permissions perms, 1260 final CodeSource cs, 1261 Principal[] principals, 1262 final PolicyEntry entry) { 1263 1264 if (debug != null) { 1265 debug.println("evaluate codesources:\n" + 1266 "\tPolicy CodeSource: " + entry.getCodeSource() + "\n" + 1267 "\tActive CodeSource: " + cs); 1268 } 1269 1270 // check to see if the CodeSource implies 1271 Boolean imp = AccessController.doPrivileged 1272 (new PrivilegedAction<Boolean>() { 1273 public Boolean run() { 1274 return entry.getCodeSource().implies(cs); 1275 } 1276 }); 1277 if (!imp.booleanValue()) { 1278 if (debug != null) { 1279 debug.println("evaluation (codesource) failed"); 1280 } 1281 1282 // CodeSource does not imply - return and try next policy entry 1283 return; 1284 } 1285 1286 // check to see if the Principals imply 1287 1288 List<PolicyParser.PrincipalEntry> entryPs = entry.getPrincipals(); 1289 if (debug != null) { 1290 List<PolicyParser.PrincipalEntry> accPs = new ArrayList<>(); 1291 if (principals != null) { 1292 for (int i = 0; i < principals.length; i++) { 1293 accPs.add(new PolicyParser.PrincipalEntry 1294 (principals[i].getClass().getName(), 1295 principals[i].getName())); 1296 } 1297 } 1298 debug.println("evaluate principals:\n" + 1299 "\tPolicy Principals: " + entryPs + "\n" + 1300 "\tActive Principals: " + accPs); 1301 } 1302 1303 if (entryPs == null || entryPs.isEmpty()) { 1304 1305 // policy entry has no principals - 1306 // add perms regardless of principals in current ACC 1307 1308 addPerms(perms, principals, entry); 1309 if (debug != null) { 1310 debug.println("evaluation (codesource/principals) passed"); 1311 } 1312 return; 1313 1314 } else if (principals == null || principals.length == 0) { 1315 1316 // current thread has no principals but this policy entry 1317 // has principals - perms are not added 1318 1319 if (debug != null) { 1320 debug.println("evaluation (principals) failed"); 1321 } 1322 return; 1323 } 1324 1325 // current thread has principals and this policy entry 1326 // has principals. see if policy entry principals match 1327 // principals in current ACC 1328 1329 for (PolicyParser.PrincipalEntry pppe : entryPs) { 1330 1331 // Check for wildcards 1332 if (pppe.isWildcardClass()) { 1333 // a wildcard class matches all principals in current ACC 1334 continue; 1335 } 1336 1337 if (pppe.isWildcardName()) { 1338 // a wildcard name matches any principal with the same class 1339 if (wildcardPrincipalNameImplies(pppe.principalClass, 1340 principals)) { 1341 continue; 1342 } 1343 if (debug != null) { 1344 debug.println("evaluation (principal name wildcard) failed"); 1345 } 1346 // policy entry principal not in current ACC - 1347 // immediately return and go to next policy entry 1348 return; 1349 } 1350 1351 Set<Principal> pSet = new HashSet<>(Arrays.asList(principals)); 1352 Subject subject = new Subject(true, pSet, 1353 Collections.EMPTY_SET, 1354 Collections.EMPTY_SET); 1355 try { 1356 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 1357 Class<?> pClass = Class.forName(pppe.principalClass, false, cl); 1358 if (!Principal.class.isAssignableFrom(pClass)) { 1359 // not the right subtype 1360 throw new ClassCastException(pppe.principalClass + 1361 " is not a Principal"); 1362 } 1363 1364 Constructor<?> c = pClass.getConstructor(PARAMS1); 1365 Principal p = (Principal)c.newInstance(new Object[] { 1366 pppe.principalName }); 1367 1368 if (debug != null) { 1369 debug.println("found Principal " + p.getClass().getName()); 1370 } 1371 1372 // check if the Principal implies the current 1373 // thread's principals 1374 if (!p.implies(subject)) { 1375 if (debug != null) { 1376 debug.println("evaluation (principal implies) failed"); 1377 } 1378 1379 // policy principal does not imply the current Subject - 1380 // immediately return and go to next policy entry 1381 return; 1382 } 1383 } catch (Exception e) { 1384 // fall back to default principal comparison. 1385 // see if policy entry principal is in current ACC 1386 1387 if (debug != null) { 1388 e.printStackTrace(); 1389 } 1390 1391 if (!pppe.implies(subject)) { 1392 if (debug != null) { 1393 debug.println("evaluation (default principal implies) failed"); 1394 } 1395 1396 // policy entry principal not in current ACC - 1397 // immediately return and go to next policy entry 1398 return; 1399 } 1400 } 1401 1402 // either the principal information matched, 1403 // or the Principal.implies succeeded. 1404 // continue loop and test the next policy principal 1405 } 1406 1407 // all policy entry principals were found in the current ACC - 1408 // grant the policy permissions 1409 1410 if (debug != null) { 1411 debug.println("evaluation (codesource/principals) passed"); 1412 } 1413 addPerms(perms, principals, entry); 1414 } 1415 1416 /** 1417 * Returns true if the array of principals contains at least one 1418 * principal of the specified class. 1419 */ 1420 private static boolean wildcardPrincipalNameImplies(String principalClass, 1421 Principal[] principals) 1422 { 1423 for (Principal p : principals) { 1424 if (principalClass.equals(p.getClass().getName())) { 1425 return true; 1426 } 1427 } 1428 return false; 1429 } 1430 1431 private void addPerms(Permissions perms, 1432 Principal[] accPs, 1433 PolicyEntry entry) { 1434 for (int i = 0; i < entry.permissions.size(); i++) { 1435 Permission p = entry.permissions.get(i); 1436 if (debug != null) { 1437 debug.println(" granting " + p); 1438 } 1439 1440 if (p instanceof SelfPermission) { 1441 // handle "SELF" permissions 1442 expandSelf((SelfPermission)p, 1443 entry.getPrincipals(), 1444 accPs, 1445 perms); 1446 } else { 1447 perms.add(p); 1448 } 1449 } 1450 } 1451 1452 /** 1453 * <p> 1454 * 1455 * @param sp the SelfPermission that needs to be expanded <p> 1456 * 1457 * @param entryPs list of principals for the Policy entry. 1458 * 1459 * @param pdp Principal array from the current ProtectionDomain. 1460 * 1461 * @param perms the PermissionCollection where the individual 1462 * Permissions will be added after expansion. 1463 */ 1464 1465 private void expandSelf(SelfPermission sp, 1466 List<PolicyParser.PrincipalEntry> entryPs, 1467 Principal[] pdp, 1468 Permissions perms) { 1469 1470 if (entryPs == null || entryPs.isEmpty()) { 1471 // No principals in the grant to substitute 1472 if (debug != null) { 1473 debug.println("Ignoring permission " 1474 + sp.getSelfType() 1475 + " with target name (" 1476 + sp.getSelfName() + "). " 1477 + "No Principal(s) specified " 1478 + "in the grant clause. " 1479 + "SELF-based target names are " 1480 + "only valid in the context " 1481 + "of a Principal-based grant entry." 1482 ); 1483 } 1484 return; 1485 } 1486 int startIndex = 0; 1487 int v; 1488 StringBuilder sb = new StringBuilder(); 1489 while ((v = sp.getSelfName().indexOf(SELF, startIndex)) != -1) { 1490 1491 // add non-SELF string 1492 sb.append(sp.getSelfName().substring(startIndex, v)); 1493 1494 // expand SELF 1495 Iterator<PolicyParser.PrincipalEntry> pli = entryPs.iterator(); 1496 while (pli.hasNext()) { 1497 PolicyParser.PrincipalEntry pppe = pli.next(); 1498 String[][] principalInfo = getPrincipalInfo(pppe, pdp); 1499 for (int i = 0; i < principalInfo.length; i++) { 1500 if (i != 0) { 1501 sb.append(", "); 1502 } 1503 sb.append(principalInfo[i][0]).append(' ').append('"') 1504 .append(principalInfo[i][1]).append('"'); 1505 } 1506 if (pli.hasNext()) { 1507 sb.append(", "); 1508 } 1509 } 1510 startIndex = v + SELF.length(); 1511 } 1512 // add remaining string (might be the entire string) 1513 sb.append(sp.getSelfName().substring(startIndex)); 1514 1515 if (debug != null) { 1516 debug.println(" expanded:\n\t" + sp.getSelfName() 1517 + "\n into:\n\t" + sb.toString()); 1518 } 1519 try { 1520 // first try to instantiate the permission 1521 perms.add(getInstance(sp.getSelfType(), 1522 sb.toString(), 1523 sp.getSelfActions())); 1524 } catch (ClassNotFoundException cnfe) { 1525 // ok, the permission is not in the bootclasspath. 1526 // before we add an UnresolvedPermission, check to see 1527 // whether this perm already belongs to the collection. 1528 // if so, use that perm's ClassLoader to create a new 1529 // one. 1530 Class<?> pc = null; 1531 synchronized (perms) { 1532 Enumeration<Permission> e = perms.elements(); 1533 while (e.hasMoreElements()) { 1534 Permission pElement = e.nextElement(); 1535 if (pElement.getClass().getName().equals(sp.getSelfType())) { 1536 pc = pElement.getClass(); 1537 break; 1538 } 1539 } 1540 } 1541 if (pc == null) { 1542 // create an UnresolvedPermission 1543 perms.add(new UnresolvedPermission(sp.getSelfType(), 1544 sb.toString(), 1545 sp.getSelfActions(), 1546 sp.getCerts())); 1547 } else { 1548 try { 1549 // we found an instantiated permission. 1550 // use its class loader to instantiate a new permission. 1551 Constructor<?> c; 1552 // name parameter can not be null 1553 if (sp.getSelfActions() == null) { 1554 try { 1555 c = pc.getConstructor(PARAMS1); 1556 perms.add((Permission)c.newInstance 1557 (new Object[] {sb.toString()})); 1558 } catch (NoSuchMethodException ne) { 1559 c = pc.getConstructor(PARAMS2); 1560 perms.add((Permission)c.newInstance 1561 (new Object[] {sb.toString(), 1562 sp.getSelfActions() })); 1563 } 1564 } else { 1565 c = pc.getConstructor(PARAMS2); 1566 perms.add((Permission)c.newInstance 1567 (new Object[] {sb.toString(), 1568 sp.getSelfActions()})); 1569 } 1570 } catch (Exception nme) { 1571 if (debug != null) { 1572 debug.println("self entry expansion " + 1573 " instantiation failed: " 1574 + nme.toString()); 1575 } 1576 } 1577 } 1578 } catch (Exception e) { 1579 if (debug != null) { 1580 debug.println(e.toString()); 1581 } 1582 } 1583 } 1584 1585 /** 1586 * return the principal class/name pair in the 2D array. 1587 * array[x][y]: x corresponds to the array length. 1588 * if (y == 0), it's the principal class. 1589 * if (y == 1), it's the principal name. 1590 */ 1591 private String[][] getPrincipalInfo 1592 (PolicyParser.PrincipalEntry pe, Principal[] pdp) { 1593 1594 // there are 3 possibilities: 1595 // 1) the entry's Principal class and name are not wildcarded 1596 // 2) the entry's Principal name is wildcarded only 1597 // 3) the entry's Principal class and name are wildcarded 1598 1599 if (!pe.isWildcardClass() && !pe.isWildcardName()) { 1600 1601 // build an info array for the principal 1602 // from the Policy entry 1603 String[][] info = new String[1][2]; 1604 info[0][0] = pe.principalClass; 1605 info[0][1] = pe.principalName; 1606 return info; 1607 1608 } else if (!pe.isWildcardClass() && pe.isWildcardName()) { 1609 1610 // build an info array for every principal 1611 // in the current domain which has a principal class 1612 // that is equal to policy entry principal class name 1613 List<Principal> plist = new ArrayList<>(); 1614 for (int i = 0; i < pdp.length; i++) { 1615 if (pe.principalClass.equals(pdp[i].getClass().getName())) 1616 plist.add(pdp[i]); 1617 } 1618 String[][] info = new String[plist.size()][2]; 1619 int i = 0; 1620 for (Principal p : plist) { 1621 info[i][0] = p.getClass().getName(); 1622 info[i][1] = p.getName(); 1623 i++; 1624 } 1625 return info; 1626 1627 } else { 1628 1629 // build an info array for every 1630 // one of the current Domain's principals 1631 1632 String[][] info = new String[pdp.length][2]; 1633 1634 for (int i = 0; i < pdp.length; i++) { 1635 info[i][0] = pdp[i].getClass().getName(); 1636 info[i][1] = pdp[i].getName(); 1637 } 1638 return info; 1639 } 1640 } 1641 1642 /* 1643 * Returns the signer certificates from the list of certificates 1644 * associated with the given code source. 1645 * 1646 * The signer certificates are those certificates that were used 1647 * to verifysigned code originating from the codesource location. 1648 * 1649 * This method assumes that in the given code source, each signer 1650 * certificate is followed by its supporting certificate chain 1651 * (which may be empty), and that the signer certificate and its 1652 * supporting certificate chain are ordered bottom-to-top 1653 * (i.e., with the signer certificate first and the (root) certificate 1654 * authority last). 1655 */ 1656 protected Certificate[] getSignerCertificates(CodeSource cs) { 1657 Certificate[] certs = null; 1658 if ((certs = cs.getCertificates()) == null) 1659 return null; 1660 for (int i=0; i<certs.length; i++) { 1661 if (!(certs[i] instanceof X509Certificate)) 1662 return cs.getCertificates(); 1663 } 1664 1665 // Do we have to do anything? 1666 int i = 0; 1667 int count = 0; 1668 while (i < certs.length) { 1669 count++; 1670 while (((i+1) < certs.length) 1671 && ((X509Certificate)certs[i]).getIssuerDN().equals( 1672 ((X509Certificate)certs[i+1]).getSubjectDN())) { 1673 i++; 1674 } 1675 i++; 1676 } 1677 if (count == certs.length) 1678 // Done 1679 return certs; 1680 1681 List<Certificate> userCertList = new ArrayList<>(); 1682 i = 0; 1683 while (i < certs.length) { 1684 userCertList.add(certs[i]); 1685 while (((i+1) < certs.length) 1686 && ((X509Certificate)certs[i]).getIssuerDN().equals( 1687 ((X509Certificate)certs[i+1]).getSubjectDN())) { 1688 i++; 1689 } 1690 i++; 1691 } 1692 Certificate[] userCerts = new Certificate[userCertList.size()]; 1693 userCertList.toArray(userCerts); 1694 return userCerts; 1695 } 1696 1697 private CodeSource canonicalizeCodebase(CodeSource cs, 1698 boolean extractSignerCerts) { 1699 1700 String path = null; 1701 1702 CodeSource canonCs = cs; 1703 URL u = cs.getLocation(); 1704 if (u != null) { 1705 if (u.getProtocol().equals("jar")) { 1706 // unwrap url embedded inside jar url 1707 String spec = u.getFile(); 1708 int separator = spec.indexOf("!/"); 1709 if (separator != -1) { 1710 try { 1711 u = new URL(spec.substring(0, separator)); 1712 } catch (MalformedURLException e) { 1713 // Fail silently. In this case, url stays what 1714 // it was above 1715 } 1716 } 1717 } 1718 if (u.getProtocol().equals("file")) { 1719 boolean isLocalFile = false; 1720 String host = u.getHost(); 1721 isLocalFile = (host == null || host.equals("") || 1722 host.equals("~") || host.equalsIgnoreCase("localhost")); 1723 1724 if (isLocalFile) { 1725 path = u.getFile().replace('/', File.separatorChar); 1726 path = ParseUtil.decode(path); 1727 } 1728 } 1729 } 1730 1731 if (path != null) { 1732 try { 1733 URL csUrl = null; 1734 path = canonPath(path); 1735 csUrl = ParseUtil.fileToEncodedURL(new File(path)); 1736 1737 if (extractSignerCerts) { 1738 canonCs = new CodeSource(csUrl, 1739 getSignerCertificates(cs)); 1740 } else { 1741 canonCs = new CodeSource(csUrl, 1742 cs.getCertificates()); 1743 } 1744 } catch (IOException ioe) { 1745 // leave codesource as it is, unless we have to extract its 1746 // signer certificates 1747 if (extractSignerCerts) { 1748 canonCs = new CodeSource(cs.getLocation(), 1749 getSignerCertificates(cs)); 1750 } 1751 } 1752 } else { 1753 if (extractSignerCerts) { 1754 canonCs = new CodeSource(cs.getLocation(), 1755 getSignerCertificates(cs)); 1756 } 1757 } 1758 return canonCs; 1759 } 1760 1761 // Wrapper to return a canonical path that avoids calling getCanonicalPath() 1762 // with paths that are intended to match all entries in the directory 1763 private static String canonPath(String path) throws IOException { 1764 if (path.endsWith("*")) { 1765 path = path.substring(0, path.length()-1) + "-"; 1766 path = new File(path).getCanonicalPath(); 1767 return path.substring(0, path.length()-1) + "*"; 1768 } else { 1769 return new File(path).getCanonicalPath(); 1770 } 1771 } 1772 1773 private String printPD(ProtectionDomain pd) { 1774 Principal[] principals = pd.getPrincipals(); 1775 String pals = "<no principals>"; 1776 if (principals != null && principals.length > 0) { 1777 StringBuilder palSB = new StringBuilder("(principals "); 1778 for (int i = 0; i < principals.length; i++) { 1779 palSB.append(principals[i].getClass().getName()) 1780 .append(" \"").append(principals[i].getName()) 1781 .append('"'); 1782 if (i < principals.length-1) 1783 palSB.append(", "); 1784 else 1785 palSB.append(')'); 1786 } 1787 pals = palSB.toString(); 1788 } 1789 return "PD CodeSource: " 1790 + pd.getCodeSource() 1791 +"\n\t" + "PD ClassLoader: " 1792 + pd.getClassLoader() 1793 +"\n\t" + "PD Principals: " 1794 + pals; 1795 } 1796 1797 /** 1798 * return true if no replacement was performed, 1799 * or if replacement succeeded. 1800 */ 1801 private boolean replacePrincipals( 1802 List<PolicyParser.PrincipalEntry> principals, KeyStore keystore) { 1803 1804 if (principals == null || principals.isEmpty() || keystore == null) 1805 return true; 1806 1807 for (PolicyParser.PrincipalEntry pppe : principals) { 1808 if (pppe.isReplaceName()) { 1809 1810 // perform replacement 1811 // (only X509 replacement is possible now) 1812 String name; 1813 if ((name = getDN(pppe.principalName, keystore)) == null) { 1814 return false; 1815 } 1816 1817 if (debug != null) { 1818 debug.println(" Replacing \"" + 1819 pppe.principalName + 1820 "\" with " + 1821 X500PRINCIPAL + "/\"" + 1822 name + 1823 "\""); 1824 } 1825 1826 pppe.principalClass = X500PRINCIPAL; 1827 pppe.principalName = name; 1828 } 1829 } 1830 // return true if no replacement was performed, 1831 // or if replacement succeeded 1832 return true; 1833 } 1834 1835 private void expandPermissionName(PolicyParser.PermissionEntry pe, 1836 KeyStore keystore) throws Exception { 1837 // short cut the common case 1838 if (pe.name == null || pe.name.indexOf("${{", 0) == -1) { 1839 return; 1840 } 1841 1842 int startIndex = 0; 1843 int b, e; 1844 StringBuilder sb = new StringBuilder(); 1845 while ((b = pe.name.indexOf("${{", startIndex)) != -1) { 1846 e = pe.name.indexOf("}}", b); 1847 if (e < 1) { 1848 break; 1849 } 1850 sb.append(pe.name.substring(startIndex, b)); 1851 1852 // get the value in ${{...}} 1853 String value = pe.name.substring(b+3, e); 1854 1855 // parse up to the first ':' 1856 int colonIndex; 1857 String prefix = value; 1858 String suffix; 1859 if ((colonIndex = value.indexOf(':')) != -1) { 1860 prefix = value.substring(0, colonIndex); 1861 } 1862 1863 // handle different prefix possibilities 1864 if (prefix.equalsIgnoreCase("self")) { 1865 // do nothing - handled later 1866 sb.append(pe.name.substring(b, e+2)); 1867 startIndex = e+2; 1868 continue; 1869 } else if (prefix.equalsIgnoreCase("alias")) { 1870 // get the suffix and perform keystore alias replacement 1871 if (colonIndex == -1) { 1872 MessageFormat form = new MessageFormat 1873 (ResourcesMgr.getString 1874 ("alias.name.not.provided.pe.name.")); 1875 Object[] source = {pe.name}; 1876 throw new Exception(form.format(source)); 1877 } 1878 suffix = value.substring(colonIndex+1); 1879 if ((suffix = getDN(suffix, keystore)) == null) { 1880 MessageFormat form = new MessageFormat 1881 (ResourcesMgr.getString 1882 ("unable.to.perform.substitution.on.alias.suffix")); 1883 Object[] source = {value.substring(colonIndex+1)}; 1884 throw new Exception(form.format(source)); 1885 } 1886 1887 sb.append(X500PRINCIPAL).append(" \"").append(suffix).append('"'); 1888 startIndex = e+2; 1889 } else { 1890 MessageFormat form = new MessageFormat 1891 (ResourcesMgr.getString 1892 ("substitution.value.prefix.unsupported")); 1893 Object[] source = {prefix}; 1894 throw new Exception(form.format(source)); 1895 } 1896 } 1897 1898 // copy the rest of the value 1899 sb.append(pe.name.substring(startIndex)); 1900 1901 // replace the name with expanded value 1902 if (debug != null) { 1903 debug.println(" Permission name expanded from:\n\t" + 1904 pe.name + "\nto\n\t" + sb.toString()); 1905 } 1906 pe.name = sb.toString(); 1907 } 1908 1909 private String getDN(String alias, KeyStore keystore) { 1910 Certificate cert = null; 1911 try { 1912 cert = keystore.getCertificate(alias); 1913 } catch (Exception e) { 1914 if (debug != null) { 1915 debug.println(" Error retrieving certificate for '" + 1916 alias + 1917 "': " + 1918 e.toString()); 1919 } 1920 return null; 1921 } 1922 1923 if (cert == null || !(cert instanceof X509Certificate)) { 1924 if (debug != null) { 1925 debug.println(" -- No certificate for '" + 1926 alias + 1927 "' - ignoring entry"); 1928 } 1929 return null; 1930 } else { 1931 X509Certificate x509Cert = (X509Certificate)cert; 1932 1933 // 4702543: X500 names with an EmailAddress 1934 // were encoded incorrectly. create new 1935 // X500Principal name with correct encoding 1936 1937 X500Principal p = new X500Principal 1938 (x509Cert.getSubjectX500Principal().toString()); 1939 return p.getName(); 1940 } 1941 } 1942 1943 /** 1944 * Checks public key. If it is marked as trusted in 1945 * the identity database, add it to the policy 1946 * with the AllPermission. 1947 */ 1948 private boolean checkForTrustedIdentity(final Certificate cert, 1949 PolicyInfo myInfo) 1950 { 1951 return false; 1952 } 1953 1954 /** 1955 * Each entry in the policy configuration file is represented by a 1956 * PolicyEntry object. <p> 1957 * 1958 * A PolicyEntry is a (CodeSource,Permission) pair. The 1959 * CodeSource contains the (URL, PublicKey) that together identify 1960 * where the Java bytecodes come from and who (if anyone) signed 1961 * them. The URL could refer to localhost. The URL could also be 1962 * null, meaning that this policy entry is given to all comers, as 1963 * long as they match the signer field. The signer could be null, 1964 * meaning the code is not signed. <p> 1965 * 1966 * The Permission contains the (Type, Name, Action) triplet. <p> 1967 * 1968 * For now, the Policy object retrieves the public key from the 1969 * X.509 certificate on disk that corresponds to the signedBy 1970 * alias specified in the Policy config file. For reasons of 1971 * efficiency, the Policy object keeps a hashtable of certs already 1972 * read in. This could be replaced by a secure internal key 1973 * store. 1974 * 1975 * <p> 1976 * For example, the entry 1977 * <pre> 1978 * permission java.io.File "/tmp", "read,write", 1979 * signedBy "Duke"; 1980 * </pre> 1981 * is represented internally 1982 * <pre> 1983 * 1984 * FilePermission f = new FilePermission("/tmp", "read,write"); 1985 * PublicKey p = publickeys.get("Duke"); 1986 * URL u = InetAddress.getLocalHost(); 1987 * CodeBase c = new CodeBase( p, u ); 1988 * pe = new PolicyEntry(f, c); 1989 * </pre> 1990 * 1991 * @author Marianne Mueller 1992 * @author Roland Schemers 1993 * @see java.security.CodeSource 1994 * @see java.security.Policy 1995 * @see java.security.Permissions 1996 * @see java.security.ProtectionDomain 1997 */ 1998 private static class PolicyEntry { 1999 2000 private final CodeSource codesource; 2001 final List<Permission> permissions; 2002 private final List<PolicyParser.PrincipalEntry> principals; 2003 2004 /** 2005 * Given a Permission and a CodeSource, create a policy entry. 2006 * 2007 * XXX Decide if/how to add validity fields and "purpose" fields to 2008 * XXX policy entries 2009 * 2010 * @param cs the CodeSource, which encapsulates the URL and the 2011 * public key 2012 * attributes from the policy config file. Validity checks 2013 * are performed on the public key before PolicyEntry is 2014 * called. 2015 * 2016 */ 2017 PolicyEntry(CodeSource cs, List<PolicyParser.PrincipalEntry> principals) 2018 { 2019 this.codesource = cs; 2020 this.permissions = new ArrayList<Permission>(); 2021 this.principals = principals; // can be null 2022 } 2023 2024 PolicyEntry(CodeSource cs) 2025 { 2026 this(cs, null); 2027 } 2028 2029 List<PolicyParser.PrincipalEntry> getPrincipals() { 2030 return principals; // can be null 2031 } 2032 2033 /** 2034 * add a Permission object to this entry. 2035 * No need to sync add op because perms are added to entry only 2036 * while entry is being initialized 2037 */ 2038 void add(Permission p) { 2039 permissions.add(p); 2040 } 2041 2042 /** 2043 * Return the CodeSource for this policy entry 2044 */ 2045 CodeSource getCodeSource() { 2046 return codesource; 2047 } 2048 2049 @Override public String toString(){ 2050 StringBuilder sb = new StringBuilder(); 2051 sb.append(ResourcesMgr.getString("LPARAM")); 2052 sb.append(getCodeSource()); 2053 sb.append("\n"); 2054 for (int j = 0; j < permissions.size(); j++) { 2055 Permission p = permissions.get(j); 2056 sb.append(ResourcesMgr.getString("SPACE")); 2057 sb.append(ResourcesMgr.getString("SPACE")); 2058 sb.append(p); 2059 sb.append(ResourcesMgr.getString("NEWLINE")); 2060 } 2061 sb.append(ResourcesMgr.getString("RPARAM")); 2062 sb.append(ResourcesMgr.getString("NEWLINE")); 2063 return sb.toString(); 2064 } 2065 } 2066 2067 private static class SelfPermission extends Permission { 2068 2069 private static final long serialVersionUID = -8315562579967246806L; 2070 2071 /** 2072 * The class name of the Permission class that will be 2073 * created when this self permission is expanded . 2074 * 2075 * @serial 2076 */ 2077 private String type; 2078 2079 /** 2080 * The permission name. 2081 * 2082 * @serial 2083 */ 2084 private String name; 2085 2086 /** 2087 * The actions of the permission. 2088 * 2089 * @serial 2090 */ 2091 private String actions; 2092 2093 /** 2094 * The certs of the permission. 2095 * 2096 * @serial 2097 */ 2098 private Certificate certs[]; 2099 2100 /** 2101 * Creates a new SelfPermission containing the permission 2102 * information needed later to expand the self 2103 * @param type the class name of the Permission class that will be 2104 * created when this permission is expanded and if necessary resolved. 2105 * @param name the name of the permission. 2106 * @param actions the actions of the permission. 2107 * @param certs the certificates the permission's class was signed with. 2108 * This is a list of certificate chains, where each chain is composed of 2109 * a signer certificate and optionally its supporting certificate chain. 2110 * Each chain is ordered bottom-to-top (i.e., with the signer 2111 * certificate first and the (root) certificate authority last). 2112 */ 2113 public SelfPermission(String type, String name, String actions, 2114 Certificate certs[]) 2115 { 2116 super(type); 2117 if (type == null) { 2118 throw new NullPointerException 2119 (ResourcesMgr.getString("type.can.t.be.null")); 2120 } 2121 this.type = type; 2122 this.name = name; 2123 this.actions = actions; 2124 if (certs != null) { 2125 // Extract the signer certs from the list of certificates. 2126 for (int i=0; i<certs.length; i++) { 2127 if (!(certs[i] instanceof X509Certificate)) { 2128 // there is no concept of signer certs, so we store the 2129 // entire cert array 2130 this.certs = certs.clone(); 2131 break; 2132 } 2133 } 2134 2135 if (this.certs == null) { 2136 // Go through the list of certs and see if all the certs are 2137 // signer certs. 2138 int i = 0; 2139 int count = 0; 2140 while (i < certs.length) { 2141 count++; 2142 while (((i+1) < certs.length) && 2143 ((X509Certificate)certs[i]).getIssuerDN().equals( 2144 ((X509Certificate)certs[i+1]).getSubjectDN())) { 2145 i++; 2146 } 2147 i++; 2148 } 2149 if (count == certs.length) { 2150 // All the certs are signer certs, so we store the 2151 // entire array 2152 this.certs = certs.clone(); 2153 } 2154 2155 if (this.certs == null) { 2156 // extract the signer certs 2157 List<Certificate> signerCerts = new ArrayList<>(); 2158 i = 0; 2159 while (i < certs.length) { 2160 signerCerts.add(certs[i]); 2161 while (((i+1) < certs.length) && 2162 ((X509Certificate)certs[i]).getIssuerDN().equals( 2163 ((X509Certificate)certs[i+1]).getSubjectDN())) { 2164 i++; 2165 } 2166 i++; 2167 } 2168 this.certs = new Certificate[signerCerts.size()]; 2169 signerCerts.toArray(this.certs); 2170 } 2171 } 2172 } 2173 } 2174 2175 /** 2176 * This method always returns false for SelfPermission permissions. 2177 * That is, an SelfPermission never considered to 2178 * imply another permission. 2179 * 2180 * @param p the permission to check against. 2181 * 2182 * @return false. 2183 */ 2184 @Override public boolean implies(Permission p) { 2185 return false; 2186 } 2187 2188 /** 2189 * Checks two SelfPermission objects for equality. 2190 * 2191 * Checks that <i>obj</i> is an SelfPermission, and has 2192 * the same type (class) name, permission name, actions, and 2193 * certificates as this object. 2194 * 2195 * @param obj the object we are testing for equality with this object. 2196 * 2197 * @return true if obj is an SelfPermission, and has the same 2198 * type (class) name, permission name, actions, and 2199 * certificates as this object. 2200 */ 2201 @Override public boolean equals(Object obj) { 2202 if (obj == this) 2203 return true; 2204 2205 if (! (obj instanceof SelfPermission)) 2206 return false; 2207 SelfPermission that = (SelfPermission) obj; 2208 2209 if (!(this.type.equals(that.type) && 2210 this.name.equals(that.name) && 2211 this.actions.equals(that.actions))) 2212 return false; 2213 2214 if (this.certs.length != that.certs.length) 2215 return false; 2216 2217 int i,j; 2218 boolean match; 2219 2220 for (i = 0; i < this.certs.length; i++) { 2221 match = false; 2222 for (j = 0; j < that.certs.length; j++) { 2223 if (this.certs[i].equals(that.certs[j])) { 2224 match = true; 2225 break; 2226 } 2227 } 2228 if (!match) return false; 2229 } 2230 2231 for (i = 0; i < that.certs.length; i++) { 2232 match = false; 2233 for (j = 0; j < this.certs.length; j++) { 2234 if (that.certs[i].equals(this.certs[j])) { 2235 match = true; 2236 break; 2237 } 2238 } 2239 if (!match) return false; 2240 } 2241 return true; 2242 } 2243 2244 /** 2245 * Returns the hash code value for this object. 2246 * 2247 * @return a hash code value for this object. 2248 */ 2249 @Override public int hashCode() { 2250 int hash = type.hashCode(); 2251 if (name != null) 2252 hash ^= name.hashCode(); 2253 if (actions != null) 2254 hash ^= actions.hashCode(); 2255 return hash; 2256 } 2257 2258 /** 2259 * Returns the canonical string representation of the actions, 2260 * which currently is the empty string "", since there are no actions 2261 * for an SelfPermission. That is, the actions for the 2262 * permission that will be created when this SelfPermission 2263 * is resolved may be non-null, but an SelfPermission 2264 * itself is never considered to have any actions. 2265 * 2266 * @return the empty string "". 2267 */ 2268 @Override public String getActions() { 2269 return ""; 2270 } 2271 2272 public String getSelfType() { 2273 return type; 2274 } 2275 2276 public String getSelfName() { 2277 return name; 2278 } 2279 2280 public String getSelfActions() { 2281 return actions; 2282 } 2283 2284 public Certificate[] getCerts() { 2285 return certs; 2286 } 2287 2288 /** 2289 * Returns a string describing this SelfPermission. The convention 2290 * is to specify the class name, the permission name, and the actions, 2291 * in the following format: '(unresolved "ClassName" "name" "actions")'. 2292 * 2293 * @return information about this SelfPermission. 2294 */ 2295 @Override public String toString() { 2296 return "(SelfPermission " + type + " " + name + " " + actions + ")"; 2297 } 2298 } 2299 2300 /** 2301 * holds policy information that we need to synch on 2302 */ 2303 private static class PolicyInfo { 2304 private static final boolean verbose = false; 2305 2306 // Stores grant entries in the policy 2307 final List<PolicyEntry> policyEntries; 2308 2309 // Stores grant entries gotten from identity database 2310 // Use separate lists to avoid sync on policyEntries 2311 final List<PolicyEntry> identityPolicyEntries; 2312 2313 // Maps aliases to certs 2314 final Map<Object, Object> aliasMapping; 2315 2316 // Maps ProtectionDomain to PermissionCollection 2317 private final ProtectionDomainCache[] pdMapping; 2318 private java.util.Random random; 2319 2320 PolicyInfo(int numCaches) { 2321 policyEntries = new ArrayList<>(); 2322 identityPolicyEntries = 2323 Collections.synchronizedList(new ArrayList<PolicyEntry>(2)); 2324 aliasMapping = Collections.synchronizedMap(new HashMap<>(11)); 2325 2326 pdMapping = new ProtectionDomainCache[numCaches]; 2327 JavaSecurityProtectionDomainAccess jspda 2328 = SharedSecrets.getJavaSecurityProtectionDomainAccess(); 2329 for (int i = 0; i < numCaches; i++) { 2330 pdMapping[i] = jspda.getProtectionDomainCache(); 2331 } 2332 if (numCaches > 1) { 2333 random = new java.util.Random(); 2334 } 2335 } 2336 ProtectionDomainCache getPdMapping() { 2337 if (pdMapping.length == 1) { 2338 return pdMapping[0]; 2339 } else { 2340 int i = java.lang.Math.abs(random.nextInt() % pdMapping.length); 2341 return pdMapping[i]; 2342 } 2343 } 2344 } 2345 }