summaryrefslogtreecommitdiff
path: root/app/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java182
2 files changed, 181 insertions, 3 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
index b3483506..3545caca 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
@@ -417,7 +417,7 @@ public final class Provider implements Parcelable {
}
public boolean hasDefinition() {
- return definition != null && definition.length() > 0;
+ return (definition != null && definition.length() > 0) || (modelsProvider != null);
}
public boolean hasGeoIpJson() {
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java
index 4e698d28..b425cfb7 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java
@@ -1,24 +1,55 @@
package se.leap.bitmaskclient.providersetup;
+import static android.text.TextUtils.isEmpty;
+import static se.leap.bitmaskclient.R.string.malformed_url;
+import static se.leap.bitmaskclient.R.string.warning_corrupted_provider_cert;
+import static se.leap.bitmaskclient.R.string.warning_expired_provider_cert;
import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY;
+import static se.leap.bitmaskclient.base.models.Constants.COUNTRYCODE;
+import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY;
+import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_SERVICE_JSON;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS;
+import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.PROVIDER_NOK;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.PROVIDER_OK;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.QUIETLY_UPDATE_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.SET_UP_PROVIDER;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.providersetup.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_INVALID_CERTIFICATE;
+import static se.leap.bitmaskclient.providersetup.ProviderSetupObservable.DOWNLOADED_EIP_SERVICE_JSON;
+import static se.leap.bitmaskclient.providersetup.ProviderSetupObservable.DOWNLOADED_PROVIDER_JSON;
import static se.leap.bitmaskclient.providersetup.ProviderSetupObservable.DOWNLOADED_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.tor.TorStatusObservable.TorStatus.OFF;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.util.Log;
+import androidx.annotation.Nullable;
+
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+
+import de.blinkt.openvpn.core.VpnStatus;
+import mobile.BitmaskMobile;
+import mobilemodels.Bridges;
+import mobilemodels.Gateways;
+import models.ModelsEIPService;
+import models.ModelsProvider;
+import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.base.models.Provider;
import se.leap.bitmaskclient.base.models.ProviderObservable;
+import se.leap.bitmaskclient.base.utils.ConfigHelper;
import se.leap.bitmaskclient.base.utils.PreferenceHelper;
+import se.leap.bitmaskclient.eip.EipStatus;
+import se.leap.bitmaskclient.tor.TorStatusObservable;
public class ProviderApiManagerV5 extends ProviderApiManagerBase implements IProviderApiManager {
@@ -64,10 +95,157 @@ public class ProviderApiManagerV5 extends ProviderApiManagerBase implements IPro
}
- protected Bundle setupProvider(Provider provider, Bundle task) {
- return null;
+
+ protected Bundle setupProvider(Provider provider, Bundle parameters) {
+ Bundle currentDownload = new Bundle();
+
+ if (isEmpty(provider.getMainUrl()) || provider.getMainUrl().isEmpty()) {
+ currentDownload.putBoolean(BROADCAST_RESULT_KEY, false);
+ eventSender.setErrorResult(currentDownload, malformed_url, null);
+ VpnStatus.logWarning("[API] MainURL String is not set. Cannot setup provider.");
+ return currentDownload;
+ }
+
+ getPersistedProviderUpdates(provider);
+ currentDownload = validateProviderDetails(provider);
+
+ //provider certificate invalid
+ if (currentDownload.containsKey(ERRORS)) {
+ currentDownload.putParcelable(PROVIDER_KEY, provider);
+ return currentDownload;
+ }
+
+ //no provider json or certificate available
+ if (currentDownload.containsKey(BROADCAST_RESULT_KEY) && !currentDownload.getBoolean(BROADCAST_RESULT_KEY)) {
+ resetProviderDetails(provider);
+ }
+
+ if (currentDownload.containsKey(PROVIDER_KEY)) {
+ provider = currentDownload.getParcelable(PROVIDER_KEY);
+ }
+ BitmaskMobile bm;
+ try {
+ bm = new BitmaskMobile(provider.getMainUrl(), new PreferenceHelper.SharedPreferenceStore());
+ } catch (IllegalStateException e) {
+ // TODO: improve error message
+ return eventSender.setErrorResult(currentDownload, R.string.config_error_found, null);
+ }
+
+ configureBaseCountryCode(bm, parameters);
+
+ try {
+ ModelsProvider p = bm.getProvider();
+ provider.setModelsProvider(p);
+ ProviderSetupObservable.updateProgress(DOWNLOADED_PROVIDER_JSON);
+ } catch (Exception e) {
+ return eventSender.setErrorResult(currentDownload, R.string.error_json_exception_user_message, null);
+ }
+ try {
+ ModelsEIPService service = bm.getService();
+ provider.setService(service);
+ ProviderSetupObservable.updateProgress(DOWNLOADED_EIP_SERVICE_JSON);
+ } catch (Exception e) {
+ return eventSender.setErrorResult(currentDownload, R.string.error_json_exception_user_message, null);
+ }
+
+ try {
+ // TODO: check if provider supports this API endpoint?
+ Gateways gateways = bm.getAllGateways("", "", "");
+ provider.setGateways(gateways);
+ } catch (Exception e) {
+ return eventSender.setErrorResult(currentDownload, R.string.error_json_exception_user_message, null);
+ }
+
+ try {
+ // TODO: check if provider supports this API endpoint?
+ Bridges bridges = bm.getAllBridges("", "", "", "");
+ provider.setBridges(bridges);
+ } catch (Exception e) {
+ return eventSender.setErrorResult(currentDownload, R.string.error_json_exception_user_message, null);
+ }
+
+ try {
+ String cert = bm.getOpenVPNCert();
+ currentDownload = loadCertificate(provider, cert);
+ } catch (Exception e) {
+ return eventSender.setErrorResult(currentDownload, R.string.error_json_exception_user_message, null);
+ }
+
+ return currentDownload;
+ }
+
+ @Nullable
+ private void configureBaseCountryCode(BitmaskMobile bm, Bundle parameters) {
+ String cc = parameters.getString(COUNTRYCODE, null);
+ if (cc == null &&
+ !EipStatus.getInstance().isDisconnected() &&
+ TorStatusObservable.getStatus() == OFF) {
+ try {
+ // FIXME: doGeolocationLookup currently sets the country code implicitly, change that in bitmask-core
+ bm.doGeolocationLookup();
+ } catch (Exception e) {
+ // print exception and ignore
+ e.printStackTrace();
+ }
+ } else {
+ bm.setCountryCode(cc);
+ }
}
+ Bundle validateProviderDetails(Provider provider) {
+ Bundle result = new Bundle();
+ result.putBoolean(BROADCAST_RESULT_KEY, false);
+
+ if (!provider.hasDefinition()) {
+ return result;
+ }
+
+ result = validateCertificateForProvider(result, provider);
+
+ //invalid certificate or no certificate or unable to connect due other connectivity issues
+ if (result.containsKey(ERRORS) || (result.containsKey(BROADCAST_RESULT_KEY) && !result.getBoolean(BROADCAST_RESULT_KEY)) ) {
+ return result;
+ }
+
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
+
+ return result;
+ }
+
+ protected Bundle validateCertificateForProvider(Bundle result, Provider provider) {
+ String caCert = provider.getCaCert();
+
+ if (ConfigHelper.checkErroneousDownload(caCert)) {
+ VpnStatus.logWarning("[API] No provider cert.");
+ return result;
+ }
+
+ ArrayList<X509Certificate> certificates = ConfigHelper.parseX509CertificatesFromString(caCert);
+ if (certificates == null) {
+ return eventSender.setErrorResult(result, warning_corrupted_provider_cert, ERROR_INVALID_CERTIFICATE.toString());
+ }
+
+ ArrayList<X509Certificate> validCertificates = new ArrayList<>();
+ int invalidCertificates = 0;
+ for (X509Certificate certificate : certificates) {
+ try {
+ certificate.checkValidity();
+ validCertificates.add(certificate);
+ } catch (CertificateNotYetValidException |
+ CertificateExpiredException e) {
+ e.printStackTrace();
+ invalidCertificates++;
+ }
+ }
+ if (validCertificates.isEmpty() && invalidCertificates > 0) {
+ return eventSender.setErrorResult(result, warning_expired_provider_cert, ERROR_INVALID_CERTIFICATE.toString());
+ }
+
+ provider.setCaCert(ConfigHelper.parseX509CertificatesToString(validCertificates));
+ result.putParcelable(PROVIDER_KEY, provider);
+ result.putBoolean(BROADCAST_RESULT_KEY, true);
+ return result;
+ }
protected Bundle updateVpnCertificate(Provider provider) {
return null;