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 <[email protected]> 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 _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

