0
votes

I am getting security certificate errors in the code below (source). The exception is:

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

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.

How do I disable the check for security certificates?

import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomNode;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlFileInput;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlPasswordInput;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;

public class WebRobot {
  public static void login(String username, String password) {
    String loginUrl = "http://example.com";
    int loginFormNum = 1;
    String usernameInputName = "nameinput";
    String passwordInputName = "passinput";
    String submitLoginButtonValue = "Sign In";

    // create the HTMLUnit WebClient instance
    WebClient wclient = new WebClient();

    // configure WebClient based on your desired
    wclient.getOptions().setPrintContentOnFailingStatusCode(false);
    wclient.getOptions().setCssEnabled(false);
    wclient.getOptions().setThrowExceptionOnFailingStatusCode(false);
    wclient.getOptions().setThrowExceptionOnScriptError(false);

    try {
      // get the login page by connect to the URL 
      final HtmlPage loginPage = (HtmlPage)wclient.getPage(loginUrl);

      // get the login form by its form number. mine is 1 (form[1])
      final HtmlForm loginForm = loginPage.getForms().get(loginFormNum);

      // get the text input field by the name and set the value
      final HtmlTextInput txtUser = loginForm.getInputByName(usernameInputName);
      txtUser.setValueAttribute(username);

      // get the password input field by the name and set the value
      final HtmlPasswordInput txtpass = loginForm.getInputByName(passwordInputName);
      txtpass.setValueAttribute(password);

      // get the submit button by the text value
      final HtmlSubmitInput submitLogin = loginForm.getInputByValue(submitLoginButtonValue);

      // after we set the name & password then we click the submit button
      // it will return a page (redirect or message alert or somethin, different sites different behaviour)
      // or it could throws an exception
      final HtmlPage returnPage = submitLogin.click();  

      // we can analyze the return page based on the body
      // ex: mine is check if its body contains less than 5 elements
      final HtmlElement returnBody = returnPage.getBody(); 
      if (returnBody==null || returnBody.getChildElementCount()<5) {
        // bla.. bla.. bla..
      }

    } catch(FailingHttpStatusCodeException e) {
      e.printStackTrace();
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
}
2
I gave up on trying to establish a secure connection. The root cert , keytool etc. drove me crazy. Nothing worked and I gave up. Luckily, I only have to make a dirty, temporary script and nothing for production. So, its not a problem for me.big_space

2 Answers

2
votes

Before you can do this, you must add the following code:

System.setProperty("jsse.enableSNIExtension", "false");

before the lines:

// get the login page by connect to the URL
final HtmlPage loginPage = (HtmlPage) wclient.getPage(loginUrl);

If you don't do this, you will get an error:

javax.net.ssl.SSLProtocolException: handshake alert:  unrecognized_name

Then, depending on the version of WebClient class you are using, try one of the lines of code below:

wclient.setUseInsecureSSL(true);
wclient.getOptions().setUseInsecureSSL(true);

Note - Disabling security is very dangerous. So don't do this in production code.

0
votes

Take a look into how to (either one of these):

  1. Generate a properly trusted SSL certificate (on the server you are accessing from your app). or
  2. Generate a self-signed SSL certificate, and add this certificate to your trusted certificates in your application, or your application's host machine. or
  3. Ignore / bypass SSL validation (play around SSLSocketFactories).

Keep in mind, that step 2 could be a potential security risk unless done in a properly trusted environment (both client and server), and step 3 eliminats completely the security functionality given by SSL. Make sure you know what you want to achieve at the end before taking an option.

Also, avoid use of SSL3 due to the POODLE vulnerability discovered recently.