diff options
author | cyberta <cyberta@riseup.net> | 2020-01-21 16:10:59 -0600 |
---|---|---|
committer | cyberta <cyberta@riseup.net> | 2020-01-21 16:10:59 -0600 |
commit | 6a015d337d6a786adb319c3f9de7b9b7e9ae80bb (patch) | |
tree | ae19d8d28d15d3b871d82e804994d810f79ad811 /app/src | |
parent | 14b84f691e369e2a4ef3fe8687688f5ba98fa719 (diff) |
implement no-dns fallback using okhttp's Dns interface
Diffstat (limited to 'app/src')
16 files changed, 270 insertions, 41 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/DnsResolver.java b/app/src/main/java/se/leap/bitmaskclient/DnsResolver.java new file mode 100644 index 00000000..55cf1123 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/DnsResolver.java @@ -0,0 +1,33 @@ +package se.leap.bitmaskclient; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; + +import okhttp3.Dns; + +class DnsResolver implements Dns { + + @Override + public List<InetAddress> lookup(String hostname) throws UnknownHostException { + try { + return Dns.SYSTEM.lookup(hostname); + } catch (UnknownHostException e) { + ProviderObservable observable = ProviderObservable.getInstance(); + Provider currentProvider; + if (observable.getProviderToSetup() != null) { + currentProvider = observable.getProviderToSetup(); + } else { + currentProvider = observable.getCurrentProvider(); + } + if (currentProvider != null && currentProvider.hasProviderIp()) { + ArrayList<InetAddress> addresses = new ArrayList<>(); + addresses.add(InetAddress.getByAddress(hostname, currentProvider.getProviderIpAsBytes())); + return addresses; + } else { + throw new UnknownHostException("Hostname " + hostname + " not found"); + } + } + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java b/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java index eceba0db..486c26bb 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java @@ -47,6 +47,7 @@ import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE; import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.ProviderAPI.ERRORS; +import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_NOK; import static se.leap.bitmaskclient.utils.PreferenceHelper.getSavedProviderFromSharedPreferences; /** @@ -155,6 +156,9 @@ class EipSetupObserver extends BroadcastReceiver implements VpnStatus.StateListe PreferenceHelper.storeProviderInPreferences(preferences, provider); EipCommand.startVPN(context.getApplicationContext(), true); break; + case PROVIDER_NOK: + ProviderObservable.getInstance().setProviderToSetup(null); + break; default: break; } diff --git a/app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java b/app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java index 69270140..9d1168aa 100644 --- a/app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java @@ -88,6 +88,7 @@ public class OkHttpClientGenerator { sslCompatFactory.initSSLSocketFactory(clientBuilder); clientBuilder.cookieJar(getCookieJar()) .connectionSpecs(Collections.singletonList(spec)); + clientBuilder.dns(new DnsResolver()); return clientBuilder.build(); } catch (IllegalArgumentException e) { e.printStackTrace(); diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index b98c3fd3..3dfee72c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -29,6 +29,8 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.Locale; +import se.leap.bitmaskclient.utils.IPAddress; + import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; import static se.leap.bitmaskclient.Constants.CAPABILITIES; import static se.leap.bitmaskclient.Constants.GATEWAYS; @@ -49,6 +51,7 @@ public final class Provider implements Parcelable { private JSONObject eipServiceJson = new JSONObject(); private DefaultedURL mainUrl = new DefaultedURL(); private DefaultedURL apiUrl = new DefaultedURL(); + private String providerIp = ""; private String certificatePin = ""; private String certificatePinEncoding = ""; private String caCert = ""; @@ -73,7 +76,8 @@ public final class Provider implements Parcelable { NAME = "name", DESCRIPTION = "description", DOMAIN = "domain", - MAIN_URL = "main_url"; + MAIN_URL = "main_url", + PROVIDER_IP = "provider_ip"; private static final String API_TERM_NAME = "name"; @@ -87,12 +91,16 @@ public final class Provider implements Parcelable { } } - public Provider(URL mainUrl) { + public Provider(URL mainUrl, String providerIp) { this.mainUrl.setUrl(mainUrl); + this.providerIp = providerIp; } - public Provider(URL mainUrl, String caCert, String definition) { + public Provider(URL mainUrl, String providerIp, String caCert, String definition) { this.mainUrl.setUrl(mainUrl); + if (this.providerIp != null) { + this.providerIp = providerIp; + } if (caCert != null) { this.caCert = caCert; } @@ -146,6 +154,18 @@ public final class Provider implements Parcelable { return false; } + public void setProviderIp(String providerIp) { + this.providerIp = providerIp; + } + + public String getProviderIp() { + return this.providerIp; + } + + public byte[] getProviderIpAsBytes() { + return IPAddress.asBytes(providerIp); + } + public void setMainUrl(URL url) { mainUrl.setUrl(url); } @@ -192,7 +212,7 @@ public final class Provider implements Parcelable { } - protected String getApiUrlString() { + public String getApiUrlString() { return getApiUrl().toString(); } @@ -265,6 +285,7 @@ public final class Provider implements Parcelable { @Override public void writeToParcel(Parcel parcel, int i) { parcel.writeString(getMainUrlString()); + parcel.writeString(getProviderIp()); parcel.writeString(getDefinitionString()); parcel.writeString(getCaCert()); parcel.writeString(getEipServiceJsonString()); @@ -281,6 +302,7 @@ public final class Provider implements Parcelable { definition.toString().equals(p.getDefinition().toString()) && eipServiceJson.toString().equals(p.getEipServiceJson().toString())&& mainUrl.equals(p.getMainUrl()) && + providerIp.equals(p.getProviderIp()) && apiUrl.equals(p.getApiUrl()) && certificatePin.equals(p.getCertificatePin()) && certificatePinEncoding.equals(p.getCertificatePinEncoding()) && @@ -298,7 +320,6 @@ public final class Provider implements Parcelable { JSONObject json = new JSONObject(); try { json.put(Provider.MAIN_URL, mainUrl); - //TODO: add other fields here? } catch (JSONException e) { e.printStackTrace(); } @@ -321,6 +342,10 @@ public final class Provider implements Parcelable { mainUrl.setUrl(new URL(in.readString())); String tmpString = in.readString(); if (!tmpString.isEmpty()) { + providerIp = tmpString; + } + tmpString = in.readString(); + if (!tmpString.isEmpty()) { definition = new JSONObject((tmpString)); parseDefinition(definition); } @@ -444,8 +469,12 @@ public final class Provider implements Parcelable { return getCertificatePinEncoding() + ":" + getCertificatePin(); } + public boolean hasProviderIp() { + return !providerIp.isEmpty(); + } + /** - * resets everything except the main url + * resets everything except the main url and the providerIp */ public void reset() { definition = new JSONObject(); diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java index c8070e18..bae237f6 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListBaseActivity.java @@ -109,7 +109,7 @@ public abstract class ProviderListBaseActivity extends ProviderSetupBaseActivity public void showAndSelectProvider(String newURL) { try { - provider = new Provider(new URL((newURL))); + provider = new Provider(new URL((newURL)), ""); autoSelectProvider(); } catch (MalformedURLException e) { e.printStackTrace(); @@ -165,6 +165,7 @@ public abstract class ProviderListBaseActivity extends ProviderSetupBaseActivity if (provider != null && !provider.isDefault()) { //TODO Code 2 pane view providerConfigState = SETTING_UP_PROVIDER; + ProviderObservable.getInstance().setProviderToSetup(provider); showProgressBar(); onItemSelectedLogic(); } else { diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java index dd9070af..134e2d76 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java @@ -21,6 +21,8 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import static se.leap.bitmaskclient.Provider.MAIN_URL; +import static se.leap.bitmaskclient.Provider.PROVIDER_IP; import static se.leap.bitmaskclient.utils.FileHelper.createFile; import static se.leap.bitmaskclient.utils.FileHelper.persistFile; import static se.leap.bitmaskclient.utils.InputStreamHelper.getInputStreamFrom; @@ -84,19 +86,21 @@ public class ProviderManager implements AdapteeCollection<Provider> { for (String file : relativeFilePaths) { String mainUrl = null; + String providerIp = null; String certificate = null; String providerDefinition = null; try { String provider = file.substring(0, file.length() - ".url".length()); - InputStream provider_file = assetsManager.open(directory + "/" + file); - mainUrl = extractMainUrlFromInputStream(provider_file); + InputStream providerFile = assetsManager.open(directory + "/" + file); + mainUrl = extractKeyFromInputStream(providerFile, MAIN_URL); + providerIp = extractKeyFromInputStream(providerFile, PROVIDER_IP); certificate = loadInputStreamAsString(assetsManager.open(provider + EXT_PEM)); providerDefinition = loadInputStreamAsString(assetsManager.open(provider + EXT_JSON)); } catch (IOException e) { e.printStackTrace(); } try { - providers.add(new Provider(new URL(mainUrl), certificate, providerDefinition)); + providers.add(new Provider(new URL(mainUrl), providerIp, certificate, providerDefinition)); } catch (MalformedURLException e) { e.printStackTrace(); } @@ -118,8 +122,10 @@ public class ProviderManager implements AdapteeCollection<Provider> { Set<Provider> providers = new HashSet<>(); try { for (String file : files) { - String mainUrl = extractMainUrlFromInputStream(getInputStreamFrom(externalFilesDir.getAbsolutePath() + "/" + file)); - providers.add(new Provider(new URL(mainUrl))); + InputStream inputStream = getInputStreamFrom(externalFilesDir.getAbsolutePath() + "/" + file); + String mainUrl = extractKeyFromInputStream(inputStream, MAIN_URL); + String providerIp = extractKeyFromInputStream(inputStream, PROVIDER_IP); + providers.add(new Provider(new URL(mainUrl), providerIp)); } } catch (MalformedURLException | FileNotFoundException | NullPointerException e) { e.printStackTrace(); @@ -128,13 +134,13 @@ public class ProviderManager implements AdapteeCollection<Provider> { return providers; } - private String extractMainUrlFromInputStream(InputStream inputStream) { - String mainUrl = ""; + private String extractKeyFromInputStream(InputStream inputStream, String key) { + String value = ""; JSONObject fileContents = inputStreamToJson(inputStream); if (fileContents != null) - mainUrl = fileContents.optString(Provider.MAIN_URL); - return mainUrl; + value = fileContents.optString(key); + return value; } private JSONObject inputStreamToJson(InputStream inputStream) { diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderObservable.java b/app/src/main/java/se/leap/bitmaskclient/ProviderObservable.java index 776c0e92..f20599ba 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderObservable.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderObservable.java @@ -2,14 +2,13 @@ package se.leap.bitmaskclient; import java.util.Observable; -import se.leap.bitmaskclient.utils.PreferenceHelper; - /** * Created by cyberta on 05.12.18. */ public class ProviderObservable extends Observable { private static ProviderObservable instance; private Provider currentProvider; + private Provider providerToSetup; public static ProviderObservable getInstance() { if (instance == null) { @@ -20,6 +19,7 @@ public class ProviderObservable extends Observable { public synchronized void updateProvider(Provider provider) { instance.currentProvider = provider; + instance.providerToSetup = null; instance.setChanged(); instance.notifyObservers(); } @@ -28,4 +28,12 @@ public class ProviderObservable extends Observable { return instance.currentProvider; } + public void setProviderToSetup(Provider provider) { + this.providerToSetup = provider; + } + + public Provider getProviderToSetup() { + return instance.providerToSetup; + } + } diff --git a/app/src/main/java/se/leap/bitmaskclient/utils/IPAddress.java b/app/src/main/java/se/leap/bitmaskclient/utils/IPAddress.java new file mode 100644 index 00000000..8b419a2c --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/utils/IPAddress.java @@ -0,0 +1,117 @@ +package se.leap.bitmaskclient.utils; + +/* + * Copyright (C) 2006-2008 Alfresco Software Limited. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ + +//package net.gqu.utils; + +import java.util.StringTokenizer; + +/** + * TCP/IP Address Utility Class + * + * @author gkspencer + */ +public class IPAddress { + + + /** + * Convert a TCP/IP address string into a byte array + * + * @param addr String + * @return byte[] + */ + public final static byte[] asBytes(String addr) { + + // Convert the TCP/IP address string to an integer value + + int ipInt = parseNumericAddress(addr); + if ( ipInt == 0) + return null; + + // Convert to bytes + + byte[] ipByts = new byte[4]; + + ipByts[3] = (byte) (ipInt & 0xFF); + ipByts[2] = (byte) ((ipInt >> 8) & 0xFF); + ipByts[1] = (byte) ((ipInt >> 16) & 0xFF); + ipByts[0] = (byte) ((ipInt >> 24) & 0xFF); + + // Return the TCP/IP bytes + + return ipByts; + } + /** + * Check if the specified address is a valid numeric TCP/IP address and return as an integer value + * + * @param ipaddr String + * @return int + */ + public final static int parseNumericAddress(String ipaddr) { + + // Check if the string is valid + + if ( ipaddr == null || ipaddr.length() < 7 || ipaddr.length() > 15) + return 0; + + // Check the address string, should be n.n.n.n format + + StringTokenizer token = new StringTokenizer(ipaddr,"."); + if ( token.countTokens() != 4) + return 0; + + int ipInt = 0; + + while ( token.hasMoreTokens()) { + + // Get the current token and convert to an integer value + + String ipNum = token.nextToken(); + + try { + + // Validate the current address part + + int ipVal = Integer.valueOf(ipNum).intValue(); + if ( ipVal < 0 || ipVal > 255) + return 0; + + // Add to the integer address + + ipInt = (ipInt << 8) + ipVal; + } + catch (NumberFormatException ex) { + return 0; + } + } + + // Return the integer address + + return ipInt; + } + + +}
\ No newline at end of file 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 40bb2eca..b6e39c50 100644 --- a/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java @@ -2,7 +2,6 @@ package se.leap.bitmaskclient.utils; import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -24,6 +23,7 @@ import se.leap.bitmaskclient.Provider; import static android.content.Context.MODE_PRIVATE; import static se.leap.bitmaskclient.Constants.ALWAYS_ON_SHOW_DIALOG; import static se.leap.bitmaskclient.Constants.DEFAULT_SHARED_PREFS_BATTERY_SAVER; +import static se.leap.bitmaskclient.Constants.EXCLUDED_APPS; import static se.leap.bitmaskclient.Constants.LAST_USED_PROFILE; import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION; import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED; @@ -33,7 +33,6 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.Constants.SU_PERMISSION; import static se.leap.bitmaskclient.Constants.USE_PLUGGABLE_TRANSPORTS; -import static se.leap.bitmaskclient.Constants.EXCLUDED_APPS; /** * Created by cyberta on 18.03.18. @@ -48,6 +47,7 @@ public class PreferenceHelper { Provider provider = new Provider(); try { provider.setMainUrl(new URL(preferences.getString(Provider.MAIN_URL, ""))); + provider.setProviderIp(preferences.getString(Provider.PROVIDER_IP, "")); provider.define(new JSONObject(preferences.getString(Provider.KEY, ""))); provider.setCaCert(preferences.getString(Provider.CA_CERT, "")); provider.setVpnCertificate(preferences.getString(PROVIDER_VPN_CERTIFICATE, "")); @@ -131,6 +131,7 @@ public class PreferenceHelper { //FIXME: don't save private keys in shared preferences! use the keystore public static void storeProviderInPreferences(SharedPreferences preferences, Provider provider) { preferences.edit().putBoolean(PROVIDER_CONFIGURED, true). + putString(Provider.PROVIDER_IP, provider.getProviderIp()). putString(Provider.MAIN_URL, provider.getMainUrlString()). putString(Provider.KEY, provider.getDefinitionString()). putString(Provider.CA_CERT, provider.getCaCert()). @@ -141,6 +142,7 @@ public class PreferenceHelper { String providerDomain = provider.getDomain(); preferences.edit().putBoolean(PROVIDER_CONFIGURED, true). + putString(Provider.PROVIDER_IP + "." + providerDomain, provider.getProviderIp()). putString(Provider.MAIN_URL + "." + providerDomain, provider.getMainUrlString()). putString(Provider.KEY + "." + providerDomain, provider.getDefinitionString()). putString(Provider.CA_CERT + "." + providerDomain, provider.getCaCert()). @@ -206,6 +208,7 @@ public class PreferenceHelper { remove(Provider.KEY + "." + providerDomain). remove(Provider.CA_CERT + "." + providerDomain). remove(Provider.CA_CERT_FINGERPRINT + "." + providerDomain). + remove(Provider.PROVIDER_IP + "." + providerDomain). remove(Provider.MAIN_URL + "." + providerDomain). remove(Provider.KEY + "." + providerDomain). remove(Provider.CA_CERT + "." + providerDomain). diff --git a/app/src/normal/assets/urls/pt.demo.bitmask.net.url b/app/src/normal/assets/urls/pt.demo.bitmask.net.url index d6e50462..cd393826 100644 --- a/app/src/normal/assets/urls/pt.demo.bitmask.net.url +++ b/app/src/normal/assets/urls/pt.demo.bitmask.net.url @@ -1,3 +1,4 @@ { - "main_url" : "https://pt.demo.bitmask.net" + "main_url" : "https://pt.demo.bitmask.net", + "provider_ip" : "198.252.153.85" } diff --git a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java index 41a63ad7..6f1e3034 100644 --- a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java +++ b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java @@ -121,14 +121,13 @@ public class ProviderApiManager extends ProviderApiManagerBase { Bundle result = new Bundle(); String caCert = provider.getCaCert(); - JSONObject providerDefinition = provider.getDefinition(); String providerDotJsonString; - if(providerDefinition.length() == 0 || caCert.isEmpty()) { + if(provider.getDefinitionString().length() == 0 || caCert.isEmpty()) { String providerJsonUrl = provider.getMainUrlString() + "/provider.json"; providerDotJsonString = downloadWithCommercialCA(providerJsonUrl, provider); } else { - providerDotJsonString = downloadFromApiUrlWithProviderCA("/provider.json", caCert, providerDefinition); + providerDotJsonString = downloadFromApiUrlWithProviderCA("/provider.json", caCert, provider); } if (ConfigHelper.checkErroneousDownload(providerDotJsonString) || !isValidJson(providerDotJsonString)) { @@ -163,8 +162,7 @@ public class ProviderApiManager extends ProviderApiManagerBase { Bundle result = new Bundle(); String eipServiceJsonString = ""; try { - JSONObject providerJson = provider.getDefinition(); - String eipServiceUrl = providerJson.getString(Provider.API_URL) + "/" + providerJson.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH; + String eipServiceUrl = provider.getApiUrlWithVersion() + "/" + EIP.SERVICE_API_PATH; eipServiceJsonString = downloadWithProviderCA(provider.getCaCert(), eipServiceUrl); JSONObject eipServiceJson = new JSONObject(eipServiceJsonString); if (BuildConfig.DEBUG) { @@ -278,10 +276,10 @@ public class ProviderApiManager extends ProviderApiManagerBase { * * @return an empty string if it fails, the response body if not. */ - private String downloadFromApiUrlWithProviderCA(String path, String caCert, JSONObject providerDefinition) { + private String downloadFromApiUrlWithProviderCA(String path, String caCert, Provider provider) { String responseString; JSONObject errorJson = new JSONObject(); - String baseUrl = getApiUrl(providerDefinition); + String baseUrl = provider.getApiUrlString(); OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(caCert, errorJson); if (okHttpClient == null) { return errorJson.toString(); 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 669abc84..89833393 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,15 @@ public class TestSetupHelper { public static Provider getConfiguredProvider() throws IOException, JSONException { - return getProvider(null, null, null, null); + return getProvider(null, null, null, null, null); } - public static Provider getProvider(String domain, String caCertFile, String providerJson, String eipServiceJson) { + public static Provider getProvider(String domain, String providerIp, String caCertFile, String providerJson, String eipServiceJson) { if (domain == null) domain = "https://riseup.net"; + if (providerIp == null) { + providerIp = ""; + } if (caCertFile == null) caCertFile = "riseup.net.pem"; if (providerJson == null) @@ -68,6 +71,7 @@ public class TestSetupHelper { try { Provider p = new Provider( new URL(domain), + providerIp, getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(caCertFile)), getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(providerJson)) diff --git a/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java index c4b8f65e..bb809a79 100644 --- a/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java @@ -53,6 +53,7 @@ public class ProviderTest { "https://pt.demo.bitmask.net", null, null, + null, "ptdemo.bitmask.eip-service.json"); assertTrue(p1.supportsPluggableTransports()); } @@ -63,6 +64,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 b37b3474..4d48372c 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, "ptdemo_misconfigured_gateway.json"); + Provider provider = getProvider(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, "ptdemo_three_mixed_gateways.json"); + Provider provider = getProvider(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, "ptdemo_three_mixed_gateways.json"); + Provider provider = getProvider(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, "ptdemo_three_mixed_gateways.json"); + Provider provider = getProvider(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, "ptdemo_three_mixed_gateways.json"); + Provider provider = getProvider(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, "ptdemo_three_mixed_gateways.json"); + Provider provider = getProvider(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, "ptdemo_two_openvpn_one_pt_gateways.json"); + Provider provider = getProvider(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 dde0601d..1120c0da 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; @@ -35,10 +36,13 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import java.io.IOException; +import java.net.UnknownHostException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; +import okhttp3.OkHttpClient; import se.leap.bitmaskclient.BuildConfig; +import se.leap.bitmaskclient.OkHttpClientGenerator; import se.leap.bitmaskclient.Provider; import se.leap.bitmaskclient.ProviderAPI; import se.leap.bitmaskclient.ProviderApiConnector; @@ -48,6 +52,13 @@ import se.leap.bitmaskclient.testutils.MockSharedPreferences; import se.leap.bitmaskclient.utils.ConfigHelper; import se.leap.bitmaskclient.utils.PreferenceHelper; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.when; import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY; import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.ProviderAPI.ERRORS; @@ -56,6 +67,7 @@ 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_DNS_RESOLUTION_ERROR; 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; @@ -269,7 +281,7 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_preseededProviderAndCA_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { - Provider provider = getProvider(null ,"outdated_cert.pem", null, null); + Provider provider = getProvider(null ,null, "outdated_cert.pem", null, null); mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); @@ -386,7 +398,7 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_outdatedPreseededProviderAndCA_successfulConfiguration() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { - Provider provider = getProvider(null, null, "riseup_net_outdated_config.json", null); + Provider provider = getProvider(null, null, null, "riseup_net_outdated_config.json", null); mockFingerprintForCertificate(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); mockProviderApiConnector(NO_ERROR); 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 481c87cb..7a50b9ce 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java @@ -21,6 +21,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.net.UnknownHostException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; @@ -434,14 +435,23 @@ public class MockHelper { BackendMockProvider.provideBackendResponsesFor(errorCase); } - public static OkHttpClientGenerator mockClientGenerator() { + public static OkHttpClientGenerator mockClientGenerator(boolean resolveDNS) throws UnknownHostException { OkHttpClientGenerator mockClientGenerator = mock(OkHttpClientGenerator.class); - OkHttpClient mockedOkHttpClient = mock(OkHttpClient.class); + OkHttpClient mockedOkHttpClient = mock(OkHttpClient.class, RETURNS_DEEP_STUBS); when(mockClientGenerator.initCommercialCAHttpClient(any(JSONObject.class))).thenReturn(mockedOkHttpClient); when(mockClientGenerator.initSelfSignedCAHttpClient(anyString(), any(JSONObject.class))).thenReturn(mockedOkHttpClient); + if (resolveDNS) { + when(mockedOkHttpClient.dns().lookup(anyString())).thenReturn(new ArrayList<>()); + } else { + when(mockedOkHttpClient.dns().lookup(anyString())).thenThrow(new UnknownHostException()); + } return mockClientGenerator; } + public static OkHttpClientGenerator mockClientGenerator() throws UnknownHostException { + return mockClientGenerator(true); + } + public static Resources mockResources(InputStream inputStream) throws IOException, JSONException { Resources mockedResources = mock(Resources.class, RETURNS_DEEP_STUBS); JSONObject errorMessages = new JSONObject(TestSetupHelper.getInputAsString(inputStream)); |