BasePolicyWrapperpublic class BasePolicyWrapper extends Policy This class is a wrapper around the default jdk policy file
implementation. BasePolicyWrapper is installed as the JRE policy object
It multiples policy decisions to the context specific instance of
sun.security.provider.PolicyFile.
Although this Policy provider is implemented using another Policy class,
this class is not a "delegating Policy provider" as defined by JACC, and
as such it SHOULD not be configured using the JACC system property
javax.security.jacc.policy.provider. |
Fields Summary |
---|
private Policy | policy | private static Logger | logger | private static com.sun.enterprise.util.LocalStringManagerImpl | localStrings | private static final String | REUSE | private static final String | IGNORE_REENTRANCY_PROP_NAMEName of the system property to enable detecting and avoiding reentrancy.
This property can be set using in domain.xml. If not set
or set to false, this class will detect or avoid reentrancy in policy
evaluation. Note that if SecurityManager is turned off, this feature is
always turned off.
Another design approach is to name the property differently
and use a list of context ids as its value, so that this feature may be
enabled for selected contexts. | private static final boolean | avoidReentrancyFlag to indicate if detecting and avoiding reentrancy is enabled.
If SecurityManager is turned off, reentrancy is less likely to occur and
this feature is always off; else if the system property IGNORE_REENTRANCY_PROP_NAME
is not set, or set to false in domain.xml, this feature is on; | private static ThreadLocal | reentrancyStatusThreadLocal object to keep track of the reentrancy status of each thread.
It contains a byte[] object whose single element is either 0 (initial
value or no reentrancy), or 1 (current thread is reentrant). When a
thread exists the implies method, byte[0] is alwasy reset to 0. | private static final String | POLICYThis method repeats the policy file loading algorithm of
sun.security.provider.Policyfile to determine if the refresh
resulted in a change to the loaded policy.
Note:
For backward compatibility with JAAS 1.0 it loads
both java.auth.policy and java.policy. However it
is recommended that java.auth.policy be not used
and the java.policy contain all grant entries including
that contain principal-based entries.
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:
-
Loop through the
java.security.Security properties,
policy.url.1, policy.url.2, ...,
policy.url.X" and
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, where <JAVA_HOME>
refers to the directory where the JDK was installed.
Each property value specifies a URL pointing to a
policy file to be loaded. Read in and load each policy.
auth.policy.url is supported only for backward compatibility.
-
The
java.lang.System property java.security.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.
-
The
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.
java.security.auth.policy is supported only for backward
compatibility.
If the java.security.policy or
java.security.auth.policy property is defined using
"==" (rather than "="), then ignore all other specified
policies and only load this policy.
| private static final String | POLICY_URL | private static final String | AUTH_POLICY | private static final String | AUTH_POLICY_URL | private static final String | FORCE_APP_REFRESH_PROP_NAMEName of the system property that effects whether or not application
policy objects are forced to refresh whenever the default context
policy object is refreshed. Normally app policy objects only refresh
when their app sepcifc policy files have changes. Since app policy
objects alos include the rules of the default context; so they should
be refreshed whenever the default context files are changed, but the
algorithm by which a policy module finds its policy files is complex;
and dependent on configuration; so this force switch is provided to
ensure refresh of the app contexts (when the performace cost of doing
so is acceptable). When this switch is not set, it may be necessary
to restart the appserver to force changes in the various policy files to
be in effect for specific applications. | private static final boolean | forceAppRefreshFlag to indicate if application specific policy objects are forced
to refresh (independent of whether or not their app specific policy
files have changed). | private long | refreshTime |
Constructors Summary |
---|
public BasePolicyWrapper()Creates a new instance of BasePolicyWrapper
if(avoidReentrancy) {
reentrancyStatus = new ThreadLocal() {
protected synchronized Object initialValue() {
return new byte[]{0};
}
};
}
// the jdk policy file implementation
policy = getNewPolicy();
refreshTime = 0L;
// call the following routine to compute the actual refreshTime
defaultContextChanged();
|
Methods Summary |
---|
synchronized boolean | defaultContextChanged()
if (forceAppRefresh) {
return true;
}
long newTime = getTimeStamp(POLICY,POLICY_URL);
newTime += getTimeStamp(AUTH_POLICY,AUTH_POLICY_URL);
boolean rvalue = refreshTime != newTime;
refreshTime = newTime;
return rvalue;
| private boolean | doImplies(java.security.ProtectionDomain domain, java.security.Permission permission)
String contextId = PolicyContext.getContextID();
PolicyConfigurationImpl pci = getPolicyConfigForContext(contextId);
Policy appPolicy = getPolicy(pci);
boolean result = appPolicy.implies(domain,permission);
//log failures but skip failures that occurred prior to redirecting to
//login pages, and javax.management.MBeanPermission
if (!result) {
if(!(permission instanceof WebResourcePermission) &&
!(permission instanceof MBeanPermission) &&
!(permission instanceof WebRoleRefPermission) &&
!(permission instanceof EJBRoleRefPermission)) {
final String contextId2 = contextId;
final Permission permission2 = permission;
final ProtectionDomain domain2 = domain;
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
logger.info("JACC Policy Provider: PolicyWrapper.implies, context("
+ contextId2
+ ")- permission(" + permission2
+ ") domain that failed(" +domain2 + ")");
return null;
}
});
}
} else {
Permissions excluded = getExcludedPolicy(pci);
if (excluded != null) {
result = !grantedIsExcluded(permission,excluded);
}
}
// at FINEST: log only denies
if (!result && logger.isLoggable(Level.FINEST)){
logger.finest("JACC Policy Provider: PolicyWrapper.implies, context ("+
contextId+")- result was("+result+") permission ("
+permission+")");
}
return result;
| private static java.security.Permissions | getExcludedPolicy(PolicyConfigurationImpl pci)
Permissions result = null;
if (pci != null) {
result = pci.getExcludedPolicy();
}
return result;
| protected java.security.Policy | getNewPolicy()gets the underlying PolicyFile implementation
can be overridden by Subclass
return (java.security.Policy) new sun.security.provider.PolicyFile();
| public java.security.PermissionCollection | getPermissions(java.security.CodeSource codesource)Evaluates the global policy and returns a
PermissionCollection object specifying the set of
permissions allowed for code from the specified
code source.
String contextId = PolicyContext.getContextID();
PolicyConfigurationImpl pci = getPolicyConfigForContext(contextId);
Policy appPolicy = getPolicy(pci);
PermissionCollection perms = appPolicy.getPermissions(codesource);
if (perms != null) {
perms = removeExcludedPermissions(pci,perms);
}
if (logger.isLoggable(Level.FINEST)){
logger.finest("JACC Policy Provider: PolicyWrapper.getPermissions(cs), context ("+contextId+") codesource ("+codesource+") permissions: "+perms);
}
return perms;
| public java.security.PermissionCollection | getPermissions(java.security.ProtectionDomain domain)Evaluates the global policy and returns a
PermissionCollection object specifying the set of
permissions allowed given the characteristics of the
protection domain.
String contextId = PolicyContext.getContextID();
PolicyConfigurationImpl pci = getPolicyConfigForContext(contextId);
Policy appPolicy = getPolicy(pci);
PermissionCollection perms = appPolicy.getPermissions(domain);
if (perms != null) {
perms = removeExcludedPermissions(pci,perms);
}
if (logger.isLoggable(Level.FINEST)){
logger.finest("JACC Policy Provider: PolicyWrapper.getPermissions(d), context ("+contextId+") permissions: "+perms);
}
return perms;
| private java.security.Policy | getPolicy(PolicyConfigurationImpl pci)
Policy result = null;
if (pci == null) {
result = policy;
} else {
result = pci.getPolicy();
if (result == null) {
// the pc is not in service so use the default context
result = policy;
}
}
return result;
| private static PolicyConfigurationImpl | getPolicyConfigForContext(java.lang.String contextId)
PolicyConfigurationImpl pci = null;
if (contextId != null) {
pci = PolicyConfigurationFactoryImpl.getPolicyConfigurationImpl(contextId);
}
return pci;
| private static long | getTimeStamp(java.lang.String propname, java.lang.String urlname)
Long l = (Long) AccessController.doPrivileged(new PrivilegedAction() {
public Long run() {
long sum = 0L;
boolean allowSystemProperties = "true".equalsIgnoreCase
(Security.getProperty("policy.allowSystemProperty"));
if (allowSystemProperties) {
String extra_policy = System.getProperty(propname);
if (extra_policy != null) {
boolean overrideAll = false;
if (extra_policy.startsWith("=")) {
overrideAll = true;
extra_policy = extra_policy.substring(1);
}
try {
String path =PropertyExpander.expand(extra_policy);
File policyFile = new File(path);
boolean found = policyFile.exists();
if (!found) {
URL policy_url = new URL(path);
if ("file".equals(policy_url.getProtocol())) {
path = policy_url.getFile().
replace('/", File.separatorChar);
path = sun.net.www.ParseUtil.decode(path);
policyFile = new File(path);
found = policyFile.exists();
}
}
if (found) {
sum += policyFile.lastModified();
if (logger.isLoggable(Level.FINE)) {
logMsg(Level.FINE,"pc.file_refreshed",
new Object[]{path},null);
}
} else {
if (logger.isLoggable(Level.FINE)) {
logMsg(Level.FINE,"pc.file_not_refreshed",
new Object[]{path},null);
}
}
} catch (Exception e) {
// ignore.
}
if (overrideAll) {
return new Long(sum);
}
}
}
int n = 1;
String policy_uri;
while ((policy_uri = Security.getProperty(urlname+n)) != null){
try {
URL policy_url = null;
String expanded_uri = PropertyExpander.expand
(policy_uri).replace(File.separatorChar, '/");
if (policy_uri.startsWith("file:${java.home}/") ||
policy_uri.startsWith("file:${user.home}/")) {
// this special case accommodates
// the situation java.home/user.home
// expand to a single slash, resulting in
// a file://foo URI
policy_url = new File
(expanded_uri.substring(5)).toURI().toURL();
} else {
policy_url = new URI(expanded_uri).toURL();
}
if ("file".equals(policy_url.getProtocol())) {
String path = policy_url.getFile().
replace('/", File.separatorChar);
path = sun.net.www.ParseUtil.decode(path);
File policyFile = new File(path);
if (policyFile.exists()) {
sum += policyFile.lastModified();
if (logger.isLoggable(Level.FINE)) {
logMsg(Level.FINE,"pc.file_refreshed",
new Object[]{path},null);
}
} else {
if (logger.isLoggable(Level.FINE)) {
logMsg(Level.FINE,"pc.file_not_refreshed",
new Object[]{path},null);
}
}
} else {
if (logger.isLoggable(Level.FINE)) {
logMsg(Level.FINE,"pc.file_not_refreshed",
new Object[]{policy_url},null);
}
}
} catch (Exception e) {
// ignore that policy
}
n++;
}
return new Long(sum);
}
});
return l.longValue();
| private static boolean | grantedIsExcluded(java.security.Permission granted, java.security.Permissions excluded)
boolean isExcluded = false;
if (excluded != null) {
if (!excluded.implies(granted)) {
Enumeration e = excluded.elements();
while (!isExcluded && e.hasMoreElements()) {
Permission excludedPerm = (Permission) e.nextElement();
if (granted.implies(excludedPerm)) {
isExcluded = true;
}
}
} else {
isExcluded = true;
}
}
if (logger.isLoggable(Level.FINEST)){
if (isExcluded) {
logger.finest("JACC Policy Provider: permission is excluded: "+granted);
}
}
return isExcluded;
| public boolean | implies(java.security.ProtectionDomain domain, java.security.Permission permission)Evaluates the global policy for the permissions granted to
the ProtectionDomain and tests whether the permission is
granted.
if(avoidReentrancy) {
byte[] alreadyCalled = (byte[]) reentrancyStatus.get();
if(alreadyCalled[0] == 1) {
return true;
} else {
alreadyCalled[0] = 1;
try {
return doImplies(domain, permission);
} finally {
alreadyCalled[0] = 0;
}
}
} else {
return doImplies(domain, permission);
}
| static java.lang.String | logMsg(java.util.logging.Level level, java.lang.String key, java.lang.Object[] params, java.lang.String defMsg)
String msg = (key == null ? defMsg : localStrings.getLocalString
(key,defMsg == null ? key : defMsg, params));
logger.log(level,msg);
return msg;
| public void | refresh()Refreshes/reloads the policy configuration. The behavior of this method
depends on the implementation. For example, calling refresh
on a file-based policy will cause the file to be re-read.
if (logger.isLoggable(Level.FINE)){
logger.fine("JACC Policy Provider: Refreshing Policy files!");
}
// always refreshes default policy context, but refresh
// of application context depends on PolicyConfigurationImpl
// this could result in an inconsistency since default context is
// included in application contexts.
policy.refresh();
// try to determine if default policy context has changed.
// if so, force refresh of application contexts.
// if the following code is not robust enough to detect
// changes to the policy files read by the default context,
// then you can configure the provider to force on every refresh
// (see FORCE_APP_REFRESH_PROP_NAME).
boolean force = defaultContextChanged();
PolicyConfigurationImpl pciArray[]
= PolicyConfigurationFactoryImpl.getPolicyConfigurationImpls();
if (pciArray != null) {
for (PolicyConfigurationImpl pci : pciArray) {
if (pci != null) {
// false means don't force refresh if no update since
// last refresh.
pci.refresh(force);
}
}
}
try {
if (PolicyContext.getHandlerKeys().contains(REUSE)) {
PolicyContext.getContext(REUSE);
}
} catch(PolicyContextException pe) {
throw new IllegalStateException(pe.toString());
}
| private static java.security.PermissionCollection | removeExcludedPermissions(PolicyConfigurationImpl pci, java.security.PermissionCollection perms)
PermissionCollection result = perms;
boolean noneRemoved = true;
Permissions excluded = getExcludedPolicy(pci);
if (excluded != null && excluded.elements().hasMoreElements()) {
result = null;
Enumeration e = perms.elements();
while (e.hasMoreElements()) {
Permission granted = (Permission) e.nextElement();
if (!grantedIsExcluded(granted,excluded)) {
if (result == null) result = new Permissions();
result.add(granted);
} else {
noneRemoved = false;
}
}
if (noneRemoved) {
result = perms;
}
}
return result;
|
|