6332953: JMX agent should bind to loopback address when starting the local connector server
authordfuchs
Thu, 09 Oct 2008 14:10:58 +0200
changeset 1447 95d5bd511ec2
parent 1446 605e30465515
child 1448 86d46701261b
6332953: JMX agent should bind to loopback address when starting the local connector server Reviewed-by: emcmanus
jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
jdk/src/share/classes/sun/management/jmxremote/LocalRMIServerSocketFactory.java
jdk/src/share/lib/management/management.properties
--- a/jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java	Wed Oct 08 18:38:25 2008 +0200
+++ b/jdk/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java	Thu Oct 09 14:10:58 2008 +0200
@@ -80,7 +80,7 @@
 import static sun.management.AgentConfigurationError.*;
 import sun.management.ConnectorAddressLink;
 import sun.management.FileSystem;
-import sun.management.snmp.util.MibLogger;
+import com.sun.jmx.remote.util.ClassLogger;
 
 import com.sun.jmx.remote.internal.RMIExporter;
 import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
@@ -115,6 +115,8 @@
                 "com.sun.management.jmxremote.port";
         public static final String CONFIG_FILE_NAME =
                 "com.sun.management.config.file";
+        public static final String USE_LOCAL_ONLY =
+                "com.sun.management.jmxremote.local.only";
         public static final String USE_SSL =
                 "com.sun.management.jmxremote.ssl";
         public static final String USE_REGISTRY_SSL =
@@ -384,7 +386,7 @@
             checkAccessFile(accessFileName);
         }
 
-        if (log.isDebugOn()) {
+        if (log.debugOn()) {
             log.debug("initialize",
                     Agent.getText("jmxremote.ConnectorBootstrap.initialize") +
                     "\n\t" + PropertyNames.PORT + "=" + port +
@@ -477,6 +479,18 @@
         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
         try {
             JMXServiceURL url = new JMXServiceURL("rmi", localhost, 0);
+            // Do we accept connections from local interfaces only?
+            Properties props = Agent.getManagementProperties();
+            if (props ==  null) {
+                props = new Properties();
+            }
+            String useLocalOnlyStr = props.getProperty(
+                    PropertyNames.USE_LOCAL_ONLY, DefaultValues.USE_LOCAL_ONLY);
+            boolean useLocalOnly = Boolean.valueOf(useLocalOnlyStr).booleanValue();
+            if (useLocalOnly) {
+                env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
+                        new LocalRMIServerSocketFactory());
+            }
             JMXConnectorServer server =
                     JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
             server.start();
@@ -764,7 +778,7 @@
     private ConnectorBootstrap() {
     }
 
-    // XXX Revisit: should probably clone this MibLogger....
-    private static final MibLogger log =
-            new MibLogger(ConnectorBootstrap.class);
+    private static final ClassLogger log =
+        new ClassLogger(ConnectorBootstrap.class.getPackage().getName(),
+                        "ConnectorBootstrap");
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/management/jmxremote/LocalRMIServerSocketFactory.java	Thu Oct 09 14:10:58 2008 +0200
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.management.jmxremote;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.rmi.server.RMIServerSocketFactory;
+import java.util.Enumeration;
+
+/**
+ * This RMI server socket factory creates server sockets that
+ * will only accept connection requests from clients running
+ * on the host where the RMI remote objects have been exported.
+ */
+public final class LocalRMIServerSocketFactory implements RMIServerSocketFactory {
+    /**
+     * Creates a server socket that only accepts connection requests from
+     * clients running on the host where the RMI remote objects have been
+     * exported.
+     */
+    public ServerSocket createServerSocket(int port) throws IOException {
+        return new ServerSocket(port) {
+            @Override
+            public Socket accept() throws IOException {
+                Socket socket = super.accept();
+                InetAddress remoteAddr = socket.getInetAddress();
+                final String msg = "The server sockets created using the " +
+                        "LocalRMIServerSocketFactory only accept connections " +
+                        "from clients running on the host where the RMI " +
+                        "remote objects have been exported.";
+                if (remoteAddr.isAnyLocalAddress()) {
+                    // local address: accept the connection.
+                    return socket;
+                }
+                // Retrieve all the network interfaces on this host.
+                Enumeration<NetworkInterface> nis;
+                try {
+                    nis = NetworkInterface.getNetworkInterfaces();
+                } catch (SocketException e) {
+                    try {
+                        socket.close();
+                    } catch (IOException ioe) {
+                        // Ignore...
+                    }
+                    throw new IOException(msg, e);
+                }
+                // Walk through the network interfaces to see
+                // if any of them matches the client's address.
+                // If true, then the client's address is local.
+                while (nis.hasMoreElements()) {
+                    NetworkInterface ni = nis.nextElement();
+                    Enumeration<InetAddress> addrs = ni.getInetAddresses();
+                    while (addrs.hasMoreElements()) {
+                        InetAddress localAddr = addrs.nextElement();
+                        if (localAddr.equals(remoteAddr)) {
+                            return socket;
+                        }
+                    }
+                }
+                // The client's address is remote so refuse the connection.
+                try {
+                    socket.close();
+                } catch (IOException ioe) {
+                    // Ignore...
+                }
+                throw new IOException(msg);
+            }
+        };
+    }
+
+    /**
+     * Two LocalRMIServerSocketFactory objects
+     * are equal if they are of the same type.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        return (obj instanceof LocalRMIServerSocketFactory);
+    }
+
+    /**
+     * Returns a hash code value for this LocalRMIServerSocketFactory.
+     */
+    @Override
+    public int hashCode() {
+        return getClass().hashCode();
+    }
+}
--- a/jdk/src/share/lib/management/management.properties	Wed Oct 08 18:38:25 2008 +0200
+++ b/jdk/src/share/lib/management/management.properties	Thu Oct 09 14:10:58 2008 +0200
@@ -82,7 +82,7 @@
 #
 # com.sun.management.snmp.interface=<InetAddress>
 #      Specifies the local interface on which the SNMP agent will bind.
-#      This is usefull when running on machines which have several
+#      This is useful when running on machines which have several
 #      interfaces defined. It makes it possible to listen to a specific
 #      subnet accessible through that interface.
 #      Default for this property is "localhost".
@@ -144,6 +144,26 @@
 #
 
 #
+# ########## RMI connector settings for local management ##########
+#
+# com.sun.management.jmxremote.local.only=true|false
+#      Default for this property is true. (Case for true/false ignored)
+#      If this property is specified as true then the local JMX RMI connector
+#      server will only accept connection requests from clients running on
+#      the host where the out-of-the-box JMX management agent is running.
+#      In order to ensure backwards compatibility this property could be
+#      set to false. However, deploying the local management agent in this
+#      way is discouraged because the local JMX RMI connector server will
+#      accept connection requests from any client either local or remote.
+#      For remote management the remote JMX RMI connector server should
+#      be used instead with authentication and SSL/TLS encryption enabled.
+#
+
+# For allowing the local management agent accept local
+# and remote connection requests use the following line
+# com.sun.management.jmxremote.local.only=false
+
+#
 # ###################### RMI SSL #############################
 #
 # com.sun.management.jmxremote.ssl=true|false