diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/gnu/java/security/PolicyFile.java | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/classpath/gnu/java/security/PolicyFile.java')
-rw-r--r-- | libjava/classpath/gnu/java/security/PolicyFile.java | 687 |
1 files changed, 687 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/java/security/PolicyFile.java b/libjava/classpath/gnu/java/security/PolicyFile.java new file mode 100644 index 000000000..0560bce07 --- /dev/null +++ b/libjava/classpath/gnu/java/security/PolicyFile.java @@ -0,0 +1,687 @@ +/* PolicyFile.java -- policy file reader + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.security; + +import gnu.classpath.debug.Component; +import gnu.classpath.debug.SystemLogger; + +import gnu.java.lang.CPStringBuilder; +import gnu.java.security.action.GetPropertyAction; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.StreamTokenizer; +import java.lang.reflect.Constructor; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.AccessController; +import java.security.CodeSource; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.security.Policy; +import java.security.Principal; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.security.Security; +import java.security.UnresolvedPermission; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.logging.Logger; + +/** + * An implementation of a {@link java.security.Policy} object whose + * permissions are specified by a <em>policy file</em>. + * + * <p>The approximate syntax of policy files is:</p> + * + * <pre> + * policyFile ::= keystoreOrGrantEntries ; + * + * keystoreOrGrantEntries ::= keystoreOrGrantEntry | + * keystoreOrGrantEntries keystoreOrGrantEntry | + * EMPTY ; + * + * keystoreOrGrantEntry ::= keystoreEntry | grantEntry ; + * + * keystoreEntry ::= "keystore" keystoreUrl ';' | + * "keystore" keystoreUrl ',' keystoreAlgorithm ';' ; + * + * keystoreUrl ::= URL ; + * keystoreAlgorithm ::= STRING ; + * + * grantEntry ::= "grant" domainParameters '{' permissions '}' ';' + * + * domainParameters ::= domainParameter | + * domainParameter ',' domainParameters ; + * + * domainParameter ::= "signedBy" signerNames | + * "codeBase" codeBaseUrl | + * "principal" principalClassName principalName | + * "principal" principalName ; + * + * signerNames ::= quotedString ; + * codeBaseUrl ::= URL ; + * principalClassName ::= STRING ; + * principalName ::= quotedString ; + * + * quotedString ::= quoteChar STRING quoteChar ; + * quoteChar ::= '"' | '\''; + * + * permissions ::= permission | permissions permission ; + * + * permission ::= "permission" permissionClassName permissionTarget permissionAction | + * "permission" permissionClassName permissionTarget | + * "permission" permissionClassName; + * </pre> + * + * <p>Comments are either form of Java comments. Keystore entries only + * affect subsequent grant entries, so if a grant entry preceeds a + * keystore entry, that grant entry is not affected by that keystore + * entry. Certian instances of <code>${property-name}</code> will be + * replaced with <code>System.getProperty("property-name")</code> in + * quoted strings.</p> + * + * <p>This class will load the following files when created or + * refreshed, in order:</p> + * + * <ol> + * <li>The file <code>${java.home}/lib/security/java.policy</code>.</li> + * <li>All URLs specified by security properties + * <code>"policy.file.<i>n</i>"</code>, for increasing <i>n</i> + * starting from 1. The sequence stops at the first undefined + * property, so you must set <code>"policy.file.1"</code> if you also + * set <code>"policy.file.2"</code>, and so on.</li> + * <li>The URL specified by the property + * <code>"java.security.policy"</code>.</li> + * </ol> + * + * @author Casey Marshall (csm@gnu.org) + * @see java.security.Policy + */ +public final class PolicyFile extends Policy +{ + + // Constants and fields. + // ------------------------------------------------------------------------- + + protected static final Logger logger = SystemLogger.SYSTEM; + // Added to cut redundant AccessController.doPrivileged calls + private static GetPropertyAction prop = new GetPropertyAction("file.separator"); + private static final String fs = (String) AccessController.doPrivileged(prop); + + private static final String DEFAULT_POLICY = + (String) AccessController.doPrivileged(prop.setParameters("java.home")) + + fs + "lib" + fs + "security" + fs + "java.policy"; + private static final String DEFAULT_USER_POLICY = + (String) AccessController.doPrivileged(prop.setParameters("user.home")) + + fs + ".java.policy"; + + private final Map cs2pc; + + // Constructors. + // ------------------------------------------------------------------------- + + public PolicyFile() + { + cs2pc = new HashMap(); + refresh(); + } + + // Instance methods. + // ------------------------------------------------------------------------- + + public PermissionCollection getPermissions(CodeSource codeSource) + { + Permissions perms = new Permissions(); + for (Iterator it = cs2pc.entrySet().iterator(); it.hasNext(); ) + { + Map.Entry e = (Map.Entry) it.next(); + CodeSource cs = (CodeSource) e.getKey(); + if (cs.implies(codeSource)) + { + logger.log (Component.POLICY, "{0} -> {1}", new Object[] + { cs, codeSource }); + PermissionCollection pc = (PermissionCollection) e.getValue(); + for (Enumeration ee = pc.elements(); ee.hasMoreElements(); ) + { + perms.add((Permission) ee.nextElement()); + } + } + else + logger.log (Component.POLICY, "{0} !-> {1}", new Object[] + { cs, codeSource }); + } + logger.log (Component.POLICY, "returning permissions {0} for {1}", + new Object[] { perms, codeSource }); + return perms; + } + + public void refresh() + { + cs2pc.clear(); + final List policyFiles = new LinkedList(); + try + { + policyFiles.add (new File (DEFAULT_POLICY).toURL()); + policyFiles.add (new File (DEFAULT_USER_POLICY).toURL ()); + + AccessController.doPrivileged( + new PrivilegedExceptionAction() + { + public Object run() throws Exception + { + String allow = Security.getProperty ("policy.allowSystemProperty"); + if (allow == null || Boolean.getBoolean (allow)) + { + String s = System.getProperty ("java.security.policy"); + logger.log (Component.POLICY, "java.security.policy={0}", s); + if (s != null) + { + boolean only = s.startsWith ("="); + if (only) + s = s.substring (1); + policyFiles.clear (); + policyFiles.add (new URL (s)); + if (only) + return null; + } + } + for (int i = 1; ; i++) + { + String pname = "policy.url." + i; + String s = Security.getProperty (pname); + logger.log (Component.POLICY, "{0}={1}", new Object [] + { pname, s }); + if (s == null) + break; + policyFiles.add (new URL (s)); + } + return null; + } + }); + } + catch (PrivilegedActionException pae) + { + logger.log (Component.POLICY, "reading policy properties", pae); + } + catch (MalformedURLException mue) + { + logger.log (Component.POLICY, "setting default policies", mue); + } + + logger.log (Component.POLICY, "building policy from URLs {0}", + policyFiles); + for (Iterator it = policyFiles.iterator(); it.hasNext(); ) + { + try + { + URL url = (URL) it.next(); + parse(url); + } + catch (IOException ioe) + { + logger.log (Component.POLICY, "reading policy", ioe); + } + } + } + + public String toString() + { + return super.toString() + " [ " + cs2pc.toString() + " ]"; + } + + // Own methods. + // ------------------------------------------------------------------------- + + private static final int STATE_BEGIN = 0; + private static final int STATE_GRANT = 1; + private static final int STATE_PERMS = 2; + + /** + * Parse a policy file, incorporating the permission definitions + * described therein. + * + * @param url The URL of the policy file to read. + * @throws IOException if an I/O error occurs, or if the policy file + * cannot be parsed. + */ + private void parse(final URL url) throws IOException + { + logger.log (Component.POLICY, "reading policy file from {0}", url); + final StreamTokenizer in = new StreamTokenizer(new InputStreamReader(url.openStream())); + in.resetSyntax(); + in.slashSlashComments(true); + in.slashStarComments(true); + in.wordChars('A', 'Z'); + in.wordChars('a', 'z'); + in.wordChars('0', '9'); + in.wordChars('.', '.'); + in.wordChars('_', '_'); + in.wordChars('$', '$'); + in.whitespaceChars(' ', ' '); + in.whitespaceChars('\t', '\t'); + in.whitespaceChars('\f', '\f'); + in.whitespaceChars('\n', '\n'); + in.whitespaceChars('\r', '\r'); + in.quoteChar('\''); + in.quoteChar('"'); + + int tok; + int state = STATE_BEGIN; + List keystores = new LinkedList(); + URL currentBase = null; + List currentCerts = new LinkedList(); + Permissions currentPerms = new Permissions(); + while ((tok = in.nextToken()) != StreamTokenizer.TT_EOF) + { + switch (tok) + { + case '{': + if (state != STATE_GRANT) + error(url, in, "spurious '{'"); + state = STATE_PERMS; + tok = in.nextToken(); + break; + case '}': + if (state != STATE_PERMS) + error(url, in, "spurious '}'"); + state = STATE_BEGIN; + currentPerms.setReadOnly(); + Certificate[] c = null; + if (!currentCerts.isEmpty()) + c = (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()]); + cs2pc.put(new CodeSource(currentBase, c), currentPerms); + currentCerts.clear(); + currentPerms = new Permissions(); + currentBase = null; + tok = in.nextToken(); + if (tok != ';') + in.pushBack(); + continue; + } + if (tok != StreamTokenizer.TT_WORD) + { + error(url, in, "expecting word token"); + } + + // keystore "<keystore-path>" [',' "<keystore-type>"] ';' + if (in.sval.equalsIgnoreCase("keystore")) + { + String alg = KeyStore.getDefaultType(); + tok = in.nextToken(); + if (tok != '"' && tok != '\'') + error(url, in, "expecting key store URL"); + String store = in.sval; + tok = in.nextToken(); + if (tok == ',') + { + tok = in.nextToken(); + if (tok != '"' && tok != '\'') + error(url, in, "expecting key store type"); + alg = in.sval; + tok = in.nextToken(); + } + if (tok != ';') + error(url, in, "expecting semicolon"); + try + { + KeyStore keystore = KeyStore.getInstance(alg); + keystore.load(new URL(url, store).openStream(), null); + keystores.add(keystore); + } + catch (Exception x) + { + error(url, in, x.toString()); + } + } + else if (in.sval.equalsIgnoreCase("grant")) + { + if (state != STATE_BEGIN) + error(url, in, "extraneous grant keyword"); + state = STATE_GRANT; + } + else if (in.sval.equalsIgnoreCase("signedBy")) + { + if (state != STATE_GRANT && state != STATE_PERMS) + error(url, in, "spurious 'signedBy'"); + if (keystores.isEmpty()) + error(url, in, "'signedBy' with no keystores"); + tok = in.nextToken(); + if (tok != '"' && tok != '\'') + error(url, in, "expecting signedBy name"); + StringTokenizer st = new StringTokenizer(in.sval, ","); + while (st.hasMoreTokens()) + { + String alias = st.nextToken(); + for (Iterator it = keystores.iterator(); it.hasNext(); ) + { + KeyStore keystore = (KeyStore) it.next(); + try + { + if (keystore.isCertificateEntry(alias)) + currentCerts.add(keystore.getCertificate(alias)); + } + catch (KeyStoreException kse) + { + error(url, in, kse.toString()); + } + } + } + tok = in.nextToken(); + if (tok != ',') + { + if (state != STATE_GRANT) + error(url, in, "spurious ','"); + in.pushBack(); + } + } + else if (in.sval.equalsIgnoreCase("codeBase")) + { + if (state != STATE_GRANT) + error(url, in, "spurious 'codeBase'"); + tok = in.nextToken(); + if (tok != '"' && tok != '\'') + error(url, in, "expecting code base URL"); + String base = expand(in.sval); + if (File.separatorChar != '/') + base = base.replace(File.separatorChar, '/'); + try + { + currentBase = new URL(base); + } + catch (MalformedURLException mue) + { + error(url, in, mue.toString()); + } + tok = in.nextToken(); + if (tok != ',') + in.pushBack(); + } + else if (in.sval.equalsIgnoreCase("principal")) + { + if (state != STATE_GRANT) + error(url, in, "spurious 'principal'"); + tok = in.nextToken(); + if (tok == StreamTokenizer.TT_WORD) + { + tok = in.nextToken(); + if (tok != '"' && tok != '\'') + error(url, in, "expecting principal name"); + String name = in.sval; + Principal p = null; + try + { + Class pclass = Class.forName(in.sval); + Constructor c = + pclass.getConstructor(new Class[] { String.class }); + p = (Principal) c.newInstance(new Object[] { name }); + } + catch (Exception x) + { + error(url, in, x.toString()); + } + for (Iterator it = keystores.iterator(); it.hasNext(); ) + { + KeyStore ks = (KeyStore) it.next(); + try + { + for (Enumeration e = ks.aliases(); e.hasMoreElements(); ) + { + String alias = (String) e.nextElement(); + if (ks.isCertificateEntry(alias)) + { + Certificate cert = ks.getCertificate(alias); + if (!(cert instanceof X509Certificate)) + continue; + if (p.equals(((X509Certificate) cert).getSubjectDN()) || + p.equals(((X509Certificate) cert).getSubjectX500Principal())) + currentCerts.add(cert); + } + } + } + catch (KeyStoreException kse) + { + error(url, in, kse.toString()); + } + } + } + else if (tok == '"' || tok == '\'') + { + String alias = in.sval; + for (Iterator it = keystores.iterator(); it.hasNext(); ) + { + KeyStore ks = (KeyStore) it.next(); + try + { + if (ks.isCertificateEntry(alias)) + currentCerts.add(ks.getCertificate(alias)); + } + catch (KeyStoreException kse) + { + error(url, in, kse.toString()); + } + } + } + else + error(url, in, "expecting principal"); + tok = in.nextToken(); + if (tok != ',') + in.pushBack(); + } + else if (in.sval.equalsIgnoreCase("permission")) + { + if (state != STATE_PERMS) + error(url, in, "spurious 'permission'"); + tok = in.nextToken(); + if (tok != StreamTokenizer.TT_WORD) + error(url, in, "expecting permission class name"); + String className = in.sval; + Class clazz = null; + try + { + clazz = Class.forName(className); + } + catch (ClassNotFoundException cnfe) + { + } + tok = in.nextToken(); + if (tok == ';') + { + if (clazz == null) + { + currentPerms.add(new UnresolvedPermission(className, + null, null, (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()]))); + continue; + } + try + { + currentPerms.add((Permission) clazz.newInstance()); + } + catch (Exception x) + { + error(url, in, x.toString()); + } + continue; + } + if (tok != '"' && tok != '\'') + error(url, in, "expecting permission target"); + String target = expand(in.sval); + tok = in.nextToken(); + if (tok == ';') + { + if (clazz == null) + { + currentPerms.add(new UnresolvedPermission(className, + target, null, (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()]))); + continue; + } + try + { + Constructor c = + clazz.getConstructor(new Class[] { String.class }); + currentPerms.add((Permission) c.newInstance( + new Object[] { target })); + } + catch (Exception x) + { + error(url, in, x.toString()); + } + continue; + } + if (tok != ',') + error(url, in, "expecting ','"); + tok = in.nextToken(); + if (tok == StreamTokenizer.TT_WORD) + { + if (!in.sval.equalsIgnoreCase("signedBy")) + error(url, in, "expecting 'signedBy'"); + try + { + Constructor c = + clazz.getConstructor(new Class[] { String.class }); + currentPerms.add((Permission) c.newInstance( + new Object[] { target })); + } + catch (Exception x) + { + error(url, in, x.toString()); + } + in.pushBack(); + continue; + } + if (tok != '"' && tok != '\'') + error(url, in, "expecting permission action"); + String action = in.sval; + if (clazz == null) + { + currentPerms.add(new UnresolvedPermission(className, + target, action, (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()]))); + continue; + } + else + { + try + { + Constructor c = clazz.getConstructor( + new Class[] { String.class, String.class }); + currentPerms.add((Permission) c.newInstance( + new Object[] { target, action })); + } + catch (Exception x) + { + error(url, in, x.toString()); + } + } + tok = in.nextToken(); + if (tok != ';' && tok != ',') + error(url, in, "expecting ';' or ','"); + } + } + } + + /** + * Expand all instances of <code>"${property-name}"</code> into + * <code>System.getProperty("property-name")</code>. + */ + private static String expand(final String s) + { + final CPStringBuilder result = new CPStringBuilder(); + final CPStringBuilder prop = new CPStringBuilder(); + int state = 0; + for (int i = 0; i < s.length(); i++) + { + switch (state) + { + case 0: + if (s.charAt(i) == '$') + state = 1; + else + result.append(s.charAt(i)); + break; + case 1: + if (s.charAt(i) == '{') + state = 2; + else + { + state = 0; + result.append('$').append(s.charAt(i)); + } + break; + case 2: + if (s.charAt(i) == '}') + { + String p = prop.toString(); + if (p.equals("/")) + p = "file.separator"; + p = System.getProperty(p); + if (p == null) + p = ""; + result.append(p); + prop.setLength(0); + state = 0; + } + else + prop.append(s.charAt(i)); + break; + } + } + if (state != 0) + result.append('$').append('{').append(prop); + return result.toString(); + } + + /** + * I miss macros. + */ + private static void error(URL base, StreamTokenizer in, String msg) + throws IOException + { + throw new IOException(base+":"+in.lineno()+": "+msg); + } +} |