Circumventing certificate checks
Hello everyone,
Short version:
I would like to hard-code into the application the self-signed certificate of an internal-only HTTPS server, so that I don't have to install and maintain special keystores on hundreds of users' machines.
Long version:
I'm working on a simple application that will poll an https url to receive an RSS feed containing some information. This information will organized and displayed in some way. No information will be submitted by the user.
The URL is on a server with an internally generated CA certificate, so for testing I've had to set up a keystore on my local machine and set the appropriate trustStore variables at runtime. This works fine, but I'd rather not have to set up every user's workstation in such a fashion. Also, the server is on an internal network, not accessible from the Internet (except under a VPN).
Is there a way to hard code the server's certificate into the app so that if the cert. ever changes, it will be a simple matter of pushing out an updated app rather than updating hundreds of workstations (using different OSs, even)?
Much obliged,
Wtt
[1168 byte] By [
wtta] at [2007-11-27 8:37:06]

# 1
Ok, so it seems that this will work:
1) create a class such as:
import java.net.URL;
import java.net.URLConnection;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
class Trusty implements X509TrustManager {
Trusty () {
}
public void checkClientTrusted(X509Certificate[] certs, String s) throws CertificateException {
// we're the client, so its possible that this method is never called
}
public void checkServerTrusted(X509Certificate[] certs, String s) throws CertificateException {
for (int i=0; i<certs.length; i++) {
X509Certificate c = certs[i];
System.out.println("[ checkServerTrusted: sent cert [ "+
c.getSubjectDN() + " ] ]");
}
}
public X509Certificate[] getAcceptedIssuers() {
System.out.println("[ getAcceptedIssuers: Queried. ]");
return new X509Certificate[0];
}
}
2)
use HttpsURLConnection.setSSLSocketFactory() to pass in a socket factory that relies on the above TrustManager:
private javax.net.ssl.SSLContext ctx;
// some stuff deleted
if (theURL.getProtocol().equals("https")) {
try {
ctx = SSLContext.getInstance("SSLv3");
} catch (NoSuchAlgorithmException nsa) {
}
TrustManager[] trs = new TrustManager[1];
trs[0] = new Trusty();
try {
if (ctx != null)
ctx.init(null, trs, null);
} catch (Throwable th) { } finally { }
SSLSocketFactory sf = ctx.getSocketFactory();
theCon = theURL.openConnection();
((HttpsURLConnection)theCon).setSSLSocketFactory(sf);
// ...
}
and so this works, and it is easy to add custom certificate verification that doesn't rely on the strict java default trustmanager.
wtta at 2007-7-12 20:34:18 >
