summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcyBerta <cyberta@riseup.net>2018-02-13 16:06:49 +0100
committercyBerta <cyberta@riseup.net>2018-02-13 16:06:49 +0100
commita41e0b0f7ec0cff1dc7a34b42d663c777a317e61 (patch)
treeeba639ead30462f595614677a8358e972fd4cef1
parentfecdec8975042d0ae27efe63e8cefc7415ca5ad6 (diff)
parent9b6c368a25510c462ea357121c97edb6d0310021 (diff)
Merge branch 'origin_0.9.8' into #8831_progress_animation_when_connecting
* added new EipCommand in StartActivity * added option to add intent extras to EipCommand * resolved merge conflicts and minor refactorings in: app/src/main/java/se/leap/bitmaskclient/EipFragment.java app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
-rw-r--r--app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java242
-rw-r--r--app/src/insecure/java/se/leap/bitmaskclient/ProviderDetailActivity.java5
-rw-r--r--app/src/insecure/java/se/leap/bitmaskclient/ProviderListActivity.java43
-rw-r--r--app/src/main/AndroidManifest.xml2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java122
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java85
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Constants.java28
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Dashboard.java139
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/DefaultedURL.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java51
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipFragment.java327
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/FeatureVersionCode.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/MainActivity.java53
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java12
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Provider.java240
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java27
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java68
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java518
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java77
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java157
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/StartActivity.java27
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java43
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EIP.java39
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java82
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java10
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java24
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java6
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java179
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java27
-rw-r--r--app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java232
-rw-r--r--app/src/production/java/se/leap/bitmaskclient/ProviderListActivity.java41
-rw-r--r--app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java33
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/DefaultedURLTest.java31
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/ProviderTest.java21
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/EipStatusTest.java35
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java248
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java32
38 files changed, 1684 insertions, 1641 deletions
diff --git a/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java
index 8ca971e0..1c5247c0 100644
--- a/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java
+++ b/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java
@@ -48,22 +48,25 @@ import okhttp3.OkHttpClient;
import se.leap.bitmaskclient.eip.EIP;
import static android.text.TextUtils.isEmpty;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOWED_REGISTERED;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_CERTIFICATE_PINNING;
+import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_CORRUPTED_PROVIDER_JSON;
import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
-import static se.leap.bitmaskclient.ProviderAPI.RESULT_KEY;
import static se.leap.bitmaskclient.R.string.certificate_error;
import static se.leap.bitmaskclient.R.string.malformed_url;
import static se.leap.bitmaskclient.R.string.warning_corrupted_provider_cert;
+import static se.leap.bitmaskclient.R.string.warning_corrupted_provider_details;
/**
* Created by cyberta on 04.01.18.
*/
public class ProviderApiManager extends ProviderApiManagerBase {
+
+ private static final String TAG = ProviderApiManagerBase.class.getName();
+
protected static boolean lastDangerOn = true;
@@ -79,142 +82,116 @@ public class ProviderApiManager extends ProviderApiManagerBase {
* Downloads a provider.json from a given URL, adding a new provider using the given name.
*
* @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.
+ * @return a bundle with a boolean value mapped to a key named BROADCAST_RESULT_KEY, and which is true if the update was successful.
*/
@Override
- protected Bundle setUpProvider(Bundle task) {
- int progress = 0;
+ protected Bundle setUpProvider(Provider provider, Bundle task) {
Bundle currentDownload = new Bundle();
if (task != null) {
lastDangerOn = task.containsKey(ProviderListContent.ProviderItem.DANGER_ON) && task.getBoolean(ProviderListContent.ProviderItem.DANGER_ON);
- lastProviderMainUrl = task.containsKey(Provider.MAIN_URL) ?
- task.getString(Provider.MAIN_URL) :
- "";
-
- if (isEmpty(lastProviderMainUrl)) {
- setErrorResult(currentDownload, malformed_url, null);
- return currentDownload;
- }
-
- providerCaCertFingerprint = task.containsKey(Provider.CA_CERT_FINGERPRINT) ?
- task.getString(Provider.CA_CERT_FINGERPRINT) :
- "";
- providerCaCert = task.containsKey(Provider.CA_CERT) ?
- task.getString(Provider.CA_CERT) :
- "";
-
- try {
- providerDefinition = task.containsKey(Provider.KEY) ?
- new JSONObject(task.getString(Provider.KEY)) :
- new JSONObject();
- } catch (JSONException e) {
- e.printStackTrace();
- providerDefinition = new JSONObject();
- }
- providerApiUrl = getApiUrlWithVersion(providerDefinition);
+ }
- checkPersistedProviderUpdates();
- currentDownload = validateProviderDetails();
+ if (isEmpty(provider.getMainUrlString()) || provider.getMainUrl().isDefault()) {
+ setErrorResult(currentDownload, malformed_url, null);
+ currentDownload.putParcelable(PROVIDER_KEY, provider);
+ return currentDownload;
+ }
- //provider details invalid
- if (currentDownload.containsKey(ERRORS)) {
- return currentDownload;
- }
+ getPersistedProviderUpdates(provider);
+ currentDownload = validateProviderDetails(provider);
- //no provider certificate available
- if (currentDownload.containsKey(RESULT_KEY) && !currentDownload.getBoolean(RESULT_KEY)) {
- resetProviderDetails();
- }
+ //provider details invalid
+ if (currentDownload.containsKey(ERRORS)) {
+ currentDownload.putParcelable(PROVIDER_KEY, provider);
+ return currentDownload;
+ }
- EIP_SERVICE_JSON_DOWNLOADED = false;
- go_ahead = true;
+ //no provider certificate available
+ if (currentDownload.containsKey(BROADCAST_RESULT_KEY) && !currentDownload.getBoolean(BROADCAST_RESULT_KEY)) {
+ resetProviderDetails(provider);
}
- if (!PROVIDER_JSON_DOWNLOADED)
- currentDownload = getAndSetProviderJson(lastProviderMainUrl, lastDangerOn, providerCaCert, providerDefinition);
- if (PROVIDER_JSON_DOWNLOADED || (currentDownload.containsKey(RESULT_KEY) && currentDownload.getBoolean(RESULT_KEY))) {
- broadcastProgress(progress++);
- PROVIDER_JSON_DOWNLOADED = true;
-
- if (!CA_CERT_DOWNLOADED)
- currentDownload = downloadCACert(lastDangerOn);
- if (CA_CERT_DOWNLOADED || (currentDownload.containsKey(RESULT_KEY) && currentDownload.getBoolean(RESULT_KEY))) {
- broadcastProgress(progress++);
- CA_CERT_DOWNLOADED = true;
- currentDownload = getAndSetEipServiceJson();
- if (currentDownload.containsKey(RESULT_KEY) && currentDownload.getBoolean(RESULT_KEY)) {
- broadcastProgress(progress++);
- EIP_SERVICE_JSON_DOWNLOADED = true;
- }
+ if (!provider.hasDefinition())
+ currentDownload = getAndSetProviderJson(provider, lastDangerOn);
+ if (provider.hasDefinition() || (currentDownload.containsKey(BROADCAST_RESULT_KEY) && currentDownload.getBoolean(BROADCAST_RESULT_KEY))) {
+ if (!provider.hasCaCert())
+ currentDownload = downloadCACert(provider, lastDangerOn);
+ if (provider.hasCaCert() || (currentDownload.containsKey(BROADCAST_RESULT_KEY) && currentDownload.getBoolean(BROADCAST_RESULT_KEY))) {
+ currentDownload = getAndSetEipServiceJson(provider);
}
}
-
+ currentDownload.putParcelable(PROVIDER_KEY, provider);
return currentDownload;
}
- private Bundle getAndSetProviderJson(String providerMainUrl, boolean dangerOn, String caCert, JSONObject providerDefinition) {
+ private Bundle getAndSetProviderJson(Provider provider, boolean dangerOn) {
Bundle result = new Bundle();
- if (go_ahead) {
- String providerDotJsonString;
- if(providerDefinition.length() == 0 || caCert.isEmpty())
- providerDotJsonString = downloadWithCommercialCA(providerMainUrl + "/provider.json", dangerOn);
- else
- providerDotJsonString = downloadFromApiUrlWithProviderCA("/provider.json", caCert, providerDefinition, dangerOn);
+ JSONObject providerDefinition = provider.getDefinition();
+ String caCert = provider.getCaCert();
+ String providerMainUrl = provider.getMainUrlString();
- if (!isValidJson(providerDotJsonString)) {
- result.putString(ERRORS, resources.getString(malformed_url));
- result.putBoolean(RESULT_KEY, false);
- return result;
- }
+ String providerDotJsonString;
+ if(providerDefinition.length() == 0 || caCert.isEmpty())
+ providerDotJsonString = downloadWithCommercialCA(providerMainUrl + "/provider.json", dangerOn);
+ else
+ providerDotJsonString = downloadFromApiUrlWithProviderCA("/provider.json", caCert, providerDefinition, dangerOn);
- try {
- JSONObject providerJson = new JSONObject(providerDotJsonString);
- String providerDomain = getDomainFromMainURL(lastProviderMainUrl);
- providerApiUrl = getApiUrlWithVersion(providerJson);
- //String name = providerJson.getString(Provider.NAME);
- //TODO setProviderName(name);
-
- preferences.edit().putString(Provider.KEY, providerJson.toString()).
- putBoolean(PROVIDER_ALLOW_ANONYMOUS, providerJson.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOW_ANONYMOUS)).
- putBoolean(PROVIDER_ALLOWED_REGISTERED, providerJson.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOWED_REGISTERED)).
- putString(Provider.KEY + "." + providerDomain, providerJson.toString()).commit();
- result.putBoolean(RESULT_KEY, true);
- } catch (JSONException e) {
- String reason_to_fail = pickErrorMessage(providerDotJsonString);
- result.putString(ERRORS, reason_to_fail);
- result.putBoolean(RESULT_KEY, false);
+ if (!isValidJson(providerDotJsonString)) {
+ result.putString(ERRORS, resources.getString(malformed_url));
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ return result;
+ }
+
+ try {
+ JSONObject providerJson = new JSONObject(providerDotJsonString);
+
+ if (provider.define(providerJson)) {
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
+ } else {
+ return setErrorResult(result, warning_corrupted_provider_details, ERROR_CORRUPTED_PROVIDER_JSON.toString());
}
+
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
+ } catch (JSONException e) {
+ String reason_to_fail = pickErrorMessage(providerDotJsonString);
+ result.putString(ERRORS, reason_to_fail);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
}
+ result.putParcelable(PROVIDER_KEY, provider);
return result;
}
/**
* Downloads the eip-service.json from a given URL, and saves eip service capabilities including the offered gateways
- * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if the download was successful.
+ * @return a bundle with a boolean value mapped to a key named BROADCAST_RESULT_KEY, and which is true if the download was successful.
*/
@Override
- protected Bundle getAndSetEipServiceJson() {
+ protected Bundle getAndSetEipServiceJson(Provider provider) {
Bundle result = new Bundle();
- String eip_service_json_string = "";
- if (go_ahead) {
- try {
- JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
- String eip_service_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH;
- eip_service_json_string = downloadWithProviderCA(eip_service_url, lastDangerOn);
- JSONObject eip_service_json = new JSONObject(eip_service_json_string);
- eip_service_json.getInt(Provider.API_RETURN_SERIAL);
-
- preferences.edit().putString(PROVIDER_KEY, eip_service_json.toString()).commit();
-
- result.putBoolean(RESULT_KEY, true);
- } catch (NullPointerException | JSONException e) {
- String reason_to_fail = pickErrorMessage(eip_service_json_string);
- result.putString(ERRORS, reason_to_fail);
- result.putBoolean(RESULT_KEY, false);
+ String eipServiceJsonString = "";
+ try {
+ JSONObject providerDefinition = provider.getDefinition();
+ String eipServiceUrl = providerDefinition.getString(Provider.API_URL) + "/" + providerDefinition.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH;
+ eipServiceJsonString = downloadWithProviderCA(provider.getCaCert(), eipServiceUrl, lastDangerOn);
+
+ JSONObject eipServiceJson = new JSONObject(eipServiceJsonString);
+
+ if (eipServiceJson.has(ERRORS)) {
+ String reasonToFail = pickErrorMessage(eipServiceJsonString);
+ result.putString(ERRORS, reasonToFail);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ } else{
+ provider.setEipServiceJson(eipServiceJson);
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
}
+ } catch (NullPointerException | JSONException e) {
+ String reasonToFail = pickErrorMessage(eipServiceJsonString);
+ result.putString(ERRORS, reasonToFail);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
}
+ result.putParcelable(PROVIDER_KEY, provider);
return result;
}
@@ -224,19 +201,19 @@ public class ProviderApiManager extends ProviderApiManagerBase {
* @return true if certificate was downloaded correctly, false if provider.json is not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error.
*/
@Override
- protected boolean updateVpnCertificate() {
+ protected boolean updateVpnCertificate(Provider provider) {
try {
- JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
+ JSONObject providerDefinition = provider.getDefinition();
- 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) + "/" + PROVIDER_VPN_CERTIFICATE);
+ String providerMainUrl = providerDefinition.getString(Provider.API_URL);
+ URL newCertStringUrl = new URL(providerMainUrl + "/" + providerDefinition.getString(Provider.API_VERSION) + "/" + PROVIDER_VPN_CERTIFICATE);
- String cert_string = downloadWithProviderCA(new_cert_string_url.toString(), lastDangerOn);
+ String certString = downloadWithProviderCA(provider.getCaCert(), newCertStringUrl.toString(), lastDangerOn);
- if (cert_string == null || cert_string.isEmpty() || ConfigHelper.checkErroneousDownload(cert_string))
+ if (certString == null || certString.isEmpty() || ConfigHelper.checkErroneousDownload(certString))
return false;
else
- return loadCertificate(cert_string);
+ return loadCertificate(provider, certString);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -249,19 +226,18 @@ public class ProviderApiManager extends ProviderApiManagerBase {
}
- private Bundle downloadCACert(boolean dangerOn) {
+ private Bundle downloadCACert(Provider provider, boolean dangerOn) {
Bundle result = new Bundle();
try {
- JSONObject providerJson = new JSONObject(preferences.getString(Provider.KEY, ""));
- String caCertUrl = providerJson.getString(Provider.CA_CERT_URI);
- String providerDomain = providerJson.getString(Provider.DOMAIN);
+ String caCertUrl = provider.getDefinition().getString(Provider.CA_CERT_URI);
+ String providerDomain = provider.getDomain();
String certString = downloadWithCommercialCA(caCertUrl, dangerOn);
- if (validCertificate(certString) && go_ahead) {
- preferences.edit().putString(Provider.CA_CERT, certString).commit();
- preferences.edit().putString(Provider.CA_CERT + "." + providerDomain, certString).commit();
- result.putBoolean(RESULT_KEY, true);
+ if (validCertificate(provider, certString)) {
+ provider.setCaCert(certString);
+ preferences.edit().putString(Provider.CA_CERT + "." + providerDomain, certString).apply();
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
} else {
setErrorResult(result, warning_corrupted_provider_cert, ERROR_CERTIFICATE_PINNING.toString());
}
@@ -275,13 +251,13 @@ public class ProviderApiManager extends ProviderApiManagerBase {
/**
* Tries to download the contents of the provided url using commercially validated CA certificate from chosen provider.
* <p/>
- * If danger_on flag is true, SSL exceptions will be managed by futher methods that will try to use some bypass methods.
+ * If dangerOn flag is true, SSL exceptions will be managed by futher methods that will try to use some bypass methods.
*
- * @param string_url
- * @param danger_on if the user completely trusts this provider
+ * @param stringUrl
+ * @param dangerOn if the user completely trusts this provider
* @return
*/
- private String downloadWithCommercialCA(String string_url, boolean danger_on) {
+ private String downloadWithCommercialCA(String stringUrl, boolean dangerOn) {
String responseString;
JSONObject errorJson = new JSONObject();
@@ -292,14 +268,14 @@ public class ProviderApiManager extends ProviderApiManagerBase {
List<Pair<String, String>> headerArgs = getAuthorizationHeader();
- responseString = sendGetStringToServer(string_url, headerArgs, okHttpClient);
+ responseString = sendGetStringToServer(stringUrl, headerArgs, okHttpClient);
if (responseString != null && responseString.contains(ERRORS)) {
try {
// try to download with provider CA on certificate error
JSONObject responseErrorJson = new JSONObject(responseString);
- if (danger_on && responseErrorJson.getString(ERRORS).equals(resources.getString(R.string.certificate_error))) {
- responseString = downloadWithoutCA(string_url);
+ if (dangerOn && responseErrorJson.getString(ERRORS).equals(resources.getString(R.string.certificate_error))) {
+ responseString = downloadWithoutCA(stringUrl);
}
} catch (JSONException e) {
e.printStackTrace();
@@ -313,7 +289,7 @@ public class ProviderApiManager extends ProviderApiManagerBase {
String responseString;
JSONObject errorJson = new JSONObject();
String baseUrl = getApiUrl(providerDefinition);
- OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(errorJson, caCert);
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(caCert, errorJson);
if (okHttpClient == null) {
return errorJson.toString();
}
@@ -344,11 +320,11 @@ public class ProviderApiManager extends ProviderApiManagerBase {
* @param dangerOn 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(String urlString, boolean dangerOn) {
+ private String downloadWithProviderCA(String caCert, String urlString, boolean dangerOn) {
JSONObject initError = new JSONObject();
String responseString;
- OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(initError);
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(caCert, initError);
if (okHttpClient == null) {
return initError.toString();
}
@@ -376,7 +352,7 @@ public class ProviderApiManager extends ProviderApiManagerBase {
* Downloads the string that's in the url with any certificate.
*/
// This method is totally insecure anyways. So no need to refactor that in order to use okHttpClient, force modern TLS etc.. DO NOT USE IN PRODUCTION!
- private String downloadWithoutCA(String url_string) {
+ private String downloadWithoutCA(String urlString) {
String string = "";
try {
@@ -406,7 +382,7 @@ public class ProviderApiManager extends ProviderApiManagerBase {
SSLContext context = SSLContext.getInstance("TLS");
context.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom());
- URL url = new URL(url_string);
+ URL url = new URL(urlString);
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
urlConnection.setHostnameVerifier(hostnameVerifier);
diff --git a/app/src/insecure/java/se/leap/bitmaskclient/ProviderDetailActivity.java b/app/src/insecure/java/se/leap/bitmaskclient/ProviderDetailActivity.java
index 6977753f..cf9ee5f5 100644
--- a/app/src/insecure/java/se/leap/bitmaskclient/ProviderDetailActivity.java
+++ b/app/src/insecure/java/se/leap/bitmaskclient/ProviderDetailActivity.java
@@ -2,15 +2,12 @@ package se.leap.bitmaskclient;
import android.content.SharedPreferences;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS;
-import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
-
public class ProviderDetailActivity extends AbstractProviderDetailActivity {
@Override
public void onBackPressed() {
SharedPreferences.Editor editor = preferences.edit();
- editor.remove(Provider.KEY).remove(ProviderListContent.ProviderItem.DANGER_ON).remove(PROVIDER_ALLOW_ANONYMOUS).remove(PROVIDER_KEY).apply();
+ editor.remove(ProviderListContent.ProviderItem.DANGER_ON).apply();
super.onBackPressed();
}
diff --git a/app/src/insecure/java/se/leap/bitmaskclient/ProviderListActivity.java b/app/src/insecure/java/se/leap/bitmaskclient/ProviderListActivity.java
index 823b5635..5ad7ea44 100644
--- a/app/src/insecure/java/se/leap/bitmaskclient/ProviderListActivity.java
+++ b/app/src/insecure/java/se/leap/bitmaskclient/ProviderListActivity.java
@@ -16,8 +16,8 @@
*/
package se.leap.bitmaskclient;
-import android.content.Intent;
import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentTransaction;
@@ -26,6 +26,8 @@ import java.net.URL;
import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
+import static se.leap.bitmaskclient.ProviderAPI.SET_UP_PROVIDER;
+
/**
* Activity that builds and shows the list of known available providers.
* <p/>
@@ -51,12 +53,12 @@ public class ProviderListActivity extends ProviderListBaseActivity {
/**
* Open the new provider dialog with data
*/
- public void addAndSelectNewProvider(String main_url, boolean danger_on) {
+ public void addAndSelectNewProvider(String mainUrl, boolean danger_on) {
FragmentTransaction fragment_transaction = fragmentManager.removePreviousFragment(NewProviderDialog.TAG);
DialogFragment newFragment = new NewProviderDialog();
Bundle data = new Bundle();
- data.putString(Provider.MAIN_URL, main_url);
+ data.putString(Provider.MAIN_URL, mainUrl);
data.putBoolean(ProviderItem.DANGER_ON, danger_on);
newFragment.setArguments(data);
newFragment.show(fragment_transaction, NewProviderDialog.TAG);
@@ -87,46 +89,19 @@ public class ProviderListActivity extends ProviderListBaseActivity {
*/
public void setUpProvider(boolean danger_on) {
mConfigState.setAction(SETTING_UP_PROVIDER);
- Intent providerAPICommand = new Intent(this, ProviderAPI.class);
+
Bundle parameters = new Bundle();
- parameters.putString(Provider.MAIN_URL, provider.getMainUrl().toString());
parameters.putBoolean(ProviderItem.DANGER_ON, danger_on);
- if (provider.hasCertificatePin()){
- parameters.putString(Provider.CA_CERT_FINGERPRINT, provider.certificatePin());
- }
- if (provider.hasCaCert()) {
- parameters.putString(Provider.CA_CERT, provider.getCaCert());
- }
- if (provider.hasDefinition()) {
- parameters.putString(Provider.KEY, provider.getDefinition().toString());
- }
- providerAPICommand.setAction(ProviderAPI.SET_UP_PROVIDER);
- providerAPICommand.putExtra(ProviderAPI.PARAMETERS, parameters);
-
- startService(providerAPICommand);
+ ProviderAPICommand.execute(this, SET_UP_PROVIDER, parameters, provider);
}
/**
* Retrys setup of last used provider, allows bypassing ca certificate validation.
*/
@Override
- public void retrySetUpProvider() {
- cancelSettingUpProvider();
- if (!ProviderAPI.caCertDownloaded()) {
- addAndSelectNewProvider(ProviderAPI.lastProviderMainUrl(), ProviderAPI.lastDangerOn());
- } else {
- showProgressBar();
-
- Intent providerAPICommand = new Intent(this, ProviderAPI.class);
-
- providerAPICommand.setAction(ProviderAPI.SET_UP_PROVIDER);
- Bundle parameters = new Bundle();
- parameters.putString(Provider.MAIN_URL, provider.getMainUrl().toString());
- providerAPICommand.putExtra(ProviderAPI.PARAMETERS, parameters);
-
- startService(providerAPICommand);
- }
+ public void retrySetUpProvider(@NonNull Provider provider) {
+ ProviderAPICommand.execute(this, SET_UP_PROVIDER, provider);
}
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 029e9fdb..f60a2db6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -21,7 +21,7 @@
<uses-sdk
android:minSdkVersion="16"
- android:targetSdkVersion="26" />
+ android:targetSdkVersion="27" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
diff --git a/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java b/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java
index ebfc1909..6738a6bb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/AbstractProviderDetailActivity.java
@@ -1,7 +1,6 @@
package se.leap.bitmaskclient;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatTextView;
@@ -12,14 +11,10 @@ import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
-import org.json.JSONException;
-import org.json.JSONObject;
-
import java.util.ArrayList;
import butterknife.InjectView;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS;
import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP;
@@ -36,56 +31,58 @@ public abstract class AbstractProviderDetailActivity extends ConfigWizardBaseAct
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ provider = getIntent().getParcelableExtra(PROVIDER_KEY);
setContentView(R.layout.a_provider_detail);
- try {
- JSONObject providerJson = new JSONObject(preferences.getString(Provider.KEY, ""));
- setProviderHeaderText(ConfigHelper.getProviderName(preferences));
- description.setText(ConfigHelper.getDescription(preferences));
+ if (provider == null) {
+ return;
+ }
- // Show only the options allowed by the provider
- ArrayList<String> optionsList = new ArrayList<>();
- if (registrationAllowed(providerJson)) {
- optionsList.add(getString(R.string.login_to_profile));
- optionsList.add(getString(R.string.create_profile));
- }
- if (anonAllowed(providerJson)) {
- optionsList.add(getString(R.string.use_anonymously_button));
- }
- options.setAdapter(new ArrayAdapter<>(
- this,
- R.layout.single_list_item,
- android.R.id.text1,
- optionsList.toArray(new String[optionsList.size()])
- ));
- options.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- String text = ((TextView) view).getText().toString();
- Intent intent;
- if (text.equals(getString(R.string.login_to_profile))) {
- Log.d(TAG, "login selected");
- intent = new Intent(getApplicationContext(), LoginActivity.class);
- } else if (text.equals(getString(R.string.create_profile))) {
- Log.d(TAG, "signup selected");
- intent = new Intent(getApplicationContext(), SignupActivity.class);
- } else {
- Log.d(TAG, "use anonymously selected");
- intent = new Intent();
- intent.putExtra(Provider.KEY, provider);
- setResult(RESULT_OK, intent);
- finish();
- return;
- }
- intent.putExtra(PROVIDER_KEY, provider);
- intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
- startActivityForResult(intent, REQUEST_CODE_CONFIGURE_LEAP);
- }
- });
- } catch (JSONException e) {
- // TODO show error and return
+ setProviderHeaderText(provider.getName());
+ description.setText(provider.getDescription());
+
+ // Show only the options allowed by the provider
+ ArrayList<String> optionsList = new ArrayList<>();
+ if (provider.allowsRegistered()) {
+ optionsList.add(getString(R.string.login_to_profile));
+ optionsList.add(getString(R.string.create_profile));
+ }
+ if (provider.allowsAnonymous()) {
+ optionsList.add(getString(R.string.use_anonymously_button));
}
+
+ options.setAdapter(new ArrayAdapter<>(
+ this,
+ R.layout.single_list_item,
+ android.R.id.text1,
+ optionsList.toArray(new String[optionsList.size()])
+ ));
+ options.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ String text = ((TextView) view).getText().toString();
+ Intent intent;
+ if (text.equals(getString(R.string.login_to_profile))) {
+ Log.d(TAG, "login selected");
+ intent = new Intent(getApplicationContext(), LoginActivity.class);
+ } else if (text.equals(getString(R.string.create_profile))) {
+ Log.d(TAG, "signup selected");
+ intent = new Intent(getApplicationContext(), SignupActivity.class);
+ } else {
+ Log.d(TAG, "use anonymously selected");
+ intent = new Intent();
+ intent.putExtra(Provider.KEY, provider);
+ setResult(RESULT_OK, intent);
+ finish();
+ return;
+ }
+ intent.putExtra(PROVIDER_KEY, provider);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
+ startActivityForResult(intent, REQUEST_CODE_CONFIGURE_LEAP);
+ }
+ });
}
@Override
@@ -104,29 +101,4 @@ public abstract class AbstractProviderDetailActivity extends ConfigWizardBaseAct
}
}
- private boolean anonAllowed(JSONObject providerJson) {
- try {
- JSONObject serviceDescription = providerJson.getJSONObject(Provider.SERVICE);
- return serviceDescription.has(PROVIDER_ALLOW_ANONYMOUS) && serviceDescription.getBoolean(PROVIDER_ALLOW_ANONYMOUS);
- } catch (JSONException e) {
- return false;
- }
- }
-
- private boolean registrationAllowed(JSONObject providerJson) {
- try {
- JSONObject serviceDescription = providerJson.getJSONObject(Provider.SERVICE);
- return serviceDescription.has(Provider.ALLOW_REGISTRATION) && serviceDescription.getBoolean(Provider.ALLOW_REGISTRATION);
- } catch (JSONException e) {
- return false;
- }
- }
-
- @Override
- public void onBackPressed() {
- SharedPreferences.Editor editor = preferences.edit();
- editor.remove(Provider.KEY).remove(PROVIDER_ALLOW_ANONYMOUS).remove(PROVIDER_KEY).apply();
- super.onBackPressed();
- }
-
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
index 22965252..7b2accd6 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
@@ -46,10 +46,17 @@ import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Locale;
+import java.util.Map;
import static android.R.attr.name;
+import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION;
import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED;
+import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION;
+import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY;
+import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
/**
* Stores constants, and implements auxiliary methods used across all Bitmask Android classes.
@@ -97,14 +104,14 @@ public class ConfigHelper {
return ret;
}
- public static X509Certificate parseX509CertificateFromString(String certificate_string) {
+ public static X509Certificate parseX509CertificateFromString(String certificateString) {
java.security.cert.Certificate certificate = null;
CertificateFactory cf;
try {
cf = CertificateFactory.getInstance("X.509");
- certificate_string = certificate_string.replaceFirst("-----BEGIN CERTIFICATE-----", "").replaceFirst("-----END CERTIFICATE-----", "").trim();
- byte[] cert_bytes = Base64.decode(certificate_string);
+ certificateString = certificateString.replaceFirst("-----BEGIN CERTIFICATE-----", "").replaceFirst("-----END CERTIFICATE-----", "").trim();
+ byte[] cert_bytes = Base64.decode(certificateString);
InputStream caInput = new ByteArrayInputStream(cert_bytes);
try {
certificate = cf.generateCertificate(caInput);
@@ -270,9 +277,11 @@ public class ConfigHelper {
public static Provider getSavedProviderFromSharedPreferences(@NonNull SharedPreferences preferences) {
Provider provider = new Provider();
try {
- provider.setUrl(new URL(preferences.getString(Provider.MAIN_URL, "")));
+ provider.setMainUrl(new URL(preferences.getString(Provider.MAIN_URL, "")));
provider.define(new JSONObject(preferences.getString(Provider.KEY, "")));
- provider.setCACert(preferences.getString(Provider.CA_CERT, ""));
+ provider.setCaCert(preferences.getString(Provider.CA_CERT, ""));
+ provider.setVpnCertificate(preferences.getString(PROVIDER_VPN_CERTIFICATE, ""));
+ provider.setPrivateKey(preferences.getString(PROVIDER_PRIVATE_KEY, ""));
} catch (MalformedURLException | JSONException e) {
e.printStackTrace();
}
@@ -280,6 +289,10 @@ public class ConfigHelper {
return provider;
}
+ public static String getFromPersistedProvider(String toFetch, String providerDomain, SharedPreferences preferences) {
+ return preferences.getString(toFetch + "." + providerDomain, "");
+ }
+
public static String getProviderName(String provider) {
return getProviderName(null, provider);
}
@@ -343,11 +356,73 @@ public class ConfigHelper {
}
}
+ // TODO: replace commit with apply after refactoring EIP
+ //FIXME: don't save private keys in shared preferences! use the keystore
public static void storeProviderInPreferences(SharedPreferences preferences, Provider provider) {
preferences.edit().putBoolean(PROVIDER_CONFIGURED, true).
putString(Provider.MAIN_URL, provider.getMainUrlString()).
putString(Provider.KEY, provider.getDefinitionString()).
putString(Provider.CA_CERT, provider.getCaCert()).
+ putString(PROVIDER_EIP_DEFINITION, provider.getEipServiceJsonString()).
+ putString(PROVIDER_PRIVATE_KEY, provider.getPrivateKey()).
+ putString(PROVIDER_VPN_CERTIFICATE, provider.getVpnCertificate()).
+ commit();
+
+ String providerDomain = provider.getDomain();
+ preferences.edit().putBoolean(PROVIDER_CONFIGURED, true).
+ putString(Provider.MAIN_URL + "." + providerDomain, provider.getMainUrlString()).
+ putString(Provider.KEY + "." + providerDomain, provider.getDefinitionString()).
+ putString(Provider.CA_CERT + "." + providerDomain, provider.getCaCert()).
+ putString(PROVIDER_EIP_DEFINITION + "." + providerDomain, provider.getEipServiceJsonString()).
+ putString(PROVIDER_PRIVATE_KEY + "." + providerDomain, provider.getPrivateKey()).
+ putString(PROVIDER_VPN_CERTIFICATE + "." + providerDomain, provider.getVpnCertificate()).
apply();
}
+
+
+ public static void clearDataOfLastProvider(SharedPreferences preferences) {
+ clearDataOfLastProvider(preferences, false);
+ }
+
+ public static void clearDataOfLastProvider(SharedPreferences preferences, boolean commit) {
+ Map<String, ?> allEntries = preferences.getAll();
+ List<String> lastProvidersKeys = new ArrayList<>();
+ for (Map.Entry<String, ?> entry : allEntries.entrySet()) {
+ //sort out all preferences that don't belong to the last provider
+ if (entry.getKey().startsWith(Provider.KEY + ".") ||
+ entry.getKey().startsWith(Provider.CA_CERT + ".") ||
+ entry.getKey().startsWith(Provider.CA_CERT_FINGERPRINT + "." )||
+ entry.getKey().equals(PREFERENCES_APP_VERSION)
+ ) {
+ continue;
+ }
+ lastProvidersKeys.add(entry.getKey());
+ }
+
+ SharedPreferences.Editor preferenceEditor = preferences.edit();
+ for (String key : lastProvidersKeys) {
+ preferenceEditor.remove(key);
+ }
+ if (commit) {
+ preferenceEditor.commit();
+ } else {
+ preferenceEditor.apply();
+ }
+ }
+
+ public static void deleteProviderDetailsFromPreferences(@NonNull SharedPreferences preferences, String providerDomain) {
+ preferences.edit().
+ remove(Provider.KEY + "." + providerDomain).
+ remove(Provider.CA_CERT + "." + providerDomain).
+ remove(Provider.CA_CERT_FINGERPRINT + "." + providerDomain).
+ remove(Provider.MAIN_URL + "." + providerDomain).
+ remove(Provider.KEY + "." + providerDomain).
+ remove(Provider.CA_CERT + "." + providerDomain).
+ remove(PROVIDER_EIP_DEFINITION + "." + providerDomain).
+ remove(PROVIDER_PRIVATE_KEY + "." + providerDomain).
+ remove(PROVIDER_VPN_CERTIFICATE + "." + providerDomain).
+ apply();
+ }
+
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java
index 79a78fe1..7fcb5816 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ConfigWizardBaseActivity.java
@@ -56,19 +56,22 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity {
@Override
public void setContentView(View view) {
super.setContentView(view);
- setProviderHeaderText(ConfigHelper.getProviderName(preferences));
+ if (provider != null)
+ setProviderHeaderText(provider.getName());
}
@Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
- setProviderHeaderText(ConfigHelper.getProviderName(preferences));
+ if (provider != null)
+ setProviderHeaderText(provider.getName());
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
super.setContentView(view, params);
- setProviderHeaderText(ConfigHelper.getProviderName(preferences));
+ if (provider != null)
+ setProviderHeaderText(provider.getName());
}
protected void setProviderHeaderLogo(@DrawableRes int providerHeaderLogo) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/Constants.java b/app/src/main/java/se/leap/bitmaskclient/Constants.java
index f197c2ed..fb2655e3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Constants.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Constants.java
@@ -17,6 +17,7 @@ public interface Constants {
String REQUEST_CODE_KEY = "request_code";
int REQUEST_CODE_CONFIGURE_LEAP = 0;
int REQUEST_CODE_SWITCH_PROVIDER = 1;
+ int REQUEST_CODE_LOG_IN = 2;
//////////////////////////////////////////////
@@ -45,16 +46,41 @@ public interface Constants {
String EIP_REQUEST = "EIP.REQUEST";
String EIP_RESTART_ON_BOOT = "EIP.RESTART_ON_BOOT";
String EIP_IS_ALWAYS_ON = "EIP.EIP_IS_ALWAYS_ON";
- String EIP_TRIGGERED_FROM_UI = "EIP.TRIGGERED_FROM_UI";
+ String EIP_EARLY_ROUTES = "EIP.EARLY_ROUTES";
//////////////////////////////////////////////
// PROVIDER CONSTANTS
/////////////////////////////////////////////
+
String PROVIDER_ALLOW_ANONYMOUS = "allow_anonymous";
String PROVIDER_ALLOWED_REGISTERED = "allow_registration";
String PROVIDER_VPN_CERTIFICATE = "cert";
String PROVIDER_PRIVATE_KEY = "Constants.PROVIDER_PRIVATE_KEY";
String PROVIDER_KEY = "Constants.PROVIDER_KEY";
String PROVIDER_CONFIGURED = "Constants.PROVIDER_CONFIGURED";
+ String PROVIDER_EIP_DEFINITION = "Constants.EIP_DEFINITION";
+
+ //////////////////////////////////////////////
+ // CREDENTIAL CONSTANTS
+ /////////////////////////////////////////////
+
+ String CREDENTIALS_USERNAME = "username";
+ String CREDENTIALS_PASSWORD = "password";
+
+ enum CREDENTIAL_ERRORS {
+ USERNAME_MISSING,
+ PASSWORD_INVALID_LENGTH,
+ RISEUP_WARNING
+ }
+
+ //////////////////////////////////////////////
+ // BROADCAST CONSTANTS
+ /////////////////////////////////////////////
+
+ String BROADCAST_EIP_EVENT = "BROADCAST.EIP_EVENT";
+ String BROADCAST_PROVIDER_API_EVENT = "BROADCAST.PROVIDER_API_EVENT";
+ String BROADCAST_RESULT_CODE = "BROADCAST.RESULT_CODE";
+ String BROADCAST_RESULT_KEY = "BROADCAST.RESULT_KEY";
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
index 78ec3fd2..48dce1c2 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
@@ -23,8 +23,6 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
-import android.os.Handler;
-import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -36,14 +34,11 @@ import org.json.JSONObject;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
import butterknife.InjectView;
import de.blinkt.openvpn.core.VpnStatus;
+import se.leap.bitmaskclient.eip.EipCommand;
import se.leap.bitmaskclient.fragments.AboutFragment;
-import se.leap.bitmaskclient.userstatus.SessionDialog;
import se.leap.bitmaskclient.userstatus.User;
import se.leap.bitmaskclient.userstatus.UserStatusFragment;
@@ -51,10 +46,8 @@ import static se.leap.bitmaskclient.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PRO
import static se.leap.bitmaskclient.Constants.APP_ACTION_QUIT;
import static se.leap.bitmaskclient.Constants.EIP_IS_ALWAYS_ON;
import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT;
-import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS;
import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED;
-import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
+import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION;
import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP;
import static se.leap.bitmaskclient.Constants.REQUEST_CODE_KEY;
import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER;
@@ -91,20 +84,15 @@ public class Dashboard extends ButterKnifeActivity {
private UserStatusFragment user_status_fragment;
private static Provider provider = new Provider();
- public static ProviderAPIResultReceiver providerAPI_result_receiver;
- private static boolean switching_provider;
private boolean handledVersion;
- public static DashboardReceiver dashboardReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- dashboardReceiver = new DashboardReceiver(this);
preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
fragment_manager = new FragmentManagerEnhanced(getSupportFragmentManager());
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler(), dashboardReceiver);
if (!handledVersion) {
handleVersion();
@@ -112,7 +100,6 @@ public class Dashboard extends ButterKnifeActivity {
}
// initialize app necessities
- ProviderAPICommand.initialize(this);
VpnStatus.initLogCache(getApplicationContext().getCacheDir());
User.init(getString(R.string.default_username));
@@ -157,9 +144,9 @@ public class Dashboard extends ButterKnifeActivity {
private Provider getSavedProviderFromSharedPreferences() {
Provider provider = new Provider();
try {
- provider.setUrl(new URL(preferences.getString(Provider.MAIN_URL, "")));
+ provider.setMainUrl(new URL(preferences.getString(Provider.MAIN_URL, "")));
provider.define(new JSONObject(preferences.getString(Provider.KEY, "")));
- provider.setCACert(preferences.getString(Provider.CA_CERT, ""));
+ provider.setCaCert(preferences.getString(Provider.CA_CERT, ""));
} catch (MalformedURLException | JSONException e) {
e.printStackTrace();
}
@@ -174,8 +161,8 @@ public class Dashboard extends ButterKnifeActivity {
switch (versionCode) {
case 91: // 0.6.0 without Bug #5999
case 101: // 0.8.0
- if (!preferences.getString(PROVIDER_KEY, "").isEmpty())
- eip_fragment.updateEipService();
+ if (!preferences.getString(PROVIDER_EIP_DEFINITION, "").isEmpty())
+ EipCommand.updateEipService(this);
break;
}
} catch (NameNotFoundException e) {
@@ -211,9 +198,9 @@ public class Dashboard extends ButterKnifeActivity {
buildDashboard(false);
invalidateOptionsMenuOnUiThread();
- if (data.hasExtra(SessionDialog.TAG)) {
- sessionDialog(Bundle.EMPTY);
- }
+ //if (data.hasExtra(SessionDialog.TAG)) {
+ // sessionDialog(Bundle.EMPTY);
+ //}
} else if (resultCode == RESULT_CANCELED && data != null && data.hasExtra(APP_ACTION_QUIT)) {
finish();
@@ -304,14 +291,14 @@ public class Dashboard extends ButterKnifeActivity {
user_status_fragment.setArguments(bundle);
fragment_manager.replace(R.id.user_status_fragment, user_status_fragment, UserStatusFragment.TAG);
- if (provider.hasEIP()) {
- fragment_manager.removePreviousFragment(EipFragment.TAG);
- eip_fragment = prepareEipFragment(hideAndTurnOnEipOnBoot);
- fragment_manager.replace(R.id.servicesCollection, eip_fragment, EipFragment.TAG);
- if (hideAndTurnOnEipOnBoot) {
- onBackPressed();
- }
- }
+// if (provider.hasEIP()) {
+// fragment_manager.removePreviousFragment(EipFragment.TAG);
+// eip_fragment = prepareEipFragment(hideAndTurnOnEipOnBoot);
+// fragment_manager.replace(R.id.servicesCollection, eip_fragment, EipFragment.TAG);
+// if (hideAndTurnOnEipOnBoot) {
+// onBackPressed();
+// }
+// }
}
/**
@@ -367,12 +354,11 @@ public class Dashboard extends ButterKnifeActivity {
showLog();
return true;
case R.id.switch_provider:
- switching_provider = true;
if (User.loggedIn()) user_status_fragment.logOut();
else switchProvider();
return true;
case R.id.signup_button:
- sessionDialog(Bundle.EMPTY);
+ //sessionDialog(Bundle.EMPTY);
return true;
default:
return super.onOptionsItemSelected(item);
@@ -389,99 +375,14 @@ public class Dashboard extends ButterKnifeActivity {
log_window_wrapper.showLog();
}
-
- // TODO MOVE TO VPNManager(?)
- public static void downloadVpnCertificate() {
- boolean is_authenticated = User.loggedIn();
- boolean allowed_anon = preferences.getBoolean(PROVIDER_ALLOW_ANONYMOUS, false);
- if (allowed_anon || is_authenticated)
- ProviderAPICommand.execute(Bundle.EMPTY, ProviderAPI.DOWNLOAD_CERTIFICATE, providerAPI_result_receiver);
- else
- sessionDialog(Bundle.EMPTY);
- }
-
- // TODO how can we replace this
- public static void sessionDialog(Bundle resultData) {
- try {
- FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG);
- SessionDialog.getInstance(provider, resultData).show(transaction, SessionDialog.TAG);
- } catch (IllegalStateException e) {
- e.printStackTrace();
- }
- }
-
private void switchProvider() {
- if (provider.hasEIP()) eip_fragment.stopEipIfPossible();
-
- clearDataOfLastProvider();
-
- switching_provider = false;
- startActivityForResult(new Intent(this, ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER);
- }
+// if (provider.hasEIP()) eip_fragment.stopEipIfPossible();
- private void clearDataOfLastProvider() {
- Map<String, ?> allEntries = preferences.getAll();
- List<String> lastProvidersKeys = new ArrayList<>();
- for (Map.Entry<String, ?> entry : allEntries.entrySet()) {
- //sort out all preferences that don't belong to the last provider
- if (entry.getKey().startsWith(Provider.KEY + ".") ||
- entry.getKey().startsWith(Provider.CA_CERT + ".") ||
- entry.getKey().startsWith(Provider.CA_CERT_FINGERPRINT + "." )||
- entry.getKey().equals(PREFERENCES_APP_VERSION)
- ) {
- continue;
- }
- lastProvidersKeys.add(entry.getKey());
- }
+ ConfigHelper.clearDataOfLastProvider(preferences);
- SharedPreferences.Editor preferenceEditor = preferences.edit();
- for (String key : lastProvidersKeys) {
- preferenceEditor.remove(key);
- }
- preferenceEditor.apply();
-
- switching_provider = false;
startActivityForResult(new Intent(this, ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER);
}
- private static class DashboardReceiver implements ProviderAPIResultReceiver.Receiver{
-
- private Dashboard dashboard;
-
- DashboardReceiver(Dashboard dashboard) {
- this.dashboard = dashboard;
- }
-
- @Override
- public void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) {
- String username = resultData.getString(SessionDialog.USERNAME);
- String password = resultData.getString(SessionDialog.PASSWORD);
- dashboard.user_status_fragment.logIn(username, password);
- } else if (resultCode == ProviderAPI.FAILED_SIGNUP) {
- //MainActivity.sessionDialog(resultData);
- } else if (resultCode == ProviderAPI.SUCCESSFUL_LOGIN) {
- Dashboard.downloadVpnCertificate();
- } else if (resultCode == ProviderAPI.FAILED_LOGIN) {
- //MainActivity.sessionDialog(resultData);
- } else if (resultCode == ProviderAPI.SUCCESSFUL_LOGOUT) {
- if (switching_provider) dashboard.switchProvider();
- } else if (resultCode == ProviderAPI.LOGOUT_FAILED) {
- dashboard.setResult(RESULT_CANCELED);
- } else if (resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
- dashboard.eip_fragment.updateEipService();
- dashboard.setResult(RESULT_OK);
- } else if (resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
- dashboard.setResult(RESULT_CANCELED);
- } else if (resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE) {
- dashboard.eip_fragment.updateEipService();
- dashboard.setResult(RESULT_OK);
- } else if (resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE) {
- dashboard.setResult(RESULT_CANCELED);
- }
- }
- }
-
public static Provider getProvider() { return provider; }
@Override
diff --git a/app/src/main/java/se/leap/bitmaskclient/DefaultedURL.java b/app/src/main/java/se/leap/bitmaskclient/DefaultedURL.java
index 57ff1fd8..0cbb0d72 100644
--- a/app/src/main/java/se/leap/bitmaskclient/DefaultedURL.java
+++ b/app/src/main/java/se/leap/bitmaskclient/DefaultedURL.java
@@ -36,4 +36,13 @@ public class DefaultedURL {
public String toString() {
return url.toString();
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof DefaultedURL) {
+ return url.equals(((DefaultedURL) o).getUrl());
+ }
+ return false;
+ }
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
index dde71642..8a6d981d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
@@ -21,6 +21,7 @@ import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import org.json.JSONObject;
@@ -38,8 +39,11 @@ import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
public class DownloadFailedDialog extends DialogFragment {
public static String TAG = "downloaded_failed_dialog";
- private String reason_to_fail;
+ private String reasonToFail;
private DOWNLOAD_ERRORS downloadError = DEFAULT;
+
+ private Provider provider;
+
public enum DOWNLOAD_ERRORS {
DEFAULT,
ERROR_CORRUPTED_PROVIDER_JSON,
@@ -50,52 +54,55 @@ public class DownloadFailedDialog extends DialogFragment {
/**
* @return a new instance of this DialogFragment.
*/
- public static DialogFragment newInstance(String reason_to_fail) {
- DownloadFailedDialog dialog_fragment = new DownloadFailedDialog();
- dialog_fragment.reason_to_fail = reason_to_fail;
- return dialog_fragment;
+ public static DialogFragment newInstance(Provider provider, String reasonToFail) {
+ DownloadFailedDialog dialogFragment = new DownloadFailedDialog();
+ dialogFragment.reasonToFail = reasonToFail;
+ dialogFragment.provider = provider;
+ return dialogFragment;
}
/**
* @return a new instance of this DialogFragment.
*/
- public static DialogFragment newInstance(JSONObject errorJson) {
- DownloadFailedDialog dialog_fragment = new DownloadFailedDialog();
+ public static DialogFragment newInstance(Provider provider, JSONObject errorJson) {
+ DownloadFailedDialog dialogFragment = new DownloadFailedDialog();
+ dialogFragment.provider = provider;
try {
if (errorJson.has(ERRORS)) {
- dialog_fragment.reason_to_fail = errorJson.getString(ERRORS);
+ dialogFragment.reasonToFail = errorJson.getString(ERRORS);
} else {
//default error msg
- dialog_fragment.reason_to_fail = dialog_fragment.getString(R.string.error_io_exception_user_message);
+ dialogFragment.reasonToFail = dialogFragment.getString(R.string.error_io_exception_user_message);
}
if (errorJson.has(ERRORID)) {
- dialog_fragment.downloadError = valueOf(errorJson.getString(ERRORID));
+ dialogFragment.downloadError = valueOf(errorJson.getString(ERRORID));
}
} catch (Exception e) {
e.printStackTrace();
- dialog_fragment.reason_to_fail = dialog_fragment.getString(R.string.error_io_exception_user_message);
+ dialogFragment.reasonToFail = dialogFragment.getString(R.string.error_io_exception_user_message);
}
- return dialog_fragment;
+ return dialogFragment;
}
@Override
+ @NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setMessage(reason_to_fail)
+ builder.setMessage(reasonToFail)
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- interface_with_ConfigurationWizard.cancelSettingUpProvider();
+ interfaceWithConfigurationWizard.cancelSettingUpProvider();
dialog.dismiss();
}
});
- switch (downloadError) {
+switch (downloadError) {
case ERROR_CORRUPTED_PROVIDER_JSON:
builder.setPositiveButton(R.string.update_provider_details, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dismiss();
- interface_with_ConfigurationWizard.updateProviderDetails();
+ interfaceWithConfigurationWizard.updateProviderDetails();
}
});
break;
@@ -105,7 +112,7 @@ public class DownloadFailedDialog extends DialogFragment {
@Override
public void onClick(DialogInterface dialog, int which) {
dismiss();
- interface_with_ConfigurationWizard.updateProviderDetails();
+ interfaceWithConfigurationWizard.updateProviderDetails();
}
});
break;
@@ -113,7 +120,7 @@ public class DownloadFailedDialog extends DialogFragment {
builder.setPositiveButton(R.string.retry, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dismiss();
- interface_with_ConfigurationWizard.retrySetUpProvider();
+ interfaceWithConfigurationWizard.retrySetUpProvider(provider);
}
});
break;
@@ -124,20 +131,20 @@ public class DownloadFailedDialog extends DialogFragment {
}
public interface DownloadFailedDialogInterface {
- void retrySetUpProvider();
+ void retrySetUpProvider(@NonNull Provider provider);
void cancelSettingUpProvider();
void updateProviderDetails();
}
- DownloadFailedDialogInterface interface_with_ConfigurationWizard;
+ DownloadFailedDialogInterface interfaceWithConfigurationWizard;
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
- interface_with_ConfigurationWizard = (DownloadFailedDialogInterface) context;
+ interfaceWithConfigurationWizard = (DownloadFailedDialogInterface) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement NoticeDialogListener");
@@ -146,7 +153,7 @@ public class DownloadFailedDialog extends DialogFragment {
@Override
public void onCancel(DialogInterface dialog) {
- interface_with_ConfigurationWizard.cancelSettingUpProvider();
+ interfaceWithConfigurationWizard.cancelSettingUpProvider();
dialog.dismiss();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
index 3c541e71..a082b047 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
@@ -18,20 +18,22 @@ package se.leap.bitmaskclient;
import android.app.Activity;
import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.os.Bundle;
-import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.ResultReceiver;
+import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
+import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.widget.AppCompatImageView;
import android.util.Log;
import android.view.LayoutInflater;
@@ -50,28 +52,37 @@ import de.blinkt.openvpn.core.IOpenVPNServiceInternal;
import de.blinkt.openvpn.core.OpenVPNService;
import de.blinkt.openvpn.core.ProfileManager;
import de.blinkt.openvpn.core.VpnStatus;
-import se.leap.bitmaskclient.eip.EIP;
+import se.leap.bitmaskclient.eip.EipCommand;
import se.leap.bitmaskclient.eip.EipStatus;
import se.leap.bitmaskclient.eip.VoidVpnService;
import se.leap.bitmaskclient.views.VpnStateImage;
+import static android.app.Activity.RESULT_OK;
+import static android.content.Intent.CATEGORY_DEFAULT;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK;
+import static se.leap.bitmaskclient.Constants.BROADCAST_EIP_EVENT;
+import static se.leap.bitmaskclient.Constants.BROADCAST_PROVIDER_API_EVENT;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_CHECK_CERT_VALIDITY;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_START;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP_BLOCKING_VPN;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_UPDATE;
import static se.leap.bitmaskclient.Constants.EIP_NOTIFICATION;
-import static se.leap.bitmaskclient.Constants.EIP_RECEIVER;
import static se.leap.bitmaskclient.Constants.EIP_REQUEST;
import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT;
-import static se.leap.bitmaskclient.Constants.EIP_TRIGGERED_FROM_UI;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOWED_REGISTERED;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS;
-import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
+import static se.leap.bitmaskclient.Constants.REQUEST_CODE_LOG_IN;
+import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER;
import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
+import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE;
+import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE;
public class EipFragment extends Fragment implements Observer {
@@ -83,6 +94,7 @@ public class EipFragment extends Fragment implements Observer {
private SharedPreferences preferences;
+ private Provider provider;
@InjectView(R.id.background)
AppCompatImageView background;
@@ -99,10 +111,11 @@ public class EipFragment extends Fragment implements Observer {
@InjectView(R.id.vpn_route)
TextView vpnRoute;
- private EIPReceiver eipReceiver;
private EipStatus eipStatus;
private boolean wantsToConnect;
+ private EIPFragmentBroadcastReceiver eipFragmentBroadcastReceiver;
+
private IOpenVPNServiceInternal mService;
private ServiceConnection openVpnConnection = new ServiceConnection() {
@@ -125,19 +138,38 @@ public class EipFragment extends Fragment implements Observer {
@Override
public void onAttach(Context context) {
super.onAttach(context);
- downloadEIPServiceConfig();
+ Bundle arguments = getArguments();
+ Activity activity = getActivity();
+ if (activity != null) {
+ if (arguments != null) {
+ provider = arguments.getParcelable(PROVIDER_KEY);
+ if (provider == null) {
+ activity.startActivityForResult(new Intent(activity, ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER);
+ } else {
+ Log.d(TAG, provider.getName() + " configured as provider");
+ }
+ } else {
+ Log.e(TAG, "no provider given - starting ProviderListActivity");
+ activity.startActivityForResult(new Intent(activity, ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER);
+ }
+ }
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
eipStatus = EipStatus.getInstance();
- eipReceiver = new EIPReceiver(new Handler());
- preferences = getActivity().getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE);
+ eipFragmentBroadcastReceiver = new EIPFragmentBroadcastReceiver();
+ Activity activity = getActivity();
+ if (activity != null) {
+ preferences = getActivity().getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE);
+ } else {
+ Log.e(TAG, "activity is null in onCreate - no preferences set!");
+ }
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
eipStatus.addObserver(this);
View view = inflater.inflate(R.layout.eip_service_fragment, container, false);
ButterKnife.inject(this, view);
@@ -154,6 +186,7 @@ public class EipFragment extends Fragment implements Observer {
super.onResume();
//FIXME: avoid race conditions while checking certificate an logging in at about the same time
//eipCommand(Constants.EIP_ACTION_CHECK_CERT_VALIDITY);
+ setUpBroadcastReceiver();
handleNewState();
bindOpenVpnService();
}
@@ -161,7 +194,13 @@ public class EipFragment extends Fragment implements Observer {
@Override
public void onPause() {
super.onPause();
- getActivity().unbindService(openVpnConnection);
+
+ Activity activity = getActivity();
+ if (activity != null) {
+ getActivity().unbindService(openVpnConnection);
+ LocalBroadcastManager.getInstance(activity).unregisterReceiver(eipFragmentBroadcastReceiver);
+ }
+ Log.d(TAG, "broadcast unregistered");
}
@Override
@@ -171,7 +210,7 @@ public class EipFragment extends Fragment implements Observer {
}
@Override
- public void onSaveInstanceState(Bundle outState) {
+ public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putBoolean(IS_CONNECTED, eipStatus.isConnected());
super.onSaveInstanceState(outState);
}
@@ -198,29 +237,36 @@ public class EipFragment extends Fragment implements Observer {
}
private void handleSwitchOn() {
- if (canStartEIP())
+ Context context = getContext();
+ if (context == null) {
+ Log.e(TAG, "context is null when switch turning on");
+ return;
+ }
+
+ if (canStartEIP()) {
startEipFromScratch();
- else if (canLogInToStartEIP()) {
+ } else if (canLogInToStartEIP()) {
wantsToConnect = true;
- /*Bundle bundle = new Bundle();
- seionDialogCallback.onSessionDialog(bundle);*/
- Log.w(TAG, "TODO: implement login from here");
- //FIXME: implement login from here
+ Intent intent = new Intent(getContext(), LoginActivity.class);
+ intent.putExtra(PROVIDER_KEY, provider);
+ Activity activity = getActivity();
+ if (activity != null) {
+ activity.startActivityForResult(intent, REQUEST_CODE_LOG_IN);
+ }
} else {
- Log.d(TAG, "WHAT IS GOING ON HERE?!");
- // TODO: implement a fallback: check if vpncertificate was not downloaded properly or give
- // a user feedback. A button that does nothing on click is not a good option
+ // provider has no VpnCertificate but user is logged in
+ downloadVpnCertificate();
}
}
private boolean canStartEIP() {
- boolean certificateExists = !preferences.getString(PROVIDER_VPN_CERTIFICATE, "").isEmpty();
- boolean isAllowedAnon = preferences.getBoolean(PROVIDER_ALLOW_ANONYMOUS, false);
+ boolean certificateExists = provider.hasVpnCertificate();
+ boolean isAllowedAnon = provider.allowsAnonymous();
return (isAllowedAnon || certificateExists) && !eipStatus.isConnected() && !eipStatus.isConnecting();
}
private boolean canLogInToStartEIP() {
- boolean isAllowedRegistered = preferences.getBoolean(PROVIDER_ALLOWED_REGISTERED, false);
+ boolean isAllowedRegistered = provider.allowsRegistered();
boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty();
return isAllowedRegistered && !isLoggedIn && !eipStatus.isConnecting() && !eipStatus.isConnected();
}
@@ -235,6 +281,10 @@ public class EipFragment extends Fragment implements Observer {
private void askPendingStartCancellation() {
Activity activity = getActivity();
+ if (activity == null) {
+ Log.e(TAG, "activity is null when asking to cancel");
+ return;
+ }
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity());
alertBuilder.setTitle(activity.getString(R.string.eip_cancel_connect_title))
.setMessage(activity.getString(R.string.eip_cancel_connect_text))
@@ -250,12 +300,18 @@ public class EipFragment extends Fragment implements Observer {
}
})
.show();
+
}
public void startEipFromScratch() {
+ Context context = getContext();
+ if (context == null) {
+ Log.e(TAG, "context is null when trying to start VPN");
+ return;
+ }
wantsToConnect = false;
saveStatus(true);
- eipCommand(EIP_ACTION_START);
+ EipCommand.startVPN(context, false);
vpnStateImage.showProgress();
routedText.setVisibility(GONE);
vpnRoute.setVisibility(GONE);
@@ -273,6 +329,11 @@ public class EipFragment extends Fragment implements Observer {
private void stopBlockingVpn() {
Log.d(TAG, "stop VoidVpn!");
Activity activity = getActivity();
+ if (activity == null) {
+ // TODO what to do if not stopping void vpn?
+ Log.e(TAG, "activity is null when trying to stop blocking vpn");
+ return;
+ }
Intent stopVoidVpnIntent = new Intent(activity, VoidVpnService.class);
stopVoidVpnIntent.setAction(EIP_ACTION_STOP_BLOCKING_VPN);
activity.startService(stopVoidVpnIntent);
@@ -290,18 +351,19 @@ public class EipFragment extends Fragment implements Observer {
}
protected void stopEipIfPossible() {
- //FIXME: no need to start a service here!
- eipCommand(EIP_ACTION_STOP);
- }
-
- private void downloadEIPServiceConfig() {
- ProviderAPIResultReceiver provider_api_receiver = new ProviderAPIResultReceiver(new Handler(), Dashboard.dashboardReceiver);
- if(eipReceiver != null)
- ProviderAPICommand.execute(Bundle.EMPTY, ProviderAPI.DOWNLOAD_EIP_SERVICE, provider_api_receiver);
+ Context context = getContext();
+ if (context == null) {
+ Log.e(TAG, "context is null when trying to stop EIP");
+ return;
+ }
+ EipCommand.stopVPN(getContext());
}
protected void askToStopEIP() {
Activity activity = getActivity();
+ if (activity == null) {
+ Log.e(TAG, "activity is null when asking to stop EIP");
+ }
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(activity);
alertBuilder.setTitle(activity.getString(R.string.eip_cancel_connect_title))
.setMessage(activity.getString(R.string.eip_warning_browser_inconsistency))
@@ -319,29 +381,6 @@ public class EipFragment extends Fragment implements Observer {
.show();
}
- protected void updateEipService() {
- eipCommand(EIP_ACTION_UPDATE);
- }
-
- /**
- * Send a command to EIP
- *
- * @param action A valid String constant from EIP class representing an Intent
- * filter for the EIP class
- */
- private void eipCommand(String action) {
- Activity activity = getActivity();
- if (activity == null) {
- return;
- }
- // TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
- Intent vpn_intent = new Intent(activity.getApplicationContext(), EIP.class);
- vpn_intent.setAction(action);
- vpn_intent.putExtra(EIP_TRIGGERED_FROM_UI, true);
- vpn_intent.putExtra(EIP_RECEIVER, eipReceiver);
- activity.startService(vpn_intent);
- }
-
@Override
public void update(Observable observable, Object data) {
if (observable instanceof EipStatus) {
@@ -363,6 +402,7 @@ public class EipFragment extends Fragment implements Observer {
private void handleNewState() {
Activity activity = getActivity();
if (activity == null) {
+ Log.e(TAG, "activity is null while trying to handle new state");
return;
}
@@ -406,76 +446,95 @@ public class EipFragment extends Fragment implements Observer {
private void bindOpenVpnService() {
Activity activity = getActivity();
+ if (activity == null) {
+ Log.e(TAG, "activity is null when binding OpenVpn");
+ return;
+ }
+
Intent intent = new Intent(activity, OpenVPNService.class);
intent.setAction(OpenVPNService.START_SERVICE);
activity.bindService(intent, openVpnConnection, Context.BIND_AUTO_CREATE);
- }
-
- protected class EIPReceiver extends ResultReceiver {
- EIPReceiver(Handler handler) {
- super(handler);
- }
+ }
+ private class EIPFragmentBroadcastReceiver extends BroadcastReceiver {
@Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- super.onReceiveResult(resultCode, resultData);
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "received Broadcast");
- String request = resultData.getString(EIP_REQUEST);
-
- if (request == null) {
+ String action = intent.getAction();
+ if (action == null) {
return;
}
- switch (request) {
- case EIP_ACTION_START:
- switch (resultCode) {
- case Activity.RESULT_OK:
- break;
- case Activity.RESULT_CANCELED:
- break;
- }
- break;
- case EIP_ACTION_STOP:
- switch (resultCode) {
- case Activity.RESULT_OK:
- stop();
- break;
- case Activity.RESULT_CANCELED:
- break;
- }
- break;
- case EIP_NOTIFICATION:
- switch (resultCode) {
- case Activity.RESULT_OK:
- break;
- case Activity.RESULT_CANCELED:
- break;
- }
+ int resultCode = intent.getIntExtra(BROADCAST_RESULT_CODE, -1);
+ Bundle resultData = intent.getParcelableExtra(BROADCAST_RESULT_KEY);
+ switch (action) {
+ case BROADCAST_EIP_EVENT:
+ handleEIPEvent(resultCode, resultData);
break;
- case EIP_ACTION_CHECK_CERT_VALIDITY:
- switch (resultCode) {
- case Activity.RESULT_OK:
- break;
- case Activity.RESULT_CANCELED:
- Dashboard.downloadVpnCertificate();
- break;
- }
+ case BROADCAST_PROVIDER_API_EVENT:
+ handleProviderApiEvent(resultCode, resultData);
break;
- case EIP_ACTION_UPDATE:
- switch (resultCode) {
- case Activity.RESULT_OK:
- if (wantsToConnect)
- startEipFromScratch();
- break;
- case Activity.RESULT_CANCELED:
- handleNewState();
- break;
- }
}
}
}
+ private void handleEIPEvent(int resultCode, Bundle resultData) {
+ String request = resultData.getString(EIP_REQUEST);
+
+ if (request == null) {
+ return;
+ }
+
+ switch (request) {
+ case EIP_ACTION_START:
+ switch (resultCode) {
+ case RESULT_OK:
+ break;
+ case Activity.RESULT_CANCELED:
+ break;
+ }
+ break;
+ case EIP_ACTION_STOP:
+ switch (resultCode) {
+ case RESULT_OK:
+ stop();
+ break;
+ case Activity.RESULT_CANCELED:
+ break;
+ }
+ break;
+ case EIP_NOTIFICATION:
+ switch (resultCode) {
+ case RESULT_OK:
+ break;
+ case Activity.RESULT_CANCELED:
+ break;
+ }
+ break;
+ case EIP_ACTION_CHECK_CERT_VALIDITY:
+ switch (resultCode) {
+ case RESULT_OK:
+ break;
+ case Activity.RESULT_CANCELED:
+ downloadVpnCertificate();
+ break;
+ }
+ break;
+ case EIP_ACTION_UPDATE:
+ switch (resultCode) {
+ case RESULT_OK:
+ if (wantsToConnect)
+ startEipFromScratch();
+ break;
+ case Activity.RESULT_CANCELED:
+ handleNewState();
+ break;
+ }
+ }
+ }
+
private void greyscaleBackground() {
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
@@ -494,4 +553,46 @@ public class EipFragment extends Fragment implements Observer {
background.setImageAlpha(210);
}
+ public void handleProviderApiEvent(int resultCode, Bundle resultData) {
+ Context context = getContext();
+ if (context == null) {
+ return;
+ }
+
+ // TODO call DOWNLOAD_EIP_SERVICES ore remove respective cases
+ switch (resultCode) {
+ case CORRECTLY_DOWNLOADED_EIP_SERVICE:
+ provider = resultData.getParcelable(PROVIDER_KEY);
+ EipCommand.updateEipService(context);
+ break;
+ case INCORRECTLY_DOWNLOADED_EIP_SERVICE:
+ //dashboard.setResult(RESULT_CANCELED);
+ // TODO CATCH ME IF YOU CAN - WHAT DO WE WANT TO DO?
+ break;
+ case CORRECTLY_DOWNLOADED_CERTIFICATE:
+ startEipFromScratch();
+ break;
+ case INCORRECTLY_DOWNLOADED_CERTIFICATE:
+ // TODO CATCH ME IF YOU CAN - LOGIN?
+ break;
+ }
+ }
+
+ private void downloadVpnCertificate() {
+ ProviderAPICommand.execute(getContext(), DOWNLOAD_CERTIFICATE, provider);
+ }
+
+ private void setUpBroadcastReceiver() {
+ Activity activity = getActivity();
+ if (activity != null) {
+ IntentFilter updateIntentFilter = new IntentFilter(BROADCAST_EIP_EVENT);
+ updateIntentFilter.addAction(BROADCAST_PROVIDER_API_EVENT);
+ updateIntentFilter.addCategory(CATEGORY_DEFAULT);
+ LocalBroadcastManager.getInstance(activity).registerReceiver(eipFragmentBroadcastReceiver, updateIntentFilter);
+ Log.d(TAG, "broadcast registered");
+ } else {
+ Log.e(TAG, "activity null when setting up broadcast receiver");
+ }
+ }
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/FeatureVersionCode.java b/app/src/main/java/se/leap/bitmaskclient/FeatureVersionCode.java
index b2a39c1a..969f006a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/FeatureVersionCode.java
+++ b/app/src/main/java/se/leap/bitmaskclient/FeatureVersionCode.java
@@ -2,4 +2,5 @@ package se.leap.bitmaskclient;
public interface FeatureVersionCode {
int MULTIPLE_PROFILES = 132;
+ int RENAMED_EIP_IN_PREFERENCES = 132;
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
index 186c2928..c82cef3b 100644
--- a/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/MainActivity.java
@@ -5,23 +5,29 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import se.leap.bitmaskclient.drawer.NavigationDrawerFragment;
-import se.leap.bitmaskclient.userstatus.SessionDialog;
+import se.leap.bitmaskclient.eip.EipCommand;
+import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP;
+import static se.leap.bitmaskclient.Constants.REQUEST_CODE_LOG_IN;
+import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER;
import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
import static se.leap.bitmaskclient.EipFragment.ASK_TO_CANCEL_VPN;
public class MainActivity extends AppCompatActivity {
+ private static Provider provider = new Provider();
+ private static FragmentManagerEnhanced fragmentManager;
private SharedPreferences preferences;
+ private NavigationDrawerFragment navigationDrawerFragment;
+
public final static String ACTION_SHOW_VPN_FRAGMENT = "action_show_vpn_fragment";
/**
@@ -32,13 +38,15 @@ public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
-
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
- NavigationDrawerFragment navigationDrawerFragment = (NavigationDrawerFragment)
+ navigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
+ provider = ConfigHelper.getSavedProviderFromSharedPreferences(preferences);
+
+ fragmentManager = new FragmentManagerEnhanced(getSupportFragmentManager());
// Set up the drawer.
navigationDrawerFragment.setUp(
R.id.navigation_drawer,
@@ -63,11 +71,12 @@ public class MainActivity extends AppCompatActivity {
switch (intent.getAction()) {
case ACTION_SHOW_VPN_FRAGMENT:
fragment = new EipFragment();
+ Bundle bundle = new Bundle();
if (intent.hasExtra(ASK_TO_CANCEL_VPN)) {
- Bundle bundle = new Bundle();
bundle.putBoolean(ASK_TO_CANCEL_VPN, true);
- fragment.setArguments(bundle);
}
+ bundle.putParcelable(PROVIDER_KEY, provider);
+ fragment.setArguments(bundle);
break;
default:
break;
@@ -82,15 +91,39 @@ public class MainActivity extends AppCompatActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
if (data == null) {
return;
}
- if (requestCode == REQUEST_CODE_CONFIGURE_LEAP) {
- if (resultCode == RESULT_OK && data.hasExtra(Provider.KEY)) {
- Provider provider = data.getParcelableExtra(Provider.KEY);
- ConfigHelper.storeProviderInPreferences(preferences, provider);
+ if (resultCode == RESULT_OK && data.hasExtra(Provider.KEY)) {
+ provider = data.getParcelableExtra(Provider.KEY);
+
+ if (provider == null) {
+ return;
+ }
+
+ ConfigHelper.storeProviderInPreferences(preferences, provider);
+ navigationDrawerFragment.refresh();
+
+ switch (requestCode) {
+ case REQUEST_CODE_SWITCH_PROVIDER:
+ EipCommand.stopVPN(this);
+ break;
+ case REQUEST_CODE_CONFIGURE_LEAP:
+ break;
+ case REQUEST_CODE_LOG_IN:
+ EipCommand.startVPN(this, true);
+ break;
}
}
+
+ Fragment fragment = new EipFragment();
+ Bundle arguments = new Bundle();
+ arguments.putParcelable(PROVIDER_KEY, provider);
+ fragment.setArguments(arguments);
+ fragmentManager.beginTransaction()
+ .replace(R.id.container, fragment)
+ .commit();
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java b/app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java
index 1bf679f8..40b2ea7f 100644
--- a/app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java
+++ b/app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java
@@ -59,11 +59,9 @@ import static se.leap.bitmaskclient.R.string.server_unreachable_message;
public class OkHttpClientGenerator {
- SharedPreferences preferences;
Resources resources;
public OkHttpClientGenerator(SharedPreferences preferences, Resources resources) {
- this.preferences = preferences;
this.resources = resources;
}
@@ -71,16 +69,10 @@ public class OkHttpClientGenerator {
return initHttpClient(initError, null);
}
- public OkHttpClient initSelfSignedCAHttpClient(JSONObject initError) {
- String certificate = preferences.getString(Provider.CA_CERT, "");
- return initHttpClient(initError, certificate);
+ public OkHttpClient initSelfSignedCAHttpClient(String caCert, JSONObject initError) {
+ return initHttpClient(initError, caCert);
}
- public OkHttpClient initSelfSignedCAHttpClient(JSONObject initError, String certificate) {
- return initHttpClient(initError, certificate);
- }
-
-
private OkHttpClient initHttpClient(JSONObject initError, String certificate) {
try {
TLSCompatSocketFactory sslCompatFactory;
diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java
index 5ff1949c..b3362409 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java
@@ -16,18 +16,21 @@
*/
package se.leap.bitmaskclient;
-import android.content.SharedPreferences;
-import android.os.*;
+import android.os.Parcel;
+import android.os.Parcelable;
import com.google.gson.Gson;
-import org.json.*;
+import org.json.JSONException;
+import org.json.JSONObject;
-import java.io.Serializable;
-import java.net.*;
-import java.util.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Locale;
-import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED;
+import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOWED_REGISTERED;
+import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS;
+import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
/**
* @author Sean Leonard <meanderingcode@aetherislands.net>
@@ -36,11 +39,18 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED;
public final class Provider implements Parcelable {
private JSONObject definition = new JSONObject(); // Represents our Provider's provider.json
+ private JSONObject eipServiceJson = new JSONObject();
private DefaultedURL mainUrl = new DefaultedURL();
private DefaultedURL apiUrl = new DefaultedURL();
private String certificatePin = "";
private String certificatePinEncoding = "";
private String caCert = "";
+ private String apiVersion = "";
+ private String privateKey = "";
+ private String vpnCertificate = "";
+
+ private boolean allowAnonymous;
+ private boolean allowRegistered;
final public static String
API_URL = "api_uri",
@@ -55,20 +65,20 @@ public final class Provider implements Parcelable {
NAME = "name",
DESCRIPTION = "description",
DOMAIN = "domain",
- MAIN_URL = "main_url",
- DOT_JSON_URL = "provider_json_url";
+ MAIN_URL = "main_url";
- // Array of what API versions we understand
- protected static final String[] API_VERSIONS = {"1"}; // I assume we might encounter arbitrary version "numbers"
- // Some API pieces we want to know about
- private static final String API_TERM_SERVICES = "services";
private static final String API_TERM_NAME = "name";
- private static final String API_TERM_DOMAIN = "domain";
- private static final String API_TERM_DEFAULT_LANGUAGE = "default_language";
- protected static final String[] API_EIP_TYPES = {"openvpn"};
public Provider() { }
+ public Provider(String mainUrl) {
+ try {
+ this.mainUrl.setUrl(new URL(mainUrl));
+ } catch (MalformedURLException e) {
+ this.mainUrl = new DefaultedURL();
+ }
+ }
+
public Provider(URL mainUrl) {
this.mainUrl.setUrl(mainUrl);
}
@@ -108,16 +118,42 @@ public final class Provider implements Parcelable {
!caCert.isEmpty();
}
- protected void setUrl(URL url) {
+ public void setMainUrl(URL url) {
mainUrl.setUrl(url);
}
- protected void define(JSONObject provider_json) {
- definition = provider_json;
- parseDefinition(definition);
+ public void setMainUrl(String url) {
+ try {
+ mainUrl.setUrl(new URL(url));
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
}
- protected JSONObject getDefinition() {
+ public boolean define(JSONObject providerJson) {
+ /*
+ * fix against "api_uri": "https://calyx.net.malicious.url.net:4430",
+ * This method aims to prevent attacks where the provider.json file got manipulated by a third party.
+ * The main url should not change.
+ */
+
+ try {
+ String providerApiUrl = providerJson.getString(Provider.API_URL);
+ String providerDomain = providerJson.getString(Provider.DOMAIN);
+ if (getMainUrlString().contains(providerDomain) && providerApiUrl.contains(providerDomain + ":")) {
+ definition = providerJson;
+ parseDefinition(definition);
+ return true;
+ } else {
+ return false;
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public JSONObject getDefinition() {
return definition;
}
@@ -141,10 +177,17 @@ public final class Provider implements Parcelable {
return apiUrl;
}
- protected String certificatePin() { return certificatePin; }
+ protected String getApiUrlWithVersion() {
+ return getApiUrlString() + "/" + getApiVersion();
+ }
+
+
+ protected String getApiUrlString() {
+ return getApiUrl().toString();
+ }
- protected boolean hasCertificatePin() {
- return certificatePin != null && !certificatePin.isEmpty();
+ public String getApiVersion() {
+ return apiVersion;
}
boolean hasCaCert() {
@@ -200,26 +243,8 @@ public final class Provider implements Parcelable {
}
protected boolean hasEIP() {
- try {
- JSONArray services = definition.getJSONArray(API_TERM_SERVICES); // returns ["openvpn"]
- for (int i = 0; i < API_EIP_TYPES.length + 1; i++) {
- try {
- // 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();
- return false;
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- }
- }
- } catch (Exception e) {
- // TODO: handle exception
- }
- return false;
+ return getEipServiceJson() != null && getEipServiceJson().length() > 0
+ && !getEipServiceJson().has(ERRORS);
}
public boolean allowsRegistration() {
@@ -237,19 +262,31 @@ public final class Provider implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int i) {
- if(mainUrl != null)
- parcel.writeString(mainUrl.toString());
- if (definition != null)
- parcel.writeString(definition.toString());
- if (caCert != null)
- parcel.writeString(caCert);
+ parcel.writeString(getMainUrlString());
+ parcel.writeString(getDefinitionString());
+ parcel.writeString(getCaCert());
+ parcel.writeString(getEipServiceJsonString());
+ parcel.writeString(getPrivateKey());
+ parcel.writeString(getVpnCertificate());
}
@Override
public boolean equals(Object o) {
if (o instanceof Provider) {
Provider p = (Provider) o;
- return p.getDomain().equals(getDomain());
+ return p.getDomain().equals(getDomain()) &&
+ definition.toString().equals(p.getDefinition().toString()) &&
+ eipServiceJson.toString().equals(p.getEipServiceJson().toString())&&
+ mainUrl.equals(p.getMainUrl()) &&
+ apiUrl.equals(p.getApiUrl()) &&
+ certificatePin.equals(p.getCertificatePin()) &&
+ certificatePinEncoding.equals(p.getCertificatePinEncoding()) &&
+ caCert.equals(p.getCaCert()) &&
+ apiVersion.equals(p.getApiVersion()) &&
+ privateKey.equals(p.getPrivateKey()) &&
+ vpnCertificate.equals(p.getVpnCertificate()) &&
+ allowAnonymous == p.allowsAnonymous() &&
+ allowRegistered == p.allowsRegistered();
} else return false;
}
@@ -280,14 +317,26 @@ public final class Provider implements Parcelable {
private Provider(Parcel in) {
try {
mainUrl.setUrl(new URL(in.readString()));
- String definitionString = in.readString();
- if (!definitionString.isEmpty()) {
- definition = new JSONObject((definitionString));
+ String tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ definition = new JSONObject((tmpString));
parseDefinition(definition);
}
- String caCert = in.readString();
- if (!caCert.isEmpty()) {
- this.caCert = caCert;
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ this.caCert = tmpString;
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ this.setEipServiceJson(new JSONObject(tmpString));
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ this.setPrivateKey(tmpString);
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
+ this.setVpnCertificate(tmpString);
}
} catch (MalformedURLException | JSONException e) {
e.printStackTrace();
@@ -300,15 +349,41 @@ public final class Provider implements Parcelable {
this.certificatePin = pin.split(":")[1].trim();
this.certificatePinEncoding = pin.split(":")[0].trim();
this.apiUrl.setUrl(new URL(definition.getString(API_URL)));
+ this.allowAnonymous = definition.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOW_ANONYMOUS);
+ this.allowRegistered = definition.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOWED_REGISTERED);
+ this.apiVersion = getDefinition().getString(Provider.API_VERSION);
} catch (JSONException | ArrayIndexOutOfBoundsException | MalformedURLException e) {
e.printStackTrace();
}
}
- public void setCACert(String cert) {
+ public void setCaCert(String cert) {
this.caCert = cert;
}
+ public boolean allowsAnonymous() {
+ return allowAnonymous;
+ }
+
+ public boolean allowsRegistered() {
+ return allowRegistered;
+ }
+
+ public boolean setEipServiceJson(JSONObject eipServiceJson) {
+ if (eipServiceJson.has(ERRORS)) {
+ return false;
+ }
+ this.eipServiceJson = eipServiceJson;
+ return true;
+ }
+
+ public JSONObject getEipServiceJson() {
+ return eipServiceJson;
+ }
+
+ public String getEipServiceJsonString() {
+ return getEipServiceJson().toString();
+ }
public boolean isDefault() {
return getMainUrl().isDefault() &&
getApiUrl().isDefault() &&
@@ -317,4 +392,53 @@ public final class Provider implements Parcelable {
caCert.isEmpty();
}
+ public String getPrivateKey() {
+ return privateKey;
+ }
+
+ public void setPrivateKey(String privateKey) {
+ this.privateKey = privateKey;
+ }
+
+ public String getVpnCertificate() {
+ return vpnCertificate;
+ }
+
+ public void setVpnCertificate(String vpnCertificate) {
+ this.vpnCertificate = vpnCertificate;
+ }
+
+ public boolean hasVpnCertificate() {
+ return getVpnCertificate() != null && getVpnCertificate().length() >0 ;
+ }
+
+ public String getCertificatePin() {
+ return certificatePin;
+ }
+
+ public String getCertificatePinEncoding() {
+ return certificatePinEncoding;
+ }
+
+ public String getCaCertFingerprint() {
+ return getCertificatePinEncoding() + ":" + getCertificatePin();
+ }
+
+ /**
+ * resets everything except the main url
+ */
+ public void reset() {
+ definition = new JSONObject();
+ eipServiceJson = new JSONObject();
+ apiUrl = new DefaultedURL();
+ certificatePin = "";
+ certificatePinEncoding = "";
+ caCert = "";
+ apiVersion = "";
+ privateKey = "";
+ vpnCertificate = "";
+ allowRegistered = false;
+ allowAnonymous = false;
+ }
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java
index ccc71a67..b3399416 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint;
import android.app.IntentService;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.support.v4.content.LocalBroadcastManager;
import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
@@ -40,22 +41,17 @@ public class ProviderAPI extends IntentService implements ProviderApiManagerBase
TAG = ProviderAPI.class.getSimpleName(),
SET_UP_PROVIDER = "setUpProvider",
UPDATE_PROVIDER_DETAILS = "updateProviderDetails",
- DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON",
SIGN_UP = "srpRegister",
LOG_IN = "srpAuth",
LOG_OUT = "logOut",
DOWNLOAD_CERTIFICATE = "downloadUserAuthedCertificate",
PARAMETERS = "parameters",
- RESULT_KEY = "result",
- RESULT_CODE = "RESULT CODE",
RECEIVER_KEY = "receiver",
ERRORS = "errors",
ERRORID = "errorId",
UPDATE_PROGRESSBAR = "update_progressbar",
- CURRENT_PROGRESS = "current_progress",
- DOWNLOAD_EIP_SERVICE = TAG + ".DOWNLOAD_EIP_SERVICE",
- PROVIDER_SET_UP = TAG + ".PROVIDER_SET_UP",
- PROVIDER_API_EVENT = "PROVIDER_API_EVENT";
+ DOWNLOAD_EIP_SERVICE = "ProviderAPI.DOWNLOAD_EIP_SERVICE",
+ PROVIDER_SET_UP = "ProviderAPI.PROVIDER_SET_UP";
final public static int
SUCCESSFUL_LOGIN = 3,
@@ -80,21 +76,6 @@ public class ProviderAPI extends IntentService implements ProviderApiManagerBase
}
//TODO: refactor me, please!
- public static void stop() {
- ProviderApiManager.stop();
- }
-
- //TODO: refactor me, please!
- public static boolean caCertDownloaded() {
- return ProviderApiManager.caCertDownloaded();
- }
-
- //TODO: refactor me, please!
- public static String lastProviderMainUrl() {
- return ProviderApiManager.lastProviderMainUrl();
- }
-
- //TODO: refactor me, please!
//used in insecure flavor only
@SuppressLint("unused")
public static boolean lastDangerOn() {
@@ -110,7 +91,7 @@ public class ProviderAPI extends IntentService implements ProviderApiManagerBase
@Override
public void broadcastEvent(Intent intent) {
- sendBroadcast(intent);
+ LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
@Override
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java
index 0e4cfe8a..65d01b22 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java
@@ -6,40 +6,74 @@ import android.os.*;
import org.jetbrains.annotations.*;
public class ProviderAPICommand {
- private static Context context;
+ private Context context;
- private static String action;
- private static Bundle parameters;
- private static ResultReceiver result_receiver;
+ private String action;
+ private Bundle parameters;
+ private ResultReceiver resultReceiver;
+ private Provider provider;
- public static void initialize(Context context) {
- ProviderAPICommand.context = context;
+ private ProviderAPICommand(@NotNull Context context, @NotNull String action, @NotNull Provider provider, ResultReceiver resultReceiver) {
+ this(context, action, Bundle.EMPTY, provider, resultReceiver);
+ }
+ private ProviderAPICommand(@NotNull Context context, @NotNull String action, @NotNull Provider provider) {
+ this(context, action, Bundle.EMPTY, provider);
}
- private static boolean isInitialized() {
- return context != null;
+ private ProviderAPICommand(@NotNull Context context, @NotNull String action, @NotNull Bundle parameters, @NotNull Provider provider) {
+ this(context, action, parameters, provider, null);
}
- public static void execute(Bundle parameters, @NotNull String action, @NotNull ResultReceiver result_receiver) throws IllegalStateException {
- if(!isInitialized()) throw new IllegalStateException();
+ private ProviderAPICommand(@NotNull Context context, @NotNull String action, @NotNull Bundle parameters, @NotNull Provider provider, @Nullable ResultReceiver resultReceiver) {
+ super();
+ this.context = context;
+ this.action = action;
+ this.parameters = parameters;
+ this.resultReceiver = resultReceiver;
+ this.provider = provider;
+ }
- ProviderAPICommand.action = action;
- ProviderAPICommand.parameters = parameters;
- ProviderAPICommand.result_receiver = result_receiver;
+ private boolean isInitialized() {
+ return context != null;
+ }
- Intent intent = setUpIntent();
- context.startService(intent);
+ private void execute() {
+ if (isInitialized()) {
+ Intent intent = setUpIntent();
+ context.startService(intent);
+ }
}
- private static Intent setUpIntent() {
+ private Intent setUpIntent() {
Intent command = new Intent(context, ProviderAPI.class);
command.setAction(action);
command.putExtra(ProviderAPI.PARAMETERS, parameters);
- command.putExtra(ProviderAPI.RECEIVER_KEY, result_receiver);
+ if (resultReceiver != null) {
+ command.putExtra(ProviderAPI.RECEIVER_KEY, resultReceiver);
+ }
+ command.putExtra(Constants.PROVIDER_KEY, provider);
return command;
}
+ public static void execute(Context context, String action, Provider provider) {
+ ProviderAPICommand command = new ProviderAPICommand(context, action, provider);
+ command.execute();
+ }
+ public static void execute(Context context, String action, Bundle parameters, Provider provider) {
+ ProviderAPICommand command = new ProviderAPICommand(context, action, parameters, provider);
+ command.execute();
+ }
+
+ public static void execute(Context context, String action, Bundle parameters, Provider provider, ResultReceiver resultReceiver) {
+ ProviderAPICommand command = new ProviderAPICommand(context, action, parameters, provider, resultReceiver);
+ command.execute();
+ }
+
+ public static void execute(Context context, String action, Provider provider, ResultReceiver resultReceiver) {
+ ProviderAPICommand command = new ProviderAPICommand(context, action, provider, resultReceiver);
+ command.execute();
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
index 8117fb99..505ee55b 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
@@ -24,6 +24,7 @@ import android.os.Bundle;
import android.os.ResultReceiver;
import android.support.annotation.NonNull;
import android.util.Base64;
+import android.util.Log;
import android.util.Pair;
import org.json.JSONException;
@@ -49,22 +50,22 @@ import java.util.List;
import javax.net.ssl.SSLHandshakeException;
import okhttp3.OkHttpClient;
-import se.leap.bitmaskclient.userstatus.SessionDialog;
-import se.leap.bitmaskclient.userstatus.User;
-import se.leap.bitmaskclient.userstatus.UserStatus;
+import se.leap.bitmaskclient.Constants.CREDENTIAL_ERRORS;
import static se.leap.bitmaskclient.ConfigHelper.getFingerprintFromCertificate;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOWED_REGISTERED;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS;
+import static se.leap.bitmaskclient.Constants.BROADCAST_PROVIDER_API_EVENT;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
+import static se.leap.bitmaskclient.Constants.CREDENTIALS_PASSWORD;
+import static se.leap.bitmaskclient.Constants.CREDENTIALS_USERNAME;
+import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY;
import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_CERTIFICATE_PINNING;
import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_CORRUPTED_PROVIDER_JSON;
import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_INVALID_CERTIFICATE;
-import static se.leap.bitmaskclient.Provider.MAIN_URL;
import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE;
-import static se.leap.bitmaskclient.ProviderAPI.CURRENT_PROGRESS;
import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_EIP_SERVICE;
import static se.leap.bitmaskclient.ProviderAPI.ERRORID;
@@ -73,23 +74,19 @@ import static se.leap.bitmaskclient.ProviderAPI.FAILED_LOGIN;
import static se.leap.bitmaskclient.ProviderAPI.FAILED_SIGNUP;
import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE;
-import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_API_EVENT;
-import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_SET_UP;
import static se.leap.bitmaskclient.ProviderAPI.LOGOUT_FAILED;
import static se.leap.bitmaskclient.ProviderAPI.LOG_IN;
import static se.leap.bitmaskclient.ProviderAPI.LOG_OUT;
import static se.leap.bitmaskclient.ProviderAPI.PARAMETERS;
import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_NOK;
import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_OK;
+import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_SET_UP;
import static se.leap.bitmaskclient.ProviderAPI.RECEIVER_KEY;
-import static se.leap.bitmaskclient.ProviderAPI.RESULT_CODE;
-import static se.leap.bitmaskclient.ProviderAPI.RESULT_KEY;
import static se.leap.bitmaskclient.ProviderAPI.SET_UP_PROVIDER;
import static se.leap.bitmaskclient.ProviderAPI.SIGN_UP;
import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_LOGIN;
import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_LOGOUT;
import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_SIGNUP;
-import static se.leap.bitmaskclient.ProviderAPI.UPDATE_PROGRESSBAR;
import static se.leap.bitmaskclient.ProviderAPI.UPDATE_PROVIDER_DETAILS;
import static se.leap.bitmaskclient.R.string.certificate_error;
import static se.leap.bitmaskclient.R.string.error_io_exception_user_message;
@@ -109,36 +106,19 @@ import static se.leap.bitmaskclient.R.string.warning_expired_provider_cert;
public abstract class ProviderApiManagerBase {
+ private final static String TAG = ProviderApiManagerBase.class.getName();
+
public interface ProviderApiServiceCallback {
void broadcastEvent(Intent intent);
}
private ProviderApiServiceCallback serviceCallback;
- protected static volatile boolean
- CA_CERT_DOWNLOADED = false,
- PROVIDER_JSON_DOWNLOADED = false,
- EIP_SERVICE_JSON_DOWNLOADED = false;
-
- protected static String lastProviderMainUrl;
- protected static boolean go_ahead = true;
- protected static SharedPreferences preferences;
- protected static String providerApiUrl;
- protected static String providerCaCertFingerprint;
- protected static String providerCaCert;
- protected static JSONObject providerDefinition;
+ protected SharedPreferences preferences;
protected Resources resources;
- protected OkHttpClientGenerator clientGenerator;
-
- public static void stop() {
- go_ahead = false;
- }
-
- public static String lastProviderMainUrl() {
- return lastProviderMainUrl;
- }
+ OkHttpClientGenerator clientGenerator;
- public ProviderApiManagerBase(SharedPreferences preferences, Resources resources, OkHttpClientGenerator clientGenerator, ProviderApiServiceCallback callback) {
+ ProviderApiManagerBase(SharedPreferences preferences, Resources resources, OkHttpClientGenerator clientGenerator, ProviderApiServiceCallback callback) {
this.preferences = preferences;
this.resources = resources;
this.serviceCallback = callback;
@@ -150,96 +130,92 @@ public abstract class ProviderApiManagerBase {
String action = command.getAction();
Bundle parameters = command.getBundleExtra(PARAMETERS);
- if (providerApiUrl == null && preferences.contains(Provider.KEY)) {
- try {
- JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
- providerApiUrl = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION);
- go_ahead = true;
- } catch (JSONException e) {
- go_ahead = false;
- }
+ Provider provider = command.getParcelableExtra(PROVIDER_KEY);
+
+ if (provider == null) {
+ Log.e(TAG, action +" called without provider!");
+ return;
+ }
+ if (action == null) {
+ Log.e(TAG, "Intent without action sent!");
+ return;
}
- if (action.equals(UPDATE_PROVIDER_DETAILS)) {
- resetProviderDetails();
- Bundle task = new Bundle();
- String mainUrl = parameters.getString(Provider.MAIN_URL);
- if (mainUrl == null) {
- mainUrl = lastProviderMainUrl;
- }
- task.putString(MAIN_URL, mainUrl);
- Bundle result = setUpProvider(task);
- if (result.getBoolean(RESULT_KEY)) {
- sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result);
- } else {
- sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result);
- }
- } else if (action.equalsIgnoreCase(SET_UP_PROVIDER)) {
- Bundle result = setUpProvider(parameters);
- if (go_ahead) {
- if (result.getBoolean(RESULT_KEY)) {
- sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result);
+ Bundle result = new Bundle();
+ switch (action) {
+ case UPDATE_PROVIDER_DETAILS:
+ resetProviderDetails(provider);
+ Bundle task = new Bundle();
+ result = setUpProvider(provider, task);
+ if (result.getBoolean(BROADCAST_RESULT_KEY)) {
+ sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider);
} else {
- sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result);
+ sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider);
}
- }
- } else if (action.equalsIgnoreCase(SIGN_UP)) {
- UserStatus.updateStatus(UserStatus.SessionStatus.SIGNING_UP, resources);
- Bundle result = tryToRegister(parameters);
- if (result.getBoolean(RESULT_KEY)) {
- sendToReceiverOrBroadcast(receiver, SUCCESSFUL_SIGNUP, result);
- } else {
- sendToReceiverOrBroadcast(receiver, FAILED_SIGNUP, result);
- }
- } else if (action.equalsIgnoreCase(LOG_IN)) {
- UserStatus.updateStatus(UserStatus.SessionStatus.LOGGING_IN, resources);
- Bundle result = tryToAuthenticate(parameters);
- if (result.getBoolean(RESULT_KEY)) {
- sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGIN, result);
- UserStatus.updateStatus(UserStatus.SessionStatus.LOGGED_IN, resources);
- } else {
- sendToReceiverOrBroadcast(receiver, FAILED_LOGIN, result);
- UserStatus.updateStatus(UserStatus.SessionStatus.NOT_LOGGED_IN, resources);
- }
- } else if (action.equalsIgnoreCase(LOG_OUT)) {
- UserStatus.updateStatus(UserStatus.SessionStatus.LOGGING_OUT, resources);
- if (logOut()) {
- sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGOUT, Bundle.EMPTY);
- UserStatus.updateStatus(UserStatus.SessionStatus.LOGGED_OUT, resources);
- } else {
- sendToReceiverOrBroadcast(receiver, LOGOUT_FAILED, Bundle.EMPTY);
- UserStatus.updateStatus(UserStatus.SessionStatus.DIDNT_LOG_OUT, resources);
- }
- } else if (action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)) {
- if (updateVpnCertificate()) {
- sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY);
- } else {
- sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY);
- }
- } else if (action.equalsIgnoreCase(DOWNLOAD_EIP_SERVICE)) {
- Bundle result = getAndSetEipServiceJson();
- if (result.getBoolean(RESULT_KEY)) {
- sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_EIP_SERVICE, result);
- } else {
- sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_EIP_SERVICE, result);
- }
- } else if (action.equalsIgnoreCase(PROVIDER_SET_UP)) {
- if(EIP_SERVICE_JSON_DOWNLOADED && CA_CERT_DOWNLOADED && PROVIDER_JSON_DOWNLOADED ) {
- if(receiver!= null) {
- sendToReceiverOrBroadcast(receiver, PROVIDER_OK, Bundle.EMPTY);
+ break;
+ case SET_UP_PROVIDER:
+ result = setUpProvider(provider, parameters);
+ if (result.getBoolean(BROADCAST_RESULT_KEY)) {
+ sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider);
+ } else {
+ sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider);
}
- }
+ break;
+ case SIGN_UP:
+ result = tryToRegister(parameters);
+ if (result.getBoolean(BROADCAST_RESULT_KEY)) {
+ sendToReceiverOrBroadcast(receiver, SUCCESSFUL_SIGNUP, result, provider);
+ } else {
+ sendToReceiverOrBroadcast(receiver, FAILED_SIGNUP, result, provider);
+ }
+ break;
+ case LOG_IN:
+ result = tryToAuthenticate(provider, parameters);
+ if (result.getBoolean(BROADCAST_RESULT_KEY)) {
+ sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGIN, result, provider);
+ } else {
+ sendToReceiverOrBroadcast(receiver, FAILED_LOGIN, result, provider);
+ }
+ break;
+ case LOG_OUT:
+ if (logOut(provider)) {
+ sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGOUT, Bundle.EMPTY, provider);
+ } else {
+ sendToReceiverOrBroadcast(receiver, LOGOUT_FAILED, Bundle.EMPTY, provider);
+ }
+ break;
+ case DOWNLOAD_CERTIFICATE:
+ if (updateVpnCertificate(provider)) {
+ sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY, provider);
+ } else {
+ sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY, provider);
+ }
+ break;
+ case DOWNLOAD_EIP_SERVICE:
+ result = getAndSetEipServiceJson(provider);
+ if (result.getBoolean(BROADCAST_RESULT_KEY)) {
+ sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_EIP_SERVICE, result, provider);
+ } else {
+ sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_EIP_SERVICE, result, provider);
+ }
+ break;
+ case PROVIDER_SET_UP:
+ if(provider.hasEIP() && provider.hasCaCert() && provider.hasDefinition()) {
+ if(receiver!= null) {
+ result.putParcelable(PROVIDER_KEY, provider);
+ receiver.send(PROVIDER_OK, result);
+ }
+ }
+ break;
}
}
- protected void resetProviderDetails() {
- CA_CERT_DOWNLOADED = PROVIDER_JSON_DOWNLOADED = false;
- deleteProviderDetailsFromPreferences(providerDefinition);
- providerCaCert = "";
- providerDefinition = new JSONObject();
+ void resetProviderDetails(Provider provider) {
+ provider.reset();
+ ConfigHelper.deleteProviderDetailsFromPreferences(preferences, provider.getDomain());
}
- protected String formatErrorMessage(final int toastStringId) {
+ String formatErrorMessage(final int toastStringId) {
return formatErrorMessage(resources.getString(toastStringId));
}
@@ -256,7 +232,7 @@ public abstract class ProviderApiManagerBase {
}
}
- protected void addErrorMessageToJson(JSONObject jsonObject, String errorMessage) {
+ private void addErrorMessageToJson(JSONObject jsonObject, String errorMessage) {
try {
jsonObject.put(ERRORS, errorMessage);
} catch (JSONException e) {
@@ -264,7 +240,7 @@ public abstract class ProviderApiManagerBase {
}
}
- protected void addErrorMessageToJson(JSONObject jsonObject, String errorMessage, String errorId) {
+ private void addErrorMessageToJson(JSONObject jsonObject, String errorMessage, String errorId) {
try {
jsonObject.put(ERRORS, errorMessage);
jsonObject.put(ERRORID, errorId);
@@ -278,32 +254,37 @@ public abstract class ProviderApiManagerBase {
private Bundle tryToRegister(Bundle task) {
Bundle result = new Bundle();
- int progress = 0;
- String username = User.userName();
- String password = task.getString(SessionDialog.PASSWORD);
+ String username = task.getString(CREDENTIALS_USERNAME);
+ String password = task.getString(CREDENTIALS_PASSWORD);
+ Provider provider = task.getParcelable(PROVIDER_KEY);
+
+ if(provider == null) {
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ Log.e(TAG, "no provider when trying to register");
+ return result;
+ }
if (validUserLoginData(username, password)) {
- result = register(username, password);
- broadcastProgress(progress++);
+ result = register(provider, username, password);
} else {
if (!wellFormedPassword(password)) {
- result.putBoolean(RESULT_KEY, false);
- result.putString(SessionDialog.USERNAME, username);
- result.putBoolean(SessionDialog.ERRORS.PASSWORD_INVALID_LENGTH.toString(), true);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ result.putString(CREDENTIALS_USERNAME, username);
+ result.putBoolean(CREDENTIAL_ERRORS.PASSWORD_INVALID_LENGTH.toString(), true);
}
if (!validUsername(username)) {
- result.putBoolean(RESULT_KEY, false);
- result.putBoolean(SessionDialog.ERRORS.USERNAME_MISSING.toString(), true);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ result.putBoolean(CREDENTIAL_ERRORS.USERNAME_MISSING.toString(), true);
}
}
return result;
}
- private Bundle register(String username, String password) {
+ private Bundle register(Provider provider, String username, String password) {
JSONObject stepResult = null;
- OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(stepResult);
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), stepResult);
if (okHttpClient == null) {
return authFailedNotification(stepResult, username);
}
@@ -313,15 +294,15 @@ public abstract class ProviderApiManagerBase {
BigInteger password_verifier = client.calculateV(username, password, salt);
- JSONObject api_result = sendNewUserDataToSRPServer(providerApiUrl, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16), okHttpClient);
+ JSONObject api_result = sendNewUserDataToSRPServer(provider.getApiUrlString(), username, new BigInteger(1, salt).toString(16), password_verifier.toString(16), okHttpClient);
Bundle result = new Bundle();
if (api_result.has(ERRORS))
result = authFailedNotification(api_result, username);
else {
- result.putString(SessionDialog.USERNAME, username);
- result.putString(SessionDialog.PASSWORD, password);
- result.putBoolean(RESULT_KEY, true);
+ result.putString(CREDENTIALS_USERNAME, username);
+ result.putString(CREDENTIALS_PASSWORD, password);
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
}
return result;
@@ -330,37 +311,39 @@ public abstract class ProviderApiManagerBase {
/**
* Starts the authentication process using SRP protocol.
*
- * @param task containing: username, password and api url.
- * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if authentication was successful.
+ * @param task containing: username, password and provider
+ * @return a bundle with a boolean value mapped to a key named BROADCAST_RESULT_KEY, and which is true if authentication was successful.
*/
- private Bundle tryToAuthenticate(Bundle task) {
+ private Bundle tryToAuthenticate(Provider provider, Bundle task) {
Bundle result = new Bundle();
- int progress = 0;
- String username = User.userName();
- String password = task.getString(SessionDialog.PASSWORD);
+ String username = task.getString(CREDENTIALS_USERNAME);
+ String password = task.getString(CREDENTIALS_PASSWORD);
+
if (validUserLoginData(username, password)) {
- result = authenticate(username, password);
- broadcastProgress(progress++);
+ result = authenticate(provider, username, password);
} else {
if (!wellFormedPassword(password)) {
- result.putBoolean(RESULT_KEY, false);
- result.putString(SessionDialog.USERNAME, username);
- result.putBoolean(SessionDialog.ERRORS.PASSWORD_INVALID_LENGTH.toString(), true);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ result.putString(CREDENTIALS_USERNAME, username);
+ result.putBoolean(CREDENTIAL_ERRORS.PASSWORD_INVALID_LENGTH.toString(), true);
}
if (!validUsername(username)) {
- result.putBoolean(RESULT_KEY, false);
- result.putBoolean(SessionDialog.ERRORS.USERNAME_MISSING.toString(), true);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ result.putBoolean(CREDENTIAL_ERRORS.USERNAME_MISSING.toString(), true);
}
}
return result;
}
- private Bundle authenticate(String username, String password) {
+ private Bundle authenticate(Provider provider, String username, String password) {
Bundle result = new Bundle();
JSONObject stepResult = new JSONObject();
- OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(stepResult);
+
+ String providerApiUrl = provider.getApiUrlWithVersion();
+
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), stepResult);
if (okHttpClient == null) {
return authFailedNotification(stepResult, username);
}
@@ -378,13 +361,13 @@ public abstract class ProviderApiManagerBase {
setTokenIfAvailable(step_result);
byte[] M2 = new BigInteger(step_result.getString(LeapSRPSession.M2), 16).toByteArray();
if (client.verify(M2)) {
- result.putBoolean(RESULT_KEY, true);
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
} else {
authFailedNotification(step_result, username);
}
} else {
- result.putBoolean(RESULT_KEY, false);
- result.putString(SessionDialog.USERNAME, username);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ result.putString(CREDENTIALS_USERNAME, username);
result.putString(resources.getString(R.string.user_message), resources.getString(R.string.error_srp_math_error_user_message));
}
} catch (JSONException e) {
@@ -428,38 +411,29 @@ public abstract class ProviderApiManagerBase {
}
if (!username.isEmpty())
- userNotificationBundle.putString(SessionDialog.USERNAME, username);
- userNotificationBundle.putBoolean(RESULT_KEY, false);
+ userNotificationBundle.putString(CREDENTIALS_USERNAME, username);
+ userNotificationBundle.putBoolean(BROADCAST_RESULT_KEY, false);
return userNotificationBundle;
}
- void sendToReceiverOrBroadcast(ResultReceiver receiver, int resultCode, Bundle resultData) {
+ void sendToReceiverOrBroadcast(ResultReceiver receiver, int resultCode, Bundle resultData, Provider provider) {
+ if (resultData == null || resultData == Bundle.EMPTY) {
+ resultData = new Bundle();
+ }
+ resultData.putParcelable(PROVIDER_KEY, provider);
if (receiver != null) {
receiver.send(resultCode, resultData);
} else {
- broadcastEvent(PROVIDER_API_EVENT, resultCode, resultData);
+ broadcastEvent(resultCode, resultData);
}
}
- /**
- * Sets up an intent with the progress value passed as a parameter
- * and sends it as a broadcast.
- *
- * @param progress
- */
- void broadcastProgress(int progress) {
- Intent intentUpdate = new Intent(UPDATE_PROGRESSBAR);
+ private void broadcastEvent(int resultCode , Bundle resultData) {
+ Intent intentUpdate = new Intent(BROADCAST_PROVIDER_API_EVENT);
intentUpdate.addCategory(Intent.CATEGORY_DEFAULT);
- intentUpdate.putExtra(CURRENT_PROGRESS, progress);
- serviceCallback.broadcastEvent(intentUpdate);
- }
-
- void broadcastEvent(String action, int resultCode , Bundle resultData) {
- Intent intentUpdate = new Intent(action);
- intentUpdate.addCategory(Intent.CATEGORY_DEFAULT);
- intentUpdate.putExtra(RESULT_CODE, resultCode);
- intentUpdate.putExtra(RESULT_KEY, resultData);
+ intentUpdate.putExtra(BROADCAST_RESULT_CODE, resultCode);
+ intentUpdate.putExtra(BROADCAST_RESULT_KEY, resultData);
serviceCallback.broadcastEvent(intentUpdate);
}
@@ -595,7 +569,7 @@ public abstract class ProviderApiManagerBase {
JSONObject errorJson = new JSONObject();
String baseUrl = getApiUrl(providerDefinition);
- OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(errorJson, caCert);
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(caCert, errorJson);
if (okHttpClient == null) {
result.putString(ERRORS, errorJson.toString());
return false;
@@ -627,28 +601,24 @@ public abstract class ProviderApiManagerBase {
/**
* Downloads a provider.json from a given URL, adding a new provider using the given name.
*
- * @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.
+ * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider
+ * @return a bundle with a boolean value mapped to a key named BROADCAST_RESULT_KEY, and which is true if the update was successful.
*/
- protected abstract Bundle setUpProvider(Bundle task);
+ protected abstract Bundle setUpProvider(Provider provider, Bundle task);
/**
* Downloads the eip-service.json from a given URL, and saves eip service capabilities including the offered gateways
- * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if the download was successful.
+ * @return a bundle with a boolean value mapped to a key named BROADCAST_RESULT_KEY, and which is true if the download was successful.
*/
- protected abstract Bundle getAndSetEipServiceJson();
+ protected abstract Bundle getAndSetEipServiceJson(Provider provider);
/**
* Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate.
*
* @return true if certificate was downloaded correctly, false if provider.json is not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error.
*/
- protected abstract boolean updateVpnCertificate();
-
+ protected abstract boolean updateVpnCertificate(Provider provider);
- protected static boolean caCertDownloaded() {
- return CA_CERT_DOWNLOADED;
- }
protected boolean isValidJson(String jsonString) {
try {
@@ -662,19 +632,19 @@ public abstract class ProviderApiManagerBase {
}
}
- protected boolean validCertificate(String cert_string) {
+ protected boolean validCertificate(Provider provider, String certString) {
boolean result = false;
- if (!ConfigHelper.checkErroneousDownload(cert_string)) {
- X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string);
+ if (!ConfigHelper.checkErroneousDownload(certString)) {
+ X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certString);
try {
if (certificate != null) {
- JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
- String fingerprint = provider_json.getString(Provider.CA_CERT_FINGERPRINT);
+ JSONObject providerJson = provider.getDefinition();
+ String fingerprint = providerJson.getString(Provider.CA_CERT_FINGERPRINT);
String encoding = fingerprint.split(":")[0];
- String expected_fingerprint = fingerprint.split(":")[1];
- String real_fingerprint = getFingerprintFromCertificate(certificate, encoding);
+ String expectedFingerprint = fingerprint.split(":")[1];
+ String realFingerprint = getFingerprintFromCertificate(certificate, encoding);
- result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim());
+ result = realFingerprint.trim().equalsIgnoreCase(expectedFingerprint.trim());
} else
result = false;
} catch (JSONException | NoSuchAlgorithmException | CertificateEncodingException e) {
@@ -685,69 +655,54 @@ public abstract class ProviderApiManagerBase {
return result;
}
- protected void checkPersistedProviderUpdates() {
- String providerDomain = getDomainFromMainURL(lastProviderMainUrl);
+ protected void getPersistedProviderUpdates(Provider provider) {
+ String providerDomain = getDomainFromMainURL(provider.getMainUrlString());
if (hasUpdatedProviderDetails(providerDomain)) {
- providerCaCert = getPersistedProviderCA(providerDomain);
- providerDefinition = getPersistedProviderDefinition(providerDomain);
- providerCaCertFingerprint = getPersistedCaCertFingerprint(providerDomain);
- providerApiUrl = getApiUrlWithVersion(providerDefinition);
+ provider.setCaCert(getPersistedProviderCA(providerDomain));
+ provider.define(getPersistedProviderDefinition(providerDomain));
+ provider.setPrivateKey(getPersistedPrivateKey(providerDomain));
+ provider.setVpnCertificate(getPersistedVPNCertificate(providerDomain));
}
}
- protected Bundle validateProviderDetails() {
- Bundle result = validateCertificateForProvider(providerCaCert, providerDefinition, lastProviderMainUrl);
+ Bundle validateProviderDetails(Provider provider) {
+ Bundle result = validateCertificateForProvider(provider);
//invalid certificate or no certificate
- if (result.containsKey(ERRORS) || (result.containsKey(RESULT_KEY) && !result.getBoolean(RESULT_KEY)) ) {
+ if (result.containsKey(ERRORS) || (result.containsKey(BROADCAST_RESULT_KEY) && !result.getBoolean(BROADCAST_RESULT_KEY)) ) {
return result;
}
- //valid certificate: skip download, save loaded provider CA cert and provider definition directly
- try {
- preferences.edit().putString(Provider.KEY, providerDefinition.toString()).
- putBoolean(PROVIDER_ALLOW_ANONYMOUS, providerDefinition.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOW_ANONYMOUS)).
- putBoolean(PROVIDER_ALLOWED_REGISTERED, providerDefinition.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOWED_REGISTERED)).
- putString(Provider.CA_CERT, providerCaCert).commit();
- CA_CERT_DOWNLOADED = true;
- PROVIDER_JSON_DOWNLOADED = true;
- result.putBoolean(RESULT_KEY, true);
- } catch (JSONException e) {
- e.printStackTrace();
- setErrorResult(result, warning_corrupted_provider_details, ERROR_CORRUPTED_PROVIDER_JSON.toString());
- }
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
return result;
}
- protected Bundle validateCertificateForProvider(String cert_string, JSONObject providerDefinition, String mainUrl) {
+ protected Bundle validateCertificateForProvider(Provider provider) {
Bundle result = new Bundle();
- result.putBoolean(RESULT_KEY, false);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
- if (ConfigHelper.checkErroneousDownload(cert_string)) {
+ String caCert = provider.getCaCert();
+
+ if (ConfigHelper.checkErroneousDownload(caCert)) {
return result;
}
- X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string);
+ X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(caCert);
if (certificate == null) {
return setErrorResult(result, warning_corrupted_provider_cert, ERROR_INVALID_CERTIFICATE.toString());
}
try {
certificate.checkValidity();
- String fingerprint = getCaCertFingerprint(providerDefinition);
- String encoding = fingerprint.split(":")[0];
- String expected_fingerprint = fingerprint.split(":")[1];
- String real_fingerprint = getFingerprintFromCertificate(certificate, encoding);
- if (!real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim())) {
- return setErrorResult(result, warning_corrupted_provider_cert, ERROR_CERTIFICATE_PINNING.toString());
- }
+ String encoding = provider.getCertificatePinEncoding();
+ String expectedFingerprint = provider.getCertificatePin();
-
- if (!hasApiUrlExpectedDomain(providerDefinition, mainUrl)){
- return setErrorResult(result, warning_corrupted_provider_details, ERROR_CORRUPTED_PROVIDER_JSON.toString());
+ String realFingerprint = getFingerprintFromCertificate(certificate, encoding);
+ if (!realFingerprint.trim().equalsIgnoreCase(expectedFingerprint.trim())) {
+ return setErrorResult(result, warning_corrupted_provider_cert, ERROR_CERTIFICATE_PINNING.toString());
}
- if (!canConnect(cert_string, providerDefinition, result)) {
+ if (!canConnect(caCert, provider.getDefinition(), result)) {
return result;
}
} catch (NoSuchAlgorithmException e ) {
@@ -758,11 +713,11 @@ public abstract class ProviderApiManagerBase {
return setErrorResult(result, warning_expired_provider_cert, ERROR_INVALID_CERTIFICATE.toString());
}
- result.putBoolean(RESULT_KEY, true);
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
return result;
}
- protected Bundle setErrorResult(Bundle result, int errorMessageId, String errorId) {
+ Bundle setErrorResult(Bundle result, int errorMessageId, String errorId) {
JSONObject errorJson = new JSONObject();
if (errorId != null) {
addErrorMessageToJson(errorJson, resources.getString(errorMessageId), errorId);
@@ -770,38 +725,10 @@ public abstract class ProviderApiManagerBase {
addErrorMessageToJson(errorJson, resources.getString(errorMessageId));
}
result.putString(ERRORS, errorJson.toString());
- result.putBoolean(RESULT_KEY, false);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
return result;
}
- /**
- * This method aims to prevent attacks where the provider.json file got manipulated by a third party.
- * The main url is visible to the provider when setting up a new provider.
- * The user is responsible to check that this is the provider main url he intends to connect to.
- *
- * @param providerDefinition
- * @param mainUrlString
- * @return
- */
- private boolean hasApiUrlExpectedDomain(JSONObject providerDefinition, String mainUrlString) {
- // fix against "api_uri": "https://calyx.net.malicious.url.net:4430",
- String apiUrlString = getApiUrl(providerDefinition);
- String providerDomain = getProviderDomain(providerDefinition);
- if (mainUrlString.contains(providerDomain) && apiUrlString.contains(providerDomain + ":")) {
- return true;
- }
- return false;
- }
-
- protected String getCaCertFingerprint(JSONObject providerDefinition) {
- try {
- return providerDefinition.getString(Provider.CA_CERT_FINGERPRINT);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return "";
- }
-
protected String getApiUrl(JSONObject providerDefinition) {
try {
return providerDefinition.getString(Provider.API_URL);
@@ -811,41 +738,17 @@ public abstract class ProviderApiManagerBase {
return "";
}
- protected String getApiUrlWithVersion(JSONObject providerDefinition) {
- try {
- return providerDefinition.getString(Provider.API_URL) + "/" + providerDefinition.getString(Provider.API_VERSION);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return "";
+ protected String getPersistedPrivateKey(String providerDomain) {
+ return ConfigHelper.getFromPersistedProvider(PROVIDER_PRIVATE_KEY, providerDomain, preferences);
}
- protected void deleteProviderDetailsFromPreferences(JSONObject providerDefinition) {
- String providerDomain = getProviderDomain(providerDefinition);
-
- if (preferences.contains(Provider.KEY + "." + providerDomain)) {
- preferences.edit().remove(Provider.KEY + "." + providerDomain).apply();
- }
- if (preferences.contains(Provider.CA_CERT + "." + providerDomain)) {
- preferences.edit().remove(Provider.CA_CERT + "." + providerDomain).apply();
- }
- if (preferences.contains(Provider.CA_CERT_FINGERPRINT + "." + providerDomain)) {
- preferences.edit().remove(Provider.CA_CERT_FINGERPRINT + "." + providerDomain).apply();
- }
- }
-
- protected String getPersistedCaCertFingerprint(String providerDomain) {
- try {
- return getPersistedProviderDefinition(providerDomain).getString(Provider.CA_CERT_FINGERPRINT);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return "";
+ protected String getPersistedVPNCertificate(String providerDomain) {
+ return ConfigHelper.getFromPersistedProvider(PROVIDER_VPN_CERTIFICATE, providerDomain, preferences);
}
protected JSONObject getPersistedProviderDefinition(String providerDomain) {
try {
- return new JSONObject(preferences.getString(Provider.KEY + "." + providerDomain, ""));
+ return new JSONObject(ConfigHelper.getFromPersistedProvider(Provider.KEY, providerDomain, preferences));
} catch (JSONException e) {
e.printStackTrace();
return new JSONObject();
@@ -856,16 +759,6 @@ public abstract class ProviderApiManagerBase {
return preferences.getString(Provider.CA_CERT + "." + providerDomain, "");
}
- protected String getProviderDomain(JSONObject providerDefinition) {
- try {
- return providerDefinition.getString(Provider.DOMAIN);
- } catch (JSONException e) {
- e.printStackTrace();
- }
-
- return "";
- }
-
protected boolean hasUpdatedProviderDetails(String domain) {
return preferences.contains(Provider.KEY + "." + domain) && preferences.contains(Provider.CA_CERT + "." + domain);
}
@@ -879,22 +772,22 @@ public abstract class ProviderApiManagerBase {
* Interprets the error message as a JSON object and extract the "errors" keyword pair.
* If the error message is not a JSON object, then it is returned untouched.
*
- * @param string_json_error_message
+ * @param stringJsonErrorMessage
* @return final error message
*/
- protected String pickErrorMessage(String string_json_error_message) {
- String error_message = "";
+ protected String pickErrorMessage(String stringJsonErrorMessage) {
+ String errorMessage = "";
try {
- JSONObject json_error_message = new JSONObject(string_json_error_message);
- error_message = json_error_message.getString(ERRORS);
+ JSONObject jsonErrorMessage = new JSONObject(stringJsonErrorMessage);
+ errorMessage = jsonErrorMessage.getString(ERRORS);
} catch (JSONException e) {
// TODO Auto-generated catch block
- error_message = string_json_error_message;
+ errorMessage = stringJsonErrorMessage;
} catch (NullPointerException e) {
//do nothing
}
- return error_message;
+ return errorMessage;
}
@NonNull
@@ -907,25 +800,22 @@ public abstract class ProviderApiManagerBase {
return headerArgs;
}
- private boolean logOut() {
- OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(new JSONObject());
+ private boolean logOut(Provider provider) {
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), new JSONObject());
if (okHttpClient == null) {
return false;
}
- String deleteUrl = providerApiUrl + "/logout";
- int progress = 0;
+ String deleteUrl = provider.getApiUrlString() + "/logout";
if (ProviderApiConnector.delete(okHttpClient, deleteUrl)) {
- broadcastProgress(progress++);
LeapSRPSession.setToken("");
return true;
}
return false;
}
- //FIXME: don't save private keys in shared preferences! use the keystore
- protected boolean loadCertificate(String cert_string) {
+ protected boolean loadCertificate(Provider provider, String cert_string) {
if (cert_string == null) {
return false;
}
@@ -944,13 +834,13 @@ public abstract class ProviderApiManagerBase {
RSAPrivateKey key = ConfigHelper.parseRsaKeyFromString(keyString);
keyString = Base64.encodeToString(key.getEncoded(), Base64.DEFAULT);
- preferences.edit().putString(PROVIDER_PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n" + keyString + "-----END RSA PRIVATE KEY-----").commit();
+ provider.setPrivateKey( "-----BEGIN RSA PRIVATE KEY-----\n" + keyString + "-----END RSA PRIVATE KEY-----");
X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificateString);
certificateString = Base64.encodeToString(certificate.getEncoded(), Base64.DEFAULT);
- preferences.edit().putString(PROVIDER_VPN_CERTIFICATE, "-----BEGIN CERTIFICATE-----\n" + certificateString + "-----END CERTIFICATE-----").commit();
+ provider.setVpnCertificate( "-----BEGIN CERTIFICATE-----\n" + certificateString + "-----END CERTIFICATE-----");
return true;
- } catch (CertificateException e) {
+ } catch (CertificateException | NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java
index 172c52d3..7714e979 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderCredentialsBaseActivity.java
@@ -11,6 +11,7 @@ import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
+import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.widget.AppCompatButton;
import android.support.v7.widget.AppCompatTextView;
import android.text.Editable;
@@ -28,17 +29,21 @@ import org.json.JSONException;
import butterknife.InjectView;
import butterknife.OnClick;
-import se.leap.bitmaskclient.userstatus.SessionDialog;
-import se.leap.bitmaskclient.userstatus.SessionDialog.ERRORS;
+import se.leap.bitmaskclient.Constants.CREDENTIAL_ERRORS;
import se.leap.bitmaskclient.userstatus.User;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
-import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_API_EVENT;
-import static se.leap.bitmaskclient.ProviderAPI.RESULT_CODE;
-import static se.leap.bitmaskclient.ProviderAPI.RESULT_KEY;
-import static se.leap.bitmaskclient.userstatus.SessionDialog.USERNAME;
+import static se.leap.bitmaskclient.Constants.BROADCAST_PROVIDER_API_EVENT;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
+import static se.leap.bitmaskclient.Constants.CREDENTIALS_PASSWORD;
+import static se.leap.bitmaskclient.Constants.CREDENTIALS_USERNAME;
+import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
+import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.LOG_IN;
+import static se.leap.bitmaskclient.ProviderAPI.SIGN_UP;
/**
* Base Activity for activities concerning a provider interaction
@@ -92,9 +97,9 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
setContentView(R.layout.a_provider_credentials);
providerAPIBroadcastReceiver = new ProviderAPIBroadcastReceiver();
- IntentFilter updateIntentFilter = new IntentFilter(PROVIDER_API_EVENT);
+ IntentFilter updateIntentFilter = new IntentFilter(BROADCAST_PROVIDER_API_EVENT);
updateIntentFilter.addCategory(Intent.CATEGORY_DEFAULT);
- registerReceiver(providerAPIBroadcastReceiver, updateIntentFilter);
+ LocalBroadcastManager.getInstance(this).registerReceiver(providerAPIBroadcastReceiver, updateIntentFilter);
setUpListeners();
if(savedInstanceState != null) {
@@ -152,7 +157,7 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
protected void onDestroy() {
super.onDestroy();
if (providerAPIBroadcastReceiver != null)
- unregisterReceiver(providerAPIBroadcastReceiver);
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(providerAPIBroadcastReceiver);
}
@OnClick(R.id.button)
@@ -186,34 +191,28 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
void login(String username, String password) {
User.setUserName(username);
- Intent providerAPICommand = new Intent(this, ProviderAPI.class);
- Bundle parameters = bundlePassword(password);
- providerAPICommand.setAction(ProviderAPI.LOG_IN);
- providerAPICommand.putExtra(ProviderAPI.PARAMETERS, parameters);
- startService(providerAPICommand);
+ Bundle parameters = bundleUsernameAndPassword(username, password);
+ ProviderAPICommand.execute(this, LOG_IN, parameters, provider);
}
public void signUp(String username, String password) {
User.setUserName(username);
- Intent providerAPICommand = new Intent(this, ProviderAPI.class);
- Bundle parameters = bundlePassword(password);
- providerAPICommand.setAction(ProviderAPI.SIGN_UP);
- providerAPICommand.putExtra(ProviderAPI.PARAMETERS, parameters);
- startService(providerAPICommand);
+ Bundle parameters = bundleUsernameAndPassword(username, password);
+ ProviderAPICommand.execute(this, SIGN_UP, parameters, provider);
}
- void downloadVpnCertificate() {
- Intent providerAPICommand = new Intent(this, ProviderAPI.class);
- providerAPICommand.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE);
- providerAPICommand.putExtra(ProviderAPI.PARAMETERS, Bundle.EMPTY);
- startService(providerAPICommand);
+ void downloadVpnCertificate(Provider handledProvider) {
+ provider = handledProvider;
+ ProviderAPICommand.execute(this, DOWNLOAD_CERTIFICATE, provider);
}
- protected Bundle bundlePassword(String password) {
+ protected Bundle bundleUsernameAndPassword(String username, String password) {
Bundle parameters = new Bundle();
+ if (!username.isEmpty())
+ parameters.putString(CREDENTIALS_USERNAME, username);
if (!password.isEmpty())
- parameters.putString(SessionDialog.PASSWORD, password);
+ parameters.putString(CREDENTIALS_PASSWORD, password);
return parameters;
}
@@ -324,17 +323,17 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
}
private void handleReceivedErrors(Bundle arguments) {
- if (arguments.containsKey(ERRORS.PASSWORD_INVALID_LENGTH.toString())) {
+ if (arguments.containsKey(CREDENTIAL_ERRORS.PASSWORD_INVALID_LENGTH.toString()))
passwordError.setError(getString(R.string.error_not_valid_password_user_message));
- } else if (arguments.containsKey(ERRORS.RISEUP_WARNING.toString())) {
+ else if (arguments.containsKey(CREDENTIAL_ERRORS.RISEUP_WARNING.toString())) {
userMessage.setVisibility(VISIBLE);
userMessage.setText(R.string.login_riseup_warning);
}
- if (arguments.containsKey(USERNAME)) {
- String username = arguments.getString(USERNAME);
+ if (arguments.containsKey(CREDENTIALS_USERNAME)) {
+ String username = arguments.getString(CREDENTIALS_USERNAME);
usernameField.setText(username);
}
- if (arguments.containsKey(ERRORS.USERNAME_MISSING.toString())) {
+ if (arguments.containsKey(CREDENTIAL_ERRORS.USERNAME_MISSING.toString())) {
usernameError.setError(getString(R.string.username_ask));
}
if (arguments.containsKey(getString(R.string.user_message))) {
@@ -364,7 +363,8 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
hideProgressBar();
}
- private void successfullyFinished() {
+ private void successfullyFinished(Provider handledProvider) {
+ provider = handledProvider;
Intent resultData = new Intent();
resultData.putExtra(Provider.KEY, provider);
setResult(RESULT_OK, resultData);
@@ -377,23 +377,26 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
Log.d(TAG, "received Broadcast");
String action = intent.getAction();
- if (action == null || !action.equalsIgnoreCase(PROVIDER_API_EVENT)) {
+ if (action == null || !action.equalsIgnoreCase(BROADCAST_PROVIDER_API_EVENT)) {
return;
}
- int resultCode = intent.getIntExtra(RESULT_CODE, -1);
+ int resultCode = intent.getIntExtra(BROADCAST_RESULT_CODE, -1);
+ Bundle resultData = intent.getParcelableExtra(BROADCAST_RESULT_KEY);
+ Provider handledProvider = resultData.getParcelable(PROVIDER_KEY);
+
switch (resultCode) {
case ProviderAPI.SUCCESSFUL_SIGNUP:
case ProviderAPI.SUCCESSFUL_LOGIN:
- downloadVpnCertificate();
+ downloadVpnCertificate(handledProvider);
break;
case ProviderAPI.FAILED_LOGIN:
case ProviderAPI.FAILED_SIGNUP:
- handleReceivedErrors((Bundle) intent.getParcelableExtra(RESULT_KEY));
+ handleReceivedErrors((Bundle) intent.getParcelableExtra(BROADCAST_RESULT_KEY));
break;
case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE:
- successfullyFinished();
+ successfullyFinished(handledProvider);
//activity.eip_fragment.updateEipService();
break;
case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE:
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
index fdf8df3c..41d2d849 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
@@ -23,8 +23,10 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
+import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentTransaction;
+import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.Menu;
import android.widget.ListView;
@@ -32,6 +34,7 @@ import android.widget.ListView;
import com.pedrogomez.renderers.Renderer;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.json.JSONException;
import org.json.JSONObject;
@@ -44,20 +47,20 @@ import butterknife.InjectView;
import butterknife.OnItemClick;
import se.leap.bitmaskclient.fragments.AboutFragment;
-import static android.view.View.GONE;
import static se.leap.bitmaskclient.Constants.APP_ACTION_QUIT;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS;
+import static se.leap.bitmaskclient.Constants.BROADCAST_PROVIDER_API_EVENT;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP;
import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE;
-import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_API_EVENT;
import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_NOK;
import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_OK;
import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_SET_UP;
-import static se.leap.bitmaskclient.ProviderAPI.RESULT_CODE;
-import static se.leap.bitmaskclient.ProviderAPI.RESULT_KEY;
+import static se.leap.bitmaskclient.ProviderAPI.UPDATE_PROVIDER_DETAILS;
/**
* abstract base Activity that builds and shows the list of known available providers.
@@ -100,7 +103,7 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
private boolean isActivityShowing;
private String reasonToFail;
- public abstract void retrySetUpProvider();
+ public abstract void retrySetUpProvider(@NonNull Provider provider);
protected abstract void onItemSelectedLogic();
@@ -116,7 +119,7 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
@Override
protected void onSaveInstanceState(@NotNull Bundle outState) {
outState.putString(ACTIVITY_STATE, mConfigState.getAction());
- outState.putParcelable(Provider.KEY, provider);
+ outState.putParcelable(PROVIDER_KEY, provider);
DialogFragment dialogFragment = (DialogFragment) fragmentManager.findFragmentByTag(DownloadFailedDialog.TAG);
if (dialogFragment != null) {
@@ -139,7 +142,6 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
if (savedInstanceState != null)
restoreState(savedInstanceState);
- setUpProviderAPIResultReceiver();
}
private void restoreState(Bundle savedInstanceState) {
@@ -163,6 +165,7 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
protected void onResume() {
Log.d(TAG, "resuming with ConfigState: " + mConfigState.getAction());
super.onResume();
+ setUpProviderAPIResultReceiver();
hideProgressBar();
isActivityShowing = true;
if (SETTING_UP_PROVIDER.equals(mConfigState.getAction())) {
@@ -185,13 +188,13 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
protected void onPause() {
super.onPause();
isActivityShowing = false;
+ if (providerAPIBroadcastReceiver != null)
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(providerAPIBroadcastReceiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
- if (providerAPIBroadcastReceiver != null)
- unregisterReceiver(providerAPIBroadcastReceiver);
providerAPIResultReceiver = null;
}
@@ -208,25 +211,17 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
private void setUpProviderAPIResultReceiver() {
providerAPIResultReceiver = new ProviderAPIResultReceiver(new Handler(), this);
providerAPIBroadcastReceiver = new ProviderAPIBroadcastReceiver();
- IntentFilter updateIntentFilter = new IntentFilter(PROVIDER_API_EVENT);
+
+ IntentFilter updateIntentFilter = new IntentFilter(BROADCAST_PROVIDER_API_EVENT);
updateIntentFilter.addCategory(Intent.CATEGORY_DEFAULT);
- registerReceiver(providerAPIBroadcastReceiver, updateIntentFilter);
+ LocalBroadcastManager.getInstance(this).registerReceiver(providerAPIBroadcastReceiver, updateIntentFilter);
}
- void handleProviderSetUp() {
- try {
- String providerJsonString = preferences.getString(Provider.KEY, "");
- if (!providerJsonString.isEmpty())
- provider.define(new JSONObject(providerJsonString));
- String caCert = preferences.getString(Provider.CA_CERT, "");
- provider.setCACert(caCert);
- } catch (JSONException e) {
- e.printStackTrace();
- }
+ void handleProviderSetUp(Provider handledProvider) {
+ this.provider = handledProvider;
- if (preferences.getBoolean(PROVIDER_ALLOW_ANONYMOUS, false)) {
+ if (provider.allowsAnonymous()) {
mConfigState.putExtra(SERVICES_RETRIEVED, true);
-
downloadVpnCertificate();
} else {
showProviderDetails();
@@ -234,29 +229,25 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
}
void handleProviderSetupFailed(Bundle resultData) {
- mConfigState.setAction(PROVIDER_NOT_SET);
- preferences.edit().remove(Provider.KEY).apply();
-
- setResult(RESULT_CANCELED, mConfigState);
-
reasonToFail = resultData.getString(ERRORS);
showDownloadFailedDialog();
}
- void handleCorrectlyDownloadedCertificate() {
+ void handleCorrectlyDownloadedCertificate(Provider handledProvider) {
+ this.provider = handledProvider;
showProviderDetails();
}
void handleIncorrectlyDownloadedCertificate() {
- mConfigState.setAction(PROVIDER_NOT_SET);
- hideProgressBar();
+ cancelSettingUpProvider();
setResult(RESULT_CANCELED, mConfigState);
}
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
if (resultCode == ProviderAPI.PROVIDER_OK) {
- handleProviderSetUp();
+ Provider provider = resultData.getParcelable(PROVIDER_KEY);
+ handleProviderSetUp(provider);
} else if (resultCode == AboutFragment.VIEWED) {
// Do nothing, right now
// I need this for CW to wait for the About activity to end before going back to Dashboard.
@@ -294,37 +285,22 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
}
private void stopSettingUpProvider() {
- ProviderAPI.stop();
- loadingScreen.setVisibility(GONE);
-
cancelSettingUpProvider();
}
@Override
public void cancelSettingUpProvider() {
- hideProgressBar();
mConfigState.setAction(PROVIDER_NOT_SET);
- preferences.edit().remove(Provider.KEY).remove(PROVIDER_ALLOW_ANONYMOUS).remove(PROVIDER_KEY).apply();
+ hideProgressBar();
}
@Override
public void updateProviderDetails() {
- mConfigState.setAction(SETTING_UP_PROVIDER);
- Intent providerAPICommand = new Intent(this, ProviderAPI.class);
-
- providerAPICommand.setAction(ProviderAPI.UPDATE_PROVIDER_DETAILS);
- Bundle parameters = new Bundle();
- parameters.putString(Provider.MAIN_URL, provider.getMainUrl().toString());
- providerAPICommand.putExtra(ProviderAPI.PARAMETERS, parameters);
-
- startService(providerAPICommand);
+ ProviderAPICommand.execute(this, UPDATE_PROVIDER_DETAILS, provider);
}
public void checkProviderSetUp() {
- Intent providerAPICommand = new Intent(this, ProviderAPI.class);
- providerAPICommand.setAction(PROVIDER_SET_UP);
- providerAPICommand.putExtra(ProviderAPI.RECEIVER_KEY, providerAPIResultReceiver);
- startService(providerAPICommand);
+ ProviderAPICommand.execute(this, PROVIDER_SET_UP, provider, providerAPIResultReceiver);
}
private void askDashboardToQuitApp() {
@@ -337,29 +313,30 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
* Asks ProviderApiService to download an anonymous (anon) VPN certificate.
*/
private void downloadVpnCertificate() {
- Intent providerAPICommand = new Intent(this, ProviderAPI.class);
- providerAPICommand.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE);
- startService(providerAPICommand);
+ ProviderAPICommand.execute(this, DOWNLOAD_CERTIFICATE, provider);
}
/**
* Open the new provider dialog
*/
public void addAndSelectNewProvider() {
- FragmentTransaction fragmentTransaction = fragmentManager.removePreviousFragment(NewProviderDialog.TAG);
- new NewProviderDialog().show(fragmentTransaction, NewProviderDialog.TAG);
+ addAndSelectNewProvider(null);
}
/**
- * Open the new provider dialog with data
+ * Open the new provider dialog
+ * @param mainUrl - the main url of the provider to add - if null add a new provider
*/
- public void addAndSelectNewProvider(String main_url) {
+ public void addAndSelectNewProvider(@Nullable String mainUrl) {
FragmentTransaction fragmentTransaction = fragmentManager.removePreviousFragment(NewProviderDialog.TAG);
DialogFragment newFragment = new NewProviderDialog();
- Bundle data = new Bundle();
- data.putString(Provider.MAIN_URL, main_url);
- newFragment.setArguments(data);
+
+ if (mainUrl != null) {
+ Bundle data = new Bundle();
+ data.putString(Provider.MAIN_URL, mainUrl);
+ newFragment.setArguments(data);
+ }
newFragment.show(fragmentTransaction, NewProviderDialog.TAG);
}
@@ -372,10 +349,10 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
DialogFragment newFragment;
try {
JSONObject errorJson = new JSONObject(reasonToFail);
- newFragment = DownloadFailedDialog.newInstance(errorJson);
+ newFragment = DownloadFailedDialog.newInstance(provider, errorJson);
} catch (JSONException e) {
e.printStackTrace();
- newFragment = DownloadFailedDialog.newInstance(reasonToFail);
+ newFragment = DownloadFailedDialog.newInstance(provider, reasonToFail);
}
newFragment.show(fragmentTransaction, DownloadFailedDialog.TAG);
} catch (IllegalStateException e) {
@@ -422,51 +399,33 @@ public abstract class ProviderListBaseActivity extends ConfigWizardBaseActivity
Log.d(TAG, "received Broadcast");
String action = intent.getAction();
- if (action == null || !action.equalsIgnoreCase(PROVIDER_API_EVENT)) {
+ if (action == null || !action.equalsIgnoreCase(BROADCAST_PROVIDER_API_EVENT)) {
return;
}
if (mConfigState.getAction() != null &&
mConfigState.getAction().equalsIgnoreCase(SETTING_UP_PROVIDER)) {
- int resultCode = intent.getIntExtra(RESULT_CODE, -1);
+ int resultCode = intent.getIntExtra(BROADCAST_RESULT_CODE, -1);
Log.d(TAG, "Broadcast resultCode: " + Integer.toString(resultCode));
- Bundle resultData = intent.getParcelableExtra(RESULT_KEY);
- String handledProvider = resultData.getString(Provider.KEY);
-
- String providerName = ConfigHelper.getProviderName(handledProvider);
- String providerDomain = ConfigHelper.getProviderDomain(handledProvider);
-
- //FIXME: remove that lines as soon as Provider gets sent via broadcast
- // and make sure providers are the same - remove providersMatch
- if (resultCode == PROVIDER_OK && handledProvider == null) {
- providerName = ConfigHelper.getProviderName(preferences);
- providerDomain = ConfigHelper.getProviderDomain(preferences);
- }
- boolean providersMatch = true;
- if (providerDomain != null) {
- providersMatch = providerDomain.equalsIgnoreCase(provider.getDomain());
- }
- if (providerName != null && !providersMatch) {
- providersMatch = providerName.equalsIgnoreCase(provider.getName());
- }
-
+ Bundle resultData = intent.getParcelableExtra(BROADCAST_RESULT_KEY);
+ Provider handledProvider = resultData.getParcelable(PROVIDER_KEY);
- switch (resultCode) {
- case PROVIDER_OK:
- if (providersMatch)
- handleProviderSetUp();
- break;
- case PROVIDER_NOK:
- if(providersMatch)
+ if (handledProvider != null && handledProvider.getDomain().equalsIgnoreCase(provider.getDomain())) {
+ switch (resultCode) {
+ case PROVIDER_OK:
+ handleProviderSetUp(handledProvider);
+ break;
+ case PROVIDER_NOK:
handleProviderSetupFailed(resultData);
- break;
- case CORRECTLY_DOWNLOADED_CERTIFICATE:
- handleCorrectlyDownloadedCertificate();
- break;
- case INCORRECTLY_DOWNLOADED_CERTIFICATE:
- handleIncorrectlyDownloadedCertificate();
- break;
+ break;
+ case CORRECTLY_DOWNLOADED_CERTIFICATE:
+ handleCorrectlyDownloadedCertificate(handledProvider);
+ break;
+ case INCORRECTLY_DOWNLOADED_CERTIFICATE:
+ handleIncorrectlyDownloadedCertificate();
+ break;
+ }
}
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
index e4758ac9..ee1e2a69 100644
--- a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
@@ -14,12 +14,15 @@ import java.lang.annotation.RetentionPolicy;
import de.blinkt.openvpn.core.VpnStatus;
import se.leap.bitmaskclient.eip.EIP;
+import se.leap.bitmaskclient.eip.EipCommand;
import se.leap.bitmaskclient.userstatus.User;
import static se.leap.bitmaskclient.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_START;
import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT;
import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION;
+import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION;
+import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP;
import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
import static se.leap.bitmaskclient.MainActivity.ACTION_SHOW_VPN_FRAGMENT;
@@ -73,7 +76,6 @@ public class StartActivity extends Activity {
}
// initialize app necessities
- ProviderAPICommand.initialize(getApplicationContext());
VpnStatus.initLogCache(getApplicationContext().getCacheDir());
User.init(getString(R.string.default_username));
@@ -128,6 +130,13 @@ public class StartActivity extends Activity {
if (hasNewFeature(FeatureVersionCode.MULTIPLE_PROFILES)) {
// TODO prepare usage of multiple profiles
}
+ if (hasNewFeature(FeatureVersionCode.RENAMED_EIP_IN_PREFERENCES)) {
+ String eipJson = preferences.getString(PROVIDER_KEY, null);
+ if (eipJson != null) {
+ preferences.edit().putString(PROVIDER_EIP_DEFINITION, eipJson).
+ remove(PROVIDER_KEY).apply();
+ }
+ }
// ensure all upgrades have passed before storing new information
storeAppVersion();
@@ -155,7 +164,7 @@ public class StartActivity extends Activity {
} else {
Log.d(TAG, "vpn provider is configured");
if (getIntent() != null && getIntent().getBooleanExtra(EIP_RESTART_ON_BOOT, false)) {
- eipCommand(EIP_ACTION_START);
+ EipCommand.startVPN(getApplicationContext(), true);
finish();
return;
}
@@ -183,7 +192,7 @@ public class StartActivity extends Activity {
if (resultCode == RESULT_OK && data.hasExtra(Provider.KEY)) {
Provider provider = data.getParcelableExtra(Provider.KEY);
ConfigHelper.storeProviderInPreferences(preferences, provider);
- eipCommand(EIP_ACTION_START);
+ EipCommand.startVPN(this.getApplicationContext(), false);
showMainActivity();
} else if (resultCode == RESULT_CANCELED) {
finish();
@@ -199,16 +208,4 @@ public class StartActivity extends Activity {
finish();
}
-
- /**
- * Send a command to EIP
- *
- * @param action A valid String constant from EIP class representing an Intent
- * filter for the EIP class
- */
- private void eipCommand(String action) {
- Intent vpn_intent = new Intent(this.getApplicationContext(), EIP.class);
- vpn_intent.setAction(action);
- this.startService(vpn_intent);
- }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
index 73c68e4c..9d5d4341 100644
--- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
@@ -1,7 +1,6 @@
package se.leap.bitmaskclient.drawer;
-import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
@@ -137,19 +136,11 @@ public class NavigationDrawerFragment extends Fragment {
}
});
-
-
accountListAdapter = new ArrayAdapter<>(actionBar.getThemedContext(),
R.layout.single_list_item,
android.R.id.text1);
- String providerName = ConfigHelper.getProviderName(preferences);
- if (providerName == null) {
- //TODO: ADD A header to the ListView containing a useful message.
- //TODO 2: disable switchProvider
- } else {
- accountListAdapter.add(providerName);
- }
+ createListAdapterData();
mDrawerAccountsListView.setAdapter(accountListAdapter);
@@ -226,16 +217,6 @@ public class NavigationDrawerFragment extends Fragment {
}
@Override
- public void onAttach(Context context) {
- super.onAttach(context);
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- }
-
- @Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
@@ -301,10 +282,7 @@ public class NavigationDrawerFragment extends Fragment {
Log.d("Drawer", String.format("Selected position %d", position));
switch (position) {
case 0:
- // TODO STOP VPN
- // if (provider.hasEIP()) eip_fragment.stopEipIfPossible();
- preferences.edit().clear().apply();
- startActivityForResult(new Intent(getActivity(), ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER);
+ getActivity().startActivityForResult(new Intent(getActivity(), ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER);
break;
case 1:
mTitle = getString(R.string.log_fragment_title);
@@ -337,4 +315,21 @@ public class NavigationDrawerFragment extends Fragment {
}
+ public void refresh() {
+ createListAdapterData();
+ accountListAdapter.notifyDataSetChanged();
+ mDrawerAccountsListView.setAdapter(accountListAdapter);
+ }
+
+ private void createListAdapterData() {
+ accountListAdapter.clear();
+ String providerName = ConfigHelper.getProviderName(preferences);
+ if (providerName == null) {
+ //TODO: ADD A header to the ListView containing a useful message.
+ //TODO 2: disable switchProvider
+ } else {
+ accountListAdapter.add(providerName);
+ }
+ }
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
index 894ad672..9c7f6d1a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
@@ -22,6 +22,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.ResultReceiver;
+import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import org.json.JSONException;
@@ -32,17 +33,20 @@ import java.lang.ref.WeakReference;
import de.blinkt.openvpn.LaunchVPN;
import se.leap.bitmaskclient.OnBootReceiver;
+import static se.leap.bitmaskclient.Constants.BROADCAST_EIP_EVENT;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_CHECK_CERT_VALIDITY;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_IS_RUNNING;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_START;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_START_ALWAYS_ON_VPN;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_UPDATE;
+import static se.leap.bitmaskclient.Constants.EIP_EARLY_ROUTES;
import static se.leap.bitmaskclient.Constants.EIP_RECEIVER;
import static se.leap.bitmaskclient.Constants.EIP_REQUEST;
import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT;
-import static se.leap.bitmaskclient.Constants.EIP_TRIGGERED_FROM_UI;
-import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
+import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION;
import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
@@ -94,7 +98,8 @@ public final class EIP extends IntentService {
switch (action) {
case EIP_ACTION_START:
- startEIP(!intent.hasExtra(EIP_TRIGGERED_FROM_UI));
+ boolean earlyRoutes = intent.getBooleanExtra(EIP_EARLY_ROUTES, true);
+ startEIP(earlyRoutes);
break;
case EIP_ACTION_START_ALWAYS_ON_VPN:
startEIPAlwaysOnVpn();
@@ -132,9 +137,9 @@ public final class EIP extends IntentService {
gateway = gatewaysManager.select();
if (gateway != null && gateway.getProfile() != null) {
launchActiveGateway();
- tellToReceiver(EIP_ACTION_START, Activity.RESULT_OK);
+ tellToReceiverOrBroadcast(EIP_ACTION_START, Activity.RESULT_OK);
} else
- tellToReceiver(EIP_ACTION_START, Activity.RESULT_CANCELED);
+ tellToReceiverOrBroadcast(EIP_ACTION_START, Activity.RESULT_CANCELED);
}
/**
@@ -182,7 +187,7 @@ public final class EIP extends IntentService {
if (eipStatus.isConnected() || eipStatus.isConnecting())
resultCode = Activity.RESULT_OK;
- tellToReceiver(EIP_ACTION_STOP, resultCode);
+ tellToReceiverOrBroadcast(EIP_ACTION_STOP, resultCode);
}
/**
@@ -195,7 +200,7 @@ public final class EIP extends IntentService {
int resultCode = (eipStatus.isConnected()) ?
Activity.RESULT_OK :
Activity.RESULT_CANCELED;
- tellToReceiver(EIP_ACTION_IS_RUNNING, resultCode);
+ tellToReceiverOrBroadcast(EIP_ACTION_IS_RUNNING, resultCode);
}
/**
@@ -206,13 +211,13 @@ public final class EIP extends IntentService {
eipDefinition = eipDefinitionFromPreferences();
if (eipDefinition.length() > 0)
updateGateways();
- tellToReceiver(EIP_ACTION_UPDATE, Activity.RESULT_OK);
+ tellToReceiverOrBroadcast(EIP_ACTION_UPDATE, Activity.RESULT_OK);
}
private JSONObject eipDefinitionFromPreferences() {
JSONObject result = new JSONObject();
try {
- String eipDefinitionString = preferences.getString(PROVIDER_KEY, "");
+ String eipDefinitionString = preferences.getString(PROVIDER_EIP_DEFINITION, "");
if (!eipDefinitionString.isEmpty()) {
result = new JSONObject(eipDefinitionString);
}
@@ -246,14 +251,26 @@ public final class EIP extends IntentService {
int resultCode = validator.isValid() ?
Activity.RESULT_OK :
Activity.RESULT_CANCELED;
- tellToReceiver(EIP_ACTION_CHECK_CERT_VALIDITY, resultCode);
+ tellToReceiverOrBroadcast(EIP_ACTION_CHECK_CERT_VALIDITY, resultCode);
}
- private void tellToReceiver(String action, int resultCode) {
+ private void tellToReceiverOrBroadcast(String action, int resultCode) {
Bundle resultData = new Bundle();
resultData.putString(EIP_REQUEST, action);
if (mReceiverRef.get() != null) {
mReceiverRef.get().send(resultCode, resultData);
+ } else {
+ broadcastEvent(resultCode, resultData);
}
}
+
+ private void broadcastEvent(int resultCode , Bundle resultData) {
+ Intent intentUpdate = new Intent(BROADCAST_EIP_EVENT);
+ intentUpdate.addCategory(Intent.CATEGORY_DEFAULT);
+ intentUpdate.putExtra(BROADCAST_RESULT_CODE, resultCode);
+ intentUpdate.putExtra(BROADCAST_RESULT_KEY, resultData);
+ Log.d(TAG, "sending broadcast");
+ LocalBroadcastManager.getInstance(this).sendBroadcast(intentUpdate);
+ }
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java
new file mode 100644
index 00000000..1c2ae5da
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java
@@ -0,0 +1,82 @@
+package se.leap.bitmaskclient.eip;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.ResultReceiver;
+import android.support.annotation.NonNull;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static se.leap.bitmaskclient.Constants.EIP_ACTION_CHECK_CERT_VALIDITY;
+import static se.leap.bitmaskclient.Constants.EIP_ACTION_START;
+import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP;
+import static se.leap.bitmaskclient.Constants.EIP_ACTION_UPDATE;
+import static se.leap.bitmaskclient.Constants.EIP_EARLY_ROUTES;
+import static se.leap.bitmaskclient.Constants.EIP_RECEIVER;
+
+/**
+ * Use this class to send commands to EIP
+ */
+
+public class EipCommand {
+
+ public static void execute(@NotNull Context context, @NotNull String action) {
+ execute(context, action, null, null);
+ }
+
+ /**
+ * Send a command to EIP
+ * @param context the context to start the command from
+ * @param action A valid String constant from EIP class representing an Intent
+ * filter for the EIP class
+ * @param resultReceiver The resultreceiver to reply to
+ */
+ public static void execute(@NotNull Context context, @NotNull String action, @Nullable ResultReceiver resultReceiver, @Nullable Intent vpnIntent) {
+ // TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
+ if (vpnIntent == null) {
+ vpnIntent = new Intent();
+ }
+ vpnIntent.setComponent(new ComponentName(context.getApplicationContext(), EIP.class));
+ vpnIntent.setAction(action);
+ if (resultReceiver != null)
+ vpnIntent.putExtra(EIP_RECEIVER, resultReceiver);
+ context.startService(vpnIntent);
+ }
+
+ public static void updateEipService(@NonNull Context context, ResultReceiver resultReceiver) {
+ execute(context, EIP_ACTION_UPDATE, resultReceiver, null);
+ }
+
+ public static void updateEipService(@NonNull Context context) {
+ execute(context, EIP_ACTION_UPDATE, null, null);
+ }
+
+ public static void startVPN(@NonNull Context context, boolean earlyRoutes) {
+ Intent baseIntent = new Intent();
+ baseIntent.putExtra(EIP_EARLY_ROUTES, earlyRoutes);
+ execute(context, EIP_ACTION_START, null, baseIntent);
+ }
+
+ public static void startVPN(@NonNull Context context, ResultReceiver resultReceiver) {
+ execute(context, EIP_ACTION_START, resultReceiver, null);
+ }
+
+ public static void stopVPN(@NonNull Context context) {
+ execute(context, EIP_ACTION_STOP);
+ }
+
+ public static void stopVPN(@NonNull Context context, ResultReceiver resultReceiver) {
+ execute(context, EIP_ACTION_STOP, resultReceiver, null);
+ }
+
+ public static void checkVpnCertificate(@NonNull Context context) {
+ execute(context, EIP_ACTION_CHECK_CERT_VALIDITY);
+ }
+
+ public static void checkVpnCertificate(@NonNull Context context, ResultReceiver resultReceiver) {
+ execute(context, EIP_ACTION_CHECK_CERT_VALIDITY, resultReceiver, null);
+ }
+
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
index 0da74872..df252500 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
@@ -24,6 +24,7 @@ import java.util.Observable;
import de.blinkt.openvpn.core.ConnectionStatus;
import de.blinkt.openvpn.core.LogItem;
+import de.blinkt.openvpn.core.ProfileManager;
import de.blinkt.openvpn.core.VpnStatus;
/**
@@ -92,7 +93,14 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
currentEipLevel = EipLevel.CONNECTED;
break;
case LEVEL_VPNPAUSED:
- throw new IllegalStateException("Ics-Openvpn's VPNPAUSED state is not supported by Bitmask");
+ if (ProfileManager.getLastConnectedVpn() != null && ProfileManager.getLastConnectedVpn().mPersistTun) {
+ //if persistTun is enabled, treat EipLevel as connecting as it *shouldn't* allow passing traffic in the clear...
+ currentEipLevel = EipLevel.CONNECTING;
+ } else {
+ //... if persistTun is not enabled, background network traffic will pass in the clear
+ currentEipLevel = EipLevel.DISCONNECTED;
+ }
+ break;
case LEVEL_CONNECTING_SERVER_REPLIED:
case LEVEL_CONNECTING_NO_SERVER_REPLY_YET:
case LEVEL_WAITING_FOR_USER_INPUT:
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
index ff7d011e..6cccdcd2 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
@@ -16,14 +16,16 @@
*/
package se.leap.bitmaskclient.eip;
-import com.google.gson.*;
+import com.google.gson.Gson;
-import org.json.*;
+import org.json.JSONException;
+import org.json.JSONObject;
-import java.io.*;
+import java.io.IOException;
+import java.io.StringReader;
-import de.blinkt.openvpn.*;
-import de.blinkt.openvpn.core.*;
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.core.ConfigParser;
/**
* Gateway provides objects defining gateways and their metadata.
@@ -37,7 +39,7 @@ public class Gateway {
public final static String TAG = Gateway.class.getSimpleName();
- private JSONObject general_configuration;
+ private JSONObject generalConfiguration;
private JSONObject secrets;
private JSONObject gateway;
@@ -54,7 +56,7 @@ public class Gateway {
this.gateway = gateway;
this.secrets = secrets;
- general_configuration = getGeneralConfiguration(eip_definition);
+ generalConfiguration = getGeneralConfiguration(eip_definition);
timezone = getTimezone(eip_definition);
mName = locationAsName(eip_definition);
@@ -80,9 +82,9 @@ public class Gateway {
return location.optString("name");
}
- private JSONObject getLocationInfo(JSONObject eip_definition) {
+ private JSONObject getLocationInfo(JSONObject eipDefinition) {
try {
- JSONObject locations = eip_definition.getJSONObject("locations");
+ JSONObject locations = eipDefinition.getJSONObject("locations");
return locations.getJSONObject(gateway.getString("location"));
} catch (JSONException e) {
@@ -97,8 +99,8 @@ public class Gateway {
try {
ConfigParser cp = new ConfigParser();
- VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(general_configuration, secrets, gateway);
- String configuration = vpn_configuration_generator.generate();
+ VpnConfigGenerator vpnConfigurationGenerator = new VpnConfigGenerator(generalConfiguration, secrets, gateway);
+ String configuration = vpnConfigurationGenerator.generate();
cp.parseConfig(new StringReader(configuration));
return cp.convertProfile();
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
index 0b330ed9..1bdb53ab 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
@@ -94,14 +94,14 @@ public class GatewaysManager {
return new Gson().toJson(gateways, list_type);
}
- public void fromEipServiceJson(JSONObject eip_definition) {
+ public void fromEipServiceJson(JSONObject eipDefinition) {
try {
- JSONArray gatewaysDefined = eip_definition.getJSONArray("gateways");
+ JSONArray gatewaysDefined = eipDefinition.getJSONArray("gateways");
for (int i = 0; i < gatewaysDefined.length(); i++) {
JSONObject gw = gatewaysDefined.getJSONObject(i);
if (isOpenVpnGateway(gw)) {
JSONObject secrets = secretsConfiguration();
- Gateway aux = new Gateway(eip_definition, secrets, gw);
+ Gateway aux = new Gateway(eipDefinition, secrets, gw);
if (!containsProfileWithSecrets(aux.getProfile())) {
addGateway(aux);
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java
deleted file mode 100644
index 29d4f01d..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java
+++ /dev/null
@@ -1,179 +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 <http://www.gnu.org/licenses/>.
- */
-package se.leap.bitmaskclient.userstatus;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AppCompatActivity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.EditText;
-import android.widget.TextView;
-
-import butterknife.ButterKnife;
-import butterknife.InjectView;
-import se.leap.bitmaskclient.Provider;
-import se.leap.bitmaskclient.R;
-
-import static android.view.View.VISIBLE;
-
-/**
- * Implements the log in dialog, currently without progress dialog.
- * <p/>
- * It returns to the previous fragment when finished, and sends username and password to the authenticate method.
- * <p/>
- * It also notifies the user if the password is not valid.
- *
- * @author parmegv
- */
-public class SessionDialog extends DialogFragment {
-
-
- final public static String TAG = SessionDialog.class.getSimpleName();
-
- final public static String USERNAME = "username";
- final public static String PASSWORD = "password";
-
- public enum ERRORS {
- USERNAME_MISSING,
- PASSWORD_INVALID_LENGTH,
- RISEUP_WARNING
- }
-
- @InjectView(R.id.user_message)
- TextView userMessage;
- @InjectView(R.id.username_entered)
- EditText usernameField;
- @InjectView(R.id.password_entered)
- EditText passwordField;
-
- public static SessionDialog getInstance(Provider provider, Bundle arguments) {
- SessionDialog dialog = new SessionDialog();
- if (provider.getName().equalsIgnoreCase("riseup")) {
- arguments =
- arguments == Bundle.EMPTY ?
- new Bundle() : arguments;
- arguments.putBoolean(SessionDialog.ERRORS.RISEUP_WARNING.toString(), true);
- }
- if (arguments != null && !arguments.isEmpty()) {
- dialog.setArguments(arguments);
- }
- return dialog;
- }
-
- public AlertDialog onCreateDialog(Bundle savedInstanceState) {
-
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View view = inflater.inflate(R.layout.session_dialog, null);
- ButterKnife.inject(this, view);
-
- Bundle arguments = getArguments();
- if (arguments != Bundle.EMPTY && arguments != null) {
- setUp(arguments);
- }
-
- builder.setView(view)
- .setPositiveButton(R.string.login_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- String username = getEnteredUsername();
- String password = getEnteredPassword();
- dialog.dismiss();
- interface_with_Dashboard.logIn(username, password);
- }
- })
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- })
- .setNeutralButton(R.string.signup_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- String username = getEnteredUsername();
- String password = getEnteredPassword();
- dialog.dismiss();
- interface_with_Dashboard.signUp(username, password);
- }
- });
-
- return builder.create();
- }
-
- private void setUp(Bundle arguments) {
- if (arguments.containsKey(ERRORS.PASSWORD_INVALID_LENGTH.toString()))
- passwordField.setError(getString(R.string.error_not_valid_password_user_message));
- else if (arguments.containsKey(ERRORS.RISEUP_WARNING.toString())) {
- userMessage.setVisibility(VISIBLE);
- userMessage.setText(R.string.login_riseup_warning);
- }
- if (arguments.containsKey(USERNAME)) {
- String username = arguments.getString(USERNAME);
- usernameField.setText(username);
- }
- if (arguments.containsKey(ERRORS.USERNAME_MISSING.toString())) {
- usernameField.setError(getString(R.string.username_ask));
- }
- if (arguments.containsKey(getString(R.string.user_message))) {
- userMessage.setText(arguments.getString(getString(R.string.user_message)));
- userMessage.setVisibility(VISIBLE);
- } else if (userMessage.getVisibility() != VISIBLE)
- userMessage.setVisibility(View.GONE);
-
- if (!usernameField.getText().toString().isEmpty() && passwordField.isFocusable())
- passwordField.requestFocus();
-
- }
-
- private String getEnteredUsername() {
- return usernameField.getText().toString();
- }
-
- private String getEnteredPassword() {
- return passwordField.getText().toString();
- }
-
-
- /**
- * Interface used to communicate SessionDialog with Dashboard.
- *
- * @author parmegv
- */
- public interface SessionDialogInterface {
- void logIn(String username, String password);
-
- void signUp(String username, String password);
-
- }
-
- SessionDialogInterface interface_with_Dashboard;
-
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
-
- try {
- interface_with_Dashboard = (SessionDialogInterface) ((AppCompatActivity) context).getSupportFragmentManager().getFragments().get(0);
- } catch (ClassCastException e) {
- throw new ClassCastException(context.toString()
- + " must implement LogInDialogListener");
- }
- }
-
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java
index 4b8ce55d..2d8b5c6f 100644
--- a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java
@@ -18,18 +18,19 @@ import java.util.Observer;
import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.OnClick;
-import se.leap.bitmaskclient.MainActivity;
import se.leap.bitmaskclient.Provider;
import se.leap.bitmaskclient.ProviderAPI;
import se.leap.bitmaskclient.ProviderAPICommand;
import se.leap.bitmaskclient.ProviderAPIResultReceiver;
import se.leap.bitmaskclient.R;
-public class UserStatusFragment extends Fragment implements Observer, SessionDialog.SessionDialogInterface {
+public class UserStatusFragment extends Fragment implements Observer {
public final static String TAG = UserStatusFragment.class.getSimpleName();
private ProviderAPIResultReceiver providerAPI_result_receiver;
+ private Provider provider;
+
@InjectView(R.id.user_status_username)
TextView username;
@InjectView(R.id.user_status_icon)
@@ -145,33 +146,13 @@ public class UserStatusFragment extends Fragment implements Observer, SessionDia
}
- @Override
- public void signUp(String username, String password) {
- User.setUserName(username);
- Bundle parameters = bundlePassword(password);
- ProviderAPICommand.execute(parameters, ProviderAPI.SIGN_UP, providerAPI_result_receiver);
- }
-
- @Override
- public void logIn(String username, String password) {
- User.setUserName(username);
- Bundle parameters = bundlePassword(password);
- ProviderAPICommand.execute(parameters, ProviderAPI.LOG_IN, providerAPI_result_receiver);
- }
-
public void logOut() {
android.util.Log.d(TAG, "Log out");
- ProviderAPICommand.execute(Bundle.EMPTY, ProviderAPI.LOG_OUT, providerAPI_result_receiver);
+ ProviderAPICommand.execute(getActivity(), ProviderAPI.LOG_OUT, provider, providerAPI_result_receiver);
}
public void cancelLoginOrSignup() {
//EipStatus.getInstance().setConnectedOrDisconnected();
}
- private Bundle bundlePassword(String password) {
- Bundle parameters = new Bundle();
- if (!password.isEmpty())
- parameters.putString(SessionDialog.PASSWORD, password);
- return parameters;
- }
}
diff --git a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java
index a30c9615..5317118b 100644
--- a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java
+++ b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java
@@ -33,15 +33,14 @@ import okhttp3.OkHttpClient;
import se.leap.bitmaskclient.eip.EIP;
import static android.text.TextUtils.isEmpty;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOWED_REGISTERED;
-import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS;
-import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_CERTIFICATE_PINNING;
+import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_CORRUPTED_PROVIDER_JSON;
import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
-import static se.leap.bitmaskclient.ProviderAPI.RESULT_KEY;
import static se.leap.bitmaskclient.R.string.malformed_url;
import static se.leap.bitmaskclient.R.string.warning_corrupted_provider_cert;
+import static se.leap.bitmaskclient.R.string.warning_corrupted_provider_details;
/**
* Implements the logic of the provider api http requests. The methods of this class need to be called from
@@ -66,76 +65,39 @@ public class ProviderApiManager extends ProviderApiManagerBase {
* Downloads a provider.json from a given URL, adding a new provider using the given name.
*
* @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.
+ * @return a bundle with a boolean value mapped to a key named BROADCAST_RESULT_KEY, and which is true if the update was successful.
*/
@Override
- protected Bundle setUpProvider(Bundle task) {
- int progress = 0;
+ protected Bundle setUpProvider(Provider provider, Bundle task) {
Bundle currentDownload = new Bundle();
- if (task != null) {
- //FIXME: this should be refactored in order to avoid static variables all over here
- lastProviderMainUrl = task.containsKey(Provider.MAIN_URL) ?
- task.getString(Provider.MAIN_URL) :
- "";
-
- if (isEmpty(lastProviderMainUrl)) {
- currentDownload.putBoolean(RESULT_KEY, false);
- setErrorResult(currentDownload, malformed_url, null);
- return currentDownload;
- }
-
- //TODO: remove that
- providerCaCertFingerprint = task.containsKey(Provider.CA_CERT_FINGERPRINT) ?
- task.getString(Provider.CA_CERT_FINGERPRINT) :
- "";
- providerCaCert = task.containsKey(Provider.CA_CERT) ?
- task.getString(Provider.CA_CERT) :
- "";
-
- try {
- providerDefinition = task.containsKey(Provider.KEY) ?
- new JSONObject(task.getString(Provider.KEY)) :
- new JSONObject();
- } catch (JSONException e) {
- e.printStackTrace();
- providerDefinition = new JSONObject();
- }
- providerApiUrl = getApiUrlWithVersion(providerDefinition);
-
- checkPersistedProviderUpdates();
- currentDownload = validateProviderDetails();
+ if (isEmpty(provider.getMainUrlString()) || provider.getMainUrl().isDefault()) {
+ currentDownload.putBoolean(BROADCAST_RESULT_KEY, false);
+ setErrorResult(currentDownload, malformed_url, null);
+ return currentDownload;
+ }
- //provider details invalid
- if (currentDownload.containsKey(ERRORS)) {
- return currentDownload;
- }
+ getPersistedProviderUpdates(provider);
+ currentDownload = validateProviderDetails(provider);
- //no provider certificate available
- if (currentDownload.containsKey(RESULT_KEY) && !currentDownload.getBoolean(RESULT_KEY)) {
- resetProviderDetails();
- }
+ //provider details invalid
+ if (currentDownload.containsKey(ERRORS)) {
+ return currentDownload;
+ }
- EIP_SERVICE_JSON_DOWNLOADED = false;
- go_ahead = true;
+ //no provider certificate available
+ if (currentDownload.containsKey(BROADCAST_RESULT_KEY) && !currentDownload.getBoolean(BROADCAST_RESULT_KEY)) {
+ resetProviderDetails(provider);
}
- if (!PROVIDER_JSON_DOWNLOADED)
- currentDownload = getAndSetProviderJson(lastProviderMainUrl, providerCaCert, providerDefinition);
- if (PROVIDER_JSON_DOWNLOADED || (currentDownload.containsKey(RESULT_KEY) && currentDownload.getBoolean(RESULT_KEY))) {
- broadcastProgress(++progress);
- PROVIDER_JSON_DOWNLOADED = true;
-
- if (!CA_CERT_DOWNLOADED)
- currentDownload = downloadCACert();
- if (CA_CERT_DOWNLOADED || (currentDownload.containsKey(RESULT_KEY) && currentDownload.getBoolean(RESULT_KEY))) {
- broadcastProgress(++progress);
- CA_CERT_DOWNLOADED = true;
- currentDownload = getAndSetEipServiceJson();
- if (currentDownload.containsKey(RESULT_KEY) && currentDownload.getBoolean(RESULT_KEY)) {
- broadcastProgress(++progress);
- EIP_SERVICE_JSON_DOWNLOADED = true;
- }
+ if (!provider.hasDefinition()) {
+ currentDownload = getAndSetProviderJson(provider);
+ }
+ if (provider.hasDefinition() || (currentDownload.containsKey(BROADCAST_RESULT_KEY) && currentDownload.getBoolean(BROADCAST_RESULT_KEY))) {
+ if (!provider.hasCaCert())
+ currentDownload = downloadCACert(provider);
+ if (provider.hasCaCert() || (currentDownload.containsKey(BROADCAST_RESULT_KEY) && currentDownload.getBoolean(BROADCAST_RESULT_KEY))) {
+ currentDownload = getAndSetEipServiceJson(provider);
}
}
@@ -143,67 +105,63 @@ public class ProviderApiManager extends ProviderApiManagerBase {
}
- private Bundle getAndSetProviderJson(String providerMainUrl, String caCert, JSONObject providerDefinition) {
+ private Bundle getAndSetProviderJson(Provider provider) {
Bundle result = new Bundle();
- if (go_ahead) {
- String providerDotJsonString;
- if(providerDefinition.length() == 0 || caCert.isEmpty())
- providerDotJsonString = downloadWithCommercialCA(providerMainUrl + "/provider.json");
- else {
- providerDotJsonString = downloadFromApiUrlWithProviderCA("/provider.json", caCert, providerDefinition);
- }
+ String caCert = provider.getCaCert();
+ JSONObject providerDefinition = provider.getDefinition();
- if (!isValidJson(providerDotJsonString)) {
- setErrorResult(result, malformed_url, null);
- return result;
- }
+ String providerDotJsonString;
+ if(providerDefinition.length() == 0 || caCert.isEmpty()) {
+ String providerJsonUrl = provider.getMainUrlString() + "/provider.json";
+ providerDotJsonString = downloadWithCommercialCA(providerJsonUrl, provider);
+ } else {
+ providerDotJsonString = downloadFromApiUrlWithProviderCA("/provider.json", caCert, providerDefinition);
+ }
- try {
- JSONObject providerJson = new JSONObject(providerDotJsonString);
- String providerDomain = getDomainFromMainURL(lastProviderMainUrl);
- providerApiUrl = getApiUrlWithVersion(providerJson);
- //String name = providerJson.getString(Provider.NAME);
- //TODO setProviderName(name);
-
- preferences.edit().putString(Provider.KEY, providerJson.toString()).
- putBoolean(PROVIDER_ALLOW_ANONYMOUS, providerJson.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOW_ANONYMOUS)).
- putBoolean(PROVIDER_ALLOWED_REGISTERED, providerJson.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOWED_REGISTERED)).
- putString(Provider.KEY + "." + providerDomain, providerJson.toString()).commit();
- result.putBoolean(RESULT_KEY, true);
- } catch (JSONException e) {
- String reason_to_fail = pickErrorMessage(providerDotJsonString);
- result.putString(ERRORS, reason_to_fail);
- result.putBoolean(RESULT_KEY, false);
+ if (!isValidJson(providerDotJsonString)) {
+ setErrorResult(result, malformed_url, null);
+ return result;
+ }
+
+ try {
+ JSONObject providerJson = new JSONObject(providerDotJsonString);
+ if (provider.define(providerJson)) {
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
+ } else {
+ return setErrorResult(result, warning_corrupted_provider_details, ERROR_CORRUPTED_PROVIDER_JSON.toString());
}
+
+ } catch (JSONException e) {
+ String reason_to_fail = pickErrorMessage(providerDotJsonString);
+ result.putString(ERRORS, reason_to_fail);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
}
return result;
}
/**
* Downloads the eip-service.json from a given URL, and saves eip service capabilities including the offered gateways
- * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if the download was successful.
+ * @return a bundle with a boolean value mapped to a key named BROADCAST_RESULT_KEY, and which is true if the download was successful.
*/
@Override
- protected Bundle getAndSetEipServiceJson() {
+ protected Bundle getAndSetEipServiceJson(Provider provider) {
Bundle result = new Bundle();
- String eip_service_json_string = "";
- if (go_ahead) {
- try {
- JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
- String eip_service_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH;
- eip_service_json_string = downloadWithProviderCA(eip_service_url);
- JSONObject eip_service_json = new JSONObject(eip_service_json_string);
- eip_service_json.getInt(Provider.API_RETURN_SERIAL);
-
- preferences.edit().putString(PROVIDER_KEY, eip_service_json.toString()).commit();
-
- result.putBoolean(RESULT_KEY, true);
- } catch (NullPointerException | JSONException e) {
- String reason_to_fail = pickErrorMessage(eip_service_json_string);
- result.putString(ERRORS, reason_to_fail);
- result.putBoolean(RESULT_KEY, false);
- }
+ String eipServiceJsonString = "";
+ try {
+ JSONObject providerJson = provider.getDefinition();
+ String eipServiceUrl = providerJson.getString(Provider.API_URL) + "/" + providerJson.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH;
+ eipServiceJsonString = downloadWithProviderCA(provider.getCaCert(), eipServiceUrl);
+ JSONObject eipServiceJson = new JSONObject(eipServiceJsonString);
+ eipServiceJson.getInt(Provider.API_RETURN_SERIAL);
+
+ provider.setEipServiceJson(eipServiceJson);
+
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
+ } catch (NullPointerException | JSONException e) {
+ String reasonToFail = pickErrorMessage(eipServiceJsonString);
+ result.putString(ERRORS, reasonToFail);
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
}
return result;
}
@@ -214,19 +172,18 @@ public class ProviderApiManager extends ProviderApiManagerBase {
* @return true if certificate was downloaded correctly, false if provider.json is not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error.
*/
@Override
- protected boolean updateVpnCertificate() {
+ protected boolean updateVpnCertificate(Provider provider) {
try {
- 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) + "/" + PROVIDER_VPN_CERTIFICATE);
+ JSONObject providerJson = provider.getDefinition();
+ String providerMainUrl = providerJson.getString(Provider.API_URL);
+ URL newCertStringUrl = new URL(providerMainUrl + "/" + providerJson.getString(Provider.API_VERSION) + "/" + PROVIDER_VPN_CERTIFICATE);
- String cert_string = downloadWithProviderCA(new_cert_string_url.toString());
+ String certString = downloadWithProviderCA(provider.getCaCert(), newCertStringUrl.toString());
- if (ConfigHelper.checkErroneousDownload(cert_string))
+ if (ConfigHelper.checkErroneousDownload(certString))
return false;
else
- return loadCertificate(cert_string);
+ return loadCertificate(provider, certString);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -238,23 +195,22 @@ public class ProviderApiManager extends ProviderApiManagerBase {
}
}
- private Bundle downloadCACert() {
+ private Bundle downloadCACert(Provider provider) {
Bundle result = new Bundle();
try {
- JSONObject providerJson = new JSONObject(preferences.getString(Provider.KEY, ""));
- String caCertUrl = providerJson.getString(Provider.CA_CERT_URI);
- String providerDomain = getDomainFromMainURL(lastProviderMainUrl);
- String cert_string = downloadWithCommercialCA(caCertUrl);
-
- if (validCertificate(cert_string) && go_ahead) {
- preferences.edit().putString(Provider.CA_CERT, cert_string).commit();
- preferences.edit().putString(Provider.CA_CERT + "." + providerDomain, cert_string).commit();
- result.putBoolean(RESULT_KEY, true);
+ String caCertUrl = provider.getDefinition().getString(Provider.CA_CERT_URI);
+ String providerDomain = getDomainFromMainURL(provider.getMainUrlString());
+ String certString = downloadWithCommercialCA(caCertUrl, provider);
+
+ if (validCertificate(provider, certString)) {
+ provider.setCaCert(certString);
+ preferences.edit().putString(Provider.CA_CERT + "." + providerDomain, certString).apply();
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
} else {
setErrorResult(result, warning_corrupted_provider_cert, ERROR_CERTIFICATE_PINNING.toString());
}
} catch (JSONException e) {
- setErrorResult(result, malformed_url, null);
+ e.printStackTrace();
}
return result;
@@ -263,10 +219,8 @@ public class ProviderApiManager extends ProviderApiManagerBase {
/**
* Tries to download the contents of the provided url using commercially validated CA certificate from chosen provider.
*
- * @param string_url
- * @return
*/
- private String downloadWithCommercialCA(String string_url) {
+ private String downloadWithCommercialCA(String stringUrl, Provider provider) {
String responseString;
JSONObject errorJson = new JSONObject();
@@ -277,14 +231,14 @@ public class ProviderApiManager extends ProviderApiManagerBase {
List<Pair<String, String>> headerArgs = getAuthorizationHeader();
- responseString = sendGetStringToServer(string_url, headerArgs, okHttpClient);
+ responseString = sendGetStringToServer(stringUrl, headerArgs, okHttpClient);
if (responseString != null && responseString.contains(ERRORS)) {
try {
// try to download with provider CA on certificate error
JSONObject responseErrorJson = new JSONObject(responseString);
if (responseErrorJson.getString(ERRORS).equals(resources.getString(R.string.certificate_error))) {
- responseString = downloadWithProviderCA(string_url);
+ responseString = downloadWithProviderCA(provider.getCaCert(), stringUrl);
}
} catch (JSONException e) {
e.printStackTrace();
@@ -304,7 +258,7 @@ public class ProviderApiManager extends ProviderApiManagerBase {
String responseString;
JSONObject errorJson = new JSONObject();
String baseUrl = getApiUrl(providerDefinition);
- OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(errorJson, caCert);
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(caCert, errorJson);
if (okHttpClient == null) {
return errorJson.toString();
}
@@ -324,11 +278,11 @@ public class ProviderApiManager extends ProviderApiManagerBase {
* @param urlString as a string
* @return an empty string if it fails, the url content if not.
*/
- private String downloadWithProviderCA(String urlString) {
+ private String downloadWithProviderCA(String caCert, String urlString) {
JSONObject initError = new JSONObject();
String responseString;
- OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(initError);
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(caCert, initError);
if (okHttpClient == null) {
return initError.toString();
}
diff --git a/app/src/production/java/se/leap/bitmaskclient/ProviderListActivity.java b/app/src/production/java/se/leap/bitmaskclient/ProviderListActivity.java
index 8403b046..725ede3e 100644
--- a/app/src/production/java/se/leap/bitmaskclient/ProviderListActivity.java
+++ b/app/src/production/java/se/leap/bitmaskclient/ProviderListActivity.java
@@ -16,12 +16,13 @@
*/
package se.leap.bitmaskclient;
-import android.content.Intent;
-import android.os.Bundle;
+import android.support.annotation.NonNull;
import java.net.MalformedURLException;
import java.net.URL;
+import static se.leap.bitmaskclient.ProviderAPI.SET_UP_PROVIDER;
+
/**
* Activity that builds and shows the list of known available providers.
* <p/>
@@ -61,42 +62,12 @@ public class ProviderListActivity extends ProviderListBaseActivity {
*/
public void setUpProvider() {
mConfigState.setAction(SETTING_UP_PROVIDER);
- Intent providerApiCommand = new Intent(this, ProviderAPI.class);
- Bundle parameters = new Bundle();
- parameters.putString(Provider.MAIN_URL, provider.getMainUrl().toString());
- if (provider.hasCertificatePin()){
- parameters.putString(Provider.CA_CERT_FINGERPRINT, provider.certificatePin());
- }
- if (provider.hasCaCert()) {
- parameters.putString(Provider.CA_CERT, provider.getCaCert());
- }
- if (provider.hasDefinition()) {
- parameters.putString(Provider.KEY, provider.getDefinition().toString());
- }
-
- providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
- providerApiCommand.putExtra(ProviderAPI.PARAMETERS, parameters);
-
- startService(providerApiCommand);
+ ProviderAPICommand.execute(this, SET_UP_PROVIDER, provider);
}
@Override
- public void retrySetUpProvider() {
- cancelSettingUpProvider();
- if (!ProviderAPI.caCertDownloaded()) {
- addAndSelectNewProvider(ProviderAPI.lastProviderMainUrl());
- } else {
- showProgressBar();
-
- Intent providerApiCommand = new Intent(this, ProviderAPI.class);
- providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
- providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, providerAPIResultReceiver);
- Bundle parameters = new Bundle();
- parameters.putString(Provider.MAIN_URL, provider.getMainUrl().toString());
- providerApiCommand.putExtra(ProviderAPI.PARAMETERS, parameters);
-
- startService(providerApiCommand);
- }
+ public void retrySetUpProvider(@NonNull Provider provider) {
+ ProviderAPICommand.execute(this, SET_UP_PROVIDER, provider);
}
}
diff --git a/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java b/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java
index 725924e6..a9584238 100644
--- a/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java
+++ b/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java
@@ -17,10 +17,17 @@
package se.leap.bitmaskclient.testutils;
+import junit.framework.Test;
+
+import org.json.JSONException;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.net.URL;
+
+import se.leap.bitmaskclient.Provider;
/**
* Created by cyberta on 08.10.17.
@@ -40,4 +47,30 @@ public class TestSetupHelper {
return sb.toString();
}
+
+ public static Provider getConfiguredProvider() throws IOException, JSONException {
+ return getProvider(null, null, null);
+ }
+
+ public static Provider getProvider(String domain, String caCertFile, String jsonFile) {
+ if (domain == null)
+ domain = "https://riseup.net";
+ if (caCertFile == null)
+ caCertFile = "riseup.net.pem";
+ if (jsonFile == null)
+ jsonFile = "riseup.net.json";
+
+ try {
+ return new Provider(
+ new URL(domain),
+ getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(caCertFile)),
+ getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(jsonFile))
+
+ );
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/DefaultedURLTest.java b/app/src/test/java/se/leap/bitmaskclient/DefaultedURLTest.java
new file mode 100644
index 00000000..cbf47621
--- /dev/null
+++ b/app/src/test/java/se/leap/bitmaskclient/DefaultedURLTest.java
@@ -0,0 +1,31 @@
+package se.leap.bitmaskclient;
+
+import org.junit.Test;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by cyberta on 11.02.18.
+ */
+public class DefaultedURLTest {
+
+ @Test
+ public void testEquals_false() throws MalformedURLException {
+ DefaultedURL defaultedURL = new DefaultedURL();
+ DefaultedURL customURL = new DefaultedURL();
+ customURL.setUrl(new URL("https://customurl.com"));
+
+ assertFalse(defaultedURL.equals(customURL));
+ }
+
+ @Test
+ public void testEquals_true() throws MalformedURLException {
+ DefaultedURL defaultedURL = new DefaultedURL();
+ DefaultedURL customURL = new DefaultedURL();
+ assertTrue(defaultedURL.equals(customURL));
+ }
+
+}
diff --git a/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java
new file mode 100644
index 00000000..794c3087
--- /dev/null
+++ b/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java
@@ -0,0 +1,21 @@
+package se.leap.bitmaskclient;
+
+import org.junit.Test;
+
+import se.leap.bitmaskclient.testutils.TestSetupHelper;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Created by cyberta on 12.02.18.
+ */
+public class ProviderTest {
+
+ @Test
+ public void testEquals_sameFields_returnsTrue() throws Exception {
+ Provider p1 = TestSetupHelper.getConfiguredProvider();
+ Provider p2 = TestSetupHelper.getConfiguredProvider();
+ assertTrue("Providers should be same:", p1.equals(p2));
+ }
+
+}
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/EipStatusTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/EipStatusTest.java
index 15085b46..f332b094 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/EipStatusTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/EipStatusTest.java
@@ -3,9 +3,12 @@ package se.leap.bitmaskclient.eip;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.core.ConnectionStatus;
+import de.blinkt.openvpn.core.ProfileManager;
import de.blinkt.openvpn.core.VpnStatus;
import se.leap.bitmaskclient.R;
@@ -18,6 +21,8 @@ import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_VPNPAUSED;
import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
import static de.blinkt.openvpn.core.ConnectionStatus.UNKNOWN_LEVEL;
import static junit.framework.Assert.assertTrue;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
import static se.leap.bitmaskclient.eip.EipStatus.EipLevel.CONNECTING;
import static se.leap.bitmaskclient.eip.EipStatus.EipLevel.DISCONNECTED;
import static se.leap.bitmaskclient.eip.EipStatus.EipLevel.UNKNOWN;
@@ -26,7 +31,8 @@ import static se.leap.bitmaskclient.eip.EipStatus.EipLevel.UNKNOWN;
* Created by cyberta on 06.12.17.
* TODO: Mock AsyncTask
*/
-@RunWith(MockitoJUnitRunner.class)
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ProfileManager.class})
public class EipStatusTest {
EipStatus eipStatus;
@@ -46,9 +52,28 @@ public class EipStatusTest {
assertTrue("LEVEL_CONNECTED state", eipStatus.getState().equals("CONNECTED"));
}
- @Test(expected= IllegalStateException.class)
- public void testUpdateState_LEVEL_VPNPAUSED() throws Exception {
- VpnStatus.updateStateString("USERPAUSE", "", R.string.state_userpause, LEVEL_VPNPAUSED);
+ @Test
+ public void testUpdateState_LEVEL_VPNPAUSED_hasPersistentTun() throws Exception {
+
+ mockStatic(ProfileManager.class);
+ VpnProfile mockVpnProfile = new VpnProfile("mockProfile");
+ mockVpnProfile.mPersistTun = true;
+ when(ProfileManager.getLastConnectedVpn()).thenReturn(mockVpnProfile);
+ VpnStatus.updateStateString("SCREENOFF", "", R.string.state_screenoff, LEVEL_VPNPAUSED);
+ assertTrue("LEVEL_VPN_PAUSED eipLevel", eipStatus.getEipLevel() == CONNECTING);
+ assertTrue("LEVEL_VPN_PAUSED level", eipStatus.getLevel() == LEVEL_VPNPAUSED);
+ }
+
+ @Test
+ public void testUpdateState_LEVEL_VPNPAUSED_hasNotPersistentTun() throws Exception {
+
+ mockStatic(ProfileManager.class);
+ VpnProfile mockVpnProfile = new VpnProfile("mockProfile");
+ mockVpnProfile.mPersistTun = false;
+ when(ProfileManager.getLastConnectedVpn()).thenReturn(mockVpnProfile);
+ VpnStatus.updateStateString("SCREENOFF", "", R.string.state_screenoff, LEVEL_VPNPAUSED);
+ assertTrue("LEVEL_VPN_PAUSED eipLevel", eipStatus.getEipLevel() == DISCONNECTED);
+ assertTrue("LEVEL_VPN_PAUSED level", eipStatus.getLevel() == LEVEL_VPNPAUSED);
}
@Test
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java
index c23e4f49..4842d170 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java
@@ -24,6 +24,7 @@ import android.content.res.Resources;
import android.os.Bundle;
import android.text.TextUtils;
+import org.json.JSONException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,21 +46,25 @@ import se.leap.bitmaskclient.ProviderApiManager;
import se.leap.bitmaskclient.ProviderApiManagerBase;
import se.leap.bitmaskclient.testutils.MockSharedPreferences;
+import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
+import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_NOK;
import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_OK;
-import static se.leap.bitmaskclient.ProviderAPI.RESULT_KEY;
import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.ERROR_CASE_UPDATED_CERTIFICATE;
import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.NO_ERROR;
-import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
import static se.leap.bitmaskclient.testutils.MockHelper.mockBundle;
import static se.leap.bitmaskclient.testutils.MockHelper.mockClientGenerator;
+import static se.leap.bitmaskclient.testutils.MockHelper.mockConfigHelper;
import static se.leap.bitmaskclient.testutils.MockHelper.mockFingerprintForCertificate;
import static se.leap.bitmaskclient.testutils.MockHelper.mockIntent;
import static se.leap.bitmaskclient.testutils.MockHelper.mockProviderApiConnector;
import static se.leap.bitmaskclient.testutils.MockHelper.mockResources;
import static se.leap.bitmaskclient.testutils.MockHelper.mockResultReceiver;
import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getConfiguredProvider;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getProvider;
/**
@@ -103,235 +108,248 @@ public class ProviderApiManagerTest {
mockResources = mockResources(getClass().getClassLoader().getResourceAsStream("error_messages.json"));
}
-
@Test
- public void test_handleIntentSetupProvider_noProviderMainURL() {
+ public void test_handleIntentSetupProvider_noProviderMainURL() throws IOException, JSONException {
+ Provider provider = new Provider("");
+
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
Bundle expectedResult = mockBundle();
- expectedResult.putBoolean(RESULT_KEY, false);
- expectedResult.putString(ERRORS, "{\"errors\":\"It doesn't seem to be a Bitmask provider.\"}");
- Intent provider_API_command = mockIntent();
- Bundle parameters = mockBundle();
- parameters.putString(Provider.MAIN_URL, "");
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
+ expectedResult.putString(ERRORS, "{\"errors\":\"It doesn't seem to be a Bitmask provider.\"}");
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
+ Intent providerApiCommand = mockIntent();
+ providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiManager.handleIntent(provider_API_command);
+ providerApiManager.handleIntent(providerApiCommand);
}
@Test
- public void test_handleIntentSetupProvider_happyPath_preseededProviderAndCA() throws IOException, CertificateEncodingException, NoSuchAlgorithmException {
+ public void test_handleIntentSetupProvider_happyPath_preseededProviderAndCA() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
+ Provider provider = getConfiguredProvider();
+
mockFingerprintForCertificate(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
Bundle expectedResult = mockBundle();
- expectedResult.putBoolean(RESULT_KEY, true);
- Intent provider_API_command = mockIntent();
- Bundle parameters = mockBundle();
- parameters.putString(Provider.MAIN_URL, "https://riseup.net");
- parameters.putString(Provider.CA_CERT, getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")));
- parameters.putString(Provider.KEY, getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")));
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, true);
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
+
+ Intent providerApiCommand = mockIntent();
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
+ providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult));
- providerApiManager.handleIntent(provider_API_command);
+ providerApiManager.handleIntent(providerApiCommand);
}
@Test
- public void test_handleIntentSetupProvider_happyPath_no_preseededProviderAndCA() throws IOException, CertificateEncodingException, NoSuchAlgorithmException {
+ public void test_handleIntentSetupProvider_happyPath_no_preseededProviderAndCA() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
+ Provider provider = new Provider("https://riseup.net");
+
mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
Bundle expectedResult = mockBundle();
- expectedResult.putBoolean(RESULT_KEY, true);
- Intent provider_API_command = mockIntent();
- Bundle parameters = mockBundle();
- parameters.putString(Provider.MAIN_URL, "https://riseup.net");
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, true);
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
+
+ Intent providerApiCommand = mockIntent();
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult));
+ providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiManager.handleIntent(provider_API_command);
+ providerApiManager.handleIntent(providerApiCommand);
}
@Test
- public void test_handleIntentSetupProvider_happyPath_storedProviderAndCAFromPreviousSetup() throws IOException, CertificateEncodingException, NoSuchAlgorithmException {
- mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ public void test_handleIntentSetupProvider_happyPath_storedProviderAndCAFromPreviousSetup() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
+ Provider provider = new Provider("https://riseup.net");
+ mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494", getConfiguredProvider());
+
mockProviderApiConnector(NO_ERROR);
mockPreferences.edit().putString(Provider.KEY + ".riseup.net", getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"))).apply();
mockPreferences.edit().putString(Provider.CA_CERT + ".riseup.net", getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"))).apply();
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+
Bundle expectedResult = mockBundle();
- expectedResult.putBoolean(RESULT_KEY, true);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, true);
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent provider_API_command = mockIntent();
- Bundle parameters = mockBundle();
- parameters.putString(Provider.MAIN_URL, "https://riseup.net");
+ Intent providerApiCommand = mockIntent();
+ providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult));
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiManager.handleIntent(provider_API_command);
+ providerApiManager.handleIntent(providerApiCommand);
}
@Test
- public void test_handleIntentSetupProvider_preseededProviderAndCA_failedCAPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException {
+ public void test_handleIntentSetupProvider_preseededProviderAndCA_failedCAPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
+ Provider provider = getConfiguredProvider();
mockFingerprintForCertificate(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495");
mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
Bundle expectedResult = mockBundle();
- expectedResult.putBoolean(RESULT_KEY, false);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_CERTIFICATE_PINNING\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
+
+ Intent providerApiCommand = mockIntent();
- Intent provider_API_command = mockIntent();
- Bundle parameters = mockBundle();
- parameters.putString(Provider.MAIN_URL, "https://riseup.net");
- parameters.putString(Provider.CA_CERT, getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")));
- parameters.putString(Provider.KEY, getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")));
+ providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiManager.handleIntent(provider_API_command);
+ providerApiManager.handleIntent(providerApiCommand);
}
@Test
- public void test_handleIntentSetupProvider_no_preseededProviderAndCA_failedPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException {
+ public void test_handleIntentSetupProvider_no_preseededProviderAndCA_failedPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
+ Provider provider = new Provider("https://riseup.net");
mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495");
mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+
Bundle expectedResult = mockBundle();
- expectedResult.putBoolean(RESULT_KEY, false);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_CERTIFICATE_PINNING\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
+
+ Intent providerApiCommand = mockIntent();
- Intent provider_API_command = mockIntent();
- Bundle parameters = mockBundle();
- parameters.putString(Provider.MAIN_URL, "https://riseup.net");
+ providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiManager.handleIntent(provider_API_command);
+ providerApiManager.handleIntent(providerApiCommand);
}
@Test
- public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_failedPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException {
- mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495");
+ public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_failedPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
+ Provider provider = new Provider("https://riseup.net");
+ mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495", getConfiguredProvider());
+
mockProviderApiConnector(NO_ERROR);
mockPreferences.edit().putString(Provider.KEY + ".riseup.net", getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"))).apply();
mockPreferences.edit().putString(Provider.CA_CERT + ".riseup.net", getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"))).apply();
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+
Bundle expectedResult = mockBundle();
- expectedResult.putBoolean(RESULT_KEY, false);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_CERTIFICATE_PINNING\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
+
+ Intent providerApiCommand = mockIntent();
- Intent provider_API_command = mockIntent();
- Bundle parameters = mockBundle();
- parameters.putString(Provider.MAIN_URL, "https://riseup.net");
+ providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiManager.handleIntent(provider_API_command);
+ providerApiManager.handleIntent(providerApiCommand);
}
@Test
- public void test_handleIntentSetupProvider_preseededProviderAndCA_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException {
+ public void test_handleIntentSetupProvider_preseededProviderAndCA_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
+ Provider provider = getProvider(null ,"outdated_cert.pem", null);
mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+
Bundle expectedResult = mockBundle();
- expectedResult.putBoolean(RESULT_KEY, false);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is expired. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
+
+ Intent providerApiCommand = mockIntent();
- Intent provider_API_command = mockIntent();
- Bundle parameters = mockBundle();
- parameters.putString(Provider.MAIN_URL, "https://riseup.net");
- parameters.putString(Provider.CA_CERT, getInputAsString(getClass().getClassLoader().getResourceAsStream("outdated_cert.pem")));
- parameters.putString(Provider.KEY, getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")));
+ providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiManager.handleIntent(provider_API_command);
+ providerApiManager.handleIntent(providerApiCommand);
}
@Test
- public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException {
+ public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
+ Provider provider = new Provider("https://riseup.net");
mockProviderApiConnector(NO_ERROR);
mockPreferences.edit().putString(Provider.KEY + ".riseup.net", getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"))).apply();
mockPreferences.edit().putString(Provider.CA_CERT + ".riseup.net", getInputAsString(getClass().getClassLoader().getResourceAsStream("outdated_cert.pem"))).apply();
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+
Bundle expectedResult = mockBundle();
- expectedResult.putBoolean(RESULT_KEY, false);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is expired. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
+
+ Intent providerApiCommand = mockIntent();
- Intent provider_API_command = mockIntent();
- Bundle parameters = mockBundle();
- parameters.putString(Provider.MAIN_URL, "https://riseup.net");
+ providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiManager.handleIntent(provider_API_command);
+ providerApiManager.handleIntent(providerApiCommand);
}
@Test
- public void test_handleIntentSetupProvider_preseededProviderAndCA_ValidCertificateButUpdatedCertificateOnServerSide() throws IOException, CertificateEncodingException, NoSuchAlgorithmException {
- mockFingerprintForCertificate(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ public void test_handleIntentSetupProvider_preseededProviderAndCA_ValidCertificateButUpdatedCertificateOnServerSide() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
+ Provider provider = getConfiguredProvider();
+
+ mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494", getConfiguredProvider());
mockProviderApiConnector(ERROR_CASE_UPDATED_CERTIFICATE);
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
Bundle expectedResult = mockBundle();
- expectedResult.putBoolean(RESULT_KEY, false);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent provider_API_command = mockIntent();
- Bundle parameters = mockBundle();
- parameters.putString(Provider.MAIN_URL, "https://riseup.net");
- parameters.putString(Provider.CA_CERT, getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")));
- parameters.putString(Provider.KEY, getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")));
+ Intent providerApiCommand = mockIntent();
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
+ providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- providerApiManager.handleIntent(provider_API_command);
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
+
+ providerApiManager.handleIntent(providerApiCommand);
}
@Test
- public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_ValidCertificateButUpdatedCertificateOnServerSide() throws IOException, CertificateEncodingException, NoSuchAlgorithmException {
- mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_ValidCertificateButUpdatedCertificateOnServerSide() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
+ Provider provider = new Provider("https://riseup.net");
+
+ mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494", getConfiguredProvider());
mockProviderApiConnector(ERROR_CASE_UPDATED_CERTIFICATE);
mockPreferences.edit().putString(Provider.KEY + ".riseup.net", getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"))).apply();
mockPreferences.edit().putString(Provider.CA_CERT + ".riseup.net", getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"))).apply();
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+
Bundle expectedResult = mockBundle();
- expectedResult.putBoolean(RESULT_KEY, false);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
+
+ Intent providerApiCommand = mockIntent();
- Intent provider_API_command = mockIntent();
- Bundle parameters = mockBundle();
- parameters.putString(Provider.MAIN_URL, "https://riseup.net");
+ providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiManager.handleIntent(provider_API_command);
+ providerApiManager.handleIntent(providerApiCommand);
}
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
index 8372c9bc..c2362c7b 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
@@ -1,6 +1,7 @@
package se.leap.bitmaskclient.testutils;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Parcelable;
@@ -28,7 +29,9 @@ import java.util.Set;
import okhttp3.OkHttpClient;
import se.leap.bitmaskclient.ConfigHelper;
+import se.leap.bitmaskclient.Constants;
import se.leap.bitmaskclient.OkHttpClientGenerator;
+import se.leap.bitmaskclient.Provider;
import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider;
import se.leap.bitmaskclient.testutils.matchers.BundleMatcher;
@@ -44,6 +47,8 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY;
+import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
/**
* Created by cyberta on 29.01.18.
@@ -338,6 +343,30 @@ public class MockHelper {
return resultReceiver;
}
+ public static void mockConfigHelper(String mockedFingerprint, final Provider providerFromPrefs) throws CertificateEncodingException, NoSuchAlgorithmException {
+ // FIXME use MockSharedPreferences instead of provider
+ mockStatic(ConfigHelper.class);
+ when(ConfigHelper.getFromPersistedProvider(anyString(), anyString(), any(SharedPreferences.class))).thenAnswer(new Answer<String>() {
+ @Override
+ public String answer(InvocationOnMock invocation) throws Throwable {
+ String key = (String) invocation.getArguments()[0];
+ switch (key) {
+ case PROVIDER_PRIVATE_KEY:
+ return providerFromPrefs.getPrivateKey();
+ case PROVIDER_VPN_CERTIFICATE:
+ return providerFromPrefs.getVpnCertificate();
+ case Provider.KEY:
+ return providerFromPrefs.getDefinition().toString();
+ case Provider.CA_CERT_FINGERPRINT:
+ return providerFromPrefs.getCaCertFingerprint();
+ }
+ return null;
+ }
+ });
+ when(ConfigHelper.getFingerprintFromCertificate(any(X509Certificate.class), anyString())).thenReturn(mockedFingerprint);
+ when(ConfigHelper.checkErroneousDownload(anyString())).thenCallRealMethod();
+ when(ConfigHelper.parseX509CertificateFromString(anyString())).thenCallRealMethod();
+ }
public static void mockFingerprintForCertificate(String mockedFingerprint) throws CertificateEncodingException, NoSuchAlgorithmException {
mockStatic(ConfigHelper.class);
when(ConfigHelper.getFingerprintFromCertificate(any(X509Certificate.class), anyString())).thenReturn(mockedFingerprint);
@@ -353,8 +382,7 @@ public class MockHelper {
OkHttpClientGenerator mockClientGenerator = mock(OkHttpClientGenerator.class);
OkHttpClient mockedOkHttpClient = mock(OkHttpClient.class);
when(mockClientGenerator.initCommercialCAHttpClient(any(JSONObject.class))).thenReturn(mockedOkHttpClient);
- when(mockClientGenerator.initSelfSignedCAHttpClient(any(JSONObject.class))).thenReturn(mockedOkHttpClient);
- when(mockClientGenerator.initSelfSignedCAHttpClient(any(JSONObject.class), anyString())).thenReturn(mockedOkHttpClient);
+ when(mockClientGenerator.initSelfSignedCAHttpClient(anyString(), any(JSONObject.class))).thenReturn(mockedOkHttpClient);
return mockClientGenerator;
}