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