phoenix
or rmid
Some Jini network technology-based services may be activatable and
as such will require the use of an activation daemon. The standard
Java(TM) 2 Standard Edition (J2SE(TM)) Remote Method Invocation (Java RMI) activation daemon is
rmid
. The Apache River release
provides phoenix
, an alternative
configurable implementation of a Java RMI activation daemon.
This note describes the security requirements to specify an
activation group descriptor (of type
java.rmi.activation.ActivationGroupDesc
) for use with
activatable objects handled by either phoenix
or
rmid
.
Note: We encourage developers to transition from rmid
and to use its configurable alternative phoenix
instead. The phoenix
activation daemon supports
configurable exporters for the remote objects that are part of the
activation system and also supports flexible access control policies
for the activation system. See the org.apache.river.phoenix
package documentation for details on configuring and starting
phoenix
.
An activation daemon, such as phoenix
or
rmid
, executes subprocesses which run virtual machines
for the Java platform (VMs). It does this to
keep activation groups separate from one another, and to allow the
use of special VM engines and options for different activation
groups.
An activation group is specified by an activation group descriptor
that describes the information necessary for an
activation daemon to start the activation group. An application
can register an activation group descriptor (of type
ActivationGroupDesc
) directly with the
ActivationSystem
of either phoenix
or
rmid
by calling the ActivationSystem
's
registerGroup
method. Alternatively, an activation
group can be registered via the service starter API, by invoking
the create
method on a
org.apache.river.start.SharedActivationGroupDescriptor
instance. As a side effect of this invocation, an
ActivationGroupDesc
is created and registered with the
ActivationSystem
as above.
An activation group descriptor used to start an activation
group affects the subprocess environment, command,
command options, and arguments for starting the activation group,
and is flexible enough that with an insecure security policy, any
command, even a non-Java-platform command or program, can be run
under the guise of starting the group. There is clearly a need
for a security control to prevent unauthorized specification of an
activation group descriptor and hence unauthorized execution
of a command. Note that whether an activation group is
registered directly with the ActivationSystem
or
registered indirectly as a result of the
SharedActivationGroupDescriptor.create
method, the
security requirements outlined below are the same for each situation.
The activation daemons phoenix
and rmid
have different schemes for preventing an unauthorized
activation group descriptor from being used. The phoenix
activation daemon may be configured with an access control policy
on its ActivationSystem
that prevents an unauthorized
ActivationGroupDesc
from either being registered via the
ActivationSystem.registerGroup
method or being
modified via the ActivationSystem.setActivationGroupDesc
method. The rmid
activation daemon has a slightly
different control point: it verifies that an
ActivationGroupDesc
is authorized (according to
rmid
's security policy) just before
using it to create an activation group. The details of each access
control model are discussed in turn below. Although
phoenix
and rmid
have different points in
which they check permissions for such access, the basic permission
requirements are the same. Also, the permission types that
phoenix
uses are modeled after the permission types
used by rmid
(ExecPermission
and
ExecOptionPermission
); each permission type has the
same class name, but is in a different package.
phoenix
Since applications need to configure the access control policy for
registering and updating an activation group descriptor with the
ActivationSystem
, the phoenix
implementation
includes a special net.jini.export.Exporter
implementation for the ActivationSystem
,
org.apache.river.phoenix.SystemAccessExporter
, that allows
the ActivationSystem
's access control policy to be
configured. The phoenix
implementation also includes a
net.jini.jeri.InvocationLayerFactory
implementation,
org.apache.river.phoenix.SystemAccessILFactory
, to use with
net.jini.jeri.BasicJeriExporter
. This
InvocationLayerFactory
implementation supports the same
configurable access control policy for the
ActivationSystem
.
By default, phoenix
's ActivationSystem
is
exported via BasicJeriExporter
with a
SystemAccessILFactory
that produces a
net.jini.jeri.Dispatcher
that enforces an access control
policy on calls to the registerGroup
and
setActivationGroupDesc
methods. The default access
control policy is specified by the
org.apache.river.phoenix.DefaultGroupPolicy.checkGroup
method.
This default group policy requires the following when an
ActivationGroupDesc
is being recorded via the
registerGroup
or setActivationGroupDesc
method:
null
(indicating the default) or specifically
org.apache.river.phoenix.ActivationGroupImpl
.
org.apache.river.phoenix.ExecOptionPermission
with a target
of the form "-Dname=value" (where name is the
name of the property and value is the value of the property).
null
command
environment, the calling context is granted the permission
org.apache.river.phoenix.ExecPermission
with the command path
as the target. Also, for each command option, the calling context is
granted ExecOptionPermission
with the option as a target.
These permissions must be specified in phoenix
's security
policy file, indicated on the command line when starting up
phoenix
:
java -J-Djava.security.policy=configDir/phoenix.policy -J-Djava.rmi.server.codebase=codebasePath [otherOptions] -jar installDir/lib/phoenix.jar configOptionswhere configDir is the directory containing
phoenix
's security policy file, codebasePath is a
codebase path (space-separated list of URLs that serves up
phoenix
's download JAR file
(installDir/lib/phoenix-dl.jar
),
otherOptions are any other standard options for the
java
command, and configOptions are the options
(typically a filename or URL) of a phoenix
configuration.
Some things to keep in mind when defining permissions
for phoenix
are:
ExecPermission
and
ExecOptionPermission
perform are case sensitive, so it is
important to make sure the case of the targets of the
ExecPermission
s and ExecOptionPermission
s
match the case of the command line elements in the
ActivationGroupDesc.CommandEnvironment
.
phoenix
can be configured to support
authentication and access control, it may be reasonable to grant more
broad ExecPermission
s and
ExecOptionPermission
s to a narrow set of trusted
subjects.
Note that the permission class names ExecPermission
and ExecOptionPermission
are the same as those used for
rmid
's access control policy except for the package name,
which, for phoenix
, is org.apache.river.phoenix
.
The examples given for rmid
below are the same as for phoenix
except that the package
name for the permissions needs to be changed to
org.apache.river.phoenix
.
rmid
In releases of the Java 2 SDK prior to 1.2.2_006, the need to
control the security of an ActivationGroupDesc
was
satisfied by the same stopgap measure used for
rmiregistry
access control: if the caller was running
on the same host as the remote object, then all access was allowed;
otherwise, no access to sensitive functions was allowed.
Registering or changing an ActivationGroupDesc
is an
example of a sensitive function; activating an object is an example
of a non-sensitive function that anyone can perform. This security
mechanism was predicated on the assumption that unprivileged code is
not allowed to connect to port 1098 on the executing host.
However, that assumption is no longer as certain, and a
stronger security model has been developed. In this new model, an extra security control has been added:
before being executed, the command and options requested by an
ActivationGroupDesc
are checked by the security manager
of rmid
, which then references the security policy file
that was set for rmid
from the command line (for
authorization).
An "exec policy" is a Java class employed by the Java RMI activation
daemon to check commands and command-line options used to launch a
VM when deciding whether or not an ActivationGroupDesc
is authorized. The exec policy is adopted when rmid
is
started. The value of the sun.rmi.activation.execPolicy
property dictates the policy that rmid
uses to
determine whether or not the information in an
ActivationGroupDesc
may be used to launch a VM
for an activation group. Some exec policies are built into
rmid
, and rmid
can be instructed to use
one of them by defining a property that specifies a built-in policy
instead of the exec policy's class name.
In the exec policy represented by the value none
(discussed later, in the section, How to achieve the
behavior of rmid
released in previous versions of the
Java 2 SDK), the new security control is disabled, and
execution is compatible with the rmid
found in previous
releases of the Java 2 SDK.
In the default exec policy (discussed in the section, How to assign and maintain security
controls), the authorized commands and options are encoded
in the security policy file, which gets set using the
"-J-Djava.security.policy=...
" option on the
rmid
command line. Each command and option string in
each ActivationGroupDesc
is separately authorized or
unauthorized. While there is no authentication of a caller (an
authorized option is authorized for everyone's use), there is still
a check to ensure that the registration of the
ActivationGroupDesc
originates from the local host.
The exec policy can be set to the name of another class that
rmid
will instantiate; the exec policy object will then
be expected to perform the security check on
ActivationGroupDesc
s at group activation time. This
option is the most flexible, but discussion of its use is beyond the
scope of this document. See the rmid
tool documentation
(manpage) for details, at:
http://java.sun.com/j2se/1.4/docs/tooldocs/solaris/rmid.htmland
http://java.sun.com/j2se/1.4/docs/tooldocs/windows/rmid.html
rmid
released in
previous versions of the Java 2 SDK
The new security control can be effectively bypassed by assigning an
exec policy that permits all commands and all options. There is a
short way to specify this behavior by setting the exec policy value
to none
:
rmid -J-Dsun.rmi.activation.execPolicy=nonewhich will run
rmid
in the normal way, but will
automatically authorize all ActivationGroupDesc
s
registered from the local host.
For the user who can control the rmid
host to guarantee the
assumptions of Java 2 SDK, v1.2.x, or who is simply impatient with the new
security control, the none
keyword is a convenient way to get
rmid
up and running quickly. Remember that this is a way to
sacrifice security for temporary convenience, and therefore is not
recommended.
The default exec policy is used if the
sun.rmi.activation.execPolicy
system property is not
set for the rmid
tool, or if the value of the
execPolicy
property is set to default
. In
this case, a security policy file must be specified on
rmid
's command line.
In the default case, the java.security.policy
system
property must be set for rmid
. For example on a Microsoft Windows platform:
rmid -J-Djava.security.policy=configDir\rmid.policy
The file named as the value of this property should contain a Java 2 platform security policy file. An example which has appropriate syntax for the Microsoft Windows platform is:
grant { // permissions granted to everyone permission com.sun.rmi.rmid.ExecPermission "C:\\jdk\\bin\\java_g"; permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=configDir\\lookup.policy"; };
The two permission types shown above, ExecPermission
and ExecOptionPermission
, are the only two security
permissions relevant to the new security control. Notice that they
are granted to all codebases (grant {
): you should
always be cautious when granting permissions to all codebases,
because these permissions are also granted to unknown downloaded
code. See the rmid
reference
pages for a complete description of the syntax for these
permissions.
The straightforward way to build up an effective
rmid.policy
is:
rmid.policy
.
rmid -J-Djava.security.policy=rmid.policy
.
printStackTrace
the
AccessControlException
that gets
thrown by the activation attempt (usually the client program will
do this anyway).
Note on restartable Activatable
objects: Some
activatable objects are activated automatically by
rmid
(if
ActivationDesc.getRestartMode()
is
true
); in this case, rmid
will
printStackTrace
the exception to its
System.err
, preceded by the English-language
message "rmid: unable to restart service
".
AccessControlException
to see the failed exception.
For example, the exception:
java.security.AccessControlException: access denied (com.sun.rmi.rmid.ExecOptionPermission -cp)
means that the permission you need to add to the security policy
file is:
grant { permission com.sun.rmi.rmid.ExecOptionPermission "-cp"; };
rmid
process (rmid -stop
)
and return to step 2.
Here's an example of an rmid.policy
which will run Reggie (the
contributed River lookup service implementation from Sun Microsystems) in the Solaris(TM) Operating System (Solaris OS):
grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=configDir/lookup.policy"; permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.rmi.server.codebase=*"; permission com.sun.rmi.rmid.ExecOptionPermission "-cp"; permission com.sun.rmi.rmid.ExecOptionPermission "installDir/lib/reggie.jar"; };
Here's an example to run Mahalo (the contributed River transaction manager service implementation from Sun Microsystems) in the Solaris OS:
grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=configDir/txn.policy"; permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.rmi.server.codebase=*"; permission com.sun.rmi.rmid.ExecOptionPermission "-cp"; permission com.sun.rmi.rmid.ExecOptionPermission "installDir/lib/mahalo.jar"; };
Here's one for FrontEndSpace
(a contributed implementation of
JavaSpaces technology from Sun Microsystems) in the Solaris OS:
grant { permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=configDir/books.policy"; permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.rmi.server.codebase=*"; permission com.sun.rmi.rmid.ExecOptionPermission "-Xbootclasspath/p::installDir/lib/outrigger.jar:installDir/lib/transient-outrigger.jar:installDir/lib/pro.zip"; };