/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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.
*/
package com.sun.security.auth;
import java.io.*;
import java.lang.RuntimePermission;
import java.lang.reflect.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.Permission;
import java.security.Permissions;
import java.security.PermissionCollection;
import java.security.Principal;
import java.security.UnresolvedPermission;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import javax.security.auth.Subject;
import javax.security.auth.PrivateCredentialPermission;
import sun.security.util.PropertyExpander;
/**
* This class represents a default implementation for
* javax.security.auth.Policy
.
*
*
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 Policy
object is:
*
*
java.security.Security
properties,
* auth.policy.url.1, auth.policy.url.2, ...,
* auth.policy.url.X". 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 URL
pointing to a
* policy file to be loaded. Read in and load each policy.
*
* java.lang.System
property java.security.auth.policy
* may also be set to a URL
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,
* policy.allowSystemProperty is set to true),
* also load that policy.
*
* * grant signedBy "alias", codeBase "URL", * principal principalClass "principalName", * principal principalClass "principalName", * ... { * * permission Type "name "action", * signedBy "alias"; * permission Type "name "action", * signedBy "alias"; * .... * }; ** * 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. * *
A grant entry must begin with the word grant
.
* The signedBy
and codeBase
* name/value pairs are optional.
* If they are not present, then any signer (including unsigned code)
* will match, and any codeBase will match. Note that the
* principal
name/value pair is not optional.
* This Policy
implementation only permits
* Principal-based grant entries. Note that the principalClass
* may be set to the wildcard value, *, which allows it to match
* any Principal
class. In addition, the principalName
* may also be set to the wildcard value, *, allowing it to match
* any Principal
name. When setting the principalName
* to the *, do not surround the * with quotes.
*
*
A permission entry must begin with the word permission
.
* The word Type
in the template above is
* a specific permission type, such as java.io.FilePermission
* or java.lang.RuntimePermission
.
*
*
The "action" is required for
* many permission types, such as java.io.FilePermission
* (where it specifies what type of file access that is permitted).
* It is not required for categories such as
* java.lang.RuntimePermission
* where it is not necessary - you either have the
* permission specified by the "name"
* value following the type name or you don't.
*
*
The signedBy
name/value pair for a permission entry
* 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:
*
*
* grant principal foo.com.Principal "Duke" { * permission Foo "foobar", signedBy "FooSoft"; * } ** *
Then this permission of type Foo is granted if the
* Foo.class
permission has been signed by the
* "FooSoft" alias, or if Foo.class
is a
* system class (i.e., is found on the CLASSPATH).
*
*
Items that appear in an entry must appear in the specified order
* (permission
, Type, "name", and
* "action"). An entry is terminated with a semicolon.
*
*
Case is unimportant for the identifiers (permission
,
* signedBy
, codeBase
, etc.) but is
* significant for the Type
* or for any string that is passed in as a value.
* *
An example of two entries in a policy configuration file is *
* // if the code is comes from "foo.com" and is running as "Duke", * // grant it read/write to all files in /tmp. * * 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"; ** *
This Policy
implementation supports
* special handling for PrivateCredentialPermissions.
* If a grant entry is configured with a
* PrivateCredentialPermission
,
* and the "Principal Class/Principal Name" for that
* PrivateCredentialPermission
is "self",
* then the entry grants the specified Subject
permission to
* access its own private Credential. For example,
* the following grants the Subject
"Duke"
* access to its own a.b.Credential.
*
*
* grant principal foo.com.Principal "Duke" { * permission javax.security.auth.PrivateCredentialPermission * "a.b.Credential self", * "read"; * }; ** * The following grants the
Subject
"Duke"
* access to all of its own private Credentials:
*
* * grant principal foo.com.Principal "Duke" { * permission javax.security.auth.PrivateCredentialPermission * "* self", * "read"; * }; ** * The following grants all Subjects authenticated as a *
SolarisPrincipal
(regardless of their respective names)
* permission to access their own private Credentials:
*
* * grant principal com.sun.security.auth.SolarisPrincipal * { * permission javax.security.auth.PrivateCredentialPermission * "* self", * "read"; * }; ** * The following grants all Subjects permission to access their own * private Credentials: * *
* grant principal * * { * permission javax.security.auth.PrivateCredentialPermission * "* self", * "read"; * }; ** @deprecated As of JDK 1.4, replaced by *
sun.security.provider.PolicyFile
.
* This class is entirely deprecated.
*
* @see java.security.CodeSource
* @see java.security.Permissions
* @see java.security.ProtectionDomain
*/
@Deprecated
public class PolicyFile extends javax.security.auth.Policy {
static final java.util.ResourceBundle rb =
java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction
*
* @exception SecurityException if the caller doesn't have permission
* to refresh the Permissions for a particular grant entry are returned
* if the The
* Note that this
*
* @param subject the Permissions granted to this
*
* @param codesource the Permissions granted to this
*
* @param p check to see if this Permission is a "SELF"
* PrivateCredentialPermission.
*
* @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.
*/
private boolean addSelfPermissions(final Permission p,
CodeSource entryCs,
CodeSource accCs,
Permissions perms) {
if (!(p instanceof PrivateCredentialPermission))
return false;
if (!(entryCs instanceof SubjectCodeSource))
return false;
PrivateCredentialPermission pcp = (PrivateCredentialPermission)p;
SubjectCodeSource scs = (SubjectCodeSource)entryCs;
// see if it is a SELF permission
String[][] pPrincipals = pcp.getPrincipals();
if (pPrincipals.length <= 0 ||
!pPrincipals[0][0].equalsIgnoreCase("self") ||
!pPrincipals[0][1].equalsIgnoreCase("self")) {
// regular PrivateCredentialPermission
return false;
} else {
// granted a SELF permission - create a
// PrivateCredentialPermission for each
// of the Policy entry's CodeSource Principals
if (scs.getPrincipals() == null) {
// XXX SubjectCodeSource has no Subject???
return true;
}
ListIterator
*
* 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.
*
* The Permission contains the (Type, Name, Action) triplet.
*
* 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.
*
*
* For example, the entry
* Policy
.
*/
public synchronized void refresh()
{
java.lang.SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new javax.security.auth.AuthPermission
("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;
java.security.AccessController.doPrivileged
(new java.security.PrivilegedActionClass.forName
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.
*
*/
private static final Permission getInstance(String type,
String name,
String actions)
throws ClassNotFoundException,
InstantiationException,
IllegalAccessException,
NoSuchMethodException,
InvocationTargetException
{
//XXX we might want to keep a hash of created factories...
Class pc = Class.forName(type);
Constructor c = pc.getConstructor(PARAMS);
return (Permission) c.newInstance(new Object[] { name, actions });
}
/**
* Fetch all certs associated with this alias.
*/
Certificate[] getCertificates(
KeyStore keyStore, String aliases) {
VectorPolicy
and returns the Permissions granted
* to the specified Subject
and CodeSource
.
*
* CodeSource
constructed using the codebase and
* signedby values specified in the entry implies
* the CodeSource
provided to this method, and if the
* Subject
provided to this method contains all of the
* Principals specified in the entry.
*
* Subject
provided to this method contains all
* of the Principals specified in the entry if, for each
* Principal
, "P1", specified in the grant entry
* one of the following two conditions is met:
*
*
*
*
* Subject
has a
* Principal
, "P2", where
* P2.getClass().getName()
equals the
* P1's class name, and where
* P2.getName()
equals the P1's name.
*
* com.sun.security.auth.PrincipalComparator
,
* and P1.implies
the provided Subject
.
* Policy
implementation has
* special handling for PrivateCredentialPermissions.
* When this method encounters a PrivateCredentialPermission
* which specifies "self" as the Principal
class and name,
* it does not add that Permission
to the returned
* PermissionCollection
. Instead, it builds
* a new PrivateCredentialPermission
* for each Principal
associated with the provided
* Subject
. Each new PrivateCredentialPermission
* contains the same Credential class as specified in the
* originally granted permission, as well as the Class and name
* for the respective Principal
.
*
* Subject
* and the additionally provided CodeSource
* are returned. CodeSource
* and the additionally provided Subject
* are returned.
*
* @return the Permissions granted to the provided Subject
* CodeSource
.
*/
public PermissionCollection getPermissions(final Subject subject,
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.
return java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction
* permission java.io.File "/tmp", "read,write",
* signedBy "Duke";
*
* is represented internally
*
*
* 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);
*
*
* @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 {
CodeSource codesource;
Vector