8

I need to consume a web service which was built under Https in java. The Web Service Client was generated using Eclipse and to call it I use the following code:

ServicioTimbradoPruebasLocator ServicioTimbradoLocator = new ServicioTimbradoPruebasLocator();
                            ServicioTimbradoPruebasSoap ServicioTimbrado = ServicioTimbradoLocator.getServicioTimbradoPruebasSoap();
                            javax.xml.rpc.Stub s =((javax.xml.rpc.Stub)ServicioTimbrado);
                            s._setProperty(javax.xml.rpc.Stub.USERNAME_PROPERTY, "XXXXXXXX");
                            s._setProperty(javax.xml.rpc.Stub.PASSWORD_PROPERTY, "psswd");          
                            String resultado = ServicioTimbrado.generaTimbre(xml.getBytes());
                            System.out.println("resultado: " +resultado);

On this line String resultado = ServicioTimbrado.generaTimbre(xml.getBytes()); I get the following error:

AxisFault
     [java]  faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
     [java]  faultSubcode: 
     [java]  faultString: 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
     [java]  faultActor: 
     [java]  faultNode: 
     [java]  faultDetail: 
     [java]     {http://xml.apache.org/axis/}stackTrace: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
     [java]     at sun.security.ssl.Alerts.getSSLException(Unknown Source)
     [java]     at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
     [java]     at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
     [java]     at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
     [java]     at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
     [java]     at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
     [java]     at sun.security.ssl.Handshaker.processLoop(Unknown Source)
     [java]     at sun.security.ssl.Handshaker.process_record(Unknown Source)
     [java]     at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
     [java]     at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
     [java]     at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
     [java]     at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
     [java]     at org.apache.axis.components.net.JSSESocketFactory.create(JSSESocketFactory.java:186)
     [java]     at org.apache.axis.transport.http.HTTPSender.getSocket(HTTPSender.java:191)
     [java]     at org.apache.axis.transport.http.HTTPSender.writeToSocket(HTTPSender.java:404)
     [java]     at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:138)
     [java]     at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
     [java]     at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
     [java]     at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
     [java]     at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)
     [java]     at org.apache.axis.client.Call.invokeEngine(Call.java:2784)
     [java]     at org.apache.axis.client.Call.invoke(Call.java:2767)
     [java]     at org.apache.axis.client.Call.invoke(Call.java:2443)
     [java]     at org.apache.axis.client.Call.invoke(Call.java:2366)
     [java]     at org.apache.axis.client.Call.invoke(Call.java:1812)
     [java]     at mx.com.timbrado.test.cfdi.ServicioTimbradoPruebasSoapStub.generaTimbre(ServicioTimbradoPruebasSoapStub.java:107)
     [java]     at natura.facturacion.general.GuardarFacturaElectronicav2.doPost(GuardarFacturaElectronicav2.java:136) ...

I want to know if there is a way to send the certificate among with the webservice call. More information about the wsdl contract and the java generated files could be found here

Community
  • 1
  • 1
user1084509
  • 1,832
  • 10
  • 33
  • 48
  • Looks to me that it's more along the lines that the CA(s)'s listed in the cert's chain can't be verified, e.g. it's using a CA that java knows nothing about. – Marc B Jan 31 '12 at 19:58
  • 2
    Ah... Spanish classes and methods.. it's been a long time since I worked with those. – Luciano Jan 31 '12 at 19:58
  • In order to communicate, client and WS must share certificates. Each one having a keystore with an own private key to decipher input and a partner's public key to cipher output. That path is configured in an XML file related to policies whose name I can't remember... – Alfabravo Jan 31 '12 at 20:10

2 Answers2

6

Depending on the version of Java you are using, one of the "recent" updates to the 1.6 JRE/JDK include a significant change in the global CACerts (the Trusted authority that signs SSL Certificats, for instance Verisign) to include some of the new certificate types that are around.

I recommend upgrading to the latest versions of Java to see if that works, if not, Option 2 is...

Using SSLPoke.java you can find out which certificates are missing, and the InstallCert.java to install them as follows;

  1. java InstallCert webserver.domain.com:443
  2. Copy the generated “jssecacerts” file to your “$JAVA_HOME\jre\lib\security” folder.

If this still causes issues, can you include the output from sslpoke, example usage;

# java SSLPoke webserver.domain.com 443
Successfully connected

If ALL that doesnt work, and you can get the certificate file (crt) you can manually import the file using the keytool command (cacerts is a file that will be created in your local working directory; ensure you move it into the java security folder in your JRE/JDK);

keytool -import -trustcacerts -alias AddTrustExternalCARoot -file cetificate.crt -keystore cacerts

Doug Porter
  • 7,721
  • 4
  • 40
  • 55
Toby Jackson
  • 937
  • 1
  • 6
  • 15
  • I used the InstallCert.java class and it indicates that the certificate is correctly added to my javastore. A file named jsseacacerts is generated with this information. I copy this file to $JAVA_HOME/jre/lib/security and I get the same error. I try to manually import my certificate to my keystore with the following command: $JAVA_HOME/bin/keytool.exe -import -file mycert.cer -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass psswd and I get a java.ioFileNotFoundException – user1084509 Jan 31 '12 at 22:20
  • The SSLPoke throws me the following error: 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(Unknown Source) at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source) at sun.security.ssl.Handshaker.fatalSE(Unknown Source) at sun.security.ssl.Handshaker.fatalSE(Unknown Source) at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)... – user1084509 Jan 31 '12 at 22:34
  • It may be possible that there are multiple installations of Java on your machine, the InstallCert.java is the [recommended](http://blogs.oracle.com/gc/entry/unable_to_find_valid_certification) way of solving this problem. Can you try running the InstallCert command using the same java runtimes that are operating your server container (I assume its in Tomcat/JBoss/Glassfish or similar?) – Toby Jackson Feb 01 '12 at 08:14
  • 1
    Works for me after following the guide from http://www.mkyong.com/webservices/jax-ws/suncertpathbuilderexception-unable-to-find-valid-certification-path-to-requested-target/. It guides how to use InstallCert.java. Ensure verification step is passed. Need to restart application server though. – antimatter Feb 07 '14 at 13:20
1

You can refer to this thread: How to handle invalid SSL certificates with Apache HttpClient?

Of course here you have a WSDL SOAP Web Service, there you have an Apache HTTP Client, but the error is the same and you can handle it in the same way (or ways).

You can:

1 - Force your program to accept ANY SSL certificate

2 - Download and install in your JVM the SSL certificate that you're missing

The 1st one is easier (in the most of the case), but you should use it ONLY before the release or you'll be easily exposed to a "Man in the middle attack". The 2nd (usually) a better choice.

Here there is a synthetic but well explained documantation to those 2 points described before with code samples: http://ws.apache.org/xmlrpc/ssl.html

Community
  • 1
  • 1
thermz
  • 2,386
  • 3
  • 20
  • 28