How to ignore server certificate when implementing mutual authentication with OkHttp? - java

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?

Related

SSL Handshake error after Client Finished handshake message

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:)

io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate

Small question regarding an issue faced when mTLS is enabled.
On a Java + Spring Webflux project for both client and server, the client is configured to send requests as such:
public SslContext getSslContext() {
try {
final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
try (InputStream file = Files.newInputStream(Paths.get(URI.create(keyStorePath)))) {
final KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(file, keyStorePassPhrase.toCharArray());
keyManagerFactory.init(keyStore, keyPassPhrase.toCharArray());
}
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
try (InputStream trustStoreFile = Files.newInputStream(Paths.get(URI.create(trustStorePath)))) {
final KeyStore trustStore = KeyStore.getInstance(trustStoreType);
trustStore.load(trustStoreFile, trustStorePassPhrase.toCharArray());
trustManagerFactory.init(trustStore);
}
return SslContextBuilder.forClient().keyManager(keyManagerFactory).trustManager(trustManagerFactory).build();
} catch (CertificateException | NoSuchAlgorithmException | IOException | KeyStoreException | UnrecoverableKeyException e) {
return null;
}
}
//the webflux web client
WebClient.create().mutate().defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).clientConnector(new ReactorClientHttpConnector(HttpClient.create().wiretap(true).secure(sslContextSpec -> sslContextSpec.sslContext(getSslContext())))).build();
Upon the HTTP call, I am seeing this on client side log:
[or-http-epoll-3] r.netty.http.client.HttpClientConnect : [id: 0x02d7d229, L:/123:44092 ! R:the-service.com/456:19010] The connection observed an error
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:478) ~[netty-codec-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795) ~[netty-transport-native-epoll-4.1.58.Final-linux-x86_64.jar!/:4.1.58.Final]
at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480) ~[netty-transport-native-epoll-4.1.58.Final-linux-x86_64.jar!/:4.1.58.Final]
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378) ~[netty-transport-native-epoll-4.1.58.Final-linux-x86_64.jar!/:4.1.58.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.58.Final.jar!/:4.1.58.Final]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na]
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:336) ~[na:na]
at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293) ~[na:na]
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:185) ~[na:na]
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:681) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:636) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:454) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:433) ~[na:na]
at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:637) ~[na:na]
at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:282) ~[netty-handler-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1387) ~[netty-handler-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1282) ~[netty-handler-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1329) ~[netty-handler-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508) ~[netty-codec-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447) ~[netty-codec-4.1.58.Final.jar!/:4.1.58.Final]
... 15 common frames omitted
And on server log, I am seeing the following.
s.ApplicationProtocolNegotiationHandler : [id: 0x10b61280, L:/1xx.xxx:19010 - R:/1xxx:45678] Failed to select the application-level protocol:
javax.net.ssl.SSLHandshakeException: Empty client certificate chain
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na]
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:336) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:292) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:283) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1193) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1180) ~[na:na]
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392) ~[na:na]
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1074) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1061) ~[na:na]
at java.base/java.security.AccessController.doPrivileged(Native Method) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:1008) ~[na:na]
at io.netty.handler.ssl.SslHandler.runAllDelegatedTasks(SslHandler.java:1557) ~[netty-handler-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1571) ~[netty-handler-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1455) ~[netty-handler-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1282) ~[netty-handler-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1329) ~[netty-handler-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508) ~[netty-codec-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447) ~[netty-codec-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795) ~[netty-transport-native-epoll-4.1.58.Final-linux-x86_64.jar!/:4.1.58.Final]
at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480) ~[netty-transport-native-epoll-4.1.58.Final-linux-x86_64.jar!/:4.1.58.Final]
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378) ~[netty-transport-native-epoll-4.1.58.Final-linux-x86_64.jar!/:4.1.58.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.58.Final.jar!/:4.1.58.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.58.Final.jar!/:4.1.58.Final]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
A first intuition was to look inside the server trust store, and for sure, I am trusting the root of the certificate chain used in the client keystore.
Why is it a "bad" certificate?
Why the client certificate chain is empty? I Build the client keystore with a full chain.
I will be glad if I can understand the root cause of this issue and how to fix it.
Thank you

Soap Webservice CA certificate validation: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors

I'm trying to validate a CA certificate from windows keystore with a wsse:BinarySecurityToken (ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3") which I get from the XML, but it fails through an exception: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors.
public static void main(String[] args) {
String alias = "foo";
KeyStore personalKS = KeyStore.getInstance("Windows-Root");
new SecurityPermission("authProvider.SunMSCAPI");
personalKS.load(null, null);
Certificate cert = personalKS.getCertificate(alias);
//has to be transmitted as byte later
byte[] caCert = cert.getEncoded();
CertificateFactory cf = CertificateFactory.getInstance("X509");
List<Object> list = new ArrayList<Object>();
list.add(caCert);
// X509Certificate x509tokenCert, received through a parameter
list.add(x509tokenCert);
CertStoreParameters certStoreParams = new CollectionCertStoreParameters(list);
// return certStoreParams.toString();
CertStore certStore = CertStore.getInstance("Collection", certStoreParams);
// trusted ca cert
Set<TrustAnchor> trust = Collections.singleton(new TrustAnchor(caCert, null));
PKIXParameters params = new PKIXParameters(trust);
// set CRL checking
params.setRevocationEnabled(false);
params.addCertStore(certStore);
// sets the time for the validity of the certification // path should be determined
params.setDate(date);
List<X509Certificate> certChain = new ArrayList<X509Certificate>(); // add certificate
certChain.add(x509tokenCert);
CertPath certPath = cf.generateCertPath(certChain);
CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX");
certPathValidator.validate(certPath, params);
}
Console:
Exception in thread "main" com.sun.xml.internal.ws.fault.ServerSOAPFaultException: Client received SOAP Fault from server: java.lang.Exception: Path does not chain with any of the trust anchors--> java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:159)
at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:85)
at java.security.cert.CertPathValidator.validate(CertPathValidator.java:292)
at evvvalidator.util.Validator.isCertificateValid(Validator.java:124)
at evvvalidator.CustomValidator.validateFromDoc(CustomValidator.java:100)
at evvvalidator.SignatureValidator.validation(SignatureValidator.java:22)
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.apache.axis.providers.java.RPCProvider.invokeMethod(RPCProvider.java:397)
at org.apache.axis.providers.java.RPCProvider.processMessage(RPCProvider.java:186)
at org.apache.axis.providers.java.JavaProvider.invoke(JavaProvider.java:323)
at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
at org.apache.axis.handlers.soap.SOAPService.invoke(SOAPService.java:454)
at org.apache.axis.server.AxisServer.invoke(AxisServer.java:281)
at org.apache.axis.transport.http.AxisServlet.doPost(AxisServlet.java:699)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at org.apache.axis.transport.http.AxisServletBase.service(AxisServletBase.java:327)
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)
Please see the server log to find more detail regarding exact cause of the failure.
at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(Unknown Source)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(Unknown Source)
at com.sun.xml.internal.ws.client.sei.StubHandler.readResponse(Unknown Source)
at com.sun.xml.internal.ws.db.DatabindingImpl.deserializeResponse(Unknown Source)
at com.sun.xml.internal.ws.db.DatabindingImpl.deserializeResponse(Unknown Source)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(Unknown Source)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(Unknown Source)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(Unknown Source)
at com.sun.proxy.$Proxy31.validation(Unknown Source)
at soaprequest.SoapRequest.main(SoapRequest.java:22)
Solved the problem with the colleague's help. Was using the wrong certificate. This Java exception was not helpful at all (or am I wrong?).

Weblogic uses configured keystore even if the TrustManager accepting all certs is configured for SSLContext

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.

How to allow self-signed SSL certificates in older version of rest-assured

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

Categories

Resources