diff --git a/README.md b/README.md index c412ce7..82c66a6 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,14 @@ Any authorization on the server must be configured using the `jmx.remote.accessc - Applications can also implement the `nl.futureedge.simple.jmx.access.JMXAccessController` interface instead of using the supplied implementations to fully customize their access control. ### Connections (client-side and server-side) -Connections are made via standaard Java sockets. Simple JMX provides two connection provider out of the box: -- Anonymous SSL (allows operation without certificates) ****default***\* +Connections are made via standaard Java sockets. Simple JMX provides three connection provider out of the box: +- Plain sockets (provides no security) ****default***\* +- Anonymous SSL (allows operation without certificates, but note that these cipher suites are often not enabled) - System SSL (uses the default Java SSL provider) Any connection configuration (on the client or the server) must be configured using the `jmx.remote.socketfactory` key in the environment; the value should be an object instance that implements the `nl.futureedge.jmx.socket.JMXSocketFactory` interface: +- Plain socket implementation (`nl.futureedge.simple.jmx.socket.PlainSocketFactory`) does not have any configuration. - The anonymous SSL implementation (`nl.futureedge.simple.jmx.socket.AnonymousSslSocketFactory`) does not have any specific configuration. - The system SSL implementation (`nl.futureedge.simple.jmx.socket.SystemSslSocketFactory`) uses the system default SSLContext and should be configured using the [system configuration](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html). - Applications can also implement the `nl.futureedge.simple.jmx.socket.JMXSocketFactory` interface to fully customize their connections. diff --git a/src/main/java/nl/futureedge/simple/jmx/environment/Environment.java b/src/main/java/nl/futureedge/simple/jmx/environment/Environment.java index 506545b..db62245 100644 --- a/src/main/java/nl/futureedge/simple/jmx/environment/Environment.java +++ b/src/main/java/nl/futureedge/simple/jmx/environment/Environment.java @@ -10,6 +10,7 @@ import nl.futureedge.simple.jmx.authenticator.StaticAuthenticator; import nl.futureedge.simple.jmx.socket.AnonymousSslSocketFactory; import nl.futureedge.simple.jmx.socket.JMXSocketFactory; +import nl.futureedge.simple.jmx.socket.PlainSocketFactory; import nl.futureedge.simple.jmx.socket.SslConfigurationException; /** @@ -33,6 +34,8 @@ private Environment() { public static final String KEY_THREADPRIORITY = "jmx.remote.threadpriority"; + public static final String KEY_ANONYMOUS_CIPHERS = "jmx.remote.anonymousciphers"; + public static JMXSocketFactory determineSocketFactory(final Map environment) throws IOException { // Custom socket factory via the environment final JMXSocketFactory custom = (JMXSocketFactory) environment.get(KEY_SOCKETFACTORY); @@ -41,10 +44,14 @@ public static JMXSocketFactory determineSocketFactory(final Map envir } // Default: no authentication - try { - return new AnonymousSslSocketFactory(); - } catch (final SslConfigurationException e) { - throw new IOException("Could not create default socket factory", e); + if (environment.containsKey(KEY_ANONYMOUS_CIPHERS)) { + try { + return new AnonymousSslSocketFactory(); + } catch (final SslConfigurationException e) { + throw new IOException("Could not create default socket factory", e); + } + } else { + return new PlainSocketFactory(); } } diff --git a/src/main/java/nl/futureedge/simple/jmx/socket/PlainSocketFactory.java b/src/main/java/nl/futureedge/simple/jmx/socket/PlainSocketFactory.java new file mode 100644 index 0000000..fcbdbeb --- /dev/null +++ b/src/main/java/nl/futureedge/simple/jmx/socket/PlainSocketFactory.java @@ -0,0 +1,48 @@ +package nl.futureedge.simple.jmx.socket; + +import javax.management.remote.JMXServiceURL; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Socket factory without any security at all. + */ +public class PlainSocketFactory implements JMXSocketFactory { + + private static final int BACKLOG = 50; + private static final Logger LOGGER = Logger.getLogger(PlainSocketFactory.class.getName()); + + /** + * Create a client socket. + * @param serviceUrl jmx service url + * @return client socket + * @throws IOException if an I/O error occurs when creating the socket + */ + @Override + public Socket createSocket(final JMXServiceURL serviceUrl) throws IOException { + final Socket socket = new Socket(serviceUrl.getHost(), serviceUrl.getPort()); + socket.setKeepAlive(true); + + LOGGER.log(Level.FINE, "Created client socket"); + return socket; + } + + /** + * Create a server socket. + * @param serviceUrl jmx service url + * @return server socket + * @throws IOException if an I/O error occurs when creating the socket + */ + @Override + public ServerSocket createServerSocket(final JMXServiceURL serviceUrl) throws IOException { + final InetAddress host = InetAddress.getByName(serviceUrl.getHost()); + final ServerSocket serverSocket = new ServerSocket(serviceUrl.getPort(), BACKLOG, host); + + LOGGER.log(Level.FINE, "Created server socket"); + return serverSocket; + } +} diff --git a/src/test/java/nl/futureedge/simple/jmx/server/ServerListenerTest.java b/src/test/java/nl/futureedge/simple/jmx/server/ServerListenerTest.java index f14f03b..98cc830 100644 --- a/src/test/java/nl/futureedge/simple/jmx/server/ServerListenerTest.java +++ b/src/test/java/nl/futureedge/simple/jmx/server/ServerListenerTest.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.lang.reflect.Field; import java.net.ServerSocket; +import java.net.Socket; import java.net.SocketException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; @@ -11,7 +12,8 @@ import javax.management.MBeanServer; import javax.management.remote.JMXServiceURL; import javax.net.ssl.SSLSocket; -import nl.futureedge.simple.jmx.socket.AnonymousSslSocketFactory; + +import nl.futureedge.simple.jmx.socket.PlainSocketFactory; import org.awaitility.Awaitility; import org.junit.After; import org.junit.Assert; @@ -38,7 +40,7 @@ public class ServerListenerTest { public void setup() throws IOException { mBeanServer = Mockito.mock(MBeanServer.class); serverConnector = new ServerConnector(new JMXServiceURL("simple", "localhost", 0), null, mBeanServer); - subject = new ServerListener(serverConnector, new AnonymousSslSocketFactory(), null, null, Thread.NORM_PRIORITY); + subject = new ServerListener(serverConnector, new PlainSocketFactory(), null, null, Thread.NORM_PRIORITY); } private void start() { @@ -61,8 +63,10 @@ public void test() throws IOException, InterruptedException { start(); - final SSLSocket client = (SSLSocket) new AnonymousSslSocketFactory().createSocket(serverConnector.getAddress()); - client.startHandshake(); + final Socket client = new PlainSocketFactory().createSocket(serverConnector.getAddress()); + if (client instanceof SSLSocket) { + ((SSLSocket)client).startHandshake(); + } Assert.assertTrue(client.isConnected()); Assert.assertNotNull(client.getOutputStream()); Assert.assertNotNull(client.getInputStream());