/hg/release/icedtea7-forest-2.6/jdk: 16 new changesets

andrew at icedtea.classpath.org andrew at icedtea.classpath.org
Thu Mar 24 21:39:21 UTC 2016


changeset dbb99226719c in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=dbb99226719c
author: andrew
date: Wed Mar 23 21:27:34 2016 +0000

	8028727, PR2814: [parfait] warnings from b116 for jdk.src.share.native.sun.security.ec: JNI pending exceptions
	Reviewed-by: alanb


changeset e3f5a9bd8195 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=e3f5a9bd8195
author: vinnie
date: Fri Oct 03 16:17:36 2014 +0100

	8048512, PR2814: Uninitialised memory in jdk/src/share/native/sun/security/ec/ECC_JNI.cpp
	Reviewed-by: mullan


changeset 9d38df9e5a9a in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=9d38df9e5a9a
author: neugens
date: Fri Feb 27 15:50:03 2015 +0100

	8071705. PR2819, RH1182694: Java application menu misbehaves when running multiple screen stacked vertically
	Summary: JMenu miscalculates the position of the Popup origin when on multiple monitors stacked vertically
	Reviewed-by: alexsch


changeset c67c8e86f068 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=c67c8e86f068
author: sgehwolf
date: Wed Nov 04 11:34:27 2015 +0100

	6425769, PR2858: Allow specifying an address to bind JMX remote connector
	Reviewed-by: jbachorik, dfuchs


changeset ec55db152451 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=ec55db152451
author: jbachorik
date: Mon Jan 04 10:07:08 2016 +0100

	8145982, PR2858: JMXInterfaceBindingTest is failing intermittently
	Reviewed-by: chegar, sgehwolf, olagneau


changeset 83437bcae253 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=83437bcae253
author: jbachorik
date: Fri Jan 29 13:35:06 2016 +0100

	8146015, PR2858: JMXInterfaceBindingTest is failing intermittently for IPv6 addresses
	Reviewed-by: dfuchs, sspitsyn


changeset 27fde4047043 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=27fde4047043
author: andrew
date: Wed Mar 23 23:46:58 2016 +0000

	8150954, PR2866, RH1176206: AWT Robot not compatible with GNOME Shell
	Summary: Use the overlay window rather than the root window when on a composite display.


changeset 09123c3eea20 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=09123c3eea20
author: andrew
date: Thu Mar 24 00:51:58 2016 +0000

	Bump to icedtea-2.6.5


changeset b8a5aed0fb7c in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=b8a5aed0fb7c
author: omajid
date: Tue Dec 29 10:40:43 2015 -0500

	6961123: setWMClass fails to null-terminate WM_CLASS string
	Reviewed-by: andrew, serb


changeset ef39ed3d2518 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=ef39ed3d2518
author: sgehwolf
date: Wed Nov 04 11:34:27 2015 +0100

	6425769: Allow specifying an address to bind JMX remote connector
	Reviewed-by: jbachorik, dfuchs


changeset 417751279615 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=417751279615
author: jbachorik
date: Mon Jan 04 10:07:08 2016 +0100

	8145982: JMXInterfaceBindingTest is failing intermittently
	Reviewed-by: chegar, sgehwolf, olagneau


changeset 852c8effb528 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=852c8effb528
author: jbachorik
date: Fri Jan 29 13:35:06 2016 +0100

	8146015: JMXInterfaceBindingTest is failing intermittently for IPv6 addresses
	Reviewed-by: dfuchs, sspitsyn


changeset 0b89eea70cf4 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=0b89eea70cf4
author: poonam
date: Mon Mar 21 13:48:36 2016 -0700

	8152335: Improve MethodHandle consistency
	Reviewed-by: vlivanov, acorn, jrose


changeset f4ba46656f02 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=f4ba46656f02
author: andrew
date: Wed Mar 23 21:08:29 2016 +0000

	Added tag jdk7u99-b00 for changeset 0b89eea70cf4


changeset e727fe32654c in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=e727fe32654c
author: andrew
date: Thu Mar 24 01:02:34 2016 +0000

	Merge jdk7u99-b00


changeset 7db52ae27b66 in /hg/release/icedtea7-forest-2.6/jdk
details: http://icedtea.classpath.org/hg/release/icedtea7-forest-2.6/jdk?cmd=changeset;node=7db52ae27b66
author: andrew
date: Thu Mar 24 21:35:22 2016 +0000

	Added tag icedtea-2.6.5 for changeset e727fe32654c


diffstat:

 .hgtags                                                               |    2 +
 make/jdk_generic_profile.sh                                           |    2 +-
 make/sun/xawt/Makefile                                                |    2 +-
 src/share/classes/java/lang/ClassLoader.java                          |    3 +
 src/share/classes/java/lang/invoke/MemberName.java                    |   29 +-
 src/share/classes/java/lang/invoke/MethodHandleNatives.java           |    2 +-
 src/share/classes/javax/swing/JMenu.java                              |    3 +-
 src/share/classes/sun/invoke/util/VerifyAccess.java                   |   68 +-
 src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java    |  212 ++++++-
 src/share/lib/management/management.properties                        |   13 +
 src/share/native/sun/security/ec/ECC_JNI.cpp                          |   43 +-
 src/solaris/classes/sun/awt/X11/XBaseWindow.java                      |    2 +-
 src/solaris/native/sun/awt/awt_Robot.c                                |   33 +
 test/javax/swing/JMenu/8071705/bug8071705.java                        |  207 ++++++
 test/sun/management/jmxremote/bootstrap/JMXAgentInterfaceBinding.java |  306 ++++++++++
 test/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java  |  267 ++++++++
 16 files changed, 1156 insertions(+), 38 deletions(-)

diffs (truncated from 1550 to 500 lines):

diff -r ab0f137e0eac -r 7db52ae27b66 .hgtags
--- a/.hgtags	Wed Jan 20 17:09:38 2016 +0000
+++ b/.hgtags	Thu Mar 24 21:35:22 2016 +0000
@@ -638,3 +638,5 @@
 5215185a1d57f11960998cdd3935b29c2b97ee25 icedtea-2.6.3
 3a74fee9ba00da3bd3a22492e1b069430a82574d jdk7u95-b00
 dc86038147b235413775e1400c32a7180e184811 icedtea-2.6.4
+0b89eea70cf4952b22dfe10ea8611ddb852d73d6 jdk7u99-b00
+e727fe32654c370a9b6dd16761b90a949194fb99 icedtea-2.6.5
diff -r ab0f137e0eac -r 7db52ae27b66 make/jdk_generic_profile.sh
--- a/make/jdk_generic_profile.sh	Wed Jan 20 17:09:38 2016 +0000
+++ b/make/jdk_generic_profile.sh	Thu Mar 24 21:35:22 2016 +0000
@@ -671,7 +671,7 @@
 
 # IcedTea versioning
 export ICEDTEA_NAME="IcedTea"
-export PACKAGE_VERSION="2.6.4"
+export PACKAGE_VERSION="2.6.5"
 export DERIVATIVE_ID="${ICEDTEA_NAME} ${PACKAGE_VERSION}"
 echo "Building ${DERIVATIVE_ID}"
 
diff -r ab0f137e0eac -r 7db52ae27b66 make/sun/xawt/Makefile
--- a/make/sun/xawt/Makefile	Wed Jan 20 17:09:38 2016 +0000
+++ b/make/sun/xawt/Makefile	Thu Mar 24 21:35:22 2016 +0000
@@ -125,7 +125,7 @@
 vpath %.c   $(PLATFORM_SRC)/native/common/deps/fontconfig2
 endif
 
-OTHER_LDLIBS = $(LIBM) -lawt -lXext -lX11 -lXrender $(LIBDL) \
+OTHER_LDLIBS = $(LIBM) -lawt -lXext -lX11 -lXrender -lXcomposite $(LIBDL) \
                    $(LDFLAGS_COMMON) $(AWT_RUNPATH) $(OTHER_LDFLAGS) -lXtst -lXi
 
 ifeq ($(SYSTEM_CUPS), true)
diff -r ab0f137e0eac -r 7db52ae27b66 src/share/classes/java/lang/ClassLoader.java
--- a/src/share/classes/java/lang/ClassLoader.java	Wed Jan 20 17:09:38 2016 +0000
+++ b/src/share/classes/java/lang/ClassLoader.java	Thu Mar 24 21:35:22 2016 +0000
@@ -654,6 +654,9 @@
         if (!checkName(name))
             throw new NoClassDefFoundError("IllegalName: " + name);
 
+        // Note:  Checking logic in java.lang.invoke.MemberName.checkForTypeAlias
+        // relies on the fact that spoofing is impossible if a class has a name
+        // of the form "java.*"
         if ((name != null) && name.startsWith("java.")) {
             throw new SecurityException
                 ("Prohibited package name: " +
diff -r ab0f137e0eac -r 7db52ae27b66 src/share/classes/java/lang/invoke/MemberName.java
--- a/src/share/classes/java/lang/invoke/MemberName.java	Wed Jan 20 17:09:38 2016 +0000
+++ b/src/share/classes/java/lang/invoke/MemberName.java	Thu Mar 24 21:35:22 2016 +0000
@@ -668,7 +668,7 @@
         assert(isResolved() == isResolved);
     }
 
-    void checkForTypeAlias() {
+    void checkForTypeAlias(Class<?> refc) {
         if (isInvocable()) {
             MethodType type;
             if (this.type instanceof MethodType)
@@ -676,16 +676,16 @@
             else
                 this.type = type = getMethodType();
             if (type.erase() == type)  return;
-            if (VerifyAccess.isTypeVisible(type, clazz))  return;
-            throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
+            if (VerifyAccess.isTypeVisible(type, refc))  return;
+            throw new LinkageError("bad method type alias: "+type+" not visible from "+refc);
         } else {
             Class<?> type;
             if (this.type instanceof Class<?>)
                 type = (Class<?>) this.type;
             else
                 this.type = type = getFieldType();
-            if (VerifyAccess.isTypeVisible(type, clazz))  return;
-            throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
+            if (VerifyAccess.isTypeVisible(type, refc))  return;
+            throw new LinkageError("bad field type alias: "+type+" not visible from "+refc);
         }
     }
 
@@ -844,10 +844,25 @@
             MemberName m = ref.clone();  // JVM will side-effect the ref
             assert(refKind == m.getReferenceKind());
             try {
+                // There are 4 entities in play here:
+                //   * LC: lookupClass
+                //   * REFC: symbolic reference class (MN.clazz before resolution);
+                //   * DEFC: resolved method holder (MN.clazz after resolution);
+                //   * PTYPES: parameter types (MN.type)
+                //
+                // What we care about when resolving a MemberName is consistency between DEFC and PTYPES.
+                // We do type alias (TA) checks on DEFC to ensure that. DEFC is not known until the JVM
+                // finishes the resolution, so do TA checks right after MHN.resolve() is over.
+                //
+                // All parameters passed by a caller are checked against MH type (PTYPES) on every invocation,
+                // so it is safe to call a MH from any context.
+                //
+                // REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't
+                // participate in method selection.
                 m = MethodHandleNatives.resolve(m, lookupClass);
-                m.checkForTypeAlias();
+                m.checkForTypeAlias(m.getDeclaringClass());
                 m.resolution = null;
-            } catch (LinkageError ex) {
+            } catch (ClassNotFoundException | LinkageError ex) {
                 // JVM reports that the "bytecode behavior" would get an error
                 assert(!m.isResolved());
                 m.resolution = ex;
diff -r ab0f137e0eac -r 7db52ae27b66 src/share/classes/java/lang/invoke/MethodHandleNatives.java
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java	Wed Jan 20 17:09:38 2016 +0000
+++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java	Thu Mar 24 21:35:22 2016 +0000
@@ -46,7 +46,7 @@
 
     static native void init(MemberName self, Object ref);
     static native void expand(MemberName self);
-    static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError;
+    static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError, ClassNotFoundException;
     static native int getMembers(Class<?> defc, String matchName, String matchSig,
             int matchFlags, Class<?> caller, int skip, MemberName[] results);
 
diff -r ab0f137e0eac -r 7db52ae27b66 src/share/classes/javax/swing/JMenu.java
--- a/src/share/classes/javax/swing/JMenu.java	Wed Jan 20 17:09:38 2016 +0000
+++ b/src/share/classes/javax/swing/JMenu.java	Thu Mar 24 21:35:22 2016 +0000
@@ -481,7 +481,8 @@
             }
             // Then the y:
             y = s.height + yOffset;    // Prefer dropping down
-            if (position.y + y + pmSize.height >= screenBounds.height &&
+            if (position.y + y + pmSize.height >= screenBounds.height
+                                                  + screenBounds.y &&
                 // popup doesn't fit - place it wherever there's more room
                 screenBounds.height - s.height < 2*(position.y
                                                   - screenBounds.y)) {
diff -r ab0f137e0eac -r 7db52ae27b66 src/share/classes/sun/invoke/util/VerifyAccess.java
--- a/src/share/classes/sun/invoke/util/VerifyAccess.java	Wed Jan 20 17:09:38 2016 +0000
+++ b/src/share/classes/sun/invoke/util/VerifyAccess.java	Thu Mar 24 21:35:22 2016 +0000
@@ -168,22 +168,66 @@
      * @param refc
      */
     public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
-        if (type == refc)  return true;  // easy check
+        if (type == refc) {
+            return true;  // easy check
+        }
         while (type.isArray())  type = type.getComponentType();
-        if (type.isPrimitive() || type == Object.class)  return true;
-        ClassLoader parent = type.getClassLoader();
-        if (parent == null)  return true;
-        ClassLoader child  = refc.getClassLoader();
-        if (child == null)  return false;
-        if (parent == child || loadersAreRelated(parent, child, true))
+        if (type.isPrimitive() || type == Object.class) {
             return true;
-        // Do it the hard way:  Look up the type name from the refc loader.
-        try {
-            Class<?> res = child.loadClass(type.getName());
-            return (type == res);
-        } catch (ClassNotFoundException ex) {
+        }
+        ClassLoader typeLoader = type.getClassLoader();
+        final ClassLoader refcLoader = refc.getClassLoader();
+        if (typeLoader == refcLoader) {
+            return true;
+        }
+        if (refcLoader == null && typeLoader != null) {
             return false;
         }
+        if (typeLoader == null && type.getName().startsWith("java.")) {
+            // Note:  The API for actually loading classes, ClassLoader.defineClass,
+            // guarantees that classes with names beginning "java." cannot be aliased,
+            // because class loaders cannot load them directly.
+            return true;
+        }
+
+        // Do it the hard way:  Look up the type name from the refc loader.
+        //
+        // Force the refc loader to report and commit to a particular binding for this type name (type.getName()).
+        //
+        // In principle, this query might force the loader to load some unrelated class,
+        // which would cause this query to fail (and the original caller to give up).
+        // This would be wasted effort, but it is expected to be very rare, occurring
+        // only when an attacker is attempting to create a type alias.
+        // In the normal case, one class loader will simply delegate to the other,
+        // and the same type will be visible through both, with no extra loading.
+        //
+        // It is important to go through Class.forName instead of ClassLoader.loadClass
+        // because Class.forName goes through the JVM system dictionary, which records
+        // the class lookup once for all. This means that even if a not-well-behaved class loader
+        // would "change its mind" about the meaning of the name, the Class.forName request
+        // will use the result cached in the JVM system dictionary. Note that the JVM system dictionary
+        // will record the first successful result. Unsuccessful results are not stored.
+        //
+        // We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary
+        // class loader about the binding of the proposed name (type.getName()).
+        // The looked up type ("res") is compared for equality against the proposed
+        // type ("type") and then is discarded.  Thus, the worst that can happen to
+        // the "child" class loader is that it is bothered to load and report a class
+        // that differs from "type"; this happens once due to JVM system dictionary
+        // memoization.  And the caller never gets to look at the alternate type binding
+        // ("res"), whether it exists or not.
+        final String name = type.getName();
+        Class<?> res = java.security.AccessController.doPrivileged(
+                new java.security.PrivilegedAction<Class>() {
+                    public Class<?> run() {
+                        try {
+                            return Class.forName(name, false, refcLoader);
+                        } catch (ClassNotFoundException | LinkageError e) {
+                            return null; // Assume the class is not found
+                        }
+                    }
+            });
+        return (type == res);
     }
 
     /**
diff -r ab0f137e0eac -r 7db52ae27b66 src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
--- a/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java	Wed Jan 20 17:09:38 2016 +0000
+++ b/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java	Thu Mar 24 21:35:22 2016 +0000
@@ -30,9 +30,12 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.lang.management.ManagementFactory;
 import java.net.InetAddress;
 import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.ServerSocket;
 import java.net.UnknownHostException;
 import java.rmi.NoSuchObjectException;
 import java.rmi.Remote;
@@ -40,6 +43,7 @@
 import java.rmi.registry.Registry;
 import java.rmi.server.RMIClientSocketFactory;
 import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RMISocketFactory;
 import java.rmi.server.RemoteObject;
 import java.rmi.server.UnicastRemoteObject;
 import java.security.KeyStore;
@@ -60,6 +64,8 @@
 import javax.management.remote.rmi.RMIConnectorServer;
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManagerFactory;
 import javax.rmi.ssl.SslRMIClientSocketFactory;
 import javax.rmi.ssl.SslRMIServerSocketFactory;
@@ -107,6 +113,8 @@
 
         public static final String PORT =
                 "com.sun.management.jmxremote.port";
+        public static final String HOST =
+                "com.sun.management.jmxremote.host";
         public static final String RMI_PORT =
                 "com.sun.management.jmxremote.rmi.port";
         public static final String CONFIG_FILE_NAME =
@@ -425,10 +433,14 @@
             checkAccessFile(accessFileName);
         }
 
+        final String bindAddress =
+                props.getProperty(PropertyNames.HOST);
+
         if (log.debugOn()) {
             log.debug("startRemoteConnectorServer",
                     Agent.getText("jmxremote.ConnectorBootstrap.starting") +
                     "\n\t" + PropertyNames.PORT + "=" + port +
+                    (bindAddress == null ? "" : "\n\t" + PropertyNames.HOST + "=" + bindAddress) +
                     "\n\t" + PropertyNames.RMI_PORT + "=" + rmiPort +
                     "\n\t" + PropertyNames.USE_SSL + "=" + useSsl +
                     "\n\t" + PropertyNames.USE_REGISTRY_SSL + "=" + useRegistrySsl +
@@ -459,7 +471,7 @@
                     sslConfigFileName, enabledCipherSuitesList,
                     enabledProtocolsList, sslNeedClientAuth,
                     useAuthentication, loginConfigName,
-                    passwordFileName, accessFileName);
+                    passwordFileName, accessFileName, bindAddress);
             cs = data.jmxConnectorServer;
             url = data.jmxRemoteURL;
             log.config("startRemoteConnectorServer",
@@ -629,12 +641,13 @@
             String sslConfigFileName,
             String[] enabledCipherSuites,
             String[] enabledProtocols,
-            boolean sslNeedClientAuth) {
+            boolean sslNeedClientAuth,
+            String bindAddress) {
         if (sslConfigFileName == null) {
-            return new SslRMIServerSocketFactory(
+            return new HostAwareSslSocketFactory(
                     enabledCipherSuites,
                     enabledProtocols,
-                    sslNeedClientAuth);
+                    sslNeedClientAuth, bindAddress);
         } else {
             checkRestrictedFile(sslConfigFileName);
             try {
@@ -697,11 +710,11 @@
                 SSLContext ctx = SSLContext.getInstance("SSL");
                 ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
 
-                return new SslRMIServerSocketFactory(
+                return new HostAwareSslSocketFactory(
                         ctx,
                         enabledCipherSuites,
                         enabledProtocols,
-                        sslNeedClientAuth);
+                        sslNeedClientAuth, bindAddress);
             } catch (Exception e) {
                 throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
             }
@@ -721,7 +734,8 @@
             boolean useAuthentication,
             String loginConfigName,
             String passwordFileName,
-            String accessFileName)
+            String accessFileName,
+            String bindAddress)
             throws IOException, MalformedURLException {
 
         /* Make sure we use non-guessable RMI object IDs.  Otherwise
@@ -729,7 +743,7 @@
          * IDs.  */
         System.setProperty("java.rmi.server.randomIDs", "true");
 
-        JMXServiceURL url = new JMXServiceURL("rmi", null, rmiPort);
+        JMXServiceURL url = new JMXServiceURL("rmi", bindAddress, rmiPort);
 
         Map<String, Object> env = new HashMap<String, Object>();
 
@@ -737,6 +751,8 @@
 
         env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter);
 
+        boolean useSocketFactory = bindAddress != null && !useSsl;
+
         if (useAuthentication) {
             if (loginConfigName != null) {
                 env.put("jmx.remote.x.login.config", loginConfigName);
@@ -761,7 +777,7 @@
             csf = new SslRMIClientSocketFactory();
             ssf = createSslRMIServerSocketFactory(
                     sslConfigFileName, enabledCipherSuites,
-                    enabledProtocols, sslNeedClientAuth);
+                    enabledProtocols, sslNeedClientAuth, bindAddress);
         }
 
         if (useSsl) {
@@ -771,6 +787,12 @@
                     ssf);
         }
 
+        if (useSocketFactory) {
+            ssf = new HostAwareSocketFactory(bindAddress);
+            env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
+                    ssf);
+        }
+
         JMXConnectorServer connServer = null;
         try {
             connServer =
@@ -790,6 +812,10 @@
             registry =
                     new SingleEntryRegistry(port, csf, ssf,
                     "jmxrmi", exporter.firstExported);
+        } else if (useSocketFactory) {
+            registry =
+                    new SingleEntryRegistry(port, csf, ssf,
+                    "jmxrmi", exporter.firstExported);
         } else {
             registry =
                     new SingleEntryRegistry(port,
@@ -823,4 +849,172 @@
     private static final ClassLogger log =
         new ClassLogger(ConnectorBootstrap.class.getPackage().getName(),
                         "ConnectorBootstrap");
+
+    private static class HostAwareSocketFactory implements RMIServerSocketFactory {
+
+        private final String bindAddress;
+
+        private HostAwareSocketFactory(String bindAddress) {
+             this.bindAddress = bindAddress;
+        }
+
+        @Override
+        public ServerSocket createServerSocket(int port) throws IOException {
+            if (bindAddress == null) {
+                return new ServerSocket(port);
+            } else {
+                try {
+                    InetAddress addr = InetAddress.getByName(bindAddress);
+                    return new ServerSocket(port, 0, addr);
+                } catch (UnknownHostException e) {
+                    return new ServerSocket(port);
+                }
+            }
+        }
+    }
+
+    private static class HostAwareSslSocketFactory extends SslRMIServerSocketFactory {
+
+        private final String bindAddress;
+        private final String[] enabledCipherSuites;
+        private final String[] enabledProtocols;
+        private final boolean needClientAuth;
+        private final SSLContext context;
+
+        private HostAwareSslSocketFactory(String[] enabledCipherSuites,
+                                          String[] enabledProtocols,
+                                          boolean sslNeedClientAuth,
+                                          String bindAddress) throws IllegalArgumentException {
+            this(null, enabledCipherSuites, enabledProtocols, sslNeedClientAuth, bindAddress);
+        }
+
+        private HostAwareSslSocketFactory(SSLContext ctx,
+                                          String[] enabledCipherSuites,
+                                          String[] enabledProtocols,
+                                          boolean sslNeedClientAuth,
+                                          String bindAddress) throws IllegalArgumentException {
+            this.context = ctx;
+            this.bindAddress = bindAddress;
+            this.enabledProtocols = enabledProtocols;
+            this.enabledCipherSuites = enabledCipherSuites;
+            this.needClientAuth = sslNeedClientAuth;
+            checkValues(ctx, enabledCipherSuites, enabledProtocols);
+        }
+
+        @Override
+        public ServerSocket createServerSocket(int port) throws IOException {
+            if (bindAddress != null) {
+                try {
+                    InetAddress addr = InetAddress.getByName(bindAddress);
+                    return new SslServerSocket(port, 0, addr, context,
+                                               enabledCipherSuites, enabledProtocols, needClientAuth);
+                } catch (UnknownHostException e) {
+                    return new SslServerSocket(port, context,
+                                               enabledCipherSuites, enabledProtocols, needClientAuth);
+                }
+            } else {
+                return new SslServerSocket(port, context,
+                                           enabledCipherSuites, enabledProtocols, needClientAuth);
+            }
+        }
+
+        private static void checkValues(SSLContext context,
+                                        String[] enabledCipherSuites,
+                                        String[] enabledProtocols) throws IllegalArgumentException {
+            // Force the initialization of the default at construction time,
+            // rather than delaying it to the first time createServerSocket()
+            // is called.
+            //
+            final SSLSocketFactory sslSocketFactory =
+                    context == null ?
+                        (SSLSocketFactory)SSLSocketFactory.getDefault() : context.getSocketFactory();
+            SSLSocket sslSocket = null;
+            if (enabledCipherSuites != null || enabledProtocols != null) {
+                try {
+                    sslSocket = (SSLSocket) sslSocketFactory.createSocket();
+                } catch (Exception e) {
+                    final String msg = "Unable to check if the cipher suites " +
+                            "and protocols to enable are supported";
+                    throw (IllegalArgumentException)
+                    new IllegalArgumentException(msg).initCause(e);
+                }
+            }
+
+            // Check if all the cipher suites and protocol versions to enable
+            // are supported by the underlying SSL/TLS implementation and if
+            // true create lists from arrays.
+            //
+            if (enabledCipherSuites != null) {
+                sslSocket.setEnabledCipherSuites(enabledCipherSuites);
+            }
+            if (enabledProtocols != null) {
+                sslSocket.setEnabledProtocols(enabledProtocols);
+            }
+        }
+    }
+
+    private static class SslServerSocket extends ServerSocket {
+
+        private static SSLSocketFactory defaultSSLSocketFactory;
+        private final String[] enabledCipherSuites;
+        private final String[] enabledProtocols;
+        private final boolean needClientAuth;
+        private final SSLContext context;
+
+        private SslServerSocket(int port,
+                                SSLContext ctx,
+                                String[] enabledCipherSuites,
+                                String[] enabledProtocols,
+                                boolean needClientAuth) throws IOException {
+            super(port);
+            this.enabledProtocols = enabledProtocols;
+            this.enabledCipherSuites = enabledCipherSuites;
+            this.needClientAuth = needClientAuth;
+            this.context = ctx;
+        }
+


More information about the distro-pkg-dev mailing list