I have a webapp that sends a SOAP request to a 3rd party server. When the request is made on my local computer it works without a problem, but when I deploy my application to my server I get an error with the following causes:
com.sun.xml.messaging.saaj.SOAPExceptionImpl: java.security.PrivilegedActionException: com.sun.xml.messaging.saaj.SOAPExceptionImpl: Message send failed
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: algorithm check failed: MD2withRSA is disabled
I've searched around but I can't find anything relevant to my situation. It's probably worth noting that the request I'm making is to an https url. My computer is running Windows XP and the server is running Slackware Linux. Any ideas what might be causing the server to reject the request?
Check your Java versions on your local machine, and your server.
From here, it seems the jvm 6u17 disabled MD2 as it is insecure, and whatever you connect to is using MD2
MD2withRSA is highly vulnerable and therefore deactivated in Sun... aeh Oracle's JVM. You should ask the owner of the remote service, whether his server supports more secure encryption methods (I think, older Apache HTTPd versions do offer MD2withRSA by default...). In order to resolve this problem without forcing the provider to change the method, you may use your own implementation of the X509TrustManager that accepts the old method.
A Google search on "MD2withRSA" showed this URL as the first hit, that seems to point to a change in a certain Java version. Probably the verasiuons on your local computer and the server do not match.
Newer Java 7 (version 1.7) allows re-enabling MD2 via $JAVA_HOME/jre/lib/security/java.security file. Download and install Java 7 and modify java.security file in text editor as follows
1) Remove MD2 from following property
jdk.certpath.disabledAlgorithms= # MD2
2) Ensure following property is commented out
# jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
3) Restart java application
Warning: MD2 is disabled by default in Jdk 7 because it is insecure. However, it can be enabled as described above to support older deployments.
Related
As per the firm's policy we are required to encrypt communication channels b/w our client processes with MQ server. In our distributed system, we have a few Java processes required to establish connection with MQ. Let me say, process A and B.
A and B run on different virtual machines. They have EXACTLY the same environment including JRE of same version(1.8.0_151-b12), same dependencies, same JCE extension files. We added ssl related JVM parameters to the launching scripts of each process, such as
-Djavax.net.ssl.trustStore
-Djavax.net.ssl.trustStorePassword
-Djavax.net.ssl.keyStore
-Djavax.net.ssl.keyStorePassword
the corresponding trustStore and keyStore files are in place and properly referred to.
A works fine and we observed the SSL handshake and encrypted messages. However, process B failed with messages such as:
ignoring unavailable cipher TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
...
Caused by: java.lang.IllegalArgumentException: Cannot support
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA with currently installed providers
I did spend time checking online and one relevant post is from here : it suggested downloading and upgrading JCE files - the thing is that I already have JCE files (unlimited) installed and those are the same for both processes. I don't think JCE files is the root of the problem.
My question is, does the MQ team also have to install JCE files as well, in order for the client to establish SSL connection? Is the configuration on my end completed, anything I might have missed?
Update: problem solved. See my comments below.
Unlimited Strength Jurisdiction Policy Files were not included and enabled (crypto.policy set to unlimited) by default until 1.8.0_162. At 1.8.0_151 Unlimited Strength Jurisdiction Policy Files were included but not enabled.
Please check that you in fact running Java 1.8.0_151-b12 on both VMs, if you are then make sure the java security file crypto.policy setting on the working VM is identical to the non-working VM.
I have two laptops running the same project on them. Both instances are configured to use Java JDK 6 (same minor version). However one machine is not able to connect to a remote REST service. By running applications with -Djavax.net.debug=all option I came to the conclusion that the issue is with the ClientKeyExchange step as this step does not happen on the problematic laptop.
A post in the IBM developer community suggests that "hardware crypto device being used is not on the supported list". However I have no understanding about "hardware crypto devices".
What I can tell is that "enabled cipher suites", "excluded cipher suites", "cipher suites have been set to" lists printed by means of -Djavax.net.debug=all are the same on both machines.
Using JDK cacerts.
Found the solution. Project is using JAX-RS so calls to external service happened through that framework and because of that I could not dig to the problem since there were no errors. So I tried different approach: tried to access the service by using simple javax.net.ssl.HttpsURLConnection which showed me java.lang.NoClassDefFoundError: Could not initialize class javax.crypto.SunJCE_b and therefore I changed my local_policy.jar and US_export_policy.jar files (thanks to #Charlie Could not initialize class javax.crypto.SunJCE_b)
I think I had changed policy jars on first laptop and forgot to do this on the new laptop.
I'm now stuck with a HTTPS/SSL issue. I'm developing on Windows 10 / Java 8 v121 on Codename One.
When I tried to call a HTTP (without SSL) connection, I get rejected with a reference to [https://www.codenameone.com/blog/ios-http-urls.html]. I don't think the call even hit the server. I tried to include the "build hint" in my codenameone_settings.properties file but to no avail.
Next, I tried to use self-signed certificate and it generated a "Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target" exception. So, I thought the error was caused because my certificate was self-signed, but it wasn't...
Then I got a free certificate from [https://www.sslforfree.com/] and it is still causing the SAME exception message. However, this cerficate works fine with my Firefox browser. I'm also using Simple DNS Plus (for Windows) for the signed certificate domain name tested to work correctly in my Firefox browser (ie. correctly hit the server with no Insecure Connection message).
I'd like to understand how to:-
Get the "build hint" to work for iOS (in the Codename One simulator) so it calls http (without ssl) connections.
How to resolve the Java exception.
Thanks!
Just use http URL during the development stage and when you are ready to publish, buy a genuine SSL certificate and change the http to https. It's for your own good, as unencrypted Webservice call will make your app vulnerable to a man-in-middle attack.
To make your http work on iOS during dev stage, add this build hint:
ios.plistInject=<key>NSAppTransportSecurity</key><dict><key>NSAllowsArbitraryLoads</key><true/></dict><key>CFBundleURLTypes</key><array><dict><key>CFBundleURLName</key><string>com.mycompany.myapp</string></dict><dict><key>CFBundleURLSchemes</key><array><string>MyApp</string></array></dict></array>
There was a similar question previously which I answered here.
I have 2 fresh machines with the same version of JDK7 installed.
And on one of the machines I can successfully connect to the remote host from my Java application via HTTPS without any issues and without importing any certificates to the default 'cacerts' keystore.
However on the other machine I'm getting the subj error.
JDKs on both machines are absolutely the same. The only difference between machines is that one of them is located in Europe, and one in the USA (this is the one where I'm getting the error).
Does anybody have a clue to what could cause this error in my case?
UPDATE
Certificate of the host I'm trying to connect to is issued by QuoVadis CA, which by default has the appropriate record in cacerts in Java distibution.
UPDATE2
Looks like the problematic machine for some reason doesn't receive the whole certificate chain from the machine to which it tries to connect (I can see only the last certificate from the chain and right after that follows a message certificate_unknown). So it doesn't get the root certificate.
Besides that the only difference I can see in the log is that working machine uses TLS_RSA_WITH_AES_128_CBC_SHA cipher suite and not working machine uses TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA cipher suite.
Could this be a reason of my problem? (I also cannot understand why they use different cipher suites while JDKs are the same and they are connecting to the same machine)
Try to compare the keystore certificates once. I had a similar issue where one machine had other applications which added the same certificates and it was working fine, but a stand alone machine was not.
I have an SSL client certificate. It was working with my app up until one of the Java updates happened at some point in the recent past (maybe as far back as a year). It works with web browsers. It works with curl.
For example, I can do this and it is fine:
curl --cert example.pem https://example.net
Now I cannot get this cert to work with Java. I've gone as far as trying a very minimal app, like SSLPoke from https://gist.github.com/4ndrej/4547029
Putting the cert into the client certs from ControlPanel doesn't do it.
Importing the .pem into a keystore and then pointing at that keystore with -Djavax.net.ssl.trustStore or .keystore doesn't do it.
All I get out of Java is:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
So I can't figure out what is wrong - the way I'm invoking Java? The place I'm putting the certificate? The way I've imported the certificate?
The debug output using -Djava.security.debug=all does not show it using the trustStore/keyStore I specify. It doesn't even show anything about the URL I'm trying to reach.
I'm out of ideas.
Your server is likely using an outdated SSL protocol, that Java is no longer allowing, by default, for security reasons.
Try running Java with this option (e.g. needed for older SQL Server instances):
-Djsse.enableCBCProtection=false
If that doesn't work, maybe the server is using SSLv3, so see this SO question for How to enable SSL 3 in Java.
If any of those work, they are workarounds need to downgrade the SSL security, so you are strongly encouraged to upgrade the server instead, and remove these workarounds again.