Thanks Gregg,
It's time to change how we use ClassLoaders and ProtectionDomains, by
splitting apart concerns of Visibility and Security. Forget about
Preferred Classes for a moment.
I'm effectively isolating downloaded code's Permissions, by placing each
codebase within it's own ProtectionDomain, typically when network
classes are given their own ClassLoader for isolation, this isolation is
provided by the ProtectionDomain. But unlike an applet, I want the
Service API code to be visible by all Application and Proxy Classes, so
it must go into the same Parent ClassLoader for visibility.
Since the Service API code can't see Application or Proxy classes, only
platform classes and other Service API classes, I'm also leveraging
ClassLoader visibility for some additional security benefit.
I want the security isolation of an applet the ProtectionDomain
provides, but not the visibility isolation an individual ClassLoader
provides for Service API.
By default I don't want any network downloaded Service API code to have
any permission whatsoever. I had even considered eliminating the
possibility of granting any permission to Service API, by using a static
ProtectionDomain
The ClassLoader structure proposed, is like this:
System ClassLoader (Java)
|
Extension ClassLoader (Java Extensions, jsk-policy.jar, etc)
|
Jini Platform ClassLoader ( Apache River, Application
Service API)
|
_______________|_______________________________________
| | | |
Application ClassLoader Proxy CL Proxy CL Proxy CL
(Service's, Apps, Libraries)
Currently we dynamically grant permissions to a ClassLoader space, with
a prerequisite set of Principals.
I'm in the process of adding new grants, in addition to ClassLoader
grants and Principal grants:
ProtectionDomain grants - useful for proxy instance specific grants.
CodeSource grants - specific to a CodeSource, may be shared by many proxy's
Certificate[] grants - specific to a Certificate chain can apply to many
CodeSource's
We will also be able to combine the grants, this particular combination
will be extremely useful:
Certificate[] and Principal[] grants
This will apply to situations that combine developers we trust and
Principals we trust.
The ClassLoader structure above is relatively simple, it allow's smart
proxy's to have complete visibility and security isolation, from
application and Service API code. In effect we can have one Service API
loaded in the Jini Platform ClassLoader space, an application using a
proxy, it can't see directly, through the Service API.
Currently we're extending the jar conventions of service construction to
include:
Implementation jar: service.jar (Application ClassLoader
shared space)
Specification/API jar: service-api.jar (Jini Platform ClassLoader
shared space)
Download jar: service-dl.jar (Proxy ClassLoader
isolated space)
The only time proxy's can share a ClassLoader is if their Principals and
CodeSource is identical, because not only will we be sharing the
ClassLoader, but the ProtectionDomain also.
I haven't figured out how to an Application can be started in a child
ClassLoader yet, so any help you can provide would be much appreciated.
Hope this helps clarify things a bit more.
Cheers,
Peter.
Gregg Wonderly wrote:
My understanding/recollection of what currently happens, is that any
class that the client already has loaded, will be used by the proxy as
long as it is not preferred, because of the classloader hierarchy.
This means, that non-preferred classes that a client has in the jars
of its classpath, have been assumed to be safe, and having them in the
classpath indicates, in a sense, trust in the content and activities
of the code in such jars.
I don't think it's a good idea to "load" classes from network
downloaded jars into the system class loader arbitrarily.
The convenience of having a lot of these things automated is a good
thing, but I think the default must be that network downloaded code
has no permissions explicitly granted by placing that code into a
classloader that is not associated with a thread of execution that is
based on the downloaded codes SecurityContext.
Gregg Wonderly
Peter Firmstone wrote:
Actually this might cause a problem if the proxy has been granted
greater priviledges than a calling thread's Principal (a user)
running with a lesser set of Permissions than the proxy, it causes
all SecurityManager checks by the proxy to throw Security Exceptions.
Does this mean restricting the PermissionDomain of the *-api.jar is
the wrong thing to do?
Should it be allowed DynamicPolicy grant's?
Perhaps it should be given the same Permissions as the most
privileged proxy instead, using the fore mentioned ClassDep tool to
verify the *-api.jar files don't depend on any security sensitive
classes prior to loading?
When performing dynamic grants to a class, get the classes interfaces
and do the dyanamic grant's on them too.
What do you think?
Peter Firmstone wrote:
Actually on Second thoughts, this security concern is unfounded
(paranoia perhaps, security is hard!), the ProtectionDomain of the
*-api.jar will be on the execution stack, the actual Permissions
will be those common to all ProtectionDomain's on the caller's
stack, so therefore having a ProtectionDomain with no permissions
assigned to a *-api.jar will cause the calling thread to have no
permissions (as the proxy sees it).
Therefore a proxy, if it is to utilise it's own permission grants,
it will need to use AccessController.doPrivileged()
That sounds better.
Anyway there will be no Permissions granted to any *-api.jar, ever
as I'm going to utilise the pre java 1.4 ProtectionDomain
constructor, that specifically prevents and excludes dynamic Policy
grants. It won't even consult the Policy.
I'm modifying DynamicPolicy to include grants by Certificate[], an
*-api.jar that is signed by a trusted certificate chain, still wont
gain any permissions. Can anyone see that as a problem?
The *-api.jar classes must not have dependencies on anything outside
of the Jini Platform, Java Platform or other *-api.jar classes. The
reason for this restriction, is if Someone want's to use OSGi or has
a dependency on another version of a library, the *-api.jar
importing an incompatible version, would obscure it's visibility and
cause a runtime error.
These restrictions shouldn't cause a problem for people as they're
easy to design around. It makes security simpler for developers
too. - You don't have to worry about the security of the code in
*-api.jar
Cheers,
Peter.
Peter Firmstone wrote:
Dennis Reedy wrote:
Chris, Dennis & Greg, your all spot on with the Service-spec.jar,
I'd like to add something to the jar Manifest of these Service
Interfaces, to ensure River loads it into the top level
ClassLoader. Any suggestions?
Why not just support the convention instead of adding configuration?
Ok.
There is one Security Concern that I will have to address with this
Approach:
ClassLoader Structure:
System ClassLoader
|
Extension ClassLoader (incl jsk-policy.jar)
|
Jini Platform ClassLoader (incl jsk-platform.jar,
*-api.jar)
|
_______________|________________
| |
Application ClassLoader Proxy ClassLoader's
The *-api.jar files will be placed into Jini Platform ClassLoader,
so the only files visible will be the jini platform classes, java
platform classes and any other *-api.jar classes.
The *-api.jar classes will have their own ProtectionDomain's
without any Permissions.
However this isn't enough to protect us from code that might be
included in the *-api.jar's that use the calling Threads
Permissions to perform security violating actions.
Due to these security concerns, we need to place some restrictions
on the API classes:
1. They must not be allowed to depend on anything other than Jini,
Java Platform and other Service-api.jar's
2. They must not be allowed to depend on any Platform classes that
could cause a Security Violation.
The Service API code really needs to be verified before loading, to
ensure that it does not utilise any platform classes that perform
security sensitive operations.
The ClassDep tool can run a Dependency Analysis on any *-api.jar to
ensure that no security sensitive classes are accessed, prior to
loading.
There is some residual risk that as the Java platform evolves, new
classes that perform Security Sensitive actions will be added,
which means the list of restricted classes will need to grow over
time.
Could the list itself be contained in a Maven Repository, we could
sign, such a list.
Thoughts?
Peter.