src/share/classes/sun/rmi/server/Activation.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -72,20 +72,22 @@
 import java.rmi.server.RMIClassLoader;
 import java.rmi.server.RMIClientSocketFactory;
 import java.rmi.server.RMIServerSocketFactory;
 import java.rmi.server.RemoteObject;
 import java.rmi.server.RemoteServer;
+import java.rmi.server.ServerNotActiveException;
 import java.rmi.server.UnicastRemoteObject;
 import java.security.AccessControlException;
 import java.security.AccessController;
 import java.security.AllPermission;
 import java.security.CodeSource;
 import java.security.Permission;
 import java.security.PermissionCollection;
 import java.security.Permissions;
 import java.security.Policy;
 import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.security.cert.Certificate;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;

@@ -105,10 +107,11 @@
 import sun.rmi.log.ReliableLog;
 import sun.rmi.registry.RegistryImpl;
 import sun.rmi.runtime.NewThreadAction;
 import sun.rmi.server.UnicastServerRef;
 import sun.rmi.transport.LiveRef;
+import sun.rmi.transport.tcp.TCPTransport;
 import sun.security.action.GetBooleanAction;
 import sun.security.action.GetIntegerAction;
 import sun.security.action.GetPropertyAction;
 import sun.security.provider.PolicyFile;
 import com.sun.rmi.rmid.ExecPermission;

@@ -180,10 +183,35 @@
         getInt("sun.rmi.activation.execTimeout", 30000);
 
     private static final Object initLock = new Object();
     private static boolean initDone = false;
 
+    private static final InetAddress remoteClientAddress;
+    static {
+        remoteClientAddress = java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<InetAddress>() {
+                public InetAddress run() {
+                    String remoteClientProp =
+                        System.getProperty("sun.rmi.activation.remoteClient",
+                           null);
+
+                    if (remoteClientProp == null) {
+                        return null;
+                    }
+
+                    try {
+                        return InetAddress.getByName(remoteClientProp);
+                    } catch (Throwable t) {
+                        System.err.println("Activation: Cannot get the IP " +
+                            "address of the remote client: " +
+                            remoteClientProp);
+                    }
+
+                    return null;
+                }});
+    }
+
     // this should be a *private* method since it is privileged
     private static int getInt(String name, int def) {
         return AccessController.doPrivileged(new GetIntegerAction(name, def));
     }
 

@@ -205,10 +233,62 @@
      * snapshot is taken during the first incarnation of rmid.
      */
     private Activation() {}
 
     /**
+     * Check that the caller has access to this interface.
+     * <p>
+     * Use the default policy as implemented in RegistryImpl.checkAccess,
+     * unless the sun.rmi.activation.remoteClient property is set, and in
+     * that case only allow access from that host.
+     *
+     * @param op name of operation used to create a meaningful exception
+     *           message, the parameter is not used to determine access
+     */
+    static void checkAccess(String op) throws AccessException {
+        if (remoteClientAddress == null) {
+            /*
+             * Note, the op arg to checkAccess is only used to build an
+             * access exception message if needed.
+             */
+            RegistryImpl.checkAccess(op);
+            return;
+        }
+
+        InetAddress clientHost;
+
+        try {
+            // Get client host that this operation was made from.
+            final String clientHostName = TCPTransport.getClientHost();
+
+            try {
+                clientHost = java.security.AccessController.doPrivileged(
+                    new java.security.PrivilegedExceptionAction<InetAddress>() {
+                        public InetAddress run()
+                            throws java.net.UnknownHostException
+                        {
+                            return InetAddress.getByName(clientHostName);
+                        }
+                    });
+            } catch (PrivilegedActionException pae) {
+                throw new AccessException("RMI " + op + " disallowed; " +
+                    clientHostName + " is an unknown client");
+            }
+        } catch (ServerNotActiveException ex) {
+            throw new AccessException("RMI " + op +
+                " is not allowed from the local host");
+        }
+
+        if (remoteClientAddress.equals(clientHost)) {
+            return;
+        }
+
+        throw new AccessException("RMI " + op + " is not allowed from " +
+            clientHost);
+    }
+
+    /**
      * Recover activation state from the reliable log and initialize
      * activation services.
      */
     private static void startActivation(int port,
                                         RMIServerSocketFactory ssf,

@@ -424,11 +504,11 @@
             try {
                 checkShutdown();
             } catch (ActivationException e) {
                 return;
             }
-            RegistryImpl.checkAccess("Activator.inactiveObject");
+            Activation.checkAccess("Activator.inactiveObject");
             getGroupEntry(id).inactiveObject(id);
         }
 
         public void activeObject(ActivationID id,
                                  MarshalledObject<? extends Remote> mobj)

@@ -437,11 +517,11 @@
             try {
                 checkShutdown();
             } catch (ActivationException e) {
                 return;
             }
-            RegistryImpl.checkAccess("ActivationSystem.activeObject");
+            Activation.checkAccess("ActivationSystem.activeObject");
             getGroupEntry(id).activeObject(id, mobj);
         }
 
         public void inactiveGroup(ActivationGroupID id,
                                   long incarnation)

@@ -450,11 +530,11 @@
             try {
                 checkShutdown();
             } catch (ActivationException e) {
                 return;
             }
-            RegistryImpl.checkAccess("ActivationMonitor.inactiveGroup");
+            Activation.checkAccess("ActivationMonitor.inactiveGroup");
             getGroupEntry(id).inactiveGroup(incarnation, false);
         }
     }
 
 

@@ -482,11 +562,11 @@
 
         public ActivationID registerObject(ActivationDesc desc)
             throws ActivationException, UnknownGroupException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.registerObject");
+            Activation.checkAccess("ActivationSystem.registerObject");
 
             ActivationGroupID groupID = desc.getGroupID();
             ActivationID id = new ActivationID(activatorStub);
             getGroupEntry(groupID).registerObject(id, desc, true);
             return id;

@@ -494,19 +574,19 @@
 
         public void unregisterObject(ActivationID id)
             throws ActivationException, UnknownObjectException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.unregisterObject");
+            Activation.checkAccess("ActivationSystem.unregisterObject");
             getGroupEntry(id).unregisterObject(id, true);
         }
 
         public ActivationGroupID registerGroup(ActivationGroupDesc desc)
             throws ActivationException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.registerGroup");
+            Activation.checkAccess("ActivationSystem.registerGroup");
             checkArgs(desc, null);
 
             ActivationGroupID id = new ActivationGroupID(systemStub);
             GroupEntry entry = new GroupEntry(id, desc);
             // table insertion must take place before log update

@@ -519,21 +599,21 @@
                                              ActivationInstantiator group,
                                              long incarnation)
             throws ActivationException, UnknownGroupException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.activeGroup");
+            Activation.checkAccess("ActivationSystem.activeGroup");
 
             getGroupEntry(id).activeGroup(group, incarnation);
             return monitor;
         }
 
         public void unregisterGroup(ActivationGroupID id)
             throws ActivationException, UnknownGroupException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.unregisterGroup");
+            Activation.checkAccess("ActivationSystem.unregisterGroup");
 
             // remove entry before unregister so state is updated before
             // logged
             removeGroupEntry(id).unregisterGroup(true);
         }

@@ -541,11 +621,11 @@
         public ActivationDesc setActivationDesc(ActivationID id,
                                                 ActivationDesc desc)
             throws ActivationException, UnknownObjectException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.setActivationDesc");
+            Activation.checkAccess("ActivationSystem.setActivationDesc");
 
             if (!getGroupID(id).equals(desc.getGroupID())) {
                 throw new ActivationException(
                     "ActivationDesc contains wrong group");
             }

@@ -555,42 +635,42 @@
         public ActivationGroupDesc setActivationGroupDesc(ActivationGroupID id,
                                                           ActivationGroupDesc desc)
             throws ActivationException, UnknownGroupException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess(
+            Activation.checkAccess(
                 "ActivationSystem.setActivationGroupDesc");
 
             checkArgs(desc, null);
             return getGroupEntry(id).setActivationGroupDesc(id, desc, true);
         }
 
         public ActivationDesc getActivationDesc(ActivationID id)
             throws ActivationException, UnknownObjectException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess("ActivationSystem.getActivationDesc");
+            Activation.checkAccess("ActivationSystem.getActivationDesc");
 
             return getGroupEntry(id).getActivationDesc(id);
         }
 
         public ActivationGroupDesc getActivationGroupDesc(ActivationGroupID id)
             throws ActivationException, UnknownGroupException, RemoteException
         {
             checkShutdown();
-            RegistryImpl.checkAccess
+            Activation.checkAccess
                 ("ActivationSystem.getActivationGroupDesc");
 
             return getGroupEntry(id).desc;
         }
 
         /**
          * Shutdown the activation system. Destroys all groups spawned by
          * the activation daemon and exits the activation daemon.
          */
         public void shutdown() throws AccessException {
-            RegistryImpl.checkAccess("ActivationSystem.shutdown");
+            Activation.checkAccess("ActivationSystem.shutdown");
 
             Object lock = startupLock;
             if (lock != null) {
                 synchronized (lock) {
                     // nothing