I have a custom httpclient that I created to take in my custom trust store, and use it for all ssl sites that it tries to access. Here's the code for that:
public class MyHttpClient extends DefaultHttpClient {
private Context context;
public MyHttpClient(Context context) {
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
KeyStore trusted = KeyStore.getInstance("BKS");
InputStream in = context.getResources().openRawResource(
R.raw.cacerts);
try {
trusted.load(in, "changeit".toCharArray());
}
catch (CertificateException c) {
System.out
.println("There was a certificate exception in myhttpclient!");
}
finally {
in.close();
}
return new SSLSocketFactory(trusted);
}
catch (Exception e) {
throw new AssertionError(e);
}
}
}
And here's the stacktrace it's giving me:
W/System.err(4194): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
W/System.err(4194): at org.apache.harmony.xnet.provider.jsse.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:258)
W/System.err(4194): at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:93)
W/System.err(4194): at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)
W/System.err(4194): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177)
W/System.err(4194): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
W/System.err(4194): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
W/System.err(4194): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:428)
W/System.err(4194): at org.apache.http.impl.client.AbstractHttpClient$1.executeRequestSending(AbstractHttpClient.java:608)
W/System.err(4194): at org.apache.http.impl.client.naf.redirect.NafRequestExecutorWrapperRedirectionHandler.executeRequestSendingUsual(NafRequestExecutorWrapperRedirectionHandler.java:96)
W/System.err(4194): at org.apache.http.impl.client.naf.redirect.NafRequestExecutorWrapperRedirectionHandler.executeRequestSending(NafRequestExecutorWrapperRedirectionHandler.java:73)
W/System.err(4194): at org.apache.http.impl.client.naf.auth.NafHttpAuthStrategyDefault.sendFirstRequest(NafHttpAuthStrategyDefault.java:487)
W/System.err(4194): at org.apache.http.impl.client.naf.auth.NafHttpAuthStrategyDefault.performAuthExecutionUnsafe(NafHttpAuthStrategyDefault.java:388)
W/System.err(4194): at org.apache.http.impl.client.naf.auth.NafHttpAuthStrategyDefault.performAuthExecution(NafHttpAuthStrategyDefault.java:200)
W/System.err(4194): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:556)
W/System.err(4194): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:505)
W/System.err(4194): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:483)
W/System.err(4194): at com.wmmccreedy.vce.AgConnection.submitInfo(AgConnection.java:111)
W/System.err(4194): at com.wmmccreedy.vce.LoginSubmitActvity$DownloadWebPageTask.doInBackground(LoginSubmitActvity.java:199)
W/System.err(4194): at com.wmmccreedy.vce.LoginSubmitActvity$DownloadWebPageTask.doInBackground(LoginSubmitActvity.java:1)
W/System.err(4194): at android.os.AsyncTask$2.call(AsyncTask.java:185)
W/System.err(4194): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
W/System.err(4194): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
W/System.err(4194): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
W/System.err(4194): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
W/System.err(4194): at java.lang.Thread.run(Thread.java:1019)
Now, this works correctly... about 50% of the time. I "solved" this by creating a while loop. It continues to recreate the httpclient client and try to access the server over and over again until it works, usually after only 1 to 2 attempts (max I've seen is 4). Obviously, this is very inefficient.
I've narrowed down the problem to the class I've posted above, since if I create the httpclient just once and try to access the site using that same class multiple times, it will either always fail, or always succeed, depending on whether I got a 'good' httpclient, or a 'bad' httpclient. However, if I create the httpclient every single time I try and access the webpage, it will sometimes work and sometimes not work.
So why is it doing this, and how can I fix this? And why is it only working intermittently, what could be changing between creations of the client?
Edit: Solved!
It appears that I had left some old versions of some aliases in my truststore, and it was randomly picking whichever one it found first, which didn't always end up being the correct one. Each alias had all the same certs in them, but each had all of the certs in a different order. I tested until I found the correct store, deleted the rest, and everything is perfect now.