FileDocCategorySizeDatePackage
BasePolicyWrapper.javaAPI DocGlassfish v2 API23494Tue Aug 14 14:23:16 BST 2007com.sun.enterprise.security.provider

BasePolicyWrapper

public 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.
author
Harpreet Singh (harpreet.singh@sun.com)
author
Jean-Francois Arcand
author
Ron Monzillo

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_NAME
Name 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
avoidReentrancy
Flag 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
reentrancyStatus
ThreadLocal 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
POLICY
This 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:

  1. 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.
  2. 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.
  3. 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_NAME
Name 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
forceAppRefresh
Flag 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 booleandefaultContextChanged()


       

	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 booleandoImplies(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.PermissionsgetExcludedPolicy(PolicyConfigurationImpl pci)

	Permissions result = null;
	if (pci != null) {
	    result = pci.getExcludedPolicy();
	}
	return result;
    
protected java.security.PolicygetNewPolicy()
gets the underlying PolicyFile implementation can be overridden by Subclass

	return (java.security.Policy) new sun.security.provider.PolicyFile();
    
public java.security.PermissionCollectiongetPermissions(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.

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 allowed for code from codesource according to the policy.The returned set of permissions must be a new mutable instance and it must support heterogeneous Permission types.

	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.PermissionCollectiongetPermissions(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.

param
domain the ProtectionDomain associated with the caller.
return
the set of permissions allowed for the domain according to the policy.The returned set of permissions must be a new mutable instance and it must support heterogeneous Permission types.
see
java.security.ProtectionDomain
see
java.security.SecureClassLoader
since
1.4

	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.PolicygetPolicy(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 PolicyConfigurationImplgetPolicyConfigForContext(java.lang.String contextId)

	PolicyConfigurationImpl pci = null;
	if (contextId != null) {
	    pci = PolicyConfigurationFactoryImpl.getPolicyConfigurationImpl(contextId);
	}
	return pci;
    
private static longgetTimeStamp(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 booleangrantedIsExcluded(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 booleanimplies(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.

param
domain the ProtectionDomain to test
param
permission the Permission object to be tested for implication.
return
true if "permission" is a proper subset of a permission granted to this ProtectionDomain.
see
java.security.ProtectionDomain
since
1.4

        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.StringlogMsg(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 voidrefresh()
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.PermissionCollectionremoveExcludedPermissions(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;