0

Java EE application where there is a SOAP call using SoapClient object (deployed in Wildfly 9):

SOAPMessage reply = con.call(message, url);

I am receiving following message:

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.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.setupWrappedStream(URLConnectionHTTPConduit.java:183)

Due to certificate problems, tried to bypass the error:

    TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                    return;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                    return;
                }
            }
    };     
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());


    soapConnectionFactory = SOAPConnectionFactory.newInstance();

This didn´t have any effect

Any ideas?

kandan
  • 715
  • 2
  • 12
  • 39

1 Answers1

2

If CXF is you client framework, then it does not use the default HTTP Socket factory, but its own.

Therefore, I advise you to use the CXF configuration tools as described in the CXF manual and the TLS parameters configuration

It boils down to creating a conduit for your particular endpoint and setting its parameters, for example to set a configuration for a endpoint on the HelloWorld namespace :

<http:conduit name="{http://apache.org/hello_world}HelloWorld.http-conduit">
<http:tlsClientParameters>
  <sec:trustManagers>
    <sec:keyStore type="JKS" password="password"
                  file="my/file/dir/Truststore.jks"/>
  </sec:trustManagers>
</http:tlsClientParameters>

Note that you can set a SSLSocketFactory instead of a keystore (see second link above) :

Client TLS Parameters : sslSocketFactory > A SSLSocketFactory to use. All other bean properties are ignored if this is set.

If you do not wish to use XML / Spring configuration, you can resort to programmatic calls, by taping into the CXF API :

How to configure the HTTPConduit for the SOAP Client?
First you need get the HTTPConduit from the Proxy object or Client, then you can set the HTTPClientPolicy, AuthorizationPolicy, ProxyAuthorizationPolicy, TLSClientParameters, and/or HttpBasicAuthSupplier.

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
...

URL wsdl = getClass().getResource("wsdl/greeting.wsdl");
SOAPService service = new SOAPService(wsdl, serviceName);
Greeter greeter = service.getPort(portName, Greeter.class);

// Okay, are you sick of configuration files 
 // This will show you how to configure the http conduit dynamically
Client client = ClientProxy.getClient(greeter);
HTTPConduit http = (HTTPConduit) client.getConduit();

HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();

httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
httpClientPolicy.setReceiveTimeout(32000);

http.setClient(httpClientPolicy);

...
  greeter.sayHi("Hello");

You can also check this SO answer How to programmatically set the SSLContext of a JAX-WS client? that has solutions for CXF and non CXF cases.

You may want to look at this solution in particular :

<http-conf:conduit name="*.http-conduit">
  <http-conf:tlsClientParameters useHttpsURLConnectionDefaultSslSocketFactory="true" />
<http-conf:conduit>
GPI
  • 9,088
  • 2
  • 31
  • 38
  • The problem I have is: don´t use Spring and don´t have WSDL file. This call is simply made by creating a SOAP client (SOAPConnectionFactory.createConnection()) and later invokes the SOAP method using the call method and the message/URL as parameters. – kandan Jun 29 '17 at 16:32
  • Understand have to set TLS parameters of the HTTP Conduit object. But is there any other way? maybe some configuration inside standalone.xml, I don´t know. Uses Wildfly 9. – kandan Jun 29 '17 at 16:34
  • Sorry, I do not know about this. The key would be to look inside the CXF/Saaj implementations to see how CXF build its transport conduit starting from the SOAPMessageFactory. The full stack trace of your error may help you navigate through the code. – GPI Jun 29 '17 at 16:53
  • Tried , JBoss SOAPConnectionImpl class gets an instance of HTTP Conduit which already has TLS parameters set. No idea how to set them. Your solution seems to point to the correct way, will ask the provider if they have the WSDL file or disable HTTPS instead. Thank you. – kandan Jun 29 '17 at 17:03
  • as workaround/temporary solution downloaded sources from jbossws.jboss.org/downloads/latest and manually modified HTTPConduit/TLS client parameters (called setTrustManagers) to skip certificate check. GPI's solution seems valid as general approach. – kandan Jul 04 '17 at 09:13