From 261dc90595e583914161e5e9011f5f5dd4a9740c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 12 Nov 2014 01:30:09 +0100 Subject: eip package, EIP constants to interface. --- .../se/leap/bitmaskclient/ConfigurationWizard.java | 50 +- .../java/se/leap/bitmaskclient/ProviderAPI.java | 79 +--- .../leap/bitmaskclient/ProviderDetailFragment.java | 37 +- .../main/java/se/leap/bitmaskclient/Dashboard.java | 81 ++-- app/src/main/java/se/leap/bitmaskclient/EIP.java | 524 --------------------- .../se/leap/bitmaskclient/EipServiceFragment.java | 92 ++-- .../java/se/leap/bitmaskclient/OnBootReceiver.java | 7 +- .../se/leap/bitmaskclient/VoidVpnLauncher.java | 37 -- .../java/se/leap/bitmaskclient/VoidVpnService.java | 36 -- .../se/leap/bitmaskclient/VpnConfigGenerator.java | 146 ------ .../java/se/leap/bitmaskclient/eip/Constants.java | 50 ++ .../main/java/se/leap/bitmaskclient/eip/EIP.java | 486 +++++++++++++++++++ .../se/leap/bitmaskclient/eip/VoidVpnLauncher.java | 37 ++ .../se/leap/bitmaskclient/eip/VoidVpnService.java | 37 ++ .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 145 ++++++ .../se/leap/bitmaskclient/ConfigurationWizard.java | 50 +- .../java/se/leap/bitmaskclient/ProviderAPI.java | 77 +-- .../leap/bitmaskclient/ProviderDetailFragment.java | 37 +- 18 files changed, 929 insertions(+), 1079 deletions(-) delete mode 100644 app/src/main/java/se/leap/bitmaskclient/EIP.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/Constants.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/EIP.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java (limited to 'app/src') diff --git a/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java b/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java index 78fcda56..38084493 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java @@ -16,39 +16,17 @@ */ package se.leap.bitmaskclient; -import android.app.Activity; -import android.app.DialogFragment; -import android.app.Fragment; -import android.app.FragmentTransaction; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; +import android.app.*; +import android.content.*; import android.content.res.AssetManager; -import android.os.Bundle; -import android.os.Handler; +import android.os.*; import android.util.Log; -import android.view.Display; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View.MeasureSpec; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.widget.ListAdapter; -import android.widget.ListView; -import android.widget.ProgressBar; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.TextView; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Iterator; -import org.json.JSONException; -import org.json.JSONObject; +import android.view.*; +import android.widget.*; +import java.io.*; +import java.net.*; +import java.util.*; +import org.json.*; import se.leap.bitmaskclient.DownloadFailedDialog.DownloadFailedDialogInterface; import se.leap.bitmaskclient.NewProviderDialog.NewProviderDialogInterface; @@ -56,7 +34,7 @@ import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver; import se.leap.bitmaskclient.ProviderDetailFragment.ProviderDetailFragmentInterface; import se.leap.bitmaskclient.ProviderListContent.ProviderItem; import se.leap.bitmaskclient.FragmentManagerEnhanced; - +import se.leap.bitmaskclient.eip.Constants; import se.leap.bitmaskclient.R; /** @@ -166,7 +144,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD if(resultCode == ProviderAPI.PROVIDER_OK) { mConfigState.setAction(PROVIDER_SET); - if (preferences.getBoolean(EIP.ALLOWED_ANON, false)){ + if (preferences.getBoolean(Constants.ALLOWED_ANON, false)){ mConfigState.putExtra(SERVICES_RETRIEVED, true); downloadAnonCert(); @@ -315,8 +293,8 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD int screenWidth = display.getWidth(); // deprecated int listViewWidth = screenWidth - 10 - 10; - int widthSpec = MeasureSpec.makeMeasureSpec(listViewWidth, - MeasureSpec.AT_MOST); + int widthSpec = View.MeasureSpec.makeMeasureSpec(listViewWidth, + View.MeasureSpec.AT_MOST); listItem.measure(widthSpec, 0); return listItem.getMeasuredHeight(); @@ -551,7 +529,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD if(provider_list_fragment != null && preferences.contains(ProviderItem.DANGER_ON)) { provider_list_fragment.removeLastItem(); } - preferences.edit().remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit(); + preferences.edit().remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit(); } @Override diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java index 52645631..ddd36d7c 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java @@ -17,60 +17,23 @@ package se.leap.bitmaskclient; import android.app.IntentService; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.os.ResultReceiver; -import android.util.Base64; -import android.util.Log; -import java.io.DataOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; +import android.content.*; +import android.os.*; +import android.util.*; +import java.io.*; import java.math.BigInteger; -import java.net.ConnectException; -import java.net.CookieHandler; -import java.net.CookieManager; -import java.net.CookiePolicy; -import java.net.MalformedURLException; -import java.net.SocketTimeoutException; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLEncoder; -import java.net.UnknownHostException; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; +import java.net.*; +import java.security.*; +import java.security.cert.*; import java.security.interfaces.RSAPrivateKey; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Scanner; -import java.util.NoSuchElementException; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.KeyManager; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; +import java.util.*; +import javax.net.ssl.*; import org.apache.http.client.ClientProtocolException; -import org.json.JSONException; -import org.json.JSONObject; +import org.json.*; + import se.leap.bitmaskclient.ProviderListContent.ProviderItem; import se.leap.bitmaskclient.R; - +import se.leap.bitmaskclient.eip.*; /** * Implements HTTP api methods used to manage communications with the provider server. @@ -629,8 +592,8 @@ public class ProviderAPI extends IntentService { //TODO setProviderName(name); preferences.edit().putString(Provider.KEY, provider_json.toString()).commit(); - preferences.edit().putBoolean(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON)).commit(); - preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_REGISTERED)).commit(); + preferences.edit().putBoolean(Constants.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_ANON)).commit(); + preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_REGISTERED)).commit(); result.putBoolean(RESULT_KEY, true); } catch (JSONException e) { @@ -654,7 +617,7 @@ public class ProviderAPI extends IntentService { JSONObject eip_service_json = new JSONObject(eip_service_json_string); eip_service_json.getInt(Provider.API_RETURN_SERIAL); - preferences.edit().putString(EIP.KEY, eip_service_json.toString()).commit(); + preferences.edit().putString(Constants.KEY, eip_service_json.toString()).commit(); result.putBoolean(RESULT_KEY, true); } catch (JSONException e) { @@ -903,7 +866,7 @@ public class ProviderAPI extends IntentService { getNewCert(); Intent updateEIP = new Intent(getApplicationContext(), EIP.class); - updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE); + updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); startService(updateEIP); return true; @@ -919,7 +882,7 @@ public class ProviderAPI extends IntentService { JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); String provider_main_url = provider_json.getString(Provider.API_URL); - URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.CERTIFICATE); + URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + Constants.CERTIFICATE); boolean danger_on = preferences.getBoolean(ProviderItem.DANGER_ON, false); @@ -956,12 +919,14 @@ public class ProviderAPI extends IntentService { } RSAPrivateKey keyCert = ConfigHelper.parseRsaKeyFromString(keyString); keyString = Base64.encodeToString( keyCert.getEncoded(), Base64.DEFAULT ); - preferences.edit().putString(EIP.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit(); + preferences.edit().putString(Constants.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit(); X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(certificateString); certificateString = Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT); - preferences.edit().putString(EIP.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit(); - preferences.edit().putString(EIP.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit(); + + preferences.edit().putString(Constants.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit(); + preferences.edit().putString(Constants.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit(); + return true; } catch (CertificateException e) { // TODO Auto-generated catch block diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java index 3ca003a0..d6f482ca 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java @@ -1,22 +1,17 @@ -package se.leap.bitmaskclient; - -import org.json.JSONException; -import org.json.JSONObject; - -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.ProviderListContent.ProviderItem; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.DialogInterface; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; - +package se.leap.bitmaskclient; + +import org.json.*; + +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.eip.Constants; +import se.leap.bitmaskclient.ProviderListContent.ProviderItem; + +import android.app.*; +import android.content.*; +import android.os.Bundle; +import android.view.*; +import android.widget.TextView; + public class ProviderDetailFragment extends DialogFragment { final public static String TAG = "providerDetailFragment"; @@ -66,7 +61,7 @@ public class ProviderDetailFragment extends DialogFragment { private boolean anon_allowed(JSONObject provider_json) { try { JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE); - return service_description.has(EIP.ALLOWED_ANON) && service_description.getBoolean(EIP.ALLOWED_ANON); + return service_description.has(Constants.ALLOWED_ANON) && service_description.getBoolean(Constants.ALLOWED_ANON); } catch (JSONException e) { return false; } @@ -85,7 +80,7 @@ public class ProviderDetailFragment extends DialogFragment { public void onCancel(DialogInterface dialog) { super.onCancel(dialog); SharedPreferences.Editor editor = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).edit(); - editor.remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit(); + editor.remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit(); interface_with_configuration_wizard.showAllProviders(); } diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 364a79af..473cd5ec 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -14,38 +14,21 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - package se.leap.bitmaskclient; +package se.leap.bitmaskclient; -import org.json.JSONException; -import org.json.JSONObject; - -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver; -import se.leap.bitmaskclient.FragmentManagerEnhanced; -import se.leap.bitmaskclient.SignUpDialog; +import se.leap.bitmaskclient.*; +import se.leap.bitmaskclient.eip.*; import de.blinkt.openvpn.activities.LogWindow; -import android.app.Activity; -import android.app.AlertDialog; -import android.app.DialogFragment; -import android.app.FragmentTransaction; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; +import android.app.*; +import android.content.*; import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Bundle; -import android.os.Handler; -import android.os.ResultReceiver; +import android.os.*; import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.Toast; +import android.view.*; +import android.widget.*; +import org.json.*; /** * The main user facing Activity of LEAP Android, consisting of status, controls, @@ -54,7 +37,7 @@ import android.widget.Toast; * @author Sean Leonard * @author parmegv */ -public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface, SignUpDialog.SignUpDialogInterface, Receiver { +public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface, SignUpDialog.SignUpDialogInterface, ProviderAPIResultReceiver.Receiver { protected static final int CONFIGURE_LEAP = 0; protected static final int SWITCH_PROVIDER = 1; @@ -95,7 +78,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); handleVersion(); - authed_eip = preferences.getBoolean(EIP.AUTHED_EIP, false); + authed_eip = preferences.getBoolean(Constants.AUTHED_EIP, false); if (preferences.getString(Provider.KEY, "").isEmpty()) startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); else @@ -113,9 +96,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf switch(versionCode) { case 91: // 0.6.0 without Bug #5999 case 101: // 0.8.0 - if(!preferences.getString(EIP.KEY, "").isEmpty()) { + if(!preferences.getString(Constants.KEY, "").isEmpty()) { Intent rebuildVpnProfiles = new Intent(getApplicationContext(), EIP.class); - rebuildVpnProfiles.setAction(EIP.ACTION_REBUILD_PROFILES); + rebuildVpnProfiles.setAction(Constants.ACTION_REBUILD_PROFILES); startService(rebuildVpnProfiles); } break; @@ -139,23 +122,21 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) { // It should be equivalent: if ( (requestCode == CONFIGURE_LEAP) || (data!= null && data.hasExtra(STOP_FIRST))) { if ( resultCode == RESULT_OK ){ - preferences.edit().putInt(EIP.PARSED_SERIAL, 0).commit(); - preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit(); - + preferences.edit().putInt(Constants.PARSED_SERIAL, 0).commit(); + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).commit(); Intent updateEIP = new Intent(getApplicationContext(), EIP.class); - updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE); + updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); startService(updateEIP); - buildDashboard(false); invalidateOptionsMenu(); if(data != null && data.hasExtra(LogInDialog.TAG)) { View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0); logInDialog(Bundle.EMPTY); } - } else if(resultCode == RESULT_CANCELED && (data == null || data.hasExtra(ACTION_QUIT))) { - finish(); - } else - configErrorDialog(); + } else if(resultCode == RESULT_CANCELED && (data == null || data.hasExtra(ACTION_QUIT))) { + finish(); + } else + configErrorDialog(); } } @@ -227,7 +208,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE); boolean authed_eip = !LeapSRPSession.getToken().isEmpty(); boolean allow_registered_eip = service_description.getBoolean(Provider.ALLOW_REGISTRATION); - preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, allow_registered_eip); + preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, allow_registered_eip); if(allow_registered_eip) { if(authed_eip) { @@ -268,7 +249,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf return true; case R.id.switch_provider: if (Provider.getInstance().hasEIP()){ - if (preferences.getBoolean(EIP.AUTHED_EIP, false)){ + if (preferences.getBoolean(Constants.AUTHED_EIP, false)){ logOut(); } eipStop(); @@ -426,7 +407,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf invalidateOptionsMenu(); authed_eip = true; - preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit(); + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).commit(); downloadAuthedUserCertificate(); } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_FAILED) { @@ -441,7 +422,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf invalidateOptionsMenu(); authed_eip = false; - preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit(); + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).commit(); } else if(resultCode == ProviderAPI.LOGOUT_FAILED) { changeStatusMessage(resultCode); @@ -457,7 +438,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf ResultReceiver eip_receiver = new ResultReceiver(new Handler()){ protected void onReceiveResult(int resultCode, Bundle resultData){ super.onReceiveResult(resultCode, resultData); - String request = resultData.getString(EIP.REQUEST_TAG); + String request = resultData.getString(Constants.REQUEST_TAG); if (resultCode == Activity.RESULT_OK){ if(authed_eip) eipStart(); @@ -466,8 +447,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } } }; - updateEIP.putExtra(EIP.RECEIVER_TAG, eip_receiver); - updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE); + updateEIP.putExtra(Constants.RECEIVER_TAG, eip_receiver); + updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); startService(updateEIP); } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { changeStatusMessage(resultCode); @@ -481,9 +462,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf ResultReceiver eip_status_receiver = new ResultReceiver(new Handler()){ protected void onReceiveResult(int resultCode, Bundle resultData){ super.onReceiveResult(resultCode, resultData); - String request = resultData.getString(EIP.REQUEST_TAG); + String request = resultData.getString(Constants.REQUEST_TAG); if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus); - if (request.equalsIgnoreCase(EIP.ACTION_IS_EIP_RUNNING)){ + if (request.equalsIgnoreCase(Constants.ACTION_IS_EIP_RUNNING)){ if (resultCode == Activity.RESULT_OK){ switch(previous_result_code){ @@ -544,8 +525,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf private void eipIsRunning(ResultReceiver eip_receiver){ // TODO validate "action"...how do we get the list of intent-filters for a class via Android API? Intent eip_intent = new Intent(this, EIP.class); - eip_intent.setAction(EIP.ACTION_IS_EIP_RUNNING); - eip_intent.putExtra(EIP.RECEIVER_TAG, eip_receiver); + eip_intent.setAction(Constants.ACTION_IS_EIP_RUNNING); + eip_intent.putExtra(Constants.RECEIVER_TAG, eip_receiver); startService(eip_intent); } diff --git a/app/src/main/java/se/leap/bitmaskclient/EIP.java b/app/src/main/java/se/leap/bitmaskclient/EIP.java deleted file mode 100644 index 2f06def3..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/EIP.java +++ /dev/null @@ -1,524 +0,0 @@ -/** - * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package se.leap.bitmaskclient; - -import android.app.Activity; -import android.app.IntentService; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.os.ResultReceiver; -import android.util.Log; -import de.blinkt.openvpn.LaunchVPN; -import de.blinkt.openvpn.VpnProfile; -import de.blinkt.openvpn.activities.DisconnectVPN; -import de.blinkt.openvpn.core.ConfigParser; -import de.blinkt.openvpn.core.ConfigParser.ConfigParseError; -import de.blinkt.openvpn.core.ProfileManager; -import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; -import java.io.IOException; -import java.io.StringReader; -import java.security.cert.CertificateExpiredException; -import java.security.cert.CertificateNotYetValidException; -import java.security.cert.X509Certificate; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Calendar; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Locale; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.TreeMap; -import java.util.Vector; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import se.leap.bitmaskclient.Dashboard; -import se.leap.bitmaskclient.Provider; -import se.leap.bitmaskclient.R; - -/** - * EIP is the abstract base class for interacting with and managing the Encrypted - * Internet Proxy connection. Connections are started, stopped, and queried through - * this IntentService. - * Contains logic for parsing eip-service.json from the provider, configuring and selecting - * gateways, and controlling {@link de.blinkt.openvpn.core.OpenVPNService} connections. - * - * @author Sean Leonard - * @author Parménides GV - */ -public final class EIP extends IntentService { - - public final static String AUTHED_EIP = "authed eip"; - public final static String ACTION_CHECK_CERT_VALIDITY = "se.leap.bitmaskclient.CHECK_CERT_VALIDITY"; - public final static String ACTION_START_EIP = "se.leap.bitmaskclient.START_EIP"; - public final static String ACTION_STOP_EIP = "se.leap.bitmaskclient.STOP_EIP"; - public final static String ACTION_UPDATE_EIP_SERVICE = "se.leap.bitmaskclient.UPDATE_EIP_SERVICE"; - public final static String ACTION_IS_EIP_RUNNING = "se.leap.bitmaskclient.IS_RUNNING"; - public final static String ACTION_REBUILD_PROFILES = "se.leap.bitmaskclient.REBUILD_PROFILES"; - public final static String EIP_NOTIFICATION = "EIP_NOTIFICATION"; - public final static String STATUS = "eip status"; - public final static String DATE_FROM_CERTIFICATE = "date from certificate"; - 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 PRIVATE_KEY = "private_key"; - public final static String KEY = "eip"; - public final static String PARSED_SERIAL = "eip_parsed_serial"; - public final static String SERVICE_API_PATH = "config/eip-service.json"; - public final static String RECEIVER_TAG = "receiverTag"; - public final static String REQUEST_TAG = "requestTag"; - public final static String TAG = EIP.class.getSimpleName(); - private static SharedPreferences preferences; - - private static Context context; - private static ResultReceiver mReceiver; - private static boolean mBound = false; - - private static JSONObject eipDefinition = null; - - private static OVPNGateway activeGateway = null; - - protected static ConnectionStatus lastConnectionStatusLevel; - protected static boolean mIsDisconnecting = false; - protected static boolean mIsStarting = false; - - public static SimpleDateFormat certificate_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US); - public EIP(){ - super("LEAPEIP"); - } - - @Override - public void onCreate() { - super.onCreate(); - - context = getApplicationContext(); - - preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); - } - - @Override - public void onDestroy() { - - mBound = false; - - super.onDestroy(); - } - - - @Override - protected void onHandleIntent(Intent intent) { - String action = intent.getAction(); - mReceiver = intent.getParcelableExtra(RECEIVER_TAG); - - if ( action == ACTION_START_EIP ) - startEIP(); - else if ( action == ACTION_STOP_EIP ) - stopEIP(); - else if ( action == ACTION_IS_EIP_RUNNING ) - isRunning(); - else if ( action == ACTION_UPDATE_EIP_SERVICE ) - updateEIPService(); - else if ( action == ACTION_CHECK_CERT_VALIDITY ) - checkCertValidity(); - else if ( action == ACTION_REBUILD_PROFILES ) - updateGateways(); - } - - /** - * Initiates an EIP connection by selecting a gateway and preparing and sending an - * Intent to {@link se.leap.openvpn.LaunchVPN}. - * It also sets up early routes. - */ - private void startEIP() { - earlyRoutes(); - activeGateway = selectGateway(); - - if(activeGateway != null && activeGateway.mVpnProfile != null) { - mReceiver = EipServiceFragment.getReceiver(); - launchActiveGateway(); - } - } - - /** - * Early routes are routes that block traffic until a new - * VpnService is started properly. - */ - private void earlyRoutes() { - Intent void_vpn_launcher = new Intent(context, VoidVpnLauncher.class); - void_vpn_launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(void_vpn_launcher); - } - - /** - * Choose a gateway to connect to based on timezone from system locale data - * - * @return The gateway to connect to - */ - private OVPNGateway selectGateway() { - String closest_location = closestGateway(); - String chosen_host = chooseHost(closest_location); - - return new OVPNGateway(chosen_host); - } - - private String closestGateway() { - TreeMap> offsets = calculateOffsets(); - return offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next(); - } - - private TreeMap> calculateOffsets() { - TreeMap> offsets = new TreeMap>(); - - int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000; - - JSONObject locations = availableLocations(); - Iterator locations_names = locations.keys(); - while(locations_names.hasNext()) { - try { - String location_name = locations_names.next(); - JSONObject location = locations.getJSONObject(location_name); - - int dist = timezoneDistance(localOffset, location.optInt("timezone")); - - Set set = (offsets.get(dist) != null) ? - offsets.get(dist) : new HashSet(); - - set.add(location_name); - offsets.put(dist, set); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - return offsets; - } - - private JSONObject availableLocations() { - JSONObject locations = null; - try { - if(eipDefinition == null) updateEIPService(); - locations = eipDefinition.getJSONObject("locations"); - } catch (JSONException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - return locations; - } - - private int timezoneDistance(int local_timezone, int remote_timezone) { - // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12 - int dist = Math.abs(local_timezone - remote_timezone); - - // Farther than 12 timezones and it's shorter around the "back" - if (dist > 12) - dist = 12 - (dist -12); // Well i'll be. Absolute values make equations do funny things. - - return dist; - } - - private String chooseHost(String location) { - String chosen_host = ""; - try { - JSONArray gateways = eipDefinition.getJSONArray("gateways"); - for (int i = 0; i < gateways.length(); i++) { - JSONObject gw = gateways.getJSONObject(i); - if ( gw.getString("location").equalsIgnoreCase(location) || location.isEmpty()){ - chosen_host = eipDefinition.getJSONObject("locations").getJSONObject(gw.getString("location")).getString("name"); - break; - } - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return chosen_host; - } - - private void launchActiveGateway() { - Intent intent = new Intent(this,LaunchVPN.class); - intent.setAction(Intent.ACTION_MAIN); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(LaunchVPN.EXTRA_KEY, activeGateway.mVpnProfile.getUUID().toString() ); - intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.mVpnProfile.getName() ); - intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true); - intent.putExtra(RECEIVER_TAG, mReceiver); - startActivity(intent); - } - - /** - * Disconnects the EIP connection gracefully through the bound service or forcefully - * if there is no bound service. Sends a message to the requesting ResultReceiver. - */ - private void stopEIP() { - if(isConnected()) { - Intent disconnect_vpn = new Intent(this, DisconnectVPN.class); - disconnect_vpn.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(disconnect_vpn); - mIsDisconnecting = true; - lastConnectionStatusLevel = ConnectionStatus.UNKNOWN_LEVEL; // Wait for the decision of the user - Log.d(TAG, "mIsDisconnecting = true"); - } - - tellToReceiver(ACTION_STOP_EIP, Activity.RESULT_OK); - } - - private void tellToReceiver(String action, int resultCode) { - if (mReceiver != null){ - Bundle resultData = new Bundle(); - resultData.putString(REQUEST_TAG, action); - mReceiver.send(resultCode, resultData); - } - } - - /** - * Checks the last stored status notified by ics-openvpn - * Sends Activity.RESULT_CANCELED to the ResultReceiver that made the - * request if it's not connected, Activity.RESULT_OK otherwise. - */ - - private void isRunning() { - int resultCode = Activity.RESULT_CANCELED; - boolean is_connected = isConnected(); - - resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED; - - tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode); - } - - protected static boolean isConnected() { - return lastConnectionStatusLevel != null && lastConnectionStatusLevel.equals(ConnectionStatus.LEVEL_CONNECTED) && !mIsDisconnecting; - } - - /** - * Loads eip-service.json from SharedPreferences and calls {@link updateGateways()} - * to parse gateway definitions. - * TODO Implement API call to refresh eip-service.json from the provider - */ - private void updateEIPService() { - try { - String eip_definition_string = preferences.getString(KEY, ""); - if(eip_definition_string.isEmpty() == false) { - eipDefinition = new JSONObject(eip_definition_string); - } - deleteAllVpnProfiles(); - updateGateways(); - if(mReceiver != null) mReceiver.send(Activity.RESULT_OK, Bundle.EMPTY); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private void deleteAllVpnProfiles() { - ProfileManager vpl = ProfileManager.getInstance(context); - Collection profiles = vpl.getProfiles(); - profiles.removeAll(profiles); - } - - /** - * Walk the list of gateways defined in eip-service.json and parse them into - * OVPNGateway objects. - * TODO Store the OVPNGateways (as Serializable) in SharedPreferences - */ - private void updateGateways(){ - JSONArray gatewaysDefined = null; - try { - if(eipDefinition == null) updateEIPService(); - gatewaysDefined = eipDefinition.getJSONArray("gateways"); - for ( int i=0 ; i < gatewaysDefined.length(); i++ ){ - JSONObject gw = null; - gw = gatewaysDefined.getJSONObject(i); - - if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ) - new OVPNGateway(gw); - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - preferences.edit().putInt(PARSED_SERIAL, eipDefinition.optInt(Provider.API_RETURN_SERIAL)).commit(); - } - - private void checkCertValidity() { - String certificate = preferences.getString(CERTIFICATE, ""); - checkCertValidity(certificate); - } - - private void checkCertValidity(String certificate_string) { - if(!certificate_string.isEmpty()) { - X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificate_string); - - Calendar offset_date = calculateOffsetCertificateValidity(certificate); - Bundle result = new Bundle(); - result.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY); - try { - Log.d(TAG, "offset_date = " + offset_date.getTime().toString()); - certificate.checkValidity(offset_date.getTime()); - mReceiver.send(Activity.RESULT_OK, result); - Log.d(TAG, "Valid certificate"); - } catch(CertificateExpiredException e) { - mReceiver.send(Activity.RESULT_CANCELED, result); - Log.d(TAG, "Updating certificate"); - } catch(CertificateNotYetValidException e) { - mReceiver.send(Activity.RESULT_CANCELED, result); - } - } - } - - private Calendar calculateOffsetCertificateValidity(X509Certificate certificate) { - String current_date = certificate_date_format.format(Calendar.getInstance().getTime()).toString(); - - String date_string = preferences.getString(DATE_FROM_CERTIFICATE, current_date); - - Calendar offset_date = Calendar.getInstance(); - try { - Date date = certificate_date_format.parse(date_string); - long difference = Math.abs(date.getTime() - certificate.getNotAfter().getTime())/2; - long current_date_millis = offset_date.getTimeInMillis(); - offset_date.setTimeInMillis(current_date_millis + difference); - Log.d(TAG, "certificate not after = " + certificate.getNotAfter()); - } catch(ParseException e) { - e.printStackTrace(); - } - - return offset_date; - } - - /** - * OVPNGateway provides objects defining gateways and their options and metadata. - * Each instance contains a VpnProfile for OpenVPN specific data and member - * variables describing capabilities and location - * - * @author Sean Leonard - */ - private class OVPNGateway { - - private String TAG = "OVPNGateway"; - - private String mName; - private VpnProfile mVpnProfile; - private JSONObject mGateway; - private HashMap>> options = new HashMap>>(); - - - /** - * Attempts to retrieve a VpnProfile by name and build an OVPNGateway around it. - * FIXME This needs to become a findGatewayByName() method - * - * @param name The hostname of the gateway to inflate - */ - private OVPNGateway(String name){ - mName = name; - - this.loadVpnProfile(); - } - - private void loadVpnProfile() { - ProfileManager vpl = ProfileManager.getInstance(context); - try { - if ( mName == null ) - mVpnProfile = vpl.getProfiles().iterator().next(); - else - mVpnProfile = vpl.getProfileByName(mName); - } catch (NoSuchElementException e) { - updateEIPService(); - this.loadVpnProfile(); // FIXME catch infinite loops - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** - * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json - * and create a VpnProfile belonging to it. - * - * @param gateway The JSON OpenVPN gateway definition to parse - */ - protected OVPNGateway(JSONObject gateway){ - - mGateway = gateway; - - // Currently deletes VpnProfile for host, if there already is one, and builds new - ProfileManager vpl = ProfileManager.getInstance(context); - Collection profiles = vpl.getProfiles(); - for (Iterator it = profiles.iterator(); it.hasNext(); ){ - VpnProfile p = it.next(); - - if ( p.mName.equalsIgnoreCase( mName ) ) { - it.remove(); - vpl.removeProfile(context, p); - } - } - - this.createVPNProfile(); - - vpl.addProfile(mVpnProfile); - vpl.saveProfile(context, mVpnProfile); - vpl.saveProfileList(context); - } - - /** - * Create and attach the VpnProfile to our gateway object - */ - protected void createVPNProfile(){ - try { - ConfigParser cp = new ConfigParser(); - - JSONObject openvpn_configuration = eipDefinition.getJSONObject("openvpn_configuration"); - VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(preferences, openvpn_configuration, mGateway); - String configuration = vpn_configuration_generator.generate(); - - cp.parseConfig(new StringReader(configuration)); - mVpnProfile = cp.convertProfile(); - mVpnProfile.mName = mName = locationAsName(); - Log.v(TAG,"Created VPNProfile"); - - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ConfigParseError e) { - // FIXME We didn't get a VpnProfile! Error handling! and log level - Log.v(TAG,"Error creating VPNProfile"); - e.printStackTrace(); - } catch (IOException e) { - // FIXME We didn't get a VpnProfile! Error handling! and log level - Log.v(TAG,"Error creating VPNProfile"); - e.printStackTrace(); - } - } - - - public String locationAsName() { - try { - return eipDefinition.getJSONObject("locations").getJSONObject(mGateway.getString("location")).getString("name"); - } catch (JSONException e) { - Log.v(TAG,"Couldn't read gateway name for profile creation! Returning original name = " + mName); - e.printStackTrace(); - return (mName != null) ? mName : ""; - } - } - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java index 6d223dd6..f35a3cfa 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java @@ -3,34 +3,18 @@ package se.leap.bitmaskclient; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.ProviderAPIResultReceiver; import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver; -import se.leap.bitmaskclient.Dashboard; - -import de.blinkt.openvpn.activities.LogWindow; -import de.blinkt.openvpn.core.VpnStatus; -import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; -import de.blinkt.openvpn.core.VpnStatus.StateListener; -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Fragment; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.os.ResultReceiver; +import se.leap.bitmaskclient.eip.*; + +import de.blinkt.openvpn.activities.*; +import de.blinkt.openvpn.core.*; +import android.app.*; +import android.content.*; +import android.os.*; import android.util.Log; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.CompoundButton.OnCheckedChangeListener; -import android.widget.CompoundButton; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.Switch; -import android.widget.TextView; - -public class EipServiceFragment extends Fragment implements StateListener, OnCheckedChangeListener { +import android.view.*; +import android.widget.*; + +public class EipServiceFragment extends Fragment implements VpnStatus.StateListener, CompoundButton.OnCheckedChangeListener { protected static final String IS_EIP_PENDING = "is_eip_pending"; public static final String START_ON_BOOT = "start on boot"; @@ -85,8 +69,8 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe super.onResume(); VpnStatus.addStateListener(this); - - eipCommand(EIP.ACTION_CHECK_CERT_VALIDITY); + + eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY); } @Override @@ -139,13 +123,13 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe } private boolean canStartEIP() { - boolean certificateExists = !Dashboard.preferences.getString(EIP.CERTIFICATE, "").isEmpty(); - boolean isAllowedAnon = Dashboard.preferences.getBoolean(EIP.ALLOWED_ANON, false); + boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty(); + boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false); return (isAllowedAnon || certificateExists) && !EIP.mIsStarting && !EIP.isConnected(); } private boolean canLogInToStartEIP() { - boolean isAllowedRegistered = Dashboard.preferences.getBoolean(EIP.ALLOWED_REGISTERED, false); + boolean isAllowedRegistered = Dashboard.preferences.getBoolean(Constants.ALLOWED_REGISTERED, false); boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty(); Log.d(TAG, "Allow registered? " + isAllowedRegistered); Log.d(TAG, "Is logged in? " + isLoggedIn); @@ -192,7 +176,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe eipSwitch.setChecked(true); saveEipStatus(); } - eipCommand(EIP.ACTION_START_EIP); + eipCommand(Constants.ACTION_START_EIP); } protected void stopEIP() { @@ -203,7 +187,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe String status = getResources().getString(R.string.eip_state_not_connected); setEipStatus(status); - eipCommand(EIP.ACTION_STOP_EIP); + eipCommand(Constants.ACTION_STOP_EIP); } /** @@ -216,16 +200,16 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe // TODO validate "action"...how do we get the list of intent-filters for a class via Android API? Intent vpn_intent = new Intent(getActivity().getApplicationContext(), EIP.class); vpn_intent.setAction(action); - vpn_intent.putExtra(EIP.RECEIVER_TAG, mEIPReceiver); + vpn_intent.putExtra(Constants.RECEIVER_TAG, mEIPReceiver); getActivity().startService(vpn_intent); } @Override - public void updateState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) { + public void updateState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) { boolean isNewLevel = EIP.lastConnectionStatusLevel != level; - boolean justDecidedOnDisconnect = EIP.lastConnectionStatusLevel == ConnectionStatus.UNKNOWN_LEVEL; + boolean justDecidedOnDisconnect = EIP.lastConnectionStatusLevel == VpnStatus.ConnectionStatus.UNKNOWN_LEVEL; Log.d(TAG, "update state with level " + level); - if(!justDecidedOnDisconnect && (isNewLevel || level == ConnectionStatus.LEVEL_CONNECTED)) { + if(!justDecidedOnDisconnect && (isNewLevel || level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED)) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { @@ -233,28 +217,28 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe handleNewState(state, logmessage, localizedResId, level); } }); - } else if(justDecidedOnDisconnect && level == ConnectionStatus.LEVEL_CONNECTED) { - EIP.lastConnectionStatusLevel = ConnectionStatus.LEVEL_NOTCONNECTED; + } else if(justDecidedOnDisconnect && level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED) { + EIP.lastConnectionStatusLevel = VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; updateState(state, logmessage, localizedResId, level); } // else if(isNewLevel || level == ConnectionStatus.LEVEL_AUTH_FAILED) // handleNewState(state, logmessage, localizedResId, level); } - private void handleNewState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) { - if (level == ConnectionStatus.LEVEL_CONNECTED) + private void handleNewState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) { + if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED) setConnectedUI(); else if (isDisconnectedLevel(level) && !EIP.mIsStarting) setDisconnectedUI(); - else if (level == ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET) + else if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET) setNoServerReplyUI(localizedResId, logmessage); - else if (level == ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED) + else if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED) setServerReplyUI(state, localizedResId, logmessage); - // else if (level == ConnectionStatus.LEVEL_AUTH_FAILED) + // else if (level == VpnStatus.ConnectionStatus.LEVEL_AUTH_FAILED) // handleSwitchOn(); } - private boolean isDisconnectedLevel(final ConnectionStatus level) { - return level == ConnectionStatus.LEVEL_NOTCONNECTED || level == ConnectionStatus.LEVEL_AUTH_FAILED; + private boolean isDisconnectedLevel(final VpnStatus.ConnectionStatus level) { + return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED || level == VpnStatus.ConnectionStatus.LEVEL_AUTH_FAILED; } private void setConnectedUI() { @@ -331,10 +315,10 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); - String request = resultData.getString(EIP.REQUEST_TAG); + String request = resultData.getString(Constants.REQUEST_TAG); boolean checked = false; - if (request == EIP.ACTION_IS_EIP_RUNNING) { + if (request == Constants.ACTION_IS_EIP_RUNNING) { switch (resultCode){ case Activity.RESULT_OK: checked = true; @@ -343,7 +327,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe checked = false; break; } - } else if (request == EIP.ACTION_START_EIP) { + } else if (request == Constants.ACTION_START_EIP) { switch (resultCode){ case Activity.RESULT_OK: Log.d(TAG, "Action start eip = Result OK"); @@ -356,7 +340,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe eipFragment.findViewById(R.id.eipProgress).setVisibility(View.GONE); break; } - } else if (request == EIP.ACTION_STOP_EIP) { + } else if (request == Constants.ACTION_STOP_EIP) { switch (resultCode){ case Activity.RESULT_OK: checked = false; @@ -365,7 +349,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe checked = true; break; } - } else if (request == EIP.EIP_NOTIFICATION) { + } else if (request == Constants.EIP_NOTIFICATION) { switch (resultCode){ case Activity.RESULT_OK: checked = true; @@ -374,7 +358,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe checked = false; break; } - } else if (request == EIP.ACTION_CHECK_CERT_VALIDITY) { + } else if (request == Constants.ACTION_CHECK_CERT_VALIDITY) { checked = eipSwitch.isChecked(); switch (resultCode) { @@ -387,7 +371,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe String status = getResources().getString(R.string.updating_certificate_message); setEipStatus(status); - if(LeapSRPSession.getToken().isEmpty() && !Dashboard.preferences.getBoolean(EIP.ALLOWED_ANON, false)) { + if(LeapSRPSession.getToken().isEmpty() && !Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false)) { dashboard.logInDialog(Bundle.EMPTY); } else { diff --git a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java index eb196d46..74f89ab8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java +++ b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java @@ -1,10 +1,9 @@ package se.leap.bitmaskclient; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; +import android.content.*; import android.util.Log; +import se.leap.bitmaskclient.eip.Constants; public class OnBootReceiver extends BroadcastReceiver { @@ -14,7 +13,7 @@ public class OnBootReceiver extends BroadcastReceiver { if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { if (!context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE).getString(Provider.KEY, "").isEmpty() && context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE).getBoolean(Dashboard.START_ON_BOOT, false)) { Intent dashboard_intent = new Intent(context, Dashboard.class); - dashboard_intent.setAction(EIP.ACTION_START_EIP); + dashboard_intent.setAction(Constants.ACTION_START_EIP); dashboard_intent.putExtra(Dashboard.ON_BOOT, true); dashboard_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(dashboard_intent); diff --git a/app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java b/app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java deleted file mode 100644 index 3b286fbf..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java +++ /dev/null @@ -1,37 +0,0 @@ -package se.leap.bitmaskclient; - -import android.app.Activity; -import android.content.Intent; -import android.net.VpnService; -import android.os.Bundle; - -public class VoidVpnLauncher extends Activity { - - private static final int VPN_USER_PERMISSION = 71; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setUp(); - } - - public void setUp() { - Intent blocking_intent = VpnService.prepare(getApplicationContext()); // stops the VPN connection created by another application. - if(blocking_intent != null) - startActivityForResult(blocking_intent, VPN_USER_PERMISSION); - else { - onActivityResult(VPN_USER_PERMISSION, RESULT_OK, null); - } - } - - protected void onActivityResult(int requestCode, int resultCode, Intent data){ - if(requestCode == VPN_USER_PERMISSION) { - if(resultCode == RESULT_OK) { - Intent void_vpn_service = new Intent(getApplicationContext(), VoidVpnService.class); - void_vpn_service.setAction(VoidVpnService.START_BLOCKING_VPN_PROFILE); - startService(void_vpn_service); - } - } - finish(); - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java deleted file mode 100644 index 7b597554..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java +++ /dev/null @@ -1,36 +0,0 @@ -package se.leap.bitmaskclient; - -import android.content.Intent; -import android.os.Process; -import android.net.VpnService; -import android.util.Log; - -public class VoidVpnService extends VpnService { - - static final String START_BLOCKING_VPN_PROFILE = "se.leap.bitmaskclient.START_BLOCKING_VPN_PROFILE"; - static final String TAG = VoidVpnService.class.getSimpleName(); - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - String action = intent.getAction(); - if (action == START_BLOCKING_VPN_PROFILE) { - new Thread(new Runnable() { - public void run() { - Builder builder = new Builder(); - builder.setSession("Blocking until running"); - builder.addAddress("10.42.0.8",16); - builder.addRoute("0.0.0.0", 1); - builder.addRoute("192.168.1.0", 24); - builder.addDnsServer("10.42.0.1"); - try { - builder.establish(); - } catch (Exception e) { - e.printStackTrace(); - } - android.util.Log.d(TAG, "VoidVpnService set up"); - } - }).run(); - } - return 0; - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java deleted file mode 100644 index ef049a3c..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package se.leap.bitmaskclient; - -import android.content.SharedPreferences; -import android.util.Log; -import java.util.Iterator; -import java.util.Vector; -import org.json.JSONArray; -import org.json.JSONObject; -import org.json.JSONException; - -import se.leap.bitmaskclient.Provider; -import se.leap.bitmaskclient.EIP; - -public class VpnConfigGenerator { - - private JSONObject general_configuration; - private JSONObject gateway; - - private static SharedPreferences preferences; - public final static String TAG = VpnConfigGenerator.class.getSimpleName(); - private final String new_line = System.getProperty("line.separator"); // Platform new line - - public VpnConfigGenerator(SharedPreferences preferences, JSONObject general_configuration, JSONObject gateway) { - this.general_configuration = general_configuration; - this.gateway = gateway; - this.preferences = preferences; - } - - public String generate() { - return - generalConfiguration() - + new_line - + gatewayConfiguration() - + new_line - + secretsConfiguration() - + new_line - + androidCustomizations(); - } - - private String generalConfiguration() { - String common_options = ""; - try { - Iterator keys = general_configuration.keys(); - Vector> value = new Vector>(); - while ( keys.hasNext() ){ - String key = keys.next().toString(); - - common_options += key + " "; - for ( String word : general_configuration.getString(key).split(" ") ) - common_options += word + " "; - common_options += new_line; - - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - common_options += "client"; - - return common_options; - } - - private String gatewayConfiguration() { - String remotes = ""; - - String remote = "ip_address"; - String remote_openvpn_keyword = "remote"; - String ports = "ports"; - String protos = "protocols"; - String capabilities = "capabilities"; - String udp = "udp"; - - try { - JSONArray protocolsJSON = gateway.getJSONObject(capabilities).getJSONArray(protos); - for ( int i=0; i" - + new_line - + preferences.getString(Provider.CA_CERT, "") - + new_line - + ""; - - String key = - "" - + new_line - + preferences.getString(EIP.PRIVATE_KEY, "") - + new_line - + ""; - - String openvpn_cert = - "" - + new_line - + preferences.getString(EIP.CERTIFICATE, "") - + new_line - + ""; - - return ca + new_line + key + new_line + openvpn_cert; - } - - private String androidCustomizations() { - return - "remote-cert-tls server" - + new_line - + "persist-tun" - + new_line - + "auth-retry nointeract"; - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java new file mode 100644 index 00000000..719fff6d --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2013 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package se.leap.bitmaskclient.eip; + +/** + * + * Constants for intent passing, shared preferences + * + * @author Parménides GV + * + */ +public interface Constants { + + public final static String TAG = Constants.class.getSimpleName(); + + public final static String AUTHED_EIP = TAG + ".AUTHED_EIP"; + public final static String ACTION_CHECK_CERT_VALIDITY = TAG + ".CHECK_CERT_VALIDITY"; + public final static String ACTION_START_EIP = TAG + ".START_EIP"; + public final static String ACTION_STOP_EIP = TAG + ".STOP_EIP"; + public final static String ACTION_UPDATE_EIP_SERVICE = TAG + ".UPDATE_EIP_SERVICE"; + public final static String ACTION_IS_EIP_RUNNING = TAG + ".IS_RUNNING"; + public final static String ACTION_REBUILD_PROFILES = TAG + ".REBUILD_PROFILES"; + public final static String EIP_NOTIFICATION = TAG + ".EIP_NOTIFICATION"; + public final static String STATUS = TAG + ".STATUS"; + public final static String DATE_FROM_CERTIFICATE = TAG + ".DATE_FROM_CERTIFICATE"; + public final static String ALLOWED_ANON = TAG + ".ALLOW_ANONYMOUS"; + public final static String ALLOWED_REGISTERED = TAG + ".ALLOW_REGISTRATION"; + public final static String CERTIFICATE = TAG + ".CERTIFICATE"; + public final static String PRIVATE_KEY = TAG + ".PRIVATE_KEY"; + public final static String KEY = TAG + ".KEY"; + public final static String PARSED_SERIAL = TAG + ".PARSED_SERIAL"; + public final static String RECEIVER_TAG = TAG + ".RECEIVER_TAG"; + public final static String REQUEST_TAG = TAG + ".REQUEST_TAG"; + public final static String START_BLOCKING_VPN_PROFILE = TAG + ".START_BLOCKING_VPN_PROFILE"; + +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java new file mode 100644 index 00000000..b668ce64 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -0,0 +1,486 @@ +/** + * Copyright (c) 2013 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package se.leap.bitmaskclient.eip; + +import android.app.*; +import android.content.*; +import android.os.*; +import android.util.Log; +import java.io.*; +import java.security.cert.*; +import java.text.*; +import java.util.*; +import org.json.*; + +import de.blinkt.openvpn.*; +import de.blinkt.openvpn.activities.*; +import de.blinkt.openvpn.core.*; +import se.leap.bitmaskclient.*; + +import static se.leap.bitmaskclient.eip.Constants.*; + +/** + * EIP is the abstract base class for interacting with and managing the Encrypted + * Internet Proxy connection. Connections are started, stopped, and queried through + * this IntentService. + * Contains logic for parsing eip-service.json from the provider, configuring and selecting + * gateways, and controlling {@link de.blinkt.openvpn.core.OpenVPNService} connections. + * + * @author Sean Leonard + * @author Parménides GV + */ +public final class EIP extends IntentService { + + public final static String TAG = EIP.class.getSimpleName(); + + public final static String SERVICE_API_PATH = "config/eip-service.json"; + + private static SharedPreferences preferences; + + private static Context context; + private static ResultReceiver mReceiver; + private static boolean mBound = false; + + private static JSONObject eipDefinition = null; + + private static OVPNGateway activeGateway = null; + + public static VpnStatus.ConnectionStatus lastConnectionStatusLevel; + public static boolean mIsDisconnecting = false; + public static boolean mIsStarting = false; + + public static SimpleDateFormat certificate_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US); + + public EIP(){ + super("LEAPEIP"); + } + + @Override + public void onCreate() { + super.onCreate(); + + context = getApplicationContext(); + + preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); + } + + @Override + public void onDestroy() { + + mBound = false; + + super.onDestroy(); + } + + + @Override + protected void onHandleIntent(Intent intent) { + String action = intent.getAction(); + mReceiver = intent.getParcelableExtra(RECEIVER_TAG); + + if ( action == ACTION_START_EIP ) + startEIP(); + else if ( action == ACTION_STOP_EIP ) + stopEIP(); + else if ( action == ACTION_IS_EIP_RUNNING ) + isRunning(); + else if ( action == ACTION_UPDATE_EIP_SERVICE ) + updateEIPService(); + else if ( action == ACTION_CHECK_CERT_VALIDITY ) + checkCertValidity(); + else if ( action == ACTION_REBUILD_PROFILES ) + updateGateways(); + } + + /** + * Initiates an EIP connection by selecting a gateway and preparing and sending an + * Intent to {@link se.leap.openvpn.LaunchVPN}. + * It also sets up early routes. + */ + private void startEIP() { + earlyRoutes(); + activeGateway = selectGateway(); + + if(activeGateway != null && activeGateway.mVpnProfile != null) { + mReceiver = EipServiceFragment.getReceiver(); + launchActiveGateway(); + } + } + + /** + * Early routes are routes that block traffic until a new + * VpnService is started properly. + */ + private void earlyRoutes() { + Intent void_vpn_launcher = new Intent(context, VoidVpnLauncher.class); + void_vpn_launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(void_vpn_launcher); + } + + /** + * Choose a gateway to connect to based on timezone from system locale data + * + * @return The gateway to connect to + */ + private OVPNGateway selectGateway() { + String closest_location = closestGateway(); + String chosen_host = chooseHost(closest_location); + + return new OVPNGateway(chosen_host); + } + + private String closestGateway() { + TreeMap> offsets = calculateOffsets(); + return offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next(); + } + + private TreeMap> calculateOffsets() { + TreeMap> offsets = new TreeMap>(); + + int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000; + + JSONObject locations = availableLocations(); + Iterator locations_names = locations.keys(); + while(locations_names.hasNext()) { + try { + String location_name = locations_names.next(); + JSONObject location = locations.getJSONObject(location_name); + + int dist = timezoneDistance(localOffset, location.optInt("timezone")); + + Set set = (offsets.get(dist) != null) ? + offsets.get(dist) : new HashSet(); + + set.add(location_name); + offsets.put(dist, set); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + return offsets; + } + + private JSONObject availableLocations() { + JSONObject locations = null; + try { + if(eipDefinition == null) updateEIPService(); + locations = eipDefinition.getJSONObject("locations"); + } catch (JSONException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + return locations; + } + + private int timezoneDistance(int local_timezone, int remote_timezone) { + // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12 + int dist = Math.abs(local_timezone - remote_timezone); + + // Farther than 12 timezones and it's shorter around the "back" + if (dist > 12) + dist = 12 - (dist -12); // Well i'll be. Absolute values make equations do funny things. + + return dist; + } + + private String chooseHost(String location) { + String chosen_host = ""; + try { + JSONArray gateways = eipDefinition.getJSONArray("gateways"); + for (int i = 0; i < gateways.length(); i++) { + JSONObject gw = gateways.getJSONObject(i); + if ( gw.getString("location").equalsIgnoreCase(location) || location.isEmpty()){ + chosen_host = eipDefinition.getJSONObject("locations").getJSONObject(gw.getString("location")).getString("name"); + break; + } + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return chosen_host; + } + + private void launchActiveGateway() { + Intent intent = new Intent(this,LaunchVPN.class); + intent.setAction(Intent.ACTION_MAIN); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(LaunchVPN.EXTRA_KEY, activeGateway.mVpnProfile.getUUID().toString() ); + intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.mVpnProfile.getName() ); + intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true); + intent.putExtra(RECEIVER_TAG, mReceiver); + startActivity(intent); + } + + /** + * Disconnects the EIP connection gracefully through the bound service or forcefully + * if there is no bound service. Sends a message to the requesting ResultReceiver. + */ + private void stopEIP() { + if(isConnected()) { + Intent disconnect_vpn = new Intent(this, DisconnectVPN.class); + disconnect_vpn.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(disconnect_vpn); + mIsDisconnecting = true; + lastConnectionStatusLevel = VpnStatus.ConnectionStatus.UNKNOWN_LEVEL; // Wait for the decision of the user + Log.d(TAG, "mIsDisconnecting = true"); + } + + tellToReceiver(ACTION_STOP_EIP, Activity.RESULT_OK); + } + + private void tellToReceiver(String action, int resultCode) { + if (mReceiver != null){ + Bundle resultData = new Bundle(); + resultData.putString(REQUEST_TAG, action); + mReceiver.send(resultCode, resultData); + } + } + + /** + * Checks the last stored status notified by ics-openvpn + * Sends Activity.RESULT_CANCELED to the ResultReceiver that made the + * request if it's not connected, Activity.RESULT_OK otherwise. + */ + + private void isRunning() { + int resultCode = Activity.RESULT_CANCELED; + boolean is_connected = isConnected(); + + resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED; + + tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode); + } + + public static boolean isConnected() { + return lastConnectionStatusLevel != null && lastConnectionStatusLevel.equals(VpnStatus.ConnectionStatus.LEVEL_CONNECTED) && !mIsDisconnecting; + } + + /** + * Loads eip-service.json from SharedPreferences and calls {@link updateGateways()} + * to parse gateway definitions. + * TODO Implement API call to refresh eip-service.json from the provider + */ + private void updateEIPService() { + try { + String eip_definition_string = preferences.getString(KEY, ""); + if(eip_definition_string.isEmpty() == false) { + eipDefinition = new JSONObject(eip_definition_string); + } + deleteAllVpnProfiles(); + updateGateways(); + if(mReceiver != null) mReceiver.send(Activity.RESULT_OK, Bundle.EMPTY); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private void deleteAllVpnProfiles() { + ProfileManager vpl = ProfileManager.getInstance(context); + Collection profiles = vpl.getProfiles(); + profiles.removeAll(profiles); + } + + /** + * Walk the list of gateways defined in eip-service.json and parse them into + * OVPNGateway objects. + * TODO Store the OVPNGateways (as Serializable) in SharedPreferences + */ + private void updateGateways(){ + JSONArray gatewaysDefined = null; + try { + if(eipDefinition == null) updateEIPService(); + gatewaysDefined = eipDefinition.getJSONArray("gateways"); + for ( int i=0 ; i < gatewaysDefined.length(); i++ ){ + JSONObject gw = null; + gw = gatewaysDefined.getJSONObject(i); + + if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ) + new OVPNGateway(gw); + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + preferences.edit().putInt(PARSED_SERIAL, eipDefinition.optInt(Provider.API_RETURN_SERIAL)).commit(); + } + + private void checkCertValidity() { + String certificate = preferences.getString(CERTIFICATE, ""); + checkCertValidity(certificate); + } + + private void checkCertValidity(String certificate_string) { + if(!certificate_string.isEmpty()) { + X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificate_string); + + Calendar offset_date = calculateOffsetCertificateValidity(certificate); + Bundle result = new Bundle(); + result.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY); + try { + Log.d(TAG, "offset_date = " + offset_date.getTime().toString()); + certificate.checkValidity(offset_date.getTime()); + mReceiver.send(Activity.RESULT_OK, result); + Log.d(TAG, "Valid certificate"); + } catch(CertificateExpiredException e) { + mReceiver.send(Activity.RESULT_CANCELED, result); + Log.d(TAG, "Updating certificate"); + } catch(CertificateNotYetValidException e) { + mReceiver.send(Activity.RESULT_CANCELED, result); + } + } + } + + private Calendar calculateOffsetCertificateValidity(X509Certificate certificate) { + String current_date = certificate_date_format.format(Calendar.getInstance().getTime()).toString(); + + String date_string = preferences.getString(DATE_FROM_CERTIFICATE, current_date); + + Calendar offset_date = Calendar.getInstance(); + try { + Date date = certificate_date_format.parse(date_string); + long difference = Math.abs(date.getTime() - certificate.getNotAfter().getTime())/2; + long current_date_millis = offset_date.getTimeInMillis(); + offset_date.setTimeInMillis(current_date_millis + difference); + Log.d(TAG, "certificate not after = " + certificate.getNotAfter()); + } catch(ParseException e) { + e.printStackTrace(); + } + + return offset_date; + } + + /** + * OVPNGateway provides objects defining gateways and their options and metadata. + * Each instance contains a VpnProfile for OpenVPN specific data and member + * variables describing capabilities and location + * + * @author Sean Leonard + */ + private class OVPNGateway { + + private String TAG = "OVPNGateway"; + + private String mName; + private VpnProfile mVpnProfile; + private JSONObject mGateway; + private HashMap>> options = new HashMap>>(); + + + /** + * Attempts to retrieve a VpnProfile by name and build an OVPNGateway around it. + * FIXME This needs to become a findGatewayByName() method + * + * @param name The hostname of the gateway to inflate + */ + private OVPNGateway(String name){ + mName = name; + + this.loadVpnProfile(); + } + + private void loadVpnProfile() { + ProfileManager vpl = ProfileManager.getInstance(context); + try { + if ( mName == null ) + mVpnProfile = vpl.getProfiles().iterator().next(); + else + mVpnProfile = vpl.getProfileByName(mName); + } catch (NoSuchElementException e) { + updateEIPService(); + this.loadVpnProfile(); // FIXME catch infinite loops + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json + * and create a VpnProfile belonging to it. + * + * @param gateway The JSON OpenVPN gateway definition to parse + */ + protected OVPNGateway(JSONObject gateway){ + + mGateway = gateway; + + // Currently deletes VpnProfile for host, if there already is one, and builds new + ProfileManager vpl = ProfileManager.getInstance(context); + Collection profiles = vpl.getProfiles(); + for (Iterator it = profiles.iterator(); it.hasNext(); ){ + VpnProfile p = it.next(); + + if ( p.mName.equalsIgnoreCase( mName ) ) { + it.remove(); + vpl.removeProfile(context, p); + } + } + + this.createVPNProfile(); + + vpl.addProfile(mVpnProfile); + vpl.saveProfile(context, mVpnProfile); + vpl.saveProfileList(context); + } + + /** + * Create and attach the VpnProfile to our gateway object + */ + protected void createVPNProfile(){ + try { + ConfigParser cp = new ConfigParser(); + + JSONObject openvpn_configuration = eipDefinition.getJSONObject("openvpn_configuration"); + VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(preferences, openvpn_configuration, mGateway); + String configuration = vpn_configuration_generator.generate(); + + cp.parseConfig(new StringReader(configuration)); + mVpnProfile = cp.convertProfile(); + mVpnProfile.mName = mName = locationAsName(); + Log.v(TAG,"Created VPNProfile"); + + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ConfigParser.ConfigParseError e) { + // FIXME We didn't get a VpnProfile! Error handling! and log level + Log.v(TAG,"Error creating VPNProfile"); + e.printStackTrace(); + } catch (IOException e) { + // FIXME We didn't get a VpnProfile! Error handling! and log level + Log.v(TAG,"Error creating VPNProfile"); + e.printStackTrace(); + } + } + + + public String locationAsName() { + try { + return eipDefinition.getJSONObject("locations").getJSONObject(mGateway.getString("location")).getString("name"); + } catch (JSONException e) { + Log.v(TAG,"Couldn't read gateway name for profile creation! Returning original name = " + mName); + e.printStackTrace(); + return (mName != null) ? mName : ""; + } + } + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java new file mode 100644 index 00000000..9814c167 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java @@ -0,0 +1,37 @@ +package se.leap.bitmaskclient.eip; + +import android.app.Activity; +import android.content.Intent; +import android.net.VpnService; +import android.os.Bundle; + +public class VoidVpnLauncher extends Activity { + + private static final int VPN_USER_PERMISSION = 71; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setUp(); + } + + public void setUp() { + Intent blocking_intent = VpnService.prepare(getApplicationContext()); // stops the VPN connection created by another application. + if(blocking_intent != null) + startActivityForResult(blocking_intent, VPN_USER_PERMISSION); + else { + onActivityResult(VPN_USER_PERMISSION, RESULT_OK, null); + } + } + + protected void onActivityResult(int requestCode, int resultCode, Intent data){ + if(requestCode == VPN_USER_PERMISSION) { + if(resultCode == RESULT_OK) { + Intent void_vpn_service = new Intent(getApplicationContext(), VoidVpnService.class); + void_vpn_service.setAction(Constants.START_BLOCKING_VPN_PROFILE); + startService(void_vpn_service); + } + } + finish(); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java new file mode 100644 index 00000000..224e3bd4 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java @@ -0,0 +1,37 @@ +package se.leap.bitmaskclient.eip; + +import android.content.Intent; +import android.os.Process; +import android.net.VpnService; +import android.util.Log; + +import static se.leap.bitmaskclient.eip.Constants.*; + +public class VoidVpnService extends VpnService { + + static final String TAG = VoidVpnService.class.getSimpleName(); + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + String action = intent.getAction(); + if (action == Constants.START_BLOCKING_VPN_PROFILE) { + new Thread(new Runnable() { + public void run() { + Builder builder = new Builder(); + builder.setSession("Blocking until running"); + builder.addAddress("10.42.0.8",16); + builder.addRoute("0.0.0.0", 1); + builder.addRoute("192.168.1.0", 24); + builder.addDnsServer("10.42.0.1"); + try { + builder.establish(); + } catch (Exception e) { + e.printStackTrace(); + } + android.util.Log.d(TAG, "VoidVpnService set up"); + } + }).run(); + } + return 0; + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java new file mode 100644 index 00000000..8e36f53c --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2013 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package se.leap.bitmaskclient.eip; + +import android.content.SharedPreferences; +import android.util.Log; +import java.util.Iterator; +import java.util.Vector; +import org.json.JSONArray; +import org.json.JSONObject; +import org.json.JSONException; + +import se.leap.bitmaskclient.*; + +public class VpnConfigGenerator { + + private JSONObject general_configuration; + private JSONObject gateway; + + private static SharedPreferences preferences; + public final static String TAG = VpnConfigGenerator.class.getSimpleName(); + private final String new_line = System.getProperty("line.separator"); // Platform new line + + public VpnConfigGenerator(SharedPreferences preferences, JSONObject general_configuration, JSONObject gateway) { + this.general_configuration = general_configuration; + this.gateway = gateway; + this.preferences = preferences; + } + + public String generate() { + return + generalConfiguration() + + new_line + + gatewayConfiguration() + + new_line + + secretsConfiguration() + + new_line + + androidCustomizations(); + } + + private String generalConfiguration() { + String common_options = ""; + try { + Iterator keys = general_configuration.keys(); + Vector> value = new Vector>(); + while ( keys.hasNext() ){ + String key = keys.next().toString(); + + common_options += key + " "; + for ( String word : general_configuration.getString(key).split(" ") ) + common_options += word + " "; + common_options += new_line; + + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + common_options += "client"; + + return common_options; + } + + private String gatewayConfiguration() { + String remotes = ""; + + String remote = "ip_address"; + String remote_openvpn_keyword = "remote"; + String ports = "ports"; + String protos = "protocols"; + String capabilities = "capabilities"; + String udp = "udp"; + + try { + JSONArray protocolsJSON = gateway.getJSONObject(capabilities).getJSONArray(protos); + for ( int i=0; i" + + new_line + + preferences.getString(Provider.CA_CERT, "") + + new_line + + ""; + + String key = + "" + + new_line + + preferences.getString(Constants.PRIVATE_KEY, "") + + new_line + + ""; + + String openvpn_cert = + "" + + new_line + + preferences.getString(Constants.CERTIFICATE, "") + + new_line + + ""; + + return ca + new_line + key + new_line + openvpn_cert; + } + + private String androidCustomizations() { + return + "remote-cert-tls server" + + new_line + + "persist-tun" + + new_line + + "auth-retry nointeract"; + } +} diff --git a/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java b/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java index 03930c61..d3203ab3 100644 --- a/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java +++ b/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java @@ -16,39 +16,17 @@ */ package se.leap.bitmaskclient; -import android.app.Activity; -import android.app.DialogFragment; -import android.app.Fragment; -import android.app.FragmentTransaction; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; +import android.app.*; +import android.content.*; import android.content.res.AssetManager; -import android.os.Bundle; -import android.os.Handler; +import android.os.*; import android.util.Log; -import android.view.Display; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View.MeasureSpec; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.widget.ListAdapter; -import android.widget.ListView; -import android.widget.ProgressBar; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.TextView; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Iterator; -import org.json.JSONException; -import org.json.JSONObject; +import android.view.*; +import android.widget.*; +import java.io.*; +import java.net.*; +import java.util.*; +import org.json.*; import se.leap.bitmaskclient.DownloadFailedDialog.DownloadFailedDialogInterface; import se.leap.bitmaskclient.NewProviderDialog.NewProviderDialogInterface; @@ -56,7 +34,7 @@ import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver; import se.leap.bitmaskclient.ProviderDetailFragment.ProviderDetailFragmentInterface; import se.leap.bitmaskclient.ProviderListContent.ProviderItem; import se.leap.bitmaskclient.FragmentManagerEnhanced; - +import se.leap.bitmaskclient.eip.Constants; import se.leap.bitmaskclient.R; /** @@ -165,7 +143,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD if(resultCode == ProviderAPI.PROVIDER_OK) { mConfigState.setAction(PROVIDER_SET); - if (preferences.getBoolean(EIP.ALLOWED_ANON, false)){ + if (preferences.getBoolean(Constants.ALLOWED_ANON, false)){ mConfigState.putExtra(SERVICES_RETRIEVED, true); downloadAnonCert(); @@ -311,8 +289,8 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD int screenWidth = display.getWidth(); // deprecated int listViewWidth = screenWidth - 10 - 10; - int widthSpec = MeasureSpec.makeMeasureSpec(listViewWidth, - MeasureSpec.AT_MOST); + int widthSpec = View.MeasureSpec.makeMeasureSpec(listViewWidth, + View.MeasureSpec.AT_MOST); listItem.measure(widthSpec, 0); return listItem.getMeasuredHeight(); @@ -544,7 +522,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD if(provider_list_fragment != null) { provider_list_fragment.removeLastItem(); } - preferences.edit().remove(Provider.KEY).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit(); + preferences.edit().remove(Provider.KEY).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit(); } @Override diff --git a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java index f419afaf..e2da588c 100644 --- a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java @@ -17,59 +17,22 @@ package se.leap.bitmaskclient; import android.app.IntentService; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.os.ResultReceiver; -import android.util.Base64; -import android.util.Log; -import java.io.DataOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; +import android.content.*; +import android.os.*; +import android.util.*; +import java.io.*; import java.math.BigInteger; -import java.net.ConnectException; -import java.net.CookieHandler; -import java.net.CookieManager; -import java.net.CookiePolicy; -import java.net.MalformedURLException; -import java.net.SocketTimeoutException; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLEncoder; -import java.net.UnknownHostException; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; +import java.net.*; +import java.security.*; +import java.security.cert.*; import java.security.interfaces.RSAPrivateKey; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Scanner; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.KeyManager; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; +import java.util.*; +import javax.net.ssl.*; import org.apache.http.client.ClientProtocolException; -import org.json.JSONException; -import org.json.JSONObject; -import se.leap.bitmaskclient.R; +import org.json.*; +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.eip.*; /** * Implements HTTP api methods used to manage communications with the provider server. @@ -619,8 +582,8 @@ public class ProviderAPI extends IntentService { //TODO setProviderName(name); preferences.edit().putString(Provider.KEY, provider_json.toString()).commit(); - preferences.edit().putBoolean(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON)).commit(); - preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_REGISTERED)).commit(); + preferences.edit().putBoolean(Constants.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_ANON)).commit(); + preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_REGISTERED)).commit(); result.putBoolean(RESULT_KEY, true); } catch (JSONException e) { @@ -644,7 +607,7 @@ public class ProviderAPI extends IntentService { JSONObject eip_service_json = new JSONObject(eip_service_json_string); eip_service_json.getInt(Provider.API_RETURN_SERIAL); - preferences.edit().putString(EIP.KEY, eip_service_json.toString()).commit(); + preferences.edit().putString(Constants.KEY, eip_service_json.toString()).commit(); result.putBoolean(RESULT_KEY, true); } catch (JSONException e) { @@ -887,7 +850,7 @@ public class ProviderAPI extends IntentService { getNewCert(); Intent updateEIP = new Intent(getApplicationContext(), EIP.class); - updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE); + updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); startService(updateEIP); return true; @@ -903,7 +866,7 @@ public class ProviderAPI extends IntentService { JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); String provider_main_url = provider_json.getString(Provider.API_URL); - URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.CERTIFICATE); + URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + Constants.CERTIFICATE); String cert_string = downloadWithProviderCA(new_cert_string_url.toString()); @@ -937,12 +900,12 @@ public class ProviderAPI extends IntentService { } RSAPrivateKey key = ConfigHelper.parseRsaKeyFromString(keyString); keyString = Base64.encodeToString(key.getEncoded(), Base64.DEFAULT); - preferences.edit().putString(EIP.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit(); + preferences.edit().putString(Constants.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit(); X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificateString); certificateString = Base64.encodeToString(certificate.getEncoded(), Base64.DEFAULT); - preferences.edit().putString(EIP.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit(); - preferences.edit().putString(EIP.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit(); + preferences.edit().putString(Constants.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit(); + preferences.edit().putString(Constants.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit(); return true; } catch (CertificateException e) { // TODO Auto-generated catch block diff --git a/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java b/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java index 9252b8fa..97ce5245 100644 --- a/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java +++ b/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java @@ -1,22 +1,17 @@ -package se.leap.bitmaskclient; - -import org.json.JSONException; -import org.json.JSONObject; - -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.ProviderListContent.ProviderItem; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.DialogInterface; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; - +package se.leap.bitmaskclient; + +import org.json.*; + +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.eip.Constants; +import se.leap.bitmaskclient.ProviderListContent.ProviderItem; + +import android.app.*; +import android.content.*; +import android.os.Bundle; +import android.view.*; +import android.widget.TextView; + public class ProviderDetailFragment extends DialogFragment { final public static String TAG = "providerDetailFragment"; @@ -66,7 +61,7 @@ public class ProviderDetailFragment extends DialogFragment { private boolean anon_allowed(JSONObject provider_json) { try { JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE); - return service_description.has(EIP.ALLOWED_ANON) && service_description.getBoolean(EIP.ALLOWED_ANON); + return service_description.has(Constants.ALLOWED_ANON) && service_description.getBoolean(Constants.ALLOWED_ANON); } catch (JSONException e) { return false; } @@ -85,7 +80,7 @@ public class ProviderDetailFragment extends DialogFragment { public void onCancel(DialogInterface dialog) { super.onCancel(dialog); SharedPreferences.Editor editor = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).edit(); - editor.remove(Provider.KEY).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit(); + editor.remove(Provider.KEY).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit(); interface_with_configuration_wizard.showAllProviders(); } -- cgit v1.2.3