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("/.*", "");
 +            }
 +        }
 +    }
  }
 | 
