[tomcat7] 02/03: Fixed BZ 57377: Enable SSL to be configured for the JMX/RMI registry as well as the server
Emmanuel Bourg
ebourg-guest at moszumanska.debian.org
Fri Dec 9 00:34:48 UTC 2016
This is an automated email from the git hooks/post-receive script.
ebourg-guest pushed a commit to branch jessie
in repository tomcat7.
commit 565c7336ede9084e87f976d3649cb2df52b1df56
Author: Emmanuel Bourg <ebourg at apache.org>
Date: Fri Dec 9 00:41:08 2016 +0100
Fixed BZ 57377: Enable SSL to be configured for the JMX/RMI registry as well as the server
---
debian/changelog | 3 +
debian/patches/BZ-57377.patch | 390 ++++++++++++++++++++++++++++++++++++++++++
debian/patches/series | 1 +
3 files changed, 394 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index eb01359..a681196 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -10,6 +10,9 @@ tomcat7 (7.0.56-3+deb8u6) UNRELEASED; urgency=medium
interpretation, to inject data into the HTTP response. By manipulating the
HTTP response the attacker could poison a web-cache, perform an XSS attack
and/or obtain sensitive information from requests other then their own.
+ * Backported the fix for upstream bug 57377: Remove the restriction that
+ prevented the use of SSL when specifying a bind address for the JMX/RMI
+ server. Enable SSL to be configured for the registry as well as the server.
* CVE-2016-5018 follow-up: Applied a missing modification fixing
a ClassNotFoundException when the security manager is enabled
(Closes: #846298)
diff --git a/debian/patches/BZ-57377.patch b/debian/patches/BZ-57377.patch
new file mode 100644
index 0000000..2f67446
--- /dev/null
+++ b/debian/patches/BZ-57377.patch
@@ -0,0 +1,390 @@
+Description: Remove the restriction that prevented the use of SSL when
+ specifying a bind address for the JMX/RMI server. Enable SSL to be
+ configured for the registry as well as the server.
+Origin: backport, https://svn.apache.org/r1666762
+Bug: https://bz.apache.org/bugzilla/show_bug.cgi?id=57377
+--- a/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java
++++ b/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java
+@@ -25,17 +25,25 @@
+ import java.net.ServerSocket;
+ import java.net.Socket;
+ import java.net.UnknownHostException;
++import java.rmi.AlreadyBoundException;
+ import java.rmi.RemoteException;
+ import java.rmi.registry.LocateRegistry;
++import java.rmi.registry.Registry;
+ import java.rmi.server.RMIClientSocketFactory;
+ import java.rmi.server.RMIServerSocketFactory;
++import java.security.NoSuchAlgorithmException;
++import java.util.ArrayList;
+ import java.util.HashMap;
++import java.util.List;
++import java.util.Locale;
+
+-import javax.management.MBeanServer;
+ import javax.management.remote.JMXConnectorServer;
+-import javax.management.remote.JMXConnectorServerFactory;
+ import javax.management.remote.JMXServiceURL;
+ import javax.management.remote.rmi.RMIConnectorServer;
++import javax.management.remote.rmi.RMIJRMPServerImpl;
++import javax.net.ssl.SSLContext;
++import javax.net.ssl.SSLServerSocket;
++import javax.net.ssl.SSLServerSocketFactory;
+ import javax.rmi.ssl.SslRMIClientSocketFactory;
+ import javax.rmi.ssl.SslRMIServerSocketFactory;
+
+@@ -55,19 +63,16 @@
+ */
+ public class JmxRemoteLifecycleListener implements LifecycleListener {
+
+- private static final Log log =
+- LogFactory.getLog(JmxRemoteLifecycleListener.class);
++ private static final Log log = LogFactory.getLog(JmxRemoteLifecycleListener.class);
+
+- /**
+- * The string resources for this package.
+- */
+ protected static final StringManager sm =
+- StringManager.getManager(Constants.Package);
++ StringManager.getManager(Constants.Package);
+
+ protected String rmiBindAddress = null;
+ protected int rmiRegistryPortPlatform = -1;
+ protected int rmiServerPortPlatform = -1;
+- protected boolean rmiSSL = true;
++ protected boolean rmiRegistrySSL = true;
++ protected boolean rmiServerSSL = true;
+ protected String ciphers[] = null;
+ protected String protocols[] = null;
+ protected boolean clientAuth = true;
+@@ -154,9 +159,13 @@
+ // Get all the other parameters required from the standard system
+ // properties. Only need to get the parameters that affect the creation
+ // of the server port.
+- String rmiSSLValue = System.getProperty(
++ String rmiRegistrySSLValue = System.getProperty(
++ "com.sun.management.jmxremote.registry.ssl", "false");
++ rmiRegistrySSL = Boolean.parseBoolean(rmiRegistrySSLValue);
++
++ String rmiServerSSLValue = System.getProperty(
+ "com.sun.management.jmxremote.ssl", "true");
+- rmiSSL = Boolean.parseBoolean(rmiSSLValue);
++ rmiServerSSL = Boolean.parseBoolean(rmiServerSSLValue);
+
+ String protocolsValue = System.getProperty(
+ "com.sun.management.jmxremote.ssl.enabled.protocols");
+@@ -171,7 +180,7 @@
+ }
+
+ String clientAuthValue = System.getProperty(
+- "com.sun.management.jmxremote.ssl.need.client.auth", "true");
++ "com.sun.management.jmxremote.ssl.need.client.auth", "true");
+ clientAuth = Boolean.parseBoolean(clientAuthValue);
+
+ String authenticateValue = System.getProperty(
+@@ -204,47 +213,64 @@
+ // Create the environment
+ HashMap<String,Object> env = new HashMap<String,Object>();
+
+- RMIClientSocketFactory csf = null;
+- RMIServerSocketFactory ssf = null;
++ RMIClientSocketFactory registryCsf = null;
++ RMIServerSocketFactory registrySsf = null;
++
++ RMIClientSocketFactory serverCsf = null;
++ RMIServerSocketFactory serverSsf = null;
+
+- // Configure SSL for RMI connection if required
+- if (rmiSSL) {
++ // Configure registry socket factories
++ if (rmiRegistrySSL) {
++ registryCsf = new SslRMIClientSocketFactory();
++ if (rmiBindAddress == null) {
++ registrySsf = new SslRMIServerSocketFactory(
++ ciphers, protocols, clientAuth);
++ } else {
++ registrySsf = new SslRmiServerBindSocketFactory(
++ ciphers, protocols, clientAuth, rmiBindAddress);
++ }
++ } else {
+ if (rmiBindAddress != null) {
+- throw new IllegalStateException(sm.getString(
+- "jmxRemoteLifecycleListener.sslRmiBindAddress"));
++ registrySsf = new RmiServerBindSocketFactory(rmiBindAddress);
+ }
++ }
+
+- csf = new SslRMIClientSocketFactory();
+- ssf = new SslRMIServerSocketFactory(ciphers, protocols,
+- clientAuth);
++ // Configure server socket factories
++ if (rmiServerSSL) {
++ serverCsf = new SslRMIClientSocketFactory();
++ if (rmiBindAddress == null) {
++ serverSsf = new SslRMIServerSocketFactory(
++ ciphers, protocols, clientAuth);
++ } else {
++ serverSsf = new SslRmiServerBindSocketFactory(
++ ciphers, protocols, clientAuth, rmiBindAddress);
++ }
++ } else {
++ if (rmiBindAddress != null) {
++ serverSsf = new RmiServerBindSocketFactory(rmiBindAddress);
++ }
+ }
+
+- // Force server bind address if required
++ // By default, the registry will pick an address to listen on.
++ // Setting this property overrides that and ensures it listens on
++ // the configured address.
+ if (rmiBindAddress != null) {
+- try {
+- ssf = new RmiServerBindSocketFactory(
+- InetAddress.getByName(rmiBindAddress));
+- } catch (UnknownHostException e) {
+- log.error(sm.getString(
+- "jmxRemoteLifecycleListener.invalidRmiBindAddress",
+- rmiBindAddress), e);
+- }
++ System.setProperty("java.rmi.server.hostname", rmiBindAddress);
+ }
+
+ // Force the use of local ports if required
+ if (useLocalPorts) {
+- csf = new RmiClientLocalhostSocketFactory(csf);
++ registryCsf = new RmiClientLocalhostSocketFactory(registryCsf);
++ serverCsf = new RmiClientLocalhostSocketFactory(serverCsf);
+ }
+
+ // Populate the env properties used to create the server
+- if (csf != null) {
+- env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE,
+- csf);
+- env.put("com.sun.jndi.rmi.factory.socket", csf);
+- }
+- if (ssf != null) {
+- env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
+- ssf);
++ if (serverCsf != null) {
++ env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, serverCsf);
++ env.put("com.sun.jndi.rmi.factory.socket", registryCsf);
++ }
++ if (serverSsf != null) {
++ env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverSsf);
+ }
+
+ // Configure authentication
+@@ -254,25 +280,27 @@
+ env.put("jmx.remote.x.login.config", loginModuleName);
+ }
+
+-
+ // Create the Platform server
+ csPlatform = createServer("Platform", rmiBindAddress, rmiRegistryPortPlatform,
+- rmiServerPortPlatform, env, csf, ssf,
+- ManagementFactory.getPlatformMBeanServer());
++ rmiServerPortPlatform, env, registryCsf, registrySsf, serverCsf, serverSsf);
+
+ } else if (Lifecycle.STOP_EVENT == event.getType()) {
+ destroyServer("Platform", csPlatform);
+ }
+ }
+
++
+ private JMXConnectorServer createServer(String serverName,
+ String bindAddress, int theRmiRegistryPort, int theRmiServerPort,
+- HashMap<String,Object> theEnv, RMIClientSocketFactory csf,
+- RMIServerSocketFactory ssf, MBeanServer theMBeanServer) {
++ HashMap<String,Object> theEnv,
++ RMIClientSocketFactory registryCsf, RMIServerSocketFactory registrySsf,
++ RMIClientSocketFactory serverCsf, RMIServerSocketFactory serverSsf) {
+
+ // Create the RMI registry
++ Registry registry;
+ try {
+- LocateRegistry.createRegistry(theRmiRegistryPort, csf, ssf);
++ registry = LocateRegistry.createRegistry(
++ theRmiRegistryPort, registryCsf, registrySsf);
+ } catch (RemoteException e) {
+ log.error(sm.getString(
+ "jmxRemoteLifecycleListener.createRegistryFailed",
+@@ -284,33 +312,23 @@
+ bindAddress = "localhost";
+ }
+
+- // Build the connection string with fixed ports
+- StringBuilder url = new StringBuilder();
+- url.append("service:jmx:rmi://");
+- url.append(bindAddress);
+- url.append(":");
+- url.append(theRmiServerPort);
+- url.append("/jndi/rmi://");
+- url.append(bindAddress);
+- url.append(":");
+- url.append(theRmiRegistryPort);
+- url.append("/jmxrmi");
++ String url = "service:jmx:rmi://" + bindAddress;
+ JMXServiceURL serviceUrl;
+ try {
+ serviceUrl = new JMXServiceURL(url.toString());
+ } catch (MalformedURLException e) {
+- log.error(sm.getString(
+- "jmxRemoteLifecycleListener.invalidURL",
+- serverName, url.toString()), e);
++ log.error(sm.getString("jmxRemoteLifecycleListener.invalidURL", serverName, url), e);
+ return null;
+ }
+
+- // Start the JMX server with the connection string
+- JMXConnectorServer cs = null;
++ RMIConnectorServer cs = null;
+ try {
+- cs = JMXConnectorServerFactory.newJMXConnectorServer(
+- serviceUrl, theEnv, theMBeanServer);
++ RMIJRMPServerImpl server = new RMIJRMPServerImpl(
++ rmiServerPortPlatform, serverCsf, serverSsf, theEnv);
++ cs = new RMIConnectorServer(serviceUrl, theEnv, server,
++ ManagementFactory.getPlatformMBeanServer());
+ cs.start();
++ registry.bind("jmxrmi", server);
+ log.info(sm.getString("jmxRemoteLifecycleListener.start",
+ Integer.toString(theRmiRegistryPort),
+ Integer.toString(theRmiServerPort), serverName));
+@@ -318,10 +336,15 @@
+ log.error(sm.getString(
+ "jmxRemoteLifecycleListener.createServerFailed",
+ serverName), e);
++ } catch (AlreadyBoundException e) {
++ log.error(sm.getString(
++ "jmxRemoteLifecycleListener.createServerFailed",
++ serverName), e);
+ }
+ return cs;
+ }
+
++
+ private void destroyServer(String serverName,
+ JMXConnectorServer theConnectorServer) {
+ if (theConnectorServer != null) {
+@@ -335,6 +358,7 @@
+ }
+ }
+
++
+ public static class RmiClientLocalhostSocketFactory
+ implements RMIClientSocketFactory, Serializable {
+
+@@ -358,13 +382,22 @@
+ }
+ }
+
+- public static class RmiServerBindSocketFactory
+- implements RMIServerSocketFactory {
++
++ public static class RmiServerBindSocketFactory implements RMIServerSocketFactory {
+
+ private final InetAddress bindAddress;
+
+- public RmiServerBindSocketFactory(InetAddress address) {
+- bindAddress = address;
++ public RmiServerBindSocketFactory(String address) {
++ InetAddress bindAddress = null;
++ try {
++ bindAddress = InetAddress.getByName(address);
++ } catch (UnknownHostException e) {
++ log.error(sm.getString(
++ "jmxRemoteLifecycleListener.invalidRmiBindAddress", address), e);
++ // bind address will be null which means any/all local addresses
++ // which should be safe
++ }
++ this.bindAddress = bindAddress;
+ }
+
+ @Override
+@@ -372,4 +405,64 @@
+ return new ServerSocket(port, 0, bindAddress);
+ }
+ }
++
++
++ public static class SslRmiServerBindSocketFactory extends SslRMIServerSocketFactory {
++
++ private static final SSLServerSocketFactory sslServerSocketFactory;
++ private static final String[] defaultProtocols;
++
++ static {
++ SSLContext sslContext;
++ try {
++ sslContext = SSLContext.getDefault();
++ } catch (NoSuchAlgorithmException e) {
++ // Can't continue. Force a failure.
++ throw new IllegalStateException(e);
++ }
++ sslServerSocketFactory = sslContext.getServerSocketFactory();
++ String[] protocols = sslContext.getDefaultSSLParameters().getProtocols();
++ List<String> filteredProtocols = new ArrayList<String>(protocols.length);
++ for (String protocol : protocols) {
++ if (protocol.toUpperCase(Locale.ENGLISH).contains("SSL")) {
++ continue;
++ }
++ filteredProtocols.add(protocol);
++ }
++ defaultProtocols = filteredProtocols.toArray(new String[filteredProtocols.size()]);
++ }
++
++ private final InetAddress bindAddress;
++
++ public SslRmiServerBindSocketFactory(String[] enabledCipherSuites,
++ String[] enabledProtocols, boolean needClientAuth, String address) {
++ super(enabledCipherSuites, enabledProtocols, needClientAuth);
++ InetAddress bindAddress = null;
++ try {
++ bindAddress = InetAddress.getByName(address);
++ } catch (UnknownHostException e) {
++ log.error(sm.getString(
++ "jmxRemoteLifecycleListener.invalidRmiBindAddress", address), e);
++ // bind address will be null which means any/all local addresses
++ // which should be safe
++ }
++ this.bindAddress = bindAddress;
++ }
++
++ @Override
++ public ServerSocket createServerSocket(int port) throws IOException {
++ SSLServerSocket sslServerSocket =
++ (SSLServerSocket) sslServerSocketFactory.createServerSocket(port, 0, bindAddress);
++ if (getEnabledCipherSuites() != null) {
++ sslServerSocket.setEnabledCipherSuites(getEnabledCipherSuites());
++ }
++ if (getEnabledProtocols() == null) {
++ sslServerSocket.setEnabledProtocols(defaultProtocols);
++ } else {
++ sslServerSocket.setEnabledProtocols(getEnabledProtocols());
++ }
++ sslServerSocket.setNeedClientAuth(getNeedClientAuth());
++ return sslServerSocket;
++ }
++ }
+ }
+--- a/java/org/apache/catalina/mbeans/LocalStrings.properties
++++ b/java/org/apache/catalina/mbeans/LocalStrings.properties
+@@ -18,5 +18,4 @@
+ jmxRemoteLifecycleListener.destroyServerFailed=The JMX connector server could not be stopped for the {0} server
+ jmxRemoteLifecycleListener.invalidURL=The JMX Service URL requested for the {0} server, "{1}", was invalid
+ jmxRemoteLifecycleListener.start=The JMX Remote Listener has configured the registry on port {0} and the server on port {1} for the {2} server
+-jmxRemoteLifecycleListener.sslRmiBindAddress=rmiBindAddress is incompatible with setting the system property com.sun.management.jmxremote.ssl to true
+ jmxRemoteLifecycleListener.invalidRmiBindAddress=Invalid RMI bind address [{0}]
+--- a/webapps/docs/config/listeners.xml
++++ b/webapps/docs/config/listeners.xml
+@@ -443,10 +443,7 @@
+ </attribute>
+
+ <attribute name="rmiBindAddress" required="false">
+- <p>The address of the interface to be used by JMX/RMI server.
+- This option is incompatible with setting the system
+- property <code>com.sun.management.jmxremote.ssl</code> to
+- <code>true</code>.</p>
++ <p>The address of the interface to be used by JMX/RMI server.</p>
+ </attribute>
+
+ <attribute name="useLocalPorts" required="false">
diff --git a/debian/patches/series b/debian/patches/series
index 18753e0..26401e9 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -35,3 +35,4 @@ CVE-2016-6794.patch
CVE-2016-6796.patch
CVE-2016-6797.patch
CVE-2016-6816.patch
+BZ-57377.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/tomcat7.git
More information about the pkg-java-commits
mailing list