static AccessControlContext getContext() {
// If we are already in getContext, but called a method that needs
// a permission check, return the all-permissive context so methods
// called from here succeed.
//
// XXX is this necessary? We should verify if there are any calls in
// the stack below this method that require permission checks.
Boolean inCall = (Boolean) inGetContext.get();
if (inCall != null && inCall.booleanValue())
{
if (DEBUG)
debug("already in getContext");
return DEFAULT_CONTEXT;
}
inGetContext.set(Boolean.TRUE);
Object[][] stack = getStack();
Class[] classes = (Class[]) stack[0];
String[] methods = (String[]) stack[1];
if (DEBUG)
debug("got trace of length " + classes.length);
HashSet domains = new HashSet();
HashSet seenDomains = new HashSet();
AccessControlContext context = null;
int privileged = 0;
// We walk down the stack, adding each ProtectionDomain for each
// class in the call stack. If we reach a call to doPrivileged,
// we don't add any more stack frames. We skip the first three stack
// frames, since they comprise the calls to getStack, getContext,
// and AccessController.getContext.
for (int i = 3; i < classes.length && privileged < 2; i++)
{
Class clazz = classes[i];
String method = methods[i];
if (DEBUG)
{
debug("checking " + clazz + "." + method);
// subject to getClassLoader RuntimePermission
debug("loader = " + clazz.getClassLoader());
}
// If the previous frame was a call to doPrivileged, then this is
// the last frame we look at.
if (privileged == 1)
privileged = 2;
if (clazz.equals (AccessController.class)
&& method.equals ("doPrivileged"))
{
// If there was a call to doPrivileged with a supplied context,
// return that context. If using JAAS doAs*, it should be
// a context with a SubjectDomainCombiner
LinkedList l = (LinkedList) contexts.get();
if (l != null)
context = (AccessControlContext) l.getFirst();
privileged = 1;
}
// subject to getProtectionDomain RuntimePermission
ProtectionDomain domain = clazz.getProtectionDomain();
if (domain == null)
continue;
if (seenDomains.contains(domain))
continue;
seenDomains.add(domain);
// Create a static snapshot of this domain, which may change over time
// if the current policy changes.
domains.add(new ProtectionDomain(domain.getCodeSource(),
domain.getPermissions()));
}
if (DEBUG)
debug("created domains: " + domains);
ProtectionDomain[] result = (ProtectionDomain[])
domains.toArray(new ProtectionDomain[domains.size()]);
if (context != null)
{
DomainCombiner dc = context.getDomainCombiner ();
// If the supplied context had no explicit DomainCombiner, use
// our private version, which computes the intersection of the
// context's domains with the derived set.
if (dc == null)
context = new AccessControlContext
(IntersectingDomainCombiner.SINGLETON.combine
(result, context.getProtectionDomains ()));
// Use the supplied DomainCombiner. This should be secure,
// because only trusted code may create an
// AccessControlContext with a custom DomainCombiner.
else
context = new AccessControlContext (result, context, dc);
}
// No context was supplied. Return the derived one.
else
context = new AccessControlContext (result);
inGetContext.set(Boolean.FALSE);
return context;
}
|