You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@river.apache.org by Peter Firmstone <ji...@zeus.net.au> on 2010/08/01 05:53:30 UTC

Learnings from a RevokeableDynamicPolicy & A Future Roadmap

A Brief evolution of java.security.Policy providers and Jini Security, 
please correct me where necessary.

Prior to Jini 2.0 security was left up to implementing developers, the 
standard tools available in Java 1.2 were insufficient.  You had to 
implement your own SecurityManager.  Or you could define Security 
policy's in policy files.  The AccessController still consulted the 
ProtectionDomain, but the ProtectionDomain Permission's were static and 
unchanging.  You could implement your own policy provider for 
java.security.Policy, by there was no way you could guarantee updates to 
the ProtectionDomain with any changes, the ProtectionDomain used the 
Policy.getPermissions(ProtectionDomain) call to obtain the 
PermissionCollection from the Policy.

To enable the Jini 2.0 Security infrastructure, Sun made changes to Java 
itself, in Java 1.4  ProtectionDomain's were given a new constructor 
that enabled the ProtectionDomain to consult an external Policy 
Provider, and the java.security.Policy gained the 
implies(ProtectionDomain, Permission) method, allowing the 
ProtectionDomain to consult the Policy, Jini 2.0 took advantage of this 
with the DynamicPolicyProvider.  This Policy system is a permissive 
system, that is security was only ever relaxed, it cannot be tightened 
without restarting the JVM.

Now we have taken a new evolutionary step, inspired by Sun's Neuromancer 
Research Project's additional security needs, for a distributed object 
registry, we now have a RevokeableDynamicPolicy interface.

RevokeableDynamicPolicy wouldn't be possible to implement without the 
changes to Java 1.4 Security that were prompted by Jini 2.0.

A RevokeableDynamicPolicy relies on the following features inherent in Java:

    * ProtectionDomain's new dynamic 4 parameter constructor support for
      dynamic Policy's, supplied with a null PermissionCollection. Added
      in Java 1.4
    * Not returning any PermissionCollection's belonging to dynamic
      grants via either of Policy.getPermissions(*) methods. Only those
      belonging to underlying static Policy providers will be returned.
    * Total reliance on Policy.implies(ProtectionDomain, Permission)
      added in Java 1.4

A RevokeableDynamicPolicy supports the addition or removal of 
PermissionGrant's

    * PermissionGrant.implies(ProtectionDomain), is the main feature of
      the RevokeableDynamicPolicy.
    * PermissionGrant is an interface.
    * A PermissionGrant can be implemented by anyone, but the
      implementing codebase must have a RuntimePermission for
      "getProtectionDomain" and GrantPermission for the Permission's it
      will grant.
    * A PermissionGrant can use any means it can to determine if it
      implies a ProtectionDomain, if it does the RevokeableDynamicPolicy
      will add Permission's to the PermissionCollection cached for that
      ProtectionDomain by calling PermissionGrant.getPermissions();
    * To remove a PermissionGrant, you must have RevokePermission.

What I discovered when implementing a Concurrent version of 
RevokeableDynamicPolicy:

    * PermissionCollection.elements() returned an
      Enumeration<Permission> that would throw a
      ConcurrentModificationException, when Permission's were added to
      the backing PermissionCollection.
    * java.security.Permissions is a heterogeneous PermissionCollection
      implementation, it's a point of contention for threads.  It needed
      a concurrent replacement.
    * The replacement,
      org.apache.river.imp.security.policy.ConcurrentPermissions
      implements a threadsafe alternative for Permissions that prevents
      Enumeration<Permission> from throwing
      ConcurrentModificationException by caching.
    * Now it is possible for Policy.implies(ProtectionDomain,
      Permission) calls to occur concurrently during adding or removal
      of PermissionGrant's.  Policy.elements() Enumeration<Permission>
      can also be enumerated during adding or removal of
      PermissionGrant's or implies() calls.
    * UmbrellaGrantPermission's have been added to
      org.apache.river.imp.security.policy.DynamicConcurrentPolicyProvider,
      so you can minimise the size of Policy files for GrantPermission's.
    * This implementation passes all the existing qa harness and jtreg
      tests for DynamicPolicy.
    * Please feel free to assist by creating new tests for Concurrency
      (many threads, hammer all methods).

What's next:

    * Adding new methods to net.jini.security.Security to provide
      support for PermissionGrant's and RevokeableDynamicPolicy.
    * Creating an Entry that provides PermissionGrantBuilder's to assist
      the client to restrict the Permission's to those that are
      acceptable to the client and only those needed by the Service.
    * Utilising the new org.apache.river.imp.util.PolicyParser interface
      (this may be added to the api at a later date), standard java
      policy file syntax can be parsed by the provided
      DefaultPolicyParser (courtesy Apache Harmony) and will return
      PermissionGrant's, the PermissionGrant's can return
      PermissionGrantBuilder's that can be used in Entry's
    * We can add standard java policy files to our downloadable jar
      archives, we just need a utility class that generates the
      PermissionGrantBuilder Entry's for us.
    * The new PolicyParser allows parsing of URL based policy files.
    * A Distributed Object Registry, inspired by Project Neuromancer,
      utilising distributed hash tables to track the location of objects.

The bigger picture, A Future Roadmap:

    * Standardise the use of a Parent ClassLoader in the ClassLoader
      hierarchy (tree) above all client and service implementation and
      proxy ClassLoader's so that the implementations can all
      communicate using COMMON SERVICE INTERFACES.
    * Standardise jar file naming to assist ClassLoader layout, see
      https://issues.apache.org/jira/browse/RIVER-341
    * Create a new ServiceStarter / ClientStarter to setup the
      ClassLoader tree based on the new naming scheme.
    * Codebase Entry's and Client Codebase Provisioning.
    * jeri Endpoint implementations to traverse firewalls.
    * DNS-SD for Internet Unicast Discovery.
    * StreamServiceRegistrar - for the Internet with delayed
      Unmarshalling of Service Proxy's
    * A new URL Handler for CodeBase's with Version information for
      Provisioning.

RevokeableDynamicPolicy and StreamServiceRegistrar lookup filter 
chaining makes it possible to:

    * Lookup Services by common Codebase Entry's
    * Process ResultStream using chained and nested ServiceItemFilters:

         1. ServiceItemFilter at the client by comparison of Entry
            contents < > =.
         2. ServiceItemFilter to Unmarshall Proxy, Provision CodeSource
         3. ServiceItemFilter to check Method Constraints
         4. ServiceItemFilter to Dynamically Grant Permission's based on
            Entry as deemed acceptable.
         5. ServiceItemFilter to Perform operation on Proxy
         6. ServiceItemFilter to Dynamically Revoke Permission's based.
         7. ServiceItemFilter to Throw away Proxy reference
         8. While next, Goto 2 repeat process, can utilise same
            ClassLoader as previous Service Proxy for speed, no need to
            downlaod, reload and re verify bytecodes for CodeSource.

    * ResultStream's are like an Enumeration, but are concurrent, used
      like a stream, a null result indicates end of ResultStream.

Best Regards,

Peter Firmstone.


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Peter Firmstone wrote:
>
>
> What I discovered when implementing a Concurrent version of 
> RevokeableDynamicPolicy:
>
>    * PermissionCollection.elements() returned an
>      Enumeration<Permission> that would throw a
>      ConcurrentModificationException, when Permission's were added to
>      the backing PermissionCollection.
>    * java.security.Permissions is a heterogeneous PermissionCollection
>      implementation, it's a point of contention for threads.  It needed
>      a concurrent replacement.
>    * The replacement,
>      org.apache.river.imp.security.policy.ConcurrentPermissions
>      implements a threadsafe alternative for Permissions that prevents
>      Enumeration<Permission> from throwing
>      ConcurrentModificationException by caching.
>    * Now it is possible for Policy.implies(ProtectionDomain,
>      Permission) calls to occur concurrently during adding or removal
>      of PermissionGrant's.  Policy.elements() Enumeration<Permission>
>      can also be enumerated during adding or removal of
>      PermissionGrant's or implies() calls.

Policy.elements() - correction this should be 
PermissionCollection.elements() as shown earlier, this is the method 
that returns the Enumeration<Permission>, Enumerating a standard 
PermissionCollection causes a ConcurrentModificationException, if the 
PermissionCollection is mutated (add(Permission) is called) at the same 
time.

>    * UmbrellaGrantPermission's have been added to
>      
> org.apache.river.imp.security.policy.DynamicConcurrentPolicyProvider,
>      so you can minimise the size of Policy files for GrantPermission's.
>    * This implementation passes all the existing qa harness and jtreg
>      tests for DynamicPolicy.
>    * Please feel free to assist by creating new tests for Concurrency
>      (many threads, hammer all methods).
>


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Hi Gregg,

I'll try having another look later, was looking in trunk but didn't find 
any java source, then got an Internal Server Error.

Cheers,

Peter.

Gregg Wonderly wrote:
> For quite some time, I've been using a package that I put together 
> which uses XML to create an interface and a SecurityDelegate as you 
> describe below.  It was embedded in one of my applications for some 
> time, but a few years back, I pulled it out into a separate codebase 
> so that I could use it in several other projects which had grown to 
> need more granular security control.
>
> I've put it out on authlib.dev.java.net.  There really is not a lot of 
> documentation at this point.  This is more or less a "throw it over 
> the wall" move.
>
> Here's a summary of how it is used, and how it works.
>
> It provides for the definition of users and groups/roles.  There is a 
> whole GUI component to the code which allows editing.  This data is 
> access/stored using a JDBC based backing store.
>
> The class, org.wonderly.authlib.BuildAccess processes the XML file.  
> There is a sample XML file which shows most of what is possible, but 
> the parsing in BuildAccess is the real clue to what is possible.
>
> There are object types, which you designate the type of permission 
> that applies to that object.  An example from the access.xml in the 
> CVS tree is:
>
>     <object type="view" access="update,read"
>             permission="PermissionTwo"/>
>
> This says that there are parameters in method class which are "view" 
> type references.  PermissionTwo is used to control access to those 
> type objects.  The "access" attribute represents the types of 
> permissions that the permission implementation supports for its 
> "access" parameter during construction.
>
> A single method definition looks like the following:
>
>     <method return="String" name="getDBUnitView" qualifiers="public">
>         <descr>
>         This method is used to get the description of the named view.
>         </descr>
>         <security>
>             <filter access="read" filtered="view" filteredType="String"
>                 params="view" filterGeneric="String" 
> class="TestUpdateAuthFilter"/>
>             <!-- limit access="read" type="view" arg="view"/ -->
>         </security>
>         <args>
>             <arg name="view" type="String" descr="name of the view to 
> get the definition of"/>
>         </args>
>         <exceptions>
>             <throws name="SQLException" descr="when a database access 
> error occurs"/>
>         </exceptions>
>     </method>
>
> The method signature and JavaDoc is generated from this definition.
>
> The security section says that a filter operation should be performed 
> to return the value if it is accessible, instead of throwing an 
> exception as <limit> does.
> The class, TestUpdateAuthFilter performs the filtering operation.  It 
> implements a standard interface to define how the filtering works.
>
> Here's the generated code:
>
>     public String getDBUnitView( String view ) throws
>                  java.rmi.RemoteException , SQLException {
>         // Check for required access rights.
>         String XXXval = null;
>         String XXXtype = "filter";
>         String XXXaccess = "read";
>
>
>         try {
>             // Call the method, authorization passes
>             // Get Initial data
>             String XXXlist = XXXacc.getDBUnitView( view );
>             UpdateAuthFilter<String> XXXfilt = null;
>             try {
>                 XXXfilt = new TestUpdateAuthFilter<String>();
>             } catch( RuntimeException ex ) {
>                 log.log( Level.SEVERE, ex.toString(), ex );
>                 throw new AuthorizationException(
>                     ex.toString(), ex );
>             }
>             String XXXret = XXXfilt.filterList( new Object[] {view},
>                  XXXlist, "read", XXXauth, XXXdb );
>             secureLog(  Level.INFO, "{0}[{1}]:
>                     "+"getDBUnitView("+view+") ==> "+XXXret,
>                      XXXauth.getUserName(), XXXaccess );
>             return XXXret;
>         } catch( RuntimeException ex ) {
>             // Make the exception source visible
>             log.log( Level.SEVERE, ex.toString(), ex );
>             // Rethrow it to stop the operation
>             throw ex;
>         }
>     }
>
> There's a quite a bit more I can talk about and document, but I just 
> wanted to throw this out.  It's licensed under the Apache license, but 
> I did not put the license into every source file, yet.
>
> Gregg Wonderly
>
> Peter Firmstone wrote:
>> Please help identify any fallacies or oversights in the following 
>> arguments.
>>
>> A Permission may be revoked, at any point in time after a revocation, 
>> untrusted code may hold a reference to a privileged object.
>>
>> Some Permission's protect methods, such as Thread.interrupt(), these 
>> are effectively revoked with the existing Java security model, 
>> however other objects are only protected in their constructor, the 
>> responsibility being on the trusted code, not to let their references 
>> escape, such as FileOutputStream.
>>
>> The moment code holding a reference becomes untrusted, the reference 
>> has escaped.
>>
>> Instead of using a GuardedObject, or checking permission in 
>> constructors, to deal with Permission's that can be revoked, we need 
>> to encapsulate the object that needs protection with a SecurityDelegate.
>>
>> During a checkPermission call, the current Thread's 
>> AccessControlContext is obtained, and (gross simplification) is asked 
>> to checkPermission.  The AccessControlContext contains all the 
>> ProtectionDomain's on the stack, all ProtectionDomains on the stack 
>> must have the Permission for it to succeed.  The ProtectionDomain's 
>> contained by the AccessControlContext are related to the class and 
>> object methods called and returned, the ProtectionDomain's are 
>> dynamically added or removed.
>>
>> So the thinking behind the SecurityDelegate's private check method is 
>> that an object must be protected in a dynamically changing environment:
>>
>>   1. Has the RevokeableDynamicPolicy advised that a check must be
>>      performed?
>>   2. Is this the same thread that the last security check was made
>>      against?  If we haven't been advised that there is a reduction of
>>      trust in our dynamic Security environment and the last
>>      checkPermission call succeeded on this thread, then we can assume
>>      that this Tread is still safe.
>>   3. If this thread is different or new, then we must checkPermission,
>>      regardless of whether trust has changed recently or not.
>>
>> The costs:
>>
>>   1. Multi-threading is penalised (although a WeakMap could be
>>      utilised, with threads as keys, and boolean check values, where
>>      all are set true by the notify() call).
>>   2. The three "if" calls on every method invocation, check, null and
>>      == Thread.
>>   3. Replicating the check method on all implementers (this will
>>      require a helper class to implement the check).
>>   4. The RevokeableDynamicPolicy will need to notify all
>>      SecurityDelegate's every time a reduction in trust occurs, it will
>>      rely on GC to clean up and remove SecurityDelegates.
>>
>> The assumption is if the current Thread was trustworthy last call and 
>> the environment hasn't experienced a reduction of trust, we can still 
>> trust this thread.  There is of course a risk that a Thread may have 
>> a new ProtectionDomain on it's stack that isn't trusted, however this 
>> could still happen in the case of the guarded object, where the 
>> environment doesn't experience a reduction of trust and the trusted 
>> code must be trusted not to let the reference escape it's own 
>> ProtectionDomain.  Any code that experiences a reduction of trust 
>> will receive an AccessControlException.
>>
>> Cheers,
>>
>> Peter.
>>
>> Peter Firmstone wrote:
>>> Tim Blackman wrote:
>>>> On Jul 31, 2010, at 11:53 PM, Peter Firmstone wrote:
>>>>
>>>> <snip>
>>>>> A RevokeableDynamicPolicy supports the addition or removal of 
>>>>> PermissionGrant's
>>>>>     
>>>> <snip>
>>>>   
>>>
>>>> Hmmm.
>>>>
>>>> I remember talking with Bob and Mike Warres about this.  The 
>>>> problem with removing permission grants is that  when code is 
>>>> granted a permission, it can very likely squirrel away something -- 
>>>> an object, or another capability available through the granted 
>>>> permission -- that will permit it to perform the same operation 
>>>> again without the JVM checking for the permission again.  Our 
>>>> conclusion was that there was probably no effective way to 
>>>> implement removal of permission grants.
>>>>
>>>> Perhaps there is something about the particulars of what you have 
>>>> done here to negate this argument -- and I have not had the time to 
>>>> check the details of your stuff myself to be sure -- but my guess 
>>>> is that it will be difficult or impossible to do this in an 
>>>> airtight manner.
>>>>   
>>>
>>> First I'd better point out that this is still an experiment and may 
>>> not make a release, but I'm glad you've responded, as security is a 
>>> difficult issue and all help is appreciated.
>>>
>>> The SecurityDelegate's I mentioned earlier, are of course a 
>>> compromise, many existing security guards on existing Java classes 
>>> are on constructors or methods that return object's, however 
>>> object's such as OutputStream and the likes, have unguarded methods, 
>>> so once these objects have been released, the reference can be 
>>> stored, by what may later become untrusted, and the methods called 
>>> by untrusted objects.
>>>
>>> The SecurityDelegate is a wrapper class that implements the same 
>>> interface as the guarded object, but once notified of a Permission 
>>> revocation ensures the next thread to access the guarded object, 
>>> through the SecurityDelegate has AccessController.checkPermission 
>>> called again.
>>>
>>> Because of the cost of the Permission check, it's too expensive to 
>>> call on every method invocation.
>>>
>>> However there is still a flaw in this, consider for a moment an 
>>> object protected by a SecurityDelegate, permission's are revoked, 
>>> the policy notifies all SecurityDelegate's of a revocation, they 
>>> ensure the next method call rechecks permission.  The flaw is that 
>>> once the SecurityDelegate, containing the protected object is in 
>>> untrusted hands, we don't know how many references to it exist.  The 
>>> next call might have permission, however there is no guarantee that 
>>> another following will.  The mixing of untrusted and trusted code is 
>>> the risk.
>>>
>>> While it cannot be eliminated entirely, every method requiring 
>>> protection, should execute a private method something like the 
>>> following (Constructors and methods excluded for clarity):
>>>
>>> class ProtectedOutputStream extends OutputStream implements 
>>> SecurityDelegate {
>>>
>>>    private final OutputStream protected;
>>>    private volatile boolean check = true;
>>>    private volatile Thread currentThread = null;
>>>
>>>    public void notify(){
>>>       check = true;
>>>    }
>>>
>>>    private void check(){
>>>       if ( check == true) {
>>>          AccessController.checkPermission(perm);
>>>          currentThread = Thread.currentThread();
>>>          check = false;
>>>          return;
>>>       }
>>>       if ( currentThread != null ) {
>>>          if (Thread.currentThread() == currentThread ) {
>>>             return;
>>>          }
>>>       }
>>>        AccessController.checkPermission(perm);
>>>        currentThread = Thread.currentThread();
>>>        return;
>>>    }
>>>      public void write(byte[] b) {
>>>        check();
>>>        protected.write(b);
>>>    }
>>>
>>> }
>>>
>>> Still, I'm not sure if this is enough to protect the object, there 
>>> are some Thread timing issues I've ignored here, but those aside, I 
>>> don't want to call the AccessController every invocation, for 
>>> obvious efficiency reasons.
>>>
>>> Thought's and ideas?
>>>
>>> Cheers,
>>>
>>> Peter.
>>>
>>>
>>
>>
>
>


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Gregg Wonderly <gr...@wonderly.org>.
For quite some time, I've been using a package that I put together which uses 
XML to create an interface and a SecurityDelegate as you describe below.  It was 
embedded in one of my applications for some time, but a few years back, I pulled 
it out into a separate codebase so that I could use it in several other projects 
which had grown to need more granular security control.

I've put it out on authlib.dev.java.net.  There really is not a lot of 
documentation at this point.  This is more or less a "throw it over the wall" 
move.

Here's a summary of how it is used, and how it works.

It provides for the definition of users and groups/roles.  There is a whole GUI 
component to the code which allows editing.  This data is access/stored using a 
JDBC based backing store.

The class, org.wonderly.authlib.BuildAccess processes the XML file.  There is a 
sample XML file which shows most of what is possible, but the parsing in 
BuildAccess is the real clue to what is possible.

There are object types, which you designate the type of permission that applies 
to that object.  An example from the access.xml in the CVS tree is:

	<object type="view" access="update,read"
			permission="PermissionTwo"/>

This says that there are parameters in method class which are "view" type 
references.  PermissionTwo is used to control access to those type objects.  The 
"access" attribute represents the types of permissions that the permission 
implementation supports for its "access" parameter during construction.

A single method definition looks like the following:

	<method return="String" name="getDBUnitView" qualifiers="public">
		<descr>
		This method is used to get the description of the named view.
		</descr>
		<security>
			<filter access="read" filtered="view" filteredType="String"
				params="view" filterGeneric="String" class="TestUpdateAuthFilter"/>
			<!-- limit access="read" type="view" arg="view"/ -->
		</security>
		<args>
			<arg name="view" type="String" descr="name of the view to get the definition 
of"/>
		</args>
		<exceptions>
			<throws name="SQLException" descr="when a database access error occurs"/>
		</exceptions>
	</method>

The method signature and JavaDoc is generated from this definition.

The security section says that a filter operation should be performed to return 
the value if it is accessible, instead of throwing an exception as <limit> does.
The class, TestUpdateAuthFilter performs the filtering operation.  It implements 
a standard interface to define how the filtering works.

Here's the generated code:

	public String getDBUnitView( String view ) throws
				 java.rmi.RemoteException , SQLException {
		// Check for required access rights.
		String XXXval = null;
		String XXXtype = "filter";
		String XXXaccess = "read";


		try {
			// Call the method, authorization passes
			// Get Initial data
			String XXXlist = XXXacc.getDBUnitView( view );
			UpdateAuthFilter<String> XXXfilt = null;
			try {
				XXXfilt = new TestUpdateAuthFilter<String>();
			} catch( RuntimeException ex ) {
				log.log( Level.SEVERE, ex.toString(), ex );
				throw new AuthorizationException(
					ex.toString(), ex );
			}
			String XXXret = XXXfilt.filterList( new Object[] {view},
				 XXXlist, "read", XXXauth, XXXdb );
			secureLog(  Level.INFO, "{0}[{1}]:
					"+"getDBUnitView("+view+") ==> "+XXXret,
					 XXXauth.getUserName(), XXXaccess );
			return XXXret;
		} catch( RuntimeException ex ) {
			// Make the exception source visible
			log.log( Level.SEVERE, ex.toString(), ex );
			// Rethrow it to stop the operation
			throw ex;
		}
	}

There's a quite a bit more I can talk about and document, but I just wanted to 
throw this out.  It's licensed under the Apache license, but I did not put the 
license into every source file, yet.

Gregg Wonderly

Peter Firmstone wrote:
> Please help identify any fallacies or oversights in the following 
> arguments.
> 
> A Permission may be revoked, at any point in time after a revocation, 
> untrusted code may hold a reference to a privileged object.
> 
> Some Permission's protect methods, such as Thread.interrupt(), these are 
> effectively revoked with the existing Java security model, however other 
> objects are only protected in their constructor, the responsibility 
> being on the trusted code, not to let their references escape, such as 
> FileOutputStream.
> 
> The moment code holding a reference becomes untrusted, the reference has 
> escaped.
> 
> Instead of using a GuardedObject, or checking permission in 
> constructors, to deal with Permission's that can be revoked, we need to 
> encapsulate the object that needs protection with a SecurityDelegate.
> 
> During a checkPermission call, the current Thread's AccessControlContext 
> is obtained, and (gross simplification) is asked to checkPermission.  
> The AccessControlContext contains all the ProtectionDomain's on the 
> stack, all ProtectionDomains on the stack must have the Permission for 
> it to succeed.  The ProtectionDomain's contained by the 
> AccessControlContext are related to the class and object methods called 
> and returned, the ProtectionDomain's are dynamically added or removed.
> 
> So the thinking behind the SecurityDelegate's private check method is 
> that an object must be protected in a dynamically changing environment:
> 
>   1. Has the RevokeableDynamicPolicy advised that a check must be
>      performed?
>   2. Is this the same thread that the last security check was made
>      against?  If we haven't been advised that there is a reduction of
>      trust in our dynamic Security environment and the last
>      checkPermission call succeeded on this thread, then we can assume
>      that this Tread is still safe.
>   3. If this thread is different or new, then we must checkPermission,
>      regardless of whether trust has changed recently or not.
> 
> The costs:
> 
>   1. Multi-threading is penalised (although a WeakMap could be
>      utilised, with threads as keys, and boolean check values, where
>      all are set true by the notify() call).
>   2. The three "if" calls on every method invocation, check, null and
>      == Thread.
>   3. Replicating the check method on all implementers (this will
>      require a helper class to implement the check).
>   4. The RevokeableDynamicPolicy will need to notify all
>      SecurityDelegate's every time a reduction in trust occurs, it will
>      rely on GC to clean up and remove SecurityDelegates.
> 
> The assumption is if the current Thread was trustworthy last call and 
> the environment hasn't experienced a reduction of trust, we can still 
> trust this thread.  There is of course a risk that a Thread may have a 
> new ProtectionDomain on it's stack that isn't trusted, however this 
> could still happen in the case of the guarded object, where the 
> environment doesn't experience a reduction of trust and the trusted code 
> must be trusted not to let the reference escape it's own 
> ProtectionDomain.  Any code that experiences a reduction of trust will 
> receive an AccessControlException.
> 
> Cheers,
> 
> Peter.
> 
> Peter Firmstone wrote:
>> Tim Blackman wrote:
>>> On Jul 31, 2010, at 11:53 PM, Peter Firmstone wrote:
>>>
>>> <snip>
>>>> A RevokeableDynamicPolicy supports the addition or removal of 
>>>> PermissionGrant's
>>>>     
>>> <snip>
>>>   
>>
>>> Hmmm.
>>>
>>> I remember talking with Bob and Mike Warres about this.  The problem 
>>> with removing permission grants is that  when code is granted a 
>>> permission, it can very likely squirrel away something -- an object, 
>>> or another capability available through the granted permission -- 
>>> that will permit it to perform the same operation again without the 
>>> JVM checking for the permission again.  Our conclusion was that there 
>>> was probably no effective way to implement removal of permission grants.
>>>
>>> Perhaps there is something about the particulars of what you have 
>>> done here to negate this argument -- and I have not had the time to 
>>> check the details of your stuff myself to be sure -- but my guess is 
>>> that it will be difficult or impossible to do this in an airtight 
>>> manner.
>>>   
>>
>> First I'd better point out that this is still an experiment and may 
>> not make a release, but I'm glad you've responded, as security is a 
>> difficult issue and all help is appreciated.
>>
>> The SecurityDelegate's I mentioned earlier, are of course a 
>> compromise, many existing security guards on existing Java classes are 
>> on constructors or methods that return object's, however object's such 
>> as OutputStream and the likes, have unguarded methods, so once these 
>> objects have been released, the reference can be stored, by what may 
>> later become untrusted, and the methods called by untrusted objects.
>>
>> The SecurityDelegate is a wrapper class that implements the same 
>> interface as the guarded object, but once notified of a Permission 
>> revocation ensures the next thread to access the guarded object, 
>> through the SecurityDelegate has AccessController.checkPermission 
>> called again.
>>
>> Because of the cost of the Permission check, it's too expensive to 
>> call on every method invocation.
>>
>> However there is still a flaw in this, consider for a moment an object 
>> protected by a SecurityDelegate, permission's are revoked, the policy 
>> notifies all SecurityDelegate's of a revocation, they ensure the next 
>> method call rechecks permission.  The flaw is that once the 
>> SecurityDelegate, containing the protected object is in untrusted 
>> hands, we don't know how many references to it exist.  The next call 
>> might have permission, however there is no guarantee that another 
>> following will.  The mixing of untrusted and trusted code is the risk.
>>
>> While it cannot be eliminated entirely, every method requiring 
>> protection, should execute a private method something like the 
>> following (Constructors and methods excluded for clarity):
>>
>> class ProtectedOutputStream extends OutputStream implements 
>> SecurityDelegate {
>>
>>    private final OutputStream protected;
>>    private volatile boolean check = true;
>>    private volatile Thread currentThread = null;
>>
>>    public void notify(){
>>       check = true;
>>    }
>>
>>    private void check(){
>>       if ( check == true) {
>>          AccessController.checkPermission(perm);
>>          currentThread = Thread.currentThread();
>>          check = false;
>>          return;
>>       }
>>       if ( currentThread != null ) {
>>          if (Thread.currentThread() == currentThread ) {
>>             return;
>>          }
>>       }
>>        AccessController.checkPermission(perm);
>>        currentThread = Thread.currentThread();
>>        return;
>>    }
>>      public void write(byte[] b) {
>>        check();
>>        protected.write(b);
>>    }
>>
>> }
>>
>> Still, I'm not sure if this is enough to protect the object, there are 
>> some Thread timing issues I've ignored here, but those aside, I don't 
>> want to call the AccessController every invocation, for obvious 
>> efficiency reasons.
>>
>> Thought's and ideas?
>>
>> Cheers,
>>
>> Peter.
>>
>>
> 
> 


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Patricia Shanahan <pa...@acm.org>.
Peter Firmstone wrote:
...
> Basically: Method call from new thread? Permission check.  Permission 
> revoked? Permission check again.  Previously checked Thread, no relevant 
> revocation's since (of same Class<Permission>)? Don't check again, 
> return quickly.
> 
> The assumption I've made is, it will be very difficult for an attacker 
> to predict when a thread will access a method on the delegate, then 
> later, be called by that very same thread, so his class can call the 
> delegate unchecked.  Any thoughts on this?  Am I overlooking something?
...

What are the implications of all this for TaskManager? I have not yet 
investigated whether it is used to run proxy code, but some proxy 
actions seem like natural parallel tasks, so it should be permitted.

There is no association between each TaskManager thread and any 
particular subset of its tasks. The timing is somewhat controllable 
through runAfter decisions. A task can sit around on the TaskManager 
queue returning false from runAfter until a task of some specified type 
has just run.

Patricia

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Has anyone spotted the security flaw?  The revoke method shouldn't 
return the Reaper, it should perform it instead before the write lock is 
released.

At first glance, there appears to be a lot going on in the ecm object, 
the size of the collections are minimised by the following strategies:

   1. When a Permission goes out of scope, it becomes weakly reachable,
      it, along with the Set of AccessControlContext's are removed from
      the cache by garbage collection.  Most Permission checks create a
      Permission at the time of checking, so the Permission goes out of
      scope quickly.    Remember the Permission checks performed by the
      ECM are intended to be repeated in succession, such that an
      initial check is made and provided the AccessControlContext hasn't
      changed, no further checks are made.
   2. The execution cache keeps track of the Threads that are within the
      try finally block, these are added and removed during very short
      intervals, until at the time of revocation the write lock is
      obtained.  The execution cache is guaranteed to be cleaned as the
      end() method is always executed by finally.
   3. Set's are used to avoid duplication.
   4. Threads cannot be confused with each other, making it easy to
      determine when a thread is in the current execution cache.
   5. The revocation is not considered complete until the policy revoke
      method has completed.  There is a period where trust is reduced,
      during revocation, but revocation is not complete.


Peter Firmstone wrote:
> Fred,
>
> Does this look more like it?
>
> Multiple policy, multiple Permission checks, and an execution cache to 
> minimise re checking during revocation.
>
> it's used like this:
>
> ecm.begin(reaper);
> try{
>    ecm.checkPermission(p);
>    ecm.checkPermission(q);
>    // Do something briefly
>    return something;
> } finally {
>    ecm.end();
> }
>
> /*
> * Licensed to the Apache Software Foundation (ASF) under one
> * or more contributor license agreements.  See the NOTICE file
> * distributed with this work for additional information
> * regarding copyright ownership. The ASF licenses this file
> * to you under the Apache License, Version 2.0 (the
> * "License"); you may not use this file except in compliance
> * with the License. You may obtain a copy of the License at
> *
> *      http://www.apache.org/licenses/LICENSE-2.0
> *
> * Unless required by applicable law or agreed to in writing, software
> * distributed under the License is distributed on an "AS IS" BASIS,
> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
> implied.
> * See the License for the specific language governing permissions and
> * limitations under the License.
> */
>
> package org.apache.river.imp.security.policy.se;
>
> import java.security.AccessControlContext;
> import java.security.AccessControlException;
> import java.security.AccessController;
> import java.security.Permission;
> import java.util.Collections;
> import java.util.HashMap;
> import java.util.HashSet;
> import java.util.Iterator;
> import java.util.Map;
> import java.util.Set;
> import java.util.concurrent.ConcurrentHashMap;
> import java.util.concurrent.ConcurrentMap;
> import java.util.concurrent.locks.Lock;
> import java.util.concurrent.locks.ReadWriteLock;
> import java.util.concurrent.locks.ReentrantReadWriteLock;
> import org.apache.river.api.security.ExecutionContextManager;
> import org.apache.river.api.security.Reaper;
> import org.apache.river.imp.util.ConcurrentWeakIdentityMap;
>
> /**
> * Only a Single instance of ECM is required per policy, it is threadsafe.
> * Threads will wait until revoke is complete.
> *
> * @author Peter Firmstone
> */
> public class ECM implements ExecutionContextManager{
>      private final ConcurrentMap<Permission,Set<AccessControlContext>> 
> checkedCache;
>    private final ConcurrentMap<AccessControlContext, Set<Thread>> 
> executionCache;
>    private final ConcurrentMap<Thread, Set<AccessControlContext>> 
> threadAssociation;
>    private final ConcurrentMap<Thread, Reaper> association;
>    private final ReadWriteLock blockLock;
>    private final Lock rl; // This lock is held briefly by callers of 
> begin and end.
>    private final Lock wl; // This lock is held by revocation.
>      ECM(){
>    checkedCache = new ConcurrentWeakIdentityMap<Permission, 
> Set<AccessControlContext>>();
>    executionCache = new ConcurrentHashMap<AccessControlContext, 
> Set<Thread>>();
>    threadAssociation = new ConcurrentHashMap<Thread, 
> Set<AccessControlContext>>();
>    association = new ConcurrentHashMap<Thread, Reaper>();
>    blockLock = new ReentrantReadWriteLock();
>    rl = blockLock.readLock();
>    wl = blockLock.writeLock();
>    }
>      Set<Reaper> revoke(Set<Permission> perms){
>    wl.lock();
>    try {
>        /* This is where we determine what needs to be revoked, we first
>         * get all the AccessControlContexts for the Permission class,
>         * these are removed from the checkedCache, then we narrow
>         * down the AccessControlContext's to only those in the
>         * execution cache, each AccessControlContext in the execution 
> cache
>         * has checkPermission(Permission) called for each revoked
>         * permission.  Any that throw AccessControlException will be
>         * caught and have their Reaper run, for the Threads referenced
>         * from that AccessControlContext.
>         *
>         * The RevokeableDynamicPolicy will have updated the current
>         * Permission's after revocation, so the ProtectionDomain's in
>         * the AccessControlContext will now throw an 
> AccessControlException
>         * if the revocation applied to them.
>         *
>         * The wl lock will be released, any threads that were interrupted
>         * will exit through the finally block and remove themselves
>         * from the execution cache.  Those that aren't may throw
>         * an exception and bubble up the stack, due to closing sockets
>         * etc.
>         *
>         * The execution cache is comprised of the following fields:
>         * executionCache
>         * threadAssociation
>         */
>        // Identify Permission's with matching class files to those 
> revoked.
>        Set<Class> permClasses = new HashSet<Class>();
>        Iterator<Permission> itp = perms.iterator();
>        while (itp.hasNext()){
>        permClasses.add(itp.next().getClass());
>        }
>        // Remove Permission's and AccessControlContexts from the 
> checked cache.
>        Map<Permission, Set<AccessControlContext>> removed =
>            new HashMap<Permission, Set<AccessControlContext>>();
>        Iterator<Permission> keysIt = checkedCache.keySet().iterator();
>        while (keysIt.hasNext()){
>        Permission p = keysIt.next();
>        if (permClasses.contains(p.getClass())){
>            Set<AccessControlContext> a = checkedCache.get(p);
>            keysIt.remove();
>            removed.put(p, a);
>        }              }
>        // Match the AccessControlContexts with the execution cache;
>        Set<AccessControlContext> exCache = executionCache.keySet();
>        // Get the AccessControlContext's in the execution cache that 
> fail.
>        Set<AccessControlContext> accFails = new 
> HashSet<AccessControlContext>();
>        Iterator<Permission> retests = removed.keySet().iterator();
>        while (retests.hasNext()){
>        Permission p = retests.next();
>        Set<AccessControlContext> rechecks = removed.get(p);
>        Iterator<AccessControlContext> recheck = rechecks.iterator();
>        while (recheck.hasNext()){
>            AccessControlContext a = recheck.next();
>            if (accFails.contains(a)) continue;
>            // This really narrows down the checks.
>            if (exCache.contains(a)){
>            try {
>                a.checkPermission(p);
>            } catch (AccessControlException e){
>                accFails.add(a);
>            }
>            }
>        }
>        }
>        // Identify the threads and prepare reapers.
>        Set<Reaper> reapers = new HashSet<Reaper>();
>        Iterator<AccessControlContext> failedAcc = accFails.iterator();
>        while (failedAcc.hasNext()){
>        AccessControlContext fail = failedAcc.next();
>        Set<Thread> threads = executionCache.get(fail);
>        Iterator<Thread> i = threads.iterator();
>        while (i.hasNext()) {
>            Thread t = i.next();
>            Reaper r = association.get(t);
>            r.put(t);
>            reapers.add(r);
>        }              }
>        return reapers;
>    } finally {
>        wl.unlock();
>    }
>    }
>
>    public void begin(Reaper r) {
>    Thread currentThread = Thread.currentThread();
>    association.put(currentThread, r);      }
>
>    public void checkPermission(Permission p) throws 
> AccessControlException {
>    Thread currentThread = Thread.currentThread();
>    AccessControlContext executionContext = AccessController.getContext();
>    rl.lock();
>    try {
>        // execution cache.
>        Set<Thread> exCacheThreadSet = 
> executionCache.get(executionContext);
>        if ( exCacheThreadSet == null ){
>        exCacheThreadSet = Collections.synchronizedSet(new 
> HashSet<Thread>());
>        Set<Thread> existed = 
> executionCache.putIfAbsent(executionContext, exCacheThreadSet);
>        if (existed != null){
>            exCacheThreadSet = existed;
>        }
>        }
>        exCacheThreadSet.add(currentThread);// end execution cache.
>        // thread association
>        Set<AccessControlContext> thAssocSet = 
> threadAssociation.get(currentThread);
>        if ( thAssocSet == null ){
>        thAssocSet = Collections.synchronizedSet(new 
> HashSet<AccessControlContext>());
>        Set<AccessControlContext> existed = 
> threadAssociation.putIfAbsent(currentThread, thAssocSet);
>        if (existed != null){
>            thAssocSet = existed;
>        }
>        }
>        thAssocSet.add(executionContext); // end thread association.
>        // checkedCache - the permission check.
>        Set<AccessControlContext> checked = checkedCache.get(p);
>        if (checked == null ){
>        checked = Collections.synchronizedSet(new 
> HashSet<AccessControlContext>());
>        Set<AccessControlContext> existed = checkedCache.putIfAbsent(p, 
> checked);
>        if (existed != null){
>            checked = existed;
>        }
>        }
>        if ( checked.contains(executionContext)) return; // it's passed 
> before.
>        executionContext.checkPermission(p); // Throws 
> AccessControlException
>        // If we get here cache the AccessControlContext.
>        checked.add(executionContext); // end checkedCache.          } 
> finally {
>        rl.unlock();
>    }
>    }
>
>    public void end() {
>    // Teardown.
>    Thread t = Thread.currentThread();
>    rl.lock();
>    try {
>        association.remove(t);
>        Set<AccessControlContext> accSet = threadAssociation.remove(t);
>        Iterator<AccessControlContext> it = accSet.iterator();
>        while (it.hasNext()){
>        AccessControlContext acc = it.next();
>        executionCache.get(acc).remove(t);
>        }
>    }finally {
>        rl.unlock();
>    }
>      }
>
> }
>
>


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred,

Does this look more like it?

Multiple policy, multiple Permission checks, and an execution cache to 
minimise re checking during revocation.

it's used like this:

ecm.begin(reaper);
try{
    ecm.checkPermission(p);
    ecm.checkPermission(q);
    // Do something briefly
    return something;
} finally {
    ecm.end();
}

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.river.imp.security.policy.se;

import java.security.AccessControlContext;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.Permission;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.river.api.security.ExecutionContextManager;
import org.apache.river.api.security.Reaper;
import org.apache.river.imp.util.ConcurrentWeakIdentityMap;

/**
 * Only a Single instance of ECM is required per policy, it is threadsafe.
 * Threads will wait until revoke is complete.
 *
 * @author Peter Firmstone
 */
public class ECM implements ExecutionContextManager{
   
    private final ConcurrentMap<Permission,Set<AccessControlContext>> 
checkedCache;
    private final ConcurrentMap<AccessControlContext, Set<Thread>> 
executionCache;
    private final ConcurrentMap<Thread, Set<AccessControlContext>> 
threadAssociation;
    private final ConcurrentMap<Thread, Reaper> association;
    private final ReadWriteLock blockLock;
    private final Lock rl; // This lock is held briefly by callers of 
begin and end.
    private final Lock wl; // This lock is held by revocation.
   
    ECM(){
    checkedCache = new ConcurrentWeakIdentityMap<Permission, 
Set<AccessControlContext>>();
    executionCache = new ConcurrentHashMap<AccessControlContext, 
Set<Thread>>();
    threadAssociation = new ConcurrentHashMap<Thread, 
Set<AccessControlContext>>();
    association = new ConcurrentHashMap<Thread, Reaper>();
    blockLock = new ReentrantReadWriteLock();
    rl = blockLock.readLock();
    wl = blockLock.writeLock();
    }
   
    Set<Reaper> revoke(Set<Permission> perms){
    wl.lock();
    try {
        /* This is where we determine what needs to be revoked, we first
         * get all the AccessControlContexts for the Permission class,
         * these are removed from the checkedCache, then we narrow
         * down the AccessControlContext's to only those in the
         * execution cache, each AccessControlContext in the execution cache
         * has checkPermission(Permission) called for each revoked
         * permission.  Any that throw AccessControlException will be
         * caught and have their Reaper run, for the Threads referenced
         * from that AccessControlContext.
         *
         * The RevokeableDynamicPolicy will have updated the current
         * Permission's after revocation, so the ProtectionDomain's in
         * the AccessControlContext will now throw an AccessControlException
         * if the revocation applied to them.
         *
         * The wl lock will be released, any threads that were interrupted
         * will exit through the finally block and remove themselves
         * from the execution cache.  Those that aren't may throw
         * an exception and bubble up the stack, due to closing sockets
         * etc.
         *
         * The execution cache is comprised of the following fields:
         * executionCache
         * threadAssociation
         */
        // Identify Permission's with matching class files to those revoked.
        Set<Class> permClasses = new HashSet<Class>();
        Iterator<Permission> itp = perms.iterator();
        while (itp.hasNext()){
        permClasses.add(itp.next().getClass());
        }
        // Remove Permission's and AccessControlContexts from the 
checked cache.
        Map<Permission, Set<AccessControlContext>> removed =
            new HashMap<Permission, Set<AccessControlContext>>();
        Iterator<Permission> keysIt = checkedCache.keySet().iterator();
        while (keysIt.hasNext()){
        Permission p = keysIt.next();
        if (permClasses.contains(p.getClass())){
            Set<AccessControlContext> a = checkedCache.get(p);
            keysIt.remove();
            removed.put(p, a);
        }       
        }
        // Match the AccessControlContexts with the execution cache;
        Set<AccessControlContext> exCache = executionCache.keySet();
        // Get the AccessControlContext's in the execution cache that fail.
        Set<AccessControlContext> accFails = new 
HashSet<AccessControlContext>();
        Iterator<Permission> retests = removed.keySet().iterator();
        while (retests.hasNext()){
        Permission p = retests.next();
        Set<AccessControlContext> rechecks = removed.get(p);
        Iterator<AccessControlContext> recheck = rechecks.iterator();
        while (recheck.hasNext()){
            AccessControlContext a = recheck.next();
            if (accFails.contains(a)) continue;
            // This really narrows down the checks.
            if (exCache.contains(a)){
            try {
                a.checkPermission(p);
            } catch (AccessControlException e){
                accFails.add(a);
            }
            }
        }
        }
        // Identify the threads and prepare reapers.
        Set<Reaper> reapers = new HashSet<Reaper>();
        Iterator<AccessControlContext> failedAcc = accFails.iterator();
        while (failedAcc.hasNext()){
        AccessControlContext fail = failedAcc.next();
        Set<Thread> threads = executionCache.get(fail);
        Iterator<Thread> i = threads.iterator();
        while (i.hasNext()) {
            Thread t = i.next();
            Reaper r = association.get(t);
            r.put(t);
            reapers.add(r);
        }       
        }
        return reapers;
    } finally {
        wl.unlock();
    }
    }

    public void begin(Reaper r) {
    Thread currentThread = Thread.currentThread();
    association.put(currentThread, r);   
    }

    public void checkPermission(Permission p) throws 
AccessControlException {
    Thread currentThread = Thread.currentThread();
    AccessControlContext executionContext = AccessController.getContext();
    rl.lock();
    try {
        // execution cache.
        Set<Thread> exCacheThreadSet = executionCache.get(executionContext);
        if ( exCacheThreadSet == null ){
        exCacheThreadSet = Collections.synchronizedSet(new 
HashSet<Thread>());
        Set<Thread> existed = 
executionCache.putIfAbsent(executionContext, exCacheThreadSet);
        if (existed != null){
            exCacheThreadSet = existed;
        }
        }
        exCacheThreadSet.add(currentThread);// end execution cache.
        // thread association
        Set<AccessControlContext> thAssocSet = 
threadAssociation.get(currentThread);
        if ( thAssocSet == null ){
        thAssocSet = Collections.synchronizedSet(new 
HashSet<AccessControlContext>());
        Set<AccessControlContext> existed = 
threadAssociation.putIfAbsent(currentThread, thAssocSet);
        if (existed != null){
            thAssocSet = existed;
        }
        }
        thAssocSet.add(executionContext); // end thread association.
        // checkedCache - the permission check.
        Set<AccessControlContext> checked = checkedCache.get(p);
        if (checked == null ){
        checked = Collections.synchronizedSet(new 
HashSet<AccessControlContext>());
        Set<AccessControlContext> existed = checkedCache.putIfAbsent(p, 
checked);
        if (existed != null){
            checked = existed;
        }
        }
        if ( checked.contains(executionContext)) return; // it's passed 
before.
        executionContext.checkPermission(p); // Throws 
AccessControlException
        // If we get here cache the AccessControlContext.
        checked.add(executionContext); // end checkedCache.       
    } finally {
        rl.unlock();
    }
    }

    public void end() {
    // Teardown.
    Thread t = Thread.currentThread();
    rl.lock();
    try {
        association.remove(t);
        Set<AccessControlContext> accSet = threadAssociation.remove(t);
        Iterator<AccessControlContext> it = accSet.iterator();
        while (it.hasNext()){
        AccessControlContext acc = it.next();
        executionCache.get(acc).remove(t);
        }
    }finally {
        rl.unlock();
    }
   
    }

}


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.river.imp.security.policy.se;

import java.security.AccessControlContext;
import java.security.AccessControlContext;
import java.security.AccessControlContext;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.Permission;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.river.api.security.ExecutionContextManager;
import org.apache.river.api.security.Reaper;
import org.apache.river.imp.util.ConcurrentWeakIdentityMap;

/**
 * Only a Single instance of ECM is required per policy, it is threadsafe.
 * Threads will wait until revoke is complete.
 *
 * @author Peter Firmstone
 */
public class ECM implements ExecutionContextManager{
   
    private final ConcurrentMap<Class,Set<AccessControlContext>> 
checkedCache;
    private final ConcurrentMap<AccessControlContext, Set<Thread>> 
executionCache;
    private final ConcurrentMap<Thread, Set<AccessControlContext>> 
threadAssociation;
    private final ConcurrentMap<Thread, Reaper> association;
    private final ReadWriteLock blockLock;
    private final Lock rl; // This lock is held briefly by callers of 
begin and end.
    private final Lock wl; // This lock is held by revocation.
   
    ECM(){
    checkedCache = new ConcurrentWeakIdentityMap<Class, 
Set<AccessControlContext>>();
    executionCache = new ConcurrentHashMap<AccessControlContext, 
Set<Thread>>();
    threadAssociation = new ConcurrentHashMap<Thread, 
Set<AccessControlContext>>();
    association = new ConcurrentHashMap<Thread, Reaper>();
    blockLock = new ReentrantReadWriteLock();
    rl = blockLock.readLock();
    wl = blockLock.writeLock();
    }
   
    boolean revoke(){
    wl.lock();
    try {
        /* This is where we determine what needs to be revoked, we first
         * get all the AccessControlContexts for the Permission class,
         * these are removed from the checkedCache, then we narrow
         * down the AccessControlContext's to only those in the
         * execution cache, each AccessControlContext in the execution cache
         * has checkPermission(Permission) called for each revoked
         * permission.  Any that throw AccessControlException will be
         * caught and have their Reaper run, for the Threads referenced
         * from that AccessControlContext.
         *
         * The RevokeableDynamicPolicy will have updated the current
         * Permission's after revocation, so the ProtectionDomain's in
         * the AccessControlContext will now throw an AccessControlException
         * if the revocation applied to them.
         *
         * The wl lock will be released, any threads that were interrupted
         * will exit through the finally block and remove themselves
         * from the execution cache.  Those that aren't may throw
         * an exception, end() and bubble up the stack, due to closing 
sockets
         * etc.
         *
         * The execution cache is comprised of the following fields:
         * executionCache
         * threadAssociation
         *
         *
         */
        return false;
    } finally {
        wl.unlock();
    }
    }

    public void begin(Reaper r) {
    Thread currentThread = Thread.currentThread();
    association.put(currentThread, r);   
    }

    public void checkPermission(Permission p) throws 
AccessControlException {
    Thread currentThread = Thread.currentThread();
    AccessControlContext executionContext = AccessController.getContext();
    rl.lock();
    try {
        // execution cache.
        Set<Thread> exCacheThreadSet = executionCache.get(executionContext);
        if ( exCacheThreadSet == null ){
        exCacheThreadSet = Collections.synchronizedSet(new 
HashSet<Thread>());
        Set<Thread> existed = 
executionCache.putIfAbsent(executionContext, exCacheThreadSet);
        if (existed != null){
            exCacheThreadSet = existed;
        }
        }
        exCacheThreadSet.add(currentThread);// end execution cache.
        // thread association
        Set<AccessControlContext> thAssocSet = 
threadAssociation.get(currentThread);
        if ( thAssocSet == null ){
        thAssocSet = Collections.synchronizedSet(new 
HashSet<AccessControlContext>());
        Set<AccessControlContext> existed = 
threadAssociation.putIfAbsent(currentThread, thAssocSet);
        if (existed != null){
            thAssocSet = existed;
        }
        }
        thAssocSet.add(executionContext); // end thread association.
        // checkedCache - the permission check.
        Set<AccessControlContext> checked = checkedCache.get(p);
        if (checked == null ){
        checked = Collections.synchronizedSet(new 
HashSet<AccessControlContext>());
        Set<AccessControlContext> existed = 
checkedCache.putIfAbsent(p.getClass(), checked);
        if (existed != null){
            checked = existed;
        }
        }
        if ( checked.contains(executionContext)) return; // it's passed 
before.
        executionContext.checkPermission(p); // Throws 
AccessControlException
        // If we get here cache the AccessControlContext.
        checked.add(executionContext); // end checkedCache.       
    } finally {
        rl.unlock();
    }
    }

    // always called from a finally block.
    public void end() {
    // Teardown.
    Thread t = Thread.currentThread();
    rl.lock();
    try {
        association.remove(t);
        Set<AccessControlContext> accSet = threadAssociation.remove(t);
        Iterator<AccessControlContext> it = accSet.iterator();
        while (it.hasNext()){
        AccessControlContext acc = it.next();
        executionCache.get(acc).remove(t);
        }
    }finally {
        rl.unlock();
    }
   
    }

}


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
How about this for an ExecutionContextManager?


public interface ExecutionContextManager {

    void begin(Reaper r);

    void checkPermission(Permission p) throws AccessControlException;

    void end();

}

public interface Reaper extends Runnable {

    void put(Thread t);

}

To be used like this:

ecm.begin(reaper);
try{
    ecm.checkPermission(p);
    ecm.checkPermission(m);
    // do something, then return
    return;
}finally {
    ecm.end();
}


Two separate things are being managed here, the begin(reaper) method 
associates the current Thread with it's AccessControlContext and Reaper, 
and places it into the current execution cache, while end() removes it.

The checkPermission(p) method, checks the cache to see if the current 
AccessControlContext has been tested with the given permission, if so it 
returns, if not it checks the Permission, if it succeeds, it places it 
into the checked cache.  The Permission is then associated with the 
current thread in the execution cache.

The end() method, removes the current Thread, AccessControlContext and 
Reaper from the current execution cache.

When a revocation event occurs, a lock is held to prevent any 
begin(reaper) method's from proceeding.  The end() method in the finally 
block stops any currently executing code blocks from returning during 
the revocation event.  Next the Permission's Class files are checked 
against the Permission's currently in the execution cache.  Any with the 
matching Permission class files will require the 
AccessContorlContext.checkPermission(Permission perm) call be made 
again, any that fail will be added to a new collection pending reaping 
and removed from the checked cache.  The RevokeableDynamicPolicy is 
capable of changing the AccessControlContext result, since it is called 
by each ProtectionDomain in the AccessControlContext.

Each Reaper will be given a copy of it's Thread of execution, it doesn't 
have to use it, but it's there if the Reaper wants to just interrupt the 
thread to stop the block's execution.  The Reapers will be placed on a 
queue and run.

The locks are released once the reapers have completed.

When exit() is called by the finally block, the thread and 
AccessControlContext's are removed from the current execution cache, 
regardless of any revocation event.

It is also possible for the ExectionContextManager to have static class 
methods like AccessController.

What are your thoughts?

Peter.





Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Gregg Wonderly <gr...@wonderly.org>.
Peter Firmstone wrote:
> Fred Oliver wrote:
>> To at least partially answer my own question, I think that the answer
>> is that the socket can't be closed (at least in all cases).
>>
>> If the delegate for a resource has multiple users (codebases,
>> principals, etc.) then closing the resource because permission for one
>> of the users has been revoked denies access to the resource by the
>> remaining valid users. (This allows a denial of service attack.) And
>> then, if you can't close the resource (socket), you can't kick loose
>> the no longer trusted thread blocked reading from it. You may be able
>> to determine the special case of no user retaining access (everyone's
>> access was revoked) and can then close the resource.
>>
>> In the standard security model, there are no checks for
>> reading/writing sockets. Allowing revocation means that checks must be
>> added for each individual read or write call on the socket streams. Is
>> that level of performance satisfactory?
>>   
> 
> I've just spotted a possible performance improvement.
> 
> We can eliminate the end() call in the finally block, put all the 
> checkPermission calls there instead.  This substantially reduces the 
> caching operations.  Perhaps we can manage the Socket some other way, we 
> just block unauthorised access using the delegate?
> 
> try {
>    // Do some processing
>    return something;
> } finally {
>    ECM.checkPermission(Collection<Permission> permissions);
> }
> 
> The current expense for making a Permission call via ECM (remembering 
> the first is always going to be expensive), currently requires the three 
> ECM calls in succession:
> 
> begin();
> checkPermission(perm);
> end();
> 
> begin():
> 
>   1. Associate the thread with the reaper.
> 
> 
> checkPermission(perm):
> 
>   1. Obtain the read lock;
>   2. Add the current thread to the execution cache.
>   3. Associate the current AccessControlContext with the current thread
>   4. Check if the AccessControlContext has been checked for this
>      Permission previously.
>   5. If it has been checked before, return, else do
>      AccessController.checkPermission(perm), cache the result if it
>      succeeds.
> 
> Each end():
> 
>   1. Obtain the read lock;
>   2. Remove the thread and reaper from the cache.
>   3. Remove the thread association with the AccessControlContext.
>   4. Remove the thread from the execution cache.
> 
>      This could be simplified to (no reaper or thread caching):
> 
> checkPermission(perms)
> 
>   1. Obtain the read lock;
>   2. For each Permission, check if the current AccessControlContext has
>      been checked for this Permission previously, if so return.
>      (HashMap lookup - fast).
>   3. If the AccessControlContext hasn't been checked previously, do
>      AccessController.checkPermission(perm), cache the result if it
>      succeeds, then return.
> 
> So for performance reasons, it looks like we need to be considering some 
> other way to manage the Socket, the ECM would serve us better if we kept 
> it simple?
> 
> I think your earlier suggestion of an event notification might be more 
> useful, if provided as a parameter in the checkPermission call, in the 
> event of failure, an event would be generated, the delegate could then 
> decide what action to take.  If it only had one user, then it knows to 
> close the Socket, if it has multiple users, it might just keep score.
> 
> This stops the transmission of data from unauthorised code, but it 
> doesn't close the socket.

If there is an interface such as:

public interface PermissionChangeDelegate {
	public void permissionGranted( Permissions p );
	public void permissionRevoked( Permissions p );
}

and the code invokes a method with a signature like:

public void checkPermission( Permissions p, PermissionChangeDelegate del );

and the provider of this method is associated with grants and revokes such that 
it can know who checking for such permission uses, then there can be a callback 
to all the delegates at revocation, and the socket can be closed as appropriate 
based on the knowledge of the PermissionChangeDelegate.

But, in the end, I really do think that this is too low of a level for 
permission checks.  Open ended resources should not be visible in the API 
without some sort of wrapper class.  I create subclasses of OutputStream and 
InputStream etc. to hold references of sockets and perform checks there by not 
using the SecurityManager, but by using the JDBC backed database which is 
completely cached in memory in the auth.dev.java.net project.  With that 
facility, I don't have to worry about what granularity of "Permission" has been 
designed into the JVM resources.  Instead, I can put an appropriately grained 
control layer on top of my API, and that layer can do what is needed to manage 
things, because every API call is checked, and if a permission is revoked, that 
fact is instantly reflected into all security delegates, and the APIs will be 
controlled based on the granularity I've decided on.

Gregg Wonderly

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
An input stream delegate, might use buffering, first obtaining the data, 
writing to a buffered byte array, then do a permission check(), if the 
check fails close the underlying input stream and throw an IOException.

If the check passes, the bytes would be copied from the buffer to the 
passed in byte array and the number of bytes returned.

The delegates would have to perform at least one optimised 
ecm.checkPermission call per method.  Writes and reads with array's 
larger than the buffered array size would do more than one permission 
check, a large buffer array would be most optimal.

By using a buffer, the permission checks are called after any potential 
blocking.  If revocation has not been performed at the time of the 
permission check, it is unlikely that a following revocation could 
complete prior to copying the buffer.

Revocation itself as a process, is not instantaneous, however the caller 
on the revoke method needs to know that trust has been revoked 
completely, once this policy method has returned.

I've also since realised that the Output stream delegate below, would 
not necessarily stop a write from completing, if revocation occurs after 
the permission check, some bytes would be written to the output stream, 
the reaper would still close the output stream, so it appears to hold 
little benefit over the simpler implementation.

public void write( byte[] b) {
   ecm.begin(reaper)
   try{
      ecm.checkPermission(writePermission);
      out.write( byte[] b);
   } finally {
      end();
   }
}

In any case it appears difficult to prevent a remaining write from 
occurring once it has passed the security check.

It appears that ECM should be simpler and not track the current thread.

To protect method returns we can use:

Object method()
    try {
       // do something
       return obj;
    } finally {
       ecm.checkPermission(perm);
    }
}

To protect state:

void replace(Object o) {
    ecm.checkPermission(perm);
    this.o = o;
}

To protect functions

void doSomething()
    ecm.checkPermission(perm);
    // do something
}

To protect Object's themselves, we need security delegates.

It seems each case needs to be checked on merit.

Perhaps the best way to protect from data loss is to be proactive, 
rather than reactive, by limiting the duration a privilege is granted, 
rather than to revoke it when it has become a matter of urgency.  So how 
would we determine when a Permission is no longer needed?

Currently the Permission's code requires is found by trial and error, by 
running the code, to see what security exceptions are thrown, instead I 
think services should have an Entry with the Permission's they require, 
a client might decide to grant these Permission's or to limit them to a 
subset, or choose another service.

Since a Smart proxy may require more than one jar file, the permission's 
required should specify the permission's each require.  I figure the 
Entry's can contain PermissionGrant builders, allowing the grantor 
(client) to make the final decision.

Once a client is finished with a service, those permission's granted 
should be revoked immediately.

Thoughts?

Cheers,

Peter.

Peter Firmstone wrote:
> Clarification (I overlooked something): The 
> checkPermission(Collection<Permission> perms) in the finally block 
> would work only for intercepting a method return, but it doesn't work 
> for InputStream read() / OutputStream write(), since we wanted to stop 
> method execution, if Permission is no longer granted.
>
> For example if a socket delegate returns an OutputStream delegate, 
> that wraps an underlying OutputStream, then during the write(), if a 
> revocation occurs, we probably want to close the OutputStream, if it 
> applies.
>
> The OutputStream write() would still need a reaper, to close the 
> OutputStream causing an IOException to be thrown, although as yet I 
> haven't determined how to add debug information for an intervening 
> revocation.
>
> public void write( byte[] b) {
>    ecm.begin(reaper)
>    try{
>       ecm.checkPermission(writePermission);
>       out.write( byte[] b);
>    } finally {
>       end();
>    }
> }
>
> Is it as critical to stop a read() operation?
>
> Since the array passed into the read() operation is written to, we can 
> close this as well, causing an IOException, however the user will 
> still get some bytes written into the byte array, which it can access 
> if it catches the IOException.
>
> public int read(byte[] b) {
>    ecm.begin(reaper)
>    try{
>        ecm.checkPermission(readPermission);
>        return in.read( byte[] b);
>    } finally {
>       end();
>    }
> }
>
> But we could provide the optimised single invocation 
> checkPermission(Collection<Permission> perms) method as well, for 
> calls that don't need to be intercepted.
>
> Perhaps we could be less pedantic about read operations, provided all 
> write operations are intercepted?
>
> public int read(byte[] b) {
>    try {
>        ecm.checkPermission(readPermission);
>    } catch (AccessControlException e) {
>       this.close();
>       throw new IOException(e.toString());
>    }
>        return in.read( byte[] b);
> }
>
> This checkPermission would be very fast, with only a small amount of 
> cpu overhead, because it caches the result for the AccessControlContext.
>
> We could do this for write() as well, if the code was trusted at the 
> time of the write() call, then we might assume that the information 
> contained within, wasn't borne from an operation of malicious intent, 
> we trusted it, so the call can be allowed to complete.  This has a 
> much smaller performance penalty, any following calls will cause an 
> AccessControlExeption to be thrown, if Permission is revoked.
>
> Then write might simply be:
>
> public void write(byte[] b) {
>    try {
>        ecm.checkPermission(writePermission);
>    } catch (AccessControlException e) {
>       this.close();
>       throw new IOException(e.toString());
>    }
>    out.write(b);
> }
>
> We might consider what the uses are for Permission revocation?  I'm 
> starting to think interception might hamper performance too greatly.
>
> The major uses I see for Revocation:
>
>    * Reusing ClassLoader's, for proxy's with common code source, by
>      removing trust gained by the previous proxy.
>    * Limit the time period for which trust is granted to a third
>      party.  A Trust lease?   Trust is only granted while contact is
>      maintained.
>    * If a proxy has lost contact with it's Server, which was trusted
>      and we want to resume (without loosing state) we can revoke
>      permission, retry connecting with the Server, verify trust, then
>      re grant trust (I'm thinking about the neuromancer remote
>      reference problem).
>
> Obviously the feature got your interest, I'm wondering what other uses 
> there might have been for permission revocation?  This might help me 
> better understand the use case scenarios.
>
>
> Peter Firmstone wrote:
>> Fred Oliver wrote:
>>> To at least partially answer my own question, I think that the answer
>>> is that the socket can't be closed (at least in all cases).
>>>
>>> If the delegate for a resource has multiple users (codebases,
>>> principals, etc.) then closing the resource because permission for one
>>> of the users has been revoked denies access to the resource by the
>>> remaining valid users. (This allows a denial of service attack.) And
>>> then, if you can't close the resource (socket), you can't kick loose
>>> the no longer trusted thread blocked reading from it. You may be able
>>> to determine the special case of no user retaining access (everyone's
>>> access was revoked) and can then close the resource.
>>>
>>> In the standard security model, there are no checks for
>>> reading/writing sockets. Allowing revocation means that checks must be
>>> added for each individual read or write call on the socket streams. Is
>>> that level of performance satisfactory?
>>>   
>>
>> I've just spotted a possible performance improvement.
>>
>> We can eliminate the end() call in the finally block, put all the 
>> checkPermission calls there instead.  This substantially reduces the 
>> caching operations.  Perhaps we can manage the Socket some other way, 
>> we just block unauthorised access using the delegate?
>>
>> try {
>>    // Do some processing
>>    return something;
>> } finally {
>>    ECM.checkPermission(Collection<Permission> permissions);
>> }
>>
>> The current expense for making a Permission call via ECM (remembering 
>> the first is always going to be expensive), currently requires the 
>> three ECM calls in succession:
>>
>> begin();
>> checkPermission(perm);
>> end();
>>
>> begin():
>>
>>   1. Associate the thread with the reaper.
>>
>>
>> checkPermission(perm):
>>
>>   1. Obtain the read lock;
>>   2. Add the current thread to the execution cache.
>>   3. Associate the current AccessControlContext with the current thread
>>   4. Check if the AccessControlContext has been checked for this
>>      Permission previously.
>>   5. If it has been checked before, return, else do
>>      AccessController.checkPermission(perm), cache the result if it
>>      succeeds.
>>
>> Each end():
>>
>>   1. Obtain the read lock;
>>   2. Remove the thread and reaper from the cache.
>>   3. Remove the thread association with the AccessControlContext.
>>   4. Remove the thread from the execution cache.
>>
>>      This could be simplified to (no reaper or thread caching):
>>
>> checkPermission(perms)
>>
>>   1. Obtain the read lock;
>>   2. For each Permission, check if the current AccessControlContext has
>>      been checked for this Permission previously, if so return.
>>      (HashMap lookup - fast).
>>   3. If the AccessControlContext hasn't been checked previously, do
>>      AccessController.checkPermission(perm), cache the result if it
>>      succeeds, then return.
>>
>> So for performance reasons, it looks like we need to be considering 
>> some other way to manage the Socket, the ECM would serve us better if 
>> we kept it simple?
>>
>> I think your earlier suggestion of an event notification might be 
>> more useful, if provided as a parameter in the checkPermission call, 
>> in the event of failure, an event would be generated, the delegate 
>> could then decide what action to take.  If it only had one user, then 
>> it knows to close the Socket, if it has multiple users, it might just 
>> keep score.
>>
>> This stops the transmission of data from unauthorised code, but it 
>> doesn't close the socket.
>>
>> Cheers,
>>
>> Peter.
>>>  
>>>> If there is untrusted code on a thread's stack, and if the thread
>>>> called a delegate, and if the delegate is in the between ECM.begin()
>>>> and ECM.end(), then the delegate's reaper will be called, and it can
>>>> close the socket.
>>>>
>>>> If the revocation happened elsewhere (e.g. the untrusted code is not
>>>> on any stack, or is occupied with some other task), how does the
>>>> socket get closed?
>>>>
>>>> Fred
>>>>     
>>
>>
>>
>
>


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
A note on ProtectionDomain's,

There can be only one! ProtectionDomain's are only ever compared with 
==, they don't override equals() or hashCode().  ProtectionDomain's are 
immutable in respect to the ClassLoader, CodeSource and Principals which 
they encapsulate.  They may be made immutable in respect of Permissions 
at construction time, however when dynamic, they consult the policy.

JAAS, uses Subject's to represents users, roles, etc, the 
SubjectDomainCombiner replaces the ProtectionDomains on the stack, with 
new ProtectionDomains, merging the Principals of the executing Subject, 
with those of the existing ProtectionDomain.

The missing equals() and hashCode() methods in ProtectionDomain, means 
that caching of results for AccessControlContext's, containing 
ProtectionDomain's created by SubjectDomainCombiner's even with 
identical Principal[]'s, will not be equal and thus, the result cannot 
be optimised much, even though the originating ProtectionDomain's and 
Subject's may be identical.

jini.net.security.Security

It's used for most of the existing Jini security decisions, similar to 
AccessController, so it's a logical place to put an optimised 
checkPermissions(Collection<Permission>) call, that obtains and calls 
the ECM from the RevokeableDynamicPolicy, if in force, it also provides 
the opportunity to remove the ExecutionContextManager interface from the 
public API if necessary.

By batching the Permission's together we only call 
AccessController.getContext() once, this is useful for PermissionGrant 
processing where we have to batch check GrantPermission's

the new checkPermissions(Collection<Permission>) call will execute 
faster than AccessController.checkPermission(Permission) and provide a 
performance boost to any existing security check, not just those 
proposed so far.

Then we can get down to business, testing, will update SVN shortly so 
you can all review the code.

N.B. I decided NOT to implement an Event for Security Delegates to be 
advised of permission revocation, since a delegate
cannot know the execution context without checking it, it must alway 
check EVERY method invocation, the ECM has been designed to skip as much 
as possible and return quickly, provided the execution context hasn't 
changed or permission revoked, since last check.  I've added the method 
checkPermission(Collection<Permission>) to net.jini.security.Security 
along with some preliminary documentation.

Cheers,

Peter.

Here's an interesting security Bug:

*Bug ID:* 4857197 *
Votes* 0 *
Synopsis* switch back from Security.doPrivileged to 
AccessController.doPrivileged
*Category* jini:other *
Reported Against* 2.0beta
*Release Fixed* 2.0
*State* 10-Fix Delivered, request for enhancement
*Priority:* 3-Medium *
Related Bugs* *Submit Date* 01-MAY-2003 *
Description*

Security.doPrivileged is very expensive. Much of our code was converted to use it from a purity of 
security model perspective, but the performance hit from doing that appears to be unacceptable. 
For at least performance-critical components, if preserving the Subject isn't semantically significant
 (most particularly, there is no call out to user code), we should switch back to using 
AccessController.doPrivileged. As such, security policy files will have to live with granting 
various permissions to codesources rather than codesource+principals.

*Work Around*

N/A

*Evaluation*

Yep.




Peter Firmstone wrote:
> Performance costs of ECM access checks?
>
> How much will delegates impact performance in comparison to existing 
> SocketPermission guards?
>
> Some interesting links:
>
> www.rewerse.net/pulications/download/REWERSE-RP-2005-141.pdf
>
> www.ida.liu.se/~almhe
>
> There's some interesting performance tests available for the above 
> paper at:
>
> http://www.ida.liu.se/~almhe/publications/sm-testdata/
>
> I suspect we'll be able to achieve respectable performance figures, 
> here are some tips in the paper we can learn from:
>
>   1. Existing SocketPermission's try to perform a DNS-lookup. Bug ID's
>      related to SocketPermission problems 4155463, 4320895, 4414825,
>      4975882, 5004073
>   2. AccessController.getStackAccessControlContext was identified as an
>      expensive native method, can't avoid that one!
>   3. Performance worsens with increasing numbers of CodeSources.
>
> Some initial observations:
>
> In comparison to the existing path for security checks, we can cache 
> the result of the AccessControlContext.checkPermission(Permission) 
> calls, until a revocation occurs, removing multiple calls to 
> ProtectionDomain's contained in the AccessControlContext.
>
> Each ProtectionDomain.implies(Permission) check is typically followed 
> by Policy.getPolicyNoCheck, PolicyFile.implies(ProtectionDomain, 
> Permission), SynchronizedMap.get(WeakHashMap.get(ProtectionDomain)), 
> Permissions.implies(Permission), Permissions.getPermissionCollection, 
> HashMap.get(Class<Permission>), PermissionCollection.implies(Permission).
>
> Synchronization creates significant points of contention, although 
> that has recently been solved with DynamicConcurrentPolicyProvider, 
> however we still need to performance test it.
>
> AccessControlContext has reasonable equals() and hashCode() 
> implementations, it will perform well in concurrent cache 
> collections.  Typically Permission equals and hashCode implementations 
> are also reasonable.  The first call from an AccessControlContext will 
> be the most expensive, however in between revocations, repeated calls 
> will be cheap, apart from the native call getStackAccessControlContext.
>
> I don't want to be calling DNS!
>
> Cheers,
>
> Peter.
>
>
> Peter Firmstone wrote:
>> Clarification (I overlooked something): The 
>> checkPermission(Collection<Permission> perms) in the finally block 
>> would work only for intercepting a method return, but it doesn't work 
>> for InputStream read() / OutputStream write(), since we wanted to 
>> stop method execution, if Permission is no longer granted.
>>
>> For example if a socket delegate returns an OutputStream delegate, 
>> that wraps an underlying OutputStream, then during the write(), if a 
>> revocation occurs, we probably want to close the OutputStream, if it 
>> applies.
>>
>> The OutputStream write() would still need a reaper, to close the 
>> OutputStream causing an IOException to be thrown, although as yet I 
>> haven't determined how to add debug information for an intervening 
>> revocation.
>>
>> public void write( byte[] b) {
>>    ecm.begin(reaper)
>>    try{
>>       ecm.checkPermission(writePermission);
>>       out.write( byte[] b);
>>    } finally {
>>       end();
>>    }
>> }
>>
>> Is it as critical to stop a read() operation?
>>
>> Since the array passed into the read() operation is written to, we 
>> can close this as well, causing an IOException, however the user will 
>> still get some bytes written into the byte array, which it can access 
>> if it catches the IOException.
>>
>> public int read(byte[] b) {
>>    ecm.begin(reaper)
>>    try{
>>        ecm.checkPermission(readPermission);
>>        return in.read( byte[] b);
>>    } finally {
>>       end();
>>    }
>> }
>>
>> But we could provide the optimised single invocation 
>> checkPermission(Collection<Permission> perms) method as well, for 
>> calls that don't need to be intercepted.
>>
>> Perhaps we could be less pedantic about read operations, provided all 
>> write operations are intercepted?
>>
>> public int read(byte[] b) {
>>    try {
>>        ecm.checkPermission(readPermission);
>>    } catch (AccessControlException e) {
>>       this.close();
>>       throw new IOException(e.toString());
>>    }
>>        return in.read( byte[] b);
>> }
>>
>> This checkPermission would be very fast, with only a small amount of 
>> cpu overhead, because it caches the result for the AccessControlContext.
>>
>> We could do this for write() as well, if the code was trusted at the 
>> time of the write() call, then we might assume that the information 
>> contained within, wasn't borne from an operation of malicious intent, 
>> we trusted it, so the call can be allowed to complete.  This has a 
>> much smaller performance penalty, any following calls will cause an 
>> AccessControlExeption to be thrown, if Permission is revoked.
>>
>> Then write might simply be:
>>
>> public void write(byte[] b) {
>>    try {
>>        ecm.checkPermission(writePermission);
>>    } catch (AccessControlException e) {
>>       this.close();
>>       throw new IOException(e.toString());
>>    }
>>    out.write(b);
>> }
>>
>> We might consider what the uses are for Permission revocation?  I'm 
>> starting to think interception might hamper performance too greatly.
>>
>> The major uses I see for Revocation:
>>
>>    * Reusing ClassLoader's, for proxy's with common code source, by
>>      removing trust gained by the previous proxy.
>>    * Limit the time period for which trust is granted to a third
>>      party.  A Trust lease?   Trust is only granted while contact is
>>      maintained.
>>    * If a proxy has lost contact with it's Server, which was trusted
>>      and we want to resume (without loosing state) we can revoke
>>      permission, retry connecting with the Server, verify trust, then
>>      re grant trust (I'm thinking about the neuromancer remote
>>      reference problem).
>>
>> Obviously the feature got your interest, I'm wondering what other 
>> uses there might have been for permission revocation?  This might 
>> help me better understand the use case scenarios.
>>
>>
>> Peter Firmstone wrote:
>>> Fred Oliver wrote:
>>>> To at least partially answer my own question, I think that the answer
>>>> is that the socket can't be closed (at least in all cases).
>>>>
>>>> If the delegate for a resource has multiple users (codebases,
>>>> principals, etc.) then closing the resource because permission for one
>>>> of the users has been revoked denies access to the resource by the
>>>> remaining valid users. (This allows a denial of service attack.) And
>>>> then, if you can't close the resource (socket), you can't kick loose
>>>> the no longer trusted thread blocked reading from it. You may be able
>>>> to determine the special case of no user retaining access (everyone's
>>>> access was revoked) and can then close the resource.
>>>>
>>>> In the standard security model, there are no checks for
>>>> reading/writing sockets. Allowing revocation means that checks must be
>>>> added for each individual read or write call on the socket streams. Is
>>>> that level of performance satisfactory?
>>>>   
>>>
>>> I've just spotted a possible performance improvement.
>>>
>>> We can eliminate the end() call in the finally block, put all the 
>>> checkPermission calls there instead.  This substantially reduces the 
>>> caching operations.  Perhaps we can manage the Socket some other 
>>> way, we just block unauthorised access using the delegate?
>>>
>>> try {
>>>    // Do some processing
>>>    return something;
>>> } finally {
>>>    ECM.checkPermission(Collection<Permission> permissions);
>>> }
>>>
>>> The current expense for making a Permission call via ECM 
>>> (remembering the first is always going to be expensive), currently 
>>> requires the three ECM calls in succession:
>>>
>>> begin();
>>> checkPermission(perm);
>>> end();
>>>
>>> begin():
>>>
>>>   1. Associate the thread with the reaper.
>>>
>>>
>>> checkPermission(perm):
>>>
>>>   1. Obtain the read lock;
>>>   2. Add the current thread to the execution cache.
>>>   3. Associate the current AccessControlContext with the current thread
>>>   4. Check if the AccessControlContext has been checked for this
>>>      Permission previously.
>>>   5. If it has been checked before, return, else do
>>>      AccessController.checkPermission(perm), cache the result if it
>>>      succeeds.
>>>
>>> Each end():
>>>
>>>   1. Obtain the read lock;
>>>   2. Remove the thread and reaper from the cache.
>>>   3. Remove the thread association with the AccessControlContext.
>>>   4. Remove the thread from the execution cache.
>>>
>>>      This could be simplified to (no reaper or thread caching):
>>>
>>> checkPermission(perms)
>>>
>>>   1. Obtain the read lock;
>>>   2. For each Permission, check if the current AccessControlContext has
>>>      been checked for this Permission previously, if so return.
>>>      (HashMap lookup - fast).
>>>   3. If the AccessControlContext hasn't been checked previously, do
>>>      AccessController.checkPermission(perm), cache the result if it
>>>      succeeds, then return.
>>>
>>> So for performance reasons, it looks like we need to be considering 
>>> some other way to manage the Socket, the ECM would serve us better 
>>> if we kept it simple?
>>>
>>> I think your earlier suggestion of an event notification might be 
>>> more useful, if provided as a parameter in the checkPermission call, 
>>> in the event of failure, an event would be generated, the delegate 
>>> could then decide what action to take.  If it only had one user, 
>>> then it knows to close the Socket, if it has multiple users, it 
>>> might just keep score.
>>>
>>> This stops the transmission of data from unauthorised code, but it 
>>> doesn't close the socket.
>>>
>>> Cheers,
>>>
>>> Peter.
>>>>  
>>>>> If there is untrusted code on a thread's stack, and if the thread
>>>>> called a delegate, and if the delegate is in the between ECM.begin()
>>>>> and ECM.end(), then the delegate's reaper will be called, and it can
>>>>> close the socket.
>>>>>
>>>>> If the revocation happened elsewhere (e.g. the untrusted code is not
>>>>> on any stack, or is occupied with some other task), how does the
>>>>> socket get closed?
>>>>>
>>>>> Fred
>>>>>     
>>>
>>>
>>>
>>
>>
>
>


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Patricia Shanahan wrote:
> On 8/22/2010 8:08 AM, Peter Firmstone wrote:
> ...
>> These ProxyPermission's will be usable whether people want to revoke
>> them or not, and should be much faster than SocketPermission's, anyone
>> with any ideas, please assist.
> ...
>
> I don't know enough about what you are trying to do to assist 
> directly. However, there is one tool that should be in your toolbox, 
> even if you decide it does not help.
>
> Are you aware of Aspect/J, and the underlying idea of organized 
> bytecode modification to manage cross-cutting concerns without 
> scattered source code change?
>
> Patricia
>
Yes, it is interesting, I started looking into it a couple of years ago, 
but got busy. Bytecode weaving with AspectJ, a problem that we might 
face, is how to understand aspects weaved from different compiled code 
fragments.  In a way similar to the problems with Generics from 
separately compiled code fragments, that come together in a distributed 
environment.  Generics in Service Interfaces only work where the 
generics are specific, wild cards and generic types don't work, because 
that information suffers from compile time erasure, causing runtime type 
cast errors.  I think we'd face similar incompatibilities, but it 
doesn't mean it's not a good idea or isn't possible ;)  I believe there 
are researchers working on distributed aspects...

Cheers,

Peter.



Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Patricia Shanahan <pa...@acm.org>.
On 8/22/2010 8:08 AM, Peter Firmstone wrote:
...
> These ProxyPermission's will be usable whether people want to revoke
> them or not, and should be much faster than SocketPermission's, anyone
> with any ideas, please assist.
...

I don't know enough about what you are trying to do to assist directly. 
However, there is one tool that should be in your toolbox, even if you 
decide it does not help.

Are you aware of Aspect/J, and the underlying idea of organized bytecode 
modification to manage cross-cutting concerns without scattered source 
code change?

Patricia

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Gregg Wonderly wrote:
> Peter Firmstone wrote:
>> I don't want to be calling DNS!
>
> This is the most significant reason why I hate resource based policy 
> implementation.  I've spent countless hours trying to figure out why 
> something was so horribly slow, only to find that the primary DNS 
> server as not functioning, and the default 10 sec cache of failure was 
> too short, and so every DNS action timed out to the first host, and 
> then failed over and worked.
>
> By setting the failure cache to 1min, my application was suddenly much 
> more responsive.
>
> Gregg Wonderly
>
I've been running some tests on my ExecutionContextManager implementation.

I think I can eliminate the need for this additional interface and 
implementation, by implementing a non blocking PermissionCollection for 
a new Permission class called ProxyPermission.

Current Performance tests indicate that my ECM performs around 1.2 to 
2.5 times the speed of AccessController.checkPermission(Permission).

When I run 5 concurrent threads looping constantly performing 
checkPermission on 4 different Permission's for 100000 loops, the 
performance per thread degrades from 11 seconds to 30 seconds for the 
total test duration, due to internal synchronization in 
RuntimePermission's PermissionCollection. (BasicPermissionCollection), 
this is performed with the mostly non blocking 
DynamicConcurrentPolicyProvider.

In comparison a comparative test on the ECM is about 7.5 seconds with 
the same number of AccessController.getContext calls, the ECM reduces 
these calls down to 4.2 seconds by testing 4 different Permission's per 
getContext call (x 100000 loops).  However this last test is atypical, 
since checkPermission calls will normally only be made once, rather than 
several in a row.

Because the ECM also uses a Synchronized Set, containing 
AccessControlContext's there is potential for blocking under different 
conditions in the ECM.  Instead of having one ECM per policy, I could 
have multiple, I can however create a non blocking 
ProxyPermissionCollection for ProxyPermission's that behave similarly to 
BasicPermission's, but are instead intended to support revocation with 
Security Delegates and perform almost as well as the ECM.

This makes for a much simpler outcome and keeps the policy 
implementation tighter.  No ExecutionContextManager.

ProxyPermission's will be created for network addresses (without DNS 
resolution), although considering that we want to be able to get through 
firewalls and the like, I'm going to have to be careful, about exactly 
what permission names are used.  Since a service may be found, not 
through DNS, but via a Registrar and a listening post, as per Sim's 
Meekong Jeri Endpoint's.

These ProxyPermission's will be usable whether people want to revoke 
them or not, and should be much faster than SocketPermission's, anyone 
with any ideas, please assist.

Cheers,

Peter.

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Gregg Wonderly <gr...@wonderly.org>.
Peter Firmstone wrote:
> I don't want to be calling DNS!

This is the most significant reason why I hate resource based policy 
implementation.  I've spent countless hours trying to figure out why something 
was so horribly slow, only to find that the primary DNS server as not 
functioning, and the default 10 sec cache of failure was too short, and so every 
DNS action timed out to the first host, and then failed over and worked.

By setting the failure cache to 1min, my application was suddenly much more 
responsive.

Gregg Wonderly

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Performance costs of ECM access checks?

How much will delegates impact performance in comparison to existing 
SocketPermission guards?

Some interesting links:

www.rewerse.net/pulications/download/REWERSE-RP-2005-141.pdf

www.ida.liu.se/~almhe

There's some interesting performance tests available for the above paper at:

http://www.ida.liu.se/~almhe/publications/sm-testdata/

I suspect we'll be able to achieve respectable performance figures, here 
are some tips in the paper we can learn from:

   1. Existing SocketPermission's try to perform a DNS-lookup. Bug ID's
      related to SocketPermission problems 4155463, 4320895, 4414825,
      4975882, 5004073
   2. AccessController.getStackAccessControlContext was identified as an
      expensive native method, can't avoid that one!
   3. Performance worsens with increasing numbers of CodeSources.

Some initial observations:

In comparison to the existing path for security checks, we can cache the 
result of the AccessControlContext.checkPermission(Permission) calls, 
until a revocation occurs, removing multiple calls to ProtectionDomain's 
contained in the AccessControlContext.

Each ProtectionDomain.implies(Permission) check is typically followed by 
Policy.getPolicyNoCheck, PolicyFile.implies(ProtectionDomain, 
Permission), SynchronizedMap.get(WeakHashMap.get(ProtectionDomain)), 
Permissions.implies(Permission), Permissions.getPermissionCollection, 
HashMap.get(Class<Permission>), PermissionCollection.implies(Permission).

Synchronization creates significant points of contention, although that 
has recently been solved with DynamicConcurrentPolicyProvider, however 
we still need to performance test it.

AccessControlContext has reasonable equals() and hashCode() 
implementations, it will perform well in concurrent cache collections.  
Typically Permission equals and hashCode implementations are also 
reasonable.  The first call from an AccessControlContext will be the 
most expensive, however in between revocations, repeated calls will be 
cheap, apart from the native call getStackAccessControlContext.

I don't want to be calling DNS!

Cheers,

Peter.


Peter Firmstone wrote:
> Clarification (I overlooked something): The 
> checkPermission(Collection<Permission> perms) in the finally block 
> would work only for intercepting a method return, but it doesn't work 
> for InputStream read() / OutputStream write(), since we wanted to stop 
> method execution, if Permission is no longer granted.
>
> For example if a socket delegate returns an OutputStream delegate, 
> that wraps an underlying OutputStream, then during the write(), if a 
> revocation occurs, we probably want to close the OutputStream, if it 
> applies.
>
> The OutputStream write() would still need a reaper, to close the 
> OutputStream causing an IOException to be thrown, although as yet I 
> haven't determined how to add debug information for an intervening 
> revocation.
>
> public void write( byte[] b) {
>    ecm.begin(reaper)
>    try{
>       ecm.checkPermission(writePermission);
>       out.write( byte[] b);
>    } finally {
>       end();
>    }
> }
>
> Is it as critical to stop a read() operation?
>
> Since the array passed into the read() operation is written to, we can 
> close this as well, causing an IOException, however the user will 
> still get some bytes written into the byte array, which it can access 
> if it catches the IOException.
>
> public int read(byte[] b) {
>    ecm.begin(reaper)
>    try{
>        ecm.checkPermission(readPermission);
>        return in.read( byte[] b);
>    } finally {
>       end();
>    }
> }
>
> But we could provide the optimised single invocation 
> checkPermission(Collection<Permission> perms) method as well, for 
> calls that don't need to be intercepted.
>
> Perhaps we could be less pedantic about read operations, provided all 
> write operations are intercepted?
>
> public int read(byte[] b) {
>    try {
>        ecm.checkPermission(readPermission);
>    } catch (AccessControlException e) {
>       this.close();
>       throw new IOException(e.toString());
>    }
>        return in.read( byte[] b);
> }
>
> This checkPermission would be very fast, with only a small amount of 
> cpu overhead, because it caches the result for the AccessControlContext.
>
> We could do this for write() as well, if the code was trusted at the 
> time of the write() call, then we might assume that the information 
> contained within, wasn't borne from an operation of malicious intent, 
> we trusted it, so the call can be allowed to complete.  This has a 
> much smaller performance penalty, any following calls will cause an 
> AccessControlExeption to be thrown, if Permission is revoked.
>
> Then write might simply be:
>
> public void write(byte[] b) {
>    try {
>        ecm.checkPermission(writePermission);
>    } catch (AccessControlException e) {
>       this.close();
>       throw new IOException(e.toString());
>    }
>    out.write(b);
> }
>
> We might consider what the uses are for Permission revocation?  I'm 
> starting to think interception might hamper performance too greatly.
>
> The major uses I see for Revocation:
>
>    * Reusing ClassLoader's, for proxy's with common code source, by
>      removing trust gained by the previous proxy.
>    * Limit the time period for which trust is granted to a third
>      party.  A Trust lease?   Trust is only granted while contact is
>      maintained.
>    * If a proxy has lost contact with it's Server, which was trusted
>      and we want to resume (without loosing state) we can revoke
>      permission, retry connecting with the Server, verify trust, then
>      re grant trust (I'm thinking about the neuromancer remote
>      reference problem).
>
> Obviously the feature got your interest, I'm wondering what other uses 
> there might have been for permission revocation?  This might help me 
> better understand the use case scenarios.
>
>
> Peter Firmstone wrote:
>> Fred Oliver wrote:
>>> To at least partially answer my own question, I think that the answer
>>> is that the socket can't be closed (at least in all cases).
>>>
>>> If the delegate for a resource has multiple users (codebases,
>>> principals, etc.) then closing the resource because permission for one
>>> of the users has been revoked denies access to the resource by the
>>> remaining valid users. (This allows a denial of service attack.) And
>>> then, if you can't close the resource (socket), you can't kick loose
>>> the no longer trusted thread blocked reading from it. You may be able
>>> to determine the special case of no user retaining access (everyone's
>>> access was revoked) and can then close the resource.
>>>
>>> In the standard security model, there are no checks for
>>> reading/writing sockets. Allowing revocation means that checks must be
>>> added for each individual read or write call on the socket streams. Is
>>> that level of performance satisfactory?
>>>   
>>
>> I've just spotted a possible performance improvement.
>>
>> We can eliminate the end() call in the finally block, put all the 
>> checkPermission calls there instead.  This substantially reduces the 
>> caching operations.  Perhaps we can manage the Socket some other way, 
>> we just block unauthorised access using the delegate?
>>
>> try {
>>    // Do some processing
>>    return something;
>> } finally {
>>    ECM.checkPermission(Collection<Permission> permissions);
>> }
>>
>> The current expense for making a Permission call via ECM (remembering 
>> the first is always going to be expensive), currently requires the 
>> three ECM calls in succession:
>>
>> begin();
>> checkPermission(perm);
>> end();
>>
>> begin():
>>
>>   1. Associate the thread with the reaper.
>>
>>
>> checkPermission(perm):
>>
>>   1. Obtain the read lock;
>>   2. Add the current thread to the execution cache.
>>   3. Associate the current AccessControlContext with the current thread
>>   4. Check if the AccessControlContext has been checked for this
>>      Permission previously.
>>   5. If it has been checked before, return, else do
>>      AccessController.checkPermission(perm), cache the result if it
>>      succeeds.
>>
>> Each end():
>>
>>   1. Obtain the read lock;
>>   2. Remove the thread and reaper from the cache.
>>   3. Remove the thread association with the AccessControlContext.
>>   4. Remove the thread from the execution cache.
>>
>>      This could be simplified to (no reaper or thread caching):
>>
>> checkPermission(perms)
>>
>>   1. Obtain the read lock;
>>   2. For each Permission, check if the current AccessControlContext has
>>      been checked for this Permission previously, if so return.
>>      (HashMap lookup - fast).
>>   3. If the AccessControlContext hasn't been checked previously, do
>>      AccessController.checkPermission(perm), cache the result if it
>>      succeeds, then return.
>>
>> So for performance reasons, it looks like we need to be considering 
>> some other way to manage the Socket, the ECM would serve us better if 
>> we kept it simple?
>>
>> I think your earlier suggestion of an event notification might be 
>> more useful, if provided as a parameter in the checkPermission call, 
>> in the event of failure, an event would be generated, the delegate 
>> could then decide what action to take.  If it only had one user, then 
>> it knows to close the Socket, if it has multiple users, it might just 
>> keep score.
>>
>> This stops the transmission of data from unauthorised code, but it 
>> doesn't close the socket.
>>
>> Cheers,
>>
>> Peter.
>>>  
>>>> If there is untrusted code on a thread's stack, and if the thread
>>>> called a delegate, and if the delegate is in the between ECM.begin()
>>>> and ECM.end(), then the delegate's reaper will be called, and it can
>>>> close the socket.
>>>>
>>>> If the revocation happened elsewhere (e.g. the untrusted code is not
>>>> on any stack, or is occupied with some other task), how does the
>>>> socket get closed?
>>>>
>>>> Fred
>>>>     
>>
>>
>>
>
>


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Clarification (I overlooked something): The 
checkPermission(Collection<Permission> perms) in the finally block would 
work only for intercepting a method return, but it doesn't work for 
InputStream read() / OutputStream write(), since we wanted to stop 
method execution, if Permission is no longer granted.

For example if a socket delegate returns an OutputStream delegate, that 
wraps an underlying OutputStream, then during the write(), if a 
revocation occurs, we probably want to close the OutputStream, if it 
applies.

The OutputStream write() would still need a reaper, to close the 
OutputStream causing an IOException to be thrown, although as yet I 
haven't determined how to add debug information for an intervening 
revocation.

public void write( byte[] b) {
    ecm.begin(reaper)
    try{
       ecm.checkPermission(writePermission);
       out.write( byte[] b);
    } finally {
       end();
    }
}

Is it as critical to stop a read() operation?

Since the array passed into the read() operation is written to, we can 
close this as well, causing an IOException, however the user will still 
get some bytes written into the byte array, which it can access if it 
catches the IOException.

public int read(byte[] b) {
    ecm.begin(reaper)
    try{
        ecm.checkPermission(readPermission);
        return in.read( byte[] b);
    } finally {
       end();
    }
}

But we could provide the optimised single invocation 
checkPermission(Collection<Permission> perms) method as well, for calls 
that don't need to be intercepted.

Perhaps we could be less pedantic about read operations, provided all 
write operations are intercepted?

public int read(byte[] b) {
    try {
        ecm.checkPermission(readPermission);
    } catch (AccessControlException e) {
       this.close();
       throw new IOException(e.toString());
    }
        return in.read( byte[] b);
}

This checkPermission would be very fast, with only a small amount of cpu 
overhead, because it caches the result for the AccessControlContext.

We could do this for write() as well, if the code was trusted at the 
time of the write() call, then we might assume that the information 
contained within, wasn't borne from an operation of malicious intent, we 
trusted it, so the call can be allowed to complete.  This has a much 
smaller performance penalty, any following calls will cause an 
AccessControlExeption to be thrown, if Permission is revoked.

Then write might simply be:

public void write(byte[] b) {
    try {
        ecm.checkPermission(writePermission);
    } catch (AccessControlException e) {
       this.close();
       throw new IOException(e.toString());
    }
    out.write(b);
}

We might consider what the uses are for Permission revocation?  I'm 
starting to think interception might hamper performance too greatly.

The major uses I see for Revocation:

    * Reusing ClassLoader's, for proxy's with common code source, by
      removing trust gained by the previous proxy.
    * Limit the time period for which trust is granted to a third
      party.  A Trust lease?   Trust is only granted while contact is
      maintained.
    * If a proxy has lost contact with it's Server, which was trusted
      and we want to resume (without loosing state) we can revoke
      permission, retry connecting with the Server, verify trust, then
      re grant trust (I'm thinking about the neuromancer remote
      reference problem).

Obviously the feature got your interest, I'm wondering what other uses 
there might have been for permission revocation?  This might help me 
better understand the use case scenarios.


Peter Firmstone wrote:
> Fred Oliver wrote:
>> To at least partially answer my own question, I think that the answer
>> is that the socket can't be closed (at least in all cases).
>>
>> If the delegate for a resource has multiple users (codebases,
>> principals, etc.) then closing the resource because permission for one
>> of the users has been revoked denies access to the resource by the
>> remaining valid users. (This allows a denial of service attack.) And
>> then, if you can't close the resource (socket), you can't kick loose
>> the no longer trusted thread blocked reading from it. You may be able
>> to determine the special case of no user retaining access (everyone's
>> access was revoked) and can then close the resource.
>>
>> In the standard security model, there are no checks for
>> reading/writing sockets. Allowing revocation means that checks must be
>> added for each individual read or write call on the socket streams. Is
>> that level of performance satisfactory?
>>   
>
> I've just spotted a possible performance improvement.
>
> We can eliminate the end() call in the finally block, put all the 
> checkPermission calls there instead.  This substantially reduces the 
> caching operations.  Perhaps we can manage the Socket some other way, 
> we just block unauthorised access using the delegate?
>
> try {
>    // Do some processing
>    return something;
> } finally {
>    ECM.checkPermission(Collection<Permission> permissions);
> }
>
> The current expense for making a Permission call via ECM (remembering 
> the first is always going to be expensive), currently requires the 
> three ECM calls in succession:
>
> begin();
> checkPermission(perm);
> end();
>
> begin():
>
>   1. Associate the thread with the reaper.
>
>
> checkPermission(perm):
>
>   1. Obtain the read lock;
>   2. Add the current thread to the execution cache.
>   3. Associate the current AccessControlContext with the current thread
>   4. Check if the AccessControlContext has been checked for this
>      Permission previously.
>   5. If it has been checked before, return, else do
>      AccessController.checkPermission(perm), cache the result if it
>      succeeds.
>
> Each end():
>
>   1. Obtain the read lock;
>   2. Remove the thread and reaper from the cache.
>   3. Remove the thread association with the AccessControlContext.
>   4. Remove the thread from the execution cache.
>
>      This could be simplified to (no reaper or thread caching):
>
> checkPermission(perms)
>
>   1. Obtain the read lock;
>   2. For each Permission, check if the current AccessControlContext has
>      been checked for this Permission previously, if so return.
>      (HashMap lookup - fast).
>   3. If the AccessControlContext hasn't been checked previously, do
>      AccessController.checkPermission(perm), cache the result if it
>      succeeds, then return.
>
> So for performance reasons, it looks like we need to be considering 
> some other way to manage the Socket, the ECM would serve us better if 
> we kept it simple?
>
> I think your earlier suggestion of an event notification might be more 
> useful, if provided as a parameter in the checkPermission call, in the 
> event of failure, an event would be generated, the delegate could then 
> decide what action to take.  If it only had one user, then it knows to 
> close the Socket, if it has multiple users, it might just keep score.
>
> This stops the transmission of data from unauthorised code, but it 
> doesn't close the socket.
>
> Cheers,
>
> Peter.
>>  
>>> If there is untrusted code on a thread's stack, and if the thread
>>> called a delegate, and if the delegate is in the between ECM.begin()
>>> and ECM.end(), then the delegate's reaper will be called, and it can
>>> close the socket.
>>>
>>> If the revocation happened elsewhere (e.g. the untrusted code is not
>>> on any stack, or is occupied with some other task), how does the
>>> socket get closed?
>>>
>>> Fred
>>>     
>
>
>


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred Oliver wrote:
> To at least partially answer my own question, I think that the answer
> is that the socket can't be closed (at least in all cases).
>
> If the delegate for a resource has multiple users (codebases,
> principals, etc.) then closing the resource because permission for one
> of the users has been revoked denies access to the resource by the
> remaining valid users. (This allows a denial of service attack.) And
> then, if you can't close the resource (socket), you can't kick loose
> the no longer trusted thread blocked reading from it. You may be able
> to determine the special case of no user retaining access (everyone's
> access was revoked) and can then close the resource.
>
> In the standard security model, there are no checks for
> reading/writing sockets. Allowing revocation means that checks must be
> added for each individual read or write call on the socket streams. Is
> that level of performance satisfactory?
>   

I've just spotted a possible performance improvement.

We can eliminate the end() call in the finally block, put all the 
checkPermission calls there instead.  This substantially reduces the 
caching operations.  Perhaps we can manage the Socket some other way, we 
just block unauthorised access using the delegate?

try {
    // Do some processing
    return something;
} finally {
    ECM.checkPermission(Collection<Permission> permissions);
}

The current expense for making a Permission call via ECM (remembering 
the first is always going to be expensive), currently requires the three 
ECM calls in succession:

begin();
checkPermission(perm);
end();

begin():

   1. Associate the thread with the reaper.


checkPermission(perm):

   1. Obtain the read lock;
   2. Add the current thread to the execution cache.
   3. Associate the current AccessControlContext with the current thread
   4. Check if the AccessControlContext has been checked for this
      Permission previously.
   5. If it has been checked before, return, else do
      AccessController.checkPermission(perm), cache the result if it
      succeeds.

Each end():

   1. Obtain the read lock;
   2. Remove the thread and reaper from the cache.
   3. Remove the thread association with the AccessControlContext.
   4. Remove the thread from the execution cache.

      
This could be simplified to (no reaper or thread caching):

checkPermission(perms)

   1. Obtain the read lock;
   2. For each Permission, check if the current AccessControlContext has
      been checked for this Permission previously, if so return.
      (HashMap lookup - fast).
   3. If the AccessControlContext hasn't been checked previously, do
      AccessController.checkPermission(perm), cache the result if it
      succeeds, then return.

So for performance reasons, it looks like we need to be considering some 
other way to manage the Socket, the ECM would serve us better if we kept 
it simple?

I think your earlier suggestion of an event notification might be more 
useful, if provided as a parameter in the checkPermission call, in the 
event of failure, an event would be generated, the delegate could then 
decide what action to take.  If it only had one user, then it knows to 
close the Socket, if it has multiple users, it might just keep score.

This stops the transmission of data from unauthorised code, but it 
doesn't close the socket.

Cheers,

Peter.
>   
>> If there is untrusted code on a thread's stack, and if the thread
>> called a delegate, and if the delegate is in the between ECM.begin()
>> and ECM.end(), then the delegate's reaper will be called, and it can
>> close the socket.
>>
>> If the revocation happened elsewhere (e.g. the untrusted code is not
>> on any stack, or is occupied with some other task), how does the
>> socket get closed?
>>
>> Fred
>>     



Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Fred Oliver <fk...@gmail.com>.
To at least partially answer my own question, I think that the answer
is that the socket can't be closed (at least in all cases).

If the delegate for a resource has multiple users (codebases,
principals, etc.) then closing the resource because permission for one
of the users has been revoked denies access to the resource by the
remaining valid users. (This allows a denial of service attack.) And
then, if you can't close the resource (socket), you can't kick loose
the no longer trusted thread blocked reading from it. You may be able
to determine the special case of no user retaining access (everyone's
access was revoked) and can then close the resource.

In the standard security model, there are no checks for
reading/writing sockets. Allowing revocation means that checks must be
added for each individual read or write call on the socket streams. Is
that level of performance satisfactory?

> If there is untrusted code on a thread's stack, and if the thread
> called a delegate, and if the delegate is in the between ECM.begin()
> and ECM.end(), then the delegate's reaper will be called, and it can
> close the socket.
>
> If the revocation happened elsewhere (e.g. the untrusted code is not
> on any stack, or is occupied with some other task), how does the
> socket get closed?
>
> Fred

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Fred Oliver <fk...@gmail.com>.
On Sun, Aug 15, 2010 at 11:57 PM, Peter Firmstone <ji...@zeus.net.au> wrote:
>> - When the run() method is called (on which thread?)
>
> It's called from a small thread pool, within the ECM.
>
>> , how does it
>> determine which codebase or principal (etc.) to use when checking
>> permissions? How does a socket delegate know to close a socket?
>>
>
> It will be from the AccessControlContext, the Reaper will have it's
> ProtectionDomain on the stack at the time.

If there is untrusted code on a thread's stack, and if the thread
called a delegate, and if the delegate is in the between ECM.begin()
and ECM.end(), then the delegate's reaper will be called, and it can
close the socket.

If the revocation happened elsewhere (e.g. the untrusted code is not
on any stack, or is occupied with some other task), how does the
socket get closed?

Fred

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred Oliver wrote:
> Why not have
>     ECM.checkPermission(Collection<Permission>)
> instead of the begin/check/end block? Would this remove the Thread
> object from those maps?
>   

No the finally block is to prevent a method returning, while revocation 
is underway, and allow a Reaper to clean up before it returns.

> What if a delegate requires multiple permissions of different classes
> from multiple ECMs? Should this be done at the RevokeableDynamicPolicy
> level instead? Should the ECM be hidden from the public API?
>   

No there's only one ECM per policy, it is concurrent, but blocks during 
revocation.

> I was looking at writing a SocketDelegate and I' m not clear on some things.
>   
Excellent!
> - How do I get a reference to the system RevokableDynamicPolicy object?
>   

I need to add a static method to net.jini.security.Security.

> - Once I have it, how do I check for actual permission to do
> something? Is there a utility to iterate through the list of
> PermissionGrants? Or some other method?
>   

Not yet, but that is my intent, to create a utility to iterate through 
the permission grants.  Perhaps we could have a utility method on 
RevokeableDynamicPolicy, since it caches the Permission's during the 
GrantPermission checks, to avoid a PermissionGrant implementer from 
using mutability to elevate privileges.  It wouldn't be too difficult to 
iterate through them, using implies(ProtectionDomain).  I'm going to 
change the array of Permission's returned from a PermissionGrant back to 
an unmodifiable collection, as per your suggestion, to enforce 
immutability, it also removes one copy operation and makes iteration 
simpler.

> - If we have class based ECM (which seems simpler), then should
> Class<? extends Permission> appear in many places where Permission
> currently appears?  e.g.
>
>     RevokableDynamicPolicy.getExecutionManager(Class<? extends Permission>);
>     Controller.revoke(Set<Class<? extends Permission>> classes);
>     Controller.getPermission() returns Class<? extends Permission>
>     Controller.getECManager(Class<? extends Permission>);
>     Controller.pool uses Class<? extends Permission> as key?
>   

I've removed controller, got rid of the static caches as you suggested.  
I've uploaded ExecutionContextManager and ECM onto
svn for review:

org.apache.river.imp.security.policy.se.ECM
org.apache.river.api.security.policy.ExecutionContextManager

The RevokeableDynamicPolicy is an interface, there's also a 
RevokeableDynamicPolicySpi, so we can utilise different features on 
different java platforms, such as concurrency etc.

> In Controller, do the pool and cont fields need to be separate? If the
> weak references get cleared at different times, then these two
> structures can briefly diverge. Is this OK?
>
> Do you still have ECM.addAction()?  

No, it's now ECM.begin(Reaper), where Reaper extends Runnable, it's 
given the thread we want to prevent from returning security sensitive 
information.  I'm still not sure if this is the right way to handle it 
yet.  I've thought about throwing an AccessControlException from the 
end() method if any Permission's are revoked, this gives someone trying 
to debug more information, it still requires the delegate have a reaper 
to clean up.  Feel free to play with it, modify it on svn.

>  The ECM.addAction() takes a
> Runnable, which gets the job done. I'm concerned that this requires
> that delegates implement Runnable, 
No just a private implementation within the delegate.  It can be as 
simple as interrupting the thread in question if that's the desired 
behaviour, that would probably cause confusion during debugging.  This 
is why I'm thinking about throwing an AccessControlException from the 
end() method in the finally block.

> in conflict with some other use of
> Runnable. Perhaps it's worth adding an interface for this like
> RevocationListener with a permissionRevoked() method.
>
> Most of the methods in the delegates get called from the untrusted
> code, but the run() method does not.
>
> - When the run() method is called (on which thread?)
It's called from a small thread pool, within the ECM.

> , how does it
> determine which codebase or principal (etc.) to use when checking
> permissions? How does a socket delegate know to close a socket?
>   
It will be from the AccessControlContext, the Reaper will have it's 
ProtectionDomain on the stack at the time.

Have a look on svn, you might have a better idea, the delegate has to 
associate the Reaper with the method at the moment. I'm not entirely 
comfortable with the Reaper.

Cheers & Thanks,

Peter.

> Fred
>
>   


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Fred Oliver <fk...@gmail.com>.
Why not have
    ECM.checkPermission(Collection<Permission>)
instead of the begin/check/end block? Would this remove the Thread
object from those maps?

What if a delegate requires multiple permissions of different classes
from multiple ECMs? Should this be done at the RevokeableDynamicPolicy
level instead? Should the ECM be hidden from the public API?

I was looking at writing a SocketDelegate and I' m not clear on some things.

- How do I get a reference to the system RevokableDynamicPolicy object?

- Once I have it, how do I check for actual permission to do
something? Is there a utility to iterate through the list of
PermissionGrants? Or some other method?

- If we have class based ECM (which seems simpler), then should
Class<? extends Permission> appear in many places where Permission
currently appears?  e.g.

    RevokableDynamicPolicy.getExecutionManager(Class<? extends Permission>);
    Controller.revoke(Set<Class<? extends Permission>> classes);
    Controller.getPermission() returns Class<? extends Permission>
    Controller.getECManager(Class<? extends Permission>);
    Controller.pool uses Class<? extends Permission> as key?

In Controller, do the pool and cont fields need to be separate? If the
weak references get cleared at different times, then these two
structures can briefly diverge. Is this OK?

Do you still have ECM.addAction()?   The ECM.addAction() takes a
Runnable, which gets the job done. I'm concerned that this requires
that delegates implement Runnable, in conflict with some other use of
Runnable. Perhaps it's worth adding an interface for this like
RevocationListener with a permissionRevoked() method.

Most of the methods in the delegates get called from the untrusted
code, but the run() method does not.

- When the run() method is called (on which thread?), how does it
determine which codebase or principal (etc.) to use when checking
permissions? How does a socket delegate know to close a socket?

Fred

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Peter Firmstone wrote:
> Fred,
>
> I've thought about it some more.  When there were smart people trying 
> to solve this problem what were the constraints they faced at the time?
>
> When Java 1.4 was released, a new Policy method was added, 
> implies(ProtectionDomain, Permission), and the ProtectionDomain 
> modified to allow dynamic ProtectionDomain's via a new 4 parameter 
> constructor.
>
> Prior to Java 1.4, the method used to get the Permission's from the 
> policy, for a ProtectionDomain, was indirectly via 
> policy.getPermissions(ProtectionDomain), this was handed to the 
> ProtectionDomain constructor,

That should read policy.getPermissions(CodeSource), and Java 1.4 onward 
merged the Permissions with a ProtectionDomain.toString() call via the 
call policy.getPermissions(ProtectionDomain).  Anyway it would have 
appeared dauntingly difficult, since there were many different 
implementations at the time, things have stabilised now thankfully.


> and was static, if ProtectionDomain.toString() was called, this caused 
> the ProtectionDomain to merge any new Permissions from the policy with 
> those in it's private Permissions collection.
>
> So anybody at that time, had to consider the problem of supporting pre 
> Java 1.4 program's, policy's and SecurityManager implementations.  To 
> enable dynamic revocation of a Permission, you cannot return any 
> dynamic Permission's via the policy.getPermissions method, they would 
> become merged within a ProtectionDomain's Permissions, checked after 
> the policy in a dynamic PD returning true after the policy returned 
> false ( the policy is not checked at all in a static PD).
>
> Then there is the problem of escaping references to objects with 
> privileged behaviour for some existing Permission's.
>
> Now, we no longer have to contend with supporting JVM's prior to 1.4, 
> so this issue has been resolved by time, the second issue, hopefully 
> now the first is resolved can be resolved now too, with new 
> Permission's, Security Delegates, and optimised repeated 
> checkPermission() calls.
>
> Some benefit's of revocation (and I suspect you know of others); the 
> reuse of ClassLoader's and the avoidance of re verification of 
> bytecode, another might be the possibility of simplifying cross domain 
> login's and the separation of concerns for "code trust" and "user 
> trust".  You can't trust code forever, at some point, even signed 
> trusted code will experience a security flaw, in which case you can 
> revoke some trust of that particular code, since it has been found 
> untrustworthy in some respect.
>
> There's a document at https://issues.apache.org/jira/browse/RIVER-341
>
> This is intended to cover the separation of implementation from API 
> and evolution of API (by extension) and evolution of implementation by 
> versioning (replacement).
>
> For Services, implementation's can be versioned, by adding version 
> metadata into the jar file, they can be updated, URL's can be 
> annotated with version information and message digests, 
> PermissionGrant's can be utilised to determine the level of trust 
> dynamically based on an implementation version and signer certificates.
>
> There are many possibilities.
>
> The issue's with fine grained permission's I'd like to see solved with 
> some new tools, Service Entry's and jar files containing the 
> Permission's they require.
>
> Best Regards,
>
> Peter.
>
> Fred Oliver wrote:
>> It's so much easier to ask questions than provide answers. This is
>> such a difficult problem you are trying to solve that other very smart
>> people have chosen other directions.
>>
>> Fred
>>
>>   
>
>


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred,

I've thought about it some more.  When there were smart people trying to 
solve this problem what were the constraints they faced at the time?

When Java 1.4 was released, a new Policy method was added, 
implies(ProtectionDomain, Permission), and the ProtectionDomain modified 
to allow dynamic ProtectionDomain's via a new 4 parameter constructor.

Prior to Java 1.4, the method used to get the Permission's from the 
policy, for a ProtectionDomain, was indirectly via 
policy.getPermissions(ProtectionDomain), this was handed to the 
ProtectionDomain constructor, and was static, if 
ProtectionDomain.toString() was called, this caused the ProtectionDomain 
to merge any new Permissions from the policy with those in it's private 
Permissions collection.

So anybody at that time, had to consider the problem of supporting pre 
Java 1.4 program's, policy's and SecurityManager implementations.  To 
enable dynamic revocation of a Permission, you cannot return any dynamic 
Permission's via the policy.getPermissions method, they would become 
merged within a ProtectionDomain's Permissions, checked after the policy 
in a dynamic PD returning true after the policy returned false ( the 
policy is not checked at all in a static PD).

Then there is the problem of escaping references to objects with 
privileged behaviour for some existing Permission's.

Now, we no longer have to contend with supporting JVM's prior to 1.4, so 
this issue has been resolved by time, the second issue, hopefully now 
the first is resolved can be resolved now too, with new Permission's, 
Security Delegates, and optimised repeated checkPermission() calls.

Some benefit's of revocation (and I suspect you know of others); the 
reuse of ClassLoader's and the avoidance of re verification of bytecode, 
another might be the possibility of simplifying cross domain login's and 
the separation of concerns for "code trust" and "user trust".  You can't 
trust code forever, at some point, even signed trusted code will 
experience a security flaw, in which case you can revoke some trust of 
that particular code, since it has been found untrustworthy in some respect.

There's a document at https://issues.apache.org/jira/browse/RIVER-341

This is intended to cover the separation of implementation from API and 
evolution of API (by extension) and evolution of implementation by 
versioning (replacement).

For Services, implementation's can be versioned, by adding version 
metadata into the jar file, they can be updated, URL's can be annotated 
with version information and message digests, PermissionGrant's can be 
utilised to determine the level of trust dynamically based on an 
implementation version and signer certificates.

There are many possibilities.

The issue's with fine grained permission's I'd like to see solved with 
some new tools, Service Entry's and jar files containing the 
Permission's they require.

Best Regards,

Peter.

Fred Oliver wrote:
> It's so much easier to ask questions than provide answers. This is
> such a difficult problem you are trying to solve that other very smart
> people have chosen other directions.
>
> Fred
>
>   


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred Oliver wrote:
> It's so much easier to ask questions than provide answers. 

Successful Problem Solving is borne out of asking the right questions.  
It takes keen senses and experience to know the right questions to ask, 
asking the wrong ones just makes it take longer.

You've asked a lot of the right questions.

> This is
> such a difficult problem you are trying to solve that other very smart
> people have chosen other directions.
>   

Perhaps it's not being at the top of the game, I have nothing to loose 
in trying, in either case, I hope we solve it.

In my game (Mechanical & Project Engineering) there's a saying: "Your 
only as good as your last stuff up".  That doesn't apply here, unless of 
course it makes release without enough review from people like yourself ;)

Cheers & thanks,

Peter.

> Fred
>
>   


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred Oliver wrote:
> It's so much easier to ask questions than provide answers. This is
> such a difficult problem you are trying to solve that other very smart
> people have chosen other directions.
>
> Fred
>
>   
Fred,

People have their reasons for deciding which problems not to solve, 
sometimes very smart people choose not to solve difficult problems, not 
because they can't, but because they're worn down by other difficult 
problems and would prefer to go fishing or spend time with their family, 
rather than solve one more problem.

But the fact they choose not to, can give the rest of us an ego boost ;) 
Every dog has his day.

Please do continue participating, your assistance has been invaluable, I 
hope you find time to hang out on this list more often.

Thanks,

Peter.

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Fred Oliver <fk...@gmail.com>.
It's so much easier to ask questions than provide answers. This is
such a difficult problem you are trying to solve that other very smart
people have chosen other directions.

Fred

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred Oliver wrote:
> It looks like permissions can only be managed or revoked by class.
I made this choice initially because Permission implies(Permssion) is 
not like equals(Object), one doesn't necessarily mean the other and 
there are many cases where !equal but implies == true.  However given 
some more thought, I'm sure it would be possible to have a water tight 
revocation by Permission instead of class.

However that in itself is not a simple problem, we don't know the 
ProtectionDomain's on the caller's stack, we don't know the combination 
of Permission's that will cause implies to return true, this would 
require a PermissionCollection implies check.

Since we cache the AccessControlContext's, we could create a 
DomainCombiner, that amalgamates them, then call implies on the 
resultant AccessControlContext, if this returns false, then we know that 
one of the ProtectionDomain's has been given access.


>  If
> a domain has been granted more than one SocketPermission (e.g. to
> grant permission to use two ports or communicate with two hosts,
> etc.), can I revoke one of them?
>   
Yes, but with the current code, both Sockets would be closed, both 
delegates would need to catch the Socket Exception and attempt to open a 
new Socket, only one would succeed, the one that hadn't been revoked.

> If I have a delegate for a complex object (say Socket) to which sets
> of permissions may apply, how would the delegate handle the sets? If
> one SocketPermission were revoked, does the delegate need deep
> knowledge of the object it protects to determine if that revoked
> permission applies? 
No, I figured the safest way is to know the Socket information, close 
it, catch the exception, then create a new Socket from the previous 
information.  If an AccessControlException is then caught, the delegate 
can then close the Socket.  This will cause a brief interruption to 
service for Sockets where Permission hasn't been revoked, but the Socket 
is closed and replaced.

The delegate shouldn't need intimate knowledge of the caller, that's the 
job of the ExecutionContextManager (ECM).

Perhaps a delegate could set an atomic integer (via the ECM for each 
protected method to monitor execution, if greater than 0, there is a 
method that has not yet returned, then action should be taken.  If 0 the 
permission check will be performed next call and no action to close the 
socket needs to be taken.

I guess the AccessControlContext's could be stored in order in an 
execution cache, then we would know which are in current execution, we 
could re call implies against those.  The trouble is, when do method's 
exit?   So a call (aptly named methodExit()?) would have to be made on 
the ECM by the delegate prior to returning any protected method.

> Can a delegate always obtain the complete set of
> permissions which apply to it to reevaluate more fully?
>   
Yes it is possible to obtain a current set of PermissionGrant's and 
query them, provided the delegate has Permission.

> Should Controller maintain static maps of its own instances? If that
> map were contained by instances of RevokeableDynamicPolicy, then there
> could be multiple policy objects in use at one time.
>   

Hmm, true, the implementation forces a single revokeable policy for the 
JVM, what advantage is there to having multiple Dynamic policies?
> PrincipalGrant extends PermissionGrant and contains two Collections
> which are both used in the hash value and equals method. I would be
> inclined to enforce their immutability with
> Collections.unmodifiableCollection(). 

OK.

> In the equals method, you might
> return false if the stored hash values are different before comparing
> the collections.
>   

Thanks, speed tip.

> PermissionGrant.getPermissions() is documented as returning an
> immutable Collection, but the method returns a mutable array instead?
>   

Previously it did, however I realised that since anyone can implement 
PermissionGrant, (with appropriate Permission) I could not guarantee the 
immutability of the underlying collection, with regard to the way the 
RevokeableDynamicPolicy see's it, so I decided that at the time the 
Policy checks GrantPermission, that it clone the array and cache it, in 
a Weakly referenced Map with PermissionGrant as it's key.

If the underlying collection cannot be guaranteed immutable, the policy 
would not check GrantPermission again, an implementer could gain 
elevated Permission's via mutability otherwise, so I figured.

Thanks, you've given me some more ideas.

Cheers,

Peter.

> Fred
>
> On Wed, Aug 11, 2010 at 2:56 AM, Peter Firmstone <ji...@zeus.net.au> wrote:
>   
>> Fred,
>>
>> Any thoughts?  The ExecutionContextManager interface and implementation
>> (Controller) are shown below, the RevokeableDynamicPolicy and
>> PermissionGrant interfaces have implementations available on svn.
>>
>> The ExecutionContextManager is based around our discussion.
>>
>> Note that no Security Delegate is provided here, just a tool, which a
>> delegate or any other object may use,
>> ExecutionContextManager.checkPermission() and another method
>> addAction(Runnable r), to accept a Runnable to perform any clean up tasks
>> for complete revocation such as closing Socket's etc.  The delegate need not
>> implement any interface other than the object it encapsulates.
>>
>> Cheers,
>>
>> Peter.
>>     
>
>   


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Thoughts?

Some minor changes to the ECM:

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.river.api.security;

import java.security.AccessControlException;
import java.security.Permission;
import java.util.Set;

/**
 * <p>
 * An ExecutionContextManager is designed to be repeatedly called, where 
calling
 * AccessController.checkPermission(Permission) is too great an overhead.
 * </p><p>
 * The ExecutionContextManager will only call
 * AccessControlContext.checkPermission(Permission) once, for each 
context.  This
 * ensures that checkPermission isn't called again until the context 
changes, or
 * the Permission checked by this ExecutionContextManager experiences a
 * revoke for any ProtectionDomain by the RevokeableDynamicPolicy.
 * </p><p>
 * A Runnable may be submitted to the ExecutionContextManager to be executed
 * when a Permission Revocation matching the stored Permission occurs.
 * </p><p>
 * Use of this class is not limited to Revokeable Permission's.
 * </p>
 * @author Peter Firmstone
 * @see RevokeableDynamicPolicy
 * @see Permission
 * @see AccessControlContext
 */
public interface ExecutionContextManager {

    /**
     * <p>
     * This is a call made by a Security Delegate, or other Object used to
     * control access to privileged methods or constructors, similar to the
     * AccessControll.checkPermssion(Permission) call, but with the 
Permission
     * pre defined and unchanging.  The Permission check is optimised,
     * typically a method may only be concerned with a single Permission 
check,
     * but in many existing cases, the AccessController check is too 
expensive
     * to be called on every method invocation.  The 
ExecutionContextManager
     * should optimise this call by ensuring that 
checkPermission(Permission) is only
     * called once per AccessControlContext.  In other words if the caller's
     * AccessControlContext hasn't changed, then checkPermission(Permission)
     * isn't called again as it would be assumed to succeed, unless the
     * RevokeableDynamicPolicy revokes a Permission with the same class,
     * in which case the Permission must be checked again.
     * </p><p>
     * Typically where it is not feasable to call 
AccessController.checkPermission
     * on every invocation, those objects are usually guarded or have the
     * checkPermission method called in the constructor.
     * </p><p>
     * ExecutionContextManager provides a more thorough form of protection.
     * </p><p>
     * ExecutionContextManager should be used sparingly, the more generic
     * or widely applicable the Permission, the more efficient the
     * ExecutionContextManager is in memory usage terms.
     * </p><p>
     * This method also add's the current context to the current execution
     * cache, it is not removed from that cache until after 
accessControlExit()
     * has been called.
     * </p>
     *
     * @param reaper - Runnable provided to clean up if Revocation 
occurs during
     * the execution that follows this call, until the try block exits,
     * the current thread is not interrupted, rather the reaper is expected
     * to know what resources need to be closed.
     *
     * @throws java.security.AccessControlException
     */
    public void accessControlCommence(Runnable reaper) throws 
AccessControlException;
   
    /**
     * <p>
     * This method is to advise the ExecutionContextManager that the
     * current method or protected region has returned, it must
     * always follow the accessControlCommence() call, in response,
     * the ECM removes the current context from the execution context cache
     * and releases the reference to the Runnable reaper.
     * </p><p>
     * If the execution context is still in the cache at the time of
     * revocation, the reaper will be run only if affected directly by the
     * revocation, the thread may be asked to wait for a short period, to
     * allow the determination to be made.
     * Revocation applicability is determined by
     * AccessControlContext.checkPermission(Permission p) where p is the
     * Permission affected.
     * </p><p>
     * This should be executed in the finally{} block of a try catch 
statement,
     * which always executes in the event of an exception or normal return.
     * </p>
     * <code>
     * try{
     *        ecm.accessControlCommence(reaper);
     *        // do something
     *        return;
     * } catch (AccessControlException e) {
     *        throw new SecurityException("Method blah caused an...", e);
     * } finally {
     *        ecm.accessControlExit();
     * }
     * </code>
     * <p>
     * This should not be confused with AccessController.doPrivileged blocks
     * </p>
     */
    public void accessControlExit();

    /**
     * Get the Permission monitored by this ExecutionContextManager.
     * @return Permission monitored by the ExecutionContextManager
     */
    public Permission getPermission();
}

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred Oliver wrote:
> If I have a delegate for a complex object (say Socket) to which sets
> of permissions may apply, how would the delegate handle the sets? If
> one SocketPermission were revoked, does the delegate need deep
> knowledge of the object it protects to determine if that revoked
> permission applies? Can a delegate always obtain the complete set of
> permissions which apply to it to reevaluate more fully?
>
>   
Hi Fred,  I don't think I answered this one properly, the delegate could 
handle the set's of Permission's by obtaining an ExecutionContextManager 
for each Permission.

So for dynamically granted Socket Permission's the delegate would create 
the ExecutionContextManager and hold it for the duration required for a 
particular environment.

The Socket delegate may also create other delegates for other objects 
that it returns, such as InputStream.

I'll upload the code to svn shortly.

Cheers,

Peter.

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Fred Oliver <fk...@gmail.com>.
It looks like permissions can only be managed or revoked by class. If
a domain has been granted more than one SocketPermission (e.g. to
grant permission to use two ports or communicate with two hosts,
etc.), can I revoke one of them?

If I have a delegate for a complex object (say Socket) to which sets
of permissions may apply, how would the delegate handle the sets? If
one SocketPermission were revoked, does the delegate need deep
knowledge of the object it protects to determine if that revoked
permission applies? Can a delegate always obtain the complete set of
permissions which apply to it to reevaluate more fully?

Should Controller maintain static maps of its own instances? If that
map were contained by instances of RevokeableDynamicPolicy, then there
could be multiple policy objects in use at one time.

PrincipalGrant extends PermissionGrant and contains two Collections
which are both used in the hash value and equals method. I would be
inclined to enforce their immutability with
Collections.unmodifiableCollection(). In the equals method, you might
return false if the stored hash values are different before comparing
the collections.

PermissionGrant.getPermissions() is documented as returning an
immutable Collection, but the method returns a mutable array instead?

Fred

On Wed, Aug 11, 2010 at 2:56 AM, Peter Firmstone <ji...@zeus.net.au> wrote:
> Fred,
>
> Any thoughts?  The ExecutionContextManager interface and implementation
> (Controller) are shown below, the RevokeableDynamicPolicy and
> PermissionGrant interfaces have implementations available on svn.
>
> The ExecutionContextManager is based around our discussion.
>
> Note that no Security Delegate is provided here, just a tool, which a
> delegate or any other object may use,
> ExecutionContextManager.checkPermission() and another method
> addAction(Runnable r), to accept a Runnable to perform any clean up tasks
> for complete revocation such as closing Socket's etc.  The delegate need not
> implement any interface other than the object it encapsulates.
>
> Cheers,
>
> Peter.

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred,

Any thoughts?  The ExecutionContextManager interface and implementation 
(Controller) are shown below, the RevokeableDynamicPolicy and 
PermissionGrant interfaces have implementations available on svn.

The ExecutionContextManager is based around our discussion.

Note that no Security Delegate is provided here, just a tool, which a 
delegate or any other object may use, 
ExecutionContextManager.checkPermission() and another method 
addAction(Runnable r), to accept a Runnable to perform any clean up 
tasks for complete revocation such as closing Socket's etc.  The 
delegate need not implement any interface other than the object it 
encapsulates.

Cheers,

Peter.

package org.apache.river.api.security;

import java.security.Permission;
import java.util.List;

/**
 * RevokeableDynamicPolicy, is a Java Security Policy Provider that supports
 * Runtime Dynamically Grantable and Revokeable Permission's, in the form
 * of PermissionGrant's
 *
 * @author Peter Firmstone
 * @see java.security.Policy
 * @see java.security.ProtectionDomain
 * @see java.security.AccessController
 * @see java.security.DomainCombiner
 * @see java.security.AccessControlContext
 * @see java.security.Permission
 */
public interface RevokeableDynamicPolicy {
    /**
     * Grant Permission's as specified in a List of PermissionGrant's
     * which can be added by concurrent threads.
     *
     * @param grants
     */
    public void grant(List<PermissionGrant> grants);
    /**
     * Revoke, only removes any PermissionGrant's that are identical, 
typically
     * a List of Grant's is obtained by getPermssionGrant's which can be
     * manipulated and investigated, any that are undesirable should be 
passed
     * to revoke.
     *
     * Revokes can only be performed synchronuously with other Revokes.
     *
     * @param grants
     */
    public void revoke(List<PermissionGrant> grants);
    /**
     * Get a List copy of the current PermissionGrant's in force.
     * @return
     */
    public List<PermissionGrant> getPermissionGrants();
    /**
     * The Revocation of Permission's requires a new construct for 
controlling
     * access.  Typically many objects that provide privileged functionality
     * are guarded in their constructor by a checkPermission(Permission) 
call
     * or by a GuardedObject, once this check has succeeded, the caller 
receives
     * a reference to the guarded object.  These Permission's cannot be
     * revoked completely, because the reference has escaped, the 
permission
     * check will not be called again.
     *
     * Instead what is needed is a permission check that is efficient enough
     * to allow the methods that provide the privileged functionality to be
     * called for every method invocation.  What the ExecutionContextManager
     * does is minimise the checkPermission calls by skipping 
checkPermission for
     * any execution AccessControlContext that has already passed, unless
     * a Permission related to the one being managed is revoked, in 
which case
     * the cache of AccessControlContext's previously checked are cleared.
     *
     * The ExecutionContextManager is specific only to one permission, this
     * is the enabler for the reduced checkPermission calls, since a
     * Permission should behave in a persistent manner, once it passes, it
     * should always pass, unless revoked.
     *
     *
     * @param p Permission the ExecutionContextManager will check.
     * @return a new ExecutionContextManager instance.
     */
    public ExecutionContextManager getExecutionContextManager(Permission p);
    /**
     *
     * @return true if Revoke supported.
     */
    public boolean revokeSupported();
}

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.river.api.security;

import java.security.AccessControlException;
import java.security.Permission;

/**
 * <p>
 * An ExecutionContextManager is designed to be repeatedly called, where 
calling
 * AccessController.checkPermission(Permission) is too great an overhead.
 * </p><p>
 * The ExecutionContextManager will only call
 * AccessControlContext.checkPermission(Permission) once, for each 
context.  This
 * ensures that checkPermission isn't called again until the context 
changes, or
 * the Permission checked by this ExecutionContextManager experiences a
 * revoke for any ProtectionDomain by the RevokeableDynamicPolicy.
 * </p><p>
 * A Runnable may be submitted to the ExecutionContextManager to be executed
 * when a Permission Revocation matching the stored Permission occurs.
 * </p><p>
 * Use of this class is not limited to Revokeable Permission's.
 * </p>
 * @author Peter Firmstone
 * @see RevokeableDynamicPolicy
 * @see Permission
 * @see AccessControlContext
 */
public interface ExecutionContextManager {

    /**
     * <p>
     * This is a call made by a Security Delegate, or other Object used to
     * control access to privileged methods or constructors, similar to the
     * AccessControll.checkPermission(Permission) call, but with the 
Permission
     * pre defined and unchanging.  The Permission check is optimised,
     * typically a method may only be concerned with a single Permission 
check,
     * but in many existing cases, the AccessController check is too 
expensive
     * to be called on every method invocation.  The 
ExecutionContextManager
     * should optimise this call by ensuring that 
checkPermission(Permission) is only
     * called once per AccessControlContext.  In other words if the caller's
     * AccessControlContext hasn't changed, then checkPermission(Permission)
     * isn't called again as it would be assumed to succeed, unless the
     * RevokeableDynamicPolicy revokes a Permission with the same class,
     * in which case the Permission must be checked again.
     * </p><p>
     * Typically where it is not feasable to call 
AccessController.checkPermission
     * on every invocation, those objects are usually guarded or have the
     * checkPermission method called in the constructor.
     * </p><p>
     * ExecutionContextManager provides a more thorough form of protection.
     * </p><p>
     * ExecutionContextManager should be used sparingly, the more generic
     * or widely applicable the Permission, the more efficient the
     * ExecutionContextManager is in memory usage terms.
     * </p>
     * @throws java.security.AccessControlException
     */
    public void checkPermission() throws AccessControlException;

    /**
     * Get the Permission monitored by this ExecutionContextManager.
     * @return Permission monitored by the ExecutionContextManager
     */
    public Permission getPermission();

    /**
     * <p>
     * Action to be taken in event that the Permission monitored by this
     * ExecutionContextManager has experienced a revocation event.  This
     * allows Sockets to be closed, or any clean up to occur or any other
     * task that must be performed to reset state.
     * </p><p>
     * This may not be the only action performed, since the same
     * ExecutionContextManager may be used by multiple clients, the Runnable
     * is only weakly referenced, garbage collection is relied upon for its
     * removal.
     * </p><p>
     * The implementer must have the Permission's required for
     * execution, no privileges are assigned.
     * </p>
     * @param r - Clean up task to be performed.
     */
    public void addAction(Runnable r);
}


/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.river.imp.security.policy.se;

import java.lang.ref.WeakReference;
import java.security.AccessControlContext;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.Permission;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import org.apache.river.api.security.ExecutionContextManager;
import org.apache.river.imp.util.ConcurrentWeakIdentityMap;

/**
 * An implementation of ExecutionContextManager.
 *
 * @author Peter Firmstone.
 */
class Controller implements ExecutionContextManager {
    /* The class manages revoke for all it's objects. */
    private static final ConcurrentMap<Permission, 
ExecutionContextManager> pool
        = new ConcurrentWeakIdentityMap<Permission, 
ExecutionContextManager>();
   
    private static final List<WeakReference<Controller>> cont =
        new ArrayList<WeakReference<Controller>>(80);
    /**
     * This method is called by the RevokeableDynamicPolicy to get a List
     * of Runnable clean up jobs that must be performed to complete the
     * revocation of Permissions.
     *
     * A Thread pool can be used to perform the work, however the policy's
     * revoke call must not return until after all the jobs are complete.
     *
     * @param classes - A set of Permission Class object's for the 
Permission's
     * being revoked.
     * @return A List of Runnable clean up tasks to be performed to complete
     * the revocation.
     */
    static List<Runnable> revoke(Set<Class> classes){
    List<Runnable> cleanupJobs;
    synchronized (cont){
        cleanupJobs = new ArrayList<Runnable>(cont.size());
        Iterator<WeakReference<Controller>> it =
            cont.iterator();
        while (it.hasNext()) {
        WeakReference<Controller> wf = it.next();
        Controller ecm = wf.get();
        if ( ecm != null ){
            if (classes.contains(ecm.getPermission().getClass())){
            ecm.clear();
            cleanupJobs.addAll(ecm.getRunnable());
            }
        } else {
            it.remove();
        }
        }
    }
    return cleanupJobs;   
    }
   
    static ExecutionContextManager getECManager(Permission p){
    ExecutionContextManager exm = pool.get(p);
    if ( exm != null ){
        return exm;
    }
    exm = new Controller(p);
    ExecutionContextManager existed = pool.putIfAbsent(p, exm);
    if ( existed != null){
        exm = existed;
    }
    return exm;   
    }
   
    /* Object state and methods */
    private final Permission perm;
    private final List<WeakReference<Runnable>> cleanup;
    private final Set<AccessControlContext> checkedExecutionContext;
   
    /* A Revocation in progress will delay construction of a new 
Controller */
    private Controller(Permission p){
    perm = p;
    WeakReference<Controller> mac =
        new WeakReference<Controller>(this);
    cleanup = new ArrayList<WeakReference<Runnable>>();
    checkedExecutionContext = new HashSet<AccessControlContext>(80);
    // this must be done last.
    synchronized (cont){
        cont.add(mac);
    }
    }

    public void checkPermission() throws AccessControlException {
    AccessControlContext executionContext = AccessController.getContext();
    synchronized (checkedExecutionContext){
        if (checkedExecutionContext.contains(executionContext)) {
        return;
        }
    }
    executionContext.checkPermission(perm);
    /* If we get to here without exception we can add it.
     * The RevokeablyDynamicPolicy will revoke the Permission prior to
     * clearing the current checked execution context as part of the revoke
     * process, this means
     * that while the revocation isn't yet complete, the checked context
     * will still return true, but the actual permission check would return
     * false, however at the completion of the revocation process, the
     * Runnable provided will be executed to perform any necessary 
cleanupJobs
     * to fully revoke.
     *
     * This prevents invalid execution context's from finding their way
     * into the checked Execution Context which would be a security breach.
     *
     * Revoke's happen synchronuously to ensure that this contract is 
honored.
     */
    synchronized (checkedExecutionContext){
        checkedExecutionContext.add(executionContext);
    }
    }

    public Permission getPermission() {
    return perm;
    }

    public void addAction(Runnable r) {
    synchronized (cleanup){
        cleanup.add(new WeakReference<Runnable>(r));
    }
    }
   
    private List<Runnable> getRunnable(){
    List<Runnable> tasks;
    synchronized (cleanup){
        tasks = new ArrayList<Runnable>(cleanup.size());
        Iterator<WeakReference<Runnable>> it = cleanup.iterator();
        while (it.hasNext()){
        WeakReference<Runnable> wr = it.next();
        Runnable r = wr.get();
        if (r != null){
            tasks.add(r);
        }else {
            cleanup.remove(wr);
        }
        }
    }
    return tasks;
    }
   
    private void clear(){
    synchronized (checkedExecutionContext){
        checkedExecutionContext.clear();
    }
    }

}

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.river.api.security;

import java.security.CodeSource;
import java.security.Permission;
import java.security.Principal;
import java.security.ProtectionDomain;

/**
 * PermissionGrant's are expected to be effectively immutable,
 * threadsafe and have a good hashCode implementation to perform well in
 * Collections.
 *
 * You shouldn't pass around PermissionGrant's to just anyone as they can
 * provide an attacker with information about which Permission's may be 
granted.
 *
 * @author Peter Firmstone
 */
public interface PermissionGrant {

    /**
     * A DynamicPolicy implementation can use a PermissionGrant as a 
container
     * for Dynamic Grant's.  A PermissionGrant is first asked by the Policy
     * if it applies to a Particular ProtectionDomain, if it does, the 
Policy
     * calls getPermissions.
     *
     * Dynamic grants can be denied to some ProtectionDomains based on
     * CodeSource or URL's for codebases, this is to remove the 
possiblity of
     * executing Permissions for vulnerable codebases, once a vulnerability
     * is identified after the fact.
     *
     * @param pd ProtectionDomain
     * @return
     * @see RevokeableDynamicPolicy
     */
    boolean implies(ProtectionDomain pd); 
    /**
     * Checks if this PermissionGrant applies to the passed in ClassLoader
     * and Principal's.
     *
     * Note that if this method returns false, it doesn't necessarily mean
     * that the grant will not apply to the ClassLoader, since it will 
depend on
     * the contents of the ClassLoader and that is indeterminate. It just
     * indicates that the grant definitely does apply if it returns true.
     *
     * If this method returns false, follow up using the 
ProtectionDomain for a
     * more specific test, which may return true.
     */
    boolean implies(ClassLoader cl, Principal[] pal);
    /**
     * Checks if this PermissionGrant applies to the passed in CodeSource
     * and Principal's.
     * @param cs
     * @return
     */
    boolean implies(CodeSource codeSource, Principal[] pal);

    @Override
    boolean equals(Object o);

    /**
     * Returns an unmodifiable collection of permissions defined by this
     * PermissionGrant, may be <code>null</code>.
     * @return
     */
    Permission[] getPermissions();

    @Override
    int hashCode();

    /**
     * Returns true if this PermissionGrant defines no Permissions, or if
     * a PermissionGrant was made to a ProtectionDomain that no longer 
exists.
     */
    boolean isVoid();

}


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Tom Hobbs wrote:
> Hi Peter,
>
> Something that occurs to me is where does the revoke message come from and
> who gets?
>   
The policy sends the message, the delegate receives it.

> Also, if I were a malicious programmer, is it possible for me to
> legitimately get the appropriate permission for something, then intercept
> and ignore any revokes that come my way?
No, it'll be passed by direct reference.

>   It seems risky if the client code
> is able to do this, and the master/server/revoker code assumes that it has
> revoked permissions.
>
> It feels like there's a certain amount of trust going on in the form of "If
> I tell you not to do something, I trust you not to do it."  I've got two
> young daughters; whilst okay, this approach isn't always reliable!  :-)
>   
There was some of that when based on threads, however by caching the 
AccessControlContext's that pass, there is no risk, since references to 
the objects the delegates protect will never escape, unless reflection 
permission has been granted.

So if there's a loop that calls a method many times, checkPermission 
will be called once initially, the AccessControlContext cached and while 
the current context doesn't change and no revocation occurs, there will 
be no further checkPermission calls.

The added cost will be getting the current context and checking it 
exists in the cache, this is much less work than calling implies() on 
every ProtectionDomain on the stack, which all eventually calls the policy.

Cheers,

Peter.
> Cheers,
>
> Tom
>
>
> On Tue, Aug 10, 2010 at 12:05 AM, Peter Firmstone <ji...@zeus.net.au> wrote:
>
>   
>> Fred Oliver wrote:
>>
>>     
>>> Peter,
>>>
>>> Thanks again.
>>>
>>>
>>>
>>>       
>>>> Further, the
>>>>         
>>>>> revocation events are delivered to one or more of the delegates to
>>>>> force the socket to close.
>>>>>
>>>>>
>>>>>
>>>>>           
>>>> That was the original intent, however, now I'm thinking the delegate
>>>> catch
>>>> AccessControlException, thrown by a helper class, called
>>>> MethodAccessContoller, which the delegate calls prior to entering the
>>>> privileged block, performs any clean up, then re-throws the exception.
>>>>  Code
>>>> that doesn't need to do any clean up, doesn't need to catch the
>>>> exception.
>>>>
>>>>
>>>>         
>>> What happens to the thread stuck in the read on the socket when the
>>> permission it had to read was revoked after the read began? Force
>>> closing the socket will free up the thread. Otherwise the thread would
>>> eventually obtain data it shouldn't have from this read (or hang
>>> indefinitely waiting for data).
>>>
>>>
>>>       
>> Hmm, yes, it needs to be closed from another thread.
>>
>>
>>
>>     
>>>> Basically: Method call from new thread? Permission check.  Permission
>>>> revoked? Permission check again.  Previously checked Thread, no relevant
>>>> revocation's since (of same Class<Permission>)? Don't check again, return
>>>> quickly.
>>>>
>>>> The assumption I've made is, it will be very difficult for an attacker to
>>>> predict when a thread will access a method on the delegate, then later,
>>>> be
>>>> called by that very same thread, so his class can call the delegate
>>>> unchecked.  Any thoughts on this?  Am I overlooking something?
>>>>
>>>>
>>>>         
>>> What happens when a delegate is passed back and forth between trusted
>>> (having permission) and untrusted (not having permission) code (on the
>>> same thread)? If you cached based on the thread, you'll get
>>> unpredictable results?
>>>
>>>
>>>       
>> Yes that is a problem, so we have take a snapshot of the
>> AccessControlContext at the time of the permission check and check that it
>> is still equal() later.  I guess I could drop the thread check and just
>> check the AccessControlContext, this might be useful for thread groups etc
>> ;)
>>
>> The AccessControlContext could be cached for each Thread.
>>
>> Cheers,
>>
>> Peter.
>>
>>  Fred
>>     
>>>
>>>       
>>     
>
>   


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Tom Hobbs <tv...@googlemail.com>.
Hi Peter,

Something that occurs to me is where does the revoke message come from and
who gets?

Also, if I were a malicious programmer, is it possible for me to
legitimately get the appropriate permission for something, then intercept
and ignore any revokes that come my way?  It seems risky if the client code
is able to do this, and the master/server/revoker code assumes that it has
revoked permissions.

It feels like there's a certain amount of trust going on in the form of "If
I tell you not to do something, I trust you not to do it."  I've got two
young daughters; whilst okay, this approach isn't always reliable!  :-)

Cheers,

Tom


On Tue, Aug 10, 2010 at 12:05 AM, Peter Firmstone <ji...@zeus.net.au> wrote:

> Fred Oliver wrote:
>
>> Peter,
>>
>> Thanks again.
>>
>>
>>
>>> Further, the
>>>> revocation events are delivered to one or more of the delegates to
>>>> force the socket to close.
>>>>
>>>>
>>>>
>>> That was the original intent, however, now I'm thinking the delegate
>>> catch
>>> AccessControlException, thrown by a helper class, called
>>> MethodAccessContoller, which the delegate calls prior to entering the
>>> privileged block, performs any clean up, then re-throws the exception.
>>>  Code
>>> that doesn't need to do any clean up, doesn't need to catch the
>>> exception.
>>>
>>>
>>
>> What happens to the thread stuck in the read on the socket when the
>> permission it had to read was revoked after the read began? Force
>> closing the socket will free up the thread. Otherwise the thread would
>> eventually obtain data it shouldn't have from this read (or hang
>> indefinitely waiting for data).
>>
>>
>
> Hmm, yes, it needs to be closed from another thread.
>
>
>
>>
>>> Basically: Method call from new thread? Permission check.  Permission
>>> revoked? Permission check again.  Previously checked Thread, no relevant
>>> revocation's since (of same Class<Permission>)? Don't check again, return
>>> quickly.
>>>
>>> The assumption I've made is, it will be very difficult for an attacker to
>>> predict when a thread will access a method on the delegate, then later,
>>> be
>>> called by that very same thread, so his class can call the delegate
>>> unchecked.  Any thoughts on this?  Am I overlooking something?
>>>
>>>
>>
>> What happens when a delegate is passed back and forth between trusted
>> (having permission) and untrusted (not having permission) code (on the
>> same thread)? If you cached based on the thread, you'll get
>> unpredictable results?
>>
>>
>
> Yes that is a problem, so we have take a snapshot of the
> AccessControlContext at the time of the permission check and check that it
> is still equal() later.  I guess I could drop the thread check and just
> check the AccessControlContext, this might be useful for thread groups etc
> ;)
>
> The AccessControlContext could be cached for each Thread.
>
> Cheers,
>
> Peter.
>
>  Fred
>>
>>
>>
>
>

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Peter Firmstone wrote:
> Fred Oliver wrote:
>> Peter,
>>
>> Thanks again.
>>
>>  
>>>> Further, the
>>>> revocation events are delivered to one or more of the delegates to
>>>> force the socket to close.
>>>>
>>>>       
>>> That was the original intent, however, now I'm thinking the delegate 
>>> catch
>>> AccessControlException, thrown by a helper class, called
>>> MethodAccessContoller, which the delegate calls prior to entering the
>>> privileged block, performs any clean up, then re-throws the 
>>> exception.  Code
>>> that doesn't need to do any clean up, doesn't need to catch the 
>>> exception.
>>>     
>>
>> What happens to the thread stuck in the read on the socket when the
>> permission it had to read was revoked after the read began? Force
>> closing the socket will free up the thread. Otherwise the thread would
>> eventually obtain data it shouldn't have from this read (or hang
>> indefinitely waiting for data).
>>   
>
> Hmm, yes, it needs to be closed from another thread.
>
>>  
>>> Basically: Method call from new thread? Permission check.  Permission
>>> revoked? Permission check again.  Previously checked Thread, no 
>>> relevant
>>> revocation's since (of same Class<Permission>)? Don't check again, 
>>> return
>>> quickly.
>>>
>>> The assumption I've made is, it will be very difficult for an 
>>> attacker to
>>> predict when a thread will access a method on the delegate, then 
>>> later, be
>>> called by that very same thread, so his class can call the delegate
>>> unchecked.  Any thoughts on this?  Am I overlooking something?
>>>     
>>
>> What happens when a delegate is passed back and forth between trusted
>> (having permission) and untrusted (not having permission) code (on the
>> same thread)? If you cached based on the thread, you'll get
>> unpredictable results?
>>   
>
> Yes that is a problem, so we have take a snapshot of the 
> AccessControlContext at the time of the permission check and check 
> that it is still equal() later.  I guess I could drop the thread check 
> and just check the AccessControlContext, this might be useful for 
> thread groups etc ;)
>
> The AccessControlContext could be cached for each Thread.

Yes, I think I'll keep a HashSet containing the AccessControlContext's 
that have passed with checkPermission, then if the Set contains the 
current AccessControlContext, we don't need to check it again.  When a 
revocation occurs the Set will be cleared.

I'm going to optimise the revocation strictly to only advise the 
delegates based on the Permission Classes, registered by the delegate's 
themselves, when they register with the policy (not individual 
Permission's since they may imply each other, just the common Class 
type).  Since the policy notifies the delegate, it also gets to close 
any sockets etc.

This should be the most optimum solution,  certainly much less work than 
calling checkPermission on every method invocation, but with no security 
trade off's.

N.B. Your time is much appreciated, thanks for the help.

Peter.

>
> Cheers,
>
> Peter.
>
>> Fred
>>
>>   
>
>


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred Oliver wrote:
> Peter,
>
> Thanks again.
>
>   
>>> Further, the
>>> revocation events are delivered to one or more of the delegates to
>>> force the socket to close.
>>>
>>>       
>> That was the original intent, however, now I'm thinking the delegate catch
>> AccessControlException, thrown by a helper class, called
>> MethodAccessContoller, which the delegate calls prior to entering the
>> privileged block, performs any clean up, then re-throws the exception.  Code
>> that doesn't need to do any clean up, doesn't need to catch the exception.
>>     
>
> What happens to the thread stuck in the read on the socket when the
> permission it had to read was revoked after the read began? Force
> closing the socket will free up the thread. Otherwise the thread would
> eventually obtain data it shouldn't have from this read (or hang
> indefinitely waiting for data).
>   

Hmm, yes, it needs to be closed from another thread.

>   
>> Basically: Method call from new thread? Permission check.  Permission
>> revoked? Permission check again.  Previously checked Thread, no relevant
>> revocation's since (of same Class<Permission>)? Don't check again, return
>> quickly.
>>
>> The assumption I've made is, it will be very difficult for an attacker to
>> predict when a thread will access a method on the delegate, then later, be
>> called by that very same thread, so his class can call the delegate
>> unchecked.  Any thoughts on this?  Am I overlooking something?
>>     
>
> What happens when a delegate is passed back and forth between trusted
> (having permission) and untrusted (not having permission) code (on the
> same thread)? If you cached based on the thread, you'll get
> unpredictable results?
>   

Yes that is a problem, so we have take a snapshot of the 
AccessControlContext at the time of the permission check and check that 
it is still equal() later.  I guess I could drop the thread check and 
just check the AccessControlContext, this might be useful for thread 
groups etc ;)

The AccessControlContext could be cached for each Thread.

Cheers,

Peter.

> Fred
>
>   


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Fred Oliver <fk...@gmail.com>.
Peter,

Thanks again.

>> Further, the
>> revocation events are delivered to one or more of the delegates to
>> force the socket to close.
>>
>
> That was the original intent, however, now I'm thinking the delegate catch
> AccessControlException, thrown by a helper class, called
> MethodAccessContoller, which the delegate calls prior to entering the
> privileged block, performs any clean up, then re-throws the exception.  Code
> that doesn't need to do any clean up, doesn't need to catch the exception.

What happens to the thread stuck in the read on the socket when the
permission it had to read was revoked after the read began? Force
closing the socket will free up the thread. Otherwise the thread would
eventually obtain data it shouldn't have from this read (or hang
indefinitely waiting for data).

> Basically: Method call from new thread? Permission check.  Permission
> revoked? Permission check again.  Previously checked Thread, no relevant
> revocation's since (of same Class<Permission>)? Don't check again, return
> quickly.
>
> The assumption I've made is, it will be very difficult for an attacker to
> predict when a thread will access a method on the delegate, then later, be
> called by that very same thread, so his class can call the delegate
> unchecked.  Any thoughts on this?  Am I overlooking something?

What happens when a delegate is passed back and forth between trusted
(having permission) and untrusted (not having permission) code (on the
same thread)? If you cached based on the thread, you'll get
unpredictable results?

Fred

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Don't worry, it's not based on Threads now, that model never did sit 
well, it's now based on AccessControlContext caching. New context, must 
be checked.

Patricia Shanahan wrote:
> Peter Firmstone wrote:
> ...
>> The assumption I've made is, it will be very difficult for an 
>> attacker to predict when a thread will access a method on the 
>> delegate, then later, be called by that very same thread, so his 
>> class can call the delegate unchecked.  Any thoughts on this?  Am I 
>> overlooking something?
> ...
>
> To win the overall game, a security system needs to block every single 
> attempt at breaking the rules.
>
> An attacker only needs have some chance of single try success and a 
> way of causing repeated attempts until one succeeds. Assuming 
> independence, an attacker with a probability p of single try success 
> gets a probability t of at least one success in log(1-t)/log(1-p) tries.
>
> For example, it takes less than 700,000 attempts to get a 50% chance 
> of at least one attempt succeeding, given a one in a million chance 
> for a single attempt.
>
> If you can enforce upper bounds on both the number of attempts and the 
> probability of each attempt succeeding it may be possible to show that 
> the overall probability of successful attack is low enough to ignore.
>
> Patricia
>


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Patricia Shanahan <pa...@acm.org>.
Peter Firmstone wrote:
...
> The assumption I've made is, it will be very difficult for an attacker 
> to predict when a thread will access a method on the delegate, then 
> later, be called by that very same thread, so his class can call the 
> delegate unchecked.  Any thoughts on this?  Am I overlooking something?
...

To win the overall game, a security system needs to block every single 
attempt at breaking the rules.

An attacker only needs have some chance of single try success and a way 
of causing repeated attempts until one succeeds. Assuming independence, 
an attacker with a probability p of single try success gets a 
probability t of at least one success in log(1-t)/log(1-p) tries.

For example, it takes less than 700,000 attempts to get a 50% chance of 
at least one attempt succeeding, given a one in a million chance for a 
single attempt.

If you can enforce upper bounds on both the number of attempts and the 
probability of each attempt succeeding it may be possible to show that 
the overall probability of successful attack is low enough to ignore.

Patricia

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred Oliver wrote:
> Peter,
>
> Thanks for the long answer. I'm still missing some implementation hints.
>
> In the case I suggested, downloaded code creates a socket on a port
> using the standard Java classes, gets the socket streams and begins
> communicating with the outside world. At this point, it is too late to
> stop the code from communicating by revoking permissions.
>   
Correct.
> If I understand correctly, instead, the downloaded code would not
> receive socket permissions at all (because they cannot be revoked
> after the socket is open), and would not be allowed to use the socket
> classes directly. Instead, a River factory class would be provided,
> and the downloaded code would be required to use that factory class to
> obtain a delegate for the socket. The delegate socket could then
> connect and return delegates for the streams to the downloaded code.
> In order to obtain permission for itself (to create and connect), the
> delegates would need to use doPrivileged() blocks? 
Correct.

> Further, the
> revocation events are delivered to one or more of the delegates to
> force the socket to close.
>   
That was the original intent, however, now I'm thinking the delegate 
catch AccessControlException, thrown by a helper class, called 
MethodAccessContoller, which the delegate calls prior to entering the 
privileged block, performs any clean up, then re-throws the exception.  
Code that doesn't need to do any clean up, doesn't need to catch the 
exception.

> Have I got the picture?
>   
Yes
> The scope of the proposal is then to allow permission revocation to
> apply to a limited (but extendable) set of delegate factory classes
> which downloaded code must be written to use?
>   
Yes, and to a limited subset of existing Java Permissions, which will be 
advised in the javadoc following auditing, although I guess there's a 
small risk that a standard JVM Permission that provides adequate 
protection today, may not in a future version.

Fred, you've just managed to clarify it in simple terms, having cleared 
that up, hopefully people can provide their insights into the risks 
associated with not calling AccessController.checkPermission on every 
method invocation on the delegate.

Basically: Method call from new thread? Permission check.  Permission 
revoked? Permission check again.  Previously checked Thread, no relevant 
revocation's since (of same Class<Permission>)? Don't check again, 
return quickly.

The assumption I've made is, it will be very difficult for an attacker 
to predict when a thread will access a method on the delegate, then 
later, be called by that very same thread, so his class can call the 
delegate unchecked.  Any thoughts on this?  Am I overlooking something?

I'm actually wondering about in the case of the given example, whether 
it is better to catch the AccessControlException, then throw an 
IOException, containing the relevant information, or to re-throw the 
AccessControlException.

After all it will be a client originated Thread that calls the proxy 
code, which is more likely to catch an IOException than an 
AccessControlException.

Thanks,

Peter.
> Fred
>
>
> On Mon, Aug 9, 2010 at 7:12 AM, Peter Firmstone <ji...@zeus.net.au> wrote:
>   
>> Fred Oliver wrote:
>>     
>>> Peter,
>>>
>>> I'm not clear on the scope of the proposal. Do you depend on
>>> enumerating all of the classes for which delegates would be needed?
>>> How would you interpose the delegate?
>>>
>>>       
>> Revokeability is intended for downloaded code.  I have some different
>> thoughts about possible implementations.  The aim is to force re checking of
>> a Permission if a reduction of trust has occurred. To never allow references
>> to objects with privileged functionality to escape into unprivileged code.
>>  The best place is to contain the privileged functionality within the
>> platform, the second best place, the client implementation or remotely in
>> the Server's service provider implementation.
>>
>> Many Java classes are subject to Permission checks only in their
>> constructors, or obtained from checked methods or GuardedObjects, these
>> Permission's are not safe to grant if they are to be later revoked, object
>> references may still exist, enabling privileged functionality in untrusted
>> client code.  What is needed are new Permission's that protect the methods
>> and creation of these classes by using a delegate to wrap the class,
>> depriving access via existing unchecked methods.   I think a builder class
>> that returns OutputStreams (InputStreams, or any other etc), could build
>> many different types of OutputStreams but utilise the same delegate.  This
>> could be provided as part of the Apache River platform.
>>
>> What I want to do, is enable a client to provide Permission's temporarily
>> for a period of time to a ProtectionDomain, then revoke that Permission
>> later.  I would want to do this if I utilise services from different servers
>> that utilise the same proxy code, so I can re-use the ClassLoader and
>> ProtectionDomain, to avoid having to use a new ClassLoader with re
>> verification of  the same bytecode.  This is based around provisioning of
>> proxy codebases, using Entry's to advertise the required codebase, version
>> and Permission's required.
>>
>> I had thought about requiring all delegates register with the revokeable
>> policy, however now I'm having a change of heart, and think instead a class
>> or delegate could use a MethodAccessController, with two methods
>> checkPermission() and getPermission().  The RevokeableDynamicPolicy
>> implementer can provide the implementation for the MethodAccessController
>> interface.  Each delegate gets it's own MethodAccessController object
>> (during construction) which has been designated a Permission to check (at
>> construction time), from the policy.  The MethodAccessController
>> implementation will have to keep a static set internally of all objects, the
>> policy will require a static method to Enumerate over these and set them to
>> check when the Permission Class matches that of a revoked Permission,
>> probably by passing a Set of Classes.
>>
>> This Permission check would be optimised, to call
>> AccessController.checkPermission(Permission) only under the following
>> conditions.
>>
>>  1. If this is the first time the current thread has called a method
>>     (or constructor) on the delegate object.
>>  2. If revocation has occurred for a Permission with the same Class in
>>     any ProtectionDomain, since the last permission check performed on
>>     that thread.  The MethodAccessController keeps track of the
>>     threads with an object weak hash map.
>>
>> The $1,000,000.00 question: Is the optimisation of only checking a thread
>> once, on the assumption that if the ProtectionDomain's on that thread's
>> stack are trustworthy to access the method, the code involved in this thread
>> can still be trusted until a Permission that implies it has become revoked?
>>  Remembering that the code was originally trusted, the object constructed
>> with the Permission check performed, utilised by that code for a period of
>> time, but now now that Permission has been revoked any method called on the
>> delegate throws an AccessControlException.
>> The only way the code could still have the Permission is if the
>> ProtectionDomain doesn't exist on the thread's stack, at the time of the
>> permission check, the check field is cleared for that thread and later, the
>> thread invokes the method with the ProtectionDomain in question on it's
>> stack, however to do so, the code in question must already hold a reference,
>> but not be involved in the current operations, it seems the probability
>> would be very low, the reference would have to be passed from another
>> thread, if an attacker could place this in the code, they'd be better off
>> attacking during the privileged period.  The Permission revoked code would
>> stop privileged operations during re verification of trust for another proxy
>> object and server.
>>
>> Static fields within the code could be used to store information between
>> service proxy's, this has a parallel to applets, where this was fixed with
>> separate ClassLoader, the client has that option however.
>>
>> Publicly shared proxy and service implementations can have their source
>> audited.
>>
>>     
>>> As an example, I think you propose that if code in a domain has a
>>> socket open on a port for which access is later revoked, the code
>>> should be denied further read/write access to the socket.
>>>
>>> -Should the socket be left open or closed?
>>>
>>>       
>> Closed, to free the port.  If somehow it is shared between threads, the
>> other thread will receive an IOException.
>>     
>>> -Was a delegate introduced and where?
>>>
>>>       
>> The best place is in a builder or factory method, since constructors create
>> a dependency link.  I'm thinking of a implementing new Platform class or
>> builder for the various Stream classes, along with new Permission's
>>     
>>> -Can the code use reflection to bypass the delegate?
>>>
>>>       
>> Yes, if it has Permission.
>>     
>>> -Is reflection denied generally?
>>>
>>>       
>> Yes, it should not be granted to code that will have Permission's revoked.
>>     
>>> Thanks,
>>>
>>>       
>> Your welcome, & thanks for asking too ;)
>>
>> Cheers,
>>
>> Peter.
>>     
>>> Fred
>>>
>>> On Sat, Aug 7, 2010 at 2:10 AM, Peter Firmstone <ji...@zeus.net.au> wrote:
>>>
>>>       
>>>> Please help identify any fallacies or oversights in the following
>>>> arguments.
>>>>
>>>> A Permission may be revoked, at any point in time after a revocation,
>>>> untrusted code may hold a reference to a privileged object.
>>>>
>>>> Some Permission's protect methods, such as Thread.interrupt(), these are
>>>> effectively revoked with the existing Java security model, however other
>>>> objects are only protected in their constructor, the responsibility being
>>>> on
>>>> the trusted code, not to let their references escape, such as
>>>> FileOutputStream.
>>>>
>>>> The moment code holding a reference becomes untrusted, the reference has
>>>> escaped.
>>>>
>>>> Instead of using a GuardedObject, or checking permission in constructors,
>>>> to
>>>> deal with Permission's that can be revoked, we need to encapsulate the
>>>> object that needs protection with a SecurityDelegate.
>>>>
>>>> During a checkPermission call, the current Thread's AccessControlContext
>>>> is
>>>> obtained, and (gross simplification) is asked to checkPermission.  The
>>>> AccessControlContext contains all the ProtectionDomain's on the stack,
>>>> all
>>>> ProtectionDomains on the stack must have the Permission for it to
>>>> succeed.
>>>>  The ProtectionDomain's contained by the AccessControlContext are related
>>>> to
>>>> the class and object methods called and returned, the ProtectionDomain's
>>>> are
>>>> dynamically added or removed.
>>>>
>>>> So the thinking behind the SecurityDelegate's private check method is
>>>> that
>>>> an object must be protected in a dynamically changing environment:
>>>>
>>>>  1. Has the RevokeableDynamicPolicy advised that a check must be
>>>>    performed?
>>>>  2. Is this the same thread that the last security check was made
>>>>    against?  If we haven't been advised that there is a reduction of
>>>>    trust in our dynamic Security environment and the last
>>>>    checkPermission call succeeded on this thread, then we can assume
>>>>    that this Tread is still safe.
>>>>  3. If this thread is different or new, then we must checkPermission,
>>>>    regardless of whether trust has changed recently or not.
>>>>
>>>> The costs:
>>>>
>>>>  1. Multi-threading is penalised (although a WeakMap could be
>>>>    utilised, with threads as keys, and boolean check values, where
>>>>    all are set true by the notify() call).
>>>>  2. The three "if" calls on every method invocation, check, null and
>>>>    == Thread.
>>>>  3. Replicating the check method on all implementers (this will
>>>>    require a helper class to implement the check).
>>>>  4. The RevokeableDynamicPolicy will need to notify all
>>>>    SecurityDelegate's every time a reduction in trust occurs, it will
>>>>    rely on GC to clean up and remove SecurityDelegates.
>>>>
>>>> The assumption is if the current Thread was trustworthy last call and the
>>>> environment hasn't experienced a reduction of trust, we can still trust
>>>> this
>>>> thread.  There is of course a risk that a Thread may have a new
>>>> ProtectionDomain on it's stack that isn't trusted, however this could
>>>> still
>>>> happen in the case of the guarded object, where the environment doesn't
>>>> experience a reduction of trust and the trusted code must be trusted not
>>>> to
>>>> let the reference escape it's own ProtectionDomain.  Any code that
>>>> experiences a reduction of trust will receive an AccessControlException.
>>>>
>>>> Cheers,
>>>>
>>>> Peter.
>>>>
>>>>         
>>>       
>>     
>
>   


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Gregg Wonderly <gr...@wonderly.org>.
Quite a long time ago, on the Jini lists, I presented the issue of resource 
oriented authorization vs role oriented authorization.  I found a reference to 
some of this at:

<http://osdir.com/ml/java.sun.jini/2005-03/msg00252.html>

I tried to stress the fact that I feel that you really never want to design your 
distributed application to use permission grants based on access to resources 
such as socket connections, files etc.  Instead, you want something at the front 
line of your application APIs that represents role based access.  First, 
authenticate and then use the associated entity's roles to find permissions.
Authentication is not always easy, but I think that this greatly faciltates the 
ability to revoke access, dynamically through API control of what roles can do, 
rather than through direct permissions on resource access.  Primarily this just 
falls out of the fact that you are making API calls for access, and you can plug 
in smart proxy returns and do other things, over time to refine the details you 
need to control.

My authlib stuff that I just threw out on java.net, represents some of what I 
had done to facilitate this for my applications.

Gregg Wonderly

Fred Oliver wrote:
> Peter,
> 
> Thanks for the long answer. I'm still missing some implementation hints.
> 
> In the case I suggested, downloaded code creates a socket on a port
> using the standard Java classes, gets the socket streams and begins
> communicating with the outside world. At this point, it is too late to
> stop the code from communicating by revoking permissions.
> 
> If I understand correctly, instead, the downloaded code would not
> receive socket permissions at all (because they cannot be revoked
> after the socket is open), and would not be allowed to use the socket
> classes directly. Instead, a River factory class would be provided,
> and the downloaded code would be required to use that factory class to
> obtain a delegate for the socket. The delegate socket could then
> connect and return delegates for the streams to the downloaded code.
> In order to obtain permission for itself (to create and connect), the
> delegates would need to use doPrivileged() blocks? Further, the
> revocation events are delivered to one or more of the delegates to
> force the socket to close.
> 
> Have I got the picture?
> 
> The scope of the proposal is then to allow permission revocation to
> apply to a limited (but extendable) set of delegate factory classes
> which downloaded code must be written to use?
> 
> Fred
> 
> 
> On Mon, Aug 9, 2010 at 7:12 AM, Peter Firmstone <ji...@zeus.net.au> wrote:
>> Fred Oliver wrote:
>>> Peter,
>>>
>>> I'm not clear on the scope of the proposal. Do you depend on
>>> enumerating all of the classes for which delegates would be needed?
>>> How would you interpose the delegate?
>>>
>> Revokeability is intended for downloaded code.  I have some different
>> thoughts about possible implementations.  The aim is to force re checking of
>> a Permission if a reduction of trust has occurred. To never allow references
>> to objects with privileged functionality to escape into unprivileged code.
>>  The best place is to contain the privileged functionality within the
>> platform, the second best place, the client implementation or remotely in
>> the Server's service provider implementation.
>>
>> Many Java classes are subject to Permission checks only in their
>> constructors, or obtained from checked methods or GuardedObjects, these
>> Permission's are not safe to grant if they are to be later revoked, object
>> references may still exist, enabling privileged functionality in untrusted
>> client code.  What is needed are new Permission's that protect the methods
>> and creation of these classes by using a delegate to wrap the class,
>> depriving access via existing unchecked methods.   I think a builder class
>> that returns OutputStreams (InputStreams, or any other etc), could build
>> many different types of OutputStreams but utilise the same delegate.  This
>> could be provided as part of the Apache River platform.
>>
>> What I want to do, is enable a client to provide Permission's temporarily
>> for a period of time to a ProtectionDomain, then revoke that Permission
>> later.  I would want to do this if I utilise services from different servers
>> that utilise the same proxy code, so I can re-use the ClassLoader and
>> ProtectionDomain, to avoid having to use a new ClassLoader with re
>> verification of  the same bytecode.  This is based around provisioning of
>> proxy codebases, using Entry's to advertise the required codebase, version
>> and Permission's required.
>>
>> I had thought about requiring all delegates register with the revokeable
>> policy, however now I'm having a change of heart, and think instead a class
>> or delegate could use a MethodAccessController, with two methods
>> checkPermission() and getPermission().  The RevokeableDynamicPolicy
>> implementer can provide the implementation for the MethodAccessController
>> interface.  Each delegate gets it's own MethodAccessController object
>> (during construction) which has been designated a Permission to check (at
>> construction time), from the policy.  The MethodAccessController
>> implementation will have to keep a static set internally of all objects, the
>> policy will require a static method to Enumerate over these and set them to
>> check when the Permission Class matches that of a revoked Permission,
>> probably by passing a Set of Classes.
>>
>> This Permission check would be optimised, to call
>> AccessController.checkPermission(Permission) only under the following
>> conditions.
>>
>>  1. If this is the first time the current thread has called a method
>>     (or constructor) on the delegate object.
>>  2. If revocation has occurred for a Permission with the same Class in
>>     any ProtectionDomain, since the last permission check performed on
>>     that thread.  The MethodAccessController keeps track of the
>>     threads with an object weak hash map.
>>
>> The $1,000,000.00 question: Is the optimisation of only checking a thread
>> once, on the assumption that if the ProtectionDomain's on that thread's
>> stack are trustworthy to access the method, the code involved in this thread
>> can still be trusted until a Permission that implies it has become revoked?
>>  Remembering that the code was originally trusted, the object constructed
>> with the Permission check performed, utilised by that code for a period of
>> time, but now now that Permission has been revoked any method called on the
>> delegate throws an AccessControlException.
>> The only way the code could still have the Permission is if the
>> ProtectionDomain doesn't exist on the thread's stack, at the time of the
>> permission check, the check field is cleared for that thread and later, the
>> thread invokes the method with the ProtectionDomain in question on it's
>> stack, however to do so, the code in question must already hold a reference,
>> but not be involved in the current operations, it seems the probability
>> would be very low, the reference would have to be passed from another
>> thread, if an attacker could place this in the code, they'd be better off
>> attacking during the privileged period.  The Permission revoked code would
>> stop privileged operations during re verification of trust for another proxy
>> object and server.
>>
>> Static fields within the code could be used to store information between
>> service proxy's, this has a parallel to applets, where this was fixed with
>> separate ClassLoader, the client has that option however.
>>
>> Publicly shared proxy and service implementations can have their source
>> audited.
>>
>>> As an example, I think you propose that if code in a domain has a
>>> socket open on a port for which access is later revoked, the code
>>> should be denied further read/write access to the socket.
>>>
>>> -Should the socket be left open or closed?
>>>
>> Closed, to free the port.  If somehow it is shared between threads, the
>> other thread will receive an IOException.
>>> -Was a delegate introduced and where?
>>>
>> The best place is in a builder or factory method, since constructors create
>> a dependency link.  I'm thinking of a implementing new Platform class or
>> builder for the various Stream classes, along with new Permission's
>>> -Can the code use reflection to bypass the delegate?
>>>
>> Yes, if it has Permission.
>>> -Is reflection denied generally?
>>>
>> Yes, it should not be granted to code that will have Permission's revoked.
>>> Thanks,
>>>
>> Your welcome, & thanks for asking too ;)
>>
>> Cheers,
>>
>> Peter.
>>> Fred
>>>
>>> On Sat, Aug 7, 2010 at 2:10 AM, Peter Firmstone <ji...@zeus.net.au> wrote:
>>>
>>>> Please help identify any fallacies or oversights in the following
>>>> arguments.
>>>>
>>>> A Permission may be revoked, at any point in time after a revocation,
>>>> untrusted code may hold a reference to a privileged object.
>>>>
>>>> Some Permission's protect methods, such as Thread.interrupt(), these are
>>>> effectively revoked with the existing Java security model, however other
>>>> objects are only protected in their constructor, the responsibility being
>>>> on
>>>> the trusted code, not to let their references escape, such as
>>>> FileOutputStream.
>>>>
>>>> The moment code holding a reference becomes untrusted, the reference has
>>>> escaped.
>>>>
>>>> Instead of using a GuardedObject, or checking permission in constructors,
>>>> to
>>>> deal with Permission's that can be revoked, we need to encapsulate the
>>>> object that needs protection with a SecurityDelegate.
>>>>
>>>> During a checkPermission call, the current Thread's AccessControlContext
>>>> is
>>>> obtained, and (gross simplification) is asked to checkPermission.  The
>>>> AccessControlContext contains all the ProtectionDomain's on the stack,
>>>> all
>>>> ProtectionDomains on the stack must have the Permission for it to
>>>> succeed.
>>>>  The ProtectionDomain's contained by the AccessControlContext are related
>>>> to
>>>> the class and object methods called and returned, the ProtectionDomain's
>>>> are
>>>> dynamically added or removed.
>>>>
>>>> So the thinking behind the SecurityDelegate's private check method is
>>>> that
>>>> an object must be protected in a dynamically changing environment:
>>>>
>>>>  1. Has the RevokeableDynamicPolicy advised that a check must be
>>>>    performed?
>>>>  2. Is this the same thread that the last security check was made
>>>>    against?  If we haven't been advised that there is a reduction of
>>>>    trust in our dynamic Security environment and the last
>>>>    checkPermission call succeeded on this thread, then we can assume
>>>>    that this Tread is still safe.
>>>>  3. If this thread is different or new, then we must checkPermission,
>>>>    regardless of whether trust has changed recently or not.
>>>>
>>>> The costs:
>>>>
>>>>  1. Multi-threading is penalised (although a WeakMap could be
>>>>    utilised, with threads as keys, and boolean check values, where
>>>>    all are set true by the notify() call).
>>>>  2. The three "if" calls on every method invocation, check, null and
>>>>    == Thread.
>>>>  3. Replicating the check method on all implementers (this will
>>>>    require a helper class to implement the check).
>>>>  4. The RevokeableDynamicPolicy will need to notify all
>>>>    SecurityDelegate's every time a reduction in trust occurs, it will
>>>>    rely on GC to clean up and remove SecurityDelegates.
>>>>
>>>> The assumption is if the current Thread was trustworthy last call and the
>>>> environment hasn't experienced a reduction of trust, we can still trust
>>>> this
>>>> thread.  There is of course a risk that a Thread may have a new
>>>> ProtectionDomain on it's stack that isn't trusted, however this could
>>>> still
>>>> happen in the case of the guarded object, where the environment doesn't
>>>> experience a reduction of trust and the trusted code must be trusted not
>>>> to
>>>> let the reference escape it's own ProtectionDomain.  Any code that
>>>> experiences a reduction of trust will receive an AccessControlException.
>>>>
>>>> Cheers,
>>>>
>>>> Peter.
>>>>
>>>
>>
> 


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Fred Oliver <fk...@gmail.com>.
Peter,

Thanks for the long answer. I'm still missing some implementation hints.

In the case I suggested, downloaded code creates a socket on a port
using the standard Java classes, gets the socket streams and begins
communicating with the outside world. At this point, it is too late to
stop the code from communicating by revoking permissions.

If I understand correctly, instead, the downloaded code would not
receive socket permissions at all (because they cannot be revoked
after the socket is open), and would not be allowed to use the socket
classes directly. Instead, a River factory class would be provided,
and the downloaded code would be required to use that factory class to
obtain a delegate for the socket. The delegate socket could then
connect and return delegates for the streams to the downloaded code.
In order to obtain permission for itself (to create and connect), the
delegates would need to use doPrivileged() blocks? Further, the
revocation events are delivered to one or more of the delegates to
force the socket to close.

Have I got the picture?

The scope of the proposal is then to allow permission revocation to
apply to a limited (but extendable) set of delegate factory classes
which downloaded code must be written to use?

Fred


On Mon, Aug 9, 2010 at 7:12 AM, Peter Firmstone <ji...@zeus.net.au> wrote:
> Fred Oliver wrote:
>>
>> Peter,
>>
>> I'm not clear on the scope of the proposal. Do you depend on
>> enumerating all of the classes for which delegates would be needed?
>> How would you interpose the delegate?
>>
>
> Revokeability is intended for downloaded code.  I have some different
> thoughts about possible implementations.  The aim is to force re checking of
> a Permission if a reduction of trust has occurred. To never allow references
> to objects with privileged functionality to escape into unprivileged code.
>  The best place is to contain the privileged functionality within the
> platform, the second best place, the client implementation or remotely in
> the Server's service provider implementation.
>
> Many Java classes are subject to Permission checks only in their
> constructors, or obtained from checked methods or GuardedObjects, these
> Permission's are not safe to grant if they are to be later revoked, object
> references may still exist, enabling privileged functionality in untrusted
> client code.  What is needed are new Permission's that protect the methods
> and creation of these classes by using a delegate to wrap the class,
> depriving access via existing unchecked methods.   I think a builder class
> that returns OutputStreams (InputStreams, or any other etc), could build
> many different types of OutputStreams but utilise the same delegate.  This
> could be provided as part of the Apache River platform.
>
> What I want to do, is enable a client to provide Permission's temporarily
> for a period of time to a ProtectionDomain, then revoke that Permission
> later.  I would want to do this if I utilise services from different servers
> that utilise the same proxy code, so I can re-use the ClassLoader and
> ProtectionDomain, to avoid having to use a new ClassLoader with re
> verification of  the same bytecode.  This is based around provisioning of
> proxy codebases, using Entry's to advertise the required codebase, version
> and Permission's required.
>
> I had thought about requiring all delegates register with the revokeable
> policy, however now I'm having a change of heart, and think instead a class
> or delegate could use a MethodAccessController, with two methods
> checkPermission() and getPermission().  The RevokeableDynamicPolicy
> implementer can provide the implementation for the MethodAccessController
> interface.  Each delegate gets it's own MethodAccessController object
> (during construction) which has been designated a Permission to check (at
> construction time), from the policy.  The MethodAccessController
> implementation will have to keep a static set internally of all objects, the
> policy will require a static method to Enumerate over these and set them to
> check when the Permission Class matches that of a revoked Permission,
> probably by passing a Set of Classes.
>
> This Permission check would be optimised, to call
> AccessController.checkPermission(Permission) only under the following
> conditions.
>
>  1. If this is the first time the current thread has called a method
>     (or constructor) on the delegate object.
>  2. If revocation has occurred for a Permission with the same Class in
>     any ProtectionDomain, since the last permission check performed on
>     that thread.  The MethodAccessController keeps track of the
>     threads with an object weak hash map.
>
> The $1,000,000.00 question: Is the optimisation of only checking a thread
> once, on the assumption that if the ProtectionDomain's on that thread's
> stack are trustworthy to access the method, the code involved in this thread
> can still be trusted until a Permission that implies it has become revoked?
>  Remembering that the code was originally trusted, the object constructed
> with the Permission check performed, utilised by that code for a period of
> time, but now now that Permission has been revoked any method called on the
> delegate throws an AccessControlException.
> The only way the code could still have the Permission is if the
> ProtectionDomain doesn't exist on the thread's stack, at the time of the
> permission check, the check field is cleared for that thread and later, the
> thread invokes the method with the ProtectionDomain in question on it's
> stack, however to do so, the code in question must already hold a reference,
> but not be involved in the current operations, it seems the probability
> would be very low, the reference would have to be passed from another
> thread, if an attacker could place this in the code, they'd be better off
> attacking during the privileged period.  The Permission revoked code would
> stop privileged operations during re verification of trust for another proxy
> object and server.
>
> Static fields within the code could be used to store information between
> service proxy's, this has a parallel to applets, where this was fixed with
> separate ClassLoader, the client has that option however.
>
> Publicly shared proxy and service implementations can have their source
> audited.
>
>> As an example, I think you propose that if code in a domain has a
>> socket open on a port for which access is later revoked, the code
>> should be denied further read/write access to the socket.
>>
>> -Should the socket be left open or closed?
>>
>
> Closed, to free the port.  If somehow it is shared between threads, the
> other thread will receive an IOException.
>>
>> -Was a delegate introduced and where?
>>
>
> The best place is in a builder or factory method, since constructors create
> a dependency link.  I'm thinking of a implementing new Platform class or
> builder for the various Stream classes, along with new Permission's
>>
>> -Can the code use reflection to bypass the delegate?
>>
>
> Yes, if it has Permission.
>>
>> -Is reflection denied generally?
>>
>
> Yes, it should not be granted to code that will have Permission's revoked.
>>
>> Thanks,
>>
>
> Your welcome, & thanks for asking too ;)
>
> Cheers,
>
> Peter.
>>
>> Fred
>>
>> On Sat, Aug 7, 2010 at 2:10 AM, Peter Firmstone <ji...@zeus.net.au> wrote:
>>
>>>
>>> Please help identify any fallacies or oversights in the following
>>> arguments.
>>>
>>> A Permission may be revoked, at any point in time after a revocation,
>>> untrusted code may hold a reference to a privileged object.
>>>
>>> Some Permission's protect methods, such as Thread.interrupt(), these are
>>> effectively revoked with the existing Java security model, however other
>>> objects are only protected in their constructor, the responsibility being
>>> on
>>> the trusted code, not to let their references escape, such as
>>> FileOutputStream.
>>>
>>> The moment code holding a reference becomes untrusted, the reference has
>>> escaped.
>>>
>>> Instead of using a GuardedObject, or checking permission in constructors,
>>> to
>>> deal with Permission's that can be revoked, we need to encapsulate the
>>> object that needs protection with a SecurityDelegate.
>>>
>>> During a checkPermission call, the current Thread's AccessControlContext
>>> is
>>> obtained, and (gross simplification) is asked to checkPermission.  The
>>> AccessControlContext contains all the ProtectionDomain's on the stack,
>>> all
>>> ProtectionDomains on the stack must have the Permission for it to
>>> succeed.
>>>  The ProtectionDomain's contained by the AccessControlContext are related
>>> to
>>> the class and object methods called and returned, the ProtectionDomain's
>>> are
>>> dynamically added or removed.
>>>
>>> So the thinking behind the SecurityDelegate's private check method is
>>> that
>>> an object must be protected in a dynamically changing environment:
>>>
>>>  1. Has the RevokeableDynamicPolicy advised that a check must be
>>>    performed?
>>>  2. Is this the same thread that the last security check was made
>>>    against?  If we haven't been advised that there is a reduction of
>>>    trust in our dynamic Security environment and the last
>>>    checkPermission call succeeded on this thread, then we can assume
>>>    that this Tread is still safe.
>>>  3. If this thread is different or new, then we must checkPermission,
>>>    regardless of whether trust has changed recently or not.
>>>
>>> The costs:
>>>
>>>  1. Multi-threading is penalised (although a WeakMap could be
>>>    utilised, with threads as keys, and boolean check values, where
>>>    all are set true by the notify() call).
>>>  2. The three "if" calls on every method invocation, check, null and
>>>    == Thread.
>>>  3. Replicating the check method on all implementers (this will
>>>    require a helper class to implement the check).
>>>  4. The RevokeableDynamicPolicy will need to notify all
>>>    SecurityDelegate's every time a reduction in trust occurs, it will
>>>    rely on GC to clean up and remove SecurityDelegates.
>>>
>>> The assumption is if the current Thread was trustworthy last call and the
>>> environment hasn't experienced a reduction of trust, we can still trust
>>> this
>>> thread.  There is of course a risk that a Thread may have a new
>>> ProtectionDomain on it's stack that isn't trusted, however this could
>>> still
>>> happen in the case of the guarded object, where the environment doesn't
>>> experience a reduction of trust and the trusted code must be trusted not
>>> to
>>> let the reference escape it's own ProtectionDomain.  Any code that
>>> experiences a reduction of trust will receive an AccessControlException.
>>>
>>> Cheers,
>>>
>>> Peter.
>>>
>>
>>
>
>

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Fred Oliver wrote:
> Peter,
>
> I'm not clear on the scope of the proposal. Do you depend on
> enumerating all of the classes for which delegates would be needed?
> How would you interpose the delegate?
>   

Revokeability is intended for downloaded code.  I have some different 
thoughts about possible implementations.  The aim is to force re 
checking of a Permission if a reduction of trust has occurred. To never 
allow references to objects with privileged functionality to escape into 
unprivileged code.  The best place is to contain the privileged 
functionality within the platform, the second best place, the client 
implementation or remotely in the Server's service provider implementation.

Many Java classes are subject to Permission checks only in their 
constructors, or obtained from checked methods or GuardedObjects, these 
Permission's are not safe to grant if they are to be later revoked, 
object references may still exist, enabling privileged functionality in 
untrusted client code.  What is needed are new Permission's that protect 
the methods and creation of these classes by using a delegate to wrap 
the class, depriving access via existing unchecked methods.   I think a 
builder class that returns OutputStreams (InputStreams, or any other 
etc), could build many different types of OutputStreams but utilise the 
same delegate.  This could be provided as part of the Apache River platform.

What I want to do, is enable a client to provide Permission's 
temporarily for a period of time to a ProtectionDomain, then revoke that 
Permission later.  I would want to do this if I utilise services from 
different servers that utilise the same proxy code, so I can re-use the 
ClassLoader and ProtectionDomain, to avoid having to use a new 
ClassLoader with re verification of  the same bytecode.  This is based 
around provisioning of proxy codebases, using Entry's to advertise the 
required codebase, version and Permission's required.

I had thought about requiring all delegates register with the revokeable 
policy, however now I'm having a change of heart, and think instead a 
class or delegate could use a MethodAccessController, with two methods 
checkPermission() and getPermission().  The RevokeableDynamicPolicy 
implementer can provide the implementation for the 
MethodAccessController interface.  Each delegate gets it's own 
MethodAccessController object (during construction) which has been 
designated a Permission to check (at construction time), from the 
policy.  The MethodAccessController implementation will have to keep a 
static set internally of all objects, the policy will require a static 
method to Enumerate over these and set them to check when the Permission 
Class matches that of a revoked Permission, probably by passing a Set of 
Classes.

This Permission check would be optimised, to call 
AccessController.checkPermission(Permission) only under the following 
conditions.

   1. If this is the first time the current thread has called a method
      (or constructor) on the delegate object.
   2. If revocation has occurred for a Permission with the same Class in
      any ProtectionDomain, since the last permission check performed on
      that thread.  The MethodAccessController keeps track of the
      threads with an object weak hash map.

The $1,000,000.00 question: Is the optimisation of only checking a 
thread once, on the assumption that if the ProtectionDomain's on that 
thread's stack are trustworthy to access the method, the code involved 
in this thread can still be trusted until a Permission that implies it 
has become revoked?  Remembering that the code was originally trusted, 
the object constructed with the Permission check performed, utilised by 
that code for a period of time, but now now that Permission has been 
revoked any method called on the delegate throws an 
AccessControlException. 

The only way the code could still have the Permission is if the 
ProtectionDomain doesn't exist on the thread's stack, at the time of the 
permission check, the check field is cleared for that thread and later, 
the thread invokes the method with the ProtectionDomain in question on 
it's stack, however to do so, the code in question must already hold a 
reference, but not be involved in the current operations, it seems the 
probability would be very low, the reference would have to be passed 
from another thread, if an attacker could place this in the code, they'd 
be better off attacking during the privileged period.  The Permission 
revoked code would stop privileged operations during re verification of 
trust for another proxy object and server.

Static fields within the code could be used to store information between 
service proxy's, this has a parallel to applets, where this was fixed 
with separate ClassLoader, the client has that option however.

Publicly shared proxy and service implementations can have their source 
audited.

> As an example, I think you propose that if code in a domain has a
> socket open on a port for which access is later revoked, the code
> should be denied further read/write access to the socket.
>
> -Should the socket be left open or closed?
>   
Closed, to free the port.  If somehow it is shared between threads, the 
other thread will receive an IOException.
> -Was a delegate introduced and where?
>   
The best place is in a builder or factory method, since constructors 
create a dependency link.  I'm thinking of a implementing new Platform 
class or builder for the various Stream classes, along with new Permission's
> -Can the code use reflection to bypass the delegate?
>   
Yes, if it has Permission.
> -Is reflection denied generally?
>   
Yes, it should not be granted to code that will have Permission's revoked.
> Thanks,
>   
Your welcome, & thanks for asking too ;)

Cheers,

Peter.
> Fred
>
> On Sat, Aug 7, 2010 at 2:10 AM, Peter Firmstone <ji...@zeus.net.au> wrote:
>   
>> Please help identify any fallacies or oversights in the following arguments.
>>
>> A Permission may be revoked, at any point in time after a revocation,
>> untrusted code may hold a reference to a privileged object.
>>
>> Some Permission's protect methods, such as Thread.interrupt(), these are
>> effectively revoked with the existing Java security model, however other
>> objects are only protected in their constructor, the responsibility being on
>> the trusted code, not to let their references escape, such as
>> FileOutputStream.
>>
>> The moment code holding a reference becomes untrusted, the reference has
>> escaped.
>>
>> Instead of using a GuardedObject, or checking permission in constructors, to
>> deal with Permission's that can be revoked, we need to encapsulate the
>> object that needs protection with a SecurityDelegate.
>>
>> During a checkPermission call, the current Thread's AccessControlContext is
>> obtained, and (gross simplification) is asked to checkPermission.  The
>> AccessControlContext contains all the ProtectionDomain's on the stack, all
>> ProtectionDomains on the stack must have the Permission for it to succeed.
>>  The ProtectionDomain's contained by the AccessControlContext are related to
>> the class and object methods called and returned, the ProtectionDomain's are
>> dynamically added or removed.
>>
>> So the thinking behind the SecurityDelegate's private check method is that
>> an object must be protected in a dynamically changing environment:
>>
>>  1. Has the RevokeableDynamicPolicy advised that a check must be
>>     performed?
>>  2. Is this the same thread that the last security check was made
>>     against?  If we haven't been advised that there is a reduction of
>>     trust in our dynamic Security environment and the last
>>     checkPermission call succeeded on this thread, then we can assume
>>     that this Tread is still safe.
>>  3. If this thread is different or new, then we must checkPermission,
>>     regardless of whether trust has changed recently or not.
>>
>> The costs:
>>
>>  1. Multi-threading is penalised (although a WeakMap could be
>>     utilised, with threads as keys, and boolean check values, where
>>     all are set true by the notify() call).
>>  2. The three "if" calls on every method invocation, check, null and
>>     == Thread.
>>  3. Replicating the check method on all implementers (this will
>>     require a helper class to implement the check).
>>  4. The RevokeableDynamicPolicy will need to notify all
>>     SecurityDelegate's every time a reduction in trust occurs, it will
>>     rely on GC to clean up and remove SecurityDelegates.
>>
>> The assumption is if the current Thread was trustworthy last call and the
>> environment hasn't experienced a reduction of trust, we can still trust this
>> thread.  There is of course a risk that a Thread may have a new
>> ProtectionDomain on it's stack that isn't trusted, however this could still
>> happen in the case of the guarded object, where the environment doesn't
>> experience a reduction of trust and the trusted code must be trusted not to
>> let the reference escape it's own ProtectionDomain.  Any code that
>> experiences a reduction of trust will receive an AccessControlException.
>>
>> Cheers,
>>
>> Peter.
>>     
>
>   


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Fred Oliver <fk...@gmail.com>.
Peter,

I'm not clear on the scope of the proposal. Do you depend on
enumerating all of the classes for which delegates would be needed?
How would you interpose the delegate?

As an example, I think you propose that if code in a domain has a
socket open on a port for which access is later revoked, the code
should be denied further read/write access to the socket.

-Should the socket be left open or closed?
-Was a delegate introduced and where?
-Can the code use reflection to bypass the delegate?
-Is reflection denied generally?

Thanks,

Fred

On Sat, Aug 7, 2010 at 2:10 AM, Peter Firmstone <ji...@zeus.net.au> wrote:
> Please help identify any fallacies or oversights in the following arguments.
>
> A Permission may be revoked, at any point in time after a revocation,
> untrusted code may hold a reference to a privileged object.
>
> Some Permission's protect methods, such as Thread.interrupt(), these are
> effectively revoked with the existing Java security model, however other
> objects are only protected in their constructor, the responsibility being on
> the trusted code, not to let their references escape, such as
> FileOutputStream.
>
> The moment code holding a reference becomes untrusted, the reference has
> escaped.
>
> Instead of using a GuardedObject, or checking permission in constructors, to
> deal with Permission's that can be revoked, we need to encapsulate the
> object that needs protection with a SecurityDelegate.
>
> During a checkPermission call, the current Thread's AccessControlContext is
> obtained, and (gross simplification) is asked to checkPermission.  The
> AccessControlContext contains all the ProtectionDomain's on the stack, all
> ProtectionDomains on the stack must have the Permission for it to succeed.
>  The ProtectionDomain's contained by the AccessControlContext are related to
> the class and object methods called and returned, the ProtectionDomain's are
> dynamically added or removed.
>
> So the thinking behind the SecurityDelegate's private check method is that
> an object must be protected in a dynamically changing environment:
>
>  1. Has the RevokeableDynamicPolicy advised that a check must be
>     performed?
>  2. Is this the same thread that the last security check was made
>     against?  If we haven't been advised that there is a reduction of
>     trust in our dynamic Security environment and the last
>     checkPermission call succeeded on this thread, then we can assume
>     that this Tread is still safe.
>  3. If this thread is different or new, then we must checkPermission,
>     regardless of whether trust has changed recently or not.
>
> The costs:
>
>  1. Multi-threading is penalised (although a WeakMap could be
>     utilised, with threads as keys, and boolean check values, where
>     all are set true by the notify() call).
>  2. The three "if" calls on every method invocation, check, null and
>     == Thread.
>  3. Replicating the check method on all implementers (this will
>     require a helper class to implement the check).
>  4. The RevokeableDynamicPolicy will need to notify all
>     SecurityDelegate's every time a reduction in trust occurs, it will
>     rely on GC to clean up and remove SecurityDelegates.
>
> The assumption is if the current Thread was trustworthy last call and the
> environment hasn't experienced a reduction of trust, we can still trust this
> thread.  There is of course a risk that a Thread may have a new
> ProtectionDomain on it's stack that isn't trusted, however this could still
> happen in the case of the guarded object, where the environment doesn't
> experience a reduction of trust and the trusted code must be trusted not to
> let the reference escape it's own ProtectionDomain.  Any code that
> experiences a reduction of trust will receive an AccessControlException.
>
> Cheers,
>
> Peter.

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Sat, Aug 7, 2010 at 2:10 PM, Peter Firmstone <ji...@zeus.net.au> wrote:
> Please help identify any fallacies or oversights in the following arguments.

I am not a security expert by any means, but in principle I know;

 * Security is hard. The more complex, the more likely it is to be flawed.
 * I suspect that any scheme is impossible to prove to be guaranteed
secure. Only "know to be" secured until proven wrong, in some cases
too late.


So the general advice is; Keep it simple, or it won't work, just make
it much harder for the developers.


Cheers
-- 
Niclas Hedhman, Software Developer
http://www.qi4j.org - New Energy for Java

I  live here; http://tinyurl.com/2qq9er
I  work here; http://tinyurl.com/2ymelc
I relax here; http://tinyurl.com/2cgsug

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Please help identify any fallacies or oversights in the following arguments.

A Permission may be revoked, at any point in time after a revocation, 
untrusted code may hold a reference to a privileged object.

Some Permission's protect methods, such as Thread.interrupt(), these are 
effectively revoked with the existing Java security model, however other 
objects are only protected in their constructor, the responsibility 
being on the trusted code, not to let their references escape, such as 
FileOutputStream.

The moment code holding a reference becomes untrusted, the reference has 
escaped.

Instead of using a GuardedObject, or checking permission in 
constructors, to deal with Permission's that can be revoked, we need to 
encapsulate the object that needs protection with a SecurityDelegate.

During a checkPermission call, the current Thread's AccessControlContext 
is obtained, and (gross simplification) is asked to checkPermission.  
The AccessControlContext contains all the ProtectionDomain's on the 
stack, all ProtectionDomains on the stack must have the Permission for 
it to succeed.  The ProtectionDomain's contained by the 
AccessControlContext are related to the class and object methods called 
and returned, the ProtectionDomain's are dynamically added or removed.

So the thinking behind the SecurityDelegate's private check method is 
that an object must be protected in a dynamically changing environment:

   1. Has the RevokeableDynamicPolicy advised that a check must be
      performed?
   2. Is this the same thread that the last security check was made
      against?  If we haven't been advised that there is a reduction of
      trust in our dynamic Security environment and the last
      checkPermission call succeeded on this thread, then we can assume
      that this Tread is still safe.
   3. If this thread is different or new, then we must checkPermission,
      regardless of whether trust has changed recently or not.

The costs:

   1. Multi-threading is penalised (although a WeakMap could be
      utilised, with threads as keys, and boolean check values, where
      all are set true by the notify() call).
   2. The three "if" calls on every method invocation, check, null and
      == Thread.
   3. Replicating the check method on all implementers (this will
      require a helper class to implement the check).
   4. The RevokeableDynamicPolicy will need to notify all
      SecurityDelegate's every time a reduction in trust occurs, it will
      rely on GC to clean up and remove SecurityDelegates.

The assumption is if the current Thread was trustworthy last call and 
the environment hasn't experienced a reduction of trust, we can still 
trust this thread.  There is of course a risk that a Thread may have a 
new ProtectionDomain on it's stack that isn't trusted, however this 
could still happen in the case of the guarded object, where the 
environment doesn't experience a reduction of trust and the trusted code 
must be trusted not to let the reference escape it's own 
ProtectionDomain.  Any code that experiences a reduction of trust will 
receive an AccessControlException.

Cheers,

Peter.

Peter Firmstone wrote:
> Tim Blackman wrote:
>> On Jul 31, 2010, at 11:53 PM, Peter Firmstone wrote:
>>
>> <snip>
>>> A RevokeableDynamicPolicy supports the addition or removal of 
>>> PermissionGrant's
>>>     
>> <snip>
>>   
>
>> Hmmm.
>>
>> I remember talking with Bob and Mike Warres about this.  The problem 
>> with removing permission grants is that  when code is granted a 
>> permission, it can very likely squirrel away something -- an object, 
>> or another capability available through the granted permission -- 
>> that will permit it to perform the same operation again without the 
>> JVM checking for the permission again.  Our conclusion was that there 
>> was probably no effective way to implement removal of permission grants.
>>
>> Perhaps there is something about the particulars of what you have 
>> done here to negate this argument -- and I have not had the time to 
>> check the details of your stuff myself to be sure -- but my guess is 
>> that it will be difficult or impossible to do this in an airtight 
>> manner.
>>   
>
> First I'd better point out that this is still an experiment and may 
> not make a release, but I'm glad you've responded, as security is a 
> difficult issue and all help is appreciated.
>
> The SecurityDelegate's I mentioned earlier, are of course a 
> compromise, many existing security guards on existing Java classes are 
> on constructors or methods that return object's, however object's such 
> as OutputStream and the likes, have unguarded methods, so once these 
> objects have been released, the reference can be stored, by what may 
> later become untrusted, and the methods called by untrusted objects.
>
> The SecurityDelegate is a wrapper class that implements the same 
> interface as the guarded object, but once notified of a Permission 
> revocation ensures the next thread to access the guarded object, 
> through the SecurityDelegate has AccessController.checkPermission 
> called again.
>
> Because of the cost of the Permission check, it's too expensive to 
> call on every method invocation.
>
> However there is still a flaw in this, consider for a moment an object 
> protected by a SecurityDelegate, permission's are revoked, the policy 
> notifies all SecurityDelegate's of a revocation, they ensure the next 
> method call rechecks permission.  The flaw is that once the 
> SecurityDelegate, containing the protected object is in untrusted 
> hands, we don't know how many references to it exist.  The next call 
> might have permission, however there is no guarantee that another 
> following will.  The mixing of untrusted and trusted code is the risk.
>
> While it cannot be eliminated entirely, every method requiring 
> protection, should execute a private method something like the 
> following (Constructors and methods excluded for clarity):
>
> class ProtectedOutputStream extends OutputStream implements 
> SecurityDelegate {
>
>    private final OutputStream protected;
>    private volatile boolean check = true;
>    private volatile Thread currentThread = null;
>
>    public void notify(){
>       check = true;
>    }
>
>    private void check(){
>       if ( check == true) {
>          AccessController.checkPermission(perm);
>          currentThread = Thread.currentThread();
>          check = false;
>          return;
>       }
>       if ( currentThread != null ) {
>          if (Thread.currentThread() == currentThread ) {
>             return;
>          }
>       }
>        AccessController.checkPermission(perm);
>        currentThread = Thread.currentThread();
>        return;
>    }
>      public void write(byte[] b) {
>        check();
>        protected.write(b);
>    }
>
> }
>
> Still, I'm not sure if this is enough to protect the object, there are 
> some Thread timing issues I've ignored here, but those aside, I don't 
> want to call the AccessController every invocation, for obvious 
> efficiency reasons.
>
> Thought's and ideas?
>
> Cheers,
>
> Peter.
>
>


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Tim Blackman wrote:
> On Jul 31, 2010, at 11:53 PM, Peter Firmstone wrote:
>
> <snip>
>> A RevokeableDynamicPolicy supports the addition or removal of PermissionGrant's
>>     
> <snip>
>   

> Hmmm.
>
> I remember talking with Bob and Mike Warres about this.  The problem with removing permission grants is that  when code is granted a permission, it can very likely squirrel away something -- an object, or another capability available through the granted permission -- that will permit it to perform the same operation again without the JVM checking for the permission again.  Our conclusion was that there was probably no effective way to implement removal of permission grants.
>
> Perhaps there is something about the particulars of what you have done here to negate this argument -- and I have not had the time to check the details of your stuff myself to be sure -- but my guess is that it will be difficult or impossible to do this in an airtight manner.
>   

First I'd better point out that this is still an experiment and may not 
make a release, but I'm glad you've responded, as security is a 
difficult issue and all help is appreciated.

The SecurityDelegate's I mentioned earlier, are of course a compromise, 
many existing security guards on existing Java classes are on 
constructors or methods that return object's, however object's such as 
OutputStream and the likes, have unguarded methods, so once these 
objects have been released, the reference can be stored, by what may 
later become untrusted, and the methods called by untrusted objects.

The SecurityDelegate is a wrapper class that implements the same 
interface as the guarded object, but once notified of a Permission 
revocation ensures the next thread to access the guarded object, through 
the SecurityDelegate has AccessController.checkPermission called again.

Because of the cost of the Permission check, it's too expensive to call 
on every method invocation.

However there is still a flaw in this, consider for a moment an object 
protected by a SecurityDelegate, permission's are revoked, the policy 
notifies all SecurityDelegate's of a revocation, they ensure the next 
method call rechecks permission.  The flaw is that once the 
SecurityDelegate, containing the protected object is in untrusted hands, 
we don't know how many references to it exist.  The next call might have 
permission, however there is no guarantee that another following will.  
The mixing of untrusted and trusted code is the risk.

While it cannot be eliminated entirely, every method requiring 
protection, should execute a private method something like the following 
(Constructors and methods excluded for clarity):

class ProtectedOutputStream extends OutputStream implements 
SecurityDelegate {

    private final OutputStream protected;
    private volatile boolean check = true;
    private volatile Thread currentThread = null;

    public void notify(){
       check = true;
    }

    private void check(){
       if ( check == true) {
          AccessController.checkPermission(perm);
          currentThread = Thread.currentThread();
          check = false;
          return;
       }
       if ( currentThread != null ) {
          if (Thread.currentThread() == currentThread ) {
             return;
          }
       }
        AccessController.checkPermission(perm);
        currentThread = Thread.currentThread();
        return;
    }
   
    public void write(byte[] b) {
        check();
        protected.write(b);
    }

}

Still, I'm not sure if this is enough to protect the object, there are 
some Thread timing issues I've ignored here, but those aside, I don't 
want to call the AccessController every invocation, for obvious 
efficiency reasons.

Thought's and ideas?

Cheers,

Peter.


Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Peter Firmstone <ji...@zeus.net.au>.
Tim Blackman wrote:
> On Jul 31, 2010, at 11:53 PM, Peter Firmstone wrote:
>
>   
>> A Brief evolution of java.security.Policy providers and Jini Security, please correct me where necessary.
>>
>> Prior to Jini 2.0 security was left up to implementing developers, the standard tools available in Java 1.2 were insufficient.  You had to implement your own SecurityManager.  Or you could define Security policy's in policy files.  The AccessController still consulted the ProtectionDomain, but the ProtectionDomain Permission's were static and unchanging.  You could implement your own policy provider for java.security.Policy, by there was no way you could guarantee updates to the ProtectionDomain with any changes, the ProtectionDomain used the Policy.getPermissions(ProtectionDomain) call to obtain the PermissionCollection from the Policy.
>>
>> To enable the Jini 2.0 Security infrastructure, Sun made changes to Java itself, in Java 1.4  ProtectionDomain's were given a new constructor that enabled the ProtectionDomain to consult an external Policy Provider, and the java.security.Policy gained the implies(ProtectionDomain, Permission) method, allowing the ProtectionDomain to consult the Policy, Jini 2.0 took advantage of this with the DynamicPolicyProvider.
>>     
>
> Yes, I remember that Bob Scheifler did manage to shoehorn some small but important changes into the JDK,  presumably these ones you mention, although I don't remember exactly.
>
>   
>>  This Policy system is a permissive system, that is security was only ever relaxed, it cannot be tightened without restarting the JVM.
>>
>> Now we have taken a new evolutionary step, inspired by Sun's Neuromancer Research Project's additional security needs, for a distributed object registry, we now have a RevokeableDynamicPolicy interface.
>>     
>
> [...]
>
>   
>> A RevokeableDynamicPolicy supports the addition or removal of PermissionGrant's
>>     
>
> Hmmm.
>
> I remember talking with Bob and Mike Warres about this.  The problem with removing permission grants is that  when code is granted a permission, it can very likely squirrel away something -- an object, or another capability available through the granted permission -- that will permit it to perform the same operation again without the JVM checking for the permission again.  Our conclusion was that there was probably no effective way to implement removal of permission grants.
>
> Perhaps there is something about the particulars of what you have done here to negate this argument -- and I have not had the time to check the details of your stuff myself to be sure -- but my guess is that it will be difficult or impossible to do this in an airtight manner.
>   
Thanks Tim, I was hoping someone would bring this up, it's something 
I've been trying to find a solution for.

I've demonstrated that Permission's can be revoked from the Policy, so 
that AccessController.checkPermission returns an AccessControlException, 
however there are caveats, with Permission's that only guard references, 
as you mention, if the client keeps a reference then the guarded object 
has escaped.  I need to create a list of Permission's that cannot safely 
be revoked.  Many shouldn't be granted to dynamically downloaded code, 
even if we trust it, such as RuntimePermission "getClassLoader"

In order to be able to make effective use of a revokeable policy, one 
must use a wrapper object (a Security Delegate) to encapsulate an object 
and place a AccessController.checkPermission call prior to effecting the 
call.

However some Permission's can be revoked, take for instance a 
FileInputStream, once it reaches the end of file, a new FileInputStream 
must be created to re read the file.  So if at the time of creation the 
client was trusted to read the stream, then at a later stage it wasn't, 
there is the possibility that the client has kept a copy of the data, 
but if that client has a copy of the data, we need to make sure it can 
no longer communicate with the outside world, so it can't be 
transmitted, until trust has been re-established.

For example, you could use a SecurityDelegate, perhaps called a 
CheckedOutputStream, that encapsulates an OutputStream, for networks and 
files.  The CheckedOutputStream can internally contain a volatile 
variable which is checked every time a method on the object is called, 
if false, the method executes, if true, prior to calling the method on 
the encapsulated OutputStream, it calls 
AccessController.checkPermission, if it passes, it set's the volatile 
variable back to false.  These SecurityDelegate's, would need to be 
registered with the policy, perhaps indirectly via 
net.jini.security.Security, every time a permission is revoked, the 
SecurityDelegate's would be notified to set their internal volatile 
boolean variable, check == true.

interface SecurityDelegate {
void notify();
}

public class CheckedOutputStream extends OutputStream implements 
SecurityDelegate{
...
}

In this case we wouldn't directly grant a "write" to the client, since 
it could easily create it's own output stream and keep the reference, 
but if we have our own wrapped by a SecurityDelegate, then this is a 
different story, we grant our code the FilePermission "write" some file, 
and we must requre a different Permission the client have to utilise our 
CheckedOutputStream.

We could use such a SecurityDelegate for the OutputStream returned by 
net.jini.jeri.OutboundRequest.getRequestOutputStream, the same could be 
done for an InputStream.

This has got me thinking about why Interfaces are essential for Service 
API, including methods and parameters, because interfaces allow us to 
implement SecurityDelegate's for our Service API.  Different code can 
use SecurityDelegates to allow trust, that's revokeable.  Once bitten 
twice shy?

We can ensure that the Service API exists in a parent ClassLoader and 
the services, proxy's and client's exist in separate Child 
ClassLoader's, they only use Service API to communicate.  That way 
proper separation is maintained.

I've been thinking about using Entry's for declaring the Permission's a 
Service requires, to enable the client to decide if the Permission's are 
acceptable to grant, and if so, restrict the permission's to only those 
declared (or a subset), after trust has been established.
> By the way, when working on Neuromancer, the team working on that project decided that assigning permissions to classloaders and principals was too hard.  We didn't make much progress on security concerns actually, but our idea was that we would treat the entire virtual machine as a single capability zone -- no different permissions for different code, threads, principals, etc., within a single Java VM.  Our hope was to keep things simple, an idea whose rightness seemed to be borne out by the complexity of developing Jini 2.0 and the difficulties that the Jini team had in plugging security holes in the model immediately afterwards (an effort I heard about but did not participate in).
>
> - Tim
>   
Security isn't easy is it?  I'd be interested to hear about the 
Neuromancer security model, I wasn't aware of it.  I've been thinking 
about a code commons where developers can share their code, and sign 
each other's jar files after review.  Much software downloaded today 
only uses sha checksum's to ensure it is safe.

Cheers,

Peter.

Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap

Posted by Tim Blackman <ti...@gmail.com>.
On Jul 31, 2010, at 11:53 PM, Peter Firmstone wrote:

> A Brief evolution of java.security.Policy providers and Jini Security, please correct me where necessary.
> 
> Prior to Jini 2.0 security was left up to implementing developers, the standard tools available in Java 1.2 were insufficient.  You had to implement your own SecurityManager.  Or you could define Security policy's in policy files.  The AccessController still consulted the ProtectionDomain, but the ProtectionDomain Permission's were static and unchanging.  You could implement your own policy provider for java.security.Policy, by there was no way you could guarantee updates to the ProtectionDomain with any changes, the ProtectionDomain used the Policy.getPermissions(ProtectionDomain) call to obtain the PermissionCollection from the Policy.
> 
> To enable the Jini 2.0 Security infrastructure, Sun made changes to Java itself, in Java 1.4  ProtectionDomain's were given a new constructor that enabled the ProtectionDomain to consult an external Policy Provider, and the java.security.Policy gained the implies(ProtectionDomain, Permission) method, allowing the ProtectionDomain to consult the Policy, Jini 2.0 took advantage of this with the DynamicPolicyProvider.

Yes, I remember that Bob Scheifler did manage to shoehorn some small but important changes into the JDK,  presumably these ones you mention, although I don't remember exactly.

>  This Policy system is a permissive system, that is security was only ever relaxed, it cannot be tightened without restarting the JVM.
> 
> Now we have taken a new evolutionary step, inspired by Sun's Neuromancer Research Project's additional security needs, for a distributed object registry, we now have a RevokeableDynamicPolicy interface.

[...]

> A RevokeableDynamicPolicy supports the addition or removal of PermissionGrant's

Hmmm.

I remember talking with Bob and Mike Warres about this.  The problem with removing permission grants is that  when code is granted a permission, it can very likely squirrel away something -- an object, or another capability available through the granted permission -- that will permit it to perform the same operation again without the JVM checking for the permission again.  Our conclusion was that there was probably no effective way to implement removal of permission grants.

Perhaps there is something about the particulars of what you have done here to negate this argument -- and I have not had the time to check the details of your stuff myself to be sure -- but my guess is that it will be difficult or impossible to do this in an airtight manner.

By the way, when working on Neuromancer, the team working on that project decided that assigning permissions to classloaders and principals was too hard.  We didn't make much progress on security concerns actually, but our idea was that we would treat the entire virtual machine as a single capability zone -- no different permissions for different code, threads, principals, etc., within a single Java VM.  Our hope was to keep things simple, an idea whose rightness seemed to be borne out by the complexity of developing Jini 2.0 and the difficulties that the Jini team had in plugging security holes in the model immediately afterwards (an effort I heard about but did not participate in).

- Tim