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