Trust all SSL certificates in Java Playframework 2.2
Asked Answered
P

4

15

I am trying to call a web-service(Which has self signed SSL certificate) in Play Framework Using the following function:

public static play.libs.F.Promise<Result> webcall() {
       String feedUrl = "https://10.0.1.1/client/api";
       final play.libs.F.Promise<Result> resultPromise = WS.url(feedUrl).get().map(
                    new Function<WS.Response, Result>() {
                        public Result apply(WS.Response response) {
                            return ok("Feed title:" + response.asJson().findPath("title").toString());
                        }
                    }
            );
            return resultPromise;
        }

It is throwing the following Error in Logs,

[error] play - Cannot invoke the action, eventually got an error: java.net.ConnectException: General SSLEngine problem to https://10.0.1.1/client/api
[error] application - 

! @6fpimpnp6 - Internal server error, for (GET) [/webcall] ->

play.api.Application$$anon$1: Execution exception[[ConnectException: General SSLEngine problem to https://10.0.1.1/client/api]]
    at play.api.Application$class.handleError(Application.scala:293) ~[play_2.10.jar:2.2.0]
    at play.api.DefaultApplication.handleError(Application.scala:399) [play_2.10.jar:2.2.0]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.0]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.0]
    at scala.Option.map(Option.scala:145) [scala-library.jar:na]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2.applyOrElse(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.0]
java.net.ConnectException: General SSLEngine problem to https://10.0.1.1/client/api
    at com.ning.http.client.providers.netty.NettyConnectListener.operationComplete(NettyConnectListener.java:103) ~[async-http-client.jar:na]
    at org.jboss.netty.channel.DefaultChannelFuture.notifyListener(DefaultChannelFuture.java:427) ~[netty.jar:na]
    at org.jboss.netty.channel.DefaultChannelFuture.notifyListeners(DefaultChannelFuture.java:413) ~[netty.jar:na]
    at org.jboss.netty.channel.DefaultChannelFuture.setFailure(DefaultChannelFuture.java:380) ~[netty.jar:na]
    at org.jboss.netty.handler.ssl.SslHandler.setHandshakeFailure(SslHandler.java:1417) ~[netty.jar:na]
    at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1293) ~[netty.jar:na]
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1362) ~[na:1.7.0_40]
    at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:513) ~[na:1.7.0_40]
    at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:790) ~[na:1.7.0_40]
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:758) ~[na:1.7.0_40]
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624) ~[na:1.7.0_40]
    at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1225) ~[netty.jar:na]
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[na:1.7.0_40]
    at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1683) ~[na:1.7.0_40]
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:278) ~[na:1.7.0_40]
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270) ~[na:1.7.0_40]
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1341) ~[na:1.7.0_40]
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153) ~[na:1.7.0_40]
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) ~[na:1.7.0_40]
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) ~[na:1.7.0_40]
    at sun.security.validator.Validator.validate(Validator.java:260) ~[na:1.7.0_40]
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326) ~[na:1.7.0_40]
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:283) ~[na:1.7.0_40]
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:138) ~[na:1.7.0_40]
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) ~[na:1.7.0_40]
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268) ~[na:1.7.0_40]
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380) ~[na:1.7.0_40]
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) ~[na:1.7.0_40]
    at sun.security.validator.Validator.validate(Validator.java:260) ~[na:1.7.0_40]
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326) ~[na:1.7.0_40]

If I call the service using HttpsURLConnection its working fine by adding

TrustManager[] trustAllcerts = new TrustManager[]{
    new X509TrustManager() {

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }
    }};

javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
sc.init(null, trustAllcerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {

    @Override
    public boolean verify(String arg0, SSLSession arg1) {
        // TODO Auto-generated method stub
        return false;
    }
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

How to Trust all Selfsigned / Untrusted ssl certificates in Play Framework?

Plash answered 10/10, 2013 at 6:42 Comment(0)
C
26

Try adding the following code to conf/application.conf file

ws.acceptAnyCertificate=true

This will work if you are using the Promise class. But won't work if you are calling the service through other HttpClients.

UPDATE: As of Play Framework 2.5, you should use the following -

play.ws.ssl.loose.acceptAnyCertificate=true

You can do this in development environment, but you should never do this in Production environment, as it can prove as a security threat. In production, instead install the certificates of the client in your keystore.

Clout answered 10/10, 2013 at 8:21 Comment(3)
Please don't do this. You can generate the certificates you need from the Play TLS activator example: typesafe.com/activator/template/play-tls-example and then add cacerts to the trustManager in ws.ssl (see the example below)Quamash
This is dangerous, security-wise. You don't want to blindly accept any certificateSev
As of play 2.5 you could use play.ws.ssl.loose.acceptAnyCertificate=true. But as said before this can be very dangerous, please read playframework.com/documentation/2.5.x/LooseSSL before using thisPeonage
Q
7

Please don't accept all certificates -- you can use the trust manager with your custom certificates, and then fall back to the default trust store.

ws.ssl {
  trustManager = {
     stores = [
      { path: ${store.directory}/exampletrust.jks }     # Added trust store
      { path: ${java.home}/lib/security/cacerts } # Fallback to default JSSE trust store
     ]
  }
}

See http://www.playframework.com/documentation/2.3.x/ExampleSSLConfig for more details.

Quamash answered 8/7, 2014 at 18:27 Comment(4)
I am new to the play framework and wondering where exactly store.directory is? How does packaging work with the custom trust store? I stuck it in conf and referenced with path 'conf/exampletrust.jks'. Will that get packaged with the application correctly?Intuition
Yes, that's fine. See github.com/wsargent/play-ws-with-letsencrypt/blob/master/conf/… for an example of some custom certificates.Quamash
It looks like if a relative path is used for a trust store, it will be relative to where the application was started. Is there a variable that can be used in the config to reference the root directory of the deployed application so that the trust store can be deployed without using an absolute path?Intuition
You can use HOCON substitution with fallback to environment variables to define an absolute path github.com/typesafehub/config/blob/master/… using ${?ABSOLUTE_PATH} etc.Quamash
C
4

Just install the certificate you're trying to trust in your trust store.

Don't accept all certificates blindly. This makes your application vulnerable to MITM attacks.

Even if it's just for development, that's the kind of code and settings that people forget to remove when it's deadline day.

The next problem you might have is host name matching. You're using an IP address in https://10.0.1.1/, so your certificate should have a SAN entry for this IP address, not just that IP address in its CN. More details here. Don't use the HostnameVerifier you've set up in your code (for the same reasons).

Contralto answered 10/10, 2013 at 11:26 Comment(1)
Thank you for your valuable suggestionPlash
C
1

You can try to set these parameters

-Dmail.smtp.ssl.trust=* -Dmail.smtp.ssl.checkserveridentity=false

when starting your app. Here is the list of all parameters: https://javamail.java.net/nonav/docs/api/com/sun/mail/smtp/package-summary.html

Chokecherry answered 24/8, 2016 at 10:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.