I'm attempting to perform mutual TLS authentication to server.com (changed), and I'm getting Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking, javax.net.ssl.SSLException: readHandshakeRecord after Produced client Finished handshake message.
I am using AdoptOpenJDK 11.0.11.9-hotspot.
JVM options:
-Djavax.net.ssl.trustStore=cacerts
-Djavax.net.ssl.trustStoreType=PKCS12
-Djavax.net.ssl.trustStorePassword=changeit
-Djavax.net.ssl.keyStore=keystore
-Djavax.net.ssl.keyStoreType=PKCS12
-Djavax.net.ssl.keyStorePassword=changeit
-Djavax.net.debug=SSL,handshake
-Djdk.tls.client.protocols=TLSv1.3
-Djdk.tls.server.protocols=TLSv1.3
-Dhttps.protocols=TLSv1.3
Code I use for debugging this problem:
public static void main (String[] args) throws IOException {
URL url = new URL( "https://server.com");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
con.connect();
}
Logs with handshake steps successfully performed:
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.505 MSK|ClientHello.java:653|Produced ClientHello handshake message ("ClientHello": { <...> })
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.505 MSK|ServerHello.java:872|Consuming ServerHello handshake message ("ServerHello": { <...> })
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.505 MSK|ServerHello.java:968|Negotiated protocol version: TLSv1.3
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.536 MSK|ChangeCipherSpec.java:246|Consuming ChangeCipherSpec message
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.552 MSK|EncryptedExtensions.java:171|Consuming EncryptedExtensions handshake message (<...>)
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.552 MSK|CertificateRequest.java:926|Consuming CertificateRequest handshake message ("CertificateRequest": { <...> })
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.568 MSK|CertificateMessage.java:1171|Consuming server Certificate handshake message ("Certificate": { <...> })
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.677 MSK|CertificateVerify.java:1161|Consuming CertificateVerify handshake message ("CertificateVerify": { <...> })
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.677 MSK|Finished.java:898|Consuming server Finished handshake message ("Finished": { <...> })
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.693 MSK|CertificateMessage.java:1139|Produced client Certificate message ("Certificate": { <...> })
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.724 MSK|CertificateVerify.java:1126|Produced client CertificateVerify handshake message ("CertificateVerify": { <...> })
javax.net.ssl|DEBUG|01|main|2022-01-12 10:07:55.739 MSK|Finished.java:673|Produced client Finished handshake message ("Finished": { <...> })
Just after that I get:
javax.net.ssl|ERROR|01|main|2022-01-12 11:38:54.523 MSK|TransportContext.java:341|Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking (
"throwable" : {
javax.net.ssl.SSLException: readHandshakeRecord
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1335)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:440)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411)
at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:567)
at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:197)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:168)
at SbbidIntegraionApplication.main(SbbidIntegraionApplication.java:17)
Caused by: java.net.SocketException: Software caused connection abort: socket write error
at java.base/java.net.SocketOutputStream.socketWrite0(Native Method)
at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110)
at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
at java.base/sun.security.ssl.SSLSocketOutputRecord.flush(SSLSocketOutputRecord.java:251)
at java.base/sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:89)
at java.base/sun.security.ssl.Finished$T13FinishedProducer.onProduceFinished(Finished.java:679)
at java.base/sun.security.ssl.Finished$T13FinishedProducer.produce(Finished.java:658)
at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
at java.base/sun.security.ssl.Finished$T13FinishedConsumer.onConsumeFinished(Finished.java:1011)
at java.base/sun.security.ssl.Finished$T13FinishedConsumer.consume(Finished.java:874)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:182)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1418)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1324)
... 6 more}
)
javax.net.ssl|WARNING|01|main|2022-01-12 11:38:54.523 MSK|TransportContext.java:383|Fatal: failed to send fatal alert HANDSHAKE_FAILURE (
"throwable" : {
java.net.SocketException: Software caused connection abort: socket write error
at java.base/java.net.SocketOutputStream.socketWrite0(Native Method)
at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110)
at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
at java.base/sun.security.ssl.SSLSocketOutputRecord.encodeAlert(SSLSocketOutputRecord.java:81)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:380)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:292)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:450)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411)
at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:567)
at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:197)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:168)
at SbbidIntegraionApplication.main(SbbidIntegraionApplication.java:17)}
)
javax.net.ssl|DEBUG|01|main|2022-01-12 11:38:54.523 MSK|SSLSocketImpl.java:1638|close the underlying socket
javax.net.ssl|DEBUG|01|main|2022-01-12 11:38:54.523 MSK|SSLSocketImpl.java:1657|close the SSL connection (initiative)
Exception in thread "main" javax.net.ssl.SSLException: readHandshakeRecord
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1335)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:440)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411)
at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:567)
at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:197)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:168)
at SbbidIntegraionApplication.main(SbbidIntegraionApplication.java:17)
Suppressed: java.net.SocketException: Software caused connection abort: socket write error
at java.base/java.net.SocketOutputStream.socketWrite0(Native Method)
at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110)
at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
at java.base/sun.security.ssl.SSLSocketOutputRecord.encodeAlert(SSLSocketOutputRecord.java:81)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:380)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:292)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:450)
... 5 more
Caused by: java.net.SocketException: Software caused connection abort: socket write error
at java.base/java.net.SocketOutputStream.socketWrite0(Native Method)
at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110)
at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
at java.base/sun.security.ssl.SSLSocketOutputRecord.flush(SSLSocketOutputRecord.java:251)
at java.base/sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:89)
at java.base/sun.security.ssl.Finished$T13FinishedProducer.onProduceFinished(Finished.java:679)
at java.base/sun.security.ssl.Finished$T13FinishedProducer.produce(Finished.java:658)
at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
at java.base/sun.security.ssl.Finished$T13FinishedConsumer.onConsumeFinished(Finished.java:1011)
at java.base/sun.security.ssl.Finished$T13FinishedConsumer.consume(Finished.java:874)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:182)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1418)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1324)
... 6 more
Process finished with exit code 1
The same request sent with curl or openssl is processed successfully and I get an expected answer from the server.
What can be the reason for such an error almost at the end of the handshake process?
Thanks
UPD:
After comment of #dkotenko I initialised SSLContext programmatically:
public static void main (String []args) throws IOException {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("keystore"), "changeit".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "changeit".toCharArray());
KeyStore trustStore = KeyStore.getInstance("PKCS12");
trustStore.load(new FileInputStream("cacerts"), "changeit".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
URL url = new URL("server.com");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
}
but got exactly the same output.
Solved. The problem was in the absence of CA certificates in the keystore.
The server administrator said that when contacting the load balancer at server.com there is a check that there is a certificate of the particular root CA in the client's certificate chain.
After importing it into the keystore, the entire handshake process was complete and a correct response was received from the server
Hope this will help somebody one day:)
Related
I'm trying to implement mutual authentication in my Java program. Basically, my program has to make an HTTP request to another server. I need to attach a client certificate to that request and ignore the self-signed certificate of the server.
In short, I'm trying to convert this part of the curl command into Java:
curl --insecure --key ${USERKEY} --cert ${USERCERT} ...
This is my attempt so far to create a proper OkHttpClient. The idea was taken from okhttp-tls.
public OkHttpClient getClient()
throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, CertificateException {
String algorithm = "RSA";
// Read public and private key to create a keypair
PrivateKey privateKey = KeyUtils.getPemPrivateKey(PRIVATE_KEY_PATH, algorithm);
PublicKey publicKey = KeyUtils.getPemPublicKey(PUBLIC_KEY_PATH, algorithm);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Read the certificate
X509Certificate certificate = KeyUtils.getX509Certificate(CERTIFICATE_PATH);
// Client certificate, used to authenticate the client
HeldCertificate clientCertificate = new HeldCertificate(keyPair, certificate);
// Create handshake certificate (which root certificate/hostname to trust)
HandshakeCertificates.Builder clientCertificatesBuilder = new HandshakeCertificates.Builder()
.addPlatformTrustedCertificates() // trust all certificate which are trusted on the platform
.heldCertificate(clientCertificate); // attach the client certificate
// Do not verify certificate of the host
clientCertificatesBuilder.addInsecureHost(HOST);
HandshakeCertificates clientCertificates = clientCertificatesBuilder.build();
return new OkHttpClient.Builder()
.sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager())
.hostnameVerifier((hostname, session) -> true) // Do not verify the hostname
.build();
}
KeyUtils is just my utility class for reading key and certificate files.
The code works fine if the HOST is a domain name, but it's failed when HOST is an IP address. Below is part of the stacktrace.
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:324) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:267) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:262) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:645) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:464) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:360) ~[na:na]
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396) ~[na:na]
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444) ~[na:na]
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:422) ~[na:na]
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:181) ~[na:na]
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1460) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1368) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:437) ~[na:na]
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:367) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:325) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:197) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:249) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:108) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:76) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:245) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:96) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:197) ~[okhttp-4.7.2.jar:na]
at okhttp3.internal.connection.RealCall.execute(RealCall.kt:148) ~[okhttp-4.7.2.jar:na]
How can I make it works when the address of the server is an IP, not the domain name?
I'm using WebLogic 12.2.1.3.0 and JDK8 to run following part of code in my PoC application deployed. Application uses weblogic.net.http.HttpsURLConnection client class:
import java.net.URL;
import java.net.URLEncoder;
import java.security.Provider;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLSession;
import weblogic.net.http.HttpURLConnection;
import weblogic.net.http.HttpsURLConnection;
import weblogic.security.SSL.HostnameVerifier;
import weblogic.security.SSL.SSLContext;
import weblogic.security.SSL.SSLSocketFactory;
import weblogic.security.SSL.TrustManager;
...
HttpURLConnection con = null;
if (url.startsWith("https")) {
HostnameVerifier hv = new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
};
TrustManager tm = new TrustManager() {
#Override
public boolean certificateCallback(X509Certificate[] arg0, int arg1) {
return true;
}
};
SSLContext ctx = SSLContext.getInstance("https");
ctx.setHostnameVerifier(hv);
ctx.setTrustManager(tm);
SSLSocketFactory sslSocketFactory = ctx.getSocketFactory();
con = new HttpsURLConnection(new URL(url));
((HttpsURLConnection)con).setSSLSocketFactory(sslSocketFactory);
//con = new HttpsURLConnection(new URL(url));
} else {
con = new HttpURLConnection(new URL(url));
}
con.setReadTimeout(10*1000); //ms
con.setRequestMethod("POST");
con.setRequestProperty("Content-length", "" + msg.length());
con.setRequestProperty("Content-type", "application/octet-stream");
con.setDoOutput(true);
con.connect();
...
this is based on Oracle WLS examples: wls/SCPRG/ssl_client.htm
it works only if I configure the CA root certificate into trusted keystore. It doesn't reflect setting my SSLContext with TrustManager (accepting all certs) and it works same way as without my SSLContext specified. My self signed root CA of the server which client connects have to be include in keystore, otherwise WLS raises:
at com.poc.PoCServlet.doGet(PoCServlet.java:24)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:286)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:260)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:137)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:350)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:247)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3697)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3667)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:326)
at weblogic.security.service.SecurityManager.runAsForUserCode(SecurityManager.java:197)
at weblogic.servlet.provider.WlsSecurityProvider.runAsForUserCode(WlsSecurityProvider.java:203)
at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:71)
at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2443)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2291)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2269)
at weblogic.servlet.internal.ServletRequestImpl.runInternal(ServletRequestImpl.java:1703)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1663)
at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:272)
at weblogic.invocation.ComponentInvocationContextManager._runAs(ComponentInvocationContextManager.java:352)
at weblogic.invocation.ComponentInvocationContextManager.runAs(ComponentInvocationContextManager.java:337)
at weblogic.work.LivePartitionUtility.doRunWorkUnderContext(LivePartitionUtility.java:57)
at weblogic.work.PartitionUtility.runWorkUnderContext(PartitionUtility.java:41)
at weblogic.work.SelfTuningWorkManagerImpl.runWorkUnderContext(SelfTuningWorkManagerImpl.java:644)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:415)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:355)
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1709)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:318)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
at sun.security.ssl.Handshaker$1.run(Handshaker.java:970)
at sun.security.ssl.Handshaker$1.run(Handshaker.java:967)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1459)
at weblogic.socket.JSSEFilterImpl.doTasks(JSSEFilterImpl.java:223)
at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:123)
... 34 common frames omitted
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)
at sun.security.validator.Validator.validate(Validator.java:262)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:105)
at weblogic.security.SSL.jsseadapter.JaTrustManager.checkServerTrusted(JaTrustManager.java:128)
at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:1006)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1626)
... 42 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392)
... 50 common frames omitted
I like to accept all the (client connecting) servers certificated (as default) in my client implementation, regardless the WebLogic server (where is my https connection implemented and deployed as part of web application) keystore content.
--UPDATE--
When I add output to the weblogic.security.SSL.TrustManager interface implementation, this is not displayed, so TrustManager method is not called.
I have to work with old version (1.8.1) of rest-assured framework. And all my post() or get() requests called from rest-assured fails, because server I am using for tests has self-signed SSL certificate.
I know that since version 2.2.0 this is quite easy to setup ssl connection to use relaxedHTTPSValidation, e.g.
given().relaxedHTTPSValidation().when().get("https://some_server.com")
I also found on rest-assured wiki how to deal with SSL config.
But my question is is it possible in older version of rest-assured (1.8.1).
Exception thrown is SSLHandshakeException.
And here is the trace I got:
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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:543)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:409)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:304)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:611)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:446)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:882)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
at org.apache.http.client.HttpClient$execute.call(Unknown Source)
at com.jayway.restassured.internal.RequestSpecificationImpl$RestAssuredHttpBuilder.doRequest(RequestSpecificationImpl.groovy:1377)
at com.jayway.restassured.internal.http.HTTPBuilder.post(HTTPBuilder.java:341)
at com.jayway.restassured.internal.http.HTTPBuilder$post.call(Unknown Source)
at com.jayway.restassured.internal.RequestSpecificationImpl.sendRequest(RequestSpecificationImpl.groovy:801)
at com.jayway.restassured.internal.RequestSpecificationImpl.this$2$sendRequest(RequestSpecificationImpl.groovy)
at com.jayway.restassured.internal.RequestSpecificationImpl$this$2$sendRequest.call(Unknown Source)
at com.jayway.restassured.internal.filter.RootFilter.filter(RootFilter.groovy:30)
at com.jayway.restassured.filter.Filter$filter.call(Unknown Source)
at com.jayway.restassured.internal.filter.FilterContextImpl.next(FilterContextImpl.groovy:49)
at com.jayway.restassured.filter.FilterContext$next.call(Unknown Source)
at com.jayway.restassured.internal.RequestSpecificationImpl.invokeFilterChain(RequestSpecificationImpl.groovy:758)
at com.jayway.restassured.internal.RequestSpecificationImpl$invokeFilterChain.callCurrent(Unknown Source)
at com.jayway.restassured.internal.RequestSpecificationImpl.applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy:1142)
at com.jayway.restassured.internal.RequestSpecificationImpl.this$2$applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy)
at com.jayway.restassured.internal.RequestSpecificationImpl$this$2$applyPathParamsAndSendRequest.callCurrent(Unknown Source)
at com.jayway.restassured.internal.RequestSpecificationImpl.post(RequestSpecificationImpl.groovy:135)
at com.ibm.datatools.webauto.framework.common.BaseWebTest.login(BaseWebTest.java:53)
at com.ibm.datatools.webauto.dynamite.svt.ui.testcases.UDXTest.idaLogin(UDXTest.java:47)
at com.ibm.datatools.webauto.dynamite.svt.ui.testcases.UDXTest.beforeClass(UDXTest.java:62)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:85)
at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:510)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:211)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:138)
at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:170)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:104)
at org.testng.TestRunner.privateRun(TestRunner.java:774)
at org.testng.TestRunner.run(TestRunner.java:624)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:359)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:354)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:312)
at org.testng.SuiteRunner.run(SuiteRunner.java:261)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1215)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
at org.testng.TestNG.run(TestNG.java:1048)
at org.testng.TestNG.privateMain(TestNG.java:1355)
at org.testng.TestNG.main(TestNG.java:1324)
Note: This is not duplicate of this or this question, because answers provided there regard newer version of rest-assured.
It worked for me with below correction
#Test
public void testUserFetchesSuccess(){
given().config(RestAssured.config().sslConfig(new SSLConfig().allowAllHostnames())).
get(restUrl).
then().body("id", equalTo("abc0"));
}
As I wrote in one of my comments I tried solution that:
Download server certificates
Creates temporary keystore to be used by rest-assured
stores server certificates in temporary keystore
Uses temporary keystore in rest-assured when connecting to server during tests
Here is important part of code:
protected Certificate[] getCertificates(String url) throws IOException, GeneralSecurityException
{
URL urlConnection = new URL(url);
SSLContext context = SSLContext.getInstance("TLS");
context.init(new KeyManager[0], new TrustManager[] {new DummyTrustManager()}, new SecureRandom());
SSLContext.setDefault(context);
HttpsURLConnection con = (HttpsURLConnection)urlConnection.openConnection();
con.setHostnameVerifier(
new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
con.setSSLSocketFactory(context.getSocketFactory());
con.connect();
Certificate[] certificates = con.getServerCertificates();
con.disconnect();
return certificates;
}
protected void storeCertificates(Certificate[] certs, String keystorePath, String keystorePassword) throws GeneralSecurityException, IOException
{
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null, keystorePassword.toCharArray());
for (Certificate c: certs)
{
keystore.setCertificateEntry(Integer.toHexString(c.hashCode()), c);
}
File f = new File(keystorePath);
FileOutputStream out_stream = new FileOutputStream(f);
keystore.store(out_stream, keystorePassword.toCharArray());
out_stream.close();
}
After that the only thing I have to do is:
RestAssured.keystore(keystorePath, keystorePassword);
Notes:
getCertificates method is based on piece of code I found under this question. DummyTrustManager is exactly the same as DefaultTrustManager there.
storeCertificates is based on this question and it's answer.
I am still not sure if SSLContext.setDefault(context) changes SSLContext only temporarly (during downloading certificates) or permanently
I have written code for mail sending in java( I am using java mail api for this). Here uerId and Password(For authentication purpose) I am giving of my domain because I want my email server to be use.
The Problem is, when I am sending mail from localhost it is working fine, But when I am deploying on my live staging server,and trying to send the mail, it is giving following exception:
Apr 08, 2015 7:32:26 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [spring] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.mail.MailSendException: Mail server connection failed; nested exception is javax.mail.MessagingException: Could not connect to SMTP host: mail.dreamdays.ae, port: 25;
nested exception is:
java.net.ConnectException: Connection timed out. Failed messages: javax.mail.MessagingException: Could not connect to SMTP host: mail.dreamdays.ae, port: 25;
nested exception is:
java.net.ConnectException: Connection timed out; message exceptions (1) are:
Failed message 1: javax.mail.MessagingException: Could not connect to SMTP host: mail.dreamdays.ae, port: 25;
nested exception is:
java.net.ConnectException: Connection timed out] with root cause
java.net.ConnectException: Connection timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:284)
at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:227)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1672)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:525)
at javax.mail.Service.connect(Service.java:291)
at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:389)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:340)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:336)
at com.service.MailMail.sendMail(MailMail.java:34)
at com.controller.UserController.saveUser(UserController.java:143)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:647)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:603)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:950)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:859)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:883)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:792)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.ajp.AjpAprProcessor.process(AjpAprProcessor.java:197)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1852)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Code is below, Please check it and help me out.
public class MailDao {
private static final String SMTP_HOST_NAME = "mail.dreamdays.ae";
private static final String SMTP_AUTH_USER ="cpverma#dreamdays.ae";
private static final String SMTP_AUTH_PWD = "********";
public void postMail(String emailTo, String recipients[ ], String subject, String message , String from) throws MessagingException, AuthenticationFailedException
{
boolean debug = false;
//Set the host smtp address
Properties props = new Properties();
props.put("mail.smtp.host", SMTP_HOST_NAME);
props.put("mail.smtp.auth", "true");
try{
Authenticator auth = new SMTPAuthenticator();
Session session = Session.getInstance(props, auth);
// session.setDebug(debug);
// create a message
Message msg = new MimeMessage(session);
// set the from and to address
InternetAddress addressFrom = new InternetAddress(from);
msg.setFrom(addressFrom);
// InternetAddress[] addressTo = new InternetAddress[recipients.length];
InternetAddress[] emailToArr = new InternetAddress[1];
emailToArr[0] = new InternetAddress(emailTo);
System.out.println("emailTo---"+emailTo);
msg.setRecipients(Message.RecipientType.TO, emailToArr);
// if(recipients.length >0)
// msg.setRecipients(Message.RecipientType.CC, emailToArr);
// Setting the Subject and Content Type
msg.setSubject(subject);
msg.setContent(message, "text/html");
Transport.send(msg);
System.out.println("emailTo3---"+emailTo);
}catch(Exception e){
System.out.println("mail sending failed:--"+e);
}
}
private class SMTPAuthenticator extends javax.mail.Authenticator {
public PasswordAuthentication getPasswordAuthentication() {
String username = SMTP_AUTH_USER;
String password = SMTP_AUTH_PWD;
return new PasswordAuthentication(username, password);
}
}
}
The exception means that connection to the host is timing out which might be because of the host not being available. So verify whether the connection to the host is possible by using telnet
telnet mail.dreamdays.ae 25
Also you are able to connect using telnet then there should not be any problem in sending mail.
So ensure that the host server is up and available in the first place
I'm building two java applications which have to communicate using SSL two way authentication, I used instructions from here to create client and server certificates.
then I built a webService in the server application like this:
#RequestMapping(value="/testssl", method = RequestMethod.POST, produces="application/json", consumes="application/json")
#ResponseBody
public String testSSl(#RequestBody String name) {
return = successfully tested;
}
and I edited tomcat server.xml file to enable SSL like this:
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="keyStore/server.jks"
keystorePass="server123" />
and put server.jks in Tomcat/Jenkins-Tomcat/keystore/server.jks
then I built the client application to invoke this web service through SSL using spring RestTemplate like this:
Properties props = new Properties();
props.put("javax.net.ssl.trustStore", "D:\\test\\server.jks");
props.put("javax.net.ssl.trustStoreType", "jks");
props.put("javax.net.ssl.trustStorePassword", "server123");
props.put("javax.net.ssl.keyStore", "D:\\test\\client.jks");
props.put("javax.net.ssl.keyStoreType", "jks");
props.put("javax.net.ssl.keyStorePassword", "client123");
props.put("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
props.put("ws.ssl.loose.disableHostnameVerification", "true");
System.setProperties(props);
SSLContext sslcontext = SSLContexts.createDefault();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,
new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
CloseableHttpClient httpClient = HttpClientBuilder.create()
.setSSLSocketFactory(sslsf).build();
org.springframework.http.client.HttpComponentsClientHttpRequestFactory cc = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate rest = new RestTemplate(cc);
String resp = rest.postForObject("https://10.141.0.77:8443/Monim/testssl", "monim", String.class);
System.err.println(resp);
but when I run this application I get unable to find valid certification path to requested target exception. I tried to create the certificates again but the error still present.
when I request the url from firefox browser I get An error occurred during a connection to 10.141.0.77:8443. SSL peer cannot verify your certificate. (Error code: ssl_error_bad_cert_alert)
and when using chrome to access the url I get
Error code: ERR_BAD_SSL_CLIENT_AUTH_CERT
here is the stacktrace of the client application
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://10.141.0.77:8443/Monim/testssl":sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is 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 org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:503)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:452)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:302)
at com.ebs.csh.sva.handler.SOAPMessage.SendingSoapPostMsg(SOAPMessage.java:135)
at com.ebs.csh.sva.handler.SVAHandler.creditSVA(SVAHandler.java:136)
at com.ebs.csh.sva.services.SVAService.creditSVA(SVAService.java:73)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.ebs.commons.services.CommonService.processRequest(CommonService.java:276)
at com.ebs.csh.commons.services.CSHService.processRequest(CSHService.java:52)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy16.processRequest(Unknown Source)
at com.ebs.commons.webServices.CommonWebService.processRequest(CommonWebService.java:80)
at com.ebs.csh.commons.webServices.CSHWebService.processRequest(CSHWebService.java:63)
at com.ebs.csh.sva.webServices.SVAWebService.creditSVA(SVAWebService.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:541)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:383)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:288)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1836)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1337)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:154)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:966)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1262)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1289)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1273)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:261)
at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:118)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:357)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:218)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:194)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:88)
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:46)
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:49)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:488)
... 60 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1319)
... 82 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
... 88 more
how to fix this error.
thanks
after spending a long time to make this work, the solution is as follows:
first when setting the properties using System.put("key", "value") I noticed after many tries it is not setting the KeyStore value it is does not appear in the ssl log , also tried to set the properties as parameters in the tomcat configuration using -Djavax.net.ssl.keyStore="" this also didn't work.
so I read the KeyStore from an InputStream like this:
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream io = new FileInputStream("path/to/jks/file.jks");
try{
keystore.load(io, "pass".toCharArray());
} finally {
io.close();
}
and use the same previous code to read the TrustStore like :
KeyStore trustStore= KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream stream = new FileInputStream("path/to/truststore/file.jks");
try{
keystore.load(stream, "trusted".toCharArray());
} finally {
stream.close();
}
after that define the SSLContext :
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keystore, "keyPassword".toCharArray())
.loadTrustMaterial(truststore, new TrustSelfSignedStrategy())
.build();
loadKeyMaterial used to load the keyStore it takes the password of your privateKey "keyPassword" as a parameter, so you must protect the private key using a password, when I tried to use a plain private key not encrypted "protected" with a password, I get exception which says: java.security.UnrecoverableKeyException: Cannot recover key, by default this is the same as the keystore password unless you changed it.
then create the SSLConnectionSocketFactory and pass it as a parameter to the HttpClient ..
this worked for me :)
For anyone looking to implement 2 way mutual auth, following code worked perfectly for me.
FileInputStream keystoreInputStream = null;
FileInputStream truststoreInputStream = null;
try {
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystoreInputStream = new FileInputStream("C:\\Users\\Aman\\STSProj\\AppSecurity\\clientkeystore.p12");
keystore.load(keystoreInputStream, "client".toCharArray());
keystoreInputStream.close();
KeyStore trustore = KeyStore.getInstance(KeyStore.getDefaultType());
truststoreInputStream = new FileInputStream("C:\\Users\\Aman\\STSProj\\AppSecurity\\clienttruststore.p12");
trustore.load(truststoreInputStream, "client".toCharArray());
SSLContext sslcontext = SSLContexts.custom().useProtocol("TLS")
.loadKeyMaterial(keystore, "client".toCharArray())
.loadTrustMaterial(trustore, null).build();
HostnameVerifier hostnameverifier = null;
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslcontext,
null, null, hostnameverifier);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslSocketFactory).build();
HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
RestTemplate restTemp = new RestTemplate(requestFactory);
String greetings = restTemp
.getForObject("https://localhost:8443/SecureAppServer/test/security/hello/aman123", String.class);
System.out.println("Received greetings from secured server ---> " + greetings);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
if (keystoreInputStream != null) {
try {
keystoreInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (truststoreInputStream != null) {
try {
truststoreInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}