Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-5029435

RMI should provide a protected registry implementation

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Unresolved
    • Icon: P4 P4
    • None
    • 1.4.2
    • core-libs
    • Fix Understood
    • x86
    • windows_xp

      Name: rmT116609 Date: 04/08/2004


      A DESCRIPTION OF THE REQUEST :
      An internal RMI Registry can be created using LocateRegistry.createRegistry(int). The result is a registry that is writable by all client instances on the localhost. It is possible for an application running locally to illegally modify the registry.


      JUSTIFICATION :
      In many cases, when a local registry is used, it should be protected from other applications tampering with its local registrations.

      Consider:

      Registry reg = LocateRegistry.createProtectedRegistry(2004)
      reg.bind("serviceAye", new MyServiceA(2004);
      reg.bind("serviceBee", new MyServiceB(2004);
      reg.bind("serviceCee", new MyServiceC2004);

      The above result exposes one tcp port (2004) on which the registry and three services are additionally exposed on port 2004. (They extend UnicastRemoteObject which takes an integer port number in a constructor)

      Clients may use (MyServiceB)Naming.lookup("//machine:2004/serviceBee") to retrieve the RMI object.

      A developer will observe that, there is no remotely managed registry
      there is no additional deployment installation only one port needs to be opened on a firewall.

      Without a protected registry, it may be tampered with by local applications.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Refering to java.rmi.Registry, the functions bind, unbind and rebind must only allow explicit registration of objects by applications local to the VM that hosts its reference. Remote clients that execute bind, unbind or rebind must receive a thrown AccessException.

      A protected registry must be retrieved through a call to,

      java.rmi.registry.LocateRegistry.createProtectedRegistry(int port)
      java.rmi.registry.LocateRegistry.createProtectedRegistry(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf)

      or possibly even better,

      java.rmi.registry.LocateRegistry.createRegistry(int port, boolean protect)
      java.rmi.registry.LocateRegistry.createRegistry(int port,RMIClientSocketFactory csf, RMIServerSocketFactory ssf, boolean protect)

      ---

      Regarding the name parameter in the following methods,

      Registry.unbind(String name)
      Registry.rebind(String name, Remote)
      Registry.bind(String name, Remote)

      It may further be preferrable to have the name parameter accept unqualified references such as "MyService" instead of "//localhost:1234/MyService" as the localhost address is superfluous and the port number may be specified incorrectly if it differs from the port number provided to createRegistry(int).
      ACTUAL -
      Naming.unbind("//localhost/myservice") will unbind a service from the registry if its on the local machine. The an internal registry created by LocateRegistry.createRegistry is not protected from local applications.

      ---------- BEGIN SOURCE ----------
      the following two methods must be added to LocateRegistry:

      public static Registry createProtectedRegistry(int port) throws RemoteException
      {
      return new ProtectedRegistry(port).getSuperRegistry();
      }

      public static Registry createProtectedRegistry(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException
      {
      return new ProtectedRegistry(port,csf,ssf).getSuperRegistry();
      }

      the following class must be created:

      class ProtectedRegistry extends sun.rmi.registry.RegistryImpl
      {
      public ProtectedRegistry(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException
      {
      super(port,csf,ssf);
      }

      public void bind(String name, Remote obj)
      throws RemoteException, AlreadyBoundException, AccessException
      {
      throw new AccessException("readonly");
      }
      public void unbind(String name)
      throws RemoteException, NotBoundException, AccessException
      {
      throw new AccessException("readonly");
      }
      public void rebind(String name, Remote obj)
      throws RemoteException, AccessException
      {
      throw new AccessException("readonly");
      }

      public Registry getSuperRegistry()
      {
      return new Registry(){
      public Remote lookup(String name)
      throws RemoteException, NotBoundException, AccessException
      {
      return pvtLookup(name);
      }
      public void bind(String name, Remote obj)
      throws RemoteException, AlreadyBoundException, AccessException
      {
      pvtBind(name,obj);
      }
      public void unbind(String name)
      throws RemoteException, NotBoundException, AccessException
      {
      pvtUnbind(name);
      }
      public void rebind(String name, Remote obj)
      throws RemoteException, AccessException
      {
      pvtRebind(name,obj);
      }
      public String[] list() throws RemoteException, AccessException
      {
      return pvtList();
      }
      };
      }

      private Remote pvtLookup(String name)
      throws RemoteException, NotBoundException, AccessException
      {
      return super.lookup(name);
      }

      private void pvtBind(String name, Remote obj)
      throws RemoteException, AlreadyBoundException, AccessException
      {
      super.bind(name, obj);
      }

      private void pvtUnbind(String name)
      throws RemoteException, NotBoundException, AccessException
      {
      super.unbind(name);
      }

      private void pvtRebind(String name, Remote obj)
      throws RemoteException, AccessException
      {
      super.rebind(name, obj);
      }

      private String[] pvtList() throws RemoteException, AccessException
      {
      return super.list();
      }
      }

      the test case would be the construction of a Client that tries to unbind, bind and rebind objects against the protected registry.

      NOTES:
      Both local and remote object references can be bound to the registry by the application itself. Remote clients may not register their objects directly to the registry, they have to pass them to an local application object that registers it to the registry.
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      This is a feature request. The source code listed above may be used.
      The need for the source code above is to protect the local registry.
      (Incident Review ID: 237524)
      ======================================================================

            Unassigned Unassigned
            rmandalasunw Ranjith Mandala (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: