summaryrefslogtreecommitdiff
path: root/app/src/main/java/se/leap/bitmaskclient
diff options
context:
space:
mode:
authorcyBerta <cyberta@riseup.net>2018-01-09 20:55:10 +0100
committercyBerta <cyberta@riseup.net>2018-01-09 20:55:10 +0100
commit0b647ea5e7ff67747080b2ffcebc948da0fbecb5 (patch)
treee01b59b626aded786cca8d25f7749c52b9150194 /app/src/main/java/se/leap/bitmaskclient
parent81a732702f7b3125ac543f92d8a5ec33cce972fe (diff)
8773 refactoring ProviderAPI for testability, setting up basic unit test framework
Diffstat (limited to 'app/src/main/java/se/leap/bitmaskclient')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java60
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java16
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java166
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java124
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderApiConnector.java102
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java (renamed from app/src/main/java/se/leap/bitmaskclient/ProviderApiBase.java)343
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java2
9 files changed, 578 insertions, 243 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java b/app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java
index 2c169e3d..c26184bb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java
@@ -56,7 +56,7 @@ import se.leap.bitmaskclient.userstatus.SessionDialog;
import static android.view.View.GONE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
-import static se.leap.bitmaskclient.ProviderApiBase.ERRORS;
+import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
/**
* abstract base Activity that builds and shows the list of known available providers.
@@ -352,7 +352,7 @@ public abstract class BaseConfigurationWizard extends Activity
}
/**
- * Asks ProviderAPI to download an anonymous (anon) VPN certificate.
+ * Asks ProviderApiService to download an anonymous (anon) VPN certificate.
*/
private void downloadVpnCertificate() {
Intent provider_API_command = new Intent(this, ProviderAPI.class);
diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
index ed527a54..54bcc1f4 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
@@ -16,16 +16,33 @@
*/
package se.leap.bitmaskclient;
-import android.util.*;
-
-import org.json.*;
-
-import java.io.*;
-import java.math.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.interfaces.*;
-import java.security.spec.*;
+import android.support.annotation.NonNull;
+import android.util.Log;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.spongycastle.util.encoders.Base64;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
import static android.R.attr.name;
@@ -82,7 +99,7 @@ public class ConfigHelper {
cf = CertificateFactory.getInstance("X.509");
certificate_string = certificate_string.replaceFirst("-----BEGIN CERTIFICATE-----", "").replaceFirst("-----END CERTIFICATE-----", "").trim();
- byte[] cert_bytes = Base64.decode(certificate_string, Base64.DEFAULT);
+ byte[] cert_bytes = Base64.decode(certificate_string);
InputStream caInput = new ByteArrayInputStream(cert_bytes);
try {
certificate = cf.generateCertificate(caInput);
@@ -90,15 +107,9 @@ public class ConfigHelper {
} finally {
caInput.close();
}
- } catch (CertificateException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- return null;
- } catch (IllegalArgumentException e) {
+ } catch (NullPointerException | CertificateException | IOException | IllegalArgumentException e) {
return null;
}
-
return (X509Certificate) certificate;
}
@@ -139,7 +150,7 @@ public class ConfigHelper {
try {
KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
rsaKeyString = rsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", "");
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(rsaKeyString, Base64.DEFAULT));
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(rsaKeyString));
key = (RSAPrivateKey) kf.generatePrivate(keySpec);
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
@@ -162,7 +173,7 @@ public class ConfigHelper {
}
public static String base64toHex(String base64_input) {
- byte[] byteArray = Base64.decode(base64_input, Base64.DEFAULT);
+ byte[] byteArray = Base64.decode(base64_input);
int readBytes = byteArray.length;
StringBuffer hexData = new StringBuffer();
int onebyte;
@@ -172,6 +183,15 @@ public class ConfigHelper {
}
return hexData.toString();
}
+
+ @NonNull
+ public static String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException /*, UnsupportedEncodingException*/ {
+ return base64toHex(
+ //new String(Base64.encode(MessageDigest.getInstance(encoding).digest(certificate.getEncoded())), "US-ASCII"));
+ android.util.Base64.encodeToString(
+ MessageDigest.getInstance(encoding).digest(certificate.getEncoded()),
+ android.util.Base64.DEFAULT));
+ }
/**
* Adds a new X509 certificate given its input stream and its provider name
diff --git a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
index 6f6a14de..9d3f4b52 100644
--- a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
@@ -16,19 +16,19 @@
*/
package se.leap.bitmaskclient;
-import android.app.*;
-import android.content.*;
-import android.os.*;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
-import org.json.JSONException;
import org.json.JSONObject;
-import se.leap.bitmaskclient.userstatus.SessionDialog;
-
import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.DEFAULT;
import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.valueOf;
-import static se.leap.bitmaskclient.ProviderApiBase.ERRORID;
-import static se.leap.bitmaskclient.ProviderApiBase.ERRORS;
+import static se.leap.bitmaskclient.ProviderAPI.ERRORID;
+import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
/**
* Implements a dialog to show why a download failed.
diff --git a/app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java b/app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java
new file mode 100644
index 00000000..1bf679f8
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/OkHttpClientGenerator.java
@@ -0,0 +1,166 @@
+/**
+ * Copyright (c) 2018 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package se.leap.bitmaskclient;
+
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.Build;
+import android.support.annotation.NonNull;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import okhttp3.CipherSuite;
+import okhttp3.ConnectionSpec;
+import okhttp3.Cookie;
+import okhttp3.CookieJar;
+import okhttp3.HttpUrl;
+import okhttp3.OkHttpClient;
+import okhttp3.TlsVersion;
+
+import static android.text.TextUtils.isEmpty;
+import static se.leap.bitmaskclient.ProviderAPI.ERRORS;
+import static se.leap.bitmaskclient.R.string.certificate_error;
+import static se.leap.bitmaskclient.R.string.error_io_exception_user_message;
+import static se.leap.bitmaskclient.R.string.error_no_such_algorithm_exception_user_message;
+import static se.leap.bitmaskclient.R.string.keyChainAccessError;
+import static se.leap.bitmaskclient.R.string.server_unreachable_message;
+
+/**
+ * Created by cyberta on 08.01.18.
+ */
+
+public class OkHttpClientGenerator {
+
+ SharedPreferences preferences;
+ Resources resources;
+
+ public OkHttpClientGenerator(SharedPreferences preferences, Resources resources) {
+ this.preferences = preferences;
+ this.resources = resources;
+ }
+
+ public OkHttpClient initCommercialCAHttpClient(JSONObject initError) {
+ return initHttpClient(initError, null);
+ }
+
+ public OkHttpClient initSelfSignedCAHttpClient(JSONObject initError) {
+ String certificate = preferences.getString(Provider.CA_CERT, "");
+ return initHttpClient(initError, certificate);
+ }
+
+ public OkHttpClient initSelfSignedCAHttpClient(JSONObject initError, String certificate) {
+ return initHttpClient(initError, certificate);
+ }
+
+
+ private OkHttpClient initHttpClient(JSONObject initError, String certificate) {
+ try {
+ TLSCompatSocketFactory sslCompatFactory;
+ ConnectionSpec spec = getConnectionSpec();
+ OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
+
+ if (!isEmpty(certificate)) {
+ sslCompatFactory = new TLSCompatSocketFactory(certificate);
+ } else {
+ sslCompatFactory = new TLSCompatSocketFactory();
+ }
+ sslCompatFactory.initSSLSocketFactory(clientBuilder);
+ clientBuilder.cookieJar(getCookieJar())
+ .connectionSpecs(Collections.singletonList(spec));
+ return clientBuilder.build();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ addErrorMessageToJson(initError, resources.getString(R.string.certificate_error));
+ } catch (IllegalStateException | KeyManagementException | KeyStoreException e) {
+ e.printStackTrace();
+ addErrorMessageToJson(initError, String.format(resources.getString(keyChainAccessError), e.getLocalizedMessage()));
+ } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
+ e.printStackTrace();
+ addErrorMessageToJson(initError, resources.getString(error_no_such_algorithm_exception_user_message));
+ } catch (CertificateException e) {
+ e.printStackTrace();
+ addErrorMessageToJson(initError, resources.getString(certificate_error));
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ addErrorMessageToJson(initError, resources.getString(server_unreachable_message));
+ } catch (IOException e) {
+ e.printStackTrace();
+ addErrorMessageToJson(initError, resources.getString(error_io_exception_user_message));
+ }
+ return null;
+ }
+
+
+
+ @NonNull
+ private ConnectionSpec getConnectionSpec() {
+ ConnectionSpec.Builder connectionSpecbuilder = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
+ .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_3);
+ //FIXME: restrict connection further to the following recommended cipher suites for ALL supported API levels
+ //figure out how to use bcjsse for that purpose
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1)
+ connectionSpecbuilder.cipherSuites(
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+ );
+ return connectionSpecbuilder.build();
+ }
+
+ @NonNull
+ private CookieJar getCookieJar() {
+ return new CookieJar() {
+ private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
+
+ @Override
+ public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
+ cookieStore.put(url.host(), cookies);
+ }
+
+ @Override
+ public List<Cookie> loadForRequest(HttpUrl url) {
+ List<Cookie> cookies = cookieStore.get(url.host());
+ return cookies != null ? cookies : new ArrayList<Cookie>();
+ }
+ };
+ }
+
+ private void addErrorMessageToJson(JSONObject jsonObject, String errorMessage) {
+ try {
+ jsonObject.put(ERRORS, errorMessage);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java
new file mode 100644
index 00000000..5a6aabc0
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPI.java
@@ -0,0 +1,124 @@
+/**
+ * Copyright (c) 2017 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package se.leap.bitmaskclient;
+
+import android.annotation.SuppressLint;
+import android.app.IntentService;
+import android.content.Intent;
+import android.content.SharedPreferences;
+
+import de.blinkt.openvpn.core.Preferences;
+
+/**
+ * Implements HTTP api methods (encapsulated in {{@link ProviderApiManager}})
+ * used to manage communications with the provider server.
+ * <p/>
+ * It's an IntentService because it downloads data from the Internet, so it operates in the background.
+ *
+ * @author parmegv
+ * @author MeanderingCode
+ * @author cyberta
+ */
+
+public class ProviderAPI extends IntentService implements ProviderApiManagerBase.ProviderApiServiceCallback {
+
+ final public static String
+ TAG = ProviderAPI.class.getSimpleName(),
+ SET_UP_PROVIDER = "setUpProvider",
+ UPDATE_PROVIDER_DETAILS = "updateProviderDetails",
+ DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON",
+ SIGN_UP = "srpRegister",
+ LOG_IN = "srpAuth",
+ LOG_OUT = "logOut",
+ DOWNLOAD_CERTIFICATE = "downloadUserAuthedCertificate",
+ PARAMETERS = "parameters",
+ RESULT_KEY = "result",
+ RECEIVER_KEY = "receiver",
+ ERRORS = "errors",
+ ERRORID = "errorId",
+ UPDATE_PROGRESSBAR = "update_progressbar",
+ CURRENT_PROGRESS = "current_progress",
+ DOWNLOAD_EIP_SERVICE = TAG + ".DOWNLOAD_EIP_SERVICE";
+
+ final public static int
+ SUCCESSFUL_LOGIN = 3,
+ FAILED_LOGIN = 4,
+ SUCCESSFUL_SIGNUP = 5,
+ FAILED_SIGNUP = 6,
+ SUCCESSFUL_LOGOUT = 7,
+ LOGOUT_FAILED = 8,
+ CORRECTLY_DOWNLOADED_CERTIFICATE = 9,
+ INCORRECTLY_DOWNLOADED_CERTIFICATE = 10,
+ PROVIDER_OK = 11,
+ PROVIDER_NOK = 12,
+ CORRECTLY_DOWNLOADED_EIP_SERVICE = 13,
+ INCORRECTLY_DOWNLOADED_EIP_SERVICE = 14;
+
+ ProviderApiManager providerApiManager;
+
+
+
+ public ProviderAPI() {
+ super(TAG);
+ }
+
+ //TODO: refactor me, please!
+ public static void stop() {
+ ProviderApiManager.stop();
+ }
+
+ //TODO: refactor me, please!
+ public static boolean caCertDownloaded() {
+ return ProviderApiManager.caCertDownloaded();
+ }
+
+ //TODO: refactor me, please!
+ public static String lastProviderMainUrl() {
+ return ProviderApiManager.lastProviderMainUrl();
+ }
+
+ //TODO: refactor me, please!
+ //used in insecure flavor only
+ @SuppressLint("unused")
+ public static boolean lastDangerOn() {
+ return ProviderApiManager.lastDangerOn();
+ }
+
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ providerApiManager = initApiManager();
+ }
+
+ @Override
+ public void broadcastProgress(Intent intent) {
+ sendBroadcast(intent);
+ }
+
+ @Override
+ protected void onHandleIntent(Intent command) {
+ providerApiManager.handleIntent(command);
+ }
+
+
+ private ProviderApiManager initApiManager() {
+ SharedPreferences preferences = getSharedPreferences(Constants.SHARED_PREFERENCES, MODE_PRIVATE);
+ OkHttpClientGenerator clientGenerator = new OkHttpClientGenerator(preferences, getResources());
+ return new ProviderApiManager(preferences, getResources(), clientGenerator, this);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
index 9b880f89..9b777e5a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
@@ -16,7 +16,9 @@
*/
package se.leap.bitmaskclient;
-import android.os.*;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ResultReceiver;
/**
* Implements the ResultReceiver needed by Activities using ProviderAPI to receive the results of its operations.
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiConnector.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiConnector.java
new file mode 100644
index 00000000..9aad14d5
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiConnector.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright (c) 2018 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package se.leap.bitmaskclient;
+
+import android.support.annotation.NonNull;
+import android.util.Pair;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Locale;
+import java.util.Scanner;
+
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+/**
+ * Created by cyberta on 08.01.18.
+ */
+
+public class ProviderApiConnector {
+
+ private static final MediaType JSON
+ = MediaType.parse("application/json; charset=utf-8");
+
+
+ public static boolean delete(OkHttpClient okHttpClient, String deleteUrl) {
+ try {
+ Request.Builder requestBuilder = new Request.Builder()
+ .url(deleteUrl)
+ .delete();
+ Request request = requestBuilder.build();
+
+ Response response = okHttpClient.newCall(request).execute();
+ if (response.isSuccessful() || response.code() == 401) {
+ return true;
+ }
+ } catch (IOException | RuntimeException e) {
+ return false;
+ }
+
+ return false;
+ }
+
+ public static boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) {
+ try {
+ Request.Builder requestBuilder = new Request.Builder()
+ .url(url)
+ .method("GET", null);
+ Request request = requestBuilder.build();
+
+ Response response = okHttpClient.newCall(request).execute();
+ return response.isSuccessful();
+ } catch (RuntimeException | IOException e) {
+ return false;
+ }
+
+ }
+
+ public static String requestStringFromServer(@NonNull String url, @NonNull String request_method, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
+
+ RequestBody jsonBody = jsonString != null ? RequestBody.create(JSON, jsonString) : null;
+ Request.Builder requestBuilder = new Request.Builder()
+ .url(url)
+ .method(request_method, jsonBody);
+ if (headerArgs != null) {
+ for (Pair<String, String> keyValPair : headerArgs) {
+ requestBuilder.addHeader(keyValPair.first, keyValPair.second);
+ }
+ }
+ //TODO: move to getHeaderArgs()?
+ String locale = Locale.getDefault().getLanguage() + Locale.getDefault().getCountry();
+ requestBuilder.addHeader("Accept-Language", locale);
+ Request request = requestBuilder.build();
+
+ Response response = okHttpClient.newCall(request).execute();
+ InputStream inputStream = response.body().byteStream();
+ Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
+ if (scanner.hasNext()) {
+ return scanner.next();
+ }
+ return null;
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
index 0013d2c2..396d642b 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiBase.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2017 LEAP Encryption Access Project and contributers
+ * 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
@@ -14,13 +14,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
package se.leap.bitmaskclient;
-import android.app.IntentService;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
-import android.os.Build;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.support.annotation.NonNull;
@@ -38,11 +37,7 @@ import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.net.UnknownServiceException;
-import java.security.KeyManagementException;
-import java.security.KeyStoreException;
-import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
@@ -50,90 +45,75 @@ import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;
import javax.net.ssl.SSLHandshakeException;
-import okhttp3.CipherSuite;
-import okhttp3.ConnectionSpec;
-import okhttp3.Cookie;
-import okhttp3.CookieJar;
-import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
-import okhttp3.TlsVersion;
import se.leap.bitmaskclient.userstatus.SessionDialog;
import se.leap.bitmaskclient.userstatus.User;
import se.leap.bitmaskclient.userstatus.UserStatus;
-import static android.text.TextUtils.isEmpty;
-import static se.leap.bitmaskclient.ConfigHelper.base64toHex;
+import static se.leap.bitmaskclient.ConfigHelper.getFingerprintFromCertificate;
import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_CERTIFICATE_PINNING;
import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_CORRUPTED_PROVIDER_JSON;
import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_INVALID_CERTIFICATE;
import static se.leap.bitmaskclient.Provider.MAIN_URL;
+import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE;
+import static se.leap.bitmaskclient.ProviderAPI.CURRENT_PROGRESS;
+import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.DOWNLOAD_EIP_SERVICE;
+import static se.leap.bitmaskclient.ProviderAPI.ERRORID;
+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_CERTIFICATE;
+import static se.leap.bitmaskclient.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE;
+import static se.leap.bitmaskclient.ProviderAPI.LOGOUT_FAILED;
+import static se.leap.bitmaskclient.ProviderAPI.LOG_IN;
+import static se.leap.bitmaskclient.ProviderAPI.LOG_OUT;
+import static se.leap.bitmaskclient.ProviderAPI.PARAMETERS;
+import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_NOK;
+import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_OK;
+import static se.leap.bitmaskclient.ProviderAPI.RECEIVER_KEY;
+import static se.leap.bitmaskclient.ProviderAPI.RESULT_KEY;
+import static se.leap.bitmaskclient.ProviderAPI.SET_UP_PROVIDER;
+import static se.leap.bitmaskclient.ProviderAPI.SIGN_UP;
+import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_LOGIN;
+import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_LOGOUT;
+import static se.leap.bitmaskclient.ProviderAPI.SUCCESSFUL_SIGNUP;
+import static se.leap.bitmaskclient.ProviderAPI.UPDATE_PROGRESSBAR;
+import static se.leap.bitmaskclient.ProviderAPI.UPDATE_PROVIDER_DETAILS;
import static se.leap.bitmaskclient.R.string.certificate_error;
import static se.leap.bitmaskclient.R.string.error_io_exception_user_message;
import static se.leap.bitmaskclient.R.string.error_json_exception_user_message;
import static se.leap.bitmaskclient.R.string.error_no_such_algorithm_exception_user_message;
-import static se.leap.bitmaskclient.R.string.keyChainAccessError;
import static se.leap.bitmaskclient.R.string.malformed_url;
+import static se.leap.bitmaskclient.R.string.retry;
import static se.leap.bitmaskclient.R.string.server_unreachable_message;
import static se.leap.bitmaskclient.R.string.service_is_down_error;
/**
- * Implements HTTP api methods used to manage communications with the provider server.
- * The implemented methods are commonly used by insecure's and production's flavor of ProviderAPI.
- * <p/>
- * It's an IntentService because it downloads data from the Internet, so it operates in the background.
- *
- * @author parmegv
- * @author MeanderingCode
- * @author cyberta
+ * Implements the logic of the http api calls. The methods of this class needs to be called from
+ * a background thread.
*/
-public abstract class ProviderApiBase extends IntentService {
-
- final public static String
- TAG = ProviderAPI.class.getSimpleName(),
- SET_UP_PROVIDER = "setUpProvider",
- UPDATE_PROVIDER_DETAILS = "updateProviderDetails",
- DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON",
- SIGN_UP = "srpRegister",
- LOG_IN = "srpAuth",
- LOG_OUT = "logOut",
- DOWNLOAD_CERTIFICATE = "downloadUserAuthedCertificate",
- PARAMETERS = "parameters",
- RESULT_KEY = "result",
- RECEIVER_KEY = "receiver",
- ERRORS = "errors",
- ERRORID = "errorId",
- UPDATE_PROGRESSBAR = "update_progressbar",
- CURRENT_PROGRESS = "current_progress",
- DOWNLOAD_EIP_SERVICE = TAG + ".DOWNLOAD_EIP_SERVICE";
-
- final public static int
- SUCCESSFUL_LOGIN = 3,
- FAILED_LOGIN = 4,
- SUCCESSFUL_SIGNUP = 5,
- FAILED_SIGNUP = 6,
- SUCCESSFUL_LOGOUT = 7,
- LOGOUT_FAILED = 8,
- CORRECTLY_DOWNLOADED_CERTIFICATE = 9,
- INCORRECTLY_DOWNLOADED_CERTIFICATE = 10,
- PROVIDER_OK = 11,
- PROVIDER_NOK = 12,
- CORRECTLY_DOWNLOADED_EIP_SERVICE = 13,
- INCORRECTLY_DOWNLOADED_EIP_SERVICE = 14;
-
- protected static boolean
+public abstract class ProviderApiManagerBase {
+
+ public interface ProviderApiServiceCallback {
+ void broadcastProgress(Intent intent);
+ }
+
+ private ProviderApiServiceCallback serviceCallback;
+
+ protected static volatile boolean
CA_CERT_DOWNLOADED = false,
PROVIDER_JSON_DOWNLOADED = false,
EIP_SERVICE_JSON_DOWNLOADED = false;
@@ -146,32 +126,28 @@ public abstract class ProviderApiBase extends IntentService {
protected static String providerCaCert;
protected static JSONObject providerDefinition;
protected Resources resources;
+ protected OkHttpClientGenerator clientGenerator;
public static void stop() {
go_ahead = false;
}
- private final MediaType JSON
- = MediaType.parse("application/json; charset=utf-8");
-
- public ProviderApiBase() {
- super(TAG);
+ public static String lastProviderMainUrl() {
+ return lastProviderMainUrl;
}
- @Override
- public void onCreate() {
- super.onCreate();
- preferences = getSharedPreferences(Constants.SHARED_PREFERENCES, MODE_PRIVATE);
- resources = getResources();
- }
+ private final MediaType JSON
+ = MediaType.parse("application/json; charset=utf-8");
- public static String lastProviderMainUrl() {
- return lastProviderMainUrl;
+ public ProviderApiManagerBase(SharedPreferences preferences, Resources resources, OkHttpClientGenerator clientGenerator, ProviderApiServiceCallback callback) {
+ this.preferences = preferences;
+ this.resources = resources;
+ this.serviceCallback = callback;
+ this.clientGenerator = clientGenerator;
}
- @Override
- protected void onHandleIntent(Intent command) {
+ public void handleIntent(Intent command) {
final ResultReceiver receiver = command.getParcelableExtra(RECEIVER_KEY);
String action = command.getAction();
Bundle parameters = command.getBundleExtra(PARAMETERS);
@@ -185,6 +161,7 @@ public abstract class ProviderApiBase extends IntentService {
go_ahead = false;
}
}
+
if (action.equals(UPDATE_PROVIDER_DETAILS)) {
resetProviderDetails();
Bundle task = new Bundle();
@@ -255,7 +232,7 @@ public abstract class ProviderApiBase extends IntentService {
}
protected String formatErrorMessage(final int toastStringId) {
- return formatErrorMessage(getResources().getString(toastStringId));
+ return formatErrorMessage(resources.getString(toastStringId));
}
private String formatErrorMessage(String errorMessage) {
@@ -288,91 +265,7 @@ public abstract class ProviderApiBase extends IntentService {
}
}
- private OkHttpClient initHttpClient(JSONObject initError, String certificate) {
- try {
- TLSCompatSocketFactory sslCompatFactory;
- ConnectionSpec spec = getConnectionSpec();
- OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
- if (!isEmpty(certificate)) {
- sslCompatFactory = new TLSCompatSocketFactory(certificate);
- } else {
- sslCompatFactory = new TLSCompatSocketFactory();
- }
- sslCompatFactory.initSSLSocketFactory(clientBuilder);
- clientBuilder.cookieJar(getCookieJar())
- .connectionSpecs(Collections.singletonList(spec));
- return clientBuilder.build();
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- addErrorMessageToJson(initError, resources.getString(R.string.certificate_error));
- } catch (IllegalStateException | KeyManagementException | KeyStoreException e) {
- e.printStackTrace();
- addErrorMessageToJson(initError, String.format(resources.getString(keyChainAccessError), e.getLocalizedMessage()));
- } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
- e.printStackTrace();
- addErrorMessageToJson(initError, resources.getString(error_no_such_algorithm_exception_user_message));
- } catch (CertificateException e) {
- e.printStackTrace();
- addErrorMessageToJson(initError, resources.getString(certificate_error));
- } catch (UnknownHostException e) {
- e.printStackTrace();
- addErrorMessageToJson(initError, resources.getString(server_unreachable_message));
- } catch (IOException e) {
- e.printStackTrace();
- addErrorMessageToJson(initError, resources.getString(error_io_exception_user_message));
- }
- return null;
- }
-
- protected OkHttpClient initCommercialCAHttpClient(JSONObject initError) {
- return initHttpClient(initError, null);
- }
-
- protected OkHttpClient initSelfSignedCAHttpClient(JSONObject initError) {
- String certificate = preferences.getString(Provider.CA_CERT, "");
- return initHttpClient(initError, certificate);
- }
-
- protected OkHttpClient initSelfSignedCAHttpClient(JSONObject initError, String certificate) {
- return initHttpClient(initError, certificate);
- }
-
- @NonNull
- private ConnectionSpec getConnectionSpec() {
- ConnectionSpec.Builder connectionSpecbuilder = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
- .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_3);
- //FIXME: restrict connection further to the following recommended cipher suites for ALL supported API levels
- //figure out how to use bcjsse for that purpose
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1)
- connectionSpecbuilder.cipherSuites(
- CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
- CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- );
- return connectionSpecbuilder.build();
- }
-
- @NonNull
- private CookieJar getCookieJar() {
- return new CookieJar() {
- private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
-
- @Override
- public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
- cookieStore.put(url.host(), cookies);
- }
-
- @Override
- public List<Cookie> loadForRequest(HttpUrl url) {
- List<Cookie> cookies = cookieStore.get(url.host());
- return cookies != null ? cookies : new ArrayList<Cookie>();
- }
- };
- }
private Bundle tryToRegister(Bundle task) {
@@ -402,7 +295,7 @@ public abstract class ProviderApiBase extends IntentService {
private Bundle register(String username, String password) {
JSONObject stepResult = null;
- OkHttpClient okHttpClient = initSelfSignedCAHttpClient(stepResult);
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(stepResult);
if (okHttpClient == null) {
return authFailedNotification(stepResult, username);
}
@@ -459,7 +352,7 @@ public abstract class ProviderApiBase extends IntentService {
private Bundle authenticate(String username, String password) {
Bundle result = new Bundle();
JSONObject stepResult = new JSONObject();
- OkHttpClient okHttpClient = initSelfSignedCAHttpClient(stepResult);
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(stepResult);
if (okHttpClient == null) {
return authFailedNotification(stepResult, username);
}
@@ -544,7 +437,8 @@ public abstract class ProviderApiBase extends IntentService {
intentUpdate.setAction(UPDATE_PROGRESSBAR);
intentUpdate.addCategory(Intent.CATEGORY_DEFAULT);
intentUpdate.putExtra(CURRENT_PROGRESS, progress);
- sendBroadcast(intentUpdate);
+ serviceCallback.broadcastProgress(intentUpdate);
+ //sendBroadcast(intentUpdate);
}
/**
@@ -646,10 +540,10 @@ public abstract class ProviderApiBase extends IntentService {
}
private String requestStringFromServer(String url, String request_method, String jsonString, List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) {
- Response response;
+ //Response response;
String plainResponseBody = null;
- RequestBody jsonBody = jsonString != null ? RequestBody.create(JSON, jsonString) : null;
+ /*RequestBody jsonBody = jsonString != null ? RequestBody.create(JSON, jsonString) : null;
Request.Builder requestBuilder = new Request.Builder()
.url(url)
.method(request_method, jsonBody);
@@ -662,16 +556,17 @@ public abstract class ProviderApiBase extends IntentService {
String locale = Locale.getDefault().getLanguage() + Locale.getDefault().getCountry();
requestBuilder.addHeader("Accept-Language", locale);
Request request = requestBuilder.build();
-
+*/
try {
- response = okHttpClient.newCall(request).execute();
-
- InputStream inputStream = response.body().byteStream();
- Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
- if (scanner.hasNext()) {
- plainResponseBody = scanner.next();
- }
-
+ //response = okHttpClient.newCall(request).execute();
+ //response = ProviderApiConnector.requestStringFromServer(url, request_method, jsonString, headerArgs, okHttpClient);
+ //InputStream inputStream = response.body().byteStream();
+ //Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
+ //if (scanner.hasNext()) {
+ // plainResponseBody = scanner.next();
+ //}
+
+ plainResponseBody = ProviderApiConnector.requestStringFromServer(url, request_method, jsonString, headerArgs, okHttpClient);
} catch (NullPointerException npe) {
plainResponseBody = formatErrorMessage(error_json_exception_user_message);
} catch (UnknownHostException | SocketTimeoutException e) {
@@ -742,14 +637,12 @@ public abstract class ProviderApiBase extends IntentService {
String fingerprint = provider_json.getString(Provider.CA_CERT_FINGERPRINT);
String encoding = fingerprint.split(":")[0];
String expected_fingerprint = fingerprint.split(":")[1];
- String real_fingerprint = base64toHex(Base64.encodeToString(
- MessageDigest.getInstance(encoding).digest(certificate.getEncoded()),
- Base64.DEFAULT));
+ String real_fingerprint = getFingerprintFromCertificate(certificate, encoding);
result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim());
} else
result = false;
- } catch (JSONException | NoSuchAlgorithmException | CertificateEncodingException e) {
+ } catch (JSONException | NoSuchAlgorithmException | CertificateEncodingException /*| UnsupportedEncodingException*/ e) {
result = false;
}
}
@@ -757,8 +650,11 @@ public abstract class ProviderApiBase extends IntentService {
return result;
}
+
+
protected void checkPersistedProviderUpdates() {
- String providerDomain = getProviderDomain(providerDefinition);
+ //String providerDomain = getProviderDomain(providerDefinition);
+ String providerDomain = getDomainFromMainURL(lastProviderMainUrl);
if (hasUpdatedProviderDetails(providerDomain)) {
providerCaCert = getPersistedProviderCA(providerDomain);
providerDefinition = getPersistedProviderDefinition(providerDomain);
@@ -787,7 +683,7 @@ public abstract class ProviderApiBase extends IntentService {
} catch (JSONException e) {
e.printStackTrace();
result.putBoolean(RESULT_KEY, false);
- result = setErrorResult(result, getString(R.string.warning_corrupted_provider_details), ERROR_CORRUPTED_PROVIDER_JSON.toString());
+ result = setErrorResult(result, resources.getString(R.string.warning_corrupted_provider_details), ERROR_CORRUPTED_PROVIDER_JSON.toString());
}
return result;
@@ -803,22 +699,21 @@ public abstract class ProviderApiBase extends IntentService {
X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string);
if (certificate == null) {
- return setErrorResult(result, getString(R.string.warning_corrupted_provider_cert), ERROR_INVALID_CERTIFICATE.toString());
+ return setErrorResult(result, resources.getString(R.string.warning_corrupted_provider_cert), ERROR_INVALID_CERTIFICATE.toString());
}
try {
certificate.checkValidity();
String fingerprint = getCaCertFingerprint(providerDefinition);
String encoding = fingerprint.split(":")[0];
String expected_fingerprint = fingerprint.split(":")[1];
- String real_fingerprint = base64toHex(Base64.encodeToString(
- MessageDigest.getInstance(encoding).digest(certificate.getEncoded()),
- Base64.DEFAULT));
+ String real_fingerprint = getFingerprintFromCertificate(certificate, encoding);
if (!real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim())) {
- return setErrorResult(result, getString(R.string.warning_corrupted_provider_cert), ERROR_CERTIFICATE_PINNING.toString());
+ return setErrorResult(result, resources.getString(R.string.warning_corrupted_provider_cert), ERROR_CERTIFICATE_PINNING.toString());
}
+
if (!hasApiUrlExpectedDomain(providerDefinition, mainUrl)){
- return setErrorResult(result, getString(R.string.warning_corrupted_provider_details), ERROR_CORRUPTED_PROVIDER_JSON.toString());
+ return setErrorResult(result, resources.getString(R.string.warning_corrupted_provider_details), ERROR_CORRUPTED_PROVIDER_JSON.toString());
}
if (!canConnect(cert_string, providerDefinition, result)) {
@@ -827,10 +722,12 @@ public abstract class ProviderApiBase extends IntentService {
} catch (NoSuchAlgorithmException e ) {
return setErrorResult(result, resources.getString(error_no_such_algorithm_exception_user_message), null);
} catch (ArrayIndexOutOfBoundsException e) {
- return setErrorResult(result, getString(R.string.warning_corrupted_provider_details), ERROR_CORRUPTED_PROVIDER_JSON.toString());
+ return setErrorResult(result, resources.getString(R.string.warning_corrupted_provider_details), ERROR_CORRUPTED_PROVIDER_JSON.toString());
} catch (CertificateEncodingException | CertificateNotYetValidException | CertificateExpiredException e) {
- return setErrorResult(result, getString(R.string.warning_expired_provider_cert), ERROR_INVALID_CERTIFICATE.toString());
- }
+ return setErrorResult(result, resources.getString(R.string.warning_expired_provider_cert), ERROR_INVALID_CERTIFICATE.toString());
+ } /*catch (UnsupportedEncodingException e) {
+ return setErrorResult(result, resources.getString(R.string.warning_corrupted_provider_cert), ERROR_CERTIFICATE_PINNING.toString());
+ }*/
result.putBoolean(RESULT_KEY, true);
return result;
@@ -870,13 +767,23 @@ public abstract class ProviderApiBase extends IntentService {
JSONObject errorJson = new JSONObject();
String baseUrl = getApiUrl(providerDefinition);
- OkHttpClient okHttpClient = initSelfSignedCAHttpClient(errorJson, caCert);
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(errorJson, caCert);
if (okHttpClient == null) {
result.putString(ERRORS, errorJson.toString());
return false;
}
- List<Pair<String, String>> headerArgs = getAuthorizationHeader();
+ //try {
+
+ return ProviderApiConnector.canConnect(okHttpClient, baseUrl);
+ /*} catch (RuntimeException | IOException e) {
+ e.printStackTrace();
+ }*/
+
+ //return false;
+
+
+ /*List<Pair<String, String>> headerArgs = getAuthorizationHeader();
String plain_response = requestStringFromServer(baseUrl, "GET", null, headerArgs, okHttpClient);
try {
@@ -888,7 +795,7 @@ public abstract class ProviderApiBase extends IntentService {
//eat me
}
- return true;
+ return true;*/
}
protected String getCaCertFingerprint(JSONObject providerDefinition) {
@@ -964,8 +871,13 @@ public abstract class ProviderApiBase extends IntentService {
return "";
}
- protected boolean hasUpdatedProviderDetails(String providerDomain) {
- return preferences.contains(Provider.KEY + "." + providerDomain) && preferences.contains(Provider.CA_CERT + "." + providerDomain);
+ protected boolean hasUpdatedProviderDetails(String domain) {
+ return preferences.contains(Provider.KEY + "." + domain) && preferences.contains(Provider.CA_CERT + "." + domain);
+ }
+
+ protected String getDomainFromMainURL(String mainUrl) {
+ return mainUrl.replaceFirst("http[s]?://", "").replaceFirst("/.*", "");
+
}
/**
@@ -983,6 +895,8 @@ public abstract class ProviderApiBase extends IntentService {
} catch (JSONException e) {
// TODO Auto-generated catch block
error_message = string_json_error_message;
+ } catch (NullPointerException e) {
+ //do nothing
}
return error_message;
@@ -999,7 +913,7 @@ public abstract class ProviderApiBase extends IntentService {
}
private boolean logOut() {
- OkHttpClient okHttpClient = initSelfSignedCAHttpClient(new JSONObject());
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(new JSONObject());
if (okHttpClient == null) {
return false;
}
@@ -1007,23 +921,32 @@ public abstract class ProviderApiBase extends IntentService {
String deleteUrl = providerApiUrl + "/logout";
int progress = 0;
- Request.Builder requestBuilder = new Request.Builder()
+ /* Request.Builder requestBuilder = new Request.Builder()
.url(deleteUrl)
.delete();
- Request request = requestBuilder.build();
-
- try {
- Response response = okHttpClient.newCall(request).execute();
- // v---- was already not authorized
- if (response.isSuccessful() || response.code() == 401) {
- broadcastProgress(progress++);
- LeapSRPSession.setToken("");
- }
-
- } catch (IOException e) {
- return false;
+ Request request = requestBuilder.build();*/
+
+ //try {
+
+ //Response response = okHttpClient.newCall(request).execute();
+// Response response = ProviderApiConnector.delete(okHttpClient, deleteUrl);
+// // v---- was already not authorized
+// if (response.isSuccessful() || response.code() == 401) {
+// broadcastProgress(progress++);
+// LeapSRPSession.setToken("");
+// }
+//
+// } catch (IOException | RuntimeException e) {
+// return false;
+// }
+// return true;
+
+ if (ProviderApiConnector.delete(okHttpClient, deleteUrl)) {
+ broadcastProgress(progress++);
+ LeapSRPSession.setToken("");
+ return true;
}
- return true;
+ return false;
}
//FIXME: don't save private keys in shared preferences! use the keystore
diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java
index 61349490..bd9324bb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java
@@ -23,8 +23,6 @@ import android.view.*;
import android.widget.*;
import butterknife.*;
-import se.leap.bitmaskclient.ProviderAPI;
-import se.leap.bitmaskclient.VpnFragment;
import se.leap.bitmaskclient.Provider;
import se.leap.bitmaskclient.R;