|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  |  | 
|  | package sun.security.provider; | 
|  |  | 
|  | import java.io.*; | 
|  | import java.lang.reflect.*; | 
|  | import java.net.MalformedURLException; | 
|  | import java.net.URL; | 
|  | import java.net.URI; | 
|  | import java.nio.file.Files; | 
|  | import java.nio.file.Path; | 
|  | import java.util.*; | 
|  | import java.security.*; | 
|  | import java.security.cert.Certificate; | 
|  | import java.security.cert.X509Certificate; | 
|  | import javax.security.auth.Subject; | 
|  | import javax.security.auth.x500.X500Principal; | 
|  | import java.net.SocketPermission; | 
|  | import java.net.NetPermission; | 
|  | import java.util.concurrent.ConcurrentHashMap; | 
|  | import jdk.internal.access.JavaSecurityAccess; | 
|  | import jdk.internal.access.SharedSecrets; | 
|  | import jdk.internal.util.StaticProperty; | 
|  | import sun.nio.fs.DefaultFileSystemProvider; | 
|  | import sun.security.util.*; | 
|  | import sun.net.www.ParseUtil; | 
|  |  | 
|  | import static java.nio.charset.StandardCharsets.UTF_8; | 
|  | import static jdk.internal.access.JavaSecurityAccess.ProtectionDomainCache; | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  | @SuppressWarnings("removal") | 
|  | public class PolicyFile extends java.security.Policy { | 
|  |  | 
|  |     private static final Debug debug = Debug.getInstance("policy"); | 
|  |  | 
|  |     private static final String SELF = "${{self}}"; | 
|  |     private static final String X500PRINCIPAL = | 
|  |                         "javax.security.auth.x500.X500Principal"; | 
|  |     private static final String POLICY = "java.security.policy"; | 
|  |     private static final String POLICY_URL = "policy.url."; | 
|  |  | 
|  |     private static final int DEFAULT_CACHE_SIZE = 1; | 
|  |  | 
|  |     // contains the policy grant entries, PD cache, and alias mapping | 
|  |      | 
|  |     private volatile PolicyInfo policyInfo; | 
|  |  | 
|  |     private boolean expandProperties = true; | 
|  |     private boolean allowSystemProperties = true; | 
|  |     private boolean notUtf8 = false; | 
|  |     private URL url; | 
|  |  | 
|  |      | 
|  |     private static final Class<?>[] PARAMS0 = { }; | 
|  |     private static final Class<?>[] PARAMS1 = { String.class }; | 
|  |     private static final Class<?>[] PARAMS2 = { String.class, String.class }; | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private static Set<URL> badPolicyURLs = | 
|  |         Collections.newSetFromMap(new ConcurrentHashMap<URL,Boolean>()); | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private static final java.nio.file.FileSystem builtInFS = | 
|  |         DefaultFileSystemProvider.theFileSystem(); | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public PolicyFile() { | 
|  |         init((URL)null); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public PolicyFile(URL url) { | 
|  |         this.url = url; | 
|  |         init(url); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private void init(URL url) { | 
|  |         // Properties are set once for each init(); ignore changes | 
|  |          | 
|  |         String numCacheStr = | 
|  |           AccessController.doPrivileged(new PrivilegedAction<>() { | 
|  |             @Override | 
|  |             public String run() { | 
|  |                 expandProperties = "true".equalsIgnoreCase | 
|  |                     (Security.getProperty("policy.expandProperties")); | 
|  |                 allowSystemProperties = "true".equalsIgnoreCase | 
|  |                     (Security.getProperty("policy.allowSystemProperty")); | 
|  |                 notUtf8 = "false".equalsIgnoreCase | 
|  |                     (System.getProperty("sun.security.policy.utf8")); | 
|  |                 return System.getProperty("sun.security.policy.numcaches"); | 
|  |             }}); | 
|  |  | 
|  |         int numCaches; | 
|  |         if (numCacheStr != null) { | 
|  |             try { | 
|  |                 numCaches = Integer.parseInt(numCacheStr); | 
|  |             } catch (NumberFormatException e) { | 
|  |                 numCaches = DEFAULT_CACHE_SIZE; | 
|  |             } | 
|  |         } else { | 
|  |             numCaches = DEFAULT_CACHE_SIZE; | 
|  |         } | 
|  |         PolicyInfo newInfo = new PolicyInfo(numCaches); | 
|  |         initPolicyFile(newInfo, url); | 
|  |         policyInfo = newInfo; | 
|  |     } | 
|  |  | 
|  |     private void initPolicyFile(final PolicyInfo newInfo, final URL url) { | 
|  |  | 
|  |          | 
|  |         AccessController.doPrivileged(new PrivilegedAction<>() { | 
|  |             @Override | 
|  |             public Void run() { | 
|  |                 initDefaultPolicy(newInfo); | 
|  |                 return null; | 
|  |             } | 
|  |         }); | 
|  |  | 
|  |         if (url != null) { | 
|  |  | 
|  |             /** | 
|  |              * If the caller specified a URL via Policy.getInstance, | 
|  |              * we only read from default.policy and that URL. | 
|  |              */ | 
|  |  | 
|  |             if (debug != null) { | 
|  |                 debug.println("reading " + url); | 
|  |             } | 
|  |             AccessController.doPrivileged(new PrivilegedAction<>() { | 
|  |                 @Override | 
|  |                 public Void run() { | 
|  |                     if (init(url, newInfo) == false) { | 
|  |                          | 
|  |                         initStaticPolicy(newInfo); | 
|  |                     } | 
|  |                     return null; | 
|  |                 } | 
|  |             }); | 
|  |  | 
|  |         } else { | 
|  |  | 
|  |             /** | 
|  |              * Caller did not specify URL via Policy.getInstance. | 
|  |              * Read from URLs listed in the java.security properties file. | 
|  |              */ | 
|  |  | 
|  |             boolean loaded_one = initPolicyFile(POLICY, POLICY_URL, newInfo); | 
|  |             // To maintain strict backward compatibility | 
|  |              | 
|  |             if (!loaded_one) { | 
|  |                  | 
|  |                 initStaticPolicy(newInfo); | 
|  |             } | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     private boolean initPolicyFile(final String propname, final String urlname, | 
|  |                                    final PolicyInfo newInfo) { | 
|  |         boolean loadedPolicy = | 
|  |             AccessController.doPrivileged(new PrivilegedAction<>() { | 
|  |             @Override | 
|  |             public Boolean run() { | 
|  |                 boolean loaded_policy = false; | 
|  |  | 
|  |                 if (allowSystemProperties) { | 
|  |                     String extra_policy = System.getProperty(propname); | 
|  |                     if (extra_policy != null) { | 
|  |                         boolean overrideAll = false; | 
|  |                         if (extra_policy.startsWith("=")) { | 
|  |                             overrideAll = true; | 
|  |                             extra_policy = extra_policy.substring(1); | 
|  |                         } | 
|  |                         try { | 
|  |                             extra_policy = | 
|  |                                 PropertyExpander.expand(extra_policy); | 
|  |                             URL policyURL; | 
|  |  | 
|  |                             File policyFile = new File(extra_policy); | 
|  |                             if (policyFile.exists()) { | 
|  |                                 policyURL = ParseUtil.fileToEncodedURL | 
|  |                                     (new File(policyFile.getCanonicalPath())); | 
|  |                             } else { | 
|  |                                 policyURL = new URL(extra_policy); | 
|  |                             } | 
|  |                             if (debug != null) { | 
|  |                                 debug.println("reading "+policyURL); | 
|  |                             } | 
|  |                             if (init(policyURL, newInfo)) { | 
|  |                                 loaded_policy = true; | 
|  |                             } | 
|  |                         } catch (Exception e) { | 
|  |                              | 
|  |                             if (debug != null) { | 
|  |                                 debug.println("caught exception: "+e); | 
|  |                             } | 
|  |                         } | 
|  |                         if (overrideAll) { | 
|  |                             if (debug != null) { | 
|  |                                 debug.println("overriding other policies!"); | 
|  |                             } | 
|  |                             return Boolean.valueOf(loaded_policy); | 
|  |                         } | 
|  |                     } | 
|  |                 } | 
|  |  | 
|  |                 int n = 1; | 
|  |                 String policy_uri; | 
|  |  | 
|  |                 while ((policy_uri = Security.getProperty(urlname+n)) != null) { | 
|  |                     try { | 
|  |                         URL policy_url = null; | 
|  |                         String expanded_uri = PropertyExpander.expand | 
|  |                                 (policy_uri).replace(File.separatorChar, '/'); | 
|  |  | 
|  |                         if (policy_uri.startsWith("file:${java.home}/") || | 
|  |                             policy_uri.startsWith("file:${user.home}/")) { | 
|  |  | 
|  |                             // this special case accommodates | 
|  |                             // the situation java.home/user.home | 
|  |                             // expand to a single slash, resulting in | 
|  |                              | 
|  |                             policy_url = new File | 
|  |                                 (expanded_uri.substring(5)).toURI().toURL(); | 
|  |                         } else { | 
|  |                             policy_url = new URI(expanded_uri).toURL(); | 
|  |                         } | 
|  |  | 
|  |                         if (debug != null) { | 
|  |                             debug.println("reading " + policy_url); | 
|  |                         } | 
|  |                         if (init(policy_url, newInfo)) { | 
|  |                             loaded_policy = true; | 
|  |                         } | 
|  |                     } catch (Exception e) { | 
|  |                         if (debug != null) { | 
|  |                             debug.println( | 
|  |                                 "Debug info only. Error reading policy " +e); | 
|  |                             e.printStackTrace(); | 
|  |                         } | 
|  |                         // ignore that policy | 
|  |                     } | 
|  |                     n++; | 
|  |                 } | 
|  |                 return Boolean.valueOf(loaded_policy); | 
|  |             } | 
|  |         }); | 
|  |  | 
|  |         return loadedPolicy; | 
|  |     } | 
|  |  | 
|  |     private void initDefaultPolicy(PolicyInfo newInfo) { | 
|  |         Path defaultPolicy = builtInFS.getPath(StaticProperty.javaHome(), | 
|  |                                      "lib", | 
|  |                                      "security", | 
|  |                                      "default.policy"); | 
|  |         if (debug != null) { | 
|  |             debug.println("reading " + defaultPolicy); | 
|  |         } | 
|  |         try (BufferedReader br = Files.newBufferedReader(defaultPolicy)) { | 
|  |  | 
|  |             PolicyParser pp = new PolicyParser(expandProperties); | 
|  |             pp.read(br); | 
|  |  | 
|  |             Enumeration<PolicyParser.GrantEntry> enum_ = pp.grantElements(); | 
|  |             while (enum_.hasMoreElements()) { | 
|  |                 PolicyParser.GrantEntry ge = enum_.nextElement(); | 
|  |                 addGrantEntry(ge, null, newInfo); | 
|  |             } | 
|  |         } catch (Exception e) { | 
|  |             throw new InternalError("Failed to load default.policy", e); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private boolean init(URL policy, PolicyInfo newInfo) { | 
|  |  | 
|  |         // skip parsing policy file if it has been previously parsed and | 
|  |          | 
|  |         if (badPolicyURLs.contains(policy)) { | 
|  |             if (debug != null) { | 
|  |                 debug.println("skipping bad policy file: " + policy); | 
|  |             } | 
|  |             return false; | 
|  |         } | 
|  |  | 
|  |         try (InputStreamReader isr = | 
|  |                  getInputStreamReader(PolicyUtil.getInputStream(policy))) { | 
|  |  | 
|  |             PolicyParser pp = new PolicyParser(expandProperties); | 
|  |             pp.read(isr); | 
|  |  | 
|  |             KeyStore keyStore = null; | 
|  |             try { | 
|  |                 keyStore = PolicyUtil.getKeyStore | 
|  |                                 (policy, | 
|  |                                 pp.getKeyStoreUrl(), | 
|  |                                 pp.getKeyStoreType(), | 
|  |                                 pp.getKeyStoreProvider(), | 
|  |                                 pp.getStorePassURL(), | 
|  |                                 debug); | 
|  |             } catch (Exception e) { | 
|  |                  | 
|  |                 if (debug != null) { | 
|  |                     debug.println("Debug info only. Ignoring exception."); | 
|  |                     e.printStackTrace(); | 
|  |                 } | 
|  |             } | 
|  |  | 
|  |             Enumeration<PolicyParser.GrantEntry> enum_ = pp.grantElements(); | 
|  |             while (enum_.hasMoreElements()) { | 
|  |                 PolicyParser.GrantEntry ge = enum_.nextElement(); | 
|  |                 addGrantEntry(ge, keyStore, newInfo); | 
|  |             } | 
|  |             return true; | 
|  |         } catch (PolicyParser.ParsingException pe) { | 
|  |              | 
|  |             badPolicyURLs.add(policy); | 
|  |             Object[] source = {policy, pe.getNonlocalizedMessage()}; | 
|  |             System.err.println(LocalizedMessage.getNonlocalized | 
|  |                 (POLICY + ".error.parsing.policy.message", source)); | 
|  |             if (debug != null) { | 
|  |                 pe.printStackTrace(); | 
|  |             } | 
|  |         } catch (Exception e) { | 
|  |             if (debug != null) { | 
|  |                 debug.println("error parsing "+policy); | 
|  |                 debug.println(e.toString()); | 
|  |                 e.printStackTrace(); | 
|  |             } | 
|  |         } | 
|  |  | 
|  |         return false; | 
|  |     } | 
|  |  | 
|  |     private InputStreamReader getInputStreamReader(InputStream is) { | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         return (notUtf8) | 
|  |             ? new InputStreamReader(is) | 
|  |             : new InputStreamReader(is, UTF_8); | 
|  |     } | 
|  |  | 
|  |     private void initStaticPolicy(final PolicyInfo newInfo) { | 
|  |         if (debug != null) { | 
|  |             debug.println("Initializing with static permissions"); | 
|  |         } | 
|  |         AccessController.doPrivileged(new PrivilegedAction<>() { | 
|  |             @Override | 
|  |             public Void run() { | 
|  |                 PolicyEntry pe = new PolicyEntry(new CodeSource(null, | 
|  |                     (Certificate[]) null)); | 
|  |                 pe.add(SecurityConstants.LOCAL_LISTEN_PERMISSION); | 
|  |                 pe.add(new PropertyPermission("java.version", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("java.vendor", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("java.vendor.url", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("java.class.version", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("os.name", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("os.version", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("os.arch", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("file.separator", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("path.separator", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("line.separator", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission | 
|  |                                 ("java.specification.version", | 
|  |                                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission | 
|  |                                 ("java.specification.vendor", | 
|  |                                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission | 
|  |                                 ("java.specification.name", | 
|  |                                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission | 
|  |                                 ("java.vm.specification.version", | 
|  |                                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission | 
|  |                                 ("java.vm.specification.vendor", | 
|  |                                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission | 
|  |                                 ("java.vm.specification.name", | 
|  |                                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("java.vm.version", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("java.vm.vendor", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |                 pe.add(new PropertyPermission("java.vm.name", | 
|  |                     SecurityConstants.PROPERTY_READ_ACTION)); | 
|  |  | 
|  |                  | 
|  |                 newInfo.policyEntries.add(pe); | 
|  |  | 
|  |                 return null; | 
|  |             } | 
|  |         }); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private CodeSource getCodeSource(PolicyParser.GrantEntry ge, KeyStore keyStore, | 
|  |         PolicyInfo newInfo) throws java.net.MalformedURLException | 
|  |     { | 
|  |         Certificate[] certs = null; | 
|  |         if (ge.signedBy != null) { | 
|  |             certs = getCertificates(keyStore, ge.signedBy, newInfo); | 
|  |             if (certs == null) { | 
|  |                 // we don't have a key for this alias, | 
|  |                  | 
|  |                 if (debug != null) { | 
|  |                     debug.println("  -- No certs for alias '" + | 
|  |                                        ge.signedBy + "' - ignoring entry"); | 
|  |                 } | 
|  |                 return null; | 
|  |             } | 
|  |         } | 
|  |  | 
|  |         URL location; | 
|  |  | 
|  |         if (ge.codeBase != null) | 
|  |             location = new URL(ge.codeBase); | 
|  |         else | 
|  |             location = null; | 
|  |  | 
|  |         return (canonicalizeCodebase(new CodeSource(location, certs),false)); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     private void addGrantEntry(PolicyParser.GrantEntry ge, | 
|  |                                KeyStore keyStore, PolicyInfo newInfo) { | 
|  |  | 
|  |         if (debug != null) { | 
|  |             debug.println("Adding policy entry: "); | 
|  |             debug.println("  signedBy " + ge.signedBy); | 
|  |             debug.println("  codeBase " + ge.codeBase); | 
|  |             if (ge.principals != null) { | 
|  |                 for (PolicyParser.PrincipalEntry pppe : ge.principals) { | 
|  |                     debug.println("  " + pppe.toString()); | 
|  |                 } | 
|  |             } | 
|  |         } | 
|  |  | 
|  |         try { | 
|  |             CodeSource codesource = getCodeSource(ge, keyStore, newInfo); | 
|  |              | 
|  |             if (codesource == null) return; | 
|  |  | 
|  |             // perform keystore alias principal replacement. | 
|  |             // for example, if alias resolves to X509 certificate, | 
|  |             // replace principal with:  <X500Principal class>  <SubjectDN> | 
|  |              | 
|  |             if (replacePrincipals(ge.principals, keyStore) == false) | 
|  |                 return; | 
|  |             PolicyEntry entry = new PolicyEntry(codesource, ge.principals); | 
|  |             Enumeration<PolicyParser.PermissionEntry> enum_ = | 
|  |                                                 ge.permissionElements(); | 
|  |             while (enum_.hasMoreElements()) { | 
|  |                 PolicyParser.PermissionEntry pe = enum_.nextElement(); | 
|  |  | 
|  |                 try { | 
|  |                      | 
|  |                     expandPermissionName(pe, keyStore); | 
|  |  | 
|  |                      | 
|  |                     Permission perm; | 
|  |                     if (pe.permission.equals | 
|  |                         ("javax.security.auth.PrivateCredentialPermission") && | 
|  |                         pe.name.endsWith(" self")) { | 
|  |                         pe.name = pe.name.substring(0, pe.name.indexOf("self")) | 
|  |                                 + SELF; | 
|  |                     } | 
|  |                      | 
|  |                     if (pe.name != null && pe.name.indexOf(SELF) != -1) { | 
|  |                         // Create a "SelfPermission" , it could be an | 
|  |                         // an unresolved permission which will be resolved | 
|  |                         // when implies is called | 
|  |                          | 
|  |                         Certificate[] certs; | 
|  |                         if (pe.signedBy != null) { | 
|  |                             certs = getCertificates(keyStore, | 
|  |                                                     pe.signedBy, | 
|  |                                                     newInfo); | 
|  |                         } else { | 
|  |                             certs = null; | 
|  |                         } | 
|  |                         perm = new SelfPermission(pe.permission, | 
|  |                                                   pe.name, | 
|  |                                                   pe.action, | 
|  |                                                   certs); | 
|  |                     } else { | 
|  |                         perm = getInstance(pe.permission, | 
|  |                                            pe.name, | 
|  |                                            pe.action); | 
|  |                     } | 
|  |                     entry.add(perm); | 
|  |                     if (debug != null) { | 
|  |                         debug.println("  "+perm); | 
|  |                     } | 
|  |                 } catch (ClassNotFoundException cnfe) { | 
|  |                     Certificate[] certs; | 
|  |                     if (pe.signedBy != null) { | 
|  |                         certs = getCertificates(keyStore, | 
|  |                                                 pe.signedBy, | 
|  |                                                 newInfo); | 
|  |                     } else { | 
|  |                         certs = null; | 
|  |                     } | 
|  |  | 
|  |                     // only add if we had no signer or we had | 
|  |                      | 
|  |                     if (certs != null || pe.signedBy == null) { | 
|  |                         Permission perm = new UnresolvedPermission( | 
|  |                                                   pe.permission, | 
|  |                                                   pe.name, | 
|  |                                                   pe.action, | 
|  |                                                   certs); | 
|  |                         entry.add(perm); | 
|  |                         if (debug != null) { | 
|  |                             debug.println("  "+perm); | 
|  |                         } | 
|  |                     } | 
|  |                 } catch (java.lang.reflect.InvocationTargetException ite) { | 
|  |                     Object[] source = {pe.permission, | 
|  |                                        ite.getCause().toString()}; | 
|  |                     System.err.println( | 
|  |                         LocalizedMessage.getNonlocalized( | 
|  |                             POLICY + ".error.adding.Permission.perm.message", | 
|  |                             source)); | 
|  |                 } catch (Exception e) { | 
|  |                     Object[] source = {pe.permission, | 
|  |                                        e.toString()}; | 
|  |                     System.err.println( | 
|  |                         LocalizedMessage.getNonlocalized( | 
|  |                             POLICY + ".error.adding.Permission.perm.message", | 
|  |                             source)); | 
|  |                 } | 
|  |             } | 
|  |  | 
|  |              | 
|  |             newInfo.policyEntries.add(entry); | 
|  |         } catch (Exception e) { | 
|  |             Object[] source = {e.toString()}; | 
|  |             System.err.println( | 
|  |                 LocalizedMessage.getNonlocalized( | 
|  |                     POLICY + ".error.adding.Entry.message", | 
|  |                     source)); | 
|  |         } | 
|  |         if (debug != null) | 
|  |             debug.println(); | 
|  |     } | 
|  |  | 
|  |     /** | 
|  |      * Returns a new Permission object of the given Type. The Permission is | 
|  |      * created by getting the | 
|  |      * Class object using the <code>Class.forName</code> method, and using | 
|  |      * the reflection API to invoke the (String name, String actions) | 
|  |      * constructor on the | 
|  |      * object. | 
|  |      * | 
|  |      * @param type the type of Permission being created. | 
|  |      * @param name the name of the Permission being created. | 
|  |      * @param actions the actions of the Permission being created. | 
|  |      * | 
|  |      * @exception  ClassNotFoundException  if the particular Permission | 
|  |      *             class could not be found. | 
|  |      * | 
|  |      * @exception  IllegalAccessException  if the class or initializer is | 
|  |      *               not accessible. | 
|  |      * | 
|  |      * @exception  InstantiationException  if getInstance tries to | 
|  |      *               instantiate an abstract class or an interface, or if the | 
|  |      *               instantiation fails for some other reason. | 
|  |      * | 
|  |      * @exception  NoSuchMethodException if the (String, String) constructor | 
|  |      *               is not found. | 
|  |      * | 
|  |      * @exception  InvocationTargetException if the underlying Permission | 
|  |      *               constructor throws an exception. | 
|  |      * | 
|  |      */ | 
|  |  | 
|  |     private static final Permission getInstance(String type, | 
|  |                                     String name, | 
|  |                                     String actions) | 
|  |         throws ClassNotFoundException, | 
|  |                InstantiationException, | 
|  |                IllegalAccessException, | 
|  |                NoSuchMethodException, | 
|  |                InvocationTargetException | 
|  |     { | 
|  |         Class<?> pc = Class.forName(type, false, null); | 
|  |         Permission answer = getKnownPermission(pc, name, actions); | 
|  |         if (answer != null) { | 
|  |             return answer; | 
|  |         } | 
|  |         if (!Permission.class.isAssignableFrom(pc)) { | 
|  |              | 
|  |             throw new ClassCastException(type + " is not a Permission"); | 
|  |         } | 
|  |  | 
|  |         if (name == null && actions == null) { | 
|  |             try { | 
|  |                 Constructor<?> c = pc.getConstructor(PARAMS0); | 
|  |                 return (Permission) c.newInstance(new Object[] {}); | 
|  |             } catch (NoSuchMethodException ne) { | 
|  |                 try { | 
|  |                     Constructor<?> c = pc.getConstructor(PARAMS1); | 
|  |                     return (Permission) c.newInstance( | 
|  |                               new Object[] { name}); | 
|  |                 } catch (NoSuchMethodException ne1 ) { | 
|  |                     Constructor<?> c = pc.getConstructor(PARAMS2); | 
|  |                     return (Permission) c.newInstance( | 
|  |                         new Object[] { name, actions }); | 
|  |                 } | 
|  |             } | 
|  |         } else { | 
|  |             if (name != null && actions == null) { | 
|  |                 try { | 
|  |                     Constructor<?> c = pc.getConstructor(PARAMS1); | 
|  |                     return (Permission) c.newInstance(new Object[] { name}); | 
|  |                 } catch (NoSuchMethodException ne) { | 
|  |                     Constructor<?> c = pc.getConstructor(PARAMS2); | 
|  |                     return (Permission) c.newInstance( | 
|  |                           new Object[] { name, actions }); | 
|  |                 } | 
|  |             } else { | 
|  |                 Constructor<?> c = pc.getConstructor(PARAMS2); | 
|  |                 return (Permission) c.newInstance( | 
|  |                       new Object[] { name, actions }); | 
|  |              } | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private static Permission getKnownPermission(Class<?> claz, String name, | 
|  |                                                  String actions) { | 
|  |         if (claz.equals(FilePermission.class)) { | 
|  |             return new FilePermission(name, actions); | 
|  |         } else if (claz.equals(SocketPermission.class)) { | 
|  |             return new SocketPermission(name, actions); | 
|  |         } else if (claz.equals(RuntimePermission.class)) { | 
|  |             return new RuntimePermission(name, actions); | 
|  |         } else if (claz.equals(PropertyPermission.class)) { | 
|  |             return new PropertyPermission(name, actions); | 
|  |         } else if (claz.equals(NetPermission.class)) { | 
|  |             return new NetPermission(name, actions); | 
|  |         } else if (claz.equals(AllPermission.class)) { | 
|  |             return SecurityConstants.ALL_PERMISSION; | 
|  |         } else if (claz.equals(SecurityPermission.class)) { | 
|  |             return new SecurityPermission(name, actions); | 
|  |         } else { | 
|  |             return null; | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private static Principal getKnownPrincipal(Class<?> claz, String name) { | 
|  |         if (claz.equals(X500Principal.class)) { | 
|  |             return new X500Principal(name); | 
|  |         } else { | 
|  |             return null; | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     private Certificate[] getCertificates | 
|  |                 (KeyStore keyStore, String aliases, PolicyInfo newInfo) { | 
|  |  | 
|  |         List<Certificate> vcerts = null; | 
|  |  | 
|  |         StringTokenizer st = new StringTokenizer(aliases, ","); | 
|  |         int n = 0; | 
|  |  | 
|  |         while (st.hasMoreTokens()) { | 
|  |             String alias = st.nextToken().trim(); | 
|  |             n++; | 
|  |             Certificate cert = null; | 
|  |              | 
|  |             synchronized (newInfo.aliasMapping) { | 
|  |                 cert = (Certificate)newInfo.aliasMapping.get(alias); | 
|  |  | 
|  |                 if (cert == null && keyStore != null) { | 
|  |  | 
|  |                     try { | 
|  |                         cert = keyStore.getCertificate(alias); | 
|  |                     } catch (KeyStoreException kse) { | 
|  |                         // never happens, because keystore has already been loaded | 
|  |                         // when we call this | 
|  |                     } | 
|  |                     if (cert != null) { | 
|  |                         newInfo.aliasMapping.put(alias, cert); | 
|  |                         newInfo.aliasMapping.put(cert, alias); | 
|  |                     } | 
|  |                 } | 
|  |             } | 
|  |  | 
|  |             if (cert != null) { | 
|  |                 if (vcerts == null) | 
|  |                     vcerts = new ArrayList<>(); | 
|  |                 vcerts.add(cert); | 
|  |             } | 
|  |         } | 
|  |  | 
|  |          | 
|  |         if (vcerts != null && n == vcerts.size()) { | 
|  |             Certificate[] certs = new Certificate[vcerts.size()]; | 
|  |             vcerts.toArray(certs); | 
|  |             return certs; | 
|  |         } else { | 
|  |             return null; | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     @Override public void refresh() { | 
|  |         init(url); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public boolean implies(ProtectionDomain pd, Permission p) { | 
|  |         ProtectionDomainCache pdMap = policyInfo.getPdMapping(); | 
|  |         PermissionCollection pc = pdMap.get(pd); | 
|  |  | 
|  |         if (pc != null) { | 
|  |             return pc.implies(p); | 
|  |         } | 
|  |  | 
|  |         pc = getPermissions(pd); | 
|  |         if (pc == null) { | 
|  |             return false; | 
|  |         } | 
|  |  | 
|  |          | 
|  |         pdMap.put(pd, pc); | 
|  |         return pc.implies(p); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public PermissionCollection getPermissions(ProtectionDomain domain) { | 
|  |         Permissions perms = new Permissions(); | 
|  |  | 
|  |         if (domain == null) | 
|  |            return perms; | 
|  |  | 
|  |          | 
|  |         getPermissions(perms, domain); | 
|  |  | 
|  |         // add static perms | 
|  |         //      - adding static perms after policy perms is necessary | 
|  |          | 
|  |         PermissionCollection pc = domain.getPermissions(); | 
|  |         if (pc != null) { | 
|  |             synchronized (pc) { | 
|  |                 Enumeration<Permission> e = pc.elements(); | 
|  |                 while (e.hasMoreElements()) { | 
|  |                     perms.add(FilePermCompat.newPermPlusAltPath(e.nextElement())); | 
|  |                 } | 
|  |             } | 
|  |         } | 
|  |  | 
|  |         return perms; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public PermissionCollection getPermissions(CodeSource codesource) { | 
|  |         return getPermissions(new Permissions(), codesource); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private PermissionCollection getPermissions(Permissions perms, | 
|  |                                         ProtectionDomain pd ) { | 
|  |         if (debug != null) { | 
|  |             debug.println("getPermissions:\n\t" + printPD(pd)); | 
|  |         } | 
|  |  | 
|  |         final CodeSource cs = pd.getCodeSource(); | 
|  |         if (cs == null) | 
|  |             return perms; | 
|  |  | 
|  |         CodeSource canonCodeSource = AccessController.doPrivileged( | 
|  |             new java.security.PrivilegedAction<>(){ | 
|  |                 @Override | 
|  |                 public CodeSource run() { | 
|  |                     return canonicalizeCodebase(cs, true); | 
|  |                 } | 
|  |             }); | 
|  |         return getPermissions(perms, canonCodeSource, pd.getPrincipals()); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private PermissionCollection getPermissions(Permissions perms, | 
|  |                                                 final CodeSource cs) { | 
|  |  | 
|  |         if (cs == null) | 
|  |             return perms; | 
|  |  | 
|  |         CodeSource canonCodeSource = AccessController.doPrivileged( | 
|  |             new PrivilegedAction<>(){ | 
|  |                 @Override | 
|  |                 public CodeSource run() { | 
|  |                     return canonicalizeCodebase(cs, true); | 
|  |                 } | 
|  |             }); | 
|  |  | 
|  |         return getPermissions(perms, canonCodeSource, null); | 
|  |     } | 
|  |  | 
|  |     private Permissions getPermissions(Permissions perms, | 
|  |                                        final CodeSource cs, | 
|  |                                        Principal[] principals) { | 
|  |         for (PolicyEntry entry : policyInfo.policyEntries) { | 
|  |             addPermissions(perms, cs, principals, entry); | 
|  |         } | 
|  |  | 
|  |         return perms; | 
|  |     } | 
|  |  | 
|  |     private void addPermissions(Permissions perms, | 
|  |         final CodeSource cs, | 
|  |         Principal[] principals, | 
|  |         final PolicyEntry entry) { | 
|  |  | 
|  |         if (debug != null) { | 
|  |             debug.println("evaluate codesources:\n" + | 
|  |                 "\tPolicy CodeSource: " + entry.getCodeSource() + "\n" + | 
|  |                 "\tActive CodeSource: " + cs); | 
|  |         } | 
|  |  | 
|  |          | 
|  |         Boolean imp = AccessController.doPrivileged | 
|  |             (new PrivilegedAction<>() { | 
|  |             @Override | 
|  |             public Boolean run() { | 
|  |                 return entry.getCodeSource().implies(cs); | 
|  |             } | 
|  |         }); | 
|  |         if (!imp.booleanValue()) { | 
|  |             if (debug != null) { | 
|  |                 debug.println("evaluation (codesource) failed"); | 
|  |             } | 
|  |  | 
|  |              | 
|  |             return; | 
|  |         } | 
|  |  | 
|  |         // check to see if the Principals imply | 
|  |  | 
|  |         List<PolicyParser.PrincipalEntry> entryPs = entry.getPrincipals(); | 
|  |         if (debug != null) { | 
|  |             List<PolicyParser.PrincipalEntry> accPs = new ArrayList<>(); | 
|  |             if (principals != null) { | 
|  |                 for (int i = 0; i < principals.length; i++) { | 
|  |                     accPs.add(new PolicyParser.PrincipalEntry | 
|  |                                         (principals[i].getClass().getName(), | 
|  |                                         principals[i].getName())); | 
|  |                 } | 
|  |             } | 
|  |             debug.println("evaluate principals:\n" + | 
|  |                 "\tPolicy Principals: " + entryPs + "\n" + | 
|  |                 "\tActive Principals: " + accPs); | 
|  |         } | 
|  |  | 
|  |         if (entryPs == null || entryPs.isEmpty()) { | 
|  |  | 
|  |             // policy entry has no principals - | 
|  |             // add perms regardless of principals in current ACC | 
|  |  | 
|  |             addPerms(perms, principals, entry); | 
|  |             if (debug != null) { | 
|  |                 debug.println("evaluation (codesource/principals) passed"); | 
|  |             } | 
|  |             return; | 
|  |  | 
|  |         } else if (principals == null || principals.length == 0) { | 
|  |  | 
|  |             // current thread has no principals but this policy entry | 
|  |             // has principals - perms are not added | 
|  |  | 
|  |             if (debug != null) { | 
|  |                 debug.println("evaluation (principals) failed"); | 
|  |             } | 
|  |             return; | 
|  |         } | 
|  |  | 
|  |         // current thread has principals and this policy entry | 
|  |         // has principals.  see if policy entry principals match | 
|  |         // principals in current ACC | 
|  |  | 
|  |         for (PolicyParser.PrincipalEntry pppe : entryPs) { | 
|  |  | 
|  |              | 
|  |             if (pppe.isWildcardClass()) { | 
|  |                  | 
|  |                 continue; | 
|  |             } | 
|  |  | 
|  |             if (pppe.isWildcardName()) { | 
|  |                  | 
|  |                 if (wildcardPrincipalNameImplies(pppe.principalClass, | 
|  |                                                  principals)) { | 
|  |                     continue; | 
|  |                 } | 
|  |                 if (debug != null) { | 
|  |                     debug.println("evaluation (principal name wildcard) failed"); | 
|  |                 } | 
|  |                 // policy entry principal not in current ACC - | 
|  |                  | 
|  |                 return; | 
|  |             } | 
|  |  | 
|  |             Set<Principal> pSet = new HashSet<>(Arrays.asList(principals)); | 
|  |             Subject subject = new Subject(true, pSet, | 
|  |                                           Collections.EMPTY_SET, | 
|  |                                           Collections.EMPTY_SET); | 
|  |             try { | 
|  |                 ClassLoader cl = Thread.currentThread().getContextClassLoader(); | 
|  |                 Class<?> pClass = Class.forName(pppe.principalClass, false, cl); | 
|  |                 Principal p = getKnownPrincipal(pClass, pppe.principalName); | 
|  |                 if (p == null) { | 
|  |                     if (!Principal.class.isAssignableFrom(pClass)) { | 
|  |                          | 
|  |                         throw new ClassCastException(pppe.principalClass + | 
|  |                                                      " is not a Principal"); | 
|  |                     } | 
|  |  | 
|  |                     Constructor<?> c = pClass.getConstructor(PARAMS1); | 
|  |                     p = (Principal)c.newInstance(new Object[] { | 
|  |                                                  pppe.principalName }); | 
|  |  | 
|  |                 } | 
|  |  | 
|  |                 if (debug != null) { | 
|  |                     debug.println("found Principal " + p.getClass().getName()); | 
|  |                 } | 
|  |  | 
|  |                 // check if the Principal implies the current | 
|  |                  | 
|  |                 if (!p.implies(subject)) { | 
|  |                     if (debug != null) { | 
|  |                         debug.println("evaluation (principal implies) failed"); | 
|  |                     } | 
|  |  | 
|  |                     // policy principal does not imply the current Subject - | 
|  |                      | 
|  |                     return; | 
|  |                 } | 
|  |             } catch (Exception e) { | 
|  |                 // fall back to default principal comparison. | 
|  |                 // see if policy entry principal is in current ACC | 
|  |  | 
|  |                 if (debug != null) { | 
|  |                     e.printStackTrace(); | 
|  |                 } | 
|  |  | 
|  |                 if (!pppe.implies(subject)) { | 
|  |                     if (debug != null) { | 
|  |                         debug.println("evaluation (default principal implies) failed"); | 
|  |                     } | 
|  |  | 
|  |                     // policy entry principal not in current ACC - | 
|  |                      | 
|  |                     return; | 
|  |                 } | 
|  |             } | 
|  |  | 
|  |             // either the principal information matched, | 
|  |             // or the Principal.implies succeeded. | 
|  |             // continue loop and test the next policy principal | 
|  |         } | 
|  |  | 
|  |         // all policy entry principals were found in the current ACC - | 
|  |         // grant the policy permissions | 
|  |  | 
|  |         if (debug != null) { | 
|  |             debug.println("evaluation (codesource/principals) passed"); | 
|  |         } | 
|  |         addPerms(perms, principals, entry); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private static boolean wildcardPrincipalNameImplies(String principalClass, | 
|  |                                                         Principal[] principals) | 
|  |     { | 
|  |         for (Principal p : principals) { | 
|  |             if (principalClass.equals(p.getClass().getName())) { | 
|  |                 return true; | 
|  |             } | 
|  |         } | 
|  |         return false; | 
|  |     } | 
|  |  | 
|  |     private void addPerms(Permissions perms, | 
|  |                         Principal[] accPs, | 
|  |                         PolicyEntry entry) { | 
|  |         for (int i = 0; i < entry.permissions.size(); i++) { | 
|  |             Permission p = entry.permissions.get(i); | 
|  |             if (debug != null) { | 
|  |                 debug.println("  granting " + p); | 
|  |             } | 
|  |  | 
|  |             if (p instanceof SelfPermission) { | 
|  |                  | 
|  |                 expandSelf((SelfPermission)p, | 
|  |                         entry.getPrincipals(), | 
|  |                         accPs, | 
|  |                         perms); | 
|  |             } else { | 
|  |                 perms.add(FilePermCompat.newPermPlusAltPath(p)); | 
|  |             } | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     /** | 
|  |      * @param sp the SelfPermission that needs to be expanded. | 
|  |      * | 
|  |      * @param entryPs list of principals for the Policy entry. | 
|  |      * | 
|  |      * @param pdp Principal array from the current ProtectionDomain. | 
|  |      * | 
|  |      * @param perms the PermissionCollection where the individual | 
|  |      *                  Permissions will be added after expansion. | 
|  |      */ | 
|  |  | 
|  |     private void expandSelf(SelfPermission sp, | 
|  |                             List<PolicyParser.PrincipalEntry> entryPs, | 
|  |                             Principal[] pdp, | 
|  |                             Permissions perms) { | 
|  |  | 
|  |         if (entryPs == null || entryPs.isEmpty()) { | 
|  |              | 
|  |             if (debug != null) { | 
|  |                 debug.println("Ignoring permission " | 
|  |                                 + sp.getSelfType() | 
|  |                                 + " with target name (" | 
|  |                                 + sp.getSelfName() + ").  " | 
|  |                                 + "No Principal(s) specified " | 
|  |                                 + "in the grant clause.  " | 
|  |                                 + "SELF-based target names are " | 
|  |                                 + "only valid in the context " | 
|  |                                 + "of a Principal-based grant entry." | 
|  |                              ); | 
|  |             } | 
|  |             return; | 
|  |         } | 
|  |         int startIndex = 0; | 
|  |         int v; | 
|  |         StringBuilder sb = new StringBuilder(); | 
|  |         while ((v = sp.getSelfName().indexOf(SELF, startIndex)) != -1) { | 
|  |  | 
|  |              | 
|  |             sb.append(sp.getSelfName().substring(startIndex, v)); | 
|  |  | 
|  |              | 
|  |             Iterator<PolicyParser.PrincipalEntry> pli = entryPs.iterator(); | 
|  |             while (pli.hasNext()) { | 
|  |                 PolicyParser.PrincipalEntry pppe = pli.next(); | 
|  |                 String[][] principalInfo = getPrincipalInfo(pppe,pdp); | 
|  |                 for (int i = 0; i < principalInfo.length; i++) { | 
|  |                     if (i != 0) { | 
|  |                         sb.append(", "); | 
|  |                     } | 
|  |                     sb.append(principalInfo[i][0] + " " + | 
|  |                         "\"" + principalInfo[i][1] + "\""); | 
|  |                 } | 
|  |                 if (pli.hasNext()) { | 
|  |                     sb.append(", "); | 
|  |                 } | 
|  |             } | 
|  |             startIndex = v + SELF.length(); | 
|  |         } | 
|  |          | 
|  |         sb.append(sp.getSelfName().substring(startIndex)); | 
|  |  | 
|  |         if (debug != null) { | 
|  |             debug.println("  expanded:\n\t" + sp.getSelfName() | 
|  |                         + "\n  into:\n\t" + sb.toString()); | 
|  |         } | 
|  |         try { | 
|  |              | 
|  |             perms.add(FilePermCompat.newPermPlusAltPath(getInstance(sp.getSelfType(), | 
|  |                                   sb.toString(), | 
|  |                                   sp.getSelfActions()))); | 
|  |         } catch (ClassNotFoundException cnfe) { | 
|  |             // ok, the permission is not in the bootclasspath. | 
|  |             // before we add an UnresolvedPermission, check to see | 
|  |             // whether this perm already belongs to the collection. | 
|  |             // if so, use that perm's ClassLoader to create a new | 
|  |              | 
|  |             Class<?> pc = null; | 
|  |             synchronized (perms) { | 
|  |                 Enumeration<Permission> e = perms.elements(); | 
|  |                 while (e.hasMoreElements()) { | 
|  |                     Permission pElement = e.nextElement(); | 
|  |                     if (pElement.getClass().getName().equals(sp.getSelfType())) { | 
|  |                         pc = pElement.getClass(); | 
|  |                         break; | 
|  |                     } | 
|  |                 } | 
|  |             } | 
|  |             if (pc == null) { | 
|  |                  | 
|  |                 perms.add(new UnresolvedPermission(sp.getSelfType(), | 
|  |                                                         sb.toString(), | 
|  |                                                         sp.getSelfActions(), | 
|  |                                                         sp.getCerts())); | 
|  |             } else { | 
|  |                 try { | 
|  |                     // we found an instantiated permission. | 
|  |                      | 
|  |                     Constructor<?> c; | 
|  |                      | 
|  |                     if (sp.getSelfActions() == null) { | 
|  |                         try { | 
|  |                             c = pc.getConstructor(PARAMS1); | 
|  |                             perms.add((Permission)c.newInstance | 
|  |                                  (new Object[] {sb.toString()})); | 
|  |                         } catch (NoSuchMethodException ne) { | 
|  |                             c = pc.getConstructor(PARAMS2); | 
|  |                             perms.add((Permission)c.newInstance | 
|  |                                  (new Object[] {sb.toString(), | 
|  |                                                 sp.getSelfActions() })); | 
|  |                         } | 
|  |                     } else { | 
|  |                         c = pc.getConstructor(PARAMS2); | 
|  |                         perms.add((Permission)c.newInstance | 
|  |                            (new Object[] {sb.toString(), | 
|  |                                           sp.getSelfActions()})); | 
|  |                     } | 
|  |                 } catch (Exception nme) { | 
|  |                     if (debug != null) { | 
|  |                         debug.println("self entry expansion " + | 
|  |                         " instantiation failed: " | 
|  |                         +  nme.toString()); | 
|  |                     } | 
|  |                 } | 
|  |             } | 
|  |         } catch (Exception e) { | 
|  |             if (debug != null) { | 
|  |                 debug.println(e.toString()); | 
|  |             } | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private String[][] getPrincipalInfo | 
|  |         (PolicyParser.PrincipalEntry pe, Principal[] pdp) { | 
|  |  | 
|  |         // there are 3 possibilities: | 
|  |         // 1) the entry's Principal class and name are not wildcarded | 
|  |         // 2) the entry's Principal name is wildcarded only | 
|  |         // 3) the entry's Principal class and name are wildcarded | 
|  |  | 
|  |         if (!pe.isWildcardClass() && !pe.isWildcardName()) { | 
|  |  | 
|  |             // build an info array for the principal | 
|  |              | 
|  |             String[][] info = new String[1][2]; | 
|  |             info[0][0] = pe.principalClass; | 
|  |             info[0][1] = pe.principalName; | 
|  |             return info; | 
|  |  | 
|  |         } else if (!pe.isWildcardClass() && pe.isWildcardName()) { | 
|  |  | 
|  |             // build an info array for every principal | 
|  |             // in the current domain which has a principal class | 
|  |              | 
|  |             List<Principal> plist = new ArrayList<>(); | 
|  |             for (int i = 0; i < pdp.length; i++) { | 
|  |                 if (pe.principalClass.equals(pdp[i].getClass().getName())) | 
|  |                     plist.add(pdp[i]); | 
|  |             } | 
|  |             String[][] info = new String[plist.size()][2]; | 
|  |             int i = 0; | 
|  |             for (Principal p : plist) { | 
|  |                 info[i][0] = p.getClass().getName(); | 
|  |                 info[i][1] = p.getName(); | 
|  |                 i++; | 
|  |             } | 
|  |             return info; | 
|  |  | 
|  |         } else { | 
|  |  | 
|  |             // build an info array for every | 
|  |             // one of the current Domain's principals | 
|  |  | 
|  |             String[][] info = new String[pdp.length][2]; | 
|  |  | 
|  |             for (int i = 0; i < pdp.length; i++) { | 
|  |                 info[i][0] = pdp[i].getClass().getName(); | 
|  |                 info[i][1] = pdp[i].getName(); | 
|  |             } | 
|  |             return info; | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     protected Certificate[] getSignerCertificates(CodeSource cs) { | 
|  |         Certificate[] certs = null; | 
|  |         if ((certs = cs.getCertificates()) == null) | 
|  |             return null; | 
|  |         for (int i=0; i<certs.length; i++) { | 
|  |             if (!(certs[i] instanceof X509Certificate)) | 
|  |                 return cs.getCertificates(); | 
|  |         } | 
|  |  | 
|  |          | 
|  |         int i = 0; | 
|  |         int count = 0; | 
|  |         while (i < certs.length) { | 
|  |             count++; | 
|  |             while (((i+1) < certs.length) | 
|  |                    && ((X509Certificate)certs[i]).getIssuerX500Principal().equals( | 
|  |                            ((X509Certificate)certs[i+1]).getSubjectX500Principal())) { | 
|  |                 i++; | 
|  |             } | 
|  |             i++; | 
|  |         } | 
|  |         if (count == certs.length) | 
|  |              | 
|  |             return certs; | 
|  |  | 
|  |         List<Certificate> userCertList = new ArrayList<>(); | 
|  |         i = 0; | 
|  |         while (i < certs.length) { | 
|  |             userCertList.add(certs[i]); | 
|  |             while (((i+1) < certs.length) | 
|  |                    && ((X509Certificate)certs[i]).getIssuerX500Principal().equals( | 
|  |                            ((X509Certificate)certs[i+1]).getSubjectX500Principal())) { | 
|  |                 i++; | 
|  |             } | 
|  |             i++; | 
|  |         } | 
|  |         Certificate[] userCerts = new Certificate[userCertList.size()]; | 
|  |         userCertList.toArray(userCerts); | 
|  |         return userCerts; | 
|  |     } | 
|  |  | 
|  |     private CodeSource canonicalizeCodebase(CodeSource cs, | 
|  |                                             boolean extractSignerCerts) { | 
|  |  | 
|  |         String path = null; | 
|  |  | 
|  |         CodeSource canonCs = cs; | 
|  |         URL u = cs.getLocation(); | 
|  |         if (u != null) { | 
|  |             if (u.getProtocol().equals("jar")) { | 
|  |                  | 
|  |                 String spec = u.getFile(); | 
|  |                 int separator = spec.indexOf("!/"); | 
|  |                 if (separator != -1) { | 
|  |                     try { | 
|  |                         u = new URL(spec.substring(0, separator)); | 
|  |                     } catch (MalformedURLException e) { | 
|  |                         // Fail silently. In this case, url stays what | 
|  |                         // it was above | 
|  |                     } | 
|  |                 } | 
|  |             } | 
|  |             if (u.getProtocol().equals("file")) { | 
|  |                 boolean isLocalFile = false; | 
|  |                 String host = u.getHost(); | 
|  |                 isLocalFile = (host == null || host.isEmpty() || | 
|  |                     host.equals("~") || host.equalsIgnoreCase("localhost")); | 
|  |  | 
|  |                 if (isLocalFile) { | 
|  |                     path = u.getFile().replace('/', File.separatorChar); | 
|  |                     path = ParseUtil.decode(path); | 
|  |                 } | 
|  |             } | 
|  |         } | 
|  |  | 
|  |         if (path != null) { | 
|  |             try { | 
|  |                 URL csUrl = null; | 
|  |                 path = canonPath(path); | 
|  |                 csUrl = ParseUtil.fileToEncodedURL(new File(path)); | 
|  |  | 
|  |                 if (extractSignerCerts) { | 
|  |                     canonCs = new CodeSource(csUrl, | 
|  |                                              getSignerCertificates(cs)); | 
|  |                 } else { | 
|  |                     canonCs = new CodeSource(csUrl, | 
|  |                                              cs.getCertificates()); | 
|  |                 } | 
|  |             } catch (IOException ioe) { | 
|  |                 // leave codesource as it is, unless we have to extract its | 
|  |                  | 
|  |                 if (extractSignerCerts) { | 
|  |                     canonCs = new CodeSource(cs.getLocation(), | 
|  |                                              getSignerCertificates(cs)); | 
|  |                 } | 
|  |             } | 
|  |         } else { | 
|  |             if (extractSignerCerts) { | 
|  |                 canonCs = new CodeSource(cs.getLocation(), | 
|  |                                          getSignerCertificates(cs)); | 
|  |             } | 
|  |         } | 
|  |         return canonCs; | 
|  |     } | 
|  |  | 
|  |     // Wrapper to return a canonical path that avoids calling getCanonicalPath() | 
|  |      | 
|  |     private static String canonPath(String path) throws IOException { | 
|  |         if (path.endsWith("*")) { | 
|  |             path = path.substring(0, path.length()-1) + "-"; | 
|  |             path = new File(path).getCanonicalPath(); | 
|  |             return path.substring(0, path.length()-1) + "*"; | 
|  |         } else { | 
|  |             return new File(path).getCanonicalPath(); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     private String printPD(ProtectionDomain pd) { | 
|  |         Principal[] principals = pd.getPrincipals(); | 
|  |         String pals = "<no principals>"; | 
|  |         if (principals != null && principals.length > 0) { | 
|  |             StringBuilder palBuf = new StringBuilder("(principals "); | 
|  |             for (int i = 0; i < principals.length; i++) { | 
|  |                 palBuf.append(principals[i].getClass().getName() + | 
|  |                               " \"" + principals[i].getName() + | 
|  |                               "\""); | 
|  |                 if (i < principals.length-1) | 
|  |                     palBuf.append(", "); | 
|  |                 else | 
|  |                     palBuf.append(")"); | 
|  |             } | 
|  |             pals = palBuf.toString(); | 
|  |         } | 
|  |         return "PD CodeSource: " | 
|  |                 + pd.getCodeSource() | 
|  |                 +"\n\t" + "PD ClassLoader: " | 
|  |                 + pd.getClassLoader() | 
|  |                 +"\n\t" + "PD Principals: " | 
|  |                 + pals; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private boolean replacePrincipals( | 
|  |         List<PolicyParser.PrincipalEntry> principals, KeyStore keystore) { | 
|  |  | 
|  |         if (principals == null || principals.isEmpty() || keystore == null) | 
|  |             return true; | 
|  |  | 
|  |         for (PolicyParser.PrincipalEntry pppe : principals) { | 
|  |             if (pppe.isReplaceName()) { | 
|  |  | 
|  |                 // perform replacement | 
|  |                  | 
|  |                 String name; | 
|  |                 if ((name = getDN(pppe.principalName, keystore)) == null) { | 
|  |                     return false; | 
|  |                 } | 
|  |  | 
|  |                 if (debug != null) { | 
|  |                     debug.println("  Replacing \"" + | 
|  |                         pppe.principalName + | 
|  |                         "\" with " + | 
|  |                         X500PRINCIPAL + "/\"" + | 
|  |                         name + | 
|  |                         "\""); | 
|  |                 } | 
|  |  | 
|  |                 pppe.principalClass = X500PRINCIPAL; | 
|  |                 pppe.principalName = name; | 
|  |             } | 
|  |         } | 
|  |         // return true if no replacement was performed, | 
|  |          | 
|  |         return true; | 
|  |     } | 
|  |  | 
|  |     private void expandPermissionName(PolicyParser.PermissionEntry pe, | 
|  |                                         KeyStore keystore) throws Exception { | 
|  |          | 
|  |         if (pe.name == null || pe.name.indexOf("${{", 0) == -1) { | 
|  |             return; | 
|  |         } | 
|  |  | 
|  |         int startIndex = 0; | 
|  |         int b, e; | 
|  |         StringBuilder sb = new StringBuilder(); | 
|  |         while ((b = pe.name.indexOf("${{", startIndex)) != -1) { | 
|  |             e = pe.name.indexOf("}}", b); | 
|  |             if (e < 1) { | 
|  |                 break; | 
|  |             } | 
|  |             sb.append(pe.name.substring(startIndex, b)); | 
|  |  | 
|  |              | 
|  |             String value = pe.name.substring(b+3, e); | 
|  |  | 
|  |              | 
|  |             int colonIndex; | 
|  |             String prefix = value; | 
|  |             String suffix; | 
|  |             if ((colonIndex = value.indexOf(':')) != -1) { | 
|  |                 prefix = value.substring(0, colonIndex); | 
|  |             } | 
|  |  | 
|  |              | 
|  |             if (prefix.equalsIgnoreCase("self")) { | 
|  |                  | 
|  |                 sb.append(pe.name.substring(b, e+2)); | 
|  |                 startIndex = e+2; | 
|  |                 continue; | 
|  |             } else if (prefix.equalsIgnoreCase("alias")) { | 
|  |                  | 
|  |                 if (colonIndex == -1) { | 
|  |                     Object[] source = {pe.name}; | 
|  |                     throw new Exception( | 
|  |                         LocalizedMessage.getNonlocalized( | 
|  |                             "alias.name.not.provided.pe.name.", | 
|  |                             source)); | 
|  |                 } | 
|  |                 suffix = value.substring(colonIndex+1); | 
|  |                 if ((suffix = getDN(suffix, keystore)) == null) { | 
|  |                     Object[] source = {value.substring(colonIndex+1)}; | 
|  |                     throw new Exception( | 
|  |                         LocalizedMessage.getNonlocalized( | 
|  |                             "unable.to.perform.substitution.on.alias.suffix", | 
|  |                             source)); | 
|  |                 } | 
|  |  | 
|  |                 sb.append(X500PRINCIPAL + " \"" + suffix + "\""); | 
|  |                 startIndex = e+2; | 
|  |             } else { | 
|  |                 Object[] source = {prefix}; | 
|  |                 throw new Exception( | 
|  |                     LocalizedMessage.getNonlocalized( | 
|  |                         "substitution.value.prefix.unsupported", | 
|  |                         source)); | 
|  |             } | 
|  |         } | 
|  |  | 
|  |          | 
|  |         sb.append(pe.name.substring(startIndex)); | 
|  |  | 
|  |          | 
|  |         if (debug != null) { | 
|  |             debug.println("  Permission name expanded from:\n\t" + | 
|  |                         pe.name + "\nto\n\t" + sb.toString()); | 
|  |         } | 
|  |         pe.name = sb.toString(); | 
|  |     } | 
|  |  | 
|  |     private String getDN(String alias, KeyStore keystore) { | 
|  |         Certificate cert = null; | 
|  |         try { | 
|  |             cert = keystore.getCertificate(alias); | 
|  |         } catch (Exception e) { | 
|  |             if (debug != null) { | 
|  |                 debug.println("  Error retrieving certificate for '" + | 
|  |                                 alias + | 
|  |                                 "': " + | 
|  |                                 e.toString()); | 
|  |             } | 
|  |             return null; | 
|  |         } | 
|  |  | 
|  |         if (cert == null || !(cert instanceof X509Certificate)) { | 
|  |             if (debug != null) { | 
|  |                 debug.println("  -- No certificate for '" + | 
|  |                                 alias + | 
|  |                                 "' - ignoring entry"); | 
|  |             } | 
|  |             return null; | 
|  |         } else { | 
|  |             X509Certificate x509Cert = (X509Certificate)cert; | 
|  |  | 
|  |             // 4702543:  X500 names with an EmailAddress | 
|  |             // were encoded incorrectly.  create new | 
|  |             // X500Principal name with correct encoding | 
|  |  | 
|  |             X500Principal p = new X500Principal | 
|  |                 (x509Cert.getSubjectX500Principal().toString()); | 
|  |             return p.getName(); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private static class PolicyEntry { | 
|  |  | 
|  |         private final CodeSource codesource; | 
|  |         final List<Permission> permissions; | 
|  |         private final List<PolicyParser.PrincipalEntry> principals; | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         PolicyEntry(CodeSource cs, List<PolicyParser.PrincipalEntry> principals) | 
|  |         { | 
|  |             this.codesource = cs; | 
|  |             this.permissions = new ArrayList<Permission>(); | 
|  |             this.principals = principals;  | 
|  |         } | 
|  |  | 
|  |         PolicyEntry(CodeSource cs) | 
|  |         { | 
|  |             this(cs, null); | 
|  |         } | 
|  |  | 
|  |         List<PolicyParser.PrincipalEntry> getPrincipals() { | 
|  |             return principals;  | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         void add(Permission p) { | 
|  |             permissions.add(p); | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |          */ | 
|  |         CodeSource getCodeSource() { | 
|  |             return codesource; | 
|  |         } | 
|  |  | 
|  |         @Override public String toString(){ | 
|  |             StringBuilder sb = new StringBuilder(); | 
|  |             sb.append(ResourcesMgr.getString("LPARAM")); | 
|  |             sb.append(getCodeSource()); | 
|  |             sb.append("\n"); | 
|  |             for (int j = 0; j < permissions.size(); j++) { | 
|  |                 Permission p = permissions.get(j); | 
|  |                 sb.append(ResourcesMgr.getString("SPACE")); | 
|  |                 sb.append(ResourcesMgr.getString("SPACE")); | 
|  |                 sb.append(p); | 
|  |                 sb.append(ResourcesMgr.getString("NEWLINE")); | 
|  |             } | 
|  |             sb.append(ResourcesMgr.getString("RPARAM")); | 
|  |             sb.append(ResourcesMgr.getString("NEWLINE")); | 
|  |             return sb.toString(); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     private static class SelfPermission extends Permission { | 
|  |  | 
|  |         @java.io.Serial | 
|  |         private static final long serialVersionUID = -8315562579967246806L; | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private String type; | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private String name; | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private String actions; | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private Certificate[] certs; | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         public SelfPermission(String type, String name, String actions, | 
|  |                               Certificate[] certs) | 
|  |         { | 
|  |             super(type); | 
|  |             if (type == null) { | 
|  |                 throw new NullPointerException | 
|  |                     (LocalizedMessage.getNonlocalized("type.can.t.be.null")); | 
|  |             } | 
|  |             this.type = type; | 
|  |             this.name = name; | 
|  |             this.actions = actions; | 
|  |             if (certs != null) { | 
|  |                  | 
|  |                 for (int i=0; i<certs.length; i++) { | 
|  |                     if (!(certs[i] instanceof X509Certificate)) { | 
|  |                         // there is no concept of signer certs, so we store the | 
|  |                          | 
|  |                         this.certs = certs.clone(); | 
|  |                         break; | 
|  |                     } | 
|  |                 } | 
|  |  | 
|  |                 if (this.certs == null) { | 
|  |                     // Go through the list of certs and see if all the certs are | 
|  |                      | 
|  |                     int i = 0; | 
|  |                     int count = 0; | 
|  |                     while (i < certs.length) { | 
|  |                         count++; | 
|  |                         while (((i+1) < certs.length) && | 
|  |                             ((X509Certificate)certs[i]).getIssuerX500Principal().equals( | 
|  |                             ((X509Certificate)certs[i+1]).getSubjectX500Principal())) { | 
|  |                             i++; | 
|  |                         } | 
|  |                         i++; | 
|  |                     } | 
|  |                     if (count == certs.length) { | 
|  |                         // All the certs are signer certs, so we store the | 
|  |                          | 
|  |                         this.certs = certs.clone(); | 
|  |                     } | 
|  |  | 
|  |                     if (this.certs == null) { | 
|  |                          | 
|  |                         List<Certificate> signerCerts = new ArrayList<>(); | 
|  |                         i = 0; | 
|  |                         while (i < certs.length) { | 
|  |                             signerCerts.add(certs[i]); | 
|  |                             while (((i+1) < certs.length) && | 
|  |                                 ((X509Certificate)certs[i]).getIssuerX500Principal().equals( | 
|  |                                 ((X509Certificate)certs[i+1]).getSubjectX500Principal())) { | 
|  |                                 i++; | 
|  |                             } | 
|  |                             i++; | 
|  |                         } | 
|  |                         this.certs = new Certificate[signerCerts.size()]; | 
|  |                         signerCerts.toArray(this.certs); | 
|  |                     } | 
|  |                 } | 
|  |             } | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         @Override public boolean implies(Permission p) { | 
|  |             return false; | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         @Override public boolean equals(Object obj) { | 
|  |             if (obj == this) | 
|  |                 return true; | 
|  |  | 
|  |             if (! (obj instanceof SelfPermission)) | 
|  |                 return false; | 
|  |             SelfPermission that = (SelfPermission) obj; | 
|  |  | 
|  |             if (!(this.type.equals(that.type) && | 
|  |                 this.name.equals(that.name) && | 
|  |                 this.actions.equals(that.actions))) | 
|  |                 return false; | 
|  |  | 
|  |             if (this.certs.length != that.certs.length) | 
|  |                 return false; | 
|  |  | 
|  |             int i,j; | 
|  |             boolean match; | 
|  |  | 
|  |             for (i = 0; i < this.certs.length; i++) { | 
|  |                 match = false; | 
|  |                 for (j = 0; j < that.certs.length; j++) { | 
|  |                     if (this.certs[i].equals(that.certs[j])) { | 
|  |                         match = true; | 
|  |                         break; | 
|  |                     } | 
|  |                 } | 
|  |                 if (!match) return false; | 
|  |             } | 
|  |  | 
|  |             for (i = 0; i < that.certs.length; i++) { | 
|  |                 match = false; | 
|  |                 for (j = 0; j < this.certs.length; j++) { | 
|  |                     if (that.certs[i].equals(this.certs[j])) { | 
|  |                         match = true; | 
|  |                         break; | 
|  |                     } | 
|  |                 } | 
|  |                 if (!match) return false; | 
|  |             } | 
|  |             return true; | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         @Override public int hashCode() { | 
|  |             int hash = type.hashCode(); | 
|  |             if (name != null) | 
|  |                 hash ^= name.hashCode(); | 
|  |             if (actions != null) | 
|  |                 hash ^= actions.hashCode(); | 
|  |             return hash; | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         @Override public String getActions() { | 
|  |             return ""; | 
|  |         } | 
|  |  | 
|  |         public String getSelfType() { | 
|  |             return type; | 
|  |         } | 
|  |  | 
|  |         public String getSelfName() { | 
|  |             return name; | 
|  |         } | 
|  |  | 
|  |         public String getSelfActions() { | 
|  |             return actions; | 
|  |         } | 
|  |  | 
|  |         public Certificate[] getCerts() { | 
|  |             return certs; | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         @Override public String toString() { | 
|  |             return "(SelfPermission " + type + " " + name + " " + actions + ")"; | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     private static class PolicyInfo { | 
|  |         private static final boolean verbose = false; | 
|  |  | 
|  |          | 
|  |         final List<PolicyEntry> policyEntries; | 
|  |  | 
|  |          | 
|  |         final Map<Object, Object> aliasMapping; | 
|  |  | 
|  |          | 
|  |         private final ProtectionDomainCache[] pdMapping; | 
|  |         private java.util.Random random; | 
|  |  | 
|  |         PolicyInfo(int numCaches) { | 
|  |             policyEntries = new ArrayList<>(); | 
|  |             aliasMapping = Collections.synchronizedMap(new HashMap<>(11)); | 
|  |  | 
|  |             pdMapping = new ProtectionDomainCache[numCaches]; | 
|  |             JavaSecurityAccess jspda | 
|  |                 = SharedSecrets.getJavaSecurityAccess(); | 
|  |             for (int i = 0; i < numCaches; i++) { | 
|  |                 pdMapping[i] = jspda.getProtectionDomainCache(); | 
|  |             } | 
|  |             if (numCaches > 1) { | 
|  |                 random = new java.util.Random(); | 
|  |             } | 
|  |         } | 
|  |         ProtectionDomainCache getPdMapping() { | 
|  |             if (pdMapping.length == 1) { | 
|  |                 return pdMapping[0]; | 
|  |             } else { | 
|  |                 int i = java.lang.Math.abs(random.nextInt() % pdMapping.length); | 
|  |                 return pdMapping[i]; | 
|  |             } | 
|  |         } | 
|  |     } | 
|  | } |