From 268a7f205fa09edc145aace8bed30f75270a801f Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Tue, 6 Feb 2018 17:02:00 +0100 Subject: 8827 - handle switch provider correctly * ProviderAPI no longer stores values in SharedPreferences * use EipCommand to start / stop EIP * update NavigationDrawer after changing provider * use Broadcasts for ProviderAPI * parse more properties from definition into Provider * ProviderApi no longer uses static variables * no more static Context in ProviderApiCommand --- .../leap/bitmaskclient/ProviderApiManagerBase.java | 339 ++++++++++----------- 1 file changed, 158 insertions(+), 181 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index cfc6e49d..2de16dfb 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -24,6 +24,7 @@ import android.os.Bundle; import android.os.ResultReceiver; import android.support.annotation.NonNull; import android.util.Base64; +import android.util.Log; import android.util.Pair; import org.json.JSONException; @@ -49,19 +50,22 @@ import java.util.List; import javax.net.ssl.SSLHandshakeException; import okhttp3.OkHttpClient; -import se.leap.bitmaskclient.userstatus.SessionDialog; -import se.leap.bitmaskclient.userstatus.User; +import se.leap.bitmaskclient.Constants.CREDENTIAL_ERRORS; import se.leap.bitmaskclient.userstatus.UserStatus; import static se.leap.bitmaskclient.ConfigHelper.getFingerprintFromCertificate; -import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOWED_REGISTERED; -import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS; +import static se.leap.bitmaskclient.Constants.BROADCAST_PROVIDER_API_EVENT; +import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE; +import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY; +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.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.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; @@ -73,17 +77,14 @@ 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.PROVIDER_API_EVENT; -import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_SET_UP; 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.PROVIDER_SET_UP; import static se.leap.bitmaskclient.ProviderAPI.RECEIVER_KEY; -import static se.leap.bitmaskclient.ProviderAPI.RESULT_CODE; -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; @@ -109,36 +110,24 @@ import static se.leap.bitmaskclient.R.string.warning_expired_provider_cert; public abstract class ProviderApiManagerBase { + private final static String TAG = ProviderApiManagerBase.class.getName(); + public interface ProviderApiServiceCallback { void broadcastEvent(Intent intent); } private ProviderApiServiceCallback serviceCallback; - protected static volatile boolean - CA_CERT_DOWNLOADED = false, - PROVIDER_JSON_DOWNLOADED = false, - EIP_SERVICE_JSON_DOWNLOADED = false; - - protected static String lastProviderMainUrl; - protected static boolean go_ahead = true; - protected static SharedPreferences preferences; - protected static String providerApiUrl; - protected static String providerCaCertFingerprint; - protected static String providerCaCert; - protected static JSONObject providerDefinition; + static boolean go_ahead = true; + protected SharedPreferences preferences; protected Resources resources; - protected OkHttpClientGenerator clientGenerator; + OkHttpClientGenerator clientGenerator; public static void stop() { go_ahead = false; } - public static String lastProviderMainUrl() { - return lastProviderMainUrl; - } - - public ProviderApiManagerBase(SharedPreferences preferences, Resources resources, OkHttpClientGenerator clientGenerator, ProviderApiServiceCallback callback) { + ProviderApiManagerBase(SharedPreferences preferences, Resources resources, OkHttpClientGenerator clientGenerator, ProviderApiServiceCallback callback) { this.preferences = preferences; this.resources = resources; this.serviceCallback = callback; @@ -150,92 +139,94 @@ public abstract class ProviderApiManagerBase { String action = command.getAction(); Bundle parameters = command.getBundleExtra(PARAMETERS); - if (providerApiUrl == null && preferences.contains(Provider.KEY)) { - try { - JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - providerApiUrl = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); - go_ahead = true; - } catch (JSONException e) { - go_ahead = false; - } + Provider provider = command.getParcelableExtra(PROVIDER_KEY); + + if (provider == null) { + Log.e(TAG, action +" called without provider!"); + return; + } + if (action == null) { + Log.e(TAG, "Intent without action sent!"); + return; } if (action.equals(UPDATE_PROVIDER_DETAILS)) { - resetProviderDetails(); + resetProviderDetails(provider); Bundle task = new Bundle(); - task.putString(MAIN_URL, lastProviderMainUrl); - Bundle result = setUpProvider(task); - if (result.getBoolean(RESULT_KEY)) { - receiver.send(PROVIDER_OK, result); + Bundle result = setUpProvider(provider, task); + if (result.getBoolean(BROADCAST_RESULT_KEY)) { + sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider); } else { - receiver.send(PROVIDER_NOK, result); + sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider); } } else if (action.equalsIgnoreCase(SET_UP_PROVIDER)) { - Bundle result = setUpProvider(parameters); + Bundle result = setUpProvider(provider, parameters); if (go_ahead) { - if (result.getBoolean(RESULT_KEY)) { - sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result); + if (result.getBoolean(BROADCAST_RESULT_KEY)) { + sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider); } else { - sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result); + sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider); } } } else if (action.equalsIgnoreCase(SIGN_UP)) { - UserStatus.updateStatus(UserStatus.SessionStatus.SIGNING_UP, resources); Bundle result = tryToRegister(parameters); - if (result.getBoolean(RESULT_KEY)) { - sendToReceiverOrBroadcast(receiver, SUCCESSFUL_SIGNUP, result); + if (result.getBoolean(BROADCAST_RESULT_KEY)) { + sendToReceiverOrBroadcast(receiver, SUCCESSFUL_SIGNUP, result, provider); } else { - sendToReceiverOrBroadcast(receiver, FAILED_SIGNUP, result); + sendToReceiverOrBroadcast(receiver, FAILED_SIGNUP, result, provider); } } else if (action.equalsIgnoreCase(LOG_IN)) { UserStatus.updateStatus(UserStatus.SessionStatus.LOGGING_IN, resources); - Bundle result = tryToAuthenticate(parameters); - if (result.getBoolean(RESULT_KEY)) { - sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGIN, result); + Bundle result = tryToAuthenticate(provider, parameters); + if (result.getBoolean(BROADCAST_RESULT_KEY)) { + sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGIN, result, provider); UserStatus.updateStatus(UserStatus.SessionStatus.LOGGED_IN, resources); } else { - sendToReceiverOrBroadcast(receiver, FAILED_LOGIN, result); + sendToReceiverOrBroadcast(receiver, FAILED_LOGIN, result, provider); UserStatus.updateStatus(UserStatus.SessionStatus.NOT_LOGGED_IN, resources); } } else if (action.equalsIgnoreCase(LOG_OUT)) { UserStatus.updateStatus(UserStatus.SessionStatus.LOGGING_OUT, resources); - if (logOut()) { - sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGOUT, Bundle.EMPTY); + if (logOut(provider)) { + sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGOUT, Bundle.EMPTY, provider); UserStatus.updateStatus(UserStatus.SessionStatus.LOGGED_OUT, resources); } else { - sendToReceiverOrBroadcast(receiver, LOGOUT_FAILED, Bundle.EMPTY); + sendToReceiverOrBroadcast(receiver, LOGOUT_FAILED, Bundle.EMPTY, provider); UserStatus.updateStatus(UserStatus.SessionStatus.DIDNT_LOG_OUT, resources); } } else if (action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)) { - if (updateVpnCertificate()) { - sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); + if (updateVpnCertificate(provider)) { + sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY, provider); } else { - sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); + sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY, provider); } } else if (action.equalsIgnoreCase(DOWNLOAD_EIP_SERVICE)) { - Bundle result = getAndSetEipServiceJson(); - if (result.getBoolean(RESULT_KEY)) { - sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_EIP_SERVICE, result); + Bundle result = getAndSetEipServiceJson(provider); + if (result.getBoolean(BROADCAST_RESULT_KEY)) { + sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_EIP_SERVICE, result, provider); } else { - sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_EIP_SERVICE, result); + sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_EIP_SERVICE, result, provider); } } else if (action.equalsIgnoreCase(PROVIDER_SET_UP)) { - if(EIP_SERVICE_JSON_DOWNLOADED && CA_CERT_DOWNLOADED && PROVIDER_JSON_DOWNLOADED ) { + if(provider.hasEIP() && provider.hasCaCert() && provider.hasDefinition()) { if(receiver!= null) { - receiver.send(PROVIDER_OK, Bundle.EMPTY); + Bundle result = new Bundle(); + result.putParcelable(PROVIDER_KEY, provider); + receiver.send(PROVIDER_OK, result); } } } } - protected void resetProviderDetails() { - CA_CERT_DOWNLOADED = PROVIDER_JSON_DOWNLOADED = false; - deleteProviderDetailsFromPreferences(providerDefinition); - providerCaCert = ""; - providerDefinition = new JSONObject(); + void resetProviderDetails(Provider provider) { + provider.setCaCert(""); + provider.define(new JSONObject()); + provider.setEipServiceJson(new JSONObject()); + + deleteProviderDetailsFromPreferences(provider.getDomain()); } - protected String formatErrorMessage(final int toastStringId) { + String formatErrorMessage(final int toastStringId) { return formatErrorMessage(resources.getString(toastStringId)); } @@ -252,7 +243,7 @@ public abstract class ProviderApiManagerBase { } } - protected void addErrorMessageToJson(JSONObject jsonObject, String errorMessage) { + private void addErrorMessageToJson(JSONObject jsonObject, String errorMessage) { try { jsonObject.put(ERRORS, errorMessage); } catch (JSONException e) { @@ -260,7 +251,7 @@ public abstract class ProviderApiManagerBase { } } - protected void addErrorMessageToJson(JSONObject jsonObject, String errorMessage, String errorId) { + private void addErrorMessageToJson(JSONObject jsonObject, String errorMessage, String errorId) { try { jsonObject.put(ERRORS, errorMessage); jsonObject.put(ERRORID, errorId); @@ -274,32 +265,37 @@ public abstract class ProviderApiManagerBase { private Bundle tryToRegister(Bundle task) { Bundle result = new Bundle(); - int progress = 0; - String username = User.userName(); - String password = task.getString(SessionDialog.PASSWORD); + String username = task.getString(CREDENTIALS_USERNAME); + String password = task.getString(CREDENTIALS_PASSWORD); + Provider provider = task.getParcelable(PROVIDER_KEY); + + if(provider == null) { + result.putBoolean(BROADCAST_RESULT_KEY, false); + Log.e(TAG, "no provider when trying to register"); + return result; + } if (validUserLoginData(username, password)) { - result = register(username, password); - broadcastProgress(progress++); + result = register(provider, username, password); } else { if (!wellFormedPassword(password)) { - result.putBoolean(RESULT_KEY, false); - result.putString(SessionDialog.USERNAME, username); - result.putBoolean(SessionDialog.ERRORS.PASSWORD_INVALID_LENGTH.toString(), true); + result.putBoolean(BROADCAST_RESULT_KEY, false); + result.putString(CREDENTIALS_USERNAME, username); + result.putBoolean(CREDENTIAL_ERRORS.PASSWORD_INVALID_LENGTH.toString(), true); } if (!validUsername(username)) { - result.putBoolean(RESULT_KEY, false); - result.putBoolean(SessionDialog.ERRORS.USERNAME_MISSING.toString(), true); + result.putBoolean(BROADCAST_RESULT_KEY, false); + result.putBoolean(CREDENTIAL_ERRORS.USERNAME_MISSING.toString(), true); } } return result; } - private Bundle register(String username, String password) { + private Bundle register(Provider provider, String username, String password) { JSONObject stepResult = null; - OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(stepResult); + OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), stepResult); if (okHttpClient == null) { return authFailedNotification(stepResult, username); } @@ -309,15 +305,15 @@ public abstract class ProviderApiManagerBase { BigInteger password_verifier = client.calculateV(username, password, salt); - JSONObject api_result = sendNewUserDataToSRPServer(providerApiUrl, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16), okHttpClient); + JSONObject api_result = sendNewUserDataToSRPServer(provider.getApiUrlString(), username, new BigInteger(1, salt).toString(16), password_verifier.toString(16), okHttpClient); Bundle result = new Bundle(); if (api_result.has(ERRORS)) result = authFailedNotification(api_result, username); else { - result.putString(SessionDialog.USERNAME, username); - result.putString(SessionDialog.PASSWORD, password); - result.putBoolean(RESULT_KEY, true); + result.putString(CREDENTIALS_USERNAME, username); + result.putString(CREDENTIALS_PASSWORD, password); + result.putBoolean(BROADCAST_RESULT_KEY, true); } return result; @@ -326,37 +322,39 @@ public abstract class ProviderApiManagerBase { /** * Starts the authentication process using SRP protocol. * - * @param task containing: username, password and api url. - * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if authentication was successful. + * @param task containing: username, password and provider + * @return a bundle with a boolean value mapped to a key named BROADCAST_RESULT_KEY, and which is true if authentication was successful. */ - private Bundle tryToAuthenticate(Bundle task) { + private Bundle tryToAuthenticate(Provider provider, Bundle task) { Bundle result = new Bundle(); - int progress = 0; - String username = User.userName(); - String password = task.getString(SessionDialog.PASSWORD); + String username = task.getString(CREDENTIALS_USERNAME); + String password = task.getString(CREDENTIALS_PASSWORD); + if (validUserLoginData(username, password)) { - result = authenticate(username, password); - broadcastProgress(progress++); + result = authenticate(provider, username, password); } else { if (!wellFormedPassword(password)) { - result.putBoolean(RESULT_KEY, false); - result.putString(SessionDialog.USERNAME, username); - result.putBoolean(SessionDialog.ERRORS.PASSWORD_INVALID_LENGTH.toString(), true); + result.putBoolean(BROADCAST_RESULT_KEY, false); + result.putString(CREDENTIALS_USERNAME, username); + result.putBoolean(CREDENTIAL_ERRORS.PASSWORD_INVALID_LENGTH.toString(), true); } if (!validUsername(username)) { - result.putBoolean(RESULT_KEY, false); - result.putBoolean(SessionDialog.ERRORS.USERNAME_MISSING.toString(), true); + result.putBoolean(BROADCAST_RESULT_KEY, false); + result.putBoolean(CREDENTIAL_ERRORS.USERNAME_MISSING.toString(), true); } } return result; } - private Bundle authenticate(String username, String password) { + private Bundle authenticate(Provider provider, String username, String password) { Bundle result = new Bundle(); JSONObject stepResult = new JSONObject(); - OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(stepResult); + + String providerApiUrl = provider.getApiUrlWithVersion(); + + OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), stepResult); if (okHttpClient == null) { return authFailedNotification(stepResult, username); } @@ -374,13 +372,13 @@ public abstract class ProviderApiManagerBase { setTokenIfAvailable(step_result); byte[] M2 = new BigInteger(step_result.getString(LeapSRPSession.M2), 16).toByteArray(); if (client.verify(M2)) { - result.putBoolean(RESULT_KEY, true); + result.putBoolean(BROADCAST_RESULT_KEY, true); } else { authFailedNotification(step_result, username); } } else { - result.putBoolean(RESULT_KEY, false); - result.putString(SessionDialog.USERNAME, username); + result.putBoolean(BROADCAST_RESULT_KEY, false); + result.putString(CREDENTIALS_USERNAME, username); result.putString(resources.getString(R.string.user_message), resources.getString(R.string.error_srp_math_error_user_message)); } } catch (JSONException e) { @@ -424,17 +422,21 @@ public abstract class ProviderApiManagerBase { } if (!username.isEmpty()) - userNotificationBundle.putString(SessionDialog.USERNAME, username); - userNotificationBundle.putBoolean(RESULT_KEY, false); + userNotificationBundle.putString(CREDENTIALS_USERNAME, username); + userNotificationBundle.putBoolean(BROADCAST_RESULT_KEY, false); return userNotificationBundle; } - void sendToReceiverOrBroadcast(ResultReceiver receiver, int resultCode, Bundle resultData) { + void sendToReceiverOrBroadcast(ResultReceiver receiver, int resultCode, Bundle resultData, Provider provider) { + if (resultData == null || resultData == Bundle.EMPTY) { + resultData = new Bundle(); + } + resultData.putParcelable(PROVIDER_KEY, provider); if (receiver != null) { receiver.send(resultCode, resultData); } else { - broadcastEvent(PROVIDER_API_EVENT, resultCode, resultData); + broadcastEvent(resultCode, resultData); } } @@ -451,11 +453,11 @@ public abstract class ProviderApiManagerBase { serviceCallback.broadcastEvent(intentUpdate); } - void broadcastEvent(String action, int resultCode , Bundle resultData) { - Intent intentUpdate = new Intent(action); + private void broadcastEvent(int resultCode , Bundle resultData) { + Intent intentUpdate = new Intent(BROADCAST_PROVIDER_API_EVENT); intentUpdate.addCategory(Intent.CATEGORY_DEFAULT); - intentUpdate.putExtra(RESULT_CODE, resultCode); - intentUpdate.putExtra(RESULT_KEY, resultData); + intentUpdate.putExtra(BROADCAST_RESULT_CODE, resultCode); + intentUpdate.putExtra(BROADCAST_RESULT_KEY, resultData); serviceCallback.broadcastEvent(intentUpdate); } @@ -624,27 +626,23 @@ public abstract class ProviderApiManagerBase { * Downloads a provider.json from a given URL, adding a new provider using the given name. * * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider, the provider name and its provider.json url. - * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if the update was successful. + * @return a bundle with a boolean value mapped to a key named BROADCAST_RESULT_KEY, and which is true if the update was successful. */ - protected abstract Bundle setUpProvider(Bundle task); + protected abstract Bundle setUpProvider(Provider provider, Bundle task); /** * Downloads the eip-service.json from a given URL, and saves eip service capabilities including the offered gateways - * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if the download was successful. + * @return a bundle with a boolean value mapped to a key named BROADCAST_RESULT_KEY, and which is true if the download was successful. */ - protected abstract Bundle getAndSetEipServiceJson(); + protected abstract Bundle getAndSetEipServiceJson(Provider provider); /** * Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate. * * @return true if certificate was downloaded correctly, false if provider.json is not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error. */ - protected abstract boolean updateVpnCertificate(); - + protected abstract boolean updateVpnCertificate(Provider provider); - protected static boolean caCertDownloaded() { - return CA_CERT_DOWNLOADED; - } protected boolean isValidJson(String jsonString) { try { @@ -658,19 +656,19 @@ public abstract class ProviderApiManagerBase { } } - protected boolean validCertificate(String cert_string) { + protected boolean validCertificate(Provider provider, String certString) { boolean result = false; - if (!ConfigHelper.checkErroneousDownload(cert_string)) { - X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string); + if (!ConfigHelper.checkErroneousDownload(certString)) { + X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certString); try { if (certificate != null) { - JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - String fingerprint = provider_json.getString(Provider.CA_CERT_FINGERPRINT); + JSONObject providerJson = provider.getDefinition(); + String fingerprint = providerJson.getString(Provider.CA_CERT_FINGERPRINT); String encoding = fingerprint.split(":")[0]; - String expected_fingerprint = fingerprint.split(":")[1]; - String real_fingerprint = getFingerprintFromCertificate(certificate, encoding); + String expectedFingerprint = fingerprint.split(":")[1]; + String realFingerprint = getFingerprintFromCertificate(certificate, encoding); - result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim()); + result = realFingerprint.trim().equalsIgnoreCase(expectedFingerprint.trim()); } else result = false; } catch (JSONException | NoSuchAlgorithmException | CertificateEncodingException e) { @@ -681,50 +679,41 @@ public abstract class ProviderApiManagerBase { return result; } - protected void checkPersistedProviderUpdates() { - String providerDomain = getDomainFromMainURL(lastProviderMainUrl); + protected void getPersistedProviderUpdates(Provider provider) { + String providerDomain = getDomainFromMainURL(provider.getMainUrlString()); if (hasUpdatedProviderDetails(providerDomain)) { - providerCaCert = getPersistedProviderCA(providerDomain); - providerDefinition = getPersistedProviderDefinition(providerDomain); - providerCaCertFingerprint = getPersistedCaCertFingerprint(providerDomain); - providerApiUrl = getApiUrlWithVersion(providerDefinition); + provider.setCaCert(getPersistedProviderCA(providerDomain)); + provider.define(getPersistedProviderDefinition(providerDomain)); + provider.setCaCertFingerprint(getPersistedCaCertFingerprint(providerDomain)); } } - protected Bundle validateProviderDetails() { - Bundle result = validateCertificateForProvider(providerCaCert, providerDefinition, lastProviderMainUrl); + Bundle validateProviderDetails(Provider provider) { + Bundle result = validateCertificateForProvider(provider); //invalid certificate or no certificate - if (result.containsKey(ERRORS) || (result.containsKey(RESULT_KEY) && !result.getBoolean(RESULT_KEY)) ) { + if (result.containsKey(ERRORS) || (result.containsKey(BROADCAST_RESULT_KEY) && !result.getBoolean(BROADCAST_RESULT_KEY)) ) { return result; } - //valid certificate: skip download, save loaded provider CA cert and provider definition directly - try { - preferences.edit().putString(Provider.KEY, providerDefinition.toString()). - putBoolean(PROVIDER_ALLOW_ANONYMOUS, providerDefinition.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOW_ANONYMOUS)). - putBoolean(PROVIDER_ALLOWED_REGISTERED, providerDefinition.getJSONObject(Provider.SERVICE).getBoolean(PROVIDER_ALLOWED_REGISTERED)). - putString(Provider.CA_CERT, providerCaCert).commit(); - CA_CERT_DOWNLOADED = true; - PROVIDER_JSON_DOWNLOADED = true; - result.putBoolean(RESULT_KEY, true); - } catch (JSONException e) { - e.printStackTrace(); - setErrorResult(result, warning_corrupted_provider_details, ERROR_CORRUPTED_PROVIDER_JSON.toString()); - } + result.putBoolean(BROADCAST_RESULT_KEY, true); return result; } - protected Bundle validateCertificateForProvider(String cert_string, JSONObject providerDefinition, String mainUrl) { + protected Bundle validateCertificateForProvider(Provider provider) { Bundle result = new Bundle(); - result.putBoolean(RESULT_KEY, false); + result.putBoolean(BROADCAST_RESULT_KEY, false); + + String caCert = provider.getCaCert(); + JSONObject providerDefinition = provider.getDefinition(); + String mainUrl = provider.getMainUrlString(); - if (ConfigHelper.checkErroneousDownload(cert_string)) { + if (ConfigHelper.checkErroneousDownload(caCert)) { return result; } - X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string); + X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(caCert); if (certificate == null) { return setErrorResult(result, warning_corrupted_provider_cert, ERROR_INVALID_CERTIFICATE.toString()); } @@ -732,9 +721,9 @@ public abstract class ProviderApiManagerBase { certificate.checkValidity(); String fingerprint = getCaCertFingerprint(providerDefinition); String encoding = fingerprint.split(":")[0]; - String expected_fingerprint = fingerprint.split(":")[1]; - String real_fingerprint = getFingerprintFromCertificate(certificate, encoding); - if (!real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim())) { + String expectedFingerprint = fingerprint.split(":")[1]; + String realFingerprint = getFingerprintFromCertificate(certificate, encoding); + if (!realFingerprint.trim().equalsIgnoreCase(expectedFingerprint.trim())) { return setErrorResult(result, warning_corrupted_provider_cert, ERROR_CERTIFICATE_PINNING.toString()); } @@ -743,7 +732,7 @@ public abstract class ProviderApiManagerBase { return setErrorResult(result, warning_corrupted_provider_details, ERROR_CORRUPTED_PROVIDER_JSON.toString()); } - if (!canConnect(cert_string, providerDefinition, result)) { + if (!canConnect(caCert, providerDefinition, result)) { return result; } } catch (NoSuchAlgorithmException e ) { @@ -754,11 +743,11 @@ public abstract class ProviderApiManagerBase { return setErrorResult(result, warning_expired_provider_cert, ERROR_INVALID_CERTIFICATE.toString()); } - result.putBoolean(RESULT_KEY, true); + result.putBoolean(BROADCAST_RESULT_KEY, true); return result; } - protected Bundle setErrorResult(Bundle result, int errorMessageId, String errorId) { + Bundle setErrorResult(Bundle result, int errorMessageId, String errorId) { JSONObject errorJson = new JSONObject(); if (errorId != null) { addErrorMessageToJson(errorJson, resources.getString(errorMessageId), errorId); @@ -766,7 +755,7 @@ public abstract class ProviderApiManagerBase { addErrorMessageToJson(errorJson, resources.getString(errorMessageId)); } result.putString(ERRORS, errorJson.toString()); - result.putBoolean(RESULT_KEY, false); + result.putBoolean(BROADCAST_RESULT_KEY, false); return result; } @@ -807,17 +796,7 @@ public abstract class ProviderApiManagerBase { return ""; } - protected String getApiUrlWithVersion(JSONObject providerDefinition) { - try { - return providerDefinition.getString(Provider.API_URL) + "/" + providerDefinition.getString(Provider.API_VERSION); - } catch (JSONException e) { - e.printStackTrace(); - } - return ""; - } - - protected void deleteProviderDetailsFromPreferences(JSONObject providerDefinition) { - String providerDomain = getProviderDomain(providerDefinition); + protected void deleteProviderDetailsFromPreferences(String providerDomain) { if (preferences.contains(Provider.KEY + "." + providerDomain)) { preferences.edit().remove(Provider.KEY + "." + providerDomain).apply(); @@ -903,17 +882,15 @@ public abstract class ProviderApiManagerBase { return headerArgs; } - private boolean logOut() { - OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(new JSONObject()); + private boolean logOut(Provider provider) { + OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(provider.getCaCert(), new JSONObject()); if (okHttpClient == null) { return false; } - String deleteUrl = providerApiUrl + "/logout"; - int progress = 0; + String deleteUrl = provider.getApiUrlString() + "/logout"; if (ProviderApiConnector.delete(okHttpClient, deleteUrl)) { - broadcastProgress(progress++); LeapSRPSession.setToken(""); return true; } -- cgit v1.2.3 From 8f7f89e757f0ac8f7a2da54d2001bb2ff88269cc Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Thu, 8 Feb 2018 14:34:20 +0100 Subject: 8827 - fix tests --- .../se/leap/bitmaskclient/ProviderApiManagerBase.java | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index 7e4acf44..000dd164 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -432,19 +432,6 @@ public abstract class ProviderApiManagerBase { } } - /** - * Sets up an intent with the progress value passed as a parameter - * and sends it as a broadcast. - * - * @param progress - */ - void broadcastProgress(int progress) { - Intent intentUpdate = new Intent(UPDATE_PROGRESSBAR); - intentUpdate.addCategory(Intent.CATEGORY_DEFAULT); - intentUpdate.putExtra(CURRENT_PROGRESS, progress); - serviceCallback.broadcastEvent(intentUpdate); - } - private void broadcastEvent(int resultCode , Bundle resultData) { Intent intentUpdate = new Intent(BROADCAST_PROVIDER_API_EVENT); intentUpdate.addCategory(Intent.CATEGORY_DEFAULT); @@ -617,7 +604,7 @@ public abstract class ProviderApiManagerBase { /** * Downloads a provider.json from a given URL, adding a new provider using the given name. * - * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider, the provider name and its provider.json url. + * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider * @return a bundle with a boolean value mapped to a key named BROADCAST_RESULT_KEY, and which is true if the update was successful. */ protected abstract Bundle setUpProvider(Provider provider, Bundle task); -- cgit v1.2.3 From 9e6fe0e215e32343b38cdf20080de209a31287dd Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Fri, 9 Feb 2018 12:46:06 +0100 Subject: 8827 - merge request discussions * add NullPointer checks to EipFragment * add Provider to DownloadFailedDialog * remove unused code * store certificates for pinning in SharedPreferences --- app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index 000dd164..6b6aa89d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -66,7 +66,6 @@ import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_C import static se.leap.bitmaskclient.DownloadFailedDialog.DOWNLOAD_ERRORS.ERROR_INVALID_CERTIFICATE; 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; @@ -572,7 +571,7 @@ public abstract class ProviderApiManagerBase { JSONObject errorJson = new JSONObject(); String baseUrl = getApiUrl(providerDefinition); - OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(errorJson, caCert); + OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(caCert, errorJson); if (okHttpClient == null) { result.putString(ERRORS, errorJson.toString()); return false; @@ -706,7 +705,6 @@ public abstract class ProviderApiManagerBase { return setErrorResult(result, warning_corrupted_provider_cert, ERROR_CERTIFICATE_PINNING.toString()); } - if (!hasApiUrlExpectedDomain(providerDefinition, mainUrl)){ return setErrorResult(result, warning_corrupted_provider_details, ERROR_CORRUPTED_PROVIDER_JSON.toString()); } -- cgit v1.2.3 From 9f6e74680e5cfe6507bd1e37ea217cf2887af3cc Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Fri, 9 Feb 2018 14:33:20 +0100 Subject: 8827 - resolve discussions * remove stop for providerApi * enable retrySetUpProvider * renamed PROVIDER_KEY for EIP_JSON to PROVIDER_EIP_DEFINITION --- .../se/leap/bitmaskclient/ProviderApiManagerBase.java | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index 6b6aa89d..f1c0ecef 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -115,15 +115,10 @@ public abstract class ProviderApiManagerBase { private ProviderApiServiceCallback serviceCallback; - static boolean go_ahead = true; protected SharedPreferences preferences; protected Resources resources; OkHttpClientGenerator clientGenerator; - public static void stop() { - go_ahead = false; - } - ProviderApiManagerBase(SharedPreferences preferences, Resources resources, OkHttpClientGenerator clientGenerator, ProviderApiServiceCallback callback) { this.preferences = preferences; this.resources = resources; @@ -158,12 +153,10 @@ public abstract class ProviderApiManagerBase { } } else if (action.equalsIgnoreCase(SET_UP_PROVIDER)) { Bundle result = setUpProvider(provider, parameters); - if (go_ahead) { - if (result.getBoolean(BROADCAST_RESULT_KEY)) { - sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider); - } else { - sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider); - } + if (result.getBoolean(BROADCAST_RESULT_KEY)) { + sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider); + } else { + sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider); } } else if (action.equalsIgnoreCase(SIGN_UP)) { Bundle result = tryToRegister(parameters); -- cgit v1.2.3 From 7f84522ce01e8bcf1b3063ff7fa19a9a7dca61ea Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Fri, 9 Feb 2018 18:29:51 +0100 Subject: 8827 - resolve discussions * use LocalBroadcastManager for broadcasts * add NullPointer checks to EipFragment * store VpnCertificate & private key in Provider not preferences * EipFragment uses provider instead of reading from preferences * use switch in ProviderApiManager --- .../leap/bitmaskclient/ProviderApiManagerBase.java | 144 +++++++++++---------- 1 file changed, 76 insertions(+), 68 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index f1c0ecef..a9321a9c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -142,63 +142,72 @@ public abstract class ProviderApiManagerBase { return; } - if (action.equals(UPDATE_PROVIDER_DETAILS)) { - resetProviderDetails(provider); - Bundle task = new Bundle(); - Bundle result = setUpProvider(provider, task); - if (result.getBoolean(BROADCAST_RESULT_KEY)) { - sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider); - } else { - sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider); - } - } else if (action.equalsIgnoreCase(SET_UP_PROVIDER)) { - Bundle result = setUpProvider(provider, parameters); - if (result.getBoolean(BROADCAST_RESULT_KEY)) { - sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider); - } else { - sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider); - } - } else if (action.equalsIgnoreCase(SIGN_UP)) { - Bundle result = tryToRegister(parameters); - if (result.getBoolean(BROADCAST_RESULT_KEY)) { - sendToReceiverOrBroadcast(receiver, SUCCESSFUL_SIGNUP, result, provider); - } else { - sendToReceiverOrBroadcast(receiver, FAILED_SIGNUP, result, provider); - } - } else if (action.equalsIgnoreCase(LOG_IN)) { - Bundle result = tryToAuthenticate(provider, parameters); - if (result.getBoolean(BROADCAST_RESULT_KEY)) { - sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGIN, result, provider); - } else { - sendToReceiverOrBroadcast(receiver, FAILED_LOGIN, result, provider); - } - } else if (action.equalsIgnoreCase(LOG_OUT)) { - if (logOut(provider)) { - sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGOUT, Bundle.EMPTY, provider); - } else { - sendToReceiverOrBroadcast(receiver, LOGOUT_FAILED, Bundle.EMPTY, provider); - } - } else if (action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)) { - if (updateVpnCertificate(provider)) { - sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY, provider); - } else { - sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY, provider); - } - } else if (action.equalsIgnoreCase(DOWNLOAD_EIP_SERVICE)) { - Bundle result = getAndSetEipServiceJson(provider); - if (result.getBoolean(BROADCAST_RESULT_KEY)) { - sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_EIP_SERVICE, result, provider); - } else { - sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_EIP_SERVICE, result, provider); - } - } else if (action.equalsIgnoreCase(PROVIDER_SET_UP)) { - if(provider.hasEIP() && provider.hasCaCert() && provider.hasDefinition()) { - if(receiver!= null) { - Bundle result = new Bundle(); - result.putParcelable(PROVIDER_KEY, provider); - receiver.send(PROVIDER_OK, result); + Bundle result = new Bundle(); + switch (action) { + case UPDATE_PROVIDER_DETAILS: + resetProviderDetails(provider); + Bundle task = new Bundle(); + result = setUpProvider(provider, task); + if (result.getBoolean(BROADCAST_RESULT_KEY)) { + sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider); + } else { + sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider); } - } + break; + case SET_UP_PROVIDER: + result = setUpProvider(provider, parameters); + if (result.getBoolean(BROADCAST_RESULT_KEY)) { + sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider); + } else { + sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider); + } + break; + case SIGN_UP: + result = tryToRegister(parameters); + if (result.getBoolean(BROADCAST_RESULT_KEY)) { + sendToReceiverOrBroadcast(receiver, SUCCESSFUL_SIGNUP, result, provider); + } else { + sendToReceiverOrBroadcast(receiver, FAILED_SIGNUP, result, provider); + } + break; + case LOG_IN: + result = tryToAuthenticate(provider, parameters); + if (result.getBoolean(BROADCAST_RESULT_KEY)) { + sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGIN, result, provider); + } else { + sendToReceiverOrBroadcast(receiver, FAILED_LOGIN, result, provider); + } + break; + case LOG_OUT: + if (logOut(provider)) { + sendToReceiverOrBroadcast(receiver, SUCCESSFUL_LOGOUT, Bundle.EMPTY, provider); + } else { + sendToReceiverOrBroadcast(receiver, LOGOUT_FAILED, Bundle.EMPTY, provider); + } + break; + case DOWNLOAD_CERTIFICATE: + if (updateVpnCertificate(provider)) { + sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY, provider); + } else { + sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY, provider); + } + break; + case DOWNLOAD_EIP_SERVICE: + result = getAndSetEipServiceJson(provider); + if (result.getBoolean(BROADCAST_RESULT_KEY)) { + sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_EIP_SERVICE, result, provider); + } else { + sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_EIP_SERVICE, result, provider); + } + break; + case PROVIDER_SET_UP: + if(provider.hasEIP() && provider.hasCaCert() && provider.hasDefinition()) { + if(receiver!= null) { + result.putParcelable(PROVIDER_KEY, provider); + receiver.send(PROVIDER_OK, result); + } + } + break; } } @@ -824,22 +833,22 @@ public abstract class ProviderApiManagerBase { * Interprets the error message as a JSON object and extract the "errors" keyword pair. * If the error message is not a JSON object, then it is returned untouched. * - * @param string_json_error_message + * @param stringJsonErrorMessage * @return final error message */ - protected String pickErrorMessage(String string_json_error_message) { - String error_message = ""; + protected String pickErrorMessage(String stringJsonErrorMessage) { + String errorMessage = ""; try { - JSONObject json_error_message = new JSONObject(string_json_error_message); - error_message = json_error_message.getString(ERRORS); + JSONObject jsonErrorMessage = new JSONObject(stringJsonErrorMessage); + errorMessage = jsonErrorMessage.getString(ERRORS); } catch (JSONException e) { // TODO Auto-generated catch block - error_message = string_json_error_message; + errorMessage = stringJsonErrorMessage; } catch (NullPointerException e) { //do nothing } - return error_message; + return errorMessage; } @NonNull @@ -867,8 +876,7 @@ public abstract class ProviderApiManagerBase { return false; } - //FIXME: don't save private keys in shared preferences! use the keystore - protected boolean loadCertificate(String cert_string) { + protected boolean loadCertificate(Provider provider, String cert_string) { if (cert_string == null) { return false; } @@ -887,13 +895,13 @@ public abstract class ProviderApiManagerBase { RSAPrivateKey key = ConfigHelper.parseRsaKeyFromString(keyString); keyString = Base64.encodeToString(key.getEncoded(), Base64.DEFAULT); - preferences.edit().putString(PROVIDER_PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n" + keyString + "-----END RSA PRIVATE KEY-----").commit(); + provider.setPrivateKey( "-----BEGIN RSA PRIVATE KEY-----\n" + keyString + "-----END RSA PRIVATE KEY-----"); X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificateString); certificateString = Base64.encodeToString(certificate.getEncoded(), Base64.DEFAULT); - preferences.edit().putString(PROVIDER_VPN_CERTIFICATE, "-----BEGIN CERTIFICATE-----\n" + certificateString + "-----END CERTIFICATE-----").commit(); + provider.setVpnCertificate( "-----BEGIN CERTIFICATE-----\n" + certificateString + "-----END CERTIFICATE-----"); return true; - } catch (CertificateException e) { + } catch (CertificateException | NullPointerException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; -- cgit v1.2.3 From ca82cdf77ee4d30b820a1f936315c6c5be78359d Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Sun, 11 Feb 2018 13:25:24 +0100 Subject: 8827 - discussion * validate urls before changing anything in Provider.define() * save private key and vpn cert after login/signup --- .../leap/bitmaskclient/ProviderApiManagerBase.java | 29 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index a9321a9c..5fe6ed05 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -87,7 +87,6 @@ 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; @@ -665,6 +664,8 @@ public abstract class ProviderApiManagerBase { provider.setCaCert(getPersistedProviderCA(providerDomain)); provider.define(getPersistedProviderDefinition(providerDomain)); provider.setCaCertFingerprint(getPersistedCaCertFingerprint(providerDomain)); + provider.setPrivateKey(getPersistedPrivateKey(providerDomain)); + provider.setVpnCertificate(getPersistedVPNCertificate(providerDomain)); } } @@ -707,10 +708,6 @@ public abstract class ProviderApiManagerBase { return setErrorResult(result, warning_corrupted_provider_cert, ERROR_CERTIFICATE_PINNING.toString()); } - if (!hasApiUrlExpectedDomain(providerDefinition, mainUrl)){ - return setErrorResult(result, warning_corrupted_provider_details, ERROR_CORRUPTED_PROVIDER_JSON.toString()); - } - if (!canConnect(caCert, providerDefinition, result)) { return result; } @@ -797,6 +794,24 @@ public abstract class ProviderApiManagerBase { return ""; } + protected String getPersistedPrivateKey(String providerDomain) { + try { + return getPersistedProviderDefinition(providerDomain).getString(PROVIDER_PRIVATE_KEY); + } catch (JSONException e) { + e.printStackTrace(); + } + return ""; + } + + protected String getPersistedVPNCertificate(String providerDomain) { + try { + return getPersistedProviderDefinition(providerDomain).getString(PROVIDER_VPN_CERTIFICATE); + } catch (JSONException e) { + e.printStackTrace(); + } + return ""; + } + protected JSONObject getPersistedProviderDefinition(String providerDomain) { try { return new JSONObject(preferences.getString(Provider.KEY + "." + providerDomain, "")); @@ -806,6 +821,10 @@ public abstract class ProviderApiManagerBase { } } + protected String getFromPersistedProvider(String toFetch, String providerDomain) { + return preferences.getString(toFetch + "." + providerDomain, ""); + } + protected String getPersistedProviderCA(String providerDomain) { return preferences.getString(Provider.CA_CERT + "." + providerDomain, ""); } -- cgit v1.2.3 From 1b97d5dfc596763c03d584d089a1e00edd1eecbc Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Sun, 11 Feb 2018 14:39:27 +0100 Subject: 8827 - merge request discussions * add deleteProviderDetailsFromPreferences to ConfigHelper * validate every field in Provider.equals * add reset() method to Provider --- .../leap/bitmaskclient/ProviderApiManagerBase.java | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index 5fe6ed05..1284ca64 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -211,11 +211,8 @@ public abstract class ProviderApiManagerBase { } void resetProviderDetails(Provider provider) { - provider.setCaCert(""); - provider.define(new JSONObject()); - provider.setEipServiceJson(new JSONObject()); - - deleteProviderDetailsFromPreferences(provider.getDomain()); + provider.reset(); + ConfigHelper.deleteProviderDetailsFromPreferences(preferences, provider.getDomain()); } String formatErrorMessage(final int toastStringId) { @@ -772,19 +769,6 @@ public abstract class ProviderApiManagerBase { return ""; } - protected void deleteProviderDetailsFromPreferences(String providerDomain) { - - if (preferences.contains(Provider.KEY + "." + providerDomain)) { - preferences.edit().remove(Provider.KEY + "." + providerDomain).apply(); - } - if (preferences.contains(Provider.CA_CERT + "." + providerDomain)) { - preferences.edit().remove(Provider.CA_CERT + "." + providerDomain).apply(); - } - if (preferences.contains(Provider.CA_CERT_FINGERPRINT + "." + providerDomain)) { - preferences.edit().remove(Provider.CA_CERT_FINGERPRINT + "." + providerDomain).apply(); - } - } - protected String getPersistedCaCertFingerprint(String providerDomain) { try { return getPersistedProviderDefinition(providerDomain).getString(Provider.CA_CERT_FINGERPRINT); -- cgit v1.2.3 From fde2fbd9de3b014bd77a517b2cb7faf7beb4a560 Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Sun, 11 Feb 2018 15:11:32 +0100 Subject: 8827 - refactoring * remove unused functions * refactor reading stored credentials from preferences --- .../leap/bitmaskclient/ProviderApiManagerBase.java | 57 ++-------------------- 1 file changed, 4 insertions(+), 53 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index 1284ca64..09e0faa8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -685,7 +685,6 @@ public abstract class ProviderApiManagerBase { String caCert = provider.getCaCert(); JSONObject providerDefinition = provider.getDefinition(); - String mainUrl = provider.getMainUrlString(); if (ConfigHelper.checkErroneousDownload(caCert)) { return result; @@ -732,25 +731,6 @@ public abstract class ProviderApiManagerBase { return result; } - /** - * This method aims to prevent attacks where the provider.json file got manipulated by a third party. - * The main url is visible to the provider when setting up a new provider. - * The user is responsible to check that this is the provider main url he intends to connect to. - * - * @param providerDefinition - * @param mainUrlString - * @return - */ - private boolean hasApiUrlExpectedDomain(JSONObject providerDefinition, String mainUrlString) { - // fix against "api_uri": "https://calyx.net.malicious.url.net:4430", - String apiUrlString = getApiUrl(providerDefinition); - String providerDomain = getProviderDomain(providerDefinition); - if (mainUrlString.contains(providerDomain) && apiUrlString.contains(providerDomain + ":")) { - return true; - } - return false; - } - protected String getCaCertFingerprint(JSONObject providerDefinition) { try { return providerDefinition.getString(Provider.CA_CERT_FINGERPRINT); @@ -770,59 +750,30 @@ public abstract class ProviderApiManagerBase { } protected String getPersistedCaCertFingerprint(String providerDomain) { - try { - return getPersistedProviderDefinition(providerDomain).getString(Provider.CA_CERT_FINGERPRINT); - } catch (JSONException e) { - e.printStackTrace(); - } - return ""; + return ConfigHelper.getFromPersistedProvider(Provider.CA_CERT_FINGERPRINT, providerDomain, preferences); } protected String getPersistedPrivateKey(String providerDomain) { - try { - return getPersistedProviderDefinition(providerDomain).getString(PROVIDER_PRIVATE_KEY); - } catch (JSONException e) { - e.printStackTrace(); - } - return ""; + return ConfigHelper.getFromPersistedProvider(PROVIDER_PRIVATE_KEY, providerDomain, preferences); } protected String getPersistedVPNCertificate(String providerDomain) { - try { - return getPersistedProviderDefinition(providerDomain).getString(PROVIDER_VPN_CERTIFICATE); - } catch (JSONException e) { - e.printStackTrace(); - } - return ""; + return ConfigHelper.getFromPersistedProvider(PROVIDER_VPN_CERTIFICATE, providerDomain, preferences); } protected JSONObject getPersistedProviderDefinition(String providerDomain) { try { - return new JSONObject(preferences.getString(Provider.KEY + "." + providerDomain, "")); + return new JSONObject(ConfigHelper.getFromPersistedProvider(Provider.KEY, providerDomain, preferences)); } catch (JSONException e) { e.printStackTrace(); return new JSONObject(); } } - protected String getFromPersistedProvider(String toFetch, String providerDomain) { - return preferences.getString(toFetch + "." + providerDomain, ""); - } - protected String getPersistedProviderCA(String providerDomain) { return preferences.getString(Provider.CA_CERT + "." + providerDomain, ""); } - protected String getProviderDomain(JSONObject providerDefinition) { - try { - return providerDefinition.getString(Provider.DOMAIN); - } catch (JSONException e) { - e.printStackTrace(); - } - - return ""; - } - protected boolean hasUpdatedProviderDetails(String domain) { return preferences.contains(Provider.KEY + "." + domain) && preferences.contains(Provider.CA_CERT + "." + domain); } -- cgit v1.2.3 From e9d3260f6439c4b00c6708658d6edd61a246ea67 Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Mon, 12 Feb 2018 13:31:13 +0100 Subject: 8827 - fix equals for Provider --- app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java | 1 - 1 file changed, 1 deletion(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index 09e0faa8..f4fee635 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -660,7 +660,6 @@ public abstract class ProviderApiManagerBase { if (hasUpdatedProviderDetails(providerDomain)) { provider.setCaCert(getPersistedProviderCA(providerDomain)); provider.define(getPersistedProviderDefinition(providerDomain)); - provider.setCaCertFingerprint(getPersistedCaCertFingerprint(providerDomain)); provider.setPrivateKey(getPersistedPrivateKey(providerDomain)); provider.setVpnCertificate(getPersistedVPNCertificate(providerDomain)); } -- cgit v1.2.3 From 24788afa45ff46616b41626e7607d4461ab77387 Mon Sep 17 00:00:00 2001 From: Fup Duck Date: Mon, 12 Feb 2018 13:35:16 +0100 Subject: 8827 - remove caCertificate from Provider It's already represented by CertificatePin & CertificatePinEncoding --- .../leap/bitmaskclient/ProviderApiManagerBase.java | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index f4fee635..505ee55b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -683,7 +683,6 @@ public abstract class ProviderApiManagerBase { result.putBoolean(BROADCAST_RESULT_KEY, false); String caCert = provider.getCaCert(); - JSONObject providerDefinition = provider.getDefinition(); if (ConfigHelper.checkErroneousDownload(caCert)) { return result; @@ -695,15 +694,15 @@ public abstract class ProviderApiManagerBase { } try { certificate.checkValidity(); - String fingerprint = getCaCertFingerprint(providerDefinition); - String encoding = fingerprint.split(":")[0]; - String expectedFingerprint = fingerprint.split(":")[1]; + String encoding = provider.getCertificatePinEncoding(); + String expectedFingerprint = provider.getCertificatePin(); + String realFingerprint = getFingerprintFromCertificate(certificate, encoding); if (!realFingerprint.trim().equalsIgnoreCase(expectedFingerprint.trim())) { return setErrorResult(result, warning_corrupted_provider_cert, ERROR_CERTIFICATE_PINNING.toString()); } - if (!canConnect(caCert, providerDefinition, result)) { + if (!canConnect(caCert, provider.getDefinition(), result)) { return result; } } catch (NoSuchAlgorithmException e ) { @@ -730,15 +729,6 @@ public abstract class ProviderApiManagerBase { return result; } - protected String getCaCertFingerprint(JSONObject providerDefinition) { - try { - return providerDefinition.getString(Provider.CA_CERT_FINGERPRINT); - } catch (JSONException e) { - e.printStackTrace(); - } - return ""; - } - protected String getApiUrl(JSONObject providerDefinition) { try { return providerDefinition.getString(Provider.API_URL); @@ -748,10 +738,6 @@ public abstract class ProviderApiManagerBase { return ""; } - protected String getPersistedCaCertFingerprint(String providerDomain) { - return ConfigHelper.getFromPersistedProvider(Provider.CA_CERT_FINGERPRINT, providerDomain, preferences); - } - protected String getPersistedPrivateKey(String providerDomain) { return ConfigHelper.getFromPersistedProvider(PROVIDER_PRIVATE_KEY, providerDomain, preferences); } -- cgit v1.2.3