Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/provider/PolicyFile.java
38830 views
/*1* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.provider;2627import java.io.*;28import java.lang.reflect.*;29import java.net.MalformedURLException;30import java.net.URL;31import java.net.URI;32import java.util.*;33import java.text.MessageFormat;34import java.security.*;35import java.security.cert.Certificate;36import java.security.cert.X509Certificate;37import javax.security.auth.Subject;38import javax.security.auth.x500.X500Principal;39import java.io.FilePermission;40import java.net.SocketPermission;41import java.net.NetPermission;42import sun.misc.JavaSecurityProtectionDomainAccess;43import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache;44import sun.misc.SharedSecrets;45import sun.security.util.PolicyUtil;46import sun.security.util.PropertyExpander;47import sun.security.util.Debug;48import sun.security.util.ResourcesMgr;49import sun.security.util.SecurityConstants;50import sun.net.www.ParseUtil;5152/**53* This class represents a default implementation for54* <code>java.security.Policy</code>.55*56* Note:57* For backward compatibility with JAAS 1.0 it loads58* both java.auth.policy and java.policy. However it59* is recommended that java.auth.policy be not used60* and the java.policy contain all grant entries including61* that contain principal-based entries.62*63*64* <p> This object stores the policy for entire Java runtime,65* and is the amalgamation of multiple static policy66* configurations that resides in files.67* The algorithm for locating the policy file(s) and reading their68* information into this <code>Policy</code> object is:69*70* <ol>71* <li>72* Loop through the <code>java.security.Security</code> properties,73* <i>policy.url.1</i>, <i>policy.url.2</i>, ...,74* <i>policy.url.X</i>" and75* <i>auth.policy.url.1</i>, <i>auth.policy.url.2</i>, ...,76* <i>auth.policy.url.X</i>". These properties are set77* in the Java security properties file, which is located in the file named78* <JAVA_HOME>/lib/security/java.security.79* <JAVA_HOME> refers to the value of the java.home system property,80* and specifies the directory where the JRE is installed.81* Each property value specifies a <code>URL</code> pointing to a82* policy file to be loaded. Read in and load each policy.83*84* <i>auth.policy.url</i> is supported only for backward compatibility.85*86* <li>87* The <code>java.lang.System</code> property <i>java.security.policy</i>88* may also be set to a <code>URL</code> pointing to another policy file89* (which is the case when a user uses the -D switch at runtime).90* If this property is defined, and its use is allowed by the91* security property file (the Security property,92* <i>policy.allowSystemProperty</i> is set to <i>true</i>),93* also load that policy.94*95* <li>96* The <code>java.lang.System</code> property97* <i>java.security.auth.policy</i> may also be set to a98* <code>URL</code> pointing to another policy file99* (which is the case when a user uses the -D switch at runtime).100* If this property is defined, and its use is allowed by the101* security property file (the Security property,102* <i>policy.allowSystemProperty</i> is set to <i>true</i>),103* also load that policy.104*105* <i>java.security.auth.policy</i> is supported only for backward106* compatibility.107*108* If the <i>java.security.policy</i> or109* <i>java.security.auth.policy</i> property is defined using110* "==" (rather than "="), then ignore all other specified111* policies and only load this policy.112* </ol>113*114* Each policy file consists of one or more grant entries, each of115* which consists of a number of permission entries.116*117* <pre>118* grant signedBy "<b>alias</b>", codeBase "<b>URL</b>",119* principal <b>principalClass</b> "<b>principalName</b>",120* principal <b>principalClass</b> "<b>principalName</b>",121* ... {122*123* permission <b>Type</b> "<b>name</b> "<b>action</b>",124* signedBy "<b>alias</b>";125* permission <b>Type</b> "<b>name</b> "<b>action</b>",126* signedBy "<b>alias</b>";127* ....128* };129* </pre>130*131* All non-bold items above must appear as is (although case132* doesn't matter and some are optional, as noted below).133* principal entries are optional and need not be present.134* Italicized items represent variable values.135*136* <p> A grant entry must begin with the word <code>grant</code>.137* The <code>signedBy</code>,<code>codeBase</code> and <code>principal</code>138* name/value pairs are optional.139* If they are not present, then any signer (including unsigned code)140* will match, and any codeBase will match.141* Note that the <i>principalClass</i>142* may be set to the wildcard value, *, which allows it to match143* any <code>Principal</code> class. In addition, the <i>principalName</i>144* may also be set to the wildcard value, *, allowing it to match145* any <code>Principal</code> name. When setting the <i>principalName</i>146* to the *, do not surround the * with quotes.147*148* <p> A permission entry must begin with the word <code>permission</code>.149* The word <code><i>Type</i></code> in the template above is150* a specific permission type, such as <code>java.io.FilePermission</code>151* or <code>java.lang.RuntimePermission</code>.152*153* <p> The "<i>action</i>" is required for154* many permission types, such as <code>java.io.FilePermission</code>155* (where it specifies what type of file access that is permitted).156* It is not required for categories such as157* <code>java.lang.RuntimePermission</code>158* where it is not necessary - you either have the159* permission specified by the <code>"<i>name</i>"</code>160* value following the type name or you don't.161*162* <p> The <code>signedBy</code> name/value pair for a permission entry163* is optional. If present, it indicates a signed permission. That is,164* the permission class itself must be signed by the given alias in165* order for it to be granted. For example,166* suppose you have the following grant entry:167*168* <pre>169* grant principal foo.com.Principal "Duke" {170* permission Foo "foobar", signedBy "FooSoft";171* }172* </pre>173*174* <p> Then this permission of type <i>Foo</i> is granted if the175* <code>Foo.class</code> permission has been signed by the176* "FooSoft" alias, or if XXX <code>Foo.class</code> is a177* system class (i.e., is found on the CLASSPATH).178*179*180* <p> Items that appear in an entry must appear in the specified order181* (<code>permission</code>, <i>Type</i>, "<i>name</i>", and182* "<i>action</i>"). An entry is terminated with a semicolon.183*184* <p> Case is unimportant for the identifiers (<code>permission</code>,185* <code>signedBy</code>, <code>codeBase</code>, etc.) but is186* significant for the <i>Type</i>187* or for any string that is passed in as a value. <p>188*189* <p> An example of two entries in a policy configuration file is190* <pre>191* // if the code is comes from "foo.com" and is running as "Duke",192* // grant it read/write to all files in /tmp.193*194* grant codeBase "foo.com", principal foo.com.Principal "Duke" {195* permission java.io.FilePermission "/tmp/*", "read,write";196* };197*198* // grant any code running as "Duke" permission to read199* // the "java.vendor" Property.200*201* grant principal foo.com.Principal "Duke" {202* permission java.util.PropertyPermission "java.vendor";203*204*205* </pre>206* This Policy implementation supports special handling of any207* permission that contains the string, "<b>${{self}}</b>", as part of208* its target name. When such a permission is evaluated209* (such as during a security check), <b>${{self}}</b> is replaced210* with one or more Principal class/name pairs. The exact211* replacement performed depends upon the contents of the212* grant clause to which the permission belongs.213*<p>214*215* If the grant clause does not contain any principal information,216* the permission will be ignored (permissions containing217* <b>${{self}}</b> in their target names are only valid in the context218* of a principal-based grant clause). For example, BarPermission219* will always be ignored in the following grant clause:220*221*<pre>222* grant codebase "www.foo.com", signedby "duke" {223* permission BarPermission "... ${{self}} ...";224* };225*</pre>226*227* If the grant clause contains principal information, <b>${{self}}</b>228* will be replaced with that same principal information.229* For example, <b>${{self}}</b> in BarPermission will be replaced by230* <b>javax.security.auth.x500.X500Principal "cn=Duke"</b>231* in the following grant clause:232*233* <pre>234* grant principal javax.security.auth.x500.X500Principal "cn=Duke" {235* permission BarPermission "... ${{self}} ...";236* };237* </pre>238*239* If there is a comma-separated list of principals in the grant240* clause, then <b>${{self}}</b> will be replaced by the same241* comma-separated list or principals.242* In the case where both the principal class and name are243* wildcarded in the grant clause, <b>${{self}}</b> is replaced244* with all the principals associated with the <code>Subject</code>245* in the current <code>AccessControlContext</code>.246*247*248* <p> For PrivateCredentialPermissions, you can also use "<b>self</b>"249* instead of "<b>${{self}}</b>". However the use of "<b>self</b>" is250* deprecated in favour of "<b>${{self}}</b>".251*252* @see java.security.CodeSource253* @see java.security.Permissions254* @see java.security.ProtectionDomain255*/256public class PolicyFile extends java.security.Policy {257258private static final Debug debug = Debug.getInstance("policy");259260private static final String NONE = "NONE";261private static final String P11KEYSTORE = "PKCS11";262263private static final String SELF = "${{self}}";264private static final String X500PRINCIPAL =265"javax.security.auth.x500.X500Principal";266private static final String POLICY = "java.security.policy";267private static final String SECURITY_MANAGER = "java.security.manager";268private static final String POLICY_URL = "policy.url.";269private static final String AUTH_POLICY = "java.security.auth.policy";270private static final String AUTH_POLICY_URL = "auth.policy.url.";271272private static final int DEFAULT_CACHE_SIZE = 1;273274// contains the policy grant entries, PD cache, and alias mapping275// can be updated if refresh() is called276private volatile PolicyInfo policyInfo;277private boolean constructed = false;278279private boolean expandProperties = true;280private boolean ignoreIdentityScope = true;281private boolean allowSystemProperties = true;282private boolean notUtf8 = false;283private URL url;284285// for use with the reflection API286287private static final Class[] PARAMS0 = { };288private static final Class[] PARAMS1 = { String.class };289private static final Class[] PARAMS2 = { String.class, String.class };290291/**292* Initializes the Policy object and reads the default policy293* configuration file(s) into the Policy object.294*/295public PolicyFile() {296init((URL)null);297}298299/**300* Initializes the Policy object and reads the default policy301* from the specified URL only.302*/303public PolicyFile(URL url) {304this.url = url;305init(url);306}307308/**309* Initializes the Policy object and reads the default policy310* configuration file(s) into the Policy object.311*312* The algorithm for locating the policy file(s) and reading their313* information into the Policy object is:314* <pre>315* loop through the Security Properties named "policy.url.1",316* ""policy.url.2", "auth.policy.url.1", "auth.policy.url.2" etc, until317* you don't find one. Each of these specify a policy file.318*319* if none of these could be loaded, use a builtin static policy320* equivalent to the default lib/security/java.policy file.321*322* if the system property "java.policy" or "java.auth.policy" is defined323* (which is the324* case when the user uses the -D switch at runtime), and325* its use is allowed by the security property file,326* also load it.327* </pre>328*329* Each policy file consists of one or more grant entries, each of330* which consists of a number of permission entries.331* <pre>332* grant signedBy "<i>alias</i>", codeBase "<i>URL</i>" {333* permission <i>Type</i> "<i>name</i>", "<i>action</i>",334* signedBy "<i>alias</i>";335* ....336* permission <i>Type</i> "<i>name</i>", "<i>action</i>",337* signedBy "<i>alias</i>";338* };339*340* </pre>341*342* All non-italicized items above must appear as is (although case343* doesn't matter and some are optional, as noted below).344* Italicized items represent variable values.345*346* <p> A grant entry must begin with the word <code>grant</code>.347* The <code>signedBy</code> and <code>codeBase</code> name/value348* pairs are optional.349* If they are not present, then any signer (including unsigned code)350* will match, and any codeBase will match.351*352* <p> A permission entry must begin with the word <code>permission</code>.353* The word <code><i>Type</i></code> in the template above would actually354* be a specific permission type, such as355* <code>java.io.FilePermission</code> or356* <code>java.lang.RuntimePermission</code>.357*358* <p>The "<i>action</i>" is required for359* many permission types, such as <code>java.io.FilePermission</code>360* (where it specifies what type of file access is permitted).361* It is not required for categories such as362* <code>java.lang.RuntimePermission</code>363* where it is not necessary - you either have the364* permission specified by the <code>"<i>name</i>"</code>365* value following the type name or you don't.366*367* <p>The <code>signedBy</code> name/value pair for a permission entry368* is optional. If present, it indicates a signed permission. That is,369* the permission class itself must be signed by the given alias in370* order for it to be granted. For example,371* suppose you have the following grant entry:372*373* <pre>374* grant {375* permission Foo "foobar", signedBy "FooSoft";376* }377* </pre>378*379* <p>Then this permission of type <i>Foo</i> is granted if the380* <code>Foo.class</code> permission has been signed by the381* "FooSoft" alias, or if <code>Foo.class</code> is a382* system class (i.e., is found on the CLASSPATH).383*384* <p>Items that appear in an entry must appear in the specified order385* (<code>permission</code>, <i>Type</i>, "<i>name</i>", and386* "<i>action</i>"). An entry is terminated with a semicolon.387*388* <p>Case is unimportant for the identifiers (<code>permission</code>,389* <code>signedBy</code>, <code>codeBase</code>, etc.) but is390* significant for the <i>Type</i>391* or for any string that is passed in as a value. <p>392*393* <p>An example of two entries in a policy configuration file is394* <pre>395* // if the code is signed by "Duke", grant it read/write to all396* // files in /tmp.397*398* grant signedBy "Duke" {399* permission java.io.FilePermission "/tmp/*", "read,write";400* };401* <p>402* // grant everyone the following permission403*404* grant {405* permission java.util.PropertyPermission "java.vendor";406* };407* </pre>408*/409private void init(URL url) {410// Properties are set once for each init(); ignore changes between411// between diff invocations of initPolicyFile(policy, url, info).412String numCacheStr =413AccessController.doPrivileged(new PrivilegedAction<String>() {414public String run() {415expandProperties = "true".equalsIgnoreCase416(Security.getProperty("policy.expandProperties"));417ignoreIdentityScope = "true".equalsIgnoreCase418(Security.getProperty("policy.ignoreIdentityScope"));419allowSystemProperties = "true".equalsIgnoreCase420(Security.getProperty("policy.allowSystemProperty"));421notUtf8 = "false".equalsIgnoreCase422(System.getProperty("sun.security.policy.utf8"));423return System.getProperty("sun.security.policy.numcaches");424}});425426int numCaches;427if (numCacheStr != null) {428try {429numCaches = Integer.parseInt(numCacheStr);430} catch (NumberFormatException e) {431numCaches = DEFAULT_CACHE_SIZE;432}433} else {434numCaches = DEFAULT_CACHE_SIZE;435}436// System.out.println("number caches=" + numCaches);437PolicyInfo newInfo = new PolicyInfo(numCaches);438initPolicyFile(newInfo, url);439policyInfo = newInfo;440}441442private void initPolicyFile(final PolicyInfo newInfo, final URL url) {443444if (url != null) {445446/**447* If the caller specified a URL via Policy.getInstance,448* we only read from that URL449*/450451if (debug != null) {452debug.println("reading "+url);453}454AccessController.doPrivileged(new PrivilegedAction<Void>() {455public Void run() {456if (init(url, newInfo) == false) {457// use static policy if all else fails458initStaticPolicy(newInfo);459}460return null;461}462});463464} else {465466/**467* Caller did not specify URL via Policy.getInstance.468* Read from URLs listed in the java.security properties file.469*470* We call initPolicyFile with POLICY , POLICY_URL and then471* call it with AUTH_POLICY and AUTH_POLICY_URL472* So first we will process the JAVA standard policy473* and then process the JAVA AUTH Policy.474* This is for backward compatibility as well as to handle475* cases where the user has a single unified policyfile476* with both java policy entries and auth entries477*/478479boolean loaded_one = initPolicyFile(POLICY, POLICY_URL, newInfo);480// To maintain strict backward compatibility481// we load the static policy only if POLICY load failed482if (!loaded_one) {483// use static policy if all else fails484initStaticPolicy(newInfo);485}486487initPolicyFile(AUTH_POLICY, AUTH_POLICY_URL, newInfo);488}489}490491private boolean initPolicyFile(final String propname, final String urlname,492final PolicyInfo newInfo) {493Boolean loadedPolicy =494AccessController.doPrivileged(new PrivilegedAction<Boolean>() {495public Boolean run() {496boolean loaded_policy = false;497498if (allowSystemProperties) {499String extra_policy = System.getProperty(propname);500if (extra_policy != null) {501boolean overrideAll = false;502if (extra_policy.startsWith("=")) {503overrideAll = true;504extra_policy = extra_policy.substring(1);505}506try {507extra_policy =508PropertyExpander.expand(extra_policy);509URL policyURL;510511File policyFile = new File(extra_policy);512if (policyFile.exists()) {513policyURL = ParseUtil.fileToEncodedURL514(new File(policyFile.getCanonicalPath()));515} else {516policyURL = new URL(extra_policy);517}518if (debug != null)519debug.println("reading "+policyURL);520if (init(policyURL, newInfo))521loaded_policy = true;522} catch (Exception e) {523// ignore.524if (debug != null) {525debug.println("caught exception: "+e);526}527}528if (overrideAll) {529if (debug != null) {530debug.println("overriding other policies!");531}532return Boolean.valueOf(loaded_policy);533}534}535}536537int n = 1;538String policy_uri;539540while ((policy_uri = Security.getProperty(urlname+n)) != null) {541try {542URL policy_url = null;543String expanded_uri = PropertyExpander.expand544(policy_uri).replace(File.separatorChar, '/');545546if (policy_uri.startsWith("file:${java.home}/") ||547policy_uri.startsWith("file:${user.home}/")) {548549// this special case accommodates550// the situation java.home/user.home551// expand to a single slash, resulting in552// a file://foo URI553policy_url = new File554(expanded_uri.substring(5)).toURI().toURL();555} else {556policy_url = new URI(expanded_uri).toURL();557}558559if (debug != null)560debug.println("reading "+policy_url);561if (init(policy_url, newInfo))562loaded_policy = true;563} catch (Exception e) {564if (debug != null) {565debug.println(566"Debug info only. Error reading policy " +e);567e.printStackTrace();568}569// ignore that policy570}571n++;572}573return Boolean.valueOf(loaded_policy);574}575});576577return loadedPolicy.booleanValue();578}579580/**581* Reads a policy configuration into the Policy object using a582* Reader object.583*584* @param policyFile the policy Reader object.585*/586private boolean init(URL policy, PolicyInfo newInfo) {587boolean success = false;588PolicyParser pp = new PolicyParser(expandProperties);589InputStreamReader isr = null;590try {591592// read in policy using UTF-8 by default593//594// check non-standard system property to see if595// the default encoding should be used instead596597if (notUtf8) {598isr = new InputStreamReader599(PolicyUtil.getInputStream(policy));600} else {601isr = new InputStreamReader602(PolicyUtil.getInputStream(policy), "UTF-8");603}604605pp.read(isr);606607KeyStore keyStore = null;608try {609keyStore = PolicyUtil.getKeyStore610(policy,611pp.getKeyStoreUrl(),612pp.getKeyStoreType(),613pp.getKeyStoreProvider(),614pp.getStorePassURL(),615debug);616} catch (Exception e) {617// ignore, treat it like we have no keystore618if (debug != null) {619debug.println("Debug info only. Ignoring exception.");620e.printStackTrace();621}622}623624Enumeration<PolicyParser.GrantEntry> enum_ = pp.grantElements();625while (enum_.hasMoreElements()) {626PolicyParser.GrantEntry ge = enum_.nextElement();627addGrantEntry(ge, keyStore, newInfo);628}629} catch (PolicyParser.ParsingException pe) {630MessageFormat form = new MessageFormat(ResourcesMgr.getString631(POLICY + ".error.parsing.policy.message"));632Object[] source = {policy, pe.getLocalizedMessage()};633System.err.println(form.format(source));634if (debug != null)635pe.printStackTrace();636637} catch (Exception e) {638if (debug != null) {639debug.println("error parsing "+policy);640debug.println(e.toString());641e.printStackTrace();642}643} finally {644if (isr != null) {645try {646isr.close();647success = true;648} catch (IOException e) {649// ignore the exception650}651} else {652success = true;653}654}655656return success;657}658659private void initStaticPolicy(final PolicyInfo newInfo) {660AccessController.doPrivileged(new PrivilegedAction<Void>() {661public Void run() {662PolicyEntry pe = new PolicyEntry(new CodeSource(null,663(Certificate[]) null));664pe.add(SecurityConstants.LOCAL_LISTEN_PERMISSION);665pe.add(new PropertyPermission("java.version",666SecurityConstants.PROPERTY_READ_ACTION));667pe.add(new PropertyPermission("java.vendor",668SecurityConstants.PROPERTY_READ_ACTION));669pe.add(new PropertyPermission("java.vendor.url",670SecurityConstants.PROPERTY_READ_ACTION));671pe.add(new PropertyPermission("java.class.version",672SecurityConstants.PROPERTY_READ_ACTION));673pe.add(new PropertyPermission("os.name",674SecurityConstants.PROPERTY_READ_ACTION));675pe.add(new PropertyPermission("os.version",676SecurityConstants.PROPERTY_READ_ACTION));677pe.add(new PropertyPermission("os.arch",678SecurityConstants.PROPERTY_READ_ACTION));679pe.add(new PropertyPermission("file.separator",680SecurityConstants.PROPERTY_READ_ACTION));681pe.add(new PropertyPermission("path.separator",682SecurityConstants.PROPERTY_READ_ACTION));683pe.add(new PropertyPermission("line.separator",684SecurityConstants.PROPERTY_READ_ACTION));685pe.add(new PropertyPermission686("java.specification.version",687SecurityConstants.PROPERTY_READ_ACTION));688pe.add(new PropertyPermission689("java.specification.vendor",690SecurityConstants.PROPERTY_READ_ACTION));691pe.add(new PropertyPermission692("java.specification.name",693SecurityConstants.PROPERTY_READ_ACTION));694pe.add(new PropertyPermission695("java.vm.specification.version",696SecurityConstants.PROPERTY_READ_ACTION));697pe.add(new PropertyPermission698("java.vm.specification.vendor",699SecurityConstants.PROPERTY_READ_ACTION));700pe.add(new PropertyPermission701("java.vm.specification.name",702SecurityConstants.PROPERTY_READ_ACTION));703pe.add(new PropertyPermission("java.vm.version",704SecurityConstants.PROPERTY_READ_ACTION));705pe.add(new PropertyPermission("java.vm.vendor",706SecurityConstants.PROPERTY_READ_ACTION));707pe.add(new PropertyPermission("java.vm.name",708SecurityConstants.PROPERTY_READ_ACTION));709710// No need to sync because noone has access to newInfo yet711newInfo.policyEntries.add(pe);712713// Add AllPermissions for standard extensions714String[] extCodebases = PolicyParser.parseExtDirs(715PolicyParser.EXTDIRS_EXPANSION, 0);716if (extCodebases != null && extCodebases.length > 0) {717for (int i = 0; i < extCodebases.length; i++) {718try {719pe = new PolicyEntry(canonicalizeCodebase(720new CodeSource(new URL(extCodebases[i]),721(Certificate[]) null), false ));722pe.add(SecurityConstants.ALL_PERMISSION);723724// No need to sync because noone has access to725// newInfo yet726newInfo.policyEntries.add(pe);727} catch (Exception e) {728// this is probably bad (though not dangerous).729// What should we do?730}731}732}733return null;734}735});736}737738/**739* Given a GrantEntry, create a codeSource.740*741* @return null if signedBy alias is not recognized742*/743private CodeSource getCodeSource(PolicyParser.GrantEntry ge, KeyStore keyStore,744PolicyInfo newInfo) throws java.net.MalformedURLException745{746Certificate[] certs = null;747if (ge.signedBy != null) {748certs = getCertificates(keyStore, ge.signedBy, newInfo);749if (certs == null) {750// we don't have a key for this alias,751// just return752if (debug != null) {753debug.println(" -- No certs for alias '" +754ge.signedBy + "' - ignoring entry");755}756return null;757}758}759760URL location;761762if (ge.codeBase != null)763location = new URL(ge.codeBase);764else765location = null;766767return (canonicalizeCodebase(new CodeSource(location, certs),false));768}769770/**771* Add one policy entry to the list.772*/773private void addGrantEntry(PolicyParser.GrantEntry ge,774KeyStore keyStore, PolicyInfo newInfo) {775776if (debug != null) {777debug.println("Adding policy entry: ");778debug.println(" signedBy " + ge.signedBy);779debug.println(" codeBase " + ge.codeBase);780if (ge.principals != null) {781for (PolicyParser.PrincipalEntry pppe : ge.principals) {782debug.println(" " + pppe.toString());783}784}785}786787try {788CodeSource codesource = getCodeSource(ge, keyStore, newInfo);789// skip if signedBy alias was unknown...790if (codesource == null) return;791792// perform keystore alias principal replacement.793// for example, if alias resolves to X509 certificate,794// replace principal with: <X500Principal class> <SubjectDN>795// -- skip if alias is unknown796if (replacePrincipals(ge.principals, keyStore) == false)797return;798PolicyEntry entry = new PolicyEntry(codesource, ge.principals);799Enumeration<PolicyParser.PermissionEntry> enum_ =800ge.permissionElements();801while (enum_.hasMoreElements()) {802PolicyParser.PermissionEntry pe = enum_.nextElement();803804try {805// perform ${{ ... }} expansions within permission name806expandPermissionName(pe, keyStore);807808// XXX special case PrivateCredentialPermission-SELF809Permission perm;810if (pe.permission.equals811("javax.security.auth.PrivateCredentialPermission") &&812pe.name.endsWith(" self")) {813pe.name = pe.name.substring(0, pe.name.indexOf("self"))814+ SELF;815}816// check for self817if (pe.name != null && pe.name.indexOf(SELF) != -1) {818// Create a "SelfPermission" , it could be an819// an unresolved permission which will be resolved820// when implies is called821// Add it to entry822Certificate certs[];823if (pe.signedBy != null) {824certs = getCertificates(keyStore,825pe.signedBy,826newInfo);827} else {828certs = null;829}830perm = new SelfPermission(pe.permission,831pe.name,832pe.action,833certs);834} else {835perm = getInstance(pe.permission,836pe.name,837pe.action);838}839entry.add(perm);840if (debug != null) {841debug.println(" "+perm);842}843} catch (ClassNotFoundException cnfe) {844Certificate certs[];845if (pe.signedBy != null) {846certs = getCertificates(keyStore,847pe.signedBy,848newInfo);849} else {850certs = null;851}852853// only add if we had no signer or we had a854// a signer and found the keys for it.855if (certs != null || pe.signedBy == null) {856Permission perm = new UnresolvedPermission(857pe.permission,858pe.name,859pe.action,860certs);861entry.add(perm);862if (debug != null) {863debug.println(" "+perm);864}865}866} catch (java.lang.reflect.InvocationTargetException ite) {867MessageFormat form = new MessageFormat868(ResourcesMgr.getString869(POLICY +870".error.adding.Permission.perm.message"));871Object[] source = {pe.permission,872ite.getTargetException().toString()};873System.err.println(form.format(source));874} catch (Exception e) {875MessageFormat form = new MessageFormat876(ResourcesMgr.getString877(POLICY +878".error.adding.Permission.perm.message"));879Object[] source = {pe.permission,880e.toString()};881System.err.println(form.format(source));882}883}884885// No need to sync because noone has access to newInfo yet886newInfo.policyEntries.add(entry);887} catch (Exception e) {888MessageFormat form = new MessageFormat(ResourcesMgr.getString889(POLICY890+ ".error.adding.Entry.message"));891Object[] source = {e.toString()};892System.err.println(form.format(source));893}894if (debug != null)895debug.println();896}897898/**899* Returns a new Permission object of the given Type. The Permission is900* created by getting the901* Class object using the <code>Class.forName</code> method, and using902* the reflection API to invoke the (String name, String actions)903* constructor on the904* object.905*906* @param type the type of Permission being created.907* @param name the name of the Permission being created.908* @param actions the actions of the Permission being created.909*910* @exception ClassNotFoundException if the particular Permission911* class could not be found.912*913* @exception IllegalAccessException if the class or initializer is914* not accessible.915*916* @exception InstantiationException if getInstance tries to917* instantiate an abstract class or an interface, or if the918* instantiation fails for some other reason.919*920* @exception NoSuchMethodException if the (String, String) constructor921* is not found.922*923* @exception InvocationTargetException if the underlying Permission924* constructor throws an exception.925*926*/927928private static final Permission getInstance(String type,929String name,930String actions)931throws ClassNotFoundException,932InstantiationException,933IllegalAccessException,934NoSuchMethodException,935InvocationTargetException936{937//XXX we might want to keep a hash of created factories...938Class<?> pc = Class.forName(type, false, null);939Permission answer = getKnownInstance(pc, name, actions);940if (answer != null) {941return answer;942}943if (!Permission.class.isAssignableFrom(pc)) {944// not the right subtype945throw new ClassCastException(type + " is not a Permission");946}947948if (name == null && actions == null) {949try {950Constructor<?> c = pc.getConstructor(PARAMS0);951return (Permission) c.newInstance(new Object[] {});952} catch (NoSuchMethodException ne) {953try {954Constructor<?> c = pc.getConstructor(PARAMS1);955return (Permission) c.newInstance(956new Object[] { name});957} catch (NoSuchMethodException ne1 ) {958Constructor<?> c = pc.getConstructor(PARAMS2);959return (Permission) c.newInstance(960new Object[] { name, actions });961}962}963} else {964if (name != null && actions == null) {965try {966Constructor<?> c = pc.getConstructor(PARAMS1);967return (Permission) c.newInstance(new Object[] { name});968} catch (NoSuchMethodException ne) {969Constructor<?> c = pc.getConstructor(PARAMS2);970return (Permission) c.newInstance(971new Object[] { name, actions });972}973} else {974Constructor<?> c = pc.getConstructor(PARAMS2);975return (Permission) c.newInstance(976new Object[] { name, actions });977}978}979}980981/**982* Creates one of the well-known permissions directly instead of983* via reflection. Keep list short to not penalize non-JDK-defined984* permissions.985*/986private static final Permission getKnownInstance(Class<?> claz,987String name, String actions) {988if (claz.equals(FilePermission.class)) {989return new FilePermission(name, actions);990} else if (claz.equals(SocketPermission.class)) {991return new SocketPermission(name, actions);992} else if (claz.equals(RuntimePermission.class)) {993return new RuntimePermission(name, actions);994} else if (claz.equals(PropertyPermission.class)) {995return new PropertyPermission(name, actions);996} else if (claz.equals(NetPermission.class)) {997return new NetPermission(name, actions);998} else if (claz.equals(AllPermission.class)) {999return SecurityConstants.ALL_PERMISSION;1000} else {1001return null;1002}1003}10041005/**1006* Fetch all certs associated with this alias.1007*/1008private Certificate[] getCertificates1009(KeyStore keyStore, String aliases, PolicyInfo newInfo) {10101011List<Certificate> vcerts = null;10121013StringTokenizer st = new StringTokenizer(aliases, ",");1014int n = 0;10151016while (st.hasMoreTokens()) {1017String alias = st.nextToken().trim();1018n++;1019Certificate cert = null;1020// See if this alias's cert has already been cached1021synchronized (newInfo.aliasMapping) {1022cert = (Certificate)newInfo.aliasMapping.get(alias);10231024if (cert == null && keyStore != null) {10251026try {1027cert = keyStore.getCertificate(alias);1028} catch (KeyStoreException kse) {1029// never happens, because keystore has already been loaded1030// when we call this1031}1032if (cert != null) {1033newInfo.aliasMapping.put(alias, cert);1034newInfo.aliasMapping.put(cert, alias);1035}1036}1037}10381039if (cert != null) {1040if (vcerts == null)1041vcerts = new ArrayList<>();1042vcerts.add(cert);1043}1044}10451046// make sure n == vcerts.size, since we are doing a logical *and*1047if (vcerts != null && n == vcerts.size()) {1048Certificate[] certs = new Certificate[vcerts.size()];1049vcerts.toArray(certs);1050return certs;1051} else {1052return null;1053}1054}10551056/**1057* Refreshes the policy object by re-reading all the policy files.1058*/1059@Override public void refresh() {1060init(url);1061}10621063/**1064* Evaluates the the global policy for the permissions granted to1065* the ProtectionDomain and tests whether the permission is1066* granted.1067*1068* @param domain the ProtectionDomain to test1069* @param permission the Permission object to be tested for implication.1070*1071* @return true if "permission" is a proper subset of a permission1072* granted to this ProtectionDomain.1073*1074* @see java.security.ProtectionDomain1075*/1076@Override1077public boolean implies(ProtectionDomain pd, Permission p) {1078ProtectionDomainCache pdMap = policyInfo.getPdMapping();1079PermissionCollection pc = pdMap.get(pd);10801081if (pc != null) {1082return pc.implies(p);1083}10841085pc = getPermissions(pd);1086if (pc == null) {1087return false;1088}10891090// cache mapping of protection domain to its PermissionCollection1091pdMap.put(pd, pc);1092return pc.implies(p);1093}10941095/**1096* Examines this <code>Policy</code> and returns the permissions granted1097* to the specified <code>ProtectionDomain</code>. This includes1098* the permissions currently associated with the domain as well1099* as the policy permissions granted to the domain's1100* CodeSource, ClassLoader, and Principals.1101*1102* <p> Note that this <code>Policy</code> implementation has1103* special handling for PrivateCredentialPermissions.1104* When this method encounters a <code>PrivateCredentialPermission</code>1105* which specifies "self" as the <code>Principal</code> class and name,1106* it does not add that <code>Permission</code> to the returned1107* <code>PermissionCollection</code>. Instead, it builds1108* a new <code>PrivateCredentialPermission</code>1109* for each <code>Principal</code> associated with the provided1110* <code>Subject</code>. Each new <code>PrivateCredentialPermission</code>1111* contains the same Credential class as specified in the1112* originally granted permission, as well as the Class and name1113* for the respective <code>Principal</code>.1114*1115* <p>1116*1117* @param domain the Permissions granted to this1118* <code>ProtectionDomain</code> are returned.1119*1120* @return the Permissions granted to the provided1121* <code>ProtectionDomain</code>.1122*/1123@Override1124public PermissionCollection getPermissions(ProtectionDomain domain) {1125Permissions perms = new Permissions();11261127if (domain == null)1128return perms;11291130// first get policy perms1131getPermissions(perms, domain);11321133// add static perms1134// - adding static perms after policy perms is necessary1135// to avoid a regression for 43010641136PermissionCollection pc = domain.getPermissions();1137if (pc != null) {1138synchronized (pc) {1139Enumeration<Permission> e = pc.elements();1140while (e.hasMoreElements()) {1141perms.add(e.nextElement());1142}1143}1144}11451146return perms;1147}11481149/**1150* Examines this Policy and creates a PermissionCollection object with1151* the set of permissions for the specified CodeSource.1152*1153* @param CodeSource the codesource associated with the caller.1154* This encapsulates the original location of the code (where the code1155* came from) and the public key(s) of its signer.1156*1157* @return the set of permissions according to the policy.1158*/1159@Override1160public PermissionCollection getPermissions(CodeSource codesource) {1161return getPermissions(new Permissions(), codesource);1162}11631164/**1165* Examines the global policy and returns the provided Permissions1166* object with additional permissions granted to the specified1167* ProtectionDomain.1168*1169* @param perm the Permissions to populate1170* @param pd the ProtectionDomain associated with the caller.1171*1172* @return the set of Permissions according to the policy.1173*/1174private PermissionCollection getPermissions(Permissions perms,1175ProtectionDomain pd ) {1176if (debug != null) {1177debug.println("getPermissions:\n\t" + printPD(pd));1178}11791180final CodeSource cs = pd.getCodeSource();1181if (cs == null)1182return perms;11831184CodeSource canonCodeSource = AccessController.doPrivileged(1185new java.security.PrivilegedAction<CodeSource>(){1186public CodeSource run() {1187return canonicalizeCodebase(cs, true);1188}1189});1190return getPermissions(perms, canonCodeSource, pd.getPrincipals());1191}11921193/**1194* Examines the global policy and returns the provided Permissions1195* object with additional permissions granted to the specified1196* CodeSource.1197*1198* @param permissions the permissions to populate1199* @param codesource the codesource associated with the caller.1200* This encapsulates the original location of the code (where the code1201* came from) and the public key(s) of its signer.1202*1203* @return the set of permissions according to the policy.1204*/1205private PermissionCollection getPermissions(Permissions perms,1206final CodeSource cs) {12071208if (cs == null)1209return perms;12101211CodeSource canonCodeSource = AccessController.doPrivileged(1212new java.security.PrivilegedAction<CodeSource>(){1213public CodeSource run() {1214return canonicalizeCodebase(cs, true);1215}1216});12171218return getPermissions(perms, canonCodeSource, null);1219}12201221private Permissions getPermissions(Permissions perms,1222final CodeSource cs,1223Principal[] principals) {1224PolicyInfo pi = policyInfo;12251226for (PolicyEntry entry : pi.policyEntries) {1227addPermissions(perms, cs, principals, entry);1228}12291230// Go through policyEntries gotten from identity db; sync required1231// because checkForTrustedIdentity (below) might update list1232synchronized (pi.identityPolicyEntries) {1233for (PolicyEntry entry : pi.identityPolicyEntries) {1234addPermissions(perms, cs, principals, entry);1235}1236}12371238// now see if any of the keys are trusted ids.1239if (!ignoreIdentityScope) {1240Certificate certs[] = cs.getCertificates();1241if (certs != null) {1242for (int k=0; k < certs.length; k++) {1243Object idMap = pi.aliasMapping.get(certs[k]);1244if (idMap == null &&1245checkForTrustedIdentity(certs[k], pi)) {1246// checkForTrustedIdentity added it1247// to the policy for us. next time1248// around we'll find it. This time1249// around we need to add it.1250perms.add(SecurityConstants.ALL_PERMISSION);1251}1252}1253}1254}1255return perms;1256}12571258private void addPermissions(Permissions perms,1259final CodeSource cs,1260Principal[] principals,1261final PolicyEntry entry) {12621263if (debug != null) {1264debug.println("evaluate codesources:\n" +1265"\tPolicy CodeSource: " + entry.getCodeSource() + "\n" +1266"\tActive CodeSource: " + cs);1267}12681269// check to see if the CodeSource implies1270Boolean imp = AccessController.doPrivileged1271(new PrivilegedAction<Boolean>() {1272public Boolean run() {1273return new Boolean(entry.getCodeSource().implies(cs));1274}1275});1276if (!imp.booleanValue()) {1277if (debug != null) {1278debug.println("evaluation (codesource) failed");1279}12801281// CodeSource does not imply - return and try next policy entry1282return;1283}12841285// check to see if the Principals imply12861287List<PolicyParser.PrincipalEntry> entryPs = entry.getPrincipals();1288if (debug != null) {1289List<PolicyParser.PrincipalEntry> accPs = new ArrayList<>();1290if (principals != null) {1291for (int i = 0; i < principals.length; i++) {1292accPs.add(new PolicyParser.PrincipalEntry1293(principals[i].getClass().getName(),1294principals[i].getName()));1295}1296}1297debug.println("evaluate principals:\n" +1298"\tPolicy Principals: " + entryPs + "\n" +1299"\tActive Principals: " + accPs);1300}13011302if (entryPs == null || entryPs.isEmpty()) {13031304// policy entry has no principals -1305// add perms regardless of principals in current ACC13061307addPerms(perms, principals, entry);1308if (debug != null) {1309debug.println("evaluation (codesource/principals) passed");1310}1311return;13121313} else if (principals == null || principals.length == 0) {13141315// current thread has no principals but this policy entry1316// has principals - perms are not added13171318if (debug != null) {1319debug.println("evaluation (principals) failed");1320}1321return;1322}13231324// current thread has principals and this policy entry1325// has principals. see if policy entry principals match1326// principals in current ACC13271328for (PolicyParser.PrincipalEntry pppe : entryPs) {13291330// Check for wildcards1331if (pppe.isWildcardClass()) {1332// a wildcard class matches all principals in current ACC1333continue;1334}13351336if (pppe.isWildcardName()) {1337// a wildcard name matches any principal with the same class1338if (wildcardPrincipalNameImplies(pppe.principalClass,1339principals)) {1340continue;1341}1342if (debug != null) {1343debug.println("evaluation (principal name wildcard) failed");1344}1345// policy entry principal not in current ACC -1346// immediately return and go to next policy entry1347return;1348}13491350Set<Principal> pSet = new HashSet<>(Arrays.asList(principals));1351Subject subject = new Subject(true, pSet,1352Collections.EMPTY_SET,1353Collections.EMPTY_SET);1354try {1355ClassLoader cl = Thread.currentThread().getContextClassLoader();1356Class<?> pClass = Class.forName(pppe.principalClass, false, cl);1357if (!Principal.class.isAssignableFrom(pClass)) {1358// not the right subtype1359throw new ClassCastException(pppe.principalClass +1360" is not a Principal");1361}13621363Constructor<?> c = pClass.getConstructor(PARAMS1);1364Principal p = (Principal)c.newInstance(new Object[] {1365pppe.principalName });13661367if (debug != null) {1368debug.println("found Principal " + p.getClass().getName());1369}13701371// check if the Principal implies the current1372// thread's principals1373if (!p.implies(subject)) {1374if (debug != null) {1375debug.println("evaluation (principal implies) failed");1376}13771378// policy principal does not imply the current Subject -1379// immediately return and go to next policy entry1380return;1381}1382} catch (Exception e) {1383// fall back to default principal comparison.1384// see if policy entry principal is in current ACC13851386if (debug != null) {1387e.printStackTrace();1388}13891390if (!pppe.implies(subject)) {1391if (debug != null) {1392debug.println("evaluation (default principal implies) failed");1393}13941395// policy entry principal not in current ACC -1396// immediately return and go to next policy entry1397return;1398}1399}14001401// either the principal information matched,1402// or the Principal.implies succeeded.1403// continue loop and test the next policy principal1404}14051406// all policy entry principals were found in the current ACC -1407// grant the policy permissions14081409if (debug != null) {1410debug.println("evaluation (codesource/principals) passed");1411}1412addPerms(perms, principals, entry);1413}14141415/**1416* Returns true if the array of principals contains at least one1417* principal of the specified class.1418*/1419private static boolean wildcardPrincipalNameImplies(String principalClass,1420Principal[] principals)1421{1422for (Principal p : principals) {1423if (principalClass.equals(p.getClass().getName())) {1424return true;1425}1426}1427return false;1428}14291430private void addPerms(Permissions perms,1431Principal[] accPs,1432PolicyEntry entry) {1433for (int i = 0; i < entry.permissions.size(); i++) {1434Permission p = entry.permissions.get(i);1435if (debug != null) {1436debug.println(" granting " + p);1437}14381439if (p instanceof SelfPermission) {1440// handle "SELF" permissions1441expandSelf((SelfPermission)p,1442entry.getPrincipals(),1443accPs,1444perms);1445} else {1446perms.add(p);1447}1448}1449}14501451/**1452* <p>1453*1454* @param sp the SelfPermission that needs to be expanded <p>1455*1456* @param entryPs list of principals for the Policy entry.1457*1458* @param pdp Principal array from the current ProtectionDomain.1459*1460* @param perms the PermissionCollection where the individual1461* Permissions will be added after expansion.1462*/14631464private void expandSelf(SelfPermission sp,1465List<PolicyParser.PrincipalEntry> entryPs,1466Principal[] pdp,1467Permissions perms) {14681469if (entryPs == null || entryPs.isEmpty()) {1470// No principals in the grant to substitute1471if (debug != null) {1472debug.println("Ignoring permission "1473+ sp.getSelfType()1474+ " with target name ("1475+ sp.getSelfName() + "). "1476+ "No Principal(s) specified "1477+ "in the grant clause. "1478+ "SELF-based target names are "1479+ "only valid in the context "1480+ "of a Principal-based grant entry."1481);1482}1483return;1484}1485int startIndex = 0;1486int v;1487StringBuilder sb = new StringBuilder();1488while ((v = sp.getSelfName().indexOf(SELF, startIndex)) != -1) {14891490// add non-SELF string1491sb.append(sp.getSelfName().substring(startIndex, v));14921493// expand SELF1494Iterator<PolicyParser.PrincipalEntry> pli = entryPs.iterator();1495while (pli.hasNext()) {1496PolicyParser.PrincipalEntry pppe = pli.next();1497String[][] principalInfo = getPrincipalInfo(pppe,pdp);1498for (int i = 0; i < principalInfo.length; i++) {1499if (i != 0) {1500sb.append(", ");1501}1502sb.append(principalInfo[i][0] + " " +1503"\"" + principalInfo[i][1] + "\"");1504}1505if (pli.hasNext()) {1506sb.append(", ");1507}1508}1509startIndex = v + SELF.length();1510}1511// add remaining string (might be the entire string)1512sb.append(sp.getSelfName().substring(startIndex));15131514if (debug != null) {1515debug.println(" expanded:\n\t" + sp.getSelfName()1516+ "\n into:\n\t" + sb.toString());1517}1518try {1519// first try to instantiate the permission1520perms.add(getInstance(sp.getSelfType(),1521sb.toString(),1522sp.getSelfActions()));1523} catch (ClassNotFoundException cnfe) {1524// ok, the permission is not in the bootclasspath.1525// before we add an UnresolvedPermission, check to see1526// whether this perm already belongs to the collection.1527// if so, use that perm's ClassLoader to create a new1528// one.1529Class<?> pc = null;1530synchronized (perms) {1531Enumeration<Permission> e = perms.elements();1532while (e.hasMoreElements()) {1533Permission pElement = e.nextElement();1534if (pElement.getClass().getName().equals(sp.getSelfType())) {1535pc = pElement.getClass();1536break;1537}1538}1539}1540if (pc == null) {1541// create an UnresolvedPermission1542perms.add(new UnresolvedPermission(sp.getSelfType(),1543sb.toString(),1544sp.getSelfActions(),1545sp.getCerts()));1546} else {1547try {1548// we found an instantiated permission.1549// use its class loader to instantiate a new permission.1550Constructor<?> c;1551// name parameter can not be null1552if (sp.getSelfActions() == null) {1553try {1554c = pc.getConstructor(PARAMS1);1555perms.add((Permission)c.newInstance1556(new Object[] {sb.toString()}));1557} catch (NoSuchMethodException ne) {1558c = pc.getConstructor(PARAMS2);1559perms.add((Permission)c.newInstance1560(new Object[] {sb.toString(),1561sp.getSelfActions() }));1562}1563} else {1564c = pc.getConstructor(PARAMS2);1565perms.add((Permission)c.newInstance1566(new Object[] {sb.toString(),1567sp.getSelfActions()}));1568}1569} catch (Exception nme) {1570if (debug != null) {1571debug.println("self entry expansion " +1572" instantiation failed: "1573+ nme.toString());1574}1575}1576}1577} catch (Exception e) {1578if (debug != null) {1579debug.println(e.toString());1580}1581}1582}15831584/**1585* return the principal class/name pair in the 2D array.1586* array[x][y]: x corresponds to the array length.1587* if (y == 0), it's the principal class.1588* if (y == 1), it's the principal name.1589*/1590private String[][] getPrincipalInfo1591(PolicyParser.PrincipalEntry pe, Principal[] pdp) {15921593// there are 3 possibilities:1594// 1) the entry's Principal class and name are not wildcarded1595// 2) the entry's Principal name is wildcarded only1596// 3) the entry's Principal class and name are wildcarded15971598if (!pe.isWildcardClass() && !pe.isWildcardName()) {15991600// build an info array for the principal1601// from the Policy entry1602String[][] info = new String[1][2];1603info[0][0] = pe.principalClass;1604info[0][1] = pe.principalName;1605return info;16061607} else if (!pe.isWildcardClass() && pe.isWildcardName()) {16081609// build an info array for every principal1610// in the current domain which has a principal class1611// that is equal to policy entry principal class name1612List<Principal> plist = new ArrayList<>();1613for (int i = 0; i < pdp.length; i++) {1614if (pe.principalClass.equals(pdp[i].getClass().getName()))1615plist.add(pdp[i]);1616}1617String[][] info = new String[plist.size()][2];1618int i = 0;1619for (Principal p : plist) {1620info[i][0] = p.getClass().getName();1621info[i][1] = p.getName();1622i++;1623}1624return info;16251626} else {16271628// build an info array for every1629// one of the current Domain's principals16301631String[][] info = new String[pdp.length][2];16321633for (int i = 0; i < pdp.length; i++) {1634info[i][0] = pdp[i].getClass().getName();1635info[i][1] = pdp[i].getName();1636}1637return info;1638}1639}16401641/*1642* Returns the signer certificates from the list of certificates1643* associated with the given code source.1644*1645* The signer certificates are those certificates that were used1646* to verifysigned code originating from the codesource location.1647*1648* This method assumes that in the given code source, each signer1649* certificate is followed by its supporting certificate chain1650* (which may be empty), and that the signer certificate and its1651* supporting certificate chain are ordered bottom-to-top1652* (i.e., with the signer certificate first and the (root) certificate1653* authority last).1654*/1655protected Certificate[] getSignerCertificates(CodeSource cs) {1656Certificate[] certs = null;1657if ((certs = cs.getCertificates()) == null)1658return null;1659for (int i=0; i<certs.length; i++) {1660if (!(certs[i] instanceof X509Certificate))1661return cs.getCertificates();1662}16631664// Do we have to do anything?1665int i = 0;1666int count = 0;1667while (i < certs.length) {1668count++;1669while (((i+1) < certs.length)1670&& ((X509Certificate)certs[i]).getIssuerDN().equals(1671((X509Certificate)certs[i+1]).getSubjectDN())) {1672i++;1673}1674i++;1675}1676if (count == certs.length)1677// Done1678return certs;16791680List<Certificate> userCertList = new ArrayList<>();1681i = 0;1682while (i < certs.length) {1683userCertList.add(certs[i]);1684while (((i+1) < certs.length)1685&& ((X509Certificate)certs[i]).getIssuerDN().equals(1686((X509Certificate)certs[i+1]).getSubjectDN())) {1687i++;1688}1689i++;1690}1691Certificate[] userCerts = new Certificate[userCertList.size()];1692userCertList.toArray(userCerts);1693return userCerts;1694}16951696private CodeSource canonicalizeCodebase(CodeSource cs,1697boolean extractSignerCerts) {16981699String path = null;17001701CodeSource canonCs = cs;1702URL u = cs.getLocation();1703if (u != null) {1704if (u.getProtocol().equals("jar")) {1705// unwrap url embedded inside jar url1706String spec = u.getFile();1707int separator = spec.indexOf("!/");1708if (separator != -1) {1709try {1710u = new URL(spec.substring(0, separator));1711} catch (MalformedURLException e) {1712// Fail silently. In this case, url stays what1713// it was above1714}1715}1716}1717if (u.getProtocol().equals("file")) {1718boolean isLocalFile = false;1719String host = u.getHost();1720isLocalFile = (host == null || host.equals("") ||1721host.equals("~") || host.equalsIgnoreCase("localhost"));17221723if (isLocalFile) {1724path = u.getFile().replace('/', File.separatorChar);1725path = ParseUtil.decode(path);1726}1727}1728}17291730if (path != null) {1731try {1732URL csUrl = null;1733path = canonPath(path);1734csUrl = ParseUtil.fileToEncodedURL(new File(path));17351736if (extractSignerCerts) {1737canonCs = new CodeSource(csUrl,1738getSignerCertificates(cs));1739} else {1740canonCs = new CodeSource(csUrl,1741cs.getCertificates());1742}1743} catch (IOException ioe) {1744// leave codesource as it is, unless we have to extract its1745// signer certificates1746if (extractSignerCerts) {1747canonCs = new CodeSource(cs.getLocation(),1748getSignerCertificates(cs));1749}1750}1751} else {1752if (extractSignerCerts) {1753canonCs = new CodeSource(cs.getLocation(),1754getSignerCertificates(cs));1755}1756}1757return canonCs;1758}17591760// Wrapper to return a canonical path that avoids calling getCanonicalPath()1761// with paths that are intended to match all entries in the directory1762private static String canonPath(String path) throws IOException {1763if (path.endsWith("*")) {1764path = path.substring(0, path.length()-1) + "-";1765path = new File(path).getCanonicalPath();1766return path.substring(0, path.length()-1) + "*";1767} else {1768return new File(path).getCanonicalPath();1769}1770}17711772private String printPD(ProtectionDomain pd) {1773Principal[] principals = pd.getPrincipals();1774String pals = "<no principals>";1775if (principals != null && principals.length > 0) {1776StringBuilder palBuf = new StringBuilder("(principals ");1777for (int i = 0; i < principals.length; i++) {1778palBuf.append(principals[i].getClass().getName() +1779" \"" + principals[i].getName() +1780"\"");1781if (i < principals.length-1)1782palBuf.append(", ");1783else1784palBuf.append(")");1785}1786pals = palBuf.toString();1787}1788return "PD CodeSource: "1789+ pd.getCodeSource()1790+"\n\t" + "PD ClassLoader: "1791+ pd.getClassLoader()1792+"\n\t" + "PD Principals: "1793+ pals;1794}17951796/**1797* return true if no replacement was performed,1798* or if replacement succeeded.1799*/1800private boolean replacePrincipals(1801List<PolicyParser.PrincipalEntry> principals, KeyStore keystore) {18021803if (principals == null || principals.isEmpty() || keystore == null)1804return true;18051806for (PolicyParser.PrincipalEntry pppe : principals) {1807if (pppe.isReplaceName()) {18081809// perform replacement1810// (only X509 replacement is possible now)1811String name;1812if ((name = getDN(pppe.principalName, keystore)) == null) {1813return false;1814}18151816if (debug != null) {1817debug.println(" Replacing \"" +1818pppe.principalName +1819"\" with " +1820X500PRINCIPAL + "/\"" +1821name +1822"\"");1823}18241825pppe.principalClass = X500PRINCIPAL;1826pppe.principalName = name;1827}1828}1829// return true if no replacement was performed,1830// or if replacement succeeded1831return true;1832}18331834private void expandPermissionName(PolicyParser.PermissionEntry pe,1835KeyStore keystore) throws Exception {1836// short cut the common case1837if (pe.name == null || pe.name.indexOf("${{", 0) == -1) {1838return;1839}18401841int startIndex = 0;1842int b, e;1843StringBuilder sb = new StringBuilder();1844while ((b = pe.name.indexOf("${{", startIndex)) != -1) {1845e = pe.name.indexOf("}}", b);1846if (e < 1) {1847break;1848}1849sb.append(pe.name.substring(startIndex, b));18501851// get the value in ${{...}}1852String value = pe.name.substring(b+3, e);18531854// parse up to the first ':'1855int colonIndex;1856String prefix = value;1857String suffix;1858if ((colonIndex = value.indexOf(":")) != -1) {1859prefix = value.substring(0, colonIndex);1860}18611862// handle different prefix possibilities1863if (prefix.equalsIgnoreCase("self")) {1864// do nothing - handled later1865sb.append(pe.name.substring(b, e+2));1866startIndex = e+2;1867continue;1868} else if (prefix.equalsIgnoreCase("alias")) {1869// get the suffix and perform keystore alias replacement1870if (colonIndex == -1) {1871MessageFormat form = new MessageFormat1872(ResourcesMgr.getString1873("alias.name.not.provided.pe.name."));1874Object[] source = {pe.name};1875throw new Exception(form.format(source));1876}1877suffix = value.substring(colonIndex+1);1878if ((suffix = getDN(suffix, keystore)) == null) {1879MessageFormat form = new MessageFormat1880(ResourcesMgr.getString1881("unable.to.perform.substitution.on.alias.suffix"));1882Object[] source = {value.substring(colonIndex+1)};1883throw new Exception(form.format(source));1884}18851886sb.append(X500PRINCIPAL + " \"" + suffix + "\"");1887startIndex = e+2;1888} else {1889MessageFormat form = new MessageFormat1890(ResourcesMgr.getString1891("substitution.value.prefix.unsupported"));1892Object[] source = {prefix};1893throw new Exception(form.format(source));1894}1895}18961897// copy the rest of the value1898sb.append(pe.name.substring(startIndex));18991900// replace the name with expanded value1901if (debug != null) {1902debug.println(" Permission name expanded from:\n\t" +1903pe.name + "\nto\n\t" + sb.toString());1904}1905pe.name = sb.toString();1906}19071908private String getDN(String alias, KeyStore keystore) {1909Certificate cert = null;1910try {1911cert = keystore.getCertificate(alias);1912} catch (Exception e) {1913if (debug != null) {1914debug.println(" Error retrieving certificate for '" +1915alias +1916"': " +1917e.toString());1918}1919return null;1920}19211922if (cert == null || !(cert instanceof X509Certificate)) {1923if (debug != null) {1924debug.println(" -- No certificate for '" +1925alias +1926"' - ignoring entry");1927}1928return null;1929} else {1930X509Certificate x509Cert = (X509Certificate)cert;19311932// 4702543: X500 names with an EmailAddress1933// were encoded incorrectly. create new1934// X500Principal name with correct encoding19351936X500Principal p = new X500Principal1937(x509Cert.getSubjectX500Principal().toString());1938return p.getName();1939}1940}19411942/**1943* Checks public key. If it is marked as trusted in1944* the identity database, add it to the policy1945* with the AllPermission.1946*/1947private boolean checkForTrustedIdentity(final Certificate cert,1948PolicyInfo myInfo)1949{1950return false;1951}19521953/**1954* Each entry in the policy configuration file is represented by a1955* PolicyEntry object. <p>1956*1957* A PolicyEntry is a (CodeSource,Permission) pair. The1958* CodeSource contains the (URL, PublicKey) that together identify1959* where the Java bytecodes come from and who (if anyone) signed1960* them. The URL could refer to localhost. The URL could also be1961* null, meaning that this policy entry is given to all comers, as1962* long as they match the signer field. The signer could be null,1963* meaning the code is not signed. <p>1964*1965* The Permission contains the (Type, Name, Action) triplet. <p>1966*1967* For now, the Policy object retrieves the public key from the1968* X.509 certificate on disk that corresponds to the signedBy1969* alias specified in the Policy config file. For reasons of1970* efficiency, the Policy object keeps a hashtable of certs already1971* read in. This could be replaced by a secure internal key1972* store.1973*1974* <p>1975* For example, the entry1976* <pre>1977* permission java.io.File "/tmp", "read,write",1978* signedBy "Duke";1979* </pre>1980* is represented internally1981* <pre>1982*1983* FilePermission f = new FilePermission("/tmp", "read,write");1984* PublicKey p = publickeys.get("Duke");1985* URL u = InetAddress.getLocalHost();1986* CodeBase c = new CodeBase( p, u );1987* pe = new PolicyEntry(f, c);1988* </pre>1989*1990* @author Marianne Mueller1991* @author Roland Schemers1992* @see java.security.CodeSource1993* @see java.security.Policy1994* @see java.security.Permissions1995* @see java.security.ProtectionDomain1996*/1997private static class PolicyEntry {19981999private final CodeSource codesource;2000final List<Permission> permissions;2001private final List<PolicyParser.PrincipalEntry> principals;20022003/**2004* Given a Permission and a CodeSource, create a policy entry.2005*2006* XXX Decide if/how to add validity fields and "purpose" fields to2007* XXX policy entries2008*2009* @param cs the CodeSource, which encapsulates the URL and the2010* public key2011* attributes from the policy config file. Validity checks2012* are performed on the public key before PolicyEntry is2013* called.2014*2015*/2016PolicyEntry(CodeSource cs, List<PolicyParser.PrincipalEntry> principals)2017{2018this.codesource = cs;2019this.permissions = new ArrayList<Permission>();2020this.principals = principals; // can be null2021}20222023PolicyEntry(CodeSource cs)2024{2025this(cs, null);2026}20272028List<PolicyParser.PrincipalEntry> getPrincipals() {2029return principals; // can be null2030}20312032/**2033* add a Permission object to this entry.2034* No need to sync add op because perms are added to entry only2035* while entry is being initialized2036*/2037void add(Permission p) {2038permissions.add(p);2039}20402041/**2042* Return the CodeSource for this policy entry2043*/2044CodeSource getCodeSource() {2045return codesource;2046}20472048@Override public String toString(){2049StringBuilder sb = new StringBuilder();2050sb.append(ResourcesMgr.getString("LPARAM"));2051sb.append(getCodeSource());2052sb.append("\n");2053for (int j = 0; j < permissions.size(); j++) {2054Permission p = permissions.get(j);2055sb.append(ResourcesMgr.getString("SPACE"));2056sb.append(ResourcesMgr.getString("SPACE"));2057sb.append(p);2058sb.append(ResourcesMgr.getString("NEWLINE"));2059}2060sb.append(ResourcesMgr.getString("RPARAM"));2061sb.append(ResourcesMgr.getString("NEWLINE"));2062return sb.toString();2063}2064}20652066private static class SelfPermission extends Permission {20672068private static final long serialVersionUID = -8315562579967246806L;20692070/**2071* The class name of the Permission class that will be2072* created when this self permission is expanded .2073*2074* @serial2075*/2076private String type;20772078/**2079* The permission name.2080*2081* @serial2082*/2083private String name;20842085/**2086* The actions of the permission.2087*2088* @serial2089*/2090private String actions;20912092/**2093* The certs of the permission.2094*2095* @serial2096*/2097private Certificate certs[];20982099/**2100* Creates a new SelfPermission containing the permission2101* information needed later to expand the self2102* @param type the class name of the Permission class that will be2103* created when this permission is expanded and if necessary resolved.2104* @param name the name of the permission.2105* @param actions the actions of the permission.2106* @param certs the certificates the permission's class was signed with.2107* This is a list of certificate chains, where each chain is composed of2108* a signer certificate and optionally its supporting certificate chain.2109* Each chain is ordered bottom-to-top (i.e., with the signer2110* certificate first and the (root) certificate authority last).2111*/2112public SelfPermission(String type, String name, String actions,2113Certificate certs[])2114{2115super(type);2116if (type == null) {2117throw new NullPointerException2118(ResourcesMgr.getString("type.can.t.be.null"));2119}2120this.type = type;2121this.name = name;2122this.actions = actions;2123if (certs != null) {2124// Extract the signer certs from the list of certificates.2125for (int i=0; i<certs.length; i++) {2126if (!(certs[i] instanceof X509Certificate)) {2127// there is no concept of signer certs, so we store the2128// entire cert array2129this.certs = certs.clone();2130break;2131}2132}21332134if (this.certs == null) {2135// Go through the list of certs and see if all the certs are2136// signer certs.2137int i = 0;2138int count = 0;2139while (i < certs.length) {2140count++;2141while (((i+1) < certs.length) &&2142((X509Certificate)certs[i]).getIssuerDN().equals(2143((X509Certificate)certs[i+1]).getSubjectDN())) {2144i++;2145}2146i++;2147}2148if (count == certs.length) {2149// All the certs are signer certs, so we store the2150// entire array2151this.certs = certs.clone();2152}21532154if (this.certs == null) {2155// extract the signer certs2156List<Certificate> signerCerts = new ArrayList<>();2157i = 0;2158while (i < certs.length) {2159signerCerts.add(certs[i]);2160while (((i+1) < certs.length) &&2161((X509Certificate)certs[i]).getIssuerDN().equals(2162((X509Certificate)certs[i+1]).getSubjectDN())) {2163i++;2164}2165i++;2166}2167this.certs = new Certificate[signerCerts.size()];2168signerCerts.toArray(this.certs);2169}2170}2171}2172}21732174/**2175* This method always returns false for SelfPermission permissions.2176* That is, an SelfPermission never considered to2177* imply another permission.2178*2179* @param p the permission to check against.2180*2181* @return false.2182*/2183@Override public boolean implies(Permission p) {2184return false;2185}21862187/**2188* Checks two SelfPermission objects for equality.2189*2190* Checks that <i>obj</i> is an SelfPermission, and has2191* the same type (class) name, permission name, actions, and2192* certificates as this object.2193*2194* @param obj the object we are testing for equality with this object.2195*2196* @return true if obj is an SelfPermission, and has the same2197* type (class) name, permission name, actions, and2198* certificates as this object.2199*/2200@Override public boolean equals(Object obj) {2201if (obj == this)2202return true;22032204if (! (obj instanceof SelfPermission))2205return false;2206SelfPermission that = (SelfPermission) obj;22072208if (!(this.type.equals(that.type) &&2209this.name.equals(that.name) &&2210this.actions.equals(that.actions)))2211return false;22122213if (this.certs.length != that.certs.length)2214return false;22152216int i,j;2217boolean match;22182219for (i = 0; i < this.certs.length; i++) {2220match = false;2221for (j = 0; j < that.certs.length; j++) {2222if (this.certs[i].equals(that.certs[j])) {2223match = true;2224break;2225}2226}2227if (!match) return false;2228}22292230for (i = 0; i < that.certs.length; i++) {2231match = false;2232for (j = 0; j < this.certs.length; j++) {2233if (that.certs[i].equals(this.certs[j])) {2234match = true;2235break;2236}2237}2238if (!match) return false;2239}2240return true;2241}22422243/**2244* Returns the hash code value for this object.2245*2246* @return a hash code value for this object.2247*/2248@Override public int hashCode() {2249int hash = type.hashCode();2250if (name != null)2251hash ^= name.hashCode();2252if (actions != null)2253hash ^= actions.hashCode();2254return hash;2255}22562257/**2258* Returns the canonical string representation of the actions,2259* which currently is the empty string "", since there are no actions2260* for an SelfPermission. That is, the actions for the2261* permission that will be created when this SelfPermission2262* is resolved may be non-null, but an SelfPermission2263* itself is never considered to have any actions.2264*2265* @return the empty string "".2266*/2267@Override public String getActions() {2268return "";2269}22702271public String getSelfType() {2272return type;2273}22742275public String getSelfName() {2276return name;2277}22782279public String getSelfActions() {2280return actions;2281}22822283public Certificate[] getCerts() {2284return certs;2285}22862287/**2288* Returns a string describing this SelfPermission. The convention2289* is to specify the class name, the permission name, and the actions,2290* in the following format: '(unresolved "ClassName" "name" "actions")'.2291*2292* @return information about this SelfPermission.2293*/2294@Override public String toString() {2295return "(SelfPermission " + type + " " + name + " " + actions + ")";2296}2297}22982299/**2300* holds policy information that we need to synch on2301*/2302private static class PolicyInfo {2303private static final boolean verbose = false;23042305// Stores grant entries in the policy2306final List<PolicyEntry> policyEntries;23072308// Stores grant entries gotten from identity database2309// Use separate lists to avoid sync on policyEntries2310final List<PolicyEntry> identityPolicyEntries;23112312// Maps aliases to certs2313final Map<Object, Object> aliasMapping;23142315// Maps ProtectionDomain to PermissionCollection2316private final ProtectionDomainCache[] pdMapping;2317private java.util.Random random;23182319PolicyInfo(int numCaches) {2320policyEntries = new ArrayList<>();2321identityPolicyEntries =2322Collections.synchronizedList(new ArrayList<PolicyEntry>(2));2323aliasMapping = Collections.synchronizedMap(new HashMap<>(11));23242325pdMapping = new ProtectionDomainCache[numCaches];2326JavaSecurityProtectionDomainAccess jspda2327= SharedSecrets.getJavaSecurityProtectionDomainAccess();2328for (int i = 0; i < numCaches; i++) {2329pdMapping[i] = jspda.getProtectionDomainCache();2330}2331if (numCaches > 1) {2332random = new java.util.Random();2333}2334}2335ProtectionDomainCache getPdMapping() {2336if (pdMapping.length == 1) {2337return pdMapping[0];2338} else {2339int i = java.lang.Math.abs(random.nextInt() % pdMapping.length);2340return pdMapping[i];2341}2342}2343}2344}234523462347