IBM MQ explorer and standalone java client with SSL - java

The bounty expires in 5 days. Answers to this question are eligible for a +50 reputation bounty.
user1929905 is looking for an answer from a reputable source.
I have a IBM MQ manager with SSL enabled .I can connect with MQ explorer with SSL keystore.
But if i try with a standalone Java client and same keystore , I am not able to connect.
I can see error messages as No X.509 selected and unavailable authentication scheme messages in the ssl logs and client is sending a empty certificate.
Standalone Java client : uses IBM JDK , java full version JRE 1.8.0 IBM
Windows AMD 64 build 8.0.7.20 - pwa6480sr7fp20-20221020_01(SR7 FP20),
Cipher suite used in Java client:
SSL_ECHDE_RSA_WITH_AES_256_GCM_SHA384
IBM MQ explorer version 9.1 ,Internal JRE: java full version JRE 1.8.0
IBM Windows AMD 64 build 8.0.5.41 - pwa6480sr5fp41-20190919_01(SR5
FP41),
Cipher Suite on the Queue manager end ECHDE_RSA_AES_256_GCM_SHA384
Same keystore used on both.( keystore doesn't have password).
Can anyone suggest what would be the issue here?

Related

TLS version used in JDK 8

We initialise our SSL context with the following code and are running on Java 8.
SSLContext context = SSLContext.getInstance("SSL");
Since Java 8 uses TLSv1.2 by default? Does it mean the above code will start sending TLSv1.2 requests if my server supports it.
Want to understand if "SSL" protocol name is just an alias but java runtime starts sending the requests with default TLS version.
UPDATE
I ran my code against "https://www.google.co.in/" and found this in fiddler
A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.
Version: 3.3 (TLS/1.2
And also if i change my protocol to TLSv1 which only supports 1.0. Then Fiddler tells me
A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.
Version: 3.1 (TLS/1.0)
So, I guess the above code with "SSL" protocol name should work well with TLS 1.2 servers.
Yes. In Java 7, server side default TLS version was 1.2. In Java 8 both server and client have default TLS version 1.2.
As TLS version is backward compatible on both side unless server is configured strictly to specific version should not be an issue.

How to add JVM argument `-Dcom.ibm.mq.cfg.useIBMCipherMappings=false` to IBM MQ?

Recently I've been migrated to IBM MQ v8 to IBM MQ v9 (v9.1.2.0 specifically). I used SSL to communicate with the broker. So as per Deprecated CipherSpecs document, IBM has deprecated number of cipher suites that came up with MQ 8 and seems all of the cipher suites I've been using, have been deprecated with v9 upward. Therefore, I've implemented new TLS cipher suites to work with my application which runs on a Oracle JVM (version 1.8.0_211). Ever since I'm getting following exception in the application though;
com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2400'.
at com.ibm.mq.MQManagedConnectionJ11.constructMQCD(MQManagedConnectionJ11.java:1437)
at com.ibm.mq.MQManagedConnectionJ11.constructCNO(MQManagedConnectionJ11.java:1537)
at com.ibm.mq.MQManagedConnectionJ11.<init>(MQManagedConnectionJ11.java:221)
... (Omitted the rest)
When I dig about the reason, found that's a problem with IBM MQ cipher suites and Oracle JRE cipher suite name mismatch. But I did refer TLS CipherSpecs and CipherSuites in IBM MQ classes for JMS document to map cipher suite names. I used some of Equivalent CipherSuite (Oracle JRE) column values in my application that already available in IBM MQ as well. But still getting the issue.
After I found this answer that advises to add this -Dcom.ibm.mq.cfg.useIBMCipherMappings=false argument to IBM MQ's JRE (As I understand). This might allow IBM MQ to use Oracle complied cipher suite names. My question is,
How to add this JVM argument -Dcom.ibm.mq.cfg.useIBMCipherMappings=false to IBM MQ JRE?
This Problem Connecting a Java Client (JMS) to a IBM MQ question suggests that the same parameter needed to be added to the application as a system property System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false"), but it didn't make any different.
Java connection to WMQ 8 question also states the same solution, but doesn't mention how to add this JVM argument to IBM MQ.
Update 1
I did some research about how to add a JVM argument to IBM MQ. But I was only able to find a solutions for Websphere application server.
CipherSuite I'm currently using in the application is;
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (Oracle JRE complied)
IBM MQ has respective;
ECDHE_ECDSA_AES_128_CBC_SHA256 (IBM MQ complied)
Update 2
After creating a key.kdb file with ikeyman tool with the stash option queue manager can successfully read the certificates in it. Also, I've included a self-signed certificate labeled with ibmwebspheremq<lowercase_queue_manage_name>. But now I'm getting a different exception in the client side;
Exception in thread "main" com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2059'.
at com.ibm.mq.MQManagedConnectionJ11.<init>(MQManagedConnectionJ11.java:255)
at com.ibm.mq.MQClientManagedConnectionFactoryJ11._createManagedConnection(MQClientManagedConnectionFactoryJ11.java:450)
at com.ibm.mq.MQClientManagedConnectionFactoryJ11.createManagedConnection(MQClientManagedConnectionFactoryJ11.java:487)
at com.ibm.mq.StoredManagedConnection.<init>(StoredManagedConnection.java:97)
and in the MQ log I can find this entry;
AMQ9637E: Channel is lacking a certificate.
with some explanation.
After working for while, I was able resolve this issue. Since the beginning I had this certificate configuration issue in the application side. Even after creating self-signed certificate labeled after ibmwebspheremq<queue_manager_name> and shared the extracted certificates with the client application using ikeyman tool, AMQ9637E: Channel is lacking a certificate. occurred.
In a nutshell, to resolve this issue entirely, I did the following;
Update the client MQ dependency to com.ibm.mq.allclient:v9.1.2.0. If you're using maven, use following dependency (MQC91: IBM MQ Clients).
<dependency>
<groupId>com.ibm.mq</groupId>
<artifactId>com.ibm.mq.allclient</artifactId>
<version>9.1.2.0</version>
</dependency>
Now, if the application runs on an Oracle JVM, we should convince the MQ client lib to use Oracle JVM complied cipher suite names. To do that, either add this -Dcom.ibm.mq.cfg.useIBMCipherMappings=false as a JVM flag or add this System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false") as a system property.
Select a appropriate cipher suite to communicate with the MQ. This TLS CipherSpecs and CipherSuites in IBM MQ classes for JMS document would be helpful as IBM has deprecated number of weak cipher specs IBMMQ 9 onwards.
I would suggest to use ECDHE_* cipher specs as they provide Ephemeral Keys to maintain Forward Secrecy.
Then, using ikeyman GUI tool, I created a self-signed certificate labeled after ibmwebspheremq<queue_manager_name> name and instead of extracting the .arm file, I export the certificate as .jks files. Both keystore.jks and truststore.jks files exported from the same certificate. After, attached them to the application using system properties;
System.setProperty("javax.net.ssl.trustStore", "truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "<password>");
System.setProperty("javax.net.ssl.keyStore", "keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "<password>");
With this configuration, SSL handshake issue went away, but the IBM MQ was still asking for user authentication with a user name and password. In order to provide them, should add these properties to MQEnvironment,
MQEnvironment.properties.put(com.ibm.mq.constants.CMQC.USER_ID_PROPERTY, "<user_name>");
MQEnvironment.properties.put(com.ibm.mq.constants.CMQC.PASSWORD_PROPERTY, "<password>");
These credentials were system credentials in my case.
If you simply want to skip user authentication like this, you can update IBMMQ config to skip credential check using runmqsc CLI tool like this (Refer this Turning on connection authentication on a queue manager document),
ALTER QMGR CONNAUTH(USE.PW)
DEFINE AUTHINFO(USE.PW) +
AUTHTYPE(IDPWOS) +
FAILDLAY(10) +
CHCKLOCL(OPTIONAL) +
CHCKCLNT(OPTIONAL)
REFRESH SECURITY TYPE(CONNAUTH)
Note that CHCKCLNT value needed to set as OPTIONAL to ignore client user credential check. IBM MQ should start to work with the client application whilst SSL enabled after these configurations.
Kudos to #JoshMc for the support to resolve this issue.
Note: Adding answer to capture information provided to OP in comments that have been removed.
See the following IBM MQ Knowledge center page for a table showing cert type compatibility with MQ v9.1:
IBM MQ 9.1.x/IBM MQ/Securing/Confidentiality of messages/Enabling CipherSpecs
The ciphers with ECDHE_ECDSA require a suite b cert for the queue manager. If using a client cert for your application it will also need to be suite b.
Note that you can use ECDHE_RSA ciphers with non-suite b certs.
The stash file (key.sth for example) is used by the queue manager to access the kdb file. The java equivalent on the client end is you specifying the jks password.

Got JAVA exception: java.security.spec.InvalidKeySpecException: Unknown KeySpec type

I have built a JAVA web application which uses SOAP to fetch data from an external database server. This works fine until a few days ago. Now, the connection to the database server is terminated while establishing them.
In my JAVA log file, I found the following sequence of exceptions:
javax.net.ssl.SSLException: Server key
at sun.security.ssl.Handshaker.throwSSLException(Handshaker.java:1260)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:283)
...
Caused by: java.security.spec.InvalidKeySpecException: Unknown KeySpec type: java.security.spec.ECPublicKeySpec
at org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory.engineGeneratePublic(Unknown Source)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
Maybe the provider of the database server has changed their SSL certificate and got another CA chain.
I noticed that the intermediate CA use SHA384withRSA as signature algorithm. (see COMODO, Domain Validation (SHA-2)).
So, what can I do to to make my system running again?
Please ask, if you need further information.
Remark: The same SOAP request from a Windows 7 client works fine. There I noticed, that the Windows 7 client uses TLSv1.2 to establish the SSL connection. The Linux system of my server (see below) uses TLSv1 ,
The configuration of my Java WebServer:
Debian Wheezy
Java: OpenJDK 1.7.0u111
Tomcat 7.0.28
https connector uses JSSE with sslProtocol="TLS"
BIRT Runtime V4.5.0
DTP V1.12.0
org.eclipse.datatools.enablement.oda.ws V1.2.6
Thanks
Friedbert
Solved!
Apparently, the configuration of the tomcat connector did no longer match current security standards.
I had set up the system 2 years ago. But the security requirements have increased in the meantime.
Now I took a recent appliance from turnkey, compared the settings and found a few differences:
JAVA: java.security
security.provider.10=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg
Tomcat7: server.xml /Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
sslProtocol="TLSv1.2" sslEnabledProtocols="TLSv1.2,TLSv1.1,TLSv1"
server="Secret" URIEncoding="UTF-8" (may be, these does not matter)
With these changes, my system works again!

Enable TLS1.2 on glassfish 3.1.2.2

I want to enable TLS1.2 on glassfish 3.1.2.2 (build 5) with JDK7, I know JDK7 enables TLSv1.2, TLSv1.1, TLSv1 (default) and SSLv3.
I have upgraded the JDK version to JDK7 from JDK6, i'm connecting to glassfish server via SOAPUI client ( SOAPUI enabled TLS1.2 by setting -Dsoapui.https.protocols=TLSv1.2) to test a webservice application.
Following error is returning from server.
ERROR:javax.net.ssl.SSLHandshakeException: Server chose TLSv1, but
that protocol version is not enabled or not supported by the client.
I'm confused why glassfish doesn't choose the latest TLS version (TLS1.2) for the handshake.
Also found a glassfish blog
(https://java.net/projects/glassfish/lists/users/archive/2012-07/message/85)
stating glassfish3.1.2 had issues running TLS1.2 with JDK1.7
Does anyone successfully connected to glassfish3 via TLS1.2?

JDK 1.6 and SSL connection

My java version is 1.6 and connect to a server over ssl using axis 2 stub; all used to work fine. It seems like they did some upgrade (apache2.4) and the ssl handshake doesn't happen anymore. I receive javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake error. Just for testing purpose, I locally installed jdk 8 and tested it works fine. Is there any way to make this work using jdk1.6? It is not possible to upgrade jdk now.
It is hard to tell without more details but I guess that the server either requires a TLS version unsupported by JDK 6 (e.g. TLS 1.1 or TLS 1.2) or uses ciphers which are not supported by JDK 6 yet. Another option might be that the server needs SNI (server name indication) which is not supported by JDK 6. If the problem is any of these things you are unfortunately out of luck with JDK 6.
I suggest you check with SSLLabs to get more details about the problem. They show also compatibility information regarding various JDK versions.
You could try using a 3rd party JCE provider, Bouncy Castle comes into mind:
https://www.bouncycastle.org

Categories

Resources