diff options
author | Parménides GV <parmegv@sdf.org> | 2015-04-10 11:19:03 +0200 |
---|---|---|
committer | Parménides GV <parmegv@sdf.org> | 2015-04-10 11:19:03 +0200 |
commit | 1f41fec6765e49838141ad29151713c7ac3dd17c (patch) | |
tree | d4c63d5bbb8e51d91d75179ad01abd9a7565badc | |
parent | c198dbd9dd583d980ae7e70118f67d09bed8de55 (diff) | |
parent | fe95b7693f0f1f90d23ba2596ad3b11195efb11d (diff) |
Merge branch 'develop'0.9.3
52 files changed, 5323 insertions, 5082 deletions
@@ -1,3 +1,18 @@ +0.9.3 +Bugs: +- If VPN connection fails, blocking VPN is turned off +- Don't try to log out if nothing is logged in. +- Give better user feedback to some problems +- Switching orientation doesn't hide any useful message +- Blocking VPN is more consistently removed if an error happens +- Typo: you is not logged in -> you *are* not logged in +- Cleaner log messages to logcat + +Features: +- Show the user status progress and info in its own place +- Remember riseup's users that this is a different service +- Advice users to be cautious when surfing the web after disconnecting the VPN + 0.9.2 Bugs: - Sign Up dialog works correctly diff --git a/app/build.gradle b/app/build.gradle index 4d3c5b9c..4441cafa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,7 +39,7 @@ android { } dependencies { - androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.2.1' + androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.3.1' compile 'com.jakewharton:butterknife:6.0.0+' provided 'com.squareup.dagger:dagger-compiler:1.2.2+' compile 'com.github.pedrovgs:renderers:1.3+' diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/ConnectionManager.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/ConnectionManager.java index e67dd820..a664c885 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/ConnectionManager.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/ConnectionManager.java @@ -1,31 +1,29 @@ package se.leap.bitmaskclient.test; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.wifi.WifiManager; -import android.util.Log; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import android.content.*; +import android.net.*; +import android.net.wifi.*; + +import java.lang.reflect.*; public class ConnectionManager { static void setMobileDataEnabled(boolean enabled, Context context) { - final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - Method[] methods = conman.getClass().getMethods(); - for (Method method : methods) { - if (method.getName().equals("setMobileDataEnabled")) { - method.setAccessible(true); - try { - method.invoke(conman, enabled); - } catch (InvocationTargetException | IllegalAccessException e) { - e.printStackTrace(); - } + final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + Method[] methods = conman.getClass().getMethods(); + for (Method method : methods) { + if (method.getName().equals("setMobileDataEnabled")) { + method.setAccessible(true); + try { + method.invoke(conman, enabled); + } catch (InvocationTargetException | IllegalAccessException e) { + e.printStackTrace(); + } + } } - } } static void setWifiEnabled(boolean enabled, Context context) { - WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - wifiManager.setWifiEnabled(enabled); + WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + wifiManager.setWifiEnabled(enabled); } } diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/FromAssets.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/FromAssets.java index 4f771922..6a4c1ee2 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/FromAssets.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/FromAssets.java @@ -1,11 +1,10 @@ package se.leap.bitmaskclient.test; -import android.content.Context; +import android.content.*; -import org.json.JSONException; +import org.json.*; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; public class FromAssets { @@ -14,11 +13,12 @@ public class FromAssets { public FromAssets(Context context) { this.context = context; } + public String toString(String filename) throws IOException, JSONException { String result = ""; InputStream is = context.getAssets().open(filename); byte[] bytes = new byte[is.available()]; - if(is.read(bytes) > 0) { + if (is.read(bytes) > 0) { result = new String(bytes); } return result; diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testConfigurationWizard.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testConfigurationWizard.java index 755f83a7..1fa4cf2f 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/testConfigurationWizard.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testConfigurationWizard.java @@ -2,41 +2,44 @@ package se.leap.bitmaskclient.test; import android.test.*; import android.widget.*; + import com.robotium.solo.*; + import java.io.*; + import se.leap.bitmaskclient.*; public class testConfigurationWizard extends ActivityInstrumentationTestCase2<ConfigurationWizard> { - private Solo solo; - private static int added_providers; - - public testConfigurationWizard() { - super(ConfigurationWizard.class); - } + private Solo solo; + private static int added_providers; + + public testConfigurationWizard() { + super(ConfigurationWizard.class); + } public testConfigurationWizard(Solo solo) { super(ConfigurationWizard.class); this.solo = solo; } - @Override - protected void setUp() throws Exception { - super.setUp(); + @Override + protected void setUp() throws Exception { + super.setUp(); solo = new Solo(getInstrumentation(), getActivity()); - ConnectionManager.setMobileDataEnabled(true, solo.getCurrentActivity().getApplicationContext()); - } + ConnectionManager.setMobileDataEnabled(true, solo.getCurrentActivity().getApplicationContext()); + } + + @Override + protected void tearDown() throws Exception { + + } - @Override - protected void tearDown() throws Exception { - solo.finishOpenedActivities(); - } - - public void testListProviders() { - assertEquals(solo.getCurrentViews(ListView.class).size(), 1); + public void testListProviders() { + assertEquals(solo.getCurrentViews(ListView.class).size(), 1); - assertEquals("Number of available providers differ", predefinedProviders() + added_providers, shownProviders()); - } + assertEquals("Number of available providers differ", predefinedProviders() + added_providers, shownProviders()); + } private int shownProviders() { return solo.getCurrentViews(ListView.class).get(0).getCount(); @@ -53,10 +56,10 @@ public class testConfigurationWizard extends ActivityInstrumentationTestCase2<Co return predefined_providers; } - - public void testSelectProvider() { + + public void testSelectProvider() { selectProvider("demo.bitmask.net"); - } + } private void selectProvider(String provider) { solo.clickOnText(provider); @@ -70,12 +73,12 @@ public class testConfigurationWizard extends ActivityInstrumentationTestCase2<Co public void testAddNewProvider() { addProvider("calyx.net"); - } + } private void addProvider(String url) { boolean is_new_provider = !solo.searchText(url); - if(is_new_provider) - added_providers = added_providers+1; + if (is_new_provider) + added_providers = added_providers + 1; solo.clickOnActionBarItem(R.id.new_provider); solo.enterText(0, url); solo.clickOnCheckBox(0); @@ -83,10 +86,10 @@ public class testConfigurationWizard extends ActivityInstrumentationTestCase2<Co waitForProviderDetails(); solo.goBack(); } - - public void testShowAbout() { - showAbout(); - } + + public void testShowAbout() { + showAbout(); + } private void showAbout() { String text = solo.getString(R.string.about); @@ -94,14 +97,18 @@ public class testConfigurationWizard extends ActivityInstrumentationTestCase2<Co assertTrue("Provider details dialog did not appear", solo.waitForActivity(AboutActivity.class)); } - protected void toDashboard(String provider) { + protected void toDashboardAnonymously(String provider) { selectProvider(provider); useAnonymously(); } private void useAnonymously() { String text = solo.getString(R.string.use_anonymously_button); - solo.clickOnText(text); - solo.waitForText(solo.getString(R.string.title_activity_dashboard)); + clickAndWaitForDashboard(text); + } + + private void clickAndWaitForDashboard(String click_text) { + solo.clickOnText(click_text); + assertTrue(solo.waitForActivity(Dashboard.class, 5000)); } } diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboardIntegration.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboardIntegration.java index 91b93d42..d2fb9901 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboardIntegration.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboardIntegration.java @@ -1,55 +1,57 @@ package se.leap.bitmaskclient.test; -import android.content.Context; +import android.content.*; import android.test.*; +import android.widget.*; + import com.robotium.solo.*; -import java.io.IOException; +import java.io.*; import de.blinkt.openvpn.activities.*; import se.leap.bitmaskclient.*; public class testDashboardIntegration extends ActivityInstrumentationTestCase2<Dashboard> { - private Solo solo; + private Solo solo; private Context context; - public testDashboardIntegration() { - super(Dashboard.class); - } + public testDashboardIntegration() { + super(Dashboard.class); + } - @Override - protected void setUp() throws Exception { - super.setUp(); + @Override + protected void setUp() throws Exception { + super.setUp(); context = getInstrumentation().getContext(); - solo = new Solo(getInstrumentation(), getActivity()); - ConnectionManager.setMobileDataEnabled(true, context); + solo = new Solo(getInstrumentation(), getActivity()); + ConnectionManager.setMobileDataEnabled(true, context); solo.unlockScreen(); - if(solo.searchText(solo.getString(R.string.configuration_wizard_title))) - new testConfigurationWizard(solo).toDashboard("demo.bitmask.net"); - } - - @Override - protected void tearDown() throws Exception { - solo.finishOpenedActivities(); - } - - /** - * This test will fail if Android does not trust VPN connection. - * I cannot automate that dialog. - */ - public void testOnOffOpenVpn() { - solo.clickOnView(solo.getView(R.id.eipSwitch)); - turningEipOn(); - - solo.clickOnView(solo.getView(R.id.eipSwitch)); - turningEipOff(); - - solo.clickOnView(solo.getView(R.id.eipSwitch)); - turningEipOn(); - - solo.clickOnView(solo.getView(R.id.eipSwitch)); - turningEipOff(); + if (solo.searchText(solo.getString(R.string.configuration_wizard_title))) + new testConfigurationWizard(solo).toDashboardAnonymously("demo.bitmask.net"); + } + + @Override + protected void tearDown() throws Exception { + solo.finishOpenedActivities(); + } + + /** + * This test will fail if Android does not trust VPN connection. + * I cannot automate that dialog. + */ + public void testOnOffOpenVpn() { + solo.clickOnView(solo.getView(R.id.eipSwitch)); + turningEipOn(); + + solo.clickOnView(solo.getView(R.id.eipSwitch)); + turningEipOff(); + + solo.clickOnView(solo.getView(R.id.eipSwitch)); + turningEipOn(); + + solo.clickOnView(solo.getView(R.id.eipSwitch)); + turningEipOff(); /*solo.clickOnView(solo.getView(R.id.eipSwitch)); turningEipOn(); @@ -57,14 +59,14 @@ public class testDashboardIntegration extends ActivityInstrumentationTestCase2<D turnNetworkOff(); restartAdbServer(); // This doesn't work */ - - } + + } private void turningEipOn() { assertAuthenticating(); int max_seconds_until_connected = 30; assertConnected(max_seconds_until_connected); - solo.sleep(2*1000); + solo.sleep(2 * 1000); } private void assertAuthenticating() { @@ -78,44 +80,44 @@ public class testDashboardIntegration extends ActivityInstrumentationTestCase2<D } private void turningEipOff() { - sayOkToDisconnect(); + sayOkToDisconnect(); assertDisconnected(); - solo.sleep(2*1000); + solo.sleep(2 * 1000); } private void sayOkToDisconnect() { - assertTrue(solo.waitForActivity(DisconnectVPN.class)); + assertTrue(solo.waitForActivity(DisconnectVPN.class)); String yes = solo.getString(android.R.string.yes); - solo.clickOnText(yes); + solo.clickOnText(yes); } private void assertDisconnected() { String message = solo.getString(R.string.eip_state_not_connected); assertTrue(solo.waitForText(message)); } - + private void turnNetworkOff() { - ConnectionManager.setMobileDataEnabled(false, context); - if(!solo.waitForText(getActivity().getString(R.string.eip_state_not_connected), 1, 15*1000)) - fail(); + ConnectionManager.setMobileDataEnabled(false, context); + if (!solo.waitForText(getActivity().getString(R.string.eip_state_not_connected), 1, 15 * 1000)) + fail(); } private void restartAdbServer() { runAdbCommand("kill-server"); runAdbCommand("start-server"); } - + public void testLogInAndOut() { - long milliseconds_to_log_in = 40 * 1000; + long milliseconds_to_log_in = 40 * 1000; + solo.clickOnActionBarItem(R.id.login_button); logIn("parmegvtest1", " S_Zw3'-"); - solo.waitForDialogToClose(milliseconds_to_log_in); + solo.waitForDialogToClose(milliseconds_to_log_in); assertSuccessfulLogin(); logOut(); - } + } private void logIn(String username, String password) { - solo.clickOnActionBarItem(R.id.login_button); solo.enterText(0, username); solo.enterText(1, password); solo.clickOnText("Log In"); @@ -123,8 +125,7 @@ public class testDashboardIntegration extends ActivityInstrumentationTestCase2<D } private void assertSuccessfulLogin() { - String message = solo.getString(R.string.succesful_authentication_message); - assertTrue(solo.waitForText(message)); + assertTrue(solo.waitForText("is logged in")); } private void logOut() { @@ -134,10 +135,10 @@ public class testDashboardIntegration extends ActivityInstrumentationTestCase2<D public void testShowAbout() { showAbout(); - solo.goBack(); - showAbout(); - solo.goBack(); - } + solo.goBack(); + showAbout(); + solo.goBack(); + } private void showAbout() { String menu_item = solo.getString(R.string.about); @@ -148,11 +149,73 @@ public class testDashboardIntegration extends ActivityInstrumentationTestCase2<D } public void testSwitchProvider() { - solo.clickOnMenuItem(solo.getString(R.string.switch_provider_menu_option)); - solo.waitForActivity(ConfigurationWizard.class); - solo.goBack(); - } + tapSwitchProvider(); + solo.goBack(); + } + + private void tapSwitchProvider() { + solo.clickOnMenuItem(solo.getString(R.string.switch_provider_menu_option)); + solo.waitForActivity(ConfigurationWizard.class); + } + + public void testEveryProvider() { + changeProvider("demo.bitmask.net"); + connectVpn(); + disconnectVpn(); + + changeProvider("riseup.net"); + connectVpn(); + disconnectVpn(); + + changeProvider("calyx.net"); + connectVpn(); + disconnectVpn(); + } + + private void changeProvider(String provider) { + tapSwitchProvider(); + solo.clickOnText(provider); + useRegistered(); + solo.waitForText("Downloading VPN certificate"); + assertDisconnected(); + } + + private void connectVpn() { + Switch vpn_switch = (Switch)solo.getView(R.id.eipSwitch); + assertFalse(vpn_switch.isChecked()); + + solo.clickOnView(vpn_switch); + turningEipOn(); + } + private void disconnectVpn() { + Switch vpn_switch = (Switch)solo.getView(R.id.eipSwitch); + assertTrue(vpn_switch.isChecked()); + + solo.clickOnView(vpn_switch); + solo.clickOnText("Yes"); + turningEipOff(); + + } + + private void useRegistered() { + String text = solo.getString(R.string.signup_or_login_button); + clickAndWaitForDashboard(text); + login(); + } + + private void clickAndWaitForDashboard(String click_text) { + solo.clickOnText(click_text); + assertTrue(solo.waitForActivity(Dashboard.class, 5000)); + } + + private void login() { + long milliseconds_to_log_in = 40 * 1000; + logIn("parmegvtest10", "holahola2"); + solo.waitForDialogToClose(milliseconds_to_log_in); + assertSuccessfulLogin(); + } + /*public void testReboot() { runAdbCommand("shell am broadcast -a android.intent.action.BOOT_COMPLETED"); }*/ diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testEIP.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testEIP.java index d9235085..b504af99 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/testEIP.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testEIP.java @@ -16,15 +16,13 @@ */ package se.leap.bitmaskclient.test; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.test.ServiceTestCase; -import android.test.suitebuilder.annotation.MediumTest; -import se.leap.bitmaskclient.Dashboard; -import se.leap.bitmaskclient.eip.Constants; -import se.leap.bitmaskclient.eip.EIP; +import android.content.*; +import android.test.*; +import android.test.suitebuilder.annotation.*; + +import se.leap.bitmaskclient.*; +import se.leap.bitmaskclient.eip.*; /** * @author parmegv diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testGatewaysManager.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testGatewaysManager.java index c4303251..086c060f 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/testGatewaysManager.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testGatewaysManager.java @@ -16,20 +16,15 @@ */ package se.leap.bitmaskclient.test; -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.MediumTest; -import android.test.suitebuilder.annotation.SmallTest; +import android.app.*; +import android.content.*; +import android.test.*; +import android.test.suitebuilder.annotation.*; -import junit.framework.Test; +import org.json.*; -import org.json.JSONObject; - -import se.leap.bitmaskclient.Dashboard; -import se.leap.bitmaskclient.eip.Gateway; -import se.leap.bitmaskclient.eip.GatewaysManager; +import se.leap.bitmaskclient.*; +import se.leap.bitmaskclient.eip.*; /** * @author parmegv @@ -83,7 +78,7 @@ public class testGatewaysManager extends InstrumentationTestCase { assertEquals("[]", gateways_manager.toString()); gateways_manager.addFromString(gateway.toString()); - assertEquals("["+gateway.toString()+"]", gateways_manager.toString()); + assertEquals("[" + gateway.toString() + "]", gateways_manager.toString()); } @SmallTest @@ -94,7 +89,7 @@ public class testGatewaysManager extends InstrumentationTestCase { gateways_manager.addFromString(gateway.toString()); assertFalse(gateways_manager.isEmpty()); } - + private void mockGatewaysManager() { context = getInstrumentation().getContext(); preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE); diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testLeapSRPSession.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testLeapSRPSession.java index d7f4bfb3..149c2c7f 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/testLeapSRPSession.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testLeapSRPSession.java @@ -1,632 +1,629 @@ package se.leap.bitmaskclient.test; -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 java.io.*; +import java.math.*; +import java.security.*; +import java.util.*; -import org.jboss.security.srp.SRPParameters; +import android.test.suitebuilder.annotation.*; -import android.test.suitebuilder.annotation.SmallTest; +import se.leap.bitmaskclient.*; -import se.leap.bitmaskclient.ConfigHelper; -import se.leap.bitmaskclient.LeapSRPSession; - -import junit.framework.TestCase; +import junit.framework.*; public class testLeapSRPSession extends TestCase { public testLeapSRPSession(String name) { - super(name); + super(name); } protected void setUp() throws Exception { - super.setUp(); + super.setUp(); } protected void tearDown() throws Exception { - super.tearDown(); + super.tearDown(); } public void testExponential() { - byte[] expected_A; - byte[] a_byte; - LeapSRPSession client; - + byte[] expected_A; + byte[] a_byte; + LeapSRPSession client; + /* Test 1: abytes = 4 */ - expected_A = new BigInteger("44eba0239ddfcc5a488d208df32a89eb00e93e6576b22ba2e4410085a413cf64e9c2f08ebc36a788a0761391150ad4a0507ca43f9ca659e2734f0457a85358c0bb39fa87183c9d3f9f8a3b148dab6303a4e796294f3e956472ba0e2ea5697382acd93c8b8f1b3a7a9d8517eebffd6301bfc8de7f7b701f0878a71faae1e25ad4", 16).toByteArray(); - String username = "username", - password = "password", - salt = "64c3289d04a6ecad", - a = "3565fdc2"; - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - - byte[] A = client.exponential(); - - assertTrue(Arrays.equals(A, expected_A)); + expected_A = new BigInteger("44eba0239ddfcc5a488d208df32a89eb00e93e6576b22ba2e4410085a413cf64e9c2f08ebc36a788a0761391150ad4a0507ca43f9ca659e2734f0457a85358c0bb39fa87183c9d3f9f8a3b148dab6303a4e796294f3e956472ba0e2ea5697382acd93c8b8f1b3a7a9d8517eebffd6301bfc8de7f7b701f0878a71faae1e25ad4", 16).toByteArray(); + String username = "username", + password = "password", + salt = "64c3289d04a6ecad", + a = "3565fdc2"; + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + + byte[] A = client.exponential(); + + assertTrue(Arrays.equals(A, expected_A)); /* Test 1: abytes = 5 */ - a = "67c152a3"; - expected_A = new BigInteger("11acfacc08178d48f95c0e69adb11f6d144dd0980ee6e44b391347592e3bd5e9cb841d243b3d9ac2adb25b367a2558e8829b22dcef96c0934378412383ccf95141c3cb5f17ada20f53a0225f56a07f2b0c0469ed6bbad3646f7b71bdd4bedf5cc6fac244b26d3195d8f55877ff94a925b0c0c8f7273eca733c0355b38360442e", 16).toByteArray(); + a = "67c152a3"; + expected_A = new BigInteger("11acfacc08178d48f95c0e69adb11f6d144dd0980ee6e44b391347592e3bd5e9cb841d243b3d9ac2adb25b367a2558e8829b22dcef96c0934378412383ccf95141c3cb5f17ada20f53a0225f56a07f2b0c0469ed6bbad3646f7b71bdd4bedf5cc6fac244b26d3195d8f55877ff94a925b0c0c8f7273eca733c0355b38360442e", 16).toByteArray(); - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - - A = client.exponential(); - - assertTrue(Arrays.equals(A, expected_A)); + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + + A = client.exponential(); + + assertTrue(Arrays.equals(A, expected_A)); } public void testResponse() throws NoSuchAlgorithmException { /* Test 1: with intermediate checks */ - byte[] expected_A = trim(new BigInteger("884380f70a62193bbe3589c4e1dbdc4467b6b5a1b4486e4b779023506fc1f885ae26fa4a5d817b3f38a35f3487b147b82d4bd0069faa64fdc845f7494a78251709e212698e42ced44b0f3849adc73f467afcb26983bd13bdc38906b178003373ddd0ac1d38ce8a39ffa3a7795787207a129a784f4b65ce0b302eb1bcf4045883", 16).toByteArray()); - byte[] expected_x = new BigInteger("4cb937fd74ee3bb53b79a3174d0c07c14131de9c825897cbca52154e74200602", 16).toByteArray(); - byte[] expected_M1 = trim(new BigInteger("e6a8efca2c07ef24e0b69be2d4d4a7e74742a4db7a92228218fec0008f7cc94b", 16).toByteArray()); - String username = "username", - password = "password", - salt = "64c3289d04a6ecad", - a = "8c911355"; - byte[] a_byte = new BigInteger(a, 16).toByteArray(); - LeapSRPSession client = new LeapSRPSession(username, password, a_byte); - - byte[] x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); - assertTrue(Arrays.equals(x, expected_x)); - - byte[] A = client.exponential(); - assertTrue(Arrays.equals(A, expected_A)); + byte[] expected_A = trim(new BigInteger("884380f70a62193bbe3589c4e1dbdc4467b6b5a1b4486e4b779023506fc1f885ae26fa4a5d817b3f38a35f3487b147b82d4bd0069faa64fdc845f7494a78251709e212698e42ced44b0f3849adc73f467afcb26983bd13bdc38906b178003373ddd0ac1d38ce8a39ffa3a7795787207a129a784f4b65ce0b302eb1bcf4045883", 16).toByteArray()); + byte[] expected_x = new BigInteger("4cb937fd74ee3bb53b79a3174d0c07c14131de9c825897cbca52154e74200602", 16).toByteArray(); + byte[] expected_M1 = trim(new BigInteger("e6a8efca2c07ef24e0b69be2d4d4a7e74742a4db7a92228218fec0008f7cc94b", 16).toByteArray()); + String username = "username", + password = "password", + salt = "64c3289d04a6ecad", + a = "8c911355"; + byte[] a_byte = new BigInteger(a, 16).toByteArray(); + LeapSRPSession client = new LeapSRPSession(username, password, a_byte); - String B = "bc745ba25564fc312f44ea09fb663aa6d95867772e412a6a23f1bc24183e54b32f134372c560f4b3fda19ba7a56b0f84fdcdecc22be6fd256639e918e019691c40a39aa5c9631820e42b28da61b8c75b45afae9d77d63ac8f4dda093762be4a890fbd86061dbd7e5e7c03c4dacde769e0f564df00403e449c0535537f1ba7263"; - - byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - assertTrue(Arrays.equals(M1, expected_M1)); + byte[] x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); + assertTrue(Arrays.equals(x, expected_x)); + + byte[] A = client.exponential(); + assertTrue(Arrays.equals(A, expected_A)); + + String B = "bc745ba25564fc312f44ea09fb663aa6d95867772e412a6a23f1bc24183e54b32f134372c560f4b3fda19ba7a56b0f84fdcdecc22be6fd256639e918e019691c40a39aa5c9631820e42b28da61b8c75b45afae9d77d63ac8f4dda093762be4a890fbd86061dbd7e5e7c03c4dacde769e0f564df00403e449c0535537f1ba7263"; + + byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + assertTrue(Arrays.equals(M1, expected_M1)); /* Test 2: no intermediate checks */ - expected_A = trim(new BigInteger("9ffc407afd7e7ecd32a8ea68aa782b0254a7e2197a955b5aa646fc1fc43ff6ef2239f01b7d5b82f152c870d3e69f3321878ca2acda06dd8fb6ce02f41c7ed48061c78697b01cf353f4222311334c707358b6ec067e317527316bfa85b5ec74537e38b5b14c1100d14c96320f385e5b1dcccde07e728c7ef624353167a29ae461", 16).toByteArray()); - expected_M1 = trim(new BigInteger("c3203ec1dd55c96038276456c18c447fb4d2a2f896c73c31d56da1781cae79a8", 16).toByteArray()); - a = "38d5b211"; - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); - A = client.exponential(); - - B = "b8ca7d93dbe2478966ffe025a9f2fb43b9995ce04af9523ea9a3fa4b132136076aa66ead1597c3da23f477ce1cfaf68b5dcc94e146db06cf8391d14a76ce53aab86067b13c93b135d7be6275669b3f51afec6cc41f19e0afca7c3ad5c4d6ee4c09d4b11bcd12e26c727ee56d173b92eea6926e72cc73deebe12dd6f30f44db8a"; - M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); + expected_A = trim(new BigInteger("9ffc407afd7e7ecd32a8ea68aa782b0254a7e2197a955b5aa646fc1fc43ff6ef2239f01b7d5b82f152c870d3e69f3321878ca2acda06dd8fb6ce02f41c7ed48061c78697b01cf353f4222311334c707358b6ec067e317527316bfa85b5ec74537e38b5b14c1100d14c96320f385e5b1dcccde07e728c7ef624353167a29ae461", 16).toByteArray()); + expected_M1 = trim(new BigInteger("c3203ec1dd55c96038276456c18c447fb4d2a2f896c73c31d56da1781cae79a8", 16).toByteArray()); + a = "38d5b211"; + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); + A = client.exponential(); + + B = "b8ca7d93dbe2478966ffe025a9f2fb43b9995ce04af9523ea9a3fa4b132136076aa66ead1597c3da23f477ce1cfaf68b5dcc94e146db06cf8391d14a76ce53aab86067b13c93b135d7be6275669b3f51afec6cc41f19e0afca7c3ad5c4d6ee4c09d4b11bcd12e26c727ee56d173b92eea6926e72cc73deebe12dd6f30f44db8a"; + M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); /* Test 3: With intermediate values */ - expected_M1 = new BigInteger("4c01f65a9bb00f95e435593083040ae1e59e59800c598b42de821c21f3a35223", 16).toByteArray(); - expected_A = new BigInteger("1bceab3047a6f84495fdd5b4dbe891f0b30f870d7d4e38eaef728f6a7d4e9342d8dae8502fdae4f16b718d2e916a38b16b6def45559a5ebae417a1b115ba6b6a0451c7ff174c3e2507d7d1f18ef646fd065bc9ba165a2a0ae4d6da54f060427178b95b0eff745f5c3f8c4f19ea35addc3ce0daf2aca3328c98bafcf98286d115", 16).toByteArray(); - B = "41a7b384f2f52312fa79b9dc650ae894f543aea49800cf9477fbcf63e39cbfe6d422f7126777d645cdf749276a3ae9eb6dfcfdb887f8f60ac4094a343013fcebbd40e95b3153f403ab7bb21ea1315aa018bab6ab84017fcb084b3870a8bf1cb717b39c9a28177c61ce7d1738379be9d192dd9793b50ebc3afabe5e78b0a4b017"; - a = "36ee80ec"; - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); - A = client.exponential(); - - M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); + expected_M1 = new BigInteger("4c01f65a9bb00f95e435593083040ae1e59e59800c598b42de821c21f3a35223", 16).toByteArray(); + expected_A = new BigInteger("1bceab3047a6f84495fdd5b4dbe891f0b30f870d7d4e38eaef728f6a7d4e9342d8dae8502fdae4f16b718d2e916a38b16b6def45559a5ebae417a1b115ba6b6a0451c7ff174c3e2507d7d1f18ef646fd065bc9ba165a2a0ae4d6da54f060427178b95b0eff745f5c3f8c4f19ea35addc3ce0daf2aca3328c98bafcf98286d115", 16).toByteArray(); + B = "41a7b384f2f52312fa79b9dc650ae894f543aea49800cf9477fbcf63e39cbfe6d422f7126777d645cdf749276a3ae9eb6dfcfdb887f8f60ac4094a343013fcebbd40e95b3153f403ab7bb21ea1315aa018bab6ab84017fcb084b3870a8bf1cb717b39c9a28177c61ce7d1738379be9d192dd9793b50ebc3afabe5e78b0a4b017"; + a = "36ee80ec"; + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); + A = client.exponential(); + + M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); } - + public void testCalculateV() throws NoSuchAlgorithmException { - String expected_v = "502f3ffddc78b866330550c2c60ebd68427c1793237d770e6390d1f794abd47b6786fa5025728d1ca4ec24cfc7a89808278330099ad66456a7c9c88be570b928f9825ac2ecdee31792335f7fa5fc9a78b692c487aa400c7d5cc5c1f2a3a74634c4afa0159600bbf22bf6dfb1e0d85061e55ce8df6243758066503bcf51c83848cf7184209731f89a90d888934c75798828859babe73c17009bf827723fc1bcd0"; - - BigInteger k = new BigInteger("bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0", 16); - BigInteger g = new BigInteger("2", 16); - BigInteger N = new BigInteger(ConfigHelper.NG_1024, 16); - BigInteger x = new BigInteger("4cb937fd74ee3bb53b79a3174d0c07c14131de9c825897cbca52154e74200602", 16); - - BigInteger v = k.multiply(g.modPow(x, N)); // g^x % N - - assertEquals(v.toString(16), expected_v); - assertTrue(Arrays.equals(v.toByteArray(), new BigInteger(expected_v, 16).toByteArray())); + String expected_v = "502f3ffddc78b866330550c2c60ebd68427c1793237d770e6390d1f794abd47b6786fa5025728d1ca4ec24cfc7a89808278330099ad66456a7c9c88be570b928f9825ac2ecdee31792335f7fa5fc9a78b692c487aa400c7d5cc5c1f2a3a74634c4afa0159600bbf22bf6dfb1e0d85061e55ce8df6243758066503bcf51c83848cf7184209731f89a90d888934c75798828859babe73c17009bf827723fc1bcd0"; + + BigInteger k = new BigInteger("bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0", 16); + BigInteger g = new BigInteger("2", 16); + BigInteger N = new BigInteger(ConfigHelper.NG_1024, 16); + BigInteger x = new BigInteger("4cb937fd74ee3bb53b79a3174d0c07c14131de9c825897cbca52154e74200602", 16); + + BigInteger v = k.multiply(g.modPow(x, N)); // g^x % N + + assertEquals(v.toString(16), expected_v); + assertTrue(Arrays.equals(v.toByteArray(), new BigInteger(expected_v, 16).toByteArray())); } - + public void testGetU() throws NoSuchAlgorithmException { /* Test 1 */ - String Astr = "46b1d1fe038a617966821bd5bb6af967be1bcd6f54c2db5a474cb80b625870e4616953271501a82198d0c14e72b95cdcfc9ec867027b0389aacb313319d4e81604ccf09ce7841dc333be2e03610ae46ec0c8e06b8e86975e0984cae4d0b61c51f1fe5499a4d4d42460261a3e134f841f2cef4d68a583130ee8d730e0b51a858f"; - String Bstr = "5e1a9ac84b1d9212a0d8f8fe444a34e7da4556a1ef5aebc043ae7276099ccdb305fd7e1c179729e24b484a35c0e33b6a898477590b93e9a4044fc1b8d6bc73db8ac7778f546b25ec3f22e92ab7144e5b974dc58e82a333262063062b6944a2e4393d2a087e4906e6a8cfa0fdfd8a5e5930b7cdb45435cbee7c49dfa1d1216881"; - String ustr = "759c3cfb6bfaccf07eeb8e46fe6ea290291d4d32faca0681830a372983ab0a61"; - - byte[] Abytes = new BigInteger(Astr, 16).toByteArray(); - byte[] Bbytes = new BigInteger(Bstr, 16).toByteArray(); - byte[] expected_u = new BigInteger(ustr, 16).toByteArray(); - - MessageDigest u_digest = MessageDigest.getInstance("SHA256"); - u_digest.update(trim(Abytes)); - u_digest.update(trim(Bbytes)); - byte[] u = new BigInteger(1, u_digest.digest()).toByteArray(); - - assertTrue(Arrays.equals(expected_u, u)); + String Astr = "46b1d1fe038a617966821bd5bb6af967be1bcd6f54c2db5a474cb80b625870e4616953271501a82198d0c14e72b95cdcfc9ec867027b0389aacb313319d4e81604ccf09ce7841dc333be2e03610ae46ec0c8e06b8e86975e0984cae4d0b61c51f1fe5499a4d4d42460261a3e134f841f2cef4d68a583130ee8d730e0b51a858f"; + String Bstr = "5e1a9ac84b1d9212a0d8f8fe444a34e7da4556a1ef5aebc043ae7276099ccdb305fd7e1c179729e24b484a35c0e33b6a898477590b93e9a4044fc1b8d6bc73db8ac7778f546b25ec3f22e92ab7144e5b974dc58e82a333262063062b6944a2e4393d2a087e4906e6a8cfa0fdfd8a5e5930b7cdb45435cbee7c49dfa1d1216881"; + String ustr = "759c3cfb6bfaccf07eeb8e46fe6ea290291d4d32faca0681830a372983ab0a61"; + + byte[] Abytes = new BigInteger(Astr, 16).toByteArray(); + byte[] Bbytes = new BigInteger(Bstr, 16).toByteArray(); + byte[] expected_u = new BigInteger(ustr, 16).toByteArray(); + + MessageDigest u_digest = MessageDigest.getInstance("SHA256"); + u_digest.update(trim(Abytes)); + u_digest.update(trim(Bbytes)); + byte[] u = new BigInteger(1, u_digest.digest()).toByteArray(); + + assertTrue(Arrays.equals(expected_u, u)); /* Test 2 */ - Astr = "c4013381bdb2fdd901944b9d823360f367c52635b576b9a50d2db77141d357ed391c3ac5fa452c2bbdc35f96bfed21df61627b40aed8f67f21ebf81e5621333f44049d6c9f6ad36464041438350e1f86000a8e3bfb63d4128c18322d2517b0d3ead63fd504a9c8f2156d46e64268110cec5f3ccab54a21559c7ab3ad67fedf90"; - Bstr = "e5d988752e8f265f01b98a1dcdecc4b685bd512e7cd9507f3c29f206c27dac91e027641eed1765c4603bbd7a9aa7fac300ef67dafe611ba2dbe29a32d83d486296f328d38b44c0c211d01d3fe422aac168b6850c87782338969c54594fc87804d4db34910ad4b5452a81027842ac8d8d8288fd44872e4c719ac8fb971d0a33e1"; - ustr = "6510328f913b81ba662e564ee5afb7c395ea27c3c0276fc5ca51f0edecd4baf1"; - - Abytes = new BigInteger(Astr, 16).toByteArray(); - Bbytes = new BigInteger(Bstr, 16).toByteArray(); - expected_u = new BigInteger(ustr, 16).toByteArray(); - expected_u = trim(expected_u); - - u_digest = MessageDigest.getInstance("SHA-256"); - u_digest.update(trim(Abytes)); - u_digest.update(trim(Bbytes)); - u = new BigInteger(1, u_digest.digest()).toByteArray(); - u = trim(u); - - assertTrue(Arrays.equals(expected_u, u)); + Astr = "c4013381bdb2fdd901944b9d823360f367c52635b576b9a50d2db77141d357ed391c3ac5fa452c2bbdc35f96bfed21df61627b40aed8f67f21ebf81e5621333f44049d6c9f6ad36464041438350e1f86000a8e3bfb63d4128c18322d2517b0d3ead63fd504a9c8f2156d46e64268110cec5f3ccab54a21559c7ab3ad67fedf90"; + Bstr = "e5d988752e8f265f01b98a1dcdecc4b685bd512e7cd9507f3c29f206c27dac91e027641eed1765c4603bbd7a9aa7fac300ef67dafe611ba2dbe29a32d83d486296f328d38b44c0c211d01d3fe422aac168b6850c87782338969c54594fc87804d4db34910ad4b5452a81027842ac8d8d8288fd44872e4c719ac8fb971d0a33e1"; + ustr = "6510328f913b81ba662e564ee5afb7c395ea27c3c0276fc5ca51f0edecd4baf1"; + + Abytes = new BigInteger(Astr, 16).toByteArray(); + Bbytes = new BigInteger(Bstr, 16).toByteArray(); + expected_u = new BigInteger(ustr, 16).toByteArray(); + expected_u = trim(expected_u); + + u_digest = MessageDigest.getInstance("SHA-256"); + u_digest.update(trim(Abytes)); + u_digest.update(trim(Bbytes)); + u = new BigInteger(1, u_digest.digest()).toByteArray(); + u = trim(u); + + assertTrue(Arrays.equals(expected_u, u)); /* Test 3 */ - Astr = "d13973fe4e0e13423cd036caf0912e23a1f9b0c23966f5a5897c8ff17c5cbac8bab7f07d9ac4ee47396a7c68e80ce854c84f243148521277900aaa132a7b93b61e54d742d7f36edb4cdef54bc78cca69ac72653a7ae0fc47ec1e9a84024ea9487a61357e28eddc185e4fe01388e64e6b8f688dd74471d56dd244204522e08483"; - Bstr = "a6701686d9d987a43f06e8497330c8add8febd191a7a975bced0d058eb03ccc6805263349363b2d54ac435b01155dc41c6067287d9b93e3637ab3b7e8bc7d9cf38d9fdbb2ca9ee8ba1946a46cb555cb7dafcc177fcf7a4b0eb1e5db2249949c1fd15e0b7c1b3616f9e2649bdf074ed841efbdc9f29ee8c8bfcedeaed3dc49378"; - ustr = "78414ec80cf44225e7ed386dcf2ceb89837327ccae11b761fc77d48c0307977"; - - Abytes = new BigInteger(Astr, 16).toByteArray(); - Bbytes = new BigInteger(Bstr, 16).toByteArray(); - expected_u = new BigInteger(ustr, 16).toByteArray(); - expected_u = trim(expected_u); - - u_digest = MessageDigest.getInstance("SHA-256"); - u_digest.update(trim(Abytes)); - u_digest.update(trim(Bbytes)); - u = new BigInteger(1, u_digest.digest()).toByteArray(); - u = trim(u); - - assertTrue(Arrays.equals(expected_u, u)); + Astr = "d13973fe4e0e13423cd036caf0912e23a1f9b0c23966f5a5897c8ff17c5cbac8bab7f07d9ac4ee47396a7c68e80ce854c84f243148521277900aaa132a7b93b61e54d742d7f36edb4cdef54bc78cca69ac72653a7ae0fc47ec1e9a84024ea9487a61357e28eddc185e4fe01388e64e6b8f688dd74471d56dd244204522e08483"; + Bstr = "a6701686d9d987a43f06e8497330c8add8febd191a7a975bced0d058eb03ccc6805263349363b2d54ac435b01155dc41c6067287d9b93e3637ab3b7e8bc7d9cf38d9fdbb2ca9ee8ba1946a46cb555cb7dafcc177fcf7a4b0eb1e5db2249949c1fd15e0b7c1b3616f9e2649bdf074ed841efbdc9f29ee8c8bfcedeaed3dc49378"; + ustr = "78414ec80cf44225e7ed386dcf2ceb89837327ccae11b761fc77d48c0307977"; + + Abytes = new BigInteger(Astr, 16).toByteArray(); + Bbytes = new BigInteger(Bstr, 16).toByteArray(); + expected_u = new BigInteger(ustr, 16).toByteArray(); + expected_u = trim(expected_u); + + u_digest = MessageDigest.getInstance("SHA-256"); + u_digest.update(trim(Abytes)); + u_digest.update(trim(Bbytes)); + u = new BigInteger(1, u_digest.digest()).toByteArray(); + u = trim(u); + + assertTrue(Arrays.equals(expected_u, u)); /* Test 4 */ - Astr = "ee8bc0cb97dd9c9937759658ff9d791df1dd57b48c5febc2e98af028d0e36eaddf1a3fc555f2bcd6456827e8c7b07ec02a1f365457843bda226bfc1a55c4776879f9df6c916810131ec65a3a4cf473c6a34299d64c91cf26542ea0fc059d24422fc783460c3fafe26bf6f7c24904ae1c5a6421e2f5315030ab007ce8f2c2fd97"; - Bstr = "95ecbd13b28c7f38318fd664ee97d9e853b0d6e9cbff9a3775a3cc5d5077ffc146aec70d9439e75c19a34b67368b8bd7035ba6254e0a260d99b1e253aae2e0d8f4a13e1ed472f3ef0e3086300cd15d059f6be7d7141ee09071b1c5e5d1c83b250a3c8f1a587f8fe59d49aaeb2cfc7e13a5a58bc76cc8baf7f6a647982c67ee49"; - ustr = "e28737c7307c84e4d0866b7cf882f22852a764b109634f77a5eb986a96ffcf9a"; - - Abytes = new BigInteger(Astr, 16).toByteArray(); - Bbytes = new BigInteger(Bstr, 16).toByteArray(); - expected_u = new BigInteger(ustr, 16).toByteArray(); - expected_u = trim(expected_u); - assertEquals(new BigInteger(1, expected_u).toString(16), ustr); - - u_digest = MessageDigest.getInstance("SHA-256"); - u_digest.update(trim(Abytes)); - u_digest.update(trim(Bbytes)); - u = new BigInteger(1, u_digest.digest()).toByteArray(); - u = trim(u); - - assertTrue(Arrays.equals(expected_u, u)); + Astr = "ee8bc0cb97dd9c9937759658ff9d791df1dd57b48c5febc2e98af028d0e36eaddf1a3fc555f2bcd6456827e8c7b07ec02a1f365457843bda226bfc1a55c4776879f9df6c916810131ec65a3a4cf473c6a34299d64c91cf26542ea0fc059d24422fc783460c3fafe26bf6f7c24904ae1c5a6421e2f5315030ab007ce8f2c2fd97"; + Bstr = "95ecbd13b28c7f38318fd664ee97d9e853b0d6e9cbff9a3775a3cc5d5077ffc146aec70d9439e75c19a34b67368b8bd7035ba6254e0a260d99b1e253aae2e0d8f4a13e1ed472f3ef0e3086300cd15d059f6be7d7141ee09071b1c5e5d1c83b250a3c8f1a587f8fe59d49aaeb2cfc7e13a5a58bc76cc8baf7f6a647982c67ee49"; + ustr = "e28737c7307c84e4d0866b7cf882f22852a764b109634f77a5eb986a96ffcf9a"; + + Abytes = new BigInteger(Astr, 16).toByteArray(); + Bbytes = new BigInteger(Bstr, 16).toByteArray(); + expected_u = new BigInteger(ustr, 16).toByteArray(); + expected_u = trim(expected_u); + assertEquals(new BigInteger(1, expected_u).toString(16), ustr); + + u_digest = MessageDigest.getInstance("SHA-256"); + u_digest.update(trim(Abytes)); + u_digest.update(trim(Bbytes)); + u = new BigInteger(1, u_digest.digest()).toByteArray(); + u = trim(u); + + assertTrue(Arrays.equals(expected_u, u)); } - + @SmallTest public void testCalculatePasswordHash() throws UnsupportedEncodingException, NoSuchAlgorithmException { - String salt_str = "", username_str = "", password_str = ""; - String expected_inner = "cfb9ae3ec5433076889c4fe5663926e20bf570cc7950a51c889a314fab2f5ed716bde9c1cc91be14", - expected_x = "9736a5e386a18f35bb08cac0f7c70bdbe120f2efe019874d0eb23b85b1955858"; + String salt_str = "", username_str = "", password_str = ""; + String expected_inner = "cfb9ae3ec5433076889c4fe5663926e20bf570cc7950a51c889a314fab2f5ed716bde9c1cc91be14", + expected_x = "9736a5e386a18f35bb08cac0f7c70bdbe120f2efe019874d0eb23b85b1955858"; /* Test 1 */ - salt_str = "cfb9ae3ec5433076"; username_str = "nostradamus"; password_str = "$[[//jjiilajfewahug43a89y¿"; - password_str = password_str.replaceAll("\\\\", "\\\\\\\\"); - // Calculate x = H(s | H(U | ':' | password)) - MessageDigest x_digest = MessageDigest.getInstance("SHA-256"); - - // Try to convert the username to a byte[] using UTF-8 - byte[] user = null; - byte[] password_bytes = null; - byte[] colon = {}; - - String encoding = "UTF-8"; - encoding = "ISO-8859-1"; - user = ConfigHelper.trim(username_str.getBytes(encoding)); - colon = ConfigHelper.trim(":".getBytes(encoding)); - password_bytes = ConfigHelper.trim(password_str.getBytes(encoding)); - - // Build the hash - x_digest.update(user); - x_digest.update(colon); - x_digest.update(password_bytes); - byte[] h = x_digest.digest(); - byte[] salt_bytes = ConfigHelper.trim(new BigInteger(salt_str, 16).toByteArray()); - - x_digest.reset(); - x_digest.update(salt_bytes); - x_digest.update(h); - byte[] x_digest_bytes = x_digest.digest(); - assertTrue(new BigInteger(1, x_digest_bytes).toString(16).equalsIgnoreCase(expected_x)); - } - - public void testCalculateS() throws NoSuchAlgorithmException { - String expected_S = "34d71467d0a30c5787e6b4384c7176a724df28f6c1d3b0b7738238621be19080942ca5d4454ab3e5664d42970ea2d42d1188ab246afb1475c481111f30886c79cc99ddd1d711034bc4ac57a0c134fef40470e1ac3386f39abcd1bf9d0cc758a1f38a87b2f7261018cdc6191cd941292c77c320b3c664a9bb1325dd7a2bf62db4"; - - String B_string = "d390da0991b84e20918764aed9bccf36fc70863f08a1d3fa0aecd9610d8c40d1895afaf3aa9b4582fb5bc673037dfc1bf0ca7d3d190a807dec563fe57d596b3551ec8a6461e0621b77fabfaa29234187063e715e2706522c65f35d89f3914a7cdf40ddd240ef3d22b5534469cf6b3b31e158f817dcf5b6b44b0914d4787d027e"; - String A_string = "c6385e56b9cb8987df3c58ffe6c47bfcd9f9d52f02b68048d72135a8522a0919b41683e3c732a0874e0555b8f288fa067842b1c40a56f1a7d910ad125e71238cb14ba47838f881cabf735d5414f4fcdd6855943621c271c5f013753d439fb124674c79e30d849e9178c780f7c25aded12f053ae41be68289787caf7c3cbb07a4"; - String a_string = "fc1c2d8d"; - - BigInteger A = new BigInteger(A_string, 16); - byte[] Bbytes = new BigInteger(B_string, 16).toByteArray(); - BigInteger a = new BigInteger(a_string, 16); - BigInteger g = ConfigHelper.G; - BigInteger N = new BigInteger(ConfigHelper.NG_1024, 16); - BigInteger k = new BigInteger("bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0", 16); - BigInteger x = new BigInteger("4cb937fd74ee3bb53b79a3174d0c07c14131de9c825897cbca52154e74200602", 16); + salt_str = "cfb9ae3ec5433076"; + username_str = "nostradamus"; + password_str = "$[[//jjiilajfewahug43a89y¿"; + password_str = password_str.replaceAll("\\\\", "\\\\\\\\"); + // Calculate x = H(s | H(U | ':' | password)) + MessageDigest x_digest = MessageDigest.getInstance("SHA-256"); + + // Try to convert the username to a byte[] using UTF-8 + byte[] user = null; + byte[] password_bytes = null; + byte[] colon = {}; + + String encoding = "UTF-8"; + encoding = "ISO-8859-1"; + user = ConfigHelper.trim(username_str.getBytes(encoding)); + colon = ConfigHelper.trim(":".getBytes(encoding)); + password_bytes = ConfigHelper.trim(password_str.getBytes(encoding)); + + // Build the hash + x_digest.update(user); + x_digest.update(colon); + x_digest.update(password_bytes); + byte[] h = x_digest.digest(); + byte[] salt_bytes = ConfigHelper.trim(new BigInteger(salt_str, 16).toByteArray()); + + x_digest.reset(); + x_digest.update(salt_bytes); + x_digest.update(h); + byte[] x_digest_bytes = x_digest.digest(); + assertTrue(new BigInteger(1, x_digest_bytes).toString(16).equalsIgnoreCase(expected_x)); + } + + public void testCalculateS() throws NoSuchAlgorithmException { + String expected_S = "34d71467d0a30c5787e6b4384c7176a724df28f6c1d3b0b7738238621be19080942ca5d4454ab3e5664d42970ea2d42d1188ab246afb1475c481111f30886c79cc99ddd1d711034bc4ac57a0c134fef40470e1ac3386f39abcd1bf9d0cc758a1f38a87b2f7261018cdc6191cd941292c77c320b3c664a9bb1325dd7a2bf62db4"; + + String B_string = "d390da0991b84e20918764aed9bccf36fc70863f08a1d3fa0aecd9610d8c40d1895afaf3aa9b4582fb5bc673037dfc1bf0ca7d3d190a807dec563fe57d596b3551ec8a6461e0621b77fabfaa29234187063e715e2706522c65f35d89f3914a7cdf40ddd240ef3d22b5534469cf6b3b31e158f817dcf5b6b44b0914d4787d027e"; + String A_string = "c6385e56b9cb8987df3c58ffe6c47bfcd9f9d52f02b68048d72135a8522a0919b41683e3c732a0874e0555b8f288fa067842b1c40a56f1a7d910ad125e71238cb14ba47838f881cabf735d5414f4fcdd6855943621c271c5f013753d439fb124674c79e30d849e9178c780f7c25aded12f053ae41be68289787caf7c3cbb07a4"; + String a_string = "fc1c2d8d"; + + BigInteger A = new BigInteger(A_string, 16); + byte[] Bbytes = new BigInteger(B_string, 16).toByteArray(); + BigInteger a = new BigInteger(a_string, 16); + BigInteger g = ConfigHelper.G; + BigInteger N = new BigInteger(ConfigHelper.NG_1024, 16); + BigInteger k = new BigInteger("bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0", 16); + BigInteger x = new BigInteger("4cb937fd74ee3bb53b79a3174d0c07c14131de9c825897cbca52154e74200602", 16); /* GetU */ - MessageDigest u_digest = MessageDigest.getInstance("SHA256"); - u_digest.update(trim(A.toByteArray())); - u_digest.update(trim(Bbytes)); - byte[] ub = new BigInteger(1, u_digest.digest()).toByteArray(); - - BigInteger v = k.multiply(g.modPow(x, N)); // g^x % N - String expected_v = "502f3ffddc78b866330550c2c60ebd68427c1793237d770e6390d1f794abd47b6786fa5025728d1ca4ec24cfc7a89808278330099ad66456a7c9c88be570b928f9825ac2ecdee31792335f7fa5fc9a78b692c487aa400c7d5cc5c1f2a3a74634c4afa0159600bbf22bf6dfb1e0d85061e55ce8df6243758066503bcf51c83848cf7184209731f89a90d888934c75798828859babe73c17009bf827723fc1bcd0"; - String v_string = v.toString(16); - - BigInteger B = new BigInteger(1, Bbytes); - BigInteger u = new BigInteger(1, ub); - String expected_u_string = "2d36f816df24da7b904c904a7e2a2500511df118ced26bda92a63aca792c93b"; - String u_string = u.toString(16); - - BigInteger B_v = B.subtract(v); - BigInteger a_ux = a.add(u.multiply(x)); - byte[] a_ux_byte= a_ux.toByteArray(); - String expected_a_aux_string = "d8d0843a60d471ab46a761b775f8fd28bbbd8affbc704424c79b822ac36b1177925404db910072737df3c5083cf20ebd2f08e1381d80d91e4f6fc99f592203"; - byte[] expected_a_aux_byte = new BigInteger(expected_a_aux_string, 16).toByteArray(); - - BigInteger S = B_v.modPow(a_ux, N); - - byte[] expected_S_bytes = new BigInteger(expected_S, 16).toByteArray(); - byte[] S_bytes = S.toByteArray(); - assertTrue(Arrays.equals(S_bytes, expected_S_bytes)); - assertEquals(S.toString(16), expected_S); - } - - public void testXor() throws Exception { - String expected_xor_string = "928ade491bc87bba9eb578701d44d30ed9080e60e542ba0d3b9c20ded9f592bf"; - byte[] expected_xor = new BigInteger(expected_xor_string, 16).toByteArray(); - - byte[] nbytes = trim(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray()); - byte[] gbytes = trim(ConfigHelper.G.toByteArray()); - - byte[] ndigest = trim(MessageDigest.getInstance("SHA-256").digest(nbytes)); - byte[] gdigest = MessageDigest.getInstance("SHA-256").digest(gbytes); + MessageDigest u_digest = MessageDigest.getInstance("SHA256"); + u_digest.update(trim(A.toByteArray())); + u_digest.update(trim(Bbytes)); + byte[] ub = new BigInteger(1, u_digest.digest()).toByteArray(); + + BigInteger v = k.multiply(g.modPow(x, N)); // g^x % N + String expected_v = "502f3ffddc78b866330550c2c60ebd68427c1793237d770e6390d1f794abd47b6786fa5025728d1ca4ec24cfc7a89808278330099ad66456a7c9c88be570b928f9825ac2ecdee31792335f7fa5fc9a78b692c487aa400c7d5cc5c1f2a3a74634c4afa0159600bbf22bf6dfb1e0d85061e55ce8df6243758066503bcf51c83848cf7184209731f89a90d888934c75798828859babe73c17009bf827723fc1bcd0"; + String v_string = v.toString(16); + + BigInteger B = new BigInteger(1, Bbytes); + BigInteger u = new BigInteger(1, ub); + String expected_u_string = "2d36f816df24da7b904c904a7e2a2500511df118ced26bda92a63aca792c93b"; + String u_string = u.toString(16); + + BigInteger B_v = B.subtract(v); + BigInteger a_ux = a.add(u.multiply(x)); + byte[] a_ux_byte = a_ux.toByteArray(); + String expected_a_aux_string = "d8d0843a60d471ab46a761b775f8fd28bbbd8affbc704424c79b822ac36b1177925404db910072737df3c5083cf20ebd2f08e1381d80d91e4f6fc99f592203"; + byte[] expected_a_aux_byte = new BigInteger(expected_a_aux_string, 16).toByteArray(); + + BigInteger S = B_v.modPow(a_ux, N); + + byte[] expected_S_bytes = new BigInteger(expected_S, 16).toByteArray(); + byte[] S_bytes = S.toByteArray(); + assertTrue(Arrays.equals(S_bytes, expected_S_bytes)); + assertEquals(S.toString(16), expected_S); + } - BigInteger ndigest_bigInteger = new BigInteger(1, ndigest); - String expected_ndigest_string = "494b6a801b379f37c9ee25d5db7cd70ffcfe53d01b7c9e4470eaca46bda24b39"; - String ndigest_string = ndigest_bigInteger.toString(16); - assertEquals(ndigest_string, expected_ndigest_string); - - BigInteger gdigest_bigInteger = new BigInteger(1, gdigest); - String xor_string = ndigest_bigInteger.xor(gdigest_bigInteger).toString(16); - - byte[] xor = new BigInteger(xor_string, 16).toByteArray(); - - assertTrue(Arrays.equals(expected_xor, xor)); - } - - public void testVerify() throws NoSuchAlgorithmException { - byte[] expected_A = trim(new BigInteger("884380f70a62193bbe3589c4e1dbdc4467b6b5a1b4486e4b779023506fc1f885ae26fa4a5d817b3f38a35f3487b147b82d4bd0069faa64fdc845f7494a78251709e212698e42ced44b0f3849adc73f467afcb26983bd13bdc38906b178003373ddd0ac1d38ce8a39ffa3a7795787207a129a784f4b65ce0b302eb1bcf4045883", 16).toByteArray()); - byte[] expected_x = new BigInteger("4cb937fd74ee3bb53b79a3174d0c07c14131de9c825897cbca52154e74200602", 16).toByteArray(); - byte[] expected_M1 = trim(new BigInteger("e6a8efca2c07ef24e0b69be2d4d4a7e74742a4db7a92228218fec0008f7cc94b", 16).toByteArray()); - byte[] expected_M2 = trim(new BigInteger("6402e108415ab4a7cd223ec435570614c8aacc09fcf081ade2dc00275e90ceee", 16).toByteArray()); - String username = "username", - password = "password", - salt = "64c3289d04a6ecad", - a = "8c911355"; - byte[] a_byte = new BigInteger(a, 16).toByteArray(); - LeapSRPSession client = new LeapSRPSession(username, password, a_byte); - - byte[] x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); - assertTrue(Arrays.equals(x, expected_x)); - - byte[] A = client.exponential(); - assertTrue(Arrays.equals(A, expected_A)); + public void testXor() throws Exception { + String expected_xor_string = "928ade491bc87bba9eb578701d44d30ed9080e60e542ba0d3b9c20ded9f592bf"; + byte[] expected_xor = new BigInteger(expected_xor_string, 16).toByteArray(); - String B = "bc745ba25564fc312f44ea09fb663aa6d95867772e412a6a23f1bc24183e54b32f134372c560f4b3fda19ba7a56b0f84fdcdecc22be6fd256639e918e019691c40a39aa5c9631820e42b28da61b8c75b45afae9d77d63ac8f4dda093762be4a890fbd86061dbd7e5e7c03c4dacde769e0f564df00403e449c0535537f1ba7263"; - - byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - assertTrue(Arrays.equals(M1, expected_M1)); - - boolean verified = client.verify(expected_M2); - assertTrue(verified); + byte[] nbytes = trim(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray()); + byte[] gbytes = trim(ConfigHelper.G.toByteArray()); + + byte[] ndigest = trim(MessageDigest.getInstance("SHA-256").digest(nbytes)); + byte[] gdigest = MessageDigest.getInstance("SHA-256").digest(gbytes); + + BigInteger ndigest_bigInteger = new BigInteger(1, ndigest); + String expected_ndigest_string = "494b6a801b379f37c9ee25d5db7cd70ffcfe53d01b7c9e4470eaca46bda24b39"; + String ndigest_string = ndigest_bigInteger.toString(16); + assertEquals(ndigest_string, expected_ndigest_string); + + BigInteger gdigest_bigInteger = new BigInteger(1, gdigest); + String xor_string = ndigest_bigInteger.xor(gdigest_bigInteger).toString(16); + + byte[] xor = new BigInteger(xor_string, 16).toByteArray(); + + assertTrue(Arrays.equals(expected_xor, xor)); + } + + public void testVerify() throws NoSuchAlgorithmException { + byte[] expected_A = trim(new BigInteger("884380f70a62193bbe3589c4e1dbdc4467b6b5a1b4486e4b779023506fc1f885ae26fa4a5d817b3f38a35f3487b147b82d4bd0069faa64fdc845f7494a78251709e212698e42ced44b0f3849adc73f467afcb26983bd13bdc38906b178003373ddd0ac1d38ce8a39ffa3a7795787207a129a784f4b65ce0b302eb1bcf4045883", 16).toByteArray()); + byte[] expected_x = new BigInteger("4cb937fd74ee3bb53b79a3174d0c07c14131de9c825897cbca52154e74200602", 16).toByteArray(); + byte[] expected_M1 = trim(new BigInteger("e6a8efca2c07ef24e0b69be2d4d4a7e74742a4db7a92228218fec0008f7cc94b", 16).toByteArray()); + byte[] expected_M2 = trim(new BigInteger("6402e108415ab4a7cd223ec435570614c8aacc09fcf081ade2dc00275e90ceee", 16).toByteArray()); + String username = "username", + password = "password", + salt = "64c3289d04a6ecad", + a = "8c911355"; + byte[] a_byte = new BigInteger(a, 16).toByteArray(); + LeapSRPSession client = new LeapSRPSession(username, password, a_byte); + + byte[] x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); + assertTrue(Arrays.equals(x, expected_x)); + + byte[] A = client.exponential(); + assertTrue(Arrays.equals(A, expected_A)); + + String B = "bc745ba25564fc312f44ea09fb663aa6d95867772e412a6a23f1bc24183e54b32f134372c560f4b3fda19ba7a56b0f84fdcdecc22be6fd256639e918e019691c40a39aa5c9631820e42b28da61b8c75b45afae9d77d63ac8f4dda093762be4a890fbd86061dbd7e5e7c03c4dacde769e0f564df00403e449c0535537f1ba7263"; + + byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + assertTrue(Arrays.equals(M1, expected_M1)); + + boolean verified = client.verify(expected_M2); + assertTrue(verified); /* Test 2 */ - expected_A = trim(new BigInteger("180a1caf84efe93610a56772edea7b2d20ef3e9f34e578147b5402a898982f33131708233f9ddd2946246703c5db705f0859cca9cfc5b72ad5a05ec0c748545aa083d5b7b1bf06efe6737e9e0fd81b832b5cba983f1b9717041df8114385b93c8c669db06d62c5773b8e8a8f07e98a840a33d04d3448d4bcd2c042387c316750", 16).toByteArray()); - expected_M1 = trim(new BigInteger("a47782f23057a7e06704ea94389589b3c70971a63268acef2aefd74e234dd3c2", 16).toByteArray()); - a = "d89f0e33"; - expected_M2 = trim(new BigInteger("517278a03a0320a52dcb391caf5264d76149d7d9b71ed2b65536233344c550cf", 16).toByteArray()); - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); - A = client.exponential(); - - B = "5f86fe2f7b7455e877e1760db8d3da1fcd4df0d10ec2a40298f87287bdb2f22c0ea54ff9b1f660cc1666459a7e2fd5501970b317490c3dfd3ba2e18f7be7526b72ea4d01e8f064754b935b107ced0892ce86112cbe32282f929907985fcb29f42c5d4dc32adeb29d12a611cac49cca3fefd2227efadc3989c2e72dd64a003141"; - M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); - - verified = client.verify(expected_M2); - assertTrue(verified); + expected_A = trim(new BigInteger("180a1caf84efe93610a56772edea7b2d20ef3e9f34e578147b5402a898982f33131708233f9ddd2946246703c5db705f0859cca9cfc5b72ad5a05ec0c748545aa083d5b7b1bf06efe6737e9e0fd81b832b5cba983f1b9717041df8114385b93c8c669db06d62c5773b8e8a8f07e98a840a33d04d3448d4bcd2c042387c316750", 16).toByteArray()); + expected_M1 = trim(new BigInteger("a47782f23057a7e06704ea94389589b3c70971a63268acef2aefd74e234dd3c2", 16).toByteArray()); + a = "d89f0e33"; + expected_M2 = trim(new BigInteger("517278a03a0320a52dcb391caf5264d76149d7d9b71ed2b65536233344c550cf", 16).toByteArray()); + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); + A = client.exponential(); + + B = "5f86fe2f7b7455e877e1760db8d3da1fcd4df0d10ec2a40298f87287bdb2f22c0ea54ff9b1f660cc1666459a7e2fd5501970b317490c3dfd3ba2e18f7be7526b72ea4d01e8f064754b935b107ced0892ce86112cbe32282f929907985fcb29f42c5d4dc32adeb29d12a611cac49cca3fefd2227efadc3989c2e72dd64a003141"; + M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); + + verified = client.verify(expected_M2); + assertTrue(verified); /* Test 3 */ - expected_A = trim(new BigInteger("a9c556c30bf4c1b1fdc1bc9e672ab4751806acc8581042b3779faaf25f85f47dfc58828742e2d2a06c51acbbb9f3fae0e01f64df0775a269f5ee4a6e71bc37b8a368e04b9053d399bc5b809ffd6ecab775a577804f2a5ed2e829f15e6af13bf0b78b6b108cf591bc9960992904fd1433698a51e0d05ee954cf98cbfe7995621e", 16).toByteArray()); - expected_M1 = trim(new BigInteger("0afca3583c4146990ec7312f9f4b4d9cceebc43a19f96709bf3d0a17b11dcc1e", 16).toByteArray()); - a = "50e662d6"; - expected_M2 = trim(new BigInteger("3bfb91c7d04b6da6381fe3d2648d992cdc6bc67b8ee16d1cfa733f786d492261", 16).toByteArray()); - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); - A = client.exponential(); - - B = "6fe41e8262f4f8bc4ed9f4e1b4802ae3adac9c348e6efc07f16c6f5704b95a1f12325097489372c3936584a37301ebab400a32ac6699f4556da84f076489060527bd50578a317a3ec8b814bf2f4dd9c4adad368610eb638aa81663a205ba26d8f0b9654bf3940357b867cd42725e8532b97a2410a557d291aa55c0b44f249361"; - M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); - - verified = client.verify(expected_M2); - assertTrue(verified); + expected_A = trim(new BigInteger("a9c556c30bf4c1b1fdc1bc9e672ab4751806acc8581042b3779faaf25f85f47dfc58828742e2d2a06c51acbbb9f3fae0e01f64df0775a269f5ee4a6e71bc37b8a368e04b9053d399bc5b809ffd6ecab775a577804f2a5ed2e829f15e6af13bf0b78b6b108cf591bc9960992904fd1433698a51e0d05ee954cf98cbfe7995621e", 16).toByteArray()); + expected_M1 = trim(new BigInteger("0afca3583c4146990ec7312f9f4b4d9cceebc43a19f96709bf3d0a17b11dcc1e", 16).toByteArray()); + a = "50e662d6"; + expected_M2 = trim(new BigInteger("3bfb91c7d04b6da6381fe3d2648d992cdc6bc67b8ee16d1cfa733f786d492261", 16).toByteArray()); + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + x = client.calculatePasswordHash(username, password, new BigInteger(salt, 16).toByteArray()); + A = client.exponential(); + + B = "6fe41e8262f4f8bc4ed9f4e1b4802ae3adac9c348e6efc07f16c6f5704b95a1f12325097489372c3936584a37301ebab400a32ac6699f4556da84f076489060527bd50578a317a3ec8b814bf2f4dd9c4adad368610eb638aa81663a205ba26d8f0b9654bf3940357b867cd42725e8532b97a2410a557d291aa55c0b44f249361"; + M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); + + verified = client.verify(expected_M2); + assertTrue(verified); /* Test 4: user abc, password abcdefghi */ - username = "abc"; - password = "abcdefghi"; - salt = "be26aac449a093e5"; - expected_A = trim(new BigInteger("c4013381bdb2fdd901944b9d823360f367c52635b576b9a50d2db77141d357ed391c3ac5fa452c2bbdc35f96bfed21df61627b40aed8f67f21ebf81e5621333f44049d6c9f6ad36464041438350e1f86000a8e3bfb63d4128c18322d2517b0d3ead63fd504a9c8f2156d46e64268110cec5f3ccab54a21559c7ab3ad67fedf90", 16).toByteArray()); - expected_x = trim(new BigInteger("6325967f1a161efd4e2d6e6fabbfccc32be05139cf82b08fb59c0a0db3f34bcf", 16).toByteArray()); - a = "5d4cde29"; - B = "e5d988752e8f265f01b98a1dcdecc4b685bd512e7cd9507f3c29f206c27dac91e027641eed1765c4603bbd7a9aa7fac300ef67dafe611ba2dbe29a32d83d486296f328d38b44c0c211d01d3fe422aac168b6850c87782338969c54594fc87804d4db34910ad4b5452a81027842ac8d8d8288fd44872e4c719ac8fb971d0a33e1"; - expected_M1 = trim(new BigInteger("e5972ddc53e6190735fc79cd823053a65ffb6041d69480adcba2f6a2dc2f2e86", 16).toByteArray()); - expected_M2 = trim(new BigInteger("8f4552b1021a4de621d8f50f0921c4d20651e702d9d71276f8f6c15b838de018", 16).toByteArray()); - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - - x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); - assertTrue(Arrays.equals(x, expected_x)); - - A = client.exponential(); - assertTrue(Arrays.equals(A, expected_A)); - - M1 = client.response(trim(new BigInteger(salt, 16).toByteArray()), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); - - verified = client.verify(expected_M2); - assertTrue(verified); + username = "abc"; + password = "abcdefghi"; + salt = "be26aac449a093e5"; + expected_A = trim(new BigInteger("c4013381bdb2fdd901944b9d823360f367c52635b576b9a50d2db77141d357ed391c3ac5fa452c2bbdc35f96bfed21df61627b40aed8f67f21ebf81e5621333f44049d6c9f6ad36464041438350e1f86000a8e3bfb63d4128c18322d2517b0d3ead63fd504a9c8f2156d46e64268110cec5f3ccab54a21559c7ab3ad67fedf90", 16).toByteArray()); + expected_x = trim(new BigInteger("6325967f1a161efd4e2d6e6fabbfccc32be05139cf82b08fb59c0a0db3f34bcf", 16).toByteArray()); + a = "5d4cde29"; + B = "e5d988752e8f265f01b98a1dcdecc4b685bd512e7cd9507f3c29f206c27dac91e027641eed1765c4603bbd7a9aa7fac300ef67dafe611ba2dbe29a32d83d486296f328d38b44c0c211d01d3fe422aac168b6850c87782338969c54594fc87804d4db34910ad4b5452a81027842ac8d8d8288fd44872e4c719ac8fb971d0a33e1"; + expected_M1 = trim(new BigInteger("e5972ddc53e6190735fc79cd823053a65ffb6041d69480adcba2f6a2dc2f2e86", 16).toByteArray()); + expected_M2 = trim(new BigInteger("8f4552b1021a4de621d8f50f0921c4d20651e702d9d71276f8f6c15b838de018", 16).toByteArray()); + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + + x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); + assertTrue(Arrays.equals(x, expected_x)); + + A = client.exponential(); + assertTrue(Arrays.equals(A, expected_A)); + + M1 = client.response(trim(new BigInteger(salt, 16).toByteArray()), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); + + verified = client.verify(expected_M2); + assertTrue(verified); /* Test 5: user abc, password abcdefghi */ - username = "abc"; - password = "abcdefghi"; - salt = "be26aac449a093e5"; - expected_A = trim(new BigInteger("d13973fe4e0e13423cd036caf0912e23a1f9b0c23966f5a5897c8ff17c5cbac8bab7f07d9ac4ee47396a7c68e80ce854c84f243148521277900aaa132a7b93b61e54d742d7f36edb4cdef54bc78cca69ac72653a7ae0fc47ec1e9a84024ea9487a61357e28eddc185e4fe01388e64e6b8f688dd74471d56dd244204522e08483", 16).toByteArray()); - expected_x = trim(new BigInteger("6325967f1a161efd4e2d6e6fabbfccc32be05139cf82b08fb59c0a0db3f34bcf", 16).toByteArray()); - a = "fc57e4b1"; - B = "a6701686d9d987a43f06e8497330c8add8febd191a7a975bced0d058eb03ccc6805263349363b2d54ac435b01155dc41c6067287d9b93e3637ab3b7e8bc7d9cf38d9fdbb2ca9ee8ba1946a46cb555cb7dafcc177fcf7a4b0eb1e5db2249949c1fd15e0b7c1b3616f9e2649bdf074ed841efbdc9f29ee8c8bfcedeaed3dc49378"; - expected_M1 = trim(new BigInteger("0b590fde631566d0d3420a898a9b469656e64bfaff165c146b78964eee7920b8", 16).toByteArray()); - expected_M2 = trim(new BigInteger("04cf3ab3b75dbc4b116ca2fec949bf3deca1e360e016d7ab2b8a49904c534a27", 16).toByteArray()); - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - - x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); - assertTrue(Arrays.equals(x, expected_x)); - - A = client.exponential(); - assertTrue(Arrays.equals(A, expected_A)); - - M1 = client.response(trim(new BigInteger(salt, 16).toByteArray()), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); - - verified = client.verify(expected_M2); - assertTrue(verified); + username = "abc"; + password = "abcdefghi"; + salt = "be26aac449a093e5"; + expected_A = trim(new BigInteger("d13973fe4e0e13423cd036caf0912e23a1f9b0c23966f5a5897c8ff17c5cbac8bab7f07d9ac4ee47396a7c68e80ce854c84f243148521277900aaa132a7b93b61e54d742d7f36edb4cdef54bc78cca69ac72653a7ae0fc47ec1e9a84024ea9487a61357e28eddc185e4fe01388e64e6b8f688dd74471d56dd244204522e08483", 16).toByteArray()); + expected_x = trim(new BigInteger("6325967f1a161efd4e2d6e6fabbfccc32be05139cf82b08fb59c0a0db3f34bcf", 16).toByteArray()); + a = "fc57e4b1"; + B = "a6701686d9d987a43f06e8497330c8add8febd191a7a975bced0d058eb03ccc6805263349363b2d54ac435b01155dc41c6067287d9b93e3637ab3b7e8bc7d9cf38d9fdbb2ca9ee8ba1946a46cb555cb7dafcc177fcf7a4b0eb1e5db2249949c1fd15e0b7c1b3616f9e2649bdf074ed841efbdc9f29ee8c8bfcedeaed3dc49378"; + expected_M1 = trim(new BigInteger("0b590fde631566d0d3420a898a9b469656e64bfaff165c146b78964eee7920b8", 16).toByteArray()); + expected_M2 = trim(new BigInteger("04cf3ab3b75dbc4b116ca2fec949bf3deca1e360e016d7ab2b8a49904c534a27", 16).toByteArray()); + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + + x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); + assertTrue(Arrays.equals(x, expected_x)); + + A = client.exponential(); + assertTrue(Arrays.equals(A, expected_A)); + + M1 = client.response(trim(new BigInteger(salt, 16).toByteArray()), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); + + verified = client.verify(expected_M2); + assertTrue(verified); /* Test 6: user and password of real use */ - username = "parmegv"; - password = "wR\"P}x@_,:k$`Y<i7PH9\\\\zubHtn[-4MoL+$(?k>Yd*s T`-n."; - salt = "40c3f47b99ce8dc9"; - expected_A = trim(new BigInteger("490b5de7a287c59cefe267441a186ec24f63210fbf28877305f5896eaec5a7245d304ecb2b09d91066e627d7b2c8bf9e5271d882361a435355d1c2d1ac9d3069877189a01d64b2dd73a569e9e96b9a99767dbc02e04c839b09444f48430b113c1827c20b684ae33f5018051169f5acf4913ebd76a205c6f1aa2cc75747687d56", 16).toByteArray()); - String x_string = "9665839759b4fb9684e7438daecbd6e7129b4ebd3e4a107916e9a64bbbf399c9"; - expected_x = trim(new BigInteger(x_string, 16).toByteArray()); - assertEquals(new BigInteger(1, expected_x).toString(16), x_string); - a = "a72111a2"; - B = "6574ddce3e33c44a77198fa8b3656627e4a24c8786948e79f0c2588febaa485c94b1deb5e420bd3b46f9a34c7862525452ca7a0542c52f939d9f277a013aeceef7353a7741440f6dd2f6c2f1dc07fa5ca003e305c89c876a3035bd04f546b711d44da06a3ba827bc8affbf9ed46de1bfbc670ef9ed7c0bb8cdc588285d13849e"; - expected_M1 = trim(new BigInteger("03bbcf57aeaec89a3a254bb9650a924ea86aa0fdd83fd7274a75b7083f221cf0", 16).toByteArray()); - expected_M2 = trim(new BigInteger("082cf49ad5a34cc5ca571e3d063aec4bd96e7b96a6d951295180631650a84587", 16).toByteArray()); - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - - x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); - assertTrue(Arrays.equals(x, expected_x)); - assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); - - A = client.exponential(); - assertTrue(Arrays.equals(A, expected_A)); - - M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); - - verified = client.verify(expected_M2); - assertTrue(verified); + username = "parmegv"; + password = "wR\"P}x@_,:k$`Y<i7PH9\\\\zubHtn[-4MoL+$(?k>Yd*s T`-n."; + salt = "40c3f47b99ce8dc9"; + expected_A = trim(new BigInteger("490b5de7a287c59cefe267441a186ec24f63210fbf28877305f5896eaec5a7245d304ecb2b09d91066e627d7b2c8bf9e5271d882361a435355d1c2d1ac9d3069877189a01d64b2dd73a569e9e96b9a99767dbc02e04c839b09444f48430b113c1827c20b684ae33f5018051169f5acf4913ebd76a205c6f1aa2cc75747687d56", 16).toByteArray()); + String x_string = "9665839759b4fb9684e7438daecbd6e7129b4ebd3e4a107916e9a64bbbf399c9"; + expected_x = trim(new BigInteger(x_string, 16).toByteArray()); + assertEquals(new BigInteger(1, expected_x).toString(16), x_string); + a = "a72111a2"; + B = "6574ddce3e33c44a77198fa8b3656627e4a24c8786948e79f0c2588febaa485c94b1deb5e420bd3b46f9a34c7862525452ca7a0542c52f939d9f277a013aeceef7353a7741440f6dd2f6c2f1dc07fa5ca003e305c89c876a3035bd04f546b711d44da06a3ba827bc8affbf9ed46de1bfbc670ef9ed7c0bb8cdc588285d13849e"; + expected_M1 = trim(new BigInteger("03bbcf57aeaec89a3a254bb9650a924ea86aa0fdd83fd7274a75b7083f221cf0", 16).toByteArray()); + expected_M2 = trim(new BigInteger("082cf49ad5a34cc5ca571e3d063aec4bd96e7b96a6d951295180631650a84587", 16).toByteArray()); + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + + x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); + assertTrue(Arrays.equals(x, expected_x)); + assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); + + A = client.exponential(); + assertTrue(Arrays.equals(A, expected_A)); + + M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); + + verified = client.verify(expected_M2); + assertTrue(verified); /* Test 7: password with ! */ - username = "parmegvtest3"; - password = "holahola!"; - salt = "1bf48d42b9a7ed32"; - expected_A = trim(new BigInteger("4e2fbe8db5d07f33ff1f4303959b5396dcffc1460b6ce8866fd388415f27fe10f9042986ab8682cdcf9a033e651bca89173688989adad854c91bc1918f98d5c82525fb6f328a8cf74ce1436b23821cba5337aaa20a3e5631e4b957053d542f2b5fc456e888371c9d6b94360b37adb2793eca8db100c24887c459e36d729a98e1", 16).toByteArray()); - x_string = "363d1d62dda07b2d987a9739ddb5ec32fcad9c7322fb64e87937f2da86c45d9f"; - expected_x = trim(new BigInteger(x_string, 16).toByteArray()); - assertEquals(new BigInteger(1, expected_x).toString(16), x_string); - a = "16dd0cf5"; - B = "dd5c9c5e13eb5daa6e7303928b3c826cec520ccef429c0dcb785be34c330d5bb89c99d7d94842b6b5c19cac600f884c50b26989b105f397115df7f3d13c5c7c2f6327cc547fc854ae40f09f1f6a104968bd510243feb104eb559e085fe1d720770be2887a1f424c534a3ab962d82e92458f652328bcf9878f95fdcf463d06193"; - expected_M1 = trim(new BigInteger("a7ffbff753a547b877f8944339b707b3ce1998da27badf253d56bf39f35308a6", 16).toByteArray()); - expected_M2 = trim(new BigInteger("5cc3d7f0077e978c83acdef14a725af01488c1728f0cf32cd7013d24faf5d901", 16).toByteArray()); - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - - x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); - assertTrue(Arrays.equals(x, expected_x)); - assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); - - A = client.exponential(); - assertTrue(Arrays.equals(A, expected_A)); - - M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); - - verified = client.verify(expected_M2); - assertTrue(verified); + username = "parmegvtest3"; + password = "holahola!"; + salt = "1bf48d42b9a7ed32"; + expected_A = trim(new BigInteger("4e2fbe8db5d07f33ff1f4303959b5396dcffc1460b6ce8866fd388415f27fe10f9042986ab8682cdcf9a033e651bca89173688989adad854c91bc1918f98d5c82525fb6f328a8cf74ce1436b23821cba5337aaa20a3e5631e4b957053d542f2b5fc456e888371c9d6b94360b37adb2793eca8db100c24887c459e36d729a98e1", 16).toByteArray()); + x_string = "363d1d62dda07b2d987a9739ddb5ec32fcad9c7322fb64e87937f2da86c45d9f"; + expected_x = trim(new BigInteger(x_string, 16).toByteArray()); + assertEquals(new BigInteger(1, expected_x).toString(16), x_string); + a = "16dd0cf5"; + B = "dd5c9c5e13eb5daa6e7303928b3c826cec520ccef429c0dcb785be34c330d5bb89c99d7d94842b6b5c19cac600f884c50b26989b105f397115df7f3d13c5c7c2f6327cc547fc854ae40f09f1f6a104968bd510243feb104eb559e085fe1d720770be2887a1f424c534a3ab962d82e92458f652328bcf9878f95fdcf463d06193"; + expected_M1 = trim(new BigInteger("a7ffbff753a547b877f8944339b707b3ce1998da27badf253d56bf39f35308a6", 16).toByteArray()); + expected_M2 = trim(new BigInteger("5cc3d7f0077e978c83acdef14a725af01488c1728f0cf32cd7013d24faf5d901", 16).toByteArray()); + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + + x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); + assertTrue(Arrays.equals(x, expected_x)); + assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); + + A = client.exponential(); + assertTrue(Arrays.equals(A, expected_A)); + + M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); + + verified = client.verify(expected_M2); + assertTrue(verified); /* Test 8: username and password *was* failing in localhost testProviderAPI*/ - username = "gg"; - password = "password"; - a = "bc925bfb"; - salt = "ff9ebb44e947cf59"; - expected_A = trim(new BigInteger("8f434633414faeaf035a0dea8c1cb7876bb1f8ee80d6fee8ea43ae60c4f9658550d825c25f1ed5c6a5543358bbcb559b76958c8047a2e7e5fe0072bc1f16401bcfa77b57651ff50dd665c6f28c302b37c98495eff397a56befead2e5ceffaace45f2ec200520258adb66df751e815e464656d869454e360d98cbc70f9c64fd4c", 16).toByteArray()); - x_string = "9cad2eca264380dd0b48e3b405e109c1be0615ee6ec92e7105eff5bc3a309fd9"; - expected_x = trim(new BigInteger(x_string, 16).toByteArray()); - assertEquals(new BigInteger(1, expected_x).toString(16), x_string); - B = "9ca2cd50b4c41047e4aa9e4fac9078ae21175e51e04a23877d6c2044765e39959e9a6a3ede99d08a556c196f51a2be12117681b1ef9d0b0498fb2fa4e88649ab9403e743504e3aaefbce8c5cb474eef8f4724ccd076fd33857de510d8509b67f166d986443bc262d776ec20985f617a7aa86e490290ce5d66332c8b45742a527"; - expected_M1 = trim(new BigInteger("7a2f768791abaeb954eb7f001bb60d91e6f61e959c8fcdefb58de857af9edaac", 16).toByteArray()); - expected_M2 = trim(new BigInteger("d78da7e0a23c9b87a2f09cdee05c510c105b4a8d471b47402c38f4cdfa49fe6d", 16).toByteArray()); - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - - x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); - assertTrue(Arrays.equals(x, expected_x)); - assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); - - A = client.exponential(); - assertTrue(Arrays.equals(A, expected_A)); - - M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); - - verified = client.verify(expected_M2); - assertTrue(verified); + username = "gg"; + password = "password"; + a = "bc925bfb"; + salt = "ff9ebb44e947cf59"; + expected_A = trim(new BigInteger("8f434633414faeaf035a0dea8c1cb7876bb1f8ee80d6fee8ea43ae60c4f9658550d825c25f1ed5c6a5543358bbcb559b76958c8047a2e7e5fe0072bc1f16401bcfa77b57651ff50dd665c6f28c302b37c98495eff397a56befead2e5ceffaace45f2ec200520258adb66df751e815e464656d869454e360d98cbc70f9c64fd4c", 16).toByteArray()); + x_string = "9cad2eca264380dd0b48e3b405e109c1be0615ee6ec92e7105eff5bc3a309fd9"; + expected_x = trim(new BigInteger(x_string, 16).toByteArray()); + assertEquals(new BigInteger(1, expected_x).toString(16), x_string); + B = "9ca2cd50b4c41047e4aa9e4fac9078ae21175e51e04a23877d6c2044765e39959e9a6a3ede99d08a556c196f51a2be12117681b1ef9d0b0498fb2fa4e88649ab9403e743504e3aaefbce8c5cb474eef8f4724ccd076fd33857de510d8509b67f166d986443bc262d776ec20985f617a7aa86e490290ce5d66332c8b45742a527"; + expected_M1 = trim(new BigInteger("7a2f768791abaeb954eb7f001bb60d91e6f61e959c8fcdefb58de857af9edaac", 16).toByteArray()); + expected_M2 = trim(new BigInteger("d78da7e0a23c9b87a2f09cdee05c510c105b4a8d471b47402c38f4cdfa49fe6d", 16).toByteArray()); + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + + x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); + assertTrue(Arrays.equals(x, expected_x)); + assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); + + A = client.exponential(); + assertTrue(Arrays.equals(A, expected_A)); + + M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); + + verified = client.verify(expected_M2); + assertTrue(verified); /* Test 9: username and password *was* failing in localhost testProviderAPI*/ - username = "oo"; - password = "password"; - a = "1322ec50"; - salt = "a93c74934dcadd90"; - expected_A = trim(new BigInteger("c8e9f30a2f67977ee7e61e9ca5af8bd854b6cc98fe01dbe1b1a4cf002c1e2523b7e49f373a600ff85a84867817ec60fec532857812a07f5c6189f6172f133023af75ca4cb98b758bb84620d0aa3cfc74dc69e0507114c0aeab5a75c3ae3f07a919c5729420f03266c26ed41d1846e07de023ec68dd6830e9ebf129cf51abb571", 16).toByteArray()); - x_string = "20470538560c4beb4908e6bfe5b0e00da94223e361302a25c898cbdd3724020"; - expected_x = trim(new BigInteger(x_string, 16).toByteArray()); - assertEquals(new BigInteger(1, expected_x).toString(16), x_string); - B = "24f98ede155212bea8b1d8bacf8153735ee8114faa824c57c84df55f8d6072ab87f5ae885ce1062939dbaa68ca6e63147c1d2dc1f751e8be20d8a6f87287a2a83fcb1dc9b85dd406d438aeee5ccbc873603cb399627e26e6444e94b3d5d26764e866776c8960fe206bd33febeca9f55f6291dd2cb832eab69e5373f548adeefb"; - expected_M1 = trim(new BigInteger("1b35c705e563bd5239cdccc6627aa877c3023286f49b4b7c21341d2949ca2d15", 16).toByteArray()); - expected_M2 = trim(new BigInteger("a382025452bad8a6ccd0f703253fda90e7ea7bd0c2d466a389455080a4bd015d", 16).toByteArray()); - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - - x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); - assertTrue(Arrays.equals(x, expected_x)); - assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); - - A = client.exponential(); - assertTrue(Arrays.equals(A, expected_A)); - - M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); - - verified = client.verify(expected_M2); - assertTrue(verified); + username = "oo"; + password = "password"; + a = "1322ec50"; + salt = "a93c74934dcadd90"; + expected_A = trim(new BigInteger("c8e9f30a2f67977ee7e61e9ca5af8bd854b6cc98fe01dbe1b1a4cf002c1e2523b7e49f373a600ff85a84867817ec60fec532857812a07f5c6189f6172f133023af75ca4cb98b758bb84620d0aa3cfc74dc69e0507114c0aeab5a75c3ae3f07a919c5729420f03266c26ed41d1846e07de023ec68dd6830e9ebf129cf51abb571", 16).toByteArray()); + x_string = "20470538560c4beb4908e6bfe5b0e00da94223e361302a25c898cbdd3724020"; + expected_x = trim(new BigInteger(x_string, 16).toByteArray()); + assertEquals(new BigInteger(1, expected_x).toString(16), x_string); + B = "24f98ede155212bea8b1d8bacf8153735ee8114faa824c57c84df55f8d6072ab87f5ae885ce1062939dbaa68ca6e63147c1d2dc1f751e8be20d8a6f87287a2a83fcb1dc9b85dd406d438aeee5ccbc873603cb399627e26e6444e94b3d5d26764e866776c8960fe206bd33febeca9f55f6291dd2cb832eab69e5373f548adeefb"; + expected_M1 = trim(new BigInteger("1b35c705e563bd5239cdccc6627aa877c3023286f49b4b7c21341d2949ca2d15", 16).toByteArray()); + expected_M2 = trim(new BigInteger("a382025452bad8a6ccd0f703253fda90e7ea7bd0c2d466a389455080a4bd015d", 16).toByteArray()); + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + + x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); + assertTrue(Arrays.equals(x, expected_x)); + assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); + + A = client.exponential(); + assertTrue(Arrays.equals(A, expected_A)); + + M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); + + verified = client.verify(expected_M2); + assertTrue(verified); /* Test 10: derived from test 11, discovered that password bytes should be in ISO-8859-1*/ - username = "nostradamus"; - password = "$[[//jjiilajfewahug43a89y¿"; - a = "800f0819"; - salt = "cfb9ae3ec5433076"; - expected_A = trim(new BigInteger("2ab09ee2fa01058f2f72fd2142b129f2ec26313801052889bcc4af57ee2e4d5b92c90cdfd6ecd660e82c635b2a091ba1b164e5b371c911ce0c4e69686baa120c58e2e0af84b2adc10da6cdfb0b579a1685032c57fd6ed1306d9713a562eddf5c833725042e825fa1abc7017f74760cb53d8c755ffe628c510022c296d1cd3584", 16).toByteArray()); - x_string = "9736a5e386a18f35bb08cac0f7c70bdbe120f2efe019874d0eb23b85b1955858"; - expected_x = trim(new BigInteger(x_string, 16).toByteArray()); - assertEquals(new BigInteger(1, expected_x).toString(16), x_string); - B = "2d19fe17dca1bda01044a0f406547895c32a10df2b0e69676de911273a8685d294763c4d16b3663f722b8980126e2c659efd33ffc6435a9594a2539e726c48e365893b3374670bd1958c13f55c2defa8ea9c0f9ba1345a5dca0e78debba434c8b755353d066d42bc5dfe0403fdcacfe5efd25c685f883ee6766c710b775c50f2"; - expected_M1 = trim(new BigInteger("a33feada1771c6f53e9343f5b9e69d51d4f15043c95fb663b6dd5b1c7af6f66b", 16).toByteArray()); - expected_M2 = trim(new BigInteger("9e99f9adfbfaa7add3626ed6e6aea94c9fa60dab6b8d56ad0cc950548f577d32", 16).toByteArray()); - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - - x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); - assertTrue(Arrays.equals(x, expected_x)); - assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); - - A = client.exponential(); - assertTrue(Arrays.equals(A, expected_A)); - - M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); - - verified = client.verify(expected_M2); - assertTrue(verified); + username = "nostradamus"; + password = "$[[//jjiilajfewahug43a89y¿"; + a = "800f0819"; + salt = "cfb9ae3ec5433076"; + expected_A = trim(new BigInteger("2ab09ee2fa01058f2f72fd2142b129f2ec26313801052889bcc4af57ee2e4d5b92c90cdfd6ecd660e82c635b2a091ba1b164e5b371c911ce0c4e69686baa120c58e2e0af84b2adc10da6cdfb0b579a1685032c57fd6ed1306d9713a562eddf5c833725042e825fa1abc7017f74760cb53d8c755ffe628c510022c296d1cd3584", 16).toByteArray()); + x_string = "9736a5e386a18f35bb08cac0f7c70bdbe120f2efe019874d0eb23b85b1955858"; + expected_x = trim(new BigInteger(x_string, 16).toByteArray()); + assertEquals(new BigInteger(1, expected_x).toString(16), x_string); + B = "2d19fe17dca1bda01044a0f406547895c32a10df2b0e69676de911273a8685d294763c4d16b3663f722b8980126e2c659efd33ffc6435a9594a2539e726c48e365893b3374670bd1958c13f55c2defa8ea9c0f9ba1345a5dca0e78debba434c8b755353d066d42bc5dfe0403fdcacfe5efd25c685f883ee6766c710b775c50f2"; + expected_M1 = trim(new BigInteger("a33feada1771c6f53e9343f5b9e69d51d4f15043c95fb663b6dd5b1c7af6f66b", 16).toByteArray()); + expected_M2 = trim(new BigInteger("9e99f9adfbfaa7add3626ed6e6aea94c9fa60dab6b8d56ad0cc950548f577d32", 16).toByteArray()); + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + + x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); + assertTrue(Arrays.equals(x, expected_x)); + assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); + + A = client.exponential(); + assertTrue(Arrays.equals(A, expected_A)); + + M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); + + verified = client.verify(expected_M2); + assertTrue(verified); /* Test 11: username and password failing in localhost testProviderAPI*/ - username = "nostradamus"; - password = "$[['//\"jjiilajfewahug43a89y¿"; - a = "5bfbc968"; - salt = "1bcae1065951bbf5"; - expected_A = trim(new BigInteger("7a74c254d46dd6010a7090e574817a03f32ba13f98ed3c695d96f09c9d334e591771541400e68b6d27a19e734baccf3965ca79c0294ffbf553716b41fbca627c7cd3ea4a0d1c640c22411881696f59ad7ed8ce6ef7010e43f57fb3858aa4c3479dd41e4073afadb6a516c41f649b8cf30dea6366efa711c5106c83ea71b00da4", 16).toByteArray()); - x_string = "9834210874c883db35785ee6648079e13d22450c472d6469192ea775ff50c646"; - expected_x = trim(new BigInteger(x_string, 16).toByteArray()); - assertEquals(new BigInteger(1, expected_x).toString(16), x_string); - B = "285b00c034da5676dd8938ce6a7b717968fef2e5f479ecca6d95828a6ce809dd37893752c956245b5d13315987c50e57cc68aa4f770ff9ce977ddfd65052f278b90545286cf32b3d18307140514e0fe2269fc0437fb16104358f6fa127dc97281a017582759644862d736f48025f2b35cb1662067c11f2fcf0753e2f72c9e028"; - expected_M1 = trim(new BigInteger("fedbaff9d9a19efc4eea949b045297a6a3121cf371e2acdda85a2a1ca61c929d", 16).toByteArray()); - expected_M2 = trim(new BigInteger("ffccafa0febc1771a428082b30b7ce409856de4581c7d7d986f5b80015aba0d3", 16).toByteArray()); - - a_byte = new BigInteger(a, 16).toByteArray(); - client = new LeapSRPSession(username, password, a_byte); - - x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); - assertTrue(Arrays.equals(x, expected_x)); - assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); - - A = client.exponential(); - assertTrue(Arrays.equals(A, expected_A)); - - M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); - - assertTrue(Arrays.equals(M1, expected_M1)); - - verified = client.verify(expected_M2); - assertTrue(verified); - } - - public void testSignUpMath() throws NoSuchAlgorithmException{ - String username = "parmegvtest29"; - String password = "holahola2"; - byte[] salt = new BigInteger("67e8348d1500d26c", 16).toByteArray(); - - LeapSRPSession client = new LeapSRPSession(username, password); - - String expected_v = "12bea84e588ffa2f8fc5ae47cb5e751a8f2d9e8125268ad9ab483eff83f98cb08484350eb478bee582b8b72363ff8e7b12e9f332e86f7a0bd77689927c609d275471c6ad2cff8b1e7bbfc3664169c3b7bccb0b974154c1f1656b64274568015ca1b849c9d9890ae4437ed686341b432340809b81c30727ed2aadea8bdec6d101"; - - assertEquals(expected_v, client.calculateV(username, password, salt).toString(16)); + username = "nostradamus"; + password = "$[['//\"jjiilajfewahug43a89y¿"; + a = "5bfbc968"; + salt = "1bcae1065951bbf5"; + expected_A = trim(new BigInteger("7a74c254d46dd6010a7090e574817a03f32ba13f98ed3c695d96f09c9d334e591771541400e68b6d27a19e734baccf3965ca79c0294ffbf553716b41fbca627c7cd3ea4a0d1c640c22411881696f59ad7ed8ce6ef7010e43f57fb3858aa4c3479dd41e4073afadb6a516c41f649b8cf30dea6366efa711c5106c83ea71b00da4", 16).toByteArray()); + x_string = "9834210874c883db35785ee6648079e13d22450c472d6469192ea775ff50c646"; + expected_x = trim(new BigInteger(x_string, 16).toByteArray()); + assertEquals(new BigInteger(1, expected_x).toString(16), x_string); + B = "285b00c034da5676dd8938ce6a7b717968fef2e5f479ecca6d95828a6ce809dd37893752c956245b5d13315987c50e57cc68aa4f770ff9ce977ddfd65052f278b90545286cf32b3d18307140514e0fe2269fc0437fb16104358f6fa127dc97281a017582759644862d736f48025f2b35cb1662067c11f2fcf0753e2f72c9e028"; + expected_M1 = trim(new BigInteger("fedbaff9d9a19efc4eea949b045297a6a3121cf371e2acdda85a2a1ca61c929d", 16).toByteArray()); + expected_M2 = trim(new BigInteger("ffccafa0febc1771a428082b30b7ce409856de4581c7d7d986f5b80015aba0d3", 16).toByteArray()); + + a_byte = new BigInteger(a, 16).toByteArray(); + client = new LeapSRPSession(username, password, a_byte); + + x = client.calculatePasswordHash(username, password, trim(new BigInteger(salt, 16).toByteArray())); + assertTrue(Arrays.equals(x, expected_x)); + assertEquals(new BigInteger(1, expected_x).toString(16), new BigInteger(1, x).toString(16)); + + A = client.exponential(); + assertTrue(Arrays.equals(A, expected_A)); + + M1 = client.response(new BigInteger(salt, 16).toByteArray(), new BigInteger(B, 16).toByteArray()); + + assertTrue(Arrays.equals(M1, expected_M1)); + + verified = client.verify(expected_M2); + assertTrue(verified); + } + + public void testSignUpMath() throws NoSuchAlgorithmException { + String username = "parmegvtest29"; + String password = "holahola2"; + byte[] salt = new BigInteger("67e8348d1500d26c", 16).toByteArray(); + + LeapSRPSession client = new LeapSRPSession(username, password); + + String expected_v = "12bea84e588ffa2f8fc5ae47cb5e751a8f2d9e8125268ad9ab483eff83f98cb08484350eb478bee582b8b72363ff8e7b12e9f332e86f7a0bd77689927c609d275471c6ad2cff8b1e7bbfc3664169c3b7bccb0b974154c1f1656b64274568015ca1b849c9d9890ae4437ed686341b432340809b81c30727ed2aadea8bdec6d101"; + + assertEquals(expected_v, client.calculateV(username, password, salt).toString(16)); + } + + public 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; } - - public 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; - } } diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testVpnCertificateValidator.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testVpnCertificateValidator.java index cd1d6c3b..672607be 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/testVpnCertificateValidator.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testVpnCertificateValidator.java @@ -56,11 +56,11 @@ public class testVpnCertificateValidator extends InstrumentationTestCase { } private void setTime(int year, int month, int day) { - shellCommand("adb shell chmod 666 /dev/alarm"); - Calendar c = Calendar.getInstance(); - c.set(year, month, day, 12, 00, 00); - SystemClock.setCurrentTimeMillis(c.getTimeInMillis()); - shellCommand("adb shell chmod 664 /dev/alarm"); + shellCommand("adb shell chmod 666 /dev/alarm"); + Calendar c = Calendar.getInstance(); + c.set(year, month, day, 12, 00, 00); + SystemClock.setCurrentTimeMillis(c.getTimeInMillis()); + shellCommand("adb shell chmod 664 /dev/alarm"); } private int shellCommand(String command) { diff --git a/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java b/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java index 27984147..59d77d83 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributors - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -28,39 +28,43 @@ import java.net.*; import java.util.*; import butterknife.*; -import org.jetbrains.annotations.NotNull; + +import org.jetbrains.annotations.*; import org.json.*; -import javax.inject.Inject; +import javax.inject.*; import se.leap.bitmaskclient.DownloadFailedDialog.DownloadFailedDialogInterface; import se.leap.bitmaskclient.NewProviderDialog.NewProviderDialogInterface; import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver; import se.leap.bitmaskclient.ProviderDetailFragment.ProviderDetailFragmentInterface; import se.leap.bitmaskclient.ProviderListContent.ProviderItem; -import se.leap.bitmaskclient.eip.Constants; +import se.leap.bitmaskclient.eip.*; /** * Activity that builds and shows the list of known available providers. - * + * <p/> * It also allows the user to enter custom providers with a button. - * - * @author parmegv * + * @author parmegv */ public class ConfigurationWizard extends Activity -implements NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver { + implements NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver { - @InjectView(R.id.progressbar_configuration_wizard) ProgressBar mProgressBar; - @InjectView(R.id.progressbar_description) TextView progressbar_description; + @InjectView(R.id.progressbar_configuration_wizard) + ProgressBar mProgressBar; + @InjectView(R.id.progressbar_description) + TextView progressbar_description; - @InjectView(R.id.provider_list) ListView provider_list_view; - @Inject ProviderListAdapter adapter; + @InjectView(R.id.provider_list) + ListView provider_list_view; + @Inject + ProviderListAdapter adapter; private ProviderManager provider_manager; private Intent mConfigState = new Intent(); private Provider selected_provider; - + final public static String TAG = ConfigurationWizard.class.getSimpleName(); final protected static String PROVIDER_SET = "PROVIDER SET"; @@ -68,7 +72,7 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download final private static String PROGRESSBAR_TEXT = TAG + "PROGRESSBAR_TEXT"; final private static String PROGRESSBAR_NUMBER = TAG + "PROGRESSBAR_NUMBER"; - + public ProviderAPIResultReceiver providerAPI_result_receiver; private ProviderAPIBroadcastReceiver_Update providerAPI_broadcast_receiver_update; @@ -86,16 +90,15 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download adapter = new ProviderListAdapter(getLayoutInflater(), providerRendererBuilder, provider_manager); provider_list_view.setAdapter(adapter); } - + @Override protected void onSaveInstanceState(@NotNull Bundle outState) { - if(mProgressBar != null) + if (mProgressBar != null) outState.putInt(PROGRESSBAR_NUMBER, mProgressBar.getProgress()); - if(progressbar_description != null) + if (progressbar_description != null) outState.putString(PROGRESSBAR_TEXT, progressbar_description.getText().toString()); - if(selected_provider != null) + if (selected_provider != null) outState.putParcelable(Provider.KEY, selected_provider); - outState.putParcelable(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); super.onSaveInstanceState(outState); } @@ -108,12 +111,11 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download setUpInitialUI(); - initProviderList(); + initProviderList(); - if(savedInstanceState != null) + if (savedInstanceState != null) restoreState(savedInstanceState); - else - setUpProviderAPIResultReceiver(); + setUpProviderAPIResultReceiver(); } private void restoreState(Bundle savedInstanceState) { @@ -121,14 +123,20 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download provider_name = savedInstanceState.getString(Provider.NAME, ""); selected_provider = savedInstanceState.getParcelable(Provider.KEY); progress = savedInstanceState.getInt(PROGRESSBAR_NUMBER, -1); - providerAPI_result_receiver = savedInstanceState.getParcelable(ProviderAPI.RECEIVER_KEY); - providerAPI_result_receiver.setReceiver(this); + + if (fragment_manager.findFragmentByTag(ProviderDetailFragment.TAG) == null && setting_up_provider) { + if (selected_provider != null) + onItemSelectedUi(selected_provider); + if (progress > 0) + mProgressBar.setProgress(progress); + } + } @Override protected void onPostResume() { super.onPostResume(); - if(!progressbar_text.isEmpty() && !provider_name.isEmpty() && progress != -1) { + if (!progressbar_text.isEmpty() && !provider_name.isEmpty() && progress != -1) { progressbar_description.setText(progressbar_text); mProgressBar.setProgress(progress); @@ -144,81 +152,81 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download hideProgressBar(); } - - private void hideProgressBar() { - mProgressBar.setVisibility(ProgressBar.INVISIBLE); - progressbar_description.setVisibility(TextView.INVISIBLE); + + private void hideProgressBar() { + mProgressBar.setVisibility(ProgressBar.INVISIBLE); + progressbar_description.setVisibility(TextView.INVISIBLE); } @Override protected void onDestroy() { - super.onDestroy(); - if(providerAPI_broadcast_receiver_update != null) - unregisterReceiver(providerAPI_broadcast_receiver_update); + super.onDestroy(); + if (providerAPI_broadcast_receiver_update != null) + unregisterReceiver(providerAPI_broadcast_receiver_update); } private void setUpProviderAPIResultReceiver() { providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); providerAPI_result_receiver.setReceiver(this); - providerAPI_broadcast_receiver_update = new ProviderAPIBroadcastReceiver_Update(); - - IntentFilter update_intent_filter = new IntentFilter(ProviderAPI.UPDATE_PROGRESSBAR); - update_intent_filter.addCategory(Intent.CATEGORY_DEFAULT); - registerReceiver(providerAPI_broadcast_receiver_update, update_intent_filter); + providerAPI_broadcast_receiver_update = new ProviderAPIBroadcastReceiver_Update(); + + IntentFilter update_intent_filter = new IntentFilter(ProviderAPI.UPDATE_PROGRESSBAR); + update_intent_filter.addCategory(Intent.CATEGORY_DEFAULT); + registerReceiver(providerAPI_broadcast_receiver_update, update_intent_filter); } @Override public void onReceiveResult(int resultCode, Bundle resultData) { - if(resultCode == ProviderAPI.PROVIDER_OK) { - mConfigState.setAction(PROVIDER_SET); + if (resultCode == ProviderAPI.PROVIDER_OK) { + mConfigState.setAction(PROVIDER_SET); try { String provider_json_string = preferences.getString(Provider.KEY, ""); - if(!provider_json_string.isEmpty()) - selected_provider.define(new JSONObject(provider_json_string)); + if (!provider_json_string.isEmpty()) + selected_provider.define(new JSONObject(provider_json_string)); } catch (JSONException e) { e.printStackTrace(); } - if (preferences.getBoolean(Constants.ALLOWED_ANON, false)){ - mConfigState.putExtra(SERVICES_RETRIEVED, true); - - downloadVpnCertificate(); - } else { - mProgressBar.incrementProgressBy(1); - hideProgressBar(); - - setResult(RESULT_OK); - - showProviderDetails(); - } - } else if(resultCode == ProviderAPI.PROVIDER_NOK) { - hideProgressBar(); - preferences.edit().remove(Provider.KEY).apply(); - setting_up_provider = false; - - setResult(RESULT_CANCELED, mConfigState); - - String reason_to_fail = resultData.getString(ProviderAPI.ERRORS); - showDownloadFailedDialog(reason_to_fail); - } - else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { - mProgressBar.incrementProgressBy(1); - hideProgressBar(); - - showProviderDetails(); - - setResult(RESULT_OK); - } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { - hideProgressBar(); - - setResult(RESULT_CANCELED, mConfigState); - } else if(resultCode == AboutActivity.VIEWED) { - // Do nothing, right now - // I need this for CW to wait for the About activity to end before going back to Dashboard. - } - } - + if (preferences.getBoolean(Constants.ALLOWED_ANON, false)) { + mConfigState.putExtra(SERVICES_RETRIEVED, true); + + downloadVpnCertificate(); + } else { + mProgressBar.incrementProgressBy(1); + hideProgressBar(); + + setResult(RESULT_OK); + + showProviderDetails(); + } + } else if (resultCode == ProviderAPI.PROVIDER_NOK) { + hideProgressBar(); + preferences.edit().remove(Provider.KEY).apply(); + setting_up_provider = false; + + setResult(RESULT_CANCELED, mConfigState); + + String reason_to_fail = resultData.getString(ProviderAPI.ERRORS); + showDownloadFailedDialog(reason_to_fail); + } else if (resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { + mProgressBar.incrementProgressBy(1); + hideProgressBar(); + + showProviderDetails(); + + setResult(RESULT_OK); + } else if (resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { + hideProgressBar(); + cancelSettingUpProvider(); + Toast.makeText(getApplicationContext(), R.string.provider_problem, Toast.LENGTH_LONG).show(); + setResult(RESULT_CANCELED, mConfigState); + } else if (resultCode == AboutActivity.VIEWED) { + // Do nothing, right now + // I need this for CW to wait for the About activity to end before going back to Dashboard. + } + } + @OnItemClick(R.id.provider_list) void onItemSelected(int position) { //TODO Code 2 pane view @@ -229,7 +237,7 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download private void onItemSelectedLogic(Provider selected_provider) { boolean danger_on = true; - if(preferences.contains(ProviderItem.DANGER_ON)) + if (preferences.contains(ProviderItem.DANGER_ON)) danger_on = preferences.getBoolean(ProviderItem.DANGER_ON, false); setUpProvider(selected_provider.mainUrl(), danger_on); } @@ -238,24 +246,24 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download startProgressBar(); adapter.hideAllBut(adapter.indexOf(provider)); } - + @Override public void onBackPressed() { - if(setting_up_provider) { - stopSettingUpProvider(); - } else { - askDashboardToQuitApp(); - super.onBackPressed(); - } - } - + if (setting_up_provider) { + stopSettingUpProvider(); + } else { + askDashboardToQuitApp(); + super.onBackPressed(); + } + } + private void stopSettingUpProvider() { - ProviderAPI.stop(); - mProgressBar.setVisibility(ProgressBar.GONE); - mProgressBar.setProgress(0); - progressbar_description.setVisibility(TextView.GONE); + ProviderAPI.stop(); + mProgressBar.setVisibility(ProgressBar.GONE); + mProgressBar.setProgress(0); + progressbar_description.setVisibility(TextView.GONE); - cancelSettingUpProvider(); + cancelSettingUpProvider(); } public void cancelSettingUpProvider() { @@ -263,11 +271,11 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download setting_up_provider = false; preferences.edit().remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit(); } - + private void askDashboardToQuitApp() { - Intent ask_quit = new Intent(); - ask_quit.putExtra(Dashboard.ACTION_QUIT, Dashboard.ACTION_QUIT); - setResult(RESULT_CANCELED, ask_quit); + Intent ask_quit = new Intent(); + ask_quit.putExtra(Dashboard.ACTION_QUIT, Dashboard.ACTION_QUIT); + setResult(RESULT_CANCELED, ask_quit); } private void startProgressBar() { @@ -276,87 +284,89 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download mProgressBar.setProgress(0); mProgressBar.setMax(3); - int measured_height = listItemHeight(); - mProgressBar.setTranslationY(measured_height); - progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight()); + int measured_height = listItemHeight(); + mProgressBar.setTranslationY(measured_height); + progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight()); } - + private int listItemHeight() { View listItem = adapter.getView(0, null, provider_list_view); listItem.setLayoutParams(new RelativeLayout.LayoutParams( - RelativeLayout.LayoutParams.WRAP_CONTENT, - RelativeLayout.LayoutParams.WRAP_CONTENT)); + RelativeLayout.LayoutParams.WRAP_CONTENT, + RelativeLayout.LayoutParams.WRAP_CONTENT)); WindowManager wm = (WindowManager) getApplicationContext() - .getSystemService(Context.WINDOW_SERVICE); + .getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); int screenWidth = display.getWidth(); // deprecated int listViewWidth = screenWidth - 10 - 10; int widthSpec = View.MeasureSpec.makeMeasureSpec(listViewWidth, - View.MeasureSpec.AT_MOST); + View.MeasureSpec.AT_MOST); listItem.measure(widthSpec, 0); return listItem.getMeasuredHeight(); } - + /** * Asks ProviderAPI to download an anonymous (anon) VPN certificate. */ private void downloadVpnCertificate() { - Intent provider_API_command = new Intent(this, ProviderAPI.class); + Intent provider_API_command = new Intent(this, ProviderAPI.class); - provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE); - provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - startService(provider_API_command); + provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE); + provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); + startService(provider_API_command); } - + /** * Open the new provider dialog */ public void addAndSelectNewProvider() { - FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); new NewProviderDialog().show(fragment_transaction, NewProviderDialog.TAG); } - + /** * Open the new provider dialog with data */ public void addAndSelectNewProvider(String main_url, boolean danger_on) { - FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); - - DialogFragment newFragment = new NewProviderDialog(); - Bundle data = new Bundle(); - data.putString(Provider.MAIN_URL, main_url); - data.putBoolean(ProviderItem.DANGER_ON, danger_on); - newFragment.setArguments(data); - newFragment.show(fragment_transaction, NewProviderDialog.TAG); - } - + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); + + DialogFragment newFragment = new NewProviderDialog(); + Bundle data = new Bundle(); + data.putString(Provider.MAIN_URL, main_url); + data.putBoolean(ProviderItem.DANGER_ON, danger_on); + newFragment.setArguments(data); + newFragment.show(fragment_transaction, NewProviderDialog.TAG); + } + /** - * Once selected a provider, this fragment offers the user to log in, - * use it anonymously (if possible) + * Once selected a provider, this fragment offers the user to log in, + * use it anonymously (if possible) * or cancel his/her election pressing the back button. + * * @param reason_to_fail */ public void showDownloadFailedDialog(String reason_to_fail) { - FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(DownloadFailedDialog.TAG); - - DialogFragment newFragment = DownloadFailedDialog.newInstance(reason_to_fail); - newFragment.show(fragment_transaction, DownloadFailedDialog.TAG); + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(DownloadFailedDialog.TAG); + + DialogFragment newFragment = DownloadFailedDialog.newInstance(reason_to_fail); + newFragment.show(fragment_transaction, DownloadFailedDialog.TAG); } /** - * Once selected a provider, this fragment offers the user to log in, - * use it anonymously (if possible) + * Once selected a provider, this fragment offers the user to log in, + * use it anonymously (if possible) * or cancel his/her election pressing the back button. */ private void showProviderDetails() { - if(setting_up_provider) { - FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(ProviderDetailFragment.TAG); + if (setting_up_provider) { + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(ProviderDetailFragment.TAG); - DialogFragment newFragment = ProviderDetailFragment.newInstance(); - newFragment.show(fragment_transaction, ProviderDetailFragment.TAG); - } + DialogFragment newFragment = ProviderDetailFragment.newInstance(); + newFragment.show(fragment_transaction, ProviderDetailFragment.TAG); + setting_up_provider = false; + } } public void showAndSelectProvider(String provider_main_url, boolean danger_on) { @@ -371,92 +381,94 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download } private void autoSelectProvider(Provider provider, boolean danger_on) { - preferences.edit().putBoolean(ProviderItem.DANGER_ON, danger_on).apply(); + preferences.edit().putBoolean(ProviderItem.DANGER_ON, danger_on).apply(); selected_provider = provider; onItemSelectedLogic(selected_provider); onItemSelectedUi(selected_provider); } - + /** * Asks ProviderAPI to download a new provider.json file + * * @param provider_main_url - * @param danger_on tells if HTTPS client should bypass certificate errors + * @param danger_on tells if HTTPS client should bypass certificate errors */ public void setUpProvider(URL provider_main_url, boolean danger_on) { - Intent provider_API_command = new Intent(this, ProviderAPI.class); - Bundle parameters = new Bundle(); - parameters.putString(Provider.MAIN_URL, provider_main_url.toString()); - parameters.putBoolean(ProviderItem.DANGER_ON, danger_on); + Intent provider_API_command = new Intent(this, ProviderAPI.class); + Bundle parameters = new Bundle(); + parameters.putString(Provider.MAIN_URL, provider_main_url.toString()); + parameters.putBoolean(ProviderItem.DANGER_ON, danger_on); - provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER); - provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); - provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); + provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER); + provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); + provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - startService(provider_API_command); - setting_up_provider = true; + startService(provider_API_command); + setting_up_provider = true; } public void retrySetUpProvider() { - cancelSettingUpProvider(); - if(!ProviderAPI.caCertDownloaded()) { - addAndSelectNewProvider(ProviderAPI.lastProviderMainUrl(), ProviderAPI.lastDangerOn()); - } else { - Intent provider_API_command = new Intent(this, ProviderAPI.class); + cancelSettingUpProvider(); + if (!ProviderAPI.caCertDownloaded()) { + addAndSelectNewProvider(ProviderAPI.lastProviderMainUrl(), ProviderAPI.lastDangerOn()); + } else { + Intent provider_API_command = new Intent(this, ProviderAPI.class); - provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER); - provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); + provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER); + provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - startService(provider_API_command); - } + startService(provider_API_command); + } } + @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu); - return true; + getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu); + return true; } - + @Override - public boolean onOptionsItemSelected(MenuItem item){ - switch (item.getItemId()){ - case R.id.about_leap: - startActivityForResult(new Intent(this, AboutActivity.class), 0); - return true; - case R.id.new_provider: - addAndSelectNewProvider(); - return true; - default: - return super.onOptionsItemSelected(item); - } + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.about_leap: + startActivityForResult(new Intent(this, AboutActivity.class), 0); + return true; + case R.id.new_provider: + addAndSelectNewProvider(); + return true; + default: + return super.onOptionsItemSelected(item); + } } public void showAllProviders() { adapter.showAllProviders(); } - + @Override public void login() { - Intent ask_login = new Intent(); - ask_login.putExtra(SessionDialog.TAG, SessionDialog.TAG); + Intent ask_login = new Intent(); + ask_login.putExtra(SessionDialog.TAG, SessionDialog.TAG); ask_login.putExtra(Provider.KEY, selected_provider); - setResult(RESULT_OK, ask_login); - setting_up_provider = false; - finish(); + setResult(RESULT_OK, ask_login); + setting_up_provider = false; + finish(); } @Override public void use_anonymously() { Intent pass_provider = new Intent(); pass_provider.putExtra(Provider.KEY, selected_provider); - setResult(RESULT_OK, pass_provider); - setting_up_provider = false; - finish(); + setResult(RESULT_OK, pass_provider); + setting_up_provider = false; + finish(); } public class ProviderAPIBroadcastReceiver_Update extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - int update = intent.getIntExtra(ProviderAPI.CURRENT_PROGRESS, 0); - mProgressBar.setProgress(update); - } + @Override + public void onReceive(Context context, Intent intent) { + int update = intent.getIntExtra(ProviderAPI.CURRENT_PROGRESS, 0); + mProgressBar.setProgress(update); + } } } diff --git a/app/src/debug/java/se/leap/bitmaskclient/NewProviderDialog.java b/app/src/debug/java/se/leap/bitmaskclient/NewProviderDialog.java index 8fe1c3eb..c1426708 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/NewProviderDialog.java +++ b/app/src/debug/java/se/leap/bitmaskclient/NewProviderDialog.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -14,28 +14,21 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - package se.leap.bitmaskclient; +package se.leap.bitmaskclient; -import butterknife.ButterKnife; -import butterknife.InjectView; +import butterknife.*; import se.leap.bitmaskclient.ProviderListContent.ProviderItem; -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.CheckBox; -import android.widget.EditText; -import android.widget.Toast; + +import android.app.*; +import android.content.*; +import android.os.*; +import android.view.*; +import android.widget.*; /** * Implements the new custom provider dialog. - * - * @author parmegv * + * @author parmegv */ public class NewProviderDialog extends DialogFragment { @@ -46,17 +39,17 @@ public class NewProviderDialog extends DialogFragment { @InjectView(R.id.danger_checkbox) CheckBox danger_checkbox; - public interface NewProviderDialogInterface { + public interface NewProviderDialogInterface { public void showAndSelectProvider(String url_provider, boolean danger_on); } - NewProviderDialogInterface interface_with_ConfigurationWizard; - + NewProviderDialogInterface interface_with_ConfigurationWizard; + @Override public void onAttach(Activity activity) { super.onAttach(activity); try { - interface_with_ConfigurationWizard = (NewProviderDialogInterface) activity; + interface_with_ConfigurationWizard = (NewProviderDialogInterface) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement NoticeDialogListener"); @@ -64,59 +57,61 @@ public class NewProviderDialog extends DialogFragment { } @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - LayoutInflater inflater = getActivity().getLayoutInflater(); - View view = inflater.inflate(R.layout.new_provider_dialog, null); + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + LayoutInflater inflater = getActivity().getLayoutInflater(); + View view = inflater.inflate(R.layout.new_provider_dialog, null); ButterKnife.inject(this, view); Bundle arguments = getArguments(); - if(arguments != null) { + if (arguments != null) { url_input_field.setText(arguments.getString(Provider.MAIN_URL, "")); danger_checkbox.setActivated(arguments.getBoolean(ProviderItem.DANGER_ON, false)); } - - builder.setView(view) - .setMessage(R.string.introduce_new_provider) - .setPositiveButton(R.string.save, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - saveProvider(); - } - }) - .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(); - } + + builder.setView(view) + .setMessage(R.string.introduce_new_provider) + .setPositiveButton(R.string.save, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + saveProvider(); + } + }) + .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(); + } private void saveProvider() { String entered_url = url_input_field.getText().toString().trim(); - if(!entered_url.startsWith("https://")) { - if (entered_url.startsWith("http://")){ + if (!entered_url.startsWith("https://")) { + if (entered_url.startsWith("http://")) { entered_url = entered_url.substring("http://".length()); } entered_url = "https://".concat(entered_url); } boolean danger_on = danger_checkbox.isChecked(); - if(validURL(entered_url)) { + if (validURL(entered_url)) { interface_with_ConfigurationWizard.showAndSelectProvider(entered_url, danger_on); Toast.makeText(getActivity().getApplicationContext(), R.string.valid_url_entered, Toast.LENGTH_LONG).show(); } else { url_input_field.setText(""); danger_checkbox.setChecked(false); - Toast.makeText(getActivity().getApplicationContext(), R.string.not_valid_url_entered, Toast.LENGTH_LONG).show();; + Toast.makeText(getActivity().getApplicationContext(), R.string.not_valid_url_entered, Toast.LENGTH_LONG).show(); + ; } } /** * 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(); - return android.util.Patterns.WEB_URL.matcher(entered_url).matches(); - } + boolean validURL(String entered_url) { + //return !entered_url.isEmpty() && entered_url.matches("http[s]?://.+") && !entered_url.replaceFirst("http[s]?://", "").isEmpty(); + return android.util.Patterns.WEB_URL.matcher(entered_url).matches(); + } } diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java index 0650f0ad..0b24e1c9 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,19 +16,22 @@ */ package se.leap.bitmaskclient; -import android.app.IntentService; +import android.app.*; import android.content.*; import android.os.*; import android.util.*; + import java.io.*; -import java.math.BigInteger; +import java.math.*; import java.net.*; import java.security.*; import java.security.cert.*; -import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.*; import java.util.*; + import javax.net.ssl.*; -import org.apache.http.client.ClientProtocolException; + +import org.apache.http.client.*; import org.json.*; import se.leap.bitmaskclient.ProviderListContent.ProviderItem; @@ -36,94 +39,89 @@ import se.leap.bitmaskclient.eip.*; /** * Implements HTTP api methods used to manage communications with the provider server. - * + * <p/> * It's an IntentService because it downloads data from the Internet, so it operates in the background. - * + * * @author parmegv * @author MeanderingCode - * */ public class ProviderAPI extends IntentService { - + final public static String - TAG = ProviderAPI.class.getSimpleName(), - SET_UP_PROVIDER = "setUpProvider", - DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON", - SRP_REGISTER = "srpRegister", - SRP_AUTH = "srpAuth", - LOG_OUT = "logOut", - DOWNLOAD_CERTIFICATE = "downloadUserAuthedCertificate", - PARAMETERS = "parameters", - RESULT_KEY = "result", - RECEIVER_KEY = "receiver", - ERRORS = "errors", - UPDATE_PROGRESSBAR = "update_progressbar", - CURRENT_PROGRESS = "current_progress", - DOWNLOAD_EIP_SERVICE = TAG + ".DOWNLOAD_EIP_SERVICE" - ; + TAG = ProviderAPI.class.getSimpleName(), + SET_UP_PROVIDER = "setUpProvider", + DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON", + SIGN_UP = "srpRegister", + LOG_IN = "srpAuth", + LOG_OUT = "logOut", + DOWNLOAD_CERTIFICATE = "downloadUserAuthedCertificate", + PARAMETERS = "parameters", + RESULT_KEY = "result", + RECEIVER_KEY = "receiver", + ERRORS = "errors", + UPDATE_PROGRESSBAR = "update_progressbar", + CURRENT_PROGRESS = "current_progress", + DOWNLOAD_EIP_SERVICE = TAG + ".DOWNLOAD_EIP_SERVICE"; final public static int SUCCESSFUL_LOGIN = 3, - FAILED_LOGIN = 4, - SUCCESSFUL_SIGNUP = 5, - FAILED_SIGNUP = 6, - SUCCESSFUL_LOGOUT = 7, - LOGOUT_FAILED = 8, - CORRECTLY_DOWNLOADED_CERTIFICATE = 9, - INCORRECTLY_DOWNLOADED_CERTIFICATE = 10, - PROVIDER_OK = 11, - PROVIDER_NOK = 12, - CORRECTLY_DOWNLOADED_EIP_SERVICE = 13, - INCORRECTLY_DOWNLOADED_EIP_SERVICE= 14 - ; - - private static boolean - CA_CERT_DOWNLOADED = false, - PROVIDER_JSON_DOWNLOADED = false, - EIP_SERVICE_JSON_DOWNLOADED = false - ; - + FAILED_LOGIN = 4, + SUCCESSFUL_SIGNUP = 5, + FAILED_SIGNUP = 6, + SUCCESSFUL_LOGOUT = 7, + LOGOUT_FAILED = 8, + CORRECTLY_DOWNLOADED_CERTIFICATE = 9, + INCORRECTLY_DOWNLOADED_CERTIFICATE = 10, + PROVIDER_OK = 11, + PROVIDER_NOK = 12, + CORRECTLY_DOWNLOADED_EIP_SERVICE = 13, + INCORRECTLY_DOWNLOADED_EIP_SERVICE = 14; + + private static boolean + CA_CERT_DOWNLOADED = false, + PROVIDER_JSON_DOWNLOADED = false, + EIP_SERVICE_JSON_DOWNLOADED = false; + private static String last_provider_main_url; private static boolean last_danger_on = false; private static boolean go_ahead = true; private static SharedPreferences preferences; private static String provider_api_url; - + public static void stop() { - go_ahead = false; + go_ahead = false; + } + + public ProviderAPI() { + super(TAG); } - public ProviderAPI() { - super("ProviderAPI"); - Log.v("ClassName", "Provider API"); - } - @Override public void onCreate() { - super.onCreate(); - - preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); - CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER) ); - } - - public static String lastProviderMainUrl() { - return last_provider_main_url; - } - + super.onCreate(); + + preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); + CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER)); + } + + public static String lastProviderMainUrl() { + return last_provider_main_url; + } + public static boolean lastDangerOn() { - return last_danger_on; - } - - private String formatErrorMessage(final int toast_string_id) { - return "{ \"" + ERRORS + "\" : \""+getResources().getString(toast_string_id)+"\" }"; - } - - @Override - protected void onHandleIntent(Intent command) { - final ResultReceiver receiver = command.getParcelableExtra(RECEIVER_KEY); - String action = command.getAction(); - Bundle parameters = command.getBundleExtra(PARAMETERS); - if(provider_api_url == null) { + return last_danger_on; + } + + private String formatErrorMessage(final int toast_string_id) { + return "{ \"" + ERRORS + "\" : \"" + getResources().getString(toast_string_id) + "\" }"; + } + + @Override + protected void onHandleIntent(Intent command) { + final ResultReceiver receiver = command.getParcelableExtra(RECEIVER_KEY); + String action = command.getAction(); + Bundle parameters = command.getBundleExtra(PARAMETERS); + if (provider_api_url == null) { try { JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "no provider")); provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); @@ -132,706 +130,724 @@ public class ProviderAPI extends IntentService { go_ahead = false; } } - - if(action.equalsIgnoreCase(SET_UP_PROVIDER)) { - Bundle result = setUpProvider(parameters); - if(go_ahead) { - if(result.getBoolean(RESULT_KEY)) { - receiver.send(PROVIDER_OK, result); - } else { - receiver.send(PROVIDER_NOK, result); - } - } - } else if (action.equalsIgnoreCase(SRP_REGISTER)) { - Bundle session_id_bundle = tryToRegister(parameters); - if(session_id_bundle.getBoolean(RESULT_KEY)) { - receiver.send(SUCCESSFUL_SIGNUP, session_id_bundle); - } else { - receiver.send(FAILED_SIGNUP, session_id_bundle); - } - } else if (action.equalsIgnoreCase(SRP_AUTH)) { - Bundle session_id_bundle = tryToAuthenticate(parameters); - if(session_id_bundle.getBoolean(RESULT_KEY)) { - receiver.send(SUCCESSFUL_LOGIN, session_id_bundle); - } else { - receiver.send(FAILED_LOGIN, session_id_bundle); - } - } else if (action.equalsIgnoreCase(LOG_OUT)) { - if(logOut()) { - receiver.send(SUCCESSFUL_LOGOUT, Bundle.EMPTY); - } else { - receiver.send(LOGOUT_FAILED, Bundle.EMPTY); - } - } else if (action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)) { - if(updateVpnCertificate()) { - receiver.send(CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); - } else { - receiver.send(INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); - } - } else if(action.equalsIgnoreCase(DOWNLOAD_EIP_SERVICE)) { + + if (action.equalsIgnoreCase(SET_UP_PROVIDER)) { + Bundle result = setUpProvider(parameters); + if (go_ahead) { + if (result.getBoolean(RESULT_KEY)) { + receiver.send(PROVIDER_OK, result); + } else { + receiver.send(PROVIDER_NOK, result); + } + } + } else if (action.equalsIgnoreCase(SIGN_UP)) { + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.SIGNING_UP); + Bundle result = tryToRegister(parameters); + if (result.getBoolean(RESULT_KEY)) { + receiver.send(SUCCESSFUL_SIGNUP, result); + } else { + receiver.send(FAILED_SIGNUP, result); + } + } else if (action.equalsIgnoreCase(LOG_IN)) { + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.LOGGING_IN); + Bundle result = tryToAuthenticate(parameters); + if (result.getBoolean(RESULT_KEY)) { + receiver.send(SUCCESSFUL_LOGIN, result); + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.LOGGED_IN); + } else { + receiver.send(FAILED_LOGIN, result); + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.NOT_LOGGED_IN); + } + } else if (action.equalsIgnoreCase(LOG_OUT)) { + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.LOGGING_OUT); + if (logOut()) { + receiver.send(SUCCESSFUL_LOGOUT, Bundle.EMPTY); + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.LOGGED_OUT); + } else { + receiver.send(LOGOUT_FAILED, Bundle.EMPTY); + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.DIDNT_LOG_OUT); + } + } else if (action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)) { + if (updateVpnCertificate()) { + receiver.send(CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); + } else { + receiver.send(INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); + } + } else if (action.equalsIgnoreCase(DOWNLOAD_EIP_SERVICE)) { Bundle result = getAndSetEipServiceJson(); - if(result.getBoolean(RESULT_KEY)) { + if (result.getBoolean(RESULT_KEY)) { receiver.send(CORRECTLY_DOWNLOADED_EIP_SERVICE, result); } else { receiver.send(INCORRECTLY_DOWNLOADED_EIP_SERVICE, result); } } - } + } private Bundle tryToRegister(Bundle task) { - Bundle result = new Bundle(); - int progress = 0; - - String username = task.getString(SessionDialog.USERNAME); - String password = task.getString(SessionDialog.PASSWORD); - - if(validUserLoginData(username, password)) { - result = register(username, password); - broadcastProgress(progress++); - } else { - if(!wellFormedPassword(password)) { - result.putBoolean(RESULT_KEY, false); - result.putString(SessionDialog.USERNAME, username); - result.putBoolean(SessionDialog.PASSWORD_INVALID_LENGTH, true); - } - if(!validUsername(username)) { - result.putBoolean(RESULT_KEY, false); - result.putBoolean(SessionDialog.USERNAME_MISSING, true); - } - } - - return result; - } - - private Bundle register(String username, String password) { - LeapSRPSession client = new LeapSRPSession(username, password); - byte[] salt = client.calculateNewSalt(); - - BigInteger password_verifier = client.calculateV(username, password, salt); - - JSONObject api_result = sendNewUserDataToSRPServer(provider_api_url, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16)); - - Bundle result = new Bundle(); - if(api_result.has(ERRORS)) - result = authFailedNotification(api_result, username); - else { - result.putString(SessionDialog.USERNAME, username); - result.putString(SessionDialog.PASSWORD, password); - result.putBoolean(RESULT_KEY, true); - } - - return result; - } - /** - * Starts the authentication process using SRP protocol. - * - * @param task containing: username, password and api url. - * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if authentication was successful. - */ - private Bundle tryToAuthenticate(Bundle task) { - Bundle result = new Bundle(); - int progress = 0; - - String username = task.getString(SessionDialog.USERNAME); - String password = task.getString(SessionDialog.PASSWORD); - if(validUserLoginData(username, password)) { - result = authenticate(username, password); - broadcastProgress(progress++); - } else { - if(!wellFormedPassword(password)) { - result.putBoolean(RESULT_KEY, false); - result.putString(SessionDialog.USERNAME, username); - result.putBoolean(SessionDialog.PASSWORD_INVALID_LENGTH, true); - } - if(!validUsername(username)) { - result.putBoolean(RESULT_KEY, false); - result.putBoolean(SessionDialog.USERNAME_MISSING, true); - } - } - - return result; - } + Bundle result = new Bundle(); + int progress = 0; + + String username = User.userName(); + String password = task.getString(SessionDialog.PASSWORD); + + if (validUserLoginData(username, password)) { + result = register(username, password); + broadcastProgress(progress++); + } else { + if (!wellFormedPassword(password)) { + result.putBoolean(RESULT_KEY, false); + result.putString(SessionDialog.USERNAME, username); + result.putBoolean(SessionDialog.ERRORS.PASSWORD_INVALID_LENGTH.toString(), true); + } + if (!validUsername(username)) { + result.putBoolean(RESULT_KEY, false); + result.putBoolean(SessionDialog.ERRORS.USERNAME_MISSING.toString(), true); + } + } + + return result; + } + + private Bundle register(String username, String password) { + LeapSRPSession client = new LeapSRPSession(username, password); + byte[] salt = client.calculateNewSalt(); + + BigInteger password_verifier = client.calculateV(username, password, salt); + + JSONObject api_result = sendNewUserDataToSRPServer(provider_api_url, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16)); + + Bundle result = new Bundle(); + if (api_result.has(ERRORS)) + result = authFailedNotification(api_result, username); + else { + result.putString(SessionDialog.USERNAME, username); + result.putString(SessionDialog.PASSWORD, password); + result.putBoolean(RESULT_KEY, true); + } + + return result; + } + + /** + * Starts the authentication process using SRP protocol. + * + * @param task containing: username, password and api url. + * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if authentication was successful. + */ + private Bundle tryToAuthenticate(Bundle task) { + Bundle result = new Bundle(); + int progress = 0; + + String username = User.userName(); + String password = task.getString(SessionDialog.PASSWORD); + if (validUserLoginData(username, password)) { + result = authenticate(username, password); + broadcastProgress(progress++); + } else { + if (!wellFormedPassword(password)) { + result.putBoolean(RESULT_KEY, false); + result.putString(SessionDialog.USERNAME, username); + result.putBoolean(SessionDialog.ERRORS.PASSWORD_INVALID_LENGTH.toString(), true); + } + if (!validUsername(username)) { + result.putBoolean(RESULT_KEY, false); + result.putBoolean(SessionDialog.ERRORS.USERNAME_MISSING.toString(), true); + } + } + + return result; + } private Bundle authenticate(String username, String password) { - Bundle result = new Bundle(); - - LeapSRPSession client = new LeapSRPSession(username, password); - byte[] A = client.exponential(); - - JSONObject step_result = sendAToSRPServer(provider_api_url, username, new BigInteger(1, A).toString(16)); - try { - String salt = step_result.getString(LeapSRPSession.SALT); - byte[] Bbytes = new BigInteger(step_result.getString("B"), 16).toByteArray(); - byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); - if(M1 != null) { - step_result = sendM1ToSRPServer(provider_api_url, username, M1); - setTokenIfAvailable(step_result); - byte[] M2 = new BigInteger(step_result.getString(LeapSRPSession.M2), 16).toByteArray(); - if(client.verify(M2)) { - result.putBoolean(RESULT_KEY, true); - } else { - authFailedNotification(step_result, username); - } - } else { - result.putBoolean(RESULT_KEY, false); - result.putString(SessionDialog.USERNAME, username); - result.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message)); - } - } catch (JSONException e) { - result = authFailedNotification(step_result, username); - e.printStackTrace(); - } - - return result; + Bundle result = new Bundle(); + + LeapSRPSession client = new LeapSRPSession(username, password); + byte[] A = client.exponential(); + + JSONObject step_result = sendAToSRPServer(provider_api_url, username, new BigInteger(1, A).toString(16)); + try { + String salt = step_result.getString(LeapSRPSession.SALT); + byte[] Bbytes = new BigInteger(step_result.getString("B"), 16).toByteArray(); + byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); + if (M1 != null) { + step_result = sendM1ToSRPServer(provider_api_url, username, M1); + setTokenIfAvailable(step_result); + byte[] M2 = new BigInteger(step_result.getString(LeapSRPSession.M2), 16).toByteArray(); + if (client.verify(M2)) { + result.putBoolean(RESULT_KEY, true); + } else { + authFailedNotification(step_result, username); + } + } else { + result.putBoolean(RESULT_KEY, false); + result.putString(SessionDialog.USERNAME, username); + result.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message)); + } + } catch (JSONException e) { + result = authFailedNotification(step_result, username); + e.printStackTrace(); + } + + return result; } private boolean setTokenIfAvailable(JSONObject authentication_step_result) { - try { - LeapSRPSession.setToken(authentication_step_result.getString(LeapSRPSession.TOKEN)); - CookieHandler.setDefault(null); // we don't need cookies anymore - } catch(JSONException e) { // - return false; - } - return true; - } - + try { + LeapSRPSession.setToken(authentication_step_result.getString(LeapSRPSession.TOKEN)); + CookieHandler.setDefault(null); // we don't need cookies anymore + } catch (JSONException e) { // + return false; + } + return true; + } + private Bundle authFailedNotification(JSONObject result, String username) { - Bundle user_notification_bundle = new Bundle(); - try{ - JSONObject error_message = result.getJSONObject(ERRORS); - String error_type = error_message.keys().next().toString(); - String message = error_message.get(error_type).toString(); - user_notification_bundle.putString(getResources().getString(R.string.user_message), message); - } catch(JSONException e) {} - - if(!username.isEmpty()) - user_notification_bundle.putString(SessionDialog.USERNAME, username); - user_notification_bundle.putBoolean(RESULT_KEY, false); - - return user_notification_bundle; - } - - /** - * Sets up an intent with the progress value passed as a parameter - * and sends it as a broadcast. - * @param progress - */ - private void broadcastProgress(int progress) { - Intent intentUpdate = new Intent(); - intentUpdate.setAction(UPDATE_PROGRESSBAR); - intentUpdate.addCategory(Intent.CATEGORY_DEFAULT); - intentUpdate.putExtra(CURRENT_PROGRESS, progress); - sendBroadcast(intentUpdate); - } - - /** - * Validates parameters entered by the user to log in - * @param username - * @param password - * @return true if both parameters are present and the entered password length is greater or equal to eight (8). - */ - private boolean validUserLoginData(String username, String password) { - return validUsername(username) && wellFormedPassword(password); - } + Bundle user_notification_bundle = new Bundle(); + try { + JSONObject error_message = result.getJSONObject(ERRORS); + String error_type = error_message.keys().next().toString(); + String message = error_message.get(error_type).toString(); + user_notification_bundle.putString(getResources().getString(R.string.user_message), message); + } catch (JSONException e) { + } + + if (!username.isEmpty()) + user_notification_bundle.putString(SessionDialog.USERNAME, username); + user_notification_bundle.putBoolean(RESULT_KEY, false); + + return user_notification_bundle; + } + + /** + * Sets up an intent with the progress value passed as a parameter + * and sends it as a broadcast. + * + * @param progress + */ + private void broadcastProgress(int progress) { + Intent intentUpdate = new Intent(); + intentUpdate.setAction(UPDATE_PROGRESSBAR); + intentUpdate.addCategory(Intent.CATEGORY_DEFAULT); + intentUpdate.putExtra(CURRENT_PROGRESS, progress); + sendBroadcast(intentUpdate); + } + + /** + * Validates parameters entered by the user to log in + * + * @param username + * @param password + * @return true if both parameters are present and the entered password length is greater or equal to eight (8). + */ + private boolean validUserLoginData(String username, String password) { + return validUsername(username) && wellFormedPassword(password); + } private boolean validUsername(String username) { return username != null && !username.isEmpty(); } - /** - * Validates a password - * @param password - * @return true if the entered password length is greater or equal to eight (8). - */ - private boolean wellFormedPassword(String password) { - return password != null && password.length() >= 8; - } - - /** - * 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 - */ - private JSONObject sendAToSRPServer(String server_url, String username, String clientA) { - Map<String, String> parameters = new HashMap<String, String>(); - parameters.put("login", username); - parameters.put("A", clientA); - return sendToServer(server_url + "/sessions.json", "POST", parameters); - } - - /** - * 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 - */ - private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) { - Map<String, String> parameters = new HashMap<String, String>(); - parameters.put("client_auth", new BigInteger(1, ConfigHelper.trim(m1)).toString(16)); - - return sendToServer(server_url + "/sessions/" + username +".json", "PUT", parameters); - } - - /** - * Sends an HTTP POST request to the api server to register a new user. - * @param server_url - * @param username - * @param salt - * @param password_verifier - * @return response from authentication server - */ + /** + * Validates a password + * + * @param password + * @return true if the entered password length is greater or equal to eight (8). + */ + private boolean wellFormedPassword(String password) { + return password != null && password.length() >= 8; + } + + /** + * 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 + */ + private JSONObject sendAToSRPServer(String server_url, String username, String clientA) { + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put("login", username); + parameters.put("A", clientA); + return sendToServer(server_url + "/sessions.json", "POST", parameters); + } + + /** + * 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 + */ + private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) { + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put("client_auth", new BigInteger(1, ConfigHelper.trim(m1)).toString(16)); + + return sendToServer(server_url + "/sessions/" + username + ".json", "PUT", parameters); + } + + /** + * Sends an HTTP POST request to the api server to register a new user. + * + * @param server_url + * @param username + * @param salt + * @param password_verifier + * @return response from authentication server + */ private JSONObject sendNewUserDataToSRPServer(String server_url, String username, String salt, String password_verifier) { - Map<String, String> parameters = new HashMap<String, String>(); - parameters.put("user[login]", username); - parameters.put("user[password_salt]", salt); - parameters.put("user[password_verifier]", password_verifier); - Log.d(TAG, server_url); - Log.d(TAG, parameters.toString()); - return sendToServer(server_url + "/users.json", "POST", parameters); - } - - /** - * Executes an HTTP request expecting a JSON response. - * @param url - * @param request_method - * @param parameters - * @return response from authentication server - */ - private JSONObject sendToServer(String url, String request_method, Map<String, String> parameters) { - JSONObject json_response; - HttpsURLConnection urlConnection = null; - try { - InputStream is = null; - urlConnection = (HttpsURLConnection)new URL(url).openConnection(); - urlConnection.setRequestMethod(request_method); - urlConnection.setChunkedStreamingMode(0); - urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); - - DataOutputStream writer = new DataOutputStream(urlConnection.getOutputStream()); - writer.writeBytes(formatHttpParameters(parameters)); - writer.close(); - - is = urlConnection.getInputStream(); - String plain_response = new Scanner(is).useDelimiter("\\A").next(); - json_response = new JSONObject(plain_response); - } catch (ClientProtocolException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (IOException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (JSONException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (KeyManagementException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (KeyStoreException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (CertificateException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } - - return json_response; - } + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put("user[login]", username); + parameters.put("user[password_salt]", salt); + parameters.put("user[password_verifier]", password_verifier); + return sendToServer(server_url + "/users.json", "POST", parameters); + } + + /** + * Executes an HTTP request expecting a JSON response. + * + * @param url + * @param request_method + * @param parameters + * @return response from authentication server + */ + private JSONObject sendToServer(String url, String request_method, Map<String, String> parameters) { + JSONObject json_response; + HttpsURLConnection urlConnection = null; + try { + InputStream is = null; + urlConnection = (HttpsURLConnection) new URL(url).openConnection(); + urlConnection.setRequestMethod(request_method); + urlConnection.setChunkedStreamingMode(0); + urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); + + DataOutputStream writer = new DataOutputStream(urlConnection.getOutputStream()); + writer.writeBytes(formatHttpParameters(parameters)); + writer.close(); + + is = urlConnection.getInputStream(); + String plain_response = new Scanner(is).useDelimiter("\\A").next(); + json_response = new JSONObject(plain_response); + } catch (ClientProtocolException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (IOException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (JSONException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (KeyManagementException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (KeyStoreException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (CertificateException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } + + return json_response; + } private JSONObject getErrorMessage(HttpsURLConnection urlConnection) { - JSONObject error_message = new JSONObject(); - if(urlConnection != null) { - InputStream error_stream = urlConnection.getErrorStream(); - if(error_stream != null) { - String error_response = new Scanner(error_stream).useDelimiter("\\A").next(); - Log.d("Error", error_response); - try { - error_message = new JSONObject(error_response); - } catch (JSONException e) { - Log.d(TAG, e.getMessage()); - e.printStackTrace(); - } - urlConnection.disconnect(); - } - } - return error_message; - } - - private String formatHttpParameters(Map<String, String> parameters) throws UnsupportedEncodingException { - StringBuilder result = new StringBuilder(); - boolean first = true; - - Iterator<String> parameter_iterator = parameters.keySet().iterator(); - while(parameter_iterator.hasNext()) { - if(first) - first = false; - else - result.append("&&"); - - String key = parameter_iterator.next(); - String value = parameters.get(key); - - result.append(URLEncoder.encode(key, "UTF-8")); - result.append("="); - result.append(URLEncoder.encode(value, "UTF-8")); - } - - return result.toString(); - } - - - - - /** - * Downloads a provider.json from a given URL, adding a new provider using the given name. - * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider, the provider name and its provider.json url. - * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if the update was successful. - */ - private Bundle setUpProvider(Bundle task) { - int progress = 0; - Bundle current_download = new Bundle(); - - if(task != null && task.containsKey(ProviderItem.DANGER_ON) && task.containsKey(Provider.MAIN_URL)) { - last_danger_on = task.getBoolean(ProviderItem.DANGER_ON); - last_provider_main_url = task.getString(Provider.MAIN_URL); - CA_CERT_DOWNLOADED = PROVIDER_JSON_DOWNLOADED = EIP_SERVICE_JSON_DOWNLOADED = false; + JSONObject error_message = new JSONObject(); + if (urlConnection != null) { + InputStream error_stream = urlConnection.getErrorStream(); + if (error_stream != null) { + String error_response = new Scanner(error_stream).useDelimiter("\\A").next(); + try { + error_message = new JSONObject(error_response); + } catch (JSONException e) { + e.printStackTrace(); + } + urlConnection.disconnect(); + } + } + return error_message; + } + + private String formatHttpParameters(Map<String, String> parameters) throws UnsupportedEncodingException { + StringBuilder result = new StringBuilder(); + boolean first = true; + + Iterator<String> parameter_iterator = parameters.keySet().iterator(); + while (parameter_iterator.hasNext()) { + if (first) + first = false; + else + result.append("&&"); + + String key = parameter_iterator.next(); + String value = parameters.get(key); + + result.append(URLEncoder.encode(key, "UTF-8")); + result.append("="); + result.append(URLEncoder.encode(value, "UTF-8")); + } + + return result.toString(); + } + + + /** + * Downloads a provider.json from a given URL, adding a new provider using the given name. + * + * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider, the provider name and its provider.json url. + * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if the update was successful. + */ + private Bundle setUpProvider(Bundle task) { + int progress = 0; + Bundle current_download = new Bundle(); + + if (task != null && task.containsKey(ProviderItem.DANGER_ON) && task.containsKey(Provider.MAIN_URL)) { + last_danger_on = task.getBoolean(ProviderItem.DANGER_ON); + last_provider_main_url = task.getString(Provider.MAIN_URL); + CA_CERT_DOWNLOADED = PROVIDER_JSON_DOWNLOADED = EIP_SERVICE_JSON_DOWNLOADED = false; go_ahead = true; - } - - if(!PROVIDER_JSON_DOWNLOADED) - current_download = getAndSetProviderJson(last_provider_main_url, last_danger_on); - if(PROVIDER_JSON_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) { - broadcastProgress(progress++); - PROVIDER_JSON_DOWNLOADED = true; - current_download = downloadCACert(last_danger_on); - - if(CA_CERT_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) { - broadcastProgress(progress++); - CA_CERT_DOWNLOADED = true; - current_download = getAndSetEipServiceJson(); - if(current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY)) { - broadcastProgress(progress++); - EIP_SERVICE_JSON_DOWNLOADED = true; - } - } - } - - return current_download; - } - - private Bundle downloadCACert(boolean danger_on) { - Bundle result = new Bundle(); - try { - JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - String ca_cert_url = provider_json.getString(Provider.CA_CERT_URI); - String cert_string = downloadWithCommercialCA(ca_cert_url, danger_on); - - if(validCertificate(cert_string) && go_ahead) { - preferences.edit().putString(Provider.CA_CERT, cert_string).commit(); - result.putBoolean(RESULT_KEY, true); - } else { - String reason_to_fail = pickErrorMessage(cert_string); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } - } catch (JSONException e) { - String reason_to_fail = formatErrorMessage(R.string.malformed_url); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } - - return result; - } - - public static boolean caCertDownloaded() { - return CA_CERT_DOWNLOADED; - } + } + + if (!PROVIDER_JSON_DOWNLOADED) + current_download = getAndSetProviderJson(last_provider_main_url, last_danger_on); + if (PROVIDER_JSON_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) { + broadcastProgress(progress++); + PROVIDER_JSON_DOWNLOADED = true; + current_download = downloadCACert(last_danger_on); + + if (CA_CERT_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) { + broadcastProgress(progress++); + CA_CERT_DOWNLOADED = true; + current_download = getAndSetEipServiceJson(); + if (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY)) { + broadcastProgress(progress++); + EIP_SERVICE_JSON_DOWNLOADED = true; + } + } + } + + return current_download; + } + + private Bundle downloadCACert(boolean danger_on) { + Bundle result = new Bundle(); + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + String ca_cert_url = provider_json.getString(Provider.CA_CERT_URI); + String cert_string = downloadWithCommercialCA(ca_cert_url, danger_on); + + if (validCertificate(cert_string) && go_ahead) { + preferences.edit().putString(Provider.CA_CERT, cert_string).commit(); + result.putBoolean(RESULT_KEY, true); + } else { + String reason_to_fail = pickErrorMessage(cert_string); + result.putString(ERRORS, reason_to_fail); + result.putBoolean(RESULT_KEY, false); + } + } catch (JSONException e) { + String reason_to_fail = formatErrorMessage(R.string.malformed_url); + result.putString(ERRORS, reason_to_fail); + result.putBoolean(RESULT_KEY, false); + } + + return result; + } + + public static boolean caCertDownloaded() { + return CA_CERT_DOWNLOADED; + } private boolean validCertificate(String cert_string) { - boolean result = false; - if(!ConfigHelper.checkErroneousDownload(cert_string)) { - X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string); - try { - if(certificate != null) { - JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - String fingerprint = provider_json.getString(Provider.CA_CERT_FINGERPRINT); - String encoding = fingerprint.split(":")[0]; - String expected_fingerprint = fingerprint.split(":")[1]; - String real_fingerprint = base64toHex(Base64.encodeToString( - MessageDigest.getInstance(encoding).digest(certificate.getEncoded()), - Base64.DEFAULT)); - - result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim()); - } else - result = false; - } catch (JSONException e) { - result = false; - } catch (NoSuchAlgorithmException e) { - result = false; - } catch (CertificateEncodingException e) { - result = false; - } - } - - return result; + boolean result = false; + if (!ConfigHelper.checkErroneousDownload(cert_string)) { + X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string); + try { + if (certificate != null) { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + String fingerprint = provider_json.getString(Provider.CA_CERT_FINGERPRINT); + String encoding = fingerprint.split(":")[0]; + String expected_fingerprint = fingerprint.split(":")[1]; + String real_fingerprint = base64toHex(Base64.encodeToString( + MessageDigest.getInstance(encoding).digest(certificate.getEncoded()), + Base64.DEFAULT)); + + result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim()); + } else + result = false; + } catch (JSONException e) { + result = false; + } catch (NoSuchAlgorithmException e) { + result = false; + } catch (CertificateEncodingException e) { + result = false; + } + } + + return result; } private String base64toHex(String base64_input) { - byte[] byteArray = Base64.decode(base64_input, Base64.DEFAULT); - int readBytes = byteArray.length; - StringBuffer hexData = new StringBuffer(); - int onebyte; - for (int i=0; i < readBytes; i++) { - onebyte = ((0x000000ff & byteArray[i]) | 0xffffff00); - hexData.append(Integer.toHexString(onebyte).substring(6)); - } - return hexData.toString(); - } - private Bundle getAndSetProviderJson(String provider_main_url, boolean danger_on) { - Bundle result = new Bundle(); - - if(go_ahead) { - String provider_dot_json_string = downloadWithCommercialCA(provider_main_url + "/provider.json", danger_on); - - try { - JSONObject provider_json = new JSONObject(provider_dot_json_string); - provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); - String name = provider_json.getString(Provider.NAME); - //TODO setProviderName(name); - - preferences.edit().putString(Provider.KEY, provider_json.toString()).commit(); - preferences.edit().putBoolean(Constants.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_ANON)).commit(); - preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_REGISTERED)).commit(); - - result.putBoolean(RESULT_KEY, true); - } catch (JSONException e) { - //TODO Error message should be contained in that provider_dot_json_string - String reason_to_fail = pickErrorMessage(provider_dot_json_string); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } - } - return result; - } - - private Bundle getAndSetEipServiceJson() { - Bundle result = new Bundle(); - String eip_service_json_string = ""; - if(go_ahead) { - try { - JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - String eip_service_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH; - eip_service_json_string = downloadWithProviderCA(eip_service_url, true); - JSONObject eip_service_json = new JSONObject(eip_service_json_string); - eip_service_json.getInt(Provider.API_RETURN_SERIAL); - - preferences.edit().putString(Constants.KEY, eip_service_json.toString()).commit(); - - result.putBoolean(RESULT_KEY, true); - } catch (JSONException e) { - String reason_to_fail = pickErrorMessage(eip_service_json_string); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } - } - return result; - } - - /** - * Interprets the error message as a JSON object and extract the "errors" keyword pair. - * If the error message is not a JSON object, then it is returned untouched. - * @param string_json_error_message - * @return final error message - */ - private String pickErrorMessage(String string_json_error_message) { - String error_message = ""; - try { - JSONObject json_error_message = new JSONObject(string_json_error_message); - error_message = json_error_message.getString(ERRORS); - } catch (JSONException e) { - // TODO Auto-generated catch block - error_message = string_json_error_message; - } - - return error_message; - } - - /** - * Tries to download the contents of the provided url using commercially validated CA certificate from chosen provider. - * - * 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 downloadWithCommercialCA(String string_url, boolean danger_on) { - - String json_file_content = ""; - - URL provider_url = null; - int seconds_of_timeout = 1; - try { - provider_url = new URL(string_url); - URLConnection url_connection = provider_url.openConnection(); - url_connection.setConnectTimeout(seconds_of_timeout*1000); - if(!LeapSRPSession.getToken().isEmpty()) - url_connection.addRequestProperty(LeapSRPSession.AUTHORIZATION_HEADER, "Token token = " + LeapSRPSession.getToken()); - json_file_content = new Scanner(url_connection.getInputStream()).useDelimiter("\\A").next(); - } catch (MalformedURLException e) { - json_file_content = formatErrorMessage(R.string.malformed_url); - } catch(SocketTimeoutException e) { - json_file_content = formatErrorMessage(R.string.server_unreachable_message); - } catch (SSLHandshakeException e) { - if(provider_url != null) { - json_file_content = downloadWithProviderCA(string_url, danger_on); - } else { - json_file_content = formatErrorMessage(R.string.certificate_error); - } - } catch(ConnectException e) { - json_file_content = formatErrorMessage(R.string.service_is_down_error); - } catch (FileNotFoundException e) { - json_file_content = formatErrorMessage(R.string.malformed_url); - } catch (Exception e) { - if(provider_url != null && danger_on) { - json_file_content = downloadWithProviderCA(string_url, danger_on); - } - } - - return json_file_content; - } - - /** - * Tries to download the contents of the provided url using not commercially validated CA certificate from chosen provider. - * @param url_string as a string - * @param danger_on true to download CA certificate in case it has not been downloaded. - * @return an empty string if it fails, the url content if not. - */ - private String downloadWithProviderCA(String url_string, boolean danger_on) { - String json_file_content = ""; - - try { - URL url = new URL(url_string); - // Tell the URLConnection to use a SocketFactory from our SSLContext - HttpsURLConnection urlConnection = - (HttpsURLConnection)url.openConnection(); - urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); - if(!LeapSRPSession.getToken().isEmpty()) - urlConnection.addRequestProperty(LeapSRPSession.AUTHORIZATION_HEADER, "Token token=" + LeapSRPSession.getToken()); - json_file_content = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (UnknownHostException e) { - e.printStackTrace(); - json_file_content = formatErrorMessage(R.string.server_unreachable_message); - } catch (IOException e) { - // The downloaded certificate doesn't validate our https connection. - if(danger_on) { - json_file_content = downloadWithoutCA(url_string); - } else { - json_file_content = formatErrorMessage(R.string.certificate_error); - } - } 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(); - } catch (NoSuchElementException e) { - e.printStackTrace(); - json_file_content = formatErrorMessage(R.string.server_unreachable_message); - } - return json_file_content; - } - - private javax.net.ssl.SSLSocketFactory getProviderSSLSocketFactory() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException { - String provider_cert_string = preferences.getString(Provider.CA_CERT,""); - - java.security.cert.Certificate provider_certificate = ConfigHelper.parseX509CertificateFromString(provider_cert_string); - - // Create a KeyStore containing our trusted CAs - String keyStoreType = KeyStore.getDefaultType(); - KeyStore keyStore = KeyStore.getInstance(keyStoreType); - keyStore.load(null, null); - keyStore.setCertificateEntry("provider_ca_certificate", provider_certificate); - - // 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); - - return context.getSocketFactory(); - } - - /** - * Downloads the string that's in the url with any certificate. - */ - private String downloadWithoutCA(String url_string) { - String string = ""; - try { - - HostnameVerifier hostnameVerifier = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; - - class DefaultTrustManager implements X509TrustManager { - - @Override - public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} - - @Override - public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} - - @Override - public X509Certificate[] getAcceptedIssuers() { - return null; - } - } - - SSLContext context = SSLContext.getInstance("TLS"); - context.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom()); - - URL url = new URL(url_string); - HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection(); - urlConnection.setSSLSocketFactory(context.getSocketFactory()); - urlConnection.setHostnameVerifier(hostnameVerifier); - string = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); - System.out.println("String ignoring certificate = " + string); - } catch (FileNotFoundException e) { - e.printStackTrace(); - string = formatErrorMessage(R.string.malformed_url); - } catch (IOException e) { - // The downloaded certificate doesn't validate our https connection. - e.printStackTrace(); - string = formatErrorMessage(R.string.certificate_error); - } catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (KeyManagementException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return string; - } - + byte[] byteArray = Base64.decode(base64_input, Base64.DEFAULT); + int readBytes = byteArray.length; + StringBuffer hexData = new StringBuffer(); + int onebyte; + for (int i = 0; i < readBytes; i++) { + onebyte = ((0x000000ff & byteArray[i]) | 0xffffff00); + hexData.append(Integer.toHexString(onebyte).substring(6)); + } + return hexData.toString(); + } + + private Bundle getAndSetProviderJson(String provider_main_url, boolean danger_on) { + Bundle result = new Bundle(); + + if (go_ahead) { + String provider_dot_json_string = downloadWithCommercialCA(provider_main_url + "/provider.json", danger_on); + + try { + JSONObject provider_json = new JSONObject(provider_dot_json_string); + provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); + String name = provider_json.getString(Provider.NAME); + //TODO setProviderName(name); + + preferences.edit().putString(Provider.KEY, provider_json.toString()).commit(); + preferences.edit().putBoolean(Constants.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_ANON)).commit(); + preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_REGISTERED)).commit(); + + result.putBoolean(RESULT_KEY, true); + } catch (JSONException e) { + //TODO Error message should be contained in that provider_dot_json_string + String reason_to_fail = pickErrorMessage(provider_dot_json_string); + result.putString(ERRORS, reason_to_fail); + result.putBoolean(RESULT_KEY, false); + } + } + return result; + } + + private Bundle getAndSetEipServiceJson() { + Bundle result = new Bundle(); + String eip_service_json_string = ""; + if (go_ahead) { + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + String eip_service_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH; + eip_service_json_string = downloadWithProviderCA(eip_service_url, true); + JSONObject eip_service_json = new JSONObject(eip_service_json_string); + eip_service_json.getInt(Provider.API_RETURN_SERIAL); + + preferences.edit().putString(Constants.KEY, eip_service_json.toString()).commit(); + + result.putBoolean(RESULT_KEY, true); + } catch (JSONException e) { + String reason_to_fail = pickErrorMessage(eip_service_json_string); + result.putString(ERRORS, reason_to_fail); + result.putBoolean(RESULT_KEY, false); + } + } + return result; + } + + /** + * Interprets the error message as a JSON object and extract the "errors" keyword pair. + * If the error message is not a JSON object, then it is returned untouched. + * + * @param string_json_error_message + * @return final error message + */ + private String pickErrorMessage(String string_json_error_message) { + String error_message = ""; + try { + JSONObject json_error_message = new JSONObject(string_json_error_message); + error_message = json_error_message.getString(ERRORS); + } catch (JSONException e) { + // TODO Auto-generated catch block + error_message = string_json_error_message; + } + + return error_message; + } + + /** + * Tries to download the contents of the provided url using commercially validated CA certificate from chosen provider. + * <p/> + * 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 downloadWithCommercialCA(String string_url, boolean danger_on) { + + String json_file_content = ""; + + URL provider_url = null; + int seconds_of_timeout = 2; + try { + provider_url = new URL(string_url); + URLConnection url_connection = provider_url.openConnection(); + url_connection.setConnectTimeout(seconds_of_timeout * 1000); + if (!LeapSRPSession.getToken().isEmpty()) + url_connection.addRequestProperty(LeapSRPSession.AUTHORIZATION_HEADER, "Token token = " + LeapSRPSession.getToken()); + json_file_content = new Scanner(url_connection.getInputStream()).useDelimiter("\\A").next(); + } catch (MalformedURLException e) { + json_file_content = formatErrorMessage(R.string.malformed_url); + } catch (SocketTimeoutException e) { + json_file_content = formatErrorMessage(R.string.server_unreachable_message); + } catch (SSLHandshakeException e) { + if (provider_url != null) { + json_file_content = downloadWithProviderCA(string_url, danger_on); + } else { + json_file_content = formatErrorMessage(R.string.certificate_error); + } + } catch (ConnectException e) { + json_file_content = formatErrorMessage(R.string.service_is_down_error); + } catch (FileNotFoundException e) { + json_file_content = formatErrorMessage(R.string.malformed_url); + } catch (Exception e) { + if (provider_url != null && danger_on) { + json_file_content = downloadWithProviderCA(string_url, danger_on); + } + } + + return json_file_content; + } + + /** + * Tries to download the contents of the provided url using not commercially validated CA certificate from chosen provider. + * + * @param url_string as a string + * @param danger_on true to download CA certificate in case it has not been downloaded. + * @return an empty string if it fails, the url content if not. + */ + private String downloadWithProviderCA(String url_string, boolean danger_on) { + String json_file_content = ""; + + try { + URL url = new URL(url_string); + // Tell the URLConnection to use a SocketFactory from our SSLContext + HttpsURLConnection urlConnection = + (HttpsURLConnection) url.openConnection(); + urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); + if (!LeapSRPSession.getToken().isEmpty()) + urlConnection.addRequestProperty(LeapSRPSession.AUTHORIZATION_HEADER, "Token token=" + LeapSRPSession.getToken()); + json_file_content = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (UnknownHostException e) { + e.printStackTrace(); + json_file_content = formatErrorMessage(R.string.server_unreachable_message); + } catch (IOException e) { + // The downloaded certificate doesn't validate our https connection. + if (danger_on) { + json_file_content = downloadWithoutCA(url_string); + } else { + json_file_content = formatErrorMessage(R.string.certificate_error); + } + } 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(); + } catch (NoSuchElementException e) { + e.printStackTrace(); + json_file_content = formatErrorMessage(R.string.server_unreachable_message); + } + return json_file_content; + } + + private javax.net.ssl.SSLSocketFactory getProviderSSLSocketFactory() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException { + String provider_cert_string = preferences.getString(Provider.CA_CERT, ""); + + java.security.cert.Certificate provider_certificate = ConfigHelper.parseX509CertificateFromString(provider_cert_string); + + // Create a KeyStore containing our trusted CAs + String keyStoreType = KeyStore.getDefaultType(); + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + keyStore.load(null, null); + keyStore.setCertificateEntry("provider_ca_certificate", provider_certificate); + + // 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); + + return context.getSocketFactory(); + } + + /** + * Downloads the string that's in the url with any certificate. + */ + private String downloadWithoutCA(String url_string) { + String string = ""; + try { + + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + + class DefaultTrustManager implements X509TrustManager { + + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + } + + SSLContext context = SSLContext.getInstance("TLS"); + context.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom()); + + URL url = new URL(url_string); + HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); + urlConnection.setSSLSocketFactory(context.getSocketFactory()); + urlConnection.setHostnameVerifier(hostnameVerifier); + string = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); + System.out.println("String ignoring certificate = " + string); + } catch (FileNotFoundException e) { + e.printStackTrace(); + string = formatErrorMessage(R.string.malformed_url); + } catch (IOException e) { + // The downloaded certificate doesn't validate our https connection. + e.printStackTrace(); + string = formatErrorMessage(R.string.certificate_error); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (KeyManagementException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return string; + } + /** * Logs out from the api url retrieved from the task. + * * @return true if there were no exceptions */ private boolean logOut() { @@ -840,117 +856,114 @@ public class ProviderAPI extends IntentService { HttpsURLConnection urlConnection = null; int responseCode = 0; int progress = 0; - try { - - urlConnection = (HttpsURLConnection)new URL(delete_url).openConnection(); - urlConnection.setRequestMethod("DELETE"); - urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); - - responseCode = urlConnection.getResponseCode(); - broadcastProgress(progress++); - LeapSRPSession.setToken(""); - Log.d(TAG, Integer.toString(responseCode)); - } 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 - try { - if(urlConnection != null) { - responseCode = urlConnection.getResponseCode(); - if(responseCode == 401) { - broadcastProgress(progress++); - LeapSRPSession.setToken(""); - Log.d(TAG, Integer.toString(responseCode)); - return true; - } - } - } catch (IOException e1) { - e1.printStackTrace(); - } - - e.printStackTrace(); - return false; - } catch (KeyManagementException 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 (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return true; - } - + try { + + urlConnection = (HttpsURLConnection) new URL(delete_url).openConnection(); + urlConnection.setRequestMethod("DELETE"); + urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); + + responseCode = urlConnection.getResponseCode(); + broadcastProgress(progress++); + LeapSRPSession.setToken(""); + } 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 + try { + if (urlConnection != null) { + responseCode = urlConnection.getResponseCode(); + if (responseCode == 401) { + broadcastProgress(progress++); + LeapSRPSession.setToken(""); + return true; + } + } + } catch (IOException e1) { + e1.printStackTrace(); + } + + e.printStackTrace(); + return false; + } catch (KeyManagementException 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 (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return true; + } + /** * Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate. - * - * @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. + * + * @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 updateVpnCertificate() { - try { - JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - - String provider_main_url = provider_json.getString(Provider.API_URL); - URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + Constants.CERTIFICATE); + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + + String provider_main_url = provider_json.getString(Provider.API_URL); + URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + Constants.CERTIFICATE); - boolean danger_on = preferences.getBoolean(ProviderItem.DANGER_ON, false); + boolean danger_on = preferences.getBoolean(ProviderItem.DANGER_ON, false); - String cert_string = downloadWithProviderCA(new_cert_string_url.toString(), danger_on); + String cert_string = downloadWithProviderCA(new_cert_string_url.toString(), danger_on); - if(cert_string.isEmpty() || ConfigHelper.checkErroneousDownload(cert_string)) - return false; - else - return loadCertificate(cert_string); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } catch (MalformedURLException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } + if (cert_string.isEmpty() || ConfigHelper.checkErroneousDownload(cert_string)) + return false; + else + return loadCertificate(cert_string); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } } private boolean loadCertificate(String cert_string) { - try { - // API returns concatenated cert & key. Split them for OpenVPN options - String certificateString = null, keyString = null; - String[] certAndKey = cert_string.split("(?<=-\n)"); - for (int i=0; i < certAndKey.length-1; i++){ - if ( certAndKey[i].contains("KEY") ) { - keyString = certAndKey[i++] + certAndKey[i]; - } - else if ( certAndKey[i].contains("CERTIFICATE") ) { - certificateString = certAndKey[i++] + certAndKey[i]; - } - } - RSAPrivateKey keyCert = ConfigHelper.parseRsaKeyFromString(keyString); - keyString = Base64.encodeToString( keyCert.getEncoded(), Base64.DEFAULT ); - preferences.edit().putString(Constants.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit(); - - X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(certificateString); - certificateString = Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT); - - preferences.edit().putString(Constants.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit(); - - return true; - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } + try { + // API returns concatenated cert & key. Split them for OpenVPN options + String certificateString = null, keyString = null; + String[] certAndKey = cert_string.split("(?<=-\n)"); + for (int i = 0; i < certAndKey.length - 1; i++) { + if (certAndKey[i].contains("KEY")) { + keyString = certAndKey[i++] + certAndKey[i]; + } else if (certAndKey[i].contains("CERTIFICATE")) { + certificateString = certAndKey[i++] + certAndKey[i]; + } + } + RSAPrivateKey keyCert = ConfigHelper.parseRsaKeyFromString(keyString); + keyString = Base64.encodeToString(keyCert.getEncoded(), Base64.DEFAULT); + preferences.edit().putString(Constants.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n" + keyString + "-----END RSA PRIVATE KEY-----").commit(); + + X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(certificateString); + certificateString = Base64.encodeToString(certCert.getEncoded(), Base64.DEFAULT); + + preferences.edit().putString(Constants.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n" + certificateString + "-----END CERTIFICATE-----").commit(); + + return true; + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } } } diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java index 4b46e48f..bd21f91e 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderDetailFragment.java @@ -2,109 +2,110 @@ package se.leap.bitmaskclient; import org.json.*;
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.eip.Constants;
+import se.leap.bitmaskclient.eip.*;
import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
import android.app.*;
import android.content.*;
-import android.os.Bundle;
+import android.os.*;
import android.view.*;
-import android.widget.TextView;
+import android.widget.*;
public class ProviderDetailFragment extends DialogFragment {
final public static String TAG = "providerDetailFragment";
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- try {
-
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View provider_detail_view = inflater.inflate(R.layout.provider_detail_fragment, null);
-
- JSONObject provider_json = new JSONObject(getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, getActivity().MODE_PRIVATE).getString(Provider.KEY, ""));
-
- final TextView domain = (TextView)provider_detail_view.findViewById(R.id.provider_detail_domain);
- domain.setText(provider_json.getString(Provider.DOMAIN));
- final TextView name = (TextView)provider_detail_view.findViewById(R.id.provider_detail_name);
- name.setText(provider_json.getJSONObject(Provider.NAME).getString("en"));
- final TextView description = (TextView)provider_detail_view.findViewById(R.id.provider_detail_description);
- description.setText(provider_json.getJSONObject(Provider.DESCRIPTION).getString("en"));
-
- builder.setView(provider_detail_view);
- builder.setTitle(R.string.provider_details_fragment_title);
-
- if(anon_allowed(provider_json)) {
- builder.setPositiveButton(R.string.use_anonymously_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- interface_with_configuration_wizard.use_anonymously();
- }
- });
- }
-
- if(registration_allowed(provider_json)) {
- builder.setNegativeButton(R.string.signup_or_login_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- interface_with_configuration_wizard.login();
- }
- });
- }
-
- return builder.create();
- } catch (JSONException e) {
- return null;
- }
- }
-
- private boolean anon_allowed(JSONObject provider_json) {
- try {
- JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
- return service_description.has(Constants.ALLOWED_ANON) && service_description.getBoolean(Constants.ALLOWED_ANON);
- } catch (JSONException e) {
- return false;
- }
- }
-
- private boolean registration_allowed(JSONObject provider_json) {
- try {
- JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
- return service_description.has(Provider.ALLOW_REGISTRATION) && service_description.getBoolean(Provider.ALLOW_REGISTRATION);
- } catch (JSONException e) {
- return false;
- }
- }
-
- @Override
- public void onCancel(DialogInterface dialog) {
- super.onCancel(dialog);
- SharedPreferences.Editor editor = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).edit();
- editor.remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit();
- interface_with_configuration_wizard.showAllProviders();
- }
-
- public static DialogFragment newInstance() {
- ProviderDetailFragment provider_detail_fragment = new ProviderDetailFragment();
- return provider_detail_fragment;
- }
-
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ try {
+
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+ View provider_detail_view = inflater.inflate(R.layout.provider_detail_fragment, null);
+
+ JSONObject provider_json = new JSONObject(getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, getActivity().MODE_PRIVATE).getString(Provider.KEY, ""));
+
+ final TextView domain = (TextView) provider_detail_view.findViewById(R.id.provider_detail_domain);
+ domain.setText(provider_json.getString(Provider.DOMAIN));
+ final TextView name = (TextView) provider_detail_view.findViewById(R.id.provider_detail_name);
+ name.setText(provider_json.getJSONObject(Provider.NAME).getString("en"));
+ final TextView description = (TextView) provider_detail_view.findViewById(R.id.provider_detail_description);
+ description.setText(provider_json.getJSONObject(Provider.DESCRIPTION).getString("en"));
+
+ builder.setView(provider_detail_view);
+ builder.setTitle(R.string.provider_details_fragment_title);
+
+ if (anon_allowed(provider_json)) {
+ builder.setPositiveButton(R.string.use_anonymously_button, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ interface_with_configuration_wizard.use_anonymously();
+ }
+ });
+ }
+
+ if (registration_allowed(provider_json)) {
+ builder.setNegativeButton(R.string.signup_or_login_button, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ interface_with_configuration_wizard.login();
+ }
+ });
+ }
+
+ return builder.create();
+ } catch (JSONException e) {
+ return null;
+ }
+ }
+
+ private boolean anon_allowed(JSONObject provider_json) {
+ try {
+ JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
+ return service_description.has(Constants.ALLOWED_ANON) && service_description.getBoolean(Constants.ALLOWED_ANON);
+ } catch (JSONException e) {
+ return false;
+ }
+ }
+
+ private boolean registration_allowed(JSONObject provider_json) {
+ try {
+ JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
+ return service_description.has(Provider.ALLOW_REGISTRATION) && service_description.getBoolean(Provider.ALLOW_REGISTRATION);
+ } catch (JSONException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ SharedPreferences.Editor editor = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).edit();
+ editor.remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit();
+ interface_with_configuration_wizard.showAllProviders();
+ }
+
+ public static DialogFragment newInstance() {
+ ProviderDetailFragment provider_detail_fragment = new ProviderDetailFragment();
+ return provider_detail_fragment;
+ }
+
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
- interface_with_configuration_wizard = (ProviderDetailFragmentInterface) activity;
+ interface_with_configuration_wizard = (ProviderDetailFragmentInterface) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement LogInDialogListener");
}
}
-
- public interface ProviderDetailFragmentInterface {
- public void login();
- public void use_anonymously();
- public void showAllProviders();
- }
-
- ProviderDetailFragmentInterface interface_with_configuration_wizard;
+
+ public interface ProviderDetailFragmentInterface {
+ public void login();
+
+ public void use_anonymously();
+
+ public void showAllProviders();
+ }
+
+ ProviderDetailFragmentInterface interface_with_configuration_wizard;
}
diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderListContent.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderListContent.java index 8c8fb69f..0a05e839 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ProviderListContent.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderListContent.java @@ -1,6 +1,6 @@ /**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -14,73 +14,69 @@ * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
- package se.leap.bitmaskclient;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.net.URL;
-import java.net.MalformedURLException;
+package se.leap.bitmaskclient;
-import org.json.JSONException;
-import org.json.JSONObject;
+import java.util.*;
+import java.net.*;
/**
* Models the provider list shown in the ConfigurationWizard.
- *
- * @author parmegv
*
+ * @author parmegv
*/
public class ProviderListContent {
- public static List<ProviderItem> ITEMS = new ArrayList<ProviderItem>();
+ public static List<ProviderItem> ITEMS = new ArrayList<ProviderItem>();
+
+ public static Map<String, ProviderItem> ITEM_MAP = new HashMap<String, ProviderItem>();
+
+ /**
+ * 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);
+ }
+
+ public static void removeItem(ProviderItem item) {
+ ITEMS.remove(item);
+ ITEM_MAP.remove(item);
+ }
+
+ /**
+ * A provider item.
+ */
+ public static class ProviderItem {
+ final public static String CUSTOM = "custom";
+ final public static String DANGER_ON = "danger_on";
+ private String provider_main_url;
+ private String name;
+
+ /**
+ * @param name of the provider
+ * @param provider_main_url used to download provider.json file of the provider
+ */
+ public ProviderItem(String name, String provider_main_url) {
+ this.name = name;
+ this.provider_main_url = provider_main_url;
+ }
- public static Map<String, ProviderItem> ITEM_MAP = new HashMap<String, ProviderItem>();
+ public String name() {
+ return name;
+ }
- /**
- * 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);
- }
- public static void removeItem(ProviderItem item) {
- ITEMS.remove(item);
- ITEM_MAP.remove(item);
- }
+ public String providerMainUrl() {
+ return provider_main_url;
+ }
- /**
- * A provider item.
- */ - public static class ProviderItem {
- final public static String CUSTOM = "custom";
- final public static String DANGER_ON = "danger_on";
- private String provider_main_url;
- private String name; - - /**
- * @param name of the provider
- * @param provider_main_url used to download provider.json file of the provider
- */ - public ProviderItem(String name, String provider_main_url) {
- this.name = name;
- this.provider_main_url = provider_main_url; - }
-
- public String name() { return name; }
-
- public String providerMainUrl() { return provider_main_url; }
-
- public String domain() {
- try {
- return new URL(provider_main_url).getHost();
- } catch (MalformedURLException e) {
- return provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("/.*", "");
- }
- }
- }
+ public String domain() {
+ try {
+ return new URL(provider_main_url).getHost();
+ } catch (MalformedURLException e) {
+ return provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("/.*", "");
+ }
+ }
+ }
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e11b57ef..cc31de43 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,8 +17,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="se.leap.bitmaskclient" - android:versionCode="116" - android:versionName="0.9.2" > + android:versionCode="120" + android:versionName="0.9.3" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> diff --git a/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java b/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java index 6c4e517b..ce762fcc 100644 --- a/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java @@ -1,35 +1,35 @@ package se.leap.bitmaskclient; -import android.app.Activity; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Bundle; -import android.widget.TextView; - -public class AboutActivity extends Activity { - +import android.app.*; +import android.content.pm.*; +import android.content.pm.PackageManager.*; +import android.os.*; +import android.widget.*; + +public class AboutActivity extends Activity { + final public static String TAG = "aboutFragment"; final public static int VIEWED = 0; @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.about); - TextView ver = (TextView) findViewById(R.id.version); - - String version; - String name="Openvpn"; - try { - PackageInfo packageinfo = getPackageManager().getPackageInfo(getPackageName(), 0); - version = packageinfo.versionName; - name = getString(R.string.app); - } catch (NameNotFoundException e) { - version = "error fetching version"; - } - - - ver.setText(getString(R.string.version_info,name,version)); - setResult(VIEWED); + super.onCreate(savedInstanceState); + setContentView(R.layout.about); + TextView ver = (TextView) findViewById(R.id.version); + + String version; + String name = "Openvpn"; + try { + PackageInfo packageinfo = getPackageManager().getPackageInfo(getPackageName(), 0); + version = packageinfo.versionName; + name = getString(R.string.app); + } catch (NameNotFoundException e) { + version = "error fetching version"; + } + + + ver.setText(getString(R.string.version_info, name, version)); + setResult(VIEWED); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java index c0f0b0c3..4929f040 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,179 +16,170 @@ */ package se.leap.bitmaskclient; -import android.util.Base64; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.security.interfaces.RSAPrivateKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; +import android.util.*; + +import org.json.*; + +import java.io.*; +import java.math.*; +import java.security.*; +import java.security.cert.*; +import java.security.interfaces.*; +import java.security.spec.*; /** * Stores constants, and implements auxiliary methods used across all LEAP Android classes. - * + * * @author parmegv * @author MeanderingCode - * */ public class ConfigHelper { private static KeyStore keystore_trusted; final public static String NG_1024 = - "eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3"; + "eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3"; final public static BigInteger G = new BigInteger("2"); - - public static boolean checkErroneousDownload(String downloaded_string) { - try { - if(new JSONObject(downloaded_string).has(ProviderAPI.ERRORS) || downloaded_string.isEmpty()) { - return true; - } else { - return false; - } - } catch(JSONException e) { - return false; - } - } - - /** - * 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; - } - - public static X509Certificate parseX509CertificateFromString(String certificate_string) { - java.security.cert.Certificate certificate = null; - CertificateFactory cf; - try { - cf = CertificateFactory.getInstance("X.509"); - - certificate_string = certificate_string.replaceFirst("-----BEGIN CERTIFICATE-----", "").replaceFirst("-----END CERTIFICATE-----", "").trim(); - byte[] cert_bytes = Base64.decode(certificate_string, Base64.DEFAULT); - InputStream caInput = new ByteArrayInputStream(cert_bytes); - try { - certificate = cf.generateCertificate(caInput); - System.out.println("ca=" + ((X509Certificate) certificate).getSubjectDN()); - } finally { - caInput.close(); - } - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - return null; - } catch (IllegalArgumentException e) { - return null; - } - - return (X509Certificate) certificate; - } - - protected static RSAPrivateKey parseRsaKeyFromString(String RsaKeyString) { - RSAPrivateKey key = null; - try { - KeyFactory kf = KeyFactory.getInstance("RSA", "BC"); - - RsaKeyString = RsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", ""); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec( Base64.decode(RsaKeyString, Base64.DEFAULT) ); - key = (RSAPrivateKey) kf.generatePrivate(keySpec); - } catch (InvalidKeySpecException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } catch (NoSuchProviderException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } - - return key; - } - - /** - * 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 { - cf = CertificateFactory.getInstance("X.509"); - X509Certificate cert = - (X509Certificate)cf.generateCertificate(inputStream); - keystore_trusted.setCertificateEntry(provider, cert); - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (KeyStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** - * 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) { - - try { - X509Certificate cert = ConfigHelper.parseX509CertificateFromString(certificate); - if(keystore_trusted == null) { - keystore_trusted = KeyStore.getInstance("BKS"); - keystore_trusted.load(null); - } - keystore_trusted.setCertificateEntry(provider, cert); - } 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(); - } - } - - /** - * @return class wide keystore - */ - public static KeyStore getKeystore() { - return keystore_trusted; - } + + public static boolean checkErroneousDownload(String downloaded_string) { + try { + if (new JSONObject(downloaded_string).has(ProviderAPI.ERRORS) || downloaded_string.isEmpty()) { + return true; + } else { + return false; + } + } catch (JSONException e) { + return false; + } + } + + /** + * 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; + } + + public static X509Certificate parseX509CertificateFromString(String certificate_string) { + java.security.cert.Certificate certificate = null; + CertificateFactory cf; + try { + cf = CertificateFactory.getInstance("X.509"); + + certificate_string = certificate_string.replaceFirst("-----BEGIN CERTIFICATE-----", "").replaceFirst("-----END CERTIFICATE-----", "").trim(); + byte[] cert_bytes = Base64.decode(certificate_string, Base64.DEFAULT); + InputStream caInput = new ByteArrayInputStream(cert_bytes); + try { + certificate = cf.generateCertificate(caInput); + System.out.println("ca=" + ((X509Certificate) certificate).getSubjectDN()); + } finally { + caInput.close(); + } + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + return null; + } catch (IllegalArgumentException e) { + return null; + } + + return (X509Certificate) certificate; + } + + protected static RSAPrivateKey parseRsaKeyFromString(String RsaKeyString) { + RSAPrivateKey key = null; + try { + KeyFactory kf = KeyFactory.getInstance("RSA", "BC"); + + RsaKeyString = RsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", ""); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(RsaKeyString, Base64.DEFAULT)); + key = (RSAPrivateKey) kf.generatePrivate(keySpec); + } catch (InvalidKeySpecException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } catch (NoSuchProviderException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + + return key; + } + + /** + * 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 { + cf = CertificateFactory.getInstance("X.509"); + X509Certificate cert = + (X509Certificate) cf.generateCertificate(inputStream); + keystore_trusted.setCertificateEntry(provider, cert); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * 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) { + + try { + X509Certificate cert = ConfigHelper.parseX509CertificateFromString(certificate); + if (keystore_trusted == null) { + keystore_trusted = KeyStore.getInstance("BKS"); + keystore_trusted.load(null); + } + keystore_trusted.setCertificateEntry(provider, cert); + } 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(); + } + } + + /** + * @return class wide keystore + */ + public static KeyStore getKeystore() { + return keystore_trusted; + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 6d368e11..ee64a1b3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,18 +16,20 @@ */ package se.leap.bitmaskclient; -import android.annotation.SuppressLint; +import android.annotation.*; import android.app.*; import android.content.*; -import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.PackageManager.*; import android.os.*; -import android.util.Log; +import android.util.*; import android.view.*; import android.widget.*; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.*; import org.json.*; + import java.net.*; +import java.util.*; import butterknife.*; import de.blinkt.openvpn.activities.*; @@ -36,11 +38,11 @@ import se.leap.bitmaskclient.eip.*; /** * The main user facing Activity of Bitmask Android, consisting of status, controls, * and access to preferences. - * + * * @author Sean Leonard <meanderingcode@aetherislands.net> * @author parmegv */ -public class Dashboard extends Activity implements SessionDialog.SessionDialogInterface, ProviderAPIResultReceiver.Receiver { +public class Dashboard extends Activity implements SessionDialog.SessionDialogInterface, ProviderAPIResultReceiver.Receiver, Observer { protected static final int CONFIGURE_LEAP = 0; protected static final int SWITCH_PROVIDER = 1; @@ -60,47 +62,65 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn @InjectView(R.id.providerName) TextView provider_name; + @InjectView(R.id.user_session_status) + TextView user_session_status_text_view; + @InjectView(R.id.user_session_status_progress) + ProgressBar user_session_status_progress_bar; EipFragment eip_fragment; private Provider provider; - private static boolean authed_eip; + private UserSessionStatus user_session_status; public ProviderAPIResultReceiver providerAPI_result_receiver; private boolean switching_provider; @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - app = this; + super.onCreate(savedInstanceState); + + app = this; + user_session_status = UserSessionStatus.getInstance(); + user_session_status.addObserver(this); - PRNGFixes.apply(); + PRNGFixes.apply(); - preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); - fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); - handleVersion(); + preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); + handleVersion(); - provider = getSavedProvider(savedInstanceState); + restoreProvider(savedInstanceState); if (provider == null || provider.getName().isEmpty()) - startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); - else - buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false)); + startActivityForResult(new Intent(this, ConfigurationWizard.class), CONFIGURE_LEAP); + else { + buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false)); + restoreSessionStatus(savedInstanceState); + } + } + + private void restoreProvider(Bundle savedInstanceState) { + if (savedInstanceState != null) { + if (savedInstanceState.containsKey(Provider.KEY)) + provider = savedInstanceState.getParcelable(Provider.KEY); + } + if (provider == null && preferences.getBoolean(Constants.PROVIDER_CONFIGURED, false)) + provider = getSavedProviderFromSharedPreferences(); + } + + private void restoreSessionStatus(Bundle savedInstanceState) { + if (savedInstanceState != null) + if (savedInstanceState.containsKey(UserSessionStatus.TAG)) { + UserSessionStatus.SessionStatus status = (UserSessionStatus.SessionStatus) savedInstanceState.getSerializable(UserSessionStatus.TAG); + user_session_status.updateStatus(status); + } } @Override protected void onSaveInstanceState(@NotNull Bundle outState) { - if(provider != null) + if (provider != null) outState.putParcelable(Provider.KEY, provider); - super.onSaveInstanceState(outState); - } - - private Provider getSavedProvider(Bundle savedInstanceState) { - Provider provider = null; - if(savedInstanceState != null) - provider = savedInstanceState.getParcelable(Provider.KEY); - else if(preferences.getBoolean(Constants.PROVIDER_CONFIGURED, false)) - provider = getSavedProviderFromSharedPreferences(); + if (user_session_status_text_view != null && user_session_status_text_view.getVisibility() == TextView.VISIBLE) + outState.putSerializable(UserSessionStatus.TAG, user_session_status.sessionStatus()); - return provider; + super.onSaveInstanceState(outState); } private Provider getSavedProviderFromSharedPreferences() { @@ -108,9 +128,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn try { provider = new Provider(new URL(preferences.getString(Provider.MAIN_URL, ""))); provider.define(new JSONObject(preferences.getString(Provider.KEY, ""))); - } catch (MalformedURLException e) { - e.printStackTrace(); - } catch (JSONException e) { + } catch (MalformedURLException | JSONException e) { e.printStackTrace(); } @@ -118,27 +136,27 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn } private void handleVersion() { - try { - int versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; - int lastDetectedVersion = preferences.getInt(APP_VERSION, 0); - preferences.edit().putInt(APP_VERSION, versionCode).apply(); - - switch(versionCode) { - case 91: // 0.6.0 without Bug #5999 - case 101: // 0.8.0 - if(!preferences.getString(Constants.KEY, "").isEmpty()) - eip_fragment.updateEipService(); - break; - } - } catch (NameNotFoundException e) { - Log.d(TAG, "Handle version didn't find any " + getPackageName() + " package"); - } + try { + int versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; + int lastDetectedVersion = preferences.getInt(APP_VERSION, 0); + preferences.edit().putInt(APP_VERSION, versionCode).apply(); + + switch (versionCode) { + case 91: // 0.6.0 without Bug #5999 + case 101: // 0.8.0 + if (!preferences.getString(Constants.KEY, "").isEmpty()) + eip_fragment.updateEipService(); + break; + } + } catch (NameNotFoundException e) { + Log.d(TAG, "Handle version didn't find any " + getPackageName() + " package"); + } } @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data){ - if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) { - if ( resultCode == RESULT_OK && data.hasExtra(Provider.KEY)) { + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) { + if (resultCode == RESULT_OK && data.hasExtra(Provider.KEY)) { provider = data.getParcelableExtra(Provider.KEY); providerToPreferences(provider); @@ -148,14 +166,13 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn sessionDialog(Bundle.EMPTY); } - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); - } else if (resultCode == RESULT_CANCELED && data.hasExtra(ACTION_QUIT)) { + } else if (resultCode == RESULT_CANCELED && data.hasExtra(ACTION_QUIT)) { finish(); - } else - configErrorDialog(); - } else if(requestCode == EIP.DISCONNECT) { - EipStatus.getInstance().setConnectedOrDisconnected(); - } + } else + configErrorDialog(); + } else if (requestCode == EIP.DISCONNECT) { + EipStatus.getInstance().setConnectedOrDisconnected(); + } } @SuppressLint("CommitPrefEdits") @@ -166,197 +183,237 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn } private void configErrorDialog() { - 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) { - preferences.edit().remove(Provider.KEY).remove(Constants.PROVIDER_CONFIGURED).apply(); - finish(); - } - }) - .show(); - } - + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getContext()); + 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(getContext(), ConfigurationWizard.class), CONFIGURE_LEAP); + } + }) + .setNegativeButton(getResources().getString(R.string.setup_error_close_button), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + preferences.edit().remove(Provider.KEY).remove(Constants.PROVIDER_CONFIGURED).apply(); + finish(); + } + }) + .show(); + } + /** * Inflates permanent UI elements of the View and contains logic for what * service dependent UI elements to include. */ private void buildDashboard(boolean hide_and_turn_on_eip) { - setContentView(R.layout.dashboard); + setContentView(R.layout.dashboard); ButterKnife.inject(this); - provider_name.setText(provider.getDomain()); - if ( provider.hasEIP()){ + provider_name.setText(provider.getDomain()); + if (provider.hasEIP()) { fragment_manager.removePreviousFragment(EipFragment.TAG); eip_fragment = new EipFragment(); - if (hide_and_turn_on_eip) { - preferences.edit().remove(Dashboard.START_ON_BOOT).apply(); - Bundle arguments = new Bundle(); - arguments.putBoolean(EipFragment.START_ON_BOOT, true); - if(eip_fragment != null) eip_fragment.setArguments(arguments); - } + if (hide_and_turn_on_eip) { + preferences.edit().remove(Dashboard.START_ON_BOOT).apply(); + Bundle arguments = new Bundle(); + arguments.putBoolean(EipFragment.START_ON_BOOT, true); + if (eip_fragment != null) eip_fragment.setArguments(arguments); + } fragment_manager.replace(R.id.servicesCollection, eip_fragment, EipFragment.TAG); - if (hide_and_turn_on_eip) { - onBackPressed(); - } - } + if (hide_and_turn_on_eip) { + onBackPressed(); + } + } + handleNewUserSessionStatus(user_session_status); } @Override public boolean onPrepareOptionsMenu(Menu menu) { - JSONObject provider_json; - try { - String provider_json_string = preferences.getString(Provider.KEY, ""); - if(!provider_json_string.isEmpty()) { - provider_json = new JSONObject(provider_json_string); - JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE); - boolean authed_eip = !LeapSRPSession.getToken().isEmpty(); - boolean allow_registered_eip = service_description.getBoolean(Provider.ALLOW_REGISTRATION); - preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, allow_registered_eip).apply(); - - if(allow_registered_eip) { - if(authed_eip) { - menu.findItem(R.id.login_button).setVisible(false); - menu.findItem(R.id.logout_button).setVisible(true); - } else { - menu.findItem(R.id.login_button).setVisible(true); - menu.findItem(R.id.logout_button).setVisible(false); - } - menu.findItem(R.id.signup_button).setVisible(true); - } - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return true; + if (provider.allowsRegistration()) { + menu.findItem(R.id.signup_button).setVisible(true); + + boolean logged_in = User.loggedIn(); + menu.findItem(R.id.login_button).setVisible(!logged_in); + menu.findItem(R.id.logout_button).setVisible(logged_in); + } + return true; } @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.client_dashboard, menu); - return true; + getMenuInflater().inflate(R.menu.client_dashboard, menu); + return true; } - + @Override - public boolean onOptionsItemSelected(MenuItem item){ - Intent intent; - switch (item.getItemId()){ - case R.id.about_leap: - intent = new Intent(this, AboutActivity.class); - startActivity(intent); - return true; - case R.id.log_window: - Intent startLW = new Intent(getAppContext(), LogWindow.class); - startLW.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - startActivity(startLW); - return true; - case R.id.switch_provider: - switching_provider = true; - if (preferences.getBoolean(Constants.AUTHED_EIP, false)) logOut(); - else switchProvider(); - return true; - case R.id.login_button: - sessionDialog(Bundle.EMPTY); - return true; - case R.id.logout_button: - logOut(); - return true; - case R.id.signup_button: - sessionDialog(Bundle.EMPTY); - return true; - default: - return super.onOptionsItemSelected(item); - } + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.about_leap: + showAbout(); + return true; + case R.id.log_window: + showLog(); + return true; + case R.id.switch_provider: + switching_provider = true; + if (LeapSRPSession.loggedIn()) logOut(); + else switchProvider(); + return true; + case R.id.login_button: + sessionDialog(Bundle.EMPTY); + return true; + case R.id.logout_button: + logOut(); + return true; + case R.id.signup_button: + sessionDialog(Bundle.EMPTY); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + public void showAbout() { + Intent intent = new Intent(this, AboutActivity.class); + startActivity(intent); + } + + public void showLog() { + Intent startLW = new Intent(getContext(), LogWindow.class); + startActivity(startLW); } @Override public void signUp(String username, String password) { - Bundle parameters = bundleParameters(username, password); - providerApiCommand(parameters, R.string.signingup_message, ProviderAPI.SRP_REGISTER); + User.setUserName(username); + Bundle parameters = bundlePassword(password); + providerApiCommand(parameters, 0, ProviderAPI.SIGN_UP); } @Override public void logIn(String username, String password) { - Bundle parameters = bundleParameters(username, password); - providerApiCommand(parameters, R.string.authenticating_message, ProviderAPI.SRP_AUTH); + User.setUserName(username); + Bundle parameters = bundlePassword(password); + providerApiCommand(parameters, 0, ProviderAPI.LOG_IN); } - + public void logOut() { - providerApiCommand(Bundle.EMPTY, R.string.logout_message, ProviderAPI.LOG_OUT); + providerApiCommand(Bundle.EMPTY, 0, ProviderAPI.LOG_OUT); + } + + @Override + public void update(Observable observable, Object data) { + if (observable instanceof UserSessionStatus) { + UserSessionStatus status = (UserSessionStatus) observable; + handleNewUserSessionStatus(status); + } + } + + private void handleNewUserSessionStatus(UserSessionStatus status) { + user_session_status = status; + if (provider.allowsRegistration()) { + if (user_session_status.inProgress()) + showUserSessionProgressBar(); + else + hideUserSessionProgressBar(); + changeSessionStatusMessage(user_session_status.toString()); + invalidateOptionsMenu(); + } + } + + private void changeSessionStatusMessage(final String message) { + runOnUiThread(new Runnable() { + @Override + public void run() { + user_session_status_text_view.setText(message); + } + }); + } + + private void showUserSessionProgressBar() { + runOnUiThread(new Runnable() { + @Override + public void run() { + user_session_status_progress_bar.setVisibility(ProgressBar.VISIBLE); + } + }); + } + + private void hideUserSessionProgressBar() { + runOnUiThread(new Runnable() { + @Override + public void run() { + user_session_status_progress_bar.setVisibility(ProgressBar.GONE); + } + }); } protected void downloadVpnCertificate() { - boolean is_authenticated = !LeapSRPSession.getToken().isEmpty(); + boolean is_authenticated = LeapSRPSession.loggedIn(); boolean allowed_anon = preferences.getBoolean(Constants.ALLOWED_ANON, false); - if(allowed_anon || is_authenticated) + if (allowed_anon || is_authenticated) providerApiCommand(Bundle.EMPTY, R.string.downloading_certificate_message, ProviderAPI.DOWNLOAD_CERTIFICATE); else sessionDialog(Bundle.EMPTY); } - private Bundle bundleParameters(String username, String password) { + private Bundle bundlePassword(String password) { Bundle parameters = new Bundle(); - if(!username.isEmpty()) - parameters.putString(SessionDialog.USERNAME, username); - if(!password.isEmpty()) - parameters.putString(SessionDialog.PASSWORD, password); - return parameters; + if (!password.isEmpty()) + parameters.putString(SessionDialog.PASSWORD, password); + return parameters; } protected void providerApiCommand(Bundle parameters, int progressbar_message_resId, String providerApi_action) { - if(eip_fragment != null && progressbar_message_resId != 0) { + if (eip_fragment != null && progressbar_message_resId != 0) { eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE); setStatusMessage(progressbar_message_resId); } - - Intent command = prepareProviderAPICommand(parameters, providerApi_action); - startService(command); + + Intent command = prepareProviderAPICommand(parameters, providerApi_action); + startService(command); } private Intent prepareProviderAPICommand(Bundle parameters, String action) { - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); - - Intent command = new Intent(this, ProviderAPI.class); - - command.putExtra(ProviderAPI.PARAMETERS, parameters); - command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - command.setAction(action); - return command; + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); + + Intent command = new Intent(this, ProviderAPI.class); + + command.putExtra(ProviderAPI.PARAMETERS, parameters); + command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); + command.setAction(action); + return command; } public void cancelLoginOrSignup() { - EipStatus.getInstance().setConnectedOrDisconnected(); + EipStatus.getInstance().setConnectedOrDisconnected(); } - + public void sessionDialog(Bundle resultData) { - - FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG); - DialogFragment newFragment = new SessionDialog(); - if(resultData != null && !resultData.isEmpty()) { - newFragment.setArguments(resultData); - } - newFragment.show(transaction, SessionDialog.TAG); + FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG); + + DialogFragment newFragment = new SessionDialog(); + if (provider.getName().equalsIgnoreCase("riseup")) { + resultData = resultData == Bundle.EMPTY ? new Bundle() : resultData; + resultData.putBoolean(SessionDialog.ERRORS.RISEUP_WARNING.toString(), true); + } + if (resultData != null && !resultData.isEmpty()) { + newFragment.setArguments(resultData); + } + newFragment.show(transaction, SessionDialog.TAG); } private void switchProvider() { - if (provider.hasEIP()) eip_fragment.askToStopEIP(); - + if (provider.hasEIP()) eip_fragment.stopEipIfPossible(); + preferences.edit().clear().apply(); switching_provider = false; startActivityForResult(new Intent(this, ConfigurationWizard.class), SWITCH_PROVIDER); @@ -364,113 +421,43 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn @Override public void onReceiveResult(int resultCode, Bundle resultData) { - Log.d(TAG, "onReceiveResult"); - if(resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) { - String username = resultData.getString(SessionDialog.USERNAME); - String password = resultData.getString(SessionDialog.PASSWORD); - logIn(username, password); - } else if(resultCode == ProviderAPI.FAILED_SIGNUP) { - updateViewHidingProgressBar(resultCode); - sessionDialog(resultData); - } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGIN) { - authed_eip = true; - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); - - updateViewHidingProgressBar(resultCode); - downloadVpnCertificate(); - } else if(resultCode == ProviderAPI.FAILED_LOGIN) { - updateViewHidingProgressBar(resultCode); - sessionDialog(resultData); - } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGOUT) { - authed_eip = false; - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); - - updateViewHidingProgressBar(resultCode); - if(switching_provider) switchProvider(); - } else if(resultCode == ProviderAPI.LOGOUT_FAILED) { - updateViewHidingProgressBar(resultCode); - setResult(RESULT_CANCELED); - } else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { - updateViewHidingProgressBar(resultCode); - eip_fragment.updateEipService(); - setResult(RESULT_OK); - } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { - updateViewHidingProgressBar(resultCode); - setResult(RESULT_CANCELED); - } - else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE) { - eip_fragment.updateEipService(); - setResult(RESULT_OK); - } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE) { - setResult(RESULT_CANCELED); - } - } - - private void updateViewHidingProgressBar(int resultCode) { - changeStatusMessage(resultCode); - hideProgressBar(); - invalidateOptionsMenu(); - } - - private void changeStatusMessage(final int previous_result_code) { - ResultReceiver status_receiver = new ResultReceiver(new Handler()){ - protected void onReceiveResult(int resultCode, Bundle resultData){ - super.onReceiveResult(resultCode, resultData); - String request = resultData.getString(Constants.REQUEST_TAG); - if (request.equalsIgnoreCase(Constants.ACTION_IS_EIP_RUNNING)){ - if (resultCode == Activity.RESULT_OK){ - switch(previous_result_code){ - case ProviderAPI.SUCCESSFUL_LOGIN: setStatusMessage(R.string.succesful_authentication_message); break; - case ProviderAPI.FAILED_LOGIN: setStatusMessage(R.string.authentication_failed_message); break; - case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: setStatusMessage(R.string.authed_secured_status); break; - case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: setStatusMessage(R.string.incorrectly_downloaded_certificate_message); break; - case ProviderAPI.SUCCESSFUL_LOGOUT: setStatusMessage(R.string.logged_out_message); break; - case ProviderAPI.LOGOUT_FAILED: setStatusMessage(R.string.log_out_failed_message); break; - - } - } - else if(resultCode == Activity.RESULT_CANCELED){ - switch(previous_result_code){ - case ProviderAPI.SUCCESSFUL_LOGIN: setStatusMessage(R.string.succesful_authentication_message); break; - case ProviderAPI.FAILED_LOGIN: setStatusMessage(R.string.authentication_failed_message); break; - case ProviderAPI.FAILED_SIGNUP: setStatusMessage(R.string.registration_failed_message); break; - case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: break; - case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: setStatusMessage(R.string.incorrectly_downloaded_certificate_message); break; - case ProviderAPI.SUCCESSFUL_LOGOUT: setStatusMessage(R.string.logged_out_message); break; - case ProviderAPI.LOGOUT_FAILED: setStatusMessage(R.string.log_out_failed_message); break; - } - } - } - - } - }; - eipIsRunning(status_receiver); + if (resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) { + String username = resultData.getString(SessionDialog.USERNAME); + String password = resultData.getString(SessionDialog.PASSWORD); + logIn(username, password); + } else if (resultCode == ProviderAPI.FAILED_SIGNUP) { + sessionDialog(resultData); + } else if (resultCode == ProviderAPI.SUCCESSFUL_LOGIN) { + downloadVpnCertificate(); + } else if (resultCode == ProviderAPI.FAILED_LOGIN) { + sessionDialog(resultData); + } else if (resultCode == ProviderAPI.SUCCESSFUL_LOGOUT) { + if (switching_provider) switchProvider(); + } else if (resultCode == ProviderAPI.LOGOUT_FAILED) { + setResult(RESULT_CANCELED); + } else if (resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { + eip_fragment.updateEipService(); + eip_fragment.handleNewVpnCertificate(); + setResult(RESULT_OK); + } else if (resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { + setResult(RESULT_CANCELED); + } else if (resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE) { + eip_fragment.updateEipService(); + setResult(RESULT_OK); + } else if (resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE) { + setResult(RESULT_CANCELED); + } } private void setStatusMessage(int string_resId) { - if(eip_fragment != null && eip_fragment.status_message != null) - eip_fragment.status_message.setText(string_resId); + if (eip_fragment != null && eip_fragment.status_message != null) + eip_fragment.status_message.setText(string_resId); } - private void eipIsRunning(ResultReceiver eip_receiver){ - // TODO validate "action"...how do we get the list of intent-filters for a class via Android API? - Intent intent = new Intent(this, EIP.class); - intent.setAction(Constants.ACTION_IS_EIP_RUNNING); - intent.putExtra(Constants.RECEIVER_TAG, eip_receiver); - startService(intent); + public static Context getContext() { + return app; } - private void hideProgressBar() { - if(eip_fragment != null) { - eip_fragment.progress_bar.setProgress(0); - eip_fragment.progress_bar.setVisibility(ProgressBar.GONE); - } - } - - public static Context getAppContext() { - return app; - } - @Override public void startActivityForResult(Intent intent, int requestCode) { intent.putExtra(Dashboard.REQUEST_CODE, requestCode); diff --git a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java index a44253c6..da32dbd4 100644 --- a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,76 +16,74 @@ */ package se.leap.bitmaskclient; -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.app.*; +import android.content.*; +import android.os.*; /** * Implements a dialog to show why a download failed. - * - * @author parmegv * + * @author parmegv */ public class DownloadFailedDialog extends DialogFragment { - public static String TAG = "downloaded_failed_dialog"; - private String reason_to_fail; - /** - * @return a new instance of this DialogFragment. - */ - public static DialogFragment newInstance(String reason_to_fail) { - DownloadFailedDialog dialog_fragment = new DownloadFailedDialog(); - dialog_fragment.reason_to_fail = reason_to_fail; - return dialog_fragment; - } + public static String TAG = "downloaded_failed_dialog"; + private String reason_to_fail; + + /** + * @return a new instance of this DialogFragment. + */ + public static DialogFragment newInstance(String reason_to_fail) { + DownloadFailedDialog dialog_fragment = new DownloadFailedDialog(); + dialog_fragment.reason_to_fail = reason_to_fail; + return dialog_fragment; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setMessage(reason_to_fail) + .setPositiveButton(R.string.retry, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dismiss(); + interface_with_ConfigurationWizard.retrySetUpProvider(); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + interface_with_ConfigurationWizard.cancelSettingUpProvider(); + dialog.dismiss(); + } + }); - builder.setMessage(reason_to_fail) - .setPositiveButton(R.string.retry, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dismiss(); - interface_with_ConfigurationWizard.retrySetUpProvider(); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - interface_with_ConfigurationWizard.cancelSettingUpProvider(); - dialog.dismiss(); - } - }); + // Create the AlertDialog object and return it + return builder.create(); + } - // Create the AlertDialog object and return it - return builder.create(); - } + public interface DownloadFailedDialogInterface { + public void retrySetUpProvider(); - public interface DownloadFailedDialogInterface { - public void retrySetUpProvider(); - public void cancelSettingUpProvider(); - } + public void cancelSettingUpProvider(); + } - DownloadFailedDialogInterface interface_with_ConfigurationWizard; + DownloadFailedDialogInterface interface_with_ConfigurationWizard; - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - try { - interface_with_ConfigurationWizard = (DownloadFailedDialogInterface) activity; - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() - + " must implement NoticeDialogListener"); - } - } + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + interface_with_ConfigurationWizard = (DownloadFailedDialogInterface) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement NoticeDialogListener"); + } + } - @Override - public void onCancel(DialogInterface dialog) { - interface_with_ConfigurationWizard.cancelSettingUpProvider(); - dialog.dismiss(); - } + @Override + public void onCancel(DialogInterface dialog) { + interface_with_ConfigurationWizard.cancelSettingUpProvider(); + dialog.dismiss(); + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 588b137b..02eedd77 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -1,35 +1,38 @@ +/** + * Copyright (c) 2013 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ package se.leap.bitmaskclient; -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Fragment; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.os.ResultReceiver; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ProgressBar; -import android.widget.Switch; -import android.widget.TextView; - -import java.util.Observable; -import java.util.Observer; - -import butterknife.ButterKnife; -import butterknife.InjectView; -import butterknife.OnCheckedChanged; -import de.blinkt.openvpn.activities.DisconnectVPN; -import se.leap.bitmaskclient.eip.Constants; -import se.leap.bitmaskclient.eip.EIP; -import se.leap.bitmaskclient.eip.EipStatus; -import se.leap.bitmaskclient.eip.VoidVpnService; +import android.app.*; +import android.content.*; +import android.os.*; +import android.util.*; +import android.view.*; +import android.widget.*; + +import org.jetbrains.annotations.*; + +import java.util.*; + +import butterknife.*; +import de.blinkt.openvpn.activities.*; +import se.leap.bitmaskclient.eip.*; public class EipFragment extends Fragment implements Observer { - + public static String TAG = EipFragment.class.getSimpleName(); protected static final String IS_PENDING = TAG + ".is_pending"; @@ -50,316 +53,347 @@ public class EipFragment extends Fragment implements Observer { private boolean is_starting_to_connect; private boolean wants_to_connect; - @Override public void onAttach(Activity activity) { - super.onAttach(activity); + super.onAttach(activity); dashboard = (Dashboard) activity; dashboard.providerApiCommand(Bundle.EMPTY, 0, ProviderAPI.DOWNLOAD_EIP_SERVICE); } - + @Override public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - eip_status = EipStatus.getInstance(); - eip_status.addObserver(this); - mEIPReceiver = new EIPReceiver(new Handler()); + super.onCreate(savedInstanceState); + eip_status = EipStatus.getInstance(); + eip_status.addObserver(this); + mEIPReceiver = new EIPReceiver(new Handler()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.eip_service_fragment, container, false); + View view = inflater.inflate(R.layout.eip_service_fragment, container, false); ButterKnife.inject(this, view); - if (eip_status.isConnecting()) - eip_switch.setVisibility(View.VISIBLE); - - Log.d(TAG, "onCreateView, eip_switch is checked? " + eip_switch.isChecked()); + if (eip_status.isConnecting()) + eip_switch.setVisibility(View.VISIBLE); Bundle arguments = getArguments(); - if(arguments != null && arguments.containsKey(START_ON_BOOT) && arguments.getBoolean(START_ON_BOOT)) - startEipFromScratch(); + if (arguments != null && arguments.containsKey(START_ON_BOOT) && arguments.getBoolean(START_ON_BOOT)) + startEipFromScratch(); + if (savedInstanceState != null) restoreState(savedInstanceState); + + return view; + } - if (savedInstanceState != null) { + private void restoreState(@NotNull Bundle savedInstanceState) { + if (savedInstanceState.getBoolean(IS_PENDING)) + eip_status.setConnecting(); + else if (savedInstanceState.getBoolean(IS_CONNECTED)) + eip_status.setConnectedOrDisconnected(); + else status_message.setText(savedInstanceState.getString(STATUS_MESSAGE)); - if(savedInstanceState.getBoolean(IS_PENDING)) - eip_status.setConnecting(); - else if(savedInstanceState.getBoolean(IS_CONNECTED)) { - eip_status.setConnectedOrDisconnected(); - } - } - return view; } @Override public void onResume() { - super.onResume(); - eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY); - handleNewState(eip_status); + super.onResume(); + eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY); + handleNewState(eip_status); } - + @Override public void onSaveInstanceState(Bundle outState) { - outState.putBoolean(IS_PENDING, eip_status.isConnecting()); - outState.putBoolean(IS_CONNECTED, eip_status.isConnected()); - Log.d(TAG, "status message onSaveInstanceState = " + status_message.getText().toString()); - outState.putString(STATUS_MESSAGE, status_message.getText().toString()); - super.onSaveInstanceState(outState); + outState.putBoolean(IS_PENDING, eip_status.isConnecting()); + outState.putBoolean(IS_CONNECTED, eip_status.isConnected()); + outState.putString(STATUS_MESSAGE, status_message.getText().toString()); + super.onSaveInstanceState(outState); } protected void saveStatus() { - boolean is_on = eip_switch.isChecked(); - Log.d(TAG, "saveStatus: is_on = " + is_on); - Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, is_on).commit(); + boolean is_on = eip_switch.isChecked(); + Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, is_on).commit(); + } + + void handleNewVpnCertificate() { + handleSwitch(!eip_switch.isEnabled()); } @OnCheckedChanged(R.id.eipSwitch) void handleSwitch(boolean isChecked) { - if(isChecked) - handleSwitchOn(); - else - handleSwitchOff(); - - saveStatus(); + if (isChecked) + handleSwitchOn(); + else + handleSwitchOff(); + + saveStatus(); } private void handleSwitchOn() { - if(canStartEIP()) - startEipFromScratch(); - else if(canLogInToStartEIP()) { - wants_to_connect = true; - Bundle bundle = new Bundle(); - bundle.putBoolean(IS_PENDING, true); - dashboard.sessionDialog(bundle); - } - } - + if (canStartEIP()) + startEipFromScratch(); + else if (canLogInToStartEIP()) { + wants_to_connect = true; + Bundle bundle = new Bundle(); + bundle.putBoolean(IS_PENDING, true); + dashboard.sessionDialog(bundle); + } + } + private boolean canStartEIP() { - boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty(); - boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false); - return (isAllowedAnon || certificateExists) && !eip_status.isConnected() && !eip_status.isConnecting(); + boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty(); + boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false); + return (isAllowedAnon || certificateExists) && !eip_status.isConnected() && !eip_status.isConnecting(); } - + private boolean canLogInToStartEIP() { - boolean isAllowedRegistered = Dashboard.preferences.getBoolean(Constants.ALLOWED_REGISTERED, false); - boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty(); - Log.d(TAG, "Allow registered? " + isAllowedRegistered); - Log.d(TAG, "Is logged in? " + isLoggedIn); - return isAllowedRegistered && !isLoggedIn && !eip_status.isConnecting() && !eip_status.isConnected(); + boolean isAllowedRegistered = Dashboard.preferences.getBoolean(Constants.ALLOWED_REGISTERED, false); + boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty(); + return isAllowedRegistered && !isLoggedIn && !eip_status.isConnecting() && !eip_status.isConnected(); } private void handleSwitchOff() { - if(eip_status.isConnecting()) { - askPendingStartCancellation(); - } else if(eip_status.isConnected()) { - askToStopEIP(); - } - } - - private void askPendingStartCancellation() { - AlertDialog.Builder alertBuilder = new AlertDialog.Builder(dashboard); - alertBuilder.setTitle(dashboard.getString(R.string.eip_cancel_connect_title)) - .setMessage(dashboard.getString(R.string.eip_cancel_connect_text)) - .setPositiveButton((R.string.yes), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - askToStopEIP(); - } - }) - .setNegativeButton(dashboard.getString(R.string.no), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - eip_switch.setChecked(true); - } - }) - .show(); + if (eip_status.isConnecting()) { + askPendingStartCancellation(); + } else if (eip_status.isConnected()) { + askToStopEIP(); + } else + setDisconnectedUI(); + } + + private void askPendingStartCancellation() { + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(dashboard); + alertBuilder.setTitle(dashboard.getString(R.string.eip_cancel_connect_title)) + .setMessage(dashboard.getString(R.string.eip_cancel_connect_text)) + .setPositiveButton((R.string.yes), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + askToStopEIP(); + } + }) + .setNegativeButton(dashboard.getString(R.string.no), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + eip_switch.setChecked(true); + } + }) + .show(); } public void startEipFromScratch() { wants_to_connect = false; is_starting_to_connect = true; progress_bar.setVisibility(View.VISIBLE); - eip_switch.setVisibility(View.VISIBLE); - String status = dashboard.getString(R.string.eip_status_start_pending); - status_message.setText(status); - - if(!eip_switch.isChecked()) { - eip_switch.setChecked(true); - } + eip_switch.setVisibility(View.VISIBLE); + String status = dashboard.getString(R.string.eip_status_start_pending); + status_message.setText(status); + + if (!eip_switch.isChecked()) { + eip_switch.setChecked(true); + } saveStatus(); - eipCommand(Constants.ACTION_START_EIP); + eipCommand(Constants.ACTION_START_EIP); } - private void stopEIP() { - if(eip_status.isConnecting()) - VoidVpnService.stop(); - Intent disconnect_vpn = new Intent(dashboard, DisconnectVPN.class); - dashboard.startActivityForResult(disconnect_vpn, EIP.DISCONNECT); - eip_status.setDisconnecting(); + private void stop() { + if (eip_status.isConnecting()) + VoidVpnService.stop(); + disconnect(); } - protected void askToStopEIP() { + private void disconnect() { + Intent disconnect_vpn = new Intent(dashboard, DisconnectVPN.class); + dashboard.startActivityForResult(disconnect_vpn, EIP.DISCONNECT); + eip_status.setDisconnecting(); + } + + protected void stopEipIfPossible() { + hideProgressBar(); - String status = dashboard.getString(R.string.eip_state_not_connected); - status_message.setText(status); + String message = dashboard.getString(R.string.eip_state_not_connected); + status_message.setText(message); - eipCommand(Constants.ACTION_STOP_EIP); + eipCommand(Constants.ACTION_STOP_EIP); + } + + private void askToStopEIP() { + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(dashboard); + alertBuilder.setTitle(dashboard.getString(R.string.eip_cancel_connect_title)) + .setMessage(dashboard.getString(R.string.eip_warning_browser_inconsistency)) + .setPositiveButton((R.string.yes), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + stopEipIfPossible(); + } + }) + .setNegativeButton(dashboard.getString(R.string.no), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + eip_switch.setChecked(true); + } + }) + .show(); } protected void updateEipService() { eipCommand(Constants.ACTION_UPDATE_EIP_SERVICE); } - + /** * Send a command to EIP - * - * @param action A valid String constant from EIP class representing an Intent - * filter for the EIP class + * + * @param action A valid String constant from EIP class representing an Intent + * filter for the EIP class */ - private void eipCommand(String action){ - // TODO validate "action"...how do we get the list of intent-filters for a class via Android API? - Intent vpn_intent = new Intent(dashboard.getApplicationContext(), EIP.class); - vpn_intent.setAction(action); - vpn_intent.putExtra(Constants.RECEIVER_TAG, mEIPReceiver); - dashboard.startService(vpn_intent); - } - + private void eipCommand(String action) { + // TODO validate "action"...how do we get the list of intent-filters for a class via Android API? + Intent vpn_intent = new Intent(dashboard.getApplicationContext(), EIP.class); + vpn_intent.setAction(action); + vpn_intent.putExtra(Constants.RECEIVER_TAG, mEIPReceiver); + dashboard.startService(vpn_intent); + } + @Override - public void update (Observable observable, Object data) { - if(observable instanceof EipStatus) { - eip_status = (EipStatus) observable; - final EipStatus eip_status = (EipStatus) observable; - dashboard.runOnUiThread(new Runnable() { - @Override - public void run() { - handleNewState(eip_status); - } - }); - } + public void update(Observable observable, Object data) { + if (observable instanceof EipStatus) { + eip_status = (EipStatus) observable; + final EipStatus eip_status = (EipStatus) observable; + dashboard.runOnUiThread(new Runnable() { + @Override + public void run() { + handleNewState(eip_status); + } + }); + } } private void handleNewState(EipStatus eip_status) { - Log.d(TAG, "handleNewState: " + eip_status.toString()); - if(eip_status.wantsToDisconnect()) - setDisconnectedUI(); - else if(eip_status.isConnecting() || is_starting_to_connect) - setInProgressUI(eip_status); - else if (eip_status.isConnected()) - setConnectedUI(); - else if (eip_status.isDisconnected() && !eip_status.isConnecting()) - setDisconnectedUI(); + if (eip_status.wantsToDisconnect()) + setDisconnectedUI(); + else if (eip_status.isConnecting() || is_starting_to_connect) + setInProgressUI(eip_status); + else if (eip_status.isConnected()) + setConnectedUI(); + else if (eip_status.isDisconnected() && !eip_status.isConnecting()) + setDisconnectedUI(); } private void setConnectedUI() { - hideProgressBar(); - Log.d(TAG, "setConnectedUi? " + eip_status.isConnected()); - adjustSwitch(); - is_starting_to_connect = false; - status_message.setText(dashboard.getString(R.string.eip_state_connected)); + hideProgressBar(); + adjustSwitch(); + is_starting_to_connect = false; + status_message.setText(dashboard.getString(R.string.eip_state_connected)); } - private void setDisconnectedUI(){ - hideProgressBar(); - adjustSwitch(); - status_message.setText(dashboard.getString(R.string.eip_state_not_connected)); + private void setDisconnectedUI() { + hideProgressBar(); + adjustSwitch(); + if (eip_status.errorInLast(5, dashboard.getApplicationContext()) + && !status_message.getText().toString().equalsIgnoreCase(dashboard.getString(R.string.eip_state_not_connected))) { + dashboard.showLog(); + VoidVpnService.stop(); + } + status_message.setText(dashboard.getString(R.string.eip_state_not_connected)); } private void adjustSwitch() { - if(eip_status.isConnected() || eip_status.isConnecting() || is_starting_to_connect) { - Log.d(TAG, "adjustSwitch, isConnected || isConnecting, is checked"); - if(!eip_switch.isChecked()) { - eip_switch.setChecked(true); - } - } else { - Log.d(TAG, "adjustSwitch, !isConnected && !isConnecting? " + eip_status.toString()); + if (eip_status.isConnected() || eip_status.isConnecting() || is_starting_to_connect) { + if (!eip_switch.isChecked()) { + eip_switch.setChecked(true); + } + } else { - if(eip_switch.isChecked()) { - eip_switch.setChecked(false); - } - } + if (eip_switch.isChecked()) { + eip_switch.setChecked(false); + } + } } private void setInProgressUI(EipStatus eip_status) { - int localizedResId = eip_status.getLocalizedResId(); - String logmessage = eip_status.getLogMessage(); - String prefix = dashboard.getString(localizedResId); + int localizedResId = eip_status.getLocalizedResId(); + String logmessage = eip_status.getLogMessage(); + String prefix = dashboard.getString(localizedResId); - status_message.setText(prefix + " " + logmessage); + showProgressBar(); + status_message.setText(prefix + " " + logmessage); is_starting_to_connect = false; - adjustSwitch(); + adjustSwitch(); } private void updatingCertificateUI() { - progress_bar.setVisibility(View.VISIBLE); + showProgressBar(); status_message.setText(getString(R.string.updating_certificate_message)); } + private void showProgressBar() { + if (progress_bar != null) + progress_bar.setVisibility(View.VISIBLE); + } + private void hideProgressBar() { - if(progress_bar != null) - progress_bar.setVisibility(View.GONE); + if (progress_bar != null) + progress_bar.setVisibility(View.GONE); } protected class EIPReceiver extends ResultReceiver { - protected EIPReceiver(Handler handler){ - super(handler); - } - - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - super.onReceiveResult(resultCode, resultData); - - String request = resultData.getString(Constants.REQUEST_TAG); - - if (request.equals(Constants.ACTION_START_EIP)) { - switch (resultCode){ - case Activity.RESULT_OK: - break; - case Activity.RESULT_CANCELED: - - break; - } - } else if (request.equals(Constants.ACTION_STOP_EIP)) { - switch (resultCode){ - case Activity.RESULT_OK: - stopEIP(); - break; - case Activity.RESULT_CANCELED: - break; - } - } else if (request.equals(Constants.EIP_NOTIFICATION)) { - switch (resultCode){ - case Activity.RESULT_OK: - break; - case Activity.RESULT_CANCELED: - break; - } - } else if (request.equals(Constants.ACTION_CHECK_CERT_VALIDITY)) { - switch (resultCode) { - case Activity.RESULT_OK: - break; - case Activity.RESULT_CANCELED: - updatingCertificateUI(); - dashboard.downloadVpnCertificate(); - break; - } - } else if (request.equals(Constants.ACTION_UPDATE_EIP_SERVICE)) { - switch (resultCode) { - case Activity.RESULT_OK: - if(wants_to_connect) - startEipFromScratch(); - break; - case Activity.RESULT_CANCELED: - handleNewState(eip_status); - break; + protected EIPReceiver(Handler handler) { + super(handler); + } + + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + super.onReceiveResult(resultCode, resultData); + + String request = resultData.getString(Constants.REQUEST_TAG); + + if (request.equals(Constants.ACTION_START_EIP)) { + switch (resultCode) { + case Activity.RESULT_OK: + break; + case Activity.RESULT_CANCELED: + + break; + } + } else if (request.equals(Constants.ACTION_STOP_EIP)) { + switch (resultCode) { + case Activity.RESULT_OK: + stop(); + break; + case Activity.RESULT_CANCELED: + break; + } + } else if (request.equals(Constants.EIP_NOTIFICATION)) { + switch (resultCode) { + case Activity.RESULT_OK: + break; + case Activity.RESULT_CANCELED: + break; + } + } else if (request.equals(Constants.ACTION_CHECK_CERT_VALIDITY)) { + switch (resultCode) { + case Activity.RESULT_OK: + break; + case Activity.RESULT_CANCELED: + updatingCertificateUI(); + dashboard.downloadVpnCertificate(); + break; + } + } else if (request.equals(Constants.ACTION_UPDATE_EIP_SERVICE)) { + switch (resultCode) { + case Activity.RESULT_OK: + if (wants_to_connect) + startEipFromScratch(); + break; + case Activity.RESULT_CANCELED: + handleNewState(eip_status); + break; + } } } - } } public static EIPReceiver getReceiver() { - return mEIPReceiver; + return mEIPReceiver; } } diff --git a/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java b/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java index 49af9274..8ba7fa34 100644 --- a/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java +++ b/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,33 +16,31 @@ */ package se.leap.bitmaskclient; -import android.app.Fragment; -import android.app.FragmentManager; -import android.app.FragmentTransaction; +import android.app.*; public class FragmentManagerEnhanced { private FragmentManager generic_fragment_manager; - + public FragmentManagerEnhanced(FragmentManager generic_fragment_manager) { - this.generic_fragment_manager = generic_fragment_manager; + this.generic_fragment_manager = generic_fragment_manager; } - + public FragmentTransaction removePreviousFragment(String tag) { - FragmentTransaction transaction = generic_fragment_manager.beginTransaction(); - Fragment previous_fragment = generic_fragment_manager.findFragmentByTag(tag); - if (previous_fragment != null) { - transaction.remove(previous_fragment); - } - transaction.addToBackStack(null); - - return transaction; + FragmentTransaction transaction = generic_fragment_manager.beginTransaction(); + Fragment previous_fragment = generic_fragment_manager.findFragmentByTag(tag); + if (previous_fragment != null) { + transaction.remove(previous_fragment); + } + transaction.addToBackStack(null); + + return transaction; } public void replace(int containerViewId, Fragment fragment, String tag) { - FragmentTransaction transaction = generic_fragment_manager.beginTransaction(); - - transaction.replace(containerViewId, fragment, tag).commit(); + FragmentTransaction transaction = generic_fragment_manager.beginTransaction(); + + transaction.replace(containerViewId, fragment, tag).commit(); } public FragmentTransaction beginTransaction() { @@ -50,6 +48,6 @@ public class FragmentManagerEnhanced { } public Fragment findFragmentByTag(String tag) { - return generic_fragment_manager.findFragmentByTag(tag); + return generic_fragment_manager.findFragmentByTag(tag); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java index 989dc395..b961350e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java +++ b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -14,338 +14,348 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - package se.leap.bitmaskclient; +package se.leap.bitmaskclient; -import org.jboss.security.srp.SRPParameters; +import org.jboss.security.srp.*; -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 java.io.*; +import java.math.*; +import java.security.*; +import java.util.*; /** * Implements all SRP algorithm logic. - * + * <p/> * It's derived from JBoss implementation, with adjustments to make it work with LEAP platform. - * - * @author parmegv * + * @author parmegv */ public class LeapSRPSession { - - private static String token = ""; - - final public static String SALT = "salt"; - final public static String M1 = "M1"; - final public static String M2 = "M2"; - final public static String TOKEN = "token"; - final public static String AUTHORIZATION_HEADER= "Authorization"; - final public static String TAG= "Leap SRP session class tag"; - - 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; - 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 */ - private MessageDigest serverHash; - - private static int A_LEN; - - - /** Creates a new SRP server session object from the username, password - verifier, - @param username, the user ID - @param password, the user clear text password - @param params, the SRP parameters for the session - */ - public LeapSRPSession(String username, String password) - { - this(username, password, null); - } - - /** Creates a new SRP server session object from the username, password - verifier, - @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 - */ - public LeapSRPSession(String username, String password, byte[] abytes) { - - params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256"); - this.g = new BigInteger(1, params.g); - 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? - if( 8*abytes.length != A_LEN ) + + private static String token = ""; + + final public static String SALT = "salt"; + final public static String M1 = "M1"; + final public static String M2 = "M2"; + final public static String TOKEN = "token"; + final public static String AUTHORIZATION_HEADER = "Authorization"; + final public static String TAG = "Leap SRP session class tag"; + + private User user; + 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; + 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 + */ + private MessageDigest serverHash; + + private static int A_LEN; + + + /** + * Creates a new SRP server session object from the username, password + * verifier, + * + * @param username, the user ID + * @param password, the user clear text password + * @param params, the SRP parameters for the session + */ + public LeapSRPSession(String username, String password) { + this(username, password, null); + } + + /** + * Creates a new SRP server session object from the username, password + * verifier, + * + * @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 + */ + public LeapSRPSession(String username, String password, byte[] abytes) { + + params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256"); + this.g = new BigInteger(1, params.g); + 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? + if( 8*abytes.length != A_LEN ) throw new IllegalArgumentException("The abytes param must be " +(A_LEN/8)+" in length, abytes.length="+abytes.length); */ - this.a = new BigInteger(abytes); - } - else - A_LEN = 64; - - serverHash = newDigest(); - clientHash = newDigest(); - } - - /** - * Calculates the parameter x of the SRP-6a algorithm. - * @param username - * @param password - * @param salt the salt of the user - * @return x - */ - 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 ISO-8859-1 - byte[] user = null; - byte[] password_bytes = null; - byte[] colon = {}; - String encoding = "ISO-8859-1"; - try { - 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 = ConfigHelper.trim(username.getBytes()); - colon = ConfigHelper.trim(":".getBytes()); - password_bytes = ConfigHelper.trim(password.getBytes()); - } - - // Build the hash - x_digest.update(user); - x_digest.update(colon); - x_digest.update(password_bytes); - byte[] h = x_digest.digest(); - - x_digest.reset(); - x_digest.update(salt); - x_digest.update(h); - byte[] x_digest_bytes = x_digest.digest(); - - return x_digest_bytes; - } + this.a = new BigInteger(abytes); + } else + A_LEN = 64; + + serverHash = newDigest(); + clientHash = newDigest(); + } + + /** + * Calculates the parameter x of the SRP-6a algorithm. + * + * @param username + * @param password + * @param salt the salt of the user + * @return x + */ + 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 ISO-8859-1 + byte[] user = null; + byte[] password_bytes = null; + byte[] colon = {}; + String encoding = "ISO-8859-1"; + try { + 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 = ConfigHelper.trim(username.getBytes()); + colon = ConfigHelper.trim(":".getBytes()); + password_bytes = ConfigHelper.trim(password.getBytes()); + } + + // Build the hash + x_digest.update(user); + x_digest.update(colon); + x_digest.update(password_bytes); + byte[] h = x_digest.digest(); + + x_digest.reset(); + x_digest.update(salt); + x_digest.update(h); + byte[] x_digest_bytes = x_digest.digest(); + + return x_digest_bytes; + } public byte[] calculateNewSalt() { - try { - BigInteger salt = new BigInteger(64, SecureRandom.getInstance("SHA1PRNG")); - return ConfigHelper.trim(salt.toByteArray()); - } catch(NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return null; + try { + BigInteger salt = new BigInteger(64, SecureRandom.getInstance("SHA1PRNG")); + return ConfigHelper.trim(salt.toByteArray()); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return null; } - /** - * Calculates the parameter V of the SRP-6a algorithm. - * @return the value of V - */ + + /** + * Calculates the parameter V of the SRP-6a algorithm. + * + * @return the value of V + */ public BigInteger calculateV(String username, String password, byte[] salt) { - byte[] x_bytes = calculatePasswordHash(username, password, ConfigHelper.trim(salt)); - x = new BigInteger(1, x_bytes); - BigInteger v = g.modPow(x, N); // g^x % N - return v; - } - - /** - * 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(); - return ConfigHelper.trim(xor_digest); - } - - /** - * @returns The exponential residue (parameter A) to be sent to the server. - */ - public byte[] exponential() { - byte[] Abytes = null; - if(A == null) { + byte[] x_bytes = calculatePasswordHash(username, password, ConfigHelper.trim(salt)); + x = new BigInteger(1, x_bytes); + BigInteger v = g.modPow(x, N); // g^x % N + return v; + } + + /** + * 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(); + return ConfigHelper.trim(xor_digest); + } + + /** + * @returns The exponential residue (parameter A) to be sent to the server. + */ + public byte[] exponential() { + byte[] Abytes = null; + if (A == null) { /* If the random component of A has not been specified use a random number */ - if( a == null ) { - BigInteger one = BigInteger.ONE; - do { - a = new BigInteger(A_LEN, pseudoRng); - } while(a.compareTo(one) <= 0); - } - A = g.modPow(a, N); - Abytes = ConfigHelper.trim(A.toByteArray()); - } - return Abytes; - } - - /** - * 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 - * @return the parameter M1 - * @throws NoSuchAlgorithmException - */ + if (a == null) { + BigInteger one = BigInteger.ONE; + do { + a = new BigInteger(A_LEN, pseudoRng); + } while (a.compareTo(one) <= 0); + } + A = g.modPow(a, N); + Abytes = ConfigHelper.trim(A.toByteArray()); + } + return Abytes; + } + + /** + * 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 + * @return the parameter M1 + * @throws NoSuchAlgorithmException + */ public byte[] response(byte[] salt_bytes, byte[] Bbytes) { - // Calculate x = H(s | H(U | ':' | password)) - byte[] M1 = null; - if(new BigInteger(1, Bbytes).mod(new BigInteger(1, N_bytes)) != BigInteger.ZERO) { - this.v = calculateV(username, password, salt_bytes); - // 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); - clientHash.update(xor_digest); - - // clientHash = H(N) xor H(g) | H(U) - 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(ConfigHelper.trim(salt_bytes)); - - K = null; - - // clientHash = H(N) xor H(g) | H(U) | A - byte[] Abytes = ConfigHelper.trim(A.toByteArray()); - clientHash.update(Abytes); - - // clientHash = H(N) xor H(g) | H(U) | s | A | B - Bbytes = ConfigHelper.trim(Bbytes); - clientHash.update(Bbytes); - - // Calculate S = (B - kg^x) ^ (a + u * x) % N - BigInteger S = calculateS(Bbytes); - byte[] S_bytes = ConfigHelper.trim(S.toByteArray()); - - // K = SessionHash(S) - MessageDigest sessionDigest = newDigest(); - K = ConfigHelper.trim(sessionDigest.digest(S_bytes)); - - // clientHash = H(N) xor H(g) | H(U) | A | B | K - clientHash.update(K); - - M1 = ConfigHelper.trim(clientHash.digest()); - - // serverHash = Astr + M + K - serverHash.update(Abytes); - serverHash.update(M1); - serverHash.update(K); - - } - return M1; - } - - /** - * It calculates the parameter S used by response() to obtain session hash K. - * @param Bbytes the parameter received from the server, in bytes - * @return the parameter S - */ - private BigInteger calculateS(byte[] Bbytes) { - byte[] Abytes = ConfigHelper.trim(A.toByteArray()); - Bbytes = ConfigHelper.trim(Bbytes); - byte[] u_bytes = getU(Abytes, Bbytes); - - BigInteger B = new BigInteger(1, Bbytes); - BigInteger u = new BigInteger(1, u_bytes); - String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; - BigInteger k = new BigInteger(k_string, 16); - BigInteger B_minus_v = B.subtract(k.multiply(v)); - BigInteger a_ux = a.add(u.multiply(x)); - BigInteger S = B_minus_v.modPow(a_ux, N); - return S; - } - - /** - * It calculates the parameter u used by calculateS to obtain S. - * @param Abytes the exponential residue sent to the server - * @param Bbytes the parameter received from the server, in bytes - * @return - */ - public byte[] getU(byte[] Abytes, byte[] Bbytes) { - MessageDigest u_digest = newDigest(); - u_digest.update(ConfigHelper.trim(Abytes)); - u_digest.update(ConfigHelper.trim(Bbytes)); - byte[] u_digest_bytes = u_digest.digest(); - return ConfigHelper.trim(new BigInteger(1, u_digest_bytes).toByteArray()); - } - - /** - * @param M2 The server's response to the client's challenge - * @returns True if and only if the server's response was correct. - */ - public boolean verify(byte[] M2) - { - // M2 = H(A | M1 | K) - M2 = ConfigHelper.trim(M2); - byte[] myM2 = ConfigHelper.trim(serverHash.digest()); - boolean valid = Arrays.equals(M2, myM2); - return valid; - } - - protected static void setToken(String token) { - LeapSRPSession.token = token; - } - - protected static String getToken() { - return token; - } - - /** - * @return a new SHA-256 digest. - */ - public MessageDigest newDigest() - { - MessageDigest md = null; - try { - md = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return md; - } + // Calculate x = H(s | H(U | ':' | password)) + byte[] M1 = null; + if (new BigInteger(1, Bbytes).mod(new BigInteger(1, N_bytes)) != BigInteger.ZERO) { + this.v = calculateV(username, password, salt_bytes); + // 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); + clientHash.update(xor_digest); + + // clientHash = H(N) xor H(g) | H(U) + 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(ConfigHelper.trim(salt_bytes)); + + K = null; + + // clientHash = H(N) xor H(g) | H(U) | A + byte[] Abytes = ConfigHelper.trim(A.toByteArray()); + clientHash.update(Abytes); + + // clientHash = H(N) xor H(g) | H(U) | s | A | B + Bbytes = ConfigHelper.trim(Bbytes); + clientHash.update(Bbytes); + + // Calculate S = (B - kg^x) ^ (a + u * x) % N + BigInteger S = calculateS(Bbytes); + byte[] S_bytes = ConfigHelper.trim(S.toByteArray()); + + // K = SessionHash(S) + MessageDigest sessionDigest = newDigest(); + K = ConfigHelper.trim(sessionDigest.digest(S_bytes)); + + // clientHash = H(N) xor H(g) | H(U) | A | B | K + clientHash.update(K); + + M1 = ConfigHelper.trim(clientHash.digest()); + + // serverHash = Astr + M + K + serverHash.update(Abytes); + serverHash.update(M1); + serverHash.update(K); + + } + return M1; + } + + /** + * It calculates the parameter S used by response() to obtain session hash K. + * + * @param Bbytes the parameter received from the server, in bytes + * @return the parameter S + */ + private BigInteger calculateS(byte[] Bbytes) { + byte[] Abytes = ConfigHelper.trim(A.toByteArray()); + Bbytes = ConfigHelper.trim(Bbytes); + byte[] u_bytes = getU(Abytes, Bbytes); + + BigInteger B = new BigInteger(1, Bbytes); + BigInteger u = new BigInteger(1, u_bytes); + String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; + BigInteger k = new BigInteger(k_string, 16); + BigInteger B_minus_v = B.subtract(k.multiply(v)); + BigInteger a_ux = a.add(u.multiply(x)); + BigInteger S = B_minus_v.modPow(a_ux, N); + return S; + } + + /** + * It calculates the parameter u used by calculateS to obtain S. + * + * @param Abytes the exponential residue sent to the server + * @param Bbytes the parameter received from the server, in bytes + * @return + */ + public byte[] getU(byte[] Abytes, byte[] Bbytes) { + MessageDigest u_digest = newDigest(); + u_digest.update(ConfigHelper.trim(Abytes)); + u_digest.update(ConfigHelper.trim(Bbytes)); + byte[] u_digest_bytes = u_digest.digest(); + return ConfigHelper.trim(new BigInteger(1, u_digest_bytes).toByteArray()); + } + + /** + * @param M2 The server's response to the client's challenge + * @returns True if and only if the server's response was correct. + */ + public boolean verify(byte[] M2) { + // M2 = H(A | M1 | K) + M2 = ConfigHelper.trim(M2); + byte[] myM2 = ConfigHelper.trim(serverHash.digest()); + boolean valid = Arrays.equals(M2, myM2); + return valid; + } + + protected static void setToken(String token) { + LeapSRPSession.token = token; + } + + protected static String getToken() { + return token; + } + + protected static boolean loggedIn() { + return !token.isEmpty(); + } + + /** + * @return a new SHA-256 digest. + */ + public MessageDigest newDigest() { + MessageDigest md = null; + try { + md = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return md; + } public byte[] getK() { - return K; + return K; } } diff --git a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java index 96b87085..9171e816 100644 --- a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java +++ b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java @@ -1,31 +1,25 @@ package se.leap.bitmaskclient; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.util.Log; +import android.content.*; -import se.leap.bitmaskclient.eip.Constants; +import se.leap.bitmaskclient.eip.*; public class OnBootReceiver extends BroadcastReceiver { SharedPreferences preferences; - + // Debug: am broadcast -a android.intent.action.BOOT_COMPLETED @Override public void onReceive(Context context, Intent intent) { - preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE); - boolean provider_configured = !preferences.getString(Provider.KEY, "").isEmpty(); - boolean start_on_boot = preferences.getBoolean(Dashboard.START_ON_BOOT, false); - Log.d("OnBootReceiver", "Provider configured " + String.valueOf(provider_configured)); - Log.d("OnBootReceiver", "Start on boot " + String.valueOf(start_on_boot)); - if(provider_configured && start_on_boot) { - Intent dashboard_intent = new Intent(context, Dashboard.class); - dashboard_intent.setAction(Constants.ACTION_START_EIP); - dashboard_intent.putExtra(Dashboard.ON_BOOT, true); - dashboard_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(dashboard_intent); - } + preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE); + boolean provider_configured = !preferences.getString(Provider.KEY, "").isEmpty(); + boolean start_on_boot = preferences.getBoolean(Dashboard.START_ON_BOOT, false); + if (provider_configured && start_on_boot) { + Intent dashboard_intent = new Intent(context, Dashboard.class); + dashboard_intent.setAction(Constants.ACTION_START_EIP); + dashboard_intent.putExtra(Dashboard.ON_BOOT, true); + dashboard_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(dashboard_intent); + } } } diff --git a/app/src/main/java/se/leap/bitmaskclient/PRNGFixes.java b/app/src/main/java/se/leap/bitmaskclient/PRNGFixes.java index a046f01f..9e523751 100644 --- a/app/src/main/java/se/leap/bitmaskclient/PRNGFixes.java +++ b/app/src/main/java/se/leap/bitmaskclient/PRNGFixes.java @@ -12,28 +12,17 @@ package se.leap.bitmaskclient; * Source: http://android-developers.blogspot.de/2013/08/some-securerandom-thoughts.html */ -import android.os.Build; +import android.os.*; import android.os.Process; -import android.util.Log; - -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.security.NoSuchAlgorithmException; +import android.util.*; + +import java.io.*; +import java.security.*; import java.security.Provider; -import java.security.SecureRandom; -import java.security.SecureRandomSpi; -import java.security.Security; /** * Fixes for the output of the default PRNG having low entropy. - * + * <p/> * The fixes need to be applied via {@link #apply()} before any use of Java * Cryptography Architecture primitives. A good place to invoke them is in the * application's {@code onCreate}. @@ -43,10 +32,13 @@ public final class PRNGFixes { private static final int VERSION_CODE_JELLY_BEAN = 16; private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18; private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL = - getBuildFingerprintAndDeviceSerial(); + getBuildFingerprintAndDeviceSerial(); - /** Hidden constructor to prevent instantiation. */ - private PRNGFixes() {} + /** + * Hidden constructor to prevent instantiation. + */ + private PRNGFixes() { + } /** * Applies all fixes. @@ -113,7 +105,7 @@ public final class PRNGFixes { if ((secureRandomProviders == null) || (secureRandomProviders.length < 1) || (!LinuxPRNGSecureRandomProvider.class.equals( - secureRandomProviders[0].getClass()))) { + secureRandomProviders[0].getClass()))) { Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1); } @@ -138,7 +130,7 @@ public final class PRNGFixes { rng2.getProvider().getClass())) { throw new SecurityException( "SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong" - + " Provider: " + rng2.getProvider().getClass()); + + " Provider: " + rng2.getProvider().getClass()); } } @@ -152,7 +144,7 @@ public final class PRNGFixes { super("LinuxPRNG", 1.0, "A Linux-specific random number provider that uses" - + " /dev/urandom"); + + " /dev/urandom"); // Although /dev/urandom is not a SHA-1 PRNG, some apps // explicitly request a SHA1PRNG SecureRandom and we thus need to // prevent them from getting the default implementation whose output diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index d7ff6633..ee06a586 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,66 +16,56 @@ */ package se.leap.bitmaskclient; -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Parcel; -import android.os.Parcelable; +import android.os.*; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import org.json.*; -import java.io.File; -import java.io.Serializable; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Arrays; -import java.util.Locale; +import java.io.*; +import java.net.*; +import java.util.*; /** * @author Sean Leonard <meanderingcode@aetherislands.net> * @author Parménides GV <parmegv@sdf.org> - * */ public final class Provider implements Parcelable { - private JSONObject definition; // Represents our Provider's provider.json + private JSONObject definition; // Represents our Provider's provider.json private URL main_url; final public static String - API_URL = "api_uri", - API_VERSION = "api_version", - ALLOW_REGISTRATION = "allow_registration", - API_RETURN_SERIAL = "serial", - SERVICE = "service", - KEY = "provider", - CA_CERT = "ca_cert", - CA_CERT_URI = "ca_cert_uri", - CA_CERT_FINGERPRINT = "ca_cert_fingerprint", - NAME = "name", - DESCRIPTION = "description", - DOMAIN = "domain", - MAIN_URL = "main_url", - DOT_JSON_URL = "provider_json_url" - ; - - // Array of what API versions we understand - protected static final String[] API_VERSIONS = {"1"}; // I assume we might encounter arbitrary version "numbers" - // Some API pieces we want to know about - private static final String API_TERM_SERVICES = "services"; - private static final String API_TERM_NAME = "name"; - private static final String API_TERM_DOMAIN = "domain"; - private static final String API_TERM_DEFAULT_LANGUAGE = "default_language"; - protected static final String[] API_EIP_TYPES = {"openvpn"}; - - public Provider(URL main_url) { + API_URL = "api_uri", + API_VERSION = "api_version", + ALLOW_REGISTRATION = "allow_registration", + API_RETURN_SERIAL = "serial", + SERVICE = "service", + KEY = "provider", + CA_CERT = "ca_cert", + CA_CERT_URI = "ca_cert_uri", + CA_CERT_FINGERPRINT = "ca_cert_fingerprint", + NAME = "name", + DESCRIPTION = "description", + DOMAIN = "domain", + MAIN_URL = "main_url", + DOT_JSON_URL = "provider_json_url"; + + // Array of what API versions we understand + protected static final String[] API_VERSIONS = {"1"}; // I assume we might encounter arbitrary version "numbers" + // Some API pieces we want to know about + private static final String API_TERM_SERVICES = "services"; + private static final String API_TERM_NAME = "name"; + private static final String API_TERM_DOMAIN = "domain"; + private static final String API_TERM_DEFAULT_LANGUAGE = "default_language"; + protected static final String[] API_EIP_TYPES = {"openvpn"}; + + public Provider(URL main_url) { this.main_url = main_url; } public Provider(File provider_file) { } + public static final Parcelable.Creator<Provider> CREATOR = new Parcelable.Creator<Provider>() { public Provider createFromParcel(Parcel in) { @@ -91,7 +81,7 @@ public final class Provider implements Parcelable { try { main_url = new URL(in.readString()); String definition_string = in.readString(); - if(definition_string != null) + if (definition_string != null) definition = new JSONObject((definition_string)); } catch (MalformedURLException e) { e.printStackTrace(); @@ -104,60 +94,62 @@ public final class Provider implements Parcelable { definition = provider_json; } - protected JSONObject definition() { return definition; } + protected JSONObject definition() { + return definition; + } - protected String getDomain(){ - return main_url.getHost(); - } + protected String getDomain() { + return main_url.getHost(); + } protected URL mainUrl() { return main_url; } - - protected String getName(){ - // Should we pass the locale in, or query the system here? - String lang = Locale.getDefault().getLanguage(); - String name = ""; - try { - if(definition != null) - name = definition.getJSONObject(API_TERM_NAME).getString(lang); + + protected String getName() { + // Should we pass the locale in, or query the system here? + String lang = Locale.getDefault().getLanguage(); + String name = ""; + try { + if (definition != null) + name = definition.getJSONObject(API_TERM_NAME).getString(lang); else throw new JSONException("Provider not defined"); - } catch (JSONException e) { - if(main_url != null) { + } catch (JSONException e) { + if (main_url != null) { String host = main_url.getHost(); name = host.substring(0, host.indexOf(".")); } - } - - return name; - } - - protected String getDescription(){ - String lang = Locale.getDefault().getLanguage(); - String desc = null; - try { - desc = definition.getJSONObject("description").getString(lang); - } catch (JSONException e) { - // TODO: handle exception!! - try { - desc = definition.getJSONObject("description").getString( definition.getString("default_language") ); - } catch (JSONException e2) { - // TODO: i can't believe you're doing it again! - } - } - - return desc; - } - - protected boolean hasEIP() { - try { + } + + return name; + } + + protected String getDescription() { + String lang = Locale.getDefault().getLanguage(); + String desc = null; + try { + desc = definition.getJSONObject("description").getString(lang); + } catch (JSONException e) { + // TODO: handle exception!! + try { + desc = definition.getJSONObject("description").getString(definition.getString("default_language")); + } catch (JSONException e2) { + // TODO: i can't believe you're doing it again! + } + } + + return desc; + } + + protected boolean hasEIP() { + try { JSONArray services = definition.getJSONArray(API_TERM_SERVICES); // returns ["openvpn"] - for (int i=0;i<API_EIP_TYPES.length+1;i++){ + for (int i = 0; i < API_EIP_TYPES.length + 1; i++) { try { // Walk the EIP types array looking for matches in provider's service definitions - if ( Arrays.asList(API_EIP_TYPES).contains( services.getString(i) ) ) + if (Arrays.asList(API_EIP_TYPES).contains(services.getString(i))) return true; - } catch (NullPointerException e){ + } catch (NullPointerException e) { e.printStackTrace(); return false; } catch (JSONException e) { @@ -166,11 +158,19 @@ public final class Provider implements Parcelable { return false; } } - } catch (Exception e) { - // TODO: handle exception - } - return false; - } + } catch (Exception e) { + // TODO: handle exception + } + return false; + } + + public boolean allowsRegistration() { + try { + return definition.getJSONObject(Provider.SERVICE).getBoolean(Provider.ALLOW_REGISTRATION); + } catch (JSONException e) { + return false; + } + } @Override public int describeContents() { @@ -180,13 +180,13 @@ public final class Provider implements Parcelable { @Override public void writeToParcel(Parcel parcel, int i) { parcel.writeString(main_url.toString()); - if(definition != null) + if (definition != null) parcel.writeString(definition.toString()); } @Override public boolean equals(Object o) { - if(o instanceof Provider) { + if (o instanceof Provider) { Provider p = (Provider) o; return p.mainUrl().getHost().equals(mainUrl().getHost()); } else return false; diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java index 7e4e95d3..533e5caf 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java @@ -1,6 +1,6 @@ /**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,32 +16,30 @@ */
package se.leap.bitmaskclient;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
+import android.os.*;
/**
- * Implements the ResultReceiver needed by Activities using ProviderAPI to receive the results of its operations.
- * @author parmegv
+ * 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;
-
- public ProviderAPIResultReceiver(Handler handler) {
- super(handler);
- // TODO Auto-generated constructor stub
- }
-
- public void setReceiver(Receiver receiver) {
+ private Receiver mReceiver;
+
+ public ProviderAPIResultReceiver(Handler handler) {
+ 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
- *
- */
+ /**
+ * Interface to enable ProviderAPIResultReceiver to receive results from the ProviderAPI IntentService.
+ *
+ * @author parmegv
+ */
public interface Receiver {
public void onReceiveResult(int resultCode, Bundle resultData);
}
@@ -52,5 +50,5 @@ public class ProviderAPIResultReceiver extends ResultReceiver { mReceiver.onReceiveResult(resultCode, resultData);
}
}
-
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java index c63e2edb..4a34caa0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java @@ -1,44 +1,35 @@ package se.leap.bitmaskclient; -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TwoLineListItem; +import android.view.*; -import com.pedrogomez.renderers.AdapteeCollection; -import com.pedrogomez.renderers.RendererAdapter; -import com.pedrogomez.renderers.RendererBuilder; +import com.pedrogomez.renderers.*; -import java.util.Collection; -import java.util.List; -import java.util.Set; +import java.util.*; public class ProviderListAdapter extends RendererAdapter<Provider> { - private static boolean[] hidden = null; - - public void hide(int position) { - hidden[getRealPosition(position)] = true; - notifyDataSetChanged(); - notifyDataSetInvalidated(); - } - - public void unHide(int position) { - hidden[getRealPosition(position)] = false; - notifyDataSetChanged(); - notifyDataSetInvalidated(); - } + private static boolean[] hidden = null; + + public void hide(int position) { + hidden[getRealPosition(position)] = true; + notifyDataSetChanged(); + notifyDataSetInvalidated(); + } + + public void unHide(int position) { + hidden[getRealPosition(position)] = false; + notifyDataSetChanged(); + notifyDataSetInvalidated(); + } public void showAllProviders() { - for(int i = 0; i < hidden.length; i++) + for (int i = 0; i < hidden.length; i++) hidden[i] = false; notifyDataSetChanged(); notifyDataSetInvalidated(); } - + public void hideAllBut(int position) { - for (int i = 0; i < hidden.length; i++) { + for (int i = 0; i < hidden.length; i++) { if (i != position) hidden[i] = true; else @@ -47,64 +38,66 @@ public class ProviderListAdapter extends RendererAdapter<Provider> { notifyDataSetChanged(); notifyDataSetInvalidated(); } - - private int getRealPosition(int position) { - int hElements = getHiddenCountUpTo(position); - int diff = 0; - for(int i=0;i<hElements;i++) { - diff++; - if(hidden[position+diff]) - i--; - } - return (position + diff); - } - private int getHiddenCount() { - int count = 0; - for(int i=0;i<hidden.length;i++) - if(hidden[i]) - count++; - return count; - } - private int getHiddenCountUpTo(int location) { - int count = 0; - for(int i=0;i<=location;i++) { - if(hidden[i]) - count++; - } - return count; - } - - @Override - public int getCount() { - return (hidden.length - getHiddenCount()); - } + + private int getRealPosition(int position) { + int hElements = getHiddenCountUpTo(position); + int diff = 0; + for (int i = 0; i < hElements; i++) { + diff++; + if (hidden[position + diff]) + i--; + } + return (position + diff); + } + + private int getHiddenCount() { + int count = 0; + for (int i = 0; i < hidden.length; i++) + if (hidden[i]) + count++; + return count; + } + + private int getHiddenCountUpTo(int location) { + int count = 0; + for (int i = 0; i <= location; i++) { + if (hidden[i]) + count++; + } + return count; + } + + @Override + public int getCount() { + return (hidden.length - getHiddenCount()); + } public ProviderListAdapter(LayoutInflater layoutInflater, RendererBuilder rendererBuilder, AdapteeCollection<Provider> collection) { - super(layoutInflater, rendererBuilder, collection); - hidden = new boolean[collection.size()]; - for (int i = 0; i < collection.size(); i++) - hidden[i] = false; + super(layoutInflater, rendererBuilder, collection); + hidden = new boolean[collection.size()]; + for (int i = 0; i < collection.size(); i++) + hidden[i] = false; } - - @Override - public void add(Provider item) { - super.add(item); - if(getCollection().size() > hidden.length) { + + @Override + public void add(Provider item) { + super.add(item); + if (getCollection().size() > hidden.length) { boolean[] new_hidden = new boolean[hidden.length + 1]; System.arraycopy(hidden, 0, new_hidden, 0, hidden.length); new_hidden[hidden.length] = false; hidden = new_hidden; } - } - - @Override - public void remove(Provider item) { - super.remove(item); - boolean[] new_hidden = new boolean[hidden.length-1]; - System.arraycopy(hidden, 0, new_hidden, 0, hidden.length-1); - hidden = new_hidden; - } + } + + @Override + public void remove(Provider item) { + super.remove(item); + boolean[] new_hidden = new boolean[hidden.length - 1]; + System.arraycopy(hidden, 0, new_hidden, 0, hidden.length - 1); + hidden = new_hidden; + } protected int indexOf(Provider item) { int index = 0; diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java index 69bd7c1e..40fe8b5a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java @@ -1,25 +1,14 @@ package se.leap.bitmaskclient; -import android.content.res.AssetManager; - -import com.pedrogomez.renderers.AdapteeCollection; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; +import android.content.res.*; + +import com.pedrogomez.renderers.*; + +import org.json.*; + +import java.io.*; +import java.net.*; +import java.util.*; /** * Created by parmegv on 4/12/14. @@ -36,7 +25,7 @@ public class ProviderManager implements AdapteeCollection<Provider> { final protected static String URLS = "urls"; public static ProviderManager getInstance(AssetManager assets_manager, File external_files_dir) { - if(instance == null) + if (instance == null) instance = new ProviderManager(assets_manager); instance.addCustomProviders(external_files_dir); @@ -59,10 +48,10 @@ public class ProviderManager implements AdapteeCollection<Provider> { private Set<Provider> providersFromAssets(String directory, String[] relative_file_paths) { Set<Provider> providers = new HashSet<Provider>(); try { - for(String file : relative_file_paths) { - String main_url = extractMainUrlFromInputStream(assets_manager.open(directory + "/" + file)); + for (String file : relative_file_paths) { + String main_url = extractMainUrlFromInputStream(assets_manager.open(directory + "/" + file)); providers.add(new Provider(new URL(main_url))); - } + } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { @@ -82,7 +71,7 @@ public class ProviderManager implements AdapteeCollection<Provider> { private Set<Provider> providersFromFiles(String[] files) { Set<Provider> providers = new HashSet<Provider>(); try { - for(String file : files) { + for (String file : files) { String main_url = extractMainUrlFromInputStream(new FileInputStream(external_files_dir.getAbsolutePath() + "/" + file)); providers.add(new Provider(new URL(main_url))); } @@ -100,7 +89,7 @@ public class ProviderManager implements AdapteeCollection<Provider> { byte[] bytes = new byte[0]; try { bytes = new byte[input_stream_file_contents.available()]; - if(input_stream_file_contents.read(bytes) > 0) { + if (input_stream_file_contents.read(bytes) > 0) { JSONObject file_contents = new JSONObject(new String(bytes)); main_url = file_contents.getString(Provider.MAIN_URL); } @@ -127,7 +116,7 @@ public class ProviderManager implements AdapteeCollection<Provider> { @Override public Provider get(int index) { Iterator<Provider> iterator = providers().iterator(); - while(iterator.hasNext() && index > 0) { + while (iterator.hasNext() && index > 0) { iterator.next(); index--; } @@ -136,7 +125,7 @@ public class ProviderManager implements AdapteeCollection<Provider> { @Override public void add(Provider element) { - if(!default_providers.contains(element)) + if (!default_providers.contains(element)) custom_providers.add(element); } @@ -163,17 +152,17 @@ public class ProviderManager implements AdapteeCollection<Provider> { } protected void saveCustomProvidersToFile() { - try { - for (Provider provider : custom_providers) { + try { + for (Provider provider : custom_providers) { File provider_file = new File(external_files_dir, provider.getName() + ".json"); - if(!provider_file.exists()) { - FileWriter writer = new FileWriter(provider_file); - writer.write(provider.toJson().toString()); - writer.close(); + if (!provider_file.exists()) { + FileWriter writer = new FileWriter(provider_file); + writer.write(provider.toJson().toString()); + writer.close(); + } } - } - } catch (IOException e) { - e.printStackTrace(); - } + } catch (IOException e) { + e.printStackTrace(); + } } } diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java b/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java index 6e194e84..4a5d0db1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java @@ -1,18 +1,12 @@ package se.leap.bitmaskclient; -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import com.pedrogomez.renderers.Renderer; - -import butterknife.ButterKnife; -import butterknife.InjectView; -import butterknife.OnItemClick; -import butterknife.OnItemSelected; +import android.content.*; +import android.view.*; +import android.widget.*; + +import com.pedrogomez.renderers.*; + +import butterknife.*; /** * Created by parmegv on 4/12/14. diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java b/app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java index 7366e68e..5a6e857d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java @@ -1,25 +1,19 @@ package se.leap.bitmaskclient; -import android.content.Context; +import com.pedrogomez.renderers.*; -import com.pedrogomez.renderers.Renderer; -import com.pedrogomez.renderers.RendererBuilder; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; - -import javax.inject.Inject; +import java.util.*; /** * Created by parmegv on 4/12/14. */ - public class ProviderRendererBuilder extends RendererBuilder<Provider> { - public ProviderRendererBuilder(Collection<Renderer<Provider>> prototypes) { - super(prototypes); - } - @Override - protected Class getPrototypeClass(Provider content) { - return ProviderRenderer.class; +public class ProviderRendererBuilder extends RendererBuilder<Provider> { + public ProviderRendererBuilder(Collection<Renderer<Provider>> prototypes) { + super(prototypes); + } + + @Override + protected Class getPrototypeClass(Provider content) { + return ProviderRenderer.class; } } diff --git a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java index 9025564b..e92c6b7b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -14,42 +14,38 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - package se.leap.bitmaskclient; - -import android.app.Activity; -import android.app.AlertDialog; -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.TextView; +package se.leap.bitmaskclient; -import org.jetbrains.annotations.NotNull; +import android.app.*; +import android.content.*; +import android.os.*; +import android.view.*; +import android.widget.*; -import butterknife.ButterKnife; -import butterknife.InjectView; +import butterknife.*; /** * Implements the log in dialog, currently without progress dialog. - * + * <p/> * 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 + * <p/> + * It also notifies the user if the password is not valid. * + * @author parmegv */ -public class SessionDialog extends DialogFragment{ +public class SessionDialog extends DialogFragment { + - final public static String TAG = SessionDialog.class.getSimpleName(); final public static String USERNAME = "username"; final public static String PASSWORD = "password"; - final public static String USERNAME_MISSING = "username missing"; - final public static String PASSWORD_INVALID_LENGTH = "password_invalid_length"; + + public static enum ERRORS { + USERNAME_MISSING, + PASSWORD_INVALID_LENGTH, + RISEUP_WARNING + } @InjectView(R.id.user_message) TextView user_message; @@ -63,63 +59,67 @@ public class SessionDialog extends DialogFragment{ public SessionDialog() { setArguments(Bundle.EMPTY); } - - public AlertDialog onCreateDialog(Bundle savedInstanceState) { - - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - LayoutInflater inflater = getActivity().getLayoutInflater(); - View view = inflater.inflate(R.layout.session_dialog, null); - ButterKnife.inject(this, view); - - Bundle arguments = getArguments(); - if (arguments != Bundle.EMPTY) { + + public AlertDialog onCreateDialog(Bundle savedInstanceState) { + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + LayoutInflater inflater = getActivity().getLayoutInflater(); + View view = inflater.inflate(R.layout.session_dialog, null); + ButterKnife.inject(this, view); + + Bundle arguments = getArguments(); + if (arguments != Bundle.EMPTY) { setUp(arguments); - } - - builder.setView(view) - .setPositiveButton(R.string.login_button, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - String username = getEnteredUsername(); - String password = getEnteredPassword(); - dialog.dismiss(); - interface_with_Dashboard.logIn(username, password); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - interface_with_Dashboard.cancelLoginOrSignup(); - } - }) - .setNeutralButton(R.string.signup_button, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - String username = getEnteredUsername(); - String password = getEnteredPassword(); - dialog.dismiss(); - interface_with_Dashboard.signUp(username, password); - } - }); - - return builder.create(); - } + } + + builder.setView(view) + .setPositiveButton(R.string.login_button, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + String username = getEnteredUsername(); + String password = getEnteredPassword(); + dialog.dismiss(); + interface_with_Dashboard.logIn(username, password); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + interface_with_Dashboard.cancelLoginOrSignup(); + } + }) + .setNeutralButton(R.string.signup_button, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + String username = getEnteredUsername(); + String password = getEnteredPassword(); + dialog.dismiss(); + interface_with_Dashboard.signUp(username, password); + } + }); + + return builder.create(); + } private void setUp(Bundle arguments) { is_eip_pending = arguments.getBoolean(EipFragment.IS_PENDING, false); - if (arguments.containsKey(PASSWORD_INVALID_LENGTH)) + if (arguments.containsKey(ERRORS.PASSWORD_INVALID_LENGTH.toString())) password_field.setError(getString(R.string.error_not_valid_password_user_message)); + else if (arguments.containsKey(ERRORS.RISEUP_WARNING.toString())) { + user_message.setVisibility(TextView.VISIBLE); + user_message.setText(R.string.login_riseup_warning); + } if (arguments.containsKey(USERNAME)) { String username = arguments.getString(USERNAME); username_field.setText(username); } - if (arguments.containsKey(USERNAME_MISSING)) { + if (arguments.containsKey(ERRORS.USERNAME_MISSING.toString())) { username_field.setError(getString(R.string.username_ask)); } - if(arguments.containsKey(getString(R.string.user_message))) + if (arguments.containsKey(getString(R.string.user_message))) user_message.setText(arguments.getString(getString(R.string.user_message))); - else + else if (user_message.getVisibility() != TextView.VISIBLE) user_message.setVisibility(View.GONE); - if(!username_field.getText().toString().isEmpty() && password_field.isFocusable()) + if (!username_field.getText().toString().isEmpty() && password_field.isFocusable()) password_field.requestFocus(); } @@ -132,26 +132,27 @@ public class SessionDialog extends DialogFragment{ return password_field.getText().toString(); } - - /** - * Interface used to communicate SessionDialog with Dashboard. - * - * @author parmegv - * - */ - public interface SessionDialogInterface { - public void logIn(String username, String password); - public void signUp(String username, String password); - public void cancelLoginOrSignup(); + + /** + * Interface used to communicate SessionDialog with Dashboard. + * + * @author parmegv + */ + public interface SessionDialogInterface { + public void logIn(String username, String password); + + public void signUp(String username, String password); + + public void cancelLoginOrSignup(); } - SessionDialogInterface interface_with_Dashboard; - + SessionDialogInterface interface_with_Dashboard; + @Override public void onAttach(Activity activity) { super.onAttach(activity); try { - interface_with_Dashboard = (SessionDialogInterface) activity; + interface_with_Dashboard = (SessionDialogInterface) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement LogInDialogListener"); @@ -160,8 +161,8 @@ public class SessionDialog extends DialogFragment{ @Override public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); - if(is_eip_pending) - interface_with_Dashboard.cancelLoginOrSignup(); + super.onCancel(dialog); + if (is_eip_pending) + interface_with_Dashboard.cancelLoginOrSignup(); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/User.java b/app/src/main/java/se/leap/bitmaskclient/User.java new file mode 100644 index 00000000..4bbd9a91 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/User.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2013 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package se.leap.bitmaskclient; + +public class User { + private static String user_name = "You"; + private static User user; + + public static User getInstance() { + if (user == null) { + user = new User(); + } + return user; + } + + public static void setUserName(String user_name) { + User.user_name = user_name; + } + + private User() { + } + + public static String userName() { + return user_name; + } + + public static boolean loggedIn() { + return LeapSRPSession.loggedIn(); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java new file mode 100644 index 00000000..e43c8a25 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2013 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package se.leap.bitmaskclient; + +import android.os.*; + +import java.util.*; + +public class UserSessionStatus extends Observable { + public static String TAG = UserSessionStatus.class.getSimpleName(); + private static UserSessionStatus current_status; + + public enum SessionStatus { + LOGGED_IN, + LOGGED_OUT, + NOT_LOGGED_IN, + DIDNT_LOG_OUT, + LOGGING_IN, + LOGGING_OUT, + SIGNING_UP + } + + private static SessionStatus session_status = SessionStatus.NOT_LOGGED_IN; + + public static UserSessionStatus getInstance() { + if (current_status == null) { + current_status = new UserSessionStatus(); + } + return current_status; + } + + private UserSessionStatus() { + } + + private void sessionStatus(SessionStatus session_status) { + this.session_status = session_status; + } + + public SessionStatus sessionStatus() { + return session_status; + } + + public boolean inProgress() { + return session_status == SessionStatus.LOGGING_IN + || session_status == SessionStatus.LOGGING_OUT; + } + + public static void updateStatus(SessionStatus session_status) { + current_status = getInstance(); + current_status.sessionStatus(session_status); + current_status.setChanged(); + current_status.notifyObservers(); + } + + @Override + public String toString() { + String username = User.userName(); + + return username + " " + conjugateToBe(username) + " " + + session_status.toString().toLowerCase().replaceAll("_", " "); + } + + private String conjugateToBe(String subject) { + String conjugation = ""; + if(subject.equalsIgnoreCase("I")) + conjugation = "am"; + else if(subject.equalsIgnoreCase("you") || subject.equalsIgnoreCase("we")|| subject.equalsIgnoreCase("they")) + conjugation = "are"; + else conjugation = "is"; + + return conjugation; + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java index 12c2e015..39ad7c08 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -17,17 +17,14 @@ package se.leap.bitmaskclient.eip; /** - * * Constants for intent passing, shared preferences * * @author Parménides GV <parmegv@sdf.org> - * */ public interface Constants { public final static String TAG = Constants.class.getSimpleName(); - - public final static String AUTHED_EIP = TAG + ".AUTHED_EIP"; + public final static String ACTION_CHECK_CERT_VALIDITY = TAG + ".CHECK_CERT_VALIDITY"; public final static String ACTION_START_EIP = TAG + ".START_EIP"; public final static String ACTION_STOP_EIP = TAG + ".STOP_EIP"; diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index 3b72a486..beed7948 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -19,7 +19,6 @@ package se.leap.bitmaskclient.eip; import android.app.*; import android.content.*; import android.os.*; -import android.util.Log; import org.json.*; @@ -34,7 +33,7 @@ import static se.leap.bitmaskclient.eip.Constants.*; * this IntentService. * Contains logic for parsing eip-service.json from the provider, configuring and selecting * gateways, and controlling {@link de.blinkt.openvpn.core.OpenVPNService} connections. - * + * * @author Sean Leonard <meanderingcode@aetherislands.net> * @author Parménides GV <parmegv@sdf.org> */ @@ -44,64 +43,64 @@ public final class EIP extends IntentService { public final static String SERVICE_API_PATH = "config/eip-service.json"; public static final int DISCONNECT = 15; - + private static Context context; private static ResultReceiver mReceiver; private static SharedPreferences preferences; - + private static JSONObject eip_definition; private static GatewaysManager gateways_manager = new GatewaysManager(); private static Gateway gateway; - - public EIP(){ - super(TAG); + + public EIP() { + super(TAG); } - + @Override public void onCreate() { - super.onCreate(); - - context = getApplicationContext(); + super.onCreate(); + + context = getApplicationContext(); preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); - eip_definition = eipDefinitionFromPreferences(); - if(gateways_manager.isEmpty()) + eip_definition = eipDefinitionFromPreferences(); + if (gateways_manager.isEmpty()) gatewaysFromPreferences(); } @Override protected void onHandleIntent(Intent intent) { - String action = intent.getAction(); - mReceiver = intent.getParcelableExtra(RECEIVER_TAG); - - if ( action.equals(ACTION_START_EIP)) - startEIP(); - else if (action.equals(ACTION_STOP_EIP)) - stopEIP(); - else if (action.equals(ACTION_IS_EIP_RUNNING)) - isRunning(); + String action = intent.getAction(); + mReceiver = intent.getParcelableExtra(RECEIVER_TAG); + + if (action.equals(ACTION_START_EIP)) + startEIP(); + else if (action.equals(ACTION_STOP_EIP)) + stopEIP(); + else if (action.equals(ACTION_IS_EIP_RUNNING)) + isRunning(); else if (action.equals(ACTION_UPDATE_EIP_SERVICE)) - updateEIPService(); - else if (action.equals(ACTION_CHECK_CERT_VALIDITY)) - checkCertValidity(); + updateEIPService(); + else if (action.equals(ACTION_CHECK_CERT_VALIDITY)) + checkCertValidity(); } - + /** * Initiates an EIP connection by selecting a gateway and preparing and sending an * Intent to {@link de.blinkt.openvpn.LaunchVPN}. * It also sets up early routes. */ private void startEIP() { - if(gateways_manager.isEmpty()) - updateEIPService(); + if (gateways_manager.isEmpty()) + updateEIPService(); earlyRoutes(); - gateway = gateways_manager.select(); - if(gateway != null && gateway.getProfile() != null) { - mReceiver = EipFragment.getReceiver(); - launchActiveGateway(); - tellToReceiver(ACTION_START_EIP, Activity.RESULT_OK); - } else - tellToReceiver(ACTION_START_EIP, Activity.RESULT_CANCELED); + gateway = gateways_manager.select(); + if (gateway != null && gateway.getProfile() != null) { + mReceiver = EipFragment.getReceiver(); + launchActiveGateway(); + tellToReceiver(ACTION_START_EIP, Activity.RESULT_OK); + } else + tellToReceiver(ACTION_START_EIP, Activity.RESULT_CANCELED); } /** @@ -109,40 +108,40 @@ public final class EIP extends IntentService { * VpnService is started properly. */ private void earlyRoutes() { - Intent void_vpn_launcher = new Intent(context, VoidVpnLauncher.class); - void_vpn_launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(void_vpn_launcher); + Intent void_vpn_launcher = new Intent(context, VoidVpnLauncher.class); + void_vpn_launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(void_vpn_launcher); } - + private void launchActiveGateway() { - Intent intent = new Intent(this,LaunchVPN.class); - intent.setAction(Intent.ACTION_MAIN); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(LaunchVPN.EXTRA_NAME, gateway.getProfile().getName()); - intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true); - startActivity(intent); + Intent intent = new Intent(this, LaunchVPN.class); + intent.setAction(Intent.ACTION_MAIN); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(LaunchVPN.EXTRA_NAME, gateway.getProfile().getName()); + intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true); + startActivity(intent); } private void stopEIP() { - EipStatus eip_status = EipStatus.getInstance(); - int result_code = Activity.RESULT_CANCELED; - if(eip_status.isConnected() || eip_status.isConnecting()) - result_code = Activity.RESULT_OK; + EipStatus eip_status = EipStatus.getInstance(); + int result_code = Activity.RESULT_CANCELED; + if (eip_status.isConnected() || eip_status.isConnecting()) + result_code = Activity.RESULT_OK; - tellToReceiver(ACTION_STOP_EIP, result_code); + tellToReceiver(ACTION_STOP_EIP, result_code); } - + /** * Checks the last stored status notified by ics-openvpn * Sends <code>Activity.RESULT_CANCELED</code> to the ResultReceiver that made the * request if it's not connected, <code>Activity.RESULT_OK</code> otherwise. */ private void isRunning() { - EipStatus eip_status = EipStatus.getInstance(); - int resultCode = (eip_status.isConnected()) ? - Activity.RESULT_OK : - Activity.RESULT_CANCELED; - tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode); + EipStatus eip_status = EipStatus.getInstance(); + int resultCode = (eip_status.isConnected()) ? + Activity.RESULT_OK : + Activity.RESULT_CANCELED; + tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode); } /** @@ -150,27 +149,27 @@ public final class EIP extends IntentService { * TODO Implement API call to refresh eip-service.json from the provider */ private void updateEIPService() { - eip_definition = eipDefinitionFromPreferences(); - if(eip_definition.length() > 0) + eip_definition = eipDefinitionFromPreferences(); + if (eip_definition.length() > 0) updateGateways(); - tellToReceiver(ACTION_UPDATE_EIP_SERVICE, Activity.RESULT_OK); + tellToReceiver(ACTION_UPDATE_EIP_SERVICE, Activity.RESULT_OK); } private JSONObject eipDefinitionFromPreferences() { JSONObject result = new JSONObject(); - try { - String eip_definition_string = preferences.getString(KEY, ""); - if(!eip_definition_string.isEmpty()) { - result = new JSONObject(eip_definition_string); - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + try { + String eip_definition_string = preferences.getString(KEY, ""); + if (!eip_definition_string.isEmpty()) { + result = new JSONObject(eip_definition_string); + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } return result; } - private void updateGateways(){ + private void updateGateways() { gateways_manager.fromEipServiceJson(eip_definition); gatewaysToPreferences(); } @@ -188,15 +187,15 @@ public final class EIP extends IntentService { } private void checkCertValidity() { - VpnCertificateValidator validator = new VpnCertificateValidator(preferences.getString(CERTIFICATE, "")); - int resultCode = validator.isValid() ? - Activity.RESULT_OK : - Activity.RESULT_CANCELED; - tellToReceiver(ACTION_CHECK_CERT_VALIDITY, resultCode); + VpnCertificateValidator validator = new VpnCertificateValidator(preferences.getString(CERTIFICATE, "")); + int resultCode = validator.isValid() ? + Activity.RESULT_OK : + Activity.RESULT_CANCELED; + tellToReceiver(ACTION_CHECK_CERT_VALIDITY, resultCode); } private void tellToReceiver(String action, int resultCode) { - if (mReceiver != null){ + if (mReceiver != null) { Bundle resultData = new Bundle(); resultData.putString(REQUEST_TAG, action); mReceiver.send(resultCode, resultData); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java index 4ac3bd6a..ad68f96e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,11 +16,11 @@ */ package se.leap.bitmaskclient.eip; -import android.util.Log; +import android.content.*; -import java.util.Observable; +import java.util.*; -import de.blinkt.openvpn.core.VpnStatus; +import de.blinkt.openvpn.core.*; public class EipStatus extends Observable implements VpnStatus.StateListener { public static String TAG = EipStatus.class.getSimpleName(); @@ -33,106 +33,123 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { private int localized_res_id; public static EipStatus getInstance() { - if(current_status == null) { - current_status = new EipStatus(); - VpnStatus.addStateListener(current_status); - } - return current_status; + if (current_status == null) { + current_status = new EipStatus(); + VpnStatus.addStateListener(current_status); + } + return current_status; } - private EipStatus() { } + private EipStatus() { + } @Override public void updateState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) { - current_status = getInstance(); - current_status.setState(state); - current_status.setLogMessage(logmessage); - current_status.setLocalizedResId(localizedResId); - current_status.setLevel(level); - current_status.setChanged(); - if(isConnected() || isDisconnected()) - setConnectedOrDisconnected(); - else if(isConnecting()) - setConnecting(); - Log.d(TAG, "update state with level " + level); - current_status.notifyObservers(); + updateStatus(state, logmessage, localizedResId, level); + if (isConnected() || isDisconnected()) { + setConnectedOrDisconnected(); + } else if (isConnecting()) + setConnecting(); + } + + private void updateStatus(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) { + current_status = getInstance(); + current_status.setState(state); + current_status.setLogMessage(logmessage); + current_status.setLocalizedResId(localizedResId); + current_status.setLevel(level); + current_status.setChanged(); } public boolean wantsToDisconnect() { - return wants_to_disconnect; + return wants_to_disconnect; } public boolean isConnecting() { - return - !isConnected() && - !isDisconnected() && - !isPaused(); + return + !isConnected() && + !isDisconnected() && + !isPaused(); } public boolean isConnected() { - return level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED; + return level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED; } public boolean isDisconnected() { - return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; + return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; } public boolean isPaused() { - return level == VpnStatus.ConnectionStatus.LEVEL_VPNPAUSED; + return level == VpnStatus.ConnectionStatus.LEVEL_VPNPAUSED; } public void setConnecting() { - wants_to_disconnect = false; - current_status.setChanged(); - current_status.notifyObservers(); + wants_to_disconnect = false; + current_status.setChanged(); + current_status.notifyObservers(); } public void setConnectedOrDisconnected() { - Log.d(TAG, "setConnectedOrDisconnected()"); - wants_to_disconnect = false; - current_status.setChanged(); - current_status.notifyObservers(); + wants_to_disconnect = false; + current_status.setChanged(); + current_status.notifyObservers(); } public void setDisconnecting() { - wants_to_disconnect = false; + wants_to_disconnect = false; } public String getState() { - return state; + return state; } public String getLogMessage() { - return log_message; + return log_message; } public int getLocalizedResId() { - return localized_res_id; + return localized_res_id; } public VpnStatus.ConnectionStatus getLevel() { - return level; + return level; } private void setState(String state) { - this.state = state; + this.state = state; } private void setLogMessage(String log_message) { - this.log_message = log_message; + this.log_message = log_message; } private void setLocalizedResId(int localized_res_id) { - this.localized_res_id = localized_res_id; + this.localized_res_id = localized_res_id; } private void setLevel(VpnStatus.ConnectionStatus level) { - EipStatus.level = level; + EipStatus.level = level; + } + + public boolean errorInLast(int lines, Context context) { + boolean result = false; + String[] error_keywords = {"error", "ERROR", "fatal", "FATAL"}; + + VpnStatus.LogItem[] log = VpnStatus.getlogbuffer(); + String message = ""; + for (int i = 1; i <= lines && log.length > i; i++) { + message = log[log.length - i].getString(context); + for (int j = 0; j < error_keywords.length; j++) + if (message.contains(error_keywords[j])) + result = true; + } + return result; } @Override public String toString() { - return "State: " + state + " Level: " + level.toString(); + return "State: " + state + " Level: " + level.toString(); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java index 0d8a2f7b..ff7d011e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,32 +16,25 @@ */ package se.leap.bitmaskclient.eip; -import android.app.Activity; -import android.content.SharedPreferences; -import android.util.Log; - -import com.google.gson.Gson; +import com.google.gson.*; -import org.json.JSONException; -import org.json.JSONObject; +import org.json.*; -import java.io.IOException; -import java.io.StringReader; +import java.io.*; -import de.blinkt.openvpn.VpnProfile; -import de.blinkt.openvpn.core.ConfigParser; -import se.leap.bitmaskclient.Dashboard; +import de.blinkt.openvpn.*; +import de.blinkt.openvpn.core.*; /** * Gateway provides objects defining gateways and their metadata. * Each instance contains a VpnProfile for OpenVPN specific data and member * variables describing capabilities and location (name) - * + * * @author Sean Leonard <meanderingcode@aetherislands.net> * @author Parménides GV <parmegv@sdf.org> */ public class Gateway { - + public final static String TAG = Gateway.class.getSimpleName(); private JSONObject general_configuration; @@ -51,86 +44,85 @@ public class Gateway { private String mName; private int timezone; private VpnProfile mVpnProfile; + /** * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json * and create a VpnProfile belonging to it. */ - public Gateway(JSONObject eip_definition, JSONObject secrets, JSONObject gateway){ + public Gateway(JSONObject eip_definition, JSONObject secrets, JSONObject gateway) { - this.gateway = gateway; + this.gateway = gateway; this.secrets = secrets; - general_configuration = getGeneralConfiguration(eip_definition); - timezone = getTimezone(eip_definition); - mName = locationAsName(eip_definition); + general_configuration = getGeneralConfiguration(eip_definition); + timezone = getTimezone(eip_definition); + mName = locationAsName(eip_definition); - mVpnProfile = createVPNProfile(); - mVpnProfile.mName = mName; + mVpnProfile = createVPNProfile(); + mVpnProfile.mName = mName; } private JSONObject getGeneralConfiguration(JSONObject eip_definition) { - try { - return eip_definition.getJSONObject("openvpn_configuration"); - } catch (JSONException e) { - return new JSONObject(); - } + try { + return eip_definition.getJSONObject("openvpn_configuration"); + } catch (JSONException e) { + return new JSONObject(); + } } private int getTimezone(JSONObject eip_definition) { - JSONObject location = getLocationInfo(eip_definition); - return location.optInt("timezone"); + JSONObject location = getLocationInfo(eip_definition); + return location.optInt("timezone"); } private String locationAsName(JSONObject eip_definition) { - JSONObject location = getLocationInfo(eip_definition); - return location.optString("name"); + JSONObject location = getLocationInfo(eip_definition); + return location.optString("name"); } private JSONObject getLocationInfo(JSONObject eip_definition) { - try { - JSONObject locations = eip_definition.getJSONObject("locations"); + try { + JSONObject locations = eip_definition.getJSONObject("locations"); - return locations.getJSONObject(gateway.getString("location")); - } catch (JSONException e) { - return new JSONObject(); - } + return locations.getJSONObject(gateway.getString("location")); + } catch (JSONException e) { + return new JSONObject(); + } } - + /** * Create and attach the VpnProfile to our gateway object */ - private VpnProfile createVPNProfile(){ - try { - ConfigParser cp = new ConfigParser(); - - VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(general_configuration, secrets, gateway); - String configuration = vpn_configuration_generator.generate(); - - cp.parseConfig(new StringReader(configuration)); - return cp.convertProfile(); - } catch (ConfigParser.ConfigParseError e) { - // FIXME We didn't get a VpnProfile! Error handling! and log level - Log.v(TAG,"Error creating VPNProfile"); - e.printStackTrace(); - return null; - } catch (IOException e) { - // FIXME We didn't get a VpnProfile! Error handling! and log level - Log.v(TAG,"Error creating VPNProfile"); - e.printStackTrace(); - return null; - } + private VpnProfile createVPNProfile() { + try { + ConfigParser cp = new ConfigParser(); + + VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(general_configuration, secrets, gateway); + String configuration = vpn_configuration_generator.generate(); + + cp.parseConfig(new StringReader(configuration)); + return cp.convertProfile(); + } catch (ConfigParser.ConfigParseError e) { + // FIXME We didn't get a VpnProfile! Error handling! and log level + e.printStackTrace(); + return null; + } catch (IOException e) { + // FIXME We didn't get a VpnProfile! Error handling! and log level + e.printStackTrace(); + return null; + } } public String getName() { - return mName; + return mName; } public VpnProfile getProfile() { - return mVpnProfile; + return mVpnProfile; } public int getTimezone() { - return timezone; + return timezone; } @Override diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java index 39ae7ca6..90c8f890 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java @@ -1,46 +1,42 @@ package se.leap.bitmaskclient.eip; -import java.util.Calendar; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.TreeMap; +import java.util.*; public class GatewaySelector { List<Gateway> gateways; public GatewaySelector(List<Gateway> gateways) { - this.gateways = gateways; + this.gateways = gateways; } public Gateway select() { - return closestGateway(); + return closestGateway(); } - + private Gateway closestGateway() { - TreeMap<Integer, Set<Gateway>> offsets = calculateOffsets(); - return offsets.isEmpty() ? null : offsets.firstEntry().getValue().iterator().next(); + TreeMap<Integer, Set<Gateway>> offsets = calculateOffsets(); + return offsets.isEmpty() ? null : offsets.firstEntry().getValue().iterator().next(); } - + private TreeMap<Integer, Set<Gateway>> calculateOffsets() { - TreeMap<Integer, Set<Gateway>> offsets = new TreeMap<Integer, Set<Gateway>>(); - int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000; - for(Gateway gateway : gateways) { - int dist = timezoneDistance(localOffset, gateway.getTimezone()); - Set<Gateway> set = (offsets.get(dist) != null) ? - offsets.get(dist) : new HashSet<Gateway>(); - set.add(gateway); - offsets.put(dist, set); - } - return offsets; + TreeMap<Integer, Set<Gateway>> offsets = new TreeMap<Integer, Set<Gateway>>(); + int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000; + for (Gateway gateway : gateways) { + int dist = timezoneDistance(localOffset, gateway.getTimezone()); + Set<Gateway> set = (offsets.get(dist) != null) ? + offsets.get(dist) : new HashSet<Gateway>(); + set.add(gateway); + offsets.put(dist, set); + } + return offsets; } - + private int timezoneDistance(int local_timezone, int remote_timezone) { - // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12 - int dist = Math.abs(local_timezone - remote_timezone); - // Farther than 12 timezones and it's shorter around the "back" - if (dist > 12) - dist = 12 - (dist -12); // Well i'll be. Absolute values make equations do funny things. - return dist; + // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12 + int dist = Math.abs(local_timezone - remote_timezone); + // Farther than 12 timezones and it's shorter around the "back" + if (dist > 12) + dist = 12 - (dist - 12); // Well i'll be. Absolute values make equations do funny things. + return dist; } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java index 401cd701..1c64328e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -17,7 +17,6 @@ package se.leap.bitmaskclient.eip; import android.content.*; -import android.util.Log; import com.google.gson.*; import com.google.gson.reflect.*; @@ -40,15 +39,18 @@ public class GatewaysManager { private SharedPreferences preferences; private List<Gateway> gateways = new ArrayList<>(); private ProfileManager profile_manager; - private Type list_type = new TypeToken<ArrayList<Gateway>>() {}.getType(); + private Type list_type = new TypeToken<ArrayList<Gateway>>() { + }.getType(); - public GatewaysManager() {} + public GatewaysManager() { + } public GatewaysManager(Context context, SharedPreferences preferences) { this.context = context; this.preferences = preferences; profile_manager = ProfileManager.getInstance(context); } + public Gateway select() { GatewaySelector gateway_selector = new GatewaySelector(gateways); return gateway_selector.select(); @@ -66,16 +68,15 @@ public class GatewaysManager { List<Gateway> gateways_list = new ArrayList<Gateway>(); try { gateways_list = new Gson().fromJson(gateways, list_type); - } catch(JsonSyntaxException e) { + } catch (JsonSyntaxException e) { gateways_list.add(new Gson().fromJson(gateways, Gateway.class)); } - if(gateways_list != null) { + if (gateways_list != null) { for (Gateway gateway : gateways_list) - addGateway(gateway); + addGateway(gateway); this.gateways.addAll(gateways_list); - } else - Log.d("GatewaysManager", "No gateways added"); + } } @Override @@ -85,21 +86,21 @@ public class GatewaysManager { public void fromEipServiceJson(JSONObject eip_definition) { try { - JSONArray gatewaysDefined = eip_definition.getJSONArray("gateways"); - for (int i = 0; i < gatewaysDefined.length(); i++) { - JSONObject gw = gatewaysDefined.getJSONObject(i); - if (isOpenVpnGateway(gw)) { - JSONObject secrets = secretsConfiguration(); - Gateway aux = new Gateway(eip_definition, secrets, gw); - if(!containsProfileWithSecrets(aux.getProfile())) { - addGateway(aux); - } - } - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + JSONArray gatewaysDefined = eip_definition.getJSONArray("gateways"); + for (int i = 0; i < gatewaysDefined.length(); i++) { + JSONObject gw = gatewaysDefined.getJSONObject(i); + if (isOpenVpnGateway(gw)) { + JSONObject secrets = secretsConfiguration(); + Gateway aux = new Gateway(eip_definition, secrets, gw); + if (!containsProfileWithSecrets(aux.getProfile())) { + addGateway(aux); + } + } + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } private boolean isOpenVpnGateway(JSONObject gateway) { @@ -127,10 +128,10 @@ public class GatewaysManager { boolean result = false; Collection<VpnProfile> profiles = profile_manager.getProfiles(); - for(VpnProfile aux : profiles) { + for (VpnProfile aux : profiles) { result = result || sameConnections(profile.mConnections, aux.mConnections) - && profile.mClientCertFilename.equalsIgnoreCase(aux.mClientCertFilename) - && profile.mClientKeyFilename.equalsIgnoreCase(aux.mClientKeyFilename); + && profile.mClientCertFilename.equalsIgnoreCase(aux.mClientCertFilename) + && profile.mClientKeyFilename.equalsIgnoreCase(aux.mClientKeyFilename); } return result; } @@ -149,9 +150,9 @@ public class GatewaysManager { private void removeDuplicatedGateway(Gateway gateway) { Iterator<Gateway> it = gateways.iterator(); List<Gateway> gateways_to_remove = new ArrayList<>(); - while(it.hasNext()) { + while (it.hasNext()) { Gateway aux = it.next(); - if(sameConnections(aux.getProfile().mConnections, gateway.getProfile().mConnections)) { + if (sameConnections(aux.getProfile().mConnections, gateway.getProfile().mConnections)) { gateways_to_remove.add(aux); } } @@ -160,21 +161,21 @@ public class GatewaysManager { } private void removeDuplicatedProfiles(VpnProfile original) { - Collection<VpnProfile> profiles = profile_manager.getProfiles(); + Collection<VpnProfile> profiles = profile_manager.getProfiles(); List<VpnProfile> remove_list = new ArrayList<>(); - for(VpnProfile aux : profiles) { - if (sameConnections(original.mConnections, aux.mConnections)) - remove_list.add(aux); - } + for (VpnProfile aux : profiles) { + if (sameConnections(original.mConnections, aux.mConnections)) + remove_list.add(aux); + } for (VpnProfile profile : remove_list) profile_manager.removeProfile(context, profile); } private boolean sameConnections(Connection[] c1, Connection[] c2) { int same_connections = 0; - for(Connection c1_aux : c1) { - for(Connection c2_aux : c2) - if(c2_aux.mServerName.equals(c1_aux.mServerName)) { + for (Connection c1_aux : c1) { + for (Connection c2_aux : c2) + if (c2_aux.mServerName.equals(c1_aux.mServerName)) { same_connections++; break; } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java index d79d8003..5c9263b3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java @@ -1,9 +1,9 @@ package se.leap.bitmaskclient.eip; -import android.app.Activity; -import android.content.Intent; -import android.net.VpnService; -import android.os.Bundle; +import android.app.*; +import android.content.*; +import android.net.*; +import android.os.*; public class VoidVpnLauncher extends Activity { @@ -11,27 +11,27 @@ public class VoidVpnLauncher extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setUp(); + super.onCreate(savedInstanceState); + setUp(); } - + public void setUp() { - Intent blocking_intent = VpnService.prepare(getApplicationContext()); // stops the VPN connection created by another application. - if(blocking_intent != null) - startActivityForResult(blocking_intent, VPN_USER_PERMISSION); - else { - onActivityResult(VPN_USER_PERMISSION, RESULT_OK, null); - } + Intent blocking_intent = VpnService.prepare(getApplicationContext()); // stops the VPN connection created by another application. + if (blocking_intent != null) + startActivityForResult(blocking_intent, VPN_USER_PERMISSION); + else { + onActivityResult(VPN_USER_PERMISSION, RESULT_OK, null); + } } - protected void onActivityResult(int requestCode, int resultCode, Intent data){ - if(requestCode == VPN_USER_PERMISSION) { - if(resultCode == RESULT_OK) { - Intent void_vpn_service = new Intent(getApplicationContext(), VoidVpnService.class); - void_vpn_service.setAction(Constants.START_BLOCKING_VPN_PROFILE); - startService(void_vpn_service); - } - } - finish(); + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == VPN_USER_PERMISSION) { + if (resultCode == RESULT_OK) { + Intent void_vpn_service = new Intent(getApplicationContext(), VoidVpnService.class); + void_vpn_service.setAction(Constants.START_BLOCKING_VPN_PROFILE); + startService(void_vpn_service); + } + } + finish(); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java index 0c773208..dac92fe2 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java @@ -1,53 +1,61 @@ package se.leap.bitmaskclient.eip; -import android.content.Intent; -import android.net.VpnService; -import android.os.ParcelFileDescriptor; +import android.content.*; +import android.net.*; +import android.os.*; -import java.io.IOException; +import java.io.*; -public class VoidVpnService extends VpnService { +public class VoidVpnService extends VpnService { static final String TAG = VoidVpnService.class.getSimpleName(); static ParcelFileDescriptor fd; + static Thread thread; + @Override public int onStartCommand(Intent intent, int flags, int startId) { - String action = intent != null ? intent.getAction() : ""; - if (action == Constants.START_BLOCKING_VPN_PROFILE) { - new Thread(new Runnable() { - public void run() { - Builder builder = new Builder(); - builder.setSession("Blocking until running"); - builder.addAddress("10.42.0.8",16); - builder.addRoute("0.0.0.0", 1); - builder.addRoute("192.168.1.0", 24); - builder.addDnsServer("10.42.0.1"); - try { - fd = builder.establish(); - } catch (Exception e) { - e.printStackTrace(); - } - android.util.Log.d(TAG, "VoidVpnService set up"); - } - }).run(); - } - return 0; + String action = intent != null ? intent.getAction() : ""; + if (action == Constants.START_BLOCKING_VPN_PROFILE) { + thread = new Thread(new Runnable() { + public void run() { + Builder builder = new Builder(); + builder.setSession("Blocking until running"); + builder.addAddress("10.42.0.8", 16); + builder.addRoute("0.0.0.0", 1); + builder.addRoute("192.168.1.0", 24); + builder.addDnsServer("10.42.0.1"); + try { + fd = builder.establish(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + thread.run(); + } + return 0; } @Override public void onRevoke() { super.onRevoke(); + closeFd(); + } + + public static void stop() { + if (thread != null) + thread.interrupt(); + closeFd(); } - public static boolean stop() { + private static void closeFd() { try { - fd.close(); - return true; - } catch (IOException | NullPointerException e) { - android.util.Log.d(TAG, "VoidVpnService didn't stop"); + if (fd != null) + fd.close(); + } catch (IOException e) { e.printStackTrace(); - return false; } } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java index 0bbe9db4..8fce6a37 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,14 +16,10 @@ */ package se.leap.bitmaskclient.eip; -import android.util.Log; - -import java.security.cert.CertificateExpiredException; -import java.security.cert.CertificateNotYetValidException; -import java.security.cert.X509Certificate; -import java.util.Calendar; +import java.security.cert.*; +import java.util.*; -import se.leap.bitmaskclient.ConfigHelper; +import se.leap.bitmaskclient.*; public class VpnCertificateValidator { public final static String TAG = VpnCertificateValidator.class.getSimpleName(); @@ -35,32 +31,30 @@ public class VpnCertificateValidator { } public boolean isValid() { - if(!certificate.isEmpty()) { - X509Certificate certificate_x509 = ConfigHelper.parseX509CertificateFromString(certificate); - return isValid(certificate_x509); - } else return true; + if (!certificate.isEmpty()) { + X509Certificate certificate_x509 = ConfigHelper.parseX509CertificateFromString(certificate); + return isValid(certificate_x509); + } else return true; } - + private boolean isValid(X509Certificate certificate) { - Calendar offset_date = calculateOffsetCertificateValidity(certificate); - try { - Log.d(TAG, "offset_date = " + offset_date.getTime().toString()); - certificate.checkValidity(offset_date.getTime()); - return true; - } catch(CertificateExpiredException e) { - return false; - } catch(CertificateNotYetValidException e) { - return false; - } + Calendar offset_date = calculateOffsetCertificateValidity(certificate); + try { + certificate.checkValidity(offset_date.getTime()); + return true; + } catch (CertificateExpiredException e) { + return false; + } catch (CertificateNotYetValidException e) { + return false; + } } private Calendar calculateOffsetCertificateValidity(X509Certificate certificate) { - Log.d(TAG, "certificate not after = " + certificate.getNotAfter()); - long preventive_time = Math.abs(certificate.getNotBefore().getTime() - certificate.getNotAfter().getTime())/2; - long current_date_millis = Calendar.getInstance().getTimeInMillis(); - - Calendar limit_date = Calendar.getInstance(); - limit_date.setTimeInMillis(current_date_millis + preventive_time); - return limit_date; + long preventive_time = Math.abs(certificate.getNotBefore().getTime() - certificate.getNotAfter().getTime()) / 2; + long current_date_millis = Calendar.getInstance().getTimeInMillis(); + + Calendar limit_date = Calendar.getInstance(); + limit_date.setTimeInMillis(current_date_millis + preventive_time); + return limit_date; } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java index 6f260f55..0b9c5832 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,16 +16,11 @@ */ package se.leap.bitmaskclient.eip; -import android.content.SharedPreferences; -import android.util.Log; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import org.json.*; -import java.util.Iterator; +import java.util.*; -import se.leap.bitmaskclient.Provider; +import se.leap.bitmaskclient.*; public class VpnConfigGenerator { @@ -37,79 +32,79 @@ public class VpnConfigGenerator { private final String new_line = System.getProperty("line.separator"); // Platform new line public VpnConfigGenerator(JSONObject general_configuration, JSONObject secrets, JSONObject gateway) { - this.general_configuration = general_configuration; - this.gateway = gateway; + this.general_configuration = general_configuration; + this.gateway = gateway; this.secrets = secrets; } - + public String generate() { - return - generalConfiguration() - + new_line - + gatewayConfiguration() - + new_line - + secretsConfiguration() - + new_line - + androidCustomizations(); + return + generalConfiguration() + + new_line + + gatewayConfiguration() + + new_line + + secretsConfiguration() + + new_line + + androidCustomizations(); } private String generalConfiguration() { - String common_options = ""; - try { - Iterator keys = general_configuration.keys(); - while ( keys.hasNext() ){ - String key = keys.next().toString(); - - common_options += key + " "; - for ( String word : general_configuration.getString(key).split(" ") ) - common_options += word + " "; - common_options += new_line; - - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - common_options += "client"; - - return common_options; + String common_options = ""; + try { + Iterator keys = general_configuration.keys(); + while (keys.hasNext()) { + String key = keys.next().toString(); + + common_options += key + " "; + for (String word : general_configuration.getString(key).split(" ")) + common_options += word + " "; + common_options += new_line; + + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + common_options += "client"; + + return common_options; } - + private String gatewayConfiguration() { - String remotes = ""; - - String ip_address_keyword = "ip_address"; - String remote_keyword = "remote"; - String ports_keyword = "ports"; - String protocol_keyword = "protocols"; - String capabilities_keyword = "capabilities"; - String udp = "udp"; - - try { - String ip_address = gateway.getString(ip_address_keyword); - JSONObject capabilities = gateway.getJSONObject(capabilities_keyword); - JSONArray ports = capabilities.getJSONArray(ports_keyword); - for (int i=0; i<ports.length(); i++) { - String port_specific_remotes = ""; - int port = ports.getInt(i); - JSONArray protocols = capabilities.getJSONArray(protocol_keyword); - for ( int j=0; j<protocols.length(); j++ ) { - String protocol = protocols.optString(j); - String new_remote = remote_keyword + " " + ip_address + " " + port + " " + protocol + new_line; - - port_specific_remotes = protocol.equalsIgnoreCase(udp) ? - port_specific_remotes.replaceFirst(remote_keyword, new_remote + new_line + remote_keyword) : - new_remote; - } - remotes += port_specific_remotes; - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - return remotes; + String remotes = ""; + + String ip_address_keyword = "ip_address"; + String remote_keyword = "remote"; + String ports_keyword = "ports"; + String protocol_keyword = "protocols"; + String capabilities_keyword = "capabilities"; + String udp = "udp"; + + try { + String ip_address = gateway.getString(ip_address_keyword); + JSONObject capabilities = gateway.getJSONObject(capabilities_keyword); + JSONArray ports = capabilities.getJSONArray(ports_keyword); + for (int i = 0; i < ports.length(); i++) { + String port_specific_remotes = ""; + int port = ports.getInt(i); + JSONArray protocols = capabilities.getJSONArray(protocol_keyword); + for (int j = 0; j < protocols.length(); j++) { + String protocol = protocols.optString(j); + String new_remote = remote_keyword + " " + ip_address + " " + port + " " + protocol + new_line; + + port_specific_remotes = protocol.equalsIgnoreCase(udp) ? + port_specific_remotes.replaceFirst(remote_keyword, new_remote + new_line + remote_keyword) : + new_remote; + } + remotes += port_specific_remotes; + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return remotes; } private String secretsConfiguration() { @@ -136,18 +131,18 @@ public class VpnConfigGenerator { + "</cert>"; return ca + new_line + key + new_line + openvpn_cert; - } catch(JSONException e) { + } catch (JSONException e) { e.printStackTrace(); return ""; } } private String androidCustomizations() { - return - "remote-cert-tls server" - + new_line - + "persist-tun" - + new_line - + "auth-retry nointeract"; + return + "remote-cert-tls server" + + new_line + + "persist-tun" + + new_line + + "auth-retry nointeract"; } } diff --git a/app/src/main/res/layout-xlarge/dashboard.xml b/app/src/main/res/layout-xlarge/dashboard.xml index bd644e1e..268bd3f9 100644 --- a/app/src/main/res/layout-xlarge/dashboard.xml +++ b/app/src/main/res/layout-xlarge/dashboard.xml @@ -52,6 +52,28 @@ </LinearLayout> </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingLeft="32dp"> + <ProgressBar + android:id="@+id/user_session_status_progress" + android:layout_width="wrap_content" + android:layout_height="fill_parent" + android:indeterminate="true" + android:visibility="gone"/> + <TextView + android:id="@+id/user_session_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="18sp" + android:layout_marginLeft="10dp" + android:ellipsize="marquee" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + </LinearLayout> + <View android:layout_width="wrap_content" android:layout_height="1dp" diff --git a/app/src/main/res/layout/dashboard.xml b/app/src/main/res/layout/dashboard.xml index 67a1122f..f4269fe2 100644 --- a/app/src/main/res/layout/dashboard.xml +++ b/app/src/main/res/layout/dashboard.xml @@ -16,7 +16,6 @@ android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:ellipsize="marquee" - android:fadingEdge="horizontal" android:singleLine="true" android:text="@string/provider_label" android:textAppearance="?android:attr/textAppearanceMedium" /> @@ -28,19 +27,33 @@ android:textSize="28sp" android:layout_marginLeft="10dp" android:ellipsize="marquee" - android:fadingEdge="horizontal" android:singleLine="true" android:text="@string/provider_label_none" android:textAppearance="?android:attr/textAppearanceMedium" /> </LinearLayout> - <View - android:layout_width="wrap_content" - android:layout_height="2dp" - android:layout_marginBottom="15dp" - android:background="@android:drawable/divider_horizontal_bright" /> - + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <ProgressBar + android:id="@+id/user_session_status_progress" + android:layout_width="wrap_content" + android:layout_height="fill_parent" + android:indeterminate="true" + android:visibility="gone"/> + <TextView + android:id="@+id/user_session_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="18sp" + android:layout_marginLeft="10dp" + android:ellipsize="marquee" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + </LinearLayout> + <LinearLayout android:id="@+id/servicesCollection" android:layout_width="match_parent" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1608f487..d1e33928 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,8 +16,6 @@ <string name="provider_label">Provider:</string> <string name="provider_label_none">No provider configured</string> <string name="status_unknown">Status unknown.</string> - <string name="anonymous_secured_status">Connection secure using an anonymous certificate.</string> - <string name="authed_secured_status">Connection secure using your own certificate.</string> <string name="eip_service_label">Encrypted Internet</string> <string name="configuration_wizard_title">Select a service provider</string> <string name="new_provider_button">Add new Provider</string> @@ -60,17 +58,19 @@ <string name="signingup_message">Signing up</string> <string name="logout_message">Logging out from this session.</string> <string name="logged_out_message">Logged out.</string> - <string name="log_out_failed_message">Didn\'t log out.</string> + <string name="log_out_failed_message">Didn\'t log out. Try later, it may be a problem in the network or in the provider. If the problem persists, then wipe Bitmask data from the Android settings</string> + <string name="login.riseup.warning">"Riseup users: You need to create a separate account to use the VPN service"</string> <string name="succesful_authentication_message">Authentication succeeded.</string> <string name="authentication_failed_message">Authentication failed.</string> <string name="registration_failed_message">Registration failed.</string> - <string name="successful_authed_cert_downloaded_message">Your own cert has been correctly downloaded.</string> - <string name="authed_cert_download_failed_message">Your own cert has incorrectly been downloaded.</string> <string name="eip_status_start_pending">Initiating connection</string> <string name="eip_cancel_connect_title">Cancel connection?</string> <string name="eip_cancel_connect_text">There is a connection attempt in progress. Do you wish to cancel it?</string> + <string name="eip.warning.browser_inconsistency">In order to avoid leaking your personal information, please close your browser and start a private window after disconnecting the Encrypted VPN Internet Access. Thanks.</string> <string name="yes">Yes</string> <string name="no">No</string> <string name="eip_state_not_connected">"Not running! Connection not secure!"</string> <string name="eip_state_connected">Connection Secure.</string> + <string name="provider_problem">It seems there is a problem with the provider.</string> + <string name="try_another_provider">Please try another provider, or contact yours.</string> </resources> diff --git a/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java b/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java index abab106d..19ba1ba8 100644 --- a/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java +++ b/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -28,10 +28,11 @@ import java.net.*; import java.util.*; import butterknife.*; -import org.jetbrains.annotations.NotNull; + +import org.jetbrains.annotations.*; import org.json.*; -import javax.inject.Inject; +import javax.inject.*; import se.leap.bitmaskclient.DownloadFailedDialog.DownloadFailedDialogInterface; import se.leap.bitmaskclient.NewProviderDialog.NewProviderDialogInterface; @@ -41,26 +42,29 @@ import se.leap.bitmaskclient.eip.Constants; /** * Activity that builds and shows the list of known available providers. - * + * <p/> * It also allows the user to enter custom providers with a button. - * - * @author parmegv * + * @author parmegv */ public class ConfigurationWizard extends Activity -implements NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver { + implements NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver { - @InjectView(R.id.progressbar_configuration_wizard) ProgressBar mProgressBar; - @InjectView(R.id.progressbar_description) TextView progressbar_description; + @InjectView(R.id.progressbar_configuration_wizard) + ProgressBar mProgressBar; + @InjectView(R.id.progressbar_description) + TextView progressbar_description; - @InjectView(R.id.provider_list) ListView provider_list_view; - @Inject ProviderListAdapter adapter; + @InjectView(R.id.provider_list) + ListView provider_list_view; + @Inject + ProviderListAdapter adapter; private ProviderManager provider_manager; private Intent mConfigState = new Intent(); private Provider selected_provider; - + final public static String TAG = ConfigurationWizard.class.getSimpleName(); final protected static String PROVIDER_SET = "PROVIDER SET"; @@ -69,7 +73,7 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download final private static String PROGRESSBAR_TEXT = TAG + "PROGRESSBAR_TEXT"; final private static String PROGRESSBAR_NUMBER = TAG + "PROGRESSBAR_NUMBER"; - + public ProviderAPIResultReceiver providerAPI_result_receiver; private ProviderAPIBroadcastReceiver_Update providerAPI_broadcast_receiver_update; @@ -87,49 +91,51 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download adapter = new ProviderListAdapter(getLayoutInflater(), providerRendererBuilder, provider_manager); provider_list_view.setAdapter(adapter); } - + @Override protected void onSaveInstanceState(@NotNull Bundle outState) { - if(mProgressBar != null) + if (mProgressBar != null) outState.putInt(PROGRESSBAR_NUMBER, mProgressBar.getProgress()); - if(progressbar_description != null) + if (progressbar_description != null) outState.putString(PROGRESSBAR_TEXT, progressbar_description.getText().toString()); - if(selected_provider != null) + if (selected_provider != null) outState.putParcelable(Provider.KEY, selected_provider); - outState.putParcelable(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); super.onSaveInstanceState(outState); } - + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); - fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); + preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); + fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); provider_manager = ProviderManager.getInstance(getAssets(), getExternalFilesDir(null)); - setUpInitialUI(); + setUpInitialUI(); + + initProviderList(); - initProviderList(); - - if (savedInstanceState != null) - restoreState(savedInstanceState); - else - setUpProviderAPIResultReceiver(); + if (savedInstanceState != null) + restoreState(savedInstanceState); + setUpProviderAPIResultReceiver(); } private void restoreState(Bundle savedInstanceState) { progressbar_text = savedInstanceState.getString(PROGRESSBAR_TEXT, ""); provider_name = savedInstanceState.getString(Provider.NAME, ""); selected_provider = savedInstanceState.getParcelable(Provider.KEY); - progress = savedInstanceState.getInt(PROGRESSBAR_NUMBER, -1); - providerAPI_result_receiver = savedInstanceState.getParcelable(ProviderAPI.RECEIVER_KEY); - providerAPI_result_receiver.setReceiver(this); + + if (fragment_manager.findFragmentByTag(ProviderDetailFragment.TAG) == null && setting_up_provider) { + if (selected_provider != null) + onItemSelectedUi(selected_provider); + if (progress > 0) + mProgressBar.setProgress(progress); + } } @Override protected void onPostResume() { super.onPostResume(); - if(!progressbar_text.isEmpty() && !provider_name.isEmpty() && progress != -1) { + if (!progressbar_text.isEmpty() && !provider_name.isEmpty() && progress != -1) { progressbar_description.setText(progressbar_text); mProgressBar.setProgress(progress); @@ -140,92 +146,91 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download } private void setUpInitialUI() { - setContentView(R.layout.configuration_wizard_activity); + setContentView(R.layout.configuration_wizard_activity); ButterKnife.inject(this); - - hideProgressBar(); + + hideProgressBar(); } - - private void hideProgressBar() { - mProgressBar.setVisibility(ProgressBar.INVISIBLE); - - progressbar_description.setVisibility(TextView.INVISIBLE); + + private void hideProgressBar() { + mProgressBar.setVisibility(ProgressBar.INVISIBLE); + + progressbar_description.setVisibility(TextView.INVISIBLE); } @Override protected void onDestroy() { - super.onDestroy(); - if(providerAPI_broadcast_receiver_update != null) - unregisterReceiver(providerAPI_broadcast_receiver_update); + super.onDestroy(); + if (providerAPI_broadcast_receiver_update != null) + unregisterReceiver(providerAPI_broadcast_receiver_update); } private void setUpProviderAPIResultReceiver() { providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); providerAPI_result_receiver.setReceiver(this); - providerAPI_broadcast_receiver_update = new ProviderAPIBroadcastReceiver_Update(); - - IntentFilter update_intent_filter = new IntentFilter(ProviderAPI.UPDATE_PROGRESSBAR); - update_intent_filter.addCategory(Intent.CATEGORY_DEFAULT); - registerReceiver(providerAPI_broadcast_receiver_update, update_intent_filter); + providerAPI_broadcast_receiver_update = new ProviderAPIBroadcastReceiver_Update(); + + IntentFilter update_intent_filter = new IntentFilter(ProviderAPI.UPDATE_PROGRESSBAR); + update_intent_filter.addCategory(Intent.CATEGORY_DEFAULT); + registerReceiver(providerAPI_broadcast_receiver_update, update_intent_filter); } - + @Override public void onReceiveResult(int resultCode, Bundle resultData) { - if(resultCode == ProviderAPI.PROVIDER_OK) { - mConfigState.setAction(PROVIDER_SET); - try { + if (resultCode == ProviderAPI.PROVIDER_OK) { + mConfigState.setAction(PROVIDER_SET); + try { String provider_json_string = preferences.getString(Provider.KEY, ""); - if(!provider_json_string.isEmpty()) - selected_provider.define(new JSONObject(provider_json_string)); + if (!provider_json_string.isEmpty()) + selected_provider.define(new JSONObject(provider_json_string)); } catch (JSONException e) { e.printStackTrace(); } - - if (preferences.getBoolean(Constants.ALLOWED_ANON, false)){ - mConfigState.putExtra(SERVICES_RETRIEVED, true); - - downloadVpnCertificate(); - } else { - mProgressBar.incrementProgressBy(1); - hideProgressBar(); - - setResult(RESULT_OK); - - showProviderDetails(); - } - } else if(resultCode == ProviderAPI.PROVIDER_NOK) { - hideProgressBar(); - preferences.edit().remove(Provider.KEY).apply(); - setting_up_provider = false; - - setResult(RESULT_CANCELED, mConfigState); - - String reason_to_fail = resultData.getString(ProviderAPI.ERRORS); - showDownloadFailedDialog(reason_to_fail); - } - else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { - mProgressBar.incrementProgressBy(1); - hideProgressBar(); - - showProviderDetails(); - - setResult(RESULT_OK); - } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { - hideProgressBar(); - - setResult(RESULT_CANCELED, mConfigState); - } else if(resultCode == AboutActivity.VIEWED) { - // Do nothing, right now - // I need this for CW to wait for the About activity to end before going back to Dashboard. - } + + if (preferences.getBoolean(Constants.ALLOWED_ANON, false)) { + mConfigState.putExtra(SERVICES_RETRIEVED, true); + + downloadVpnCertificate(); + } else { + mProgressBar.incrementProgressBy(1); + hideProgressBar(); + + setResult(RESULT_OK); + + showProviderDetails(); + } + } else if (resultCode == ProviderAPI.PROVIDER_NOK) { + hideProgressBar(); + preferences.edit().remove(Provider.KEY).apply(); + setting_up_provider = false; + + setResult(RESULT_CANCELED, mConfigState); + + String reason_to_fail = resultData.getString(ProviderAPI.ERRORS); + showDownloadFailedDialog(reason_to_fail); + } else if (resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { + mProgressBar.incrementProgressBy(1); + hideProgressBar(); + + showProviderDetails(); + + setResult(RESULT_OK); + } else if (resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { + hideProgressBar(); + + setResult(RESULT_CANCELED, mConfigState); + } else if (resultCode == AboutActivity.VIEWED) { + // Do nothing, right now + // I need this for CW to wait for the About activity to end before going back to Dashboard. + } } @OnItemClick(R.id.provider_list) void onItemSelected(int position) { - //TODO Code 2 pane view + //TODO Code 2 pane view selected_provider = adapter.getItem(position); onItemSelectedUi(selected_provider); - onItemSelectedLogic(selected_provider); + onItemSelectedLogic(selected_provider); } private void onItemSelectedLogic(Provider selected_provider) { @@ -234,226 +239,231 @@ implements NewProviderDialogInterface, ProviderDetailFragmentInterface, Download private void onItemSelectedUi(Provider provider) { startProgressBar(); - adapter.hideAllBut(adapter.indexOf(provider)); + adapter.hideAllBut(adapter.indexOf(provider)); } - + @Override public void onBackPressed() { - if(setting_up_provider) { - stopSettingUpProvider(); - } else { - askDashboardToQuitApp(); - super.onBackPressed(); - } - } - + if (setting_up_provider) { + stopSettingUpProvider(); + } else { + askDashboardToQuitApp(); + super.onBackPressed(); + } + } + private void stopSettingUpProvider() { - ProviderAPI.stop(); - mProgressBar.setVisibility(ProgressBar.GONE); - mProgressBar.setProgress(0); - progressbar_description.setVisibility(TextView.GONE); + ProviderAPI.stop(); + mProgressBar.setVisibility(ProgressBar.GONE); + mProgressBar.setProgress(0); + progressbar_description.setVisibility(TextView.GONE); - cancelSettingUpProvider(); + cancelSettingUpProvider(); } - + public void cancelSettingUpProvider() { - adapter.showAllProviders(); - setting_up_provider = false; - preferences.edit().remove(Provider.KEY).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).apply(); + adapter.showAllProviders(); + setting_up_provider = false; + preferences.edit().remove(Provider.KEY).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).apply(); } - + private void askDashboardToQuitApp() { - Intent ask_quit = new Intent(); - ask_quit.putExtra(Dashboard.ACTION_QUIT, Dashboard.ACTION_QUIT); - setResult(RESULT_CANCELED, ask_quit); + Intent ask_quit = new Intent(); + ask_quit.putExtra(Dashboard.ACTION_QUIT, Dashboard.ACTION_QUIT); + setResult(RESULT_CANCELED, ask_quit); } - + private void startProgressBar() { mProgressBar.setVisibility(ProgressBar.VISIBLE); progressbar_description.setVisibility(TextView.VISIBLE); mProgressBar.setProgress(0); mProgressBar.setMax(3); - int measured_height = listItemHeight(); - mProgressBar.setTranslationY(measured_height); - progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight()); + int measured_height = listItemHeight(); + mProgressBar.setTranslationY(measured_height); + progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight()); } - + private int listItemHeight() { View listItem = adapter.getView(0, null, provider_list_view); listItem.setLayoutParams(new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT)); WindowManager wm = (WindowManager) getApplicationContext() - .getSystemService(Context.WINDOW_SERVICE); + .getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); int screenWidth = display.getWidth(); // deprecated int listViewWidth = screenWidth - 10 - 10; int widthSpec = View.MeasureSpec.makeMeasureSpec(listViewWidth, - View.MeasureSpec.AT_MOST); + View.MeasureSpec.AT_MOST); listItem.measure(widthSpec, 0); return listItem.getMeasuredHeight(); } - + /** * Asks ProviderAPI to download an anonymous (anon) VPN certificate. */ private void downloadVpnCertificate() { - Intent provider_API_command = new Intent(this, ProviderAPI.class); + Intent provider_API_command = new Intent(this, ProviderAPI.class); - provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE); - provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); + provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE); + provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - startService(provider_API_command); + startService(provider_API_command); } - + /** * Open the new provider dialog */ public void addAndSelectNewProvider() { - FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); new NewProviderDialog().show(fragment_transaction, NewProviderDialog.TAG); } - + /** * Open the new provider dialog with data */ public void addAndSelectNewProvider(String main_url) { - FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); - - DialogFragment newFragment = new NewProviderDialog(); - Bundle data = new Bundle(); - data.putString(Provider.MAIN_URL, main_url); - newFragment.setArguments(data); - newFragment.show(fragment_transaction, NewProviderDialog.TAG); - } - + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); + + DialogFragment newFragment = new NewProviderDialog(); + Bundle data = new Bundle(); + data.putString(Provider.MAIN_URL, main_url); + newFragment.setArguments(data); + newFragment.show(fragment_transaction, NewProviderDialog.TAG); + } + /** - * Once selected a provider, this fragment offers the user to log in, - * use it anonymously (if possible) + * Once selected a provider, this fragment offers the user to log in, + * use it anonymously (if possible) * or cancel his/her election pressing the back button. - * @param reason_to_fail + * + * @param reason_to_fail */ public void showDownloadFailedDialog(String reason_to_fail) { - FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(DownloadFailedDialog.TAG); - - DialogFragment newFragment = DownloadFailedDialog.newInstance(reason_to_fail); - newFragment.show(fragment_transaction, DownloadFailedDialog.TAG); + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(DownloadFailedDialog.TAG); + + DialogFragment newFragment = DownloadFailedDialog.newInstance(reason_to_fail); + newFragment.show(fragment_transaction, DownloadFailedDialog.TAG); } - + /** - * Once selected a provider, this fragment offers the user to log in, - * use it anonymously (if possible) + * Once selected a provider, this fragment offers the user to log in, + * use it anonymously (if possible) * or cancel his/her election pressing the back button. + * * @param view */ private void showProviderDetails() { - if(setting_up_provider) { - FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(ProviderDetailFragment.TAG); + if (setting_up_provider) { + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(ProviderDetailFragment.TAG); - DialogFragment newFragment = ProviderDetailFragment.newInstance(); - newFragment.show(fragment_transaction, ProviderDetailFragment.TAG); - } + DialogFragment newFragment = ProviderDetailFragment.newInstance(); + newFragment.show(fragment_transaction, ProviderDetailFragment.TAG); + setting_up_provider = false; + } } public void showAndSelectProvider(String provider_main_url) { - try { - selected_provider = new Provider(new URL((provider_main_url))); - adapter.add(selected_provider); - adapter.saveProviders(); + try { + selected_provider = new Provider(new URL((provider_main_url))); + adapter.add(selected_provider); + adapter.saveProviders(); autoSelectProvider(selected_provider); - } catch (MalformedURLException e) { - e.printStackTrace(); - } + } catch (MalformedURLException e) { + e.printStackTrace(); + } } - + private void autoSelectProvider(Provider provider) { - selected_provider = provider; + selected_provider = provider; onItemSelectedUi(selected_provider); - onItemSelectedLogic(selected_provider); + onItemSelectedLogic(selected_provider); } - + /** * Asks ProviderAPI to download a new provider.json file + * * @param provider_name * @param provider_main_url */ public void setUpProvider(URL provider_main_url) { - Intent provider_API_command = new Intent(this, ProviderAPI.class); - Bundle parameters = new Bundle(); - parameters.putString(Provider.MAIN_URL, provider_main_url.toString()); + Intent provider_API_command = new Intent(this, ProviderAPI.class); + Bundle parameters = new Bundle(); + parameters.putString(Provider.MAIN_URL, provider_main_url.toString()); - provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER); - provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); - provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); + provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER); + provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); + provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - startService(provider_API_command); - setting_up_provider = true; + startService(provider_API_command); + setting_up_provider = true; } public void retrySetUpProvider() { - cancelSettingUpProvider(); - if(!ProviderAPI.caCertDownloaded()) { - addAndSelectNewProvider(ProviderAPI.lastProviderMainUrl()); - } else { - Intent provider_API_command = new Intent(this, ProviderAPI.class); + cancelSettingUpProvider(); + if (!ProviderAPI.caCertDownloaded()) { + addAndSelectNewProvider(ProviderAPI.lastProviderMainUrl()); + } else { + Intent provider_API_command = new Intent(this, ProviderAPI.class); - provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER); - provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); + provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER); + provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - startService(provider_API_command); - } + startService(provider_API_command); + } } + @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu); - return true; + getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu); + return true; } - + @Override - public boolean onOptionsItemSelected(MenuItem item){ - switch (item.getItemId()){ - case R.id.about_leap: - startActivityForResult(new Intent(this, AboutActivity.class), 0); - return true; - case R.id.new_provider: - addAndSelectNewProvider(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.about_leap: + startActivityForResult(new Intent(this, AboutActivity.class), 0); + return true; + case R.id.new_provider: + addAndSelectNewProvider(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + public void showAllProviders() { - adapter.showAllProviders(); + adapter.showAllProviders(); } @Override public void login() { - Intent ask_login = new Intent(); - ask_login.putExtra(Provider.KEY, selected_provider); - ask_login.putExtra(SessionDialog.TAG, SessionDialog.TAG); - setResult(RESULT_OK, ask_login); - setting_up_provider = false; - finish(); + Intent ask_login = new Intent(); + ask_login.putExtra(Provider.KEY, selected_provider); + ask_login.putExtra(SessionDialog.TAG, SessionDialog.TAG); + setResult(RESULT_OK, ask_login); + setting_up_provider = false; + finish(); } @Override public void use_anonymously() { - Intent pass_provider = new Intent(); - pass_provider.putExtra(Provider.KEY, selected_provider); - setResult(RESULT_OK, pass_provider); - setting_up_provider = false; - finish(); + Intent pass_provider = new Intent(); + pass_provider.putExtra(Provider.KEY, selected_provider); + setResult(RESULT_OK, pass_provider); + setting_up_provider = false; + finish(); } public class ProviderAPIBroadcastReceiver_Update extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - int update = intent.getIntExtra(ProviderAPI.CURRENT_PROGRESS, 0); - mProgressBar.setProgress(update); - } + @Override + public void onReceive(Context context, Intent intent) { + int update = intent.getIntExtra(ProviderAPI.CURRENT_PROGRESS, 0); + mProgressBar.setProgress(update); + } } } diff --git a/app/src/release/java/se/leap/bitmaskclient/NewProviderDialog.java b/app/src/release/java/se/leap/bitmaskclient/NewProviderDialog.java index f6709c22..1823d3e3 100644 --- a/app/src/release/java/se/leap/bitmaskclient/NewProviderDialog.java +++ b/app/src/release/java/se/leap/bitmaskclient/NewProviderDialog.java @@ -16,26 +16,19 @@ */ package se.leap.bitmaskclient; -import butterknife.ButterKnife; -import butterknife.InjectView; +import butterknife.*; import se.leap.bitmaskclient.ProviderListContent.ProviderItem; -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.CheckBox; -import android.widget.EditText; -import android.widget.Toast; + +import android.app.*; +import android.content.*; +import android.os.*; +import android.view.*; +import android.widget.*; /** * Implements the new custom provider dialog. * * @author parmegv - * */ public class NewProviderDialog extends DialogFragment { @@ -68,7 +61,7 @@ public class NewProviderDialog extends DialogFragment { View view = inflater.inflate(R.layout.new_provider_dialog, null); ButterKnife.inject(this, view); Bundle arguments = getArguments(); - if(arguments != null) { + if (arguments != null) { url_input_field.setText(arguments.getString(Provider.MAIN_URL, "")); } @@ -90,24 +83,26 @@ public class NewProviderDialog extends DialogFragment { private void saveProvider() { String entered_url = url_input_field.getText().toString().trim(); - if(!entered_url.startsWith("https://")) { - if (entered_url.startsWith("http://")){ + if (!entered_url.startsWith("https://")) { + if (entered_url.startsWith("http://")) { entered_url = entered_url.substring("http://".length()); } entered_url = "https://".concat(entered_url); } - if(validURL(entered_url)) { + if (validURL(entered_url)) { interface_with_ConfigurationWizard.showAndSelectProvider(entered_url); Toast.makeText(getActivity().getApplicationContext(), R.string.valid_url_entered, Toast.LENGTH_LONG).show(); } else { url_input_field.setText(""); - Toast.makeText(getActivity().getApplicationContext(), R.string.not_valid_url_entered, Toast.LENGTH_LONG).show();; + Toast.makeText(getActivity().getApplicationContext(), R.string.not_valid_url_entered, Toast.LENGTH_LONG).show(); + ; } } /** * Checks if the entered url is valid or not. + * * @param entered_url * @return true if it's not empty nor contains only the protocol. */ diff --git a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java index c8efe0de..7cf80a4f 100644 --- a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java @@ -1,6 +1,6 @@ /** * Copyright (c) 2013 LEAP Encryption Access Project and contributers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,312 +16,321 @@ */ package se.leap.bitmaskclient; -import android.app.IntentService; +import android.app.*; import android.content.*; import android.os.*; import android.util.*; + import java.io.*; -import java.math.BigInteger; +import java.math.*; import java.net.*; import java.security.*; import java.security.cert.*; -import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.*; import java.util.*; + import javax.net.ssl.*; -import org.apache.http.client.ClientProtocolException; + +import org.apache.http.client.*; import org.json.*; +import se.leap.bitmaskclient.ProviderListContent.ProviderItem; import se.leap.bitmaskclient.eip.*; /** * Implements HTTP api methods used to manage communications with the provider server. - * + * <p/> * It's an IntentService because it downloads data from the Internet, so it operates in the background. - * + * * @author parmegv * @author MeanderingCode - * */ public class ProviderAPI extends IntentService { - + final public static String TAG = ProviderAPI.class.getSimpleName(), - SET_UP_PROVIDER = "setUpProvider", - DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON", - SRP_REGISTER = "srpRegister", - SRP_AUTH = "srpAuth", - LOG_OUT = "logOut", - DOWNLOAD_CERTIFICATE = "downloadUserAuthedCertificate", - PARAMETERS = "parameters", - RESULT_KEY = "result", - RECEIVER_KEY = "receiver", - ERRORS = "errors", - UPDATE_PROGRESSBAR = "update_progressbar", - CURRENT_PROGRESS = "current_progress", - DOWNLOAD_EIP_SERVICE = TAG + ".DOWNLOAD_EIP_SERVICE" - ; + SET_UP_PROVIDER = "setUpProvider", + DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON", + SIGN_UP = "srpRegister", + LOG_IN = "srpAuth", + LOG_OUT = "logOut", + DOWNLOAD_CERTIFICATE = "downloadUserAuthedCertificate", + PARAMETERS = "parameters", + RESULT_KEY = "result", + RECEIVER_KEY = "receiver", + ERRORS = "errors", + UPDATE_PROGRESSBAR = "update_progressbar", + CURRENT_PROGRESS = "current_progress", + DOWNLOAD_EIP_SERVICE = TAG + ".DOWNLOAD_EIP_SERVICE"; final public static int - SUCCESSFUL_LOGIN = 3, - FAILED_LOGIN = 4, - SUCCESSFUL_SIGNUP = 5, - FAILED_SIGNUP = 6, - SUCCESSFUL_LOGOUT = 7, - LOGOUT_FAILED = 8, - CORRECTLY_DOWNLOADED_CERTIFICATE = 9, - INCORRECTLY_DOWNLOADED_CERTIFICATE = 10, - PROVIDER_OK = 11, - PROVIDER_NOK = 12, + SUCCESSFUL_LOGIN = 3, + FAILED_LOGIN = 4, + SUCCESSFUL_SIGNUP = 5, + FAILED_SIGNUP = 6, + SUCCESSFUL_LOGOUT = 7, + LOGOUT_FAILED = 8, + CORRECTLY_DOWNLOADED_CERTIFICATE = 9, + INCORRECTLY_DOWNLOADED_CERTIFICATE = 10, + PROVIDER_OK = 11, + PROVIDER_NOK = 12, CORRECTLY_DOWNLOADED_EIP_SERVICE = 13, - INCORRECTLY_DOWNLOADED_EIP_SERVICE= 14 - ; - - private static boolean - CA_CERT_DOWNLOADED = false, - PROVIDER_JSON_DOWNLOADED = false, - EIP_SERVICE_JSON_DOWNLOADED = false - ; - + INCORRECTLY_DOWNLOADED_EIP_SERVICE = 14; + + private static boolean + CA_CERT_DOWNLOADED = false, + PROVIDER_JSON_DOWNLOADED = false, + EIP_SERVICE_JSON_DOWNLOADED = false; + private static String last_provider_main_url; private static boolean go_ahead = true; private static SharedPreferences preferences; private static String provider_api_url; - + public static void stop() { - go_ahead = false; + go_ahead = false; + } + + public ProviderAPI() { + super(TAG); } - public ProviderAPI() { - super("ProviderAPI"); - Log.v("ClassName", "Provider API"); - } - @Override public void onCreate() { - super.onCreate(); - - preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); - CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER)); - } - - public static String lastProviderMainUrl() { - return last_provider_main_url; - } - - private String formatErrorMessage(final int toast_string_id) { - return "{ \"" + ERRORS + "\" : \""+getResources().getString(toast_string_id)+"\" }"; - } - - @Override - protected void onHandleIntent(Intent command) { - final ResultReceiver receiver = command.getParcelableExtra(RECEIVER_KEY); - String action = command.getAction(); - Bundle parameters = command.getBundleExtra(PARAMETERS); - - if(provider_api_url == null && preferences.contains(Provider.KEY)) { - try { - JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); - go_ahead = true; - } catch (JSONException e) { - go_ahead = false; - } - } - - if(action.equalsIgnoreCase(SET_UP_PROVIDER)) { - Bundle result = setUpProvider(parameters); - if(go_ahead) { - if(result.getBoolean(RESULT_KEY)) { - receiver.send(PROVIDER_OK, result); - } else { - receiver.send(PROVIDER_NOK, result); - } - } - } else if (action.equalsIgnoreCase(SRP_REGISTER)) { - Bundle result = tryToRegister(parameters); - if(result.getBoolean(RESULT_KEY)) { - receiver.send(SUCCESSFUL_SIGNUP, result); - } else { - receiver.send(FAILED_SIGNUP, result); - } - } else if (action.equalsIgnoreCase(SRP_AUTH)) { - Bundle result = tryToAuthenticate(parameters); - if(result.getBoolean(RESULT_KEY)) { - receiver.send(SUCCESSFUL_LOGIN, result); - } else { - receiver.send(FAILED_LOGIN, result); - } - } else if (action.equalsIgnoreCase(LOG_OUT)) { - if(logOut()) { - receiver.send(SUCCESSFUL_LOGOUT, Bundle.EMPTY); - } else { - receiver.send(LOGOUT_FAILED, Bundle.EMPTY); - } - } else if (action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)) { - if(updateVpnCertificate()) { - receiver.send(CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); - } else { - receiver.send(INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); - } - } else if(action.equalsIgnoreCase(DOWNLOAD_EIP_SERVICE)) { + super.onCreate(); + + preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); + CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER)); + } + + public static String lastProviderMainUrl() { + return last_provider_main_url; + } + + private String formatErrorMessage(final int toast_string_id) { + return "{ \"" + ERRORS + "\" : \"" + getResources().getString(toast_string_id) + "\" }"; + } + + @Override + protected void onHandleIntent(Intent command) { + final ResultReceiver receiver = command.getParcelableExtra(RECEIVER_KEY); + String action = command.getAction(); + Bundle parameters = command.getBundleExtra(PARAMETERS); + + if (provider_api_url == null && preferences.contains(Provider.KEY)) { + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); + go_ahead = true; + } catch (JSONException e) { + go_ahead = false; + } + } + + if (action.equalsIgnoreCase(SET_UP_PROVIDER)) { + Bundle result = setUpProvider(parameters); + if (go_ahead) { + if (result.getBoolean(RESULT_KEY)) { + receiver.send(PROVIDER_OK, result); + } else { + receiver.send(PROVIDER_NOK, result); + } + } + } else if (action.equalsIgnoreCase(SIGN_UP)) { + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.SIGNING_UP); + Bundle result = tryToRegister(parameters); + if (result.getBoolean(RESULT_KEY)) { + receiver.send(SUCCESSFUL_SIGNUP, result); + } else { + receiver.send(FAILED_SIGNUP, result); + } + } else if (action.equalsIgnoreCase(LOG_IN)) { + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.LOGGING_IN); + Bundle result = tryToAuthenticate(parameters); + if (result.getBoolean(RESULT_KEY)) { + receiver.send(SUCCESSFUL_LOGIN, result); + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.LOGGED_IN); + } else { + receiver.send(FAILED_LOGIN, result); + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.NOT_LOGGED_IN); + } + } else if (action.equalsIgnoreCase(LOG_OUT)) { + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.LOGGING_OUT); + if (logOut()) { + receiver.send(SUCCESSFUL_LOGOUT, Bundle.EMPTY); + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.LOGGED_OUT); + } else { + receiver.send(LOGOUT_FAILED, Bundle.EMPTY); + UserSessionStatus.updateStatus(UserSessionStatus.SessionStatus.DIDNT_LOG_OUT); + } + } else if (action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)) { + if (updateVpnCertificate()) { + receiver.send(CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); + } else { + receiver.send(INCORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); + } + } else if (action.equalsIgnoreCase(DOWNLOAD_EIP_SERVICE)) { Bundle result = getAndSetEipServiceJson(); - if(result.getBoolean(RESULT_KEY)) { + if (result.getBoolean(RESULT_KEY)) { receiver.send(CORRECTLY_DOWNLOADED_EIP_SERVICE, result); } else { receiver.send(INCORRECTLY_DOWNLOADED_EIP_SERVICE, result); } } - } + } private Bundle tryToRegister(Bundle task) { - Bundle result = new Bundle(); - int progress = 0; - - String username = task.getString(SessionDialog.USERNAME); - String password = task.getString(SessionDialog.PASSWORD); - - if(validUserLoginData(username, password)) { - result = register(username, password); - broadcastProgress(progress++); - } else { - if(!wellFormedPassword(password)) { - result.putBoolean(RESULT_KEY, false); - result.putString(SessionDialog.USERNAME, username); - result.putBoolean(SessionDialog.PASSWORD_INVALID_LENGTH, true); - } - if(!validUsername(username)) { - result.putBoolean(RESULT_KEY, false); - result.putBoolean(SessionDialog.USERNAME_MISSING, true); - } - } - - return result; - } - - private Bundle register(String username, String password) { - LeapSRPSession client = new LeapSRPSession(username, password); - byte[] salt = client.calculateNewSalt(); - - BigInteger password_verifier = client.calculateV(username, password, salt); - - JSONObject api_result = sendNewUserDataToSRPServer(provider_api_url, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16)); - - Bundle result = new Bundle(); - if(api_result.has(ERRORS)) - result = authFailedNotification(api_result, username); - else { - result.putString(SessionDialog.USERNAME, username); - result.putString(SessionDialog.PASSWORD, password); - result.putBoolean(RESULT_KEY, true); - } - - return result; - } - - /** - * Starts the authentication process using SRP protocol. - * - * @param task containing: username, password and api url. - * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if authentication was successful. - */ - private Bundle tryToAuthenticate(Bundle task) { - Bundle result = new Bundle(); - int progress = 0; - - String username = (String) task.get(SessionDialog.USERNAME); - String password = (String) task.get(SessionDialog.PASSWORD); - if(validUserLoginData(username, password)) { - result = authenticate(username, password); - broadcastProgress(progress++); - } else { - if(!wellFormedPassword(password)) { - result.putBoolean(RESULT_KEY, false); - result.putString(SessionDialog.USERNAME, username); - result.putBoolean(SessionDialog.PASSWORD_INVALID_LENGTH, true); - } - if(!validUsername(username)) { - result.putBoolean(RESULT_KEY, false); - result.putBoolean(SessionDialog.USERNAME_MISSING, true); - } - } - - return result; - } + Bundle result = new Bundle(); + int progress = 0; + + String username = User.userName(); + String password = task.getString(SessionDialog.PASSWORD); + + if (validUserLoginData(username, password)) { + result = register(username, password); + broadcastProgress(progress++); + } else { + if (!wellFormedPassword(password)) { + result.putBoolean(RESULT_KEY, false); + result.putString(SessionDialog.USERNAME, username); + result.putBoolean(SessionDialog.ERRORS.PASSWORD_INVALID_LENGTH.toString(), true); + } + if (!validUsername(username)) { + result.putBoolean(RESULT_KEY, false); + result.putBoolean(SessionDialog.ERRORS.USERNAME_MISSING.toString(), true); + } + } + + return result; + } + + private Bundle register(String username, String password) { + LeapSRPSession client = new LeapSRPSession(username, password); + byte[] salt = client.calculateNewSalt(); + + BigInteger password_verifier = client.calculateV(username, password, salt); + + JSONObject api_result = sendNewUserDataToSRPServer(provider_api_url, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16)); + + Bundle result = new Bundle(); + if (api_result.has(ERRORS)) + result = authFailedNotification(api_result, username); + else { + result.putString(SessionDialog.USERNAME, username); + result.putString(SessionDialog.PASSWORD, password); + result.putBoolean(RESULT_KEY, true); + } + + return result; + } + + /** + * Starts the authentication process using SRP protocol. + * + * @param task containing: username, password and api url. + * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if authentication was successful. + */ + private Bundle tryToAuthenticate(Bundle task) { + Bundle result = new Bundle(); + int progress = 0; + + String username = User.userName(); + String password = task.getString(SessionDialog.PASSWORD); + if (validUserLoginData(username, password)) { + result = authenticate(username, password); + broadcastProgress(progress++); + } else { + if (!wellFormedPassword(password)) { + result.putBoolean(RESULT_KEY, false); + result.putString(SessionDialog.USERNAME, username); + result.putBoolean(SessionDialog.ERRORS.PASSWORD_INVALID_LENGTH.toString(), true); + } + if (!validUsername(username)) { + result.putBoolean(RESULT_KEY, false); + result.putBoolean(SessionDialog.ERRORS.USERNAME_MISSING.toString(), true); + } + } + + return result; + } private Bundle authenticate(String username, String password) { - Bundle result = new Bundle(); - - LeapSRPSession client = new LeapSRPSession(username, password); - byte[] A = client.exponential(); - - JSONObject step_result = sendAToSRPServer(provider_api_url, username, new BigInteger(1, A).toString(16)); - try { - String salt = step_result.getString(LeapSRPSession.SALT); - byte[] Bbytes = new BigInteger(step_result.getString("B"), 16).toByteArray(); - byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); - if(M1 != null) { - step_result = sendM1ToSRPServer(provider_api_url, username, M1); - setTokenIfAvailable(step_result); - byte[] M2 = new BigInteger(step_result.getString(LeapSRPSession.M2), 16).toByteArray(); - if(client.verify(M2)) { - result.putBoolean(RESULT_KEY, true); - } else { - authFailedNotification(step_result, username); - } - } else { - result.putBoolean(RESULT_KEY, false); - result.putString(SessionDialog.USERNAME, username); - result.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message)); - } - } catch (JSONException e) { - result = authFailedNotification(step_result, username); - e.printStackTrace(); - } - - return result; + Bundle result = new Bundle(); + + LeapSRPSession client = new LeapSRPSession(username, password); + byte[] A = client.exponential(); + + JSONObject step_result = sendAToSRPServer(provider_api_url, username, new BigInteger(1, A).toString(16)); + try { + String salt = step_result.getString(LeapSRPSession.SALT); + byte[] Bbytes = new BigInteger(step_result.getString("B"), 16).toByteArray(); + byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); + if (M1 != null) { + step_result = sendM1ToSRPServer(provider_api_url, username, M1); + setTokenIfAvailable(step_result); + byte[] M2 = new BigInteger(step_result.getString(LeapSRPSession.M2), 16).toByteArray(); + if (client.verify(M2)) { + result.putBoolean(RESULT_KEY, true); + } else { + authFailedNotification(step_result, username); + } + } else { + result.putBoolean(RESULT_KEY, false); + result.putString(SessionDialog.USERNAME, username); + result.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message)); + } + } catch (JSONException e) { + result = authFailedNotification(step_result, username); + e.printStackTrace(); + } + + return result; } private boolean setTokenIfAvailable(JSONObject authentication_step_result) { - try { - LeapSRPSession.setToken(authentication_step_result.getString(LeapSRPSession.TOKEN)); - CookieHandler.setDefault(null); // we don't need cookies anymore - } catch(JSONException e) { // - return false; - } - return true; - } - + try { + LeapSRPSession.setToken(authentication_step_result.getString(LeapSRPSession.TOKEN)); + CookieHandler.setDefault(null); // we don't need cookies anymore + } catch (JSONException e) { // + return false; + } + return true; + } + private Bundle authFailedNotification(JSONObject result, String username) { - Bundle user_notification_bundle = new Bundle(); - try{ - JSONObject error_message = result.getJSONObject(ERRORS); - String error_type = error_message.keys().next().toString(); - String message = error_message.get(error_type).toString(); - user_notification_bundle.putString(getResources().getString(R.string.user_message), message); - } catch(JSONException e) {} - - if(!username.isEmpty()) - user_notification_bundle.putString(SessionDialog.USERNAME, username); - user_notification_bundle.putBoolean(RESULT_KEY, false); - - return user_notification_bundle; - } - - /** - * Sets up an intent with the progress value passed as a parameter - * and sends it as a broadcast. - * @param progress - */ - private void broadcastProgress(int progress) { - Intent intentUpdate = new Intent(); - intentUpdate.setAction(UPDATE_PROGRESSBAR); - intentUpdate.addCategory(Intent.CATEGORY_DEFAULT); - intentUpdate.putExtra(CURRENT_PROGRESS, progress); - sendBroadcast(intentUpdate); - } + Bundle user_notification_bundle = new Bundle(); + try { + JSONObject error_message = result.getJSONObject(ERRORS); + String error_type = error_message.keys().next().toString(); + String message = error_message.get(error_type).toString(); + user_notification_bundle.putString(getResources().getString(R.string.user_message), message); + } catch (JSONException e) { + } + + if (!username.isEmpty()) + user_notification_bundle.putString(SessionDialog.USERNAME, username); + user_notification_bundle.putBoolean(RESULT_KEY, false); + + return user_notification_bundle; + } + + /** + * Sets up an intent with the progress value passed as a parameter + * and sends it as a broadcast. + * + * @param progress + */ + private void broadcastProgress(int progress) { + Intent intentUpdate = new Intent(); + intentUpdate.setAction(UPDATE_PROGRESSBAR); + intentUpdate.addCategory(Intent.CATEGORY_DEFAULT); + intentUpdate.putExtra(CURRENT_PROGRESS, progress); + sendBroadcast(intentUpdate); + } /** * Validates parameters entered by the user to log in + * * @param username * @param password * @return true if both parameters are present and the entered password length is greater or equal to eight (8). @@ -334,491 +343,496 @@ public class ProviderAPI extends IntentService { return username != null && !username.isEmpty(); } - /** - * Validates a password - * @param password - * @return true if the entered password length is greater or equal to eight (8). - */ - private boolean wellFormedPassword(String password) { - return password != null && password.length() >= 8; - } - - /** - * 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 - */ + /** + * Validates a password + * + * @param password + * @return true if the entered password length is greater or equal to eight (8). + */ + private boolean wellFormedPassword(String password) { + return password != null && password.length() >= 8; + } + + /** + * 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 + */ private JSONObject sendAToSRPServer(String server_url, String username, String clientA) { - Map<String, String> parameters = new HashMap<String, String>(); - parameters.put("login", username); - parameters.put("A", clientA); - return sendToServer(server_url + "/sessions.json", "POST", parameters); - } - - /** - * 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 - */ + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put("login", username); + parameters.put("A", clientA); + return sendToServer(server_url + "/sessions.json", "POST", parameters); + } + + /** + * 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 + */ private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) { - Map<String, String> parameters = new HashMap<String, String>(); - parameters.put("client_auth", new BigInteger(1, ConfigHelper.trim(m1)).toString(16)); - return sendToServer(server_url + "/sessions/" + username +".json", "PUT", parameters); - } - - /** - * Sends an HTTP POST request to the api server to register a new user. - * @param server_url - * @param username - * @param salt - * @param password_verifier - * @return response from authentication server - */ + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put("client_auth", new BigInteger(1, ConfigHelper.trim(m1)).toString(16)); + return sendToServer(server_url + "/sessions/" + username + ".json", "PUT", parameters); + } + + /** + * Sends an HTTP POST request to the api server to register a new user. + * + * @param server_url + * @param username + * @param salt + * @param password_verifier + * @return response from authentication server + */ private JSONObject sendNewUserDataToSRPServer(String server_url, String username, String salt, String password_verifier) { - Map<String, String> parameters = new HashMap<String, String>(); - parameters.put("user[login]", username); - parameters.put("user[password_salt]", salt); - parameters.put("user[password_verifier]", password_verifier); - Log.d(TAG, server_url); - Log.d(TAG, parameters.toString()); - return sendToServer(server_url + "/users.json", "POST", parameters); - } - - /** - * Executes an HTTP request expecting a JSON response. - * @param url - * @param request_method - * @param parameters - * @return response from authentication server - */ - private JSONObject sendToServer(String url, String request_method, Map<String, String> parameters) { - JSONObject json_response; - HttpsURLConnection urlConnection = null; - try { - InputStream is = null; - urlConnection = (HttpsURLConnection)new URL(url).openConnection(); - urlConnection.setRequestMethod(request_method); - urlConnection.setChunkedStreamingMode(0); - urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); - - DataOutputStream writer = new DataOutputStream(urlConnection.getOutputStream()); - writer.writeBytes(formatHttpParameters(parameters)); - writer.close(); - - is = urlConnection.getInputStream(); - String plain_response = new Scanner(is).useDelimiter("\\A").next(); - json_response = new JSONObject(plain_response); - } catch (ClientProtocolException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (IOException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (JSONException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (KeyManagementException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (KeyStoreException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } catch (CertificateException e) { - json_response = getErrorMessage(urlConnection); - e.printStackTrace(); - } - - return json_response; - } + Map<String, String> parameters = new HashMap<String, String>(); + parameters.put("user[login]", username); + parameters.put("user[password_salt]", salt); + parameters.put("user[password_verifier]", password_verifier); + return sendToServer(server_url + "/users.json", "POST", parameters); + } + + /** + * Executes an HTTP request expecting a JSON response. + * + * @param url + * @param request_method + * @param parameters + * @return response from authentication server + */ + private JSONObject sendToServer(String url, String request_method, Map<String, String> parameters) { + JSONObject json_response; + HttpsURLConnection urlConnection = null; + try { + InputStream is = null; + urlConnection = (HttpsURLConnection) new URL(url).openConnection(); + urlConnection.setRequestMethod(request_method); + urlConnection.setChunkedStreamingMode(0); + urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); + + DataOutputStream writer = new DataOutputStream(urlConnection.getOutputStream()); + writer.writeBytes(formatHttpParameters(parameters)); + writer.close(); + + is = urlConnection.getInputStream(); + String plain_response = new Scanner(is).useDelimiter("\\A").next(); + json_response = new JSONObject(plain_response); + } catch (ClientProtocolException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (IOException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (JSONException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (KeyManagementException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (KeyStoreException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (CertificateException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } + + return json_response; + } private JSONObject getErrorMessage(HttpsURLConnection urlConnection) { - JSONObject error_message = new JSONObject(); - if(urlConnection != null) { - InputStream error_stream = urlConnection.getErrorStream(); - if(error_stream != null) { - String error_response = new Scanner(error_stream).useDelimiter("\\A").next(); - Log.d("Error", error_response); - try { - error_message = new JSONObject(error_response); - } catch (JSONException e) { - Log.d(TAG, e.getMessage()); - e.printStackTrace(); - } - urlConnection.disconnect(); - } - } - return error_message; - } - - private String formatHttpParameters(Map<String, String> parameters) throws UnsupportedEncodingException { - StringBuilder result = new StringBuilder(); - boolean first = true; - - Iterator<String> parameter_iterator = parameters.keySet().iterator(); - while(parameter_iterator.hasNext()) { - if(first) - first = false; - else - result.append("&&"); - - String key = parameter_iterator.next(); - String value = parameters.get(key); - - result.append(URLEncoder.encode(key, "UTF-8")); - result.append("="); - result.append(URLEncoder.encode(value, "UTF-8")); - } - - return result.toString(); - } - - /** - * Downloads a provider.json from a given URL, adding a new provider using the given name. - * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider, the provider name and its provider.json url. - * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if the update was successful. - */ + JSONObject error_message = new JSONObject(); + if (urlConnection != null) { + InputStream error_stream = urlConnection.getErrorStream(); + if (error_stream != null) { + String error_response = new Scanner(error_stream).useDelimiter("\\A").next(); + try { + error_message = new JSONObject(error_response); + } catch (JSONException e) { + e.printStackTrace(); + } + urlConnection.disconnect(); + } + } + return error_message; + } + + private String formatHttpParameters(Map<String, String> parameters) throws UnsupportedEncodingException { + StringBuilder result = new StringBuilder(); + boolean first = true; + + Iterator<String> parameter_iterator = parameters.keySet().iterator(); + while (parameter_iterator.hasNext()) { + if (first) + first = false; + else + result.append("&&"); + + String key = parameter_iterator.next(); + String value = parameters.get(key); + + result.append(URLEncoder.encode(key, "UTF-8")); + result.append("="); + result.append(URLEncoder.encode(value, "UTF-8")); + } + + return result.toString(); + } + + /** + * Downloads a provider.json from a given URL, adding a new provider using the given name. + * + * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider, the provider name and its provider.json url. + * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if the update was successful. + */ private Bundle setUpProvider(Bundle task) { - int progress = 0; - Bundle current_download = new Bundle(); - - if(task != null && task.containsKey(Provider.MAIN_URL)) { - last_provider_main_url = task.getString(Provider.MAIN_URL); - CA_CERT_DOWNLOADED = PROVIDER_JSON_DOWNLOADED = EIP_SERVICE_JSON_DOWNLOADED = false; - go_ahead = true; - } - - if(!PROVIDER_JSON_DOWNLOADED) - current_download = getAndSetProviderJson(last_provider_main_url); - if(PROVIDER_JSON_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) { - broadcastProgress(progress++); - PROVIDER_JSON_DOWNLOADED = true; - - if(!CA_CERT_DOWNLOADED) - current_download = downloadCACert(); - if(CA_CERT_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) { - broadcastProgress(progress++); - CA_CERT_DOWNLOADED = true; - current_download = getAndSetEipServiceJson(); - if(current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY)) { - broadcastProgress(progress++); - EIP_SERVICE_JSON_DOWNLOADED = true; - } - } - } - - return current_download; - } - - private Bundle downloadCACert() { - Bundle result = new Bundle(); - try { - JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - String ca_cert_url = provider_json.getString(Provider.CA_CERT_URI); - String cert_string = downloadWithCommercialCA(ca_cert_url); - result.putBoolean(RESULT_KEY, true); - - if(validCertificate(cert_string) && go_ahead) { - preferences.edit().putString(Provider.CA_CERT, cert_string).commit(); - result.putBoolean(RESULT_KEY, true); - } else { - String reason_to_fail = pickErrorMessage(cert_string); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } - } catch (JSONException e) { - String reason_to_fail = formatErrorMessage(R.string.malformed_url); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } - - return result; - } - - - public static boolean caCertDownloaded() { - return CA_CERT_DOWNLOADED; - } + int progress = 0; + Bundle current_download = new Bundle(); + + if (task != null && task.containsKey(Provider.MAIN_URL)) { + last_provider_main_url = task.getString(Provider.MAIN_URL); + CA_CERT_DOWNLOADED = PROVIDER_JSON_DOWNLOADED = EIP_SERVICE_JSON_DOWNLOADED = false; + go_ahead = true; + } + + if (!PROVIDER_JSON_DOWNLOADED) + current_download = getAndSetProviderJson(last_provider_main_url); + if (PROVIDER_JSON_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) { + broadcastProgress(progress++); + PROVIDER_JSON_DOWNLOADED = true; + + if (!CA_CERT_DOWNLOADED) + current_download = downloadCACert(); + if (CA_CERT_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) { + broadcastProgress(progress++); + CA_CERT_DOWNLOADED = true; + current_download = getAndSetEipServiceJson(); + if (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY)) { + broadcastProgress(progress++); + EIP_SERVICE_JSON_DOWNLOADED = true; + } + } + } + + return current_download; + } + + private Bundle downloadCACert() { + Bundle result = new Bundle(); + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + String ca_cert_url = provider_json.getString(Provider.CA_CERT_URI); + String cert_string = downloadWithCommercialCA(ca_cert_url); + result.putBoolean(RESULT_KEY, true); + + if (validCertificate(cert_string) && go_ahead) { + preferences.edit().putString(Provider.CA_CERT, cert_string).commit(); + result.putBoolean(RESULT_KEY, true); + } else { + String reason_to_fail = pickErrorMessage(cert_string); + result.putString(ERRORS, reason_to_fail); + result.putBoolean(RESULT_KEY, false); + } + } catch (JSONException e) { + String reason_to_fail = formatErrorMessage(R.string.malformed_url); + result.putString(ERRORS, reason_to_fail); + result.putBoolean(RESULT_KEY, false); + } + + return result; + } + + + public static boolean caCertDownloaded() { + return CA_CERT_DOWNLOADED; + } private boolean validCertificate(String cert_string) { - boolean result = false; - if(!ConfigHelper.checkErroneousDownload(cert_string)) { - X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string); - try { - if(certificate != null) { - JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - String fingerprint = provider_json.getString(Provider.CA_CERT_FINGERPRINT); - String encoding = fingerprint.split(":")[0]; - String expected_fingerprint = fingerprint.split(":")[1]; - String real_fingerprint = base64toHex(Base64.encodeToString( - MessageDigest.getInstance(encoding).digest(certificate.getEncoded()), - Base64.DEFAULT)); - - result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim()); - } - else - result = false; - } catch (JSONException e) { - result = false; - } catch (NoSuchAlgorithmException e) { - result = false; - } catch (CertificateEncodingException e) { - result = false; - } - } - - return result; + boolean result = false; + if (!ConfigHelper.checkErroneousDownload(cert_string)) { + X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string); + try { + if (certificate != null) { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + String fingerprint = provider_json.getString(Provider.CA_CERT_FINGERPRINT); + String encoding = fingerprint.split(":")[0]; + String expected_fingerprint = fingerprint.split(":")[1]; + String real_fingerprint = base64toHex(Base64.encodeToString( + MessageDigest.getInstance(encoding).digest(certificate.getEncoded()), + Base64.DEFAULT)); + + result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim()); + } else + result = false; + } catch (JSONException e) { + result = false; + } catch (NoSuchAlgorithmException e) { + result = false; + } catch (CertificateEncodingException e) { + result = false; + } + } + + return result; } private String base64toHex(String base64_input) { - byte[] byteArray = Base64.decode(base64_input, Base64.DEFAULT); - int readBytes = byteArray.length; - StringBuffer hexData = new StringBuffer(); - int onebyte; - for (int i=0; i < readBytes; i++) { - onebyte = ((0x000000ff & byteArray[i]) | 0xffffff00); - hexData.append(Integer.toHexString(onebyte).substring(6)); - } - return hexData.toString(); - } - - private Bundle getAndSetProviderJson(String provider_main_url) { - Bundle result = new Bundle(); - - if(go_ahead) { - String provider_dot_json_string = downloadWithCommercialCA(provider_main_url + "/provider.json"); - - try { - JSONObject provider_json = new JSONObject(provider_dot_json_string); - provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); - String name = provider_json.getString(Provider.NAME); - //TODO setProviderName(name); - - preferences.edit().putString(Provider.KEY, provider_json.toString()).commit(); - preferences.edit().putBoolean(Constants.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_ANON)).commit(); - preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_REGISTERED)).commit(); - - result.putBoolean(RESULT_KEY, true); - } catch (JSONException e) { - //TODO Error message should be contained in that provider_dot_json_string - String reason_to_fail = pickErrorMessage(provider_dot_json_string); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } - } - return result; - } - - private Bundle getAndSetEipServiceJson() { - Bundle result = new Bundle(); - String eip_service_json_string = ""; - if(go_ahead) { - try { - JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - String eip_service_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH; - eip_service_json_string = downloadWithProviderCA(eip_service_url); - JSONObject eip_service_json = new JSONObject(eip_service_json_string); - eip_service_json.getInt(Provider.API_RETURN_SERIAL); - - preferences.edit().putString(Constants.KEY, eip_service_json.toString()).commit(); - - result.putBoolean(RESULT_KEY, true); - } catch (JSONException e) { - String reason_to_fail = pickErrorMessage(eip_service_json_string); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(RESULT_KEY, false); - } - } - return result; - } - - /** - * Interprets the error message as a JSON object and extract the "errors" keyword pair. - * If the error message is not a JSON object, then it is returned untouched. - * @param string_json_error_message - * @return final error message - */ - private String pickErrorMessage(String string_json_error_message) { - String error_message = ""; - try { - JSONObject json_error_message = new JSONObject(string_json_error_message); - error_message = json_error_message.getString(ERRORS); - } catch (JSONException e) { - // TODO Auto-generated catch block - error_message = string_json_error_message; - } - - return error_message; - } - - /** - * Tries to download the contents of the provided url using commercially validated CA certificate from chosen provider. - * - * @param string_url - * @return - */ - private String downloadWithCommercialCA(String string_url) { - - String json_file_content = ""; - - URL provider_url = null; - int seconds_of_timeout = 1; - try { - provider_url = new URL(string_url); - URLConnection url_connection = provider_url.openConnection(); - url_connection.setConnectTimeout(seconds_of_timeout*1000); - if(!LeapSRPSession.getToken().isEmpty()) - url_connection.addRequestProperty(LeapSRPSession.AUTHORIZATION_HEADER, "Token token = " + LeapSRPSession.getToken()); - json_file_content = new Scanner(url_connection.getInputStream()).useDelimiter("\\A").next(); - } catch (MalformedURLException e) { - json_file_content = formatErrorMessage(R.string.malformed_url); - } catch(SocketTimeoutException e) { - e.printStackTrace(); - json_file_content = formatErrorMessage(R.string.server_unreachable_message); - } catch (SSLHandshakeException e) { - if(provider_url != null) { - json_file_content = downloadWithProviderCA(string_url); - } else { - json_file_content = formatErrorMessage(R.string.certificate_error); - } - } catch(ConnectException e) { - json_file_content = formatErrorMessage(R.string.service_is_down_error); - } catch (FileNotFoundException e) { - json_file_content = formatErrorMessage(R.string.malformed_url); - } catch (Exception e) { - e.printStackTrace(); - if(provider_url != null) { - json_file_content = downloadWithProviderCA(string_url); - } - } - - return json_file_content; - } - - /** - * Tries to download the contents of the provided url using not commercially validated CA certificate from chosen provider. - * @param url_string as a string - * @return an empty string if it fails, the url content if not. - */ - private String downloadWithProviderCA(String url_string) { - String json_file_content = ""; - - try { - URL url = new URL(url_string); - // Tell the URLConnection to use a SocketFactory from our SSLContext - HttpsURLConnection urlConnection = - (HttpsURLConnection)url.openConnection(); - urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); - if(!LeapSRPSession.getToken().isEmpty()) - urlConnection.addRequestProperty(LeapSRPSession.AUTHORIZATION_HEADER, "Token token=" + LeapSRPSession.getToken()); - json_file_content = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (UnknownHostException e) { - e.printStackTrace(); - json_file_content = formatErrorMessage(R.string.server_unreachable_message); - } catch (IOException e) { - // The downloaded certificate doesn't validate our https connection. - json_file_content = formatErrorMessage(R.string.certificate_error); - } 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(); - } catch (NoSuchElementException e) { - e.printStackTrace(); - json_file_content = formatErrorMessage(R.string.server_unreachable_message); - } - return json_file_content; - } - - private javax.net.ssl.SSLSocketFactory getProviderSSLSocketFactory() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException { - String provider_cert_string = preferences.getString(Provider.CA_CERT,""); - - java.security.cert.Certificate provider_certificate = ConfigHelper.parseX509CertificateFromString(provider_cert_string); - - // Create a KeyStore containing our trusted CAs - String keyStoreType = KeyStore.getDefaultType(); - KeyStore keyStore = KeyStore.getInstance(keyStoreType); - keyStore.load(null, null); - keyStore.setCertificateEntry("provider_ca_certificate", provider_certificate); - - // 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); - - return context.getSocketFactory(); - } - - /** - * Downloads the string that's in the url with any certificate. - */ - private String downloadWithoutCA(String url_string) { - String string = ""; - try { - - HostnameVerifier hostnameVerifier = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; - - class DefaultTrustManager implements X509TrustManager { - - @Override - public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} - - @Override - public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} - - @Override - public X509Certificate[] getAcceptedIssuers() { - return null; - } - } - - SSLContext context = SSLContext.getInstance("TLS"); - context.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom()); - - URL url = new URL(url_string); - HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection(); - urlConnection.setSSLSocketFactory(context.getSocketFactory()); - urlConnection.setHostnameVerifier(hostnameVerifier); - string = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); - System.out.println("String ignoring certificate = " + string); - } catch (FileNotFoundException e) { - e.printStackTrace(); - string = formatErrorMessage(R.string.malformed_url); - } catch (IOException e) { - // The downloaded certificate doesn't validate our https connection. - e.printStackTrace(); - string = formatErrorMessage(R.string.certificate_error); - } catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (KeyManagementException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return string; - } + byte[] byteArray = Base64.decode(base64_input, Base64.DEFAULT); + int readBytes = byteArray.length; + StringBuffer hexData = new StringBuffer(); + int onebyte; + for (int i = 0; i < readBytes; i++) { + onebyte = ((0x000000ff & byteArray[i]) | 0xffffff00); + hexData.append(Integer.toHexString(onebyte).substring(6)); + } + return hexData.toString(); + } + + private Bundle getAndSetProviderJson(String provider_main_url) { + Bundle result = new Bundle(); + + if (go_ahead) { + String provider_dot_json_string = downloadWithCommercialCA(provider_main_url + "/provider.json"); + + try { + JSONObject provider_json = new JSONObject(provider_dot_json_string); + provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); + String name = provider_json.getString(Provider.NAME); + //TODO setProviderName(name); + + preferences.edit().putString(Provider.KEY, provider_json.toString()).commit(); + preferences.edit().putBoolean(Constants.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_ANON)).commit(); + preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(Constants.ALLOWED_REGISTERED)).commit(); + + result.putBoolean(RESULT_KEY, true); + } catch (JSONException e) { + //TODO Error message should be contained in that provider_dot_json_string + String reason_to_fail = pickErrorMessage(provider_dot_json_string); + result.putString(ERRORS, reason_to_fail); + result.putBoolean(RESULT_KEY, false); + } + } + return result; + } + + private Bundle getAndSetEipServiceJson() { + Bundle result = new Bundle(); + String eip_service_json_string = ""; + if (go_ahead) { + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + String eip_service_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH; + eip_service_json_string = downloadWithProviderCA(eip_service_url); + JSONObject eip_service_json = new JSONObject(eip_service_json_string); + eip_service_json.getInt(Provider.API_RETURN_SERIAL); + + preferences.edit().putString(Constants.KEY, eip_service_json.toString()).commit(); + + result.putBoolean(RESULT_KEY, true); + } catch (JSONException e) { + String reason_to_fail = pickErrorMessage(eip_service_json_string); + result.putString(ERRORS, reason_to_fail); + result.putBoolean(RESULT_KEY, false); + } + } + return result; + } + + /** + * Interprets the error message as a JSON object and extract the "errors" keyword pair. + * If the error message is not a JSON object, then it is returned untouched. + * + * @param string_json_error_message + * @return final error message + */ + private String pickErrorMessage(String string_json_error_message) { + String error_message = ""; + try { + JSONObject json_error_message = new JSONObject(string_json_error_message); + error_message = json_error_message.getString(ERRORS); + } catch (JSONException e) { + // TODO Auto-generated catch block + error_message = string_json_error_message; + } + + return error_message; + } + + /** + * Tries to download the contents of the provided url using commercially validated CA certificate from chosen provider. + * + * @param string_url + * @return + */ + private String downloadWithCommercialCA(String string_url) { + + String json_file_content = ""; + + URL provider_url = null; + int seconds_of_timeout = 1; + try { + provider_url = new URL(string_url); + URLConnection url_connection = provider_url.openConnection(); + url_connection.setConnectTimeout(seconds_of_timeout * 1000); + if (!LeapSRPSession.getToken().isEmpty()) + url_connection.addRequestProperty(LeapSRPSession.AUTHORIZATION_HEADER, "Token token = " + LeapSRPSession.getToken()); + json_file_content = new Scanner(url_connection.getInputStream()).useDelimiter("\\A").next(); + } catch (MalformedURLException e) { + json_file_content = formatErrorMessage(R.string.malformed_url); + } catch (SocketTimeoutException e) { + e.printStackTrace(); + json_file_content = formatErrorMessage(R.string.server_unreachable_message); + } catch (SSLHandshakeException e) { + if (provider_url != null) { + json_file_content = downloadWithProviderCA(string_url); + } else { + json_file_content = formatErrorMessage(R.string.certificate_error); + } + } catch (ConnectException e) { + json_file_content = formatErrorMessage(R.string.service_is_down_error); + } catch (FileNotFoundException e) { + json_file_content = formatErrorMessage(R.string.malformed_url); + } catch (Exception e) { + e.printStackTrace(); + if (provider_url != null) { + json_file_content = downloadWithProviderCA(string_url); + } + } + + return json_file_content; + } + + /** + * Tries to download the contents of the provided url using not commercially validated CA certificate from chosen provider. + * + * @param url_string as a string + * @return an empty string if it fails, the url content if not. + */ + private String downloadWithProviderCA(String url_string) { + String json_file_content = ""; + + try { + URL url = new URL(url_string); + // Tell the URLConnection to use a SocketFactory from our SSLContext + HttpsURLConnection urlConnection = + (HttpsURLConnection) url.openConnection(); + urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); + if (!LeapSRPSession.getToken().isEmpty()) + urlConnection.addRequestProperty(LeapSRPSession.AUTHORIZATION_HEADER, "Token token=" + LeapSRPSession.getToken()); + json_file_content = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (UnknownHostException e) { + e.printStackTrace(); + json_file_content = formatErrorMessage(R.string.server_unreachable_message); + } catch (IOException e) { + // The downloaded certificate doesn't validate our https connection. + json_file_content = formatErrorMessage(R.string.certificate_error); + } 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(); + } catch (NoSuchElementException e) { + e.printStackTrace(); + json_file_content = formatErrorMessage(R.string.server_unreachable_message); + } + return json_file_content; + } + + private javax.net.ssl.SSLSocketFactory getProviderSSLSocketFactory() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException { + String provider_cert_string = preferences.getString(Provider.CA_CERT, ""); + + java.security.cert.Certificate provider_certificate = ConfigHelper.parseX509CertificateFromString(provider_cert_string); + + // Create a KeyStore containing our trusted CAs + String keyStoreType = KeyStore.getDefaultType(); + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + keyStore.load(null, null); + keyStore.setCertificateEntry("provider_ca_certificate", provider_certificate); + + // 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); + + return context.getSocketFactory(); + } + + /** + * Downloads the string that's in the url with any certificate. + */ + private String downloadWithoutCA(String url_string) { + String string = ""; + try { + + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + + class DefaultTrustManager implements X509TrustManager { + + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + } + + SSLContext context = SSLContext.getInstance("TLS"); + context.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom()); + + URL url = new URL(url_string); + HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); + urlConnection.setSSLSocketFactory(context.getSocketFactory()); + urlConnection.setHostnameVerifier(hostnameVerifier); + string = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); + System.out.println("String ignoring certificate = " + string); + } catch (FileNotFoundException e) { + e.printStackTrace(); + string = formatErrorMessage(R.string.malformed_url); + } catch (IOException e) { + // The downloaded certificate doesn't validate our https connection. + e.printStackTrace(); + string = formatErrorMessage(R.string.certificate_error); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (KeyManagementException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return string; + } private boolean logOut() { String delete_url = provider_api_url + "/logout"; @@ -826,113 +840,110 @@ public class ProviderAPI extends IntentService { HttpsURLConnection urlConnection = null; int responseCode = 0; int progress = 0; - try { - - urlConnection = (HttpsURLConnection)new URL(delete_url).openConnection(); - urlConnection.setRequestMethod("DELETE"); - urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); - - responseCode = urlConnection.getResponseCode(); - broadcastProgress(progress++); - LeapSRPSession.setToken(""); - Log.d(TAG, Integer.toString(responseCode)); - } 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 - try { - if(urlConnection != null) { - responseCode = urlConnection.getResponseCode(); - if(responseCode == 401) { - broadcastProgress(progress++); - LeapSRPSession.setToken(""); - Log.d(TAG, Integer.toString(responseCode)); - return true; - } - } - } catch (IOException e1) { - e1.printStackTrace(); - } - - e.printStackTrace(); - return false; - } catch (KeyManagementException 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 (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return true; - } - - /** - * Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate. - * - * @return true if certificate was downloaded correctly, false if provider.json is not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error. - */ - private boolean updateVpnCertificate() { - try { - JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - - String provider_main_url = provider_json.getString(Provider.API_URL); - URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + Constants.CERTIFICATE); - - String cert_string = downloadWithProviderCA(new_cert_string_url.toString()); - - if(cert_string.isEmpty() || ConfigHelper.checkErroneousDownload(cert_string)) - return false; - else - return loadCertificate(cert_string); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } - } + try { + + urlConnection = (HttpsURLConnection) new URL(delete_url).openConnection(); + urlConnection.setRequestMethod("DELETE"); + urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); + + responseCode = urlConnection.getResponseCode(); + broadcastProgress(progress++); + LeapSRPSession.setToken(""); + } 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 + try { + if (urlConnection != null) { + responseCode = urlConnection.getResponseCode(); + if (responseCode == 401) { + broadcastProgress(progress++); + LeapSRPSession.setToken(""); + return true; + } + } + } catch (IOException e1) { + e1.printStackTrace(); + } + + e.printStackTrace(); + return false; + } catch (KeyManagementException 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 (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return true; + } + + /** + * Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate. + * + * @return true if certificate was downloaded correctly, false if provider.json is not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error. + */ + private boolean updateVpnCertificate() { + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + + String provider_main_url = provider_json.getString(Provider.API_URL); + URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + Constants.CERTIFICATE); + + String cert_string = downloadWithProviderCA(new_cert_string_url.toString()); + + if (cert_string.isEmpty() || ConfigHelper.checkErroneousDownload(cert_string)) + return false; + else + return loadCertificate(cert_string); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + } private boolean loadCertificate(String cert_string) { - try { - // API returns concatenated cert & key. Split them for OpenVPN options - String certificateString = null, keyString = null; - String[] certAndKey = cert_string.split("(?<=-\n)"); - for (int i=0; i < certAndKey.length-1; i++){ - if ( certAndKey[i].contains("KEY") ) { - keyString = certAndKey[i++] + certAndKey[i]; - } - else if ( certAndKey[i].contains("CERTIFICATE") ) { - certificateString = certAndKey[i++] + certAndKey[i]; - } - } - - RSAPrivateKey key = ConfigHelper.parseRsaKeyFromString(keyString); - keyString = Base64.encodeToString(key.getEncoded(), Base64.DEFAULT); - preferences.edit().putString(Constants.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit(); - - X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificateString); - certificateString = Base64.encodeToString(certificate.getEncoded(), Base64.DEFAULT); - preferences.edit().putString(Constants.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit(); - return true; - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } + try { + // API returns concatenated cert & key. Split them for OpenVPN options + String certificateString = null, keyString = null; + String[] certAndKey = cert_string.split("(?<=-\n)"); + for (int i = 0; i < certAndKey.length - 1; i++) { + if (certAndKey[i].contains("KEY")) { + keyString = certAndKey[i++] + certAndKey[i]; + } else if (certAndKey[i].contains("CERTIFICATE")) { + certificateString = certAndKey[i++] + certAndKey[i]; + } + } + + RSAPrivateKey key = ConfigHelper.parseRsaKeyFromString(keyString); + keyString = Base64.encodeToString(key.getEncoded(), Base64.DEFAULT); + preferences.edit().putString(Constants.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n" + keyString + "-----END RSA PRIVATE KEY-----").commit(); + + X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificateString); + certificateString = Base64.encodeToString(certificate.getEncoded(), Base64.DEFAULT); + preferences.edit().putString(Constants.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n" + certificateString + "-----END CERTIFICATE-----").commit(); + return true; + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } } } diff --git a/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java b/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java index 97ce5245..24d048a6 100644 --- a/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java +++ b/app/src/release/java/se/leap/bitmaskclient/ProviderDetailFragment.java @@ -1,110 +1,111 @@ -package se.leap.bitmaskclient; - -import org.json.*; - -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.eip.Constants; -import se.leap.bitmaskclient.ProviderListContent.ProviderItem; - -import android.app.*; -import android.content.*; -import android.os.Bundle; -import android.view.*; -import android.widget.TextView; - +package se.leap.bitmaskclient;
+
+import org.json.*;
+
+import se.leap.bitmaskclient.eip.*;
+import se.leap.bitmaskclient.ProviderListContent.ProviderItem;
+
+import android.app.*;
+import android.content.*;
+import android.os.*;
+import android.view.*;
+import android.widget.*;
+
public class ProviderDetailFragment extends DialogFragment {
final public static String TAG = "providerDetailFragment";
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- try {
-
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View provider_detail_view = inflater.inflate(R.layout.provider_detail_fragment, null);
-
- JSONObject provider_json = new JSONObject(getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, getActivity().MODE_PRIVATE).getString(Provider.KEY, ""));
-
- final TextView domain = (TextView)provider_detail_view.findViewById(R.id.provider_detail_domain);
- domain.setText(provider_json.getString(Provider.DOMAIN));
- final TextView name = (TextView)provider_detail_view.findViewById(R.id.provider_detail_name);
- name.setText(provider_json.getJSONObject(Provider.NAME).getString("en"));
- final TextView description = (TextView)provider_detail_view.findViewById(R.id.provider_detail_description);
- description.setText(provider_json.getJSONObject(Provider.DESCRIPTION).getString("en"));
-
- builder.setView(provider_detail_view);
- builder.setTitle(R.string.provider_details_fragment_title);
-
- if(anon_allowed(provider_json)) {
- builder.setPositiveButton(R.string.use_anonymously_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- interface_with_configuration_wizard.use_anonymously();
- }
- });
- }
-
- if(registration_allowed(provider_json)) {
- builder.setNegativeButton(R.string.signup_or_login_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- interface_with_configuration_wizard.login();
- }
- });
- }
-
- return builder.create();
- } catch (JSONException e) {
- return null;
- }
- }
-
- private boolean anon_allowed(JSONObject provider_json) {
- try {
- JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
- return service_description.has(Constants.ALLOWED_ANON) && service_description.getBoolean(Constants.ALLOWED_ANON); - } catch (JSONException e) {
- return false;
- }
- }
-
- private boolean registration_allowed(JSONObject provider_json) {
- try {
- JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
- return service_description.has(Provider.ALLOW_REGISTRATION) && service_description.getBoolean(Provider.ALLOW_REGISTRATION);
- } catch (JSONException e) {
- return false;
- }
- }
-
- @Override
- public void onCancel(DialogInterface dialog) {
- super.onCancel(dialog);
- SharedPreferences.Editor editor = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).edit();
- editor.remove(Provider.KEY).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit(); - interface_with_configuration_wizard.showAllProviders(); - }
-
- public static DialogFragment newInstance() {
- ProviderDetailFragment provider_detail_fragment = new ProviderDetailFragment();
- return provider_detail_fragment;
- }
-
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ try {
+
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+ View provider_detail_view = inflater.inflate(R.layout.provider_detail_fragment, null);
+
+ JSONObject provider_json = new JSONObject(getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, getActivity().MODE_PRIVATE).getString(Provider.KEY, ""));
+
+ final TextView domain = (TextView) provider_detail_view.findViewById(R.id.provider_detail_domain);
+ domain.setText(provider_json.getString(Provider.DOMAIN));
+ final TextView name = (TextView) provider_detail_view.findViewById(R.id.provider_detail_name);
+ name.setText(provider_json.getJSONObject(Provider.NAME).getString("en"));
+ final TextView description = (TextView) provider_detail_view.findViewById(R.id.provider_detail_description);
+ description.setText(provider_json.getJSONObject(Provider.DESCRIPTION).getString("en"));
+
+ builder.setView(provider_detail_view);
+ builder.setTitle(R.string.provider_details_fragment_title);
+
+ if (anon_allowed(provider_json)) {
+ builder.setPositiveButton(R.string.use_anonymously_button, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ interface_with_configuration_wizard.use_anonymously();
+ }
+ });
+ }
+
+ if (registration_allowed(provider_json)) {
+ builder.setNegativeButton(R.string.signup_or_login_button, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ interface_with_configuration_wizard.login();
+ }
+ });
+ }
+
+ return builder.create();
+ } catch (JSONException e) {
+ return null;
+ }
+ }
+
+ private boolean anon_allowed(JSONObject provider_json) {
+ try {
+ JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
+ return service_description.has(Constants.ALLOWED_ANON) && service_description.getBoolean(Constants.ALLOWED_ANON);
+ } catch (JSONException e) {
+ return false;
+ }
+ }
+
+ private boolean registration_allowed(JSONObject provider_json) {
+ try {
+ JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
+ return service_description.has(Provider.ALLOW_REGISTRATION) && service_description.getBoolean(Provider.ALLOW_REGISTRATION);
+ } catch (JSONException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ SharedPreferences.Editor editor = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).edit();
+ editor.remove(Provider.KEY).remove(Constants.ALLOWED_ANON).remove(Constants.KEY).commit();
+ interface_with_configuration_wizard.showAllProviders();
+ }
+
+ public static DialogFragment newInstance() {
+ ProviderDetailFragment provider_detail_fragment = new ProviderDetailFragment();
+ return provider_detail_fragment;
+ }
+
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
- interface_with_configuration_wizard = (ProviderDetailFragmentInterface) activity;
+ interface_with_configuration_wizard = (ProviderDetailFragmentInterface) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement LogInDialogListener");
}
}
-
- public interface ProviderDetailFragmentInterface {
- public void login();
- public void use_anonymously();
- public void showAllProviders();
- }
-
- ProviderDetailFragmentInterface interface_with_configuration_wizard;
+
+ public interface ProviderDetailFragmentInterface {
+ public void login();
+
+ public void use_anonymously();
+
+ public void showAllProviders();
+ }
+
+ ProviderDetailFragmentInterface interface_with_configuration_wizard;
}
diff --git a/app/src/release/java/se/leap/bitmaskclient/ProviderListContent.java b/app/src/release/java/se/leap/bitmaskclient/ProviderListContent.java index a5402fd8..235ae5ab 100644 --- a/app/src/release/java/se/leap/bitmaskclient/ProviderListContent.java +++ b/app/src/release/java/se/leap/bitmaskclient/ProviderListContent.java @@ -1,6 +1,6 @@ /**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -14,72 +14,68 @@ * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
- package se.leap.bitmaskclient;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.net.URL;
-import java.net.MalformedURLException;
+package se.leap.bitmaskclient;
-import org.json.JSONException;
-import org.json.JSONObject;
+import java.util.*;
+import java.net.*;
/**
* Models the provider list shown in the ConfigurationWizard.
- *
- * @author parmegv
*
+ * @author parmegv
*/
public class ProviderListContent {
- public static List<ProviderItem> ITEMS = new ArrayList<ProviderItem>();
+ public static List<ProviderItem> ITEMS = new ArrayList<ProviderItem>();
+
+ public static Map<String, ProviderItem> ITEM_MAP = new HashMap<String, ProviderItem>();
+
+ /**
+ * 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);
+ }
+
+ public static void removeItem(ProviderItem item) {
+ ITEMS.remove(item);
+ ITEM_MAP.remove(item);
+ }
+
+ /**
+ * A provider item.
+ */
+ public static class ProviderItem {
+ final public static String CUSTOM = "custom";
+ private String provider_main_url;
+ private String name;
- public static Map<String, ProviderItem> ITEM_MAP = new HashMap<String, ProviderItem>();
+ /**
+ * @param name of the provider
+ * @param provider_main_url used to download provider.json file of the provider
+ */
+ public ProviderItem(String name, String provider_main_url) {
+ this.name = name;
+ this.provider_main_url = provider_main_url;
+ }
- /**
- * 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);
- }
- public static void removeItem(ProviderItem item) {
- ITEMS.remove(item);
- ITEM_MAP.remove(item);
- }
+ public String name() {
+ return name;
+ }
- /**
- * A provider item.
- */ - public static class ProviderItem {
- final public static String CUSTOM = "custom";
- private String provider_main_url;
- private String name; + public String providerMainUrl() {
+ return provider_main_url;
+ }
- /**
- * @param name of the provider
- * @param provider_main_url used to download provider.json file of the provider
- */ - public ProviderItem(String name, String provider_main_url) {
- this.name = name;
- this.provider_main_url = provider_main_url; - }
-
- public String name() { return name; }
-
- public String providerMainUrl() { return provider_main_url; }
-
- public String domain() {
- try {
- return new URL(provider_main_url).getHost();
- } catch (MalformedURLException e) {
- return provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("/.*", "");
- }
- }
- }
+ public String domain() {
+ try {
+ return new URL(provider_main_url).getHost();
+ } catch (MalformedURLException e) {
+ return provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("/.*", "");
+ }
+ }
+ }
}
|