From 8e47afc7f4f85b80d59d253378681cb85ec54d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 16 Apr 2013 20:12:13 +0200 Subject: Made SRP working with ProviderAPI methods more frequently than not in localhost, but I cannot succeed in api.bitmask.net with my personal account. Next step: add tests from api.bitmask.net. --- src/se/leap/leapclient/LeapSRPSession.java | 2 ++ src/se/leap/leapclient/ProviderAPI.java | 22 +++++++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index abdf6b2..6fc8b2b 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -70,6 +70,8 @@ public class LeapSRPSession { */ this.a = new BigInteger(abytes); } + else + A_LEN = 64; // Calculate x = H(s | H(U | ':' | password)) byte[] salt_bytes = Util.trim(params.s); diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 4ffd276..5113ebc 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -20,6 +20,7 @@ import org.apache.http.cookie.Cookie; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; +import org.jboss.security.Util; import org.jboss.security.srp.SRPParameters; import org.json.JSONException; import org.json.JSONObject; @@ -56,6 +57,12 @@ public class ProviderAPI extends IntentService { else receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY); } + else if ((task = task_for.getBundleExtra(ConfigHelper.srpAuth)) != null) { + if(authenticateBySRP(task)) + receiver.send(ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL, Bundle.EMPTY); + else + receiver.send(ConfigHelper.SRP_AUTHENTICATION_FAILED, Bundle.EMPTY); + } } private boolean downloadJsonFiles(Bundle task) { @@ -105,17 +112,16 @@ public class ProviderAPI extends IntentService { LeapSRPSession client = new LeapSRPSession(username, password.toCharArray(), params); byte[] A = client.exponential(); try { - JSONObject saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(A).toString(16)); + JSONObject saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); if(saltAndB.length() > 0) { byte[] B = saltAndB.getString("B").getBytes(); salt = saltAndB.getString("salt"); params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256"); - //client = new SRPClientSession(username, password.toCharArray(), params); client = new LeapSRPSession(username, password.toCharArray(), params); A = client.exponential(); - saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(A).toString(16)); - String Bhex = saltAndB.getString("B"); - byte[] M1 = client.response(new BigInteger(Bhex, 16).toByteArray()); + saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); + byte[] Bbytes = new BigInteger(saltAndB.getString("B"), 16).toByteArray(); + 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"); @@ -162,7 +168,7 @@ public class ProviderAPI extends IntentService { private byte[] sendM1ToSRPServer(String server_url, String username, byte[] m1) throws ClientProtocolException, IOException, JSONException { DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); - String parameter_chain = "client_auth" + "=" + new BigInteger(m1).toString(16); + String parameter_chain = "client_auth" + "=" + new BigInteger(1, Util.trim(m1)).toString(16); HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + parameter_chain); HttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.COOKIE_STORE, client.getCookieStore()); @@ -175,7 +181,9 @@ public class ProviderAPI extends IntentService { return new byte[0]; } - return json_response.getString("M2").getBytes(); + byte[] M2_not_trimmed = new BigInteger(json_response.getString("M2"), 16).toByteArray(); + return Util.trim(M2_not_trimmed); + //return M2_not_trimmed; } private boolean downloadNewProviderDotJSON(Bundle task) { -- cgit v1.2.3 From f9b9827ec1975cb01e83826f0ad77542e514b21f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 17 Apr 2013 21:17:22 +0200 Subject: This commit contains: - SRP algorithm improved (validate method uses trim, and some other trims have been added). - Refactored calculatePasswordHash, so that it receives a String instead of a char array, and now it is capable of escaping "\" correctly. - A 1000*2 successful logins, with a new test that performs 1000 trials for 2 different username/password/server trios. Next step: think about how the user is going to trigger the log in fragment. --- src/se/leap/leapclient/LeapSRPSession.java | 36 +++++++++++++++++------------- src/se/leap/leapclient/ProviderAPI.java | 6 ++--- 2 files changed, 23 insertions(+), 19 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 6fc8b2b..d266cd7 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -34,7 +34,7 @@ public class LeapSRPSession { @param password, the user clear text password @param params, the SRP parameters for the session */ - public LeapSRPSession(String username, char[] password, SRPParameters params) + public LeapSRPSession(String username, String password, SRPParameters params) { this(username, password, params, null); } @@ -47,7 +47,7 @@ public class LeapSRPSession { @param abytes, the random exponent used in the A public key. This must be 8 bytes in length. */ - public LeapSRPSession(String username, char[] password, SRPParameters params, + public LeapSRPSession(String username, String password, SRPParameters params, byte[] abytes) { try { // Initialize the secure random number and message digests @@ -117,11 +117,11 @@ public class LeapSRPSession { * @param salt the salt of the user * @return x */ - public byte[] calculatePasswordHash(String username, char[] password, byte[] salt) + public byte[] calculatePasswordHash(String username, String password, byte[] salt) { + password = password.replaceAll("\\\\", "\\\\\\\\"); // Calculate x = H(s | H(U | ':' | password)) MessageDigest x_digest = newDigest(); - // Try to convert the username to a byte[] using UTF-8 byte[] user = null; byte[] colon = {}; @@ -135,10 +135,10 @@ public class LeapSRPSession { colon = Util.trim(":".getBytes()); } - byte[] passBytes = new byte[2*password.length]; + byte[] passBytes = new byte[2*password.toCharArray().length]; int passBytesLength = 0; - for(int p = 0; p < password.length; p++) { - int c = (password[p] & 0x00FFFF); + for(int p = 0; p < password.toCharArray().length; p++) { + int c = (password.toCharArray()[p] & 0x00FFFF); // The low byte of the char byte b0 = (byte) (c & 0x0000FF); // The high byte of the char @@ -159,7 +159,7 @@ public class LeapSRPSession { x_digest.reset(); x_digest.update(salt); x_digest.update(h); - byte[] x_digest_bytes = Util.trim(x_digest.digest()); + byte[] x_digest_bytes = x_digest.digest(); return x_digest_bytes; } @@ -171,7 +171,8 @@ public class LeapSRPSession { */ private BigInteger calculateV(String k_string) { BigInteger k = new BigInteger(k_string, 16); - return k.multiply(g.modPow(x, N)); // g^x % N + BigInteger v = k.multiply(g.modPow(x, N)); // g^x % N + return v; } public byte[] xor(byte[] b1, byte[] b2, int length) @@ -229,13 +230,13 @@ public class LeapSRPSession { // K = SessionHash(S) String hash_algorithm = params.hashAlgorithm; MessageDigest sessionDigest = MessageDigest.getInstance(hash_algorithm); - K = sessionDigest.digest(S_bytes); + K = Util.trim(sessionDigest.digest(S_bytes)); //K = Util.trim(K); //String K_bytes_string = new BigInteger(1, K).toString(16); // clientHash = H(N) xor H(g) | H(U) | A | B | K clientHash.update(K); - byte[] M1 = clientHash.digest(); + byte[] M1 = Util.trim(clientHash.digest()); // serverHash = Astr + M + K serverHash.update(M1); @@ -250,10 +251,11 @@ public class LeapSRPSession { */ private BigInteger calculateS(byte[] Bbytes) { byte[] Abytes = Util.trim(A.toByteArray()); + Bbytes = Util.trim(Bbytes); byte[] u_bytes = getU(Abytes, Bbytes); - //ub = Util.trim(ub); BigInteger B = new BigInteger(1, Bbytes); + //String Bstring = B.toString(16); BigInteger u = new BigInteger(1, u_bytes); //String u_string = u.toString(16); @@ -273,9 +275,10 @@ public class LeapSRPSession { */ public byte[] getU(byte[] Abytes, byte[] Bbytes) { MessageDigest u_digest = newDigest(); - u_digest.update(Abytes); - u_digest.update(Bbytes); - return new BigInteger(1, u_digest.digest()).toByteArray(); + u_digest.update(Util.trim(Abytes)); + u_digest.update(Util.trim(Bbytes)); + byte[] u_digest_bytes = u_digest.digest();//Util.trim(u_digest.digest()); + return Util.trim(new BigInteger(1, u_digest_bytes).toByteArray()); } /** @@ -285,7 +288,8 @@ public class LeapSRPSession { public boolean verify(byte[] M2) { // M2 = H(A | M1 | K) - byte[] myM2 = serverHash.digest(); + M2 = Util.trim(M2); + byte[] myM2 = Util.trim(serverHash.digest()); boolean valid = Arrays.equals(M2, myM2); return valid; } diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 5113ebc..55686f7 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -109,7 +109,7 @@ public class ProviderAPI extends IntentService { SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256"); //SRPClientSession client = new SRPClientSession(username, password.toCharArray(), params); - LeapSRPSession client = new LeapSRPSession(username, password.toCharArray(), params); + LeapSRPSession client = new LeapSRPSession(username, password, params); byte[] A = client.exponential(); try { JSONObject saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); @@ -117,14 +117,14 @@ public class ProviderAPI extends IntentService { byte[] B = saltAndB.getString("B").getBytes(); salt = saltAndB.getString("salt"); params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256"); - client = new LeapSRPSession(username, password.toCharArray(), params); + client = new LeapSRPSession(username, password, params); A = client.exponential(); saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); byte[] Bbytes = new BigInteger(saltAndB.getString("B"), 16).toByteArray(); 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"); + throw new SecurityException("Failed to validate server reply: M2 = " + new BigInteger(1, M2).toString(16)); return true; } else return false; -- cgit v1.2.3 From 5c05094401d6ed3c69ab8f64e47278973bc87425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 18 Apr 2013 21:56:06 +0200 Subject: Coded logout method, and tested. --- src/se/leap/leapclient/ConfigHelper.java | 7 ++-- src/se/leap/leapclient/ProviderAPI.java | 60 +++++++++++++++----------------- 2 files changed, 33 insertions(+), 34 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 7476c89..8f38cbe 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -32,6 +32,7 @@ public class ConfigHelper { final static String downloadNewProviderDotJSON = "downloadNewProviderDotJSON"; public static final String srpRegister = "srpRegister"; final public static String srpAuth = "srpAuth"; + public static String logOut = "logOut"; final public static String resultKey = "result"; final static String provider_key = "provider"; final static String cert_key = "cert"; @@ -53,8 +54,10 @@ public class ConfigHelper { final public static int INCORRECTLY_DOWNLOADED_JSON_FILES = 2; final public static int SRP_AUTHENTICATION_SUCCESSFUL = 3; final public static int SRP_AUTHENTICATION_FAILED = 4; - public static final int SRP_REGISTRATION_SUCCESSFUL = 5; - public static final int SRP_REGISTRATION_FAILED = 6; + final public static int SRP_REGISTRATION_SUCCESSFUL = 5; + final public static int SRP_REGISTRATION_FAILED = 6; + final public static int LOGOUT_SUCCESSFUL = 7; + final public static int LOGOUT_FAILED = 8; static void saveSharedPref(String shared_preferences_key, JSONObject content) { diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 55686f7..d47e3b6 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -12,6 +12,7 @@ import java.util.Scanner; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; @@ -63,6 +64,12 @@ public class ProviderAPI extends IntentService { else receiver.send(ConfigHelper.SRP_AUTHENTICATION_FAILED, Bundle.EMPTY); } + else if ((task = task_for.getBundleExtra(ConfigHelper.logOut)) != null) { + if(logOut(task)) + receiver.send(ConfigHelper.LOGOUT_SUCCESSFUL, Bundle.EMPTY); + else + receiver.send(ConfigHelper.LOGOUT_FAILED, Bundle.EMPTY); + } } private boolean downloadJsonFiles(Bundle task) { @@ -215,38 +222,6 @@ public class ProviderAPI extends IntentService { } } - private boolean downloadJsonFilesBundleExtra(Bundle task) { - //TODO task only contains provider main url -> we need to infer cert_url, provider_name and eip_service_json_url from that. - String provider_main_url = (String) task.get(ConfigHelper.provider_main_url); - String provider_name = ConfigHelper.extractProviderName(provider_main_url); - String cert_url = (String) task.get(ConfigHelper.cert_key); - String eip_service_json_url = (String) task.get(ConfigHelper.eip_service_key); - try { - //JSONObject provider_json = new JSONObject("{ \"provider\" : \"" + provider_name + "\"}"); - //ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); - - /*String cert_string = getStringFromProvider(cert_url); - JSONObject cert_json = new JSONObject("{ \"certificate\" : \"" + cert_string + "\"}"); - ConfigHelper.saveSharedPref(ConfigHelper.cert_key, cert_json); - ConfigHelper.addTrustedCertificate(provider_name, cert_string);*/ - URL cacert = new URL(cert_url); - ConfigHelper.addTrustedCertificate(provider_name, cacert.openStream()); - JSONObject eip_service_json = getJSONFromProvider(eip_service_json_url); - ConfigHelper.saveSharedPref(ConfigHelper.eip_service_key, eip_service_json); - return true; - } catch (IOException e) { - //TODO It could happen when the url is not valid. - e.printStackTrace(); - return false; - } catch (JSONException e) { - ConfigHelper.rescueJSONException(e); - return false; - } catch(Exception e) { - e.printStackTrace(); - return false; - } - } - private JSONObject downloadNewProviderDotJsonWithoutCert( String provider_json_url) { JSONObject provider_json = null; @@ -284,8 +259,29 @@ 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); return new JSONObject(json_file_content); } + + private boolean logOut(Bundle task) { + DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); + int session_id_index = 0; + //String delete_url = task.getString(ConfigHelper.srp_server_url_key) + "/sessions/" + client.getCookieStore().getCookies().get(0).getValue(); + String delete_url = task.getString(ConfigHelper.srp_server_url_key) + "/logout" + "?authenticity_token=" + client.getCookieStore().getCookies().get(session_id_index).getValue(); + HttpDelete delete = new HttpDelete(delete_url); + try { + HttpResponse getResponse = client.execute(delete); + HttpEntity responseEntity = getResponse.getEntity(); + responseEntity.consumeContent(); + } catch (ClientProtocolException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return true; + } } -- cgit v1.2.3 From 75728462433b19567710f54a9d4767681b10be95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 22 Apr 2013 18:07:07 +0200 Subject: Coded dialog (now there is a button in the Dashboard), time to test. I need to implement bypass for dev.bitmask.net, because bitmask.net is down. --- src/se/leap/leapclient/ConfigHelper.java | 7 ++- src/se/leap/leapclient/ConfigurationWizard.java | 4 +- src/se/leap/leapclient/Dashboard.java | 64 +++++++++++++++++++++- src/se/leap/leapclient/LogInDialog.java | 73 +++++++++++++++++++++++++ src/se/leap/leapclient/ProviderAPI.java | 8 +-- 5 files changed, 147 insertions(+), 9 deletions(-) create mode 100644 src/se/leap/leapclient/LogInDialog.java (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 8f38cbe..de14eed 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -30,8 +30,11 @@ public class ConfigHelper { final static String downloadJsonFilesBundleExtra = "downloadJSONFiles"; final static String downloadNewProviderDotJSON = "downloadNewProviderDotJSON"; - public static final String srpRegister = "srpRegister"; + final public static String logInDialog = "logInDialog"; + final public static String newProviderDialog = "logInDialog"; + final public static String srpRegister = "srpRegister"; final public static String srpAuth = "srpAuth"; + public static String logIn = "logIn"; public static String logOut = "logOut"; final public static String resultKey = "result"; final static String provider_key = "provider"; @@ -40,7 +43,7 @@ public class ConfigHelper { public static final String PREFERENCES_KEY = "LEAPPreferences"; public static final String user_directory = "leap_android"; public static String provider_main_url = "provider_main_url"; - final public static String srp_server_url_key = "srp_server_url"; + final public static String api_url_key = "srp_server_url"; 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"; diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 0d44522..417752e 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -172,14 +172,14 @@ public class ConfigurationWizard extends Activity public void addNewProvider(View view) { FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); - Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag("newProviderDialog"); + Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.newProviderDialog); if (previous_new_provider_dialog != null) { fragment_transaction.remove(previous_new_provider_dialog); } fragment_transaction.addToBackStack(null); DialogFragment newFragment = NewProviderDialog.newInstance(); - newFragment.show(fragment_transaction, "newProviderDialog"); + newFragment.show(fragment_transaction, ConfigHelper.newProviderDialog); } @Override diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index dce99b1..815df18 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -1,13 +1,20 @@ package se.leap.leapclient; +import org.json.JSONException; +import org.json.JSONObject; + +import se.leap.leapclient.ProviderAPIResultReceiver.Receiver; import se.leap.openvpn.AboutFragment; import se.leap.openvpn.MainActivity; import android.app.Activity; +import android.app.DialogFragment; import android.app.Fragment; +import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; +import android.os.Handler; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -16,7 +23,7 @@ import android.widget.CompoundButton; import android.widget.Switch; import android.widget.TextView; -public class Dashboard extends Activity { +public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface, Receiver { protected static final int CONFIGURE_LEAP = 0; @@ -26,6 +33,8 @@ public class Dashboard extends Activity { private TextView providerNameTV; private TextView eipTypeTV; + public ProviderAPIResultReceiver providerAPI_result_receiver; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -127,6 +136,9 @@ public class Dashboard extends Activity { // TODO call se.leap.openvpn.MainActivity intent = new Intent(this,MainActivity.class); startActivity(intent); + return true; + case R.id.login_button: + return true; default: return super.onOptionsItemSelected(item); @@ -139,4 +151,54 @@ public class Dashboard extends Activity { // TODO Expand the one line overview item to show some details } + @Override + public void authenticate(String username, String password) { + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); + + Intent provider_API_command = new Intent(this, ProviderAPI.class); + + Bundle method_and_parameters = new Bundle(); + method_and_parameters.putString(ConfigHelper.username_key, username); + method_and_parameters.putString(ConfigHelper.password_key, password); + + JSONObject provider_json; + try { + provider_json = new JSONObject(preferences.getString(ConfigHelper.provider_key, "")); + method_and_parameters.putString(ConfigHelper.api_url_key, provider_json.getString(ConfigHelper.api_url_key)); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + provider_API_command.putExtra(ConfigHelper.srpAuth, method_and_parameters); + provider_API_command.putExtra("receiver", providerAPI_result_receiver); + + startService(provider_API_command); + } + + public void logInDialog(View view) { + FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); + Fragment previous_log_in_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.logInDialog); + if (previous_log_in_dialog != null) { + fragment_transaction.remove(previous_log_in_dialog); + } + fragment_transaction.addToBackStack(null); + + DialogFragment newFragment = LogInDialog.newInstance(); + newFragment.show(fragment_transaction, ConfigHelper.logInDialog); + } + + @Override + public void onReceiveResult(int resultCode, Bundle resultData) { + if(resultCode == ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL){ + setResult(RESULT_OK); + //TODO What should we do know? + } + else if(resultCode == ConfigHelper.SRP_AUTHENTICATION_FAILED) { + setResult(RESULT_CANCELED); + finish(); + } + } + } diff --git a/src/se/leap/leapclient/LogInDialog.java b/src/se/leap/leapclient/LogInDialog.java new file mode 100644 index 0000000..b9583d8 --- /dev/null +++ b/src/se/leap/leapclient/LogInDialog.java @@ -0,0 +1,73 @@ +package se.leap.leapclient; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.Toast; + +public class LogInDialog extends DialogFragment { + + public interface LogInDialogInterface { + public void authenticate(String username, String password); + } + + LogInDialogInterface interface_with_ConfigurationWizard; + + public static DialogFragment newInstance() { + LogInDialog dialog_fragment = new LogInDialog(); + return dialog_fragment; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + // Verify that the host activity implements the callback interface + try { + // Instantiate the NoticeDialogListener so we can send events to the host + interface_with_ConfigurationWizard = (LogInDialogInterface) activity; + } catch (ClassCastException e) { + // The activity doesn't implement the interface, throw exception + throw new ClassCastException(activity.toString() + + " must implement NoticeDialogListener"); + } + } + + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + LayoutInflater inflater = getActivity().getLayoutInflater(); + View log_in_dialog_view = inflater.inflate(R.layout.log_in_dialog, null); + final EditText username_field = (EditText)log_in_dialog_view.findViewById(R.id.username_entered); + final EditText password_field = (EditText)log_in_dialog_view.findViewById(R.id.password_entered); + builder.setView(log_in_dialog_view) + .setPositiveButton(R.string.log_in_button, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + String username = username_field.getText().toString().trim(); + String password = password_field.getText().toString().trim(); + if(validPassword(password)) { + interface_with_ConfigurationWizard.authenticate(username, password); + Toast.makeText(getActivity().getApplicationContext(), "It seems your URL is well formed", Toast.LENGTH_LONG).show(); + } else { + password_field.setText(""); + Toast.makeText(getActivity().getApplicationContext(), "It seems your URL is not well formed", Toast.LENGTH_LONG).show(); + } + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + // Create the AlertDialog object and return it + return builder.create(); + } + + boolean validPassword(String entered_password) { + return !(entered_password.length() > 8); + } +} diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index d47e3b6..0b114e3 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -83,7 +83,7 @@ public class ProviderAPI extends IntentService { ConfigHelper.saveSharedPref(ConfigHelper.eip_service_key, eip_service_json); return true; } catch (IOException e) { - // TODO Auto-generated catch block + // TODO e.printStackTrace(); return false; } catch (JSONException e) { @@ -98,7 +98,7 @@ public class ProviderAPI extends IntentService { private boolean registerWithSRP(Bundle task) { String username = (String) task.get(ConfigHelper.username_key); String password = (String) task.get(ConfigHelper.password_key); - String authentication_server = (String) task.get(ConfigHelper.srp_server_url_key); + String authentication_server = (String) task.get(ConfigHelper.api_url_key); BigInteger ng_1024 = new BigInteger(ConfigHelper.NG_1024, 16); BigInteger salt = ng_1024.probablePrime(1024, null); @@ -110,7 +110,7 @@ public class ProviderAPI extends IntentService { private boolean authenticateBySRP(Bundle task) { String username = (String) task.get(ConfigHelper.username_key); String password = (String) task.get(ConfigHelper.password_key); - String authentication_server = (String) task.get(ConfigHelper.srp_server_url_key); + String authentication_server = (String) task.get(ConfigHelper.api_url_key); String salt = "abcd"; @@ -269,7 +269,7 @@ public class ProviderAPI extends IntentService { DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); int session_id_index = 0; //String delete_url = task.getString(ConfigHelper.srp_server_url_key) + "/sessions/" + client.getCookieStore().getCookies().get(0).getValue(); - String delete_url = task.getString(ConfigHelper.srp_server_url_key) + "/logout" + "?authenticity_token=" + client.getCookieStore().getCookies().get(session_id_index).getValue(); + String delete_url = task.getString(ConfigHelper.api_url_key) + "/logout" + "?authenticity_token=" + client.getCookieStore().getCookies().get(session_id_index).getValue(); HttpDelete delete = new HttpDelete(delete_url); try { HttpResponse getResponse = client.execute(delete); -- cgit v1.2.3 From bfe2263d6b73159a4f929bc7b1fdeb724c88e8de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 22 Apr 2013 20:17:43 +0200 Subject: Added danger mode: we can bypass dev.bitmask.net hostname io exception. --- src/se/leap/leapclient/ConfigHelper.java | 3 +- src/se/leap/leapclient/ConfigurationWizard.java | 3 +- src/se/leap/leapclient/Dashboard.java | 4 +- src/se/leap/leapclient/LogInDialog.java | 8 ++-- src/se/leap/leapclient/NewProviderDialog.java | 8 +++- src/se/leap/leapclient/ProviderAPI.java | 50 ++++++++++++++++++++++++- 6 files changed, 65 insertions(+), 11 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index de14eed..78c71cc 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -42,7 +42,8 @@ public class ConfigHelper { final static String eip_service_key = "eip"; public static final String PREFERENCES_KEY = "LEAPPreferences"; public static final String user_directory = "leap_android"; - public static String provider_main_url = "provider_main_url"; + 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 username_key = "username"; final public static String password_key = "password"; diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 417752e..9edaa28 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -183,7 +183,7 @@ public class ConfigurationWizard extends Activity } @Override - public void saveProvider(String provider_main_url) { + public void saveProvider(String provider_main_url, boolean danger_on) { providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); providerAPI_result_receiver.setReceiver(this); @@ -193,6 +193,7 @@ public class ConfigurationWizard extends Activity method_and_parameters.putString(ConfigHelper.provider_main_url, provider_main_url); 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 815df18..a169c9d 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -18,6 +18,7 @@ import android.os.Handler; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.ViewGroup; import android.view.ViewStub; import android.widget.CompoundButton; import android.widget.Switch; @@ -138,7 +139,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startActivity(intent); return true; case R.id.login_button: - + View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0); + logInDialog(view); return true; default: return super.onOptionsItemSelected(item); diff --git a/src/se/leap/leapclient/LogInDialog.java b/src/se/leap/leapclient/LogInDialog.java index b9583d8..61526c6 100644 --- a/src/se/leap/leapclient/LogInDialog.java +++ b/src/se/leap/leapclient/LogInDialog.java @@ -17,7 +17,7 @@ public class LogInDialog extends DialogFragment { public void authenticate(String username, String password); } - LogInDialogInterface interface_with_ConfigurationWizard; + LogInDialogInterface interface_with_Dashboard; public static DialogFragment newInstance() { LogInDialog dialog_fragment = new LogInDialog(); @@ -30,7 +30,7 @@ public class LogInDialog extends DialogFragment { // Verify that the host activity implements the callback interface try { // Instantiate the NoticeDialogListener so we can send events to the host - interface_with_ConfigurationWizard = (LogInDialogInterface) activity; + interface_with_Dashboard = (LogInDialogInterface) activity; } catch (ClassCastException e) { // The activity doesn't implement the interface, throw exception throw new ClassCastException(activity.toString() @@ -50,7 +50,7 @@ public class LogInDialog extends DialogFragment { String username = username_field.getText().toString().trim(); String password = password_field.getText().toString().trim(); if(validPassword(password)) { - interface_with_ConfigurationWizard.authenticate(username, password); + interface_with_Dashboard.authenticate(username, password); Toast.makeText(getActivity().getApplicationContext(), "It seems your URL is well formed", Toast.LENGTH_LONG).show(); } else { password_field.setText(""); @@ -68,6 +68,6 @@ public class LogInDialog extends DialogFragment { } boolean validPassword(String entered_password) { - return !(entered_password.length() > 8); + return entered_password.length() > 8; } } diff --git a/src/se/leap/leapclient/NewProviderDialog.java b/src/se/leap/leapclient/NewProviderDialog.java index 88e4711..6101846 100644 --- a/src/se/leap/leapclient/NewProviderDialog.java +++ b/src/se/leap/leapclient/NewProviderDialog.java @@ -8,13 +8,14 @@ import android.content.DialogInterface; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; +import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; public class NewProviderDialog extends DialogFragment { public interface NewProviderDialogInterface { - public void saveProvider(String url_provider); + public void saveProvider(String url_provider, boolean danger_on); } NewProviderDialogInterface interface_with_ConfigurationWizard; @@ -43,13 +44,16 @@ public class NewProviderDialog extends DialogFragment { LayoutInflater inflater = getActivity().getLayoutInflater(); View new_provider_dialog_view = inflater.inflate(R.layout.new_provider_dialog, null); final EditText url_input_field = (EditText)new_provider_dialog_view.findViewById(R.id.new_provider_url); + final CheckBox danger_checkbox = (CheckBox)new_provider_dialog_view.findViewById(R.id.danger_checkbox); + builder.setView(new_provider_dialog_view) .setMessage(R.string.introduce_new_provider) .setPositiveButton(R.string.save, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { String entered_url = url_input_field.getText().toString().trim(); + boolean danger_on = danger_checkbox.isChecked(); if(validURL(entered_url)) { - interface_with_ConfigurationWizard.saveProvider(entered_url); + interface_with_ConfigurationWizard.saveProvider(entered_url, danger_on); Toast.makeText(getActivity().getApplicationContext(), "It seems your URL is well formed", Toast.LENGTH_LONG).show(); } else { url_input_field.setText(""); diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 0b114e3..63db18e 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -9,6 +9,10 @@ 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.SSLSession; + import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; @@ -195,6 +199,8 @@ public class ProviderAPI extends IntentService { private boolean downloadNewProviderDotJSON(Bundle task) { boolean custom = true; + boolean danger_on = ((Boolean)task.get(ConfigHelper.danger_on)).booleanValue(); + 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); @@ -203,7 +209,7 @@ public class ProviderAPI extends IntentService { 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); + provider_json = downloadNewProviderDotJsonWithoutCert(provider_json_url, danger_on); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -223,7 +229,7 @@ public class ProviderAPI extends IntentService { } private JSONObject downloadNewProviderDotJsonWithoutCert( - String provider_json_url) { + String provider_json_url, boolean danger_on) { JSONObject provider_json = null; try { URL provider_url = new URL(provider_json_url); @@ -234,6 +240,12 @@ public class ProviderAPI extends IntentService { } 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(); @@ -241,6 +253,40 @@ public class ProviderAPI extends IntentService { return provider_json; } + private JSONObject downloadNewProviderDotJsonWithoutValidate( + String provider_json_url) { + JSONObject provider_json = null; + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + HostnameVerifier hostname_verifier = + HttpsURLConnection.getDefaultHostnameVerifier(); + return hostname_verifier.verify("", session); + } + }; + + // 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); + } 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(); + } + return provider_json; + + } + private String guessURL(String provider_main_url) { return provider_main_url + "/provider.json"; } -- cgit v1.2.3 From 69389ee7db23ce7182b21da08d227d88d6cfdc46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 24 Apr 2013 20:01:28 +0200 Subject: "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. --- src/se/leap/leapclient/ConfigHelper.java | 21 ++- src/se/leap/leapclient/ConfigurationWizard.java | 5 +- src/se/leap/leapclient/Dashboard.java | 4 +- src/se/leap/leapclient/LogInDialog.java | 2 +- src/se/leap/leapclient/ProviderAPI.java | 193 +++++++++++++++--------- src/se/leap/leapclient/ProviderListContent.java | 16 +- 6 files changed, 160 insertions(+), 81 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 78c71cc..7c52629 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 9edaa28..3d16521 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 a169c9d..577092b 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 61526c6..74db92e 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 63db18e..04185ed 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 dd227bf..9ed7e9b 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) { -- cgit v1.2.3 From 09493a9dec5fb235d5c4914eb8f8142e3312e246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 29 Apr 2013 21:32:10 +0200 Subject: Changed the message shown when checking if the password is valid or not. Refactored LeapSRPSession so that there is no need to send A twice. --- src/se/leap/leapclient/LeapSRPSession.java | 94 ++++++++++++++++-------------- src/se/leap/leapclient/LogInDialog.java | 4 +- src/se/leap/leapclient/ProviderAPI.java | 8 +-- 3 files changed, 57 insertions(+), 49 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index d266cd7..f9037de 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -14,7 +14,10 @@ import org.jboss.security.srp.SRPPermission; public class LeapSRPSession { private SRPParameters params; + private String username; + private String password; private BigInteger N; + private byte[] N_bytes; private BigInteger g; private BigInteger x; private BigInteger v; @@ -58,9 +61,11 @@ public class LeapSRPSession { this.params = params; this.g = new BigInteger(1, params.g); - byte[] N_bytes = Util.trim(params.N); + N_bytes = Util.trim(params.N); this.N = new BigInteger(1, N_bytes); - + this.username = username; + this.password = password; + if( abytes != null ) { A_LEN = 8*abytes.length; /* TODO Why did they put this condition? @@ -73,41 +78,8 @@ public class LeapSRPSession { else A_LEN = 64; - // Calculate x = H(s | H(U | ':' | password)) - byte[] salt_bytes = Util.trim(params.s); - byte[] xb = calculatePasswordHash(username, password, salt_bytes); - this.x = new BigInteger(1, xb); - - // Calculate v = kg^x mod N - String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; - this.v = calculateV(k_string); - //String v_string = v.toString(16); - serverHash = newDigest(); clientHash = newDigest(); - - // H(N) - byte[] digest_of_n = newDigest().digest(N_bytes); - - // H(g) - byte[] digest_of_g = newDigest().digest(params.g); - - // clientHash = H(N) xor H(g) - byte[] xor_digest = xor(digest_of_n, digest_of_g, digest_of_g.length); - //String hxg_string = new BigInteger(1, xor_digest).toString(16); - clientHash.update(xor_digest); - - // clientHash = H(N) xor H(g) | H(U) - byte[] username_digest = newDigest().digest(Util.trim(username.getBytes())); - username_digest = Util.trim(username_digest); - //String username_digest_string = new BigInteger(1, username_digest).toString(16); - clientHash.update(username_digest); - - // clientHash = H(N) xor H(g) | H(U) | s - //String salt_string = new BigInteger(1, salt_bytes).toString(16); - clientHash.update(salt_bytes); - - K = null; } /** @@ -198,13 +170,6 @@ public class LeapSRPSession { } A = g.modPow(a, N); Abytes = Util.trim(A.toByteArray()); - //String Abytes_string = new BigInteger(1, Abytes).toString(16); - - // clientHash = H(N) xor H(g) | H(U) | A - clientHash.update(Abytes); - - // serverHash = A - serverHash.update(Abytes); } return Abytes; } @@ -213,10 +178,52 @@ public class LeapSRPSession { * Calculates the parameter M1, to be sent to the SRP server. * It also updates hashes of client and server for further calculations in other methods. * @param Bbytes the parameter received from the server, in bytes + * @param bs * @return the parameter M1 * @throws NoSuchAlgorithmException */ - public byte[] response(byte[] Bbytes) throws NoSuchAlgorithmException { + public byte[] response(byte[] salt_bytes, byte[] Bbytes) throws NoSuchAlgorithmException { + // Calculate x = H(s | H(U | ':' | password)) + byte[] xb = calculatePasswordHash(username, password, salt_bytes); + this.x = new BigInteger(1, xb); + + // Calculate v = kg^x mod N + String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; + this.v = calculateV(k_string); + //String v_string = v.toString(16); + + + // H(N) + byte[] digest_of_n = newDigest().digest(N_bytes); + + // H(g) + byte[] digest_of_g = newDigest().digest(params.g); + + // clientHash = H(N) xor H(g) + byte[] xor_digest = xor(digest_of_n, digest_of_g, digest_of_g.length); + //String hxg_string = new BigInteger(1, xor_digest).toString(16); + clientHash.update(xor_digest); + + // clientHash = H(N) xor H(g) | H(U) + byte[] username_digest = newDigest().digest(Util.trim(username.getBytes())); + username_digest = Util.trim(username_digest); + //String username_digest_string = new BigInteger(1, username_digest).toString(16); + clientHash.update(username_digest); + + // clientHash = H(N) xor H(g) | H(U) | s + //String salt_string = new BigInteger(1, salt_bytes).toString(16); + clientHash.update(Util.trim(salt_bytes)); + + K = null; + + // clientHash = H(N) xor H(g) | H(U) | s | A | B + + byte[] Abytes = Util.trim(A.toByteArray()); + //String Abytes_string = new BigInteger(1, Abytes).toString(16); + + // clientHash = H(N) xor H(g) | H(U) | A + clientHash.update(Abytes); + // clientHash = H(N) xor H(g) | H(U) | s | A | B Bbytes = Util.trim(Bbytes); //String Bbytes_string = new BigInteger(1, Bbytes).toString(16); @@ -239,6 +246,7 @@ public class LeapSRPSession { byte[] M1 = Util.trim(clientHash.digest()); // serverHash = Astr + M + K + serverHash.update(Abytes); serverHash.update(M1); serverHash.update(K); return M1; diff --git a/src/se/leap/leapclient/LogInDialog.java b/src/se/leap/leapclient/LogInDialog.java index 74db92e..30984db 100644 --- a/src/se/leap/leapclient/LogInDialog.java +++ b/src/se/leap/leapclient/LogInDialog.java @@ -51,10 +51,10 @@ public class LogInDialog extends DialogFragment { String password = password_field.getText().toString().trim(); if(validPassword(password)) { interface_with_Dashboard.authenticate(username, password); - Toast.makeText(getActivity().getApplicationContext(), "It seems your URL is well formed", Toast.LENGTH_LONG).show(); + Toast.makeText(getActivity().getApplicationContext(), "Your password is valid", Toast.LENGTH_LONG).show(); } else { password_field.setText(""); - Toast.makeText(getActivity().getApplicationContext(), "It seems your URL is not well formed", Toast.LENGTH_LONG).show(); + Toast.makeText(getActivity().getApplicationContext(), "Your password is not valid: it should have at least 8 characters", Toast.LENGTH_LONG).show(); } } }) diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 04185ed..66eb3e6 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -131,14 +131,14 @@ public class ProviderAPI extends IntentService { try { JSONObject saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); if(saltAndB.length() > 0) { - byte[] B = saltAndB.getString("B").getBytes(); - salt = saltAndB.getString("salt"); + /*byte[] B = saltAndB.getString("B").getBytes(); params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256"); client = new LeapSRPSession(username, password, params); A = client.exponential(); - saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); + saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16));*/ + salt = saltAndB.getString("salt"); byte[] Bbytes = new BigInteger(saltAndB.getString("B"), 16).toByteArray(); - byte[] M1 = client.response(Bbytes); + byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), 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)); -- cgit v1.2.3 From ff3d469a9549e3670e097fc0e49c043c84e7b7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 1 May 2013 18:41:05 +0200 Subject: If the app is restarted with a custom provider selected, the client can request a log in without certificates problems. I've removed the addition of the certificate when downloaded eip-service.json, because I already do that in LeapHttpClient. Solves issue 2367: https://leap.se/code/issues/2367 --- src/se/leap/leapclient/ConfigHelper.java | 16 ++++++++++++---- src/se/leap/leapclient/Dashboard.java | 4 +++- src/se/leap/leapclient/LeapHttpClient.java | 7 ++++++- src/se/leap/leapclient/ProviderAPI.java | 8 ++++++-- src/se/leap/leapclient/ProviderListContent.java | 2 +- 5 files changed, 28 insertions(+), 9 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 7c52629..7684522 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -48,7 +48,7 @@ public class ConfigHelper { 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"; + final public static String eip_service_api_path = "config/eip-service.json"; final public static String NG_1024 = "eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3"; @@ -159,6 +159,9 @@ public class ConfigHelper { cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate)cf.generateCertificate(openFileInputStream(filename_to_save)); + if(keystore_trusted == null) { + getNewKeystore(null); + } keystore_trusted.setCertificateEntry(provider, cert); } catch (CertificateException e) { // TODO Auto-generated catch block @@ -179,10 +182,15 @@ 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); + if(leap_keystore != null) { + //keystore_trusted.load(leap_keystore, "uer92jf".toCharArray()); + keystore_trusted.load(null, null); + } else { + keystore_trusted.load(null, null); + } } finally { - leap_keystore.close(); + if(leap_keystore != null) + leap_keystore.close(); } } catch (KeyStoreException e) { // TODO Auto-generated catch block diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index 577092b..a68c048 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -43,7 +43,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf setContentView(R.layout.client_dashboard); preferences = getSharedPreferences(ConfigHelper.PREFERENCES_KEY,MODE_PRIVATE); - + if(ConfigHelper.shared_preferences == null) + ConfigHelper.setSharedPreferences(preferences); + // Check if we have preferences, run configuration wizard if not // TODO We should do a better check for config that this! if (!preferences.contains("provider") ) diff --git a/src/se/leap/leapclient/LeapHttpClient.java b/src/se/leap/leapclient/LeapHttpClient.java index d1908c3..f911982 100644 --- a/src/se/leap/leapclient/LeapHttpClient.java +++ b/src/se/leap/leapclient/LeapHttpClient.java @@ -51,8 +51,13 @@ public class LeapHttpClient extends DefaultHttpClient { } public static LeapHttpClient getInstance(Context context) { - if(client == null) + if(client == null) { client = new LeapHttpClient(context); + String cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.cert_key); + if(!cert_string.isEmpty()) { + ConfigHelper.addTrustedCertificate("recovered_certificate", cert_string); + } + } return client; } } diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 66eb3e6..4a28878 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -93,7 +93,7 @@ public class ProviderAPI extends IntentService { boolean danger_on = task.getBoolean(ConfigHelper.danger_on); try { String cert_string = getStringFromProvider(cert_url, danger_on); - ConfigHelper.addTrustedCertificate(provider_name, cert_string); + //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, danger_on); @@ -177,9 +177,11 @@ public class ProviderAPI extends IntentService { if(!json_response.isNull("errors") || json_response.has("errors")) { return new JSONObject(); } + + String session_id = ""; List cookies = client.getCookieStore().getCookies(); if(!cookies.isEmpty()) { - String session_id = cookies.get(0).getValue(); + session_id = cookies.get(0).getValue(); } return json_response; } @@ -190,6 +192,8 @@ public class ProviderAPI extends IntentService { HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + parameter_chain); HttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.COOKIE_STORE, client.getCookieStore()); + String session_id = client.getCookieStore().getCookies().get(0).getValue(); + int number_of_cookies = client.getCookieStore().getCookies().size(); HttpResponse getResponse = client.execute(put, localContext); HttpEntity responseEntity = getResponse.getEntity(); diff --git a/src/se/leap/leapclient/ProviderListContent.java b/src/se/leap/leapclient/ProviderListContent.java index 9ed7e9b..8cc349c 100644 --- a/src/se/leap/leapclient/ProviderListContent.java +++ b/src/se/leap/leapclient/ProviderListContent.java @@ -88,7 +88,7 @@ public class ProviderListContent { 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; + eip_service_json_url = file_contents.getString("api_uri") + "/" + file_contents.getString("api_version") + "/" + ConfigHelper.eip_service_api_path; cert_json_url = (String) file_contents.get("ca_cert_uri"); this.custom = custom; this.danger_on = danger_on; -- cgit v1.2.3 From a16605fd16a87faa5fa530288e01f0d7c7c7bf98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 1 May 2013 19:01:16 +0200 Subject: Logging in successfully to dev.bitmask.net :) The problem was that I needed to append the api_version to the api_uri. I was doing well in tests because I hardcoded the api urls, but in production code I was getting from provider.json only api_url and not api_version. --- src/se/leap/leapclient/ConfigHelper.java | 1 + src/se/leap/leapclient/Dashboard.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 7684522..72d966b 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -37,6 +37,7 @@ public class ConfigHelper { final public static String srpAuth = "srpAuth"; public static String logIn = "logIn"; public static String logOut = "logOut"; + public static String api_version_key = "api_version"; final public static String resultKey = "result"; final static String provider_key = "provider"; final static String cert_key = "cert"; diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index a68c048..67e33e7 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -170,7 +170,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf JSONObject provider_json; try { provider_json = new JSONObject(preferences.getString(ConfigHelper.provider_key, "")); - method_and_parameters.putString(ConfigHelper.api_url_key, provider_json.getString(ConfigHelper.api_url_key)); + method_and_parameters.putString(ConfigHelper.api_url_key, provider_json.getString(ConfigHelper.api_url_key) + "/" + provider_json.getString(ConfigHelper.api_version_key)); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); -- cgit v1.2.3 From 0cb5d9470127e280d2d955effd32b82e533d9de3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 7 May 2013 16:10:20 +0200 Subject: Ready to create a new branch for the download of the new user auth'ed certificate. Next step in this branch: detect what the selected provider support in terms of authenticated/anon users, and show login/logout methods consecuently. --- src/se/leap/leapclient/Dashboard.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index 67e33e7..0444502 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -199,7 +199,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if(resultCode == ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL){ setResult(RESULT_OK); Toast.makeText(getApplicationContext(), "Authentication succeeded", Toast.LENGTH_LONG).show(); - //TODO What should we do know? + //TODO Download certificate requesting /1/cert with session_id cookie + } else if(resultCode == ConfigHelper.SRP_AUTHENTICATION_FAILED) { setResult(RESULT_CANCELED); -- cgit v1.2.3 From fb5e26c2ff4f95dd826a3ce3545865ac4388b711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 8 May 2013 18:23:10 +0200 Subject: After loggin in successfully, the new client certificate is downloaded. It is stored in SharedPrefs, with ConfigHelper.cert_key (="cert") key. --- src/se/leap/leapclient/ConfigHelper.java | 27 +++-- src/se/leap/leapclient/ConfigurationWizard.java | 8 +- src/se/leap/leapclient/Dashboard.java | 31 ++++- src/se/leap/leapclient/LeapHttpClient.java | 17 ++- src/se/leap/leapclient/ProviderAPI.java | 146 ++++++++++++++++-------- 5 files changed, 170 insertions(+), 59 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 72d966b..98761b6 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -37,11 +37,15 @@ public class ConfigHelper { final public static String srpAuth = "srpAuth"; public static String logIn = "logIn"; public static String logOut = "logOut"; + public static String downloadUserAuthedCertificate = "downloadUserAuthedCertificate"; public static String api_version_key = "api_version"; final public static String resultKey = "result"; final static String provider_key = "provider"; + final static String main_cert_key = "main_cert"; final static String cert_key = "cert"; final static String eip_service_key = "eip"; + final static String session_id_cookie_key = "session_id_cookie_key"; + final static String session_id_key = "session_id"; public static final String PREFERENCES_KEY = "LEAPPreferences"; public static final String user_directory = "leap_android"; final public static String provider_main_url = "provider_main_url"; @@ -64,17 +68,23 @@ public class ConfigHelper { final public static int SRP_REGISTRATION_FAILED = 6; final public static int LOGOUT_SUCCESSFUL = 7; final public static int LOGOUT_FAILED = 8; + final public static int CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE = 9; + final public static int INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE = 10; 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; + //TODO This is not OK -> when reading provider.json it only shows "open" + if(shared_preferences != null) { + String content = shared_preferences.getString(shared_preferences_key, ""); + try { + JSONObject json_object = new JSONObject(content); + value = json_object.toString(); + /*JSONArray names = json_object.names(); + String key = names.getString(0); + value = json_object.getString(key);*/ + } catch (JSONException e) { + value = content; + } } return value; } @@ -184,6 +194,7 @@ public class ConfigHelper { // Initialize the keystore with the provided trusted certificates // Also provide the password of the keystore if(leap_keystore != null) { + InputStream android_default_keystore; //keystore_trusted.load(leap_keystore, "uer92jf".toCharArray()); keystore_trusted.load(null, null); } else { diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 3d16521..a50a8e6 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -150,6 +150,12 @@ public class ConfigurationWizard extends Activity ConfigHelper.rescueJSONException(e); } ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); + try { + ConfigHelper.saveSharedPref(ConfigHelper.danger_on, new JSONObject().put(ConfigHelper.danger_on, current_provider_item.danger_on)); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } private void downloadJSONFiles(ProviderItem current_provider_item) throws IOException { @@ -161,7 +167,7 @@ public class ConfigurationWizard extends Activity Bundle method_and_parameters = new Bundle(); 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.main_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); diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index 0444502..dbee9c4 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -1,5 +1,7 @@ package se.leap.leapclient; +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.cookie.BasicClientCookie; import org.json.JSONException; import org.json.JSONObject; @@ -194,18 +196,45 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf newFragment.show(fragment_transaction, ConfigHelper.logInDialog); } + private void downloadAuthedUserCertificate(Cookie session_id) { + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); + + Intent provider_API_command = new Intent(this, ProviderAPI.class); + + Bundle method_and_parameters = new Bundle(); + method_and_parameters.putString(ConfigHelper.session_id_cookie_key, session_id.getName()); + method_and_parameters.putString(ConfigHelper.session_id_key, session_id.getValue()); + + provider_API_command.putExtra(ConfigHelper.downloadUserAuthedCertificate, method_and_parameters); + provider_API_command.putExtra("receiver", providerAPI_result_receiver); + + startService(provider_API_command); + } + @Override public void onReceiveResult(int resultCode, Bundle resultData) { if(resultCode == ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL){ + String session_id_cookie_key = resultData.getString(ConfigHelper.session_id_cookie_key); + String session_id_string = resultData.getString(ConfigHelper.session_id_key); setResult(RESULT_OK); Toast.makeText(getApplicationContext(), "Authentication succeeded", Toast.LENGTH_LONG).show(); //TODO Download certificate requesting /1/cert with session_id cookie - + Cookie session_id = new BasicClientCookie(session_id_cookie_key, session_id_string); + downloadAuthedUserCertificate(session_id); } else if(resultCode == ConfigHelper.SRP_AUTHENTICATION_FAILED) { setResult(RESULT_CANCELED); Toast.makeText(getApplicationContext(), "Authentication failed", Toast.LENGTH_LONG).show(); } + else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE) { + setResult(RESULT_CANCELED); + Toast.makeText(getApplicationContext(), "Your own cert has been correctly downloaded", Toast.LENGTH_LONG).show(); + } + else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE) { + setResult(RESULT_CANCELED); + Toast.makeText(getApplicationContext(), "Your own cert has incorrectly been downloaded", Toast.LENGTH_LONG).show(); + } } } diff --git a/src/se/leap/leapclient/LeapHttpClient.java b/src/se/leap/leapclient/LeapHttpClient.java index f911982..4de7ae0 100644 --- a/src/se/leap/leapclient/LeapHttpClient.java +++ b/src/se/leap/leapclient/LeapHttpClient.java @@ -9,6 +9,8 @@ import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.SingleClientConnManager; +import org.json.JSONException; +import org.json.JSONObject; import android.content.Context; @@ -49,13 +51,20 @@ public class LeapHttpClient extends DefaultHttpClient { throw new AssertionError(e); } } - + public static LeapHttpClient getInstance(Context context) { if(client == null) { client = new LeapHttpClient(context); - String cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.cert_key); - if(!cert_string.isEmpty()) { - ConfigHelper.addTrustedCertificate("recovered_certificate", cert_string); + String cert_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.main_cert_key); + String cert_string; + try { + cert_string = new JSONObject(cert_json_string).getString(ConfigHelper.main_cert_key); + if(!cert_string.isEmpty()) { + ConfigHelper.addTrustedCertificate("recovered_certificate", cert_string); + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } } return client; diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 4a28878..bdfd620 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -12,7 +12,12 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.List; +import java.net.CookieHandler; +import java.net.CookieManager; +import java.net.HttpCookie; +import java.net.HttpURLConnection; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; import java.util.Scanner; @@ -25,13 +30,16 @@ import javax.net.ssl.TrustManagerFactory; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.CookieStore; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.protocol.ClientContext; import org.apache.http.cookie.Cookie; +import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.jboss.security.Util; @@ -73,10 +81,20 @@ public class ProviderAPI extends IntentService { receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY); } else if ((task = task_for.getBundleExtra(ConfigHelper.srpAuth)) != null) { - if(authenticateBySRP(task)) - receiver.send(ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL, Bundle.EMPTY); - else - receiver.send(ConfigHelper.SRP_AUTHENTICATION_FAILED, Bundle.EMPTY); + try { + JSONObject session_idAndResult = authenticateBySRP(task); + if(session_idAndResult.getBoolean(ConfigHelper.resultKey)) { + Bundle session_id_bundle = new Bundle(); + session_id_bundle.putString(ConfigHelper.session_id_cookie_key, session_idAndResult.getString(ConfigHelper.session_id_cookie_key)); + session_id_bundle.putString(ConfigHelper.session_id_key, session_idAndResult.getString(ConfigHelper.session_id_key)); + receiver.send(ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL, session_id_bundle); + } else { + receiver.send(ConfigHelper.SRP_AUTHENTICATION_FAILED, Bundle.EMPTY); + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } else if ((task = task_for.getBundleExtra(ConfigHelper.logOut)) != null) { if(logOut(task)) @@ -84,18 +102,24 @@ public class ProviderAPI extends IntentService { else receiver.send(ConfigHelper.LOGOUT_FAILED, Bundle.EMPTY); } + else if ((task = task_for.getBundleExtra(ConfigHelper.downloadUserAuthedCertificate)) != null) { + if(getNewCert(task)) + receiver.send(ConfigHelper.CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE, Bundle.EMPTY); + else + receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE, Bundle.EMPTY); + } } private boolean downloadJsonFiles(Bundle task) { - String provider_name = task.getString(ConfigHelper.provider_key); - String cert_url = task.getString(ConfigHelper.cert_key); + //String provider_name = task.getString(ConfigHelper.provider_key); + String cert_url = task.getString(ConfigHelper.main_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, danger_on); //ConfigHelper.addTrustedCertificate(provider_name, cert_string); - JSONObject cert_json = new JSONObject("{ \"certificate\" : \"" + cert_string + "\"}"); - ConfigHelper.saveSharedPref(ConfigHelper.cert_key, cert_json); + JSONObject cert_json = new JSONObject().put(ConfigHelper.main_cert_key, cert_string); + ConfigHelper.saveSharedPref(ConfigHelper.main_cert_key, cert_json); JSONObject eip_service_json = getJSONFromProvider(eip_service_json_url, danger_on); ConfigHelper.saveSharedPref(ConfigHelper.eip_service_key, eip_service_json); return true; @@ -117,7 +141,9 @@ public class ProviderAPI extends IntentService { return false; } - private boolean authenticateBySRP(Bundle task) { + private JSONObject authenticateBySRP(Bundle task) { + JSONObject successfulAndsession_id = new JSONObject(); + String username = (String) task.get(ConfigHelper.username_key); String password = (String) task.get(ConfigHelper.password_key); String authentication_server = (String) task.get(ConfigHelper.api_url_key); @@ -131,38 +157,36 @@ public class ProviderAPI extends IntentService { try { JSONObject saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); if(saltAndB.length() > 0) { - /*byte[] B = saltAndB.getString("B").getBytes(); - params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256"); - client = new LeapSRPSession(username, password, params); - A = client.exponential(); - saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16));*/ salt = saltAndB.getString("salt"); byte[] Bbytes = new BigInteger(saltAndB.getString("B"), 16).toByteArray(); byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); - byte[] M2 = sendM1ToSRPServer(authentication_server, username, M1); - if( client.verify(M2) == false ) + //byte[] M2 = sendM1ToSRPServer(authentication_server, username, M1); + JSONObject session_idAndM2 = sendM1ToSRPServer(authentication_server, username, M1); + if( client.verify((byte[])session_idAndM2.get("M2")) == false ) { //throw new SecurityException("Failed to validate server reply: M2 = " + new BigInteger(1, M2).toString(16)); - return false; - return true; + successfulAndsession_id.put(ConfigHelper.resultKey, false); + return successfulAndsession_id; + } else { + successfulAndsession_id.put(ConfigHelper.resultKey, true); + successfulAndsession_id.put(ConfigHelper.session_id_key, session_idAndM2.getString(ConfigHelper.session_id_key)); + successfulAndsession_id.put(ConfigHelper.session_id_cookie_key, session_idAndM2.getString(ConfigHelper.session_id_cookie_key)); + return successfulAndsession_id; + } } - else return false; } catch (ClientProtocolException e1) { // TODO Auto-generated catch block e1.printStackTrace(); - return false; } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); - return false; } catch (JSONException e1) { // TODO Auto-generated catch block e1.printStackTrace(); - return false; } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); - return false; } + return successfulAndsession_id; } private JSONObject sendAToSRPServer(String server_url, String username, String clientA) throws ClientProtocolException, IOException, JSONException { @@ -186,7 +210,8 @@ public class ProviderAPI extends IntentService { return json_response; } - private byte[] sendM1ToSRPServer(String server_url, String username, byte[] m1) throws ClientProtocolException, IOException, JSONException { + private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) throws ClientProtocolException, IOException, JSONException { + JSONObject session_idAndM2 = new JSONObject(); DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); String parameter_chain = "client_auth" + "=" + new BigInteger(1, Util.trim(m1)).toString(16); HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + parameter_chain); @@ -200,12 +225,15 @@ public class ProviderAPI extends IntentService { String plain_response = new Scanner(responseEntity.getContent()).useDelimiter("\\A").next(); JSONObject json_response = new JSONObject(plain_response); if(!json_response.isNull("errors") || json_response.has("errors")) { - return new byte[0]; + return session_idAndM2; } - + + number_of_cookies = client.getCookieStore().getCookies().size(); byte[] M2_not_trimmed = new BigInteger(json_response.getString("M2"), 16).toByteArray(); - return Util.trim(M2_not_trimmed); - //return M2_not_trimmed; + session_idAndM2.put(ConfigHelper.session_id_cookie_key, client.getCookieStore().getCookies().get(0).getName()); + session_idAndM2.put(ConfigHelper.session_id_key, client.getCookieStore().getCookies().get(0).getValue()); + session_idAndM2.put("M2", Util.trim(M2_not_trimmed)); + return session_idAndM2; } private boolean downloadNewProviderDotJSON(Bundle task) { @@ -229,7 +257,7 @@ public class ProviderAPI extends IntentService { } else { String filename = provider_name + "_provider.json".replaceFirst("__", "_"); ConfigHelper.saveFile(filename, provider_json.toString()); - ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); + //ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, ConfigHelper.openFileInputStream(filename), custom, danger_on)); return true; @@ -301,7 +329,8 @@ public class ProviderAPI extends IntentService { try { cf = CertificateFactory.getInstance("X.509"); - String cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.cert_key); + String cert_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.main_cert_key); + String cert_string = new JSONObject(cert_json_string).getString(ConfigHelper.main_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); @@ -348,24 +377,12 @@ public class ProviderAPI extends IntentService { } catch (KeyManagementException e) { // TODO Auto-generated catch block e.printStackTrace(); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } return json_file_content; } - - private String getStringFromProvider_2(String string_url) throws IOException { - - String json_file_content = ""; - - DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); - HttpGet get = new HttpGet(string_url); - // Execute the GET call and obtain the response - HttpResponse getResponse = client.execute(get); - HttpEntity responseEntity = getResponse.getEntity(); - - json_file_content = new Scanner(responseEntity.getContent()).useDelimiter("\\A").next(); - - return json_file_content; - } private JSONObject getJSONFromProvider(String json_url, boolean danger_on) throws JSONException { String json_file_content = getStringFromProvider(json_url, danger_on); @@ -391,4 +408,43 @@ public class ProviderAPI extends IntentService { } return true; } + + private boolean getNewCert(Bundle task) { + String provider_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.provider_key); + HttpCookie session_id_cookie = new HttpCookie(task.getString(ConfigHelper.session_id_cookie_key), task.getString(ConfigHelper.session_id_key)); + + try { + JSONObject provider_json = new JSONObject(provider_json_string); + URL provider_main_url = new URL(provider_json.getString(ConfigHelper.api_url_key).replace("api.", "")); + String new_cert_string_url = provider_main_url.getProtocol() + "://" + provider_main_url.getHost() + "/" + provider_json.getString(ConfigHelper.api_version_key) + "/" + ConfigHelper.cert_key; + + CookieManager cookieManager = new CookieManager(); + cookieManager.getCookieStore().add(provider_main_url.toURI(), session_id_cookie); + CookieHandler.setDefault(cookieManager); + + String danger_on_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.danger_on); + boolean danger_on = new JSONObject(danger_on_json_string).getBoolean(ConfigHelper.danger_on); + String cert_string = getStringFromProvider(new_cert_string_url, danger_on); + if(!cert_string.isEmpty()) { + JSONObject cert_json = new JSONObject().put(ConfigHelper.cert_key, cert_string); + ConfigHelper.saveSharedPref(ConfigHelper.cert_key, cert_json); + return true; + } else { + return false; + } + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (URISyntaxException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return true; + } } -- cgit v1.2.3 From 84a11bb1620d2b9080992427c847b58007f2304a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 9 May 2013 17:29:38 +0200 Subject: Log in and Log out options are shown only if allow registration is true. Allow registration is present in provider.json. Provider.json is downloaded from both preseeded and custom providers. Authentication success or fail is notified correctly to the user. --- src/se/leap/leapclient/ConfigHelper.java | 14 +++- src/se/leap/leapclient/ConfigurationWizard.java | 78 ++++++++++++++------- src/se/leap/leapclient/Dashboard.java | 62 ++++++++++++++--- src/se/leap/leapclient/ProviderAPI.java | 90 +++++++++++++++++++++---- src/se/leap/leapclient/ProviderListContent.java | 5 +- 5 files changed, 202 insertions(+), 47 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 98761b6..0dab26f 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -16,7 +16,6 @@ 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; @@ -30,6 +29,7 @@ public class ConfigHelper { private static KeyStore keystore_trusted; final static String downloadJsonFilesBundleExtra = "downloadJSONFiles"; + final static String updateProviderDotJSON = "updateProviderDotJSON"; final static String downloadNewProviderDotJSON = "downloadNewProviderDotJSON"; final public static String logInDialog = "logInDialog"; final public static String newProviderDialog = "logInDialog"; @@ -41,6 +41,7 @@ public class ConfigHelper { public static String api_version_key = "api_version"; final public static String resultKey = "result"; final static String provider_key = "provider"; + final static String service_key = "service"; final static String main_cert_key = "main_cert"; final static String cert_key = "cert"; final static String eip_service_key = "eip"; @@ -48,11 +49,15 @@ public class ConfigHelper { final static String session_id_key = "session_id"; public static final String PREFERENCES_KEY = "LEAPPreferences"; public static final String user_directory = "leap_android"; + final public static String provider_name = "provider_name"; final public static String provider_main_url = "provider_main_url"; + final public static String provider_json_url = "provider_json_url"; + final public static String custom = "custom"; final public static String danger_on = "danger_on"; 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 allow_registration_key = "allow_registration"; final public static String eip_service_api_path = "config/eip-service.json"; final public static String NG_1024 = @@ -70,6 +75,8 @@ public class ConfigHelper { final public static int LOGOUT_FAILED = 8; final public static int CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE = 9; final public static int INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE = 10; + final public static int CORRECTLY_UPDATED_PROVIDER_DOT_JSON = 11; + final public static int INCORRECTLY_UPDATED_PROVIDER_DOT_JSON = 12; static String getStringFromSharedPref(String shared_preferences_key) { String value = ""; @@ -194,7 +201,6 @@ public class ConfigHelper { // Initialize the keystore with the provided trusted certificates // Also provide the password of the keystore if(leap_keystore != null) { - InputStream android_default_keystore; //keystore_trusted.load(leap_keystore, "uer92jf".toCharArray()); keystore_trusted.load(null, null); } else { @@ -221,7 +227,9 @@ public class ConfigHelper { public static int getSrpAuthenticationFailed() { return SRP_AUTHENTICATION_FAILED; - }static String extractProviderName(String provider_main_url) { + } + + static String extractProviderName(String provider_main_url) { return null; } diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index a50a8e6..ba17f9b 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -3,6 +3,7 @@ package se.leap.leapclient; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.net.URL; import java.util.Iterator; import java.util.Scanner; @@ -133,29 +134,27 @@ public class ConfigurationWizard extends Activity } } - private void saveProviderJson(ProviderItem current_provider_item) { - AssetManager assets_manager = getAssets(); - JSONObject provider_json = new JSONObject(); - try { - String provider_contents = ""; - if(!current_provider_item.custom) - provider_contents = new Scanner(new InputStreamReader(assets_manager.open(current_provider_item.provider_json_filename))).useDelimiter("\\A").next(); - else - provider_contents = new Scanner(ConfigHelper.openFileInputStream(current_provider_item.provider_json_filename)).useDelimiter("\\A").next(); - provider_json = new JSONObject(provider_contents); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (JSONException e) { - ConfigHelper.rescueJSONException(e); - } - ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); - try { - ConfigHelper.saveSharedPref(ConfigHelper.danger_on, new JSONObject().put(ConfigHelper.danger_on, current_provider_item.danger_on)); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + private void saveProviderJson(ProviderItem current_provider_item) { + JSONObject provider_json = new JSONObject(); + try { + String provider_contents = ""; + if(!current_provider_item.custom) { + //provider_contents = new Scanner(new InputStreamReader(assets_manager.open(current_provider_item.provider_json_filename))).useDelimiter("\\A").next(); + updateProviderDotJson(current_provider_item.name, current_provider_item.provider_json_url, current_provider_item.danger_on); + } else { + provider_contents = new Scanner(ConfigHelper.openFileInputStream(current_provider_item.provider_json_filename)).useDelimiter("\\A").next(); + provider_json = new JSONObject(provider_contents); + ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); + try { + ConfigHelper.saveSharedPref(ConfigHelper.danger_on, new JSONObject().put(ConfigHelper.danger_on, current_provider_item.danger_on)); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } catch (JSONException e) { + ConfigHelper.rescueJSONException(e); + } } private void downloadJSONFiles(ProviderItem current_provider_item) throws IOException { @@ -205,6 +204,23 @@ public class ConfigurationWizard extends Activity startService(provider_API_command); } + + public void updateProviderDotJson(String provider_name, String provider_json_url, boolean danger_on) { + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); + + Intent provider_API_command = new Intent(this, ProviderAPI.class); + + Bundle method_and_parameters = new Bundle(); + method_and_parameters.putString(ConfigHelper.provider_name, provider_name); + method_and_parameters.putString(ConfigHelper.provider_json_url, provider_json_url); + method_and_parameters.putBoolean(ConfigHelper.danger_on, danger_on); + + provider_API_command.putExtra(ConfigHelper.updateProviderDotJSON, method_and_parameters); + provider_API_command.putExtra("receiver", providerAPI_result_receiver); + + startService(provider_API_command); + } @Override public void onReceiveResult(int resultCode, Bundle resultData) { @@ -224,5 +240,21 @@ public class ConfigurationWizard extends Activity setResult(RESULT_CANCELED); Toast.makeText(getApplicationContext(), "You have not entered a LEAP provider URL", Toast.LENGTH_LONG).show(); } + else if(resultCode == ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON) { + JSONObject provider_json; + try { + provider_json = new JSONObject(resultData.getString(ConfigHelper.provider_key)); + boolean danger_on = resultData.getBoolean(ConfigHelper.danger_on); + ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); + ConfigHelper.saveSharedPref(ConfigHelper.danger_on, new JSONObject().put(ConfigHelper.danger_on, danger_on)); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + else if(resultCode == ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON) { + Toast.makeText(getApplicationContext(), "Install a new version of this app.", Toast.LENGTH_LONG).show(); + } + } } diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index dbee9c4..c8cbc5a 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -11,7 +11,6 @@ import se.leap.openvpn.MainActivity; import android.app.Activity; import android.app.DialogFragment; import android.app.Fragment; -import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.Intent; import android.content.SharedPreferences; @@ -115,6 +114,25 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf // TODO attach settings button to something } + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + String provider_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.provider_key); + try { + JSONObject provider_json = new JSONObject(provider_json_string); + JSONObject service_description = provider_json.getJSONObject(ConfigHelper.service_key); + if(service_description.getBoolean(ConfigHelper.allow_registration_key)) { + menu.findItem(R.id.login_button).setVisible(true); + menu.findItem(R.id.logout_button).setVisible(true); + return true; + } + } catch (JSONException e) { + menu.findItem(R.id.login_button).setVisible(false); + menu.findItem(R.id.logout_button).setVisible(false); + return false; + } + return false; + } + @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. @@ -147,6 +165,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0); logInDialog(view); return true; + case R.id.logout_button: + logOut(); + return true; default: return super.onOptionsItemSelected(item); } @@ -184,6 +205,28 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startService(provider_API_command); } + public void logOut() { + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); + Intent provider_API_command = new Intent(this, ProviderAPI.class); + + Bundle method_and_parameters = new Bundle(); + + JSONObject provider_json; + try { + provider_json = new JSONObject(preferences.getString(ConfigHelper.provider_key, "")); + method_and_parameters.putString(ConfigHelper.api_url_key, provider_json.getString(ConfigHelper.api_url_key) + "/" + provider_json.getString(ConfigHelper.api_version_key)); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + provider_API_command.putExtra(ConfigHelper.logOut, method_and_parameters); + provider_API_command.putExtra("receiver", providerAPI_result_receiver); + + startService(provider_API_command); + } + public void logInDialog(View view) { FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); Fragment previous_log_in_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.logInDialog); @@ -219,19 +262,22 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf String session_id_string = resultData.getString(ConfigHelper.session_id_key); setResult(RESULT_OK); Toast.makeText(getApplicationContext(), "Authentication succeeded", Toast.LENGTH_LONG).show(); - //TODO Download certificate requesting /1/cert with session_id cookie + Cookie session_id = new BasicClientCookie(session_id_cookie_key, session_id_string); downloadAuthedUserCertificate(session_id); - } - else if(resultCode == ConfigHelper.SRP_AUTHENTICATION_FAILED) { + } else if(resultCode == ConfigHelper.SRP_AUTHENTICATION_FAILED) { setResult(RESULT_CANCELED); Toast.makeText(getApplicationContext(), "Authentication failed", Toast.LENGTH_LONG).show(); - } - else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE) { + } else if(resultCode == ConfigHelper.LOGOUT_SUCCESSFUL) { + setResult(RESULT_OK); + Toast.makeText(getApplicationContext(), "Logged out", Toast.LENGTH_LONG).show(); + } else if(resultCode == ConfigHelper.LOGOUT_FAILED) { + setResult(RESULT_CANCELED); + Toast.makeText(getApplicationContext(), "Didn't logged out", Toast.LENGTH_LONG).show(); + } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE) { setResult(RESULT_CANCELED); Toast.makeText(getApplicationContext(), "Your own cert has been correctly downloaded", Toast.LENGTH_LONG).show(); - } - else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE) { + } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE) { setResult(RESULT_CANCELED); Toast.makeText(getApplicationContext(), "Your own cert has incorrectly been downloaded", Toast.LENGTH_LONG).show(); } diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index bdfd620..b44c997 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -15,7 +15,6 @@ import java.util.List; import java.net.CookieHandler; import java.net.CookieManager; import java.net.HttpCookie; -import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; @@ -30,16 +29,12 @@ import javax.net.ssl.TrustManagerFactory; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.CookieStore; import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.protocol.ClientContext; import org.apache.http.cookie.Cookie; -import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.jboss.security.Util; @@ -74,6 +69,24 @@ public class ProviderAPI extends IntentService { else receiver.send(ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY); } + else if ((task = task_for.getBundleExtra(ConfigHelper.updateProviderDotJSON)) != null) { + JSONObject result = updateProviderDotJSON(task); + boolean successful; + try { + successful = result.getBoolean(ConfigHelper.resultKey); + if(successful) { + Bundle provider_dot_json_and_danger_on = new Bundle(); + provider_dot_json_and_danger_on.putBoolean(ConfigHelper.danger_on, result.getBoolean(ConfigHelper.danger_on)); + provider_dot_json_and_danger_on.putString(ConfigHelper.provider_key, result.getJSONObject(ConfigHelper.provider_key).toString()); + receiver.send(ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON, provider_dot_json_and_danger_on); + } else { + receiver.send(ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON, Bundle.EMPTY); + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } else if ((task = task_for.getBundleExtra(ConfigHelper.downloadNewProviderDotJSON)) != null) { if(downloadNewProviderDotJSON(task)) receiver.send(ConfigHelper.CUSTOM_PROVIDER_ADDED, Bundle.EMPTY); @@ -172,6 +185,9 @@ public class ProviderAPI extends IntentService { successfulAndsession_id.put(ConfigHelper.session_id_cookie_key, session_idAndM2.getString(ConfigHelper.session_id_cookie_key)); return successfulAndsession_id; } + } else { + successfulAndsession_id.put(ConfigHelper.resultKey, false); + return successfulAndsession_id; } } catch (ClientProtocolException e1) { // TODO Auto-generated catch block @@ -236,6 +252,50 @@ public class ProviderAPI extends IntentService { return session_idAndM2; } + private JSONObject updateProviderDotJSON(Bundle task) { + JSONObject result = new JSONObject(); + boolean custom = task.getBoolean(ConfigHelper.custom); + boolean danger_on = task.getBoolean(ConfigHelper.danger_on); + String provider_json_url = task.getString(ConfigHelper.provider_json_url); + String provider_name = task.getString(ConfigHelper.provider_name); + + JSONObject provider_json = null; + try { + provider_json = getJSONFromProvider(provider_json_url, danger_on); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + try { + return result.put(ConfigHelper.resultKey, false); + } catch (JSONException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + + if(provider_json == null) { + try { + return result.put(ConfigHelper.resultKey, false); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } else { + String filename = provider_name + "_provider.json".replaceFirst("__", "_"); + ConfigHelper.saveFile(filename, provider_json.toString()); + //ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); + + ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, filename, custom, danger_on)); + try { + return result.put(ConfigHelper.resultKey, true).put(ConfigHelper.provider_key, provider_json).put(ConfigHelper.danger_on, danger_on); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return result; + } + private boolean downloadNewProviderDotJSON(Bundle task) { boolean custom = true; boolean danger_on = task.getBoolean(ConfigHelper.danger_on); @@ -259,7 +319,7 @@ public class ProviderAPI extends IntentService { ConfigHelper.saveFile(filename, provider_json.toString()); //ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); - ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, ConfigHelper.openFileInputStream(filename), custom, danger_on)); + ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, filename, custom, danger_on)); return true; } } @@ -291,10 +351,6 @@ public class ProviderAPI extends IntentService { } 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) { @@ -388,23 +444,33 @@ public class ProviderAPI extends IntentService { String json_file_content = getStringFromProvider(json_url, danger_on); return new JSONObject(json_file_content); } + + private String guessURL(String provider_main_url) { + return provider_main_url + "/provider.json"; + } private boolean logOut(Bundle task) { DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); int session_id_index = 0; //String delete_url = task.getString(ConfigHelper.srp_server_url_key) + "/sessions/" + client.getCookieStore().getCookies().get(0).getValue(); - String delete_url = task.getString(ConfigHelper.api_url_key) + "/logout" + "?authenticity_token=" + client.getCookieStore().getCookies().get(session_id_index).getValue(); - HttpDelete delete = new HttpDelete(delete_url); try { + String delete_url = task.getString(ConfigHelper.api_url_key) + "/logout" + "?authenticity_token=" + client.getCookieStore().getCookies().get(session_id_index).getValue(); + HttpDelete delete = new HttpDelete(delete_url); HttpResponse getResponse = client.execute(delete); HttpEntity responseEntity = getResponse.getEntity(); responseEntity.consumeContent(); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); + return false; + } catch (IndexOutOfBoundsException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); + return false; } return true; } diff --git a/src/se/leap/leapclient/ProviderListContent.java b/src/se/leap/leapclient/ProviderListContent.java index 8cc349c..d4bb6a9 100644 --- a/src/se/leap/leapclient/ProviderListContent.java +++ b/src/se/leap/leapclient/ProviderListContent.java @@ -78,8 +78,10 @@ public class ProviderListContent { } } - public ProviderItem(String name, String provider_json_url, FileInputStream provider_json, boolean custom, boolean danger_on) { + public ProviderItem(String name, String provider_json_url, String provider_json_filename, boolean custom, boolean danger_on) { + + FileInputStream provider_json = ConfigHelper.openFileInputStream(provider_json_filename); try { byte[] urls_file_bytes = new byte[provider_json.available()]; provider_json.read(urls_file_bytes); @@ -88,6 +90,7 @@ public class ProviderListContent { id = name; this.name = name; this.provider_json_url = provider_json_url; + this.provider_json_filename = provider_json_filename; eip_service_json_url = file_contents.getString("api_uri") + "/" + file_contents.getString("api_version") + "/" + ConfigHelper.eip_service_api_path; cert_json_url = (String) file_contents.get("ca_cert_uri"); this.custom = custom; -- cgit v1.2.3 From 80a8106afc8956008beb9d1ed9396f1d695d5b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 13 May 2013 20:39:34 +0200 Subject: A bit more clean. I've upper cased ConfigHelper constants. I've created a new method in ConfigHelper, to send requests to a server, that it's used when sending A and M1. --- src/se/leap/leapclient/ConfigHelper.java | 185 ++++++--------- src/se/leap/leapclient/ConfigurationWizard.java | 210 ++++++++--------- src/se/leap/leapclient/Dashboard.java | 40 ++-- src/se/leap/leapclient/LeapHttpClient.java | 96 ++++---- src/se/leap/leapclient/LeapSRPSession.java | 39 +--- src/se/leap/leapclient/LogInDialog.java | 67 +++--- src/se/leap/leapclient/NewProviderDialog.java | 7 +- src/se/leap/leapclient/Provider.java | 2 +- src/se/leap/leapclient/ProviderAPI.java | 289 +++++++++--------------- src/se/leap/leapclient/ProviderListContent.java | 2 +- 10 files changed, 391 insertions(+), 546 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 0dab26f..5d44f00 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -1,6 +1,5 @@ package se.leap.leapclient; - import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; @@ -28,103 +27,94 @@ public class ConfigHelper { public static SharedPreferences shared_preferences; private static KeyStore keystore_trusted; - final static String downloadJsonFilesBundleExtra = "downloadJSONFiles"; - final static String updateProviderDotJSON = "updateProviderDotJSON"; - final static String downloadNewProviderDotJSON = "downloadNewProviderDotJSON"; - final public static String logInDialog = "logInDialog"; - final public static String newProviderDialog = "logInDialog"; - final public static String srpRegister = "srpRegister"; - final public static String srpAuth = "srpAuth"; - public static String logIn = "logIn"; - public static String logOut = "logOut"; - public static String downloadUserAuthedCertificate = "downloadUserAuthedCertificate"; - public static String api_version_key = "api_version"; - final public static String resultKey = "result"; - final static String provider_key = "provider"; - final static String service_key = "service"; - final static String main_cert_key = "main_cert"; - final static String cert_key = "cert"; - final static String eip_service_key = "eip"; - final static String session_id_cookie_key = "session_id_cookie_key"; - final static String session_id_key = "session_id"; - public static final String PREFERENCES_KEY = "LEAPPreferences"; - public static final String user_directory = "leap_android"; - final public static String provider_name = "provider_name"; - final public static String provider_main_url = "provider_main_url"; - final public static String provider_json_url = "provider_json_url"; - final public static String custom = "custom"; - final public static String danger_on = "danger_on"; - 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 allow_registration_key = "allow_registration"; - final public static String eip_service_api_path = "config/eip-service.json"; + final public static String + DOWNLOAD_JSON_FILES_BUNDLE_EXTRA = "downloadJSONFiles", + UPDATE_PROVIDER_DOTJSON = "updateProviderDotJSON", + DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON", + LOG_IN_DIALOG = "logInDialog", + NEW_PROVIDER_DIALOG = "logInDialog", + SRP_REGISTER = "srpRegister", + SRP_AUTH = "srpAuth", + LOG_IN = "logIn", + LOG_OUT = "logOut", + DOWNLOAD_USER_AUTHED_CERTIFICATE = "downloadUserAuthedCertificate", + API_VERSION_KEY = "api_version", + RESULT_KEY = "result", + PROVIDER_KEY = "provider", + SERVICE_KEY = "service", + MAIN_CERT_KEY = "main_cert", + CERT_KEY = "cert", + EIP_SERVICE_KEY = "eip", + SALT_KEY = "salt", + SESSION_ID_COOKIE_KEY = "session_id_cookie_key", + SESSION_ID_KEY = "session_id", + PREFERENCES_KEY = "LEAPPreferences", + USER_DIRECTORY = "leap_android", + PROVIDER_NAME = "provider_name", + PROVIDER_MAIN_URL = "provider_main_url", + PROVIDER_JSON_URL = "provider_json_url", + CUSTOM = "custom", + DANGER_ON = "danger_on", + API_URL_KEY = "api_uri", + USERNAME_KEY = "username", + PASSWORD_KEY = "password", + ALLOW_REGISTRATION_KEY = "allow_registration", + EIP_SERVICE_API_PATH = "config/eip-service.json" + ; - final public static String NG_1024 = - "eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3"; - final public static BigInteger g = BigInteger.valueOf(2); + final public static String NG_1024 = + "eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3"; + final public static BigInteger G = new BigInteger("2"); + + final public static int + CUSTOM_PROVIDER_ADDED = 0, + CORRECTLY_DOWNLOADED_JSON_FILES = 1, + INCORRECTLY_DOWNLOADED_JSON_FILES = 2, + SRP_AUTHENTICATION_SUCCESSFUL = 3, + SRP_AUTHENTICATION_FAILED = 4, + SRP_REGISTRATION_SUCCESSFUL = 5, + SRP_REGISTRATION_FAILED = 6, + LOGOUT_SUCCESSFUL = 7, + LOGOUT_FAILED = 8, + CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE = 9, + INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE = 10, + CORRECTLY_UPDATED_PROVIDER_DOT_JSON = 11, + INCORRECTLY_UPDATED_PROVIDER_DOT_JSON = 12 + ; - final public static int CUSTOM_PROVIDER_ADDED = 0; - final public static int CORRECTLY_DOWNLOADED_JSON_FILES = 1; - final public static int INCORRECTLY_DOWNLOADED_JSON_FILES = 2; - final public static int SRP_AUTHENTICATION_SUCCESSFUL = 3; - final public static int SRP_AUTHENTICATION_FAILED = 4; - final public static int SRP_REGISTRATION_SUCCESSFUL = 5; - final public static int SRP_REGISTRATION_FAILED = 6; - final public static int LOGOUT_SUCCESSFUL = 7; - final public static int LOGOUT_FAILED = 8; - final public static int CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE = 9; - final public static int INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE = 10; - final public static int CORRECTLY_UPDATED_PROVIDER_DOT_JSON = 11; - final public static int INCORRECTLY_UPDATED_PROVIDER_DOT_JSON = 12; + public static void saveSharedPref(String shared_preferences_key, JSONObject content) { + + SharedPreferences.Editor shared_preferences_editor = shared_preferences + .edit(); + shared_preferences_editor.putString(shared_preferences_key, + content.toString()); + shared_preferences_editor.commit(); + } - static String getStringFromSharedPref(String shared_preferences_key) { + public static String getStringFromSharedPref(String shared_preferences_key) { String value = ""; - //TODO This is not OK -> when reading provider.json it only shows "open" if(shared_preferences != null) { String content = shared_preferences.getString(shared_preferences_key, ""); try { JSONObject json_object = new JSONObject(content); value = json_object.toString(); - /*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 - .edit(); - shared_preferences_editor.putString(shared_preferences_key, - content.toString()); - shared_preferences_editor.commit(); - System.out.println("Shared preferences updated: key = " - + shared_preferences_key - + " Content = " - + shared_preferences.getString( - shared_preferences_key, "Default")); - } - static void rescueJSONException(JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - static void saveFile(String filename, String content) { + public static void saveFile(String filename, String content) { File root = Environment.getExternalStorageDirectory(); - File leap_dir = new File(root.getAbsolutePath() + File.separator + user_directory); + File leap_dir = new File(root.getAbsolutePath() + File.separator + USER_DIRECTORY); if (!leap_dir.isDirectory()) { leap_dir.mkdir(); } try { if (!leap_dir.isDirectory()) { throw new IOException( - "Unable to create directory " + user_directory + ". Maybe the SD card is mounted?"); + "Unable to create directory " + USER_DIRECTORY + ". Maybe the SD card is mounted?"); } File outputFile = new File(leap_dir, filename); BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile)); @@ -135,10 +125,10 @@ public class ConfigHelper { } } - static FileInputStream openFileInputStream(String filename) { + public static FileInputStream openFileInputStream(String filename) { FileInputStream input_stream = null; File root = Environment.getExternalStorageDirectory(); - File leap_dir = new File(root.getAbsolutePath() + File.separator + user_directory); + File leap_dir = new File(root.getAbsolutePath() + File.separator + USER_DIRECTORY); try { input_stream = new FileInputStream(leap_dir + File.separator + filename); } catch (FileNotFoundException e) { @@ -178,7 +168,8 @@ public class ConfigHelper { X509Certificate cert = (X509Certificate)cf.generateCertificate(openFileInputStream(filename_to_save)); if(keystore_trusted == null) { - getNewKeystore(null); + keystore_trusted = KeyStore.getInstance("BKS"); + keystore_trusted.load(null); } keystore_trusted.setCertificateEntry(provider, cert); } catch (CertificateException e) { @@ -187,50 +178,16 @@ public class ConfigHelper { } catch (KeyStoreException e) { // TODO Auto-generated catch block e.printStackTrace(); - } - } - - public static KeyStore getKeystore() { - return keystore_trusted; - } - - public static void getNewKeystore(InputStream leap_keystore) { - try { - keystore_trusted = KeyStore.getInstance("BKS"); - try { - // Initialize the keystore with the provided trusted certificates - // Also provide the password of the keystore - if(leap_keystore != null) { - //keystore_trusted.load(leap_keystore, "uer92jf".toCharArray()); - keystore_trusted.load(null, null); - } else { - keystore_trusted.load(null, null); - } - } finally { - if(leap_keystore != null) - leap_keystore.close(); - } - } catch (KeyStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } - - public static int getSrpAuthenticationFailed() { - return SRP_AUTHENTICATION_FAILED; - } - static String extractProviderName(String provider_main_url) { - - return null; + public static KeyStore getKeystore() { + return keystore_trusted; } } diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index ba17f9b..78ac046 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -1,9 +1,6 @@ package se.leap.leapclient; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; import java.util.Iterator; import java.util.Scanner; @@ -12,6 +9,9 @@ import org.json.JSONObject; import se.leap.leapclient.ProviderAPIResultReceiver.Receiver; import se.leap.leapclient.ProviderListContent.ProviderItem; +import se.leap.leapclient.R; +import se.leap.leapclient.R.id; +import se.leap.leapclient.R.layout; import android.app.Activity; import android.app.DialogFragment; import android.app.Fragment; @@ -24,23 +24,6 @@ import android.os.Handler; import android.view.View; import android.widget.Toast; - -/** - * An activity representing a list of Providers. This activity - * has different presentations for handset and tablet-size devices. On - * handsets, the activity presents a list of items, which when touched, - * lead to a {@link DashboardActivity} representing - * item details. On tablets, the activity presents the list of items and - * item details side-by-side using two vertical panes. - *

- * The activity makes heavy use of fragments. The list of items is a - * {@link ProviderListFragment} and the item details - * (if present) is a {@link DashboardFragment}. - *

- * This activity also implements the required - * {@link ProviderListFragment.Callbacks} interface - * to listen for item selections. - */ public class ConfigurationWizard extends Activity implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogInterface, Receiver { @@ -63,11 +46,6 @@ public class ConfigurationWizard extends Activity loadPreseededProviders(); - if(ConfigHelper.getKeystore() == null) { - InputStream keystore_input_stream = getResources().openRawResource(R.raw.leapkeystore); - ConfigHelper.getNewKeystore(keystore_input_stream); - } - // Only create our fragments if we're not restoring a saved instance if ( savedInstanceState == null ){ // TODO Some welcome screen? @@ -83,7 +61,67 @@ public class ConfigurationWizard extends Activity // TODO: If exposing deep links into your app, handle intents here. } - private void loadPreseededProviders() { + @Override + public void onReceiveResult(int resultCode, Bundle resultData) { + if(resultCode == ConfigHelper.CUSTOM_PROVIDER_ADDED){ + ProviderListFragment providerList = new ProviderListFragment(); + + FragmentManager fragmentManager = getFragmentManager(); + fragmentManager.beginTransaction() + .replace(R.id.configuration_wizard_layout, providerList, "providerlist") + .commit(); + } + else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES) { + setResult(RESULT_OK); + finish(); + } + else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES) { + setResult(RESULT_CANCELED); + Toast.makeText(getApplicationContext(), "You have not entered a LEAP provider URL or it is unavailable", Toast.LENGTH_LONG).show(); + } + else if(resultCode == ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON) { + JSONObject provider_json; + try { + provider_json = new JSONObject(resultData.getString(ConfigHelper.PROVIDER_KEY)); + boolean danger_on = resultData.getBoolean(ConfigHelper.DANGER_ON); + ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); + ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, new JSONObject().put(ConfigHelper.DANGER_ON, danger_on)); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + else if(resultCode == ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON) { + Toast.makeText(getApplicationContext(), "Install a new version of this app.", Toast.LENGTH_LONG).show(); + } + } + + /** + * Callback method from {@link ProviderListFragment.Callbacks} + * indicating that the item with the given ID was selected. + */ + @Override + public void onItemSelected(String id) { + //TODO Code 2 pane view + Iterator preseeded_providers_iterator = ProviderListContent.ITEMS.iterator(); + while(preseeded_providers_iterator.hasNext()) + { + ProviderItem current_provider_item = preseeded_providers_iterator.next(); + if(current_provider_item.id.equalsIgnoreCase(id)) + { + try { + saveProviderJson(current_provider_item); + downloadJSONFiles(current_provider_item); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } + + private boolean loadPreseededProviders() { + boolean loaded_preseeded_providers = false; AssetManager asset_manager = getAssets(); String[] urls_filepaths = null; try { @@ -97,65 +135,33 @@ public class ConfigurationWizard extends Activity 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, true)); // By default, it trusts the provider + loaded_preseeded_providers = true; } } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + loaded_preseeded_providers = false; + } + + return loaded_preseeded_providers; } - /** - * Callback method from {@link ProviderListFragment.Callbacks} - * indicating that the item with the given ID was selected. - */ - @Override - public void onItemSelected(String id) { - if (mTwoPane) { - // TODO Hmmm...is this how we should do this? What if it /is/ two pane? - } else { - // In single-pane mode, simply start the detail activity - // for the selected item ID. - - Iterator preseeded_providers_iterator = ProviderListContent.ITEMS.iterator(); - while(preseeded_providers_iterator.hasNext()) - { - ProviderItem current_provider_item = preseeded_providers_iterator.next(); - if(current_provider_item.id.equalsIgnoreCase(id)) - { - try { - saveProviderJson(current_provider_item); - downloadJSONFiles(current_provider_item); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - } - } - - private void saveProviderJson(ProviderItem current_provider_item) { + private boolean saveProviderJson(ProviderItem current_provider_item) { JSONObject provider_json = new JSONObject(); try { String provider_contents = ""; if(!current_provider_item.custom) { - //provider_contents = new Scanner(new InputStreamReader(assets_manager.open(current_provider_item.provider_json_filename))).useDelimiter("\\A").next(); updateProviderDotJson(current_provider_item.name, current_provider_item.provider_json_url, current_provider_item.danger_on); + return true; } else { provider_contents = new Scanner(ConfigHelper.openFileInputStream(current_provider_item.provider_json_filename)).useDelimiter("\\A").next(); provider_json = new JSONObject(provider_contents); - ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); - try { - ConfigHelper.saveSharedPref(ConfigHelper.danger_on, new JSONObject().put(ConfigHelper.danger_on, current_provider_item.danger_on)); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); + ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, new JSONObject().put(ConfigHelper.DANGER_ON, current_provider_item.danger_on)); + return true; } } catch (JSONException e) { - ConfigHelper.rescueJSONException(e); + return false; } - } + } private void downloadJSONFiles(ProviderItem current_provider_item) throws IOException { providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); @@ -165,12 +171,12 @@ public class ConfigurationWizard extends Activity Bundle method_and_parameters = new Bundle(); - method_and_parameters.putString(ConfigHelper.provider_key, current_provider_item.name); - method_and_parameters.putString(ConfigHelper.main_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); + method_and_parameters.putString(ConfigHelper.PROVIDER_KEY, current_provider_item.name); + method_and_parameters.putString(ConfigHelper.MAIN_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(ConfigHelper.DOWNLOAD_JSON_FILES_BUNDLE_EXTRA, method_and_parameters); provider_API_command.putExtra("receiver", providerAPI_result_receiver); startService(provider_API_command); @@ -178,14 +184,14 @@ public class ConfigurationWizard extends Activity public void addNewProvider(View view) { FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); - Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.newProviderDialog); + Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.NEW_PROVIDER_DIALOG); if (previous_new_provider_dialog != null) { fragment_transaction.remove(previous_new_provider_dialog); } fragment_transaction.addToBackStack(null); DialogFragment newFragment = NewProviderDialog.newInstance(); - newFragment.show(fragment_transaction, ConfigHelper.newProviderDialog); + newFragment.show(fragment_transaction, ConfigHelper.NEW_PROVIDER_DIALOG); } @Override @@ -196,10 +202,10 @@ public class ConfigurationWizard extends Activity Intent provider_API_command = new Intent(this, ProviderAPI.class); 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); + 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.DOWNLOAD_NEW_PROVIDER_DOTJSON, method_and_parameters); provider_API_command.putExtra("receiver", providerAPI_result_receiver); startService(provider_API_command); @@ -212,49 +218,13 @@ public class ConfigurationWizard extends Activity Intent provider_API_command = new Intent(this, ProviderAPI.class); Bundle method_and_parameters = new Bundle(); - method_and_parameters.putString(ConfigHelper.provider_name, provider_name); - method_and_parameters.putString(ConfigHelper.provider_json_url, provider_json_url); - method_and_parameters.putBoolean(ConfigHelper.danger_on, danger_on); + method_and_parameters.putString(ConfigHelper.PROVIDER_NAME, provider_name); + method_and_parameters.putString(ConfigHelper.PROVIDER_JSON_URL, provider_json_url); + method_and_parameters.putBoolean(ConfigHelper.DANGER_ON, danger_on); - provider_API_command.putExtra(ConfigHelper.updateProviderDotJSON, method_and_parameters); + provider_API_command.putExtra(ConfigHelper.UPDATE_PROVIDER_DOTJSON, method_and_parameters); provider_API_command.putExtra("receiver", providerAPI_result_receiver); startService(provider_API_command); } - - @Override - public void onReceiveResult(int resultCode, Bundle resultData) { - if(resultCode == ConfigHelper.CUSTOM_PROVIDER_ADDED){ - ProviderListFragment providerList = new ProviderListFragment(); - - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction() - .replace(R.id.configuration_wizard_layout, providerList, "providerlist") - .commit(); - } - else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES) { - setResult(RESULT_OK); - finish(); - } - else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES) { - setResult(RESULT_CANCELED); - Toast.makeText(getApplicationContext(), "You have not entered a LEAP provider URL", Toast.LENGTH_LONG).show(); - } - else if(resultCode == ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON) { - JSONObject provider_json; - try { - provider_json = new JSONObject(resultData.getString(ConfigHelper.provider_key)); - boolean danger_on = resultData.getBoolean(ConfigHelper.danger_on); - ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); - ConfigHelper.saveSharedPref(ConfigHelper.danger_on, new JSONObject().put(ConfigHelper.danger_on, danger_on)); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - else if(resultCode == ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON) { - Toast.makeText(getApplicationContext(), "Install a new version of this app.", Toast.LENGTH_LONG).show(); - } - - } } diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index c8cbc5a..b937c94 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -6,6 +6,10 @@ import org.json.JSONException; import org.json.JSONObject; import se.leap.leapclient.ProviderAPIResultReceiver.Receiver; +import se.leap.leapclient.R; +import se.leap.leapclient.R.id; +import se.leap.leapclient.R.layout; +import se.leap.leapclient.R.menu; import se.leap.openvpn.AboutFragment; import se.leap.openvpn.MainActivity; import android.app.Activity; @@ -116,11 +120,11 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf @Override public boolean onPrepareOptionsMenu(Menu menu) { - String provider_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.provider_key); + String provider_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.PROVIDER_KEY); try { JSONObject provider_json = new JSONObject(provider_json_string); - JSONObject service_description = provider_json.getJSONObject(ConfigHelper.service_key); - if(service_description.getBoolean(ConfigHelper.allow_registration_key)) { + JSONObject service_description = provider_json.getJSONObject(ConfigHelper.SERVICE_KEY); + if(service_description.getBoolean(ConfigHelper.ALLOW_REGISTRATION_KEY)) { menu.findItem(R.id.login_button).setVisible(true); menu.findItem(R.id.logout_button).setVisible(true); return true; @@ -187,19 +191,19 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf Intent provider_API_command = new Intent(this, ProviderAPI.class); Bundle method_and_parameters = new Bundle(); - method_and_parameters.putString(ConfigHelper.username_key, username); - method_and_parameters.putString(ConfigHelper.password_key, password); + method_and_parameters.putString(ConfigHelper.USERNAME_KEY, username); + method_and_parameters.putString(ConfigHelper.PASSWORD_KEY, password); JSONObject provider_json; try { - provider_json = new JSONObject(preferences.getString(ConfigHelper.provider_key, "")); - method_and_parameters.putString(ConfigHelper.api_url_key, provider_json.getString(ConfigHelper.api_url_key) + "/" + provider_json.getString(ConfigHelper.api_version_key)); + provider_json = new JSONObject(preferences.getString(ConfigHelper.PROVIDER_KEY, "")); + method_and_parameters.putString(ConfigHelper.API_URL_KEY, provider_json.getString(ConfigHelper.API_URL_KEY) + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY)); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } - provider_API_command.putExtra(ConfigHelper.srpAuth, method_and_parameters); + provider_API_command.putExtra(ConfigHelper.SRP_AUTH, method_and_parameters); provider_API_command.putExtra("receiver", providerAPI_result_receiver); startService(provider_API_command); @@ -214,14 +218,14 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf JSONObject provider_json; try { - provider_json = new JSONObject(preferences.getString(ConfigHelper.provider_key, "")); - method_and_parameters.putString(ConfigHelper.api_url_key, provider_json.getString(ConfigHelper.api_url_key) + "/" + provider_json.getString(ConfigHelper.api_version_key)); + provider_json = new JSONObject(preferences.getString(ConfigHelper.PROVIDER_KEY, "")); + method_and_parameters.putString(ConfigHelper.API_URL_KEY, provider_json.getString(ConfigHelper.API_URL_KEY) + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY)); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } - provider_API_command.putExtra(ConfigHelper.logOut, method_and_parameters); + provider_API_command.putExtra(ConfigHelper.LOG_OUT, method_and_parameters); provider_API_command.putExtra("receiver", providerAPI_result_receiver); startService(provider_API_command); @@ -229,14 +233,14 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf public void logInDialog(View view) { FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); - Fragment previous_log_in_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.logInDialog); + Fragment previous_log_in_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.LOG_IN_DIALOG); if (previous_log_in_dialog != null) { fragment_transaction.remove(previous_log_in_dialog); } fragment_transaction.addToBackStack(null); DialogFragment newFragment = LogInDialog.newInstance(); - newFragment.show(fragment_transaction, ConfigHelper.logInDialog); + newFragment.show(fragment_transaction, ConfigHelper.LOG_IN_DIALOG); } private void downloadAuthedUserCertificate(Cookie session_id) { @@ -246,10 +250,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf Intent provider_API_command = new Intent(this, ProviderAPI.class); Bundle method_and_parameters = new Bundle(); - method_and_parameters.putString(ConfigHelper.session_id_cookie_key, session_id.getName()); - method_and_parameters.putString(ConfigHelper.session_id_key, session_id.getValue()); + method_and_parameters.putString(ConfigHelper.SESSION_ID_COOKIE_KEY, session_id.getName()); + method_and_parameters.putString(ConfigHelper.SESSION_ID_KEY, session_id.getValue()); - provider_API_command.putExtra(ConfigHelper.downloadUserAuthedCertificate, method_and_parameters); + provider_API_command.putExtra(ConfigHelper.DOWNLOAD_USER_AUTHED_CERTIFICATE, method_and_parameters); provider_API_command.putExtra("receiver", providerAPI_result_receiver); startService(provider_API_command); @@ -258,8 +262,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf @Override public void onReceiveResult(int resultCode, Bundle resultData) { if(resultCode == ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL){ - String session_id_cookie_key = resultData.getString(ConfigHelper.session_id_cookie_key); - String session_id_string = resultData.getString(ConfigHelper.session_id_key); + String session_id_cookie_key = resultData.getString(ConfigHelper.SESSION_ID_COOKIE_KEY); + String session_id_string = resultData.getString(ConfigHelper.SESSION_ID_KEY); setResult(RESULT_OK); Toast.makeText(getApplicationContext(), "Authentication succeeded", Toast.LENGTH_LONG).show(); diff --git a/src/se/leap/leapclient/LeapHttpClient.java b/src/se/leap/leapclient/LeapHttpClient.java index 4de7ae0..a2ee8ad 100644 --- a/src/se/leap/leapclient/LeapHttpClient.java +++ b/src/se/leap/leapclient/LeapHttpClient.java @@ -16,57 +16,57 @@ import android.content.Context; public class LeapHttpClient extends DefaultHttpClient { final Context context; - + private static LeapHttpClient client; - public LeapHttpClient(Context context) { - this.context = context; - } + public static LeapHttpClient getInstance(Context context) { + if(client == null) { + client = new LeapHttpClient(context); + String cert_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_CERT_KEY); + String cert_string; + try { + cert_string = new JSONObject(cert_json_string).getString(ConfigHelper.MAIN_CERT_KEY); + if(!cert_string.isEmpty()) { + ConfigHelper.addTrustedCertificate("recovered_certificate", cert_string); + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return client; + } + + @Override + protected ClientConnectionManager createClientConnectionManager() { + SchemeRegistry registry = new SchemeRegistry(); + registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); + // Register for port 443 our SSLSocketFactory with our keystore + // to the ConnectionManager + registry.register(new Scheme("https", newSslSocketFactory(), 443)); + return new SingleClientConnManager(getParams(), registry); + } + + private SSLSocketFactory newSslSocketFactory() { + try { + // Get an instance of the Bouncy Castle KeyStore format + KeyStore trusted = ConfigHelper.getKeystore(); + + // Pass the keystore to the SSLSocketFactory. The factory is responsible + // for the verification of the server certificate. + SSLSocketFactory sf = new SSLSocketFactory(trusted); - @Override - protected ClientConnectionManager createClientConnectionManager() { - SchemeRegistry registry = new SchemeRegistry(); - registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); - // Register for port 443 our SSLSocketFactory with our keystore - // to the ConnectionManager - registry.register(new Scheme("https", newSslSocketFactory(), 443)); - return new SingleClientConnManager(getParams(), registry); - } + // Hostname verification from certificate + // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506 + sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); - private SSLSocketFactory newSslSocketFactory() { - try { - // Get an instance of the Bouncy Castle KeyStore format - KeyStore trusted = ConfigHelper.getKeystore(); - - // Pass the keystore to the SSLSocketFactory. The factory is responsible - // for the verification of the server certificate. - SSLSocketFactory sf = new SSLSocketFactory(trusted); - - // Hostname verification from certificate - // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506 - sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); - - return sf; - } catch (Exception e) { - throw new AssertionError(e); - } - } + return sf; + } catch (Exception e) { + throw new AssertionError(e); + } + } - public static LeapHttpClient getInstance(Context context) { - if(client == null) { - client = new LeapHttpClient(context); - String cert_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.main_cert_key); - String cert_string; - try { - cert_string = new JSONObject(cert_json_string).getString(ConfigHelper.main_cert_key); - if(!cert_string.isEmpty()) { - ConfigHelper.addTrustedCertificate("recovered_certificate", cert_string); - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return client; - } + public LeapHttpClient(Context context) { + this.context = context; + } } diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index f9037de..7b32e79 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -47,8 +47,7 @@ public class LeapSRPSession { @param username, the user ID @param password, the user clear text password @param params, the SRP parameters for the session - @param abytes, the random exponent used in the A public key. This must be - 8 bytes in length. + @param abytes, the random exponent used in the A public key */ public LeapSRPSession(String username, String password, SRPParameters params, byte[] abytes) { @@ -177,8 +176,9 @@ public class LeapSRPSession { /** * Calculates the parameter M1, to be sent to the SRP server. * It also updates hashes of client and server for further calculations in other methods. + * It uses a predefined k. + * @param salt_bytes * @param Bbytes the parameter received from the server, in bytes - * @param bs * @return the parameter M1 * @throws NoSuchAlgorithmException */ @@ -190,8 +190,6 @@ public class LeapSRPSession { // Calculate v = kg^x mod N String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; this.v = calculateV(k_string); - //String v_string = v.toString(16); - // H(N) byte[] digest_of_n = newDigest().digest(N_bytes); @@ -201,54 +199,45 @@ public class LeapSRPSession { // clientHash = H(N) xor H(g) byte[] xor_digest = xor(digest_of_n, digest_of_g, digest_of_g.length); - //String hxg_string = new BigInteger(1, xor_digest).toString(16); clientHash.update(xor_digest); // clientHash = H(N) xor H(g) | H(U) byte[] username_digest = newDigest().digest(Util.trim(username.getBytes())); username_digest = Util.trim(username_digest); - //String username_digest_string = new BigInteger(1, username_digest).toString(16); clientHash.update(username_digest); // clientHash = H(N) xor H(g) | H(U) | s - //String salt_string = new BigInteger(1, salt_bytes).toString(16); clientHash.update(Util.trim(salt_bytes)); K = null; - - // clientHash = H(N) xor H(g) | H(U) | s | A | B - - byte[] Abytes = Util.trim(A.toByteArray()); - //String Abytes_string = new BigInteger(1, Abytes).toString(16); // clientHash = H(N) xor H(g) | H(U) | A + byte[] Abytes = Util.trim(A.toByteArray()); clientHash.update(Abytes); // clientHash = H(N) xor H(g) | H(U) | s | A | B Bbytes = Util.trim(Bbytes); - //String Bbytes_string = new BigInteger(1, Bbytes).toString(16); clientHash.update(Bbytes); // Calculate S = (B - kg^x) ^ (a + u * x) % N BigInteger S = calculateS(Bbytes); byte[] S_bytes = Util.trim(S.toByteArray()); - //String S_bytes_string = new BigInteger(1, S_bytes).toString(16); // K = SessionHash(S) String hash_algorithm = params.hashAlgorithm; MessageDigest sessionDigest = MessageDigest.getInstance(hash_algorithm); K = Util.trim(sessionDigest.digest(S_bytes)); - //K = Util.trim(K); - //String K_bytes_string = new BigInteger(1, K).toString(16); // clientHash = H(N) xor H(g) | H(U) | A | B | K clientHash.update(K); + byte[] M1 = Util.trim(clientHash.digest()); // serverHash = Astr + M + K serverHash.update(Abytes); serverHash.update(M1); serverHash.update(K); + return M1; } @@ -263,13 +252,10 @@ public class LeapSRPSession { byte[] u_bytes = getU(Abytes, Bbytes); BigInteger B = new BigInteger(1, Bbytes); - //String Bstring = B.toString(16); BigInteger u = new BigInteger(1, u_bytes); - //String u_string = u.toString(16); BigInteger B_minus_v = B.subtract(v); BigInteger a_ux = a.add(u.multiply(x)); - //String a_ux_string = a_ux.toString(16); BigInteger S = B_minus_v.modPow(a_ux, N); return S; @@ -285,7 +271,7 @@ public class LeapSRPSession { MessageDigest u_digest = newDigest(); u_digest.update(Util.trim(Abytes)); u_digest.update(Util.trim(Bbytes)); - byte[] u_digest_bytes = u_digest.digest();//Util.trim(u_digest.digest()); + byte[] u_digest_bytes = u_digest.digest(); return Util.trim(new BigInteger(1, u_digest_bytes).toByteArray()); } @@ -302,17 +288,6 @@ public class LeapSRPSession { return valid; } - /** Returns the negotiated session K, K = SHA_Interleave(S) - @return the private session K byte[] - @throws SecurityException - if the current thread does not have an - getSessionKey SRPPermission. - */ - public byte[] getSessionKey() throws SecurityException - { - return K; - } - - /** * @return a new SHA-256 digest. */ diff --git a/src/se/leap/leapclient/LogInDialog.java b/src/se/leap/leapclient/LogInDialog.java index 30984db..370a138 100644 --- a/src/se/leap/leapclient/LogInDialog.java +++ b/src/se/leap/leapclient/LogInDialog.java @@ -1,8 +1,11 @@ package se.leap.leapclient; +import se.leap.leapclient.R; +import se.leap.leapclient.R.id; +import se.leap.leapclient.R.layout; +import se.leap.leapclient.R.string; import android.app.Activity; import android.app.AlertDialog; -import android.app.Dialog; import android.app.DialogFragment; import android.content.DialogInterface; import android.os.Bundle; @@ -12,49 +15,25 @@ import android.widget.EditText; import android.widget.Toast; public class LogInDialog extends DialogFragment { - - public interface LogInDialogInterface { - public void authenticate(String username, String password); - } - - LogInDialogInterface interface_with_Dashboard; - - public static DialogFragment newInstance() { - LogInDialog dialog_fragment = new LogInDialog(); - return dialog_fragment; - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - // Verify that the host activity implements the callback interface - try { - // Instantiate the NoticeDialogListener so we can send events to the host - interface_with_Dashboard = (LogInDialogInterface) activity; - } catch (ClassCastException e) { - // The activity doesn't implement the interface, throw exception - throw new ClassCastException(activity.toString() - + " must implement NoticeDialogListener"); - } - } - public Dialog onCreateDialog(Bundle savedInstanceState) { + public AlertDialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); LayoutInflater inflater = getActivity().getLayoutInflater(); View log_in_dialog_view = inflater.inflate(R.layout.log_in_dialog, null); + final EditText username_field = (EditText)log_in_dialog_view.findViewById(R.id.username_entered); final EditText password_field = (EditText)log_in_dialog_view.findViewById(R.id.password_entered); + builder.setView(log_in_dialog_view) .setPositiveButton(R.string.log_in_button, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { String username = username_field.getText().toString().trim(); String password = password_field.getText().toString().trim(); - if(validPassword(password)) { + if(wellFormedPassword(password)) { interface_with_Dashboard.authenticate(username, password); - Toast.makeText(getActivity().getApplicationContext(), "Your password is valid", Toast.LENGTH_LONG).show(); } else { password_field.setText(""); - Toast.makeText(getActivity().getApplicationContext(), "Your password is not valid: it should have at least 8 characters", Toast.LENGTH_LONG).show(); + Toast.makeText(getActivity().getApplicationContext(), "Your password is not well-formed: it should have at least 8 characters", Toast.LENGTH_LONG).show(); } } }) @@ -63,11 +42,33 @@ public class LogInDialog extends DialogFragment { dialog.cancel(); } }); - // Create the AlertDialog object and return it + return builder.create(); } - boolean validPassword(String entered_password) { - return entered_password.length() > 4; + boolean wellFormedPassword(String entered_password) { + return entered_password.length() > 8; } + + public interface LogInDialogInterface { + public void authenticate(String username, String password); + } + + LogInDialogInterface interface_with_Dashboard; + + public static DialogFragment newInstance() { + LogInDialog dialog_fragment = new LogInDialog(); + return dialog_fragment; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + interface_with_Dashboard = (LogInDialogInterface) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement NoticeDialogListener"); + } + } } diff --git a/src/se/leap/leapclient/NewProviderDialog.java b/src/se/leap/leapclient/NewProviderDialog.java index 6101846..9978800 100644 --- a/src/se/leap/leapclient/NewProviderDialog.java +++ b/src/se/leap/leapclient/NewProviderDialog.java @@ -1,5 +1,9 @@ package se.leap.leapclient; +import se.leap.leapclient.R; +import se.leap.leapclient.R.id; +import se.leap.leapclient.R.layout; +import se.leap.leapclient.R.string; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; @@ -28,12 +32,9 @@ public class NewProviderDialog extends DialogFragment { @Override public void onAttach(Activity activity) { super.onAttach(activity); - // Verify that the host activity implements the callback interface try { - // Instantiate the NoticeDialogListener so we can send events to the host interface_with_ConfigurationWizard = (NewProviderDialogInterface) activity; } catch (ClassCastException e) { - // The activity doesn't implement the interface, throw exception throw new ClassCastException(activity.toString() + " must implement NoticeDialogListener"); } diff --git a/src/se/leap/leapclient/Provider.java b/src/se/leap/leapclient/Provider.java index 4235acf..f86bbf5 100644 --- a/src/se/leap/leapclient/Provider.java +++ b/src/se/leap/leapclient/Provider.java @@ -18,7 +18,7 @@ import android.content.SharedPreferences; * @author Sean Leonard * */ -final class Provider implements Serializable { +public final class Provider implements Serializable { private static final long serialVersionUID = 6003835972151761353L; diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index b44c997..0003344 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -11,7 +11,6 @@ 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.CookieHandler; import java.net.CookieManager; import java.net.HttpCookie; @@ -32,6 +31,7 @@ import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.protocol.ClientContext; import org.apache.http.cookie.Cookie; import org.apache.http.impl.client.DefaultHttpClient; @@ -63,89 +63,72 @@ public class ProviderAPI extends IntentService { final ResultReceiver receiver = task_for.getParcelableExtra("receiver"); Bundle task; - if((task = task_for.getBundleExtra(ConfigHelper.downloadJsonFilesBundleExtra)) != null) { - if(!downloadJsonFiles(task)) + if((task = task_for.getBundleExtra(ConfigHelper.DOWNLOAD_JSON_FILES_BUNDLE_EXTRA)) != null) { + if(!downloadJsonFiles(task)) { receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY); - else + } else { receiver.send(ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY); + } } - else if ((task = task_for.getBundleExtra(ConfigHelper.updateProviderDotJSON)) != null) { - JSONObject result = updateProviderDotJSON(task); - boolean successful; - try { - successful = result.getBoolean(ConfigHelper.resultKey); - if(successful) { - Bundle provider_dot_json_and_danger_on = new Bundle(); - provider_dot_json_and_danger_on.putBoolean(ConfigHelper.danger_on, result.getBoolean(ConfigHelper.danger_on)); - provider_dot_json_and_danger_on.putString(ConfigHelper.provider_key, result.getJSONObject(ConfigHelper.provider_key).toString()); - receiver.send(ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON, provider_dot_json_and_danger_on); - } else { - receiver.send(ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON, Bundle.EMPTY); - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + else if ((task = task_for.getBundleExtra(ConfigHelper.UPDATE_PROVIDER_DOTJSON)) != null) { + Bundle result = updateProviderDotJSON(task); + if(result.getBoolean(ConfigHelper.RESULT_KEY)) { + receiver.send(ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON, result); + } else { + receiver.send(ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON, Bundle.EMPTY); } } - else if ((task = task_for.getBundleExtra(ConfigHelper.downloadNewProviderDotJSON)) != null) { - if(downloadNewProviderDotJSON(task)) + else if ((task = task_for.getBundleExtra(ConfigHelper.DOWNLOAD_NEW_PROVIDER_DOTJSON)) != null) { + if(downloadNewProviderDotJSON(task)) { receiver.send(ConfigHelper.CUSTOM_PROVIDER_ADDED, Bundle.EMPTY); - else + } else { receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY); + } } - else if ((task = task_for.getBundleExtra(ConfigHelper.srpAuth)) != null) { - try { - JSONObject session_idAndResult = authenticateBySRP(task); - if(session_idAndResult.getBoolean(ConfigHelper.resultKey)) { - Bundle session_id_bundle = new Bundle(); - session_id_bundle.putString(ConfigHelper.session_id_cookie_key, session_idAndResult.getString(ConfigHelper.session_id_cookie_key)); - session_id_bundle.putString(ConfigHelper.session_id_key, session_idAndResult.getString(ConfigHelper.session_id_key)); - receiver.send(ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL, session_id_bundle); - } else { - receiver.send(ConfigHelper.SRP_AUTHENTICATION_FAILED, Bundle.EMPTY); - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + else if ((task = task_for.getBundleExtra(ConfigHelper.SRP_AUTH)) != null) { + Bundle session_id_bundle = authenticateBySRP(task); + if(session_id_bundle.getBoolean(ConfigHelper.RESULT_KEY)) { + receiver.send(ConfigHelper.SRP_AUTHENTICATION_SUCCESSFUL, session_id_bundle); + } else { + receiver.send(ConfigHelper.SRP_AUTHENTICATION_FAILED, Bundle.EMPTY); } } - else if ((task = task_for.getBundleExtra(ConfigHelper.logOut)) != null) { - if(logOut(task)) + else if ((task = task_for.getBundleExtra(ConfigHelper.LOG_OUT)) != null) { + if(logOut(task)) { receiver.send(ConfigHelper.LOGOUT_SUCCESSFUL, Bundle.EMPTY); - else + } else { receiver.send(ConfigHelper.LOGOUT_FAILED, Bundle.EMPTY); + } } - else if ((task = task_for.getBundleExtra(ConfigHelper.downloadUserAuthedCertificate)) != null) { - if(getNewCert(task)) + else if ((task = task_for.getBundleExtra(ConfigHelper.DOWNLOAD_USER_AUTHED_CERTIFICATE)) != null) { + if(getNewCert(task)) { receiver.send(ConfigHelper.CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE, Bundle.EMPTY); - else + } else { receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE, Bundle.EMPTY); + } } } private boolean downloadJsonFiles(Bundle task) { - //String provider_name = task.getString(ConfigHelper.provider_key); - String cert_url = task.getString(ConfigHelper.main_cert_key); - String eip_service_json_url = task.getString(ConfigHelper.eip_service_key); - boolean danger_on = task.getBoolean(ConfigHelper.danger_on); + String cert_url = task.getString(ConfigHelper.MAIN_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, danger_on); - //ConfigHelper.addTrustedCertificate(provider_name, cert_string); - JSONObject cert_json = new JSONObject().put(ConfigHelper.main_cert_key, cert_string); - ConfigHelper.saveSharedPref(ConfigHelper.main_cert_key, cert_json); + JSONObject cert_json = new JSONObject().put(ConfigHelper.MAIN_CERT_KEY, cert_string); + ConfigHelper.saveSharedPref(ConfigHelper.MAIN_CERT_KEY, cert_json); JSONObject eip_service_json = getJSONFromProvider(eip_service_json_url, danger_on); - ConfigHelper.saveSharedPref(ConfigHelper.eip_service_key, eip_service_json); + ConfigHelper.saveSharedPref(ConfigHelper.EIP_SERVICE_KEY, eip_service_json); return true; } catch (JSONException e) { - ConfigHelper.rescueJSONException(e); return false; } } private boolean registerWithSRP(Bundle task) { - String username = (String) task.get(ConfigHelper.username_key); - String password = (String) task.get(ConfigHelper.password_key); - String authentication_server = (String) task.get(ConfigHelper.api_url_key); + String username = (String) task.get(ConfigHelper.USERNAME_KEY); + String password = (String) task.get(ConfigHelper.PASSWORD_KEY); + String authentication_server = (String) task.get(ConfigHelper.API_URL_KEY); BigInteger ng_1024 = new BigInteger(ConfigHelper.NG_1024, 16); BigInteger salt = ng_1024.probablePrime(1024, null); @@ -154,173 +137,127 @@ public class ProviderAPI extends IntentService { return false; } - private JSONObject authenticateBySRP(Bundle task) { - JSONObject successfulAndsession_id = new JSONObject(); - - String username = (String) task.get(ConfigHelper.username_key); - String password = (String) task.get(ConfigHelper.password_key); - String authentication_server = (String) task.get(ConfigHelper.api_url_key); + private Bundle authenticateBySRP(Bundle task) { + Bundle session_id_bundle = new Bundle(); - String salt = "abcd"; + String username = (String) task.get(ConfigHelper.USERNAME_KEY); + String password = (String) task.get(ConfigHelper.PASSWORD_KEY); + String authentication_server = (String) task.get(ConfigHelper.API_URL_KEY); - SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), new BigInteger("2").toByteArray(), new BigInteger(salt, 16).toByteArray(), "SHA-256"); - //SRPClientSession client = new SRPClientSession(username, password.toCharArray(), params); + SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256"); LeapSRPSession client = new LeapSRPSession(username, password, params); byte[] A = client.exponential(); try { JSONObject saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); if(saltAndB.length() > 0) { - salt = saltAndB.getString("salt"); + String salt = saltAndB.getString(ConfigHelper.SALT_KEY); byte[] Bbytes = new BigInteger(saltAndB.getString("B"), 16).toByteArray(); byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); - //byte[] M2 = sendM1ToSRPServer(authentication_server, username, M1); JSONObject session_idAndM2 = sendM1ToSRPServer(authentication_server, username, M1); if( client.verify((byte[])session_idAndM2.get("M2")) == false ) { - //throw new SecurityException("Failed to validate server reply: M2 = " + new BigInteger(1, M2).toString(16)); - successfulAndsession_id.put(ConfigHelper.resultKey, false); - return successfulAndsession_id; + session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false); } else { - successfulAndsession_id.put(ConfigHelper.resultKey, true); - successfulAndsession_id.put(ConfigHelper.session_id_key, session_idAndM2.getString(ConfigHelper.session_id_key)); - successfulAndsession_id.put(ConfigHelper.session_id_cookie_key, session_idAndM2.getString(ConfigHelper.session_id_cookie_key)); - return successfulAndsession_id; + session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, true); + session_id_bundle.putString(ConfigHelper.SESSION_ID_KEY, session_idAndM2.getString(ConfigHelper.SESSION_ID_KEY)); + session_id_bundle.putString(ConfigHelper.SESSION_ID_COOKIE_KEY, session_idAndM2.getString(ConfigHelper.SESSION_ID_COOKIE_KEY)); } } else { - successfulAndsession_id.put(ConfigHelper.resultKey, false); - return successfulAndsession_id; + session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false); } - } catch (ClientProtocolException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } catch (JSONException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); + } catch (ClientProtocolException e) { + session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false); + } catch (IOException e) { + session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false); + } catch (JSONException e) { + session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false); } catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false); } - return successfulAndsession_id; + + return session_id_bundle; } private JSONObject sendAToSRPServer(String server_url, String username, String clientA) throws ClientProtocolException, IOException, JSONException { - DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); - String parameter_chain = "A" + "=" + clientA + "&" + "login" + "=" + username; - HttpPost post = new HttpPost(server_url + "/sessions.json" + "?" + parameter_chain); - - HttpResponse getResponse = client.execute(post); - HttpEntity responseEntity = getResponse.getEntity(); - String plain_response = new Scanner(responseEntity.getContent()).useDelimiter("\\A").next(); - JSONObject json_response = new JSONObject(plain_response); - if(!json_response.isNull("errors") || json_response.has("errors")) { - return new JSONObject(); - } - - String session_id = ""; - List cookies = client.getCookieStore().getCookies(); - if(!cookies.isEmpty()) { - session_id = cookies.get(0).getValue(); - } - return json_response; + HttpPost post = new HttpPost(server_url + "/sessions.json" + "?" + "login=" + username + "&&" + "A=" + clientA); + return sendToServer(post); } private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) throws ClientProtocolException, IOException, JSONException { + HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + "client_auth" + "=" + new BigInteger(1, Util.trim(m1)).toString(16)); + JSONObject json_response = sendToServer(put); + JSONObject session_idAndM2 = new JSONObject(); + if(json_response.length() > 0) { + byte[] M2_not_trimmed = new BigInteger(json_response.getString("M2"), 16).toByteArray(); + Cookie session_id_cookie = LeapHttpClient.getInstance(getApplicationContext()).getCookieStore().getCookies().get(0); + session_idAndM2.put(ConfigHelper.SESSION_ID_COOKIE_KEY, session_id_cookie.getName()); + session_idAndM2.put(ConfigHelper.SESSION_ID_KEY, session_id_cookie.getValue()); + session_idAndM2.put("M2", Util.trim(M2_not_trimmed)); + } + return session_idAndM2; + } + + private JSONObject sendToServer(HttpUriRequest request) throws ClientProtocolException, IOException, JSONException { DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); - String parameter_chain = "client_auth" + "=" + new BigInteger(1, Util.trim(m1)).toString(16); - HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + parameter_chain); HttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.COOKIE_STORE, client.getCookieStore()); - String session_id = client.getCookieStore().getCookies().get(0).getValue(); - int number_of_cookies = client.getCookieStore().getCookies().size(); - HttpResponse getResponse = client.execute(put, localContext); + HttpResponse getResponse = client.execute(request, localContext); HttpEntity responseEntity = getResponse.getEntity(); String plain_response = new Scanner(responseEntity.getContent()).useDelimiter("\\A").next(); JSONObject json_response = new JSONObject(plain_response); if(!json_response.isNull("errors") || json_response.has("errors")) { - return session_idAndM2; + return new JSONObject(); } - number_of_cookies = client.getCookieStore().getCookies().size(); - byte[] M2_not_trimmed = new BigInteger(json_response.getString("M2"), 16).toByteArray(); - session_idAndM2.put(ConfigHelper.session_id_cookie_key, client.getCookieStore().getCookies().get(0).getName()); - session_idAndM2.put(ConfigHelper.session_id_key, client.getCookieStore().getCookies().get(0).getValue()); - session_idAndM2.put("M2", Util.trim(M2_not_trimmed)); - return session_idAndM2; + return json_response; } - private JSONObject updateProviderDotJSON(Bundle task) { - JSONObject result = new JSONObject(); - boolean custom = task.getBoolean(ConfigHelper.custom); - boolean danger_on = task.getBoolean(ConfigHelper.danger_on); - String provider_json_url = task.getString(ConfigHelper.provider_json_url); - String provider_name = task.getString(ConfigHelper.provider_name); + private Bundle updateProviderDotJSON(Bundle task) { + Bundle result = new Bundle(); + boolean custom = task.getBoolean(ConfigHelper.CUSTOM); + boolean danger_on = task.getBoolean(ConfigHelper.DANGER_ON); + String provider_json_url = task.getString(ConfigHelper.PROVIDER_JSON_URL); + String provider_name = task.getString(ConfigHelper.PROVIDER_NAME); - JSONObject provider_json = null; try { - provider_json = getJSONFromProvider(provider_json_url, danger_on); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - try { - return result.put(ConfigHelper.resultKey, false); - } catch (JSONException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - } - - if(provider_json == null) { - try { - return result.put(ConfigHelper.resultKey, false); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } else { - String filename = provider_name + "_provider.json".replaceFirst("__", "_"); - ConfigHelper.saveFile(filename, provider_json.toString()); - //ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); + JSONObject provider_json = getJSONFromProvider(provider_json_url, danger_on); + if(provider_json == null) { + result.putBoolean(ConfigHelper.RESULT_KEY, false); + } else { + String filename = provider_name + "_provider.json".replaceFirst("__", "_"); + ConfigHelper.saveFile(filename, provider_json.toString()); - ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, filename, custom, danger_on)); - try { - return result.put(ConfigHelper.resultKey, true).put(ConfigHelper.provider_key, provider_json).put(ConfigHelper.danger_on, danger_on); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, filename, custom, danger_on)); + result.putBoolean(ConfigHelper.RESULT_KEY, true); + result.putString(ConfigHelper.PROVIDER_KEY, provider_json.toString()); + result.putBoolean(ConfigHelper.DANGER_ON, danger_on); } + } catch (JSONException e) { + result.putBoolean(ConfigHelper.RESULT_KEY, false); } + return result; } private boolean downloadNewProviderDotJSON(Bundle task) { boolean custom = true; - boolean danger_on = task.getBoolean(ConfigHelper.danger_on); + boolean danger_on = task.getBoolean(ConfigHelper.DANGER_ON); - String provider_main_url = (String) task.get(ConfigHelper.provider_main_url); + 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, danger_on); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } - - if(provider_json == null) { - return false; - } else { + String filename = provider_name + "_provider.json".replaceFirst("__", "_"); ConfigHelper.saveFile(filename, provider_json.toString()); - //ConfigHelper.saveSharedPref(ConfigHelper.provider_key, provider_json); ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, filename, custom, danger_on)); return true; + } catch (JSONException e) { + return false; } } @@ -385,8 +322,8 @@ public class ProviderAPI extends IntentService { try { cf = CertificateFactory.getInstance("X.509"); - String cert_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.main_cert_key); - String cert_string = new JSONObject(cert_json_string).getString(ConfigHelper.main_cert_key); + String cert_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_CERT_KEY); + String cert_string = new JSONObject(cert_json_string).getString(ConfigHelper.MAIN_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); @@ -454,7 +391,7 @@ public class ProviderAPI extends IntentService { int session_id_index = 0; //String delete_url = task.getString(ConfigHelper.srp_server_url_key) + "/sessions/" + client.getCookieStore().getCookies().get(0).getValue(); try { - String delete_url = task.getString(ConfigHelper.api_url_key) + "/logout" + "?authenticity_token=" + client.getCookieStore().getCookies().get(session_id_index).getValue(); + String delete_url = task.getString(ConfigHelper.API_URL_KEY) + "/logout" + "?authenticity_token=" + client.getCookieStore().getCookies().get(session_id_index).getValue(); HttpDelete delete = new HttpDelete(delete_url); HttpResponse getResponse = client.execute(delete); HttpEntity responseEntity = getResponse.getEntity(); @@ -476,24 +413,24 @@ public class ProviderAPI extends IntentService { } private boolean getNewCert(Bundle task) { - String provider_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.provider_key); - HttpCookie session_id_cookie = new HttpCookie(task.getString(ConfigHelper.session_id_cookie_key), task.getString(ConfigHelper.session_id_key)); + String provider_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.PROVIDER_KEY); + HttpCookie session_id_cookie = new HttpCookie(task.getString(ConfigHelper.SESSION_ID_COOKIE_KEY), task.getString(ConfigHelper.SESSION_ID_KEY)); try { JSONObject provider_json = new JSONObject(provider_json_string); - URL provider_main_url = new URL(provider_json.getString(ConfigHelper.api_url_key).replace("api.", "")); - String new_cert_string_url = provider_main_url.getProtocol() + "://" + provider_main_url.getHost() + "/" + provider_json.getString(ConfigHelper.api_version_key) + "/" + ConfigHelper.cert_key; + URL provider_main_url = new URL(provider_json.getString(ConfigHelper.API_URL_KEY).replace("api.", "")); + String new_cert_string_url = provider_main_url.getProtocol() + "://" + provider_main_url.getHost() + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY) + "/" + ConfigHelper.CERT_KEY; CookieManager cookieManager = new CookieManager(); cookieManager.getCookieStore().add(provider_main_url.toURI(), session_id_cookie); CookieHandler.setDefault(cookieManager); - String danger_on_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.danger_on); - boolean danger_on = new JSONObject(danger_on_json_string).getBoolean(ConfigHelper.danger_on); + String danger_on_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.DANGER_ON); + boolean danger_on = new JSONObject(danger_on_json_string).getBoolean(ConfigHelper.DANGER_ON); String cert_string = getStringFromProvider(new_cert_string_url, danger_on); if(!cert_string.isEmpty()) { - JSONObject cert_json = new JSONObject().put(ConfigHelper.cert_key, cert_string); - ConfigHelper.saveSharedPref(ConfigHelper.cert_key, cert_json); + JSONObject cert_json = new JSONObject().put(ConfigHelper.CERT_KEY, cert_string); + ConfigHelper.saveSharedPref(ConfigHelper.CERT_KEY, cert_json); return true; } else { return false; diff --git a/src/se/leap/leapclient/ProviderListContent.java b/src/se/leap/leapclient/ProviderListContent.java index d4bb6a9..b83bbd8 100644 --- a/src/se/leap/leapclient/ProviderListContent.java +++ b/src/se/leap/leapclient/ProviderListContent.java @@ -91,7 +91,7 @@ public class ProviderListContent { this.name = name; this.provider_json_url = provider_json_url; this.provider_json_filename = provider_json_filename; - eip_service_json_url = file_contents.getString("api_uri") + "/" + file_contents.getString("api_version") + "/" + ConfigHelper.eip_service_api_path; + eip_service_json_url = file_contents.getString("api_uri") + "/" + file_contents.getString("api_version") + "/" + ConfigHelper.EIP_SERVICE_API_PATH; cert_json_url = (String) file_contents.get("ca_cert_uri"); this.custom = custom; this.danger_on = danger_on; -- cgit v1.2.3 From 75edcdb601be69f4c1ee6783cf7f80390a9f094d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 14 May 2013 21:03:07 +0200 Subject: Anon certificate is downloaded if possible. I download the anon certificate only if allow_anonymous is true, and before launching Dashboard. I store it in SharedPreferences, with "cert" key, as a JSON object. --- src/se/leap/leapclient/ConfigHelper.java | 14 ++++++--- src/se/leap/leapclient/ConfigurationWizard.java | 39 ++++++++++++++++++++++++- src/se/leap/leapclient/Dashboard.java | 7 +++-- src/se/leap/leapclient/ProviderAPI.java | 24 ++++++++------- 4 files changed, 66 insertions(+), 18 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 5d44f00..6a70378 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -37,14 +37,18 @@ public class ConfigHelper { SRP_AUTH = "srpAuth", LOG_IN = "logIn", LOG_OUT = "logOut", - DOWNLOAD_USER_AUTHED_CERTIFICATE = "downloadUserAuthedCertificate", + DOWNLOAD_CERTIFICATE = "downloadUserAuthedCertificate", API_VERSION_KEY = "api_version", RESULT_KEY = "result", PROVIDER_KEY = "provider", SERVICE_KEY = "service", + ALLOWED_ANON = "allow_anonymous", MAIN_CERT_KEY = "main_cert", CERT_KEY = "cert", EIP_SERVICE_KEY = "eip", + TYPE_OF_CERTIFICATE = "type_of_certificate", + ANON_CERTIFICATE = "anon_certificate", + AUTHED_CERTIFICATE = "authed_certificate", SALT_KEY = "salt", SESSION_ID_COOKIE_KEY = "session_id_cookie_key", SESSION_ID_KEY = "session_id", @@ -76,10 +80,12 @@ public class ConfigHelper { SRP_REGISTRATION_FAILED = 6, LOGOUT_SUCCESSFUL = 7, LOGOUT_FAILED = 8, - CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE = 9, - INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE = 10, + CORRECTLY_DOWNLOADED_CERTIFICATE = 9, + INCORRECTLY_DOWNLOADED_CERTIFICATE = 10, CORRECTLY_UPDATED_PROVIDER_DOT_JSON = 11, - INCORRECTLY_UPDATED_PROVIDER_DOT_JSON = 12 + INCORRECTLY_UPDATED_PROVIDER_DOT_JSON = 12, + CORRECTLY_DOWNLOADED_ANON_CERTIFICATE = 13, + INCORRECTLY_DOWNLOADED_ANON_CERTIFICATE = 14 ; public static void saveSharedPref(String shared_preferences_key, JSONObject content) { diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 78ac046..fff155a 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -73,7 +73,6 @@ public class ConfigurationWizard extends Activity } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES) { setResult(RESULT_OK); - finish(); } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES) { setResult(RESULT_CANCELED); @@ -86,6 +85,7 @@ public class ConfigurationWizard extends Activity boolean danger_on = resultData.getBoolean(ConfigHelper.DANGER_ON); ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, new JSONObject().put(ConfigHelper.DANGER_ON, danger_on)); + downloadAnonCert(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -94,6 +94,14 @@ public class ConfigurationWizard extends Activity else if(resultCode == ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON) { Toast.makeText(getApplicationContext(), "Install a new version of this app.", Toast.LENGTH_LONG).show(); } + else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE) { + setResult(RESULT_OK); + Toast.makeText(getApplicationContext(), "Your anon cert has been correctly downloaded", Toast.LENGTH_LONG).show(); + finish(); + } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_CERTIFICATE) { + setResult(RESULT_CANCELED); + Toast.makeText(getApplicationContext(), "Your anon cert was not downloaded", Toast.LENGTH_LONG).show(); + } } /** @@ -155,7 +163,9 @@ public class ConfigurationWizard extends Activity provider_contents = new Scanner(ConfigHelper.openFileInputStream(current_provider_item.provider_json_filename)).useDelimiter("\\A").next(); provider_json = new JSONObject(provider_contents); ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); + ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, new JSONObject().put(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON))); ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, new JSONObject().put(ConfigHelper.DANGER_ON, current_provider_item.danger_on)); + downloadAnonCert(); return true; } } catch (JSONException e) { @@ -182,6 +192,33 @@ public class ConfigurationWizard extends Activity startService(provider_API_command); } + private boolean downloadAnonCert() { + + JSONObject allowed_anon; + try { + allowed_anon = new JSONObject(ConfigHelper.getStringFromSharedPref(ConfigHelper.ALLOWED_ANON)); + if(allowed_anon.getBoolean(ConfigHelper.ALLOWED_ANON)) { + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); + + Intent provider_API_command = new Intent(this, ProviderAPI.class); + + Bundle method_and_parameters = new Bundle(); + + method_and_parameters.putString(ConfigHelper.TYPE_OF_CERTIFICATE, ConfigHelper.ANON_CERTIFICATE); + + provider_API_command.putExtra(ConfigHelper.DOWNLOAD_CERTIFICATE, method_and_parameters); + provider_API_command.putExtra("receiver", providerAPI_result_receiver); + + startService(provider_API_command); + return true; + } else { + return false; + } + } catch (JSONException e) { + return false; + } + } public void addNewProvider(View view) { FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.NEW_PROVIDER_DIALOG); diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index b937c94..5ffbc19 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -250,10 +250,11 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf Intent provider_API_command = new Intent(this, ProviderAPI.class); Bundle method_and_parameters = new Bundle(); + method_and_parameters.putString(ConfigHelper.TYPE_OF_CERTIFICATE, ConfigHelper.AUTHED_CERTIFICATE); method_and_parameters.putString(ConfigHelper.SESSION_ID_COOKIE_KEY, session_id.getName()); method_and_parameters.putString(ConfigHelper.SESSION_ID_KEY, session_id.getValue()); - provider_API_command.putExtra(ConfigHelper.DOWNLOAD_USER_AUTHED_CERTIFICATE, method_and_parameters); + provider_API_command.putExtra(ConfigHelper.DOWNLOAD_CERTIFICATE, method_and_parameters); provider_API_command.putExtra("receiver", providerAPI_result_receiver); startService(provider_API_command); @@ -278,10 +279,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } else if(resultCode == ConfigHelper.LOGOUT_FAILED) { setResult(RESULT_CANCELED); Toast.makeText(getApplicationContext(), "Didn't logged out", Toast.LENGTH_LONG).show(); - } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE) { + } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE) { setResult(RESULT_CANCELED); Toast.makeText(getApplicationContext(), "Your own cert has been correctly downloaded", Toast.LENGTH_LONG).show(); - } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE) { + } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_CERTIFICATE) { setResult(RESULT_CANCELED); Toast.makeText(getApplicationContext(), "Your own cert has incorrectly been downloaded", Toast.LENGTH_LONG).show(); } diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 0003344..d5e164d 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -100,11 +100,11 @@ public class ProviderAPI extends IntentService { receiver.send(ConfigHelper.LOGOUT_FAILED, Bundle.EMPTY); } } - else if ((task = task_for.getBundleExtra(ConfigHelper.DOWNLOAD_USER_AUTHED_CERTIFICATE)) != null) { + else if ((task = task_for.getBundleExtra(ConfigHelper.DOWNLOAD_CERTIFICATE)) != null) { if(getNewCert(task)) { - receiver.send(ConfigHelper.CORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE, Bundle.EMPTY); + receiver.send(ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); } else { - receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_AUTHED_USER_CERTIFICATE, Bundle.EMPTY); + receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); } } } @@ -224,7 +224,9 @@ public class ProviderAPI extends IntentService { JSONObject provider_json = getJSONFromProvider(provider_json_url, danger_on); if(provider_json == null) { result.putBoolean(ConfigHelper.RESULT_KEY, false); - } else { + } else { + ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, new JSONObject().put(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON))); + String filename = provider_name + "_provider.json".replaceFirst("__", "_"); ConfigHelper.saveFile(filename, provider_json.toString()); @@ -414,17 +416,20 @@ public class ProviderAPI extends IntentService { private boolean getNewCert(Bundle task) { String provider_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.PROVIDER_KEY); - HttpCookie session_id_cookie = new HttpCookie(task.getString(ConfigHelper.SESSION_ID_COOKIE_KEY), task.getString(ConfigHelper.SESSION_ID_KEY)); - + String type_of_certificate = task.getString(ConfigHelper.TYPE_OF_CERTIFICATE); try { JSONObject provider_json = new JSONObject(provider_json_string); URL provider_main_url = new URL(provider_json.getString(ConfigHelper.API_URL_KEY).replace("api.", "")); String new_cert_string_url = provider_main_url.getProtocol() + "://" + provider_main_url.getHost() + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY) + "/" + ConfigHelper.CERT_KEY; - CookieManager cookieManager = new CookieManager(); - cookieManager.getCookieStore().add(provider_main_url.toURI(), session_id_cookie); - CookieHandler.setDefault(cookieManager); + if(type_of_certificate.equalsIgnoreCase(ConfigHelper.AUTHED_CERTIFICATE)) { + HttpCookie session_id_cookie = new HttpCookie(task.getString(ConfigHelper.SESSION_ID_COOKIE_KEY), task.getString(ConfigHelper.SESSION_ID_KEY)); + CookieManager cookieManager = new CookieManager(); + cookieManager.getCookieStore().add(provider_main_url.toURI(), session_id_cookie); + CookieHandler.setDefault(cookieManager); + } + String danger_on_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.DANGER_ON); boolean danger_on = new JSONObject(danger_on_json_string).getBoolean(ConfigHelper.DANGER_ON); String cert_string = getStringFromProvider(new_cert_string_url, danger_on); @@ -435,7 +440,6 @@ public class ProviderAPI extends IntentService { } else { return false; } - } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); -- cgit v1.2.3 From 7b75fbe9ca3b2d6175b124b26f5d8f527b15d1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 29 May 2013 19:54:26 +0200 Subject: Fixed passwords with strange characters? Using two test with values from my localhost leap_web deployment, I've achieved to login with passwords containing ! and $ without problems. This should fix bug #2348. --- src/se/leap/leapclient/LeapSRPSession.java | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 7b32e79..715e9de 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -95,35 +95,24 @@ public class LeapSRPSession { MessageDigest x_digest = newDigest(); // Try to convert the username to a byte[] using UTF-8 byte[] user = null; + byte[] password_bytes = null; byte[] colon = {}; try { user = Util.trim(username.getBytes("UTF-8")); colon = Util.trim(":".getBytes("UTF-8")); + password_bytes = Util.trim(password.getBytes("UTF-8")); } catch(UnsupportedEncodingException e) { // Use the default platform encoding user = Util.trim(username.getBytes()); colon = Util.trim(":".getBytes()); + password_bytes = Util.trim(password.getBytes()); } - - byte[] passBytes = new byte[2*password.toCharArray().length]; - int passBytesLength = 0; - for(int p = 0; p < password.toCharArray().length; p++) { - int c = (password.toCharArray()[p] & 0x00FFFF); - // The low byte of the char - byte b0 = (byte) (c & 0x0000FF); - // The high byte of the char - byte b1 = (byte) ((c & 0x00FF00) >> 8); - passBytes[passBytesLength ++] = b0; - // Only encode the high byte if c is a multi-byte char - if( c > 255 ) - passBytes[passBytesLength ++] = b1; - } - + // Build the hash x_digest.update(user); x_digest.update(colon); - x_digest.update(passBytes, 0, passBytesLength); + x_digest.update(password_bytes); byte[] h = x_digest.digest(); //h = Util.trim(h); -- cgit v1.2.3 From ac47aab124d63add14189cb3d03e3a05361a7932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 4 Jun 2013 16:31:39 +0200 Subject: Fixed 2 important bugs. LeapSRPSession was doing bad SRP calculations when salt byte array started with a 0. Now I trimmed that array before using it. ProviderAPI was not timing out when a server didn't respond. Now, I use a timeout of 1 second to stop waiting for a response. --- src/se/leap/leapclient/LeapSRPSession.java | 27 ++++++++++++++++++++++++--- src/se/leap/leapclient/ProviderAPI.java | 13 +++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 715e9de..8d6f77b 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -109,13 +109,29 @@ public class LeapSRPSession { password_bytes = Util.trim(password.getBytes()); } + /*byte[] passBytes = new byte[2*password.toCharArray().length]; + int passBytesLength = 0; + for(int p = 0; p < password.toCharArray().length; p++) { + int c = (password.toCharArray()[p] & 0x00FFFF); + // The low byte of the char + byte b0 = (byte) (c & 0x0000FF); + // The high byte of the char + byte b1 = (byte) ((c & 0x00FF00) >> 8); + passBytes[passBytesLength ++] = b0; + // Only encode the high byte if c is a multi-byte char + if( c > 255 ) + passBytes[passBytesLength ++] = b1; + }*/ + // Build the hash x_digest.update(user); x_digest.update(colon); x_digest.update(password_bytes); + //x_digest.update(passBytes, 0, passBytesLength); byte[] h = x_digest.digest(); + String hstr = new BigInteger(1, h).toString(16); //h = Util.trim(h); - + //25c19c2b903ff36dd5acd6e1136b8f3af008ceee45103ef9771334f4246d6226 x_digest.reset(); x_digest.update(salt); x_digest.update(h); @@ -173,8 +189,9 @@ public class LeapSRPSession { */ public byte[] response(byte[] salt_bytes, byte[] Bbytes) throws NoSuchAlgorithmException { // Calculate x = H(s | H(U | ':' | password)) - byte[] xb = calculatePasswordHash(username, password, salt_bytes); + byte[] xb = calculatePasswordHash(username, password, Util.trim(salt_bytes)); this.x = new BigInteger(1, xb); + String xstr = x.toString(16); // Calculate v = kg^x mod N String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; @@ -211,6 +228,7 @@ public class LeapSRPSession { // Calculate S = (B - kg^x) ^ (a + u * x) % N BigInteger S = calculateS(Bbytes); byte[] S_bytes = Util.trim(S.toByteArray()); + String Sstr = S.toString(16); // K = SessionHash(S) String hash_algorithm = params.hashAlgorithm; @@ -219,8 +237,10 @@ public class LeapSRPSession { // clientHash = H(N) xor H(g) | H(U) | A | B | K clientHash.update(K); + String Kstr = new BigInteger(1, K).toString(16); byte[] M1 = Util.trim(clientHash.digest()); + String M1str = new BigInteger(1, M1).toString(16); // serverHash = Astr + M + K serverHash.update(Abytes); @@ -244,9 +264,10 @@ public class LeapSRPSession { BigInteger u = new BigInteger(1, u_bytes); BigInteger B_minus_v = B.subtract(v); + String vstr = v.toString(16); BigInteger a_ux = a.add(u.multiply(x)); + String xstr = x.toString(16); BigInteger S = B_minus_v.modPow(a_ux, N); - return S; } diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index d5e164d..a6a2d6b 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -15,8 +15,10 @@ import java.net.CookieHandler; import java.net.CookieManager; import java.net.HttpCookie; import java.net.MalformedURLException; +import java.net.SocketTimeoutException; import java.net.URISyntaxException; import java.net.URL; +import java.net.URLConnection; import java.util.Scanner; import javax.net.ssl.HostnameVerifier; @@ -296,12 +298,17 @@ public class ProviderAPI extends IntentService { String json_file_content = ""; URL provider_url = null; + int seconds_of_timeout = 1; try { provider_url = new URL(string_url); - json_file_content = new Scanner(provider_url.openStream()).useDelimiter("\\A").next(); + URLConnection url_connection = provider_url.openConnection(); + url_connection.setConnectTimeout(seconds_of_timeout*1000); + json_file_content = new Scanner(url_connection.getInputStream()).useDelimiter("\\A").next(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); + } catch(SocketTimeoutException e) { + return ""; } catch (IOException e) { // TODO SSLHandshakeException // This means that we have not added ca.crt to the trusted certificates. @@ -310,8 +317,10 @@ public class ProviderAPI extends IntentService { } //json_file_content = downloadStringFromProviderWithCACertAdded(string_url); e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); } - + return json_file_content; } -- cgit v1.2.3 From 46bc4830705bc0a21f28d3e7b3899c2a978f4915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 4 Jun 2013 17:09:28 +0200 Subject: Fix bug #2717. "https://" is automatically appended. --- src/se/leap/leapclient/NewProviderDialog.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/NewProviderDialog.java b/src/se/leap/leapclient/NewProviderDialog.java index 9978800..07185b4 100644 --- a/src/se/leap/leapclient/NewProviderDialog.java +++ b/src/se/leap/leapclient/NewProviderDialog.java @@ -52,6 +52,9 @@ public class NewProviderDialog extends DialogFragment { .setPositiveButton(R.string.save, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { String entered_url = url_input_field.getText().toString().trim(); + if(!entered_url.startsWith("https://")) { + entered_url = "https://".concat(entered_url); + } boolean danger_on = danger_checkbox.isChecked(); if(validURL(entered_url)) { interface_with_ConfigurationWizard.saveProvider(entered_url, danger_on); -- cgit v1.2.3 From 611bb7869ea6a98fe656b6e86ef98118d232fd45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 4 Jun 2013 20:42:05 +0200 Subject: Fixed SRP strange characters bugs. The problem was the encoding of the bytes when calculating the password hash. I supposed that it was UTF-8 (I already saw that encoding in the html code from leap_web), but not, it was ISO-8859-1 (trial/error). --- src/se/leap/leapclient/LeapSRPSession.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 8d6f77b..77f4394 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -97,10 +97,11 @@ public class LeapSRPSession { byte[] user = null; byte[] password_bytes = null; byte[] colon = {}; + String encoding = "ISO-8859-1"; try { - user = Util.trim(username.getBytes("UTF-8")); - colon = Util.trim(":".getBytes("UTF-8")); - password_bytes = Util.trim(password.getBytes("UTF-8")); + user = Util.trim(username.getBytes(encoding)); + colon = Util.trim(":".getBytes(encoding)); + password_bytes = Util.trim(password.getBytes(encoding)); } catch(UnsupportedEncodingException e) { // Use the default platform encoding -- cgit v1.2.3 From d74a3ae14a27893572d170c138e18522b541866a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 5 Jun 2013 18:57:55 +0200 Subject: Fixed passwords with \ character. The substitution I was doing let me to pass my tests localhost, but was not valid for real use in Android emulator. This was so because JSONObject getString method understood \/ simply as /, while what I wanted was plain \/. This commit makes #2368 --- src/se/leap/leapclient/LeapSRPSession.java | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 77f4394..47dff27 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -90,10 +90,10 @@ public class LeapSRPSession { */ public byte[] calculatePasswordHash(String username, String password, byte[] salt) { - password = password.replaceAll("\\\\", "\\\\\\\\"); + //password = password.replaceAll("\\\\", "\\\\\\\\"); // Calculate x = H(s | H(U | ':' | password)) MessageDigest x_digest = newDigest(); - // Try to convert the username to a byte[] using UTF-8 + // Try to convert the username to a byte[] using ISO-8859-1 byte[] user = null; byte[] password_bytes = null; byte[] colon = {}; @@ -110,29 +110,12 @@ public class LeapSRPSession { password_bytes = Util.trim(password.getBytes()); } - /*byte[] passBytes = new byte[2*password.toCharArray().length]; - int passBytesLength = 0; - for(int p = 0; p < password.toCharArray().length; p++) { - int c = (password.toCharArray()[p] & 0x00FFFF); - // The low byte of the char - byte b0 = (byte) (c & 0x0000FF); - // The high byte of the char - byte b1 = (byte) ((c & 0x00FF00) >> 8); - passBytes[passBytesLength ++] = b0; - // Only encode the high byte if c is a multi-byte char - if( c > 255 ) - passBytes[passBytesLength ++] = b1; - }*/ - // Build the hash x_digest.update(user); x_digest.update(colon); x_digest.update(password_bytes); - //x_digest.update(passBytes, 0, passBytesLength); byte[] h = x_digest.digest(); - String hstr = new BigInteger(1, h).toString(16); - //h = Util.trim(h); - //25c19c2b903ff36dd5acd6e1136b8f3af008ceee45103ef9771334f4246d6226 + x_digest.reset(); x_digest.update(salt); x_digest.update(h); -- cgit v1.2.3 From 899583d474a0b04e168203ce06195403461b9215 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sat, 8 Jun 2013 20:55:48 -0600 Subject: Improve retrieving and saving SharedPreferences for different types (String, boolean, JSONObject) --- src/se/leap/leapclient/ConfigHelper.java | 63 +++++++++++++++++++++---- src/se/leap/leapclient/ConfigurationWizard.java | 46 +++++++++--------- src/se/leap/leapclient/Dashboard.java | 9 ++++ src/se/leap/leapclient/ProviderAPI.java | 21 +++------ 4 files changed, 91 insertions(+), 48 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 6a70378..e8bc27c 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -18,6 +18,7 @@ import java.security.cert.X509Certificate; import org.json.JSONException; import org.json.JSONObject; +import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; import android.util.Log; @@ -88,6 +89,17 @@ public class ConfigHelper { INCORRECTLY_DOWNLOADED_ANON_CERTIFICATE = 14 ; + + private static boolean checkSharedPrefs() { + try { + shared_preferences = Dashboard.getAppContext().getSharedPreferences(PREFERENCES_KEY,Context.MODE_PRIVATE); + } catch (Exception e) { + return false; + } + + return true; + } + public static void saveSharedPref(String shared_preferences_key, JSONObject content) { SharedPreferences.Editor shared_preferences_editor = shared_preferences @@ -97,16 +109,49 @@ public class ConfigHelper { shared_preferences_editor.commit(); } + public static void saveSharedPref(String shared_preferences_key, String content) { + + SharedPreferences.Editor shared_preferences_editor = shared_preferences + .edit(); + shared_preferences_editor.putString(shared_preferences_key, + content); + shared_preferences_editor.commit(); + } + + public static void saveSharedPref(String shared_preferences_key, boolean content) { + + SharedPreferences.Editor shared_preferences_editor = shared_preferences + .edit(); + shared_preferences_editor.putBoolean(shared_preferences_key, content); + shared_preferences_editor.commit(); + } + public static String getStringFromSharedPref(String shared_preferences_key) { - String value = ""; - if(shared_preferences != null) { - String content = shared_preferences.getString(shared_preferences_key, ""); - try { - JSONObject json_object = new JSONObject(content); - value = json_object.toString(); - } catch (JSONException e) { - value = content; - } + String content = null; + if ( checkSharedPrefs() ) { + content = shared_preferences.getString(shared_preferences_key, ""); + } + return content; + } + + public static JSONObject getJsonFromSharedPref(String shared_preferences_key) throws JSONException { + JSONObject content = null; + if ( checkSharedPrefs() ) { + content = new JSONObject( shared_preferences.getString(shared_preferences_key, "") ); + } + + return content; + } + + /* + * This method defaults to false. + * If you use this method, be sure to fail-closed on false! + * TODO This is obviously less than ideal...solve it! + */ + public static boolean getBoolFromSharedPref(String shared_preferences_key) { + boolean value = false; + if ( checkSharedPrefs() ) { + value = shared_preferences.getBoolean(shared_preferences_key, false); } return value; } diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index fff155a..3afbdac 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -84,7 +84,7 @@ public class ConfigurationWizard extends Activity provider_json = new JSONObject(resultData.getString(ConfigHelper.PROVIDER_KEY)); boolean danger_on = resultData.getBoolean(ConfigHelper.DANGER_ON); ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); - ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, new JSONObject().put(ConfigHelper.DANGER_ON, danger_on)); + ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, danger_on); downloadAnonCert(); } catch (JSONException e) { // TODO Auto-generated catch block @@ -163,9 +163,8 @@ public class ConfigurationWizard extends Activity provider_contents = new Scanner(ConfigHelper.openFileInputStream(current_provider_item.provider_json_filename)).useDelimiter("\\A").next(); provider_json = new JSONObject(provider_contents); ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); - ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, new JSONObject().put(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON))); - ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, new JSONObject().put(ConfigHelper.DANGER_ON, current_provider_item.danger_on)); - downloadAnonCert(); + ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON)); + ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, current_provider_item.danger_on); return true; } } catch (JSONException e) { @@ -194,31 +193,28 @@ public class ConfigurationWizard extends Activity private boolean downloadAnonCert() { - JSONObject allowed_anon; - try { - allowed_anon = new JSONObject(ConfigHelper.getStringFromSharedPref(ConfigHelper.ALLOWED_ANON)); - if(allowed_anon.getBoolean(ConfigHelper.ALLOWED_ANON)) { - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); - - Intent provider_API_command = new Intent(this, ProviderAPI.class); - - Bundle method_and_parameters = new Bundle(); - - method_and_parameters.putString(ConfigHelper.TYPE_OF_CERTIFICATE, ConfigHelper.ANON_CERTIFICATE); - - provider_API_command.putExtra(ConfigHelper.DOWNLOAD_CERTIFICATE, method_and_parameters); - provider_API_command.putExtra("receiver", providerAPI_result_receiver); + boolean allowed_anon; + allowed_anon = ConfigHelper.getBoolFromSharedPref(ConfigHelper.ALLOWED_ANON); + if(allowed_anon) { + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); - startService(provider_API_command); - return true; - } else { - return false; - } - } catch (JSONException e) { + Intent provider_API_command = new Intent(this, ProviderAPI.class); + + Bundle method_and_parameters = new Bundle(); + + method_and_parameters.putString(ConfigHelper.TYPE_OF_CERTIFICATE, ConfigHelper.ANON_CERTIFICATE); + + provider_API_command.putExtra(ConfigHelper.DOWNLOAD_CERTIFICATE, method_and_parameters); + provider_API_command.putExtra("receiver", providerAPI_result_receiver); + + startService(provider_API_command); + return true; + } else { return false; } } + public void addNewProvider(View view) { FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.NEW_PROVIDER_DIALOG); diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index 5ffbc19..de7946e 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -16,6 +16,7 @@ import android.app.Activity; import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentTransaction; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; @@ -34,6 +35,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf protected static final int CONFIGURE_LEAP = 0; + private static Context app; private static SharedPreferences preferences; private static Provider provider; @@ -45,6 +47,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + app = this; + setContentView(R.layout.client_dashboard); preferences = getSharedPreferences(ConfigHelper.PREFERENCES_KEY,MODE_PRIVATE); @@ -288,4 +293,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } } + // Used for getting Context when outside of a class extending Context + public static Context getAppContext() { + return app; + } } diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index a6a2d6b..cd19da0 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -117,8 +117,7 @@ public class ProviderAPI extends IntentService { boolean danger_on = task.getBoolean(ConfigHelper.DANGER_ON); try { String cert_string = getStringFromProvider(cert_url, danger_on); - JSONObject cert_json = new JSONObject().put(ConfigHelper.MAIN_CERT_KEY, cert_string); - ConfigHelper.saveSharedPref(ConfigHelper.MAIN_CERT_KEY, cert_json); + ConfigHelper.saveSharedPref(ConfigHelper.MAIN_CERT_KEY, cert_string); JSONObject eip_service_json = getJSONFromProvider(eip_service_json_url, danger_on); ConfigHelper.saveSharedPref(ConfigHelper.EIP_SERVICE_KEY, eip_service_json); return true; @@ -227,7 +226,7 @@ public class ProviderAPI extends IntentService { if(provider_json == null) { result.putBoolean(ConfigHelper.RESULT_KEY, false); } else { - ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, new JSONObject().put(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON))); + ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON)); String filename = provider_name + "_provider.json".replaceFirst("__", "_"); ConfigHelper.saveFile(filename, provider_json.toString()); @@ -333,8 +332,7 @@ public class ProviderAPI extends IntentService { try { cf = CertificateFactory.getInstance("X.509"); - String cert_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_CERT_KEY); - String cert_string = new JSONObject(cert_json_string).getString(ConfigHelper.MAIN_CERT_KEY); + String cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_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); @@ -381,10 +379,8 @@ public class ProviderAPI extends IntentService { } catch (KeyManagementException e) { // TODO Auto-generated catch block e.printStackTrace(); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); } + return json_file_content; } @@ -424,10 +420,9 @@ public class ProviderAPI extends IntentService { } private boolean getNewCert(Bundle task) { - String provider_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.PROVIDER_KEY); String type_of_certificate = task.getString(ConfigHelper.TYPE_OF_CERTIFICATE); try { - JSONObject provider_json = new JSONObject(provider_json_string); + JSONObject provider_json = ConfigHelper.getJsonFromSharedPref(ConfigHelper.PROVIDER_KEY); URL provider_main_url = new URL(provider_json.getString(ConfigHelper.API_URL_KEY).replace("api.", "")); String new_cert_string_url = provider_main_url.getProtocol() + "://" + provider_main_url.getHost() + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY) + "/" + ConfigHelper.CERT_KEY; @@ -439,12 +434,10 @@ public class ProviderAPI extends IntentService { CookieHandler.setDefault(cookieManager); } - String danger_on_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.DANGER_ON); - boolean danger_on = new JSONObject(danger_on_json_string).getBoolean(ConfigHelper.DANGER_ON); + boolean danger_on = ConfigHelper.getBoolFromSharedPref(ConfigHelper.DANGER_ON); String cert_string = getStringFromProvider(new_cert_string_url, danger_on); if(!cert_string.isEmpty()) { - JSONObject cert_json = new JSONObject().put(ConfigHelper.CERT_KEY, cert_string); - ConfigHelper.saveSharedPref(ConfigHelper.CERT_KEY, cert_json); + ConfigHelper.saveSharedPref(ConfigHelper.CERT_KEY, cert_string); return true; } else { return false; -- cgit v1.2.3 From 344a4596e38bb4a908f2791e2f710eb485a5e719 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sat, 8 Jun 2013 21:33:11 -0600 Subject: Make LogInDialog accept passwords >= 8 characters, instead of > 8 --- src/se/leap/leapclient/LogInDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LogInDialog.java b/src/se/leap/leapclient/LogInDialog.java index 370a138..2688967 100644 --- a/src/se/leap/leapclient/LogInDialog.java +++ b/src/se/leap/leapclient/LogInDialog.java @@ -47,7 +47,7 @@ public class LogInDialog extends DialogFragment { } boolean wellFormedPassword(String entered_password) { - return entered_password.length() > 8; + return entered_password.length() >= 8; } public interface LogInDialogInterface { -- cgit v1.2.3 From d14ae81fe92494a67994d703e1175ef4264adddb Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sat, 8 Jun 2013 21:58:00 -0600 Subject: Refactor ConfigurationWizard for better task handling, completion, and return information --- src/se/leap/leapclient/ConfigurationWizard.java | 99 ++++++++++++++----------- 1 file changed, 54 insertions(+), 45 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 3afbdac..389c291 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -33,7 +33,12 @@ public class ConfigurationWizard extends Activity * device. */ private boolean mTwoPane; + private ProviderItem mSelectedProvider; + private Intent mConfigState = new Intent(); + protected static final String PROVIDER_SET = "PROVIDER SET"; + protected static final String SERVICES_RETRIEVED = "SERVICES RETRIEVED"; + public ProviderAPIResultReceiver providerAPI_result_receiver; @Override @@ -41,6 +46,9 @@ public class ConfigurationWizard extends Activity super.onCreate(savedInstanceState); setContentView(R.layout.activity_configuration_wizard); + + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); ConfigHelper.setSharedPreferences(getSharedPreferences(ConfigHelper.PREFERENCES_KEY, MODE_PRIVATE)); @@ -72,11 +80,19 @@ public class ConfigurationWizard extends Activity .commit(); } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES) { - setResult(RESULT_OK); + if (ConfigHelper.getBoolFromSharedPref(ConfigHelper.ALLOWED_ANON)){ + mConfigState.putExtra(SERVICES_RETRIEVED, true); + downloadAnonCert(); + } else { + Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_LONG).show(); + setResult(RESULT_OK); + finish(); + } } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES) { - setResult(RESULT_CANCELED); Toast.makeText(getApplicationContext(), "You have not entered a LEAP provider URL or it is unavailable", Toast.LENGTH_LONG).show(); + setResult(RESULT_CANCELED, mConfigState); + finish(); } else if(resultCode == ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON) { JSONObject provider_json; @@ -85,22 +101,35 @@ public class ConfigurationWizard extends Activity boolean danger_on = resultData.getBoolean(ConfigHelper.DANGER_ON); ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, danger_on); - downloadAnonCert(); + ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getBoolean(ConfigHelper.ALLOWED_ANON)); + + mConfigState.setAction(PROVIDER_SET); + + downloadJSONFiles(mSelectedProvider); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); + + Toast.makeText(this, getResources().getString(R.string.config_error_parsing), Toast.LENGTH_LONG); + setResult(RESULT_CANCELED, mConfigState); + finish(); } } else if(resultCode == ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON) { Toast.makeText(getApplicationContext(), "Install a new version of this app.", Toast.LENGTH_LONG).show(); + setResult(RESULT_CANCELED, mConfigState); + finish(); } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE) { - setResult(RESULT_OK); Toast.makeText(getApplicationContext(), "Your anon cert has been correctly downloaded", Toast.LENGTH_LONG).show(); + Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_LONG).show(); + //mConfigState.putExtra(CERTIFICATE_RETRIEVED, true); // If this isn't the last step and finish() is moved... + setResult(RESULT_OK); finish(); } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_CERTIFICATE) { - setResult(RESULT_CANCELED); Toast.makeText(getApplicationContext(), "Your anon cert was not downloaded", Toast.LENGTH_LONG).show(); + setResult(RESULT_CANCELED, mConfigState); + finish(); } } @@ -114,16 +143,11 @@ public class ConfigurationWizard extends Activity Iterator preseeded_providers_iterator = ProviderListContent.ITEMS.iterator(); while(preseeded_providers_iterator.hasNext()) { - ProviderItem current_provider_item = preseeded_providers_iterator.next(); - if(current_provider_item.id.equalsIgnoreCase(id)) + ProviderItem provider = preseeded_providers_iterator.next(); + if(provider.id.equalsIgnoreCase(id)) { - try { - saveProviderJson(current_provider_item); - downloadJSONFiles(current_provider_item); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + mSelectedProvider = provider; + saveProviderJson(mSelectedProvider); } } } @@ -152,30 +176,31 @@ public class ConfigurationWizard extends Activity return loaded_preseeded_providers; } - private boolean saveProviderJson(ProviderItem current_provider_item) { + private void saveProviderJson(ProviderItem current_provider_item) { JSONObject provider_json = new JSONObject(); try { String provider_contents = ""; if(!current_provider_item.custom) { updateProviderDotJson(current_provider_item.name, current_provider_item.provider_json_url, current_provider_item.danger_on); - return true; } else { + // FIXME!! We should we be updating our seeded providers list at ConfigurationWizard onStart() ? + // I think yes, but if so, where does this list live? leap.se, as it's the non-profit project for the software? + // If not, we should just be getting names/urls, and fetching the provider.json like in custom entries provider_contents = new Scanner(ConfigHelper.openFileInputStream(current_provider_item.provider_json_filename)).useDelimiter("\\A").next(); provider_json = new JSONObject(provider_contents); ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON)); ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, current_provider_item.danger_on); - return true; + + downloadJSONFiles(mSelectedProvider); } } catch (JSONException e) { - return false; + setResult(RESULT_CANCELED); + finish(); } } - private void downloadJSONFiles(ProviderItem current_provider_item) throws IOException { - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); - + private void downloadJSONFiles(ProviderItem current_provider_item) { Intent provider_API_command = new Intent(this, ProviderAPI.class); Bundle method_and_parameters = new Bundle(); @@ -192,27 +217,17 @@ public class ConfigurationWizard extends Activity } private boolean downloadAnonCert() { + Intent provider_API_command = new Intent(this, ProviderAPI.class); - boolean allowed_anon; - allowed_anon = ConfigHelper.getBoolFromSharedPref(ConfigHelper.ALLOWED_ANON); - if(allowed_anon) { - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); - - Intent provider_API_command = new Intent(this, ProviderAPI.class); - - Bundle method_and_parameters = new Bundle(); + Bundle method_and_parameters = new Bundle(); - method_and_parameters.putString(ConfigHelper.TYPE_OF_CERTIFICATE, ConfigHelper.ANON_CERTIFICATE); + method_and_parameters.putString(ConfigHelper.TYPE_OF_CERTIFICATE, ConfigHelper.ANON_CERTIFICATE); - provider_API_command.putExtra(ConfigHelper.DOWNLOAD_CERTIFICATE, method_and_parameters); - provider_API_command.putExtra("receiver", providerAPI_result_receiver); + provider_API_command.putExtra(ConfigHelper.DOWNLOAD_CERTIFICATE, method_and_parameters); + provider_API_command.putExtra("receiver", providerAPI_result_receiver); - startService(provider_API_command); - return true; - } else { - return false; - } + startService(provider_API_command); + return true; } public void addNewProvider(View view) { @@ -229,9 +244,6 @@ public class ConfigurationWizard extends Activity @Override public void saveProvider(String provider_main_url, boolean danger_on) { - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); - Intent provider_API_command = new Intent(this, ProviderAPI.class); Bundle method_and_parameters = new Bundle(); @@ -245,9 +257,6 @@ public class ConfigurationWizard extends Activity } public void updateProviderDotJson(String provider_name, String provider_json_url, boolean danger_on) { - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); - Intent provider_API_command = new Intent(this, ProviderAPI.class); Bundle method_and_parameters = new Bundle(); -- cgit v1.2.3 From 626b32fba7b6b45bead3b79fb7e7aa6cddc5c535 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sat, 8 Jun 2013 22:07:39 -0600 Subject: Add ProgressDialog to ConfigurationWizard while downloading from provider --- src/se/leap/leapclient/ConfigurationWizard.java | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 389c291..164b1d4 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -17,6 +17,7 @@ import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; +import android.app.ProgressDialog; import android.content.Intent; import android.content.res.AssetManager; import android.os.Bundle; @@ -34,6 +35,7 @@ public class ConfigurationWizard extends Activity */ private boolean mTwoPane; private ProviderItem mSelectedProvider; + private ProgressDialog mProgressDialog; private Intent mConfigState = new Intent(); protected static final String PROVIDER_SET = "PROVIDER SET"; @@ -81,9 +83,11 @@ public class ConfigurationWizard extends Activity } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES) { if (ConfigHelper.getBoolFromSharedPref(ConfigHelper.ALLOWED_ANON)){ + mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_certificates)); mConfigState.putExtra(SERVICES_RETRIEVED, true); downloadAnonCert(); } else { + mProgressDialog.dismiss(); Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_LONG).show(); setResult(RESULT_OK); finish(); @@ -105,28 +109,33 @@ public class ConfigurationWizard extends Activity mConfigState.setAction(PROVIDER_SET); + mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_services)); downloadJSONFiles(mSelectedProvider); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); + mProgressDialog.dismiss(); Toast.makeText(this, getResources().getString(R.string.config_error_parsing), Toast.LENGTH_LONG); setResult(RESULT_CANCELED, mConfigState); finish(); } } else if(resultCode == ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON) { + mProgressDialog.dismiss(); Toast.makeText(getApplicationContext(), "Install a new version of this app.", Toast.LENGTH_LONG).show(); setResult(RESULT_CANCELED, mConfigState); finish(); } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE) { + mProgressDialog.dismiss(); Toast.makeText(getApplicationContext(), "Your anon cert has been correctly downloaded", Toast.LENGTH_LONG).show(); Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_LONG).show(); //mConfigState.putExtra(CERTIFICATE_RETRIEVED, true); // If this isn't the last step and finish() is moved... setResult(RESULT_OK); finish(); } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_CERTIFICATE) { + mProgressDialog.dismiss(); Toast.makeText(getApplicationContext(), "Your anon cert was not downloaded", Toast.LENGTH_LONG).show(); setResult(RESULT_CANCELED, mConfigState); finish(); @@ -146,6 +155,7 @@ public class ConfigurationWizard extends Activity ProviderItem provider = preseeded_providers_iterator.next(); if(provider.id.equalsIgnoreCase(id)) { + mProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.config_wait_title), getResources().getString(R.string.config_connecting_provider), true); mSelectedProvider = provider; saveProviderJson(mSelectedProvider); } @@ -192,6 +202,7 @@ public class ConfigurationWizard extends Activity ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON)); ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, current_provider_item.danger_on); + mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_services)); downloadJSONFiles(mSelectedProvider); } } catch (JSONException e) { -- cgit v1.2.3 From 769344327d5cb16adbdc04db224ff6902b4a4771 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sat, 8 Jun 2013 22:27:25 -0600 Subject: Better config/partial config handling in Dashboard --- src/se/leap/leapclient/Dashboard.java | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index de7946e..6bdd74d 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -13,10 +13,12 @@ import se.leap.leapclient.R.menu; import se.leap.openvpn.AboutFragment; import se.leap.openvpn.MainActivity; import android.app.Activity; +import android.app.AlertDialog; import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; @@ -58,10 +60,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf // Check if we have preferences, run configuration wizard if not // TODO We should do a better check for config that this! - if (!preferences.contains("provider") ) - startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); - else + if (preferences.contains("provider") && preferences.getString(ConfigHelper.PROVIDER_KEY, null) != null) buildDashboard(); + else + startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); } @Override @@ -73,8 +75,26 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf buildDashboard(); } else { - // Something went wrong... TODO figure out what - // TODO Error dialog + // Something went wrong in configuration + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getAppContext()); + alertBuilder.setTitle(getResources().getString(R.string.setup_error_title)); + alertBuilder + .setMessage(getResources().getString(R.string.setup_error_text)) + .setCancelable(false) + .setPositiveButton(getResources().getString(R.string.setup_error_configure_button), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + startActivityForResult(new Intent(getAppContext(),ConfigurationWizard.class),CONFIGURE_LEAP); + } + }) + .setNegativeButton(getResources().getString(R.string.setup_error_close_button), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + SharedPreferences.Editor prefsEdit = getSharedPreferences(ConfigHelper.PREFERENCES_KEY, MODE_PRIVATE).edit(); + prefsEdit.remove(ConfigHelper.PROVIDER_KEY).commit(); + finish(); + } + }); } } } -- cgit v1.2.3 From 8acc7febb78c5a6480aa0b326e9464592e792097 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sat, 8 Jun 2013 22:44:01 -0600 Subject: Fixed onPrepareOptionsMenu to not return prematurely. Also implements ConfigHelper.getJsonFromSharedPref(), now --- src/se/leap/leapclient/Dashboard.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index 6bdd74d..f72af80 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -145,21 +145,19 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf @Override public boolean onPrepareOptionsMenu(Menu menu) { - String provider_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.PROVIDER_KEY); + JSONObject provider_json; try { - JSONObject provider_json = new JSONObject(provider_json_string); + provider_json = ConfigHelper.getJsonFromSharedPref(ConfigHelper.PROVIDER_KEY); JSONObject service_description = provider_json.getJSONObject(ConfigHelper.SERVICE_KEY); if(service_description.getBoolean(ConfigHelper.ALLOW_REGISTRATION_KEY)) { menu.findItem(R.id.login_button).setVisible(true); menu.findItem(R.id.logout_button).setVisible(true); - return true; } } catch (JSONException e) { - menu.findItem(R.id.login_button).setVisible(false); - menu.findItem(R.id.logout_button).setVisible(false); - return false; - } - return false; + // TODO Auto-generated catch block + e.printStackTrace(); + } + return true; } @Override -- cgit v1.2.3 From e581c6f2c1844d5dd96b12413df91dbb06102282 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sat, 8 Jun 2013 22:50:07 -0600 Subject: Clean up some unused and some formatting --- src/se/leap/leapclient/ConfigurationWizard.java | 10 +--------- src/se/leap/leapclient/Dashboard.java | 5 +---- src/se/leap/leapclient/LeapSRPSession.java | 2 -- src/se/leap/leapclient/LogInDialog.java | 3 --- src/se/leap/leapclient/NewProviderDialog.java | 3 --- src/se/leap/leapclient/Provider.java | 3 ++- src/se/leap/leapclient/ProviderListFragment.java | 3 --- 7 files changed, 4 insertions(+), 25 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 164b1d4..69f7356 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -10,8 +10,6 @@ import org.json.JSONObject; import se.leap.leapclient.ProviderAPIResultReceiver.Receiver; import se.leap.leapclient.ProviderListContent.ProviderItem; import se.leap.leapclient.R; -import se.leap.leapclient.R.id; -import se.leap.leapclient.R.layout; import android.app.Activity; import android.app.DialogFragment; import android.app.Fragment; @@ -26,14 +24,8 @@ import android.view.View; import android.widget.Toast; public class ConfigurationWizard extends Activity - implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogInterface, Receiver { +implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogInterface, Receiver { - - /** - * Whether or not the activity is in two-pane mode, i.e. running on a tablet - * device. - */ - private boolean mTwoPane; private ProviderItem mSelectedProvider; private ProgressDialog mProgressDialog; private Intent mConfigState = new Intent(); diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index f72af80..c1f4697 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -7,9 +7,6 @@ import org.json.JSONObject; import se.leap.leapclient.ProviderAPIResultReceiver.Receiver; import se.leap.leapclient.R; -import se.leap.leapclient.R.id; -import se.leap.leapclient.R.layout; -import se.leap.leapclient.R.menu; import se.leap.openvpn.AboutFragment; import se.leap.openvpn.MainActivity; import android.app.Activity; @@ -116,7 +113,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf private void serviceItemEIP() { // FIXME Provider service (eip/openvpn) - View eipOverview = ((ViewStub) findViewById(R.id.eipOverviewStub)).inflate(); + ((ViewStub) findViewById(R.id.eipOverviewStub)).inflate(); // Set our EIP type title eipTypeTV = (TextView) findViewById(R.id.eipType); diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 47dff27..8eb28c4 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -7,9 +7,7 @@ import java.security.NoSuchAlgorithmException; import java.util.Arrays; import org.jboss.security.Util; -import org.jboss.security.srp.SRPClientSession; import org.jboss.security.srp.SRPParameters; -import org.jboss.security.srp.SRPPermission; public class LeapSRPSession { diff --git a/src/se/leap/leapclient/LogInDialog.java b/src/se/leap/leapclient/LogInDialog.java index 2688967..c20413d 100644 --- a/src/se/leap/leapclient/LogInDialog.java +++ b/src/se/leap/leapclient/LogInDialog.java @@ -1,9 +1,6 @@ package se.leap.leapclient; import se.leap.leapclient.R; -import se.leap.leapclient.R.id; -import se.leap.leapclient.R.layout; -import se.leap.leapclient.R.string; import android.app.Activity; import android.app.AlertDialog; import android.app.DialogFragment; diff --git a/src/se/leap/leapclient/NewProviderDialog.java b/src/se/leap/leapclient/NewProviderDialog.java index 07185b4..60ac8d2 100644 --- a/src/se/leap/leapclient/NewProviderDialog.java +++ b/src/se/leap/leapclient/NewProviderDialog.java @@ -1,9 +1,6 @@ package se.leap.leapclient; import se.leap.leapclient.R; -import se.leap.leapclient.R.id; -import se.leap.leapclient.R.layout; -import se.leap.leapclient.R.string; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; diff --git a/src/se/leap/leapclient/Provider.java b/src/se/leap/leapclient/Provider.java index f86bbf5..50bd292 100644 --- a/src/se/leap/leapclient/Provider.java +++ b/src/se/leap/leapclient/Provider.java @@ -11,6 +11,7 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import android.content.Context; import android.app.Activity; import android.content.SharedPreferences; @@ -67,7 +68,7 @@ public final class Provider implements Serializable { //preferences = context.getgetPreferences(0); // 0 == MODE_PRIVATE, but we don't extend Android's classes... // Load SharedPreferences - preferences = activity.getSharedPreferences(ConfigHelper.PREFERENCES_KEY,0); // We don't get MODE_PRIVATE by importing SharedPreferences; i guess it's in Activity? + preferences = activity.getSharedPreferences(ConfigHelper.PREFERENCES_KEY,Context.MODE_PRIVATE); // Inflate our provider.json data try { definition = new JSONObject( preferences.getString("provider", "") ); diff --git a/src/se/leap/leapclient/ProviderListFragment.java b/src/se/leap/leapclient/ProviderListFragment.java index 4316e9f..ee3ee8e 100644 --- a/src/se/leap/leapclient/ProviderListFragment.java +++ b/src/se/leap/leapclient/ProviderListFragment.java @@ -2,9 +2,6 @@ package se.leap.leapclient; import se.leap.leapclient.ProviderListContent.ProviderItem; import android.app.Activity; -import android.app.DialogFragment; -import android.app.Fragment; -import android.app.FragmentTransaction; import android.app.ListFragment; import android.os.Bundle; import android.view.LayoutInflater; -- cgit v1.2.3 From 1559bc45048fb877d45247f1aa9b51ee3632a3b8 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sat, 8 Jun 2013 23:07:36 -0600 Subject: Rearrange if/elseif statements in ConfigurationWizard for logical sequence readability --- src/se/leap/leapclient/ConfigurationWizard.java | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 69f7356..2a9b93b 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -73,23 +73,6 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn .replace(R.id.configuration_wizard_layout, providerList, "providerlist") .commit(); } - else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES) { - if (ConfigHelper.getBoolFromSharedPref(ConfigHelper.ALLOWED_ANON)){ - mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_certificates)); - mConfigState.putExtra(SERVICES_RETRIEVED, true); - downloadAnonCert(); - } else { - mProgressDialog.dismiss(); - Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_LONG).show(); - setResult(RESULT_OK); - finish(); - } - } - else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES) { - Toast.makeText(getApplicationContext(), "You have not entered a LEAP provider URL or it is unavailable", Toast.LENGTH_LONG).show(); - setResult(RESULT_CANCELED, mConfigState); - finish(); - } else if(resultCode == ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON) { JSONObject provider_json; try { @@ -119,6 +102,23 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn setResult(RESULT_CANCELED, mConfigState); finish(); } + else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES) { + if (ConfigHelper.getBoolFromSharedPref(ConfigHelper.ALLOWED_ANON)){ + mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_certificates)); + mConfigState.putExtra(SERVICES_RETRIEVED, true); + downloadAnonCert(); + } else { + mProgressDialog.dismiss(); + Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_LONG).show(); + setResult(RESULT_OK); + finish(); + } + } + else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES) { + Toast.makeText(getApplicationContext(), "You have not entered a LEAP provider URL or it is unavailable", Toast.LENGTH_LONG).show(); + setResult(RESULT_CANCELED, mConfigState); + finish(); + } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE) { mProgressDialog.dismiss(); Toast.makeText(getApplicationContext(), "Your anon cert has been correctly downloaded", Toast.LENGTH_LONG).show(); -- cgit v1.2.3 From 57ac2c271561fe9f1255109733f5daae06e9234c Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sat, 8 Jun 2013 23:12:49 -0600 Subject: More changes to calls for SharedPreferences via ConfigHelper methods --- src/se/leap/leapclient/LeapHttpClient.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LeapHttpClient.java b/src/se/leap/leapclient/LeapHttpClient.java index a2ee8ad..646f80f 100644 --- a/src/se/leap/leapclient/LeapHttpClient.java +++ b/src/se/leap/leapclient/LeapHttpClient.java @@ -9,9 +9,6 @@ import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.SingleClientConnManager; -import org.json.JSONException; -import org.json.JSONObject; - import android.content.Context; public class LeapHttpClient extends DefaultHttpClient { @@ -22,16 +19,9 @@ public class LeapHttpClient extends DefaultHttpClient { public static LeapHttpClient getInstance(Context context) { if(client == null) { client = new LeapHttpClient(context); - String cert_json_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_CERT_KEY); - String cert_string; - try { - cert_string = new JSONObject(cert_json_string).getString(ConfigHelper.MAIN_CERT_KEY); - if(!cert_string.isEmpty()) { - ConfigHelper.addTrustedCertificate("recovered_certificate", cert_string); - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + String cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_CERT_KEY); + if(!cert_string.isEmpty()) { + ConfigHelper.addTrustedCertificate("recovered_certificate", cert_string); } } return client; -- cgit v1.2.3 From 5d14f128f8da5384e6834008326e435524c8fe33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 10 Jun 2013 18:18:07 +0200 Subject: NullPointer solved. ConfigHelper refactored methods returning nulls instead of empty objects broke LeapHttpClient getInstance implementation, because it checked the emptiness of the object and not if it was null. --- src/se/leap/leapclient/LeapHttpClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LeapHttpClient.java b/src/se/leap/leapclient/LeapHttpClient.java index 646f80f..3eeebe9 100644 --- a/src/se/leap/leapclient/LeapHttpClient.java +++ b/src/se/leap/leapclient/LeapHttpClient.java @@ -20,7 +20,7 @@ public class LeapHttpClient extends DefaultHttpClient { if(client == null) { client = new LeapHttpClient(context); String cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_CERT_KEY); - if(!cert_string.isEmpty()) { + if(cert_string != null) { ConfigHelper.addTrustedCertificate("recovered_certificate", cert_string); } } -- cgit v1.2.3 From 265a66e66cffacbd2c99f99bebbcec3bf100a546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 10 Jun 2013 18:43:50 +0200 Subject: OpenVPN certificate is downloaded from API_BASE, using api_uri field from provider.json. This fixes bug #2780 --- src/se/leap/leapclient/ProviderAPI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index cd19da0..a51c3a0 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -423,8 +423,8 @@ public class ProviderAPI extends IntentService { String type_of_certificate = task.getString(ConfigHelper.TYPE_OF_CERTIFICATE); try { JSONObject provider_json = ConfigHelper.getJsonFromSharedPref(ConfigHelper.PROVIDER_KEY); - URL provider_main_url = new URL(provider_json.getString(ConfigHelper.API_URL_KEY).replace("api.", "")); - String new_cert_string_url = provider_main_url.getProtocol() + "://" + provider_main_url.getHost() + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY) + "/" + ConfigHelper.CERT_KEY; + URL provider_main_url = new URL(provider_json.getString(ConfigHelper.API_URL_KEY)); + String new_cert_string_url = provider_main_url.toString() + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY) + "/" + ConfigHelper.CERT_KEY; if(type_of_certificate.equalsIgnoreCase(ConfigHelper.AUTHED_CERTIFICATE)) { HttpCookie session_id_cookie = new HttpCookie(task.getString(ConfigHelper.SESSION_ID_COOKIE_KEY), task.getString(ConfigHelper.SESSION_ID_KEY)); -- cgit v1.2.3 From 1e2470b1e940877f6fe247a65bccd2b62b621eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 10 Jun 2013 18:56:34 +0200 Subject: Removed unused methods and variables. Variables from LeapSRPSession were there because I used it while testing srp calculations, comparing that strings with the ones from javascript. Unused method from ProviderAPI was there because I foresee I'll have to implement it in the future, but I've removed it since it's already in the history. This fixes #2781. --- src/se/leap/leapclient/LeapSRPSession.java | 6 ------ src/se/leap/leapclient/ProviderAPI.java | 12 ------------ 2 files changed, 18 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 8eb28c4..0a8e735 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -173,7 +173,6 @@ public class LeapSRPSession { // Calculate x = H(s | H(U | ':' | password)) byte[] xb = calculatePasswordHash(username, password, Util.trim(salt_bytes)); this.x = new BigInteger(1, xb); - String xstr = x.toString(16); // Calculate v = kg^x mod N String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; @@ -210,7 +209,6 @@ public class LeapSRPSession { // Calculate S = (B - kg^x) ^ (a + u * x) % N BigInteger S = calculateS(Bbytes); byte[] S_bytes = Util.trim(S.toByteArray()); - String Sstr = S.toString(16); // K = SessionHash(S) String hash_algorithm = params.hashAlgorithm; @@ -219,10 +217,8 @@ public class LeapSRPSession { // clientHash = H(N) xor H(g) | H(U) | A | B | K clientHash.update(K); - String Kstr = new BigInteger(1, K).toString(16); byte[] M1 = Util.trim(clientHash.digest()); - String M1str = new BigInteger(1, M1).toString(16); // serverHash = Astr + M + K serverHash.update(Abytes); @@ -246,9 +242,7 @@ public class LeapSRPSession { BigInteger u = new BigInteger(1, u_bytes); BigInteger B_minus_v = B.subtract(v); - String vstr = v.toString(16); BigInteger a_ux = a.add(u.multiply(x)); - String xstr = x.toString(16); BigInteger S = B_minus_v.modPow(a_ux, N); return S; } diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index a51c3a0..0898ebb 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -125,18 +125,6 @@ public class ProviderAPI extends IntentService { return false; } } - - private boolean registerWithSRP(Bundle task) { - String username = (String) task.get(ConfigHelper.USERNAME_KEY); - String password = (String) task.get(ConfigHelper.PASSWORD_KEY); - String authentication_server = (String) task.get(ConfigHelper.API_URL_KEY); - - BigInteger ng_1024 = new BigInteger(ConfigHelper.NG_1024, 16); - BigInteger salt = ng_1024.probablePrime(1024, null); - byte[] salt_in_bytes = salt.toByteArray(); - - return false; - } private Bundle authenticateBySRP(Bundle task) { Bundle session_id_bundle = new Bundle(); -- cgit v1.2.3 From 6c90e0043ec68254c15562fd12a707f5e45f47e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 11 Jun 2013 19:01:36 +0200 Subject: We are not using SD storage anymore. We were using it to save certificate and provider.json files from chosen provider, so that exporting them was easily done. We don't need that files, because if we wanted to export that files we would be able to recover them easily and updated. This fixes #2783 --- src/se/leap/leapclient/ConfigHelper.java | 20 -------------------- src/se/leap/leapclient/ProviderAPI.java | 2 -- 2 files changed, 22 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index e8bc27c..11f9504 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -156,26 +156,6 @@ public class ConfigHelper { return value; } - public static void saveFile(String filename, String content) { - File root = Environment.getExternalStorageDirectory(); - File leap_dir = new File(root.getAbsolutePath() + File.separator + USER_DIRECTORY); - if (!leap_dir.isDirectory()) { - leap_dir.mkdir(); - } - try { - if (!leap_dir.isDirectory()) { - throw new IOException( - "Unable to create directory " + USER_DIRECTORY + ". Maybe the SD card is mounted?"); - } - File outputFile = new File(leap_dir, filename); - BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile)); - writer.write(content); - writer.close(); - } catch (IOException e) { - Log.w("leap_android", e.getMessage(), e); - } - } - public static FileInputStream openFileInputStream(String filename) { FileInputStream input_stream = null; File root = Environment.getExternalStorageDirectory(); diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 0898ebb..10f04c5 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -217,7 +217,6 @@ public class ProviderAPI extends IntentService { ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON)); String filename = provider_name + "_provider.json".replaceFirst("__", "_"); - ConfigHelper.saveFile(filename, provider_json.toString()); ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, filename, custom, danger_on)); result.putBoolean(ConfigHelper.RESULT_KEY, true); @@ -243,7 +242,6 @@ public class ProviderAPI extends IntentService { provider_json = getJSONFromProvider(provider_json_url, danger_on); String filename = provider_name + "_provider.json".replaceFirst("__", "_"); - ConfigHelper.saveFile(filename, provider_json.toString()); ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, filename, custom, danger_on)); return true; -- cgit v1.2.3 From 2f69eb6eb9aa3993354e8de295df68558ab7b71e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 12 Jun 2013 18:51:44 +0200 Subject: Removed some unnecessary libraries. I've also removed some unnecessary comments from LeapHttpClient. --- src/se/leap/leapclient/LeapHttpClient.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/LeapHttpClient.java b/src/se/leap/leapclient/LeapHttpClient.java index 3eeebe9..00ee15e 100644 --- a/src/se/leap/leapclient/LeapHttpClient.java +++ b/src/se/leap/leapclient/LeapHttpClient.java @@ -31,23 +31,15 @@ public class LeapHttpClient extends DefaultHttpClient { protected ClientConnectionManager createClientConnectionManager() { SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); - // Register for port 443 our SSLSocketFactory with our keystore - // to the ConnectionManager registry.register(new Scheme("https", newSslSocketFactory(), 443)); + return new SingleClientConnManager(getParams(), registry); } private SSLSocketFactory newSslSocketFactory() { try { - // Get an instance of the Bouncy Castle KeyStore format KeyStore trusted = ConfigHelper.getKeystore(); - - // Pass the keystore to the SSLSocketFactory. The factory is responsible - // for the verification of the server certificate. SSLSocketFactory sf = new SSLSocketFactory(trusted); - - // Hostname verification from certificate - // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506 sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); return sf; -- cgit v1.2.3 From 30c7bab5d8618df665e602fdd08bafa010a15497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 13 Jun 2013 17:37:37 +0200 Subject: bitmask json files are downloaded. There was a problem on the assets file "bitmask.url". It had an error in the eip-service url. We should use this file only for main url, and proceed as if it were a new provider but with a preseeded main url. --- src/se/leap/leapclient/ConfigHelper.java | 1 - src/se/leap/leapclient/ConfigurationWizard.java | 4 ++-- src/se/leap/leapclient/ProviderAPI.java | 18 ++++++++---------- src/se/leap/leapclient/ProviderListContent.java | 17 +++-------------- 4 files changed, 13 insertions(+), 27 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 11f9504..0e50c7d 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -192,7 +192,6 @@ public class ConfigHelper { public static void addTrustedCertificate(String provider, String certificate) { String filename_to_save = provider + "_certificate.cer"; - saveFile(filename_to_save, certificate); CertificateFactory cf; try { cf = CertificateFactory.getInstance("X.509"); diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 2a9b93b..1dc0093 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -80,8 +80,8 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn boolean danger_on = resultData.getBoolean(ConfigHelper.DANGER_ON); ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, danger_on); - ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getBoolean(ConfigHelper.ALLOWED_ANON)); - + ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON)); + mConfigState.setAction(PROVIDER_SET); mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_services)); diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 10f04c5..471eb6c 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -216,9 +216,7 @@ public class ProviderAPI extends IntentService { } else { ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON)); - String filename = provider_name + "_provider.json".replaceFirst("__", "_"); - - ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, filename, custom, danger_on)); + ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, provider_json, custom, danger_on)); result.putBoolean(ConfigHelper.RESULT_KEY, true); result.putString(ConfigHelper.PROVIDER_KEY, provider_json.toString()); result.putBoolean(ConfigHelper.DANGER_ON, danger_on); @@ -237,17 +235,17 @@ public class ProviderAPI extends IntentService { 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; + + JSONObject provider_json; try { provider_json = getJSONFromProvider(provider_json_url, danger_on); - - String filename = provider_name + "_provider.json".replaceFirst("__", "_"); - - ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, filename, custom, danger_on)); - return true; + ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, provider_json, custom, danger_on)); } catch (JSONException e) { - return false; + // TODO Auto-generated catch block + e.printStackTrace(); } + + return true; } private String getStringFromProviderWithoutValidate( diff --git a/src/se/leap/leapclient/ProviderListContent.java b/src/se/leap/leapclient/ProviderListContent.java index b83bbd8..10dce57 100644 --- a/src/se/leap/leapclient/ProviderListContent.java +++ b/src/se/leap/leapclient/ProviderListContent.java @@ -1,6 +1,5 @@ package se.leap.leapclient; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -78,21 +77,14 @@ public class ProviderListContent { } } - public ProviderItem(String name, String provider_json_url, String provider_json_filename, boolean custom, boolean danger_on) { + public ProviderItem(String name, String provider_json_url, JSONObject provider_json, boolean custom, boolean danger_on) { - - FileInputStream provider_json = ConfigHelper.openFileInputStream(provider_json_filename); try { - byte[] urls_file_bytes = new byte[provider_json.available()]; - provider_json.read(urls_file_bytes); - String urls_file_content = new String(urls_file_bytes); - JSONObject file_contents = new JSONObject(urls_file_content); id = name; this.name = name; this.provider_json_url = provider_json_url; - this.provider_json_filename = provider_json_filename; - eip_service_json_url = file_contents.getString("api_uri") + "/" + file_contents.getString("api_version") + "/" + ConfigHelper.EIP_SERVICE_API_PATH; - cert_json_url = (String) file_contents.get("ca_cert_uri"); + eip_service_json_url = provider_json.getString("api_uri") + "/" + provider_json.getString("api_version") + "/" + ConfigHelper.EIP_SERVICE_API_PATH; + cert_json_url = (String) provider_json.get("ca_cert_uri"); this.custom = custom; this.danger_on = danger_on; if(custom) @@ -100,9 +92,6 @@ public class ProviderListContent { } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); } } -- cgit v1.2.3 From bffd21a326bcb86d814dd3fe2caf5295ea705f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 13 Jun 2013 21:12:24 +0200 Subject: Bypasses self signed certificates. It's working against cdev.bitmask.net and bitmask.net. Look at #2840 for further explanation about self signed certificates. I've also removed some file dependant configuration (when a provider was custom, ConfigurationWizard still tried to read from file a provider.json that now I store in memory via ProviderItem class). --- src/se/leap/leapclient/ConfigurationWizard.java | 3 +- src/se/leap/leapclient/ProviderAPI.java | 126 +++++++++++++++++------- src/se/leap/leapclient/ProviderListContent.java | 2 + 3 files changed, 94 insertions(+), 37 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 1dc0093..6f26adc 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -188,8 +188,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn // FIXME!! We should we be updating our seeded providers list at ConfigurationWizard onStart() ? // I think yes, but if so, where does this list live? leap.se, as it's the non-profit project for the software? // If not, we should just be getting names/urls, and fetching the provider.json like in custom entries - provider_contents = new Scanner(ConfigHelper.openFileInputStream(current_provider_item.provider_json_filename)).useDelimiter("\\A").next(); - provider_json = new JSONObject(provider_contents); + provider_json = current_provider_item.provider_json; ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON)); ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, current_provider_item.danger_on); diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 471eb6c..f98e436 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -26,6 +26,8 @@ import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -247,34 +249,6 @@ public class ProviderAPI extends IntentService { return true; } - - private String getStringFromProviderWithoutValidate( - URL provider_json_url) { - - String json_string = ""; - HostnameVerifier hostnameVerifier = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; - - // Tell the URLConnection to use our HostnameVerifier - try { - HttpsURLConnection urlConnection = - (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 - json_string = getStringFromProviderWithCACertAdded(provider_json_url); - //e.printStackTrace(); - } - return json_string; - } private String getStringFromProvider(String string_url, boolean danger_on) { @@ -307,25 +281,56 @@ public class ProviderAPI extends IntentService { return json_file_content; } + private String getStringFromProviderWithoutValidate( + URL provider_json_url) { + + String json_string = ""; + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + + try { + HttpsURLConnection urlConnection = + (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) { + json_string = getStringFromProviderWithCACertAdded(provider_json_url); + //e.printStackTrace(); + } + + return json_string; + } + private String getStringFromProviderWithCACertAdded(URL url) { String json_file_content = ""; - + // Load CAs from an InputStream // (could be from a resource or ByteArrayInputStream or ...) + String cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_CERT_KEY); + if(cert_string.isEmpty()) { + cert_string = downloadCertificateWithoutTrusting(url.getProtocol() + "://" + url.getHost() + "/" + "ca.crt"); + ConfigHelper.saveSharedPref(ConfigHelper.MAIN_CERT_KEY, cert_string); + } CertificateFactory cf; try { cf = CertificateFactory.getInstance("X.509"); - String cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_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()); + ca = cf.generateCertificate(caInput); + System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN()); } finally { - caInput.close(); + caInput.close(); } // Create a KeyStore containing our trusted CAs @@ -345,7 +350,7 @@ public class ProviderAPI extends IntentService { // Tell the URLConnection to use a SocketFactory from our SSLContext HttpsURLConnection urlConnection = - (HttpsURLConnection)url.openConnection(); + (HttpsURLConnection)url.openConnection(); urlConnection.setSSLSocketFactory(context.getSocketFactory()); json_file_content = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); } catch (CertificateException e) { @@ -364,10 +369,61 @@ public class ProviderAPI extends IntentService { // TODO Auto-generated catch block e.printStackTrace(); } - return json_file_content; } + private String downloadCertificateWithoutTrusting(String certificate_url_string) { + + String cert_string = ""; + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + + TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) { + } + public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) { + } + } + }; + + try { + URL certificate_url = new URL(certificate_url_string); + HttpsURLConnection urlConnection = + (HttpsURLConnection)certificate_url.openConnection(); + urlConnection.setHostnameVerifier(hostnameVerifier); + + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, trustAllCerts, new java.security.SecureRandom()); + + urlConnection.setSSLSocketFactory(sc.getSocketFactory()); + + cert_string = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); + + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // This should never happen + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (KeyManagementException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return cert_string; + } + 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 10dce57..4cf0a5f 100644 --- a/src/se/leap/leapclient/ProviderListContent.java +++ b/src/se/leap/leapclient/ProviderListContent.java @@ -40,6 +40,7 @@ public class ProviderListContent { public String id; public String name; public String provider_json_url; + public JSONObject provider_json; public String provider_json_filename; public String eip_service_json_url; public String cert_json_url; @@ -83,6 +84,7 @@ public class ProviderListContent { id = name; this.name = name; this.provider_json_url = provider_json_url; + this.provider_json = provider_json; eip_service_json_url = provider_json.getString("api_uri") + "/" + provider_json.getString("api_version") + "/" + ConfigHelper.EIP_SERVICE_API_PATH; cert_json_url = (String) provider_json.get("ca_cert_uri"); this.custom = custom; -- cgit v1.2.3 From d475ae617d8dc0994a1294be7c8cca338a68fd9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 19 Jun 2013 19:05:12 +0200 Subject: First round of comments. This resolves the first step from issue #2908. Next step: Put user message strings into an appropiate place. --- src/se/leap/leapclient/ConfigHelper.java | 59 +++++++++- src/se/leap/leapclient/ConfigurationWizard.java | 63 ++++++++--- src/se/leap/leapclient/Dashboard.java | 11 ++ src/se/leap/leapclient/LeapHttpClient.java | 17 +++ src/se/leap/leapclient/LeapSRPSession.java | 19 +++- src/se/leap/leapclient/LogInDialog.java | 31 +++++- src/se/leap/leapclient/NewProviderDialog.java | 15 +++ src/se/leap/leapclient/ProviderAPI.java | 121 ++++++++++++++++++++- .../leap/leapclient/ProviderAPIResultReceiver.java | 12 +- src/se/leap/leapclient/ProviderListContent.java | 44 ++++---- 10 files changed, 344 insertions(+), 48 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 0e50c7d..5838f52 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -1,10 +1,8 @@ package se.leap.leapclient; -import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileWriter; import java.io.IOException; import java.math.BigInteger; import java.io.InputStream; @@ -21,8 +19,14 @@ import org.json.JSONObject; import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; -import android.util.Log; +/** + * Stores constants, and implements auxiliary methods used across all LEAP Android classes. + * + * @author parmegv + * @author MeanderingCode + * + */ public class ConfigHelper { public static SharedPreferences shared_preferences; @@ -100,6 +104,11 @@ public class ConfigHelper { return true; } + /** + * Saves a JSON object into class scope Shared Preferences + * @param shared_preferences_key + * @param content + */ public static void saveSharedPref(String shared_preferences_key, JSONObject content) { SharedPreferences.Editor shared_preferences_editor = shared_preferences @@ -109,6 +118,11 @@ public class ConfigHelper { shared_preferences_editor.commit(); } + /** + * Saves a String object into class scope Shared Preferences + * @param shared_preferences_key + * @param content + */ public static void saveSharedPref(String shared_preferences_key, String content) { SharedPreferences.Editor shared_preferences_editor = shared_preferences @@ -117,7 +131,12 @@ public class ConfigHelper { content); shared_preferences_editor.commit(); } - + + /** + * Saves a boolean object into class scope Shared Preferences + * @param shared_preferences_key + * @param content + */ public static void saveSharedPref(String shared_preferences_key, boolean content) { SharedPreferences.Editor shared_preferences_editor = shared_preferences @@ -126,6 +145,11 @@ public class ConfigHelper { shared_preferences_editor.commit(); } + /** + * Gets String object from class scope Shared Preferences + * @param shared_preferences_key + * @return the string correspondent to the key parameter + */ public static String getStringFromSharedPref(String shared_preferences_key) { String content = null; if ( checkSharedPrefs() ) { @@ -134,6 +158,11 @@ public class ConfigHelper { return content; } + /** + * Gets JSON object from class scope Shared Preferences + * @param shared_preferences_key + * @return the JSON object correspondent to the key parameter + */ public static JSONObject getJsonFromSharedPref(String shared_preferences_key) throws JSONException { JSONObject content = null; if ( checkSharedPrefs() ) { @@ -156,6 +185,11 @@ public class ConfigHelper { return value; } + /** + * Opens a FileInputStream from the user directory of the external storage directory. + * @param filename + * @return a file input stream + */ public static FileInputStream openFileInputStream(String filename) { FileInputStream input_stream = null; File root = Environment.getExternalStorageDirectory(); @@ -169,11 +203,20 @@ public class ConfigHelper { return input_stream; } + /** + * Sets class scope Shared Preferences + * @param shared_preferences + */ public static void setSharedPreferences( SharedPreferences shared_preferences) { ConfigHelper.shared_preferences = shared_preferences; } + /** + * Adds a new X509 certificate given its input stream and its provider name + * @param provider used to store the certificate in the keystore + * @param inputStream from which X509 certificate must be generated. + */ public static void addTrustedCertificate(String provider, InputStream inputStream) { CertificateFactory cf; try { @@ -190,6 +233,11 @@ public class ConfigHelper { } } + /** + * Adds a new X509 certificate given in its string from and using its provider name + * @param provider used to store the certificate in the keystore + * @param certificate + */ public static void addTrustedCertificate(String provider, String certificate) { String filename_to_save = provider + "_certificate.cer"; CertificateFactory cf; @@ -217,6 +265,9 @@ public class ConfigHelper { } } + /** + * @return class wide keystore + */ public static KeyStore getKeystore() { return keystore_trusted; } diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 6f26adc..91b92d6 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -2,7 +2,6 @@ package se.leap.leapclient; import java.io.IOException; import java.util.Iterator; -import java.util.Scanner; import org.json.JSONException; import org.json.JSONObject; @@ -23,6 +22,14 @@ import android.os.Handler; import android.view.View; import android.widget.Toast; +/** + * Activity that builds and shows the list of known available providers. + * + * It also allows the user to enter custom providers with a button. + * + * @author parmegv + * + */ public class ConfigurationWizard extends Activity implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogInterface, Receiver { @@ -154,6 +161,10 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn } } + /** + * Loads providers data from url file contained in the project + * @return true if the file was read correctly + */ private boolean loadPreseededProviders() { boolean loaded_preseeded_providers = false; AssetManager asset_manager = getAssets(); @@ -178,20 +189,26 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn return loaded_preseeded_providers; } - private void saveProviderJson(ProviderItem current_provider_item) { + /** + * Saves provider.json file associated with provider. + * + * If the provider is custom, the file has already been downloaded so we load it from memory. + * If not, the file is updated using the provider's URL. + * @param provider + */ + private void saveProviderJson(ProviderItem provider) { JSONObject provider_json = new JSONObject(); try { - String provider_contents = ""; - if(!current_provider_item.custom) { - updateProviderDotJson(current_provider_item.name, current_provider_item.provider_json_url, current_provider_item.danger_on); + if(!provider.custom) { + updateProviderDotJson(provider.name, provider.provider_json_url, provider.danger_on); } else { // FIXME!! We should we be updating our seeded providers list at ConfigurationWizard onStart() ? // I think yes, but if so, where does this list live? leap.se, as it's the non-profit project for the software? // If not, we should just be getting names/urls, and fetching the provider.json like in custom entries - provider_json = current_provider_item.provider_json; + provider_json = provider.provider_json; ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON)); - ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, current_provider_item.danger_on); + ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, provider.danger_on); mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_services)); downloadJSONFiles(mSelectedProvider); @@ -202,15 +219,21 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn } } - private void downloadJSONFiles(ProviderItem current_provider_item) { + /** + * Asks ProviderAPI to download provider site's certificate and eip-service.json + * + * URLs are fetched from the provider parameter + * @param provider from which certificate and eip-service.json files are going to be downloaded + */ + private void downloadJSONFiles(ProviderItem provider) { Intent provider_API_command = new Intent(this, ProviderAPI.class); Bundle method_and_parameters = new Bundle(); - method_and_parameters.putString(ConfigHelper.PROVIDER_KEY, current_provider_item.name); - method_and_parameters.putString(ConfigHelper.MAIN_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); + method_and_parameters.putString(ConfigHelper.PROVIDER_KEY, provider.name); + method_and_parameters.putString(ConfigHelper.MAIN_CERT_KEY, provider.cert_json_url); + method_and_parameters.putString(ConfigHelper.EIP_SERVICE_KEY, provider.eip_service_json_url); + method_and_parameters.putBoolean(ConfigHelper.DANGER_ON, provider.danger_on); provider_API_command.putExtra(ConfigHelper.DOWNLOAD_JSON_FILES_BUNDLE_EXTRA, method_and_parameters); provider_API_command.putExtra("receiver", providerAPI_result_receiver); @@ -218,7 +241,10 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn startService(provider_API_command); } - private boolean downloadAnonCert() { + /** + * Asks ProviderAPI to download an anonymous (anon) VPN certificate. + */ + private void downloadAnonCert() { Intent provider_API_command = new Intent(this, ProviderAPI.class); Bundle method_and_parameters = new Bundle(); @@ -229,9 +255,12 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn provider_API_command.putExtra("receiver", providerAPI_result_receiver); startService(provider_API_command); - return true; } + /** + * Open the new provider dialog + * @param view from which the dialog is showed + */ public void addNewProvider(View view) { FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.NEW_PROVIDER_DIALOG); @@ -258,6 +287,12 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn startService(provider_API_command); } + /** + * Asks ProviderAPI to download a new provider.json file + * @param provider_name + * @param provider_json_url + * @param danger_on tells if HTTPS client should bypass certificate errors + */ public void updateProviderDotJson(String provider_name, String provider_json_url, boolean danger_on) { Intent provider_API_command = new Intent(this, ProviderAPI.class); diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index c1f4697..e8ea270 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -229,6 +229,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startService(provider_API_command); } + /** + * Asks ProviderAPI to log out. + */ public void logOut() { providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); providerAPI_result_receiver.setReceiver(this); @@ -251,6 +254,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startService(provider_API_command); } + /** + * Shows the log in dialog. + * @param view from which the dialog is created. + */ public void logInDialog(View view) { FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); Fragment previous_log_in_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.LOG_IN_DIALOG); @@ -263,6 +270,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf newFragment.show(fragment_transaction, ConfigHelper.LOG_IN_DIALOG); } + /** + * Asks ProviderAPI to download an authenticated OpenVPN certificate. + * @param session_id cookie for the server to allow us to download the certificate. + */ private void downloadAuthedUserCertificate(Cookie session_id) { providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); providerAPI_result_receiver.setReceiver(this); diff --git a/src/se/leap/leapclient/LeapHttpClient.java b/src/se/leap/leapclient/LeapHttpClient.java index 00ee15e..42f9a52 100644 --- a/src/se/leap/leapclient/LeapHttpClient.java +++ b/src/se/leap/leapclient/LeapHttpClient.java @@ -11,11 +11,22 @@ import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.SingleClientConnManager; import android.content.Context; +/** + * Implements an HTTP client, enabling LEAP Android app to manage its own runtime keystore or bypass default Android security measures. + * + * @author rafa + * + */ public class LeapHttpClient extends DefaultHttpClient { final Context context; private static LeapHttpClient client; + /** + * If the class scope client is null, it creates one and imports, if existing, the main certificate from Shared Preferences. + * @param context + * @return the new client. + */ public static LeapHttpClient getInstance(Context context) { if(client == null) { client = new LeapHttpClient(context); @@ -36,6 +47,12 @@ public class LeapHttpClient extends DefaultHttpClient { return new SingleClientConnManager(getParams(), registry); } + /** + * Uses keystore from ConfigHelper for the SSLSocketFactory. + * + * Sets hostname verifier to allow all hostname verifier. + * @return + */ private SSLSocketFactory newSslSocketFactory() { try { KeyStore trusted = ConfigHelper.getKeystore(); diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 0a8e735..beb286d 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -9,6 +9,14 @@ import java.util.Arrays; import org.jboss.security.Util; import org.jboss.security.srp.SRPParameters; +/** + * Implements all SRP algorithm logic. + * + * It's derived from JBoss implementation, with adjustments to make it work with LEAP platform. + * + * @author parmegv + * + */ public class LeapSRPSession { private SRPParameters params; @@ -133,7 +141,14 @@ public class LeapSRPSession { return v; } - public byte[] xor(byte[] b1, byte[] b2, int length) + /** + * Calculates the trimmed xor from two BigInteger numbers + * @param b1 the positive source to build first BigInteger + * @param b2 the positive source to build second BigInteger + * @param length + * @return + */ + public byte[] xor(byte[] b1, byte[] b2) { //TODO Check if length matters in the order, when b2 is smaller than b1 or viceversa byte[] xor_digest = new BigInteger(1, b1).xor(new BigInteger(1, b2)).toByteArray(); @@ -185,7 +200,7 @@ public class LeapSRPSession { byte[] digest_of_g = newDigest().digest(params.g); // clientHash = H(N) xor H(g) - byte[] xor_digest = xor(digest_of_n, digest_of_g, digest_of_g.length); + byte[] xor_digest = xor(digest_of_n, digest_of_g); clientHash.update(xor_digest); // clientHash = H(N) xor H(g) | H(U) diff --git a/src/se/leap/leapclient/LogInDialog.java b/src/se/leap/leapclient/LogInDialog.java index c20413d..00429d1 100644 --- a/src/se/leap/leapclient/LogInDialog.java +++ b/src/se/leap/leapclient/LogInDialog.java @@ -11,6 +11,16 @@ import android.view.View; import android.widget.EditText; import android.widget.Toast; +/** + * Implements the log in dialog, currently without progress dialog. + * + * It returns to the previous fragment when finished, and sends username and password to the authenticate method. + * + * It also notifies the user if the password is not valid. + * + * @author parmegv + * + */ public class LogInDialog extends DialogFragment { public AlertDialog onCreateDialog(Bundle savedInstanceState) { @@ -43,16 +53,35 @@ public class LogInDialog extends DialogFragment { return builder.create(); } - boolean wellFormedPassword(String entered_password) { + /** + * Validates a password + * @param entered_password + * @return true if the entered password length is greater or equal to eight (8). + */ + private boolean wellFormedPassword(String entered_password) { return entered_password.length() >= 8; } + /** + * Interface used to communicate LogInDialog with Dashboard. + * + * @author parmegv + * + */ public interface LogInDialogInterface { + /** + * Starts authentication process. + * @param username + * @param password + */ public void authenticate(String username, String password); } LogInDialogInterface interface_with_Dashboard; + /** + * @return a new instance of this DialogFragment. + */ public static DialogFragment newInstance() { LogInDialog dialog_fragment = new LogInDialog(); return dialog_fragment; diff --git a/src/se/leap/leapclient/NewProviderDialog.java b/src/se/leap/leapclient/NewProviderDialog.java index 60ac8d2..5b84ec0 100644 --- a/src/se/leap/leapclient/NewProviderDialog.java +++ b/src/se/leap/leapclient/NewProviderDialog.java @@ -13,6 +13,12 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; +/** + * Implements the new custom provider dialog. + * + * @author parmegv + * + */ public class NewProviderDialog extends DialogFragment { public interface NewProviderDialogInterface { @@ -21,6 +27,9 @@ public class NewProviderDialog extends DialogFragment { NewProviderDialogInterface interface_with_ConfigurationWizard; + /** + * @return a new instance of this DialogFragment. + */ public static DialogFragment newInstance() { NewProviderDialog dialog_fragment = new NewProviderDialog(); return dialog_fragment; @@ -37,6 +46,7 @@ public class NewProviderDialog extends DialogFragment { } } + @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); LayoutInflater inflater = getActivity().getLayoutInflater(); @@ -71,6 +81,11 @@ public class NewProviderDialog extends DialogFragment { return builder.create(); } + /** + * Checks if the entered url is valid or not. + * @param entered_url + * @return true if it's not empty nor contains only the protocol. + */ boolean validURL(String entered_url) { return !entered_url.isEmpty() && entered_url.matches("http[s]?://.+") && !entered_url.replaceFirst("http[s]?://", "").isEmpty(); } diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index f98e436..f8d730e 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -55,6 +55,15 @@ import android.os.ResultReceiver; import android.util.Base64; import android.util.Log; +/** + * Implements HTTP api methods used to manage communications with the provider server. + * + * It's an IntentService because it downloads data fromt he Internet, so it operates in the background. + * + * @author parmegv + * @author MeanderingCode + * + */ public class ProviderAPI extends IntentService { public ProviderAPI() { @@ -113,6 +122,11 @@ public class ProviderAPI extends IntentService { } } + /** + * Downloads the main cert and the eip-service.json files given through the task parameter + * @param task + * @return true if eip-service.json was parsed as a JSON object correctly. + */ private boolean downloadJsonFiles(Bundle task) { String cert_url = task.getString(ConfigHelper.MAIN_CERT_KEY); String eip_service_json_url = task.getString(ConfigHelper.EIP_SERVICE_KEY); @@ -128,6 +142,12 @@ public class ProviderAPI extends IntentService { } } + /** + * 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 ConfigHelper.RESULT_KEY, and which is true if authentication was successful. + */ private Bundle authenticateBySRP(Bundle task) { Bundle session_id_bundle = new Bundle(); @@ -168,11 +188,31 @@ public class ProviderAPI extends IntentService { return session_id_bundle; } + /** + * Sends an HTTP POST request to the authentication server with the SRP Parameter A. + * @param server_url + * @param username + * @param clientA First SRP parameter sent + * @return response from authentication server + * @throws ClientProtocolException + * @throws IOException + * @throws JSONException + */ private JSONObject sendAToSRPServer(String server_url, String username, String clientA) throws ClientProtocolException, IOException, JSONException { HttpPost post = new HttpPost(server_url + "/sessions.json" + "?" + "login=" + username + "&&" + "A=" + clientA); return sendToServer(post); } + /** + * Sends an HTTP PUT request to the authentication server with the SRP Parameter M1 (or simply M). + * @param server_url + * @param username + * @param m1 Second SRP parameter sent + * @return response from authentication server + * @throws ClientProtocolException + * @throws IOException + * @throws JSONException + */ private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) throws ClientProtocolException, IOException, JSONException { HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + "client_auth" + "=" + new BigInteger(1, Util.trim(m1)).toString(16)); JSONObject json_response = sendToServer(put); @@ -188,6 +228,14 @@ public class ProviderAPI extends IntentService { return session_idAndM2; } + /** + * Executes an HTTP request expecting a JSON response. + * @param request + * @return response from authentication server + * @throws ClientProtocolException + * @throws IOException + * @throws JSONException + */ private JSONObject sendToServer(HttpUriRequest request) throws ClientProtocolException, IOException, JSONException { DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); HttpContext localContext = new BasicHttpContext(); @@ -204,6 +252,11 @@ public class ProviderAPI extends IntentService { return json_response; } + /** + * 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 ConfigHelper.RESULT_KEY, and which is true if the update was successful. + */ private Bundle updateProviderDotJSON(Bundle task) { Bundle result = new Bundle(); boolean custom = task.getBoolean(ConfigHelper.CUSTOM); @@ -230,13 +283,18 @@ public class ProviderAPI extends IntentService { return result; } + /** + * Downloads a custom provider provider.json file + * @param task containing a boolean meaning if the user completely trusts this provider, and the provider main url entered in the new custom provider dialog. + * @return true if provider.json file was successfully parsed as a JSON object. + */ private boolean downloadNewProviderDotJSON(Bundle task) { boolean custom = true; 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); + String provider_json_url = guessProviderDotJsonURL(provider_main_url); JSONObject provider_json; try { @@ -245,11 +303,20 @@ public class ProviderAPI extends IntentService { } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); + return false; } return true; } + /** + * Tries to download whatever is pointed by the string_url. + * + * If danger_on flag is true, SSL exceptions will be managed by futher methods that will try to use some bypass methods. + * @param string_url + * @param danger_on if the user completely trusts this provider + * @return + */ private String getStringFromProvider(String string_url, boolean danger_on) { String json_file_content = ""; @@ -281,8 +348,15 @@ public class ProviderAPI extends IntentService { return json_file_content; } + /** + * Tries to download a string from given url without verifying the hostname. + * + * If a IOException still occurs, it tries with another bypass method: getStringFromProviderWithCACertAdded. + * @param string_url + * @return an empty string if everything fails, the url content if not. + */ private String getStringFromProviderWithoutValidate( - URL provider_json_url) { + URL string_url) { String json_string = ""; HostnameVerifier hostnameVerifier = new HostnameVerifier() { @@ -294,20 +368,25 @@ public class ProviderAPI extends IntentService { try { HttpsURLConnection urlConnection = - (HttpsURLConnection)provider_json_url.openConnection(); + (HttpsURLConnection)string_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) { - json_string = getStringFromProviderWithCACertAdded(provider_json_url); + json_string = getStringFromProviderWithCACertAdded(string_url); //e.printStackTrace(); } return json_string; } + /** + * Tries to download the contents of the provided url using main certificate from choosen provider. + * @param url + * @return an empty string if it fails, the url content if not. + */ private String getStringFromProviderWithCACertAdded(URL url) { String json_file_content = ""; @@ -372,6 +451,11 @@ public class ProviderAPI extends IntentService { return json_file_content; } + /** + * Downloads the certificate from the parameter url bypassing self signed certificate SSL errors. + * @param certificate_url_string + * @return the certificate, as a string + */ private String downloadCertificateWithoutTrusting(String certificate_url_string) { String cert_string = ""; @@ -424,15 +508,34 @@ public class ProviderAPI extends IntentService { return cert_string; } + /** + * Downloads a JSON object from the given url. + * + * It first downloads the JSON object as a String, and then parses it to JSON object. + * @param json_url + * @param danger_on if the user completely trusts the certificate of the url address. + * @return + * @throws JSONException + */ 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); } - private String guessURL(String provider_main_url) { + /** + * Tries to guess the provider.json url given the main provider url. + * @param provider_main_url + * @return the guessed provider.json url + */ + private String guessProviderDotJsonURL(String provider_main_url) { return provider_main_url + "/provider.json"; } + /** + * Logs out from the api url retrieved from the task. + * @param task containing api url from which the user will log out + * @return true if there were no exceptions + */ private boolean logOut(Bundle task) { DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); int session_id_index = 0; @@ -459,6 +562,12 @@ public class ProviderAPI extends IntentService { return true; } + /** + * Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate. + * + * @param task containing the type of the certificate to be downloaded + * @return true if certificate was downloaded correctly, false if provider.json or danger_on flag are not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error. + */ private boolean getNewCert(Bundle task) { String type_of_certificate = task.getString(ConfigHelper.TYPE_OF_CERTIFICATE); try { @@ -493,7 +602,7 @@ public class ProviderAPI extends IntentService { } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); + return false; } - return true; } } diff --git a/src/se/leap/leapclient/ProviderAPIResultReceiver.java b/src/se/leap/leapclient/ProviderAPIResultReceiver.java index a6a8d9d..e32f6ff 100644 --- a/src/se/leap/leapclient/ProviderAPIResultReceiver.java +++ b/src/se/leap/leapclient/ProviderAPIResultReceiver.java @@ -4,6 +4,11 @@ import android.os.Bundle; import android.os.Handler; import android.os.ResultReceiver; +/** + * Implements the ResultReceiver needed by Activities using ProviderAPI to receive the results of its operations. + * @author parmegv + * + */ public class ProviderAPIResultReceiver extends ResultReceiver { private Receiver mReceiver; @@ -11,11 +16,16 @@ public class ProviderAPIResultReceiver extends ResultReceiver { super(handler); // TODO Auto-generated constructor stub } - + public void setReceiver(Receiver receiver) { mReceiver = receiver; } + /** + * Interface to enable ProviderAPIResultReceiver to receive results from the ProviderAPI IntentService. + * @author parmegv + * + */ public interface Receiver { public void onReceiveResult(int resultCode, Bundle resultData); } diff --git a/src/se/leap/leapclient/ProviderListContent.java b/src/se/leap/leapclient/ProviderListContent.java index 4cf0a5f..4ae4609 100644 --- a/src/se/leap/leapclient/ProviderListContent.java +++ b/src/se/leap/leapclient/ProviderListContent.java @@ -10,30 +10,29 @@ import java.util.Map; import org.json.JSONException; import org.json.JSONObject; - +/** + * Models the provider list shown in the ConfigurationWizard. + * + * @author parmegv + * + */ public class ProviderListContent { - /** - * An array of sample (dummy) items. - */ public static List ITEMS = new ArrayList(); - /** - * A map of sample (dummy) items, by ID. - */ public static Map ITEM_MAP = new HashMap(); - - static { - //addItem(new ProviderItem("1", "bitmask", "https://bitmask.net/provider.json", "https://api.bitmask.net:4430/1/config/eip-service.json")); - } + /** + * Adds a new provider item to the end of the items map, and to the items list. + * @param item + */ public static void addItem(ProviderItem item) { ITEMS.add(item); ITEM_MAP.put(String.valueOf(ITEMS.size()), item); } /** - * A dummy item representing a piece of content. + * A provider item. */ public static class ProviderItem { public boolean custom = false; @@ -45,15 +44,13 @@ public class ProviderListContent { 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; - this.name = name; - this.provider_json_url = provider_json_url; - this.eip_service_json_url = eip_service_json_url; - this.cert_json_url = cert_json_url; - } + /** + * @param name of the provider + * @param urls_file_input_stream file input stream linking with the assets url file + * @param custom if it's a new provider entered by the user or not + * @param danger_on if the user trusts completely the new provider + */ public ProviderItem(String name, InputStream urls_file_input_stream, boolean custom, boolean danger_on) { try { @@ -78,6 +75,13 @@ public class ProviderListContent { } } + /** + * @param name of the provider + * @param provider_json_url used to download provider.json file of the provider + * @param provider_json already downloaded + * @param custom if it's a new provider entered by the user or not + * @param danger_on if the user trusts completely the new provider + */ public ProviderItem(String name, String provider_json_url, JSONObject provider_json, boolean custom, boolean danger_on) { try { -- cgit v1.2.3 From f4956bb818fb9ed04760e6de3b53b876272da5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 20 Jun 2013 16:52:43 +0200 Subject: User messages are now in string.xml Some more constants added to ConfigHelper. This solves #2908. --- src/se/leap/leapclient/ConfigHelper.java | 6 +++++- src/se/leap/leapclient/ConfigurationWizard.java | 16 ++++++++-------- src/se/leap/leapclient/Dashboard.java | 18 +++++++++--------- src/se/leap/leapclient/LogInDialog.java | 2 +- src/se/leap/leapclient/NewProviderDialog.java | 4 ++-- src/se/leap/leapclient/ProviderAPI.java | 6 +++--- src/se/leap/leapclient/ProviderListContent.java | 6 +++--- 7 files changed, 31 insertions(+), 27 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 5838f52..cb4a550 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -40,11 +40,14 @@ public class ConfigHelper { NEW_PROVIDER_DIALOG = "logInDialog", SRP_REGISTER = "srpRegister", SRP_AUTH = "srpAuth", + M1_KEY = "M1", + M2_KEY = "M2", LOG_IN = "logIn", LOG_OUT = "logOut", DOWNLOAD_CERTIFICATE = "downloadUserAuthedCertificate", API_VERSION_KEY = "api_version", RESULT_KEY = "result", + RECEIVER_KEY = "receiver", PROVIDER_KEY = "provider", SERVICE_KEY = "service", ALLOWED_ANON = "allow_anonymous", @@ -68,7 +71,8 @@ public class ConfigHelper { USERNAME_KEY = "username", PASSWORD_KEY = "password", ALLOW_REGISTRATION_KEY = "allow_registration", - EIP_SERVICE_API_PATH = "config/eip-service.json" + EIP_SERVICE_API_PATH = "config/eip-service.json", + ERRORS_KEY = "errors" ; final public static String NG_1024 = diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 91b92d6..ce27942 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -105,7 +105,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn } else if(resultCode == ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON) { mProgressDialog.dismiss(); - Toast.makeText(getApplicationContext(), "Install a new version of this app.", Toast.LENGTH_LONG).show(); + Toast.makeText(getApplicationContext(), R.string.incorrectly_updated_provider_dot_json_message, Toast.LENGTH_LONG).show(); setResult(RESULT_CANCELED, mConfigState); finish(); } @@ -122,20 +122,20 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn } } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES) { - Toast.makeText(getApplicationContext(), "You have not entered a LEAP provider URL or it is unavailable", Toast.LENGTH_LONG).show(); + Toast.makeText(getApplicationContext(), R.string.incorrectly_downloaded_json_files_message, Toast.LENGTH_LONG).show(); setResult(RESULT_CANCELED, mConfigState); finish(); } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE) { mProgressDialog.dismiss(); - Toast.makeText(getApplicationContext(), "Your anon cert has been correctly downloaded", Toast.LENGTH_LONG).show(); + Toast.makeText(getApplicationContext(), R.string.correctly_downloaded_json_files_message, Toast.LENGTH_LONG).show(); Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_LONG).show(); //mConfigState.putExtra(CERTIFICATE_RETRIEVED, true); // If this isn't the last step and finish() is moved... setResult(RESULT_OK); finish(); } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_CERTIFICATE) { mProgressDialog.dismiss(); - Toast.makeText(getApplicationContext(), "Your anon cert was not downloaded", Toast.LENGTH_LONG).show(); + Toast.makeText(getApplicationContext(), R.string.incorrectly_downloaded_certificate_message, Toast.LENGTH_LONG).show(); setResult(RESULT_CANCELED, mConfigState); finish(); } @@ -236,7 +236,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn method_and_parameters.putBoolean(ConfigHelper.DANGER_ON, provider.danger_on); provider_API_command.putExtra(ConfigHelper.DOWNLOAD_JSON_FILES_BUNDLE_EXTRA, method_and_parameters); - provider_API_command.putExtra("receiver", providerAPI_result_receiver); + provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver); startService(provider_API_command); } @@ -252,7 +252,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn method_and_parameters.putString(ConfigHelper.TYPE_OF_CERTIFICATE, ConfigHelper.ANON_CERTIFICATE); provider_API_command.putExtra(ConfigHelper.DOWNLOAD_CERTIFICATE, method_and_parameters); - provider_API_command.putExtra("receiver", providerAPI_result_receiver); + provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver); startService(provider_API_command); } @@ -282,7 +282,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn method_and_parameters.putBoolean(ConfigHelper.DANGER_ON, danger_on); provider_API_command.putExtra(ConfigHelper.DOWNLOAD_NEW_PROVIDER_DOTJSON, method_and_parameters); - provider_API_command.putExtra("receiver", providerAPI_result_receiver); + provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver); startService(provider_API_command); } @@ -302,7 +302,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn method_and_parameters.putBoolean(ConfigHelper.DANGER_ON, danger_on); provider_API_command.putExtra(ConfigHelper.UPDATE_PROVIDER_DOTJSON, method_and_parameters); - provider_API_command.putExtra("receiver", providerAPI_result_receiver); + provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver); startService(provider_API_command); } diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index e8ea270..dd8ee33 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -224,7 +224,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } provider_API_command.putExtra(ConfigHelper.SRP_AUTH, method_and_parameters); - provider_API_command.putExtra("receiver", providerAPI_result_receiver); + provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver); startService(provider_API_command); } @@ -249,7 +249,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } provider_API_command.putExtra(ConfigHelper.LOG_OUT, method_and_parameters); - provider_API_command.putExtra("receiver", providerAPI_result_receiver); + provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver); startService(provider_API_command); } @@ -286,7 +286,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf method_and_parameters.putString(ConfigHelper.SESSION_ID_KEY, session_id.getValue()); provider_API_command.putExtra(ConfigHelper.DOWNLOAD_CERTIFICATE, method_and_parameters); - provider_API_command.putExtra("receiver", providerAPI_result_receiver); + provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver); startService(provider_API_command); } @@ -297,25 +297,25 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf String session_id_cookie_key = resultData.getString(ConfigHelper.SESSION_ID_COOKIE_KEY); String session_id_string = resultData.getString(ConfigHelper.SESSION_ID_KEY); setResult(RESULT_OK); - Toast.makeText(getApplicationContext(), "Authentication succeeded", Toast.LENGTH_LONG).show(); + Toast.makeText(getApplicationContext(), R.string.succesful_authentication_message, Toast.LENGTH_LONG).show(); Cookie session_id = new BasicClientCookie(session_id_cookie_key, session_id_string); downloadAuthedUserCertificate(session_id); } else if(resultCode == ConfigHelper.SRP_AUTHENTICATION_FAILED) { setResult(RESULT_CANCELED); - Toast.makeText(getApplicationContext(), "Authentication failed", Toast.LENGTH_LONG).show(); + Toast.makeText(getApplicationContext(), R.string.authentication_failed_message, Toast.LENGTH_LONG).show(); } else if(resultCode == ConfigHelper.LOGOUT_SUCCESSFUL) { setResult(RESULT_OK); - Toast.makeText(getApplicationContext(), "Logged out", Toast.LENGTH_LONG).show(); + Toast.makeText(getApplicationContext(), R.string.successful_log_out_message, Toast.LENGTH_LONG).show(); } else if(resultCode == ConfigHelper.LOGOUT_FAILED) { setResult(RESULT_CANCELED); - Toast.makeText(getApplicationContext(), "Didn't logged out", Toast.LENGTH_LONG).show(); + Toast.makeText(getApplicationContext(), R.string.log_out_failed_message, Toast.LENGTH_LONG).show(); } else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE) { setResult(RESULT_CANCELED); - Toast.makeText(getApplicationContext(), "Your own cert has been correctly downloaded", Toast.LENGTH_LONG).show(); + Toast.makeText(getApplicationContext(), R.string.successful_authed_cert_downloaded_message, Toast.LENGTH_LONG).show(); } else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_CERTIFICATE) { setResult(RESULT_CANCELED); - Toast.makeText(getApplicationContext(), "Your own cert has incorrectly been downloaded", Toast.LENGTH_LONG).show(); + Toast.makeText(getApplicationContext(), R.string.authed_cert_download_failed_message, Toast.LENGTH_LONG).show(); } } diff --git a/src/se/leap/leapclient/LogInDialog.java b/src/se/leap/leapclient/LogInDialog.java index 00429d1..dcb92d8 100644 --- a/src/se/leap/leapclient/LogInDialog.java +++ b/src/se/leap/leapclient/LogInDialog.java @@ -40,7 +40,7 @@ public class LogInDialog extends DialogFragment { interface_with_Dashboard.authenticate(username, password); } else { password_field.setText(""); - Toast.makeText(getActivity().getApplicationContext(), "Your password is not well-formed: it should have at least 8 characters", Toast.LENGTH_LONG).show(); + Toast.makeText(getActivity().getApplicationContext(), R.string.not_valid_password_message, Toast.LENGTH_LONG).show(); } } }) diff --git a/src/se/leap/leapclient/NewProviderDialog.java b/src/se/leap/leapclient/NewProviderDialog.java index 5b84ec0..678e805 100644 --- a/src/se/leap/leapclient/NewProviderDialog.java +++ b/src/se/leap/leapclient/NewProviderDialog.java @@ -65,10 +65,10 @@ public class NewProviderDialog extends DialogFragment { boolean danger_on = danger_checkbox.isChecked(); if(validURL(entered_url)) { interface_with_ConfigurationWizard.saveProvider(entered_url, danger_on); - Toast.makeText(getActivity().getApplicationContext(), "It seems your URL is well formed", Toast.LENGTH_LONG).show(); + Toast.makeText(getActivity().getApplicationContext(), R.string.valid_url_entered, Toast.LENGTH_LONG).show(); } else { url_input_field.setText(""); - Toast.makeText(getActivity().getApplicationContext(), "It seems your URL is not well formed", Toast.LENGTH_LONG).show(); + Toast.makeText(getActivity().getApplicationContext(), R.string.not_valid_password_message, Toast.LENGTH_LONG).show(); } } }) diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index f8d730e..4dfe200 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -219,11 +219,11 @@ public class ProviderAPI extends IntentService { JSONObject session_idAndM2 = new JSONObject(); if(json_response.length() > 0) { - byte[] M2_not_trimmed = new BigInteger(json_response.getString("M2"), 16).toByteArray(); + byte[] M2_not_trimmed = new BigInteger(json_response.getString(ConfigHelper.M2_KEY), 16).toByteArray(); Cookie session_id_cookie = LeapHttpClient.getInstance(getApplicationContext()).getCookieStore().getCookies().get(0); session_idAndM2.put(ConfigHelper.SESSION_ID_COOKIE_KEY, session_id_cookie.getName()); session_idAndM2.put(ConfigHelper.SESSION_ID_KEY, session_id_cookie.getValue()); - session_idAndM2.put("M2", Util.trim(M2_not_trimmed)); + session_idAndM2.put(ConfigHelper.M2_KEY, Util.trim(M2_not_trimmed)); } return session_idAndM2; } @@ -245,7 +245,7 @@ public class ProviderAPI extends IntentService { HttpEntity responseEntity = getResponse.getEntity(); String plain_response = new Scanner(responseEntity.getContent()).useDelimiter("\\A").next(); JSONObject json_response = new JSONObject(plain_response); - if(!json_response.isNull("errors") || json_response.has("errors")) { + if(!json_response.isNull(ConfigHelper.ERRORS_KEY) || json_response.has(ConfigHelper.ERRORS_KEY)) { return new JSONObject(); } diff --git a/src/se/leap/leapclient/ProviderListContent.java b/src/se/leap/leapclient/ProviderListContent.java index 4ae4609..8727b16 100644 --- a/src/se/leap/leapclient/ProviderListContent.java +++ b/src/se/leap/leapclient/ProviderListContent.java @@ -60,10 +60,10 @@ public class ProviderListContent { JSONObject file_contents = new JSONObject(urls_file_content); id = name; this.name = name; - provider_json_url = file_contents.getString("json_provider"); + provider_json_url = file_contents.getString(ConfigHelper.PROVIDER_JSON_URL); 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"); + cert_json_url = file_contents.getString(ConfigHelper.CERT_KEY); this.custom = custom; this.danger_on = danger_on; } catch (JSONException e) { @@ -89,7 +89,7 @@ public class ProviderListContent { this.name = name; this.provider_json_url = provider_json_url; this.provider_json = provider_json; - eip_service_json_url = provider_json.getString("api_uri") + "/" + provider_json.getString("api_version") + "/" + ConfigHelper.EIP_SERVICE_API_PATH; + eip_service_json_url = provider_json.getString(ConfigHelper.API_URL_KEY) + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY) + "/" + ConfigHelper.EIP_SERVICE_API_PATH; cert_json_url = (String) provider_json.get("ca_cert_uri"); this.custom = custom; this.danger_on = danger_on; -- cgit v1.2.3 From 65e2f56a8a10877964fb9fc57963d1bf8104801a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 20 Jun 2013 17:47:07 +0200 Subject: No binary library needed. I've decided not to include any lib, but to copy the SRPParameters class to our codebase and Util.trim method to ConfigHelper. --- src/se/leap/leapclient/ConfigHelper.java | 20 +++++++++ src/se/leap/leapclient/LeapSRPSession.java | 69 +++++++++++++++--------------- src/se/leap/leapclient/ProviderAPI.java | 5 +-- 3 files changed, 57 insertions(+), 37 deletions(-) (limited to 'src/se/leap/leapclient') diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index cb4a550..dd20112 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -207,6 +207,26 @@ public class ConfigHelper { return input_stream; } + /** + * Treat the input as the MSB representation of a number, + * and lop off leading zero elements. For efficiency, the + * input is simply returned if no leading zeroes are found. + * + * @param in array to be trimmed + */ + public static byte[] trim(byte[] in) { + if(in.length == 0 || in[0] != 0) + return in; + + int len = in.length; + int i = 1; + while(in[i] == 0 && i < len) + ++i; + byte[] ret = new byte[len - i]; + System.arraycopy(in, i, ret, 0, len - i); + return ret; + } + /** * Sets class scope Shared Preferences * @param shared_preferences diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index beb286d..d21ccff 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -4,9 +4,9 @@ import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.Arrays; -import org.jboss.security.Util; import org.jboss.security.srp.SRPParameters; /** @@ -30,6 +30,7 @@ public class LeapSRPSession { private BigInteger a; private BigInteger A; private byte[] K; + private SecureRandom pseudoRng; /** The M1 = H(H(N) xor H(g) | H(U) | s | A | B | K) hash */ private MessageDigest clientHash; /** The M2 = H(A | M | K) hash */ @@ -57,20 +58,20 @@ public class LeapSRPSession { */ public LeapSRPSession(String username, String password, SRPParameters params, byte[] abytes) { - try { - // Initialize the secure random number and message digests - Util.init(); - } - catch(NoSuchAlgorithmException e) { - } - this.params = params; this.g = new BigInteger(1, params.g); - N_bytes = Util.trim(params.N); + N_bytes = ConfigHelper.trim(params.N); this.N = new BigInteger(1, N_bytes); this.username = username; this.password = password; + try { + pseudoRng = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if( abytes != null ) { A_LEN = 8*abytes.length; /* TODO Why did they put this condition? @@ -105,15 +106,15 @@ public class LeapSRPSession { byte[] colon = {}; String encoding = "ISO-8859-1"; try { - user = Util.trim(username.getBytes(encoding)); - colon = Util.trim(":".getBytes(encoding)); - password_bytes = Util.trim(password.getBytes(encoding)); + user = ConfigHelper.trim(username.getBytes(encoding)); + colon = ConfigHelper.trim(":".getBytes(encoding)); + password_bytes = ConfigHelper.trim(password.getBytes(encoding)); } catch(UnsupportedEncodingException e) { // Use the default platform encoding - user = Util.trim(username.getBytes()); - colon = Util.trim(":".getBytes()); - password_bytes = Util.trim(password.getBytes()); + user = ConfigHelper.trim(username.getBytes()); + colon = ConfigHelper.trim(":".getBytes()); + password_bytes = ConfigHelper.trim(password.getBytes()); } // Build the hash @@ -152,7 +153,7 @@ public class LeapSRPSession { { //TODO Check if length matters in the order, when b2 is smaller than b1 or viceversa byte[] xor_digest = new BigInteger(1, b1).xor(new BigInteger(1, b2)).toByteArray(); - return Util.trim(xor_digest); + return ConfigHelper.trim(xor_digest); } /** @@ -166,11 +167,11 @@ public class LeapSRPSession { if( a == null ) { BigInteger one = BigInteger.ONE; do { - a = new BigInteger(A_LEN, Util.getPRNG()); + a = new BigInteger(A_LEN, pseudoRng); } while(a.compareTo(one) <= 0); } A = g.modPow(a, N); - Abytes = Util.trim(A.toByteArray()); + Abytes = ConfigHelper.trim(A.toByteArray()); } return Abytes; } @@ -186,7 +187,7 @@ public class LeapSRPSession { */ public byte[] response(byte[] salt_bytes, byte[] Bbytes) throws NoSuchAlgorithmException { // Calculate x = H(s | H(U | ':' | password)) - byte[] xb = calculatePasswordHash(username, password, Util.trim(salt_bytes)); + byte[] xb = calculatePasswordHash(username, password, ConfigHelper.trim(salt_bytes)); this.x = new BigInteger(1, xb); // Calculate v = kg^x mod N @@ -204,36 +205,36 @@ public class LeapSRPSession { clientHash.update(xor_digest); // clientHash = H(N) xor H(g) | H(U) - byte[] username_digest = newDigest().digest(Util.trim(username.getBytes())); - username_digest = Util.trim(username_digest); + byte[] username_digest = newDigest().digest(ConfigHelper.trim(username.getBytes())); + username_digest = ConfigHelper.trim(username_digest); clientHash.update(username_digest); // clientHash = H(N) xor H(g) | H(U) | s - clientHash.update(Util.trim(salt_bytes)); + clientHash.update(ConfigHelper.trim(salt_bytes)); K = null; // clientHash = H(N) xor H(g) | H(U) | A - byte[] Abytes = Util.trim(A.toByteArray()); + byte[] Abytes = ConfigHelper.trim(A.toByteArray()); clientHash.update(Abytes); // clientHash = H(N) xor H(g) | H(U) | s | A | B - Bbytes = Util.trim(Bbytes); + Bbytes = ConfigHelper.trim(Bbytes); clientHash.update(Bbytes); // Calculate S = (B - kg^x) ^ (a + u * x) % N BigInteger S = calculateS(Bbytes); - byte[] S_bytes = Util.trim(S.toByteArray()); + byte[] S_bytes = ConfigHelper.trim(S.toByteArray()); // K = SessionHash(S) String hash_algorithm = params.hashAlgorithm; MessageDigest sessionDigest = MessageDigest.getInstance(hash_algorithm); - K = Util.trim(sessionDigest.digest(S_bytes)); + K = ConfigHelper.trim(sessionDigest.digest(S_bytes)); // clientHash = H(N) xor H(g) | H(U) | A | B | K clientHash.update(K); - byte[] M1 = Util.trim(clientHash.digest()); + byte[] M1 = ConfigHelper.trim(clientHash.digest()); // serverHash = Astr + M + K serverHash.update(Abytes); @@ -249,8 +250,8 @@ public class LeapSRPSession { * @return the parameter S */ private BigInteger calculateS(byte[] Bbytes) { - byte[] Abytes = Util.trim(A.toByteArray()); - Bbytes = Util.trim(Bbytes); + byte[] Abytes = ConfigHelper.trim(A.toByteArray()); + Bbytes = ConfigHelper.trim(Bbytes); byte[] u_bytes = getU(Abytes, Bbytes); BigInteger B = new BigInteger(1, Bbytes); @@ -270,10 +271,10 @@ public class LeapSRPSession { */ public byte[] getU(byte[] Abytes, byte[] Bbytes) { MessageDigest u_digest = newDigest(); - u_digest.update(Util.trim(Abytes)); - u_digest.update(Util.trim(Bbytes)); + u_digest.update(ConfigHelper.trim(Abytes)); + u_digest.update(ConfigHelper.trim(Bbytes)); byte[] u_digest_bytes = u_digest.digest(); - return Util.trim(new BigInteger(1, u_digest_bytes).toByteArray()); + return ConfigHelper.trim(new BigInteger(1, u_digest_bytes).toByteArray()); } /** @@ -283,8 +284,8 @@ public class LeapSRPSession { public boolean verify(byte[] M2) { // M2 = H(A | M1 | K) - M2 = Util.trim(M2); - byte[] myM2 = Util.trim(serverHash.digest()); + M2 = ConfigHelper.trim(M2); + byte[] myM2 = ConfigHelper.trim(serverHash.digest()); boolean valid = Arrays.equals(M2, myM2); return valid; } diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 4dfe200..00d7d82 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -41,7 +41,6 @@ import org.apache.http.cookie.Cookie; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; -import org.jboss.security.Util; import org.jboss.security.srp.SRPParameters; import org.json.JSONException; import org.json.JSONObject; @@ -214,7 +213,7 @@ public class ProviderAPI extends IntentService { * @throws JSONException */ private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) throws ClientProtocolException, IOException, JSONException { - HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + "client_auth" + "=" + new BigInteger(1, Util.trim(m1)).toString(16)); + HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + "client_auth" + "=" + new BigInteger(1, ConfigHelper.trim(m1)).toString(16)); JSONObject json_response = sendToServer(put); JSONObject session_idAndM2 = new JSONObject(); @@ -223,7 +222,7 @@ public class ProviderAPI extends IntentService { Cookie session_id_cookie = LeapHttpClient.getInstance(getApplicationContext()).getCookieStore().getCookies().get(0); session_idAndM2.put(ConfigHelper.SESSION_ID_COOKIE_KEY, session_id_cookie.getName()); session_idAndM2.put(ConfigHelper.SESSION_ID_KEY, session_id_cookie.getValue()); - session_idAndM2.put(ConfigHelper.M2_KEY, Util.trim(M2_not_trimmed)); + session_idAndM2.put(ConfigHelper.M2_KEY, ConfigHelper.trim(M2_not_trimmed)); } return session_idAndM2; } -- cgit v1.2.3