/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This class represents a default implementation for
* <code>javax.security.auth.Policy</code>.
*
* <p> This object stores the policy for entire Java runtime,
* and is the amalgamation of multiple static policy
* configurations that resides in files.
* The algorithm for locating the policy file(s) and reading their
* information into this <code>Policy</code> object is:
*
* <ol>
* <li>
* Loop through the <code>java.security.Security</code> properties,
* <i>auth.policy.url.1</i>, <i>auth.policy.url.2</i>, ...,
* <i>auth.policy.url.X</i>". These properties are set
* in the Java security properties file, which is located in the file named
* <JAVA_HOME>/lib/security/java.security.
* <JAVA_HOME> refers to the value of the java.home system property,
* and specifies the directory where the JRE is installed.
* Each property value specifies a <code>URL</code> pointing to a
* policy file to be loaded. Read in and load each policy.
*
* <li>
* The <code>java.lang.System</code> property <i>java.security.auth.policy</i>
* may also be set to a <code>URL</code> pointing to another policy file
* (which is the case when a user uses the -D switch at runtime).
* If this property is defined, and its use is allowed by the
* security property file (the Security property,
* <i>policy.allowSystemProperty</i> is set to <i>true</i>),
* also load that policy.
*
* <li>
* If the <i>java.security.auth.policy</i> property is defined using
* "==" (rather than "="), then ignore all other specified
* policies and only load this policy.
* </ol>
*
* Each policy file consists of one or more grant entries, each of
* which consists of a number of permission entries.
*
* <pre>
* grant signedBy "<b>alias</b>", codeBase "<b>URL</b>",
* principal <b>principalClass</b> "<b>principalName</b>",
* principal <b>principalClass</b> "<b>principalName</b>",
* ... {
*
* permission <b>Type</b> "<b>name</b> "<b>action</b>",
* signedBy "<b>alias</b>";
* permission <b>Type</b> "<b>name</b> "<b>action</b>",
* signedBy "<b>alias</b>";
* ....
* };
* </pre>
*
* All non-bold items above must appear as is (although case
* doesn't matter and some are optional, as noted below).
* Italicized items represent variable values.
*
* <p> A grant entry must begin with the word <code>grant</code>.
* The <code>signedBy</code> and <code>codeBase</code>
* If they are not present, then any signer (including unsigned code)
* will match, and any codeBase will match. Note that the
* This <code>Policy</code> implementation only permits
* Principal-based grant entries. Note that the <i>principalClass</i>
* may be set to the wildcard value, *, which allows it to match
* any <code>Principal</code> class. In addition, the <i>principalName</i>
* may also be set to the wildcard value, *, allowing it to match
* any <code>Principal</code> name. When setting the <i>principalName</i>
* to the *, do not surround the * with quotes.
*
* <p> A permission entry must begin with the word <code>permission</code>.
* The word <code><i>Type</i></code> in the template above is
* a specific permission type, such as <code>java.io.FilePermission</code>
* or <code>java.lang.RuntimePermission</code>.
*
* <p> The "<i>action</i>" is required for
* many permission types, such as <code>java.io.FilePermission</code>
* (where it specifies what type of file access that is permitted).
* It is not required for categories such as
* <code>java.lang.RuntimePermission</code>
* where it is not necessary - you either have the
* permission specified by the <code>"<i>name</i>"</code>
* value following the type name or you don't.
*
* is optional. If present, it indicates a signed permission. That is,
* the permission class itself must be signed by the given alias in
* order for it to be granted. For example,
* suppose you have the following grant entry:
*
* <pre>
* grant principal foo.com.Principal "Duke" {
* permission Foo "foobar", signedBy "FooSoft";
* }
* </pre>
*
* <p> Then this permission of type <i>Foo</i> is granted if the
* <code>Foo.class</code> permission has been signed by the
* "FooSoft" alias, or if <code>Foo.class</code> is a
* system class (i.e., is found on the CLASSPATH).
*
* <p> Items that appear in an entry must appear in the specified order
* (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
* "<i>action</i>"). An entry is terminated with a semicolon.
*
* <p> Case is unimportant for the identifiers (<code>permission</code>,
* <code>signedBy</code>, <code>codeBase</code>, etc.) but is
* significant for the <i>Type</i>
* or for any string that is passed in as a value. <p>
*
* <p> An example of two entries in a policy configuration file is
* <pre>
* // if the code is comes from "foo.com" and is running as "Duke",
*
* grant codeBase "foo.com", principal foo.com.Principal "Duke" {
* permission java.io.FilePermission "/tmp/*", "read,write";
* };
*
* // grant any code running as "Duke" permission to read
* // the "java.vendor" Property.
*
* grant principal foo.com.Principal "Duke" {
* permission java.util.PropertyPermission "java.vendor";
* </pre>
*
* <p> This <code>Policy</code> implementation supports
* special handling for PrivateCredentialPermissions.
* If a grant entry is configured with a
* <code>PrivateCredentialPermission</code>,
* <code>PrivateCredentialPermission</code> is "self",
* then the entry grants the specified <code>Subject</code> permission to
* access its own private Credential. For example,
* the following grants the <code>Subject</code> "Duke"
* access to its own a.b.Credential.
*
* <pre>
* grant principal foo.com.Principal "Duke" {
* permission javax.security.auth.PrivateCredentialPermission
* "a.b.Credential self",
* "read";
* };
* </pre>
*
* The following grants the <code>Subject</code> "Duke"
* access to all of its own private Credentials:
*
* <pre>
* grant principal foo.com.Principal "Duke" {
* permission javax.security.auth.PrivateCredentialPermission
* "* self",
* "read";
* };
* </pre>
*
* The following grants all Subjects authenticated as a
* <code>SolarisPrincipal</code> (regardless of their respective names)
* permission to access their own private Credentials:
*
* <pre>
* grant principal com.sun.security.auth.SolarisPrincipal * {
* permission javax.security.auth.PrivateCredentialPermission
* "* self",
* "read";
* };
* </pre>
*
* The following grants all Subjects permission to access their own
* private Credentials:
*
* <pre>
* grant principal * * {
* permission javax.security.auth.PrivateCredentialPermission
* "* self",
* "read";
* };
* </pre>
* @deprecated As of JDK 1.4, replaced by
* <code>sun.security.provider.PolicyFile</code>.
* This class is entirely deprecated.
*
* @see java.security.CodeSource
* @see java.security.Permissions
* @see java.security.ProtectionDomain
*/
("sun.security.util.AuthResources"));
}
});
// needs to be package private
private boolean initialized = false;
private boolean expandProperties = true;
private boolean ignoreIdentityScope = true;
// for use with the reflection API
/**
* Initializes the Policy object and reads the default policy
* configuration file(s) into the Policy object.
*/
public PolicyFile() {
// initialize Policy if either the AUTH_POLICY or
// SECURITY_MANAGER properties are set
}
init();
}
private synchronized void init() {
if (initialized)
return;
initialized = true;
}
/**
* Refreshes the policy object by re-reading all the policy files.
*
* <p>
*
* @exception SecurityException if the caller doesn't have permission
* to refresh the <code>Policy</code>.
*/
public synchronized void refresh()
{
("refreshPolicy"));
}
// XXX
//
// 1) if code instantiates PolicyFile directly, then it will need
// all the permissions required for the PolicyFile initialization
// 2) if code calls Policy.getPolicy, then it simply needs
// AuthPermission(getPolicy), and the javax.security.auth.Policy
// implementation instantiates PolicyFile in a doPrivileged block
// 3) if after instantiating a Policy (either via #1 or #2),
// code calls refresh, it simply needs
// AuthPermission(refreshPolicy). then PolicyFile wraps
// the refresh in a doPrivileged block.
initialized = false;
init();
return null;
}
});
}
if (keyStoreName != null) {
try {
/*
* location of keystore is specified as absolute URL in policy
* file, or is relative to URL of policy file
*/
try {
// absolute URL
// relative URL
}
}
if (keyStoreType != null)
else
return ks;
} catch (Exception e) {
// ignore, treat it like we have no keystore
e.printStackTrace();
}
return null;
}
}
return null;
}
private void initPolicyFile() {
if (extra_policy != null) {
boolean overrideAll = false;
overrideAll = true;
}
try {
if (policyFile.exists()) {
} else {
}
} catch (Exception e) {
// ignore.
}
}
if (overrideAll) {
}
return;
}
}
}
int n = 1;
boolean loaded_one = false;
try {
loaded_one = true;
} catch (Exception e) {
e.printStackTrace();
}
// ignore that policy
}
n++;
}
if (loaded_one == false) {
// do not load a static policy
}
}
/**
* Checks public key. If it is marked as trusted in
* the identity database, add it to the policy
* with the AllPermission.
*/
// XXX JAAS has no way to access the SUN package.
// we'll add this back in when JAAS goes into core.
return false;
}
/**
* Reads a policy configuration into the Policy object using a
* Reader object.
*
* @param policyFile the policy Reader object.
*/
try {
pp.getKeyStoreType());
while (enum_.hasMoreElements()) {
}
pe.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*
* Fast path reading from file urls in order to avoid calling
* FileURLConnection.connect() which can be quite slow the first time
* it is called. We really should clean up FileURLConnection so that
* this is not a problem but in the meantime this fix helps reduce
* start up time noticeably for the new launcher. -- DAC
*/
return new FileInputStream(path);
} else {
return url.openStream();
}
}
/**
* Given a PermissionEntry, create a codeSource.
*
* @return null if signedBy alias is not recognized
*/
{
// we don't have a key for this alias,
// just return
}
return null;
}
}
else
return (canonicalizeCodebase
false));
} else {
return (canonicalizeCodebase
false));
}
}
/**
* Add one policy entry to the vector.
*/
}
}
}
try {
// skip if signedBy alias was unknown...
if (codesource == null) return;
while (enum_.hasMoreElements()) {
try {
// XXX special case PrivateCredentialPermission-SELF
("javax.security.auth.PrivateCredentialPermission") &&
} else {
}
}
} catch (ClassNotFoundException cnfe) {
Certificate certs[];
else
// only add if we had no signer or we had a
// a signer and found the keys for it.
certs);
}
}
(AUTH_POLICY +
pe.permission +
} catch (Exception e) {
(AUTH_POLICY +
pe.permission +
e);
}
}
} catch (Exception e) {
(AUTH_POLICY +
ge +
e);
}
}
/**
* Returns a new Permission object of the given Type. The Permission is
* created by getting the
* Class object using the <code>Class.forName</code> method, and using
* the reflection API to invoke the (String name, String actions)
* constructor on the
* object.
*
* @param type the type of Permission being created.
* @param name the name of the Permission being created.
* @param actions the actions of the Permission being created.
*
* @exception ClassNotFoundException if the particular Permission
* class could not be found.
*
* @exception IllegalAccessException if the class or initializer is
* not accessible.
*
* @exception InstantiationException if getInstance tries to
* instantiate an abstract class or an interface, or if the
* instantiation fails for some other reason.
*
* @exception NoSuchMethodException if the (String, String) constructor
* is not found.
*
* @exception InvocationTargetException if the underlying Permission
* constructor throws an exception.
*
*/
throws ClassNotFoundException,
{
//XXX we might want to keep a hash of created factories...
}
/**
* Fetch all certs associated with this alias.
*/
int n = 0;
while (st.hasMoreTokens()) {
n++;
//See if this alias's cert has already been cached
try {
} catch (KeyStoreException kse) {
// never happens, because keystore has already been loaded
// when we call this
}
}
}
}
}
// make sure n == vcerts.size, since we are doing a logical *and*
return certs;
} else {
return null;
}
}
/**
* Enumerate all the entries in the global policy object.
* This method is used by policy admin tools. The tools
* should use the Enumeration methods on the returned object
* to fetch the elements sequentially.
*/
return policyEntries.elements();
}
/**
* Examines this <code>Policy</code> and returns the Permissions granted
* to the specified <code>Subject</code> and <code>CodeSource</code>.
*
* <p> Permissions for a particular <i>grant</i> entry are returned
* if the <code>CodeSource</code> constructed using the codebase and
* signedby values specified in the entry <code>implies</code>
* the <code>CodeSource</code> provided to this method, and if the
* <code>Subject</code> provided to this method contains all of the
* Principals specified in the entry.
*
* <p> The <code>Subject</code> provided to this method contains all
* of the Principals specified in the entry if, for each
* <code>Principal</code>, "P1", specified in the <i>grant</i> entry
* one of the following two conditions is met:
*
* <p>
* <ol>
* <li> the <code>Subject</code> has a
* <code>Principal</code>, "P2", where
* <code>P2.getClass().getName()</code> equals the
* P1's class name, and where
* <code>P2.getName()</code> equals the P1's name.
*
* <li> P1 implements
* <code>com.sun.security.auth.PrincipalComparator</code>,
* and <code>P1.implies</code> the provided <code>Subject</code>.
* </ol>
*
* <p> Note that this <code>Policy</code> implementation has
* special handling for PrivateCredentialPermissions.
* When this method encounters a <code>PrivateCredentialPermission</code>
* which specifies "self" as the <code>Principal</code> class and name,
* it does not add that <code>Permission</code> to the returned
* <code>PermissionCollection</code>. Instead, it builds
* a new <code>PrivateCredentialPermission</code>
* for each <code>Principal</code> associated with the provided
* <code>Subject</code>. Each new <code>PrivateCredentialPermission</code>
* contains the same Credential class as specified in the
* originally granted permission, as well as the Class and name
* for the respective <code>Principal</code>.
*
* <p>
*
* @param subject the Permissions granted to this <code>Subject</code>
* and the additionally provided <code>CodeSource</code>
* are returned. <p>
*
* @param codesource the Permissions granted to this <code>CodeSource</code>
* and the additionally provided <code>Subject</code>
* are returned.
*
* @return the Permissions granted to the provided <code>Subject</code>
* <code>CodeSource</code>.
*/
final CodeSource codesource) {
// XXX when JAAS goes into the JDK core,
// we can remove this method and simply
// rely on the getPermissions variant that takes a codesource,
// which no one can use at this point in time.
// at that time, we can also make SubjectCodeSource a public
// class.
// XXX
//
// 1) if code instantiates PolicyFile directly, then it will need
// all the permissions required for the PolicyFile initialization
// 2) if code calls Policy.getPolicy, then it simply needs
// AuthPermission(getPolicy), and the javax.security.auth.Policy
// implementation instantiates PolicyFile in a doPrivileged block
// 3) if after instantiating a Policy (either via #1 or #2),
// code calls getPermissions, PolicyFile wraps the call
// in a doPrivileged block.
public PermissionCollection run() {
(subject,
null,
if (initialized)
else
}
});
}
/**
* Examines the global policy for the specified CodeSource, and
* creates a PermissionCollection object with
* the set of permissions for that principal's protection domain.
*
* @param CodeSource the codesource associated with the caller.
* This encapsulates the original location of the code (where the code
* came from) and the public key(s) of its signer.
*
* @return the set of permissions according to the policy.
*/
if (initialized)
else
return new PolicyPermissions(this, codesource);
}
/**
* Examines the global policy for the specified CodeSource, and
* creates a PermissionCollection object with
* the set of permissions for that principal's protection domain.
*
* @param permissions the permissions to populate
* @param codesource the codesource associated with the caller.
* This encapsulates the original location of the code (where the code
* came from) and the public key(s) of its signer.
*
* @return the set of permissions according to the policy.
*/
final CodeSource cs)
{
if (!initialized) {
init();
}
}
// needs to be in a begin/endPrivileged block because
// codesource.implies calls URL.equals which does an
// InetAddress lookup
}
}
// we could check for duplicates
// before adding new permissions,
// but the SubjectDomainCombiner
// already checks for duplicates later
}
}
}
}
// now see if any of the keys are trusted ids.
if (!ignoreIdentityScope) {
checkForTrustedIdentity(certs[k])) {
// checkForTrustedIdentity added it
// to the policy for us. next time
// around we'll find it. This time
// around we need to add it.
}
}
}
}
return perms;
}
/**
* Returns true if 'Self' permissions were added to the provided
* 'perms', and false otherwise.
*
* <p>
*
* @param p check to see if this Permission is a "SELF"
* PrivateCredentialPermission. <p>
*
* @param entryCs the codesource for the Policy entry.
*
* @param accCs the codesource for from the current AccessControlContext.
*
* @param perms the PermissionCollection where the individual
* PrivateCredentialPermissions will be added.
*/
Permissions perms) {
if (!(p instanceof PrivateCredentialPermission))
return false;
if (!(entryCs instanceof SubjectCodeSource))
return false;
// see if it is a SELF permission
// regular PrivateCredentialPermission
return false;
} else {
// granted a SELF permission - create a
// PrivateCredentialPermission for each
// of the Policy entry's CodeSource Principals
// XXX SubjectCodeSource has no Subject???
return true;
}
// XXX
// if the Policy entry's Principal does not contain a
// WILDCARD for the Principal name, then a
// new PrivateCredentialPermission is created
// for the Principal listed in the Policy entry.
// if the Policy entry's Principal contains a WILDCARD
// for the Principal name, then a new
// PrivateCredentialPermission is created
// for each Principal associated with the Subject
// in the current ACC.
// here's the new PrivateCredentialPermission
(pcp.getCredentialClass() +
" " +
principalInfo[i][0] +
" " +
"read");
}
}
}
}
return true;
}
/**
* array[x][y]: x corresponds to the array length.
* if (y == 0), it's the principal class.
* if (y == 1), it's the principal name.
*/
final CodeSource accCs) {
// there are 3 possibilities:
// 1) the entry's Principal class and name are not wildcarded
// 2) the entry's Principal name is wildcarded only
// 3) the entry's Principal class and name are wildcarded
// build a PrivateCredentialPermission for the principal
// from the Policy entry
return info;
// build a PrivateCredentialPermission for all
// the Subject's principals that are instances of principalClass
// the accCs is guaranteed to be a SubjectCodeSource
// because the earlier CodeSource.implies succeeded
try {
} catch (Exception e) {
"when expanding SELF permission: " +
e.toString());
}
}
if (principalSet == null) {
// error
}
int i = 0;
i++;
}
return info;
} else {
// build a PrivateCredentialPermission for every
// one of the current Subject's principals
// the accCs is guaranteed to be a SubjectCodeSource
// because the earlier CodeSource.implies succeeded
int i = 0;
i++;
}
return info;
}
}
/*
* Returns the signer certificates from the list of certificates associated
* with the given code source.
*
* The signer certificates are those certificates that were used to verify
* signed code originating from the codesource location.
*
* This method assumes that in the given code source, each signer
* certificate is followed by its supporting certificate chain
* (which may be empty), and that the signer certificate and its
* supporting certificate chain are ordered bottom-to-top (i.e., with the
* signer certificate first and the (root) certificate authority last).
*/
return null;
if (!(certs[i] instanceof X509Certificate))
return cs.getCertificates();
}
// Do we have to do anything?
int i = 0;
int count = 0;
count++;
i++;
}
i++;
}
// Done
return certs;
i = 0;
i++;
}
i++;
}
return userCerts;
}
boolean extractSignerCerts) {
try {
('/',
// remove trailing '*' because it causes canonicalization
// to fail on win32
boolean appendFileSep = false;
appendFileSep = true;
}
path = f.getCanonicalPath();
// reappend '*' to canonicalized filename (note that
// canonicalization may have removed trailing file
// separator, so we have to check for that, too)
(appendFileSep || f.isDirectory()))
} else {
}
if (cs instanceof SubjectCodeSource) {
if (extractSignerCerts) {
canonCs = new SubjectCodeSource
(scs.getSubject(),
scs.getPrincipals(),
} else {
canonCs = new SubjectCodeSource
(scs.getSubject(),
scs.getPrincipals(),
scs.getCertificates());
}
} else {
if (extractSignerCerts) {
} else {
cs.getCertificates());
}
}
} catch (IOException ioe) {
// leave codesource as it is, unless we have to extract its
// signer certificates
if (extractSignerCerts) {
if (!(cs instanceof SubjectCodeSource)) {
} else {
scs.getPrincipals(),
scs.getLocation(),
}
}
}
} else {
if (extractSignerCerts) {
if (!(cs instanceof SubjectCodeSource)) {
} else {
scs.getPrincipals(),
scs.getLocation(),
}
}
}
return canonCs;
}
/**
* Each entry in the policy configuration file is represented by a
* PolicyEntry object. <p>
*
* A PolicyEntry is a (CodeSource,Permission) pair. The
* CodeSource contains the (URL, PublicKey) that together identify
* where the Java bytecodes come from and who (if anyone) signed
* them. The URL could refer to localhost. The URL could also be
* null, meaning that this policy entry is given to all comers, as
* long as they match the signer field. The signer could be null,
* meaning the code is not signed. <p>
*
* The Permission contains the (Type, Name, Action) triplet. <p>
*
* For now, the Policy object retrieves the public key from the
* X.509 certificate on disk that corresponds to the signedBy
* alias specified in the Policy config file. For reasons of
* efficiency, the Policy object keeps a hashtable of certs already
* read in. This could be replaced by a secure internal key
* store.
*
* <p>
* For example, the entry
* <pre>
* permission java.io.File "/tmp", "read,write",
* signedBy "Duke";
* </pre>
* is represented internally
* <pre>
*
* FilePermission f = new FilePermission("/tmp", "read,write");
* PublicKey p = publickeys.get("Duke");
* URL u = InetAddress.getLocalHost();
* CodeBase c = new CodeBase( p, u );
* pe = new PolicyEntry(f, c);
* </pre>
*
* @author Marianne Mueller
* @author Roland Schemers
* @see java.security.CodeSource
* @see java.security.Policy
* @see java.security.Permissions
* @see java.security.ProtectionDomain
*/
private static class PolicyEntry {
/**
* Given a Permission and a CodeSource, create a policy entry.
*
* XXX policy entries
*
* @param cs the CodeSource, which encapsulates the URL and the public
* key
* attributes from the policy config file. Validity checks are
* performed on the public key before PolicyEntry is called.
*
*/
{
this.codesource = cs;
}
/**
* add a Permission object to this entry.
*/
}
/**
* Return the CodeSource for this policy entry
*/
return this.codesource;
}
}
}
}
}
{
this.codesource = codesource;
this.notInit = true;
this.additionalPerms = null;
}
if (isReadOnly())
throw new SecurityException
("attempt.to.add.a.Permission.to.a.readonly.PermissionCollection"));
if (additionalPerms == null)
} else {
}
}
private synchronized void init() {
if (notInit) {
perms = new Permissions();
if (additionalPerms != null) {
while (e.hasMoreElements()) {
}
}
notInit=false;
}
}
if (notInit)
init();
}
if (notInit)
init();
}
if (notInit)
init();
}
}