summaryrefslogtreecommitdiff
path: root/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java3
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java25
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderApiConnector.java18
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java159
-rw-r--r--app/src/main/res/values/strings.xml2
5 files changed, 74 insertions, 133 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java b/app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java
index c26184bb..63453ac3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/BaseConfigurationWizard.java
@@ -409,8 +409,6 @@ public abstract class BaseConfigurationWizard extends Activity
}
-
-
/**
* Once selected a provider, this fragment offers the user to log in,
* use it anonymously (if possible)
@@ -430,7 +428,6 @@ public abstract class BaseConfigurationWizard extends Activity
}
}
-
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu);
diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
index 54bcc1f4..0e861059 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
@@ -47,7 +47,7 @@ import java.security.spec.PKCS8EncodedKeySpec;
import static android.R.attr.name;
/**
- * Stores constants, and implements auxiliary methods used across all LEAP Android classes.
+ * Stores constants, and implements auxiliary methods used across all Bitmask Android classes.
*
* @author parmegv
* @author MeanderingCode
@@ -172,25 +172,30 @@ public class ConfigHelper {
return key;
}
- public static String base64toHex(String base64_input) {
- byte[] byteArray = Base64.decode(base64_input);
- int readBytes = byteArray.length;
+ private static String byteArrayToHex(byte[] input) {
+ int readBytes = input.length;
StringBuffer hexData = new StringBuffer();
int onebyte;
for (int i = 0; i < readBytes; i++) {
- onebyte = ((0x000000ff & byteArray[i]) | 0xffffff00);
+ onebyte = ((0x000000ff & input[i]) | 0xffffff00);
hexData.append(Integer.toHexString(onebyte).substring(6));
}
return hexData.toString();
}
+ /**
+ * Calculates the hexadecimal representation of a sha256/sha1 fingerprint of a certificate
+ *
+ * @param certificate
+ * @param encoding
+ * @return
+ * @throws NoSuchAlgorithmException
+ * @throws CertificateEncodingException
+ */
@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));
+ byte[] byteArray = MessageDigest.getInstance(encoding).digest(certificate.getEncoded());
+ return byteArrayToHex(byteArray);
}
/**
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiConnector.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiConnector.java
index 9aad14d5..439fb5e2 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiConnector.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiConnector.java
@@ -60,18 +60,14 @@ public class ProviderApiConnector {
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();
+ public static boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
+ 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;
- }
+ Response response = okHttpClient.newCall(request).execute();
+ return response.isSuccessful();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
index 396d642b..cc005fcd 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java
@@ -30,7 +30,6 @@ import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
-import java.io.InputStream;
import java.math.BigInteger;
import java.net.ConnectException;
import java.net.MalformedURLException;
@@ -46,16 +45,10 @@ import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
-import java.util.Scanner;
import javax.net.ssl.SSLHandshakeException;
-import okhttp3.MediaType;
import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.RequestBody;
-import okhttp3.Response;
import se.leap.bitmaskclient.userstatus.SessionDialog;
import se.leap.bitmaskclient.userstatus.User;
import se.leap.bitmaskclient.userstatus.UserStatus;
@@ -96,9 +89,11 @@ 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.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;
+import static se.leap.bitmaskclient.R.string.warning_corrupted_provider_cert;
+import static se.leap.bitmaskclient.R.string.warning_corrupted_provider_details;
+import static se.leap.bitmaskclient.R.string.warning_expired_provider_cert;
/**
* Implements the logic of the http api calls. The methods of this class needs to be called from
@@ -136,10 +131,6 @@ public abstract class ProviderApiManagerBase {
return lastProviderMainUrl;
}
-
- private final MediaType JSON
- = MediaType.parse("application/json; charset=utf-8");
-
public ProviderApiManagerBase(SharedPreferences preferences, Resources resources, OkHttpClientGenerator clientGenerator, ProviderApiServiceCallback callback) {
this.preferences = preferences;
this.resources = resources;
@@ -390,7 +381,7 @@ public abstract class ProviderApiManagerBase {
private boolean setTokenIfAvailable(JSONObject authentication_step_result) {
try {
LeapSRPSession.setToken(authentication_step_result.getString(LeapSRPSession.TOKEN));
- } catch (JSONException e) { //
+ } catch (JSONException e) {
return false;
}
return true;
@@ -540,33 +531,12 @@ public abstract class ProviderApiManagerBase {
}
private String requestStringFromServer(String url, String request_method, String jsonString, List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) {
- //Response response;
String plainResponseBody = null;
- /*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();
-*/
try {
- //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) {
@@ -589,6 +559,39 @@ public abstract class ProviderApiManagerBase {
return plainResponseBody;
}
+ private boolean canConnect(String caCert, JSONObject providerDefinition, Bundle result) {
+ JSONObject errorJson = new JSONObject();
+ String baseUrl = getApiUrl(providerDefinition);
+
+ OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(errorJson, caCert);
+ if (okHttpClient == null) {
+ result.putString(ERRORS, errorJson.toString());
+ return false;
+ }
+
+ try {
+
+ return ProviderApiConnector.canConnect(okHttpClient, baseUrl);
+
+ } catch (UnknownHostException | SocketTimeoutException e) {
+ setErrorResult(result, server_unreachable_message, null);
+ } catch (MalformedURLException e) {
+ setErrorResult(result, malformed_url, null);
+ } catch (SSLHandshakeException e) {
+ setErrorResult(result, warning_corrupted_provider_cert, ERROR_INVALID_CERTIFICATE.toString());
+ } catch (ConnectException e) {
+ setErrorResult(result, service_is_down_error, null);
+ } catch (IllegalArgumentException e) {
+ setErrorResult(result, error_no_such_algorithm_exception_user_message, null);
+ } catch (UnknownServiceException e) {
+ //unable to find acceptable protocols - tlsv1.2 not enabled?
+ setErrorResult(result, error_no_such_algorithm_exception_user_message, null);
+ } catch (IOException e) {
+ setErrorResult(result, error_io_exception_user_message, null);
+ }
+ return false;
+ }
+
/**
* Downloads a provider.json from a given URL, adding a new provider using the given name.
*
@@ -642,7 +645,7 @@ public abstract class ProviderApiManagerBase {
result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim());
} else
result = false;
- } catch (JSONException | NoSuchAlgorithmException | CertificateEncodingException /*| UnsupportedEncodingException*/ e) {
+ } catch (JSONException | NoSuchAlgorithmException | CertificateEncodingException e) {
result = false;
}
}
@@ -650,10 +653,7 @@ public abstract class ProviderApiManagerBase {
return result;
}
-
-
protected void checkPersistedProviderUpdates() {
- //String providerDomain = getProviderDomain(providerDefinition);
String providerDomain = getDomainFromMainURL(lastProviderMainUrl);
if (hasUpdatedProviderDetails(providerDomain)) {
providerCaCert = getPersistedProviderCA(providerDomain);
@@ -682,8 +682,7 @@ public abstract class ProviderApiManagerBase {
result.putBoolean(RESULT_KEY, true);
} catch (JSONException e) {
e.printStackTrace();
- result.putBoolean(RESULT_KEY, false);
- result = setErrorResult(result, resources.getString(R.string.warning_corrupted_provider_details), ERROR_CORRUPTED_PROVIDER_JSON.toString());
+ setErrorResult(result, warning_corrupted_provider_details, ERROR_CORRUPTED_PROVIDER_JSON.toString());
}
return result;
@@ -699,7 +698,7 @@ public abstract class ProviderApiManagerBase {
X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string);
if (certificate == null) {
- return setErrorResult(result, resources.getString(R.string.warning_corrupted_provider_cert), ERROR_INVALID_CERTIFICATE.toString());
+ return setErrorResult(result, warning_corrupted_provider_cert, ERROR_INVALID_CERTIFICATE.toString());
}
try {
certificate.checkValidity();
@@ -708,39 +707,38 @@ public abstract class ProviderApiManagerBase {
String expected_fingerprint = fingerprint.split(":")[1];
String real_fingerprint = getFingerprintFromCertificate(certificate, encoding);
if (!real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim())) {
- return setErrorResult(result, resources.getString(R.string.warning_corrupted_provider_cert), ERROR_CERTIFICATE_PINNING.toString());
+ return setErrorResult(result, warning_corrupted_provider_cert, ERROR_CERTIFICATE_PINNING.toString());
}
if (!hasApiUrlExpectedDomain(providerDefinition, mainUrl)){
- return setErrorResult(result, resources.getString(R.string.warning_corrupted_provider_details), ERROR_CORRUPTED_PROVIDER_JSON.toString());
+ return setErrorResult(result, warning_corrupted_provider_details, ERROR_CORRUPTED_PROVIDER_JSON.toString());
}
if (!canConnect(cert_string, providerDefinition, result)) {
return result;
}
} catch (NoSuchAlgorithmException e ) {
- return setErrorResult(result, resources.getString(error_no_such_algorithm_exception_user_message), null);
+ return setErrorResult(result, error_no_such_algorithm_exception_user_message, null);
} catch (ArrayIndexOutOfBoundsException e) {
- return setErrorResult(result, resources.getString(R.string.warning_corrupted_provider_details), ERROR_CORRUPTED_PROVIDER_JSON.toString());
+ return setErrorResult(result, warning_corrupted_provider_details, ERROR_CORRUPTED_PROVIDER_JSON.toString());
} catch (CertificateEncodingException | CertificateNotYetValidException | CertificateExpiredException e) {
- 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());
- }*/
+ return setErrorResult(result, warning_expired_provider_cert, ERROR_INVALID_CERTIFICATE.toString());
+ }
result.putBoolean(RESULT_KEY, true);
return result;
}
- protected Bundle setErrorResult(Bundle result, String errorMessage, String errorId) {
+ protected Bundle setErrorResult(Bundle result, int errorMessageId, String errorId) {
JSONObject errorJson = new JSONObject();
if (errorId != null) {
- addErrorMessageToJson(errorJson, errorMessage, errorId);
+ addErrorMessageToJson(errorJson, resources.getString(errorMessageId), errorId);
} else {
- addErrorMessageToJson(errorJson, errorMessage);
+ addErrorMessageToJson(errorJson, resources.getString(errorMessageId));
}
result.putString(ERRORS, errorJson.toString());
+ result.putBoolean(RESULT_KEY, false);
return result;
}
@@ -763,41 +761,6 @@ public abstract class ProviderApiManagerBase {
return false;
}
- private boolean canConnect(String caCert, JSONObject providerDefinition, Bundle result) {
- JSONObject errorJson = new JSONObject();
- String baseUrl = getApiUrl(providerDefinition);
-
- OkHttpClient okHttpClient = clientGenerator.initSelfSignedCAHttpClient(errorJson, caCert);
- if (okHttpClient == null) {
- result.putString(ERRORS, errorJson.toString());
- return false;
- }
-
- //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 {
- if (new JSONObject(plain_response).has(ERRORS)) {
- result.putString(ERRORS, plain_response);
- return false;
- }
- } catch (JSONException e) {
- //eat me
- }
-
- return true;*/
- }
-
protected String getCaCertFingerprint(JSONObject providerDefinition) {
try {
return providerDefinition.getString(Provider.CA_CERT_FINGERPRINT);
@@ -921,26 +884,6 @@ public abstract class ProviderApiManagerBase {
String deleteUrl = providerApiUrl + "/logout";
int progress = 0;
- /* Request.Builder requestBuilder = new Request.Builder()
- .url(deleteUrl)
- .delete();
- 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("");
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 680f92e1..f59acd3d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -85,6 +85,6 @@
<string name="update_provider_details">Update provider details</string>
<string name="update_certificate">Update certificate</string>
<string name="warning_corrupted_provider_details">Stored provider details are corrupted. You can either update Bitmask (recommended) or update the provider details using a commercial CA certificate.</string>
- <string name="warning_corrupted_provider_cert">Stored provider certificate is corrupted. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.</string>
+ <string name="warning_corrupted_provider_cert">Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.</string>
<string name="warning_expired_provider_cert">Stored provider certificate is expired. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.</string>
</resources>