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 <[email protected]> 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 <[email protected]> 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.



Reply via email to