Author: ritchiem
Date: Mon Apr 13 11:59:29 2009
New Revision: 764422

URL: http://svn.apache.org/viewvc?rev=764422&view=rev
Log:
QPID-1511 : Adds authentication and ssl encryption capabilities to the RMI 
based JMXConnectorServer in use, enforces use of the custom 
MBeanInvocationhandlerImp when using the RMI based JMX, and implements a 
customised RMI registry to prevent external changes
being possible. Updated Management console accordingly.

Patch from Robbert Gemmell <[email protected]>

merged from trunk r744113


Added:
    
qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/
      - copied from r744113, 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/
    
qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
      - copied unchanged from r744113, 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
    
qpid/branches/0.5-fix/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/
      - copied from r744113, 
qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/
    
qpid/branches/0.5-fix/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
      - copied unchanged from r744113, 
qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
Modified:
    qpid/branches/0.5-fix/qpid/   (props changed)
    qpid/branches/0.5-fix/qpid/java/broker/etc/config.xml
    qpid/branches/0.5-fix/qpid/java/broker/etc/persistent_config.xml
    qpid/branches/0.5-fix/qpid/java/broker/etc/transient_config.xml
    
qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
    
qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java
    
qpid/branches/0.5-fix/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/JMXConnnectionFactory.java
    
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java
    
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini
    
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini
    
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini

Propchange: qpid/branches/0.5-fix/qpid/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Apr 13 11:59:29 2009
@@ -1 +1 @@
-/qpid/trunk/qpid:742626,743015,743028-743029,743304,743306,743311,743357
+/qpid/trunk/qpid:742626,743015,743028-743029,743304,743306,743311,743357,744113

Modified: qpid/branches/0.5-fix/qpid/java/broker/etc/config.xml
URL: 
http://svn.apache.org/viewvc/qpid/branches/0.5-fix/qpid/java/broker/etc/config.xml?rev=764422&r1=764421&r2=764422&view=diff
==============================================================================
--- qpid/branches/0.5-fix/qpid/java/broker/etc/config.xml (original)
+++ qpid/branches/0.5-fix/qpid/java/broker/etc/config.xml Mon Apr 13 11:59:29 
2009
@@ -43,9 +43,15 @@
         <socketSendBuffer>32768</socketSendBuffer>
     </connector>
     <management>
-        <enabled>false</enabled>
+        <enabled>true</enabled>
         <jmxport>8999</jmxport>
         <security-enabled>false</security-enabled>
+        <ssl>
+            <enabled>true</enabled>
+            <!-- Update below path to your keystore location, eg 
${conf}/qpid.keystore  -->
+            
<keyStorePath>${prefix}/../test_resources/ssl/keystore.jks</keyStorePath>
+            <keyStorePassword>password</keyStorePassword>
+        </ssl>
     </management>
     <advanced>
         <filterchain enableExecutorPool="true"/>

Modified: qpid/branches/0.5-fix/qpid/java/broker/etc/persistent_config.xml
URL: 
http://svn.apache.org/viewvc/qpid/branches/0.5-fix/qpid/java/broker/etc/persistent_config.xml?rev=764422&r1=764421&r2=764422&view=diff
==============================================================================
--- qpid/branches/0.5-fix/qpid/java/broker/etc/persistent_config.xml (original)
+++ qpid/branches/0.5-fix/qpid/java/broker/etc/persistent_config.xml Mon Apr 13 
11:59:29 2009
@@ -35,8 +35,15 @@
         <socketSendBuffer>32768</socketSendBuffer>
     </connector>
     <management>
-        <enabled>false</enabled>
+        <enabled>true</enabled>
         <jmxport>8999</jmxport>
+        <security-enabled>false</security-enabled>
+        <ssl>
+            <enabled>true</enabled>
+            <!-- Update below path to your keystore location, eg 
${conf}/qpid.keystore  -->
+            
<keyStorePath>${prefix}/../test_resources/ssl/keystore.jks</keyStorePath>
+            <keyStorePassword>password</keyStorePassword>
+        </ssl>
     </management>
     <advanced>
         <filterchain enableExecutorPool="true"/>

Modified: qpid/branches/0.5-fix/qpid/java/broker/etc/transient_config.xml
URL: 
http://svn.apache.org/viewvc/qpid/branches/0.5-fix/qpid/java/broker/etc/transient_config.xml?rev=764422&r1=764421&r2=764422&view=diff
==============================================================================
--- qpid/branches/0.5-fix/qpid/java/broker/etc/transient_config.xml (original)
+++ qpid/branches/0.5-fix/qpid/java/broker/etc/transient_config.xml Mon Apr 13 
11:59:29 2009
@@ -35,8 +35,15 @@
         <socketSendBuffer>32768</socketSendBuffer>
     </connector>
     <management>
-        <enabled>false</enabled>
+        <enabled>true</enabled>
         <jmxport>8999</jmxport>
+        <security-enabled>false</security-enabled>
+        <ssl>
+            <enabled>true</enabled>
+            <!-- Update below path to your keystore location, eg 
${conf}/qpid.keystore  -->
+            
<keyStorePath>${prefix}/../test_resources/ssl/keystore.jks</keyStorePath>
+            <keyStorePassword>password</keyStorePassword>
+        </ssl>
     </management>
     <advanced>
         <filterchain enableExecutorPool="true"/>

Modified: 
qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
URL: 
http://svn.apache.org/viewvc/qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java?rev=764422&r1=764421&r2=764422&view=diff
==============================================================================
--- 
qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
 (original)
+++ 
qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
 Mon Apr 13 11:59:29 2009
@@ -20,6 +20,7 @@
  */
 package org.apache.qpid.server.management;
 
+import org.apache.commons.configuration.ConfigurationException;
 import org.apache.log4j.Logger;
 import org.apache.qpid.AMQException;
 import org.apache.qpid.server.registry.ApplicationRegistry;
@@ -27,6 +28,7 @@
 import 
org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase;
 import 
org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase;
 import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator;
 import 
org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HashedInitialiser;
 import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser;
 
@@ -37,31 +39,45 @@
 import javax.management.remote.JMXConnectorServerFactory;
 import javax.management.remote.JMXServiceURL;
 import javax.management.remote.MBeanServerForwarder;
+import javax.management.remote.rmi.RMIConnectorServer;
+import javax.management.remote.rmi.RMIJRMPServerImpl;
+import javax.management.remote.rmi.RMIServerImpl;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+import javax.rmi.ssl.SslRMIServerSocketFactory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+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.rmi.server.UnicastRemoteObject;
 import java.util.HashMap;
 import java.util.Map;
 
 /**
- * This class starts up an MBeanserver. If out of the box agent is being used 
then there are no security features
- * implemented. To use the security features like user authentication, turn 
off the jmx options in the "QPID_OPTS" env
- * variable and use JMXMP connector server. If JMXMP connector is not 
available, then the standard JMXConnector will be
- * used, which again doesn't have user authentication.
+ * This class starts up an MBeanserver. If out of the box agent has been 
enabled then there are no 
+ * security features implemented like user authentication and authorisation.
  */
 public class JMXManagedObjectRegistry implements ManagedObjectRegistry
 {
     private static final Logger _log = 
Logger.getLogger(JMXManagedObjectRegistry.class);
+    private static final Logger _startupLog = Logger.getLogger("Qpid.Broker");
+    
+    public static final String MANAGEMENT_PORT_CONFIG_PATH = 
"management.jmxport";
+    public static final int MANAGEMENT_PORT_DEFAULT = 8999;
+    public static final int PORT_EXPORT_OFFSET = 100;
 
     private final MBeanServer _mbeanServer;
     private Registry _rmiRegistry;
-    private JMXServiceURL _jmxURL;
     
-    public static final String MANAGEMENT_PORT_CONFIG_PATH = 
"management.jmxport";
-    public static final int MANAGEMENT_PORT_DEFAULT = 8999;
 
     public JMXManagedObjectRegistry() throws AMQException
     {
@@ -77,44 +93,38 @@
     }
 
 
-    public void start() throws IOException
+    public void start() throws IOException, ConfigurationException
     {
-        // Check if the "QPID_OPTS" is set to use Out of the Box JMXAgent
+        //check if system properties are set to use the JVM's out-of-the-box 
JMXAgent
         if (areOutOfTheBoxJMXOptionsSet())
         {
-            _log.info("JMX: Using the out of the box JMX Agent");
+            _log.warn("JMX: Using the out of the box JMX Agent");
+            _startupLog.warn("JMX: Using the out of the box JMX Agent");
             return;
         }
 
         IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
 
-        boolean security = 
appRegistry.getConfiguration().getBoolean("management.security-enabled", false);
+        boolean jmxmpSecurity = 
appRegistry.getConfiguration().getBoolean("management.security-enabled", false);
         int port = 
appRegistry.getConfiguration().getInt(MANAGEMENT_PORT_CONFIG_PATH, 
MANAGEMENT_PORT_DEFAULT);
 
-        if (security)
-        {
-            // For SASL using JMXMP
-            _jmxURL = new JMXServiceURL("jmxmp", null, port);
+        //retrieve the Principal Database assigned to JMX authentication duties
+        String jmxDatabaseName = 
appRegistry.getConfiguration().getString("security.jmx.principal-database");
+        Map<String, PrincipalDatabase> map = 
appRegistry.getDatabaseManager().getDatabases();        
+        PrincipalDatabase db = map.get(jmxDatabaseName);
 
-            Map env = new HashMap();
-            Map<String, PrincipalDatabase> map = 
appRegistry.getDatabaseManager().getDatabases();
-            PrincipalDatabase db = null;
+        final JMXConnectorServer cs;
+        HashMap<String,Object> env = new HashMap<String,Object>();
 
-            for (Map.Entry<String, PrincipalDatabase> entry : map.entrySet())
-            {
-                if (entry.getValue() instanceof 
Base64MD5PasswordFilePrincipalDatabase)
-                {
-                    db = entry.getValue();
-                    break;
-                }
-                else if (entry.getValue() instanceof 
PlainPasswordFilePrincipalDatabase)
-                {
-                    db = entry.getValue();
-                }
-            }
+        if (jmxmpSecurity)
+        {
+            // For SASL using JMXMP
+            JMXServiceURL jmxURL = new JMXServiceURL("jmxmp", null, port);
 
+            String saslType = null;
             if (db instanceof Base64MD5PasswordFilePrincipalDatabase)
             {
+                saslType = "SASL/CRAM-MD5";
                 env.put("jmx.remote.profiles", "SASL/CRAM-MD5");
                 CRAMMD5HashedInitialiser initialiser = new 
CRAMMD5HashedInitialiser();
                 initialiser.initialise(db);
@@ -122,6 +132,7 @@
             }
             else if (db instanceof PlainPasswordFilePrincipalDatabase)
             {
+                saslType = "SASL/PLAIN";
                 PlainInitialiser initialiser = new PlainInitialiser();
                 initialiser.initialise(db);
                 env.put("jmx.remote.sasl.callback.handler", 
initialiser.getCallbackHandler());
@@ -131,43 +142,209 @@
             //workaround NPE generated from env map classloader issue when 
using Eclipse 3.4 to launch
             env.put("jmx.remote.profile.provider.class.loader", 
this.getClass().getClassLoader());
 
-            // Enable the SSL security and server authentication
-            /*
-           SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory();
-           SslRMIServerSocketFactory ssf = new SslRMIServerSocketFactory();
-           env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, 
csf);
-           env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, 
ssf);
-            */
-
-            JMXConnectorServer cs = 
JMXConnectorServerFactory.newJMXConnectorServer(_jmxURL, env, _mbeanServer);
-            MBeanServerForwarder mbsf = 
MBeanInvocationHandlerImpl.newProxyInstance();
-            cs.setMBeanServerForwarder(mbsf);
-            cs.start();
-            _log.warn("JMX: Started JMXConnector server  on port '" + port + 
"' with SASL");
-
+            _log.warn("Starting JMXMP based JMX ConnectorServer on port '" + 
port + "' with " + saslType);
+            _startupLog.warn("Starting JMXMP based JMX ConnectorServer on port 
'" + port + "' with " + saslType);
+            
+            cs = JMXConnectorServerFactory.newJMXConnectorServer(jmxURL, env, 
_mbeanServer);
         }
         else
-        {
-            startJMXConnectorServer(port);
-            _log.warn("JMX: Started JMXConnector server on port '" + port + "' 
with security disabled");
+        {   
+            //Socket factories for the RMIConnectorServer, either default or 
SLL depending on configuration
+            RMIClientSocketFactory csf;
+            RMIServerSocketFactory ssf;
+            
+            //check ssl enabled option in config, default to true if option is 
not set
+            boolean sslEnabled = 
appRegistry.getConfiguration().getBoolean("management.ssl.enabled", true);
+
+            if (sslEnabled)
+            {
+                //set the SSL related system properties used by the SSL RMI 
socket factories to the values
+                //given in the configuration file, unless command line 
settings have already been specified
+                String keyStorePath;
+                
+                if(System.getProperty("javax.net.ssl.keyStore") != null)
+                {
+                    keyStorePath = 
System.getProperty("javax.net.ssl.keyStore");
+                }
+                else{
+                    keyStorePath = 
appRegistry.getConfiguration().getString("management.ssl.keyStorePath", null);
+                }
+                
+                //check the keystore path value is valid
+                if (keyStorePath == null)
+                {
+                    throw new ConfigurationException("JMX management SSL 
keystore path not defined, " +
+                                                        "unable to start SSL 
protected JMX ConnectorServer");
+                }
+                else
+                {
+                    //ensure the system property is set
+                    System.setProperty("javax.net.ssl.keyStore", keyStorePath);
+                    
+                    //check the file is usable
+                    File ksf = new File(keyStorePath);
+                    
+                    if (!ksf.exists())
+                    {
+                        throw new FileNotFoundException("Cannot find JMX 
management SSL keystore file " + ksf);
+                    }
+                    if (!ksf.canRead())
+                    {
+                        throw new FileNotFoundException("Cannot read JMX 
management SSL keystore file: " 
+                                                        + ksf +  ". Check 
permissions.");
+                    }
+                    
+                    _log.info("JMX ConnectorServer using SSL keystore file " + 
ksf.getAbsolutePath());
+                    _startupLog.info("JMX ConnectorServer using SSL keystore 
file " + ksf.getAbsolutePath());
+                }
+
+                //check the key store password is set
+                if (System.getProperty("javax.net.ssl.keyStorePassword") == 
null)
+                {
+                
+                    if 
(appRegistry.getConfiguration().getString("management.ssl.keyStorePassword") == 
null)
+                    {
+                        throw new ConfigurationException("JMX management SSL 
keystore password not defined, " +
+                                                                "unable to 
start requested SSL protected JMX server");
+                    }
+                    else
+                    {
+                        System.setProperty("javax.net.ssl.keyStorePassword",
+                                
appRegistry.getConfiguration().getString("management.ssl.keyStorePassword"));
+                    }
+                }
+
+                //create the SSL RMI socket factories
+                csf = new SslRMIClientSocketFactory();
+                ssf = new SslRMIServerSocketFactory();
+
+                _log.warn("Starting JMX ConnectorServer on port '"+ port + "' 
(+" + 
+                        (port +PORT_EXPORT_OFFSET) + ") with SSL");
+                _startupLog.warn("Starting JMX ConnectorServer on port '"+ 
port + "' (+" + 
+                        (port +PORT_EXPORT_OFFSET) + ") with SSL");
+            }
+            else
+            {
+                //Do not specify any specific RMI socket factories, resulting 
in use of the defaults.
+                csf = null;
+                ssf = null;
+                
+                _log.warn("Starting JMX ConnectorServer on port '" + port + "' 
(+" + (port +PORT_EXPORT_OFFSET) + ")");
+                _startupLog.warn("Starting JMX ConnectorServer on port '" + 
port + "' (+" + (port +PORT_EXPORT_OFFSET) + ")");
+            }
+            
+            //add a JMXAuthenticator implementation the env map to 
authenticate the RMI based JMX connector server
+            RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator();
+            rmipa.setPrincipalDatabase(db);
+            env.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
+            
+            /*
+             * Start a RMI registry on the management port, to hold the JMX 
RMI ConnectorServer stub. 
+             * Using custom socket factory to prevent anyone (including us 
unfortunately) binding to the registry using RMI.
+             * As a result, only binds made using the object reference will 
succeed, thus securing it from external change. 
+             */
+            System.setProperty("java.rmi.server.randomIDs", "true");
+            _rmiRegistry = LocateRegistry.createRegistry(port, null, new 
CustomRMIServerSocketFactory());
+            
+            /*
+             * We must now create the RMI ConnectorServer manually, as the JMX 
Factory methods use RMI calls 
+             * to bind the ConnectorServer to the registry, which will now 
fail as for security we have
+             * locked it from any RMI based modifications, including our own. 
Instead, we will manually bind 
+             * the RMIConnectorServer stub to the registry using its object 
reference, which will still succeed.
+             * 
+             * The registry is exported on the defined management port 'port'. 
We will export the RMIConnectorServer
+             * on 'port +1'. Use of these two well-defined ports will ease any 
navigation through firewall's. 
+             */
+            final RMIServerImpl rmiConnectorServerStub = new 
RMIJRMPServerImpl(port+PORT_EXPORT_OFFSET, csf, ssf, env); 
+            final String hostname = InetAddress.getLocalHost().getHostName();
+            final JMXServiceURL externalUrl = new JMXServiceURL(
+                    
"service:jmx:rmi://"+hostname+":"+(port+PORT_EXPORT_OFFSET)+"/jndi/rmi://"+hostname+":"+port+"/jmxrmi");
+
+            final JMXServiceURL internalUrl = new JMXServiceURL("rmi", 
hostname, port+PORT_EXPORT_OFFSET);
+            cs = new RMIConnectorServer(internalUrl, env, 
rmiConnectorServerStub, _mbeanServer)
+            {   
+                @Override  
+                public synchronized void start() throws IOException
+                {   
+                    try
+                    {   
+                        //manually bind the connector server to the registry 
at key 'jmxrmi', like the out-of-the-box agent                        
+                        _rmiRegistry.bind("jmxrmi", rmiConnectorServerStub);   
+                    }
+                    catch (AlreadyBoundException abe)
+                    {   
+                        //key was already in use. shouldnt happen here as its 
a new registry, unbindable by normal means.
+                        
+                        //IOExceptions are the only checked type throwable by 
the method, wrap and rethrow
+                        IOException ioe = new IOException(abe.getMessage());   
+                        ioe.initCause(abe);   
+                        throw ioe;   
+                    }
+                    
+                    //now do the normal tasks
+                    super.start();   
+                }   
+                
+                @Override  
+                public JMXServiceURL getAddress()
+                {
+                    //must return our pre-crafted url that includes the full 
details, inc JNDI details
+                    return externalUrl;
+                }   
+
+            };   
         }
+
+        //Add the custom invoker as an MBeanServerForwarder, and start the 
RMIConnectorServer.
+        MBeanServerForwarder mbsf = 
MBeanInvocationHandlerImpl.newProxyInstance();
+        cs.setMBeanServerForwarder(mbsf);
+        cs.start();
     }
 
-    /**
-     * Starts up an RMIRegistry at configured port and attaches a 
JMXConnectorServer to it.
-     *
-     * @param port
-     *
-     * @throws IOException
+    /*
+     * Custom RMIServerSocketFactory class, used to prevent updates to the RMI 
registry. 
+     * Supplied to the registry at creation, this will prevent RMI-based 
operations on the
+     * registry such as attempting to bind a new object, thereby securing it 
from tampering.
+     * This is accomplished by always returning null when attempting to 
determine the address
+     * of the caller, thus ensuring the registry will refuse the attempt. 
Calls to bind etc
+     * made using the object reference will not be affected and continue to 
operate normally.
      */
-    private void startJMXConnectorServer(int port) throws IOException
+    
+    private class CustomRMIServerSocketFactory implements 
RMIServerSocketFactory
     {
-        startRMIRegistry(port);
-        _jmxURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" 
+ port + "/jmxrmi");
-        JMXConnectorServer cs = 
JMXConnectorServerFactory.newJMXConnectorServer(_jmxURL, null, _mbeanServer);
-        cs.start();
+
+        public ServerSocket createServerSocket(int port) throws IOException
+        {
+            return new NoLocalAddressServerSocket(port);
+        }
+
+        private class NoLocalAddressServerSocket extends ServerSocket
+        {
+            NoLocalAddressServerSocket(int port) throws IOException
+            {
+                super(port);
+            }
+
+            @Override
+            public Socket accept() throws IOException
+            {
+                Socket s = new NoLocalAddressSocket();
+                super.implAccept(s);
+                return s;
+            }
+        }
+
+        private class NoLocalAddressSocket extends Socket
+        {
+            @Override
+            public InetAddress getInetAddress()
+            {
+                return null;
+            }
+        }
     }
 
+
     public void registerObject(ManagedObject managedObject) throws JMException
     {
         _mbeanServer.registerMBean(managedObject, 
managedObject.getObjectName());
@@ -178,11 +355,7 @@
         _mbeanServer.unregisterMBean(managedObject.getObjectName());
     }
 
-    /**
-     * Checks is the "QPID_OPTS" env variable is set to use the out of the box 
JMXAgent.
-     *
-     * @return
-     */
+    // checks if the system properties are set which enable the JVM's 
out-of-the-box JMXAgent.
     private boolean areOutOfTheBoxJMXOptionsSet()
     {
         if (System.getProperty("com.sun.management.jmxremote") != null)
@@ -198,19 +371,6 @@
         return false;
     }
 
-    /**
-     * Starts the rmi registry at given port
-     *
-     * @param port
-     *
-     * @throws RemoteException
-     */
-    private void startRMIRegistry(int port) throws RemoteException
-    {
-        System.setProperty("java.rmi.server.randomIDs", "true");
-        _rmiRegistry = LocateRegistry.createRegistry(port);
-    }
-
     // stops the RMIRegistry, if it was running and bound to a port
     public void close() throws RemoteException
     {

Modified: 
qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java
URL: 
http://svn.apache.org/viewvc/qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java?rev=764422&r1=764421&r2=764422&view=diff
==============================================================================
--- 
qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java
 (original)
+++ 
qpid/branches/0.5-fix/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java
 Mon Apr 13 11:59:29 2009
@@ -21,6 +21,9 @@
 package org.apache.qpid.server.management;
 
 import javax.management.JMException;
+
+import org.apache.commons.configuration.ConfigurationException;
+
 import java.rmi.RemoteException;
 import java.io.IOException;
 
@@ -38,7 +41,7 @@
  */
 public interface ManagedObjectRegistry
 {
-    void start() throws IOException;
+    void start() throws IOException, ConfigurationException;
 
     void registerObject(ManagedObject managedObject) throws JMException;
 

Modified: 
qpid/branches/0.5-fix/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/JMXConnnectionFactory.java
URL: 
http://svn.apache.org/viewvc/qpid/branches/0.5-fix/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/JMXConnnectionFactory.java?rev=764422&r1=764421&r2=764422&view=diff
==============================================================================
--- 
qpid/branches/0.5-fix/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/JMXConnnectionFactory.java
 (original)
+++ 
qpid/branches/0.5-fix/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/JMXConnnectionFactory.java
 Mon Apr 13 11:59:29 2009
@@ -29,6 +29,7 @@
 import javax.management.remote.JMXConnector;
 import javax.management.remote.JMXConnectorFactory;
 import javax.management.remote.JMXServiceURL;
+import javax.net.ssl.SSLException;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.sasl.SaslClientFactory;
 
@@ -40,8 +41,13 @@
 import 
org.apache.qpid.management.common.sasl.UsernameHashedPasswordCallbackHandler;
 
 public class JMXConnnectionFactory {
-
-       public static JMXConnector getJMXConnection(long timeout, String host, 
int port, String username, String password) throws Exception
+       
+       private static final String NON_JRMP_SERVER = "non-JRMP server at 
remote endpoint";
+       private static final String SERVER_SUPPORTED_PROFILES = "The server 
supported profiles";
+       private static final String CLIENT_REQUIRED_PROFILES = "do not match 
the client required profiles";
+       
+       public static JMXConnector getJMXConnection(long timeout, String host, 
int port, String username, String password) 
+                                                                               
throws SSLException, IOException, Exception
        {
                //auto-negotiate an RMI or JMXMP (SASL/CRAM-MD5 or SASL/PLAIN) 
JMX connection to broker
         try
@@ -51,11 +57,30 @@
         catch (IOException rmiIOE)
         {
             // check if the ioe was raised because we tried connecting to a 
non RMI-JRMP based JMX server
-            boolean jrmpServer = !rmiIOE.getMessage().contains("non-JRMP 
server at remote endpoint");
+            boolean jrmpServer = 
!rmiIOE.getMessage().contains(NON_JRMP_SERVER);
 
             if (jrmpServer)
             {
-                throw rmiIOE;
+                //it was an RMI-JRMP based JMX server, so something else went 
wrong. Check for SSL issues.
+                Throwable rmiIOECause = rmiIOE.getCause();
+                boolean isSSLException = false;
+                if (rmiIOECause != null)
+                {
+                    isSSLException = rmiIOECause instanceof SSLException;
+                }
+                
+                //if it was an SSLException based cause, throw it
+                if (isSSLException)
+                {
+                    throw (SSLException) rmiIOECause;
+                }
+                else
+                {
+                    //can't determine cause, throw new IOE citing the original 
as cause
+                    IOException nioe = new IOException();
+                    nioe.initCause(rmiIOE);
+                    throw nioe;
+                }
             }
             else
             {
@@ -67,8 +92,8 @@
                 catch (IOException cramIOE)
                 {
                     // check if the IOE was raised because we tried connecting 
to a SASL/PLAIN server using SASL/CRAM-MD5
-                    boolean plainProfileServer = 
cramIOE.getMessage().contains("The server supported profiles [SASL/PLAIN]" +
-                                                                               
    " do not match the client required profiles [SASL/CRAM-MD5]");
+                    boolean plainProfileServer = 
cramIOE.getMessage().contains(SERVER_SUPPORTED_PROFILES + 
+                               " [" + Constants.SASL_PLAIN + "] " + 
CLIENT_REQUIRED_PROFILES + " [" + Constants.SASL_CRAMMD5 + "]");
 
                     if (!plainProfileServer)
                     {
@@ -87,7 +112,7 @@
                         {
                             /* Out of options now. Check that the IOE was 
raised because we tried connecting to a server
                              * which didnt support SASL/PLAIN. If so, signal 
an unknown profile type. If not, raise the exception. */
-                            boolean unknownProfile = 
cramIOE.getMessage().contains("do not match the client required profiles 
[SASL/PLAIN]");
+                            boolean unknownProfile = 
plainIOE.getMessage().contains(CLIENT_REQUIRED_PROFILES + " [" + 
Constants.SASL_PLAIN + "]");
 
                             if (unknownProfile)
                             {
@@ -106,18 +131,19 @@
         }
        }
        
-       private static JMXConnector createJMXconnector(String connectionType, 
long timeout, String host, int port, String userName, String password) throws 
IOException, Exception
+       private static JMXConnector createJMXconnector(String connectionType, 
long timeout, String host, int port, 
+                                                       String userName, String 
password) throws IOException, Exception
     {
            Map<String, Object> env = new HashMap<String, Object>();
-           String securityMechanism = null;
            JMXServiceURL jmxUrl = null;
            
         if (connectionType == "RMI")
         {
-            securityMechanism = Constants.MECH_PLAIN;
-
             jmxUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + host 
+ ":" + port + "/jmxrmi");
-            env = null;
+
+            //Add user credential's to environment map for RMIConnector 
startup. 
+            //These will be used for authentication by the remote 
RMIConnectorServer if supported, or ignored otherwise.
+            env.put(JMXConnector.CREDENTIALS, new String[] 
{userName,password});
         }
         else if (connectionType.contains("JMXMP"))
         {
@@ -143,8 +169,6 @@
 
             if (connectionType == "JMXMP_CRAM-MD5")
             {
-                securityMechanism = Constants.MECH_CRAMMD5;
-
                 Map<String, Class<? extends SaslClientFactory>> map = new 
HashMap<String, Class<? extends SaslClientFactory>>();
                 map.put("CRAM-MD5-HASHED", 
CRAMMD5HashedSaslClientFactory.class);
                 Security.addProvider(new JCAProvider(map));
@@ -156,8 +180,6 @@
             }
             else if (connectionType == "JMXMP_PLAIN")
             {
-                securityMechanism = Constants.MECH_PLAIN;
-
                 Security.addProvider(new SaslProvider());
                 CallbackHandler handler = new 
UserPasswordCallbackHandler(userName, password);
                 env.put("jmx.remote.profiles", Constants.SASL_PLAIN);
@@ -165,7 +187,7 @@
             }
             else
             {
-                throw new Exception("Unknown authentication mechanism");
+                throw new Exception("Unknown JMXMP authentication mechanism");
             }
         }
         else

Modified: 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java
URL: 
http://svn.apache.org/viewvc/qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java?rev=764422&r1=764421&r2=764422&view=diff
==============================================================================
--- 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java
 (original)
+++ 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java
 Mon Apr 13 11:59:29 2009
@@ -24,6 +24,11 @@
 
 import java.io.IOException;
 
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLKeyException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+
 import org.apache.qpid.management.ui.ApplicationRegistry;
 import org.apache.qpid.management.ui.ApplicationWorkbenchAdvisor;
 import org.apache.qpid.management.ui.Constants;
@@ -47,6 +52,10 @@
     public static final String SERVER_UNAVAILABLE = "Unable to connect to the 
specified Qpid JMX server";
     public static final String INVALID_PERSPECTIVE = "Invalid Perspective";
     public static final String CHANGE_PERSPECTIVE = "Please use the Qpid 
Management Perspective";
+    
+    private static final String SSL_EMPTY_TRUSTANCHORS = "the trustAnchors 
parameter must be non-empty";
+    private static final String SSL_UNABLE_TO_FIND_CERTPATH = 
"sun.security.provider.certpath.SunCertPathBuilderException: " +
+                                                   "unable to find valid 
certification path to requested target";
       
     /**
      * We will cache window object in order to
@@ -93,9 +102,59 @@
         //determine the error message to display
         if (msg == null)
         {
-            if (ex instanceof IOException)
+            if (ex instanceof SSLException)
+            {
+                if (ex instanceof SSLKeyException)
+                {
+                    msg = "SSL key was invalid, please check the certificate 
configuration.";
+                    //Display error dialogue and return
+                    displayErrorDialogue(msg, title);
+                    return;
+                }
+                else if (ex instanceof SSLPeerUnverifiedException)
+                {
+                    msg = "SSL peer identity could not be verified, please 
ensure valid certificate configuration.";
+                    //Display error dialogue and return
+                    displayErrorDialogue(msg, title);
+                    return;
+                }
+                else if (ex instanceof SSLHandshakeException)
+                {
+                    if (ex.getMessage().contains(SSL_UNABLE_TO_FIND_CERTPATH))
+                    {
+                        msg = "Unable to certify the provided SSL certificate 
using the current SSL trust store.";
+                    }
+                    else
+                    {
+                        //cause unknown, provide a trace too
+                        MBeanUtility.printStackTrace(ex);
+                        msg = "SSL handhshake error.";
+                    }
+                    //Display error dialogue and return
+                    displayErrorDialogue(msg, title);
+                    return;
+                }
+                else
+                {
+                    //general SSL Exception.
+                    if (ex.getMessage().contains(SSL_EMPTY_TRUSTANCHORS))
+                    {
+                        msg = "Unable to locate the specified SSL certificate 
trust store, please check the configuration.";
+                    }
+                    else
+                    {
+                        //cause unknown, print stack trace
+                        MBeanUtility.printStackTrace(ex);
+                        msg = "SSL connection error.";
+                    }
+                    //Display error dialogue and return
+                    displayErrorDialogue(msg, title);
+                    return;
+                }
+            }
+            else if (ex instanceof IOException)
             {
-                //IOException, eg when trying to connect to a server/port with 
no JMX server running
+                //uncaught IOException, eg when trying to connect to a 
server/port with no JMX server running
                 msg = SERVER_UNAVAILABLE;
                 //Display error dialogue and return
                 displayErrorDialogue(msg, title);

Modified: 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini
URL: 
http://svn.apache.org/viewvc/qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini?rev=764422&r1=764421&r2=764422&view=diff
==============================================================================
--- 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini
 (original)
+++ 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini
 Mon Apr 13 11:59:29 2009
@@ -23,3 +23,15 @@
 -XX:MaxPermSize=256m
 -Dosgi.requiredJavaVersion=1.5
 -Declipse.consoleLog=true
+
+#===============================================
+# SSL trust store configuration options.
+#===============================================
+
+# Uncomment lines below to specify custom truststore for server SSL
+# certificate verification, eg when using self-signed server certs.
+#
+#-Djavax.net.ssl.trustStore=<path.to.truststore>
+#-Djavax.net.ssl.trustStorePassword=<truststore.password>
+
+

Modified: 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini
URL: 
http://svn.apache.org/viewvc/qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini?rev=764422&r1=764421&r2=764422&view=diff
==============================================================================
--- 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini
 (original)
+++ 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini
 Mon Apr 13 11:59:29 2009
@@ -29,3 +29,14 @@
 -Dosgi.requiredJavaVersion=1.5
 -Declipse.consoleLog=true
 -Dorg.eclipse.swt.internal.carbon.smallFonts
+
+#===============================================
+# SSL trust store configuration options.
+#===============================================
+
+# Uncomment lines below to specify custom truststore for server SSL
+# certificate verification, eg when using self-signed server certs.
+#
+#-Djavax.net.ssl.trustStore=<path.to.truststore>
+#-Djavax.net.ssl.trustStorePassword=<truststore.password>
+

Modified: 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini
URL: 
http://svn.apache.org/viewvc/qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini?rev=764422&r1=764421&r2=764422&view=diff
==============================================================================
--- 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini
 (original)
+++ 
qpid/branches/0.5-fix/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini
 Mon Apr 13 11:59:29 2009
@@ -23,3 +23,14 @@
 -XX:MaxPermSize=256m
 -Dosgi.requiredJavaVersion=1.5
 -Declipse.consoleLog=true
+
+#===============================================
+# SSL trust store configuration options.
+#===============================================
+
+# Uncomment lines below to specify custom truststore for server SSL
+# certificate verification, eg when using self-signed server certs.
+#
+#-Djavax.net.ssl.trustStore=<path.to.truststore>
+#-Djavax.net.ssl.trustStorePassword=<truststore.password>
+



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:[email protected]

Reply via email to