diff options
-rw-r--r-- | AndroidManifest.xml | 4 | ||||
-rw-r--r-- | CHANGELOG | 13 | ||||
-rw-r--r-- | assets/urls/bitmask.url | 6 | ||||
-rw-r--r-- | src/se/leap/bitmaskclient/AboutFragment.java | 3 | ||||
-rw-r--r-- | src/se/leap/bitmaskclient/ConfigurationWizard.java | 237 | ||||
-rw-r--r-- | src/se/leap/bitmaskclient/Dashboard.java | 70 | ||||
-rw-r--r-- | src/se/leap/bitmaskclient/EIP.java | 12 | ||||
-rw-r--r-- | src/se/leap/bitmaskclient/EipServiceFragment.java | 15 | ||||
-rw-r--r-- | src/se/leap/bitmaskclient/NewProviderDialog.java | 4 | ||||
-rw-r--r-- | src/se/leap/bitmaskclient/Provider.java | 4 | ||||
-rw-r--r-- | src/se/leap/bitmaskclient/ProviderAPI.java | 251 | ||||
-rw-r--r-- | src/se/leap/bitmaskclient/ProviderListAdapter.java | 19 | ||||
-rw-r--r-- | src/se/leap/bitmaskclient/ProviderListContent.java | 78 | ||||
-rw-r--r-- | src/se/leap/bitmaskclient/ProviderListFragment.java | 23 | ||||
-rw-r--r-- | src/se/leap/openvpn/OpenVPN.java | 5 | ||||
-rw-r--r-- | src/se/leap/openvpn/OpenVPNThread.java | 2 | ||||
-rw-r--r-- | src/se/leap/openvpn/OpenVpnManagementThread.java | 28 | ||||
-rw-r--r-- | src/se/leap/openvpn/OpenVpnService.java | 4 |
18 files changed, 313 insertions, 465 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 2cb8766e..bb788109 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -17,8 +17,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="se.leap.bitmaskclient" - android:versionCode="62" - android:versionName="0.2.2" > + android:versionCode="64" + android:versionName="0.2.3" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> @@ -1,3 +1,14 @@ +0.2.3-rc1 Nov 29 2013 +Features +- Begin integrating tests into repository +- Clearer wording in some places +- Show VPN Gateway location in notification +Bugs Fixed +- URL parsing error if http entered for custom provider +- Issues with certificates and gateways when switching providers +- SEVERE: Routes were not set on VPN connection and traffic was routed in the clear + + 0.2.2 - Nov 15 2013 - the "rampant growth" release: Features - Rebranded to Bitmask @@ -11,6 +22,8 @@ Bugs Fixed - Complex certificate verification - Remember authentication status - Widget shortcut crashes app + + 0.2.1 - Oct 21 2013 - the "get on that rolling bandwagon" release: Bugs Fixed - SRP tests should be runnable localhost diff --git a/assets/urls/bitmask.url b/assets/urls/bitmask.url index a17a5ff8..f924301e 100644 --- a/assets/urls/bitmask.url +++ b/assets/urls/bitmask.url @@ -1,7 +1,3 @@ {
- "name" : "bitmask",
- "assets_json_provider" : "providers/bitmask.net_provider.json",
- "provider_json_url" : "https://bitmask.net/provider.json",
- "cert" : "https://bitmask.net/ca.crt",
- "json_eip_service" : "https://api.bitmask.net:4430/1/config/eip-service.json"
+ "main_url" : "https://bitmask.net/"
}
\ No newline at end of file diff --git a/src/se/leap/bitmaskclient/AboutFragment.java b/src/se/leap/bitmaskclient/AboutFragment.java index d751dc2f..4d03a44b 100644 --- a/src/se/leap/bitmaskclient/AboutFragment.java +++ b/src/se/leap/bitmaskclient/AboutFragment.java @@ -4,9 +4,6 @@ import android.app.Fragment; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; -import android.text.Html; -import android.text.Spanned; -import android.text.method.LinkMovementMethod; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/src/se/leap/bitmaskclient/ConfigurationWizard.java b/src/se/leap/bitmaskclient/ConfigurationWizard.java index 28a8a44a..a4d8599f 100644 --- a/src/se/leap/bitmaskclient/ConfigurationWizard.java +++ b/src/se/leap/bitmaskclient/ConfigurationWizard.java @@ -25,18 +25,19 @@ import org.json.JSONObject; import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver;
import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
-
import android.app.Activity;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
-import android.app.ListFragment;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.Handler;
+import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
@@ -62,12 +63,12 @@ import android.widget.TextView; public class ConfigurationWizard extends Activity
implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogInterface, ProviderDetailFragment.ProviderDetailFragmentInterface, Receiver {
- private ProviderItem mSelectedProvider;
private ProgressBar mProgressBar;
private TextView progressbar_description;
private ProviderListFragment provider_list_fragment;
private Intent mConfigState = new Intent();
+ final public static String TAG = "se.leap.bitmaskclient.ConfigurationWizard";
final public static String TYPE_OF_CERTIFICATE = "type_of_certificate";
final public static String ANON_CERTIFICATE = "anon_certificate";
final public static String AUTHED_CERTIFICATE = "authed_certificate";
@@ -76,6 +77,8 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn final protected static String SERVICES_RETRIEVED = "SERVICES RETRIEVED";
public ProviderAPIResultReceiver providerAPI_result_receiver;
+ private ProviderAPIBroadcastReceiver_Update providerAPI_broadcast_receiver_update;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -88,7 +91,11 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn progressbar_description.setVisibility(TextView.INVISIBLE);
providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
providerAPI_result_receiver.setReceiver(this);
-
+ providerAPI_broadcast_receiver_update = new ProviderAPIBroadcastReceiver_Update();
+ IntentFilter update_intent_filter = new IntentFilter(ProviderAPI.UPDATE_PROGRESSBAR);
+ update_intent_filter.addCategory(Intent.CATEGORY_DEFAULT);
+ registerReceiver(providerAPI_broadcast_receiver_update, update_intent_filter);
+
ConfigHelper.setSharedPreferences(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE));
loadPreseededProviders();
@@ -114,6 +121,12 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn // TODO: If exposing deep links into your app, handle intents here.
}
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ unregisterReceiver(providerAPI_broadcast_receiver_update);
+ }
+
public void refreshProviderList(int top_padding) {
ProviderListFragment new_provider_list_fragment = new ProviderListFragment();
Bundle top_padding_bundle = new Bundle();
@@ -125,87 +138,29 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn .replace(R.id.configuration_wizard_layout, new_provider_list_fragment, ProviderListFragment.TAG)
.commit();
}
-
- private void setProviderList(ProviderListFragment new_provider_list_fragment) {
- FragmentManager fragmentManager = getFragmentManager();
- fragmentManager.beginTransaction()
- .replace(R.id.configuration_wizard_layout, new_provider_list_fragment, ProviderListFragment.TAG)
- .commit();
- }
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
- if(resultCode == ProviderAPI.CORRECTLY_UPDATED_PROVIDER_DOT_JSON) {
- JSONObject provider_json;
- try {
- provider_json = new JSONObject(resultData.getString(Provider.KEY));
- boolean danger_on = resultData.getBoolean(ProviderItem.DANGER_ON);
- ConfigHelper.saveSharedPref(Provider.KEY, provider_json);
- ConfigHelper.saveSharedPref(ProviderItem.DANGER_ON, danger_on);
- ConfigHelper.saveSharedPref(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON));
+ if(resultCode == ProviderAPI.PROVIDER_OK) {
mConfigState.setAction(PROVIDER_SET);
- if(resultData.containsKey(Provider.NAME)) {
- String provider_id = resultData.getString(Provider.NAME);
- mSelectedProvider = getProvider(provider_id);
- provider_list_fragment.addItem(mSelectedProvider);
- ProviderListContent.removeItem(mSelectedProvider);
-
- if(mSelectedProvider.custom)
- refreshProviderList(0);
-
- if(!mProgressBar.isShown()) {
- int provider_index = getProviderIndex(provider_id);
- startProgressBar(provider_index);
- provider_list_fragment = (ProviderListFragment) getFragmentManager().findFragmentByTag(ProviderListFragment.TAG);
- provider_list_fragment.hide(provider_index-2);
- //setProviderList(provider_list_fragment);
- }
+ if (ConfigHelper.getBoolFromSharedPref(EIP.ALLOWED_ANON)){
+ mConfigState.putExtra(SERVICES_RETRIEVED, true);
+ downloadAnonCert();
+ } else {
mProgressBar.incrementProgressBy(1);
- }
-
- downloadJSONFiles(mSelectedProvider);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE);
- refreshProviderList(0);
- //Toast.makeText(this, getResources().getString(R.string.config_error_parsing), Toast.LENGTH_LONG);
- setResult(RESULT_CANCELED, mConfigState);
- }
- }
- else if(resultCode == ProviderAPI.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON) {
- String reason_to_fail = resultData.getString(ProviderAPI.ERRORS);
- showDownloadFailedDialog(getCurrentFocus(), reason_to_fail);
- refreshProviderList(0);
- mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE);
- setResult(RESULT_CANCELED, mConfigState);
- }
- else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_JSON_FILES) {
- mProgressBar.incrementProgressBy(1);
- if (ConfigHelper.getBoolFromSharedPref(EIP.ALLOWED_ANON)){
- mConfigState.putExtra(SERVICES_RETRIEVED, true);
- downloadAnonCert();
- } else {
- mProgressBar.incrementProgressBy(1);
- mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE);
- refreshProviderList(0);
- //Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_LONG).show();
- setResult(RESULT_OK);
- showProviderDetails(getCurrentFocus());
- }
- }
- else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_JSON_FILES) {
- //Toast.makeText(getApplicationContext(), R.string.incorrectly_downloaded_json_files_message, Toast.LENGTH_LONG).show();
+ mProgressBar.setVisibility(ProgressBar.GONE);
+ progressbar_description.setVisibility(TextView.GONE);
+ setResult(RESULT_OK);
+ showProviderDetails(getCurrentFocus());
+ } + } else if(resultCode == ProviderAPI.PROVIDER_NOK) {
+ //refreshProviderList(0); String reason_to_fail = resultData.getString(ProviderAPI.ERRORS);
showDownloadFailedDialog(getCurrentFocus(), reason_to_fail);
- refreshProviderList(0);
- //Toast.makeText(getApplicationContext(), R.string.incorrectly_downloaded_json_files_message,
mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE);
+ progressbar_description.setVisibility(TextView.GONE);
+ ConfigHelper.removeFromSharedPref(Provider.KEY); setResult(RESULT_CANCELED, mConfigState);
}
else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
@@ -231,11 +186,12 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn @Override
public void onItemSelected(String id) {
//TODO Code 2 pane view
+ // resetOldConnection();
ProviderItem selected_provider = getProvider(id);
int provider_index = getProviderIndex(id);
startProgressBar(provider_index);
- mSelectedProvider = selected_provider;
- saveProviderJson(mSelectedProvider);
+ provider_list_fragment.hideAllBut(provider_index); + setUpProvider(selected_provider.providerMainUrl(), true); }
@Override
@@ -258,16 +214,27 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn setResult(RESULT_CANCELED, ask_quit);
}
- private ProviderItem getProvider(String id) {
+ private ProviderItem getProvider(String name) {
Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
while(providers_iterator.hasNext()) {
ProviderItem provider = providers_iterator.next();
- if(provider.id.equalsIgnoreCase(id)) {
+ if(provider.name().equalsIgnoreCase(name)) {
return provider;
}
}
return null;
}
+
+ private String getId(String provider_main_url) {
+ Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
+ while(providers_iterator.hasNext()) {
+ ProviderItem provider = providers_iterator.next();
+ if(provider.providerMainUrl().equalsIgnoreCase(provider_main_url)) {
+ return provider.name();
+ }
+ }
+ return "";
+ }
private void startProgressBar(int list_item_index) {
mProgressBar.setVisibility(ProgressBar.VISIBLE);
@@ -284,10 +251,10 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
while(providers_iterator.hasNext()) {
ProviderItem provider = providers_iterator.next();
- index++;
- if(provider.id.equalsIgnoreCase(id)) {
+ if(provider.name().equalsIgnoreCase(id)) {
break;
}
+ index++;
}
return index;
}
@@ -330,7 +297,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn boolean custom = false;
provider_name = url_filepath.subSequence(0, url_filepath.indexOf(".")).toString();
if(ProviderListContent.ITEMS.isEmpty()) //TODO I have to implement a way of checking if a provider new or is already present in that ITEMS list
- ProviderListContent.addItem(new ProviderItem(provider_name, asset_manager.open(url_files_folder + "/" + url_filepath), custom, false));
+ ProviderListContent.addItem(new ProviderItem(provider_name, asset_manager.open(url_files_folder + "/" + url_filepath))); loaded_preseeded_providers = true;
}
} catch (IOException e) {
@@ -339,59 +306,6 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn return loaded_preseeded_providers;
}
-
- /**
- * Saves provider.json file associated with provider.
- *
- * If the provider is custom, the file has already been downloaded so we load it from memory.
- * If not, the file is updated using the provider's URL.
- * @param provider
- */
- private void saveProviderJson(ProviderItem provider) {
- JSONObject provider_json = new JSONObject();
- try {
- if(!provider.custom) {
- updateProviderDotJson(provider.name, provider.provider_json_url, provider.danger_on);
- } else {
- // FIXME!! We should we be updating our seeded providers list at ConfigurationWizard onStart() ?
- // I think yes, but if so, where does this list live? leap.se, as it's the non-profit project for the software?
- // If not, we should just be getting names/urls, and fetching the provider.json like in custom entries
- provider_json = provider.provider_json;
- ConfigHelper.saveSharedPref(Provider.KEY, provider_json);
- ConfigHelper.saveSharedPref(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON));
- ConfigHelper.saveSharedPref(ProviderItem.DANGER_ON, provider.danger_on);
-
- mProgressBar.incrementProgressBy(1);
- downloadJSONFiles(mSelectedProvider);
- }
- } catch (JSONException e) {
- setResult(RESULT_CANCELED);
- finish();
- }
- }
-
- /**
- * Asks ProviderAPI to download provider site's certificate and eip-service.json
- *
- * URLs are fetched from the provider parameter
- * @param provider from which certificate and eip-service.json files are going to be downloaded
- */
- private void downloadJSONFiles(ProviderItem provider) {
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle parameters = new Bundle();
-
- parameters.putString(Provider.KEY, provider.name);
- parameters.putString(Provider.CA_CERT, provider.cert_json_url);
- parameters.putString(EIP.KEY, provider.eip_service_json_url);
- parameters.putBoolean(ProviderItem.DANGER_ON, provider.danger_on);
-
- provider_API_command.setAction(ProviderAPI.DOWNLOAD_JSON_FILES_BUNDLE_EXTRA);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
-
- startService(provider_API_command);
- }
/**
* Asks ProviderAPI to download an anonymous (anon) VPN certificate.
@@ -462,42 +376,40 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn newFragment.show(fragment_transaction, ProviderDetailFragment.TAG);
}
- @Override
- public void saveAndSelectProvider(String provider_main_url, boolean danger_on) {
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle parameters = new Bundle();
- parameters.putString(Provider.MAIN_URL, provider_main_url);
- parameters.putBoolean(ProviderItem.DANGER_ON, danger_on);
-
- provider_API_command.setAction(ProviderAPI.DOWNLOAD_NEW_PROVIDER_DOTJSON);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
-
- startService(provider_API_command);
+ public void showAndSelectProvider(String provider_main_url, boolean danger_on) {
+ showProvider(provider_main_url, danger_on);
+ autoSelectProvider(provider_main_url, danger_on);
+ }
+
+ private void showProvider(final String provider_main_url, final boolean danger_on) {
+ String provider_name = provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("\\/", "_");
+ ProviderItem added_provider = new ProviderItem(provider_name, provider_main_url);
+ provider_list_fragment.addItem(added_provider);
+ }
+
+ private void autoSelectProvider(String provider_main_url, boolean danger_on) {
+ onItemSelected(getId(provider_main_url));
}
/**
* Asks ProviderAPI to download a new provider.json file
* @param provider_name
- * @param provider_json_url
+ * @param provider_main_url
* @param danger_on tells if HTTPS client should bypass certificate errors
*/
- public void updateProviderDotJson(String provider_name, String provider_json_url, boolean danger_on) {
+ public void setUpProvider(String provider_main_url, boolean danger_on) {
Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
Bundle parameters = new Bundle();
- parameters.putString(Provider.NAME, provider_name);
- parameters.putString(Provider.DOT_JSON_URL, provider_json_url);
+ parameters.putString(Provider.MAIN_URL, provider_main_url);
parameters.putBoolean(ProviderItem.DANGER_ON, danger_on);
- provider_API_command.setAction(ProviderAPI.UPDATE_PROVIDER_DOTJSON);
+ provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
-
+
startService(provider_API_command);
}
-
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu);
@@ -534,7 +446,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn fragment_transaction.replace(R.id.configuration_wizard_layout, newFragment, AboutFragment.TAG).commit();
}
}
-
+
public void showAllProviders() {
provider_list_fragment = (ProviderListFragment) getFragmentManager().findFragmentByTag(ProviderListFragment.TAG);
if(provider_list_fragment != null)
@@ -554,4 +466,13 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn setResult(RESULT_OK);
finish();
}
+
+ public class ProviderAPIBroadcastReceiver_Update extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int update = intent.getIntExtra(ProviderAPI.CURRENT_PROGRESS, 0);
+ mProgressBar.setProgress(update);
+ }
+ }
}
diff --git a/src/se/leap/bitmaskclient/Dashboard.java b/src/se/leap/bitmaskclient/Dashboard.java index ca619e9f..7f898a67 100644 --- a/src/se/leap/bitmaskclient/Dashboard.java +++ b/src/se/leap/bitmaskclient/Dashboard.java @@ -16,8 +16,6 @@ */ package se.leap.bitmaskclient; -import org.apache.http.cookie.Cookie; -import org.apache.http.impl.cookie.BasicClientCookie; import org.json.JSONException; import org.json.JSONObject; @@ -30,25 +28,19 @@ import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; -import android.app.ProgressDialog; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.os.ResultReceiver; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.view.ViewStub; -import android.widget.CompoundButton; import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; @@ -63,15 +55,18 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf protected static final int CONFIGURE_LEAP = 0; protected static final int SWITCH_PROVIDER = 1; + private static final String TAG_EIP_FRAGMENT = "EIP_DASHBOARD_FRAGMENT"; final public static String SHARED_PREFERENCES = "LEAPPreferences"; final public static String ACTION_QUIT = "quit"; public static final String REQUEST_CODE = "request_code"; + + + private ProgressBar mProgressBar; private TextView eipStatus; - private ProviderAPIBroadcastReceiver_Update providerAPI_broadcast_receiver_update; private static Context app; private static SharedPreferences preferences; private static Provider provider; @@ -89,17 +84,15 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf app = this; PRNGFixes.apply(); - //mProgressBar = (ProgressBar) findViewById(R.id.progressbar_dashboard); + // mProgressBar = (ProgressBar) findViewById(R.id.progressbar_dashboard); + // mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); + // eipStatus = (TextView) findViewById(R.id.eipStatus); - - providerAPI_broadcast_receiver_update = new ProviderAPIBroadcastReceiver_Update(); - IntentFilter update_intent_filter = new IntentFilter(ProviderAPI.UPDATE_ACTION); - update_intent_filter.addCategory(Intent.CATEGORY_DEFAULT); - registerReceiver(providerAPI_broadcast_receiver_update, update_intent_filter); + mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); ConfigHelper.setSharedPreferences(getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE)); preferences = ConfigHelper.shared_preferences; - + authed_eip = ConfigHelper.getBoolFromSharedPref(EIP.AUTHED_EIP); if (ConfigHelper.getStringFromSharedPref(Provider.KEY).isEmpty()) startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); @@ -110,16 +103,18 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf @Override protected void onDestroy() { super.onDestroy(); - unregisterReceiver(providerAPI_broadcast_receiver_update); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) { - if ( resultCode == RESULT_OK ){ + // It should be equivalent: if ( (requestCode == CONFIGURE_LEAP) || (data!= null && data.hasExtra(STOP_FIRST))) { + if ( resultCode == RESULT_OK ){ + ConfigHelper.saveSharedPref(EIP.PARSED_SERIAL, 0); ConfigHelper.saveSharedPref(EIP.AUTHED_EIP, authed_eip); startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) ); buildDashboard(); + if(data != null && data.hasExtra(LogInDialog.VERB)) { View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0); logInDialog(view, Bundle.EMPTY); @@ -130,7 +125,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf configErrorDialog(); } } - + /** * Dialog shown when encountering a configuration error. Such errors require * reconfiguring LEAP or aborting the application. @@ -167,11 +162,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf provider.init( this ); setContentView(R.layout.client_dashboard); - - providerAPI_broadcast_receiver_update = new ProviderAPIBroadcastReceiver_Update(); - IntentFilter update_intent_filter = new IntentFilter(ProviderAPI.UPDATE_ACTION); - update_intent_filter.addCategory(Intent.CATEGORY_DEFAULT); - registerReceiver(providerAPI_broadcast_receiver_update, update_intent_filter); providerNameTV = (TextView) findViewById(R.id.providerName); providerNameTV.setText(provider.getDomain()); @@ -228,6 +218,13 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startActivity(intent); return true; case R.id.switch_provider: + if (Provider.getInstance().hasEIP()){ + if (ConfigHelper.getBoolFromSharedPref(EIP.AUTHED_EIP)){ + logOut(); + } + eipStop(); + } + ConfigHelper.removeFromSharedPref(Provider.KEY); startActivityForResult(new Intent(this,ConfigurationWizard.class), SWITCH_PROVIDER); return true; case R.id.login_button: @@ -299,14 +296,13 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - //if(mProgressDialog != null) mProgressDialog.dismiss(); - //mProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.logout_title), getResources().getString(R.string.logout_message), true); if(mProgressBar == null) mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); mProgressBar.setVisibility(ProgressBar.VISIBLE); if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus); eipStatus.setText("Starting to logout"); - //mProgressBar.setMax(1); startService(provider_API_command); + //mProgressBar.setMax(1); + } /** @@ -456,13 +452,17 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf eip_intent.putExtra(EIP.RECEIVER_TAG, eip_receiver); startService(eip_intent); } + + /** + * Send a command to EIP + * + */ + private void eipStop(){ + // 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_STOP_EIP); + // eip_intent.putExtra(EIP.RECEIVER_TAG, eip_receiver); + startService(eip_intent); - public class ProviderAPIBroadcastReceiver_Update extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - int update = intent.getIntExtra(ProviderAPI.UPDATE_DATA, 0); - //mProgressBar.setProgress(update); - } } } diff --git a/src/se/leap/bitmaskclient/EIP.java b/src/se/leap/bitmaskclient/EIP.java index 22f7558d..ec2f6972 100644 --- a/src/se/leap/bitmaskclient/EIP.java +++ b/src/se/leap/bitmaskclient/EIP.java @@ -214,8 +214,7 @@ public final class EIP extends IntentService { * Intent to {@link se.leap.openvpn.LaunchVPN} */ private void startEIP() { - if (activeGateway==null) - activeGateway = selectGateway(); + activeGateway = selectGateway(); Intent intent = new Intent(this,LaunchVPN.class); intent.setAction(Intent.ACTION_MAIN); @@ -252,10 +251,19 @@ public final class EIP extends IntentService { private void updateEIPService() { try { eipDefinition = ConfigHelper.getJsonFromSharedPref(EIP.KEY); + parsedEipSerial = ConfigHelper.getIntFromSharedPref(PARSED_SERIAL); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } + if(parsedEipSerial == 0) { + // Delete all vpn profiles + ProfileManager vpl = ProfileManager.getInstance(context); + Collection<VpnProfile> profiles = vpl.getProfiles(); + for (VpnProfile profile : profiles){ + vpl.removeProfile(context, profile); + } + } if (eipDefinition.optInt("serial") > parsedEipSerial) updateGateways(); } diff --git a/src/se/leap/bitmaskclient/EipServiceFragment.java b/src/se/leap/bitmaskclient/EipServiceFragment.java index 4d778b1a..e182b3fd 100644 --- a/src/se/leap/bitmaskclient/EipServiceFragment.java +++ b/src/se/leap/bitmaskclient/EipServiceFragment.java @@ -12,6 +12,7 @@ import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.ResultReceiver; +import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -38,6 +39,9 @@ public class EipServiceFragment extends Fragment implements StateListener, OnCli private EIPReceiver mEIPReceiver; + + public static String TAG = "se.leap.bitmask.EipServiceFragment"; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -57,6 +61,8 @@ public class EipServiceFragment extends Fragment implements StateListener, OnCli eipStatus.setOnClickListener(this); eipSwitch = (Switch) eipFragment.findViewById(R.id.eipSwitch); + + eipSwitch.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { @@ -66,6 +72,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnCli }); eipSwitch.setOnCheckedChangeListener(this); + return eipFragment; } @@ -152,6 +159,8 @@ public class EipServiceFragment extends Fragment implements StateListener, OnCli eipAutoSwitched = true; } + + /** * Send a command to EIP * @@ -186,15 +195,14 @@ public class EipServiceFragment extends Fragment implements StateListener, OnCli statusMessage = getString(R.string.eip_state_connected); getActivity().findViewById(R.id.eipProgress).setVisibility(View.GONE); mEipStartPending = false; - } else if ( (state.equals("NOPROCESS") && !mEipStartPending ) || state.equals("EXITING")) { + } else if ( (state.equals("NOPROCESS") && !mEipStartPending ) || state.equals("EXITING") || state.equals("FATAL")) { statusMessage = getString(R.string.eip_state_not_connected); getActivity().findViewById(R.id.eipProgress).setVisibility(View.GONE); mEipStartPending = false; switchState = false; } else if (state.equals("NOPROCESS")){ statusMessage = logmessage; - } - else { + } else { statusMessage = prefix + " " + logmessage; } @@ -207,6 +215,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnCli }); } + /** * Inner class for handling messages related to EIP status and control requests * diff --git a/src/se/leap/bitmaskclient/NewProviderDialog.java b/src/se/leap/bitmaskclient/NewProviderDialog.java index a0b8a763..98686bd2 100644 --- a/src/se/leap/bitmaskclient/NewProviderDialog.java +++ b/src/se/leap/bitmaskclient/NewProviderDialog.java @@ -41,7 +41,7 @@ public class NewProviderDialog extends DialogFragment { final public static String TAG = "newProviderDialog"; public interface NewProviderDialogInterface { - public void saveAndSelectProvider(String url_provider, boolean danger_on); + public void showAndSelectProvider(String url_provider, boolean danger_on); } NewProviderDialogInterface interface_with_ConfigurationWizard; @@ -85,7 +85,7 @@ public class NewProviderDialog extends DialogFragment { } boolean danger_on = danger_checkbox.isChecked(); if(validURL(entered_url)) { - interface_with_ConfigurationWizard.saveAndSelectProvider(entered_url, danger_on); + interface_with_ConfigurationWizard.showAndSelectProvider(entered_url, danger_on); Toast.makeText(getActivity().getApplicationContext(), R.string.valid_url_entered, Toast.LENGTH_LONG).show(); } else { url_input_field.setText(""); diff --git a/src/se/leap/bitmaskclient/Provider.java b/src/se/leap/bitmaskclient/Provider.java index e462829f..598999fd 100644 --- a/src/se/leap/bitmaskclient/Provider.java +++ b/src/se/leap/bitmaskclient/Provider.java @@ -99,7 +99,7 @@ public final class Provider implements Serializable { preferences = activity.getSharedPreferences(Dashboard.SHARED_PREFERENCES,Context.MODE_PRIVATE); // Inflate our provider.json data try { - definition = new JSONObject( preferences.getString("provider", "") ); + definition = new JSONObject( preferences.getString(Provider.KEY, "") ); } catch (JSONException e) { // TODO: handle exception @@ -166,6 +166,8 @@ public final class Provider implements Serializable { // Walk the EIP types array looking for matches in provider's service definitions if ( Arrays.asList(API_EIP_TYPES).contains( services.getString(i) ) ) return true; + } catch (NullPointerException e){ + e.printStackTrace(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/src/se/leap/bitmaskclient/ProviderAPI.java b/src/se/leap/bitmaskclient/ProviderAPI.java index a553851b..2a1cd29b 100644 --- a/src/se/leap/bitmaskclient/ProviderAPI.java +++ b/src/se/leap/bitmaskclient/ProviderAPI.java @@ -36,6 +36,7 @@ import java.security.KeyStore; import java.security.KeyStoreException; 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.security.interfaces.RSAPrivateKey; @@ -68,7 +69,6 @@ import android.os.Handler; import android.os.ResultReceiver; import android.util.Base64; import android.util.Log; -import android.widget.ProgressBar; import android.widget.Toast; /** @@ -85,8 +85,7 @@ public class ProviderAPI extends IntentService { private Handler mHandler; final public static String - DOWNLOAD_JSON_FILES_BUNDLE_EXTRA = "downloadJSONFiles", - UPDATE_PROVIDER_DOTJSON = "updateProviderDotJSON", + SET_UP_PROVIDER = "setUpProvider", DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON", SRP_REGISTER = "srpRegister", SRP_AUTH = "srpAuth", @@ -98,14 +97,13 @@ public class ProviderAPI extends IntentService { SESSION_ID_COOKIE_KEY = "session_id_cookie_key", SESSION_ID_KEY = "session_id", ERRORS = "errors", - UPDATE_ACTION = "update_action", - UPDATE_DATA = "update data" + UPDATE_PROGRESSBAR = "update_action", + CURRENT_PROGRESS = "update data", + TAG = "provider_api_tag" ; final public static int CUSTOM_PROVIDER_ADDED = 0, - CORRECTLY_DOWNLOADED_JSON_FILES = 1, - INCORRECTLY_DOWNLOADED_JSON_FILES = 2, SRP_AUTHENTICATION_SUCCESSFUL = 3, SRP_AUTHENTICATION_FAILED = 4, SRP_REGISTRATION_SUCCESSFUL = 5, @@ -114,8 +112,8 @@ public class ProviderAPI extends IntentService { LOGOUT_FAILED = 8, CORRECTLY_DOWNLOADED_CERTIFICATE = 9, INCORRECTLY_DOWNLOADED_CERTIFICATE = 10, - CORRECTLY_UPDATED_PROVIDER_DOT_JSON = 11, - INCORRECTLY_UPDATED_PROVIDER_DOT_JSON = 12, + PROVIDER_OK = 11, + PROVIDER_NOK = 12, CORRECTLY_DOWNLOADED_ANON_CERTIFICATE = 13, INCORRECTLY_DOWNLOADED_ANON_CERTIFICATE = 14 ; @@ -142,26 +140,12 @@ public class ProviderAPI extends IntentService { String action = command.getAction(); Bundle parameters = command.getBundleExtra(PARAMETERS); - if(action.equalsIgnoreCase(DOWNLOAD_JSON_FILES_BUNDLE_EXTRA)) { - Bundle result = downloadJsonFiles(parameters); + if(action.equalsIgnoreCase(SET_UP_PROVIDER)) { + Bundle result = setUpProvider(parameters); if(result.getBoolean(RESULT_KEY)) { - receiver.send(CORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY); - } else { - receiver.send(INCORRECTLY_DOWNLOADED_JSON_FILES, result); - } - } else if(action.equalsIgnoreCase(UPDATE_PROVIDER_DOTJSON)) { - Bundle result = updateProviderDotJSON(parameters); - if(result.getBoolean(RESULT_KEY)) { - receiver.send(CORRECTLY_UPDATED_PROVIDER_DOT_JSON, result); + receiver.send(PROVIDER_OK, result); } else { - receiver.send(INCORRECTLY_UPDATED_PROVIDER_DOT_JSON, Bundle.EMPTY); - } - } else if (action.equalsIgnoreCase(DOWNLOAD_NEW_PROVIDER_DOTJSON)) { - Bundle result = downloadNewProviderDotJSON(parameters); - if(result.getBoolean(RESULT_KEY)) { - receiver.send(CORRECTLY_UPDATED_PROVIDER_DOT_JSON, result); - } else { - receiver.send(INCORRECTLY_DOWNLOADED_JSON_FILES, result); + receiver.send(PROVIDER_NOK, Bundle.EMPTY); } } else if (action.equalsIgnoreCase(SRP_AUTH)) { Bundle session_id_bundle = authenticateBySRP(parameters); @@ -184,60 +168,6 @@ public class ProviderAPI extends IntentService { } } } - - /** - * Downloads the main cert and the eip-service.json files given through the task parameter - * @param task - * @return true if eip-service.json was parsed as a JSON object correctly. - */ - private Bundle downloadJsonFiles(Bundle task) { - Bundle result = new Bundle(); - String cert_url = task.getString(Provider.CA_CERT); - String eip_service_json_url = task.getString(EIP.KEY); - boolean danger_on = task.getBoolean(ProviderItem.DANGER_ON); - try { - String cert_string = downloadWithCommercialCA(cert_url, danger_on); - - if(ConfigHelper.checkErroneousDownload(cert_string)) { - JSONObject possible_errors = new JSONObject(cert_string); - String reason_to_fail = ""; - if(cert_string.isEmpty()) - reason_to_fail = "Empty certificate downloaded"; - else - reason_to_fail = possible_errors.getString(ERRORS); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } else { - X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(cert_string); - cert_string = Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT); - ConfigHelper.saveSharedPref(Provider.CA_CERT, "-----BEGIN CERTIFICATE-----\n"+cert_string+"-----END CERTIFICATE-----"); - } - } catch (JSONException e) { - e.printStackTrace(); - result.putBoolean(RESULT_KEY, false); - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - result.putBoolean(RESULT_KEY, false); - } - - try { - String eip_service_string = downloadWithCommercialCA(eip_service_json_url, danger_on); - JSONObject eip_service_json = new JSONObject(eip_service_string); - if(eip_service_json.has(ERRORS)) { - String reason_to_fail = eip_service_json.getString(ERRORS); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } - else ConfigHelper.saveSharedPref(EIP.KEY, eip_service_json); - - result.putBoolean(RESULT_KEY, true); - } catch (JSONException e) { - result.putBoolean(RESULT_KEY, false); - } - - return result; - } /** * Starts the authentication process using SRP protocol. @@ -336,9 +266,9 @@ public class ProviderAPI extends IntentService { */ private void broadcast_progress(int progress) { Intent intentUpdate = new Intent(); - intentUpdate.setAction(UPDATE_ACTION); + intentUpdate.setAction(UPDATE_PROGRESSBAR); intentUpdate.addCategory(Intent.CATEGORY_DEFAULT); - intentUpdate.putExtra(UPDATE_DATA, progress); + intentUpdate.putExtra(CURRENT_PROGRESS, progress); sendBroadcast(intentUpdate); } @@ -489,85 +419,85 @@ public class ProviderAPI extends IntentService { * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider, the provider name and its provider.json url. * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if the update was successful. */ - private Bundle updateProviderDotJSON(Bundle task) { + private Bundle setUpProvider(Bundle task) { Bundle result = new Bundle(); - boolean custom = task.getBoolean(ProviderItem.CUSTOM); + int progress = 0; boolean danger_on = task.getBoolean(ProviderItem.DANGER_ON); - String provider_json_url = task.getString(Provider.DOT_JSON_URL); - String provider_name = task.getString(Provider.NAME); + String provider_main_url = task.getString(Provider.MAIN_URL); + if(downloadCACert(provider_main_url, danger_on)) { + broadcast_progress(progress++); + result.putBoolean(RESULT_KEY, true); + if(getAndSetProviderJson(provider_main_url)) { + broadcast_progress(progress++); + if(getAndSetEipServiceJson()) + broadcast_progress(progress++); + } + } + return result; + } + + private boolean downloadCACert(String provider_main_url, boolean danger_on) { + String cert_string = downloadWithCommercialCA(provider_main_url + "/ca.crt", danger_on); + if(validCertificate(cert_string)) + ConfigHelper.saveSharedPref(Provider.CA_CERT, cert_string); + else + return false; - try { - String provider_dot_json_string = downloadWithCommercialCA(provider_json_url, danger_on); - if(provider_dot_json_string.isEmpty()) { - result.putBoolean(RESULT_KEY, false); - } else { - JSONObject provider_json = new JSONObject(provider_dot_json_string); - if(provider_json.has(ERRORS)) { - String reason_to_fail = provider_json.getString(ERRORS); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } else { - ConfigHelper.saveSharedPref(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON)); - - //ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, provider_json, custom, danger_on)); - result.putBoolean(RESULT_KEY, true); - result.putString(Provider.KEY, provider_json.toString()); - result.putBoolean(ProviderItem.DANGER_ON, danger_on); - } + return true; + } + + private boolean validCertificate(String cert_string) { + boolean result = false; + if(!ConfigHelper.checkErroneousDownload(cert_string)) { + X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(cert_string); + try { + Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT); + result = true; + } catch (CertificateEncodingException e) { + Log.d(TAG, e.getLocalizedMessage()); } - } catch (JSONException e) { - result.putBoolean(RESULT_KEY, false); } return result; } + + private boolean getAndSetProviderJson(String provider_main_url) { + boolean result = false; - /** - * Downloads a custom provider provider.json file - * @param task containing a boolean meaning if the user completely trusts this provider, and the provider main url entered in the new custom provider dialog. - * @return true if provider.json file was successfully parsed as a JSON object. - */ - private Bundle downloadNewProviderDotJSON(Bundle task) { - Bundle result = new Bundle(); - boolean custom = true; - boolean danger_on = task.getBoolean(ProviderItem.DANGER_ON); - - String provider_main_url = (String) task.get(Provider.MAIN_URL); - String provider_name = provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("\\/", "_"); - String provider_json_url = guessProviderDotJsonURL(provider_main_url); - - String provider_json_string = downloadWithCommercialCA(provider_json_url, danger_on); - try { - if(provider_json_string.isEmpty()) { - result.putBoolean(RESULT_KEY, false); - } else { - JSONObject provider_json = new JSONObject(provider_json_string); + String provider_dot_json_string = downloadWithProviderCA(provider_main_url + "/provider.json", true); - if(provider_json.has(ERRORS)) { - String reason_to_fail = provider_json.getString(ERRORS); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } else { - ConfigHelper.saveSharedPref(Provider.KEY, provider_json); - ConfigHelper.saveSharedPref(ProviderItem.DANGER_ON, danger_on); - ConfigHelper.saveSharedPref(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON)); - ProviderItem added_provider = new ProviderItem(provider_name, provider_json_url, provider_json, custom, danger_on); - ProviderListContent.addItem(added_provider); - - result.putString(Provider.NAME, added_provider.getName()); - result.putBoolean(RESULT_KEY, true); - result.putString(Provider.KEY, provider_json.toString()); - result.putBoolean(ProviderItem.DANGER_ON, danger_on); - } - } + try { + JSONObject provider_json = new JSONObject(provider_dot_json_string); + String name = provider_json.getString(Provider.NAME); + //TODO setProviderName(name); + + ConfigHelper.saveSharedPref(Provider.KEY, provider_json); + ConfigHelper.saveSharedPref(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON)); + ProviderItem added_provider = new ProviderItem(name, provider_main_url); + + result = true; } catch (JSONException e) { - result.putBoolean(RESULT_KEY, false); - result.putString(ERRORS, "Corrupt download"); } - return result; } + + private boolean getAndSetEipServiceJson() { + boolean result = false; + + try { + JSONObject provider_json = ConfigHelper.getJsonFromSharedPref(Provider.KEY); + String eip_service_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH; + String eip_service_json_string = downloadWithProviderCA(eip_service_url, true); + JSONObject eip_service_json = new JSONObject(eip_service_json_string); + eip_service_json.getInt(Provider.API_RETURN_SERIAL); + + ConfigHelper.saveSharedPref(EIP.KEY, eip_service_json); + result = true; + } catch (JSONException e) { + } + return result; + } /** * Tries to download the contents of the provided url using commercially validated CA certificate from chosen provider. * @@ -593,13 +523,13 @@ public class ProviderAPI extends IntentService { json_file_content = formatErrorMessage(R.string.server_is_down_message); } catch (IOException e) { if(provider_url != null) { - json_file_content = downloadWithProviderCA(provider_url, danger_on); + json_file_content = downloadWithProviderCA(string_url, danger_on); } else { json_file_content = formatErrorMessage(R.string.certificate_error); } } catch (Exception e) { if(provider_url != null && danger_on) { - json_file_content = downloadWithProviderCA(provider_url, danger_on); + json_file_content = downloadWithProviderCA(string_url, danger_on); } } @@ -607,15 +537,16 @@ public class ProviderAPI extends IntentService { } /** - * Tries to download the contents of the provided url using not commercially validated CA certificate from chosen provider. - * @param url + * Tries to download the contents of the provided url using not commercially validated CA certificate from chosen provider. + * @param url as a string * @param danger_on true to download CA certificate in case it has not been downloaded. * @return an empty string if it fails, the url content if not. */ - private String downloadWithProviderCA(URL url, boolean danger_on) { + private String downloadWithProviderCA(String url_string, boolean danger_on) { String json_file_content = ""; try { + URL url = new URL(url_string); // Tell the URLConnection to use a SocketFactory from our SSLContext HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection(); @@ -629,7 +560,7 @@ public class ProviderAPI extends IntentService { } catch (IOException e) { // The downloaded certificate doesn't validate our https connection. if(danger_on) { - json_file_content = downloadWithoutCA(url); + json_file_content = downloadWithoutCA(url_string); } else { json_file_content = formatErrorMessage(R.string.certificate_error); } @@ -672,7 +603,7 @@ public class ProviderAPI extends IntentService { /** * Downloads the string that's in the url with any certificate. */ - private String downloadWithoutCA(URL url) { + private String downloadWithoutCA(String url_string) { String string = ""; try { @@ -700,6 +631,7 @@ public class ProviderAPI extends IntentService { SSLContext context = SSLContext.getInstance("TLS"); context.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom()); + URL url = new URL(url_string); HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection(); urlConnection.setSSLSocketFactory(context.getSocketFactory()); urlConnection.setHostnameVerifier(hostnameVerifier); @@ -721,15 +653,6 @@ public class ProviderAPI extends IntentService { } return string; } - - /** - * Tries to guess the provider.json url given the main provider url. - * @param provider_main_url - * @return the guessed provider.json url - */ - private String guessProviderDotJsonURL(String provider_main_url) { - return provider_main_url + "/provider.json"; - } /** * Logs out from the api url retrieved from the task. @@ -791,7 +714,7 @@ public class ProviderAPI extends IntentService { String new_cert_string_url = provider_main_url.toString() + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.CERTIFICATE; boolean danger_on = ConfigHelper.getBoolFromSharedPref(ProviderItem.DANGER_ON); - String cert_string = downloadWithCommercialCA(new_cert_string_url, danger_on); + String cert_string = downloadWithProviderCA(new_cert_string_url, true); if(!cert_string.isEmpty()) { if(ConfigHelper.checkErroneousDownload(cert_string)) { String reason_to_fail = provider_json.getString(ERRORS); diff --git a/src/se/leap/bitmaskclient/ProviderListAdapter.java b/src/se/leap/bitmaskclient/ProviderListAdapter.java index 19c4f72c..4abf15a2 100644 --- a/src/se/leap/bitmaskclient/ProviderListAdapter.java +++ b/src/se/leap/bitmaskclient/ProviderListAdapter.java @@ -10,7 +10,6 @@ import android.widget.ArrayAdapter; import android.widget.TwoLineListItem; public class ProviderListAdapter<T> extends ArrayAdapter<T> { - private T[] items = null; private static boolean[] hidden = null; public void hide(int position) { @@ -42,7 +41,7 @@ public class ProviderListAdapter<T> extends ArrayAdapter<T> { } private int getHiddenCount() { int count = 0; - for(int i=0;i<items.length;i++) + for(int i=0;i<hidden.length;i++) if(hidden[i]) count++; return count; @@ -58,25 +57,23 @@ public class ProviderListAdapter<T> extends ArrayAdapter<T> { @Override public int getCount() { - return (items.length - getHiddenCount()); + return (hidden.length - getHiddenCount()); } public ProviderListAdapter(Context mContext, int layout, List<T> objects) { super(mContext, layout, objects); - items = objects.toArray((T[])new Object[0]); if(hidden == null) { - hidden = new boolean[items.length]; - for (int i = 0; i < items.length; i++) + hidden = new boolean[objects.size()]; + for (int i = 0; i < objects.size(); i++) hidden[i] = false; } } public ProviderListAdapter(Context mContext, int layout, List<T> objects, boolean show_all_providers) { super(mContext, layout, objects); - items = objects.toArray((T[])new Object[0]); if(show_all_providers) { - hidden = new boolean[items.length]; - for (int i = 0; i < items.length; i++) + hidden = new boolean[objects.size()]; + for (int i = 0; i < objects.size(); i++) hidden[i] = false; } } @@ -101,8 +98,8 @@ public class ProviderListAdapter<T> extends ArrayAdapter<T> { row = (TwoLineListItem)convertView; } ProviderListContent.ProviderItem data = ProviderListContent.ITEMS.get(position); - row.getText1().setText(data.domain); - row.getText2().setText(data.name); + row.getText1().setText(data.domain()); + row.getText2().setText(data.name()); return row; } diff --git a/src/se/leap/bitmaskclient/ProviderListContent.java b/src/se/leap/bitmaskclient/ProviderListContent.java index 75d91733..e1ca4f9a 100644 --- a/src/se/leap/bitmaskclient/ProviderListContent.java +++ b/src/se/leap/bitmaskclient/ProviderListContent.java @@ -55,23 +55,12 @@ public class ProviderListContent { /**
* A provider item.
- */
+ */ public static class ProviderItem {
-
-
final public static String CUSTOM = "custom";
final public static String DANGER_ON = "danger_on";
-
- public boolean custom = false;
- public String id;
- public String name;
- public String domain;
- public String provider_json_url;
- public JSONObject provider_json;
- public String provider_json_filename;
- public String eip_service_json_url;
- public String cert_json_url;
- public boolean danger_on = false;
+ private String provider_main_url;
+ private String name; /**
* @param name of the provider
@@ -79,25 +68,15 @@ public class ProviderListContent { * @param custom if it's a new provider entered by the user or not
* @param danger_on if the user trusts completely the new provider
*/
- public ProviderItem(String name, InputStream urls_file_input_stream, boolean custom, boolean danger_on) {
+ public ProviderItem(String name, InputStream urls_file_input_stream) {
try {
byte[] urls_file_bytes = new byte[urls_file_input_stream.available()];
urls_file_input_stream.read(urls_file_bytes);
String urls_file_content = new String(urls_file_bytes);
- JSONObject file_contents = new JSONObject(urls_file_content);
- id = name;
+ JSONObject file_contents = new JSONObject(urls_file_content); + provider_main_url = file_contents.getString(Provider.MAIN_URL);
this.name = name;
- provider_json_url = file_contents.getString(Provider.DOT_JSON_URL);
- domain = new URL(provider_json_url).getHost();
- //provider_json_filename = file_contents.getString("assets_json_provider");
- eip_service_json_url = file_contents.getString("json_eip_service");
- cert_json_url = file_contents.getString(EIP.CERTIFICATE);
- this.custom = custom;
- this.danger_on = danger_on;
- } catch (MalformedURLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -109,42 +88,25 @@ public class ProviderListContent { /**
* @param name of the provider
- * @param provider_json_url used to download provider.json file of the provider
+ * @param provider_main_url used to download provider.json file of the provider
* @param provider_json already downloaded
* @param custom if it's a new provider entered by the user or not
- * @param danger_on if the user trusts completely the new provider
- */
- public ProviderItem(String name, String provider_json_url, JSONObject provider_json, boolean custom, boolean danger_on) {
-
+ */ + public ProviderItem(String name, String provider_main_url) {
+ this.name = name;
+ this.provider_main_url = provider_main_url; + }
+
+ public String name() { return name; }
+
+ public String providerMainUrl() { return provider_main_url; }
+
+ public String domain() {
try {
- id = name;
- //this.name = name;
- this.provider_json_url = provider_json_url;
- this.provider_json = provider_json;
- this.name = provider_json.getJSONObject("name").getString("en");
- domain = new URL(provider_json_url).getHost();
- eip_service_json_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH;
- cert_json_url = provider_json.getString("ca_cert_uri");
- this.custom = custom;
- this.danger_on = danger_on;
- if(custom)
- provider_json_filename = name + "_provider.json".replaceFirst("__", "_");
+ return new URL(provider_main_url).getHost();
} catch (MalformedURLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ return provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("/.*", "");
}
}
-
- @Override
- public String toString() {
- return name;
- }
-
- public String getName() {
- return id;
- }
}
}
diff --git a/src/se/leap/bitmaskclient/ProviderListFragment.java b/src/se/leap/bitmaskclient/ProviderListFragment.java index 84d46a11..501da609 100644 --- a/src/se/leap/bitmaskclient/ProviderListFragment.java +++ b/src/se/leap/bitmaskclient/ProviderListFragment.java @@ -155,12 +155,7 @@ public class ProviderListFragment extends ListFragment { // Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
- mCallbacks.onItemSelected(ProviderListContent.ITEMS.get(position).id);
-
- for(int item_position = 0; item_position < listView.getCount(); item_position++) {
- if(item_position != position)
- content_adapter.hide(item_position);
- }
+ mCallbacks.onItemSelected(ProviderListContent.ITEMS.get(position).name());
}
@Override
@@ -172,6 +167,9 @@ public class ProviderListFragment extends ListFragment { }
}
+ public void notifyAdapter() {
+ content_adapter.notifyDataSetChanged();
+ }
/**
* Turns on activate-on-click mode. When this mode is on, list items will be
* given the 'activated' state when touched.
@@ -196,10 +194,19 @@ public class ProviderListFragment extends ListFragment { public void addItem(ProviderItem provider) {
content_adapter.add(provider);
+ content_adapter.notifyDataSetChanged();
}
- public void hide(int position) {
- content_adapter.hide(position);
+ public void hideAllBut(int position) {
+ int real_count = content_adapter.getCount();
+ for(int i = 0; i < real_count;)
+ if(i != position) {
+ content_adapter.hide(i);
+ position--;
+ real_count--;
+ } else {
+ i++;
+ }
}
public void unhideAll() {
diff --git a/src/se/leap/openvpn/OpenVPN.java b/src/se/leap/openvpn/OpenVPN.java index d7d17b4f..8acdc423 100644 --- a/src/se/leap/openvpn/OpenVPN.java +++ b/src/se/leap/openvpn/OpenVPN.java @@ -25,6 +25,7 @@ public class OpenVPN { private static String mLaststate; private static int mLastStateresid=R.string.state_noprocess; + public static String TAG="se.leap.openvpn.OpenVPN"; static { logbuffer = new LinkedList<LogItem>(); @@ -166,6 +167,8 @@ public class OpenVPN { return R.string.state_resolve; else if (state.equals("TCP_CONNECT")) return R.string.state_tcp_connect; + else if (state.equals("FATAL")) + return R.string.eip_state_not_connected; else return R.string.unknown_state; @@ -197,7 +200,7 @@ public class OpenVPN { } - public static void updateStateString (String state, String msg) { + public static void updateStateString (String state, String msg) { int rid = getLocalizedState(state); updateStateString(state, msg,rid); } diff --git a/src/se/leap/openvpn/OpenVPNThread.java b/src/se/leap/openvpn/OpenVPNThread.java index 0c383ab0..ffd21732 100644 --- a/src/se/leap/openvpn/OpenVPNThread.java +++ b/src/se/leap/openvpn/OpenVPNThread.java @@ -56,7 +56,7 @@ public class OpenVPNThread implements Runnable { if( exitvalue != 0)
OpenVPN.logError("Process exited with exit value " + exitvalue);
- OpenVPN.updateStateString("NOPROCESS","No process running.", R.string.state_noprocess);
+// OpenVPN.updateStateString("NOPROCESS","No process running.", R.string.state_noprocess); fixes bug #4565
if(mDumpPath!=null) {
try {
BufferedWriter logout = new BufferedWriter(new FileWriter(mDumpPath + ".log"));
diff --git a/src/se/leap/openvpn/OpenVpnManagementThread.java b/src/se/leap/openvpn/OpenVpnManagementThread.java index 78ce5a2b..27a3db65 100644 --- a/src/se/leap/openvpn/OpenVpnManagementThread.java +++ b/src/se/leap/openvpn/OpenVpnManagementThread.java @@ -19,7 +19,6 @@ import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException;
import se.leap.bitmaskclient.R;
-
import android.content.SharedPreferences;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
@@ -177,11 +176,12 @@ public class OpenVpnManagementThread implements Runnable { private void processCommand(String command) {
+ Log.d(TAG, "processCommand: " + command);
+
if (command.startsWith(">") && command.contains(":")) {
String[] parts = command.split(":",2);
String cmd = parts[0].substring(1);
String argument = parts[1];
-
if(cmd.equals("INFO")) {
// Ignore greeting from mgmt
//logStatusMessage(command);
@@ -195,6 +195,8 @@ public class OpenVpnManagementThread implements Runnable { processByteCount(argument);
} else if (cmd.equals("STATE")) {
processState(argument);
+ } else if (cmd.equals("FATAL")){
+ processState(","+cmd+","); //handles FATAL as state
} else if (cmd.equals("PROXY")) {
processProxyCMD(argument);
} else if (cmd.equals("LOG")) {
@@ -209,8 +211,11 @@ public class OpenVpnManagementThread implements Runnable { OpenVPN.logMessage(0, "MGMT:", "Got unrecognized command" + command);
Log.i(TAG, "Got unrecognized command" + command);
}
- } else if (command.startsWith("SUCCESS:")) {
- // ignore
+ } else if (command.startsWith("SUCCESS:")) { //Fixes bug LEAP #4565
+ if (command.equals("SUCCESS: signal SIGINT thrown")){
+ Log.d(TAG, "SUCCESS: signal SIGINT thrown");
+ processState(",EXITING,SIGINT,,");
+ }
} else {
Log.i(TAG, "Got unrecognized line from managment" + command);
OpenVPN.logMessage(0, "MGMT:", "Got unrecognized line from management:" + command);
@@ -272,11 +277,17 @@ public class OpenVpnManagementThread implements Runnable { private void processState(String argument) {
String[] args = argument.split(",",3);
String currentstate = args[1];
- Log.d("OpenVPN log", argument);
- if(args[2].equals(",,"))
+ if(args[2].equals(",,")){
OpenVPN.updateStateString(currentstate,"");
- else
+ }
+ else if (args[2].endsWith(",,")){ //fixes LEAP Bug #4546
+ args[2] = (String) args[2].subSequence(0, args[2].length()-2);
+ Log.d(TAG, "processState() STATE: "+ currentstate + " msg: " + args[2]);
+ OpenVPN.updateStateString(currentstate,args[2]);
+ }
+ else{
OpenVPN.updateStateString(currentstate,args[2]);
+ }
}
private static int repeated_byte_counts = 0;
@@ -333,8 +344,7 @@ public class OpenVpnManagementThread implements Runnable { mOpenVPNService.setDomain(extra);
} else if (needed.equals("ROUTE")) {
String[] routeparts = extra.split(" ");
- if(!mOpenVPNService.isRunning()) // We cannot add routes to an existing openvpn session
- mOpenVPNService.addRoute(routeparts[0], routeparts[1]);
+ mOpenVPNService.addRoute(routeparts[0], routeparts[1]);
} else if (needed.equals("ROUTE6")) {
mOpenVPNService.addRoutev6(extra);
} else if (needed.equals("IFCONFIG")) {
diff --git a/src/se/leap/openvpn/OpenVpnService.java b/src/se/leap/openvpn/OpenVpnService.java index 1ef291df..69dd56f4 100644 --- a/src/se/leap/openvpn/OpenVpnService.java +++ b/src/se/leap/openvpn/OpenVpnService.java @@ -106,7 +106,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac String ns = Context.NOTIFICATION_SERVICE; mNotificationManager = (NotificationManager) getSystemService(ns); int icon; - if (state.equals("NOPROCESS") || state.equals("AUTH_FAILED") || state.equals("NONETWORK")){ + if (state.equals("NOPROCESS") || state.equals("AUTH_FAILED") || state.equals("NONETWORK") || state.equals("EXITING")){ icon = R.drawable.ic_vpn_disconnected; }else{ icon = R.drawable.ic_stat_vpn; @@ -479,7 +479,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac // CONNECTED String ticker = getString(resid); boolean persist = false; - if (("NOPROCESS".equals(state) ) || ("EXIT").equals(state)){ + if (("NOPROCESS".equals(state) ) || ("EXITING").equals(state)){ showNotification(state, getString(R.string.eip_state_not_connected), ticker, false, 0, persist); } else{ |