Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/provider/AuthPolicyFile.java
38830 views
/*1* Copyright (c) 1999, 2013, 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.URL;30import java.util.*;3132import java.security.AccessController;33import java.security.CodeSource;34import java.security.KeyStore;35import java.security.KeyStoreException;36import java.security.Permission;37import java.security.Permissions;38import java.security.PermissionCollection;39import java.security.Principal;40import java.security.PrivilegedAction;41import java.security.UnresolvedPermission;42import java.security.Security;43import java.security.cert.Certificate;44import java.security.cert.X509Certificate;4546import javax.security.auth.Subject;47import javax.security.auth.PrivateCredentialPermission;4849import sun.security.provider.PolicyParser.GrantEntry;50import sun.security.provider.PolicyParser.PermissionEntry;51import sun.security.provider.PolicyParser.PrincipalEntry;52import sun.security.util.Debug;53import sun.security.util.PolicyUtil;54import sun.security.util.PropertyExpander;5556/**57* See {@code com.sun.security.auth.PolicyFile} for the class description.58* This class is necessary in order to support a default59* {@code javax.security.auth.Policy} implementation on the compact1 and60* compact2 profiles.61*62* @deprecated As of JDK 1.4, replaced by63* {@code sun.security.provider.PolicyFile}.64* This class is entirely deprecated.65*/66@Deprecated67public class AuthPolicyFile extends javax.security.auth.Policy {6869static final ResourceBundle rb =70AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {71@Override public ResourceBundle run() {72return (ResourceBundle.getBundle73("sun.security.util.AuthResources"));74}75});7677private static final Debug debug = Debug.getInstance("policy",78"\t[Auth Policy]");7980private static final String AUTH_POLICY = "java.security.auth.policy";81private static final String SECURITY_MANAGER = "java.security.manager";82private static final String AUTH_POLICY_URL = "auth.policy.url.";8384private Vector<PolicyEntry> policyEntries;85private Hashtable<Object, Object> aliasMapping;8687private boolean initialized = false;8889private boolean expandProperties = true;90private boolean ignoreIdentityScope = true;9192// for use with the reflection API93private static final Class<?>[] PARAMS = { String.class, String.class};9495/**96* Initializes the Policy object and reads the default policy97* configuration file(s) into the Policy object.98*/99public AuthPolicyFile() {100// initialize Policy if either the AUTH_POLICY or101// SECURITY_MANAGER properties are set102String prop = System.getProperty(AUTH_POLICY);103104if (prop == null) {105prop = System.getProperty(SECURITY_MANAGER);106}107if (prop != null) {108init();109}110}111112private synchronized void init() {113if (initialized) {114return;115}116117policyEntries = new Vector<PolicyEntry>();118aliasMapping = new Hashtable<Object, Object>(11);119120initPolicyFile();121initialized = true;122}123124@Override125public synchronized void refresh() {126127java.lang.SecurityManager sm = System.getSecurityManager();128if (sm != null) {129sm.checkPermission(new javax.security.auth.AuthPermission130("refreshPolicy"));131}132133// XXX134//135// 1) if code instantiates PolicyFile directly, then it will need136// all the permissions required for the PolicyFile initialization137// 2) if code calls Policy.getPolicy, then it simply needs138// AuthPermission(getPolicy), and the javax.security.auth.Policy139// implementation instantiates PolicyFile in a doPrivileged block140// 3) if after instantiating a Policy (either via #1 or #2),141// code calls refresh, it simply needs142// AuthPermission(refreshPolicy). then PolicyFile wraps143// the refresh in a doPrivileged block.144initialized = false;145AccessController.doPrivileged(new PrivilegedAction<Void>() {146@Override public Void run() {147init();148return null;149}150});151}152153private KeyStore initKeyStore(URL policyUrl, String keyStoreName,154String keyStoreType) {155if (keyStoreName != null) {156try {157/*158* location of keystore is specified as absolute URL in policy159* file, or is relative to URL of policy file160*/161URL keyStoreUrl = null;162try {163keyStoreUrl = new URL(keyStoreName);164// absolute URL165} catch (java.net.MalformedURLException e) {166// relative URL167keyStoreUrl = new URL(policyUrl, keyStoreName);168}169170if (debug != null) {171debug.println("reading keystore"+keyStoreUrl);172}173174InputStream inStream = new BufferedInputStream(175PolicyUtil.getInputStream(keyStoreUrl));176177KeyStore ks;178if (keyStoreType != null)179ks = KeyStore.getInstance(keyStoreType);180else181ks = KeyStore.getInstance(KeyStore.getDefaultType());182ks.load(inStream, null);183inStream.close();184return ks;185} catch (Exception e) {186// ignore, treat it like we have no keystore187if (debug != null) {188debug.println("Debug info only. No keystore.");189e.printStackTrace();190}191return null;192}193}194return null;195}196197private void initPolicyFile() {198199String prop = Security.getProperty("policy.expandProperties");200if (prop != null) {201expandProperties = prop.equalsIgnoreCase("true");202}203204String iscp = Security.getProperty("policy.ignoreIdentityScope");205if (iscp != null) {206ignoreIdentityScope = iscp.equalsIgnoreCase("true");207}208209String allowSys = Security.getProperty("policy.allowSystemProperty");210if (allowSys != null && allowSys.equalsIgnoreCase("true")) {211String extra_policy = System.getProperty(AUTH_POLICY);212if (extra_policy != null) {213boolean overrideAll = false;214if (extra_policy.startsWith("=")) {215overrideAll = true;216extra_policy = extra_policy.substring(1);217}218try {219extra_policy = PropertyExpander.expand(extra_policy);220URL policyURL;221File policyFile = new File(extra_policy);222if (policyFile.exists()) {223policyURL =224new URL("file:" + policyFile.getCanonicalPath());225} else {226policyURL = new URL(extra_policy);227}228if (debug != null) {229debug.println("reading " + policyURL);230}231init(policyURL);232} catch (Exception e) {233// ignore.234if (debug != null) {235debug.println("caught exception: " + e);236}237238}239if (overrideAll) {240if (debug != null) {241debug.println("overriding other policies!");242}243return;244}245}246}247248int n = 1;249boolean loaded_one = false;250String policy_url;251252while ((policy_url = Security.getProperty(AUTH_POLICY_URL+n)) != null) {253try {254policy_url = PropertyExpander.expand(policy_url).replace255(File.separatorChar, '/');256if (debug != null) {257debug.println("reading " + policy_url);258}259init(new URL(policy_url));260loaded_one = true;261} catch (Exception e) {262if (debug != null) {263debug.println("Debug info only. Error reading policy " + e);264e.printStackTrace();265}266// ignore that policy267}268n++;269}270271if (loaded_one == false) {272// do not load a static policy273}274}275276/**277* Checks public key. If it is marked as trusted in278* the identity database, add it to the policy279* with the AllPermission.280*/281private boolean checkForTrustedIdentity(final Certificate cert) {282return false;283}284285/**286* Reads a policy configuration into the Policy object using a287* Reader object.288*289* @param policyFile the policy Reader object.290*/291private void init(URL policy) {292PolicyParser pp = new PolicyParser(expandProperties);293try (InputStreamReader isr294= new InputStreamReader(PolicyUtil.getInputStream(policy))) {295pp.read(isr);296KeyStore keyStore = initKeyStore(policy, pp.getKeyStoreUrl(),297pp.getKeyStoreType());298Enumeration<GrantEntry> enum_ = pp.grantElements();299while (enum_.hasMoreElements()) {300GrantEntry ge = enum_.nextElement();301addGrantEntry(ge, keyStore);302}303} catch (PolicyParser.ParsingException pe) {304System.err.println(AUTH_POLICY +305rb.getString(".error.parsing.") + policy);306System.err.println(AUTH_POLICY + rb.getString("COLON") +307pe.getMessage());308if (debug != null) {309pe.printStackTrace();310}311} catch (Exception e) {312if (debug != null) {313debug.println("error parsing " + policy);314debug.println(e.toString());315e.printStackTrace();316}317}318}319320/**321* Given a PermissionEntry, create a codeSource.322*323* @return null if signedBy alias is not recognized324*/325CodeSource getCodeSource(GrantEntry ge, KeyStore keyStore)326throws java.net.MalformedURLException327{328Certificate[] certs = null;329if (ge.signedBy != null) {330certs = getCertificates(keyStore, ge.signedBy);331if (certs == null) {332// we don't have a key for this alias,333// just return334if (debug != null) {335debug.println(" no certs for alias " +336ge.signedBy + ", ignoring.");337}338return null;339}340}341342URL location;343if (ge.codeBase != null) {344location = new URL(ge.codeBase);345} else {346location = null;347}348349if (ge.principals == null || ge.principals.size() == 0) {350return (canonicalizeCodebase351(new CodeSource(location, certs),352false));353} else {354return (canonicalizeCodebase355(new SubjectCodeSource(null, ge.principals, location, certs),356false));357}358}359360/**361* Add one policy entry to the vector.362*/363private void addGrantEntry(GrantEntry ge, KeyStore keyStore) {364365if (debug != null) {366debug.println("Adding policy entry: ");367debug.println(" signedBy " + ge.signedBy);368debug.println(" codeBase " + ge.codeBase);369if (ge.principals != null) {370for (PrincipalEntry pppe : ge.principals) {371debug.println(" " + pppe.getPrincipalClass() +372" " + pppe.getPrincipalName());373}374}375debug.println();376}377378try {379CodeSource codesource = getCodeSource(ge, keyStore);380// skip if signedBy alias was unknown...381if (codesource == null) return;382383PolicyEntry entry = new PolicyEntry(codesource);384Enumeration<PermissionEntry> enum_ = ge.permissionElements();385while (enum_.hasMoreElements()) {386PermissionEntry pe = enum_.nextElement();387try {388// XXX special case PrivateCredentialPermission-SELF389Permission perm;390if (pe.permission.equals391("javax.security.auth.PrivateCredentialPermission") &&392pe.name.endsWith(" self")) {393perm = getInstance(pe.permission,394pe.name + " \"self\"",395pe.action);396} else {397perm = getInstance(pe.permission,398pe.name,399pe.action);400}401entry.add(perm);402if (debug != null) {403debug.println(" "+perm);404}405} catch (ClassNotFoundException cnfe) {406Certificate certs[];407if (pe.signedBy != null) {408certs = getCertificates(keyStore, pe.signedBy);409} else {410certs = null;411}412413// only add if we had no signer or we had a414// a signer and found the keys for it.415if (certs != null || pe.signedBy == null) {416Permission perm = new UnresolvedPermission(417pe.permission,418pe.name,419pe.action,420certs);421entry.add(perm);422if (debug != null) {423debug.println(" "+perm);424}425}426} catch (java.lang.reflect.InvocationTargetException ite) {427System.err.println428(AUTH_POLICY +429rb.getString(".error.adding.Permission.") +430pe.permission +431rb.getString("SPACE") +432ite.getTargetException());433} catch (Exception e) {434System.err.println435(AUTH_POLICY +436rb.getString(".error.adding.Permission.") +437pe.permission +438rb.getString("SPACE") +439e);440}441}442policyEntries.addElement(entry);443} catch (Exception e) {444System.err.println445(AUTH_POLICY +446rb.getString(".error.adding.Entry.") +447ge +448rb.getString("SPACE") +449e);450}451452if (debug != null) {453debug.println();454}455}456457/**458* Returns a new Permission object of the given Type. The Permission is459* created by getting the460* Class object using the <code>Class.forName</code> method, and using461* the reflection API to invoke the (String name, String actions)462* constructor on the463* object.464*465* @param type the type of Permission being created.466* @param name the name of the Permission being created.467* @param actions the actions of the Permission being created.468*469* @exception ClassNotFoundException if the particular Permission470* class could not be found.471*472* @exception IllegalAccessException if the class or initializer is473* not accessible.474*475* @exception InstantiationException if getInstance tries to476* instantiate an abstract class or an interface, or if the477* instantiation fails for some other reason.478*479* @exception NoSuchMethodException if the (String, String) constructor480* is not found.481*482* @exception InvocationTargetException if the underlying Permission483* constructor throws an exception.484*485*/486private static final Permission getInstance(String type,487String name,488String actions)489throws ClassNotFoundException,490InstantiationException,491IllegalAccessException,492NoSuchMethodException,493InvocationTargetException494{495//XXX we might want to keep a hash of created factories...496Class<?> pc = Class.forName(type);497Constructor<?> c = pc.getConstructor(PARAMS);498return (Permission) c.newInstance(new Object[] { name, actions });499}500501/**502* Fetch all certs associated with this alias.503*/504Certificate[] getCertificates(KeyStore keyStore, String aliases) {505506Vector<Certificate> vcerts = null;507508StringTokenizer st = new StringTokenizer(aliases, ",");509int n = 0;510511while (st.hasMoreTokens()) {512String alias = st.nextToken().trim();513n++;514Certificate cert = null;515// See if this alias's cert has already been cached516cert = (Certificate) aliasMapping.get(alias);517if (cert == null && keyStore != null) {518519try {520cert = keyStore.getCertificate(alias);521} catch (KeyStoreException kse) {522// never happens, because keystore has already been loaded523// when we call this524}525if (cert != null) {526aliasMapping.put(alias, cert);527aliasMapping.put(cert, alias);528}529}530531if (cert != null) {532if (vcerts == null) {533vcerts = new Vector<Certificate>();534}535vcerts.addElement(cert);536}537}538539// make sure n == vcerts.size, since we are doing a logical *and*540if (vcerts != null && n == vcerts.size()) {541Certificate[] certs = new Certificate[vcerts.size()];542vcerts.copyInto(certs);543return certs;544} else {545return null;546}547}548549/**550* Enumerate all the entries in the global policy object.551* This method is used by policy admin tools. The tools552* should use the Enumeration methods on the returned object553* to fetch the elements sequentially.554*/555private final synchronized Enumeration<PolicyEntry> elements() {556return policyEntries.elements();557}558559@Override560public PermissionCollection getPermissions(final Subject subject,561final CodeSource codesource) {562563// 1) if code instantiates PolicyFile directly, then it will need564// all the permissions required for the PolicyFile initialization565// 2) if code calls Policy.getPolicy, then it simply needs566// AuthPermission(getPolicy), and the javax.security.auth.Policy567// implementation instantiates PolicyFile in a doPrivileged block568// 3) if after instantiating a Policy (either via #1 or #2),569// code calls getPermissions, PolicyFile wraps the call570// in a doPrivileged block.571return AccessController.doPrivileged572(new PrivilegedAction<PermissionCollection>() {573@Override public PermissionCollection run() {574SubjectCodeSource scs = new SubjectCodeSource(575subject, null,576codesource == null ? null : codesource.getLocation(),577codesource == null ? null : codesource.getCertificates());578if (initialized) {579return getPermissions(new Permissions(), scs);580} else {581return new PolicyPermissions(AuthPolicyFile.this, scs);582}583}584});585}586587/**588* Examines the global policy for the specified CodeSource, and589* creates a PermissionCollection object with590* the set of permissions for that principal's protection domain.591*592* @param CodeSource the codesource associated with the caller.593* This encapsulates the original location of the code (where the code594* came from) and the public key(s) of its signer.595*596* @return the set of permissions according to the policy.597*/598PermissionCollection getPermissions(CodeSource codesource) {599600if (initialized) {601return getPermissions(new Permissions(), codesource);602} else {603return new PolicyPermissions(this, codesource);604}605}606607/**608* Examines the global policy for the specified CodeSource, and609* creates a PermissionCollection object with610* the set of permissions for that principal's protection domain.611*612* @param permissions the permissions to populate613* @param codesource the codesource associated with the caller.614* This encapsulates the original location of the code (where the code615* came from) and the public key(s) of its signer.616*617* @return the set of permissions according to the policy.618*/619Permissions getPermissions(final Permissions perms,620final CodeSource cs)621{622if (!initialized) {623init();624}625626final CodeSource codesource[] = {null};627628codesource[0] = canonicalizeCodebase(cs, true);629630if (debug != null) {631debug.println("evaluate(" + codesource[0] + ")\n");632}633634// needs to be in a begin/endPrivileged block because635// codesource.implies calls URL.equals which does an636// InetAddress lookup637638for (int i = 0; i < policyEntries.size(); i++) {639640PolicyEntry entry = policyEntries.elementAt(i);641642if (debug != null) {643debug.println("PolicyFile CodeSource implies: " +644entry.codesource.toString() + "\n\n" +645"\t" + codesource[0].toString() + "\n\n");646}647648if (entry.codesource.implies(codesource[0])) {649for (int j = 0; j < entry.permissions.size(); j++) {650Permission p = entry.permissions.elementAt(j);651if (debug != null) {652debug.println(" granting " + p);653}654if (!addSelfPermissions(p, entry.codesource,655codesource[0], perms)) {656// we could check for duplicates657// before adding new permissions,658// but the SubjectDomainCombiner659// already checks for duplicates later660perms.add(p);661}662}663}664}665666// now see if any of the keys are trusted ids.667668if (!ignoreIdentityScope) {669Certificate certs[] = codesource[0].getCertificates();670if (certs != null) {671for (int k=0; k < certs.length; k++) {672if (aliasMapping.get(certs[k]) == null &&673checkForTrustedIdentity(certs[k])) {674// checkForTrustedIdentity added it675// to the policy for us. next time676// around we'll find it. This time677// around we need to add it.678perms.add(new java.security.AllPermission());679}680}681}682}683return perms;684}685686/**687* Returns true if 'Self' permissions were added to the provided688* 'perms', and false otherwise.689*690* <p>691*692* @param p check to see if this Permission is a "SELF"693* PrivateCredentialPermission. <p>694*695* @param entryCs the codesource for the Policy entry.696*697* @param accCs the codesource for from the current AccessControlContext.698*699* @param perms the PermissionCollection where the individual700* PrivateCredentialPermissions will be added.701*/702private boolean addSelfPermissions(final Permission p,703CodeSource entryCs,704CodeSource accCs,705Permissions perms) {706707if (!(p instanceof PrivateCredentialPermission)) {708return false;709}710711if (!(entryCs instanceof SubjectCodeSource)) {712return false;713}714715PrivateCredentialPermission pcp = (PrivateCredentialPermission)p;716SubjectCodeSource scs = (SubjectCodeSource)entryCs;717718// see if it is a SELF permission719String[][] pPrincipals = pcp.getPrincipals();720if (pPrincipals.length <= 0 ||721!pPrincipals[0][0].equalsIgnoreCase("self") ||722!pPrincipals[0][1].equalsIgnoreCase("self")) {723724// regular PrivateCredentialPermission725return false;726} else {727728// granted a SELF permission - create a729// PrivateCredentialPermission for each730// of the Policy entry's CodeSource Principals731732if (scs.getPrincipals() == null) {733// XXX SubjectCodeSource has no Subject???734return true;735}736737for (PrincipalEntry principal : scs.getPrincipals()) {738739// if the Policy entry's Principal does not contain a740// WILDCARD for the Principal name, then a741// new PrivateCredentialPermission is created742// for the Principal listed in the Policy entry.743// if the Policy entry's Principal contains a WILDCARD744// for the Principal name, then a new745// PrivateCredentialPermission is created746// for each Principal associated with the Subject747// in the current ACC.748749String[][] principalInfo = getPrincipalInfo(principal, accCs);750751for (int i = 0; i < principalInfo.length; i++) {752753// here's the new PrivateCredentialPermission754755PrivateCredentialPermission newPcp =756new PrivateCredentialPermission757(pcp.getCredentialClass() +758" " +759principalInfo[i][0] +760" " +761"\"" + principalInfo[i][1] + "\"",762"read");763764if (debug != null) {765debug.println("adding SELF permission: " +766newPcp.toString());767}768769perms.add(newPcp);770}771}772}773return true;774}775776/**777* return the principal class/name pair in the 2D array.778* array[x][y]: x corresponds to the array length.779* if (y == 0), it's the principal class.780* if (y == 1), it's the principal name.781*/782private String[][] getPrincipalInfo(PrincipalEntry principal,783final CodeSource accCs) {784785// there are 3 possibilities:786// 1) the entry's Principal class and name are not wildcarded787// 2) the entry's Principal name is wildcarded only788// 3) the entry's Principal class and name are wildcarded789790if (!principal.getPrincipalClass().equals791(PrincipalEntry.WILDCARD_CLASS) &&792!principal.getPrincipalName().equals793(PrincipalEntry.WILDCARD_NAME)) {794795// build a PrivateCredentialPermission for the principal796// from the Policy entry797String[][] info = new String[1][2];798info[0][0] = principal.getPrincipalClass();799info[0][1] = principal.getPrincipalName();800return info;801802} else if (!principal.getPrincipalClass().equals803(PrincipalEntry.WILDCARD_CLASS) &&804principal.getPrincipalName().equals805(PrincipalEntry.WILDCARD_NAME)) {806807// build a PrivateCredentialPermission for all808// the Subject's principals that are instances of principalClass809810// the accCs is guaranteed to be a SubjectCodeSource811// because the earlier CodeSource.implies succeeded812SubjectCodeSource scs = (SubjectCodeSource)accCs;813814Set<? extends Principal> principalSet = null;815try {816// principal.principalClass should extend Principal817// If it doesn't, we should stop here with a ClassCastException.818@SuppressWarnings("unchecked")819Class<? extends Principal> pClass = (Class<? extends Principal>)820Class.forName(principal.getPrincipalClass(), false,821ClassLoader.getSystemClassLoader());822principalSet = scs.getSubject().getPrincipals(pClass);823} catch (Exception e) {824if (debug != null) {825debug.println("problem finding Principal Class " +826"when expanding SELF permission: " +827e.toString());828}829}830831if (principalSet == null) {832// error833return new String[0][0];834}835836String[][] info = new String[principalSet.size()][2];837838int i = 0;839for (Principal p : principalSet) {840info[i][0] = p.getClass().getName();841info[i][1] = p.getName();842i++;843}844return info;845846} else {847848// build a PrivateCredentialPermission for every849// one of the current Subject's principals850851// the accCs is guaranteed to be a SubjectCodeSource852// because the earlier CodeSource.implies succeeded853SubjectCodeSource scs = (SubjectCodeSource)accCs;854Set<Principal> principalSet = scs.getSubject().getPrincipals();855856String[][] info = new String[principalSet.size()][2];857858int i = 0;859for (Principal p : principalSet) {860info[i][0] = p.getClass().getName();861info[i][1] = p.getName();862i++;863}864return info;865}866}867868/*869* Returns the signer certificates from the list of certificates associated870* with the given code source.871*872* The signer certificates are those certificates that were used to verify873* signed code originating from the codesource location.874*875* This method assumes that in the given code source, each signer876* certificate is followed by its supporting certificate chain877* (which may be empty), and that the signer certificate and its878* supporting certificate chain are ordered bottom-to-top (i.e., with the879* signer certificate first and the (root) certificate authority last).880*/881Certificate[] getSignerCertificates(CodeSource cs) {882Certificate[] certs = null;883if ((certs = cs.getCertificates()) == null) {884return null;885}886for (int i = 0; i < certs.length; i++) {887if (!(certs[i] instanceof X509Certificate))888return cs.getCertificates();889}890891// Do we have to do anything?892int i = 0;893int count = 0;894while (i < certs.length) {895count++;896while (((i+1) < certs.length)897&& ((X509Certificate)certs[i]).getIssuerDN().equals(898((X509Certificate)certs[i+1]).getSubjectDN())) {899i++;900}901i++;902}903if (count == certs.length) {904// Done905return certs;906}907908ArrayList<Certificate> userCertList = new ArrayList<>();909i = 0;910while (i < certs.length) {911userCertList.add(certs[i]);912while (((i+1) < certs.length)913&& ((X509Certificate)certs[i]).getIssuerDN().equals(914((X509Certificate)certs[i+1]).getSubjectDN())) {915i++;916}917i++;918}919Certificate[] userCerts = new Certificate[userCertList.size()];920userCertList.toArray(userCerts);921return userCerts;922}923924private CodeSource canonicalizeCodebase(CodeSource cs,925boolean extractSignerCerts) {926CodeSource canonCs = cs;927if (cs.getLocation() != null &&928cs.getLocation().getProtocol().equalsIgnoreCase("file")) {929try {930String path = cs.getLocation().getFile().replace931('/',932File.separatorChar);933URL csUrl = null;934if (path.endsWith("*")) {935// remove trailing '*' because it causes canonicalization936// to fail on win32937path = path.substring(0, path.length()-1);938boolean appendFileSep = false;939if (path.endsWith(File.separator)) {940appendFileSep = true;941}942if (path.equals("")) {943path = System.getProperty("user.dir");944}945File f = new File(path);946path = f.getCanonicalPath();947StringBuffer sb = new StringBuffer(path);948// reappend '*' to canonicalized filename (note that949// canonicalization may have removed trailing file950// separator, so we have to check for that, too)951if (!path.endsWith(File.separator) &&952(appendFileSep || f.isDirectory())) {953sb.append(File.separatorChar);954}955sb.append('*');956path = sb.toString();957} else {958path = new File(path).getCanonicalPath();959}960csUrl = new File(path).toURL();961962if (cs instanceof SubjectCodeSource) {963SubjectCodeSource scs = (SubjectCodeSource)cs;964if (extractSignerCerts) {965canonCs = new SubjectCodeSource(scs.getSubject(),966scs.getPrincipals(),967csUrl,968getSignerCertificates(scs));969} else {970canonCs = new SubjectCodeSource(scs.getSubject(),971scs.getPrincipals(),972csUrl,973scs.getCertificates());974}975} else {976if (extractSignerCerts) {977canonCs = new CodeSource(csUrl,978getSignerCertificates(cs));979} else {980canonCs = new CodeSource(csUrl,981cs.getCertificates());982}983}984} catch (IOException ioe) {985// leave codesource as it is, unless we have to extract its986// signer certificates987if (extractSignerCerts) {988if (!(cs instanceof SubjectCodeSource)) {989canonCs = new CodeSource(cs.getLocation(),990getSignerCertificates(cs));991} else {992SubjectCodeSource scs = (SubjectCodeSource)cs;993canonCs = new SubjectCodeSource(scs.getSubject(),994scs.getPrincipals(),995scs.getLocation(),996getSignerCertificates(scs));997}998}999}1000} else {1001if (extractSignerCerts) {1002if (!(cs instanceof SubjectCodeSource)) {1003canonCs = new CodeSource(cs.getLocation(),1004getSignerCertificates(cs));1005} else {1006SubjectCodeSource scs = (SubjectCodeSource)cs;1007canonCs = new SubjectCodeSource(scs.getSubject(),1008scs.getPrincipals(),1009scs.getLocation(),1010getSignerCertificates(scs));1011}1012}1013}1014return canonCs;1015}10161017/**1018* Each entry in the policy configuration file is represented by a1019* PolicyEntry object. <p>1020*1021* A PolicyEntry is a (CodeSource,Permission) pair. The1022* CodeSource contains the (URL, PublicKey) that together identify1023* where the Java bytecodes come from and who (if anyone) signed1024* them. The URL could refer to localhost. The URL could also be1025* null, meaning that this policy entry is given to all comers, as1026* long as they match the signer field. The signer could be null,1027* meaning the code is not signed. <p>1028*1029* The Permission contains the (Type, Name, Action) triplet. <p>1030*1031* For now, the Policy object retrieves the public key from the1032* X.509 certificate on disk that corresponds to the signedBy1033* alias specified in the Policy config file. For reasons of1034* efficiency, the Policy object keeps a hashtable of certs already1035* read in. This could be replaced by a secure internal key1036* store.1037*1038* <p>1039* For example, the entry1040* <pre>1041* permission java.io.File "/tmp", "read,write",1042* signedBy "Duke";1043* </pre>1044* is represented internally1045* <pre>1046*1047* FilePermission f = new FilePermission("/tmp", "read,write");1048* PublicKey p = publickeys.get("Duke");1049* URL u = InetAddress.getLocalHost();1050* CodeBase c = new CodeBase( p, u );1051* pe = new PolicyEntry(f, c);1052* </pre>1053*1054* @author Marianne Mueller1055* @author Roland Schemers1056* @see java.security.CodeSource1057* @see java.security.Policy1058* @see java.security.Permissions1059* @see java.security.ProtectionDomain1060*/1061private static class PolicyEntry {10621063CodeSource codesource;1064Vector<Permission> permissions;10651066/**1067* Given a Permission and a CodeSource, create a policy entry.1068*1069* XXX Decide if/how to add validity fields and "purpose" fields to1070* XXX policy entries1071*1072* @param cs the CodeSource, which encapsulates the URL and the public1073* key attributes from the policy config file. Validity checks1074* are performed on the public key before PolicyEntry is called.1075*1076*/1077PolicyEntry(CodeSource cs) {1078this.codesource = cs;1079this.permissions = new Vector<Permission>();1080}10811082/**1083* add a Permission object to this entry.1084*/1085void add(Permission p) {1086permissions.addElement(p);1087}10881089/**1090* Return the CodeSource for this policy entry1091*/1092CodeSource getCodeSource() {1093return this.codesource;1094}10951096@Override1097public String toString(){1098StringBuffer sb = new StringBuffer();1099sb.append(rb.getString("LPARAM"));1100sb.append(getCodeSource());1101sb.append("\n");1102for (int j = 0; j < permissions.size(); j++) {1103Permission p = permissions.elementAt(j);1104sb.append(rb.getString("SPACE"));1105sb.append(rb.getString("SPACE"));1106sb.append(p);1107sb.append(rb.getString("NEWLINE"));1108}1109sb.append(rb.getString("RPARAM"));1110sb.append(rb.getString("NEWLINE"));1111return sb.toString();1112}11131114}1115}11161117@SuppressWarnings("deprecation")1118class PolicyPermissions extends PermissionCollection {11191120private static final long serialVersionUID = -1954188373270545523L;11211122private CodeSource codesource;1123private Permissions perms;1124private AuthPolicyFile policy;1125private boolean notInit; // have we pulled in the policy permissions yet?1126private Vector<Permission> additionalPerms;11271128PolicyPermissions(AuthPolicyFile policy,1129CodeSource codesource)1130{1131this.codesource = codesource;1132this.policy = policy;1133this.perms = null;1134this.notInit = true;1135this.additionalPerms = null;1136}11371138@Override1139public void add(Permission permission) {1140if (isReadOnly())1141throw new SecurityException1142(AuthPolicyFile.rb.getString1143("attempt.to.add.a.Permission.to.a.readonly.PermissionCollection"));11441145if (perms == null) {1146if (additionalPerms == null) {1147additionalPerms = new Vector<Permission>();1148}1149additionalPerms.add(permission);1150} else {1151perms.add(permission);1152}1153}11541155private synchronized void init() {1156if (notInit) {1157if (perms == null) {1158perms = new Permissions();1159}1160if (additionalPerms != null) {1161Enumeration<Permission> e = additionalPerms.elements();1162while (e.hasMoreElements()) {1163perms.add(e.nextElement());1164}1165additionalPerms = null;1166}1167policy.getPermissions(perms, codesource);1168notInit = false;1169}1170}11711172@Override1173public boolean implies(Permission permission) {1174if (notInit) {1175init();1176}1177return perms.implies(permission);1178}11791180@Override1181public Enumeration<Permission> elements() {1182if (notInit) {1183init();1184}1185return perms.elements();1186}11871188@Override1189public String toString() {1190if (notInit) {1191init();1192}1193return perms.toString();1194}1195}119611971198