add in debugging for jettyPolicy that outputs to system.out since normal logging is not appropriate for this sort of goop

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@723 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Jesse McConnell 2009-08-14 17:55:35 +00:00
parent c8414e5ed1
commit bcc8a456fc

View File

@ -20,6 +20,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.security.AccessControlException;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
@ -27,151 +28,216 @@ import java.security.Permissions;
import java.security.Policy;
import java.security.Principal;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jetty.policy.loader.DefaultPolicyLoader;
import org.eclipse.jetty.util.Scanner;
/**
* Policy implementation that will load a set of policy files and manage the mapping of permissions and protection domains
* Policy implementation that will load a set of policy files and manage the mapping of permissions and protection domains
*
* The reason I created this class and added this mechanism are:
*
* 1) I wanted a way to be able to follow the startup mechanic that jetty uses with jetty-start using OPTIONS=policy,default
* to be able to startup a security manager and policy implementation without have to rely on the existing JVM cli options
* 2) establish a starting point to add on further functionality to permissions based security with jetty like jmx enabled
* permission tweaking or runtime creation and specification of policies for specific webapps
* 3) I wanted to have support for specifying multiple policy files to source permissions from
* 1) I wanted a way to be able to follow the startup mechanic that jetty uses with jetty-start using OPTIONS=policy,default to be able to startup a security manager and policy implementation without have to rely on the existing JVM cli options 2)
* establish a starting point to add on further functionality to permissions based security with jetty like jmx enabled permission tweaking or runtime creation and specification of policies for specific webapps 3) I wanted to have support for specifying
* multiple policy files to source permissions from
*
* Possible additions are:
* - directories of policy file support
* - jmx enabled a la #2 above
* - proxying of system security policy where we can proxy access to the system policy should the jvm have been started with
* one, I had support for this but ripped it out to add in again later
* - merging of protection domains if process multiple policy files that declare permissions for the same codebase
* - an xml policy file parser, had originally added this using modello but tore it out since it would have been
* a nightmare to get its dependencies through IP validation, could do this with jvm xml parser instead sometime
* - check performance of the synch'd map I am using for the protection domain mapping
* Possible additions are: - directories of policy file support - jmx enabled a la #2 above - proxying of system security policy where we can proxy access to the system policy should the jvm have been started with one, I had support for this but ripped it
* out to add in again later - merging of protection domains if process multiple policy files that declare permissions for the same codebase - an xml policy file parser, had originally added this using modello but tore it out since it would have been a
* nightmare to get its dependencies through IP validation, could do this with jvm xml parser instead sometime - check performance of the synch'd map I am using for the protection domain mapping
*/
public class JettyPolicy extends Policy
{
private static boolean __DEBUG = false;
// Policy files that are actively managed by the aggregate policy mechanism
private final Set<String> _policies;
private final Map<ProtectionDomain, PolicyBlock> pdMapping =
Collections.synchronizedMap( new HashMap<ProtectionDomain, PolicyBlock>() );
private final Map<ProtectionDomain, PolicyBlock> pdMapping = Collections.synchronizedMap(new HashMap<ProtectionDomain, PolicyBlock>());
private final Map<Object, PermissionCollection> _cache = new HashMap<Object, PermissionCollection>(); // Object can be ProtectionDomain or CodeSource
private final PolicyContext _context = new PolicyContext();
// private final Scanner scanner = new Scanner();
private final Scanner scanner = new Scanner();
private boolean initialized = false;
public JettyPolicy( Set<String> policies, Map<String,String> properties )
public JettyPolicy(Set<String> policies, Map<String, String> properties)
{
try
{
__DEBUG = Boolean.getBoolean("org.eclipse.jetty.policy.DEBUG");
}
catch (AccessControlException ace)
{
__DEBUG = false;
}
_policies = policies;
_context.setProperties( properties );
_context.setProperties(properties);
refresh();
}
@Override
public PermissionCollection getPermissions( ProtectionDomain domain )
{
PermissionCollection perms = new Permissions();
for ( Iterator<ProtectionDomain> i = pdMapping.keySet().iterator(); i.hasNext(); )
public PermissionCollection getPermissions(ProtectionDomain domain)
{
if (!initialized)
{
ProtectionDomain pd = i.next();
// System.out.println("----START----");
// System.out.println("PDCS: " + pd.getCodeSource());
// System.out.println("CS: " + domain.getCodeSource());
synchronized (this)
{
refresh();
}
}
if (pd.getCodeSource() == null || pd.getCodeSource().implies(domain.getCodeSource()) && pd.getPrincipals() == null || pd.getCodeSource().implies(domain.getCodeSource()) && validate(pd.getPrincipals(),domain.getPrincipals()))
{
// gather dynamic permissions
if ( pdMapping.get( pd ) != null )
if (_cache.containsKey(domain))
{
if (__DEBUG)
{
System.out.println("Pulling from a cache for " + domain.getCodeSource().getLocation() + " with " + _cache.size() + " entries");
}
return _cache.get(domain);
}
else
{
PermissionCollection perms = new Permissions();
for (Iterator<ProtectionDomain> i = pdMapping.keySet().iterator(); i.hasNext();)
{
ProtectionDomain pd = i.next();
if (__DEBUG)
{
for ( Enumeration<Permission> e = pdMapping.get( pd ).getPermissions().elements(); e.hasMoreElements(); )
System.out.println("----START----");
System.out.println("PDCS: " + pd.getCodeSource());
System.out.println("CS: " + domain.getCodeSource());
}
if (pd.getCodeSource() == null || pd.getCodeSource().implies(domain.getCodeSource()) && pd.getPrincipals() == null || pd.getCodeSource().implies(domain.getCodeSource()) && validate(pd.getPrincipals(),domain.getPrincipals()))
{
// gather dynamic permissions
if (pdMapping.get(pd) != null)
{
Permission perm = e.nextElement();
// System.out.println("D: " + perm);
perms.add(perm);
for (Enumeration<Permission> e = pdMapping.get(pd).getPermissions().elements(); e.hasMoreElements();)
{
Permission perm = e.nextElement();
if (__DEBUG)
{
System.out.println("D: " + perm);
}
perms.add(perm);
}
}
}
if (__DEBUG)
{
System.out.println("----STOP----");
}
}
// System.out.println("----STOP----");
_cache.put(domain,perms);
return perms;
}
return perms;
}
@Override
public PermissionCollection getPermissions( CodeSource codesource )
public PermissionCollection getPermissions(CodeSource codesource)
{
PermissionCollection perms = new Permissions();
for ( Iterator<ProtectionDomain> i = pdMapping.keySet().iterator(); i.hasNext(); )
if (!initialized)
{
ProtectionDomain pd = i.next();
if ( pd.getCodeSource() == null || pd.getCodeSource().implies( codesource ) )
synchronized (this)
{
// System.out.println("----START----");
// System.out.println("PDCS: " + pd.getCodeSource());
// System.out.println("CS: " + codesource);
// gather dynamic permissions
if ( pdMapping.get( pd ) != null )
{
for ( Enumeration<Permission> e = pdMapping.get( pd ).getPermissions().elements(); e.hasMoreElements(); )
{
Permission perm = e.nextElement();
// System.out.println("D: " + perm);
perms.add(perm);
}
}
// System.out.println("----STOP----");
refresh();
}
}
return perms;
if (_cache.containsKey(codesource))
{
if (__DEBUG)
{
System.out.println("Pulling from a cache for " + codesource.getLocation() + " with " + _cache.size() + " entries");
}
return _cache.get(codesource);
}
else
{
PermissionCollection perms = new Permissions();
for (Iterator<ProtectionDomain> i = pdMapping.keySet().iterator(); i.hasNext();)
{
ProtectionDomain pd = i.next();
if (pd.getCodeSource() == null || pd.getCodeSource().implies(codesource))
{
if (__DEBUG)
{
System.out.println("----START----");
System.out.println("PDCS: " + pd.getCodeSource());
System.out.println("CS: " + codesource);
}
// gather dynamic permissions
if (pdMapping.get(pd) != null)
{
for (Enumeration<Permission> e = pdMapping.get(pd).getPermissions().elements(); e.hasMoreElements();)
{
Permission perm = e.nextElement();
if (__DEBUG)
{
System.out.println("D: " + perm);
}
perms.add(perm);
}
}
if (__DEBUG)
{
System.out.println("----STOP----");
}
}
}
_cache.put(codesource,perms);
return perms;
}
}
private static boolean validate( Principal[] permCerts, Principal[] classCerts )
private static boolean validate(Principal[] permCerts, Principal[] classCerts)
{
if ( classCerts == null )
if (classCerts == null)
{
return false;
}
for ( int i = 0; i < permCerts.length; ++i )
for (int i = 0; i < permCerts.length; ++i)
{
boolean found = false;
for ( int j = 0; j < classCerts.length; ++j )
boolean found = false;
for (int j = 0; j < classCerts.length; ++j)
{
if ( permCerts[i].equals( classCerts[j] ) )
if (permCerts[i].equals(classCerts[j]))
{
found = true;
break;
}
}
// if we didn't find the permCert in the classCerts then we don't match up
if ( found == false )
if (found == false)
{
return false;
}
}
return true;
}
@Override
public void refresh()
{
@ -183,70 +249,100 @@ public class JettyPolicy extends Policy
initialize();
}
// System.out.println("refreshing policy files");
if (__DEBUG)
{
System.out.println("refreshing policy files");
}
pdMapping.clear();
for ( Iterator<String> i = _policies.iterator(); i.hasNext(); )
for (Iterator<String> i = _policies.iterator(); i.hasNext();)
{
File policyFile = new File( i.next() );
pdMapping.putAll( DefaultPolicyLoader.load( new FileInputStream( policyFile ), _context ) );
File policyFile = new File(i.next());
pdMapping.putAll(DefaultPolicyLoader.load(new FileInputStream(policyFile),_context));
}
// System.setSecurityManager(null);
// Policy.setPolicy(null);
// Policy.setPolicy(this);
// System.setSecurityManager(new SecurityManager());
if (__DEBUG)
{
System.out.println("refreshing policy files");
// for (Iterator<ProtectionDomain> i = pdMapping.keySet().iterator(); i.hasNext();)
// {
// System.out.println(i.next().toString());
// }
synchronized (this)
{
_cache.clear();
System.setSecurityManager(null);
Policy.setPolicy(null);
Policy.setPolicy(this);
System.setSecurityManager(new SecurityManager());
}
// System.setSecurityManager(null);
// Policy.setPolicy(null);
// Policy.setPolicy(this);
// System.setSecurityManager(new SecurityManager());
for (Iterator<ProtectionDomain> i = pdMapping.keySet().iterator(); i.hasNext();)
{
System.out.println(i.next().toString());
}
System.out.println("finished reloading policies");
}
}
catch ( Exception e )
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* TODO make this optional
*/
private void initialize() throws Exception
{
/*
* List scanDirs = new ArrayList();
*
* for (Iterator<String> i = _policies.iterator(); i.hasNext();) { File policyFile = new File(i.next()); scanDirs.add(policyFile.getParentFile()); }
*
* scanner.addListener(new Scanner.DiscreteListener() {
*
* public void fileRemoved(String filename) throws Exception { // TODO Auto-generated method stub
*
* }
*
* public void fileChanged(String filename) throws Exception { refresh(); }
*
* public void fileAdded(String filename) throws Exception { // TODO Auto-generated method stub
*
* } });
*
* scanner.setScanDirs(scanDirs); scanner.start(); scanner.setScanInterval(10);
*/
List scanDirs = new ArrayList();
for (Iterator<String> i = _policies.iterator(); i.hasNext();)
{
File policyFile = new File(i.next());
scanDirs.add(policyFile.getParentFile());
}
scanner.addListener(new Scanner.DiscreteListener()
{
public void fileRemoved(String filename) throws Exception
{ // TODO Auto-generated method stub
}
public void fileChanged(String filename) throws Exception
{
refresh();
}
public void fileAdded(String filename) throws Exception
{ // TODO Auto-generated method stub
}
});
scanner.setScanDirs(scanDirs);
scanner.start();
scanner.setScanInterval(10);
initialized = true;
}
public void dump( PrintStream out )
public void dump(PrintStream out)
{
PrintWriter write = new PrintWriter( out );
PrintWriter write = new PrintWriter(out);
write.println("dumping policy settings");
for( Iterator<ProtectionDomain> i = pdMapping.keySet().iterator(); i.hasNext(); )
for (Iterator<ProtectionDomain> i = pdMapping.keySet().iterator(); i.hasNext();)
{
ProtectionDomain domain = i.next();
PolicyBlock block = pdMapping.get( domain );
write.println(domain.toString());
PolicyBlock block = pdMapping.get(domain);
write.println(domain.toString());
}
write.flush();
}