package info.guardianproject.otr.app.im.plugin.xmpp; import android.content.Context; import android.os.Build; import android.test.AndroidTestCase; import android.util.Log; import info.guardianproject.cacheword.PRNGFixes; import info.guardianproject.otr.app.im.R; import info.guardianproject.otr.app.im.app.AccountActivity; import info.guardianproject.util.Debug; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; import java.util.Arrays; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode; import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.thoughtcrime.ssl.pinning.PinningTrustManager; import org.thoughtcrime.ssl.pinning.SystemKeyStore; public class XMPPCertPinsTest extends AndroidTestCase { private static final String TAG = "XMPPCertPinsTest"; SystemKeyStore systemKeyStore; PinningTrustManager pinningTrustManager; SSLContext sslContext; SecureRandom secureRandom; String domainsWithPins[]; String domainsWithoutPins[] = { // signed by cacert.org, can't be pinned with AndroidPinning "jabber.ccc.de", // "vodka-pomme.net", // "jabber.cn" }; @Override public void setUp() { Context c = getContext(); PRNGFixes.apply(); systemKeyStore = SystemKeyStore.getInstance(c); pinningTrustManager = new PinningTrustManager(systemKeyStore, XMPPCertPins.getPinList(), 0); secureRandom = new java.security.SecureRandom(); try { sslContext = SSLContext.getInstance("TLS"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); assert true; } ArrayList<String> domains = new ArrayList<String>( Arrays.asList(c.getResources().getStringArray(R.array.account_domains))); domains.add(AccountActivity.DEFAULT_SERVER_FACEBOOK); domains.add(AccountActivity.DEFAULT_SERVER_JABBERORG); // currently fails here, needs SRV tricks // domains.add(AccountActivity.DEFAULT_SERVER_GOOGLE); domainsWithPins = domains.toArray(new String[domains.size()]); } private ConnectionConfiguration getConfig(String domain) throws KeyManagementException { ConnectionConfiguration config = new ConnectionConfiguration(domain, 5222); config.setDebuggerEnabled(Debug.DEBUG_ENABLED); config.setHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier()); config.setSecurityMode(SecurityMode.required); config.setVerifyChainEnabled(true); config.setVerifyRootCAEnabled(true); config.setExpiredCertificatesCheckEnabled(true); config.setNotMatchingDomainCheckEnabled(true); config.setSelfSignedCertificateEnabled(false); return config; } public void testDomainsWithPins() { XMPPConnection connection = null; try { for (String domain : domainsWithPins) { Log.i(TAG, "TESTING DOMAINS WITH PINS: " + domain); ConnectionConfiguration config = getConfig(domain); sslContext.init(null, new javax.net.ssl.TrustManager[] { pinningTrustManager }, secureRandom); config.setCustomSSLContext(sslContext); connection = new XMPPConnection(config); connection.addConnectionListener(new ConnectionListener() { @Override public void reconnectionSuccessful() { Log.i(TAG, "reconnectionSuccessful"); assertTrue(false); } @Override public void reconnectionFailed(Exception e) { Log.i(TAG, "reconnectionSuccessful"); e.printStackTrace(); assertTrue(false); } @Override public void reconnectingIn(int arg0) { Log.i(TAG, "reconnectingIn " + arg0); assertTrue(false); } @Override public void connectionClosedOnError(Exception e) { Log.i(TAG, "connectionClosedOnError"); e.printStackTrace(); assertTrue(false); } @Override public void connectionClosed() { Log.i(TAG, "connectionClosed"); } }); connection.connect(); assertTrue(connection.isConnected()); } } catch (KeyManagementException e) { Log.e(TAG, "KeyManagementException"); e.printStackTrace(); assertTrue(false); } catch (XMPPException e) { Log.e(TAG, "XMPPException"); e.printStackTrace(); assertTrue(false); } if (connection != null) connection.disconnect(); } public void testSettingCipherSuites() { try { sslContext.init(null, new javax.net.ssl.TrustManager[] { pinningTrustManager }, secureRandom); sslContext.getDefaultSSLParameters().getCipherSuites(); if (Build.VERSION.SDK_INT >= 20) { sslContext.getDefaultSSLParameters().setCipherSuites( XMPPCertPins.SSL_IDEAL_CIPHER_SUITES_API_20); } else { sslContext.getDefaultSSLParameters().setCipherSuites( XMPPCertPins.SSL_IDEAL_CIPHER_SUITES); } } catch (KeyManagementException e) { e.printStackTrace(); assert true; } } }