1 /* 2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.provider; 27 28 import java.io.*; 29 import java.lang.reflect.*; 30 import java.net.URL; 31 import java.util.*; 32 33 import java.security.AccessController; 34 import java.security.CodeSource; 35 import java.security.KeyStore; 36 import java.security.KeyStoreException; 37 import java.security.Permission; 38 import java.security.Permissions; 39 import java.security.PermissionCollection; 40 import java.security.Principal; 41 import java.security.PrivilegedAction; 42 import java.security.UnresolvedPermission; 43 import java.security.Security; 44 import java.security.cert.Certificate; 45 import java.security.cert.X509Certificate; 46 47 import javax.security.auth.Subject; 48 import javax.security.auth.PrivateCredentialPermission; 49 50 import sun.security.provider.PolicyParser.GrantEntry; 51 import sun.security.provider.PolicyParser.PermissionEntry; 52 import sun.security.provider.PolicyParser.PrincipalEntry; 53 import sun.security.util.Debug; 54 import sun.security.util.PolicyUtil; 55 import sun.security.util.PropertyExpander; 56 57 /** 58 * See {@code com.sun.security.auth.PolicyFile} for the class description. 59 * This class is necessary in order to support a default 60 * {@code javax.security.auth.Policy} implementation on the compact1 and 61 * compact2 profiles. 62 * 63 * @deprecated As of JDK 1.4, replaced by 64 * {@code sun.security.provider.PolicyFile}. 65 * This class is entirely deprecated. 66 */ 67 @Deprecated 68 @SuppressWarnings("removal") 69 public class AuthPolicyFile extends javax.security.auth.Policy { 70 71 static final ResourceBundle rb = 72 AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() { 73 @Override public ResourceBundle run() { 74 return (ResourceBundle.getBundle 75 ("sun.security.util.AuthResources")); 76 } 77 }); 78 79 private static final Debug debug = Debug.getInstance("policy", 80 "\t[Auth Policy]"); 81 82 private static final String AUTH_POLICY = "java.security.auth.policy"; 83 private static final String SECURITY_MANAGER = "java.security.manager"; 84 private static final String AUTH_POLICY_URL = "auth.policy.url."; 85 86 private Vector<PolicyEntry> policyEntries; 87 private Hashtable<Object, Object> aliasMapping; 88 89 private boolean initialized = false; 90 91 private boolean expandProperties = true; 92 private boolean ignoreIdentityScope = true; 93 94 // for use with the reflection API 95 private static final Class<?>[] PARAMS = { String.class, String.class}; 96 97 /** 98 * Initializes the Policy object and reads the default policy 99 * configuration file(s) into the Policy object. 100 */ 101 public AuthPolicyFile() { 102 // initialize Policy if either the AUTH_POLICY or 103 // SECURITY_MANAGER properties are set 104 String prop = System.getProperty(AUTH_POLICY); 105 106 if (prop == null) { 107 prop = System.getProperty(SECURITY_MANAGER); 108 } 109 if (prop != null) { 110 init(); 111 } 112 } 113 114 private synchronized void init() { 115 if (initialized) { 116 return; 117 } 118 119 policyEntries = new Vector<PolicyEntry>(); 120 aliasMapping = new Hashtable<Object, Object>(11); 121 122 initPolicyFile(); 123 initialized = true; 124 } 125 126 @Override 127 public synchronized void refresh() { 128 129 java.lang.SecurityManager sm = System.getSecurityManager(); 130 if (sm != null) { 131 sm.checkPermission(new javax.security.auth.AuthPermission 132 ("refreshPolicy")); 133 } 134 135 // XXX 136 // 137 // 1) if code instantiates PolicyFile directly, then it will need 138 // all the permissions required for the PolicyFile initialization 139 // 2) if code calls Policy.getPolicy, then it simply needs 140 // AuthPermission(getPolicy), and the javax.security.auth.Policy 141 // implementation instantiates PolicyFile in a doPrivileged block 142 // 3) if after instantiating a Policy (either via #1 or #2), 143 // code calls refresh, it simply needs 144 // AuthPermission(refreshPolicy). then PolicyFile wraps 145 // the refresh in a doPrivileged block. 146 initialized = false; 147 AccessController.doPrivileged(new PrivilegedAction<Void>() { 148 @Override public Void run() { 149 init(); 150 return null; 151 } 152 }); 153 } 154 155 private KeyStore initKeyStore(URL policyUrl, String keyStoreName, 156 String keyStoreType) { 157 if (keyStoreName != null) { 158 try { 159 /* 160 * location of keystore is specified as absolute URL in policy 161 * file, or is relative to URL of policy file 162 */ 163 URL keyStoreUrl = null; 164 try { 165 keyStoreUrl = new URL(keyStoreName); 166 // absolute URL 167 } catch (java.net.MalformedURLException e) { 168 // relative URL 169 keyStoreUrl = new URL(policyUrl, keyStoreName); 170 } 171 172 if (debug != null) { 173 debug.println("reading keystore"+keyStoreUrl); 174 } 175 176 InputStream inStream = new BufferedInputStream( 177 PolicyUtil.getInputStream(keyStoreUrl)); 178 179 KeyStore ks; 180 if (keyStoreType != null) 181 ks = KeyStore.getInstance(keyStoreType); 182 else 183 ks = KeyStore.getInstance(KeyStore.getDefaultType()); 184 ks.load(inStream, null); 185 inStream.close(); 186 return ks; 187 } catch (Exception e) { 188 // ignore, treat it like we have no keystore 189 if (debug != null) { 190 debug.println("Debug info only. No keystore."); 191 e.printStackTrace(); 192 } 193 return null; 194 } 195 } 196 return null; 197 } 198 199 private void initPolicyFile() { 200 201 String prop = Security.getProperty("policy.expandProperties"); 202 if (prop != null) { 203 expandProperties = prop.equalsIgnoreCase("true"); 204 } 205 206 String iscp = Security.getProperty("policy.ignoreIdentityScope"); 207 if (iscp != null) { 208 ignoreIdentityScope = iscp.equalsIgnoreCase("true"); 209 } 210 211 String allowSys = Security.getProperty("policy.allowSystemProperty"); 212 if (allowSys != null && allowSys.equalsIgnoreCase("true")) { 213 String extra_policy = System.getProperty(AUTH_POLICY); 214 if (extra_policy != null) { 215 boolean overrideAll = false; 216 if (extra_policy.startsWith("=")) { 217 overrideAll = true; 218 extra_policy = extra_policy.substring(1); 219 } 220 try { 221 extra_policy = PropertyExpander.expand(extra_policy); 222 URL policyURL; 223 File policyFile = new File(extra_policy); 224 if (policyFile.exists()) { 225 policyURL = 226 new URL("file:" + policyFile.getCanonicalPath()); 227 } else { 228 policyURL = new URL(extra_policy); 229 } 230 if (debug != null) { 231 debug.println("reading " + policyURL); 232 } 233 init(policyURL); 234 } catch (Exception e) { 235 // ignore. 236 if (debug != null) { 237 debug.println("caught exception: " + e); 238 } 239 240 } 241 if (overrideAll) { 242 if (debug != null) { 243 debug.println("overriding other policies!"); 244 } 245 return; 246 } 247 } 248 } 249 250 int n = 1; 251 boolean loaded_one = false; 252 String policy_url; 253 254 while ((policy_url = Security.getProperty(AUTH_POLICY_URL+n)) != null) { 255 try { 256 policy_url = PropertyExpander.expand(policy_url).replace 257 (File.separatorChar, '/'); 258 if (debug != null) { 259 debug.println("reading " + policy_url); 260 } 261 init(new URL(policy_url)); 262 loaded_one = true; 263 } catch (Exception e) { 264 if (debug != null) { 265 debug.println("Debug info only. Error reading policy " + e); 266 e.printStackTrace(); 267 } 268 // ignore that policy 269 } 270 n++; 271 } 272 273 if (loaded_one == false) { 274 // do not load a static policy 275 } 276 } 277 278 /** 279 * Checks public key. If it is marked as trusted in 280 * the identity database, add it to the policy 281 * with the AllPermission. 282 */ 283 private boolean checkForTrustedIdentity(final Certificate cert) { 284 return false; 285 } 286 287 /** 288 * Reads a policy configuration into the Policy object using a 289 * Reader object. 290 * 291 * @param policyFile the policy Reader object. 292 */ 293 private void init(URL policy) { 294 PolicyParser pp = new PolicyParser(expandProperties); 295 try (InputStreamReader isr 296 = new InputStreamReader(PolicyUtil.getInputStream(policy))) { 297 pp.read(isr); 298 KeyStore keyStore = initKeyStore(policy, pp.getKeyStoreUrl(), 299 pp.getKeyStoreType()); 300 Enumeration<GrantEntry> enum_ = pp.grantElements(); 301 while (enum_.hasMoreElements()) { 302 GrantEntry ge = enum_.nextElement(); 303 addGrantEntry(ge, keyStore); 304 } 305 } catch (PolicyParser.ParsingException pe) { 306 System.err.println(AUTH_POLICY + 307 rb.getString(".error.parsing.") + policy); 308 System.err.println(AUTH_POLICY + rb.getString("COLON") + 309 pe.getMessage()); 310 if (debug != null) { 311 pe.printStackTrace(); 312 } 313 } catch (Exception e) { 314 if (debug != null) { 315 debug.println("error parsing " + policy); 316 debug.println(e.toString()); 317 e.printStackTrace(); 318 } 319 } 320 } 321 322 /** 323 * Given a PermissionEntry, create a codeSource. 324 * 325 * @return null if signedBy alias is not recognized 326 */ 327 CodeSource getCodeSource(GrantEntry ge, KeyStore keyStore) 328 throws java.net.MalformedURLException 329 { 330 Certificate[] certs = null; 331 if (ge.signedBy != null) { 332 certs = getCertificates(keyStore, ge.signedBy); 333 if (certs == null) { 334 // we don't have a key for this alias, 335 // just return 336 if (debug != null) { 337 debug.println(" no certs for alias " + 338 ge.signedBy + ", ignoring."); 339 } 340 return null; 341 } 342 } 343 344 URL location; 345 if (ge.codeBase != null) { 346 location = new URL(ge.codeBase); 347 } else { 348 location = null; 349 } 350 351 if (ge.principals == null || ge.principals.size() == 0) { 352 return (canonicalizeCodebase 353 (new CodeSource(location, certs), 354 false)); 355 } else { 356 return (canonicalizeCodebase 357 (new SubjectCodeSource(null, ge.principals, location, certs), 358 false)); 359 } 360 } 361 362 /** 363 * Add one policy entry to the vector. 364 */ 365 private void addGrantEntry(GrantEntry ge, KeyStore keyStore) { 366 367 if (debug != null) { 368 debug.println("Adding policy entry: "); 369 debug.println(" signedBy " + ge.signedBy); 370 debug.println(" codeBase " + ge.codeBase); 371 if (ge.principals != null) { 372 for (PrincipalEntry pppe : ge.principals) { 373 debug.println(" " + pppe.getPrincipalClass() + 374 " " + pppe.getPrincipalName()); 375 } 376 } 377 debug.println(); 378 } 379 380 try { 381 CodeSource codesource = getCodeSource(ge, keyStore); 382 // skip if signedBy alias was unknown... 383 if (codesource == null) return; 384 385 PolicyEntry entry = new PolicyEntry(codesource); 386 Enumeration<PermissionEntry> enum_ = ge.permissionElements(); 387 while (enum_.hasMoreElements()) { 388 PermissionEntry pe = enum_.nextElement(); 389 try { 390 // XXX special case PrivateCredentialPermission-SELF 391 Permission perm; 392 if (pe.permission.equals 393 ("javax.security.auth.PrivateCredentialPermission") && 394 pe.name.endsWith(" self")) { 395 perm = getInstance(pe.permission, 396 pe.name + " \"self\"", 397 pe.action); 398 } else { 399 perm = getInstance(pe.permission, 400 pe.name, 401 pe.action); 402 } 403 entry.add(perm); 404 if (debug != null) { 405 debug.println(" "+perm); 406 } 407 } catch (ClassNotFoundException cnfe) { 408 Certificate[] certs; 409 if (pe.signedBy != null) { 410 certs = getCertificates(keyStore, pe.signedBy); 411 } else { 412 certs = null; 413 } 414 415 // only add if we had no signer or we had 416 // a signer and found the keys for it. 417 if (certs != null || pe.signedBy == null) { 418 Permission perm = new UnresolvedPermission( 419 pe.permission, 420 pe.name, 421 pe.action, 422 certs); 423 entry.add(perm); 424 if (debug != null) { 425 debug.println(" "+perm); 426 } 427 } 428 } catch (java.lang.reflect.InvocationTargetException ite) { 429 System.err.println 430 (AUTH_POLICY + 431 rb.getString(".error.adding.Permission.") + 432 pe.permission + 433 rb.getString("SPACE") + 434 ite.getTargetException()); 435 } catch (Exception e) { 436 System.err.println 437 (AUTH_POLICY + 438 rb.getString(".error.adding.Permission.") + 439 pe.permission + 440 rb.getString("SPACE") + 441 e); 442 } 443 } 444 policyEntries.addElement(entry); 445 } catch (Exception e) { 446 System.err.println 447 (AUTH_POLICY + 448 rb.getString(".error.adding.Entry.") + 449 ge + 450 rb.getString("SPACE") + 451 e); 452 } 453 454 if (debug != null) { 455 debug.println(); 456 } 457 } 458 459 /** 460 * Returns a new Permission object of the given Type. The Permission is 461 * created by getting the 462 * Class object using the <code>Class.forName</code> method, and using 463 * the reflection API to invoke the (String name, String actions) 464 * constructor on the 465 * object. 466 * 467 * @param type the type of Permission being created. 468 * @param name the name of the Permission being created. 469 * @param actions the actions of the Permission being created. 470 * 471 * @exception ClassNotFoundException if the particular Permission 472 * class could not be found. 473 * 474 * @exception IllegalAccessException if the class or initializer is 475 * not accessible. 476 * 477 * @exception InstantiationException if getInstance tries to 478 * instantiate an abstract class or an interface, or if the 479 * instantiation fails for some other reason. 480 * 481 * @exception NoSuchMethodException if the (String, String) constructor 482 * is not found. 483 * 484 * @exception InvocationTargetException if the underlying Permission 485 * constructor throws an exception. 486 * 487 */ 488 private static final Permission getInstance(String type, 489 String name, 490 String actions) 491 throws ClassNotFoundException, 492 InstantiationException, 493 IllegalAccessException, 494 NoSuchMethodException, 495 InvocationTargetException 496 { 497 //XXX we might want to keep a hash of created factories... 498 Class<?> pc = Class.forName(type); 499 Constructor<?> c = pc.getConstructor(PARAMS); 500 return (Permission) c.newInstance(new Object[] { name, actions }); 501 } 502 503 /** 504 * Fetch all certs associated with this alias. 505 */ 506 Certificate[] getCertificates(KeyStore keyStore, String aliases) { 507 508 Vector<Certificate> vcerts = null; 509 510 StringTokenizer st = new StringTokenizer(aliases, ","); 511 int n = 0; 512 513 while (st.hasMoreTokens()) { 514 String alias = st.nextToken().trim(); 515 n++; 516 Certificate cert = null; 517 // See if this alias's cert has already been cached 518 cert = (Certificate) aliasMapping.get(alias); 519 if (cert == null && keyStore != null) { 520 521 try { 522 cert = keyStore.getCertificate(alias); 523 } catch (KeyStoreException kse) { 524 // never happens, because keystore has already been loaded 525 // when we call this 526 } 527 if (cert != null) { 528 aliasMapping.put(alias, cert); 529 aliasMapping.put(cert, alias); 530 } 531 } 532 533 if (cert != null) { 534 if (vcerts == null) { 535 vcerts = new Vector<Certificate>(); 536 } 537 vcerts.addElement(cert); 538 } 539 } 540 541 // make sure n == vcerts.size, since we are doing a logical *and* 542 if (vcerts != null && n == vcerts.size()) { 543 Certificate[] certs = new Certificate[vcerts.size()]; 544 vcerts.copyInto(certs); 545 return certs; 546 } else { 547 return null; 548 } 549 } 550 551 /** 552 * Enumerate all the entries in the global policy object. 553 * This method is used by policy admin tools. The tools 554 * should use the Enumeration methods on the returned object 555 * to fetch the elements sequentially. 556 */ 557 private final synchronized Enumeration<PolicyEntry> elements() { 558 return policyEntries.elements(); 559 } 560 561 @Override 562 public PermissionCollection getPermissions(final Subject subject, 563 final CodeSource codesource) { 564 565 // 1) if code instantiates PolicyFile directly, then it will need 566 // all the permissions required for the PolicyFile initialization 567 // 2) if code calls Policy.getPolicy, then it simply needs 568 // AuthPermission(getPolicy), and the javax.security.auth.Policy 569 // implementation instantiates PolicyFile in a doPrivileged block 570 // 3) if after instantiating a Policy (either via #1 or #2), 571 // code calls getPermissions, PolicyFile wraps the call 572 // in a doPrivileged block. 573 return AccessController.doPrivileged 574 (new PrivilegedAction<PermissionCollection>() { 575 @Override public PermissionCollection run() { 576 SubjectCodeSource scs = new SubjectCodeSource( 577 subject, null, 578 codesource == null ? null : codesource.getLocation(), 579 codesource == null ? null : codesource.getCertificates()); 580 if (initialized) { 581 return getPermissions(new Permissions(), scs); 582 } else { 583 return new PolicyPermissions(AuthPolicyFile.this, scs); 584 } 585 } 586 }); 587 } 588 589 /** 590 * Examines the global policy for the specified CodeSource, and 591 * creates a PermissionCollection object with 592 * the set of permissions for that principal's protection domain. 593 * 594 * @param CodeSource the codesource associated with the caller. 595 * This encapsulates the original location of the code (where the code 596 * came from) and the public key(s) of its signer. 597 * 598 * @return the set of permissions according to the policy. 599 */ 600 PermissionCollection getPermissions(CodeSource codesource) { 601 602 if (initialized) { 603 return getPermissions(new Permissions(), codesource); 604 } else { 605 return new PolicyPermissions(this, codesource); 606 } 607 } 608 609 /** 610 * Examines the global policy for the specified CodeSource, and 611 * creates a PermissionCollection object with 612 * the set of permissions for that principal's protection domain. 613 * 614 * @param permissions the permissions to populate 615 * @param codesource the codesource associated with the caller. 616 * This encapsulates the original location of the code (where the code 617 * came from) and the public key(s) of its signer. 618 * 619 * @return the set of permissions according to the policy. 620 */ 621 Permissions getPermissions(final Permissions perms, 622 final CodeSource cs) 623 { 624 if (!initialized) { 625 init(); 626 } 627 628 final CodeSource[] codesource = {null}; 629 630 codesource[0] = canonicalizeCodebase(cs, true); 631 632 if (debug != null) { 633 debug.println("evaluate(" + codesource[0] + ")\n"); 634 } 635 636 // needs to be in a begin/endPrivileged block because 637 // codesource.implies calls URL.equals which does an 638 // InetAddress lookup 639 640 for (int i = 0; i < policyEntries.size(); i++) { 641 642 PolicyEntry entry = policyEntries.elementAt(i); 643 644 if (debug != null) { 645 debug.println("PolicyFile CodeSource implies: " + 646 entry.codesource.toString() + "\n\n" + 647 "\t" + codesource[0].toString() + "\n\n"); 648 } 649 650 if (entry.codesource.implies(codesource[0])) { 651 for (int j = 0; j < entry.permissions.size(); j++) { 652 Permission p = entry.permissions.elementAt(j); 653 if (debug != null) { 654 debug.println(" granting " + p); 655 } 656 if (!addSelfPermissions(p, entry.codesource, 657 codesource[0], perms)) { 658 // we could check for duplicates 659 // before adding new permissions, 660 // but the SubjectDomainCombiner 661 // already checks for duplicates later 662 perms.add(p); 663 } 664 } 665 } 666 } 667 668 // now see if any of the keys are trusted ids. 669 670 if (!ignoreIdentityScope) { 671 Certificate[] certs = codesource[0].getCertificates(); 672 if (certs != null) { 673 for (int k=0; k < certs.length; k++) { 674 if (aliasMapping.get(certs[k]) == null && 675 checkForTrustedIdentity(certs[k])) { 676 // checkForTrustedIdentity added it 677 // to the policy for us. next time 678 // around we'll find it. This time 679 // around we need to add it. 680 perms.add(new java.security.AllPermission()); 681 } 682 } 683 } 684 } 685 return perms; 686 } 687 688 /** 689 * Returns true if 'Self' permissions were added to the provided 690 * 'perms', and false otherwise. 691 * 692 * <p> 693 * 694 * @param p check to see if this Permission is a "SELF" 695 * PrivateCredentialPermission. <p> 696 * 697 * @param entryCs the codesource for the Policy entry. 698 * 699 * @param accCs the codesource for from the current AccessControlContext. 700 * 701 * @param perms the PermissionCollection where the individual 702 * PrivateCredentialPermissions will be added. 703 */ 704 private boolean addSelfPermissions(final Permission p, 705 CodeSource entryCs, 706 CodeSource accCs, 707 Permissions perms) { 708 709 if (!(p instanceof PrivateCredentialPermission)) { 710 return false; 711 } 712 713 if (!(entryCs instanceof SubjectCodeSource)) { 714 return false; 715 } 716 717 PrivateCredentialPermission pcp = (PrivateCredentialPermission)p; 718 SubjectCodeSource scs = (SubjectCodeSource)entryCs; 719 720 // see if it is a SELF permission 721 String[][] pPrincipals = pcp.getPrincipals(); 722 if (pPrincipals.length <= 0 || 723 !pPrincipals[0][0].equalsIgnoreCase("self") || 724 !pPrincipals[0][1].equalsIgnoreCase("self")) { 725 726 // regular PrivateCredentialPermission 727 return false; 728 } else { 729 730 // granted a SELF permission - create a 731 // PrivateCredentialPermission for each 732 // of the Policy entry's CodeSource Principals 733 734 if (scs.getPrincipals() == null) { 735 // XXX SubjectCodeSource has no Subject??? 736 return true; 737 } 738 739 for (PrincipalEntry principal : scs.getPrincipals()) { 740 741 // if the Policy entry's Principal does not contain a 742 // WILDCARD for the Principal name, then a 743 // new PrivateCredentialPermission is created 744 // for the Principal listed in the Policy entry. 745 // if the Policy entry's Principal contains a WILDCARD 746 // for the Principal name, then a new 747 // PrivateCredentialPermission is created 748 // for each Principal associated with the Subject 749 // in the current ACC. 750 751 String[][] principalInfo = getPrincipalInfo(principal, accCs); 752 753 for (int i = 0; i < principalInfo.length; i++) { 754 755 // here's the new PrivateCredentialPermission 756 757 PrivateCredentialPermission newPcp = 758 new PrivateCredentialPermission 759 (pcp.getCredentialClass() + 760 " " + 761 principalInfo[i][0] + 762 " " + 763 "\"" + principalInfo[i][1] + "\"", 764 "read"); 765 766 if (debug != null) { 767 debug.println("adding SELF permission: " + 768 newPcp.toString()); 769 } 770 771 perms.add(newPcp); 772 } 773 } 774 } 775 return true; 776 } 777 778 /** 779 * return the principal class/name pair in the 2D array. 780 * array[x][y]: x corresponds to the array length. 781 * if (y == 0), it's the principal class. 782 * if (y == 1), it's the principal name. 783 */ 784 private String[][] getPrincipalInfo(PrincipalEntry principal, 785 final CodeSource accCs) { 786 787 // there are 3 possibilities: 788 // 1) the entry's Principal class and name are not wildcarded 789 // 2) the entry's Principal name is wildcarded only 790 // 3) the entry's Principal class and name are wildcarded 791 792 if (!principal.getPrincipalClass().equals 793 (PrincipalEntry.WILDCARD_CLASS) && 794 !principal.getPrincipalName().equals 795 (PrincipalEntry.WILDCARD_NAME)) { 796 797 // build a PrivateCredentialPermission for the principal 798 // from the Policy entry 799 String[][] info = new String[1][2]; 800 info[0][0] = principal.getPrincipalClass(); 801 info[0][1] = principal.getPrincipalName(); 802 return info; 803 804 } else if (!principal.getPrincipalClass().equals 805 (PrincipalEntry.WILDCARD_CLASS) && 806 principal.getPrincipalName().equals 807 (PrincipalEntry.WILDCARD_NAME)) { 808 809 // build a PrivateCredentialPermission for all 810 // the Subject's principals that are instances of principalClass 811 812 // the accCs is guaranteed to be a SubjectCodeSource 813 // because the earlier CodeSource.implies succeeded 814 SubjectCodeSource scs = (SubjectCodeSource)accCs; 815 816 Set<? extends Principal> principalSet = null; 817 try { 818 // principal.principalClass should extend Principal 819 // If it doesn't, we should stop here with a ClassCastException. 820 @SuppressWarnings("unchecked") 821 Class<? extends Principal> pClass = (Class<? extends Principal>) 822 Class.forName(principal.getPrincipalClass(), false, 823 ClassLoader.getSystemClassLoader()); 824 principalSet = scs.getSubject().getPrincipals(pClass); 825 } catch (Exception e) { 826 if (debug != null) { 827 debug.println("problem finding Principal Class " + 828 "when expanding SELF permission: " + 829 e.toString()); 830 } 831 } 832 833 if (principalSet == null) { 834 // error 835 return new String[0][0]; 836 } 837 838 String[][] info = new String[principalSet.size()][2]; 839 840 int i = 0; 841 for (Principal p : principalSet) { 842 info[i][0] = p.getClass().getName(); 843 info[i][1] = p.getName(); 844 i++; 845 } 846 return info; 847 848 } else { 849 850 // build a PrivateCredentialPermission for every 851 // one of the current Subject's principals 852 853 // the accCs is guaranteed to be a SubjectCodeSource 854 // because the earlier CodeSource.implies succeeded 855 SubjectCodeSource scs = (SubjectCodeSource)accCs; 856 Set<Principal> principalSet = scs.getSubject().getPrincipals(); 857 858 String[][] info = new String[principalSet.size()][2]; 859 860 int i = 0; 861 for (Principal p : principalSet) { 862 info[i][0] = p.getClass().getName(); 863 info[i][1] = p.getName(); 864 i++; 865 } 866 return info; 867 } 868 } 869 870 /* 871 * Returns the signer certificates from the list of certificates associated 872 * with the given code source. 873 * 874 * The signer certificates are those certificates that were used to verify 875 * signed code originating from the codesource location. 876 * 877 * This method assumes that in the given code source, each signer 878 * certificate is followed by its supporting certificate chain 879 * (which may be empty), and that the signer certificate and its 880 * supporting certificate chain are ordered bottom-to-top (i.e., with the 881 * signer certificate first and the (root) certificate authority last). 882 */ 883 Certificate[] getSignerCertificates(CodeSource cs) { 884 Certificate[] certs = null; 885 if ((certs = cs.getCertificates()) == null) { 886 return null; 887 } 888 for (int i = 0; i < certs.length; i++) { 889 if (!(certs[i] instanceof X509Certificate)) 890 return cs.getCertificates(); 891 } 892 893 // Do we have to do anything? 894 int i = 0; 895 int count = 0; 896 while (i < certs.length) { 897 count++; 898 while (((i+1) < certs.length) 899 && ((X509Certificate)certs[i]).getIssuerDN().equals( 900 ((X509Certificate)certs[i+1]).getSubjectDN())) { 901 i++; 902 } 903 i++; 904 } 905 if (count == certs.length) { 906 // Done 907 return certs; 908 } 909 910 ArrayList<Certificate> userCertList = new ArrayList<>(); 911 i = 0; 912 while (i < certs.length) { 913 userCertList.add(certs[i]); 914 while (((i+1) < certs.length) 915 && ((X509Certificate)certs[i]).getIssuerDN().equals( 916 ((X509Certificate)certs[i+1]).getSubjectDN())) { 917 i++; 918 } 919 i++; 920 } 921 Certificate[] userCerts = new Certificate[userCertList.size()]; 922 userCertList.toArray(userCerts); 923 return userCerts; 924 } 925 926 private CodeSource canonicalizeCodebase(CodeSource cs, 927 boolean extractSignerCerts) { 928 CodeSource canonCs = cs; 929 if (cs.getLocation() != null && 930 cs.getLocation().getProtocol().equalsIgnoreCase("file")) { 931 try { 932 String path = cs.getLocation().getFile().replace 933 ('/', 934 File.separatorChar); 935 URL csUrl = null; 936 if (path.endsWith("*")) { 937 // remove trailing '*' because it causes canonicalization 938 // to fail on win32 939 path = path.substring(0, path.length()-1); 940 boolean appendFileSep = false; 941 if (path.endsWith(File.separator)) { 942 appendFileSep = true; 943 } 944 if (path.equals("")) { 945 path = System.getProperty("user.dir"); 946 } 947 File f = new File(path); 948 path = f.getCanonicalPath(); 949 StringBuilder sb = new StringBuilder(path); 950 // reappend '*' to canonicalized filename (note that 951 // canonicalization may have removed trailing file 952 // separator, so we have to check for that, too) 953 if (!path.endsWith(File.separator) && 954 (appendFileSep || f.isDirectory())) { 955 sb.append(File.separatorChar); 956 } 957 sb.append('*'); 958 path = sb.toString(); 959 } else { 960 path = new File(path).getCanonicalPath(); 961 } 962 csUrl = new File(path).toURL(); 963 964 if (cs instanceof SubjectCodeSource) { 965 SubjectCodeSource scs = (SubjectCodeSource)cs; 966 if (extractSignerCerts) { 967 canonCs = new SubjectCodeSource(scs.getSubject(), 968 scs.getPrincipals(), 969 csUrl, 970 getSignerCertificates(scs)); 971 } else { 972 canonCs = new SubjectCodeSource(scs.getSubject(), 973 scs.getPrincipals(), 974 csUrl, 975 scs.getCertificates()); 976 } 977 } else { 978 if (extractSignerCerts) { 979 canonCs = new CodeSource(csUrl, 980 getSignerCertificates(cs)); 981 } else { 982 canonCs = new CodeSource(csUrl, 983 cs.getCertificates()); 984 } 985 } 986 } catch (IOException ioe) { 987 // leave codesource as it is, unless we have to extract its 988 // signer certificates 989 if (extractSignerCerts) { 990 if (!(cs instanceof SubjectCodeSource)) { 991 canonCs = new CodeSource(cs.getLocation(), 992 getSignerCertificates(cs)); 993 } else { 994 SubjectCodeSource scs = (SubjectCodeSource)cs; 995 canonCs = new SubjectCodeSource(scs.getSubject(), 996 scs.getPrincipals(), 997 scs.getLocation(), 998 getSignerCertificates(scs)); 999 } 1000 } 1001 } 1002 } else { 1003 if (extractSignerCerts) { 1004 if (!(cs instanceof SubjectCodeSource)) { 1005 canonCs = new CodeSource(cs.getLocation(), 1006 getSignerCertificates(cs)); 1007 } else { 1008 SubjectCodeSource scs = (SubjectCodeSource)cs; 1009 canonCs = new SubjectCodeSource(scs.getSubject(), 1010 scs.getPrincipals(), 1011 scs.getLocation(), 1012 getSignerCertificates(scs)); 1013 } 1014 } 1015 } 1016 return canonCs; 1017 } 1018 1019 /** 1020 * Each entry in the policy configuration file is represented by a 1021 * PolicyEntry object. <p> 1022 * 1023 * A PolicyEntry is a (CodeSource,Permission) pair. The 1024 * CodeSource contains the (URL, PublicKey) that together identify 1025 * where the Java bytecodes come from and who (if anyone) signed 1026 * them. The URL could refer to localhost. The URL could also be 1027 * null, meaning that this policy entry is given to all comers, as 1028 * long as they match the signer field. The signer could be null, 1029 * meaning the code is not signed. <p> 1030 * 1031 * The Permission contains the (Type, Name, Action) triplet. <p> 1032 * 1033 * For now, the Policy object retrieves the public key from the 1034 * X.509 certificate on disk that corresponds to the signedBy 1035 * alias specified in the Policy config file. For reasons of 1036 * efficiency, the Policy object keeps a hashtable of certs already 1037 * read in. This could be replaced by a secure internal key 1038 * store. 1039 * 1040 * <p> 1041 * For example, the entry 1042 * <pre> 1043 * permission java.io.File "/tmp", "read,write", 1044 * signedBy "Duke"; 1045 * </pre> 1046 * is represented internally 1047 * <pre> 1048 * 1049 * FilePermission f = new FilePermission("/tmp", "read,write"); 1050 * PublicKey p = publickeys.get("Duke"); 1051 * URL u = InetAddress.getLocalHost(); 1052 * CodeBase c = new CodeBase( p, u ); 1053 * pe = new PolicyEntry(f, c); 1054 * </pre> 1055 * 1056 * @author Marianne Mueller 1057 * @author Roland Schemers 1058 * @see java.security.CodeSource 1059 * @see java.security.Policy 1060 * @see java.security.Permissions 1061 * @see java.security.ProtectionDomain 1062 */ 1063 private static class PolicyEntry { 1064 1065 CodeSource codesource; 1066 Vector<Permission> permissions; 1067 1068 /** 1069 * Given a Permission and a CodeSource, create a policy entry. 1070 * 1071 * XXX Decide if/how to add validity fields and "purpose" fields to 1072 * XXX policy entries 1073 * 1074 * @param cs the CodeSource, which encapsulates the URL and the public 1075 * key attributes from the policy config file. Validity checks 1076 * are performed on the public key before PolicyEntry is called. 1077 * 1078 */ 1079 PolicyEntry(CodeSource cs) { 1080 this.codesource = cs; 1081 this.permissions = new Vector<Permission>(); 1082 } 1083 1084 /** 1085 * add a Permission object to this entry. 1086 */ 1087 void add(Permission p) { 1088 permissions.addElement(p); 1089 } 1090 1091 /** 1092 * Return the CodeSource for this policy entry 1093 */ 1094 CodeSource getCodeSource() { 1095 return this.codesource; 1096 } 1097 1098 @Override 1099 public String toString(){ 1100 StringBuilder sb = new StringBuilder(); 1101 sb.append(rb.getString("LPARAM")); 1102 sb.append(getCodeSource()); 1103 sb.append("\n"); 1104 for (int j = 0; j < permissions.size(); j++) { 1105 Permission p = permissions.elementAt(j); 1106 sb.append(rb.getString("SPACE")); 1107 sb.append(rb.getString("SPACE")); 1108 sb.append(p); 1109 sb.append(rb.getString("NEWLINE")); 1110 } 1111 sb.append(rb.getString("RPARAM")); 1112 sb.append(rb.getString("NEWLINE")); 1113 return sb.toString(); 1114 } 1115 1116 } 1117 } 1118 1119 @SuppressWarnings("deprecation") 1120 class PolicyPermissions extends PermissionCollection { 1121 1122 private static final long serialVersionUID = -1954188373270545523L; 1123 1124 private CodeSource codesource; 1125 private Permissions perms; 1126 private AuthPolicyFile policy; 1127 private boolean notInit; // have we pulled in the policy permissions yet? 1128 private Vector<Permission> additionalPerms; 1129 1130 PolicyPermissions(AuthPolicyFile policy, 1131 CodeSource codesource) 1132 { 1133 this.codesource = codesource; 1134 this.policy = policy; 1135 this.perms = null; 1136 this.notInit = true; 1137 this.additionalPerms = null; 1138 } 1139 1140 @Override 1141 public void add(Permission permission) { 1142 if (isReadOnly()) 1143 throw new SecurityException 1144 (AuthPolicyFile.rb.getString 1145 ("attempt.to.add.a.Permission.to.a.readonly.PermissionCollection")); 1146 1147 if (perms == null) { 1148 if (additionalPerms == null) { 1149 additionalPerms = new Vector<Permission>(); 1150 } 1151 additionalPerms.add(permission); 1152 } else { 1153 perms.add(permission); 1154 } 1155 } 1156 1157 private synchronized void init() { 1158 if (notInit) { 1159 if (perms == null) { 1160 perms = new Permissions(); 1161 } 1162 if (additionalPerms != null) { 1163 Enumeration<Permission> e = additionalPerms.elements(); 1164 while (e.hasMoreElements()) { 1165 perms.add(e.nextElement()); 1166 } 1167 additionalPerms = null; 1168 } 1169 policy.getPermissions(perms, codesource); 1170 notInit = false; 1171 } 1172 } 1173 1174 @Override 1175 public boolean implies(Permission permission) { 1176 if (notInit) { 1177 init(); 1178 } 1179 return perms.implies(permission); 1180 } 1181 1182 @Override 1183 public Enumeration<Permission> elements() { 1184 if (notInit) { 1185 init(); 1186 } 1187 return perms.elements(); 1188 } 1189 1190 @Override 1191 public String toString() { 1192 if (notInit) { 1193 init(); 1194 } 1195 return perms.toString(); 1196 } 1197 }