Normally the client should be written in such a way that it can be configured to allow for variations in the steps used to prepare a proxy for subsequent use. The usual way is to obtain a {@link net.jini.security.ProxyPreparer} from a {@link net.jini.config.Configuration}, using as a default value a {@link net.jini.security.BasicProxyPreparer} that simply returns the proxy. The client can then be configured at deployment time to perform whatever steps are desired.
Configuration config = ...; SomeService proxy = ...; ProxyPreparer preparer = (ProxyPreparer) config.getEntry( "MyClient", "someServicePreparer", ProxyPreparer.class, new BasicProxyPreparer()); proxy = (SomeService) preparer.prepareProxy(proxy);
{@link net.jini.security.BasicProxyPreparer} can be used to perform all combinations of these three common steps of proxy preparation.
The client needs some way to decide that it trusts a proxy. Rather than
mandating any specific mechanism(s), a pluggable framework is provided.
The client calls
{@link net.jini.security.Security#verifyObjectTrust
Security.verifyObjectTrust}, passing the proxy and a caller context collection
that typically contains a
{@link net.jini.core.constraint.MethodConstraints} instance.
This method uses whatever
{@link net.jini.security.TrustVerifier} instances have been
configured to determine if the proxy can be trusted; if any verifier says
that it trusts the proxy, then the proxy is assumed to be trusted. If no
verifier trusts the proxy, a SecurityException
is thrown. The
caller context collection contains whatever context information might be
required by verifiers; a MethodConstraints
element in the
collection is typically used to control any calls to the remote server that
are made by verifiers.
A baseline for deciding a proxy can be trusted is to examine the proxy and all of its constituent objects, excluding the client constraints, to ensure that they are all instances of locally trusted (typically, not downloaded) classes, containing trusted data. For example, {@link net.jini.jeri.BasicJeriTrustVerifier} provides this baseline for basic dynamic proxies of remote objects exported to use Jini extensible remote invocation (Jini ERI), in conjunction with {@link net.jini.constraint.ConstraintTrustVerifier}, which verifies the standard constraints. {@link net.jini.security.proxytrust.ProxyTrustVerifier} depends on this baseline as a bootstrap, but ultimately asks the server if it trusts the proxy.
The client constraints are excluded from the trust verification of a proxy because it is assumed that the caller will subsequently either replace them with its own constraints that are known to be trusted, or has independently decided to trust the existing client constraints.
Note that trust verification does not prevent denial-of-service attacks. If a proxy that uses untrusted code is unmarshalled, the untrusted code can execute before trust verification takes place. In deployments where the trusted sources of downloaded code are known in advance, the {@link net.jini.loader.pref.RequireDlPermProvider} can be used to prevent code downloading from untrusted sources.
Dynamic grants require support from the {@link java.security.Policy} provider. The {@link net.jini.security.policy} package provides a standard interface for security policy providers capable of dynamic permission grants, as well as a set of composable security policy providers supporting dynamic permission grants and aggregation of multiple security policies in a single virtual machine.
{@link net.jini.security.Security#grantSupported Security.grantSupported} can be used to determine if the installed security policy supports dynamic grants, and {@link net.jini.security.Security#grant Security.grant} can be used to make dynamic permission grants. The typical use is to grant permissions to the class loader of the proxy object's top-level class, coupled with the principals of the currently executing subject:
SomeService proxy = ...; Permission[] grants = ...; Security.grant(proxy.getClass(), grants);In order to dynamically grant a permission, the client itself must have the corresponding {@link net.jini.security.GrantPermission}. Because the dynamic grant is coupled with the current subject, proxy code must assume that actions executed using {@link java.security.AccessController#doPrivileged AccessController.doPrivileged} will not have the granted permissions (because that method executes the action with no subject); {@link net.jini.security.Security#doPrivileged Security.doPrivileged} should be used instead to maintain the current subject and thereby enable privileges in a way that retains the granted permissions.