Java – Connecting to WebSphere MQ using anonymous SSL

ibm-mqjavapcfssl

I get exception "com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2393'" in the below code. My requirement is to connect QM using a SSL server-connection channel. Client authentication is not required.

import com.ibm.mq.*;
public class MQSeriesDataCollector implements CustomDCInf
{
public static void main (String [] args)
{
    String qName="apm_qm";
    MQEnvironment.hostname=args [0]; 
    MQEnvironment.channel=args [1]; 
    MQEnvironment.port=Integer.parseInt(args [2]);
    MQEnvironment.sslFipsRequired=true;
    MQEnvironment.sslCipherSuite = "SSL_RSA_WITH_RC4_128_MD5";//RC4_MD5_US
    MQQueueManager qMgr=null;
    try{
        qMgr = new MQQueueManager("apm_qm");
    }catch (MQException mqe){
        mqe.printStackTrace();
}
PCFMessageAgent agent=null;
StringBuffer output = new StringBuffer();
MQSeriesDataCollector mqTest=new MQSeriesDataCollector();
        try{
            agent = mqTest.getMQConnection(qMgr);
            output.append(mqTest.getQueueStats(agent));
        }
        catch(MQException mqe){
            System.out.println("Error:" + mqe.reasonCode + " Description:"+PCFConstants.lookupReasonCode (mqe.reasonCode));
            mqe.printStackTrace();
        }
        catch(NoClassDefFoundError ex){
            ex.printStackTrace();
        }
        catch (Exception e){            
             e.printStackTrace();           
        }
        finally{
            try{
                if(agent!=null){
                    agent.disconnect();
                }
            }            
            catch(Exception ex){                
                ex.printStackTrace();
            }
        }

        System.out.println(output.toString());
    }
Exception:
com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2393'.
        at com.ibm.mq.MQManagedConnectionJ11.(MQManagedConnectionJ11.java:235)
        at com.ibm.mq.MQClientManagedConnectionFactoryJ11._createManagedConnection(MQClientManagedConnectionFactoryJ11.java:505)
        at com.ibm.mq.MQClientManagedConnectionFactoryJ11.createManagedConnection(MQClientManagedConnectionFactoryJ11.java:547)

Best Answer

To meet your requirement of not authenticating the client side, the channel must be set to SSLCAUTH(OPTIONAL). The queue manager must have a certificate and the client must have a trsuststore that contains the signer chain for the QMgr's cert (if CA signed) or the public key of the QMgr's cert (if self-signed). Remember that with SSL/TLS the server side is always authenticated and that requires the personal certificate at the server and a way for the client to validate it. Also, the client and QMgr must agree on the protocols used and if FIPS is required they must use one of the FIPS certified algorithms.

There is one thing definitely wrong in the code posted above and several things that are secondary possible causes for the problem. Once you resolve the config I'll described below, you may hit one of the secondary problems. To be sure which of these applies, it would be necessary to know which version of WMQ client and server, channel definition, the SSL settings for the JSSE and/or command-line invocation, etc.

So in this case the 2393 indicates that the client side isn't able to initialize the SSL/TLS session. The obvious problem is that, according to the Infocenter page SSL CipherSpecs and CipherSuites, these two settings are an invalid combination:

MQEnvironment.sslFipsRequired=true;
MQEnvironment.sslCipherSuite = "SSL_RSA_WITH_RC4_128_MD5";//RC4_MD5_US

You didn't mention which version of WMQ client and server you are at so here's a link to that page for V7.0, V7.1 and V7.5. Note that the column listing FIPS compliance does not include any MD5 Ciphersuite. (MD5 is broken and should not be used for signing certs, SSL, TLS or much of anything else. For that matter, SSL is broken and only TLS ciphers should be used going forward but that's a discussion for another question.) To get this working you will either need to set MQEnvironment.sslFipsRequired=false or pick one of the ciphersuites that is certified and listed in the far right column.

Not knowing the versions you are working with, I'd suggest setting FIPS to false and using NULL_SHA on the channel and SSL_RSA_WITH_NULL_SHA at the app until you are sure all the other configurations are working. This ciphersuite is available on all platforms at all versions of WMQ. Using this to test with will insure all the other settings are correct. Once you get it working, then pick a stronger ciphersuite based on TLS and SHA that is available on both the server and client side.

That said, here are some of the other possible issues you may run into.

You can get a 2393 when the app doesn't find its truststore or the certificate or signer chain in that truststore which represents the server side. You can pass these in on the command line:

java -Djavax.net.ssl.trustStore=key2.jks \
     -Djavax.net.ssl.trustStorePassword=passw0rd \
     -cp "%CLASSPATH%"  \
     com.ibm.examples.JMSDemo -pub -topic JMSDEMOPubTopic

The keystore and truststore operations are handled by the JSSE provider and not by WMQ itself. So whichever method you usually use to configure the JSSE provider should work. In addition to command line as shown above, that might include container-managed settings in a Java EE server, for example.

You can also get an error (I don't recall if its 2393) if the connection gets as far as the server presenting its certificate and the truststore has the wrong or incomplete signer chain.

Other possible causes for the 2393 include file permissions, misspellings of the path or file name, etc.