summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcyberta <cyberta@riseup.net>2020-07-24 10:20:22 -0700
committercyberta <cyberta@riseup.net>2020-07-24 10:20:22 -0700
commitbdd909d1faae569f27d61ad510d11fad74a5a27c (patch)
treec3266b79c930a6a902814e6c58c457280ed67c2a
parent4198c9b3bb1fee4bfcb3009ac9d80610ead13466 (diff)
parent38f5720502fda7b89ce204fe4afdffa67ac0ae82 (diff)
Merge branch 'support_geoip' into 'master'
Support geoip See merge request leap/bitmask_android!108
-rw-r--r--app/build.gradle3
-rw-r--r--app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java56
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Constants.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipFragment.java29
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java23
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Provider.java184
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java10
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java44
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderManager.java5
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/StartActivity.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EIP.java13
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java191
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java7
-rw-r--r--app/src/normal/assets/urls/riseup.net.url3
-rw-r--r--app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java73
-rw-r--r--app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java14
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/PreferenceHelperTest.java15
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/ProviderTest.java18
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java110
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java137
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java5
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java3
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java93
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java3
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java3
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java2
-rw-r--r--app/src/test/resources/ptdemo_three_mixed_gateways.geoip.json12
-rw-r--r--app/src/test/resources/riseup.geoip.json20
31 files changed, 845 insertions, 261 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 6c236669..088be987 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -41,6 +41,7 @@ android {
buildConfigField "String", "customProviderUrl", '""'
buildConfigField "String", "customProviderIp", '""'
buildConfigField "String", "customProviderApiIp", '""'
+ buildConfigField "String", "geoipUrl", '""'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
dexOptions {
@@ -97,6 +98,8 @@ android {
//static ip address of the provider api, using a self signed certificate to serve provider.json, eip-service.json etc.
def customProviderApiIp = '"198.252.153.107"'
buildConfigField "String", "customProviderApiIp", customProviderApiIp
+ def geoipUrl = '"https://api.black.riseup.net:9001/json"'
+ buildConfigField "String", "geoipUrl", geoipUrl
//Change the versionCode as needed
//versionCode 1
//Change the versionName as needed
diff --git a/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java
index b67f6fa5..a111e907 100644
--- a/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java
+++ b/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java
@@ -136,15 +136,14 @@ public class ProviderApiManager extends ProviderApiManagerBase {
private Bundle getAndSetProviderJson(Provider provider, boolean dangerOn) {
Bundle result = new Bundle();
- String caCert = provider.getCaCert();
JSONObject providerDefinition = provider.getDefinition();
String providerMainUrl = provider.getMainUrlString();
String providerDotJsonString;
- if(providerDefinition.length() == 0 || caCert.isEmpty())
+ if(providerDefinition.length() == 0 || provider.getCaCert().isEmpty())
providerDotJsonString = downloadWithCommercialCA(providerMainUrl + "/provider.json", dangerOn);
else
- providerDotJsonString = downloadFromApiUrlWithProviderCA("/provider.json", caCert, provider, dangerOn);
+ providerDotJsonString = downloadFromApiUrlWithProviderCA("/provider.json", provider, dangerOn);
if (ConfigHelper.checkErroneousDownload(providerDotJsonString) || !isValidJson(providerDotJsonString)) {
setErrorResult(result, malformed_url, null);
@@ -230,6 +229,44 @@ public class ProviderApiManager extends ProviderApiManagerBase {
return result;
}
+ /**
+ * Fetches the Geo ip Json, containing a list of gateways sorted by distance from the users current location
+ *
+ * @param provider
+ * @return
+ */
+ @Override
+ protected Bundle getGeoIPJson(Provider provider) {
+ Bundle result = new Bundle();
+
+ if (!provider.shouldUpdateGeoIpJson() || provider.getGeoipUrl().isDefault()) {
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ return result;
+ }
+
+
+ try {
+ URL geoIpUrl = provider.getGeoipUrl().getUrl();
+
+ String geoipJsonString = downloadFromUrlWithProviderCA(geoIpUrl.toString(), provider, lastDangerOn);
+ JSONObject geoipJson = new JSONObject(geoipJsonString);
+
+ if (geoipJson.has(ERRORS)) {
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ } else {
+ provider.setGeoIpJson(geoipJson);
+ provider.setLastEipServiceUpdate(System.currentTimeMillis());
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
+ }
+
+
+ } catch (JSONException | NullPointerException e) {
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ e.printStackTrace();
+ }
+ return result;
+ }
+
private Bundle downloadCACert(Provider provider, boolean dangerOn) {
Bundle result = new Bundle();
@@ -291,16 +328,21 @@ public class ProviderApiManager extends ProviderApiManagerBase {
return responseString;
}
- private String downloadFromApiUrlWithProviderCA(String path, String caCert, Provider provider, boolean dangerOn) {
+ private String downloadFromApiUrlWithProviderCA(String path, Provider provider, boolean dangerOn) {
+ String baseUrl = provider.getApiUrlString();
+ String urlString = baseUrl + path;
+
+ return downloadFromUrlWithProviderCA(urlString, provider, dangerOn);
+ }
+
+ private String downloadFromUrlWithProviderCA(String urlString, Provider provider, boolean dangerOn) {
String responseString;
JSONObject errorJson = new JSONObject();
- String baseUrl = provider.getApiUrlString();
- OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(caCert, errorJson);
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), errorJson);
if (okHttpClient == null) {
return errorJson.toString();
}
- String urlString = baseUrl + path;
List<Pair<String, String>> headerArgs = getAuthorizationHeader();
responseString = sendGetStringToServer(urlString, headerArgs, okHttpClient);
diff --git a/app/src/main/java/se/leap/bitmaskclient/Constants.java b/app/src/main/java/se/leap/bitmaskclient/Constants.java
index 6ec3076c..6462b663 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Constants.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Constants.java
@@ -142,4 +142,5 @@ public interface Constants {
String LOCATION = "location";
String OPENVPN_CONFIGURATION = "openvpn_configuration";
String GATEWAYS = "gateways";
+ String HOST = "host";
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
index b8883f77..fceadd88 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
@@ -27,14 +27,6 @@ import android.graphics.ColorMatrixColorFilter;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Vibrator;
-import androidx.annotation.NonNull;
-import androidx.fragment.app.DialogFragment;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentTransaction;
-import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.widget.AppCompatButton;
-import androidx.appcompat.widget.AppCompatImageView;
-import androidx.appcompat.widget.AppCompatTextView;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
@@ -44,6 +36,15 @@ import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.widget.AppCompatButton;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentTransaction;
+
import java.util.Observable;
import java.util.Observer;
@@ -62,6 +63,8 @@ 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.ASK_TO_CANCEL_VPN;
+import static se.leap.bitmaskclient.Constants.EIP_ACTION_START;
+import static se.leap.bitmaskclient.Constants.EIP_EARLY_ROUTES;
import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT;
import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP;
@@ -71,6 +74,7 @@ import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
import static se.leap.bitmaskclient.EipSetupObserver.connectionRetry;
import static se.leap.bitmaskclient.EipSetupObserver.gatewayOrder;
import static se.leap.bitmaskclient.EipSetupObserver.reconnectingWithDifferentGateway;
+import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_GEOIP_JSON;
import static se.leap.bitmaskclient.ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.USER_MESSAGE;
import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message;
@@ -301,7 +305,14 @@ public class EipFragment extends Fragment implements Observer {
Log.e(TAG, "context is null when trying to start VPN");
return;
}
- EipCommand.startVPN(context.getApplicationContext(), false);
+ if (!provider.getGeoipUrl().isDefault() && provider.shouldUpdateGeoIpJson()) {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(EIP_ACTION_START, true);
+ bundle.putBoolean(EIP_EARLY_ROUTES, false);
+ ProviderAPICommand.execute(getContext().getApplicationContext(), DOWNLOAD_GEOIP_JSON, bundle, provider);
+ } else {
+ EipCommand.startVPN(context.getApplicationContext(), false);
+ }
vpnStateImage.showProgress();
routedText.setVisibility(GONE);
vpnRoute.setVisibility(GONE);
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java b/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java
index ee7e7ef5..7504e0c0 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java
@@ -6,9 +6,10 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
-import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.util.Log;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
import org.json.JSONObject;
import java.util.Vector;
@@ -39,11 +40,14 @@ import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
import static se.leap.bitmaskclient.Constants.EIP_ACTION_PREPARE_VPN;
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_EARLY_ROUTES;
import static se.leap.bitmaskclient.Constants.EIP_REQUEST;
import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.Constants.PROVIDER_PROFILE;
import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE;
+import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_GEOIP_JSON;
import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_GEOIP_JSON;
/**
* Created by cyberta on 05.12.18.
@@ -151,6 +155,15 @@ class EipSetupObserver extends BroadcastReceiver implements VpnStatus.StateListe
PreferenceHelper.storeProviderInPreferences(preferences, provider);
EipCommand.startVPN(context.getApplicationContext(), true);
break;
+ case CORRECTLY_DOWNLOADED_GEOIP_JSON:
+ provider = resultData.getParcelable(PROVIDER_KEY);
+ ProviderObservable.getInstance().updateProvider(provider);
+ PreferenceHelper.storeProviderInPreferences(preferences, provider);
+ maybeStartEipService(resultData);
+ break;
+ case INCORRECTLY_DOWNLOADED_GEOIP_JSON:
+ maybeStartEipService(resultData);
+ break;
default:
break;
}
@@ -160,6 +173,13 @@ class EipSetupObserver extends BroadcastReceiver implements VpnStatus.StateListe
}
}
+ private void maybeStartEipService(Bundle resultData) {
+ if (resultData.getBoolean(EIP_ACTION_START)) {
+ boolean earlyRoutes = resultData.getBoolean(EIP_EARLY_ROUTES);
+ EipCommand.startVPN(context.getApplicationContext(), earlyRoutes);
+ }
+ }
+
private void handleEipEvent(Intent intent) {
int resultCode = intent.getIntExtra(BROADCAST_RESULT_CODE, RESULT_CANCELED);
@@ -184,6 +204,7 @@ class EipSetupObserver extends BroadcastReceiver implements VpnStatus.StateListe
finishGatewaySetup(false);
EipCommand.startBlockingVPN(context.getApplicationContext());
} else {
+ //FIXME:
finishGatewaySetup(false);
EipCommand.stopVPN(context);
EipStatus.refresh();
diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java
index 4dd7c76e..186ce11e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java
@@ -18,7 +18,6 @@ package se.leap.bitmaskclient;
import android.os.Parcel;
import android.os.Parcelable;
-import androidx.annotation.NonNull;
import com.google.gson.Gson;
@@ -46,10 +45,13 @@ import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
public final class Provider implements Parcelable {
private static long EIP_SERVICE_TIMEOUT = 1000 * 60 * 60 * 24 * 3;
+ private static long GEOIP_SERVICE_TIMEOUT = 1000 * 60 * 60;
private JSONObject definition = new JSONObject(); // Represents our Provider's provider.json
private JSONObject eipServiceJson = new JSONObject();
+ private JSONObject geoIpJson = new JSONObject();
private DefaultedURL mainUrl = new DefaultedURL();
private DefaultedURL apiUrl = new DefaultedURL();
+ private DefaultedURL geoipUrl = new DefaultedURL();
private String providerIp = "";
private String providerApiIp = "";
private String certificatePin = "";
@@ -59,6 +61,7 @@ public final class Provider implements Parcelable {
private String privateKey = "";
private String vpnCertificate = "";
private long lastEipServiceUpdate = 0L;
+ private long lastGeoIpUpdate = 0L;
private boolean allowAnonymous;
private boolean allowRegistered;
@@ -78,21 +81,31 @@ public final class Provider implements Parcelable {
DOMAIN = "domain",
MAIN_URL = "main_url",
PROVIDER_IP = "provider_ip",
- PROVIDER_API_IP = "provider_api_ip";
+ PROVIDER_API_IP = "provider_api_ip",
+ GEOIP_URL = "geoip_url";
private static final String API_TERM_NAME = "name";
public Provider() { }
public Provider(String mainUrl) {
+ this(mainUrl, null);
+ }
+
+ public Provider(String mainUrl, String geoipUrl) {
try {
this.mainUrl.setUrl(new URL(mainUrl));
} catch (MalformedURLException e) {
this.mainUrl = new DefaultedURL();
}
+ setGeoipUrl(geoipUrl);
}
public Provider(String mainUrl, String providerIp, String providerApiIp) {
+ this(mainUrl, null, providerIp, providerApiIp);
+ }
+
+ public Provider(String mainUrl, String geoipUrl, String providerIp, String providerApiIp) {
try {
this.mainUrl.setUrl(new URL(mainUrl));
if (providerIp != null) {
@@ -103,21 +116,14 @@ public final class Provider implements Parcelable {
}
} catch (MalformedURLException e) {
e.printStackTrace();
+ return;
}
+ setGeoipUrl(geoipUrl);
}
- public Provider(String mainUrl, String providerIp, String providerApiIp, String caCert, String definition) {
- try {
- this.mainUrl.setUrl(new URL(mainUrl));
- } catch (MalformedURLException e) {
- e.printStackTrace();
- }
- if (this.providerIp != null) {
- this.providerIp = providerIp;
- }
- if (this.providerApiIp != null) {
- this.providerApiIp = providerApiIp;
- }
+
+ public Provider(String mainUrl, String geoipUrl, String providerIp, String providerApiIp, String caCert, String definition) {
+ this(mainUrl, geoipUrl, providerIp, providerApiIp);
if (caCert != null) {
this.caCert = caCert;
}
@@ -240,6 +246,18 @@ public final class Provider implements Parcelable {
protected DefaultedURL getApiUrl() {
return apiUrl;
}
+
+ public DefaultedURL getGeoipUrl() {
+ return geoipUrl;
+ }
+
+ public void setGeoipUrl(String url) {
+ try {
+ this.geoipUrl.setUrl(new URL(url));
+ } catch (MalformedURLException e) {
+ this.geoipUrl = new DefaultedURL();
+ }
+ }
protected String getApiUrlWithVersion() {
return getApiUrlString() + "/" + getApiVersion();
@@ -262,6 +280,10 @@ public final class Provider implements Parcelable {
return definition != null && definition.length() > 0;
}
+ public boolean hasGeoIpJson() {
+ return geoIpJson != null && geoIpJson.length() > 0;
+ }
+
public String getCaCert() {
return caCert;
@@ -321,56 +343,17 @@ public final class Provider implements Parcelable {
parcel.writeString(getMainUrlString());
parcel.writeString(getProviderIp());
parcel.writeString(getProviderApiIp());
+ parcel.writeString(getGeoipUrl().toString());
parcel.writeString(getDefinitionString());
parcel.writeString(getCaCert());
parcel.writeString(getEipServiceJsonString());
+ parcel.writeString(getGeoIpJsonString());
parcel.writeString(getPrivateKey());
parcel.writeString(getVpnCertificate());
parcel.writeLong(lastEipServiceUpdate);
+ parcel.writeLong(lastGeoIpUpdate);
}
- @Override
- public boolean equals(Object o) {
- if (o instanceof Provider) {
- Provider p = (Provider) o;
- return p.getDomain().equals(getDomain()) &&
- definition.toString().equals(p.getDefinition().toString()) &&
- eipServiceJson.toString().equals(p.getEipServiceJson().toString())&&
- mainUrl.equals(p.getMainUrl()) &&
- providerIp.equals(p.getProviderIp()) &&
- providerApiIp.equals(p.getProviderApiIp()) &&
- 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() &&
- lastEipServiceUpdate == p.getLastEipServiceUpdate();
- } else return false;
- }
-
- public JSONObject toJson() {
- JSONObject json = new JSONObject();
- try {
- json.put(Provider.MAIN_URL, mainUrl);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return json;
- }
-
- @Override
- public int hashCode() {
- return getDomain().hashCode();
- }
-
- @Override
- public String toString() {
- return new Gson().toJson(this);
- }
//TODO: write a test for marshalling!
private Provider(Parcel in) {
@@ -386,6 +369,10 @@ public final class Provider implements Parcelable {
}
tmpString = in.readString();
if (!tmpString.isEmpty()) {
+ geoipUrl.setUrl(new URL(tmpString));
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
definition = new JSONObject((tmpString));
parseDefinition(definition);
}
@@ -399,6 +386,10 @@ public final class Provider implements Parcelable {
}
tmpString = in.readString();
if (!tmpString.isEmpty()) {
+ this.setGeoIpJson(new JSONObject(tmpString));
+ }
+ tmpString = in.readString();
+ if (!tmpString.isEmpty()) {
this.setPrivateKey(tmpString);
}
tmpString = in.readString();
@@ -406,11 +397,57 @@ public final class Provider implements Parcelable {
this.setVpnCertificate(tmpString);
}
this.lastEipServiceUpdate = in.readLong();
+ this.lastGeoIpUpdate = in.readLong();
} catch (MalformedURLException | JSONException e) {
e.printStackTrace();
}
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Provider) {
+ Provider p = (Provider) o;
+ return p.getDomain().equals(getDomain()) &&
+ definition.toString().equals(p.getDefinition().toString()) &&
+ eipServiceJson.toString().equals(p.getEipServiceJsonString()) &&
+ geoIpJson.toString().equals(p.getGeoIpJsonString()) &&
+ providerIp.equals(p.getProviderIp()) &&
+ providerApiIp.equals(p.getProviderApiIp()) &&
+ apiUrl.equals(p.getApiUrl()) &&
+ geoipUrl.equals(p.getGeoipUrl()) &&
+ 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;
+ }
+
+
+ public JSONObject toJson() {
+ JSONObject json = new JSONObject();
+ try {
+ json.put(Provider.MAIN_URL, mainUrl);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+
+ @Override
+ public int hashCode() {
+ return getDomain().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return new Gson().toJson(this);
+ }
+
private boolean parseDefinition(JSONObject definition) {
try {
String pin = definition.getString(CA_CERT_FINGERPRINT);
@@ -442,14 +479,20 @@ public final class Provider implements Parcelable {
lastEipServiceUpdate = timestamp;
}
- public long getLastEipServiceUpdate() {
- return lastEipServiceUpdate;
- }
-
public boolean shouldUpdateEipServiceJson() {
return System.currentTimeMillis() - lastEipServiceUpdate >= EIP_SERVICE_TIMEOUT;
}
+
+ public void setLastGeoIpUpdate(long timestamp) {
+ lastGeoIpUpdate = timestamp;
+ }
+
+ public boolean shouldUpdateGeoIpJson() {
+ return System.currentTimeMillis() - lastGeoIpUpdate >= GEOIP_SERVICE_TIMEOUT;
+ }
+
+
public boolean setEipServiceJson(JSONObject eipServiceJson) {
if (eipServiceJson.has(ERRORS)) {
return false;
@@ -458,16 +501,34 @@ public final class Provider implements Parcelable {
return true;
}
+ public boolean setGeoIpJson(JSONObject geoIpJson) {
+ if (geoIpJson.has(ERRORS)) {
+ return false;
+ }
+ this.geoIpJson = geoIpJson;
+ return true;
+ }
+
public JSONObject getEipServiceJson() {
return eipServiceJson;
}
+ public JSONObject getGeoIpJson() {
+ return geoIpJson;
+ }
+
+ public String getGeoIpJsonString() {
+ return geoIpJson.toString();
+ }
+
public String getEipServiceJsonString() {
return getEipServiceJson().toString();
}
+
public boolean isDefault() {
return getMainUrl().isDefault() &&
getApiUrl().isDefault() &&
+ getGeoipUrl().isDefault() &&
certificatePin.isEmpty() &&
certificatePinEncoding.isEmpty() &&
caCert.isEmpty();
@@ -515,6 +576,7 @@ public final class Provider implements Parcelable {
public void reset() {
definition = new JSONObject();
eipServiceJson = new JSONObject();
+ geoIpJson = new JSONObject();
apiUrl = new DefaultedURL();
certificatePin = "";
certificatePinEncoding = "";
@@ -524,5 +586,7 @@ public final class Provider implements Parcelable {
vpnCertificate = "";
allowRegistered = false;
allowAnonymous = false;
+ lastGeoIpUpdate = 0L;
+ lastEipServiceUpdate = 0L;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java
index 9d34b38f..767e6a78 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java
@@ -24,6 +24,7 @@ import android.content.SharedPreferences;
import androidx.annotation.NonNull;
import androidx.core.app.JobIntentService;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES;
/**
@@ -48,6 +49,7 @@ public class ProviderAPI extends JobIntentService implements ProviderApiManagerB
TAG = ProviderAPI.class.getSimpleName(),
SET_UP_PROVIDER = "setUpProvider",
UPDATE_PROVIDER_DETAILS = "updateProviderDetails",
+ DOWNLOAD_GEOIP_JSON = "downloadGeoIpJson",
SIGN_UP = "srpRegister",
LOG_IN = "srpAuth",
LOG_OUT = "logOut",
@@ -77,7 +79,9 @@ public class ProviderAPI extends JobIntentService implements ProviderApiManagerB
CORRECTLY_DOWNLOADED_EIP_SERVICE = 13,
INCORRECTLY_DOWNLOADED_EIP_SERVICE = 14,
CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE = 15,
- INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE = 16;
+ INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE = 16,
+ CORRECTLY_DOWNLOADED_GEOIP_JSON = 17,
+ INCORRECTLY_DOWNLOADED_GEOIP_JSON = 18;
ProviderApiManager providerApiManager;
@@ -99,11 +103,12 @@ public class ProviderAPI extends JobIntentService implements ProviderApiManagerB
*/
static void enqueueWork(Context context, Intent work) {
try {
- enqueueWork(context, ProviderAPI.class, JOB_ID, work);
+ ProviderAPI.enqueueWork(context, ProviderAPI.class, JOB_ID, work);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
+
@Override
protected void onHandleWork(@NonNull Intent command) {
providerApiManager.handleIntent(command);
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java
index f3122376..9a0731cd 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPICommand.java
@@ -4,11 +4,13 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.ResultReceiver;
+import android.util.Log;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ProviderAPICommand {
+ private static final String TAG = ProviderAPICommand.class.getSimpleName();
private Context context;
private String action;
@@ -60,22 +62,22 @@ public class ProviderAPICommand {
return command;
}
- public static void execute(Context context, String action, Provider provider) {
+ public static void execute(Context context, String action, @NotNull Provider provider) {
ProviderAPICommand command = new ProviderAPICommand(context, action, provider);
command.execute();
}
- public static void execute(Context context, String action, Bundle parameters, Provider provider) {
+ public static void execute(Context context, String action, Bundle parameters, @NotNull 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) {
+ public static void execute(Context context, String action, Bundle parameters, @NotNull 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) {
+ public static void execute(Context context, String action, @NotNull 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 1fb6bf48..e5ca184f 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
@@ -22,11 +22,12 @@ import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.ResultReceiver;
-import androidx.annotation.NonNull;
import android.util.Base64;
import android.util.Log;
import android.util.Pair;
+import androidx.annotation.NonNull;
+
import org.json.JSONException;
import org.json.JSONObject;
@@ -60,17 +61,21 @@ 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.EIP_ACTION_START;
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.Provider.CA_CERT;
+import static se.leap.bitmaskclient.Provider.GEOIP_URL;
import static se.leap.bitmaskclient.Provider.PROVIDER_API_IP;
import static se.leap.bitmaskclient.Provider.PROVIDER_IP;
import static se.leap.bitmaskclient.ProviderAPI.BACKEND_ERROR_KEY;
import static se.leap.bitmaskclient.ProviderAPI.BACKEND_ERROR_MESSAGE;
import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE;
+import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_GEOIP_JSON;
import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_GEOIP_JSON;
import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_SERVICE_JSON;
import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.ERRORID;
@@ -78,6 +83,7 @@ import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
import static se.leap.bitmaskclient.ProviderAPI.FAILED_LOGIN;
import static se.leap.bitmaskclient.ProviderAPI.FAILED_SIGNUP;
import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE;
+import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_GEOIP_JSON;
import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.ProviderAPI.LOGOUT_FAILED;
@@ -143,7 +149,11 @@ public abstract class ProviderApiManagerBase {
}
public void handleIntent(Intent command) {
- final ResultReceiver receiver = command.getParcelableExtra(RECEIVER_KEY);
+// Log.d(TAG, "handleIntent was called!");
+ ResultReceiver receiver = null;
+ if (command.getParcelableExtra(RECEIVER_KEY) != null) {
+ receiver = command.getParcelableExtra(RECEIVER_KEY);
+ }
String action = command.getAction();
Bundle parameters = command.getBundleExtra(PARAMETERS);
@@ -167,6 +177,7 @@ public abstract class ProviderApiManagerBase {
Bundle task = new Bundle();
result = setUpProvider(provider, task);
if (result.getBoolean(BROADCAST_RESULT_KEY)) {
+ getGeoIPJson(provider);
sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider);
} else {
sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider);
@@ -177,6 +188,7 @@ public abstract class ProviderApiManagerBase {
ProviderObservable.getInstance().setProviderForDns(provider);
result = setUpProvider(provider, parameters);
if (result.getBoolean(BROADCAST_RESULT_KEY)) {
+ getGeoIPJson(provider);
sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider);
} else {
sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider);
@@ -245,6 +257,20 @@ public abstract class ProviderApiManagerBase {
}
}
break;
+
+ case DOWNLOAD_GEOIP_JSON:
+ if (!provider.getGeoipUrl().isDefault()) {
+ boolean startEIP = parameters.getBoolean(EIP_ACTION_START);
+ ProviderObservable.getInstance().setProviderForDns(provider);
+ result = getGeoIPJson(provider);
+ result.putBoolean(EIP_ACTION_START, startEIP);
+ if (result.getBoolean(BROADCAST_RESULT_KEY)) {
+ sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_GEOIP_JSON, result, provider);
+ } else {
+ sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_GEOIP_JSON, result, provider);
+ }
+ ProviderObservable.getInstance().setProviderForDns(null);
+ }
}
}
@@ -664,6 +690,15 @@ public abstract class ProviderApiManagerBase {
protected abstract Bundle updateVpnCertificate(Provider provider);
+ /**
+ * Fetches the Geo ip Json, containing a list of gateways sorted by distance from the users current location
+ *
+ * @param provider
+ * @return
+ */
+ protected abstract Bundle getGeoIPJson(Provider provider);
+
+
protected boolean isValidJson(String jsonString) {
try {
new JSONObject(jsonString);
@@ -708,6 +743,7 @@ public abstract class ProviderApiManagerBase {
provider.setVpnCertificate(getPersistedVPNCertificate(providerDomain));
provider.setProviderApiIp(getPersistedProviderApiIp(providerDomain));
provider.setProviderIp(getPersistedProviderIp(providerDomain));
+ provider.setGeoipUrl(getPersistedGeoIp(providerDomain));
}
}
@@ -816,6 +852,10 @@ public abstract class ProviderApiManagerBase {
return getFromPersistedProvider(PROVIDER_IP, providerDomain, preferences);
}
+ protected String getPersistedGeoIp(String providerDomain) {
+ return getFromPersistedProvider(GEOIP_URL, providerDomain, preferences);
+ }
+
protected boolean hasUpdatedProviderDetails(String domain) {
return preferences.contains(Provider.KEY + "." + domain) && preferences.contains(CA_CERT + "." + domain);
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
index 7c45c921..a7d0f916 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java
@@ -106,7 +106,7 @@ public abstract class ProviderListBaseActivity extends ProviderSetupBaseActivity
}
public void showAndSelectProvider(String newURL) {
- provider = new Provider(newURL, "", "");
+ provider = new Provider(newURL, null, null);
autoSelectProvider();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
index 6d074a7a..c23ad270 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
@@ -20,6 +20,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import static se.leap.bitmaskclient.Provider.GEOIP_URL;
import static se.leap.bitmaskclient.Provider.MAIN_URL;
import static se.leap.bitmaskclient.Provider.PROVIDER_API_IP;
import static se.leap.bitmaskclient.Provider.PROVIDER_IP;
@@ -90,18 +91,20 @@ public class ProviderManager implements AdapteeCollection<Provider> {
String providerApiIp = null;
String certificate = null;
String providerDefinition = null;
+ String geoipUrl = null;
try {
String provider = file.substring(0, file.length() - ".url".length());
InputStream providerFile = assetsManager.open(directory + "/" + file);
mainUrl = extractKeyFromInputStream(providerFile, MAIN_URL);
providerIp = extractKeyFromInputStream(providerFile, PROVIDER_IP);
providerApiIp = extractKeyFromInputStream(providerFile, PROVIDER_API_IP);
+ geoipUrl = extractKeyFromInputStream(providerFile, GEOIP_URL);
certificate = loadInputStreamAsString(assetsManager.open(provider + EXT_PEM));
providerDefinition = loadInputStreamAsString(assetsManager.open(provider + EXT_JSON));
} catch (IOException e) {
e.printStackTrace();
}
- providers.add(new Provider(mainUrl, providerIp, providerApiIp, certificate, providerDefinition));
+ providers.add(new Provider(mainUrl, geoipUrl, providerIp, providerApiIp, certificate, providerDefinition));
}
return providers;
diff --git a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
index b6ace6db..dd4878f3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java
@@ -21,9 +21,10 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
+import android.util.Log;
+
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
-import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -40,8 +41,6 @@ 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;
import static se.leap.bitmaskclient.utils.ConfigHelper.isDefaultBitmask;
-import static se.leap.bitmaskclient.utils.PreferenceHelper.getSavedProviderFromSharedPreferences;
-import static se.leap.bitmaskclient.utils.PreferenceHelper.providerInSharedPreferences;
import static se.leap.bitmaskclient.utils.PreferenceHelper.storeProviderInPreferences;
/**
@@ -162,9 +161,9 @@ public class StartActivity extends Activity{
}
private void prepareEIP() {
- boolean providerExists = providerInSharedPreferences(preferences);
+ boolean providerExists = ProviderObservable.getInstance().getCurrentProvider() != null;
if (providerExists) {
- Provider provider = getSavedProviderFromSharedPreferences(preferences);
+ Provider provider = ProviderObservable.getInstance().getCurrentProvider();
if(!provider.isConfigured()) {
configureLeapProvider();
} else {
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 34c88ef9..e0c96ebb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
@@ -226,7 +226,7 @@ public final class EIP extends JobIntentService implements Observer {
return;
}
- GatewaysManager gatewaysManager = gatewaysFromPreferences();
+ GatewaysManager gatewaysManager = new GatewaysManager(getApplicationContext());
if (gatewaysManager.isEmpty()) {
setErrorResult(result, warning_client_parsing_error_gateways, null);
tellToReceiverOrBroadcast(this, EIP_ACTION_START, RESULT_CANCELED, result);
@@ -248,7 +248,7 @@ public final class EIP extends JobIntentService implements Observer {
* The {@link OnBootReceiver} will care if there is no profile.
*/
private void startEIPAlwaysOnVpn() {
- GatewaysManager gatewaysManager = gatewaysFromPreferences();
+ GatewaysManager gatewaysManager = new GatewaysManager(getApplicationContext());
Gateway gateway = gatewaysManager.select(0);
if (!launchActiveGateway(gateway, 0)) {
@@ -310,15 +310,6 @@ public final class EIP extends JobIntentService implements Observer {
}
/**
- * read eipServiceJson from preferences and parse Gateways
- *
- * @return GatewaysManager
- */
- private GatewaysManager gatewaysFromPreferences() {
- return new GatewaysManager(getApplicationContext(), preferences);
- }
-
- /**
* read VPN certificate from preferences and check it
* broadcast result
*/
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 66c9fe84..f3eea415 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
@@ -34,6 +34,7 @@ import de.blinkt.openvpn.core.ConfigParser;
import de.blinkt.openvpn.core.connection.Connection;
import se.leap.bitmaskclient.utils.PreferenceHelper;
+import static se.leap.bitmaskclient.Constants.HOST;
import static se.leap.bitmaskclient.Constants.IP_ADDRESS;
import static se.leap.bitmaskclient.Constants.LOCATION;
import static se.leap.bitmaskclient.Constants.LOCATIONS;
@@ -114,6 +115,10 @@ public class Gateway {
return gateway.optString(IP_ADDRESS);
}
+ public String getHost() {
+ return gateway.optString(HOST);
+ }
+
private String locationAsName(JSONObject eipDefinition) {
JSONObject location = getLocationInfo(eipDefinition);
return location.optString(NAME);
@@ -152,6 +157,10 @@ public class Gateway {
return vpnProfiles.get(transportType);
}
+ public boolean suppoortsTransport(Connection.TransportType transportType) {
+ return vpnProfiles.get(transportType) != null;
+ }
+
public int getTimezone() {
return timezone;
}
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 fbe1861a..0515a35e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
@@ -17,7 +17,6 @@
package se.leap.bitmaskclient.eip;
import android.content.Context;
-import android.content.SharedPreferences;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
@@ -30,6 +29,7 @@ import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedHashMap;
+import java.util.List;
import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.core.ConfigParser;
@@ -37,7 +37,6 @@ import de.blinkt.openvpn.core.VpnStatus;
import de.blinkt.openvpn.core.connection.Connection;
import se.leap.bitmaskclient.Provider;
import se.leap.bitmaskclient.ProviderObservable;
-import se.leap.bitmaskclient.utils.PreferenceHelper;
import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4;
import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN;
@@ -54,15 +53,9 @@ public class GatewaysManager {
private static final String TAG = GatewaysManager.class.getSimpleName();
private Context context;
- private SharedPreferences preferences;
private LinkedHashMap<String, Gateway> gateways = new LinkedHashMap<>();
private Type listType = new TypeToken<ArrayList<Gateway>>() {}.getType();
-
- public GatewaysManager(Context context, SharedPreferences preferences) {
- this.preferences = preferences;
- this.context = context;
- configureFromPreferences();
- }
+ private ArrayList<Gateway> presortedList = new ArrayList<>();
public GatewaysManager(Context context) {
configureFromCurrentProvider();
@@ -75,13 +68,42 @@ public class GatewaysManager {
*/
public Gateway select(int nClosest) {
Connection.TransportType transportType = getUsePluggableTransports(context) ? OBFS4 : OPENVPN;
- GatewaySelector gatewaySelector = new GatewaySelector(new ArrayList<>(gateways.values()));
+
+ if (presortedList.size() > 0) {
+ return getGatewayFromPresortedList(nClosest, transportType);
+ }
+
+ return getGatewayFromTimezoneCalculation(nClosest, transportType);
+ }
+
+
+ private Gateway getGatewayFromTimezoneCalculation(int nClosest, Connection.TransportType transportType) {
+ List<Gateway> list = new ArrayList<>(gateways.values());
+ GatewaySelector gatewaySelector = new GatewaySelector(list);
Gateway gateway;
- while ((gateway = gatewaySelector.select(nClosest)) != null) {
- if (gateway.getProfile(transportType) != null) {
- return gateway;
+ int found = 0;
+ int i = 0;
+ while ((gateway = gatewaySelector.select(i)) != null) {
+ if (gateway.suppoortsTransport(transportType)) {
+ if (found == nClosest) {
+ return gateway;
+ }
+ found++;
+ }
+ i++;
+ }
+ return null;
+ }
+
+ private Gateway getGatewayFromPresortedList(int nClosest, Connection.TransportType transportType) {
+ int found = 0;
+ for (Gateway gateway : presortedList) {
+ if (gateway.suppoortsTransport(transportType)) {
+ if (found == nClosest) {
+ return gateway;
+ }
+ found++;
}
- nClosest++;
}
return null;
}
@@ -92,15 +114,41 @@ public class GatewaysManager {
* @return position of the gateway owning to the profile
*/
public int getPosition(VpnProfile profile) {
- Connection.TransportType transportType = getUsePluggableTransports(context) ? OBFS4 : OPENVPN;
+ if (presortedList.size() > 0) {
+ return getPositionFromPresortedList(profile);
+ }
+
+ return getPositionFromTimezoneCalculatedList(profile);
+ }
+
+ private int getPositionFromPresortedList(VpnProfile profile) {
+ Connection.TransportType transportType = profile.mUsePluggableTransports ? OBFS4 : OPENVPN;
+ int nClosest = 0;
+ for (Gateway gateway : presortedList) {
+ if (gateway.suppoortsTransport(transportType)) {
+ if (profile.equals(gateway.getProfile(transportType))) {
+ return nClosest;
+ }
+ nClosest++;
+ }
+ }
+ return -1;
+ }
+
+ private int getPositionFromTimezoneCalculatedList(VpnProfile profile) {
+ Connection.TransportType transportType = profile.mUsePluggableTransports ? OBFS4 : OPENVPN;
GatewaySelector gatewaySelector = new GatewaySelector(new ArrayList<>(gateways.values()));
Gateway gateway;
int nClosest = 0;
- while ((gateway = gatewaySelector.select(nClosest)) != null) {
- if (profile.equals(gateway.getProfile(transportType))) {
- return nClosest;
+ int i = 0;
+ while ((gateway = gatewaySelector.select(i)) != null) {
+ if (gateway.suppoortsTransport(transportType)) {
+ if (profile.equals(gateway.getProfile(transportType))) {
+ return nClosest;
+ }
+ nClosest++;
}
- nClosest++;
+ i++;
}
return -1;
}
@@ -126,41 +174,56 @@ public class GatewaysManager {
}
/**
- * parse gateways from eipDefinition
- * @param eipDefinition eipServiceJson
+ * parse gateways from Provider's eip service
+ * @param provider
*/
- private void fromEipServiceJson(JSONObject eipDefinition, JSONObject secrets) {
- JSONArray gatewaysDefined = new JSONArray();
- try {
- gatewaysDefined = eipDefinition.getJSONArray(GATEWAYS);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- for (int i = 0; i < gatewaysDefined.length(); i++) {
- try {
- JSONObject gw = gatewaysDefined.getJSONObject(i);
- Gateway aux = new Gateway(eipDefinition, secrets, gw, this.context);
- if (gateways.get(aux.getRemoteIP()) == null) {
- addGateway(aux);
- }
- } catch (JSONException | ConfigParser.ConfigParseError | IOException e) {
- e.printStackTrace();
- VpnStatus.logError("Unable to parse gateway config!");
- }
- }
+ private void parseDefaultGateways(Provider provider) {
+ try {
+ JSONObject eipDefinition = provider.getEipServiceJson();
+ JSONObject secrets = secretsConfigurationFromCurrentProvider();
+
+ JSONArray gatewaysDefined = new JSONArray();
+ try {
+ gatewaysDefined = eipDefinition.getJSONArray(GATEWAYS);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ for (int i = 0; i < gatewaysDefined.length(); i++) {
+ try {
+ JSONObject gw = gatewaysDefined.getJSONObject(i);
+ Gateway aux = new Gateway(eipDefinition, secrets, gw, this.context);
+ if (gateways.get(aux.getHost()) == null) {
+ addGateway(aux);
+ }
+ } catch (JSONException | ConfigParser.ConfigParseError | IOException e) {
+ e.printStackTrace();
+ VpnStatus.logError("Unable to parse gateway config!");
+ }
+ }
+ } catch (NullPointerException npe) {
+ npe.printStackTrace();
+ }
}
- private JSONObject secretsConfigurationFromPreferences() {
- JSONObject result = new JSONObject();
- try {
- result.put(Provider.CA_CERT, preferences.getString(Provider.CA_CERT, ""));
- result.put(PROVIDER_PRIVATE_KEY, preferences.getString(PROVIDER_PRIVATE_KEY, ""));
- result.put(PROVIDER_VPN_CERTIFICATE, preferences.getString(PROVIDER_VPN_CERTIFICATE, ""));
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return result;
+ private void parseGatewaysFromGeoIpServiceJson(Provider provider) {
+ try {
+ JSONObject geoIpJson = provider.getGeoIpJson();
+ JSONArray gatewaylist = geoIpJson.getJSONArray(GATEWAYS);
+
+ for (int i = 0; i < gatewaylist.length(); i++) {
+ try {
+ String key = gatewaylist.getString(i);
+ if (gateways.containsKey(key)) {
+ presortedList.add(gateways.get(key));
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ } catch (NullPointerException | JSONException npe) {
+ npe.printStackTrace();
+ }
}
private JSONObject secretsConfigurationFromCurrentProvider() {
@@ -177,31 +240,13 @@ public class GatewaysManager {
return result;
}
-
- void clearGateways() {
- gateways.clear();
- }
-
private void addGateway(Gateway gateway) {
- gateways.put(gateway.getRemoteIP(), gateway);
- }
-
- /**
- * read EipServiceJson from preferences and set gateways
- */
- private void configureFromPreferences() {
- fromEipServiceJson(
- PreferenceHelper.getEipDefinitionFromPreferences(preferences), secretsConfigurationFromPreferences()
- );
+ gateways.put(gateway.getHost(), gateway);
}
private void configureFromCurrentProvider() {
- try {
- JSONObject json = ProviderObservable.getInstance().getCurrentProvider().getEipServiceJson();
- fromEipServiceJson(json, secretsConfigurationFromCurrentProvider());
- } catch (NullPointerException npe) {
- npe.printStackTrace();
- }
-
+ Provider provider = ProviderObservable.getInstance().getCurrentProvider();
+ parseDefaultGateways(provider);
+ parseGatewaysFromGeoIpServiceJson(provider);
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java
index 669b7f8e..cb2aeb26 100644
--- a/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java
@@ -37,9 +37,6 @@ import static se.leap.bitmaskclient.Constants.USE_PLUGGABLE_TRANSPORTS;
*/
public class PreferenceHelper {
- public static boolean providerInSharedPreferences(@NonNull SharedPreferences preferences) {
- return preferences.getBoolean(PROVIDER_CONFIGURED, false);
- }
public static Provider getSavedProviderFromSharedPreferences(@NonNull SharedPreferences preferences) {
Provider provider = new Provider();
@@ -47,6 +44,7 @@ public class PreferenceHelper {
provider.setMainUrl(new URL(preferences.getString(Provider.MAIN_URL, "")));
provider.setProviderIp(preferences.getString(Provider.PROVIDER_IP, ""));
provider.setProviderApiIp(preferences.getString(Provider.PROVIDER_API_IP, ""));
+ provider.setGeoipUrl(preferences.getString(Provider.GEOIP_URL, ""));
provider.define(new JSONObject(preferences.getString(Provider.KEY, "")));
provider.setCaCert(preferences.getString(Provider.CA_CERT, ""));
provider.setVpnCertificate(preferences.getString(PROVIDER_VPN_CERTIFICATE, ""));
@@ -68,6 +66,7 @@ public class PreferenceHelper {
public static void storeProviderInPreferences(SharedPreferences preferences, Provider provider) {
preferences.edit().putBoolean(PROVIDER_CONFIGURED, true).
putString(Provider.PROVIDER_IP, provider.getProviderIp()).
+ putString(Provider.GEOIP_URL, provider.getGeoipUrl().toString()).
putString(Provider.PROVIDER_API_IP, provider.getProviderApiIp()).
putString(Provider.MAIN_URL, provider.getMainUrlString()).
putString(Provider.KEY, provider.getDefinitionString()).
@@ -82,6 +81,7 @@ public class PreferenceHelper {
putString(Provider.PROVIDER_IP + "." + providerDomain, provider.getProviderIp()).
putString(Provider.PROVIDER_API_IP + "." + providerDomain, provider.getProviderApiIp()).
putString(Provider.MAIN_URL + "." + providerDomain, provider.getMainUrlString()).
+ putString(Provider.GEOIP_URL + "." + providerDomain, provider.getGeoipUrl().toString()).
putString(Provider.KEY + "." + providerDomain, provider.getDefinitionString()).
putString(Provider.CA_CERT + "." + providerDomain, provider.getCaCert()).
putString(PROVIDER_EIP_DEFINITION + "." + providerDomain, provider.getEipServiceJsonString()).
@@ -114,6 +114,7 @@ public class PreferenceHelper {
remove(Provider.PROVIDER_IP + "." + providerDomain).
remove(Provider.PROVIDER_API_IP + "." + providerDomain).
remove(Provider.MAIN_URL + "." + providerDomain).
+ remove(Provider.GEOIP_URL + "." + providerDomain).
remove(PROVIDER_EIP_DEFINITION + "." + providerDomain).
remove(PROVIDER_PRIVATE_KEY + "." + providerDomain).
remove(PROVIDER_VPN_CERTIFICATE + "." + providerDomain).
diff --git a/app/src/normal/assets/urls/riseup.net.url b/app/src/normal/assets/urls/riseup.net.url
index a4a90f90..3c1e6b49 100644
--- a/app/src/normal/assets/urls/riseup.net.url
+++ b/app/src/normal/assets/urls/riseup.net.url
@@ -1,5 +1,6 @@
{
"main_url" : "https://riseup.net",
"provider_ip" : "198.252.153.70",
- "provider_api_ip" : "198.252.153.107"
+ "provider_api_ip" : "198.252.153.107",
+ "geoip_url" : "https://api.black.riseup.net:9001/json"
}
diff --git a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java
index ceaeebc0..04ffe9e6 100644
--- a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java
+++ b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java
@@ -20,9 +20,10 @@ package se.leap.bitmaskclient;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
-import androidx.multidex.BuildConfig;
import android.util.Pair;
+import androidx.multidex.BuildConfig;
+
import org.json.JSONException;
import org.json.JSONObject;
@@ -58,6 +59,8 @@ import static se.leap.bitmaskclient.utils.ConfigHelper.getProviderFormattedStrin
public class ProviderApiManager extends ProviderApiManagerBase {
+ private static final String TAG = ProviderApiManager.class.getSimpleName();
+
public ProviderApiManager(SharedPreferences preferences, Resources resources, OkHttpClientGenerator clientGenerator, ProviderApiServiceCallback callback) {
super(preferences, resources, clientGenerator, callback);
}
@@ -120,14 +123,12 @@ public class ProviderApiManager extends ProviderApiManagerBase {
private Bundle getAndSetProviderJson(Provider provider) {
Bundle result = new Bundle();
- String caCert = provider.getCaCert();
-
String providerDotJsonString;
- if(provider.getDefinitionString().length() == 0 || caCert.isEmpty()) {
+ if(provider.getDefinitionString().length() == 0 || provider.getCaCert().isEmpty()) {
String providerJsonUrl = provider.getMainUrlString() + "/provider.json";
providerDotJsonString = downloadWithCommercialCA(providerJsonUrl, provider);
} else {
- providerDotJsonString = downloadFromApiUrlWithProviderCA("/provider.json", caCert, provider);
+ providerDotJsonString = downloadFromApiUrlWithProviderCA("/provider.json", provider);
}
if (ConfigHelper.checkErroneousDownload(providerDotJsonString) || !isValidJson(providerDotJsonString)) {
@@ -214,6 +215,43 @@ public class ProviderApiManager extends ProviderApiManagerBase {
return result;
}
+ /**
+ * Fetches the Geo ip Json, containing a list of gateways sorted by distance from the users current location
+ *
+ * @param provider
+ * @return
+ */
+ @Override
+ protected Bundle getGeoIPJson(Provider provider) {
+ Bundle result = new Bundle();
+
+ if (!provider.shouldUpdateGeoIpJson() || provider.getGeoipUrl().isDefault()) {
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ return result;
+ }
+
+ try {
+ URL geoIpUrl = provider.getGeoipUrl().getUrl();
+
+ String geoipJsonString = downloadFromUrlWithProviderCA(geoIpUrl.toString(), provider);
+ JSONObject geoipJson = new JSONObject(geoipJsonString);
+
+ if (geoipJson.has(ERRORS)) {
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ } else{
+ provider.setGeoIpJson(geoipJson);
+ provider.setLastGeoIpUpdate(System.currentTimeMillis());
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
+ }
+
+ } catch (JSONException | NullPointerException e) {
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+
private Bundle downloadCACert(Provider provider) {
Bundle result = new Bundle();
try {
@@ -276,30 +314,33 @@ public class ProviderApiManager extends ProviderApiManagerBase {
*
* @return an empty string if it fails, the response body if not.
*/
- private String downloadFromApiUrlWithProviderCA(String path, String caCert, Provider provider) {
+ private String downloadFromApiUrlWithProviderCA(String path, Provider provider) {
+ String baseUrl = provider.getApiUrlString();
+ String urlString = baseUrl + path;
+ return downloadFromUrlWithProviderCA(urlString, provider);
+ }
+
+ private String downloadFromUrlWithProviderCA(String urlString, Provider provider) {
String responseString;
JSONObject errorJson = new JSONObject();
- String baseUrl = provider.getApiUrlString();
- OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(caCert, errorJson);
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), errorJson);
if (okHttpClient == null) {
return errorJson.toString();
}
- String urlString = baseUrl + path;
List<Pair<String, String>> headerArgs = getAuthorizationHeader();
responseString = sendGetStringToServer(urlString, headerArgs, okHttpClient);
return responseString;
-
}
- /**
- * Tries to download the contents of the provided url using not commercially validated CA certificate from chosen provider.
- *
- * @param urlString as a string
- * @return an empty string if it fails, the url content if not.
- */
+ /**
+ * Tries to download the contents of the provided url using not commercially validated CA certificate from chosen provider.
+ *
+ * @param urlString as a string
+ * @return an empty string if it fails, the url content if not.
+ */
private String downloadWithProviderCA(String caCert, String urlString) {
JSONObject initError = new JSONObject();
String responseString;
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 c7c85f8d..c741faf2 100644
--- a/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java
+++ b/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java
@@ -51,12 +51,14 @@ public class TestSetupHelper {
public static Provider getConfiguredProvider() throws IOException, JSONException {
- return getProvider(null, null, null, null, null, null);
+ return getProvider(null, null, null, null, null, null, null, null);
}
- public static Provider getProvider(String domain, String providerIp, String providerApiIp, String caCertFile, String providerJson, String eipServiceJson) {
+ public static Provider getProvider(String domain, String geoipUrl, String providerIp, String providerApiIp, String caCertFile, String providerJson, String eipServiceJson, String geoIpJson) {
if (domain == null)
domain = "https://riseup.net";
+ if (geoipUrl == null)
+ geoipUrl = "https://api.black.riseup.net:9001/json";
if (providerIp == null) {
providerIp = "";
}
@@ -70,10 +72,14 @@ public class TestSetupHelper {
if (eipServiceJson == null) {
eipServiceJson = "riseup.service.json";
}
+ if (geoIpJson == null) {
+ geoIpJson = "riseup.geoip.json";
+ }
try {
Provider p = new Provider(
domain,
+ geoipUrl,
providerIp,
providerApiIp,
getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(caCertFile)),
@@ -83,6 +89,10 @@ public class TestSetupHelper {
JSONObject eipServiceJsonObject = new JSONObject(
getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(eipServiceJson)));
p.setEipServiceJson(eipServiceJsonObject);
+
+ JSONObject geoIpJsonObject = new JSONObject(
+ getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(geoIpJson)));
+ p.setGeoIpJson(geoIpJsonObject);
return p;
} catch (IOException | JSONException e) {
e.printStackTrace();
diff --git a/app/src/test/java/se/leap/bitmaskclient/PreferenceHelperTest.java b/app/src/test/java/se/leap/bitmaskclient/PreferenceHelperTest.java
index d49fa08c..edac3480 100644
--- a/app/src/test/java/se/leap/bitmaskclient/PreferenceHelperTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/PreferenceHelperTest.java
@@ -6,18 +6,14 @@ import org.junit.Before;
import org.junit.Test;
import se.leap.bitmaskclient.testutils.MockSharedPreferences;
-import se.leap.bitmaskclient.utils.ConfigHelper;
-import se.leap.bitmaskclient.utils.PreferenceHelper;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-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;
import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
import static se.leap.bitmaskclient.utils.PreferenceHelper.getSavedProviderFromSharedPreferences;
-import static se.leap.bitmaskclient.utils.PreferenceHelper.providerInSharedPreferences;
/**
* Created by cyberta on 17.01.18.
@@ -33,17 +29,6 @@ public class PreferenceHelperTest {
}
@Test
- public void providerInSharedPreferences_notInPreferences_returnsFalse() throws Exception {
- assertFalse(providerInSharedPreferences(mockPreferences));
- }
-
- @Test
- public void providerInSharedPreferences_inPreferences_returnsTrue() throws Exception {
- mockPreferences.edit().putBoolean(PROVIDER_CONFIGURED, true).apply();
- assertTrue(providerInSharedPreferences(mockPreferences));
- }
-
- @Test
public void getSavedProviderFromSharedPreferences_notInPreferences_returnsDefaultProvider() throws Exception {
Provider provider = getSavedProviderFromSharedPreferences(mockPreferences);
assertFalse(provider.isConfigured());
diff --git a/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java
index 0f9d358e..8a74e5de 100644
--- a/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java
@@ -23,13 +23,21 @@ public class ProviderTest {
}
@Test
- public void testEquals_sameFields_returnsFalse() throws Exception {
+ public void testEquals_differntMainUrl_returnsFalse() throws Exception {
Provider p1 = TestSetupHelper.getConfiguredProvider();
Provider p2 = TestSetupHelper.getConfiguredProvider();
p2.setMainUrl("http://somethingsdiffer.org");
assertFalse("Providers should be same:", p1.equals(p2));
}
+ @Test
+ public void testEquals_differentGeoIpUrl_returnsFalse() throws Exception {
+ Provider p1 = TestSetupHelper.getConfiguredProvider();
+ Provider p2 = TestSetupHelper.getConfiguredProvider();
+ p2.setGeoipUrl(null);
+ assertFalse("Providers should be same:", p1.equals(p2));
+ }
+
// see ProviderManagerTest testing add(...)
@Test
public void testEqualsThroughSetContains_differentFields_returnsFalse() throws Exception {
@@ -55,7 +63,9 @@ public class ProviderTest {
null,
null,
null,
- "ptdemo.bitmask.eip-service.json");
+ null,
+ "ptdemo.bitmask.eip-service.json",
+ null);
assertTrue(p1.supportsPluggableTransports());
}
@@ -67,7 +77,9 @@ public class ProviderTest {
null,
null,
null,
- "eip-service-two-gateways.json");
+ null,
+ "eip-service-two-gateways.json",
+ null);
assertFalse(p1.supportsPluggableTransports());
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
index 417c4bfc..bfe96d2c 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
@@ -74,29 +74,6 @@ public class GatewaysManagerTest {
.commit();
}
- @Test
- public void testFromEipServiceJson_emptyJson() throws Exception {
- GatewaysManager gatewaysManager = new GatewaysManager(mockContext, sharedPreferences);
- assertEquals(0, gatewaysManager.size());
- }
-
- @Test
- public void testFromEipServiceJson_ignoreGatewaysWithMisconfiguredTransportsWhileAddingValidOnes() throws Exception {
- updateEipServiceJson("ptdemo_misconfigured_mixed_gateways.json");
- GatewaysManager gatewaysManager = new GatewaysManager(mockContext, sharedPreferences);
- assertEquals(1, gatewaysManager.size());
- assertNull(gatewaysManager.select(0).getProfile(OBFS4));
- assertNotNull(gatewaysManager.select(0).getProfile(Connection.TransportType.OPENVPN));
- }
-
- @Test
- public void testClearGatewaysAndProfiles_resetGateways() throws Exception {
- updateEipServiceJson("eip-service-two-gateways.json");
- GatewaysManager gatewaysManager = new GatewaysManager(mockContext, sharedPreferences);
- assertEquals(2, gatewaysManager.size());
- gatewaysManager.clearGateways();
- assertEquals(0, gatewaysManager.size());
- }
@Test
public void testGatewayManagerFromCurrentProvider_noProvider_noGateways() {
@@ -107,7 +84,7 @@ public class GatewaysManagerTest {
@Test
public void testGatewayManagerFromCurrentProvider_misconfiguredProvider_noGateways() throws IOException, NullPointerException {
- Provider provider = getProvider(null, null, null, null, null, "ptdemo_misconfigured_gateway.json");
+ Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_misconfigured_gateway.json", null);
MockHelper.mockProviderObserver(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals(0, gatewaysManager.size());
@@ -115,7 +92,7 @@ public class GatewaysManagerTest {
@Test
public void testGatewayManagerFromCurrentProvider_threeGateways() {
- Provider provider = getProvider(null, null, null,null, null, "ptdemo_three_mixed_gateways.json");
+ Provider provider = getProvider(null, null, null, null,null, null, "ptdemo_three_mixed_gateways.json", null);
MockHelper.mockProviderObserver(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals(3, gatewaysManager.size());
@@ -123,12 +100,10 @@ public class GatewaysManagerTest {
@Test
public void TestGetPosition_VpnProfileExtistingObfs4_returnPositionZero() throws JSONException, ConfigParser.ConfigParseError, IOException {
- Provider provider = getProvider(null, null, null, null, null, "ptdemo_three_mixed_gateways.json");
+ Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null);
JSONObject eipServiceJson = provider.getEipServiceJson();
JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0);
MockHelper.mockProviderObserver(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUsePluggableTransports(any(Context.class))).thenReturn(true);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
@@ -140,12 +115,10 @@ public class GatewaysManagerTest {
@Test
public void TestGetPosition_VpnProfileExtistingOpenvpn_returnPositionZero() throws JSONException, ConfigParser.ConfigParseError, IOException {
- Provider provider = getProvider(null, null, null, null, null, "ptdemo_three_mixed_gateways.json");
+ Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null);
JSONObject eipServiceJson = provider.getEipServiceJson();
JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0);
MockHelper.mockProviderObserver(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUsePluggableTransports(any(Context.class))).thenReturn(false);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
@@ -156,13 +129,41 @@ public class GatewaysManagerTest {
}
@Test
+ public void TestGetPosition_VpnProfileExistingObfs4FromPresortedList_returnsPositionOne() throws JSONException, ConfigParser.ConfigParseError, IOException {
+ Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json");
+ JSONObject eipServiceJson = provider.getEipServiceJson();
+ JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0);
+ MockHelper.mockProviderObserver(provider);
+ GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
+
+ VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
+ VpnProfile profile = configGenerator.createProfile(OBFS4);
+ profile.mGatewayIp = "37.218.247.60";
+
+ assertEquals(1, gatewaysManager.getPosition(profile));
+ }
+
+ @Test
+ public void TestGetPosition_VpnProfileExistingOpenvpnFromPresortedList_returnsPositionOne() throws JSONException, ConfigParser.ConfigParseError, IOException {
+ Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json");
+ JSONObject eipServiceJson = provider.getEipServiceJson();
+ JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0);
+ MockHelper.mockProviderObserver(provider);
+ GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
+
+ VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
+ VpnProfile profile = configGenerator.createProfile(OPENVPN);
+ profile.mGatewayIp = "37.218.247.60";
+
+ assertEquals(2, gatewaysManager.getPosition(profile));
+ }
+
+ @Test
public void TestGetPosition_VpnProfileDifferentIp_returnMinusOne() throws JSONException, ConfigParser.ConfigParseError, IOException {
- Provider provider = getProvider(null, null, null, null, null, "ptdemo_three_mixed_gateways.json");
+ Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null);
JSONObject eipServiceJson = provider.getEipServiceJson();
JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0);
MockHelper.mockProviderObserver(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUsePluggableTransports(any(Context.class))).thenReturn(true);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
@@ -174,12 +175,10 @@ public class GatewaysManagerTest {
@Test
public void TestGetPosition_VpnProfileMoscow_returnOne() throws JSONException, ConfigParser.ConfigParseError, IOException {
- Provider provider = getProvider(null, null, null, null, null, "ptdemo_three_mixed_gateways.json");
+ Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null);
JSONObject eipServiceJson = provider.getEipServiceJson();
JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(1);
MockHelper.mockProviderObserver(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUsePluggableTransports(any(Context.class))).thenReturn(true);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
@@ -190,10 +189,8 @@ public class GatewaysManagerTest {
}
@Test
- public void TestSelectN_selectFirstObfs4Connection_returnThirdGateway() throws JSONException, ConfigParser.ConfigParseError, IOException {
- Provider provider = getProvider(null, null, null, null, null, "ptdemo_two_openvpn_one_pt_gateways.json");
- JSONObject eipServiceJson = provider.getEipServiceJson();
- JSONObject gateway3 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(2);
+ public void TestSelectN_selectFirstObfs4Connection_returnThirdGateway() {
+ Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_two_openvpn_one_pt_gateways.json", null);
MockHelper.mockProviderObserver(provider);
mockStatic(PreferenceHelper.class);
@@ -203,6 +200,37 @@ public class GatewaysManagerTest {
assertEquals("37.12.247.10", gatewaysManager.select(0).getRemoteIP());
}
+ @Test
+ public void testSelectN_selectFromPresortedGateways_returnsGatewaysInPresortedOrder() {
+ Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json");
+
+ MockHelper.mockProviderObserver(provider);
+ //use openvpn, not pluggable transports
+ mockStatic(PreferenceHelper.class);
+ when(PreferenceHelper.getUsePluggableTransports(any(Context.class))).thenReturn(false);
+ GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
+
+ assertEquals("manila.bitmask.net", gatewaysManager.select(0).getHost());
+ assertEquals("moscow.bitmask.net", gatewaysManager.select(1).getHost());
+ assertEquals("pt.demo.bitmask.net", gatewaysManager.select(2).getHost());
+ }
+
+ @Test
+ public void testSelectN_selectObfs4FromPresortedGateways_returnsObfs4GatewaysInPresortedOrder() {
+ Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json");
+
+ MockHelper.mockProviderObserver(provider);
+ //use openvpn, not pluggable transports
+ mockStatic(PreferenceHelper.class);
+ when(PreferenceHelper.getUsePluggableTransports(any(Context.class))).thenReturn(true);
+ GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
+
+ assertEquals("moscow.bitmask.net", gatewaysManager.select(0).getHost());
+ assertEquals("pt.demo.bitmask.net", gatewaysManager.select(1).getHost());
+ assertNull(gatewaysManager.select(2));
+ }
+
+
private String getJsonStringFor(String filename) throws IOException {
return TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream(filename));
}
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 753a9474..efa6f78c 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java
@@ -25,6 +25,7 @@ import android.os.Bundle;
import android.text.TextUtils;
import org.json.JSONException;
+import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -44,18 +45,24 @@ import se.leap.bitmaskclient.ProviderAPI;
import se.leap.bitmaskclient.ProviderApiConnector;
import se.leap.bitmaskclient.ProviderApiManager;
import se.leap.bitmaskclient.ProviderApiManagerBase;
+import se.leap.bitmaskclient.testutils.BackendMockResponses.GeoIpServiceIsDownBackendResponse;
import se.leap.bitmaskclient.testutils.MockSharedPreferences;
import se.leap.bitmaskclient.utils.ConfigHelper;
import se.leap.bitmaskclient.utils.PreferenceHelper;
import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
+import static se.leap.bitmaskclient.Constants.EIP_ACTION_START;
import static se.leap.bitmaskclient.Constants.PROVIDER_KEY;
+import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_GEOIP_JSON;
import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
+import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_GEOIP_JSON;
+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.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID;
import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.ERROR_CASE_MICONFIGURED_PROVIDER;
import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.ERROR_CASE_UPDATED_CERTIFICATE;
+import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.ERROR_GEOIP_SERVICE_IS_DOWN;
import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.NO_ERROR;
import static se.leap.bitmaskclient.testutils.MockHelper.mockBundle;
import static se.leap.bitmaskclient.testutils.MockHelper.mockClientGenerator;
@@ -155,7 +162,7 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_happyPath_no_preseededProviderAndCA() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
- Provider provider = new Provider("https://riseup.net");
+ Provider provider = getConfiguredProvider();
mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
mockProviderApiConnector(NO_ERROR);
@@ -269,7 +276,7 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_preseededProviderAndCA_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
- Provider provider = getProvider(null ,null, null, "outdated_cert.pem", null, null);
+ Provider provider = getProvider(null ,null, null, null, "outdated_cert.pem", null, null, null);
mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
@@ -290,7 +297,7 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
- Provider provider = new Provider("https://riseup.net");
+ Provider provider = getConfiguredProvider(); //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();
@@ -386,7 +393,7 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_outdatedPreseededProviderAndCA_successfulConfiguration() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
- Provider provider = getProvider(null, null, null, null, "riseup_net_outdated_config.json", null);
+ Provider provider = getProvider(null, null, null, null, null, "riseup_net_outdated_config.json", null, null);
mockFingerprintForCertificate(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
mockProviderApiConnector(NO_ERROR);
@@ -431,4 +438,126 @@ public class ProviderApiManagerTest {
providerApiManager.handleIntent(providerApiCommand);
}
+
+
+ @Test
+ public void test_handleIntentGetGeoip_happyPath() throws IOException, NoSuchAlgorithmException, CertificateEncodingException, JSONException {
+ if ("insecure".equals(BuildConfig.FLAVOR_implementation )) {
+ return;
+ }
+
+ Provider inputProvider = getConfiguredProvider();
+ inputProvider.setGeoIpJson(new JSONObject());
+ Provider expectedProvider = getConfiguredProvider();
+ mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ mockProviderApiConnector(NO_ERROR);
+ providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+
+ Bundle expectedResult = mockBundle();
+ expectedResult.putBoolean(EIP_ACTION_START, true);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, true);
+ expectedResult.putParcelable(PROVIDER_KEY, expectedProvider);
+
+ Intent providerApiCommand = mockIntent();
+
+ providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON);
+ Bundle extrasBundle = mockBundle();
+ extrasBundle.putBoolean(EIP_ACTION_START, true);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(CORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, inputProvider);
+ providerApiCommand.putExtra(PARAMETERS, extrasBundle);
+
+ providerApiManager.handleIntent(providerApiCommand);
+
+ }
+
+
+ @Test
+ public void test_handleIntentGetGeoip_serviceDown_failToDownload() throws IOException, NoSuchAlgorithmException, CertificateEncodingException, JSONException {
+ if ("insecure".equals(BuildConfig.FLAVOR_implementation)) {
+ return;
+ }
+
+ Provider provider = getConfiguredProvider();
+ mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ mockProviderApiConnector(ERROR_GEOIP_SERVICE_IS_DOWN);
+ providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+
+ Bundle expectedResult = mockBundle();
+ expectedResult.putBoolean(EIP_ACTION_START, true);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
+
+ Intent providerApiCommand = mockIntent();
+
+ providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON);
+ Bundle extrasBundle = mockBundle();
+ extrasBundle.putBoolean(EIP_ACTION_START, true);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
+ providerApiCommand.putExtra(PARAMETERS, extrasBundle);
+
+ providerApiManager.handleIntent(providerApiCommand);
+
+ }
+
+ @Test
+ public void test_handleIntentGetGeoip_didNotReachTimeoutToFetchNew_returnsFailure() throws IOException, NoSuchAlgorithmException, CertificateEncodingException, JSONException {
+ if ("insecure".equals(BuildConfig.FLAVOR_implementation)) {
+ return;
+ }
+
+ Provider provider = getConfiguredProvider();
+ provider.setLastGeoIpUpdate(System.currentTimeMillis());
+ mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ mockProviderApiConnector(NO_ERROR);
+ providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+
+ Bundle expectedResult = mockBundle();
+ expectedResult.putBoolean(EIP_ACTION_START, true);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
+
+ Intent providerApiCommand = mockIntent();
+
+ providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON);
+ Bundle extrasBundle = mockBundle();
+ extrasBundle.putBoolean(EIP_ACTION_START, true);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
+ providerApiCommand.putExtra(PARAMETERS, extrasBundle);
+
+ providerApiManager.handleIntent(providerApiCommand);
+ }
+
+ @Test
+ public void test_handleIntentGetGeoip_noGeoipServiceURLDefined_returnsFailure() throws IOException, NoSuchAlgorithmException, CertificateEncodingException, JSONException {
+ if ("insecure".equals(BuildConfig.FLAVOR_implementation)) {
+ return;
+ }
+
+ Provider provider = getConfiguredProvider();
+ provider.setGeoipUrl(null);
+ provider.setGeoIpJson(new JSONObject());
+ mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ mockProviderApiConnector(NO_ERROR);
+ providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+
+ Bundle expectedResult = mockBundle();
+ expectedResult.putBoolean(EIP_ACTION_START, true);
+ expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
+ expectedResult.putParcelable(PROVIDER_KEY, provider);
+
+ Intent providerApiCommand = mockIntent();
+
+ providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON);
+ Bundle extrasBundle = mockBundle();
+ extrasBundle.putBoolean(EIP_ACTION_START, true);
+ providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult));
+ providerApiCommand.putExtra(PROVIDER_KEY, provider);
+ providerApiCommand.putExtra(PARAMETERS, extrasBundle);
+
+ providerApiManager.handleIntent(providerApiCommand);
+ }
+
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java
index a10b1414..3e8dfd5f 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java
@@ -32,6 +32,7 @@ public class BackendMockProvider {
ERROR_CASE_UPDATED_CERTIFICATE,
ERROR_CASE_MICONFIGURED_PROVIDER,
ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID,
+ ERROR_GEOIP_SERVICE_IS_DOWN,
ERROR_NO_RESPONSE_BODY, // => NullPointerException
ERROR_DNS_RESOLUTION_ERROR, // => UnkownHostException
ERROR_SOCKET_TIMEOUT, // => SocketTimeoutException
@@ -62,6 +63,10 @@ public class BackendMockProvider {
break;
case ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID:
new EipSerivceJsonInvalidCertificateBackendResponse();
+ break;
+ case ERROR_GEOIP_SERVICE_IS_DOWN:
+ new GeoIpServiceIsDownBackendResponse();
+ break;
case ERROR_NO_RESPONSE_BODY:
break;
case ERROR_DNS_RESOLUTION_ERROR:
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java
index b84c5508..7c2d49cc 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java
@@ -52,6 +52,9 @@ public class EipSerivceJsonInvalidCertificateBackendResponse extends BaseBackend
} else if (url.contains("config/eip-service.json")) {
// download provider service json containing gateways, locations and openvpn settings
throw new SSLHandshakeException("Invalid provider CA certificate");
+ } else if (url.contains(":9001/json")) {
+ // download geoip json, containing a sorted list of gateways
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
} else if (url.contains("/users.json")) {
//create new user
//TODO: implement me
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java
new file mode 100644
index 00000000..3a08d8da
--- /dev/null
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2018 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.testutils.BackendMockResponses;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.IOException;
+import java.net.ConnectException;
+
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+
+/**
+ * Created by cyberta on 10.01.18.
+ */
+
+public class GeoIpServiceIsDownBackendResponse extends BaseBackendResponse {
+ public GeoIpServiceIsDownBackendResponse() throws IOException {
+ super();
+ }
+
+ @Override
+ public Answer<String> getAnswerForRequestStringFromServer() {
+ return new Answer<String>() {
+ @Override
+ public String answer(InvocationOnMock invocation) throws Throwable {
+ String url = (String) invocation.getArguments()[0];
+ String requestMethod = (String) invocation.getArguments()[1];
+ String jsonPayload = (String) invocation.getArguments()[2];
+
+ if (url.contains("/provider.json")) {
+ //download provider json
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"));
+ } else if (url.contains("/ca.crt")) {
+ //download provider ca cert
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
+ } else if (url.contains("config/eip-service.json")) {
+ // download provider service json containing gateways, locations and openvpn settings
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
+ } else if (url.contains(":9001/json")) {
+ // download geoip json, containing a sorted list of gateways
+ throw new ConnectException("Failed to connect to api.black.riseup.net/198.252.153.107:9001");
+ } else if (url.contains("/users.json")) {
+ //create new user
+ //TODO: implement me
+ } else if (url.contains("/sessions.json")) {
+ //srp auth: sendAToSRPServer
+ //TODO: implement me
+ } else if (url.contains("/sessions/parmegvtest10.json")){
+ //srp auth: sendM1ToSRPServer
+ //TODO: implement me
+ }
+
+ return null;
+ }
+ };
+ }
+
+ @Override
+ public Answer<Boolean> getAnswerForCanConnect() {
+ return new Answer<Boolean>() {
+ @Override
+ public Boolean answer(InvocationOnMock invocation) throws Throwable {
+ return true;
+ }
+ };
+ }
+
+ @Override
+ public Answer<Boolean> getAnswerForDelete() {
+ return new Answer<Boolean>() {
+ @Override
+ public Boolean answer(InvocationOnMock invocation) throws Throwable {
+ return true;
+ }
+ };
+ }
+
+}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java
index 4600e879..10e69bc3 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java
@@ -50,6 +50,9 @@ public class MisconfiguredProviderBackendResponse extends BaseBackendResponse {
} else if (url.contains("config/eip-service.json")) {
// download provider service json containing gateways, locations and openvpn settings
return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
+ } else if (url.contains(":9001/json")) {
+ // download geoip json, containing a sorted list of gateways
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
} else if (url.contains("/users.json")) {
//create new user
//TODO: implement me
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java
index fa318e42..3c3a8ffa 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java
@@ -50,6 +50,9 @@ public class NoErrorBackendResponse extends BaseBackendResponse {
} else if (url.contains("config/eip-service.json")) {
// download provider service json containing gateways, locations and openvpn settings
return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
+ } else if (url.contains(":9001/json")) {
+ // download geoip json, containing a sorted list of gateways
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
} else if (url.contains("/users.json")) {
//create new user
//TODO: implement me
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 1c205c83..d3d07308 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
@@ -401,6 +401,8 @@ public class MockHelper {
return providerFromPrefs.getCaCertFingerprint();
case Provider.CA_CERT:
return providerFromPrefs.getCaCert();
+ case Provider.GEOIP_URL:
+ return providerFromPrefs.getGeoipUrl().toString();
}
return null;
diff --git a/app/src/test/resources/ptdemo_three_mixed_gateways.geoip.json b/app/src/test/resources/ptdemo_three_mixed_gateways.geoip.json
new file mode 100644
index 00000000..a72a85f5
--- /dev/null
+++ b/app/src/test/resources/ptdemo_three_mixed_gateways.geoip.json
@@ -0,0 +1,12 @@
+{
+ "ip":"51.158.144.32",
+ "cc":"FR",
+ "city":"Paris",
+ "lat":48.8628,
+ "lon":2.3292,
+ "gateways":[
+ "manila.bitmask.net",
+ "moscow.bitmask.net",
+ "pt.demo.bitmask.net"
+ ]
+} \ No newline at end of file
diff --git a/app/src/test/resources/riseup.geoip.json b/app/src/test/resources/riseup.geoip.json
new file mode 100644
index 00000000..b646052e
--- /dev/null
+++ b/app/src/test/resources/riseup.geoip.json
@@ -0,0 +1,20 @@
+{
+ "ip":"51.158.144.32",
+ "cc":"FR",
+ "city":"Paris",
+ "lat":48.8628,
+ "lon":2.3292,
+ "gateways":[
+ "mouette.riseup.net",
+ "hoatzin.riseup.net",
+ "zarapito.riseup.net",
+ "redshank.riseup.net",
+ "shag.riseup.net",
+ "yal.riseup.net",
+ "gaei.riseup.net",
+ "cisne.riseup.net",
+ "swan.riseup.net",
+ "garza.riseup.net",
+ "gaviota.riseup.net"
+ ]
+} \ No newline at end of file