views:

1963

answers:

2

Hello,

I've been working on a program to extract information from a dynamic web application, and the program worked fine until I set my tomcat server to use SSL using a self-signed(thus, untrusted) certificate. The stack trace of the error 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 Error: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1584) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174) at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848) at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106) at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495) at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:877) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1089) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1116) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1100) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:402) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:170) at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:857) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230) at com.certicom.gls.glscs.nongui.URLReader$PostURL.setupURL(URLReader.java:34) at com.certicom.gls.glscs.nongui.URLReader.getLogin(URLReader.java:227) at com.certicom.gls.glscs.nongui.URLReader.testLogin(URLReader.java:436) at com.certicom.gls.glscs.nongui.Controller.loginMenu(Controller.java:384) at com.certicom.gls.glscs.nongui.Controller.menu(Controller.java:324) at com.certicom.gls.glscs.nongui.Controller.(Controller.java:49) at com.certicom.gls.glscs.nongui.Controller.main(Controller.java:61)

In a web browser, the user is prompted a warning when accessing a HTTPS site with an untrusted certificate, and asked to make an exception if he likes to proceed; I would like to implement a similar functionality for my command-line application... I admit that I am new to socket programming and networking in general; any advice solving this problem will be great!

+9  A: 

Here is some relevant code (from here):

// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public void checkClientTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }
        public void checkServerTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }
    }
};

// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
}

// Now you can access an https URL without having the certificate in the truststore
try {
    URL url = new URL("https://hostname/index.html");
} catch (MalformedURLException e) {
}

This will completely disable SSL checking. Just don't learn exception handling from such code!

To do what you want you would have to implement a check in your TrustManager that prompts the user.

Yishai
This is the way to do it; however, you need to be really careful that this code doesn't make it to production- and if you're using untrusted certs in a production app, it's a Bad Thing.If you have a dependency injection framework like spring in your app, consider isolating this code and have a secure version for the production environment.
Tim Howland
A: 

Hi,

Can you tell me the package for TrustManager which you are using here. I have seen similar code in The Java Developers Almanac 1.4, but when I tried to use it with JDK 5, it could not be resolved.