I am trying to override the trust manager in Android. I want to let the underlying trust manager check certificates but I need to determine if a certificate is expired. If the certificate is expired, I need to ignore it and accept the certificate. Some mobile devices will reset the date to an old date if the battery is removed, causing the certificate to appear as though it expired. My app must continue to keep running even if this happens.
The problem I am having is that this line of code throws a NullPointerException:
origTrustmanager.checkServerTrusted(certs, authType);
According to the docs, checkServerTrusted should never throw a NullPointerExeption. certs has two items in it. authType is set to "RSA". If I don't implement a custom Trust Manager, an exception will be thrown that clearly indicates that the certificate has expired, so I know that the underlying Trust Manager is doing its job. Even if I set the date and time on my device to be within the validity time of the certificate, the checkServerTrusted line above generates an exception. Why? Clearly I'm doing something wrong. Here is the code for my custom Trust Manager and how I am accessing the Url:
class SSLTrustManager
{
private X509TrustManager origTrustmanager;
public SSLTrustManager()
{
try
{
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null);
TrustManager[] trustManagers = tmf.getTrustManagers();
this.origTrustmanager = (X509TrustManager) trustManagers[0];
}
catch (Exception ex)
{
}
}
public javax.net.ssl.SSLSocketFactory GetSocketFactory()
{
try
{
TrustManager[] wrappedTrustManagers = new TrustManager[] {
new X509TrustManager()
{
public java.security.cert.X509Certificate[] getAcceptedIssuers()
{
return origTrustmanager.getAcceptedIssuers();
}
public void checkClientTrusted(X509Certificate[] certs, String authType)
{
try
{
origTrustmanager.checkClientTrusted(certs, authType);
}
catch (CertificateException e)
{
}
}
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException
{
try
{
origTrustmanager.checkServerTrusted(certs, authType);
}
catch(Exception ex)
{
}
}
}
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, wrappedTrustManagers, new java.security.SecureRandom());
javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
return sslSocketFactory;
}
catch (Exception ex)
{
return null;
}
}
}
Code for accessing a url:
SSLTrustManager sslTrustManager = new SSLTrustManager();
HttpsURLConnection.setDefaultSSLSocketFactory(sslTrustManager.GetSocketFactory());
URL siteUrl = new URL(url);
HttpsURLConnection conn = (HttpsURLConnection) siteUrl.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
tmf.init((KeyStore) null);
will cause theTMF
to return the default systemTrustManager
. This is not documented in the API docs. I was incorrectly usingtmf.init(KeyStore.getDefaultKeyStore())
– GaspSSLContext.getInstance()
be sure to useTLSv1.2
or similar. – Ellipticity