# Security Requirements on Activation Group Descriptors used with `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`.

## Introduction and Rationale

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:

- The group class name in the descriptor is either `null` (indicating the default) or specifically `org.apache.river.phoenix.ActivationGroupImpl`.
- For each property in the descriptor's property overrides, the calling context is granted the permission `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).
- If the descriptor contains a non-`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 configOptions

where 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:

- Although in many cases all or part of the command line will be case insensitive (e.g. host names, files, and command paths on some operating systems), the checks `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`.
- Because `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.html

and

         http://java.sun.com/j2se/1.4/docs/tooldocs/windows/rmid.html

### How to achieve the behavior of `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=none

which 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.

### How to assign and maintain security controls

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:

1. Start with an empty `rmid.policy`.
2. Run `rmid -J-Djava.security.policy=rmid.policy`.
3. Run a client program to activate an object (you might need to register the object if you haven't already).
4. Catch and `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`".

5. Look in the `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";
          };

6. Kill the `rmid` process (`rmid -stop`) and return to step 2.

### Specific examples for some River technology-enabled service implementations

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";
      };

Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.