views:

505

answers:

5

Dear stack overflow.

I get a weird error when trying to use AXIS1.4 Wsdl2Java tool to generate client code for the web service that is installed on the secure IIS site. When I run the tool I get the following SSL exception:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No
 name matching XXXXXXX.net found
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1
591)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Clien
tHandshaker.java:975)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHa
ndshaker.java:123)
        at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:5
16)
        at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.jav
a:454)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.j
ava:884)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SS
LSocketImpl.java:1096)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketIm
pl.java:1123)

Weird thing is that this error only occurs when I run WSDL2Java, and only for this particular server. I have another web server with the identical set-up and everything works fine there. I triple checked all the keystores and it looks like all the CA certificates are loaded correctly. I tried using another server with the identical setup, and was able to generate the client proxy code without any problems. Weird thing is that if I use the code generated from the other server against the weird server everything works fine. It is only Wsdl2Java that is giving me a problem.

A: 

There is very likely a mismatch between the DNS name of the host (e.g. machine1.mydomain.tld) and the CommonName value from the certificate, hence the CertificateException. From this blog post:

  • if you'd like to connect via using IP as hostname;
    your certificate should include that ip value as a subject alternative name value (of type IPAddress : key=7).
  • if you'd like to connect via using DNS as hostname;
    your certificate should either include that DNS name as a subject alternative name value (of type DNS : key=2) or as a CommonName(CN) value.
Pascal Thivent
@Pascal not really, if it was a simple domain name mismatch, the browsers would complain and the code generated against the other server would complain as well.
Vlad
@Vlad Java and browsers may not share the same algorithm. And maybe the generated code contains a `HostnameVerifier` implementation so this doesn't prove anything. Did you check the CN in the certificate?
Pascal Thivent
@Pascal the CN is correct. This was the first thing I checked.
Vlad
A: 

If you have the server certificate at hand and openssl installed you can dump the contents of the certificate with something like:

$ openssl x509 -noout -text -in filename-here.pem

You'll see "CN=" as part of the Subject, and if it has the altSubjectName extension in the certificate, you'll see that below under X509v3 extensions, as X509v3 Subject Alternative Name, and you'll be looking for something like DNS:host-name-here.

If that matches the hostname you are connecting to, then just check if you are connecting by IP address, or by hostname, in whatever SSL interface you go through, and make sure it is by hostname and not by IP address.

If there is no matching name in the certificate (that matches the hostname you are connecting to), some SSL interfaces will let you ignore the "name mismatch". (I don't know how to do that in your specific case.)

EDIT:

Try connecting by hostname instead of IP address and see if there is a difference.

If the IP is listed in the certificate, you'll see something like IP:xx.xx.xx.xx under X509v3 Subject Alternative Name in the openssl output.

If the IP is not listed, run nslookup from a shell prompt and compare the output for both the working and non-working server addresses. This may be how the working server is matching the hostname (i.e. by way of getnetbyaddr).

EDIT 2:

Have you tried connecting by hostname (in your connect string) and still get the same error? It doesn't matter if connecting via browser using the IP address works -- the browser may not be verifying the hostname using the same algorithm. Have you tried connecting to the good server using an IP address in the connect? Also, look here for something to try: found with quick Google

Jim Flood
The CN is correct and I am connecting by the IP address. It is not simple name mismatch problem. If it were, the browsers and generated code would complain. The problem only comes up with WSDL2Java
Vlad
A: 

The problem is that WSDL2Java has rejected the Server certificate because of name. In Java, the hostname you use to connect to the remote system much match the common name in the certificate. It will not reverse lookup based on the IP Address. You must connect using the hostname.

Other replies indicated that you are connecting via the IP Address. This is not the correct way to do things. Java will validate the certificate against the hostname it is connecting to.

If you are connecting using the IP Address you might not have DNS set up in your environment. The easiest way to get around this is to add the hostname to your hosts file. In windows this is located in 'C:\Windows\System32\drivers\etc\hosts'.

xx.xx.xx.xx      XXXXXXXXXX.net

This will allow you to use the hostname to get the WSDL through WSDL2Java.

Alternative:

There is an alternative if that still does not work. Download the .wsdl file using your web browser. Have WSDL2Java create your Java stubs from the local file on disk instead of on the web server. The code generated will be identical but it will not have to go through SSL to get the WSDL.

Chris Dail
Please read the problem description carefully. The host name does match certificate CN= name. So, all browsers and even generated client code works fine. WSDL2Java is the only thing that doesn't work against this specific server. I was able to generate the client code against the other server that I used for development which has identical set of software. The only difference between two servers is that the production (which doesn't work) uses the cert signed by GlobalSign and the development uses the cert signed by CACert.org
Vlad
When the same WSDL2Java connects to the good server then, you are also connecting by IP address? Have you tried connecting by hostname in the broken case and it still doesn't work? (With the WSDL2Java connection -- not just trying from a browser.) In that case, I would check if the X509 certificate extensions differ between the certificates, specifically Key Usage and Extended Key Usage -- but that's just a shot in the dark.
Jim Flood
A: 

Could it be that you are missing the appropriate GlobalSign root certificate for Java.

# Import a root or intermediate CA certificate to an existing Java keystore
keytool -import -trustcacerts -alias root -file Thawte.crt -keystore keystore.jks

Another possibility relates to the combination of the root and intermediate certificate. More from the GlobalSign website:

"Some Apache and Java-based applications require the root and intermediate certificates to be bundled in one certificate..."

jt
A: 

You may find using the SSL debugging system properties can be helpful to investigate this problem:

-Djavax.net.debug=ssl

If there's too much printed out, you can filter some things, perhaps this:

-Djavax.net.debug=ssl,trustmanager

The output is not necessarily obvious to read, but it should tell you where the error is in more detail.

Bruno