From 68bc106ee872b13830dfa5fa9794f7cecb306d8e Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 28 Oct 2017 20:41:05 +0200 Subject: #8757 refactores ProviderAPI for insecure flavor, fixes tests, renames confusing constants, updates robotium --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 4 +- .../leap/bitmaskclient/TLSCompatSocketFactory.java | 60 +++++++++++++++------- .../java/se/leap/bitmaskclient/VpnFragment.java | 7 ++- .../java/se/leap/bitmaskclient/eip/Constants.java | 2 +- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 2 +- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 2 +- .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 2 +- 7 files changed, 53 insertions(+), 26 deletions(-) (limited to 'app/src/main/java/se') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 9fc7d593..a47b8767 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -363,9 +363,7 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec @Override public void onReceiveResult(int resultCode, Bundle resultData) { - if (resultCode == ProviderAPI.INITIALIZATION_ERROR) { - sessionDialog(resultData); - } else if (resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) { + if (resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) { String username = resultData.getString(SessionDialog.USERNAME); String password = resultData.getString(SessionDialog.PASSWORD); user_status_fragment.logIn(username, password); diff --git a/app/src/main/java/se/leap/bitmaskclient/TLSCompatSocketFactory.java b/app/src/main/java/se/leap/bitmaskclient/TLSCompatSocketFactory.java index fdad6ba9..76d38447 100644 --- a/app/src/main/java/se/leap/bitmaskclient/TLSCompatSocketFactory.java +++ b/app/src/main/java/se/leap/bitmaskclient/TLSCompatSocketFactory.java @@ -1,6 +1,6 @@ package se.leap.bitmaskclient; -import android.util.Log; +import android.text.TextUtils; import java.io.IOException; import java.net.InetAddress; @@ -33,14 +33,14 @@ public class TLSCompatSocketFactory extends SSLSocketFactory { private static final String TAG = TLSCompatSocketFactory.class.getName(); private SSLSocketFactory internalSSLSocketFactory; - private SSLContext sslContext; private TrustManager trustManager; public TLSCompatSocketFactory(String trustedCaCert) throws KeyManagementException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, NoSuchProviderException { + initForSelfSignedCAs(trustedCaCert); + } - initTrustManager(trustedCaCert); - internalSSLSocketFactory = sslContext.getSocketFactory(); - + public TLSCompatSocketFactory() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, NoSuchProviderException, IOException { + initForCommercialCAs(); } public void initSSLSocketFactory(OkHttpClient.Builder builder) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, IllegalStateException { @@ -48,14 +48,15 @@ public class TLSCompatSocketFactory extends SSLSocketFactory { } - private void initTrustManager(String trustedCaCert) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, IllegalStateException, KeyManagementException, NoSuchProviderException { - java.security.cert.Certificate provider_certificate = ConfigHelper.parseX509CertificateFromString(trustedCaCert); - + private void initForSelfSignedCAs(String trustedSelfSignedCaCert) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, IllegalStateException, KeyManagementException, NoSuchProviderException { // Create a KeyStore containing our trusted CAs String defaultType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(defaultType); keyStore.load(null, null); - keyStore.setCertificateEntry("provider_ca_certificate", provider_certificate); + if (!TextUtils.isEmpty(trustedSelfSignedCaCert)) { + java.security.cert.Certificate provider_certificate = ConfigHelper.parseX509CertificateFromString(trustedSelfSignedCaCert); + keyStore.setCertificateEntry("provider_ca_certificate", provider_certificate); + } // Create a TrustManager that trusts the CAs in our KeyStore String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); @@ -72,9 +73,32 @@ public class TLSCompatSocketFactory extends SSLSocketFactory { trustManager = trustManagers[0]; // Create an SSLContext that uses our TrustManager - sslContext = SSLContext.getInstance("TLS"); + SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); + internalSSLSocketFactory = sslContext.getSocketFactory(); + + } + + + private void initForCommercialCAs() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException { + + // Create a TrustManager that trusts the CAs in our KeyStore + String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); + tmf.init((KeyStore) null); + + // Check if there's only 1 X509Trustmanager -> from okttp3 source code example + TrustManager[] trustManagers = tmf.getTrustManagers(); + if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { + throw new IllegalStateException("Unexpected default trust managers:" + + Arrays.toString(trustManagers)); + } + + trustManager = trustManagers[0]; + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, null, null); + internalSSLSocketFactory = context.getSocketFactory(); } @@ -89,39 +113,39 @@ public class TLSCompatSocketFactory extends SSLSocketFactory { } @Override - public Socket createSocket() throws IOException { + public Socket createSocket() throws IOException, IllegalArgumentException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket()); } @Override - public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { + public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException, IllegalArgumentException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)); } @Override - public Socket createSocket(String host, int port) throws IOException, UnknownHostException { + public Socket createSocket(String host, int port) throws IOException, UnknownHostException, IllegalArgumentException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); } @Override - public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException, IllegalArgumentException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort)); } @Override - public Socket createSocket(InetAddress host, int port) throws IOException { + public Socket createSocket(InetAddress host, int port) throws IOException, IllegalArgumentException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); } @Override - public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException, IllegalArgumentException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)); } - private Socket enableTLSOnSocket(Socket socket) { + private Socket enableTLSOnSocket(Socket socket) throws IllegalArgumentException { if(socket != null && (socket instanceof SSLSocket)) { ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"}); - ((SSLSocket)socket).setEnabledCipherSuites(getSupportedCipherSuites()); + //TODO: add a android version check as soon as a new Android API or bcjsse supports TLSv1.3 } return socket; diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java b/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java index 8cd9fa0f..c85b0151 100644 --- a/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java @@ -19,6 +19,7 @@ package se.leap.bitmaskclient; import android.app.*; import android.content.*; import android.os.*; +import android.util.Log; import android.view.*; import android.widget.*; @@ -152,11 +153,15 @@ public class VpnFragment extends Fragment implements Observer { Bundle bundle = new Bundle(); bundle.putBoolean(IS_PENDING, true); dashboard.sessionDialog(bundle); + } else { + Log.d(TAG, "WHAT IS GOING ON HERE?!"); + // TODO: implement a fallback: check if vpncertificate was not downloaded properly or give + // a user feedback. A button that does nothing on click is not a good option } } private boolean canStartEIP() { - boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty(); + boolean certificateExists = !Dashboard.preferences.getString(Constants.VPN_CERTIFICATE, "").isEmpty(); boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false); return (isAllowedAnon || certificateExists) && !eip_status.isConnected() && !eip_status.isConnecting(); } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java index 39ad7c08..db1cb4a1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java @@ -33,7 +33,7 @@ public interface Constants { public final static String EIP_NOTIFICATION = TAG + ".EIP_NOTIFICATION"; public final static String ALLOWED_ANON = "allow_anonymous"; public final static String ALLOWED_REGISTERED = "allow_registration"; - public final static String CERTIFICATE = "cert"; + public final static String VPN_CERTIFICATE = "cert"; public final static String PRIVATE_KEY = TAG + ".PRIVATE_KEY"; public final static String KEY = TAG + ".KEY"; public final static String RECEIVER_TAG = TAG + ".RECEIVER_TAG"; diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index 73c7337b..28a9bb50 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -186,7 +186,7 @@ public final class EIP extends IntentService { } private void checkCertValidity() { - VpnCertificateValidator validator = new VpnCertificateValidator(preferences.getString(CERTIFICATE, "")); + VpnCertificateValidator validator = new VpnCertificateValidator(preferences.getString(VPN_CERTIFICATE, "")); int resultCode = validator.isValid() ? Activity.RESULT_OK : Activity.RESULT_CANCELED; diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java index 6a7e3d0b..177f553e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -124,7 +124,7 @@ public class GatewaysManager { try { result.put(Provider.CA_CERT, preferences.getString(Provider.CA_CERT, "")); result.put(Constants.PRIVATE_KEY, preferences.getString(Constants.PRIVATE_KEY, "")); - result.put(Constants.CERTIFICATE, preferences.getString(Constants.CERTIFICATE, "")); + result.put(Constants.VPN_CERTIFICATE, preferences.getString(Constants.VPN_CERTIFICATE, "")); } catch (JSONException e) { e.printStackTrace(); } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java index 53d81ed3..f428099e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -125,7 +125,7 @@ public class VpnConfigGenerator { String openvpn_cert = "" + new_line - + secrets.getString(Constants.CERTIFICATE) + + secrets.getString(Constants.VPN_CERTIFICATE) + new_line + ""; -- cgit v1.2.3