Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bypass certificate checking in a Java web service client

Tags:

java

wsdl

https

Use Case: There is a web service posted as https://a.b.c.d/zz?wsdl

What i would like to do is to query this URI and IF i get a VALID WSDL, i return a boolean "true" else "false. Now, if i go via Chrome browser to this URL, i would have to manually do an accept on the cert warning, and THEN the WSDL gets downloaded. But how can do this via Java / HttpsURLConnection

import java.net.URL;
import java.io.*;
import javax.net.ssl.HttpsURLConnection;

public class JavaHttpsExample
{
  public static void main(String[] args)
  throws Exception
  {
    String httpsURL = "https://a.b.c.d/zz/V2.0/api?wsdl";
    URL myurl = new URL(httpsURL);
    HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
    InputStream ins = con.getInputStream();
    InputStreamReader isr = new InputStreamReader(ins);
    BufferedReader in = new BufferedReader(isr);

    String inputLine;

    while ((inputLine = in.readLine()) != null)
    {
      System.out.println(inputLine);
    }

    in.close();
  }
}

and i get an error:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names matching IP address a.b.c.d found at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source) at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source) at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source) at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source) at JavaHttpsExample.main(JavaHttpsExample.java:14) Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address a.b.c.d found at sun.security.util.HostnameChecker.matchIP(Unknown Source) at sun.security.util.HostnameChecker.match(Unknown Source) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)

i have replaced the real IP with a.b.c.d (of course)

like image 303
kamal Avatar asked Aug 16 '12 16:08

kamal


People also ask

How do you bypass a certificate on a website?

Select the options gear, then select “Internet Options“. Select the “Advanced” tab. Scroll down to the “Security” section, and uncheck the “Warn about certficate address mismatch” option. Select “OK“.


1 Answers

Don't use a stubbed out TrustManager as this makes your application trust everyone. I would recommend downloading the certificate presented by the site and adding it to a private, trusted keystore. This lets you make an exception for that one site without greenlighting everyone.

I also like this approach because it requires no code changes.

In Chrome, click the lock icon to the left of the url. Then click "Certificate Information". Go to the "Details" tab and click "Copy to file". Save it as a "base64 encoded X.509 (.cer)" to "SITENAME.cer".

Copy $JAVA_HOME/lib/security/cacerts to your application's directory as "mykeystore.jks".

Install the certificate with:

keytool -keystore mykeystore.jks -storepass changeit -importcert -alias SITENAME -trustcacerts -file SITE.cer

Now, when you run your application, tell it to use the private certificate store:

java -Djavax.net.ssl.trustStore=mykeystore.jks ...
like image 166
Devon_C_Miller Avatar answered Sep 19 '22 16:09

Devon_C_Miller