6332953: JMX agent should bind to loopback address when starting the local connector server
Reviewed-by: emcmanus
--- 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