Reputation: 17831
How do I get a JMS Client using SSL_RSA_WITH_AES_128_CBC_SHA (in the queue connection factory) to connect to a server using TLS_RSA_WITH_AES_128_CBC_SHA
Code:
// Instantiate the initial context
String contextFactory = "com.sun.jndi.fscontext.RefFSContextFactory";
Hashtable environment = new Hashtable();
environment.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
environment.put(Context.PROVIDER_URL, initialContextUrl);
Context context = new InitialDirContext(environment);
System.out.println("Initial context found!");
String keystoreName = System.getProperty("javax.net.ssl.keyStore");
System.out.println("keystoreName " + keystoreName + " canRead " + new File(keystoreName).canRead());
String truststoreName = System.getProperty("javax.net.ssl.trustStore");
System.out.println("truststoreName " + keystoreName + " canRead " + new File(truststoreName).canRead());
// Lookup the connection factory
JmsConnectionFactory cf = (JmsConnectionFactory) context.lookup(connectionFactoryFromJndi);
System.out.println("CF = " + cf.getClass().getName());
MQConnectionFactory mqcf = (MQConnectionFactory) cf;
System.out.println("getSSLCipherSuite:" + mqcf.getSSLCipherSuite());
System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());
// Lookup the destination
destination = (JmsDestination) context.lookup(destinationFromJndi);
System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());
// Create JMS objects
connection = cf.createConnection();
System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());
consumer = session.createConsumer(destination);
System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());
// Start the connection
connection.start();
System.out.println("getSSLSocketFactory:" + mqcf.getSSLSocketFactory());
Gives me:
Initial context found!
keystoreName C:/Users/...key.jks canRead true
truststoreName C:/Users/.../key.jks canRead true
CF = com.ibm.mq.jms.MQConnectionFactory
getSSLCipherSuite:SSL_RSA_WITH_AES_128_CBC_SHA
getSSLSocketFactory:null
getSSLSocketFactory:null
keyStore is : C:/Users/.../key.jks
keyStore type is : jks
keyStore provider is :
init keystore
init keymanager of type SunX509
***
found key for : ibmwebspheremquserid
.....
Valid from Mon May 14 23:59:46 CEST 2012 until Thu May 14 23:59:46 CEST 2015
trigger seeding of SecureRandom
done seeding SecureRandom
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
com.ibm.msg.client.jms.DetailedJMSException: JMSWMQ0018: Failed to connect to queue manager 'qm' with connection mode 'Client' and host name 'host(1414)'.
Check the queue manager is started and if running in client mode, check there is a listener running. Please see the linked exception for more information.
Inner exception(s):
com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2393' ('MQRC_SSL_INITIALIZATION_ERROR').
com.ibm.mq.jmqi.JmqiException: CC=2;RC=2393;AMQ9204: Connection to host 'host(1414)' rejected. [1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2393;AMQ9771: SSL handshake failed. [1=java.lang.IllegalArgumentException[Unsupported ciphersuite SSL_RSA_WITH_AES_128_CBC_SHA],3=host/host:1414 (10.20.28.12),4=SSLSocket.createSocket,5=default]],3=host(1414),5=RemoteTCPConnection.makeSocketSecure]
com.ibm.mq.jmqi.JmqiException: CC=2;RC=2393;AMQ9771: SSL handshake failed. [1=java.lang.IllegalArgumentException[Unsupported ciphersuite SSL_RSA_WITH_AES_128_CBC_SHA],3=host/host:1414 (10.20.28.12),4=SSLSocket.createSocket,5=default]
java.lang.IllegalArgumentException: Unsupported ciphersuite SSL_RSA_WITH_AES_128_CBC_SHA
FAILURE
Upvotes: 1
Views: 4619
Reputation: 17831
Using SSL from the Oracle JVM (JSSE)
In MQ Client version 8.0.0.2 there is a patch is included to use the TLS with Oracle JVM, this works with lanes answer above
The get this to work you will need the latest MQ Client that contains
IV66840: WMQ V7 JAVA/JMS: ADD SUPPORT FOR SELECTED TLS CIPHERSPECS WHEN
RUNNING IN NON-IBM JAVA RUNTIME ENVIRONMENT
http://www-01.ibm.com/support/docview.wss?uid=swg1IV66840
(download)
Depending on your location you may also need to install Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 8 (download)
To use this you have to configured by using the JVM argument:
-Dcom.ibm.mq.cfg.useIBMCipherMappings=false
Note that the default security implementation behaviour differs between Oracle and IBM JVMs :
The Oracle JSSE Reference guide says:
If the KeyManager[] parameter is null, then an empty KeyManager will be defined for this context.
The IBM JSSE Reference guide says:
If the KeyManager[] paramater is null, the installed security providers will be searched for the highest-priority implementation of the KeyManagerFactory, from which an appropriate KeyManager will be obtained.
Which means that you have to setup your own ssl context
SSLContext sslcontext = SSLContext.getInstance("TLS");
String keyStore = System.getProperty("javax.net.ssl.keyStore");
String keyStoreType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType());
String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword","");
KeyManager[] kms = null;
if (keyStore != null)
{
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance(keyStoreType);
if (keyStore != null && !keyStore.equals("NONE")) {
fs = new FileInputStream(keyStore);
ks.load(fs, keyStorePassword.toCharArray());
if (fs != null)
fs.close();
char[] password = null;
if (keyStorePassword.length() > 0)
password = keyStorePassword.toCharArray();
kmf.init(ks,password);
kms = kmf.getKeyManagers();
}
sslcontext.init(kms,null,null);
And then supply that to the MQ JMS client:
JmsConnectionFactory cf = ...
MQConnectionFactory mqcf = (MQConnectionFactory) cf;
mqcf.setSSLSocketFactory(sslcontext.getSocketFactory());
If using a application server this might be handled by your application server.
Upvotes: 1