diff options
author | Aidan Skinner <aidan@apache.org> | 2009-02-13 14:00:10 +0000 |
---|---|---|
committer | Aidan Skinner <aidan@apache.org> | 2009-02-13 14:00:10 +0000 |
commit | 448e6bff629c2d8d9b3cbd7c39d8eefd2b33c06e (patch) | |
tree | df337797ff6438c5b09f208604fd4d54951ee312 /qpid/java/management | |
parent | bc5378a4b3220ec8c1e700c5fe705d983b4b0c7b (diff) | |
download | qpid-python-448e6bff629c2d8d9b3cbd7c39d8eefd2b33c06e.tar.gz |
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 <gemmellr@dcs.gla.ac.uk>
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@744113 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java/management')
5 files changed, 134 insertions, 19 deletions
diff --git a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/JMXConnnectionFactory.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/JMXConnnectionFactory.java index c9955329d0..f5831c9e28 100644 --- a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/JMXConnnectionFactory.java +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/JMXConnnectionFactory.java @@ -29,6 +29,7 @@ import java.util.Map; 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.UserPasswordCallbackHandler; 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 @@ public class JMXConnnectionFactory { 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 @@ public class JMXConnnectionFactory { 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 @@ public class JMXConnnectionFactory { { /* 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 @@ public class JMXConnnectionFactory { } } - 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 @@ public class JMXConnnectionFactory { 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 @@ public class JMXConnnectionFactory { } 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 @@ public class JMXConnnectionFactory { } else { - throw new Exception("Unknown authentication mechanism"); + throw new Exception("Unknown JMXMP authentication mechanism"); } } else diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java index 202c6ea650..474e31cd8f 100644 --- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java +++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java @@ -24,6 +24,11 @@ import static org.apache.qpid.management.ui.Constants.ERROR_SERVER_CONNECTION; 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 class AbstractAction 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 @@ public class AbstractAction //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); diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini index 8fd70ba19f..19ceb6f717 100644 --- a/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini +++ b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini @@ -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> + + diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini index 231adf2d8b..2a31b9b2c7 100644 --- a/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini +++ b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini @@ -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> + diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini b/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini index 9f3ad202ad..9e3de042d5 100644 --- a/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini +++ b/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini @@ -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> + |