From 015d8f9f512b5020d380aadf4af70a89a4b3dc42 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 1 Jul 2020 00:15:52 +0200 Subject: inject preshipped geoip url to provider object --- .../main/java/se/leap/bitmaskclient/Provider.java | 42 +++++++++++++++------- .../java/se/leap/bitmaskclient/ProviderAPI.java | 1 + .../bitmaskclient/ProviderListBaseActivity.java | 2 +- .../se/leap/bitmaskclient/ProviderManager.java | 5 ++- app/src/normal/assets/urls/riseup.net.url | 3 +- .../testutils/TestSetupHelper.java | 7 ++-- .../java/se/leap/bitmaskclient/ProviderTest.java | 2 ++ .../bitmaskclient/eip/GatewaysManagerTest.java | 14 ++++---- .../bitmaskclient/eip/ProviderApiManagerTest.java | 4 +-- app/src/test/resources/riseup_geoip.json | 20 +++++++++++ 10 files changed, 74 insertions(+), 26 deletions(-) create mode 100644 app/src/test/resources/riseup_geoip.json (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index 4dd7c76e..8db3cc97 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -50,6 +50,7 @@ public final class Provider implements Parcelable { private JSONObject eipServiceJson = 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 = ""; @@ -78,21 +79,35 @@ 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(); } + try { + this.geoipUrl.setUrl(new URL(geoipUrl)); + } catch (MalformedURLException e) { + this.geoipUrl = new DefaultedURL(); + } } 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 +118,18 @@ public final class Provider implements Parcelable { } } catch (MalformedURLException e) { e.printStackTrace(); + return; } - } - - public Provider(String mainUrl, String providerIp, String providerApiIp, String caCert, String definition) { try { - this.mainUrl.setUrl(new URL(mainUrl)); + this.geoipUrl.setUrl(new URL(geoipUrl)); } catch (MalformedURLException e) { - e.printStackTrace(); - } - if (this.providerIp != null) { - this.providerIp = providerIp; - } - if (this.providerApiIp != null) { - this.providerApiIp = providerApiIp; + this.geoipUrl = new DefaultedURL(); } + } + + + 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; } @@ -241,6 +253,10 @@ public final class Provider implements Parcelable { return apiUrl; } + protected DefaultedURL getGeoipUrl() { + return geoipUrl; + } + protected String getApiUrlWithVersion() { return getApiUrlString() + "/" + getApiVersion(); } @@ -321,6 +337,7 @@ 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()); @@ -340,6 +357,7 @@ public final class Provider implements Parcelable { 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()) && diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java index 9d34b38f..df67f282 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java @@ -53,6 +53,7 @@ public class ProviderAPI extends JobIntentService implements ProviderApiManagerB LOG_OUT = "logOut", DOWNLOAD_VPN_CERTIFICATE = "downloadUserAuthedVPNCertificate", UPDATE_INVALID_VPN_CERTIFICATE = "ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE", + GEOSERVICE = "geoService", PARAMETERS = "parameters", RECEIVER_KEY = "receiver", ERRORS = "errors", 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 { 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/normal/assets/urls/riseup.net.url b/app/src/normal/assets/urls/riseup.net.url index a4a90f90..cfea527c 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" } 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..69fffcb4 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); } - 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) { if (domain == null) domain = "https://riseup.net"; + if (geoipUrl == null) + geoipUrl = "https://api.black.riseup.net:9001/json"; if (providerIp == null) { providerIp = ""; } @@ -74,6 +76,7 @@ public class TestSetupHelper { try { Provider p = new Provider( domain, + geoipUrl, providerIp, providerApiIp, getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(caCertFile)), diff --git a/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java index 0f9d358e..5e55add0 100644 --- a/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java @@ -55,6 +55,7 @@ public class ProviderTest { null, null, null, + null, "ptdemo.bitmask.eip-service.json"); assertTrue(p1.supportsPluggableTransports()); } @@ -67,6 +68,7 @@ public class ProviderTest { null, null, null, + null, "eip-service-two-gateways.json"); 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..be3d2e12 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java @@ -107,7 +107,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"); MockHelper.mockProviderObserver(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals(0, gatewaysManager.size()); @@ -115,7 +115,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"); MockHelper.mockProviderObserver(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals(3, gatewaysManager.size()); @@ -123,7 +123,7 @@ 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"); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0); MockHelper.mockProviderObserver(provider); @@ -140,7 +140,7 @@ 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"); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0); MockHelper.mockProviderObserver(provider); @@ -157,7 +157,7 @@ public class GatewaysManagerTest { @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"); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0); MockHelper.mockProviderObserver(provider); @@ -174,7 +174,7 @@ 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"); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(1); MockHelper.mockProviderObserver(provider); @@ -191,7 +191,7 @@ 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"); + Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_two_openvpn_one_pt_gateways.json"); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway3 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(2); 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..7a96310c 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java @@ -269,7 +269,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); mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); @@ -386,7 +386,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); mockFingerprintForCertificate(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); mockProviderApiConnector(NO_ERROR); 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 -- cgit v1.2.3 From 49b18fcdc45433d34eefb46ab236144e19022dcb Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 23 Jul 2020 16:56:41 +0200 Subject: implement gateway selection based on geoip service --- .../se/leap/bitmaskclient/ProviderApiManager.java | 56 ++++++- .../main/java/se/leap/bitmaskclient/Constants.java | 1 + .../java/se/leap/bitmaskclient/EipFragment.java | 29 ++-- .../se/leap/bitmaskclient/EipSetupObserver.java | 23 ++- .../main/java/se/leap/bitmaskclient/Provider.java | 164 ++++++++++++++------- .../java/se/leap/bitmaskclient/ProviderAPI.java | 10 +- .../se/leap/bitmaskclient/ProviderAPICommand.java | 10 +- .../leap/bitmaskclient/ProviderApiManagerBase.java | 44 +++++- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 13 +- .../java/se/leap/bitmaskclient/eip/Gateway.java | 5 + .../se/leap/bitmaskclient/eip/GatewaysManager.java | 125 +++++++++------- .../leap/bitmaskclient/utils/PreferenceHelper.java | 4 + app/src/normal/assets/urls/riseup.net.url | 2 +- .../se/leap/bitmaskclient/ProviderApiManager.java | 73 +++++++-- app/src/test/resources/riseup.geoip.json | 20 +++ app/src/test/resources/riseup_geoip.json | 20 --- 16 files changed, 414 insertions(+), 185 deletions(-) create mode 100644 app/src/test/resources/riseup.geoip.json delete mode 100644 app/src/test/resources/riseup_geoip.json (limited to 'app/src') diff --git a/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java index b67f6fa5..ba226957 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()) { + 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> 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 8db3cc97..9d1b0095 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,8 +45,10 @@ 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(); @@ -60,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; @@ -96,11 +98,7 @@ public final class Provider implements Parcelable { } catch (MalformedURLException e) { this.mainUrl = new DefaultedURL(); } - try { - this.geoipUrl.setUrl(new URL(geoipUrl)); - } catch (MalformedURLException e) { - this.geoipUrl = new DefaultedURL(); - } + setGeoipUrl(geoipUrl); } public Provider(String mainUrl, String providerIp, String providerApiIp) { @@ -120,11 +118,7 @@ public final class Provider implements Parcelable { e.printStackTrace(); return; } - try { - this.geoipUrl.setUrl(new URL(geoipUrl)); - } catch (MalformedURLException e) { - this.geoipUrl = new DefaultedURL(); - } + setGeoipUrl(geoipUrl); } @@ -252,11 +246,19 @@ public final class Provider implements Parcelable { protected DefaultedURL getApiUrl() { return apiUrl; } - - protected DefaultedURL getGeoipUrl() { + + 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(); } @@ -278,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; @@ -341,19 +347,71 @@ public final class Provider implements Parcelable { parcel.writeString(getDefinitionString()); parcel.writeString(getCaCert()); parcel.writeString(getEipServiceJsonString()); + parcel.writeString(getGeoIpJsonString()); parcel.writeString(getPrivateKey()); parcel.writeString(getVpnCertificate()); parcel.writeLong(lastEipServiceUpdate); + parcel.writeLong(lastGeoIpUpdate); + } + + + //TODO: write a test for marshalling! + private Provider(Parcel in) { + try { + mainUrl.setUrl(new URL(in.readString())); + String tmpString = in.readString(); + if (!tmpString.isEmpty()) { + providerIp = tmpString; + } + tmpString = in.readString(); + if (!tmpString.isEmpty()) { + providerApiIp = tmpString; + } + tmpString = in.readString(); + if (!tmpString.isEmpty()) { + geoipUrl.setUrl(new URL(tmpString)); + } + tmpString = in.readString(); + if (!tmpString.isEmpty()) { + definition = new JSONObject((tmpString)); + parseDefinition(definition); + } + tmpString = in.readString(); + if (!tmpString.isEmpty()) { + this.caCert = tmpString; + } + tmpString = in.readString(); + if (!tmpString.isEmpty()) { + this.setEipServiceJson(new JSONObject(tmpString)); + } + tmpString = in.readString(); + if (!tmpString.isEmpty()) { + this.setGeoIpJson(new JSONObject(tmpString)); + } + tmpString = in.readString(); + if (!tmpString.isEmpty()) { + this.setPrivateKey(tmpString); + } + tmpString = in.readString(); + if (!tmpString.isEmpty()) { + 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.getEipServiceJson().toString())&& - mainUrl.equals(p.getMainUrl()) && + eipServiceJson.toString().equals(p.getEipServiceJsonString()) && + geoIpJson.toString().equals(p.getGeoIpJsonString()) && providerIp.equals(p.getProviderIp()) && providerApiIp.equals(p.getProviderApiIp()) && apiUrl.equals(p.getApiUrl()) && @@ -366,10 +424,12 @@ public final class Provider implements Parcelable { vpnCertificate.equals(p.getVpnCertificate()) && allowAnonymous == p.allowsAnonymous() && allowRegistered == p.allowsRegistered() && - lastEipServiceUpdate == p.getLastEipServiceUpdate(); + lastEipServiceUpdate == p.getLastEipServiceUpdate() && + lastGeoIpUpdate == p.getLastGeoIpUpdate(); } else return false; } + public JSONObject toJson() { JSONObject json = new JSONObject(); try { @@ -390,45 +450,6 @@ public final class Provider implements Parcelable { return new Gson().toJson(this); } - //TODO: write a test for marshalling! - private Provider(Parcel in) { - try { - mainUrl.setUrl(new URL(in.readString())); - String tmpString = in.readString(); - if (!tmpString.isEmpty()) { - providerIp = tmpString; - } - tmpString = in.readString(); - if (!tmpString.isEmpty()) { - providerApiIp = tmpString; - } - tmpString = in.readString(); - if (!tmpString.isEmpty()) { - definition = new JSONObject((tmpString)); - parseDefinition(definition); - } - tmpString = in.readString(); - if (!tmpString.isEmpty()) { - this.caCert = tmpString; - } - tmpString = in.readString(); - if (!tmpString.isEmpty()) { - this.setEipServiceJson(new JSONObject(tmpString)); - } - tmpString = in.readString(); - if (!tmpString.isEmpty()) { - this.setPrivateKey(tmpString); - } - tmpString = in.readString(); - if (!tmpString.isEmpty()) { - this.setVpnCertificate(tmpString); - } - this.lastEipServiceUpdate = in.readLong(); - } catch (MalformedURLException | JSONException e) { - e.printStackTrace(); - } - } - private boolean parseDefinition(JSONObject definition) { try { String pin = definition.getString(CA_CERT_FINGERPRINT); @@ -468,6 +489,20 @@ public final class Provider implements Parcelable { return System.currentTimeMillis() - lastEipServiceUpdate >= EIP_SERVICE_TIMEOUT; } + + public void setLastGeoIpUpdate(long timestamp) { + lastGeoIpUpdate = timestamp; + } + + public long getLastGeoIpUpdate() { + return lastGeoIpUpdate; + } + + public boolean shouldUpdateGeoIpJson() { + return System.currentTimeMillis() - lastGeoIpUpdate >= GEOIP_SERVICE_TIMEOUT; + } + + public boolean setEipServiceJson(JSONObject eipServiceJson) { if (eipServiceJson.has(ERRORS)) { return false; @@ -476,16 +511,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(); @@ -533,6 +586,7 @@ public final class Provider implements Parcelable { public void reset() { definition = new JSONObject(); eipServiceJson = new JSONObject(); + geoIpJson = new JSONObject(); apiUrl = new DefaultedURL(); certificatePin = ""; certificatePinEncoding = ""; diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java index df67f282..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,12 +49,12 @@ 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", DOWNLOAD_VPN_CERTIFICATE = "downloadUserAuthedVPNCertificate", UPDATE_INVALID_VPN_CERTIFICATE = "ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE", - GEOSERVICE = "geoService", PARAMETERS = "parameters", RECEIVER_KEY = "receiver", ERRORS = "errors", @@ -78,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; @@ -100,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/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)) { @@ -309,15 +309,6 @@ public final class EIP extends JobIntentService implements Observer { tellToReceiverOrBroadcast(this, EIP_ACTION_IS_RUNNING, resultCode); } - /** - * 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..589fa751 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); 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..e3932cb6 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 gateways = new LinkedHashMap<>(); private Type listType = new TypeToken>() {}.getType(); - - public GatewaysManager(Context context, SharedPreferences preferences) { - this.preferences = preferences; - this.context = context; - configureFromPreferences(); - } + private ArrayList presortedList = new ArrayList<>(); public GatewaysManager(Context context) { configureFromCurrentProvider(); @@ -75,7 +68,18 @@ 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 getGatewayFromPreorderedList(nClosest, transportType); + } + + return getGatewayFromTimezoneCalculation(nClosest, transportType); + } + + + private Gateway getGatewayFromTimezoneCalculation(int nClosest, Connection.TransportType transportType) { + List list = new ArrayList<>(gateways.values()); + GatewaySelector gatewaySelector = new GatewaySelector(list); Gateway gateway; while ((gateway = gatewaySelector.select(nClosest)) != null) { if (gateway.getProfile(transportType) != null) { @@ -86,6 +90,17 @@ public class GatewaysManager { return null; } + private Gateway getGatewayFromPreorderedList(int nClosest, Connection.TransportType transportType) { + while (nClosest < presortedList.size()) { + Gateway gateway = presortedList.get(nClosest); + if (gateway.getProfile(transportType) != null) { + return gateway; + } + nClosest++; + } + return null; + } + /** * Get position of the gateway from a sorted set (along the distance of the gw to your time zone) * @param profile profile belonging to a gateway @@ -126,43 +141,59 @@ 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(); + 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 void parseGatewaysFromGeoIpServiceJson(Provider provider) { + JSONObject geoIpJson = provider.getGeoIpJson(); + JSONArray gatewaylist = new JSONArray(); try { - gatewaysDefined = eipDefinition.getJSONArray(GATEWAYS); + gatewaylist = geoIpJson.getJSONArray(GATEWAYS); } catch (Exception e) { e.printStackTrace(); } - for (int i = 0; i < gatewaysDefined.length(); i++) { + for (int i = 0; i < gatewaylist.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); + String key = gatewaylist.getString(i); + if (gateways.containsKey(key)) { + presortedList.add(gateways.get(key)); } - } catch (JSONException | ConfigParser.ConfigParseError | IOException e) { + } catch (JSONException e) { e.printStackTrace(); - VpnStatus.logError("Unable to parse gateway config!"); } } } - 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 JSONObject secretsConfigurationFromCurrentProvider() { JSONObject result = new JSONObject(); Provider provider = ProviderObservable.getInstance().getCurrentProvider(); @@ -177,31 +208,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..87bd5f93 100644 --- a/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java @@ -47,6 +47,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 +69,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 +84,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 +117,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 cfea527c..3c1e6b49 100644 --- a/app/src/normal/assets/urls/riseup.net.url +++ b/app/src/normal/assets/urls/riseup.net.url @@ -2,5 +2,5 @@ "main_url" : "https://riseup.net", "provider_ip" : "198.252.153.70", "provider_api_ip" : "198.252.153.107", - "geoip_url" : "https://api.black.riseup.net:9001" + "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..e5d5bd0e 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()) { + 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> 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/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 diff --git a/app/src/test/resources/riseup_geoip.json b/app/src/test/resources/riseup_geoip.json deleted file mode 100644 index b646052e..00000000 --- a/app/src/test/resources/riseup_geoip.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "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 -- cgit v1.2.3 From 7b5ad7e802aae82b69ed8ecd916916e6545f01f2 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 23 Jul 2020 17:03:15 +0200 Subject: always use provider from ProviderObservable if possible --- app/src/main/java/se/leap/bitmaskclient/StartActivity.java | 9 ++++----- .../main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java | 3 --- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'app/src') 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/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java index 87bd5f93..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(); -- cgit v1.2.3 From 0d2c7adabfe0b6863163051c53dc8c9c6852ec40 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 23 Jul 2020 17:08:21 +0200 Subject: clean up PreferenceHelperTest after removal of providerInSharedPreferences method --- .../java/se/leap/bitmaskclient/PreferenceHelperTest.java | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'app/src') 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. @@ -32,17 +28,6 @@ public class PreferenceHelperTest { mockPreferences = new MockSharedPreferences(); } - @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); -- cgit v1.2.3 From b92177a2d26f0f96671c848d26c79b08dca13f71 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 23 Jul 2020 17:25:20 +0200 Subject: fix potential nullpointer exception in geoipservice json parsing --- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 33 +++++++++++----------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'app/src') 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 e3932cb6..70d757d4 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -174,24 +174,23 @@ public class GatewaysManager { } private void parseGatewaysFromGeoIpServiceJson(Provider provider) { - JSONObject geoIpJson = provider.getGeoIpJson(); - JSONArray gatewaylist = new JSONArray(); - try { - gatewaylist = geoIpJson.getJSONArray(GATEWAYS); - } catch (Exception e) { - e.printStackTrace(); - } + 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(); - } - } + 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() { -- cgit v1.2.3 From 4e861a972a28bd7eb268fb03c80b989a8b36c2a0 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 23 Jul 2020 17:41:26 +0200 Subject: adapt existing tests for geoipservice api --- .../testutils/TestSetupHelper.java | 11 +++++-- .../java/se/leap/bitmaskclient/ProviderTest.java | 16 ++++++++-- .../bitmaskclient/eip/GatewaysManagerTest.java | 37 ++++------------------ .../bitmaskclient/eip/ProviderApiManagerTest.java | 28 +++++++++++++--- ...rivceJsonInvalidCertificateBackendResponse.java | 3 ++ .../MisconfiguredProviderBackendResponse.java | 3 ++ .../NoErrorBackendResponse.java | 3 ++ .../leap/bitmaskclient/testutils/MockHelper.java | 2 ++ 8 files changed, 64 insertions(+), 39 deletions(-) (limited to 'app/src') 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 69fffcb4..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,10 +51,10 @@ public class TestSetupHelper { public static Provider getConfiguredProvider() throws IOException, JSONException { - return getProvider(null, null, null, null, null, null, null); + return getProvider(null, null, null, null, null, null, null, null); } - public static Provider getProvider(String domain, String geoipUrl, 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) @@ -72,6 +72,9 @@ public class TestSetupHelper { if (eipServiceJson == null) { eipServiceJson = "riseup.service.json"; } + if (geoIpJson == null) { + geoIpJson = "riseup.geoip.json"; + } try { Provider p = new Provider( @@ -86,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/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java index 5e55add0..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 { @@ -56,7 +64,8 @@ public class ProviderTest { null, null, null, - "ptdemo.bitmask.eip-service.json"); + "ptdemo.bitmask.eip-service.json", + null); assertTrue(p1.supportsPluggableTransports()); } @@ -69,7 +78,8 @@ public class ProviderTest { null, null, null, - "eip-service-two-gateways.json"); + "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 be3d2e12..da9e04e4 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, 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, 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,7 +100,7 @@ public class GatewaysManagerTest { @Test public void TestGetPosition_VpnProfileExtistingObfs4_returnPositionZero() throws JSONException, ConfigParser.ConfigParseError, IOException { - Provider provider = getProvider(null, 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); @@ -140,7 +117,7 @@ public class GatewaysManagerTest { @Test public void TestGetPosition_VpnProfileExtistingOpenvpn_returnPositionZero() throws JSONException, ConfigParser.ConfigParseError, IOException { - Provider provider = getProvider(null, 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); @@ -157,7 +134,7 @@ public class GatewaysManagerTest { @Test public void TestGetPosition_VpnProfileDifferentIp_returnMinusOne() throws JSONException, ConfigParser.ConfigParseError, IOException { - Provider provider = getProvider(null, 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); @@ -174,7 +151,7 @@ public class GatewaysManagerTest { @Test public void TestGetPosition_VpnProfileMoscow_returnOne() throws JSONException, ConfigParser.ConfigParseError, IOException { - Provider provider = getProvider(null, 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); @@ -191,7 +168,7 @@ public class GatewaysManagerTest { @Test public void TestSelectN_selectFirstObfs4Connection_returnThirdGateway() throws JSONException, ConfigParser.ConfigParseError, IOException { - Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_two_openvpn_one_pt_gateways.json"); + Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_two_openvpn_one_pt_gateways.json", null); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway3 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(2); 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 7a96310c..722cc3f2 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java @@ -155,7 +155,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 +269,7 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_preseededProviderAndCA_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { - Provider provider = getProvider(null ,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 +290,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 +386,7 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_outdatedPreseededProviderAndCA_successfulConfiguration() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { - Provider provider = getProvider(null, 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 +431,24 @@ 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 provider = getConfiguredProvider(); + mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + mockProviderApiConnector(NO_ERROR); + providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); + + Bundle expectedResult = mockBundle(); + expectedResult.putBoolean(BROADCAST_RESULT_KEY, true); + expectedResult.putParcelable(PROVIDER_KEY, provider); + + + + } } 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/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; -- cgit v1.2.3 From 20c02163b83912d7dc2f85499c118799c95f9e25 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 23 Jul 2020 18:27:08 +0200 Subject: finish happy path unit test for geoipservice api --- .../se/leap/bitmaskclient/eip/ProviderApiManagerTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'app/src') 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 722cc3f2..c764edf1 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java @@ -49,8 +49,11 @@ 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.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; @@ -445,10 +448,20 @@ public class ProviderApiManagerTest { 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, 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(CORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult)); + providerApiCommand.putExtra(PROVIDER_KEY, provider); + providerApiCommand.putExtra(PARAMETERS, extrasBundle); + providerApiManager.handleIntent(providerApiCommand); } } -- cgit v1.2.3 From ab6a95483e2c5f726d15216cbb32af0281334485 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 24 Jul 2020 13:41:05 +0200 Subject: remove timestamps from providers equals() check and reset timestamps in reset method --- app/src/main/java/se/leap/bitmaskclient/Provider.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index 9d1b0095..3aa66cc2 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -423,9 +423,7 @@ public final class Provider implements Parcelable { privateKey.equals(p.getPrivateKey()) && vpnCertificate.equals(p.getVpnCertificate()) && allowAnonymous == p.allowsAnonymous() && - allowRegistered == p.allowsRegistered() && - lastEipServiceUpdate == p.getLastEipServiceUpdate() && - lastGeoIpUpdate == p.getLastGeoIpUpdate(); + allowRegistered == p.allowsRegistered(); } else return false; } @@ -596,5 +594,7 @@ public final class Provider implements Parcelable { vpnCertificate = ""; allowRegistered = false; allowAnonymous = false; + lastGeoIpUpdate = 0L; + lastEipServiceUpdate = 0L; } } -- cgit v1.2.3 From acdd39af9962863b6d210b005e6aab340460bdaf Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 24 Jul 2020 13:42:57 +0200 Subject: add test for case if geoip service is not available/down --- .../bitmaskclient/eip/ProviderApiManagerTest.java | 42 +++++++++- .../BackendMockResponses/BackendMockProvider.java | 5 ++ .../GeoIpServiceIsDownBackendResponse.java | 93 ++++++++++++++++++++++ 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java (limited to 'app/src') 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 c764edf1..469ccfc9 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,6 +45,7 @@ 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; @@ -53,12 +55,14 @@ 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; @@ -442,7 +446,9 @@ public class ProviderApiManagerTest { return; } - Provider provider = getConfiguredProvider(); + Provider inputProvider = getConfiguredProvider(); + inputProvider.setGeoIpJson(new JSONObject()); + Provider expectedProvider = getConfiguredProvider(); mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); @@ -450,7 +456,7 @@ public class ProviderApiManagerTest { Bundle expectedResult = mockBundle(); expectedResult.putBoolean(EIP_ACTION_START, true); expectedResult.putBoolean(BROADCAST_RESULT_KEY, true); - expectedResult.putParcelable(PROVIDER_KEY, provider); + expectedResult.putParcelable(PROVIDER_KEY, expectedProvider); Intent providerApiCommand = mockIntent(); @@ -458,10 +464,42 @@ public class ProviderApiManagerTest { 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); } + + } 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/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 . + */ +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 getAnswerForRequestStringFromServer() { + return new Answer() { + @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 getAnswerForCanConnect() { + return new Answer() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + return true; + } + }; + } + + @Override + public Answer getAnswerForDelete() { + return new Answer() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + return true; + } + }; + } + +} -- cgit v1.2.3 From d8b9f60f961e55d0a9204149eb0e8604b9479f55 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 24 Jul 2020 13:51:33 +0200 Subject: add test that geoip service is only fetched when the timeout was reached --- .../bitmaskclient/eip/ProviderApiManagerTest.java | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'app/src') 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 469ccfc9..60a60580 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java @@ -501,5 +501,33 @@ public class ProviderApiManagerTest { } + @Test + public void test_handleIntentGetGeoip_noNeedToUpdate_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); + } } -- cgit v1.2.3 From 501a451b8b932e1f0e001599dbfe53810cb9ead0 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 24 Jul 2020 15:41:17 +0200 Subject: adapt profile selection after perordered gateway list was introduced and use profiles mUsePluggableTransports flag instead of shared preferences to get the requested transport --- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 28 +++++++++++++++++++--- .../bitmaskclient/eip/GatewaysManagerTest.java | 8 ------- 2 files changed, 25 insertions(+), 11 deletions(-) (limited to 'app/src') 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 70d757d4..aa10ffae 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -70,7 +70,7 @@ public class GatewaysManager { Connection.TransportType transportType = getUsePluggableTransports(context) ? OBFS4 : OPENVPN; if (presortedList.size() > 0) { - return getGatewayFromPreorderedList(nClosest, transportType); + return getGatewayFromPresortedList(nClosest, transportType); } return getGatewayFromTimezoneCalculation(nClosest, transportType); @@ -90,7 +90,7 @@ public class GatewaysManager { return null; } - private Gateway getGatewayFromPreorderedList(int nClosest, Connection.TransportType transportType) { + private Gateway getGatewayFromPresortedList(int nClosest, Connection.TransportType transportType) { while (nClosest < presortedList.size()) { Gateway gateway = presortedList.get(nClosest); if (gateway.getProfile(transportType) != null) { @@ -107,7 +107,29 @@ 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; + Gateway gateway; + int nClosest = 0; + while ((nClosest < presortedList.size())) { + gateway = presortedList.get(nClosest); + 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; 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 da9e04e4..dd5eb00c 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java @@ -104,8 +104,6 @@ public class GatewaysManagerTest { 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); @@ -121,8 +119,6 @@ public class GatewaysManagerTest { 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); @@ -138,8 +134,6 @@ public class GatewaysManagerTest { 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); @@ -155,8 +149,6 @@ public class GatewaysManagerTest { 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); -- cgit v1.2.3 From e986a294ec3e328bd48bb4c423fe835d1aa2dc69 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 24 Jul 2020 16:30:02 +0200 Subject: fix bug in gateway selection - always iterate through all gateways and count those supporting the requested transport in order to get the nClosest gateway; adding more tests --- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 21 +++++++++----- .../bitmaskclient/eip/GatewaysManagerTest.java | 33 ++++++++++++++++++++-- .../ptdemo_three_mixed_gateways.geoip.json | 12 ++++++++ 3 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 app/src/test/resources/ptdemo_three_mixed_gateways.geoip.json (limited to 'app/src') 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 aa10ffae..f3773758 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -81,22 +81,29 @@ public class GatewaysManager { List list = new ArrayList<>(gateways.values()); GatewaySelector gatewaySelector = new GatewaySelector(list); Gateway gateway; - while ((gateway = gatewaySelector.select(nClosest)) != null) { + int found = 0; + int i = 0; + while ((gateway = gatewaySelector.select(i)) != null) { if (gateway.getProfile(transportType) != null) { - return gateway; + if (found == nClosest) { + return gateway; + } + found++; } - nClosest++; + i++; } return null; } private Gateway getGatewayFromPresortedList(int nClosest, Connection.TransportType transportType) { - while (nClosest < presortedList.size()) { - Gateway gateway = presortedList.get(nClosest); + int found = 0; + for (Gateway gateway : presortedList) { if (gateway.getProfile(transportType) != null) { - return gateway; + if (found == nClosest) { + return gateway; + } + found++; } - nClosest++; } return null; } 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 dd5eb00c..5c5ebbfe 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java @@ -161,8 +161,6 @@ public class GatewaysManagerTest { @Test public void TestSelectN_selectFirstObfs4Connection_returnThirdGateway() throws JSONException, ConfigParser.ConfigParseError, IOException { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_two_openvpn_one_pt_gateways.json", null); - JSONObject eipServiceJson = provider.getEipServiceJson(); - JSONObject gateway3 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(2); MockHelper.mockProviderObserver(provider); mockStatic(PreferenceHelper.class); @@ -172,6 +170,37 @@ public class GatewaysManagerTest { assertEquals("37.12.247.10", gatewaysManager.select(0).getRemoteIP()); } + @Test + public void testSelectN_selectFromPresortedGateways_returnsGatewaysInPresortedOrder() throws JSONException { + 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() throws JSONException { + 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/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 -- cgit v1.2.3 From d1ddaa7b10fde24b0b5f07369d1a22c221b81287 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 24 Jul 2020 17:40:15 +0200 Subject: fix bug in vpn profile based gateway order detection, write additional tests for it --- .../java/se/leap/bitmaskclient/eip/Gateway.java | 4 +++ .../se/leap/bitmaskclient/eip/GatewaysManager.java | 28 +++++++++-------- .../bitmaskclient/eip/GatewaysManagerTest.java | 36 ++++++++++++++++++++-- 3 files changed, 53 insertions(+), 15 deletions(-) (limited to 'app/src') 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 589fa751..f3eea415 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -157,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 f3773758..0515a35e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -84,7 +84,7 @@ public class GatewaysManager { int found = 0; int i = 0; while ((gateway = gatewaySelector.select(i)) != null) { - if (gateway.getProfile(transportType) != null) { + if (gateway.suppoortsTransport(transportType)) { if (found == nClosest) { return gateway; } @@ -98,7 +98,7 @@ public class GatewaysManager { private Gateway getGatewayFromPresortedList(int nClosest, Connection.TransportType transportType) { int found = 0; for (Gateway gateway : presortedList) { - if (gateway.getProfile(transportType) != null) { + if (gateway.suppoortsTransport(transportType)) { if (found == nClosest) { return gateway; } @@ -123,14 +123,14 @@ public class GatewaysManager { private int getPositionFromPresortedList(VpnProfile profile) { Connection.TransportType transportType = profile.mUsePluggableTransports ? OBFS4 : OPENVPN; - Gateway gateway; int nClosest = 0; - while ((nClosest < presortedList.size())) { - gateway = presortedList.get(nClosest); - if (profile.equals(gateway.getProfile(transportType))) { - return nClosest; + for (Gateway gateway : presortedList) { + if (gateway.suppoortsTransport(transportType)) { + if (profile.equals(gateway.getProfile(transportType))) { + return nClosest; + } + nClosest++; } - nClosest++; } return -1; } @@ -140,11 +140,15 @@ public class GatewaysManager { 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; } 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 5c5ebbfe..bfe96d2c 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java @@ -128,6 +128,36 @@ public class GatewaysManagerTest { assertEquals(0, gatewaysManager.getPosition(profile)); } + @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, null, "ptdemo_three_mixed_gateways.json", null); @@ -159,7 +189,7 @@ public class GatewaysManagerTest { } @Test - public void TestSelectN_selectFirstObfs4Connection_returnThirdGateway() throws JSONException, ConfigParser.ConfigParseError, IOException { + 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); @@ -171,7 +201,7 @@ public class GatewaysManagerTest { } @Test - public void testSelectN_selectFromPresortedGateways_returnsGatewaysInPresortedOrder() throws JSONException { + 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); @@ -186,7 +216,7 @@ public class GatewaysManagerTest { } @Test - public void testSelectN_selectObfs4FromPresortedGateways_returnsObfs4GatewaysInPresortedOrder() throws JSONException { + 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); -- cgit v1.2.3 From fa0ff0970173908acc9ab2b37d4d4cc2d67c1597 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 24 Jul 2020 17:48:46 +0200 Subject: remove unused methods --- app/src/main/java/se/leap/bitmaskclient/Provider.java | 8 -------- 1 file changed, 8 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index 3aa66cc2..186ce11e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -479,10 +479,6 @@ public final class Provider implements Parcelable { lastEipServiceUpdate = timestamp; } - public long getLastEipServiceUpdate() { - return lastEipServiceUpdate; - } - public boolean shouldUpdateEipServiceJson() { return System.currentTimeMillis() - lastEipServiceUpdate >= EIP_SERVICE_TIMEOUT; } @@ -492,10 +488,6 @@ public final class Provider implements Parcelable { lastGeoIpUpdate = timestamp; } - public long getLastGeoIpUpdate() { - return lastGeoIpUpdate; - } - public boolean shouldUpdateGeoIpJson() { return System.currentTimeMillis() - lastGeoIpUpdate >= GEOIP_SERVICE_TIMEOUT; } -- cgit v1.2.3 From 38f5720502fda7b89ce204fe4afdffa67ac0ae82 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 24 Jul 2020 18:38:45 +0200 Subject: try to fetch geoip service only if non-default url exists --- .../se/leap/bitmaskclient/ProviderApiManager.java | 2 +- .../se/leap/bitmaskclient/ProviderApiManager.java | 2 +- .../bitmaskclient/eip/ProviderApiManagerTest.java | 32 +++++++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) (limited to 'app/src') diff --git a/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java index ba226957..a111e907 100644 --- a/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java +++ b/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java @@ -239,7 +239,7 @@ public class ProviderApiManager extends ProviderApiManagerBase { protected Bundle getGeoIPJson(Provider provider) { Bundle result = new Bundle(); - if (!provider.shouldUpdateGeoIpJson()) { + if (!provider.shouldUpdateGeoIpJson() || provider.getGeoipUrl().isDefault()) { result.putBoolean(BROADCAST_RESULT_KEY, false); return result; } diff --git a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java index e5d5bd0e..04ffe9e6 100644 --- a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java +++ b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java @@ -225,7 +225,7 @@ public class ProviderApiManager extends ProviderApiManagerBase { protected Bundle getGeoIPJson(Provider provider) { Bundle result = new Bundle(); - if (!provider.shouldUpdateGeoIpJson()) { + if (!provider.shouldUpdateGeoIpJson() || provider.getGeoipUrl().isDefault()) { result.putBoolean(BROADCAST_RESULT_KEY, false); return result; } 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 60a60580..efa6f78c 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java @@ -502,7 +502,7 @@ public class ProviderApiManagerTest { } @Test - public void test_handleIntentGetGeoip_noNeedToUpdate_returnsFailure() throws IOException, NoSuchAlgorithmException, CertificateEncodingException, JSONException { + public void test_handleIntentGetGeoip_didNotReachTimeoutToFetchNew_returnsFailure() throws IOException, NoSuchAlgorithmException, CertificateEncodingException, JSONException { if ("insecure".equals(BuildConfig.FLAVOR_implementation)) { return; } @@ -530,4 +530,34 @@ public class ProviderApiManagerTest { 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); + } + } -- cgit v1.2.3