/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package javax.security.auth;
import java.security.
Security;
import java.security.
AccessController;
import java.security.
PrivilegedAction;
import java.security.
PrivilegedExceptionAction;
import java.util.
Objects;
import sun.security.util.
Debug;
/**
* <p> This is an abstract class for representing the system policy for
* Subject-based authorization. A subclass implementation
* of this class provides a means to specify a Subject-based
* access control {@code Policy}.
*
* <p> A {@code Policy} object can be queried for the set of
* Permissions granted to code running as a
* {@code Principal} in the following manner:
*
* <pre>
* policy = Policy.getPolicy();
* PermissionCollection perms = policy.getPermissions(subject,
* codeSource);
* </pre>
*
* The {@code Policy} object consults the local policy and returns
* and appropriate {@code Permissions} object with the
* Permissions granted to the Principals associated with the
* provided <i>subject</i>, and granted to the code specified
* by the provided <i>codeSource</i>.
*
* <p> A {@code Policy} contains the following information.
* Note that this example only represents the syntax for the default
* {@code Policy} implementation. Subclass implementations of this class
* may implement alternative syntaxes and may retrieve the
* {@code Policy} from any source such as files, databases,
* or servers.
*
* <p> Each entry in the {@code Policy} is represented as
* a <b><i>grant</i></b> entry. Each <b><i>grant</i></b> entry
* specifies a codebase, code signers, and Principals triplet,
* as well as the Permissions granted to that triplet.
*
* <pre>
* grant CodeBase ["URL"], Signedby ["signers"],
* Principal [Principal_Class] "Principal_Name" {
* Permission Permission_Class ["Target_Name"]
* [, "Permission_Actions"]
* [, signedBy "SignerName"];
* };
* </pre>
*
* The CodeBase and Signedby components of the triplet name/value pairs
* are optional. If they are not present, then any any codebase will match,
* and any signer (including unsigned code) will match.
* For Example,
*
* <pre>
* grant CodeBase "foo.com", Signedby "foo",
* Principal com.sun.security.auth.SolarisPrincipal "duke" {
* permission java.io.FilePermission "/home/duke", "read, write";
* };
* </pre>
*
* This <b><i>grant</i></b> entry specifies that code from "foo.com",
* signed by "foo', and running as a {@code SolarisPrincipal} with the
* name, duke, has one {@code Permission}. This {@code Permission}
* permits the executing code to read and write files in the directory,
* "/home/duke".
*
* <p> To "run" as a particular {@code Principal},
* code invokes the {@code Subject.doAs(subject, ...)} method.
* After invoking that method, the code runs as all the Principals
* associated with the specified {@code Subject}.
* Note that this {@code Policy} (and the Permissions
* granted in this {@code Policy}) only become effective
* after the call to {@code Subject.doAs} has occurred.
*
* <p> Multiple Principals may be listed within one <b><i>grant</i></b> entry.
* All the Principals in the grant entry must be associated with
* the {@code Subject} provided to {@code Subject.doAs}
* for that {@code Subject} to be granted the specified Permissions.
*
* <pre>
* grant Principal com.sun.security.auth.SolarisPrincipal "duke",
* Principal com.sun.security.auth.SolarisNumericUserPrincipal "0" {
* permission java.io.FilePermission "/home/duke", "read, write";
* permission java.net.SocketPermission "duke.com", "connect";
* };
* </pre>
*
* This entry grants any code running as both "duke" and "0"
* permission to read and write files in duke's home directory,
* as well as permission to make socket connections to "duke.com".
*
* <p> Note that non Principal-based grant entries are not permitted
* in this {@code Policy}. Therefore, grant entries such as:
*
* <pre>
* grant CodeBase "foo.com", Signedby "foo" {
* permission java.io.FilePermission "/tmp/scratch", "read, write";
* };
* </pre>
*
* are rejected. Such permission must be listed in the
* {@code java.security.Policy}.
*
* <p> The default {@code Policy} implementation can be changed by
* setting the value of the {@code auth.policy.provider} security property to
* the fully qualified name of the desired {@code Policy} implementation class.
*
* @deprecated as of JDK version 1.4 -- Replaced by java.security.Policy.
* java.security.Policy has a method:
* <pre>
* public PermissionCollection getPermissions
* (java.security.ProtectionDomain pd)
*
* </pre>
* and ProtectionDomain has a constructor:
* <pre>
* public ProtectionDomain
* (CodeSource cs,
* PermissionCollection permissions,
* ClassLoader loader,
* Principal[] principals)
* </pre>
*
* These two APIs provide callers the means to query the
* Policy for Principal-based Permission entries.
*
* @see java.security.Security security properties
*/
@
Deprecated
public abstract class
Policy {
private static
Policy policy;
private final static
String AUTH_POLICY =
"sun.security.provider.AuthPolicyFile";
private final java.security.
AccessControlContext acc =
java.security.
AccessController.
getContext();
// true if a custom (not AUTH_POLICY) system-wide policy object is set
private static boolean
isCustomPolicy;
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected
Policy() { }
/**
* Returns the installed Policy object.
* This method first calls
* {@code SecurityManager.checkPermission} with the
* {@code AuthPermission("getPolicy")} permission
* to ensure the caller has permission to get the Policy object.
*
* <p>
*
* @return the installed Policy. The return value cannot be
* {@code null}.
*
* @exception java.lang.SecurityException if the current thread does not
* have permission to get the Policy object.
*
* @see #setPolicy
*/
public static
Policy getPolicy() {
java.lang.
SecurityManager sm =
System.
getSecurityManager();
if (
sm != null)
sm.
checkPermission(new
AuthPermission("getPolicy"));
return
getPolicyNoCheck();
}
/**
* Returns the installed Policy object, skipping the security check.
*
* @return the installed Policy.
*
*/
static
Policy getPolicyNoCheck() {
if (
policy == null) {
synchronized(
Policy.class) {
if (
policy == null) {
String policy_class = null;
policy_class =
AccessController.
doPrivileged
(new
PrivilegedAction<
String>() {
public
String run() {
return java.security.
Security.
getProperty
("auth.policy.provider");
}
});
if (
policy_class == null) {
policy_class =
AUTH_POLICY;
}
try {
final
String finalClass =
policy_class;
Policy untrustedImpl =
AccessController.
doPrivileged(
new
PrivilegedExceptionAction<
Policy>() {
public
Policy run() throws
ClassNotFoundException,
InstantiationException,
IllegalAccessException {
Class<? extends
Policy>
implClass =
Class.
forName(
finalClass, false,
Thread.
currentThread().
getContextClassLoader()
).
asSubclass(
Policy.class);
return
implClass.
newInstance();
}
});
AccessController.
doPrivileged(
new
PrivilegedExceptionAction<
Void>() {
public
Void run() {
setPolicy(
untrustedImpl);
isCustomPolicy = !
finalClass.
equals(
AUTH_POLICY);
return null;
}
},
Objects.
requireNonNull(
untrustedImpl.
acc)
);
} catch (
Exception e) {
throw new
SecurityException
(sun.security.util.
ResourcesMgr.
getString
("unable.to.instantiate.Subject.based.policy"));
}
}
}
}
return
policy;
}
/**
* Sets the system-wide Policy object. This method first calls
* {@code SecurityManager.checkPermission} with the
* {@code AuthPermission("setPolicy")}
* permission to ensure the caller has permission to set the Policy.
*
* <p>
*
* @param policy the new system Policy object.
*
* @exception java.lang.SecurityException if the current thread does not
* have permission to set the Policy.
*
* @see #getPolicy
*/
public static void
setPolicy(
Policy policy) {
java.lang.
SecurityManager sm =
System.
getSecurityManager();
if (
sm != null)
sm.
checkPermission(new
AuthPermission("setPolicy"));
Policy.
policy =
policy;
// all non-null policy objects are assumed to be custom
isCustomPolicy =
policy != null ? true : false;
}
/**
* Returns true if a custom (not AUTH_POLICY) system-wide policy object
* has been set or installed. This method is called by
* SubjectDomainCombiner to provide backwards compatibility for
* developers that provide their own javax.security.auth.Policy
* implementations.
*
* @return true if a custom (not AUTH_POLICY) system-wide policy object
* has been set; false otherwise
*/
static boolean
isCustomPolicySet(
Debug debug) {
if (
policy != null) {
if (
debug != null &&
isCustomPolicy) {
debug.
println("Providing backwards compatibility for " +
"javax.security.auth.policy implementation: " +
policy.
toString());
}
return
isCustomPolicy;
}
// check if custom policy has been set using auth.policy.provider prop
String policyClass = java.security.
AccessController.
doPrivileged
(new java.security.
PrivilegedAction<
String>() {
public
String run() {
return
Security.
getProperty("auth.policy.provider");
}
});
if (
policyClass != null && !
policyClass.
equals(
AUTH_POLICY)) {
if (
debug != null) {
debug.
println("Providing backwards compatibility for " +
"javax.security.auth.policy implementation: " +
policyClass);
}
return true;
}
return false;
}
/**
* Retrieve the Permissions granted to the Principals associated with
* the specified {@code CodeSource}.
*
* <p>
*
* @param subject the {@code Subject}
* whose associated Principals,
* in conjunction with the provided
* {@code CodeSource}, determines the Permissions
* returned by this method. This parameter
* may be {@code null}. <p>
*
* @param cs the code specified by its {@code CodeSource}
* that determines, in conjunction with the provided
* {@code Subject}, the Permissions
* returned by this method. This parameter may be
* {@code null}.
*
* @return the Collection of Permissions granted to all the
* {@code Subject} and code specified in
* the provided <i>subject</i> and <i>cs</i>
* parameters.
*/
public abstract java.security.
PermissionCollection getPermissions
(
Subject subject,
java.security.
CodeSource cs);
/**
* Refresh and reload the Policy.
*
* <p>This method causes this object to refresh/reload its current
* Policy. This is implementation-dependent.
* For example, if the Policy object is stored in
* a file, calling {@code refresh} will cause the file to be re-read.
*
* <p>
*
* @exception SecurityException if the caller does not have permission
* to refresh the Policy.
*/
public abstract void
refresh();
}