[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