refactored policy parsing for clarity and to decompose the more complex resolveFoo mechanic

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@443 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Jesse McConnell 2009-06-30 04:15:01 +00:00
parent d71050fa73
commit 1d13e96704
12 changed files with 810 additions and 445 deletions

View File

@ -59,13 +59,15 @@ public class JettyPolicy extends Policy
private PropertyEvaluator _evaluator; private PropertyEvaluator _evaluator;
private Map<ProtectionDomain, PermissionCollection> pdMapping = private Map<ProtectionDomain, PolicyEntry> pdMapping =
Collections.synchronizedMap( new HashMap<ProtectionDomain, PermissionCollection>() ); Collections.synchronizedMap( new HashMap<ProtectionDomain, PolicyEntry>() );
private PolicyContext _context = new PolicyContext();
public JettyPolicy( Set<String> policies, Map<String,String> properties ) public JettyPolicy( Set<String> policies, Map<String,String> properties )
{ {
_policies = policies; _policies = policies;
_evaluator = new PropertyEvaluator( properties ); _context.setEvaluator( new PropertyEvaluator( properties ) );
// we have the policies we need and an evaluator to reference, lets refresh and save the user a call. // we have the policies we need and an evaluator to reference, lets refresh and save the user a call.
refresh(); refresh();
@ -84,7 +86,7 @@ public class JettyPolicy extends Policy
// gather dynamic permissions // gather dynamic permissions
if ( pdMapping.get( pd ) != null ) if ( pdMapping.get( pd ) != null )
{ {
for ( Enumeration<Permission> e = pdMapping.get( pd ).elements(); e.hasMoreElements(); ) for ( Enumeration<Permission> e = pdMapping.get( pd ).getPermissions().elements(); e.hasMoreElements(); )
{ {
perms.add( e.nextElement() ); perms.add( e.nextElement() );
} }
@ -117,7 +119,7 @@ public class JettyPolicy extends Policy
// gather dynamic permissions // gather dynamic permissions
if ( pdMapping.get( pd ) != null ) if ( pdMapping.get( pd ) != null )
{ {
for ( Enumeration<Permission> e = pdMapping.get( pd ).elements(); e.hasMoreElements(); ) for ( Enumeration<Permission> e = pdMapping.get( pd ).getPermissions().elements(); e.hasMoreElements(); )
{ {
perms.add( e.nextElement() ); perms.add( e.nextElement() );
} }
@ -174,7 +176,7 @@ public class JettyPolicy extends Policy
for ( Iterator<String> i = _policies.iterator(); i.hasNext(); ) for ( Iterator<String> i = _policies.iterator(); i.hasNext(); )
{ {
File policyFile = new File( i.next() ); File policyFile = new File( i.next() );
pdMapping.putAll( DefaultPolicyLoader.load( new FileInputStream( policyFile ), _evaluator ) ); pdMapping.putAll( DefaultPolicyLoader.load( new FileInputStream( policyFile ), _context ) );
} }
} }
catch ( Exception e ) catch ( Exception e )

View File

@ -0,0 +1,40 @@
package org.eclipse.jetty.policy;
import java.security.KeyStore;
public class PolicyContext
{
private PropertyEvaluator evaluator;
private KeyStore keystore;
public PolicyContext()
{
}
public PolicyContext( PropertyEvaluator evaluator )
{
this.evaluator = evaluator;
}
public PropertyEvaluator getEvaluator()
{
return evaluator;
}
public void setEvaluator( PropertyEvaluator evaluator )
{
this.evaluator = evaluator;
}
public KeyStore getKeystore()
{
return keystore;
}
public void setKeystore( KeyStore keystores )
{
this.keystore = keystore;
}
}

View File

@ -0,0 +1,80 @@
package org.eclipse.jetty.policy;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.security.Principal;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.Set;
public class PolicyEntry
{
public CodeSource codesource;
public Set<Certificate> certificates;
public Principal[] principals;
public PermissionCollection permissions;
private ProtectionDomain protectionDomain;
public ProtectionDomain toProtectionDomain()
{
if ( protectionDomain == null )
{
if ( codesource == null )
{
protectionDomain = new ProtectionDomain( null, permissions );
}
else
{
protectionDomain = new ProtectionDomain( codesource, permissions, Thread.currentThread().getContextClassLoader(), principals );
}
}
return protectionDomain;
}
public CodeSource getCodeSource()
{
return codesource;
}
public void setCodeSource( CodeSource codesource )
{
this.codesource = codesource;
}
public Set<Certificate> getCertificates()
{
return certificates;
}
public void setCertificates( Set<Certificate> certificates )
{
this.certificates = certificates;
}
public Principal[] getPrincipals()
{
return principals;
}
public void setPrincipals( Principal[] principals )
{
this.principals = principals;
}
public PermissionCollection getPermissions()
{
return permissions;
}
public void setPermissions( PermissionCollection permissions )
{
this.permissions = permissions;
}
}

View File

@ -0,0 +1,34 @@
package org.eclipse.jetty.policy.component;
import org.eclipse.jetty.policy.PolicyContext;
import org.eclipse.jetty.policy.PolicyException;
public abstract class AbstractNode
{
private boolean isDirty = false;
private boolean isExpanded = false;
public abstract void expand( PolicyContext context ) throws PolicyException;
public boolean isDirty()
{
return isDirty;
}
public void setDirty( boolean isDirty )
{
this.isDirty = isDirty;
}
public boolean isExpanded()
{
return isExpanded;
}
public void setExpanded( boolean isExpanded )
{
this.isExpanded = isExpanded;
}
}

View File

@ -0,0 +1,187 @@
package org.eclipse.jetty.policy.component;
import java.net.URL;
import java.security.CodeSource;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.Principal;
import java.security.cert.Certificate;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.jetty.policy.PolicyContext;
import org.eclipse.jetty.policy.PolicyException;
public class GrantNode extends AbstractNode
{
/**
* The signers part of grant clause. This is a comma-separated list of certificate aliases.
*/
private String signers;
/**
* The codebase part of grant clause. This is an URL from which code originates.
*/
private String codebase;
/**
* Collection of PrincipalEntries of grant clause.
*/
private Collection<PrincipalNode> principalNodes;
/**
* Collection of PermissionEntries of grant clause.
*/
private Collection<PermissionNode> permissionNodes;
// cached permissions
private PermissionCollection permissions;
private Certificate[] signerArray;
private CodeSource codesource;
private Principal[] principals;
/**
* Adds specified element to the <code>principals</code> collection. If collection does not exist yet, creates a
* new one.
*/
public void addPrincipal( PrincipalNode pe )
{
if ( principalNodes == null )
{
principalNodes = new HashSet<PrincipalNode>();
}
principalNodes.add( pe );
}
public void expand( PolicyContext context ) throws PolicyException
{
signerArray = resolveToCertificates( context.getKeystore(), signers ); // TODO alter to support self:: etc
codebase = context.getEvaluator().evaluate( codebase );
if ( principalNodes != null )
{
Set<Principal> principalSet = new HashSet<Principal>(); // TODO address this not being accurate ( missing prinicipals in codestore)
for ( Iterator<PrincipalNode> i = principalNodes.iterator(); i.hasNext(); )
{
PrincipalNode node = i.next();
node.expand( context );
principalSet.add( node.toPrincipal( context ) );
}
principals = principalSet.toArray( new Principal[principalSet.size()] );
}
permissions = new Permissions();
for ( Iterator<PermissionNode> i = permissionNodes.iterator(); i.hasNext(); )
{
PermissionNode node = i.next();
node.expand( context );
permissions.add( node.toPermission() );
}
setExpanded( true );
}
public PermissionCollection getPermissions() throws PolicyException
{
return permissions;
}
public Principal[] getPrincipals() throws PolicyException
{
return principals;
}
public CodeSource getCodeSource() throws PolicyException
{
if ( !isExpanded() )
{
throw new PolicyException("GrantNode needs to be expanded.");
}
try
{
if ( codesource == null && codebase != null )
{
URL url = new URL( codebase );
codesource = new CodeSource( url, signerArray );
}
return codesource;
}
catch ( Exception e )
{
throw new PolicyException( e );
}
}
/**
* resolve signers into an array of certificates using a given keystore
*
* @param keyStore
* @param signers
* @return
* @throws Exception
*/
private Certificate[] resolveToCertificates( KeyStore keyStore, String signers ) throws PolicyException
{
if ( keyStore == null )
{
Certificate[] certs = null;
return certs;
}
Set<Certificate> certificateSet = new HashSet<Certificate>();
StringTokenizer strTok = new StringTokenizer( signers, ",");
for ( int i = 0; strTok.hasMoreTokens(); ++i )
{
try
{
Certificate certificate = keyStore.getCertificate( strTok.nextToken().trim() );
if ( certificate != null )
{
certificateSet.add( certificate );
}
}
catch ( KeyStoreException kse )
{
throw new PolicyException( kse );
}
}
return certificateSet.toArray( new Certificate[certificateSet.size()] );
}
public void setSigners( String signers )
{
this.signers = signers;
}
public void setCodebase( String codebase )
{
this.codebase = codebase;
}
public void setPrincipals( Collection<PrincipalNode> principals )
{
this.principalNodes = principals;
}
public void setPermissions( Collection<PermissionNode> permissions )
{
this.permissionNodes = permissions;
}
}

View File

@ -0,0 +1,75 @@
package org.eclipse.jetty.policy.component;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import org.eclipse.jetty.policy.PolicyContext;
import org.eclipse.jetty.policy.PolicyException;
public class KeystoreNode extends AbstractNode
{
/**
* The URL part of keystore clause.
*/
private String url;
/**
* The typename part of keystore clause.
*/
private String type;
// cached value
private KeyStore keystore;
public KeyStore toKeyStore() throws PolicyException
{
if ( keystore != null && !isDirty() )
{
return keystore;
}
try
{
keystore = KeyStore.getInstance( type );
URL keyStoreLocation = new URL ( url );
InputStream istream = keyStoreLocation.openStream();
keystore.load( istream, null );
}
catch ( Exception e )
{
throw new PolicyException( e );
}
return keystore;
}
public void expand( PolicyContext context ) throws PolicyException
{
url = context.getEvaluator().evaluate( url );
setExpanded( true );
}
public String getUrl()
{
return url;
}
public void setUrl( String url )
{
this.url = url;
}
public String getType()
{
return type;
}
public void setType( String type )
{
this.type = type;
}
}

View File

@ -0,0 +1,197 @@
package org.eclipse.jetty.policy.component;
import java.lang.reflect.Constructor;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.Permission;
import java.security.cert.Certificate;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.jetty.policy.PolicyContext;
import org.eclipse.jetty.policy.PolicyException;
public class PermissionNode extends AbstractNode
{
/**
* The classname part of permission clause.
*/
private String klass;
/**
* The name part of permission clause.
*/
private String name;
/**
* The actions part of permission clause.
*/
private String actions;
/**
* The signers part of permission clause. This is a comma-separated list of certificate aliases.
*/
private String signers;
private Certificate[] signerArray;
public Permission toPermission() throws PolicyException
{
try
{
Class clazz = Class.forName( klass );
if ( signerArray != null && !validate( signerArray, (Certificate[])clazz.getSigners() ) )
{
throw new PolicyException( "Unvalidated Permissions: " + klass + "/" + name );
}
Permission permission = null;
if ( name == null && actions == null )
{
permission = (Permission) clazz.newInstance();
}
else if ( name != null && actions == null )
{
Constructor c = clazz.getConstructor( new Class[] { String.class } );
permission = (Permission) c.newInstance( name );
}
else if ( name != null && actions != null )
{
Constructor c = clazz.getConstructor( new Class[] { String.class, String.class } );
permission = (Permission) c.newInstance( name, actions );
}
return permission;
}
catch ( Exception e )
{
throw new PolicyException( e );
}
}
public void expand( PolicyContext context ) throws PolicyException
{
name = context.getEvaluator().evaluate( name );
if ( signers != null )
{
signerArray = resolveCertificates( context.getKeystore(), signers );
}
setExpanded( true );
}
/**
* validate that all permission certs are present in the class certs
*
* @param permCerts
* @param classCerts
* @return true if the permissions match up
*/
private static boolean validate( Certificate[] permCerts, Certificate[] classCerts )
{
if ( classCerts == null )
{
return false;
}
for ( int i = 0; i < permCerts.length; ++i )
{
boolean found = false;
for ( int j = 0; j < classCerts.length; ++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 )
{
return false;
}
}
// we found all the permCerts in classCerts so return true
return true;
}
private static Certificate[] resolveCertificates( KeyStore keyStore, String signers ) throws PolicyException
{
if ( keyStore == null )
{
Certificate[] certs = null;
return certs;
}
Set<Certificate> certificateSet = new HashSet<Certificate>();
StringTokenizer strTok = new StringTokenizer( signers, ",");
for ( int i = 0; strTok.hasMoreTokens(); ++i )
{
try
{
Certificate certificate = keyStore.getCertificate( strTok.nextToken().trim() );
if ( certificate != null )
{
certificateSet.add( certificate );
}
}
catch ( KeyStoreException kse )
{
throw new PolicyException( kse );
}
}
return certificateSet.toArray( new Certificate[certificateSet.size()]);
}
public String getKlass()
{
return klass;
}
public void setKlass( String klass )
{
this.klass = klass;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public String getActions()
{
return actions;
}
public void setActions( String actions )
{
this.actions = actions;
}
public String getSigners()
{
return signers;
}
public void setSigners( String signers )
{
this.signers = signers;
}
}

View File

@ -0,0 +1,96 @@
package org.eclipse.jetty.policy.component;
import java.security.KeyStoreException;
import java.security.Principal;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import org.eclipse.jetty.policy.PolicyContext;
import org.eclipse.jetty.policy.PolicyException;
public class PrincipalNode extends AbstractNode
{
/**
* Wildcard value denotes any class and/or any name. Must be asterisk, for proper general expansion and
* PrivateCredentialsPermission wildcarding
*/
public static final String WILDCARD = "*"; //$NON-NLS-1$
/**
* The classname part of principal clause.
*/
private String klass;
/**
* The name part of principal clause.
*/
private String name;
/**
* cached principal if already computed
*/
private Principal principal;
public Principal toPrincipal( PolicyContext context ) throws PolicyException
{
if ( principal != null && !isDirty() )
{
return principal;
}
// if there is no keystore, there is no way to obtain a principal object // TODO validate we need this check
if ( context.getKeystore() == null )
{
return null;
}
try
{
Certificate certificate = context.getKeystore().getCertificate( name );
if ( certificate instanceof X509Certificate )
{
principal = ( (X509Certificate) certificate ).getSubjectX500Principal();
return principal;
}
else
{
throw new PolicyException( "Unknown Certificate, unable to obtain Principal: " + certificate.getType() );
}
}
catch ( KeyStoreException kse )
{
throw new PolicyException( kse );
}
}
public void expand( PolicyContext context )
throws PolicyException
{
name = context.getEvaluator().evaluate( name );
setExpanded(true);
}
public String getKlass()
{
return klass;
}
public void setKlass( String klass )
{
this.klass = klass;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
}

View File

@ -18,30 +18,20 @@ package org.eclipse.jetty.policy.loader;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.security.CodeSource;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.Principal;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.jetty.policy.PolicyContext;
import org.eclipse.jetty.policy.PolicyException; import org.eclipse.jetty.policy.PolicyException;
import org.eclipse.jetty.policy.PropertyEvaluator; import org.eclipse.jetty.policy.PolicyEntry;
import org.eclipse.jetty.policy.component.GrantNode;
import org.eclipse.jetty.policy.component.KeystoreNode;
/** /**
* Load the policies within the stream and resolve into protection domains and permission collections * Load the policies within the stream and resolve into protection domains and permission collections
@ -50,405 +40,55 @@ import org.eclipse.jetty.policy.PropertyEvaluator;
public class DefaultPolicyLoader public class DefaultPolicyLoader
{ {
public static Map<ProtectionDomain, PermissionCollection> load( InputStream policyStream, PropertyEvaluator evaluator ) throws PolicyException public static Map<ProtectionDomain, PolicyEntry> load( InputStream policyStream, PolicyContext context ) throws PolicyException
{ {
Map<ProtectionDomain, PermissionCollection> pdMappings = new HashMap<ProtectionDomain, PermissionCollection>(); Map<ProtectionDomain, PolicyEntry> policies = new HashMap<ProtectionDomain, PolicyEntry>();
KeyStore keystore = null; KeyStore keystore = null;
try try
{ {
PolicyFileScanner loader = new PolicyFileScanner(); PolicyFileScanner loader = new PolicyFileScanner();
Collection<GrantEntry> grantEntries = new ArrayList<GrantEntry>(); Collection<GrantNode> grantEntries = new ArrayList<GrantNode>();
List<KeystoreEntry> keystoreEntries = new ArrayList<KeystoreEntry>(); List<KeystoreNode> keystoreEntries = new ArrayList<KeystoreNode>();
loader.scanStream( new InputStreamReader(policyStream), grantEntries, keystoreEntries ); loader.scanStream( new InputStreamReader(policyStream), grantEntries, keystoreEntries );
for ( Iterator<KeystoreEntry> i = keystoreEntries.iterator(); i.hasNext();) for ( Iterator<KeystoreNode> i = keystoreEntries.iterator(); i.hasNext();)
{ {
keystore = resolveKeyStore( i.next(), evaluator ); KeystoreNode node = i.next();
node.expand( context );
keystore = node.toKeyStore();
if ( keystore != null ) if ( keystore != null )
{ {
// we only process the first valid keystore // we only process the first valid keystore
context.setKeystore( keystore );
break; break;
} }
} }
for ( Iterator<GrantEntry> i = grantEntries.iterator(); i.hasNext(); ) for ( Iterator<GrantNode> i = grantEntries.iterator(); i.hasNext(); )
{ {
GrantEntry grant = i.next(); GrantNode grant = i.next();
Permissions permissions = processPermissions( grant, keystore, evaluator ); grant.expand( context );
ProtectionDomain pd; PolicyEntry policy = new PolicyEntry();
if ( grant.codebase == null ) // these are hereby known as global permissions (no codebase associated) policy.setCodeSource( grant.getCodeSource() );
{ policy.setPrincipals( grant.getPrincipals() );
pd = new ProtectionDomain( null, permissions ); policy.setPermissions( grant.getPermissions() );
}
else policies.put( policy.toProtectionDomain(), policy );
{
Certificate[] certs = resolveToCertificates( keystore, grant.signers );
Principal[] principals = resolvePrincipals( keystore, grant.principals );
CodeSource codeSource = resolveToCodeSource( grant.codebase, certs, evaluator );
pd = new ProtectionDomain( codeSource, permissions, Thread.currentThread().getContextClassLoader(),principals );
//System.out.println( pd.toString() );
}
pdMappings.put( pd, null );
} }
return pdMappings; return policies;
} }
catch ( Exception e ) catch ( Exception e )
{ {
throw new PolicyException( e ); throw new PolicyException( e );
} }
} }
private static Permissions processPermissions( GrantEntry grant, KeyStore keystore, PropertyEvaluator evaluator ) throws PolicyException
{
Collection<PermissionEntry> collection = grant.permissions;
Permissions permissions = new Permissions();
for ( Iterator<PermissionEntry> i = collection.iterator(); i.hasNext(); )
{
PermissionEntry perm = i.next();
Class clazz;
try
{
clazz = Class.forName( perm.klass );
// if we have perm.signers then we need to validate against the class certificates
if ( perm.signers != null )
{
if ( validate( resolveToCertificates( keystore, perm.signers ), (Certificate[]) clazz.getSigners() ))
{
permissions.add( resolveToPermission( clazz, perm, evaluator ) );
}
}
else
{
permissions.add( resolveToPermission( clazz, perm, evaluator ) );
}
}
catch ( Exception e )
{
throw new PolicyException( e );
}
}
return permissions;
}
private static Permission resolveToPermission(Class clazz, PermissionEntry perm, PropertyEvaluator evaluator ) throws PolicyException
{
try
{
Permission permission = null;
if ( perm.name == null && perm.actions == null )
{
permission = (Permission) clazz.newInstance();
}
else if ( perm.name != null && perm.actions == null )
{
Constructor c = clazz.getConstructor( new Class[] { String.class } );
permission = (Permission) c.newInstance( evaluator.evaluate( perm.name ) );
}
else if ( perm.name != null && perm.actions != null )
{
Constructor c = clazz.getConstructor( new Class[] { String.class, String.class } );
permission = (Permission) c.newInstance( evaluator.evaluate( perm.name ), perm.actions );
}
return permission;
}
catch ( Exception e )
{
throw new PolicyException( e );
}
}
/*
* resolve the use of the klass in the principal entry
*
* @param keystore
* @param collection
* @return
* @throws PolicyException
*/
private static Principal[] resolvePrincipals( KeyStore keystore, Collection<PrincipalEntry> collection ) throws PolicyException
{
if ( keystore == null || collection == null )
{
Principal[] principals = null;
return principals;
}
Set<Principal> principalSet = new HashSet<Principal>();
for ( Iterator<PrincipalEntry> i = collection.iterator(); i.hasNext(); )
{
PrincipalEntry principal = i.next();
try
{
Certificate certificate = keystore.getCertificate( principal.name );
if ( certificate instanceof X509Certificate )
{
principalSet.add( ((X509Certificate) certificate).getSubjectX500Principal() );
}
}
catch ( KeyStoreException kse )
{
throw new PolicyException( kse );
}
}
return principalSet.toArray( new Principal[principalSet.size()]);
}
private static CodeSource resolveToCodeSource( String codeBase, Certificate[] signers, PropertyEvaluator evaluator ) throws PolicyException
{
try
{
URL url = new URL( evaluator.evaluate(codeBase) );
return new CodeSource( url, signers);
}
catch ( Exception e )
{
throw new PolicyException( e );
}
}
/**
* resolve signers into an array of certificates using a given keystore
*
* @param keyStore
* @param signers
* @return
* @throws Exception
*/
private static Certificate[] resolveToCertificates( KeyStore keyStore, String signers ) throws PolicyException
{
if ( keyStore == null )
{
Certificate[] certs = null;
return certs;
}
Set<Certificate> certificateSet = new HashSet<Certificate>();
StringTokenizer strTok = new StringTokenizer( signers, ",");
for ( int i = 0; strTok.hasMoreTokens(); ++i )
{
try
{
Certificate certificate = keyStore.getCertificate( strTok.nextToken().trim() );
if ( certificate != null )
{
certificateSet.add( certificate );
}
}
catch ( KeyStoreException kse )
{
throw new PolicyException( kse );
}
}
return certificateSet.toArray( new Certificate[certificateSet.size()]);
}
private static KeyStore resolveKeyStore( KeystoreEntry entry, PropertyEvaluator evaluator ) throws PolicyException
{
KeyStore keyStore = null;
try
{
keyStore = KeyStore.getInstance( entry.type );
URL keyStoreLocation = new URL ( evaluator.evaluate( entry.url ) );
InputStream istream = keyStoreLocation.openStream();
keyStore.load( istream, null );
}
catch ( Exception e )
{
e.printStackTrace();
//throw new PolicyException( kse );
}
return keyStore;
}
/**
* validate that all permission certs are present in the class certs
*
* @param permCerts
* @param classCerts
* @return true if the permissions match up
*/
private static boolean validate( Certificate[] permCerts, Certificate[] classCerts )
{
if ( classCerts == null )
{
return false;
}
for ( int i = 0; i < permCerts.length; ++i )
{
boolean found = false;
for ( int j = 0; j < classCerts.length; ++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 )
{
return false;
}
}
// we found all the permCerts in classCerts so return true
return true;
}
/**
* Compound token representing <i>keystore</i> clause. See policy format
* {@link org.apache.harmony.security.DefaultPolicy description}for details.
*
* @see org.apache.harmony.security.fortress.DefaultPolicyParser
* @see org.apache.harmony.security.DefaultPolicyScanner
*/
public static class KeystoreEntry
{
/**
* The URL part of keystore clause.
*/
public String url;
/**
* The typename part of keystore clause.
*/
public String type;
}
/**
* Compound token representing <i>grant </i> clause. See policy format
* {@link org.apache.harmony.security.DefaultPolicy description}for details.
*
* @see org.apache.harmony.security.fortress.DefaultPolicyParser
* @see org.apache.harmony.security.DefaultPolicyScanner
*/
public static class GrantEntry
{
/**
* The signers part of grant clause. This is a comma-separated list of certificate aliases.
*/
public String signers;
/**
* The codebase part of grant clause. This is an URL from which code originates.
*/
public String codebase;
/**
* Collection of PrincipalEntries of grant clause.
*/
public Collection<PrincipalEntry> principals;
/**
* Collection of PermissionEntries of grant clause.
*/
public Collection<PermissionEntry> permissions;
/**
* Adds specified element to the <code>principals</code> collection. If collection does not exist yet, creates a
* new one.
*/
public void addPrincipal( PrincipalEntry pe )
{
if ( principals == null )
{
principals = new HashSet<PrincipalEntry>();
}
principals.add( pe );
}
}
/**
* Compound token representing <i>principal </i> entry of a <i>grant </i> clause. See policy format
* {@link org.apache.harmony.security.DefaultPolicy description}for details.
*
* @see org.apache.harmony.security.fortress.DefaultPolicyParser
* @see org.apache.harmony.security.DefaultPolicyScanner
*/
public static class PrincipalEntry
{
/**
* Wildcard value denotes any class and/or any name. Must be asterisk, for proper general expansion and
* PrivateCredentialsPermission wildcarding
*/
public static final String WILDCARD = "*"; //$NON-NLS-1$
/**
* The classname part of principal clause.
*/
public String klass;
/**
* The name part of principal clause.
*/
public String name;
}
/**
* Compound token representing <i>permission </i> entry of a <i>grant </i> clause. See policy format
* {@link org.apache.harmony.security.DefaultPolicy description}for details.
*
* @see org.apache.harmony.security.fortress.DefaultPolicyParser
* @see org.apache.harmony.security.DefaultPolicyScanner
*/
public static class PermissionEntry
{
/**
* The classname part of permission clause.
*/
public String klass;
/**
* The name part of permission clause.
*/
public String name;
/**
* The actions part of permission clause.
*/
public String actions;
/**
* The signers part of permission clause. This is a comma-separated list of certificate aliases.
*/
public String signers;
}
} }

View File

@ -40,10 +40,10 @@ import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import org.eclipse.jetty.policy.loader.DefaultPolicyLoader.GrantEntry; import org.eclipse.jetty.policy.component.GrantNode;
import org.eclipse.jetty.policy.loader.DefaultPolicyLoader.KeystoreEntry; import org.eclipse.jetty.policy.component.KeystoreNode;
import org.eclipse.jetty.policy.loader.DefaultPolicyLoader.PermissionEntry; import org.eclipse.jetty.policy.component.PermissionNode;
import org.eclipse.jetty.policy.loader.DefaultPolicyLoader.PrincipalEntry; import org.eclipse.jetty.policy.component.PrincipalNode;
/** /**
@ -126,7 +126,7 @@ public class PolicyFileScanner
* @throws IOException if stream reading failed * @throws IOException if stream reading failed
* @throws InvalidFormatException if unexpected or unknown token encountered * @throws InvalidFormatException if unexpected or unknown token encountered
*/ */
public void scanStream( Reader r, Collection<GrantEntry> grantEntries, List<KeystoreEntry> keystoreEntries ) public void scanStream( Reader r, Collection<GrantNode> grantEntries, List<KeystoreNode> keystoreEntries )
throws IOException, InvalidFormatException throws IOException, InvalidFormatException
{ {
StreamTokenizer st = configure( new StreamTokenizer( r ) ); StreamTokenizer st = configure( new StreamTokenizer( r ) );
@ -140,10 +140,10 @@ public class PolicyFileScanner
case StreamTokenizer.TT_WORD: case StreamTokenizer.TT_WORD:
if ( Util.equalsIgnoreCase( "keystore", st.sval ) ) { //$NON-NLS-1$ if ( Util.equalsIgnoreCase( "keystore", st.sval ) ) { //$NON-NLS-1$
keystoreEntries.add( readKeystoreEntry( st ) ); keystoreEntries.add( readKeystoreNode( st ) );
} }
else if ( Util.equalsIgnoreCase( "grant", st.sval ) ) { //$NON-NLS-1$ else if ( Util.equalsIgnoreCase( "grant", st.sval ) ) { //$NON-NLS-1$
grantEntries.add( readGrantEntry( st ) ); grantEntries.add( readGrantNode( st ) );
} }
else else
{ {
@ -171,20 +171,20 @@ public class PolicyFileScanner
* *
* </pre> * </pre>
* *
* @return successfully parsed KeystoreEntry * @return successfully parsed KeystoreNode
* @throws IOException if stream reading failed * @throws IOException if stream reading failed
* @throws InvalidFormatException if unexpected or unknown token encountered * @throws InvalidFormatException if unexpected or unknown token encountered
*/ */
protected KeystoreEntry readKeystoreEntry( StreamTokenizer st ) protected KeystoreNode readKeystoreNode( StreamTokenizer st )
throws IOException, InvalidFormatException throws IOException, InvalidFormatException
{ {
KeystoreEntry ke = new KeystoreEntry(); KeystoreNode ke = new KeystoreNode();
if ( st.nextToken() == '"' ) if ( st.nextToken() == '"' )
{ {
ke.url = st.sval; ke.setUrl( st.sval );
if ( ( st.nextToken() == '"' ) || ( ( st.ttype == ',' ) && ( st.nextToken() == '"' ) ) ) if ( ( st.nextToken() == '"' ) || ( ( st.ttype == ',' ) && ( st.nextToken() == '"' ) ) )
{ {
ke.type = st.sval; ke.setType( st.sval );
} }
else else
{ // handle token in the main loop { // handle token in the main loop
@ -203,7 +203,7 @@ public class PolicyFileScanner
* Tries to read <i>grant </i> clause. <br> * Tries to read <i>grant </i> clause. <br>
* First, it reads <i>codebase </i>, <i>signedby </i>, <i>principal </i> entries till the '{' (opening curly brace) * First, it reads <i>codebase </i>, <i>signedby </i>, <i>principal </i> entries till the '{' (opening curly brace)
* symbol. Then it calls readPermissionEntries() method to read the permissions of this clause. <br> * symbol. Then it calls readPermissionEntries() method to read the permissions of this clause. <br>
* Principal entries (if any) are read by invoking readPrincipalEntry() method, obtained PrincipalEntries are * Principal entries (if any) are read by invoking readPrincipalNode() method, obtained PrincipalEntries are
* accumulated. <br> * accumulated. <br>
* The expected syntax is * The expected syntax is
* *
@ -214,14 +214,14 @@ public class PolicyFileScanner
* *
* </pre> * </pre>
* *
* @return successfully parsed GrantEntry * @return successfully parsed GrantNode
* @throws IOException if stream reading failed * @throws IOException if stream reading failed
* @throws InvalidFormatException if unexpected or unknown token encountered * @throws InvalidFormatException if unexpected or unknown token encountered
*/ */
protected GrantEntry readGrantEntry( StreamTokenizer st ) protected GrantNode readGrantNode( StreamTokenizer st )
throws IOException, InvalidFormatException throws IOException, InvalidFormatException
{ {
GrantEntry ge = new GrantEntry(); GrantNode ge = new GrantNode();
parsing: while ( true ) parsing: while ( true )
{ {
switch ( st.nextToken() ) switch ( st.nextToken() )
@ -231,7 +231,7 @@ public class PolicyFileScanner
if ( Util.equalsIgnoreCase( "signedby", st.sval ) ) { //$NON-NLS-1$ if ( Util.equalsIgnoreCase( "signedby", st.sval ) ) { //$NON-NLS-1$
if ( st.nextToken() == '"' ) if ( st.nextToken() == '"' )
{ {
ge.signers = st.sval; ge.setSigners( st.sval );
} }
else else
{ {
@ -241,7 +241,7 @@ public class PolicyFileScanner
else if ( Util.equalsIgnoreCase( "codebase", st.sval ) ) { //$NON-NLS-1$ else if ( Util.equalsIgnoreCase( "codebase", st.sval ) ) { //$NON-NLS-1$
if ( st.nextToken() == '"' ) if ( st.nextToken() == '"' )
{ {
ge.codebase = st.sval; ge.setCodebase( st.sval );
} }
else else
{ {
@ -249,7 +249,7 @@ public class PolicyFileScanner
} }
} }
else if ( Util.equalsIgnoreCase( "principal", st.sval ) ) { //$NON-NLS-1$ else if ( Util.equalsIgnoreCase( "principal", st.sval ) ) { //$NON-NLS-1$
ge.addPrincipal( readPrincipalEntry( st ) ); ge.addPrincipal( readPrincipalNode( st ) );
} }
else else
{ {
@ -261,7 +261,7 @@ public class PolicyFileScanner
break; break;
case '{': case '{':
ge.permissions = readPermissionEntries( st ); ge.setPermissions( readPermissionEntries( st ) );
break parsing; break parsing;
default: // handle token in the main loop default: // handle token in the main loop
@ -274,7 +274,7 @@ public class PolicyFileScanner
} }
/** /**
* Tries to read <i>Principal </i> entry fields. The expected syntax is * Tries to read <i>Principal </i> Node fields. The expected syntax is
* *
* <pre> * <pre>
* *
@ -284,31 +284,31 @@ public class PolicyFileScanner
* *
* Both class and name may be wildcards, wildcard names should not surrounded by quotes. * Both class and name may be wildcards, wildcard names should not surrounded by quotes.
* *
* @return successfully parsed PrincipalEntry * @return successfully parsed PrincipalNode
* @throws IOException if stream reading failed * @throws IOException if stream reading failed
* @throws InvalidFormatException if unexpected or unknown token encountered * @throws InvalidFormatException if unexpected or unknown token encountered
*/ */
protected PrincipalEntry readPrincipalEntry( StreamTokenizer st ) protected PrincipalNode readPrincipalNode( StreamTokenizer st )
throws IOException, InvalidFormatException throws IOException, InvalidFormatException
{ {
PrincipalEntry pe = new PrincipalEntry(); PrincipalNode pe = new PrincipalNode();
if ( st.nextToken() == StreamTokenizer.TT_WORD ) if ( st.nextToken() == StreamTokenizer.TT_WORD )
{ {
pe.klass = st.sval; pe.setKlass( st.sval );
st.nextToken(); st.nextToken();
} }
else if ( st.ttype == '*' ) else if ( st.ttype == '*' )
{ {
pe.klass = PrincipalEntry.WILDCARD; pe.setKlass( PrincipalNode.WILDCARD );
st.nextToken(); st.nextToken();
} }
if ( st.ttype == '"' ) if ( st.ttype == '"' )
{ {
pe.name = st.sval; pe.setName( st.sval );
} }
else if ( st.ttype == '*' ) else if ( st.ttype == '*' )
{ {
pe.name = PrincipalEntry.WILDCARD; pe.setName( PrincipalNode.WILDCARD );
} }
else else
{ {
@ -334,10 +334,10 @@ public class PolicyFileScanner
* @throws IOException if stream reading failed * @throws IOException if stream reading failed
* @throws InvalidFormatException if unexpected or unknown token encountered * @throws InvalidFormatException if unexpected or unknown token encountered
*/ */
protected Collection<PermissionEntry> readPermissionEntries( StreamTokenizer st ) protected Collection<PermissionNode> readPermissionEntries( StreamTokenizer st )
throws IOException, InvalidFormatException throws IOException, InvalidFormatException
{ {
Collection<PermissionEntry> permissions = new HashSet<PermissionEntry>(); Collection<PermissionNode> permissions = new HashSet<PermissionNode>();
parsing: while ( true ) parsing: while ( true )
{ {
switch ( st.nextToken() ) switch ( st.nextToken() )
@ -345,13 +345,13 @@ public class PolicyFileScanner
case StreamTokenizer.TT_WORD: case StreamTokenizer.TT_WORD:
if ( Util.equalsIgnoreCase( "permission", st.sval ) ) { //$NON-NLS-1$ if ( Util.equalsIgnoreCase( "permission", st.sval ) ) { //$NON-NLS-1$
PermissionEntry pe = new PermissionEntry(); PermissionNode pe = new PermissionNode();
if ( st.nextToken() == StreamTokenizer.TT_WORD ) if ( st.nextToken() == StreamTokenizer.TT_WORD )
{ {
pe.klass = st.sval; pe.setKlass( st.sval );
if ( st.nextToken() == '"' ) if ( st.nextToken() == '"' )
{ {
pe.name = st.sval; pe.setName( st.sval );
st.nextToken(); st.nextToken();
} }
if ( st.ttype == ',' ) if ( st.ttype == ',' )
@ -360,7 +360,7 @@ public class PolicyFileScanner
} }
if ( st.ttype == '"' ) if ( st.ttype == '"' )
{ {
pe.actions = st.sval; pe.setActions( st.sval );
if ( st.nextToken() == ',' ) if ( st.nextToken() == ',' )
{ {
st.nextToken(); st.nextToken();
@ -369,7 +369,7 @@ public class PolicyFileScanner
if ( st.ttype == StreamTokenizer.TT_WORD && Util.equalsIgnoreCase( "signedby", st.sval ) ) { //$NON-NLS-1$ if ( st.ttype == StreamTokenizer.TT_WORD && Util.equalsIgnoreCase( "signedby", st.sval ) ) { //$NON-NLS-1$
if ( st.nextToken() == '"' ) if ( st.nextToken() == '"' )
{ {
pe.signers = st.sval; pe.setSigners( st.sval );
} }
else else
{ {

View File

@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.Set; import java.util.Set;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -155,7 +156,13 @@ public class TestJettyPolicy extends TestCase
private String getWorkingDirectory() private String getWorkingDirectory()
{ {
return System.getProperty( "basedir" ); // TODO work in eclipse String cwd = System.getProperty( "basedir" );
if ( cwd == null )
{
cwd = System.getProperty( "user.dir" );
}
return cwd;
} }
} }

View File

@ -30,14 +30,26 @@ public class TestJettyPolicyRuntime extends TestCase
PropertyEvaluator evaluator = new PropertyEvaluator( new HashMap<String,String>()); PropertyEvaluator evaluator = new PropertyEvaluator( new HashMap<String,String>());
@Override @Override
protected void setUp() protected void setUp() throws Exception
throws Exception
{ {
super.setUp(); super.setUp();
evaluator.put( "jetty.home", getWorkingDirectory() ); evaluator.put( "jetty.home", getWorkingDirectory() );
} }
@Override
protected void tearDown() throws Exception
{
super.tearDown();
System.setSecurityManager( null );
Policy.setPolicy( null );
}
public void testSimplePolicyReplacement() throws Exception public void testSimplePolicyReplacement() throws Exception
{ {
JettyPolicy ap = JettyPolicy ap =
@ -52,9 +64,6 @@ public class TestJettyPolicyRuntime extends TestCase
assertTrue ( test.canRead() ); assertTrue ( test.canRead() );
// Policy nulling must occur after Security Manager null
System.setSecurityManager( null );
Policy.setPolicy( null );
} }
public void testRepeatedPolicyReplacement() throws Exception public void testRepeatedPolicyReplacement() throws Exception
@ -102,8 +111,6 @@ public class TestJettyPolicyRuntime extends TestCase
assertTrue( "Exception was thrown as it should be.", true ); assertTrue( "Exception was thrown as it should be.", true );
} }
System.setSecurityManager( null );
Policy.setPolicy( null );
} }
@ -138,8 +145,6 @@ public class TestJettyPolicyRuntime extends TestCase
assertTrue( "Exception was thrown", true ); assertTrue( "Exception was thrown", true );
} }
System.setSecurityManager( null );
Policy.setPolicy( null );
} }
public void testCertificateLoader() public void testCertificateLoader()
@ -203,9 +208,6 @@ public class TestJettyPolicyRuntime extends TestCase
assertFalse( "should not have got here", true ); assertFalse( "should not have got here", true );
} }
System.setSecurityManager( null );
Policy.setPolicy( null );
} }
@ -274,12 +276,17 @@ public class TestJettyPolicyRuntime extends TestCase
assertTrue( "checking that we through a security exception", excepted ); assertTrue( "checking that we through a security exception", excepted );
System.setSecurityManager( null );
Policy.setPolicy( null );
} }
private String getWorkingDirectory() private String getWorkingDirectory()
{ {
return System.getProperty( "basedir" ); // TODO work in eclipse String cwd = System.getProperty( "basedir" );
if ( cwd == null )
{
cwd = System.getProperty( "user.dir" );
}
return cwd;
} }
} }