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