2
votes

I've tried to connect (send some data between) my standalone app and my other app served by Tomcat via SSL:

https://tomcat_server:8843/app

Unfortunately an error appears in my standalone app:

Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source) at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(Unknown Source) at com.sun.net.ssl.internal.ssl.AppOutputStream.write(Unknown Source) at java.io.BufferedOutputStream.flushBuffer(Unknown Source) at java.io.BufferedOutputStream.flush(Unknown Source) at org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(HttpConnection.java:827) at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.flushRequestOutputStream(MultiThreadedHttpConnectionManager.java:1525) at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:1975) at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:993) at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:397) at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:170) at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:396) at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:324) at org.apache.commons.vfs.provider.http.HttpClientFactory.createConnection(HttpClientFactory.java:101) ... 9 more

If I define url as a http it works fine:

http://tomcat_server:8080/app

It is also not a problem of app I think. I've tried the same thing with the same app on the other Tomcat server and it works via https. The only difference between these servers is I did not create the keystore file (pfx) on that server which works. I can't of course use the same keystore, because its different domain (I access this app also via browser). There is nothing in the Tomcat's log on the server. Maybe I did something wrong while creating the keystore.

Here's how I generated the keystore file using openssl tool with my key, certificate and intermediate cert:

openssl pkcs12 -export -out certificate.pfx -inkey server.key -in server.crt -certfile intermediate.crt

Here is my connector config:

protocol="org.apache.coyote.http11.Http11Protocol"
       port="8443" maxThreads="200"
       scheme="https" secure="true" SSLEnabled="true"
       keystoreFile="/path/to/keystore/certificate.pfx" keystorePass="changeit"  ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA"
       keystoreType="PKCS12" clientAuth="false" sslProtocol="TLS"/>

Both servers have same configs so I assume it must be certificate. Does anyone knows how to fix it?

3
Maybe you need certificate file on app side.disable1992
@disable1992 As I wrote, same app works with second Tomcat (different keystore).James

3 Answers

1
votes

You need to import the certificate in JDK security. Follow below 2 step and get done.

  • Step-1 Goto Below java security directory

/path/to/java/jdk/jre/lib/security

  • Step-2 Run below command

keytool -import -keystore cacerts -file /path/to/your/cert.cer

1
votes

Your application must a use a truststore with the public part of the certificate that you added to the keystore specified for 8443. This can be done by using system properties:

-Djavax.net.ssl.trustStore=/path/to/truststore/truststore.jks
-Djavax.net.ssl.trustStorePassword=truststorepassword
0
votes

Run: openssl s_client -connect [working_server]:[working_port] and then do the same for the server which isn't working. Compare the results; based on your description it is likely that there are no common certificates between them. One of the certificates in the 'broken' server's certificate chain must be in your app's truststore for it to work (the logs indicate that they are not); preferably you use the root certificate, but there are business cases where you may prefer an intermediate or the leaf certificate itself.