/* * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.provider; import java.io.*; import java.lang.reflect.*; import java.net.URL; import java.util.*; import java.security.AccessController; import java.security.CodeSource; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.Permission; import java.security.Permissions; import java.security.PermissionCollection; import java.security.Principal; import java.security.PrivilegedAction; import java.security.UnresolvedPermission; import java.security.Security; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import javax.security.auth.Subject; import javax.security.auth.PrivateCredentialPermission; import sun.security.provider.PolicyParser.GrantEntry; import sun.security.provider.PolicyParser.PermissionEntry; import sun.security.provider.PolicyParser.PrincipalEntry; import sun.security.util.Debug; import sun.security.util.PolicyUtil; import sun.security.util.PropertyExpander; /** * See {@code com.sun.security.auth.PolicyFile} for the class description. * This class is necessary in order to support a default * {@code javax.security.auth.Policy} implementation on the compact1 and * compact2 profiles. * * @deprecated As of JDK 1.4, replaced by * {@code sun.security.provider.PolicyFile}. * This class is entirely deprecated. */ @Deprecated public class AuthPolicyFile extends javax.security.auth.Policy { static final ResourceBundle rb = AccessController.doPrivileged(new PrivilegedAction() { @Override public ResourceBundle run() { return (ResourceBundle.getBundle ("sun.security.util.AuthResources")); } }); private static final Debug debug = Debug.getInstance("policy", "\t[Auth Policy]"); private static final String AUTH_POLICY = "java.security.auth.policy"; private static final String SECURITY_MANAGER = "java.security.manager"; private static final String AUTH_POLICY_URL = "auth.policy.url."; private Vector policyEntries; private Hashtable aliasMapping; private boolean initialized = false; private boolean expandProperties = true; private boolean ignoreIdentityScope = true; // for use with the reflection API private static final Class[] PARAMS = { String.class, String.class}; /** * Initializes the Policy object and reads the default policy * configuration file(s) into the Policy object. */ public AuthPolicyFile() { // initialize Policy if either the AUTH_POLICY or // SECURITY_MANAGER properties are set String prop = System.getProperty(AUTH_POLICY); if (prop == null) { prop = System.getProperty(SECURITY_MANAGER); } if (prop != null) { init(); } } private synchronized void init() { if (initialized) { return; } policyEntries = new Vector(); aliasMapping = new Hashtable(11); initPolicyFile(); initialized = true; } @Override public synchronized void refresh() { java.lang.SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new javax.security.auth.AuthPermission ("refreshPolicy")); } // XXX // // 1) if code instantiates PolicyFile directly, then it will need // all the permissions required for the PolicyFile initialization // 2) if code calls Policy.getPolicy, then it simply needs // AuthPermission(getPolicy), and the javax.security.auth.Policy // implementation instantiates PolicyFile in a doPrivileged block // 3) if after instantiating a Policy (either via #1 or #2), // code calls refresh, it simply needs // AuthPermission(refreshPolicy). then PolicyFile wraps // the refresh in a doPrivileged block. initialized = false; AccessController.doPrivileged(new PrivilegedAction() { @Override public Void run() { init(); return null; } }); } private KeyStore initKeyStore(URL policyUrl, String keyStoreName, String keyStoreType) { if (keyStoreName != null) { try { /* * location of keystore is specified as absolute URL in policy * file, or is relative to URL of policy file */ URL keyStoreUrl = null; try { keyStoreUrl = new URL(keyStoreName); // absolute URL } catch (java.net.MalformedURLException e) { // relative URL keyStoreUrl = new URL(policyUrl, keyStoreName); } if (debug != null) { debug.println("reading keystore"+keyStoreUrl); } InputStream inStream = new BufferedInputStream( PolicyUtil.getInputStream(keyStoreUrl)); KeyStore ks; if (keyStoreType != null) ks = KeyStore.getInstance(keyStoreType); else ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(inStream, null); inStream.close(); return ks; } catch (Exception e) { // ignore, treat it like we have no keystore if (debug != null) { e.printStackTrace(); } return null; } } return null; } private void initPolicyFile() { String prop = Security.getProperty("policy.expandProperties"); if (prop != null) { expandProperties = prop.equalsIgnoreCase("true"); } String iscp = Security.getProperty("policy.ignoreIdentityScope"); if (iscp != null) { ignoreIdentityScope = iscp.equalsIgnoreCase("true"); } String allowSys = Security.getProperty("policy.allowSystemProperty"); if (allowSys != null && allowSys.equalsIgnoreCase("true")) { String extra_policy = System.getProperty(AUTH_POLICY); 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 = new URL("file:" + policyFile.getCanonicalPath()); } else { policyURL = new URL(extra_policy); } if (debug != null) { debug.println("reading " + policyURL); } init(policyURL); } catch (Exception e) { // ignore. if (debug != null) { debug.println("caught exception: " + e); } } if (overrideAll) { if (debug != null) { debug.println("overriding other policies!"); } return; } } } int n = 1; boolean loaded_one = false; String policy_url; while ((policy_url = Security.getProperty(AUTH_POLICY_URL+n)) != null) { try { policy_url = PropertyExpander.expand(policy_url).replace (File.separatorChar, '/'); if (debug != null) { debug.println("reading " + policy_url); } init(new URL(policy_url)); loaded_one = true; } catch (Exception e) { if (debug != null) { debug.println("error reading policy " + e); e.printStackTrace(); } // ignore that policy } n++; } if (loaded_one == false) { // do not load a static policy } } /** * Checks public key. If it is marked as trusted in * the identity database, add it to the policy * with the AllPermission. */ private boolean checkForTrustedIdentity(final Certificate cert) { return false; } /** * Reads a policy configuration into the Policy object using a * Reader object. * * @param policyFile the policy Reader object. */ private void init(URL policy) { PolicyParser pp = new PolicyParser(expandProperties); try (InputStreamReader isr = new InputStreamReader(PolicyUtil.getInputStream(policy))) { pp.read(isr); KeyStore keyStore = initKeyStore(policy, pp.getKeyStoreUrl(), pp.getKeyStoreType()); Enumeration enum_ = pp.grantElements(); while (enum_.hasMoreElements()) { GrantEntry ge = enum_.nextElement(); addGrantEntry(ge, keyStore); } } catch (PolicyParser.ParsingException pe) { System.err.println(AUTH_POLICY + rb.getString(".error.parsing.") + policy); System.err.println(AUTH_POLICY + rb.getString("COLON") + pe.getMessage()); if (debug != null) { pe.printStackTrace(); } } catch (Exception e) { if (debug != null) { debug.println("error parsing " + policy); debug.println(e.toString()); e.printStackTrace(); } } } /** * Given a PermissionEntry, create a codeSource. * * @return null if signedBy alias is not recognized */ CodeSource getCodeSource(GrantEntry ge, KeyStore keyStore) throws java.net.MalformedURLException { Certificate[] certs = null; if (ge.signedBy != null) { certs = getCertificates(keyStore, ge.signedBy); if (certs == null) { // we don't have a key for this alias, // just return if (debug != null) { debug.println(" no certs for alias " + ge.signedBy + ", ignoring."); } return null; } } URL location; if (ge.codeBase != null) { location = new URL(ge.codeBase); } else { location = null; } if (ge.principals == null || ge.principals.size() == 0) { return (canonicalizeCodebase (new CodeSource(location, certs), false)); } else { return (canonicalizeCodebase (new SubjectCodeSource(null, ge.principals, location, certs), false)); } } /** * Add one policy entry to the vector. */ private void addGrantEntry(GrantEntry ge, KeyStore keyStore) { if (debug != null) { debug.println("Adding policy entry: "); debug.println(" signedBy " + ge.signedBy); debug.println(" codeBase " + ge.codeBase); if (ge.principals != null) { for (PrincipalEntry pppe : ge.principals) { debug.println(" " + pppe.getPrincipalClass() + " " + pppe.getPrincipalName()); } } debug.println(); } try { CodeSource codesource = getCodeSource(ge, keyStore); // skip if signedBy alias was unknown... if (codesource == null) return; PolicyEntry entry = new PolicyEntry(codesource); Enumeration enum_ = ge.permissionElements(); while (enum_.hasMoreElements()) { PermissionEntry pe = enum_.nextElement(); try { // XXX special case PrivateCredentialPermission-SELF Permission perm; if (pe.permission.equals ("javax.security.auth.PrivateCredentialPermission") && pe.name.endsWith(" self")) { perm = getInstance(pe.permission, pe.name + " \"self\"", pe.action); } 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); } else { certs = null; } // only add if we had no signer or we had a // a signer and found the keys for it. 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) { System.err.println (AUTH_POLICY + rb.getString(".error.adding.Permission.") + pe.permission + rb.getString("SPACE") + ite.getTargetException()); } catch (Exception e) { System.err.println (AUTH_POLICY + rb.getString(".error.adding.Permission.") + pe.permission + rb.getString("SPACE") + e); } } policyEntries.addElement(entry); } catch (Exception e) { System.err.println (AUTH_POLICY + rb.getString(".error.adding.Entry.") + ge + rb.getString("SPACE") + e); } 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 Class.forName 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 { //XXX we might want to keep a hash of created factories... Class pc = Class.forName(type); Constructor c = pc.getConstructor(PARAMS); return (Permission) c.newInstance(new Object[] { name, actions }); } /** * Fetch all certs associated with this alias. */ Certificate[] getCertificates(KeyStore keyStore, String aliases) { Vector vcerts = null; StringTokenizer st = new StringTokenizer(aliases, ","); int n = 0; while (st.hasMoreTokens()) { String alias = st.nextToken().trim(); n++; Certificate cert = null; // See if this alias's cert has already been cached cert = (Certificate) 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) { aliasMapping.put(alias, cert); aliasMapping.put(cert, alias); } } if (cert != null) { if (vcerts == null) { vcerts = new Vector(); } vcerts.addElement(cert); } } // make sure n == vcerts.size, since we are doing a logical *and* if (vcerts != null && n == vcerts.size()) { Certificate[] certs = new Certificate[vcerts.size()]; vcerts.copyInto(certs); return certs; } else { return null; } } /** * Enumerate all the entries in the global policy object. * This method is used by policy admin tools. The tools * should use the Enumeration methods on the returned object * to fetch the elements sequentially. */ private final synchronized Enumeration elements() { return policyEntries.elements(); } @Override public PermissionCollection getPermissions(final Subject subject, final CodeSource codesource) { // 1) if code instantiates PolicyFile directly, then it will need // all the permissions required for the PolicyFile initialization // 2) if code calls Policy.getPolicy, then it simply needs // AuthPermission(getPolicy), and the javax.security.auth.Policy // implementation instantiates PolicyFile in a doPrivileged block // 3) if after instantiating a Policy (either via #1 or #2), // code calls getPermissions, PolicyFile wraps the call // in a doPrivileged block. return AccessController.doPrivileged (new PrivilegedAction() { @Override public PermissionCollection run() { SubjectCodeSource scs = new SubjectCodeSource( subject, null, codesource == null ? null : codesource.getLocation(), codesource == null ? null : codesource.getCertificates()); if (initialized) { return getPermissions(new Permissions(), scs); } else { return new PolicyPermissions(AuthPolicyFile.this, scs); } } }); } /** * Examines the global policy for the specified CodeSource, and * creates a PermissionCollection object with * the set of permissions for that principal's protection domain. * * @param CodeSource the codesource associated with the caller. * This encapsulates the original location of the code (where the code * came from) and the public key(s) of its signer. * * @return the set of permissions according to the policy. */ PermissionCollection getPermissions(CodeSource codesource) { if (initialized) { return getPermissions(new Permissions(), codesource); } else { return new PolicyPermissions(this, codesource); } } /** * Examines the global policy for the specified CodeSource, and * creates a PermissionCollection object with * the set of permissions for that principal's protection domain. * * @param permissions the permissions to populate * @param codesource the codesource associated with the caller. * This encapsulates the original location of the code (where the code * came from) and the public key(s) of its signer. * * @return the set of permissions according to the policy. */ Permissions getPermissions(final Permissions perms, final CodeSource cs) { if (!initialized) { init(); } final CodeSource codesource[] = {null}; codesource[0] = canonicalizeCodebase(cs, true); if (debug != null) { debug.println("evaluate(" + codesource[0] + ")\n"); } // needs to be in a begin/endPrivileged block because // codesource.implies calls URL.equals which does an // InetAddress lookup for (int i = 0; i < policyEntries.size(); i++) { PolicyEntry entry = policyEntries.elementAt(i); if (debug != null) { debug.println("PolicyFile CodeSource implies: " + entry.codesource.toString() + "\n\n" + "\t" + codesource[0].toString() + "\n\n"); } if (entry.codesource.implies(codesource[0])) { for (int j = 0; j < entry.permissions.size(); j++) { Permission p = entry.permissions.elementAt(j); if (debug != null) { debug.println(" granting " + p); } if (!addSelfPermissions(p, entry.codesource, codesource[0], perms)) { // we could check for duplicates // before adding new permissions, // but the SubjectDomainCombiner // already checks for duplicates later perms.add(p); } } } } // now see if any of the keys are trusted ids. if (!ignoreIdentityScope) { Certificate certs[] = codesource[0].getCertificates(); if (certs != null) { for (int k=0; k < certs.length; k++) { if (aliasMapping.get(certs[k]) == null && checkForTrustedIdentity(certs[k])) { // checkForTrustedIdentity added it // to the policy for us. next time // around we'll find it. This time // around we need to add it. perms.add(new java.security.AllPermission()); } } } } return perms; } /** * Returns true if 'Self' permissions were added to the provided * 'perms', and false otherwise. * *

* * @param p check to see if this Permission is a "SELF" * PrivateCredentialPermission.

* * @param entryCs the codesource for the Policy entry. * * @param accCs the codesource for from the current AccessControlContext. * * @param perms the PermissionCollection where the individual * PrivateCredentialPermissions will be added. */ private boolean addSelfPermissions(final Permission p, CodeSource entryCs, CodeSource accCs, Permissions perms) { if (!(p instanceof PrivateCredentialPermission)) { return false; } if (!(entryCs instanceof SubjectCodeSource)) { return false; } PrivateCredentialPermission pcp = (PrivateCredentialPermission)p; SubjectCodeSource scs = (SubjectCodeSource)entryCs; // see if it is a SELF permission String[][] pPrincipals = pcp.getPrincipals(); if (pPrincipals.length <= 0 || !pPrincipals[0][0].equalsIgnoreCase("self") || !pPrincipals[0][1].equalsIgnoreCase("self")) { // regular PrivateCredentialPermission return false; } else { // granted a SELF permission - create a // PrivateCredentialPermission for each // of the Policy entry's CodeSource Principals if (scs.getPrincipals() == null) { // XXX SubjectCodeSource has no Subject??? return true; } for (PrincipalEntry principal : scs.getPrincipals()) { // if the Policy entry's Principal does not contain a // WILDCARD for the Principal name, then a // new PrivateCredentialPermission is created // for the Principal listed in the Policy entry. // if the Policy entry's Principal contains a WILDCARD // for the Principal name, then a new // PrivateCredentialPermission is created // for each Principal associated with the Subject // in the current ACC. String[][] principalInfo = getPrincipalInfo(principal, accCs); for (int i = 0; i < principalInfo.length; i++) { // here's the new PrivateCredentialPermission PrivateCredentialPermission newPcp = new PrivateCredentialPermission (pcp.getCredentialClass() + " " + principalInfo[i][0] + " " + "\"" + principalInfo[i][1] + "\"", "read"); if (debug != null) { debug.println("adding SELF permission: " + newPcp.toString()); } perms.add(newPcp); } } } return true; } /** * return the principal class/name pair in the 2D array. * array[x][y]: x corresponds to the array length. * if (y == 0), it's the principal class. * if (y == 1), it's the principal name. */ private String[][] getPrincipalInfo(PrincipalEntry principal, final CodeSource accCs) { // 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 (!principal.getPrincipalClass().equals (PrincipalEntry.WILDCARD_CLASS) && !principal.getPrincipalName().equals (PrincipalEntry.WILDCARD_NAME)) { // build a PrivateCredentialPermission for the principal // from the Policy entry String[][] info = new String[1][2]; info[0][0] = principal.getPrincipalClass(); info[0][1] = principal.getPrincipalName(); return info; } else if (!principal.getPrincipalClass().equals (PrincipalEntry.WILDCARD_CLASS) && principal.getPrincipalName().equals (PrincipalEntry.WILDCARD_NAME)) { // build a PrivateCredentialPermission for all // the Subject's principals that are instances of principalClass // the accCs is guaranteed to be a SubjectCodeSource // because the earlier CodeSource.implies succeeded SubjectCodeSource scs = (SubjectCodeSource)accCs; Set principalSet = null; try { // principal.principalClass should extend Principal // If it doesn't, we should stop here with a ClassCastException. @SuppressWarnings("unchecked") Class pClass = (Class) Class.forName(principal.getPrincipalClass(), false, ClassLoader.getSystemClassLoader()); principalSet = scs.getSubject().getPrincipals(pClass); } catch (Exception e) { if (debug != null) { debug.println("problem finding Principal Class " + "when expanding SELF permission: " + e.toString()); } } if (principalSet == null) { // error return new String[0][0]; } String[][] info = new String[principalSet.size()][2]; int i = 0; for (Principal p : principalSet) { info[i][0] = p.getClass().getName(); info[i][1] = p.getName(); i++; } return info; } else { // build a PrivateCredentialPermission for every // one of the current Subject's principals // the accCs is guaranteed to be a SubjectCodeSource // because the earlier CodeSource.implies succeeded SubjectCodeSource scs = (SubjectCodeSource)accCs; Set principalSet = scs.getSubject().getPrincipals(); String[][] info = new String[principalSet.size()][2]; int i = 0; for (Principal p : principalSet) { info[i][0] = p.getClass().getName(); info[i][1] = p.getName(); i++; } return info; } } /* * Returns the signer certificates from the list of certificates associated * with the given code source. * * The signer certificates are those certificates that were used to verify * signed code originating from the codesource location. * * This method assumes that in the given code source, each signer * certificate is followed by its supporting certificate chain * (which may be empty), and that the signer certificate and its * supporting certificate chain are ordered bottom-to-top (i.e., with the * signer certificate first and the (root) certificate authority last). */ 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(); } // Do we have to do anything? int i = 0; int count = 0; while (i < certs.length) { count++; while (((i+1) < certs.length) && ((X509Certificate)certs[i]).getIssuerDN().equals( ((X509Certificate)certs[i+1]).getSubjectDN())) { i++; } i++; } if (count == certs.length) { // Done return certs; } ArrayList userCertList = new ArrayList<>(); i = 0; while (i < certs.length) { userCertList.add(certs[i]); while (((i+1) < certs.length) && ((X509Certificate)certs[i]).getIssuerDN().equals( ((X509Certificate)certs[i+1]).getSubjectDN())) { i++; } i++; } Certificate[] userCerts = new Certificate[userCertList.size()]; userCertList.toArray(userCerts); return userCerts; } private CodeSource canonicalizeCodebase(CodeSource cs, boolean extractSignerCerts) { CodeSource canonCs = cs; if (cs.getLocation() != null && cs.getLocation().getProtocol().equalsIgnoreCase("file")) { try { String path = cs.getLocation().getFile().replace ('/', File.separatorChar); URL csUrl = null; if (path.endsWith("*")) { // remove trailing '*' because it causes canonicalization // to fail on win32 path = path.substring(0, path.length()-1); boolean appendFileSep = false; if (path.endsWith(File.separator)) { appendFileSep = true; } if (path.equals("")) { path = System.getProperty("user.dir"); } File f = new File(path); path = f.getCanonicalPath(); StringBuffer sb = new StringBuffer(path); // reappend '*' to canonicalized filename (note that // canonicalization may have removed trailing file // separator, so we have to check for that, too) if (!path.endsWith(File.separator) && (appendFileSep || f.isDirectory())) { sb.append(File.separatorChar); } sb.append('*'); path = sb.toString(); } else { path = new File(path).getCanonicalPath(); } csUrl = new File(path).toURL(); if (cs instanceof SubjectCodeSource) { SubjectCodeSource scs = (SubjectCodeSource)cs; if (extractSignerCerts) { canonCs = new SubjectCodeSource(scs.getSubject(), scs.getPrincipals(), csUrl, getSignerCertificates(scs)); } else { canonCs = new SubjectCodeSource(scs.getSubject(), scs.getPrincipals(), csUrl, scs.getCertificates()); } } else { 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 // signer certificates if (extractSignerCerts) { if (!(cs instanceof SubjectCodeSource)) { canonCs = new CodeSource(cs.getLocation(), getSignerCertificates(cs)); } else { SubjectCodeSource scs = (SubjectCodeSource)cs; canonCs = new SubjectCodeSource(scs.getSubject(), scs.getPrincipals(), scs.getLocation(), getSignerCertificates(scs)); } } } } else { if (extractSignerCerts) { if (!(cs instanceof SubjectCodeSource)) { canonCs = new CodeSource(cs.getLocation(), getSignerCertificates(cs)); } else { SubjectCodeSource scs = (SubjectCodeSource)cs; canonCs = new SubjectCodeSource(scs.getSubject(), scs.getPrincipals(), scs.getLocation(), getSignerCertificates(scs)); } } } return canonCs; } /** * Each entry in the policy configuration file is represented by a * PolicyEntry object.

* * A PolicyEntry is a (CodeSource,Permission) pair. The * CodeSource contains the (URL, PublicKey) that together identify * where the Java bytecodes come from and who (if anyone) signed * them. The URL could refer to localhost. The URL could also be * null, meaning that this policy entry is given to all comers, as * long as they match the signer field. The signer could be null, * meaning the code is not signed.

* * The Permission contains the (Type, Name, Action) triplet.

* * For now, the Policy object retrieves the public key from the * X.509 certificate on disk that corresponds to the signedBy * alias specified in the Policy config file. For reasons of * efficiency, the Policy object keeps a hashtable of certs already * read in. This could be replaced by a secure internal key * store. * *

* For example, the entry *

     *          permission java.io.File "/tmp", "read,write",
     *          signedBy "Duke";
     * 
* is represented internally *
     *
     * FilePermission f = new FilePermission("/tmp", "read,write");
     * PublicKey p = publickeys.get("Duke");
     * URL u = InetAddress.getLocalHost();
     * CodeBase c = new CodeBase( p, u );
     * pe = new PolicyEntry(f, c);
     * 
* * @author Marianne Mueller * @author Roland Schemers * @see java.security.CodeSource * @see java.security.Policy * @see java.security.Permissions * @see java.security.ProtectionDomain */ private static class PolicyEntry { CodeSource codesource; Vector permissions; /** * Given a Permission and a CodeSource, create a policy entry. * * XXX Decide if/how to add validity fields and "purpose" fields to * XXX policy entries * * @param cs the CodeSource, which encapsulates the URL and the public * key attributes from the policy config file. Validity checks * are performed on the public key before PolicyEntry is called. * */ PolicyEntry(CodeSource cs) { this.codesource = cs; this.permissions = new Vector(); } /** * add a Permission object to this entry. */ void add(Permission p) { permissions.addElement(p); } /** * Return the CodeSource for this policy entry */ CodeSource getCodeSource() { return this.codesource; } @Override public String toString(){ StringBuffer sb = new StringBuffer(); sb.append(rb.getString("LPARAM")); sb.append(getCodeSource()); sb.append("\n"); for (int j = 0; j < permissions.size(); j++) { Permission p = permissions.elementAt(j); sb.append(rb.getString("SPACE")); sb.append(rb.getString("SPACE")); sb.append(p); sb.append(rb.getString("NEWLINE")); } sb.append(rb.getString("RPARAM")); sb.append(rb.getString("NEWLINE")); return sb.toString(); } } } @SuppressWarnings("deprecation") class PolicyPermissions extends PermissionCollection { private static final long serialVersionUID = -1954188373270545523L; private CodeSource codesource; private Permissions perms; private AuthPolicyFile policy; private boolean notInit; // have we pulled in the policy permissions yet? private Vector additionalPerms; PolicyPermissions(AuthPolicyFile policy, CodeSource codesource) { this.codesource = codesource; this.policy = policy; this.perms = null; this.notInit = true; this.additionalPerms = null; } @Override public void add(Permission permission) { if (isReadOnly()) throw new SecurityException (AuthPolicyFile.rb.getString ("attempt.to.add.a.Permission.to.a.readonly.PermissionCollection")); if (perms == null) { if (additionalPerms == null) { additionalPerms = new Vector(); } additionalPerms.add(permission); } else { perms.add(permission); } } private synchronized void init() { if (notInit) { if (perms == null) { perms = new Permissions(); } if (additionalPerms != null) { Enumeration e = additionalPerms.elements(); while (e.hasMoreElements()) { perms.add(e.nextElement()); } additionalPerms = null; } policy.getPermissions(perms, codesource); notInit = false; } } @Override public boolean implies(Permission permission) { if (notInit) { init(); } return perms.implies(permission); } @Override public Enumeration elements() { if (notInit) { init(); } return perms.elements(); } @Override public String toString() { if (notInit) { init(); } return perms.toString(); } }