summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2013-04-24 20:01:28 +0200
committerParménides GV <parmegv@sdf.org>2013-04-29 17:09:12 +0200
commit69389ee7db23ce7182b21da08d227d88d6cfdc46 (patch)
treeb521f6c8b86a153b3a126af4ff28b78283de7e84
parentbfe2263d6b73159a4f929bc7b1fdeb724c88e8de (diff)
"Trust completely" checkbox saves that trust for the new provider
entered, so that if in the future the client tries to log in or whatever, it can use the certificate downloaded when added. Log in dialog works ok, showing a toast when authentication fails (by this time, I have not managed to get a correct login due to dev.bitmask.net problems). dev.bitmask.net works perfectly, via adding it as a new provider (MeanderingCode, this is for you ;) ). All GET requests are done by default Android URL class, which means that certificates trusted by Android are also trusted by us. If there are problems when logging in due to certificates, the app is able to use only the certificate associated to the provider in the moment it was selected as the chosen provider.
-rw-r--r--assets/urls/bitmask.url3
-rw-r--r--hosts-for-android-emulator1
-rw-r--r--src/se/leap/leapclient/ConfigHelper.java21
-rw-r--r--src/se/leap/leapclient/ConfigurationWizard.java5
-rw-r--r--src/se/leap/leapclient/Dashboard.java4
-rw-r--r--src/se/leap/leapclient/LogInDialog.java2
-rw-r--r--src/se/leap/leapclient/ProviderAPI.java193
-rw-r--r--src/se/leap/leapclient/ProviderListContent.java16
8 files changed, 163 insertions, 82 deletions
diff --git a/assets/urls/bitmask.url b/assets/urls/bitmask.url
index 910f0400..bc4d59db 100644
--- a/assets/urls/bitmask.url
+++ b/assets/urls/bitmask.url
@@ -3,5 +3,6 @@
"assets_json_provider" : "providers/bitmask.net_provider.json",
"json_provider" : "https://bitmask.net/provider.json",
"cert" : "https://bitmask.net/ca.crt",
- "json_eip_service" : "https://api.bitmask.net:4430/1/config/eip-service.json"
+ "json_eip_service_antiguo" : "https://api.bitmask.net:4430/1/config/eip-service.json",
+ "json_eip_service" : "https://api.bitmask.net:4430/config/eip-service.json"
} \ No newline at end of file
diff --git a/hosts-for-android-emulator b/hosts-for-android-emulator
index b10103ef..ab0cf906 100644
--- a/hosts-for-android-emulator
+++ b/hosts-for-android-emulator
@@ -1,5 +1,6 @@
127.0.0.1 localhost
10.0.2.2 api.lvh.me
+10.0.2.2 lvh.me
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java
index 78c71cc4..7c52629b 100644
--- a/src/se/leap/leapclient/ConfigHelper.java
+++ b/src/se/leap/leapclient/ConfigHelper.java
@@ -16,6 +16,7 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -44,7 +45,7 @@ public class ConfigHelper {
public static final String user_directory = "leap_android";
final public static String provider_main_url = "provider_main_url";
final public static String danger_on = "danger_on";
- final public static String api_url_key = "srp_server_url";
+ final public static String api_url_key = "api_uri";
final public static String username_key = "username";
final public static String password_key = "password";
final public static String eip_service_api_path = "/config/eip-service.json";
@@ -63,6 +64,20 @@ public class ConfigHelper {
final public static int LOGOUT_SUCCESSFUL = 7;
final public static int LOGOUT_FAILED = 8;
+ static String getStringFromSharedPref(String shared_preferences_key) {
+ String value = "";
+ String content = shared_preferences.getString(shared_preferences_key, "");
+ try {
+ JSONObject json_object = new JSONObject(content);
+ JSONArray names = json_object.names();
+ String key = names.getString(0);
+ value = json_object.getString(key);
+ } catch (JSONException e) {
+ value = content;
+ }
+ return value;
+ }
+
static void saveSharedPref(String shared_preferences_key, JSONObject content) {
SharedPreferences.Editor shared_preferences_editor = shared_preferences
@@ -164,8 +179,8 @@ public class ConfigHelper {
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
- keystore_trusted.load(leap_keystore, "uer92jf".toCharArray());
- //keystore_trusted.load(null, null);
+ //keystore_trusted.load(leap_keystore, "uer92jf".toCharArray());
+ keystore_trusted.load(null, null);
} finally {
leap_keystore.close();
}
diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java
index 9edaa288..3d165211 100644
--- a/src/se/leap/leapclient/ConfigurationWizard.java
+++ b/src/se/leap/leapclient/ConfigurationWizard.java
@@ -95,7 +95,7 @@ public class ConfigurationWizard extends Activity
boolean custom = false;
provider_name = url_filepath.subSequence(0, url_filepath.indexOf(".")).toString();
if(ProviderListContent.ITEMS.isEmpty()) //TODO I have to implement a way of checking if a provider new or is already present in that ITEMS list
- ProviderListContent.addItem(new ProviderItem(provider_name, asset_manager.open(url_files_folder + "/" + url_filepath), custom));
+ ProviderListContent.addItem(new ProviderItem(provider_name, asset_manager.open(url_files_folder + "/" + url_filepath), custom, true)); // By default, it trusts the provider
}
} catch (IOException e) {
// TODO Auto-generated catch block
@@ -163,6 +163,7 @@ public class ConfigurationWizard extends Activity
method_and_parameters.putString(ConfigHelper.provider_key, current_provider_item.name);
method_and_parameters.putString(ConfigHelper.cert_key, current_provider_item.cert_json_url);
method_and_parameters.putString(ConfigHelper.eip_service_key, current_provider_item.eip_service_json_url);
+ method_and_parameters.putBoolean(ConfigHelper.danger_on, current_provider_item.danger_on);
provider_API_command.putExtra(ConfigHelper.downloadJsonFilesBundleExtra, method_and_parameters);
provider_API_command.putExtra("receiver", providerAPI_result_receiver);
@@ -191,9 +192,9 @@ public class ConfigurationWizard extends Activity
Bundle method_and_parameters = new Bundle();
method_and_parameters.putString(ConfigHelper.provider_main_url, provider_main_url);
+ method_and_parameters.putBoolean(ConfigHelper.danger_on, danger_on);
provider_API_command.putExtra(ConfigHelper.downloadNewProviderDotJSON, method_and_parameters);
- provider_API_command.putExtra(ConfigHelper.danger_on, danger_on);
provider_API_command.putExtra("receiver", providerAPI_result_receiver);
startService(provider_API_command);
diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java
index a169c9d4..577092bb 100644
--- a/src/se/leap/leapclient/Dashboard.java
+++ b/src/se/leap/leapclient/Dashboard.java
@@ -23,6 +23,7 @@ import android.view.ViewStub;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
+import android.widget.Toast;
public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface, Receiver {
@@ -195,11 +196,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
public void onReceiveResult(int resultCode, Bundle resultData) {
if(resultCode == ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL){
setResult(RESULT_OK);
+ Toast.makeText(getApplicationContext(), "Authentication succeeded", Toast.LENGTH_LONG).show();
//TODO What should we do know?
}
else if(resultCode == ConfigHelper.SRP_AUTHENTICATION_FAILED) {
setResult(RESULT_CANCELED);
- finish();
+ Toast.makeText(getApplicationContext(), "Authentication failed", Toast.LENGTH_LONG).show();
}
}
diff --git a/src/se/leap/leapclient/LogInDialog.java b/src/se/leap/leapclient/LogInDialog.java
index 61526c69..74db92ea 100644
--- a/src/se/leap/leapclient/LogInDialog.java
+++ b/src/se/leap/leapclient/LogInDialog.java
@@ -68,6 +68,6 @@ public class LogInDialog extends DialogFragment {
}
boolean validPassword(String entered_password) {
- return entered_password.length() > 8;
+ return entered_password.length() > 4;
}
}
diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java
index 63db18e1..04185eda 100644
--- a/src/se/leap/leapclient/ProviderAPI.java
+++ b/src/se/leap/leapclient/ProviderAPI.java
@@ -1,17 +1,26 @@
package se.leap.leapclient;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.math.BigInteger;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
import java.util.List;
import java.net.MalformedURLException;
import java.net.URL;
-import java.net.UnknownHostException;
import java.util.Scanner;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManagerFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
@@ -36,6 +45,7 @@ import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.os.ResultReceiver;
+import android.util.Base64;
import android.util.Log;
public class ProviderAPI extends IntentService {
@@ -58,7 +68,7 @@ public class ProviderAPI extends IntentService {
}
else if ((task = task_for.getBundleExtra(ConfigHelper.downloadNewProviderDotJSON)) != null) {
if(downloadNewProviderDotJSON(task))
- receiver.send(ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY);
+ receiver.send(ConfigHelper.CUSTOM_PROVIDER_ADDED, Bundle.EMPTY);
else
receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY);
}
@@ -77,25 +87,21 @@ public class ProviderAPI extends IntentService {
}
private boolean downloadJsonFiles(Bundle task) {
- String cert_url = (String) task.get(ConfigHelper.cert_key);
- String eip_service_json_url = (String) task.get(ConfigHelper.eip_service_key);
+ String provider_name = task.getString(ConfigHelper.provider_key);
+ String cert_url = task.getString(ConfigHelper.cert_key);
+ String eip_service_json_url = task.getString(ConfigHelper.eip_service_key);
+ boolean danger_on = task.getBoolean(ConfigHelper.danger_on);
try {
- String cert_string = getStringFromProvider(cert_url);
+ String cert_string = getStringFromProvider(cert_url, danger_on);
+ ConfigHelper.addTrustedCertificate(provider_name, cert_string);
JSONObject cert_json = new JSONObject("{ \"certificate\" : \"" + cert_string + "\"}");
ConfigHelper.saveSharedPref(ConfigHelper.cert_key, cert_json);
- JSONObject eip_service_json = getJSONFromProvider(eip_service_json_url);
+ JSONObject eip_service_json = getJSONFromProvider(eip_service_json_url, danger_on);
ConfigHelper.saveSharedPref(ConfigHelper.eip_service_key, eip_service_json);
return true;
- } catch (IOException e) {
- // TODO
- e.printStackTrace();
- return false;
} catch (JSONException e) {
ConfigHelper.rescueJSONException(e);
return false;
- } catch(Exception e) {
- e.printStackTrace();
- return false;
}
}
@@ -135,7 +141,8 @@ public class ProviderAPI extends IntentService {
byte[] M1 = client.response(Bbytes);
byte[] M2 = sendM1ToSRPServer(authentication_server, username, M1);
if( client.verify(M2) == false )
- throw new SecurityException("Failed to validate server reply: M2 = " + new BigInteger(1, M2).toString(16));
+ //throw new SecurityException("Failed to validate server reply: M2 = " + new BigInteger(1, M2).toString(16));
+ return false;
return true;
}
else return false;
@@ -199,17 +206,14 @@ public class ProviderAPI extends IntentService {
private boolean downloadNewProviderDotJSON(Bundle task) {
boolean custom = true;
- boolean danger_on = ((Boolean)task.get(ConfigHelper.danger_on)).booleanValue();
+ boolean danger_on = task.getBoolean(ConfigHelper.danger_on);
String provider_main_url = (String) task.get(ConfigHelper.provider_main_url);
String provider_name = provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("\\/", "_");
String provider_json_url = guessURL(provider_main_url);
JSONObject provider_json = null;
try {
- provider_json = getJSONFromProvider(provider_json_url);
- } catch (IOException e) {
- // It could happen that an https site used a certificate not trusted.
- provider_json = downloadNewProviderDotJsonWithoutCert(provider_json_url, danger_on);
+ provider_json = getJSONFromProvider(provider_json_url, danger_on);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -223,75 +227,128 @@ public class ProviderAPI extends IntentService {
ConfigHelper.saveFile(filename, provider_json.toString());
ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json);
- ProviderListContent.addItem(new ProviderItem(provider_name, ConfigHelper.openFileInputStream(filename), custom));
+ ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, ConfigHelper.openFileInputStream(filename), custom, danger_on));
return true;
}
}
- private JSONObject downloadNewProviderDotJsonWithoutCert(
- String provider_json_url, boolean danger_on) {
- JSONObject provider_json = null;
- try {
- URL provider_url = new URL(provider_json_url);
- String provider_json_string = new Scanner(provider_url.openStream()).useDelimiter("\\A").next();
- provider_json = new JSONObject(provider_json_string);
- } catch (MalformedURLException e1) {
- e1.printStackTrace();
- } catch (UnknownHostException e1) {
- e1.printStackTrace();
- } catch (IOException e1) {
- if(danger_on) {
- provider_json = downloadNewProviderDotJsonWithoutValidate(provider_json_url);
- }
- else {
- //TODO Show error message advising to check the checkbox if the url is completely trusted.
- }
- e1.printStackTrace();
- } catch (JSONException e1) {
- e1.printStackTrace();
- }
- return provider_json;
- }
-
- private JSONObject downloadNewProviderDotJsonWithoutValidate(
- String provider_json_url) {
- JSONObject provider_json = null;
+ private String getStringFromProviderWithoutValidate(
+ URL provider_json_url) {
+
+ String json_string = "";
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
- @Override
- public boolean verify(String hostname, SSLSession session) {
- HostnameVerifier hostname_verifier =
- HttpsURLConnection.getDefaultHostnameVerifier();
- return hostname_verifier.verify("", session);
- }
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
};
// Tell the URLConnection to use our HostnameVerifier
try {
- URL url = new URL(provider_json_url);
HttpsURLConnection urlConnection =
- (HttpsURLConnection)url.openConnection();
- urlConnection.setHostnameVerifier(hostnameVerifier);
- String provider_json_string = new Scanner(url.openStream()).useDelimiter("\\A").next();
- provider_json = new JSONObject(provider_json_string);
+ (HttpsURLConnection)provider_json_url.openConnection();
+ urlConnection.setHostnameVerifier(hostnameVerifier);
+ json_string = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
- e.printStackTrace();
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ json_string = getStringFromProviderWithCACertAdded(provider_json_url);
+ //e.printStackTrace();
}
- return provider_json;
-
+ return json_string;
}
private String guessURL(String provider_main_url) {
return provider_main_url + "/provider.json";
}
+
+ private String getStringFromProvider(String string_url, boolean danger_on) {
+
+ String json_file_content = "";
+
+ URL provider_url = null;
+ try {
+ provider_url = new URL(string_url);
+ json_file_content = new Scanner(provider_url.openStream()).useDelimiter("\\A").next();
+ } catch (MalformedURLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO SSLHandshakeException
+ // This means that we have not added ca.crt to the trusted certificates.
+ if(provider_url != null && danger_on) {
+ json_file_content = getStringFromProviderWithoutValidate(provider_url);
+ }
+ //json_file_content = downloadStringFromProviderWithCACertAdded(string_url);
+ e.printStackTrace();
+ }
+
+ return json_file_content;
+ }
+
+ private String getStringFromProviderWithCACertAdded(URL url) {
+ String json_file_content = "";
+
+ // Load CAs from an InputStream
+ // (could be from a resource or ByteArrayInputStream or ...)
+ CertificateFactory cf;
+ try {
+ cf = CertificateFactory.getInstance("X.509");
+
+ String cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.cert_key);
+ cert_string = cert_string.replaceFirst("-----BEGIN CERTIFICATE-----", "").replaceFirst("-----END CERTIFICATE-----", "").trim();
+ byte[] cert_bytes = Base64.decode(cert_string, Base64.DEFAULT);
+ InputStream caInput = new ByteArrayInputStream(cert_bytes);
+ java.security.cert.Certificate ca;
+ try {
+ ca = cf.generateCertificate(caInput);
+ System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
+ } finally {
+ caInput.close();
+ }
+
+ // Create a KeyStore containing our trusted CAs
+ String keyStoreType = KeyStore.getDefaultType();
+ KeyStore keyStore = KeyStore.getInstance(keyStoreType);
+ keyStore.load(null, null);
+ keyStore.setCertificateEntry("ca", ca);
+
+ // Create a TrustManager that trusts the CAs in our KeyStore
+ String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
+ tmf.init(keyStore);
+
+ // Create an SSLContext that uses our TrustManager
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(null, tmf.getTrustManagers(), null);
+
+ // Tell the URLConnection to use a SocketFactory from our SSLContext
+ HttpsURLConnection urlConnection =
+ (HttpsURLConnection)url.openConnection();
+ urlConnection.setSSLSocketFactory(context.getSocketFactory());
+ json_file_content = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next();
+ } catch (CertificateException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (KeyStoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (NoSuchAlgorithmException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (KeyManagementException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return json_file_content;
+ }
- private String getStringFromProvider(String string_url) throws IOException {
+ private String getStringFromProvider_2(String string_url) throws IOException {
String json_file_content = "";
@@ -306,8 +363,8 @@ public class ProviderAPI extends IntentService {
return json_file_content;
}
- private JSONObject getJSONFromProvider(String json_url) throws IOException, JSONException {
- String json_file_content = getStringFromProvider(json_url);
+ private JSONObject getJSONFromProvider(String json_url, boolean danger_on) throws JSONException {
+ String json_file_content = getStringFromProvider(json_url, danger_on);
return new JSONObject(json_file_content);
}
diff --git a/src/se/leap/leapclient/ProviderListContent.java b/src/se/leap/leapclient/ProviderListContent.java
index dd227bfd..9ed7e9bf 100644
--- a/src/se/leap/leapclient/ProviderListContent.java
+++ b/src/se/leap/leapclient/ProviderListContent.java
@@ -44,6 +44,7 @@ public class ProviderListContent {
public String provider_json_filename;
public String eip_service_json_url;
public String cert_json_url;
+ public boolean danger_on = false;
public ProviderItem(String id, String name, String provider_json_url, String eip_service_json_url, String cert_json_url) {
this.id = id;
@@ -53,7 +54,7 @@ public class ProviderListContent {
this.cert_json_url = cert_json_url;
}
- public ProviderItem(String name, InputStream urls_file_input_stream, boolean custom) {
+ public ProviderItem(String name, InputStream urls_file_input_stream, boolean custom, boolean danger_on) {
try {
byte[] urls_file_bytes = new byte[urls_file_input_stream.available()];
@@ -62,11 +63,12 @@ public class ProviderListContent {
JSONObject file_contents = new JSONObject(urls_file_content);
id = name;
this.name = name;
- provider_json_url = (String) file_contents.get("json_provider");
- provider_json_filename = (String) file_contents.get("assets_json_provider");
- eip_service_json_url = (String) file_contents.get("json_eip_service");
- cert_json_url = (String) file_contents.get("cert");
+ provider_json_url = file_contents.getString("json_provider");
+ provider_json_filename = file_contents.getString("assets_json_provider");
+ eip_service_json_url = file_contents.getString("json_eip_service");
+ cert_json_url = file_contents.getString("cert");
this.custom = custom;
+ this.danger_on = danger_on;
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -76,7 +78,7 @@ public class ProviderListContent {
}
}
- public ProviderItem(String name, FileInputStream provider_json, boolean custom) {
+ public ProviderItem(String name, String provider_json_url, FileInputStream provider_json, boolean custom, boolean danger_on) {
try {
byte[] urls_file_bytes = new byte[provider_json.available()];
@@ -85,9 +87,11 @@ public class ProviderListContent {
JSONObject file_contents = new JSONObject(urls_file_content);
id = name;
this.name = name;
+ this.provider_json_url = provider_json_url;
eip_service_json_url = (String) file_contents.get("api_uri") + ConfigHelper.eip_service_api_path;
cert_json_url = (String) file_contents.get("ca_cert_uri");
this.custom = custom;
+ this.danger_on = danger_on;
if(custom)
provider_json_filename = name + "_provider.json".replaceFirst("__", "_");
} catch (JSONException e) {