# HG changeset patch # User mullan # Date 1376947037 14400 # Node ID 57876ed3c4262b46972efd4e2bc8ecbf27021373 # Parent 7de6ae3cecad5afe1a3506d87406659ae3ed0080 8016850: JCK javax.security.auth.Policy tests fail when run in Profiles mode Summary: Move default javax.security.auth.Policy implementation to compact1 profile Reviewed-by: vinnie diff -r 7de6ae3cecad -r 57876ed3c426 jdk/src/share/classes/com/sun/security/auth/PolicyFile.java --- a/jdk/src/share/classes/com/sun/security/auth/PolicyFile.java Mon Aug 19 12:38:56 2013 -0700 +++ b/jdk/src/share/classes/com/sun/security/auth/PolicyFile.java Mon Aug 19 17:17:17 2013 -0400 @@ -25,31 +25,9 @@ package com.sun.security.auth; -import java.io.*; -import java.lang.reflect.*; -import java.net.URL; -import java.util.*; - 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.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.util.PropertyExpander; - -import sun.security.provider.PolicyParser.PrincipalEntry; -import sun.security.provider.PolicyParser.GrantEntry; -import sun.security.provider.PolicyParser.PermissionEntry; /** * This class represents a default implementation for @@ -240,61 +218,14 @@ @Deprecated public class PolicyFile extends javax.security.auth.Policy { - static final java.util.ResourceBundle rb = - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public java.util.ResourceBundle run() { - return (java.util.ResourceBundle.getBundle - ("sun.security.util.AuthResources")); - } - }); - // needs to be package private - - private static final sun.security.util.Debug debug = - sun.security.util.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}; + private final sun.security.provider.AuthPolicyFile apf; /** * Initializes the Policy object and reads the default policy * configuration file(s) into the Policy object. */ public PolicyFile() { - // 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; + apf = new sun.security.provider.AuthPolicyFile(); } /** @@ -305,460 +236,9 @@ * @exception SecurityException if the caller doesn't have permission * to refresh the Policy. */ - 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; - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - 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(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) { - // XXX JAAS has no way to access the SUN package. - // we'll add this back in when JAAS goes into core. - 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) { - sun.security.provider.PolicyParser pp = - new sun.security.provider.PolicyParser(expandProperties); - try { - InputStreamReader isr - = new InputStreamReader(getInputStream(policy)); - pp.read(isr); - isr.close(); - KeyStore keyStore = initKeyStore(policy, pp.getKeyStoreUrl(), - pp.getKeyStoreType()); - Enumeration enum_ = pp.grantElements(); - while (enum_.hasMoreElements()) { - GrantEntry ge = enum_.nextElement(); - addGrantEntry(ge, keyStore); - } - } catch (sun.security.provider.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(); - } - } - } - - /* - * Fast path reading from file urls in order to avoid calling - * FileURLConnection.connect() which can be quite slow the first time - * it is called. We really should clean up FileURLConnection so that - * this is not a problem but in the meantime this fix helps reduce - * start up time noticeably for the new launcher. -- DAC - */ - private InputStream getInputStream(URL url) throws IOException { - if ("file".equals(url.getProtocol())) { - String path = url.getFile().replace('/', File.separatorChar); - return new FileInputStream(path); - } else { - return url.openStream(); - } - } - - /** - * 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 && ge.principals.size() > 0) { - ListIterator li = ge.principals.listIterator(); - while (li.hasNext()) { - PrincipalEntry pppe = li.next(); - 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 void refresh() { + apf.refresh(); } /** @@ -816,646 +296,9 @@ * @return the Permissions granted to the provided Subject * CodeSource. */ + @Override public PermissionCollection getPermissions(final Subject subject, - final CodeSource codesource) { - - // XXX when JAAS goes into the JDK core, - // we can remove this method and simply - // rely on the getPermissions variant that takes a codesource, - // which no one can use at this point in time. - // at that time, we can also make SubjectCodeSource a public - // class. - - // 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 getPermissions, PolicyFile wraps the call - // in a doPrivileged block. - return java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - 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(PolicyFile.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; - } - - ListIterator pli = - scs.getPrincipals().listIterator(); - while (pli.hasNext()) { - - PrincipalEntry principal = pli.next(); - - // XXX - // 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]; - java.util.Iterator pIterator = principalSet.iterator(); - - int i = 0; - while (pIterator.hasNext()) { - Principal p = pIterator.next(); - 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 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; - } - - 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(); - } - + final CodeSource codesource) { + return apf.getPermissions(subject, codesource); } } - -@SuppressWarnings("deprecation") -class PolicyPermissions extends PermissionCollection { - - private static final long serialVersionUID = -1954188373270545523L; - - private CodeSource codesource; - private Permissions perms; - private PolicyFile policy; - private boolean notInit; // have we pulled in the policy permissions yet? - private Vector additionalPerms; - - PolicyPermissions(PolicyFile policy, - CodeSource codesource) - { - this.codesource = codesource; - this.policy = policy; - this.perms = null; - this.notInit = true; - this.additionalPerms = null; - } - - public void add(Permission permission) { - if (isReadOnly()) - throw new SecurityException - (PolicyFile.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; - } - } - - public boolean implies(Permission permission) { - if (notInit) - init(); - return perms.implies(permission); - } - - public Enumeration elements() { - if (notInit) - init(); - return perms.elements(); - } - - public String toString() { - if (notInit) - init(); - return perms.toString(); - } -} diff -r 7de6ae3cecad -r 57876ed3c426 jdk/src/share/classes/com/sun/security/auth/PolicyParser.java --- a/jdk/src/share/classes/com/sun/security/auth/PolicyParser.java Mon Aug 19 12:38:56 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,964 +0,0 @@ -/* - * Copyright (c) 1998, 2011, 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 com.sun.security.auth; - -import java.io.*; -import java.lang.RuntimePermission; -import java.net.MalformedURLException; -import java.net.SocketPermission; -import java.net.URL; -import java.security.GeneralSecurityException; -import java.text.MessageFormat; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.LinkedList; -import java.util.ListIterator; -import java.util.Vector; -import java.util.StringTokenizer; -import sun.security.util.PropertyExpander; - -/** - * The policy for a Java runtime (specifying - * which permissions are available for code from various principals) - * is represented as a separate - * persistent configuration. The configuration may be stored as a - * flat ASCII file, as a serialized binary file of - * the Policy class, or as a database.

- * - *

The Java runtime creates one global Policy object, which is used to - * represent the static policy configuration file. It is consulted by - * a ProtectionDomain when the protection domain initializes its set of - * permissions.

- * - *

The Policy init method parses the policy - * configuration file, and then - * populates the Policy object. The Policy object is agnostic in that - * it is not involved in making policy decisions. It is merely the - * Java runtime representation of the persistent policy configuration - * file.

- * - *

When a protection domain needs to initialize its set of - * permissions, it executes code such as the following - * to ask the global Policy object to populate a - * Permissions object with the appropriate permissions: - *

- *  policy = Policy.getPolicy();
- *  Permissions perms = policy.getPermissions(MyCodeSource)
- * 
- * - *

The protection domain passes in a CodeSource - * object, which encapsulates its codebase (URL) and public key attributes. - * The Policy object evaluates the global policy in light of who the - * principal is and returns an appropriate Permissions object. - * - * @deprecated As of JDK 1.4, replaced by - * {@link sun.security.provider.PolicyParser}. - * This class is entirely deprecated. - * - * @author Roland Schemers - * - * @since 1.2 - */ -@Deprecated -class PolicyParser { - - private static final java.util.ResourceBundle rb = - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public java.util.ResourceBundle run() { - return (java.util.ResourceBundle.getBundle - ("sun.security.util.AuthResources")); - } - }); - - private Vector grantEntries; - - // Convenience variables for parsing - private static final sun.security.util.Debug debug = - sun.security.util.Debug.getInstance("parser", "\t[Auth Policy Parser]"); - private StreamTokenizer st; - private int lookahead; - private int linenum; - private boolean expandProp = false; - private String keyStoreUrlString = null; // unexpanded - private String keyStoreType = null; - - private String expand(String value) - throws PropertyExpander.ExpandException - { - if (expandProp) - return PropertyExpander.expand(value); - else - return value; - } - /** - * Creates a PolicyParser object. - */ - - public PolicyParser() { - grantEntries = new Vector(); - } - - - public PolicyParser(boolean expandProp) { - this(); - this.expandProp = expandProp; - } - - /** - * Reads a policy configuration into the Policy object using a - * Reader object.

- * - * @param policy the policy Reader object. - * - * @exception ParsingException if the policy configuration contains - * a syntax error. - * - * @exception IOException if an error occurs while reading the policy - * configuration. - */ - - public void read(Reader policy) - throws ParsingException, IOException - { - if (!(policy instanceof BufferedReader)) { - policy = new BufferedReader(policy); - } - - /** - * Configure the stream tokenizer: - * Recognize strings between "..." - * Don't convert words to lowercase - * Recognize both C-style and C++-style comments - * Treat end-of-line as white space, not as a token - */ - st = new StreamTokenizer(policy); - - st.resetSyntax(); - st.wordChars('a', 'z'); - st.wordChars('A', 'Z'); - st.wordChars('.', '.'); - st.wordChars('0', '9'); - st.wordChars('_', '_'); - st.wordChars('$', '$'); - st.wordChars(128 + 32, 255); - st.whitespaceChars(0, ' '); - st.commentChar('/'); - st.quoteChar('\''); - st.quoteChar('"'); - st.lowerCaseMode(false); - st.ordinaryChar('/'); - st.slashSlashComments(true); - st.slashStarComments(true); - - /** - * The main parsing loop. The loop is executed once - * for each entry in the config file. The entries - * are delimited by semicolons. Once we've read in - * the information for an entry, go ahead and try to - * add it to the policy vector. - * - */ - - lookahead = st.nextToken(); - while (lookahead != StreamTokenizer.TT_EOF) { - if (peek("grant")) { - GrantEntry ge = parseGrantEntry(); - // could be null if we couldn't expand a property - if (ge != null) - add(ge); - } else if (peek("keystore") && keyStoreUrlString==null) { - // only one keystore entry per policy file, others will be - // ignored - parseKeyStoreEntry(); - } else { - // error? - } - match(";"); - } - } - - public void add(GrantEntry ge) - { - grantEntries.addElement(ge); - } - - public void replace(GrantEntry origGe, GrantEntry newGe) - { - grantEntries.setElementAt(newGe, grantEntries.indexOf(origGe)); - } - - public boolean remove(GrantEntry ge) - { - return grantEntries.removeElement(ge); - } - - /** - * Returns the (possibly expanded) keystore location, or null if the - * expansion fails. - */ - public String getKeyStoreUrl() { - try { - if (keyStoreUrlString!=null && keyStoreUrlString.length()!=0) { - return expand(keyStoreUrlString).replace(File.separatorChar, - '/'); - } - } catch (PropertyExpander.ExpandException peee) { - return null; - } - return null; - } - - public void setKeyStoreUrl(String url) { - keyStoreUrlString = url; - } - - public String getKeyStoreType() { - return keyStoreType; - } - - public void setKeyStoreType(String type) { - keyStoreType = type; - } - - /** - * 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. - */ - public Enumeration grantElements(){ - return grantEntries.elements(); - } - - /** - * write out the policy - */ - - public void write(Writer policy) - { - PrintWriter out = new PrintWriter(new BufferedWriter(policy)); - - Enumeration enum_ = grantElements(); - - out.println("/* AUTOMATICALLY GENERATED ON "+ - (new java.util.Date()) + "*/"); - out.println("/* DO NOT EDIT */"); - out.println(); - - // write the (unexpanded) keystore entry as the first entry of the - // policy file - if (keyStoreUrlString != null) { - writeKeyStoreEntry(out); - } - - // write "grant" entries - while (enum_.hasMoreElements()) { - GrantEntry ge = enum_.nextElement(); - ge.write(out); - out.println(); - } - out.flush(); - } - - /** - * parses a keystore entry - */ - private void parseKeyStoreEntry() throws ParsingException, IOException { - match("keystore"); - keyStoreUrlString = match("quoted string"); - - // parse keystore type - if (!peek(",")) { - return; // default type - } - match(","); - - if (peek("\"")) { - keyStoreType = match("quoted string"); - } else { - throw new ParsingException(st.lineno(), - rb.getString("expected.keystore.type")); - } - } - - /** - * writes the (unexpanded) keystore entry - */ - private void writeKeyStoreEntry(PrintWriter out) { - out.print("keystore \""); - out.print(keyStoreUrlString); - out.print('"'); - if (keyStoreType != null && keyStoreType.length() > 0) - out.print(", \"" + keyStoreType + "\""); - out.println(";"); - out.println(); - } - - /** - * parse a Grant entry - */ - private GrantEntry parseGrantEntry() - throws ParsingException, IOException - { - GrantEntry e = new GrantEntry(); - LinkedList principals = null; - boolean ignoreEntry = false; - - match("grant"); - - while(!peek("{")) { - - if (peekAndMatch("Codebase")) { - e.codeBase = match("quoted string"); - peekAndMatch(","); - } else if (peekAndMatch("SignedBy")) { - e.signedBy = match("quoted string"); - peekAndMatch(","); - } else if (peekAndMatch("Principal")) { - if (principals == null) { - principals = new LinkedList(); - } - - // check for principalClass wildcard - String principalClass; - if (peek("*")) { - match("*"); - principalClass = PrincipalEntry.WILDCARD_CLASS; - } else { - principalClass = match("principal type"); - } - - // check for principalName wildcard - String principalName; - if (peek("*")) { - match("*"); - principalName = PrincipalEntry.WILDCARD_NAME; - } else { - principalName = match("quoted string"); - } - - // disallow WILDCARD_CLASS && actual name - if (principalClass.equals(PrincipalEntry.WILDCARD_CLASS) && - !principalName.equals(PrincipalEntry.WILDCARD_NAME)) { - if (debug != null) - debug.println("disallowing principal that has " + - "WILDCARD class but no WILDCARD name"); - throw new ParsingException - (st.lineno(), - rb.getString("can.not.specify.Principal.with.a." + - "wildcard.class.without.a.wildcard.name")); - } - - try { - principalName = expand(principalName); - principals.add - (new PrincipalEntry(principalClass, principalName)); - } catch (PropertyExpander.ExpandException peee) { - // ignore the entire policy entry - // but continue parsing all the info - // so we can get to the next entry - if (debug != null) - debug.println("principal name expansion failed: " + - principalName); - ignoreEntry = true; - } - peekAndMatch(","); - } else { - throw new - ParsingException(st.lineno(), - rb.getString("expected.codeBase.or.SignedBy")); - } - } - - // disallow non principal-based grant entries - if (principals == null) { - throw new ParsingException - (st.lineno(), - rb.getString("only.Principal.based.grant.entries.permitted")); - } - - e.principals = principals; - match("{"); - - while(!peek("}")) { - if (peek("Permission")) { - try { - PermissionEntry pe = parsePermissionEntry(); - e.add(pe); - } catch (PropertyExpander.ExpandException peee) { - // ignore. The add never happened - skipEntry(); // BugId 4219343 - } - match(";"); - } else { - throw new - ParsingException(st.lineno(), - rb.getString("expected.permission.entry")); - } - } - match("}"); - - try { - if (e.codeBase != null) - e.codeBase = expand(e.codeBase).replace(File.separatorChar, '/'); - e.signedBy = expand(e.signedBy); - } catch (PropertyExpander.ExpandException peee) { - return null; - } - - return (ignoreEntry == true) ? null : e; - } - - /** - * parse a Permission entry - */ - private PermissionEntry parsePermissionEntry() - throws ParsingException, IOException, PropertyExpander.ExpandException - { - PermissionEntry e = new PermissionEntry(); - - // Permission - match("Permission"); - e.permission = match("permission type"); - - if (peek("\"")) { - // Permission name - e.name = expand(match("quoted string")); - } - - if (!peek(",")) { - return e; - } - match(","); - - if (peek("\"")) { - e.action = expand(match("quoted string")); - if (!peek(",")) { - return e; - } - match(","); - } - - if (peekAndMatch("SignedBy")) { - e.signedBy = expand(match("quoted string")); - } - return e; - } - - private boolean peekAndMatch(String expect) - throws ParsingException, IOException - { - if (peek(expect)) { - match(expect); - return true; - } else { - return false; - } - } - - private boolean peek(String expect) { - boolean found = false; - - switch (lookahead) { - - case StreamTokenizer.TT_WORD: - if (expect.equalsIgnoreCase(st.sval)) - found = true; - break; - case ',': - if (expect.equalsIgnoreCase(",")) - found = true; - break; - case '{': - if (expect.equalsIgnoreCase("{")) - found = true; - break; - case '}': - if (expect.equalsIgnoreCase("}")) - found = true; - break; - case '"': - if (expect.equalsIgnoreCase("\"")) - found = true; - break; - case '*': - if (expect.equalsIgnoreCase("*")) - found = true; - break; - default: - - } - return found; - } - - private String match(String expect) - throws ParsingException, IOException - { - String value = null; - - switch (lookahead) { - case StreamTokenizer.TT_NUMBER: - throw new ParsingException(st.lineno(), expect, - rb.getString("number.") + - String.valueOf(st.nval)); - case StreamTokenizer.TT_EOF: - MessageFormat form = new MessageFormat( - rb.getString("expected.expect.read.end.of.file.")); - Object[] source = {expect}; - throw new ParsingException(form.format(source)); - case StreamTokenizer.TT_WORD: - if (expect.equalsIgnoreCase(st.sval)) { - lookahead = st.nextToken(); - } else if (expect.equalsIgnoreCase("permission type")) { - value = st.sval; - lookahead = st.nextToken(); - } else if (expect.equalsIgnoreCase("principal type")) { - value = st.sval; - lookahead = st.nextToken(); - } else { - throw new ParsingException(st.lineno(), expect, st.sval); - } - break; - case '"': - if (expect.equalsIgnoreCase("quoted string")) { - value = st.sval; - lookahead = st.nextToken(); - } else if (expect.equalsIgnoreCase("permission type")) { - value = st.sval; - lookahead = st.nextToken(); - } else if (expect.equalsIgnoreCase("principal type")) { - value = st.sval; - lookahead = st.nextToken(); - } else { - throw new ParsingException(st.lineno(), expect, st.sval); - } - break; - case ',': - if (expect.equalsIgnoreCase(",")) - lookahead = st.nextToken(); - else - throw new ParsingException(st.lineno(), expect, ","); - break; - case '{': - if (expect.equalsIgnoreCase("{")) - lookahead = st.nextToken(); - else - throw new ParsingException(st.lineno(), expect, "{"); - break; - case '}': - if (expect.equalsIgnoreCase("}")) - lookahead = st.nextToken(); - else - throw new ParsingException(st.lineno(), expect, "}"); - break; - case ';': - if (expect.equalsIgnoreCase(";")) - lookahead = st.nextToken(); - else - throw new ParsingException(st.lineno(), expect, ";"); - break; - case '*': - if (expect.equalsIgnoreCase("*")) - lookahead = st.nextToken(); - else - throw new ParsingException(st.lineno(), expect, "*"); - break; - default: - throw new ParsingException(st.lineno(), expect, - new String(new char[] {(char)lookahead})); - } - return value; - } - - /** - * skip all tokens for this entry leaving the delimiter ";" - * in the stream. - */ - private void skipEntry() - throws ParsingException, IOException - { - while(lookahead != ';') { - switch (lookahead) { - case StreamTokenizer.TT_NUMBER: - throw new ParsingException(st.lineno(), ";", - rb.getString("number.") + - String.valueOf(st.nval)); - case StreamTokenizer.TT_EOF: - throw new ParsingException - (rb.getString("expected.read.end.of.file")); - default: - lookahead = st.nextToken(); - } - } - } - - /** - * Each grant entry in the policy configuration file is - * represented by a - * GrantEntry object.

- * - *

- * For example, the entry - *

-     *      grant signedBy "Duke" {
-     *          permission java.io.FilePermission "/tmp", "read,write";
-     *      };
-     *
-     * 
- * is represented internally - *
-     *
-     * pe = new PermissionEntry("java.io.FilePermission",
-     *                           "/tmp", "read,write");
-     *
-     * ge = new GrantEntry("Duke", null);
-     *
-     * ge.add(pe);
-     *
-     * 
- * - * @author Roland Schemers - * - * version 1.19, 05/21/98 - */ - - static class GrantEntry { - - public String signedBy; - public String codeBase; - public LinkedList principals; - public Vector permissionEntries; - - public GrantEntry() { - permissionEntries = new Vector(); - } - - public GrantEntry(String signedBy, String codeBase) { - this.codeBase = codeBase; - this.signedBy = signedBy; - permissionEntries = new Vector(); - } - - public void add(PermissionEntry pe) - { - permissionEntries.addElement(pe); - } - - public boolean remove(PermissionEntry pe) - { - return permissionEntries.removeElement(pe); - } - - public boolean contains(PermissionEntry pe) - { - return permissionEntries.contains(pe); - } - - /** - * Enumerate all the permission entries in this GrantEntry. - */ - public Enumeration permissionElements(){ - return permissionEntries.elements(); - } - - - public void write(PrintWriter out) { - out.print("grant"); - if (signedBy != null) { - out.print(" signedBy \""); - out.print(signedBy); - out.print('"'); - if (codeBase != null) - out.print(", "); - } - if (codeBase != null) { - out.print(" codeBase \""); - out.print(codeBase); - out.print('"'); - if (principals != null && principals.size() > 0) - out.print(",\n"); - } - if (principals != null && principals.size() > 0) { - ListIterator pli = principals.listIterator(); - while (pli.hasNext()) { - out.print("\tPrincipal "); - PrincipalEntry pe = pli.next(); - out.print(pe.principalClass + - " \"" + pe.principalName + "\""); - if (pli.hasNext()) - out.print(",\n"); - } - } - out.println(" {"); - Enumeration enum_ = permissionEntries.elements(); - while (enum_.hasMoreElements()) { - PermissionEntry pe = enum_.nextElement(); - out.write(" "); - pe.write(out); - } - out.println("};"); - } - - } - - /** - * Principal info (class and name) in a grant entry - */ - static class PrincipalEntry { - - static final String WILDCARD_CLASS = "WILDCARD_PRINCIPAL_CLASS"; - static final String WILDCARD_NAME = "WILDCARD_PRINCIPAL_NAME"; - - String principalClass; - String principalName; - - /** - * A PrincipalEntry consists of the Principal - * class and Principal name. - * - *

- * - * @param principalClass the Principal class.

- * - * @param principalName the Principal name.

- */ - public PrincipalEntry(String principalClass, String principalName) { - if (principalClass == null || principalName == null) - throw new NullPointerException - ("null principalClass or principalName"); - this.principalClass = principalClass; - this.principalName = principalName; - } - - /** - * Test for equality between the specified object and this object. - * Two PrincipalEntries are equal if their PrincipalClass and - * PrincipalName values are equal. - * - *

- * - * @param obj the object to test for equality with this object. - * - * @return true if the objects are equal, false otherwise. - */ - public boolean equals(Object obj) { - if (this == obj) - return true; - - if (!(obj instanceof PrincipalEntry)) - return false; - - PrincipalEntry that = (PrincipalEntry)obj; - if (this.principalClass.equals(that.principalClass) && - this.principalName.equals(that.principalName)) { - return true; - } - - return false; - } - - /** - * Return a hashcode for this PrincipalEntry. - * - *

- * - * @return a hashcode for this PrincipalEntry. - */ - public int hashCode() { - return principalClass.hashCode(); - } - } - - /** - * Each permission entry in the policy configuration file is - * represented by a - * PermissionEntry object.

- * - *

- * For example, the entry - *

-     *          permission java.io.FilePermission "/tmp", "read,write";
-     * 
- * is represented internally - *
-     *
-     * pe = new PermissionEntry("java.io.FilePermission",
-     *                           "/tmp", "read,write");
-     * 
- * - * @author Roland Schemers - * - * version 1.19, 05/21/98 - */ - - static class PermissionEntry { - - public String permission; - public String name; - public String action; - public String signedBy; - - public PermissionEntry() { - } - - public PermissionEntry(String permission, - String name, - String action) { - this.permission = permission; - this.name = name; - this.action = action; - } - - /** - * Calculates a hash code value for the object. Objects - * which are equal will also have the same hashcode. - */ - public int hashCode() { - int retval = permission.hashCode(); - if (name != null) retval ^= name.hashCode(); - if (action != null) retval ^= action.hashCode(); - return retval; - } - - public boolean equals(Object obj) { - if (obj == this) - return true; - - if (! (obj instanceof PermissionEntry)) - return false; - - PermissionEntry that = (PermissionEntry) obj; - - if (this.permission == null) { - if (that.permission != null) return false; - } else { - if (!this.permission.equals(that.permission)) return false; - } - - if (this.name == null) { - if (that.name != null) return false; - } else { - if (!this.name.equals(that.name)) return false; - } - - if (this.action == null) { - if (that.action != null) return false; - } else { - if (!this.action.equals(that.action)) return false; - } - - if (this.signedBy == null) { - if (that.signedBy != null) return false; - } else { - if (!this.signedBy.equals(that.signedBy)) return false; - } - - // everything matched -- the 2 objects are equal - return true; - } - - public void write(PrintWriter out) { - out.print("permission "); - out.print(permission); - if (name != null) { - out.print(" \""); - - // have to add escape chars for quotes - if (name.indexOf("\"") != -1) { - int numQuotes = 0; - char[] chars = name.toCharArray(); - - // count the number of quote chars - for (int i = 0; i < chars.length; i++) { - if (chars[i] == '"') - numQuotes++; - } - - // now, add an escape char before each quote - char[] newChars = new char[chars.length + numQuotes]; - for (int i = 0, j = 0; i < chars.length; i++) { - if (chars[i] != '"') { - newChars[j++] = chars[i]; - } else { - newChars[j++] = '\\'; - newChars[j++] = chars[i]; - } - } - name = new String(newChars); - } - out.print(name); - out.print('"'); - } - if (action != null) { - out.print(", \""); - out.print(action); - out.print('"'); - } - if (signedBy != null) { - out.print(", signedBy \""); - out.print(signedBy); - out.print('"'); - } - out.println(";"); - } - } - - static class ParsingException extends GeneralSecurityException { - - private static final long serialVersionUID = 8240970523155877400L; - - /** - * Constructs a ParsingException with the specified - * detail message. A detail message is a String that describes - * this particular exception, which may, for example, specify which - * algorithm is not available. - * - * @param msg the detail message. - */ - public ParsingException(String msg) { - super(msg); - } - - public ParsingException(int line, String msg) { - super(rb.getString("line.") + line + rb.getString("COLON") + msg); - } - - public ParsingException(int line, String expect, String actual) { - super(rb.getString("line.") + line + rb.getString(".expected.") + - expect + rb.getString(".found.") + actual + - rb.getString("QUOTE")); - } - } - - public static void main(String arg[]) throws Exception { - PolicyParser pp = new PolicyParser(true); - pp.read(new FileReader(arg[0])); - FileWriter fr = new FileWriter(arg[1]); - pp.write(fr); - fr.close(); - } -} diff -r 7de6ae3cecad -r 57876ed3c426 jdk/src/share/classes/com/sun/security/auth/SubjectCodeSource.java --- a/jdk/src/share/classes/com/sun/security/auth/SubjectCodeSource.java Mon Aug 19 12:38:56 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,398 +0,0 @@ -/* - * 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 com.sun.security.auth; - -import java.net.URL; -import java.util.*; -import java.security.CodeSource; -import java.security.Principal; -import java.security.cert.Certificate; -import java.lang.reflect.Constructor; - -import javax.security.auth.Subject; -import sun.security.provider.PolicyParser.PrincipalEntry; - -/** - *

This SubjectCodeSource class contains - * a URL, signer certificates, and either a Subject - * (that represents the Subject in the current - * AccessControlContext), - * or a linked list of Principals/PrincipalComparators - * (that represent a "subject" in a Policy). - * - */ -class SubjectCodeSource extends CodeSource implements java.io.Serializable { - - private static final long serialVersionUID = 6039418085604715275L; - - private static final java.util.ResourceBundle rb = - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public java.util.ResourceBundle run() { - return (java.util.ResourceBundle.getBundle - ("sun.security.util.AuthResources")); - } - }); - - private Subject subject; - private LinkedList principals; - private static final Class[] PARAMS = { String.class }; - private static final sun.security.util.Debug debug = - sun.security.util.Debug.getInstance("auth", "\t[Auth Access]"); - private ClassLoader sysClassLoader; - - /** - * Creates a new SubjectCodeSource - * with the given Subject, principals, URL, - * and signers (Certificates). The Subject - * represents the Subject associated with the current - * AccessControlContext. - * The Principals are given as a LinkedList - * of PolicyParser.PrincipalEntry objects. - * Typically either a Subject will be provided, - * or a list of principals will be provided - * (not both). - * - *

- * - * @param subject the Subject associated with this - * SubjectCodeSource

- * - * @param url the URL associated with this - * SubjectCodeSource

- * - * @param certs the signers associated with this - * SubjectCodeSource

- */ - SubjectCodeSource(Subject subject, - LinkedList principals, - URL url, Certificate[] certs) { - - super(url, certs); - this.subject = subject; - this.principals = (principals == null ? - new LinkedList() : - new LinkedList(principals)); - sysClassLoader = java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public ClassLoader run() { - return ClassLoader.getSystemClassLoader(); - } - }); - } - - /** - * Get the Principals associated with this SubjectCodeSource. - * The Principals are retrieved as a LinkedList - * of PolicyParser.PrincipalEntry objects. - * - *

- * - * @return the Principals associated with this - * SubjectCodeSource as a LinkedList - * of PolicyParser.PrincipalEntry objects. - */ - LinkedList getPrincipals() { - return principals; - } - - /** - * Get the Subject associated with this - * SubjectCodeSource. The Subject - * represents the Subject associated with the - * current AccessControlContext. - * - *

- * - * @return the Subject associated with this - * SubjectCodeSource. - */ - Subject getSubject() { - return subject; - } - - /** - * Returns true if this SubjectCodeSource object "implies" - * the specified CodeSource. - * More specifically, this method makes the following checks. - * If any fail, it returns false. If they all succeed, it returns true. - * - *

- *

    - *
  1. The provided codesource must not be null. - *
  2. codesource must be an instance of SubjectCodeSource. - *
  3. super.implies(codesource) must return true. - *
  4. for each principal in this codesource's principal list: - *
      - *
    1. if the principal is an instanceof - * PrincipalComparator, then the principal must - * imply the provided codesource's Subject. - *
    2. if the principal is not an instanceof - * PrincipalComparator, then the provided - * codesource's Subject must have an - * associated Principal, P, where - * P.getClass().getName equals principal.principalClass, - * and P.getName() equals principal.principalName. - *
    - *
- * - *

- * - * @param codesource the CodeSource to compare against. - * - * @return true if this SubjectCodeSource implies the - * the specified CodeSource. - */ - public boolean implies(CodeSource codesource) { - - LinkedList subjectList = null; - - if (codesource == null || - !(codesource instanceof SubjectCodeSource) || - !(super.implies(codesource))) { - - if (debug != null) - debug.println("\tSubjectCodeSource.implies: FAILURE 1"); - return false; - } - - SubjectCodeSource that = (SubjectCodeSource)codesource; - - // if the principal list in the policy "implies" - // the Subject associated with the current AccessControlContext, - // then return true - - if (this.principals == null) { - if (debug != null) - debug.println("\tSubjectCodeSource.implies: PASS 1"); - return true; - } - - if (that.getSubject() == null || - that.getSubject().getPrincipals().size() == 0) { - if (debug != null) - debug.println("\tSubjectCodeSource.implies: FAILURE 2"); - return false; - } - - ListIterator li = this.principals.listIterator(0); - while (li.hasNext()) { - PrincipalEntry pppe = li.next(); - try { - - // handle PrincipalComparators - - Class principalComparator = Class.forName( - pppe.getPrincipalClass(), true, sysClassLoader); - Constructor c = principalComparator.getConstructor(PARAMS); - PrincipalComparator pc = - (PrincipalComparator)c.newInstance - (new Object[] { pppe.getPrincipalName() }); - - if (!pc.implies(that.getSubject())) { - if (debug != null) - debug.println("\tSubjectCodeSource.implies: FAILURE 3"); - return false; - } else { - if (debug != null) - debug.println("\tSubjectCodeSource.implies: PASS 2"); - return true; - } - } catch (Exception e) { - - // no PrincipalComparator, simply compare Principals - - if (subjectList == null) { - - if (that.getSubject() == null) { - if (debug != null) - debug.println("\tSubjectCodeSource.implies: " + - "FAILURE 4"); - return false; - } - Iterator i = - that.getSubject().getPrincipals().iterator(); - - subjectList = new LinkedList(); - while (i.hasNext()) { - Principal p = i.next(); - PrincipalEntry spppe = new PrincipalEntry - (p.getClass().getName(), p.getName()); - subjectList.add(spppe); - } - } - - if (!subjectListImpliesPrincipalEntry(subjectList, pppe)) { - if (debug != null) - debug.println("\tSubjectCodeSource.implies: FAILURE 5"); - return false; - } - } - } - - if (debug != null) - debug.println("\tSubjectCodeSource.implies: PASS 3"); - return true; - } - - /** - * This method returns, true, if the provided subjectList - * "contains" the Principal specified - * in the provided pppe argument. - * - * Note that the provided pppe argument may have - * wildcards (*) for the Principal class and name, - * which need to be considered. - * - *

- * - * @param subjectList a list of PolicyParser.PrincipalEntry objects - * that correspond to all the Principals in the Subject currently - * on this thread's AccessControlContext.

- * - * @param pppe the Principals specified in a grant entry. - * - * @return true if the provided subjectList "contains" - * the Principal specified in the provided - * pppe argument. - */ - private boolean subjectListImpliesPrincipalEntry( - LinkedList subjectList, PrincipalEntry pppe) { - - ListIterator li = subjectList.listIterator(0); - while (li.hasNext()) { - PrincipalEntry listPppe = li.next(); - - if (pppe.getPrincipalClass().equals - (PrincipalEntry.WILDCARD_CLASS) || - pppe.getPrincipalClass().equals(listPppe.getPrincipalClass())) - { - if (pppe.getPrincipalName().equals - (PrincipalEntry.WILDCARD_NAME) || - pppe.getPrincipalName().equals(listPppe.getPrincipalName())) - return true; - } - } - return false; - } - - /** - * Tests for equality between the specified object and this - * object. Two SubjectCodeSource objects are considered equal - * if their locations are of identical value, if the two sets of - * Certificates are of identical values, and if the - * Subjects are equal, and if the PolicyParser.PrincipalEntry values - * are of identical values. It is not required that - * the Certificates or PolicyParser.PrincipalEntry values - * be in the same order. - * - *

- * - * @param obj the object to test for equality with this object. - * - * @return true if the objects are considered equal, false otherwise. - */ - public boolean equals(Object obj) { - - if (obj == this) - return true; - - if (super.equals(obj) == false) - return false; - - if (!(obj instanceof SubjectCodeSource)) - return false; - - SubjectCodeSource that = (SubjectCodeSource)obj; - - // the principal lists must match - try { - if (this.getSubject() != that.getSubject()) - return false; - } catch (SecurityException se) { - return false; - } - - if ((this.principals == null && that.principals != null) || - (this.principals != null && that.principals == null)) - return false; - - if (this.principals != null && that.principals != null) { - if (!this.principals.containsAll(that.principals) || - !that.principals.containsAll(this.principals)) - - return false; - } - - return true; - } - - /** - * Return a hashcode for this SubjectCodeSource. - * - *

- * - * @return a hashcode for this SubjectCodeSource. - */ - public int hashCode() { - return super.hashCode(); - } - - /** - * Return a String representation of this SubjectCodeSource. - * - *

- * - * @return a String representation of this SubjectCodeSource. - */ - public String toString() { - String returnMe = super.toString(); - if (getSubject() != null) { - if (debug != null) { - final Subject finalSubject = getSubject(); - returnMe = returnMe + "\n" + - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public String run() { - return finalSubject.toString(); - } - }); - } else { - returnMe = returnMe + "\n" + getSubject().toString(); - } - } - if (principals != null) { - ListIterator li = principals.listIterator(); - while (li.hasNext()) { - PrincipalEntry pppe = li.next(); - returnMe = returnMe + rb.getString("NEWLINE") + - pppe.getPrincipalClass() + " " + - pppe.getPrincipalName(); - } - } - return returnMe; - } -} diff -r 7de6ae3cecad -r 57876ed3c426 jdk/src/share/classes/javax/security/auth/Policy.java --- a/jdk/src/share/classes/javax/security/auth/Policy.java Mon Aug 19 12:38:56 2013 -0700 +++ b/jdk/src/share/classes/javax/security/auth/Policy.java Mon Aug 19 17:17:17 2013 -0400 @@ -156,9 +156,10 @@ private static Policy policy; private static ClassLoader contextClassLoader; + private final static String AUTH_POLICY = + "sun.security.provider.AuthPolicyFile"; - // true if a custom (not com.sun.security.auth.PolicyFile) system-wide - // policy object is set + // true if a custom (not AUTH_POLICY) system-wide policy object is set private static boolean isCustomPolicy; static { @@ -220,7 +221,7 @@ } }); if (policy_class == null) { - policy_class = "com.sun.security.auth.PolicyFile"; + policy_class = AUTH_POLICY; } try { @@ -236,8 +237,7 @@ contextClassLoader).newInstance(); } }); - isCustomPolicy = - !finalClass.equals("com.sun.security.auth.PolicyFile"); + isCustomPolicy = !finalClass.equals(AUTH_POLICY); } catch (Exception e) { throw new SecurityException (sun.security.util.ResourcesMgr.getString @@ -274,14 +274,14 @@ } /** - * Returns true if a custom (not com.sun.security.auth.PolicyFile) - * system-wide policy object has been set or installed. This method is - * called by SubjectDomainCombiner to provide backwards compatibility for + * Returns true if a custom (not AUTH_POLICY) system-wide policy object + * has been set or installed. This method is called by + * SubjectDomainCombiner to provide backwards compatibility for * developers that provide their own javax.security.auth.Policy * implementations. * - * @return true if a custom (not com.sun.security.auth.PolicyFile) - * system-wide policy object has been set; false otherwise + * @return true if a custom (not AUTH_POLICY) system-wide policy object + * has been set; false otherwise */ static boolean isCustomPolicySet(Debug debug) { if (policy != null) { @@ -299,8 +299,7 @@ return Security.getProperty("auth.policy.provider"); } }); - if (policyClass != null - && !policyClass.equals("com.sun.security.auth.PolicyFile")) { + if (policyClass != null && !policyClass.equals(AUTH_POLICY)) { if (debug != null) { debug.println("Providing backwards compatibility for " + "javax.security.auth.policy implementation: " + diff -r 7de6ae3cecad -r 57876ed3c426 jdk/src/share/classes/sun/security/provider/AuthPolicyFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/security/provider/AuthPolicyFile.java Mon Aug 19 17:17:17 2013 -0400 @@ -0,0 +1,1195 @@ +/* + * 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(); + } +} diff -r 7de6ae3cecad -r 57876ed3c426 jdk/src/share/classes/sun/security/provider/SubjectCodeSource.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/security/provider/SubjectCodeSource.java Mon Aug 19 17:17:17 2013 -0400 @@ -0,0 +1,401 @@ +/* + * 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.net.URL; +import java.util.*; +import java.security.CodeSource; +import java.security.Principal; +import java.security.cert.Certificate; +import java.lang.reflect.Constructor; + +import javax.security.auth.Subject; +import sun.security.provider.PolicyParser.PrincipalEntry; + +/** + *

This SubjectCodeSource class contains + * a URL, signer certificates, and either a Subject + * (that represents the Subject in the current + * AccessControlContext), or a linked list of Principals + * (that represent a "subject" in a Policy). + * + */ +class SubjectCodeSource extends CodeSource implements java.io.Serializable { + + private static final long serialVersionUID = 6039418085604715275L; + + private static final java.util.ResourceBundle rb = + java.security.AccessController.doPrivileged + (new java.security.PrivilegedAction() { + public java.util.ResourceBundle run() { + return (java.util.ResourceBundle.getBundle + ("sun.security.util.AuthResources")); + } + }); + + private Subject subject; + private LinkedList principals; + private static final Class[] PARAMS = { String.class }; + private static final sun.security.util.Debug debug = + sun.security.util.Debug.getInstance("auth", "\t[Auth Access]"); + private ClassLoader sysClassLoader; + + /** + * Creates a new SubjectCodeSource + * with the given Subject, principals, URL, + * and signers (Certificates). The Subject + * represents the Subject associated with the current + * AccessControlContext. + * The Principals are given as a LinkedList + * of PolicyParser.PrincipalEntry objects. + * Typically either a Subject will be provided, + * or a list of principals will be provided + * (not both). + * + *

+ * + * @param subject the Subject associated with this + * SubjectCodeSource

+ * + * @param url the URL associated with this + * SubjectCodeSource

+ * + * @param certs the signers associated with this + * SubjectCodeSource

+ */ + SubjectCodeSource(Subject subject, + LinkedList principals, + URL url, Certificate[] certs) { + + super(url, certs); + this.subject = subject; + this.principals = (principals == null ? + new LinkedList() : + new LinkedList(principals)); + sysClassLoader = java.security.AccessController.doPrivileged + (new java.security.PrivilegedAction() { + public ClassLoader run() { + return ClassLoader.getSystemClassLoader(); + } + }); + } + + /** + * Get the Principals associated with this SubjectCodeSource. + * The Principals are retrieved as a LinkedList + * of PolicyParser.PrincipalEntry objects. + * + *

+ * + * @return the Principals associated with this + * SubjectCodeSource as a LinkedList + * of PolicyParser.PrincipalEntry objects. + */ + LinkedList getPrincipals() { + return principals; + } + + /** + * Get the Subject associated with this + * SubjectCodeSource. The Subject + * represents the Subject associated with the + * current AccessControlContext. + * + *

+ * + * @return the Subject associated with this + * SubjectCodeSource. + */ + Subject getSubject() { + return subject; + } + + /** + * Returns true if this SubjectCodeSource object "implies" + * the specified CodeSource. + * More specifically, this method makes the following checks. + * If any fail, it returns false. If they all succeed, it returns true. + * + *

+ *

    + *
  1. The provided codesource must not be null. + *
  2. codesource must be an instance of SubjectCodeSource. + *
  3. super.implies(codesource) must return true. + *
  4. for each principal in this codesource's principal list: + *
      + *
    1. if the principal is an instanceof + * Principal, then the principal must + * imply the provided codesource's Subject. + *
    2. if the principal is not an instanceof + * Principal, then the provided + * codesource's Subject must have an + * associated Principal, P, where + * P.getClass().getName equals principal.principalClass, + * and P.getName() equals principal.principalName. + *
    + *
+ * + *

+ * + * @param codesource the CodeSource to compare against. + * + * @return true if this SubjectCodeSource implies the + * the specified CodeSource. + */ + public boolean implies(CodeSource codesource) { + + LinkedList subjectList = null; + + if (codesource == null || + !(codesource instanceof SubjectCodeSource) || + !(super.implies(codesource))) { + + if (debug != null) + debug.println("\tSubjectCodeSource.implies: FAILURE 1"); + return false; + } + + SubjectCodeSource that = (SubjectCodeSource)codesource; + + // if the principal list in the policy "implies" + // the Subject associated with the current AccessControlContext, + // then return true + + if (this.principals == null) { + if (debug != null) + debug.println("\tSubjectCodeSource.implies: PASS 1"); + return true; + } + + if (that.getSubject() == null || + that.getSubject().getPrincipals().size() == 0) { + if (debug != null) + debug.println("\tSubjectCodeSource.implies: FAILURE 2"); + return false; + } + + ListIterator li = this.principals.listIterator(0); + while (li.hasNext()) { + PrincipalEntry pppe = li.next(); + try { + + // use new Principal.implies method + + Class pClass = Class.forName(pppe.principalClass, + true, sysClassLoader); + if (!Principal.class.isAssignableFrom(pClass)) { + // not the right subtype + throw new ClassCastException(pppe.principalClass + + " is not a Principal"); + } + Constructor c = pClass.getConstructor(PARAMS); + Principal p = (Principal)c.newInstance(new Object[] { + pppe.principalName }); + + if (!p.implies(that.getSubject())) { + if (debug != null) + debug.println("\tSubjectCodeSource.implies: FAILURE 3"); + return false; + } else { + if (debug != null) + debug.println("\tSubjectCodeSource.implies: PASS 2"); + return true; + } + } catch (Exception e) { + + // simply compare Principals + + if (subjectList == null) { + + if (that.getSubject() == null) { + if (debug != null) + debug.println("\tSubjectCodeSource.implies: " + + "FAILURE 4"); + return false; + } + Iterator i = + that.getSubject().getPrincipals().iterator(); + + subjectList = new LinkedList(); + while (i.hasNext()) { + Principal p = i.next(); + PrincipalEntry spppe = new PrincipalEntry + (p.getClass().getName(), p.getName()); + subjectList.add(spppe); + } + } + + if (!subjectListImpliesPrincipalEntry(subjectList, pppe)) { + if (debug != null) + debug.println("\tSubjectCodeSource.implies: FAILURE 5"); + return false; + } + } + } + + if (debug != null) + debug.println("\tSubjectCodeSource.implies: PASS 3"); + return true; + } + + /** + * This method returns, true, if the provided subjectList + * "contains" the Principal specified + * in the provided pppe argument. + * + * Note that the provided pppe argument may have + * wildcards (*) for the Principal class and name, + * which need to be considered. + * + *

+ * + * @param subjectList a list of PolicyParser.PrincipalEntry objects + * that correspond to all the Principals in the Subject currently + * on this thread's AccessControlContext.

+ * + * @param pppe the Principals specified in a grant entry. + * + * @return true if the provided subjectList "contains" + * the Principal specified in the provided + * pppe argument. + */ + private boolean subjectListImpliesPrincipalEntry( + LinkedList subjectList, PrincipalEntry pppe) { + + ListIterator li = subjectList.listIterator(0); + while (li.hasNext()) { + PrincipalEntry listPppe = li.next(); + + if (pppe.getPrincipalClass().equals + (PrincipalEntry.WILDCARD_CLASS) || + pppe.getPrincipalClass().equals(listPppe.getPrincipalClass())) + { + if (pppe.getPrincipalName().equals + (PrincipalEntry.WILDCARD_NAME) || + pppe.getPrincipalName().equals(listPppe.getPrincipalName())) + return true; + } + } + return false; + } + + /** + * Tests for equality between the specified object and this + * object. Two SubjectCodeSource objects are considered equal + * if their locations are of identical value, if the two sets of + * Certificates are of identical values, and if the + * Subjects are equal, and if the PolicyParser.PrincipalEntry values + * are of identical values. It is not required that + * the Certificates or PolicyParser.PrincipalEntry values + * be in the same order. + * + *

+ * + * @param obj the object to test for equality with this object. + * + * @return true if the objects are considered equal, false otherwise. + */ + public boolean equals(Object obj) { + + if (obj == this) + return true; + + if (super.equals(obj) == false) + return false; + + if (!(obj instanceof SubjectCodeSource)) + return false; + + SubjectCodeSource that = (SubjectCodeSource)obj; + + // the principal lists must match + try { + if (this.getSubject() != that.getSubject()) + return false; + } catch (SecurityException se) { + return false; + } + + if ((this.principals == null && that.principals != null) || + (this.principals != null && that.principals == null)) + return false; + + if (this.principals != null && that.principals != null) { + if (!this.principals.containsAll(that.principals) || + !that.principals.containsAll(this.principals)) + + return false; + } + + return true; + } + + /** + * Return a hashcode for this SubjectCodeSource. + * + *

+ * + * @return a hashcode for this SubjectCodeSource. + */ + public int hashCode() { + return super.hashCode(); + } + + /** + * Return a String representation of this SubjectCodeSource. + * + *

+ * + * @return a String representation of this SubjectCodeSource. + */ + public String toString() { + String returnMe = super.toString(); + if (getSubject() != null) { + if (debug != null) { + final Subject finalSubject = getSubject(); + returnMe = returnMe + "\n" + + java.security.AccessController.doPrivileged + (new java.security.PrivilegedAction() { + public String run() { + return finalSubject.toString(); + } + }); + } else { + returnMe = returnMe + "\n" + getSubject().toString(); + } + } + if (principals != null) { + ListIterator li = principals.listIterator(); + while (li.hasNext()) { + PrincipalEntry pppe = li.next(); + returnMe = returnMe + rb.getString("NEWLINE") + + pppe.getPrincipalClass() + " " + + pppe.getPrincipalName(); + } + } + return returnMe; + } +}