0001: /*
0002: * @(#)PolicyFile.java 1.6 06/10/11
0003: *
0004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006: *
0007: * This program is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU General Public License version
0009: * 2 only, as published by the Free Software Foundation.
0010: *
0011: * This program is distributed in the hope that it will be useful, but
0012: * WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * General Public License version 2 for more details (a copy is
0015: * included at /legal/license.txt).
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * version 2 along with this work; if not, write to the Free Software
0019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA
0021: *
0022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023: * Clara, CA 95054 or visit www.sun.com if you need additional
0024: * information or have any questions.
0025: *
0026: */
0027:
0028: /*
0029: * Note that there are three versions of
0030: * sun.security.Provider.PolicyFile:
0031: * a subsetted version for CDC;
0032: * this subsetted version for CDC/FP; and
0033: * a more complete version for the security optional package.
0034: * Make sure you're editting the correct one!
0035: */
0036:
0037: package sun.security.provider;
0038:
0039: import java.io.*;
0040: import java.lang.RuntimePermission;
0041: import java.lang.reflect.*;
0042: import java.lang.ref.*;
0043: import java.net.MalformedURLException;
0044: import java.net.URL;
0045: import java.net.URI;
0046: import java.util.*;
0047: import java.util.Enumeration;
0048: import java.util.Hashtable;
0049: import java.util.List;
0050: import java.util.StringTokenizer;
0051: import java.util.PropertyPermission;
0052: import java.util.ArrayList;
0053: import java.util.LinkedList;
0054: import java.util.ListIterator;
0055: import java.util.WeakHashMap;
0056: import java.text.MessageFormat; // Subset out PrincipalComparator references for CDC/FP
0057: //import com.sun.security.auth.PrincipalComparator;
0058: import java.security.*;
0059: import java.security.cert.Certificate;
0060: import java.security.cert.X509Certificate; // Subset out javax.security.auth references for CDC/FP,
0061: // with the exception of X500Principal.
0062: //import javax.security.auth.PrivateCredentialPermission;
0063: //import javax.security.auth.Subject;
0064: import javax.security.auth.x500.X500Principal;
0065: import java.io.FilePermission;
0066: import java.net.SocketPermission;
0067: import java.net.NetPermission;
0068: import java.util.PropertyPermission; // Subset out AWTPermission reference for CDC/FP.
0069: //import java.awt.AWTPermission;
0070: /*
0071: import javax.security.auth.AuthPermission;
0072: import javax.security.auth.kerberos.ServicePermission;
0073: import javax.security.auth.kerberos.DelegationPermission;
0074: import java.io.SerializablePermission;
0075: import java.util.logging.LoggingPermission;
0076: import java.sql.SQLPermission;
0077: import java.lang.reflect.ReflectPermission;
0078: import javax.sound.sampled.AudioPermission;
0079: import javax.net.ssl.SSLPermission;
0080: */
0081:
0082: import sun.security.util.PropertyExpander;
0083: import sun.security.util.Debug;
0084: import sun.security.util.ResourcesMgr;
0085: import sun.security.util.SecurityConstants;
0086: import sun.net.www.ParseUtil;
0087:
0088: /**
0089: * This class represents a default implementation for
0090: * <code>java.security.Policy</code>.
0091: *
0092: * Note:
0093: * For backward compatibility with JAAS 1.0 it loads
0094: * both java.auth.policy and java.policy. However it
0095: * is recommended that java.auth.policy be not used
0096: * and the java.policy contain all grant entries including
0097: * that contain principal-based entries.
0098: *
0099: *
0100: * <p> This object stores the policy for entire Java runtime,
0101: * and is the amalgamation of multiple static policy
0102: * configurations that resides in files.
0103: * The algorithm for locating the policy file(s) and reading their
0104: * information into this <code>Policy</code> object is:
0105: *
0106: * <ol>
0107: * <li>
0108: * Loop through the <code>java.security.Security</code> properties,
0109: * <i>policy.url.1</i>, <i>policy.url.2</i>, ...,
0110: * <i>policy.url.X</i>" and
0111: * <i>auth.policy.url.1</i>, <i>auth.policy.url.2</i>, ...,
0112: * <i>auth.policy.url.X</i>". These properties are set
0113: * in the Java security properties file, which is located in the file named
0114: * <JAVA_HOME>/lib/security/java.security, where <JAVA_HOME>
0115: * refers to the directory where the JDK was installed.
0116: * Each property value specifies a <code>URL</code> pointing to a
0117: * policy file to be loaded. Read in and load each policy.
0118: *
0119: * <i>auth.policy.url</i> is supported only for backward compatibility.
0120: *
0121: * <li>
0122: * The <code>java.lang.System</code> property <i>java.security.policy</i>
0123: * may also be set to a <code>URL</code> pointing to another policy file
0124: * (which is the case when a user uses the -D switch at runtime).
0125: * If this property is defined, and its use is allowed by the
0126: * security property file (the Security property,
0127: * <i>policy.allowSystemProperty</i> is set to <i>true</i>),
0128: * also load that policy.
0129: *
0130: * <li>
0131: * The <code>java.lang.System</code> property
0132: * <i>java.security.auth.policy</i> may also be set to a
0133: * <code>URL</code> pointing to another policy file
0134: * (which is the case when a user uses the -D switch at runtime).
0135: * If this property is defined, and its use is allowed by the
0136: * security property file (the Security property,
0137: * <i>policy.allowSystemProperty</i> is set to <i>true</i>),
0138: * also load that policy.
0139: *
0140: * <i>java.security.auth.policy</i> is supported only for backward
0141: * compatibility.
0142: *
0143: * If the <i>java.security.policy</i> or
0144: * <i>java.security.auth.policy</i> property is defined using
0145: * "==" (rather than "="), then ignore all other specified
0146: * policies and only load this policy.
0147: * </ol>
0148: *
0149: * Each policy file consists of one or more grant entries, each of
0150: * which consists of a number of permission entries.
0151: *
0152: * <pre>
0153: * grant signedBy "<b>alias</b>", codeBase "<b>URL</b>",
0154: * principal <b>principalClass</b> "<b>principalName</b>",
0155: * principal <b>principalClass</b> "<b>principalName</b>",
0156: * ... {
0157: *
0158: * permission <b>Type</b> "<b>name</b> "<b>action</b>",
0159: * signedBy "<b>alias</b>";
0160: * permission <b>Type</b> "<b>name</b> "<b>action</b>",
0161: * signedBy "<b>alias</b>";
0162: * ....
0163: * };
0164: * </pre>
0165: *
0166: * All non-bold items above must appear as is (although case
0167: * doesn't matter and some are optional, as noted below).
0168: * principal entries are optional and need not be present.
0169: * Italicized items represent variable values.
0170: *
0171: * <p> A grant entry must begin with the word <code>grant</code>.
0172: * The <code>signedBy</code>,<code>codeBase</code> and <code>principal</code>
0173: * name/value pairs are optional.
0174: * If they are not present, then any signer (including unsigned code)
0175: * will match, and any codeBase will match.
0176: * Note that the <i>principalClass</i>
0177: * may be set to the wildcard value, *, which allows it to match
0178: * any <code>Principal</code> class. In addition, the <i>principalName</i>
0179: * may also be set to the wildcard value, *, allowing it to match
0180: * any <code>Principal</code> name. When setting the <i>principalName</i>
0181: * to the *, do not surround the * with quotes.
0182: *
0183: * <p> A permission entry must begin with the word <code>permission</code>.
0184: * The word <code><i>Type</i></code> in the template above is
0185: * a specific permission type, such as <code>java.io.FilePermission</code>
0186: * or <code>java.lang.RuntimePermission</code>.
0187: *
0188: * <p> The "<i>action</i>" is required for
0189: * many permission types, such as <code>java.io.FilePermission</code>
0190: * (where it specifies what type of file access that is permitted).
0191: * It is not required for categories such as
0192: * <code>java.lang.RuntimePermission</code>
0193: * where it is not necessary - you either have the
0194: * permission specified by the <code>"<i>name</i>"</code>
0195: * value following the type name or you don't.
0196: *
0197: * <p> The <code>signedBy</code> name/value pair for a permission entry
0198: * is optional. If present, it indicates a signed permission. That is,
0199: * the permission class itself must be signed by the given alias in
0200: * order for it to be granted. For example,
0201: * suppose you have the following grant entry:
0202: *
0203: * <pre>
0204: * grant principal foo.com.Principal "Duke" {
0205: * permission Foo "foobar", signedBy "FooSoft";
0206: * }
0207: * </pre>
0208: *
0209: * <p> Then this permission of type <i>Foo</i> is granted if the
0210: * <code>Foo.class</code> permission has been signed by the
0211: * "FooSoft" alias, or if XXX <code>Foo.class</code> is a
0212: * system class (i.e., is found on the CLASSPATH).
0213: *
0214: *
0215: * <p> Items that appear in an entry must appear in the specified order
0216: * (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
0217: * "<i>action</i>"). An entry is terminated with a semicolon.
0218: *
0219: * <p> Case is unimportant for the identifiers (<code>permission</code>,
0220: * <code>signedBy</code>, <code>codeBase</code>, etc.) but is
0221: * significant for the <i>Type</i>
0222: * or for any string that is passed in as a value. <p>
0223: *
0224: * <p> An example of two entries in a policy configuration file is
0225: * <pre>
0226: * // if the code is comes from "foo.com" and is running as "Duke",
0227: * // grant it read/write to all files in /tmp.
0228: *
0229: * grant codeBase "foo.com", principal foo.com.Principal "Duke" {
0230: * permission java.io.FilePermission "/tmp/*", "read,write";
0231: * };
0232: *
0233: * // grant any code running as "Duke" permission to read
0234: * // the "java.vendor" Property.
0235: *
0236: * grant principal foo.com.Principal "Duke" {
0237: * permission java.util.PropertyPermission "java.vendor";
0238: *
0239: *
0240: * </pre>
0241: * This Policy implementation supports special handling of any
0242: * permission that contains the string, "<b>${{self}}</b>", as part of
0243: * its target name. When such a permission is evaluated
0244: * (such as during a security check), <b>${{self}}</b> is replaced
0245: * with one or more Principal class/name pairs. The exact
0246: * replacement performed depends upon the contents of the
0247: * grant clause to which the permission belongs.
0248: *<p>
0249: *
0250: * If the grant clause does not contain any principal information,
0251: * the permission will be ignored (permissions containing
0252: * <b>${{self}}</b> in their target names are only valid in the context
0253: * of a principal-based grant clause). For example, BarPermission
0254: * will always be ignored in the following grant clause:
0255: *
0256: *<pre>
0257: * grant codebase "www.foo.com", signedby "duke" {
0258: * permission BarPermission "... ${{self}} ...";
0259: * };
0260: *</pre>
0261: *
0262: * If the grant clause contains principal information, <b>${{self}}</b>
0263: * will be replaced with that same principal information.
0264: * For example, <b>${{self}}</b> in BarPermission will be replaced by
0265: * <b>javax.security.auth.x500.X500Principal "cn=Duke"</b>
0266: * in the following grant clause:
0267: *
0268: * <pre>
0269: * grant principal javax.security.auth.x500.X500Principal "cn=Duke" {
0270: * permission BarPermission "... ${{self}} ...";
0271: * };
0272: * </pre>
0273: *
0274: * If there is a comma-separated list of principals in the grant
0275: * clause, then <b>${{self}}</b> will be replaced by the same
0276: * comma-separated list or principals.
0277: * In the case where both the principal class and name are
0278: * wildcarded in the grant clause, <b>${{self}}</b> is replaced
0279: * with all the principals associated with the <code>Subject</code>
0280: * in the current <code>AccessControlContext</code>.
0281: *
0282: *
0283: * <p> For PrivateCredentialPermissions, you can also use "<b>self</b>"
0284: * instead of "<b>${{self}}</b>". However the use of "<b>self</b>" is
0285: * deprecated in favour of "<b>${{self}}</b>".
0286: *
0287: * @version 1.47, 11/17/03
0288: * @see java.security.CodeSource
0289: * @see java.security.Permissions
0290: * @see java.security.ProtectionDomain
0291: */
0292: public class PolicyFile extends java.security.Policy {
0293: private static final Debug debug = Debug.getInstance("policy");
0294:
0295: private static final String SELF = "${{self}}";
0296: private static final String X500PRINCIPAL = "javax.security.auth.x500.X500Principal";
0297: private static final String POLICY = "java.security.policy";
0298: private static final String SECURITY_MANAGER = "java.security.manager";
0299: private static final String POLICY_URL = "policy.url.";
0300: private static final String AUTH_POLICY = "java.security.auth.policy";
0301: private static final String AUTH_POLICY_URL = "auth.policy.url.";
0302:
0303: private static final int DEFAULT_CACHE_SIZE = 1;
0304:
0305: /** the scope to check */
0306: private static IdentityScope scope = null;
0307:
0308: // contains the policy grant entries, PD cache, and alias mapping
0309: private PolicyInfo policyInfo;
0310: private boolean constructed = false;
0311:
0312: private boolean expandProperties = true;
0313: private boolean ignoreIdentityScope = false;
0314: private boolean allowSystemProperties = true;
0315: private boolean notUtf8 = false;
0316:
0317: // for use with the reflection API
0318:
0319: private static final Class[] PARAMS0 = {};
0320: private static final Class[] PARAMS1 = { String.class };
0321: private static final Class[] PARAMS2 = { String.class, String.class };
0322:
0323: /**
0324: * Initializes the Policy object and reads the default policy
0325: * configuration file(s) into the Policy object.
0326: */
0327: public PolicyFile() {
0328: init();
0329: }
0330:
0331: /**
0332: * Initializes the Policy object and reads the default policy
0333: * configuration file(s) into the Policy object.
0334: *
0335: * The algorithm for locating the policy file(s) and reading their
0336: * information into the Policy object is:
0337: * <pre>
0338: * loop through the Security Properties named "policy.url.1",
0339: * ""policy.url.2", "auth.policy.url.1", "auth.policy.url.2" etc, until
0340: * you don't find one. Each of these specify a policy file.
0341: *
0342: * if none of these could be loaded, use a builtin static policy
0343: * equivalent to the default lib/security/java.policy file.
0344: *
0345: * if the system property "java.policy" or "java.auth.policy" is defined
0346: * (which is the
0347: * case when the user uses the -D switch at runtime), and
0348: * its use is allowed by the security property file,
0349: * also load it.
0350: * </pre>
0351: *
0352: * Each policy file consists of one or more grant entries, each of
0353: * which consists of a number of permission entries.
0354: * <pre>
0355: * grant signedBy "<i>alias</i>", codeBase "<i>URL</i>" {
0356: * permission <i>Type</i> "<i>name</i>", "<i>action</i>",
0357: * signedBy "<i>alias</i>";
0358: * ....
0359: * permission <i>Type</i> "<i>name</i>", "<i>action</i>",
0360: * signedBy "<i>alias</i>";
0361: * };
0362: *
0363: * </pre>
0364: *
0365: * All non-italicized items above must appear as is (although case
0366: * doesn't matter and some are optional, as noted below).
0367: * Italicized items represent variable values.
0368: *
0369: * <p> A grant entry must begin with the word <code>grant</code>.
0370: * The <code>signedBy</code> and <code>codeBase</code> name/value
0371: * pairs are optional.
0372: * If they are not present, then any signer (including unsigned code)
0373: * will match, and any codeBase will match.
0374: *
0375: * <p> A permission entry must begin with the word <code>permission</code>.
0376: * The word <code><i>Type</i></code> in the template above would actually
0377: * be a specific permission type, such as
0378: * <code>java.io.FilePermission</code> or
0379: * <code>java.lang.RuntimePermission</code>.
0380: *
0381: * <p>The "<i>action</i>" is required for
0382: * many permission types, such as <code>java.io.FilePermission</code>
0383: * (where it specifies what type of file access is permitted).
0384: * It is not required for categories such as
0385: * <code>java.lang.RuntimePermission</code>
0386: * where it is not necessary - you either have the
0387: * permission specified by the <code>"<i>name</i>"</code>
0388: * value following the type name or you don't.
0389: *
0390: * <p>The <code>signedBy</code> name/value pair for a permission entry
0391: * is optional. If present, it indicates a signed permission. That is,
0392: * the permission class itself must be signed by the given alias in
0393: * order for it to be granted. For example,
0394: * suppose you have the following grant entry:
0395: *
0396: * <pre>
0397: * grant {
0398: * permission Foo "foobar", signedBy "FooSoft";
0399: * }
0400: * </pre>
0401: *
0402: * <p>Then this permission of type <i>Foo</i> is granted if the
0403: * <code>Foo.class</code> permission has been signed by the
0404: * "FooSoft" alias, or if <code>Foo.class</code> is a
0405: * system class (i.e., is found on the CLASSPATH).
0406: *
0407: * <p>Items that appear in an entry must appear in the specified order
0408: * (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
0409: * "<i>action</i>"). An entry is terminated with a semicolon.
0410: *
0411: * <p>Case is unimportant for the identifiers (<code>permission</code>,
0412: * <code>signedBy</code>, <code>codeBase</code>, etc.) but is
0413: * significant for the <i>Type</i>
0414: * or for any string that is passed in as a value. <p>
0415: *
0416: * <p>An example of two entries in a policy configuration file is
0417: * <pre>
0418: * // if the code is signed by "Duke", grant it read/write to all
0419: * // files in /tmp.
0420: *
0421: * grant signedBy "Duke" {
0422: * permission java.io.FilePermission "/tmp/*", "read,write";
0423: * };
0424: * <p>
0425: * // grant everyone the following permission
0426: *
0427: * grant {
0428: * permission java.util.PropertyPermission "java.vendor";
0429: * };
0430: * </pre>
0431: */
0432: private void init() {
0433: // Properties are set once for each init(); ignore changes between
0434: // between diff invocations of initPolicyFile(policy, url, info).
0435: String numCacheStr = (String) AccessController
0436: .doPrivileged(new PrivilegedAction() {
0437: public Object run() {
0438: expandProperties = "true"
0439: .equalsIgnoreCase(Security
0440: .getProperty("policy.expandProperties"));
0441: ignoreIdentityScope = "true"
0442: .equalsIgnoreCase(Security
0443: .getProperty("policy.ignoreIdentityScope"));
0444: allowSystemProperties = "true"
0445: .equalsIgnoreCase(Security
0446: .getProperty("policy.allowSystemProperty"));
0447: notUtf8 = "false"
0448: .equalsIgnoreCase(System
0449: .getProperty("sun.security.policy.utf8"));
0450: return System
0451: .getProperty("sun.security.policy.numcaches");
0452: }
0453: });
0454:
0455: int numCaches;
0456: if (numCacheStr != null) {
0457: try {
0458: numCaches = Integer.parseInt(numCacheStr);
0459: } catch (NumberFormatException e) {
0460: numCaches = DEFAULT_CACHE_SIZE;
0461: }
0462: } else {
0463: numCaches = DEFAULT_CACHE_SIZE;
0464: }
0465: // System.out.println("number caches=" + numCaches);
0466: PolicyInfo newInfo = new PolicyInfo(numCaches);
0467: initPolicyFile(newInfo);
0468: policyInfo = newInfo;
0469: }
0470:
0471: private void initPolicyFile(PolicyInfo newInfo) {
0472:
0473: /* We call initPolicyFile with POLICY , POLICY_URL and then
0474: * call it with AUTH_POLICY and AUTH_POLICY_URL
0475: * So first we will process the JAVA standard policy
0476: * and then process the JAVA AUTH Policy.
0477: * This is for backward compatibility as well as to handle
0478: * cases where the user has a single unified policyfile
0479: * with both java policy entries and auth entries
0480: */
0481: boolean loaded_one = initPolicyFile(POLICY, POLICY_URL, newInfo);
0482: // To maintain strict backward compatibility we load the static policy
0483: // only if POLICY load failed
0484: if (!loaded_one) {
0485: // use static policy if all else fails
0486: initStaticPolicy(newInfo);
0487: }
0488:
0489: initPolicyFile(AUTH_POLICY, AUTH_POLICY_URL, newInfo);
0490: }
0491:
0492: private boolean initPolicyFile(final String propname,
0493: final String urlname, final PolicyInfo newInfo) {
0494: Boolean loadedPolicy = (Boolean) AccessController
0495: .doPrivileged(new PrivilegedAction() {
0496: public Object run() {
0497: boolean loaded_policy = false;
0498:
0499: if (allowSystemProperties) {
0500: String extra_policy = System
0501: .getProperty(propname);
0502: if (extra_policy != null) {
0503: boolean overrideAll = false;
0504: if (extra_policy.startsWith("=")) {
0505: overrideAll = true;
0506: extra_policy = extra_policy
0507: .substring(1);
0508: }
0509: try {
0510: extra_policy = PropertyExpander
0511: .expand(extra_policy);
0512: URL policyURL;
0513:
0514: File policyFile = new File(
0515: extra_policy);
0516: if (policyFile.exists()) {
0517: policyURL = ParseUtil
0518: .fileToEncodedURL(new File(
0519: policyFile
0520: .getCanonicalPath()));
0521: } else {
0522: policyURL = new URL(
0523: extra_policy);
0524: }
0525: if (debug != null)
0526: debug.println("reading "
0527: + policyURL);
0528: if (init(policyURL, newInfo))
0529: loaded_policy = true;
0530: } catch (Exception e) {
0531: // ignore.
0532: if (debug != null) {
0533: debug
0534: .println("caught exception: "
0535: + e);
0536: }
0537: }
0538: if (overrideAll) {
0539: if (debug != null) {
0540: debug
0541: .println("overriding other policies!");
0542: }
0543: return Boolean
0544: .valueOf(loaded_policy);
0545: }
0546: }
0547: }
0548:
0549: int n = 1;
0550: String policy_uri;
0551:
0552: while ((policy_uri = Security
0553: .getProperty(urlname + n)) != null) {
0554: try {
0555: URL policy_url = null;
0556: String expanded_uri = PropertyExpander
0557: .expand(policy_uri)
0558: .replace(File.separatorChar,
0559: '/');
0560:
0561: if (policy_uri
0562: .startsWith("file:${java.home}/")
0563: || policy_uri
0564: .startsWith("file:${user.home}/")) {
0565:
0566: // this special case accommodates
0567: // the situation java.home/user.home
0568: // expand to a single slash, resulting in
0569: // a file://foo URI
0570: policy_url = new File(expanded_uri
0571: .substring(5)).toURI()
0572: .toURL();
0573: } else {
0574: policy_url = new URI(expanded_uri)
0575: .toURL();
0576: }
0577:
0578: if (debug != null)
0579: debug.println("reading "
0580: + policy_url);
0581: if (init(policy_url, newInfo))
0582: loaded_policy = true;
0583: } catch (Exception e) {
0584: if (debug != null) {
0585: debug
0586: .println("error reading policy "
0587: + e);
0588: e.printStackTrace();
0589: }
0590: // ignore that policy
0591: }
0592: n++;
0593: }
0594: return Boolean.valueOf(loaded_policy);
0595: }
0596: });
0597:
0598: return loadedPolicy.booleanValue();
0599: }
0600:
0601: /**
0602: * Reads a policy configuration into the Policy object using a
0603: * Reader object.
0604: *
0605: * @param policyFile the policy Reader object.
0606: */
0607: private boolean init(URL policy, PolicyInfo newInfo) {
0608: boolean success = false;
0609: PolicyParser pp = new PolicyParser(expandProperties);
0610: try {
0611:
0612: // read in policy using UTF-8 by default
0613: //
0614: // check non-standard system property to see if
0615: // the default encoding should be used instead
0616:
0617: InputStreamReader isr;
0618: if (notUtf8) {
0619: isr = new InputStreamReader(getInputStream(policy));
0620: } else {
0621: isr = new InputStreamReader(getInputStream(policy),
0622: "UTF-8");
0623: }
0624:
0625: pp.read(isr);
0626: isr.close();
0627: KeyStore keyStore = initKeyStore(policy, pp
0628: .getKeyStoreUrl(), pp.getKeyStoreType());
0629: Enumeration enum_ = pp.grantElements();
0630: while (enum_.hasMoreElements()) {
0631: PolicyParser.GrantEntry ge = (PolicyParser.GrantEntry) enum_
0632: .nextElement();
0633: addGrantEntry(ge, keyStore, newInfo);
0634: }
0635: success = true;
0636: } catch (PolicyParser.ParsingException pe) {
0637: MessageFormat form = new MessageFormat(ResourcesMgr
0638: .getString(POLICY
0639: + ": error parsing policy:\n\tmessage"));
0640: Object[] source = { policy, pe.getLocalizedMessage() };
0641: System.err.println(form.format(source));
0642: if (debug != null)
0643: pe.printStackTrace();
0644:
0645: } catch (Exception e) {
0646: if (debug != null) {
0647: debug.println("error parsing " + policy);
0648: debug.println(e.toString());
0649: e.printStackTrace();
0650: }
0651: }
0652: return success;
0653: }
0654:
0655: private void initStaticPolicy(final PolicyInfo newInfo) {
0656: AccessController.doPrivileged(new PrivilegedAction() {
0657: public Object run() {
0658: PolicyEntry pe = new PolicyEntry(new CodeSource(null,
0659: null));
0660: pe.add(SecurityConstants.LOCAL_LISTEN_PERMISSION);
0661: pe.add(new PropertyPermission("java.version",
0662: SecurityConstants.PROPERTY_READ_ACTION));
0663: pe.add(new PropertyPermission("java.vendor",
0664: SecurityConstants.PROPERTY_READ_ACTION));
0665: pe.add(new PropertyPermission("java.vendor.url",
0666: SecurityConstants.PROPERTY_READ_ACTION));
0667: pe.add(new PropertyPermission("java.class.version",
0668: SecurityConstants.PROPERTY_READ_ACTION));
0669: pe.add(new PropertyPermission("os.name",
0670: SecurityConstants.PROPERTY_READ_ACTION));
0671: pe.add(new PropertyPermission("os.version",
0672: SecurityConstants.PROPERTY_READ_ACTION));
0673: pe.add(new PropertyPermission("os.arch",
0674: SecurityConstants.PROPERTY_READ_ACTION));
0675: pe.add(new PropertyPermission("file.separator",
0676: SecurityConstants.PROPERTY_READ_ACTION));
0677: pe.add(new PropertyPermission("path.separator",
0678: SecurityConstants.PROPERTY_READ_ACTION));
0679: pe.add(new PropertyPermission("line.separator",
0680: SecurityConstants.PROPERTY_READ_ACTION));
0681: pe.add(new PropertyPermission(
0682: "java.specification.version",
0683: SecurityConstants.PROPERTY_READ_ACTION));
0684: pe.add(new PropertyPermission(
0685: "java.specification.vendor",
0686: SecurityConstants.PROPERTY_READ_ACTION));
0687: pe.add(new PropertyPermission(
0688: "java.specification.name",
0689: SecurityConstants.PROPERTY_READ_ACTION));
0690: pe.add(new PropertyPermission(
0691: "java.vm.specification.version",
0692: SecurityConstants.PROPERTY_READ_ACTION));
0693: pe.add(new PropertyPermission(
0694: "java.vm.specification.vendor",
0695: SecurityConstants.PROPERTY_READ_ACTION));
0696: pe.add(new PropertyPermission(
0697: "java.vm.specification.name",
0698: SecurityConstants.PROPERTY_READ_ACTION));
0699: pe.add(new PropertyPermission("java.vm.version",
0700: SecurityConstants.PROPERTY_READ_ACTION));
0701: pe.add(new PropertyPermission("java.vm.vendor",
0702: SecurityConstants.PROPERTY_READ_ACTION));
0703: pe.add(new PropertyPermission("java.vm.name",
0704: SecurityConstants.PROPERTY_READ_ACTION));
0705:
0706: // No need to sync because noone has access to newInfo yet
0707: newInfo.policyEntries.add(pe);
0708: try {
0709: File f = new File(PropertyExpander
0710: .expand("${java.home}/lib/ext/*"));
0711: pe = new PolicyEntry(new CodeSource(ParseUtil
0712: .fileToEncodedURL(f), null));
0713: pe.add(SecurityConstants.ALL_PERMISSION);
0714:
0715: // No need to sync because noone has access to newInfo yet
0716: newInfo.policyEntries.add(pe);
0717: } catch (Exception e) {
0718: // this is probably bad (though not dangerous).
0719: // What should we do?
0720: }
0721: return null;
0722: }
0723: });
0724: }
0725:
0726: private KeyStore initKeyStore(URL policyUrl, String keyStoreName,
0727: String keyStoreType) {
0728: if (keyStoreName != null) {
0729: try {
0730: /*
0731: * location of keystore is specified as absolute URL in policy
0732: * file, or is relative to URL of policy file
0733: */
0734: URL keyStoreUrl = null;
0735: try {
0736: keyStoreUrl = new URL(keyStoreName);
0737: // absolute URL
0738: } catch (java.net.MalformedURLException e) {
0739: // relative URL
0740: keyStoreUrl = new URL(policyUrl, keyStoreName);
0741: }
0742:
0743: if (debug != null) {
0744: debug.println("reading keystore" + keyStoreUrl);
0745: }
0746:
0747: InputStream inStream = new BufferedInputStream(
0748: getInputStream(keyStoreUrl));
0749:
0750: KeyStore ks;
0751: if (keyStoreType != null)
0752: ks = KeyStore.getInstance(keyStoreType);
0753: else
0754: ks = KeyStore
0755: .getInstance(KeyStore.getDefaultType());
0756: ks.load(inStream, null);
0757: inStream.close();
0758: return ks;
0759: } catch (Exception e) {
0760: // ignore, treat it like we have no keystore
0761: if (debug != null) {
0762: e.printStackTrace();
0763: }
0764: return null;
0765: }
0766: }
0767: return null;
0768: }
0769:
0770: /*
0771: * Fast path reading from file urls in order to avoid calling
0772: * FileURLConnection.connect() which can be quite slow the first time
0773: * it is called. We really should clean up FileURLConnection so that
0774: * this is not a problem but in the meantime this fix helps reduce
0775: * start up time noticeably for the new launcher. -- DAC
0776: */
0777: private InputStream getInputStream(URL url) throws IOException {
0778: if ("file".equals(url.getProtocol())) {
0779: String path = url.getFile()
0780: .replace('/', File.separatorChar);
0781: path = ParseUtil.decode(path);
0782: return new FileInputStream(path);
0783: } else {
0784: return url.openStream();
0785: }
0786: }
0787:
0788: /**
0789: * Given a GrantEntry, create a codeSource.
0790: *
0791: * @return null if signedBy alias is not recognized
0792: */
0793: private CodeSource getCodeSource(PolicyParser.GrantEntry ge,
0794: KeyStore keyStore, PolicyInfo newInfo)
0795: throws java.net.MalformedURLException {
0796: Certificate[] certs = null;
0797: if (ge.signedBy != null) {
0798: certs = getCertificates(keyStore, ge.signedBy, newInfo);
0799: if (certs == null) {
0800: // we don't have a key for this alias,
0801: // just return
0802: if (debug != null) {
0803: debug.println(" -- No certs for alias '"
0804: + ge.signedBy + "' - ignoring entry");
0805: }
0806: return null;
0807: }
0808: }
0809:
0810: URL location;
0811:
0812: if (ge.codeBase != null)
0813: location = new URL(ge.codeBase);
0814: else
0815: location = null;
0816:
0817: return (canonicalizeCodebase(new CodeSource(location, certs),
0818: false));
0819: }
0820:
0821: /**
0822: * Add one policy entry to the list.
0823: */
0824: private void addGrantEntry(PolicyParser.GrantEntry ge,
0825: KeyStore keyStore, PolicyInfo newInfo) {
0826:
0827: if (debug != null) {
0828: debug.println("Adding policy entry: ");
0829: debug.println(" signedBy " + ge.signedBy);
0830: debug.println(" codeBase " + ge.codeBase);
0831: if (ge.principals != null && ge.principals.size() > 0) {
0832: ListIterator li = ge.principals.listIterator();
0833: while (li.hasNext()) {
0834: PolicyParser.PrincipalEntry pppe = (PolicyParser.PrincipalEntry) li
0835: .next();
0836: debug.println(" " + pppe.toString());
0837: }
0838: }
0839: }
0840:
0841: try {
0842: CodeSource codesource = getCodeSource(ge, keyStore, newInfo);
0843: // skip if signedBy alias was unknown...
0844: if (codesource == null)
0845: return;
0846:
0847: // perform keystore alias principal replacement.
0848: // for example, if alias resolves to X509 certificate,
0849: // replace principal with: <X500Principal class> <SubjectDN>
0850: // -- skip if alias is unknown
0851: if (replacePrincipals(ge.principals, keyStore) == false)
0852: return;
0853: PolicyEntry entry = new PolicyEntry(codesource,
0854: ge.principals);
0855: Enumeration enum_ = ge.permissionElements();
0856: while (enum_.hasMoreElements()) {
0857: PolicyParser.PermissionEntry pe = (PolicyParser.PermissionEntry) enum_
0858: .nextElement();
0859:
0860: try {
0861: // perform ${{ ... }} expansions within permission name
0862: expandPermissionName(pe, keyStore);
0863:
0864: // special case PrivateCredentialPermission-SELF
0865: Permission perm;
0866: if (pe.permission
0867: .equals("javax.security.auth.PrivateCredentialPermission")
0868: && pe.name.endsWith(" self")) {
0869: pe.name = pe.name.substring(0, pe.name
0870: .indexOf("self"))
0871: + SELF;
0872: }
0873: // check for self
0874: if (pe.name != null && pe.name.indexOf(SELF) != -1) {
0875: // Create a "SelfPermission" , it could be an
0876: // an unresolved permission which will be resolved
0877: // when implies is called
0878: // Add it to entry
0879: Certificate certs[];
0880: if (pe.signedBy != null) {
0881: certs = getCertificates(keyStore,
0882: pe.signedBy, newInfo);
0883: } else {
0884: certs = null;
0885: }
0886: perm = new SelfPermission(pe.permission,
0887: pe.name, pe.action, certs);
0888: } else {
0889: perm = getInstance(pe.permission, pe.name,
0890: pe.action);
0891: }
0892: entry.add(perm);
0893: if (debug != null) {
0894: debug.println(" " + perm);
0895: }
0896: } catch (ClassNotFoundException cnfe) {
0897: Certificate certs[];
0898: if (pe.signedBy != null) {
0899: certs = getCertificates(keyStore, pe.signedBy,
0900: newInfo);
0901: } else {
0902: certs = null;
0903: }
0904:
0905: // only add if we had no signer or we had a
0906: // a signer and found the keys for it.
0907: if (certs != null || pe.signedBy == null) {
0908: Permission perm = new UnresolvedPermission(
0909: pe.permission, pe.name, pe.action,
0910: certs);
0911: entry.add(perm);
0912: if (debug != null) {
0913: debug.println(" " + perm);
0914: }
0915: }
0916: } catch (java.lang.reflect.InvocationTargetException ite) {
0917: MessageFormat form = new MessageFormat(
0918: ResourcesMgr
0919: .getString(POLICY
0920: + ": error adding Permission, perm:\n\tmessage"));
0921: Object[] source = { pe.permission,
0922: ite.getTargetException().toString() };
0923: System.err.println(form.format(source));
0924: } catch (Exception e) {
0925: MessageFormat form = new MessageFormat(
0926: ResourcesMgr
0927: .getString(POLICY
0928: + ": error adding Permission, perm:\n\tmessage"));
0929: Object[] source = { pe.permission, e.toString() };
0930: System.err.println(form.format(source));
0931: }
0932: }
0933:
0934: // No need to sync because noone has access to newInfo yet
0935: newInfo.policyEntries.add(entry);
0936: } catch (Exception e) {
0937: MessageFormat form = new MessageFormat(ResourcesMgr
0938: .getString(POLICY
0939: + ": error adding Entry:\n\tmessage"));
0940: Object[] source = { e.toString() };
0941: System.err.println(form.format(source));
0942: }
0943: if (debug != null)
0944: debug.println();
0945: }
0946:
0947: /**
0948: * Returns a new Permission object of the given Type. The Permission is
0949: * created by getting the
0950: * Class object using the <code>Class.forName</code> method, and using
0951: * the reflection API to invoke the (String name, String actions)
0952: * constructor on the
0953: * object.
0954: *
0955: * @param type the type of Permission being created.
0956: * @param name the name of the Permission being created.
0957: * @param actions the actions of the Permission being created.
0958: *
0959: * @exception ClassNotFoundException if the particular Permission
0960: * class could not be found.
0961: *
0962: * @exception IllegalAccessException if the class or initializer is
0963: * not accessible.
0964: *
0965: * @exception InstantiationException if getInstance tries to
0966: * instantiate an abstract class or an interface, or if the
0967: * instantiation fails for some other reason.
0968: *
0969: * @exception NoSuchMethodException if the (String, String) constructor
0970: * is not found.
0971: *
0972: * @exception InvocationTargetException if the underlying Permission
0973: * constructor throws an exception.
0974: *
0975: */
0976:
0977: private static final Permission getInstance(String type,
0978: String name, String actions) throws ClassNotFoundException,
0979: InstantiationException, IllegalAccessException,
0980: NoSuchMethodException, InvocationTargetException {
0981: //we might want to keep a hash of created factories...
0982: Class pc = Class.forName(type);
0983: Permission answer = getKnownInstance(pc, name, actions);
0984: if (answer != null) {
0985: return answer;
0986: }
0987:
0988: if (name == null && actions == null) {
0989: try {
0990: Constructor c = pc.getConstructor(PARAMS0);
0991: return (Permission) c.newInstance(new Object[] {});
0992: } catch (NoSuchMethodException ne) {
0993: try {
0994: Constructor c = pc.getConstructor(PARAMS1);
0995: return (Permission) c
0996: .newInstance(new Object[] { name });
0997: } catch (NoSuchMethodException ne1) {
0998: Constructor c = pc.getConstructor(PARAMS2);
0999: return (Permission) c.newInstance(new Object[] {
1000: name, actions });
1001: }
1002: }
1003: } else {
1004: if (name != null && actions == null) {
1005: try {
1006: Constructor c = pc.getConstructor(PARAMS1);
1007: return (Permission) c
1008: .newInstance(new Object[] { name });
1009: } catch (NoSuchMethodException ne) {
1010: Constructor c = pc.getConstructor(PARAMS2);
1011: return (Permission) c.newInstance(new Object[] {
1012: name, actions });
1013: }
1014: } else {
1015: Constructor c = pc.getConstructor(PARAMS2);
1016: return (Permission) c.newInstance(new Object[] { name,
1017: actions });
1018: }
1019: }
1020: }
1021:
1022: /**
1023: * Creates one of the well-known permissions directly instead of
1024: * via reflection. Keep list short to not penalize non-JDK-defined
1025: * permissions.
1026: */
1027: private static final Permission getKnownInstance(Class claz,
1028: String name, String actions) {
1029: // TODO: shorten list to most popular ones?
1030: if (claz.equals(FilePermission.class)) {
1031: return new FilePermission(name, actions);
1032: } else if (claz.equals(SocketPermission.class)) {
1033: return new SocketPermission(name, actions);
1034: } else if (claz.equals(RuntimePermission.class)) {
1035: return new RuntimePermission(name, actions);
1036: } else if (claz.equals(PropertyPermission.class)) {
1037: return new PropertyPermission(name, actions);
1038: } else if (claz.equals(NetPermission.class)) {
1039: return new NetPermission(name, actions);
1040: } else if (claz.equals(AllPermission.class)) {
1041: return SecurityConstants.ALL_PERMISSION;
1042: /* Subset out AWTPermission for CDC/FP.
1043: } else if (claz.equals(AWTPermission.class)) {
1044: return new AWTPermission(name, actions);
1045: */
1046: /*
1047: } else if (claz.equals(ReflectPermission.class)) {
1048: return new ReflectPermission(name, actions);
1049: } else if (claz.equals(SecurityPermission.class)) {
1050: return new SecurityPermission(name, actions);
1051: } else if (claz.equals(PrivateCredentialPermission.class)) {
1052: return new PrivateCredentialPermission(name, actions);
1053: } else if (claz.equals(AuthPermission.class)) {
1054: return new AuthPermission(name, actions);
1055: } else if (claz.equals(ServicePermission.class)) {
1056: return new ServicePermission(name, actions);
1057: } else if (claz.equals(DelegationPermission.class)) {
1058: return new DelegationPermission(name, actions);
1059: } else if (claz.equals(SerializablePermission.class)) {
1060: return new SerializablePermission(name, actions);
1061: } else if (claz.equals(AudioPermission.class)) {
1062: return new AudioPermission(name, actions);
1063: } else if (claz.equals(SSLPermission.class)) {
1064: return new SSLPermission(name, actions);
1065: } else if (claz.equals(LoggingPermission.class)) {
1066: return new LoggingPermission(name, actions);
1067: } else if (claz.equals(SQLPermission.class)) {
1068: return new SQLPermission(name, actions);
1069: */
1070: } else {
1071: return null;
1072: }
1073: }
1074:
1075: /**
1076: * Fetch all certs associated with this alias.
1077: */
1078: private Certificate[] getCertificates(KeyStore keyStore,
1079: String aliases, PolicyInfo newInfo) {
1080:
1081: List vcerts = null;
1082:
1083: StringTokenizer st = new StringTokenizer(aliases, ",");
1084: int n = 0;
1085:
1086: while (st.hasMoreTokens()) {
1087: String alias = st.nextToken().trim();
1088: n++;
1089: Certificate cert = null;
1090: // See if this alias's cert has already been cached
1091: synchronized (newInfo.aliasMapping) {
1092: cert = (Certificate) newInfo.aliasMapping.get(alias);
1093:
1094: if (cert == null && keyStore != null) {
1095:
1096: try {
1097: cert = keyStore.getCertificate(alias);
1098: } catch (KeyStoreException kse) {
1099: // never happens, because keystore has already been loaded
1100: // when we call this
1101: }
1102: if (cert != null) {
1103: newInfo.aliasMapping.put(alias, cert);
1104: newInfo.aliasMapping.put(cert, alias);
1105: }
1106: }
1107: }
1108:
1109: if (cert != null) {
1110: if (vcerts == null)
1111: vcerts = new ArrayList();
1112: vcerts.add(cert);
1113: }
1114: }
1115:
1116: // make sure n == vcerts.size, since we are doing a logical *and*
1117: if (vcerts != null && n == vcerts.size()) {
1118: Certificate[] certs = new Certificate[vcerts.size()];
1119: vcerts.toArray(certs);
1120: return certs;
1121: } else {
1122: return null;
1123: }
1124: }
1125:
1126: /**
1127: * Refreshes the policy object by re-reading all the policy files.
1128: */
1129: public void refresh() {
1130: init();
1131: }
1132:
1133: /**
1134: * Evaluates the the global policy for the permissions granted to
1135: * the ProtectionDomain and tests whether the permission is
1136: * granted.
1137: *
1138: * @param domain the ProtectionDomain to test
1139: * @param permission the Permission object to be tested for implication.
1140: *
1141: * @return true if "permission" is a proper subset of a permission
1142: * granted to this ProtectionDomain.
1143: *
1144: * @see java.security.ProtectionDomain
1145: */
1146: public boolean implies(ProtectionDomain pd, Permission p) {
1147: Map pdMap = policyInfo.getPdMapping();
1148:
1149: PermissionCollection pc = (PermissionCollection) pdMap.get(pd);
1150:
1151: if (pc != null) {
1152: return pc.implies(p);
1153: }
1154:
1155: pc = getPermissions(pd);
1156: if (pc == null) {
1157: return false;
1158: }
1159:
1160: // cache mapping of protection domain to its PermissionCollection
1161: pdMap.put(pd, pc);
1162: return pc.implies(p);
1163: }
1164:
1165: /**
1166: * Examines this <code>Policy</code> and returns the permissions granted
1167: * to the specified <code>ProtectionDomain</code>. This includes
1168: * the permissions currently associated with the domain as well
1169: * as the policy permissions granted to the domain's
1170: * CodeSource, ClassLoader, and Principals.
1171: *
1172: * <p> Note that this <code>Policy</code> implementation has
1173: * special handling for PrivateCredentialPermissions.
1174: * When this method encounters a <code>PrivateCredentialPermission</code>
1175: * which specifies "self" as the <code>Principal</code> class and name,
1176: * it does not add that <code>Permission</code> to the returned
1177: * <code>PermissionCollection</code>. Instead, it builds
1178: * a new <code>PrivateCredentialPermission</code>
1179: * for each <code>Principal</code> associated with the provided
1180: * <code>Subject</code>. Each new <code>PrivateCredentialPermission</code>
1181: * contains the same Credential class as specified in the
1182: * originally granted permission, as well as the Class and name
1183: * for the respective <code>Principal</code>.
1184: *
1185: * <p>
1186: *
1187: * @param domain the Permissions granted to this
1188: * <code>ProtectionDomain</code> are returned.
1189: *
1190: * @return the Permissions granted to the provided
1191: * <code>ProtectionDomain</code>.
1192: */
1193: public PermissionCollection getPermissions(ProtectionDomain domain) {
1194: Permissions perms = new Permissions();
1195:
1196: if (domain == null)
1197: return perms;
1198:
1199: // first get policy perms
1200: getPermissions(perms, domain);
1201:
1202: // add static perms
1203: // - adding static perms after policy perms is necessary
1204: // to avoid a regression for 4301064
1205: PermissionCollection pc = domain.getPermissions();
1206: if (pc != null) {
1207: Enumeration e = pc.elements();
1208: while (e.hasMoreElements()) {
1209: perms.add((Permission) e.nextElement());
1210: }
1211: }
1212:
1213: return perms;
1214: }
1215:
1216: /**
1217: * Examines this Policy and creates a PermissionCollection object with
1218: * the set of permissions for the specified CodeSource.
1219: *
1220: * @param CodeSource the codesource associated with the caller.
1221: * This encapsulates the original location of the code (where the code
1222: * came from) and the public key(s) of its signer.
1223: *
1224: * @return the set of permissions according to the policy.
1225: */
1226: public PermissionCollection getPermissions(CodeSource codesource) {
1227: return getPermissions(new Permissions(), codesource);
1228: }
1229:
1230: /**
1231: * Examines the global policy and returns the provided Permissions
1232: * object with additional permissions granted to the specified
1233: * ProtectionDomain.
1234: *
1235: * @param perm the Permissions to populate
1236: * @param pd the ProtectionDomain associated with the caller.
1237: *
1238: * @return the set of Permissions according to the policy.
1239: */
1240: private PermissionCollection getPermissions(Permissions perms,
1241: ProtectionDomain pd) {
1242: if (debug != null) {
1243: debug.println("getPermissions:\n\t" + printPD(pd));
1244: }
1245:
1246: final CodeSource cs = pd.getCodeSource();
1247: if (cs == null)
1248: return perms;
1249:
1250: CodeSource canonCodeSource = (CodeSource) AccessController
1251: .doPrivileged(new java.security.PrivilegedAction() {
1252: public Object run() {
1253: return canonicalizeCodebase(cs, true);
1254: }
1255: });
1256: return getPermissions(perms, canonCodeSource, pd
1257: .getPrincipals());
1258: }
1259:
1260: /**
1261: * Examines the global policy and returns the provided Permissions
1262: * object with additional permissions granted to the specified
1263: * CodeSource.
1264: *
1265: * @param permissions the permissions to populate
1266: * @param codesource the codesource associated with the caller.
1267: * This encapsulates the original location of the code (where the code
1268: * came from) and the public key(s) of its signer.
1269: *
1270: * @return the set of permissions according to the policy.
1271: */
1272: private PermissionCollection getPermissions(Permissions perms,
1273: final CodeSource cs) {
1274:
1275: CodeSource canonCodeSource = (CodeSource) AccessController
1276: .doPrivileged(new java.security.PrivilegedAction() {
1277: public Object run() {
1278: return canonicalizeCodebase(cs, true);
1279: }
1280: });
1281:
1282: return getPermissions(perms, canonCodeSource, null);
1283: }
1284:
1285: private Permissions getPermissions(Permissions perms,
1286: final CodeSource cs, Principal[] principals) {
1287: // No need to sync because policyEntries do not changed after init
1288: int numEntries = policyInfo.policyEntries.size();
1289: PolicyEntry entry;
1290: for (int i = 0; i < numEntries; i++) {
1291: entry = (PolicyEntry) policyInfo.policyEntries.get(i);
1292: addPermissions(perms, cs, principals, entry);
1293: }
1294:
1295: // Go through policyEntries gotten from identity db; sync required
1296: // because checkForTrustedIdentity (below) might update list
1297: synchronized (policyInfo.identityPolicyEntries) {
1298: numEntries = policyInfo.identityPolicyEntries.size();
1299: for (int i = 0; i < numEntries; i++) {
1300: entry = (PolicyEntry) policyInfo.identityPolicyEntries
1301: .get(i);
1302: addPermissions(perms, cs, principals, entry);
1303: }
1304: }
1305:
1306: // now see if any of the keys are trusted ids.
1307: if (!ignoreIdentityScope) {
1308: Certificate certs[] = cs.getCertificates();
1309: if (certs != null) {
1310: for (int k = 0; k < certs.length; k++) {
1311: Object idMap;
1312: synchronized (policyInfo.aliasMapping) {
1313: idMap = policyInfo.aliasMapping.get(certs[k]);
1314: }
1315: if (idMap == null
1316: && checkForTrustedIdentity(certs[k],
1317: policyInfo)) {
1318: // checkForTrustedIdentity added it
1319: // to the policy for us. next time
1320: // around we'll find it. This time
1321: // around we need to add it.
1322: perms.add(SecurityConstants.ALL_PERMISSION);
1323: }
1324: }
1325: }
1326: }
1327: return perms;
1328: }
1329:
1330: private void addPermissions(Permissions perms, final CodeSource cs,
1331: Principal[] principals, final PolicyEntry entry) {
1332:
1333: boolean addPerms = false;
1334:
1335: if (debug != null) {
1336: debug.println("evaluate codesources:\n"
1337: + "\tPolicy CodeSource: " + entry.getCodeSource()
1338: + "\n" + "\tActive CodeSource: " + cs);
1339: }
1340:
1341: // check to see if the CodeSource implies
1342: Boolean imp = (Boolean) AccessController
1343: .doPrivileged(new java.security.PrivilegedAction() {
1344: public Object run() {
1345: return new Boolean(entry.getCodeSource()
1346: .implies(cs));
1347: }
1348: });
1349:
1350: if (!imp.booleanValue()) {
1351: if (debug != null) {
1352: debug.println("evaluation (codesource) failed");
1353: }
1354: } else {
1355:
1356: // check to see if the Principals imply
1357:
1358: final Principal[] pdp = principals;
1359: List entryPs = entry.getPrincipals();
1360: List domainPs = new LinkedList();
1361: if (pdp != null && pdp.length != 0) {
1362: PolicyParser.PrincipalEntry pe = null;
1363: for (int j = 0; j < pdp.length; j++) {
1364: pe = new PolicyParser.PrincipalEntry(pdp[j]
1365: .getClass().getName(), pdp[j].getName());
1366: domainPs.add(pe);
1367: }
1368: }
1369: if (debug != null) {
1370: debug.println("evaluate principals:\n"
1371: + "\tPolicy Principals: " + entryPs + "\n"
1372: + "\tActive Principals: " + domainPs);
1373: }
1374: if (entryPs == null || entryPs.size() == 0) {
1375: // policy entry has no principals --
1376: // grant the permissions
1377: addPerms = true;
1378: } else if (domainPs.size() != 0) {
1379:
1380: ListIterator li = entryPs.listIterator(0);
1381: while (li.hasNext()) {
1382: PolicyParser.PrincipalEntry pppe = (PolicyParser.PrincipalEntry) li
1383: .next();
1384:
1385: /* Subset out PrincipalComparator references
1386: * and java.security.auth classes in CDC/FP
1387: try {
1388: // handle PrincipalComparators
1389: Class principalComparator = Class.forName
1390: (pppe.principalClass, true,
1391: Thread.currentThread().getContextClassLoader());
1392:
1393: Constructor c =
1394: principalComparator.getConstructor(PARAMS1);
1395: PrincipalComparator pc =
1396: (PrincipalComparator)c.newInstance
1397: (new Object[] { pppe.principalName });
1398:
1399: if (debug != null) {
1400: debug.println("found PrincipalComparator " +
1401: pc.getClass().getName());
1402: }
1403:
1404: // check if the PrincipalComparator
1405: // implies the current Subject in the ACC
1406:
1407: final Subject subject = new Subject();
1408: AccessController.doPrivileged
1409: (new java.security.PrivilegedAction() {
1410: public Object run() {
1411: Set pSet = subject.getPrincipals();
1412: for (int j = 0; j < pdp.length; j++) {
1413: pSet.add(pdp[j]);
1414: }
1415: return null;
1416: }
1417: });
1418:
1419: if ((addPerms = pc.implies(subject)) == false) {
1420: // immediately break if one principal
1421: // in the policy does not imply the
1422: // current Subject
1423: break;
1424: }
1425:
1426: } catch (Exception e) {
1427:
1428: if (debug != null) {
1429: debug.println
1430: ("Exception while attempting " +
1431: "to construct PrincipalComparator");
1432: e.printStackTrace();
1433: }
1434:
1435: if ((addPerms = subjectListImpliesPrincipalEntry
1436: (domainPs, pppe)) == false) {
1437: break;
1438: }
1439: }
1440: * end of CDC/FP subsetting.
1441: */
1442: }
1443: }
1444:
1445: // implies succeeded - grant the permissions
1446: if (!addPerms) {
1447: if (debug != null) {
1448: debug.println("evaluation failed");
1449: }
1450: } else {
1451: if (debug != null) {
1452: debug
1453: .println("evaluation (codesource/principals) passed");
1454: }
1455: for (int j = 0; j < entry.permissions.size(); j++) {
1456: Permission p = (Permission) entry.permissions
1457: .get(j);
1458: if (debug != null) {
1459: debug.println(" granting " + p);
1460: }
1461: // handle "SELF" permissions
1462: if (p instanceof SelfPermission) {
1463: expandSelf((SelfPermission) p, entryPs, pdp,
1464: perms);
1465: } else {
1466: perms.add(p);
1467: }
1468: }
1469: }
1470: }
1471: }
1472:
1473: /**
1474: * This method returns, true, if the provided <i>subjectList</i>
1475: * "contains" the <code>Principal</code> specified
1476: * in the provided <i>pppe</i> argument.
1477: *
1478: * Note that the provided <i>pppe</i> argument may have
1479: * wildcards (*) for the <code>Principal</code> class and name,
1480: * which need to be considered.
1481: *
1482: * <p>
1483: *
1484: * @param subjectList a list of PolicyParser.PrincipalEntry objects
1485: * that correspond to all the Principals in the Subject
1486: * currently on this thread's AccessControlContext. <p>
1487: *
1488: * @param pppe the Principals specified in a grant entry.
1489: *
1490: * @return true if the provided <i>subjectList</i> "contains"
1491: * the <code>Principal</code> specified in the provided
1492: * <i>pppe</i> argument.
1493: */
1494: private boolean subjectListImpliesPrincipalEntry(List subjectList,
1495: PolicyParser.PrincipalEntry pppe) {
1496:
1497: ListIterator li = subjectList.listIterator(0);
1498: while (li.hasNext()) {
1499: PolicyParser.PrincipalEntry listPppe = (PolicyParser.PrincipalEntry) li
1500: .next();
1501:
1502: if (pppe.principalClass
1503: .equals(PolicyParser.PrincipalEntry.WILDCARD_CLASS)
1504: || pppe.principalClass
1505: .equals(listPppe.principalClass)) {
1506:
1507: if (pppe.principalName
1508: .equals(PolicyParser.PrincipalEntry.WILDCARD_NAME)
1509: || pppe.principalName
1510: .equals(listPppe.principalName))
1511: return true;
1512: }
1513: }
1514: return false;
1515: }
1516:
1517: /**
1518: * <p>
1519: *
1520: * @param sp the SelfPermission that needs to be expanded <p>
1521: *
1522: * @param entryPs list of principals for the Policy entry.
1523: *
1524: * @param pdp Principal array from the current ProtectionDomain.
1525: *
1526: * @param perms the PermissionCollection where the individual
1527: * Permissions will be added after expansion.
1528: */
1529:
1530: private void expandSelf(SelfPermission sp, List entryPs,
1531: Principal[] pdp, Permissions perms) {
1532:
1533: if (entryPs == null || entryPs.size() == 0) {
1534: // No principals in the grant to substitute
1535: if (debug != null) {
1536: debug.println("Ignoring permission " + sp.getSelfType()
1537: + " with target name (" + sp.getSelfName()
1538: + "). " + "No Principal(s) specified "
1539: + "in the grant clause. "
1540: + "SELF-based target names are "
1541: + "only valid in the context "
1542: + "of a Principal-based grant entry.");
1543: }
1544: return;
1545: }
1546: int startIndex = 0;
1547: int v;
1548: StringBuffer sb = new StringBuffer();
1549: while ((v = sp.getSelfName().indexOf(SELF, startIndex)) != -1) {
1550:
1551: // add non-SELF string
1552: sb.append(sp.getSelfName().substring(startIndex, v));
1553:
1554: // expand SELF
1555: ListIterator pli = entryPs.listIterator();
1556: while (pli.hasNext()) {
1557: PolicyParser.PrincipalEntry pppe = (PolicyParser.PrincipalEntry) pli
1558: .next();
1559: String[][] principalInfo = getPrincipalInfo(pppe, pdp);
1560: for (int i = 0; i < principalInfo.length; i++) {
1561: if (i != 0) {
1562: sb.append(", ");
1563: }
1564: sb.append(principalInfo[i][0] + " " + "\""
1565: + principalInfo[i][1] + "\"");
1566: }
1567: if (pli.hasNext()) {
1568: sb.append(", ");
1569: }
1570: }
1571: startIndex = v + SELF.length();
1572: }
1573: // add remaining string (might be the entire string)
1574: sb.append(sp.getSelfName().substring(startIndex));
1575:
1576: if (debug != null) {
1577: debug.println(" expanded:\n\t" + sp.getSelfName()
1578: + "\n into:\n\t" + sb.toString());
1579: }
1580: try {
1581: // first try to instantiate the permission
1582: perms.add(getInstance(sp.getSelfType(), sb.toString(), sp
1583: .getSelfActions()));
1584: } catch (ClassNotFoundException cnfe) {
1585: // ok, the permission is not in the bootclasspath.
1586: // before we add an UnresolvedPermission, check to see
1587: // whether this perm already belongs to the collection.
1588: // if so, use that perm's ClassLoader to create a new
1589: // one.
1590: Enumeration e = perms.elements();
1591: Class pc = null;
1592: while (e.hasMoreElements()) {
1593: Permission pElement = (Permission) e.nextElement();
1594: if (pElement.getClass().getName().equals(
1595: sp.getSelfType())) {
1596: pc = pElement.getClass();
1597: break;
1598: }
1599: }
1600: if (pc == null) {
1601: // create an UnresolvedPermission
1602: perms
1603: .add(new UnresolvedPermission(sp.getSelfType(),
1604: sb.toString(), sp.getSelfActions(), sp
1605: .getCerts()));
1606: } else {
1607: try {
1608: // we found an instantiated permission.
1609: // use its class loader to instantiate a new permission.
1610: Constructor c;
1611: // name parameter can not be null
1612: if (sp.getSelfActions() == null) {
1613: try {
1614: c = pc.getConstructor(PARAMS1);
1615: perms.add((Permission) c
1616: .newInstance(new Object[] { sb
1617: .toString() }));
1618: } catch (NoSuchMethodException ne) {
1619: c = pc.getConstructor(PARAMS2);
1620: perms.add((Permission) c
1621: .newInstance(new Object[] {
1622: sb.toString(),
1623: sp.getSelfActions() }));
1624: }
1625: } else {
1626: c = pc.getConstructor(PARAMS2);
1627: perms.add((Permission) c
1628: .newInstance(new Object[] {
1629: sb.toString(),
1630: sp.getSelfActions() }));
1631: }
1632: } catch (Exception nme) {
1633: if (debug != null) {
1634: debug.println("self entry expansion "
1635: + " instantiation failed: "
1636: + nme.toString());
1637: }
1638: }
1639: }
1640: } catch (Exception e) {
1641: if (debug != null) {
1642: debug.println(e.toString());
1643: }
1644: }
1645: }
1646:
1647: /**
1648: * return the principal class/name pair in the 2D array.
1649: * array[x][y]: x corresponds to the array length.
1650: * if (y == 0), it's the principal class.
1651: * if (y == 1), it's the principal name.
1652: */
1653: private String[][] getPrincipalInfo(PolicyParser.PrincipalEntry pe,
1654: Principal[] pdp) {
1655:
1656: // there are 3 possibilities:
1657: // 1) the entry's Principal class and name are not wildcarded
1658: // 2) the entry's Principal name is wildcarded only
1659: // 3) the entry's Principal class and name are wildcarded
1660:
1661: if (!pe.principalClass
1662: .equals(PolicyParser.PrincipalEntry.WILDCARD_CLASS)
1663: && !pe.principalName
1664: .equals(PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
1665:
1666: // build an info array for the principal
1667: // from the Policy entry
1668: String[][] info = new String[1][2];
1669: info[0][0] = pe.principalClass;
1670: info[0][1] = pe.principalName;
1671: return info;
1672:
1673: } else if (!pe.principalClass
1674: .equals(PolicyParser.PrincipalEntry.WILDCARD_CLASS)
1675: && pe.principalName
1676: .equals(PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
1677:
1678: // build an info array for every principal
1679: // in the current domain which has a principal class
1680: // that is equal to policy entry principal class name
1681: List plist = new LinkedList();
1682: for (int i = 0; i < pdp.length; i++) {
1683: if (pe.principalClass.equals(pdp[i].getClass()
1684: .getName()))
1685: plist.add(pdp[i]);
1686: }
1687: String[][] info = new String[plist.size()][2];
1688: int i = 0;
1689: java.util.Iterator pIterator = plist.iterator();
1690: while (pIterator.hasNext()) {
1691: Principal p = (Principal) pIterator.next();
1692: info[i][0] = p.getClass().getName();
1693: info[i][1] = p.getName();
1694: i++;
1695: }
1696: return info;
1697:
1698: } else {
1699:
1700: // build an info array for every
1701: // one of the current Domain's principals
1702:
1703: String[][] info = new String[pdp.length][2];
1704:
1705: for (int i = 0; i < pdp.length; i++) {
1706: info[i][0] = pdp[i].getClass().getName();
1707: info[i][1] = pdp[i].getName();
1708: }
1709: return info;
1710: }
1711: }
1712:
1713: /*
1714: * Returns the signer certificates from the list of certificates
1715: * associated with the given code source.
1716: *
1717: * The signer certificates are those certificates that were used
1718: * to verifysigned code originating from the codesource location.
1719: *
1720: * This method assumes that in the given code source, each signer
1721: * certificate is followed by its supporting certificate chain
1722: * (which may be empty), and that the signer certificate and its
1723: * supporting certificate chain are ordered bottom-to-top
1724: * (i.e., with the signer certificate first and the (root) certificate
1725: * authority last).
1726: */
1727: protected Certificate[] getSignerCertificates(CodeSource cs) {
1728: Certificate[] certs = null;
1729: if ((certs = cs.getCertificates()) == null)
1730: return null;
1731: for (int i = 0; i < certs.length; i++) {
1732: if (!(certs[i] instanceof X509Certificate))
1733: return cs.getCertificates();
1734: }
1735:
1736: // Do we have to do anything?
1737: int i = 0;
1738: int count = 0;
1739: while (i < certs.length) {
1740: count++;
1741: while (((i + 1) < certs.length)
1742: && ((X509Certificate) certs[i]).getIssuerDN()
1743: .equals(
1744: ((X509Certificate) certs[i + 1])
1745: .getSubjectDN())) {
1746: i++;
1747: }
1748: i++;
1749: }
1750: if (count == certs.length)
1751: // Done
1752: return certs;
1753:
1754: ArrayList userCertList = new ArrayList();
1755: i = 0;
1756: while (i < certs.length) {
1757: userCertList.add(certs[i]);
1758: while (((i + 1) < certs.length)
1759: && ((X509Certificate) certs[i]).getIssuerDN()
1760: .equals(
1761: ((X509Certificate) certs[i + 1])
1762: .getSubjectDN())) {
1763: i++;
1764: }
1765: i++;
1766: }
1767: Certificate[] userCerts = new Certificate[userCertList.size()];
1768: userCertList.toArray(userCerts);
1769: return userCerts;
1770: }
1771:
1772: private CodeSource canonicalizeCodebase(CodeSource cs,
1773: boolean extractSignerCerts) {
1774: String path = null;
1775:
1776: CodeSource canonCs = cs;
1777: URL u = cs.getLocation();
1778:
1779: if (u != null) {
1780: Permission p;
1781: try {
1782: p = u.openConnection().getPermission();
1783: } catch (java.io.IOException ioe) {
1784: p = null;
1785: }
1786:
1787: if (p instanceof FilePermission) {
1788: path = p.getName();
1789: } else if ((p == null) && (u.getProtocol().equals("file"))) {
1790: path = u.getFile().replace('/', File.separatorChar);
1791: path = ParseUtil.decode(path);
1792: }
1793: }
1794:
1795: if (path != null) {
1796: try {
1797: URL csUrl = null;
1798: if (path.endsWith("*")) {
1799: // remove trailing '*' because it causes canonicaization
1800: // to fail on win32
1801: path = path.substring(0, path.length() - 1);
1802: boolean appendFileSep = false;
1803: if (path.endsWith(File.separator))
1804: appendFileSep = true;
1805: if (path.equals("")) {
1806: path = System.getProperty("user.dir");
1807: }
1808: File f = new File(path);
1809: path = f.getCanonicalPath();
1810: StringBuffer sb = new StringBuffer(path);
1811: // reappend '*' to canonicalized filename (note that
1812: // canonicalization may have removed trailing file
1813: // separator, so we have to check for that, too)
1814: if (!path.endsWith(File.separator)
1815: && (appendFileSep || f.isDirectory()))
1816: sb.append(File.separatorChar);
1817: sb.append('*');
1818: path = sb.toString();
1819: } else {
1820: path = new File(path).getCanonicalPath();
1821: }
1822: csUrl = ParseUtil.fileToEncodedURL(new File(path));
1823:
1824: if (extractSignerCerts) {
1825: canonCs = new CodeSource(csUrl,
1826: getSignerCertificates(cs));
1827: } else {
1828: canonCs = new CodeSource(csUrl, cs
1829: .getCertificates());
1830: }
1831: } catch (IOException ioe) {
1832: // leave codesource as it is, unless we have to extract its
1833: // signer certificates
1834: if (extractSignerCerts) {
1835: canonCs = new CodeSource(cs.getLocation(),
1836: getSignerCertificates(cs));
1837: }
1838: }
1839: } else {
1840: if (extractSignerCerts) {
1841: canonCs = new CodeSource(cs.getLocation(),
1842: getSignerCertificates(cs));
1843: }
1844: }
1845: return canonCs;
1846: }
1847:
1848: private String printPD(ProtectionDomain pd) {
1849: Principal[] principals = pd.getPrincipals();
1850: String pals = "<no principals>";
1851: if (principals != null && principals.length > 0) {
1852: StringBuffer palBuf = new StringBuffer("(principals ");
1853: for (int i = 0; i < principals.length; i++) {
1854: palBuf.append(principals[i].getClass().getName()
1855: + " \"" + principals[i].getName() + "\"");
1856: if (i < principals.length - 1)
1857: palBuf.append(", ");
1858: else
1859: palBuf.append(")");
1860: }
1861: pals = palBuf.toString();
1862: }
1863: return "PD CodeSource: " + pd.getCodeSource() + "\n\t"
1864: + "PD ClassLoader: " + pd.getClassLoader() + "\n\t"
1865: + "PD Principals: " + pals;
1866: }
1867:
1868: /**
1869: * return true if no replacement was performed,
1870: * or if replacement succeeded.
1871: */
1872: private boolean replacePrincipals(List principals, KeyStore keystore) {
1873:
1874: if (principals == null || principals.size() == 0
1875: || keystore == null)
1876: return true;
1877:
1878: ListIterator i = principals.listIterator();
1879: while (i.hasNext()) {
1880: PolicyParser.PrincipalEntry pppe = (PolicyParser.PrincipalEntry) i
1881: .next();
1882: if (pppe.principalClass.equals(PolicyParser.REPLACE_NAME)) {
1883:
1884: // perform replacement
1885: // (only X509 replacement is possible now)
1886: String name;
1887: if ((name = getDN(pppe.principalName, keystore)) == null) {
1888: return false;
1889: }
1890:
1891: if (debug != null) {
1892: debug.println(" Replacing \"" + pppe.principalName
1893: + "\" with " + X500PRINCIPAL + "/\"" + name
1894: + "\"");
1895: }
1896:
1897: pppe.principalClass = X500PRINCIPAL;
1898: pppe.principalName = name;
1899: }
1900: }
1901: // return true if no replacement was performed,
1902: // or if replacement succeeded
1903: return true;
1904: }
1905:
1906: private void expandPermissionName(PolicyParser.PermissionEntry pe,
1907: KeyStore keystore) throws Exception {
1908: // short cut the common case
1909: if (pe.name == null || pe.name.indexOf("${{", 0) == -1) {
1910: return;
1911: }
1912:
1913: int startIndex = 0;
1914: int b, e;
1915: StringBuffer sb = new StringBuffer();
1916: while ((b = pe.name.indexOf("${{", startIndex)) != -1) {
1917: e = pe.name.indexOf("}}", b);
1918: if (e < 1) {
1919: break;
1920: }
1921: sb.append(pe.name.substring(startIndex, b));
1922:
1923: // get the value in ${{...}}
1924: String value = pe.name.substring(b + 3, e);
1925:
1926: // parse up to the first ':'
1927: int colonIndex;
1928: String prefix = value;
1929: String suffix;
1930: if ((colonIndex = value.indexOf(":")) != -1) {
1931: prefix = value.substring(0, colonIndex);
1932: }
1933:
1934: // handle different prefix possibilities
1935: if (prefix.equalsIgnoreCase("self")) {
1936: // do nothing - handled later
1937: sb.append(pe.name.substring(b, e + 2));
1938: startIndex = e + 2;
1939: continue;
1940: } else if (prefix.equalsIgnoreCase("alias")) {
1941: // get the suffix and perform keystore alias replacement
1942: if (colonIndex == -1) {
1943: MessageFormat form = new MessageFormat(
1944: ResourcesMgr
1945: .getString("alias name not provided (pe.name)"));
1946: Object[] source = { pe.name };
1947: throw new Exception(form.format(source));
1948: }
1949: suffix = value.substring(colonIndex + 1);
1950: if ((suffix = getDN(suffix, keystore)) == null) {
1951: MessageFormat form = new MessageFormat(
1952: ResourcesMgr
1953: .getString("unable to perform substitution on alias, suffix"));
1954: Object[] source = { value.substring(colonIndex + 1) };
1955: throw new Exception(form.format(source));
1956: }
1957:
1958: sb.append(X500PRINCIPAL + " \"" + suffix + "\"");
1959: startIndex = e + 2;
1960: } else {
1961: MessageFormat form = new MessageFormat(
1962: ResourcesMgr
1963: .getString("substitution value, prefix, unsupported"));
1964: Object[] source = { prefix };
1965: throw new Exception(form.format(source));
1966: }
1967: }
1968:
1969: // copy the rest of the value
1970: sb.append(pe.name.substring(startIndex));
1971:
1972: // replace the name with expanded value
1973: if (debug != null) {
1974: debug.println(" Permission name expanded from:\n\t"
1975: + pe.name + "\nto\n\t" + sb.toString());
1976: }
1977: pe.name = sb.toString();
1978: }
1979:
1980: private String getDN(String alias, KeyStore keystore) {
1981: Certificate cert = null;
1982: try {
1983: cert = keystore.getCertificate(alias);
1984: } catch (Exception e) {
1985: if (debug != null) {
1986: debug.println(" Error retrieving certificate for '"
1987: + alias + "': " + e.toString());
1988: }
1989: return null;
1990: }
1991:
1992: if (cert == null || !(cert instanceof X509Certificate)) {
1993: if (debug != null) {
1994: debug.println(" -- No certificate for '" + alias
1995: + "' - ignoring entry");
1996: }
1997: return null;
1998: } else {
1999: X509Certificate x509Cert = (X509Certificate) cert;
2000:
2001: // 4702543: X500 names with an EmailAddress
2002: // were encoded incorrectly. create new
2003: // X500Principal name with correct encoding
2004:
2005: X500Principal p = new X500Principal(x509Cert
2006: .getSubjectX500Principal().toString());
2007: return p.getName();
2008: }
2009: }
2010:
2011: /**
2012: * Checks public key. If it is marked as trusted in
2013: * the identity database, add it to the policy
2014: * with the AllPermission.
2015: */
2016: private boolean checkForTrustedIdentity(final Certificate cert,
2017: PolicyInfo myInfo) {
2018: if (cert == null)
2019: return false;
2020:
2021: // see if we are ignoring the identity scope or not
2022: if (ignoreIdentityScope)
2023: return false;
2024:
2025: // try to initialize scope
2026: synchronized (PolicyFile.class) {
2027: if (scope == null) {
2028: IdentityScope is = (IdentityScope) AccessController
2029: .doPrivileged(new java.security.PrivilegedAction() {
2030: public Object run() {
2031: return IdentityScope.getSystemScope();
2032: }
2033: });
2034:
2035: if (is instanceof sun.security.provider.IdentityDatabase) {
2036: scope = is;
2037: } else {
2038: // leave scope null
2039: }
2040: }
2041: }
2042:
2043: if (scope == null) {
2044: ignoreIdentityScope = true;
2045: return false;
2046: }
2047:
2048: // need privileged block for getIdentity in case we are trying
2049: // to get a signer
2050: final Identity id = (Identity) AccessController
2051: .doPrivileged(new java.security.PrivilegedAction() {
2052: public Object run() {
2053: return scope.getIdentity(cert.getPublicKey());
2054: }
2055: });
2056:
2057: if (isTrusted(id)) {
2058: if (debug != null) {
2059: debug
2060: .println("Adding policy entry for trusted Identity: ");
2061: //needed for identity toString!
2062: AccessController
2063: .doPrivileged(new java.security.PrivilegedAction() {
2064: public Object run() {
2065: debug.println(" identity = " + id);
2066: return null;
2067: }
2068: });
2069: debug.println("");
2070: }
2071:
2072: // add it to the policy for future reference
2073: Certificate certs[] = new Certificate[] { cert };
2074: PolicyEntry pe = new PolicyEntry(
2075: new CodeSource(null, certs));
2076: pe.add(SecurityConstants.ALL_PERMISSION);
2077:
2078: synchronized (myInfo.identityPolicyEntries) {
2079: myInfo.identityPolicyEntries.add(pe);
2080: }
2081:
2082: synchronized (myInfo.aliasMapping) {
2083: // add it to the mapping as well so
2084: // we don't have to go through this again
2085: myInfo.aliasMapping.put(cert, id.getName());
2086: }
2087:
2088: return true;
2089: }
2090: return false;
2091: }
2092:
2093: private static boolean isTrusted(Identity id) {
2094: if (id instanceof SystemIdentity) {
2095: SystemIdentity sysid = (SystemIdentity) id;
2096: if (sysid.isTrusted()) {
2097: return true;
2098: }
2099: } else if (id instanceof SystemSigner) {
2100: SystemSigner sysid = (SystemSigner) id;
2101: if (sysid.isTrusted()) {
2102: return true;
2103: }
2104: }
2105: return false;
2106: }
2107:
2108: /**
2109: * Each entry in the policy configuration file is represented by a
2110: * PolicyEntry object. <p>
2111: *
2112: * A PolicyEntry is a (CodeSource,Permission) pair. The
2113: * CodeSource contains the (URL, PublicKey) that together identify
2114: * where the Java bytecodes come from and who (if anyone) signed
2115: * them. The URL could refer to localhost. The URL could also be
2116: * null, meaning that this policy entry is given to all comers, as
2117: * long as they match the signer field. The signer could be null,
2118: * meaning the code is not signed. <p>
2119: *
2120: * The Permission contains the (Type, Name, Action) triplet. <p>
2121: *
2122: * For now, the Policy object retrieves the public key from the
2123: * X.509 certificate on disk that corresponds to the signedBy
2124: * alias specified in the Policy config file. For reasons of
2125: * efficiency, the Policy object keeps a hashtable of certs already
2126: * read in. This could be replaced by a secure internal key
2127: * store.
2128: *
2129: * <p>
2130: * For example, the entry
2131: * <pre>
2132: * permission java.io.File "/tmp", "read,write",
2133: * signedBy "Duke";
2134: * </pre>
2135: * is represented internally
2136: * <pre>
2137: *
2138: * FilePermission f = new FilePermission("/tmp", "read,write");
2139: * PublicKey p = publickeys.get("Duke");
2140: * URL u = InetAddress.getLocalHost();
2141: * CodeBase c = new CodeBase( p, u );
2142: * pe = new PolicyEntry(f, c);
2143: * </pre>
2144: *
2145: * @author Marianne Mueller
2146: * @author Roland Schemers
2147: * @version 1.52, 10/26/00
2148: * @see java.security.CodeSource
2149: * @see java.security.Policy
2150: * @see java.security.Permissions
2151: * @see java.security.ProtectionDomain
2152: */
2153:
2154: private static class PolicyEntry {
2155:
2156: private final CodeSource codesource;
2157: final List permissions;
2158: private final List principals;
2159:
2160: /**
2161: * Given a Permission and a CodeSource, create a policy entry.
2162: *
2163: * TODO: Decide if/how to add validity fields and "purpose" fields to
2164: * policy entries
2165: *
2166: * @param cs the CodeSource, which encapsulates the URL and the
2167: * public key
2168: * attributes from the policy config file. Validity checks
2169: * are performed on the public key before PolicyEntry is
2170: * called.
2171: *
2172: */
2173: PolicyEntry(CodeSource cs, List principals) {
2174: this .codesource = cs;
2175: this .permissions = new ArrayList();
2176: this .principals = principals; // can be null
2177: }
2178:
2179: PolicyEntry(CodeSource cs) {
2180: this (cs, null);
2181: }
2182:
2183: List getPrincipals() {
2184: return principals; // can be null
2185: }
2186:
2187: /**
2188: * add a Permission object to this entry.
2189: * No need to sync add op because perms are added to entry only
2190: * while entry is being initialized
2191: */
2192: void add(Permission p) {
2193: permissions.add(p);
2194: }
2195:
2196: /**
2197: * Return the CodeSource for this policy entry
2198: */
2199: CodeSource getCodeSource() {
2200: return codesource;
2201: }
2202:
2203: public String toString() {
2204: StringBuffer sb = new StringBuffer();
2205: sb.append(ResourcesMgr.getString("("));
2206: sb.append(getCodeSource());
2207: sb.append("\n");
2208: for (int j = 0; j < permissions.size(); j++) {
2209: Permission p = (Permission) permissions.get(j);
2210: sb.append(ResourcesMgr.getString(" "));
2211: sb.append(ResourcesMgr.getString(" "));
2212: sb.append(p);
2213: sb.append(ResourcesMgr.getString("\n"));
2214: }
2215: sb.append(ResourcesMgr.getString(")"));
2216: sb.append(ResourcesMgr.getString("\n"));
2217: return sb.toString();
2218: }
2219: }
2220: }
2221:
2222: class SelfPermission extends Permission {
2223: /**
2224: * The class name of the Permission class that will be
2225: * created when this self permission is expanded .
2226: *
2227: * @serial
2228: */
2229: private String type;
2230:
2231: /**
2232: * The permission name.
2233: *
2234: * @serial
2235: */
2236: private String name;
2237:
2238: /**
2239: * The actions of the permission.
2240: *
2241: * @serial
2242: */
2243: private String actions;
2244:
2245: /**
2246: * The certs of the permission.
2247: *
2248: * @serial
2249: */
2250: private java.security.cert.Certificate certs[];
2251:
2252: /**
2253: * Creates a new SelfPermission containing the permission
2254: * information needed later to expand the self
2255: * @param type the class name of the Permission class that will be
2256: * created when this permission is expanded and if necessary resolved.
2257: * @param name the name of the permission.
2258: * @param actions the actions of the permission.
2259: * @param certs the certificates the permission's class was signed with.
2260: * This is a list of certificate chains, where each chain is composed of a
2261: * signer certificate and optionally its supporting certificate chain.
2262: * Each chain is ordered bottom-to-top (i.e., with the signer certificate
2263: * first and the (root) certificate authority last).
2264: */
2265: public SelfPermission(String type, String name, String actions,
2266: java.security.cert.Certificate certs[]) {
2267: super (type);
2268: if (type == null)
2269: throw new NullPointerException(ResourcesMgr
2270: .getString("type can't be null"));
2271: this .type = type;
2272: this .name = name;
2273: this .actions = actions;
2274: if (certs != null) {
2275: // Extract the signer certs from the list of certificates.
2276: for (int i = 0; i < certs.length; i++) {
2277: if (!(certs[i] instanceof X509Certificate)) {
2278: // there is no concept of signer certs, so we store the
2279: // entire cert array
2280: this .certs = (java.security.cert.Certificate[]) certs
2281: .clone();
2282: break;
2283: }
2284: }
2285:
2286: if (this .certs == null) {
2287: // Go through the list of certs and see if all the certs are
2288: // signer certs.
2289: int i = 0;
2290: int count = 0;
2291: while (i < certs.length) {
2292: count++;
2293: while (((i + 1) < certs.length)
2294: && ((X509Certificate) certs[i])
2295: .getIssuerDN()
2296: .equals(
2297: ((X509Certificate) certs[i + 1])
2298: .getSubjectDN())) {
2299: i++;
2300: }
2301: i++;
2302: }
2303: if (count == certs.length) {
2304: // All the certs are signer certs, so we store the entire
2305: // array
2306: this .certs = (java.security.cert.Certificate[]) certs
2307: .clone();
2308: }
2309:
2310: if (this .certs == null) {
2311: // extract the signer certs
2312: ArrayList signerCerts = new ArrayList();
2313: i = 0;
2314: while (i < certs.length) {
2315: signerCerts.add(certs[i]);
2316: while (((i + 1) < certs.length)
2317: && ((X509Certificate) certs[i])
2318: .getIssuerDN()
2319: .equals(
2320: ((X509Certificate) certs[i + 1])
2321: .getSubjectDN())) {
2322: i++;
2323: }
2324: i++;
2325: }
2326: this .certs = new java.security.cert.Certificate[signerCerts
2327: .size()];
2328: signerCerts.toArray(this .certs);
2329: }
2330: }
2331: }
2332: }
2333:
2334: /**
2335: * This method always returns false for SelfPermission permissions.
2336: * That is, an SelfPermission never considered to
2337: * imply another permission.
2338: *
2339: * @param p the permission to check against.
2340: *
2341: * @return false.
2342: */
2343: public boolean implies(Permission p) {
2344: return false;
2345: }
2346:
2347: /**
2348: * Checks two SelfPermission objects for equality.
2349:
2350: * Checks that <i>obj</i> is an SelfPermission, and has
2351: * the same type (class) name, permission name, actions, and
2352: * certificates as this object.
2353: *
2354: * @param obj the object we are testing for equality with this object.
2355: *
2356: * @return true if obj is an SelfPermission, and has the same
2357: * type (class) name, permission name, actions, and
2358: * certificates as this object.
2359: */
2360: public boolean equals(Object obj) {
2361: if (obj == this )
2362: return true;
2363:
2364: if (!(obj instanceof SelfPermission))
2365: return false;
2366: SelfPermission that = (SelfPermission) obj;
2367:
2368: if (!(this .type.equals(that.type)
2369: && this .name.equals(that.name) && this .actions
2370: .equals(that.actions)))
2371: return false;
2372:
2373: if (this .certs.length != that.certs.length)
2374: return false;
2375:
2376: int i, j;
2377: boolean match;
2378:
2379: for (i = 0; i < this .certs.length; i++) {
2380: match = false;
2381: for (j = 0; j < that.certs.length; j++) {
2382: if (this .certs[i].equals(that.certs[j])) {
2383: match = true;
2384: break;
2385: }
2386: }
2387: if (!match)
2388: return false;
2389: }
2390:
2391: for (i = 0; i < that.certs.length; i++) {
2392: match = false;
2393: for (j = 0; j < this .certs.length; j++) {
2394: if (that.certs[i].equals(this .certs[j])) {
2395: match = true;
2396: break;
2397: }
2398: }
2399: if (!match)
2400: return false;
2401: }
2402: return true;
2403: }
2404:
2405: /**
2406: * Returns the hash code value for this object.
2407: *
2408: * @return a hash code value for this object.
2409: */
2410:
2411: public int hashCode() {
2412: int hash = type.hashCode();
2413: if (name != null)
2414: hash ^= name.hashCode();
2415: if (actions != null)
2416: hash ^= actions.hashCode();
2417: return hash;
2418: }
2419:
2420: /**
2421: * Returns the canonical string representation of the actions,
2422: * which currently is the empty string "", since there are no actions for
2423: * an SelfPermission. That is, the actions for the
2424: * permission that will be created when this SelfPermission
2425: * is resolved may be non-null, but an SelfPermission
2426: * itself is never considered to have any actions.
2427: *
2428: * @return the empty string "".
2429: */
2430: public String getActions() {
2431: return "";
2432: }
2433:
2434: public String getSelfType() {
2435: return type;
2436: }
2437:
2438: public String getSelfName() {
2439: return name;
2440: }
2441:
2442: public String getSelfActions() {
2443: return actions;
2444: }
2445:
2446: public java.security.cert.Certificate[] getCerts() {
2447: return certs;
2448: }
2449:
2450: /**
2451: * Returns a string describing this SelfPermission. The convention
2452: * is to specify the class name, the permission name, and the actions, in
2453: * the following format: '(unresolved "ClassName" "name" "actions")'.
2454: *
2455: * @return information about this SelfPermission.
2456: */
2457:
2458: public String toString() {
2459: return "(SelfPermission " + type + " " + name + " " + actions
2460: + ")";
2461: }
2462: }
2463:
2464: /**
2465: * holds policy information that we need to synch on
2466: */
2467: class PolicyInfo {
2468: private static final boolean verbose = false;
2469:
2470: // Stores grant entries in the policy
2471: final List policyEntries;
2472:
2473: // Stores grant entries gotten from identity database
2474: // Use separate lists to avoid sync on policyEntries
2475: final List identityPolicyEntries;
2476:
2477: // Maps aliases to certs
2478: final Map aliasMapping;
2479:
2480: // Maps ProtectionDomain to PermissionCollection
2481: private final Map[] pdMapping;
2482: private java.util.Random random;
2483:
2484: PolicyInfo(int numCaches) {
2485: policyEntries = new ArrayList();
2486: identityPolicyEntries = new ArrayList(2);
2487: aliasMapping = new HashMap(11);
2488:
2489: pdMapping = new Map[numCaches];
2490: for (int i = 0; i < numCaches; i++) {
2491: pdMapping[i] = Collections
2492: .synchronizedMap(new WeakHashMap());
2493: }
2494: if (numCaches > 1) {
2495: random = new java.util.Random();
2496: }
2497: }
2498:
2499: Map getPdMapping() {
2500: if (pdMapping.length == 1) {
2501: return pdMapping[0];
2502: } else {
2503: int i = java.lang.Math.abs(random.nextInt()
2504: % pdMapping.length);
2505: return pdMapping[i];
2506: }
2507: }
2508: }
|