How can I ignore SSL certificate issues from the context of the WebConversation
or WebRequest
object? I know I can create a fake TrustManager
that accepts all certificates but how can I set this in the HttpUnit context?
Here is the exception I am getting:
[Security:090508]Certificate chain received from my.domain.com - NUM.NUM.NUM.NUM was incomplete.,
[Security:090477]Certificate chain received from my.domain.com - NUM.NUM.NUM.NUM was not trusted causing SSL handshake failure.
I need to somehow set the SSLSocket settings to the WebConversation or WebRequest object; looking at the JavaDocs for HttpUnit there is no such method or constructor to do so. Is there a way I can wrap this inside some object which has exposed SSLSocket properties?
According to this FAQ entry, it seems that HttpUnit is using the SSL implementation provided by the Java standard library. Writing and installing an "accept all" TrustManager
is straightforward:
private static class AnyTrustManager implements X509TrustManager
{
public void checkClientTrusted(X509Certificate[] chain, String authType)
{
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
{
}
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[0];
}
}
static {
try {
SSLContext ssl = SSLContext.getInstance("SSL");
ssl.init(null, new X509TrustManager[] {new AnyTrustManager()}, null);
HttpsURLConnection.setDefaultSSLSocketFactory(ssl.getSocketFactory());
} catch (NoSuchAlgorithmException ex) {
throw new Error(ex);
} catch (KeyManagementException ex) {
throw new Error(ex);
}
}
However you should keep in mind that this code sample may need some modifications to work with HttpUnit (for instance if the library establishes the connections using a custom SocketFactory)
Since it seems that HttpUnit does not provide any API to set a custom SSLSocketFactry here is an alternative solution setting the default SSL context (Java 6 only)
static {
try {
SSLContext ssl = SSLContext.getDefault();
ssl.init(null, new X509TrustManager[] {new AnyTrustManager()}, null);
} catch (NoSuchAlgorithmException ex) {
throw new Error(ex);
} catch (KeyManagementException ex) {
throw new Error(ex);
}
}
What worked for me was using this tool to add the server's invalid cert to a new keystore (creates a file jssecacerts), then replace my existing keystore with the new one.
cp cacerts cacerts.bak
cp ~/tools/jssecacerts cacerts
HttpUnit worked fine after that.
If you have access to the WebClient you can do this to skip SSL certificate validation:
WebClient client = new WebClient();
client.getOptions().setUseInsecureSSL(true);
A little late, i only just ran into this issue, but i managed to get httpunit 1.7.2
working with AnyTrustManager
as per Jsc
's answer with the following code (httpunit uses HttpsURLConnectionOldImpl
under de hood):
static {
try {
SSLContext ssl = SSLContext.getInstance("TLS");
ssl.init(null, new X509TrustManager[] {new AnyTrustManager()}, null);
com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnectionOldImpl.setDefaultSSLSocketFactory(ssl.getSocketFactory());
} catch (NoSuchAlgorithmException ex) {
throw new Error(ex);
} catch (KeyManagementException ex) {
throw new Error(ex);
}
}
as of 2019, with an oracle 8 jvm on a mac, and httpunit 1.7, Jcs' answer from 8 years ago is still very close, just needs one more line.
// trust anything.
static void setupSSL() {
if(sslSetupDone) {
return;
}
// System.setProperty("javax.net.debug", "ssl");
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
SSLContext sc = null;
try {
sc = SSLContext.getInstance("TLS"); // formerly "ssl"
sc.init(null, trustAllCerts, null);
SSLContext.setDefault(sc); //<====== one more line needed
} catch (Exception e) {
e.printStackTrace(System.out);
}
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String urlHostname, SSLSession sslSession) {
return true;
}
});
sslSetupDone = true;
}