river-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Peter Firmstone <j...@zeus.net.au>
Subject Untrusted Networks: Security, Policy's and Services - Peer review of code needed.
Date Wed, 21 Jul 2010 23:54:34 GMT
If your interested, I could use some peer code review.  I recently 
created ConcurrentDynamicPolicyProvider, motivated by Gregg's 
identification of a DynamicPolicyProvider concurrency bottleneck, here's 
some background:

Previous Policy implementations, including DynamicPolicyProvider  (the 
original implementation was renamed to 
org.apache.river.imp.security.cdc.DynamicPolicyProviderImp) are a 
bottleneck to multi threaded performance.  Every check via the 
AccessController or SecurityManager results in checks of every 
ProtectionDomain within the context of the current thread (or defined 
AccessControlContext, which may of course be expanded or changed by the 
DomainCombiner).  implies(Permission) is called on each 
ProtectionDomain, the ProtectionDomain (if created with the dynamic 
constructor) then asks the Policy, if it implies(Permission), if it 
does, it returns true, if false, it checks it's internal 
PermissionCollection.  This makes the Policy provider an obvious point 
for lock contention between threads.  And all this is just for one 
security check!

The new ConcurrentDynamicPolicyProvider also implements a new interface 
called RevokeableDynamicPolicy, which supersedes DynamicPolicy.  
DynamicPolicy is an interface for Policy Providers to implement that 
allow dynamic permission grants, or more accurately, the delay of 
permission grants until runtime, it's used in the proxy verification 
process (see net.jini.security.Security). DynamicPolicy grant 
Permission's to a ClassLoader domain, this grant may cover multiple 
ProtectionDomain's.  Dynamic grant's could not be revoked, trust once 
granted, couldn't be removed.

One of our goals for Apache River is to continue the push into untrusted 
networks that Jini 2.0 started.  One of the problems that Project 
Neuromancer highlighted was that for a remote reference implementation 
that utilised a distributed hashtable based object registry, there was 
an issue with proxy trust, once a proxy's server has moved, a proxy can 
no longer be trusted (for the remote reference proxy implementation that 
is), but the proxy itself had to be given a thread of control to 
discover the new location of it's referent (server).

This might seem peculiar, but the reason is that the server is involved 
with trust verification; the client asks the server if it trusts the 
proxy.  The client can authenticate the server and the server can 
authenticate the client, the connection having been severed requires the 
process to repeat itself, this cannot be done without first revoking trust.

One could change the AccessControlContext, by adding a ProtectionDomain 
that had limited Permission, then run a method on the proxy to allow it 
to retrieve a new referent, but it would be a hack, it isn't the 
solution if the proxy is used from another thread, it still has elevated 
permissions.

Trust for the client can be broken down into two components:

    * Do I trust the downloaded code? (Proxy Verification)
    * Do I trust the Service's Principal? (Authentication)

The foundation of RevokeableDynamicPolicy, is that trust may change at 
runtime, due to many factors, such as that mentioned above, or it may be 
due to a vulnerability found in a CodeSource, but for whatever reason, 
the ability to Grant some trust as well as Revoke it is important.  
(Note in order to be able to revoke, the Policy must not be allowed to 
provide the dynamic permission grant's PermissionCollection's to the 
ProtectionDomain, otherwise these will become merged into the 
ProtectionDomain's private PermissionCollection, resulting in implies() 
returning true by the ProtectionDomain, even though the Policy may have 
returned false).
 
Dynamic Grants, are currently applied to a ClassLoader domain, where a 
proxy is loaded, so they may cover multiple ProtectionDomain's within 
that ClassLoader space.  I've decided to expand the scope of grant 
possibilities to allow runtime Permission grant's to apply:

   1. To a specific CodeSource, no matter what it's ClassLoader,
   2. A ProtectionDomain (more accurately, a CodeSource within a
      Particular ClassLoader **),
   3. Or Certificate based grant's, which require certain developers
      having signed the CodeSource, no matter what CodeSource.

The above grants can all be restricted to a set of Pricipal[]'s, for 
instances where Authentication is also required.

**At the time of the AccessController Permission check, the 
SubjectDomainCombiner creates copies of the ProtectionDomain's from the 
stack of the current thread's context, so the actual ProtectionDomain 
grant also applies to ProtectionDomain's with an identical CodeSource 
and ClassLoader.

In a RevokeableDynamicPolicy, the dynamic grant is known as a 
PermissionGrant, which is an interface for which many implementations 
are permitted to exist.  The code involved in the PermissionGrant must 
also be able to satisfy Permission checks, before the grant will be 
accepted by the Policy implementation for obvious security reasons.

It is the implementation of PermissionGrant which determines both the 
scope and how the grant applies.

I created another Policy, called ConcurrentPolicyFile, to replace the 
standard file based PolicyFile provided by the JRE.  To make it easier I 
borrowed some code from Harmony, used to parse Java policy files, an 
interface called PolicyParser.  DefaultPolicyParser, has been refactored 
to generate PermissionGrant's from the standard java policy file syntax 
which ConcurrentPolicyFile utilises.  Custom Policy Parsers and Scanners 
may be written by implementers also, for example to parse the OSGi 
bundle Permission's text file syntax. 

The PolicyParser may also retrieve policy files via URL from across the 
network, enabling centralised deployment of dynamic grant security 
policies if required.

This allows another new possibility, that of utilising the existing Java 
policy file syntax, to store the Dynamic PermissionGrant's for the proxy 
in a jar file.  By permitting the standard java policy file syntax, it 
also allows the proxy to utilise other third party jar files or 
libraries and specify the Permissions required for each of those too.

Furthermore, PermissionGrant's could be utilised as Service Entry's to 
advertise the Permission client's are expected to grant, a client can 
then decide if the PermissionGrant is acceptable (by querying it's 
Permission's) before unmarshalling a proxy ,using the new 
StreamServiceRegistrar with delayed unmarshalling ( the implementation 
of StreamServiceRegistrar pending interface peer review).  We can 
implement Apache River framework utility classes that create the Entry 
from the jar file for Service deployment.

A client having decided that the Permission's required by a Service, can 
then go through the process of Proxy Verification, knowing precisely the 
grant's required, the client can create a new instance of the 
PermissionGrant with additional Principals and make the Permission's 
specific to the ClassLoader and CodeSources, the proxy will be using.  
At any time, the client may revoke the permission, it may do this 
directly after discarding the service, or it may revoke some permission 
based on the discovery of a new security vulnerability, thereby 
eliminating it.

In essence, the developer decides the required Permission's, the 
deployment framework obtains the PermissionGrant's from the jar's policy 
file and the client decides if they are acceptable.

I also recall Gregg needing a method of determining the Constraint's a 
Service requires, perhaps Constraints could be advertised via a 
Constraint Entry, to allow filtering of Services which have restraint's 
that cannot be satisfied.

To summarise recent discussions regarding Entry's we could have standard:
    Codebase Entry's (as per Patrick's suggestion for provisioning)
    PermissionGrant Entry's
    Constraint Entry's

Any suggestions for the Entry format's would be most welcome.

This renewed focus on Security is intended to make it easier to deploy 
Services over the internet.  If Apache River is to succeed on the 
internet, it will need to be robust from a security perspective, to have 
a significant advantage in order to replace current protocol based 
internet applications.

Apache River won't restrict internet based applications to Java.  
Perhaps if we can succeed in making River run on the internet, we could 
create a River Service Browser Firefox Plugin.

There's plenty of new code in need of peer review, if you have some free 
time to assist, please SVN the latest source and browse under 
trunk/src/org/apache/river/

Best Regards,

Peter Firmstone.



Mime
View raw message