summaryrefslogtreecommitdiff
path: root/app/src/main/java/se/leap/bitmaskclient
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/se/leap/bitmaskclient')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java5
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Dashboard.java471
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EIP.java534
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java40
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java51
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/LeapHttpClient.java77
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java13
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/LogInDialog.java15
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Provider.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java39
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java11
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java37
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java36
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java146
15 files changed, 792 insertions, 686 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
index a8bd3b7a..c95d0c8b 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
@@ -18,8 +18,9 @@ package se.leap.bitmaskclient;
import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.math.BigInteger;
import java.io.InputStream;
+import java.math.BigInteger;
+import java.lang.IllegalArgumentException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
@@ -105,6 +106,8 @@ public class ConfigHelper {
e.printStackTrace();
} catch (IOException e) {
return null;
+ } catch (IllegalArgumentException e) {
+ return null;
}
return (X509Certificate) certificate;
diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
index 761afc0a..364a79af 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
@@ -21,13 +21,14 @@ import org.json.JSONObject;
import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver;
+import se.leap.bitmaskclient.FragmentManagerEnhanced;
import se.leap.bitmaskclient.SignUpDialog;
+
import de.blinkt.openvpn.activities.LogWindow;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DialogFragment;
-import android.app.Fragment;
-import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.DialogInterface;
@@ -65,6 +66,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
public static final String START_ON_BOOT = "dashboard start on boot";
final public static String ON_BOOT = "dashboard on boot";
public static final String APP_VERSION = "bitmask version";
+ final public static String TAG = Dashboard.class.getSimpleName();
private EipServiceFragment eipFragment;
@@ -74,11 +76,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
protected static SharedPreferences preferences;
private static Provider provider;
- private TextView providerNameTV;
-
private boolean authed_eip = false;
public ProviderAPIResultReceiver providerAPI_result_receiver;
+ private FragmentManagerEnhanced fragment_manager;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -91,6 +92,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
+ fragment_manager = new FragmentManagerEnhanced(getFragmentManager());
handleVersion();
authed_eip = preferences.getBoolean(EIP.AUTHED_EIP, false);
@@ -110,11 +112,13 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
switch(versionCode) {
case 91: // 0.6.0 without Bug #5999
+ case 101: // 0.8.0
if(!preferences.getString(EIP.KEY, "").isEmpty()) {
Intent rebuildVpnProfiles = new Intent(getApplicationContext(), EIP.class);
rebuildVpnProfiles.setAction(EIP.ACTION_REBUILD_PROFILES);
startService(rebuildVpnProfiles);
}
+ break;
}
} catch (NameNotFoundException e) {
}
@@ -131,21 +135,23 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
}
@Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data){
+ protected void onActivityResult(int requestCode, int resultCode, final Intent data){
if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) {
// It should be equivalent: if ( (requestCode == CONFIGURE_LEAP) || (data!= null && data.hasExtra(STOP_FIRST))) {
- if ( resultCode == RESULT_OK ){
- preferences.edit().putInt(EIP.PARSED_SERIAL, 0).commit();
- preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit();
- Intent updateEIP = new Intent(getApplicationContext(), EIP.class);
- updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE);
- startService(updateEIP);
- buildDashboard(false);
- invalidateOptionsMenu();
- if(data != null && data.hasExtra(LogInDialog.VERB)) {
- View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
- logInDialog(Bundle.EMPTY);
- }
+ if ( resultCode == RESULT_OK ){
+ preferences.edit().putInt(EIP.PARSED_SERIAL, 0).commit();
+ preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit();
+
+ Intent updateEIP = new Intent(getApplicationContext(), EIP.class);
+ updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE);
+ startService(updateEIP);
+
+ buildDashboard(false);
+ invalidateOptionsMenu();
+ if(data != null && data.hasExtra(LogInDialog.TAG)) {
+ View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
+ logInDialog(Bundle.EMPTY);
+ }
} else if(resultCode == RESULT_CANCELED && (data == null || data.hasExtra(ACTION_QUIT))) {
finish();
} else
@@ -189,13 +195,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
setContentView(R.layout.client_dashboard);
- providerNameTV = (TextView) findViewById(R.id.providerName);
+ TextView providerNameTV = (TextView) findViewById(R.id.providerName);
providerNameTV.setText(provider.getDomain());
providerNameTV.setTextSize(28);
mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
- FragmentManager fragMan = getFragmentManager();
if ( provider.hasEIP()){
eipFragment = new EipServiceFragment();
if (hide_and_turn_on_eip) {
@@ -204,7 +209,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
arguments.putBoolean(EipServiceFragment.START_ON_BOOT, true);
eipFragment.setArguments(arguments);
}
- fragMan.beginTransaction().replace(R.id.servicesCollection, eipFragment, EipServiceFragment.TAG).commit();
+ fragment_manager.replace(R.id.servicesCollection, eipFragment, EipServiceFragment.TAG);
if (hide_and_turn_on_eip) {
onBackPressed();
@@ -212,31 +217,35 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
}
}
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- JSONObject provider_json;
- try {
- provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
- JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
- boolean authed_eip = preferences.getBoolean(EIP.AUTHED_EIP, false);
- boolean allow_registered_eip = service_description.getBoolean(Provider.ALLOW_REGISTRATION);
- preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, allow_registered_eip);
- 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;
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ JSONObject provider_json;
+ try {
+ String provider_json_string = preferences.getString(Provider.KEY, "");
+ if(provider_json_string.isEmpty() == false) {
+ 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(EIP.ALLOWED_REGISTERED, allow_registered_eip);
+
+ 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;
+ }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
@@ -268,14 +277,13 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
startActivityForResult(new Intent(this,ConfigurationWizard.class), SWITCH_PROVIDER);
return true;
case R.id.login_button:
- View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
logInDialog(Bundle.EMPTY);
return true;
case R.id.logout_button:
logOut();
return true;
case R.id.signup_button:
- signUpDialog(((ViewGroup)findViewById(android.R.id.content)).getChildAt(0), Bundle.EMPTY);
+ signUpDialog(Bundle.EMPTY);
return true;
default:
return super.onOptionsItemSelected(item);
@@ -283,38 +291,48 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
}
- @Override
- public void authenticate(String username, String password) {
- mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
- eipStatus = (TextView) findViewById(R.id.eipStatus);
+ private Intent prepareProviderAPICommand() {
+ mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
+ eipStatus = (TextView) findViewById(R.id.eipStatus);
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- providerAPI_result_receiver.setReceiver(this);
+ providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
+ providerAPI_result_receiver.setReceiver(this);
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
+ Intent command = new Intent(this, ProviderAPI.class);
- Bundle parameters = new Bundle();
- parameters.putString(LogInDialog.USERNAME, username);
- parameters.putString(LogInDialog.PASSWORD, password);
-
- JSONObject provider_json;
- try {
- provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
- parameters.putString(Provider.API_URL, provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION));
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
+ command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
+ return command;
+ }
+
+ /**
+ * Shows the log in dialog.
+ */
+ public void logInDialog(Bundle resultData) {
+ FragmentTransaction transaction = fragment_manager.removePreviousFragment(LogInDialog.TAG);
+
+ DialogFragment newFragment = LogInDialog.newInstance();
+ if(resultData != null && !resultData.isEmpty())
+ newFragment.setArguments(resultData);
+ newFragment.show(transaction, LogInDialog.TAG);
+ }
- provider_API_command.setAction(ProviderAPI.SRP_AUTH);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
-
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- eipStatus.setText(R.string.authenticating_message);
- //mProgressBar.setMax(4);
- startService(provider_API_command);
- }
+ @Override
+ public void logIn(String username, String password) {
+ Intent provider_API_command = prepareProviderAPICommand();
+ Bundle parameters = provider_API_command.getExtras().getBundle(ProviderAPI.PARAMETERS);
+ if(parameters == null)
+ parameters = new Bundle();
+
+ parameters.putString(SessionDialogInterface.USERNAME, username);
+ parameters.putString(SessionDialogInterface.PASSWORD, password);
+
+ mProgressBar.setVisibility(ProgressBar.VISIBLE);
+ eipStatus.setText(R.string.authenticating_message);
+
+ provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
+ provider_API_command.setAction(ProviderAPI.SRP_AUTH);
+ startService(provider_API_command);
+ }
public void cancelAuthedEipOn() {
EipServiceFragment eipFragment = (EipServiceFragment) getFragmentManager().findFragmentByTag(EipServiceFragment.TAG);
@@ -322,125 +340,59 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
}
public void cancelLoginOrSignup() {
- if(mProgressBar == null) mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
- if(mProgressBar != null) {
- mProgressBar.setVisibility(ProgressBar.GONE);
- if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus);
- if(eipStatus != null) eipStatus.setText("");
- }
- cancelAuthedEipOn();
+ hideProgressBar();
}
- /**
- * Asks ProviderAPI to log out.
- */
- public void logOut() {
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- providerAPI_result_receiver.setReceiver(this);
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle parameters = new Bundle();
-
- JSONObject provider_json;
- try {
- provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
- parameters.putString(Provider.API_URL, provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION));
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- provider_API_command.setAction(ProviderAPI.LOG_OUT);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
-
- if(mProgressBar == null) mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus);
- eipStatus.setText(R.string.logout_message);
- // eipStatus.setText("Starting to logout");
-
- startService(provider_API_command);
- //mProgressBar.setMax(1);
-
- }
-
- /**
- * Shows the log in dialog.
- */
- public void logInDialog(Bundle resultData) {
- Log.d("Dashboard", "Log In Dialog");
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_log_in_dialog = getFragmentManager().findFragmentByTag(LogInDialog.TAG);
- if (previous_log_in_dialog != null) {
- fragment_transaction.remove(previous_log_in_dialog);
- }
- fragment_transaction.addToBackStack(null);
-
- DialogFragment newFragment = LogInDialog.newInstance();
- if(resultData != null && !resultData.isEmpty()) {
- newFragment.setArguments(resultData);
- }
- newFragment.show(fragment_transaction, LogInDialog.TAG);
- }
-
- @Override
- public void signUp(String username, String password) {
- mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
- eipStatus = (TextView) findViewById(R.id.eipStatus);
-
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- providerAPI_result_receiver.setReceiver(this);
-
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle parameters = new Bundle();
- parameters.putString(SignUpDialog.USERNAME, username);
- parameters.putString(SignUpDialog.PASSWORD, password);
-
- JSONObject provider_json;
- try {
- provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
- parameters.putString(Provider.API_URL, provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION));
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- provider_API_command.setAction(ProviderAPI.SRP_REGISTER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
+ /**
+ * Asks ProviderAPI to log out.
+ */
+ public void logOut() {
+ Intent provider_API_command = prepareProviderAPICommand();
+
+ if(mProgressBar == null) mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
+ mProgressBar.setVisibility(ProgressBar.VISIBLE);
+ if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus);
+ eipStatus.setText(R.string.logout_message);
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- eipStatus.setText(R.string.signingup_message);
- //mProgressBar.setMax(4);
- startService(provider_API_command);
- }
+ provider_API_command.setAction(ProviderAPI.LOG_OUT);
+ startService(provider_API_command);
+ }
- /**
- * Shows the sign up dialog.
- * @param view from which the dialog is created.
- */
- public void signUpDialog(View view, Bundle resultData) {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_sign_up_dialog = getFragmentManager().findFragmentByTag(SignUpDialog.TAG);
- if (previous_sign_up_dialog != null) {
- fragment_transaction.remove(previous_sign_up_dialog);
- }
- fragment_transaction.addToBackStack(null);
-
- DialogFragment newFragment = SignUpDialog.newInstance();
- if(resultData != null && !resultData.isEmpty()) {
- newFragment.setArguments(resultData);
- }
- newFragment.show(fragment_transaction, SignUpDialog.TAG);
+ /**
+ * Shows the sign up dialog.
+ */
+ public void signUpDialog(Bundle resultData) {
+ FragmentTransaction transaction = fragment_manager.removePreviousFragment(SignUpDialog.TAG);
+
+ DialogFragment newFragment = SignUpDialog.newInstance();
+ if(resultData != null && !resultData.isEmpty()) {
+ newFragment.setArguments(resultData);
}
+ newFragment.show(transaction, SignUpDialog.TAG);
+ }
+
+ @Override
+ public void signUp(String username, String password) {
+ Intent provider_API_command = prepareProviderAPICommand();
+ Bundle parameters = provider_API_command.getExtras().getBundle(ProviderAPI.PARAMETERS);
+ if(parameters == null)
+ parameters = new Bundle();
+
+ parameters.putString(SessionDialogInterface.USERNAME, username);
+ parameters.putString(SessionDialogInterface.PASSWORD, password);
+
+ mProgressBar.setVisibility(ProgressBar.VISIBLE);
+ eipStatus.setText(R.string.signingup_message);
+
+ provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
+ provider_API_command.setAction(ProviderAPI.SRP_REGISTER);
+ startService(provider_API_command);
+ }
/**
* Asks ProviderAPI to download an authenticated OpenVPN certificate.
- * @param session_id cookie for the server to allow us to download the certificate.
*/
- private void downloadAuthedUserCertificate(/*Cookie session_id*/) {
+ private void downloadAuthedUserCertificate() {
providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
providerAPI_result_receiver.setReceiver(this);
@@ -448,8 +400,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
Bundle parameters = new Bundle();
parameters.putString(ConfigurationWizard.TYPE_OF_CERTIFICATE, ConfigurationWizard.AUTHED_CERTIFICATE);
- /*parameters.putString(ConfigHelper.SESSION_ID_COOKIE_KEY, session_id.getName());
- parameters.putString(ConfigHelper.SESSION_ID_KEY, session_id.getValue());*/
provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE);
provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
@@ -460,53 +410,70 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
- if(resultCode == ProviderAPI.SRP_REGISTRATION_SUCCESSFUL){
- authenticate(resultData.getString(LogInDialog.USERNAME), resultData.getString(LogInDialog.PASSWORD));
- } else if(resultCode == ProviderAPI.SRP_REGISTRATION_FAILED){
- signUpDialog(((ViewGroup)findViewById(android.R.id.content)).getChildAt(0), resultData);
- } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL){
- String session_id_cookie_key = resultData.getString(ProviderAPI.SESSION_ID_COOKIE_KEY);
- String session_id_string = resultData.getString(ProviderAPI.SESSION_ID_KEY);
- setResult(RESULT_OK);
-
- authed_eip = true;
- preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit();
+ if(resultCode == ProviderAPI.SRP_REGISTRATION_SUCCESSFUL) {
+ String username = resultData.getString(SessionDialogInterface.USERNAME);
+ String password = resultData.getString(SessionDialogInterface.PASSWORD);
+ logIn(username, password);
+ } else if(resultCode == ProviderAPI.SRP_REGISTRATION_FAILED) {
+ changeStatusMessage(resultCode);
+ hideProgressBar();
+
+ signUpDialog(resultData);
+ } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL) {
+ changeStatusMessage(resultCode);
+ hideProgressBar();
+
+ invalidateOptionsMenu();
+
+ authed_eip = true;
+ preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit();
- invalidateOptionsMenu();
- mProgressBar.setVisibility(ProgressBar.GONE);
- changeStatusMessage(resultCode);
+ downloadAuthedUserCertificate();
+ } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_FAILED) {
+ changeStatusMessage(resultCode);
+ hideProgressBar();
+
+ logInDialog(resultData);
+ } else if(resultCode == ProviderAPI.LOGOUT_SUCCESSFUL) {
+ changeStatusMessage(resultCode);
+ hideProgressBar();
+
+ invalidateOptionsMenu();
+
+ authed_eip = false;
+ preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit();
- //Cookie session_id = new BasicClientCookie(session_id_cookie_key, session_id_string);
- downloadAuthedUserCertificate(/*session_id*/);
- } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_FAILED) {
- logInDialog(resultData);
- } else if(resultCode == ProviderAPI.LOGOUT_SUCCESSFUL) {
- authed_eip = false;
- preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit();
- mProgressBar.setVisibility(ProgressBar.GONE);
- mProgressBar.setProgress(0);
- invalidateOptionsMenu();
- setResult(RESULT_OK);
- changeStatusMessage(resultCode);
-
- } else if(resultCode == ProviderAPI.LOGOUT_FAILED) {
- setResult(RESULT_CANCELED);
- changeStatusMessage(resultCode);
- mProgressBar.setVisibility(ProgressBar.GONE);
- } else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
+ } else if(resultCode == ProviderAPI.LOGOUT_FAILED) {
+ changeStatusMessage(resultCode);
+ hideProgressBar();
+
+ setResult(RESULT_CANCELED);
+ } else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
+ changeStatusMessage(resultCode);
+ hideProgressBar();
+
setResult(RESULT_OK);
+ Intent updateEIP = new Intent(getApplicationContext(), EIP.class);
+ ResultReceiver eip_receiver = new ResultReceiver(new Handler()){
+ protected void onReceiveResult(int resultCode, Bundle resultData){
+ super.onReceiveResult(resultCode, resultData);
+ String request = resultData.getString(EIP.REQUEST_TAG);
+ if (resultCode == Activity.RESULT_OK){
+ if(authed_eip)
+ eipStart();
+ else
+ eipStatus.setText("Certificate updated");
+ }
+ }
+ };
+ updateEIP.putExtra(EIP.RECEIVER_TAG, eip_receiver);
+ updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE);
+ startService(updateEIP);
+ } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
changeStatusMessage(resultCode);
- if(mProgressBar != null)
- mProgressBar.setVisibility(ProgressBar.GONE);
- if(EipServiceFragment.isEipSwitchChecked())
- eipStart();
- else
- eipStatus.setText(R.string.eip_state_not_connected);
- } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
+ hideProgressBar();
setResult(RESULT_CANCELED);
- changeStatusMessage(resultCode);
- mProgressBar.setVisibility(ProgressBar.GONE);
- }
+ }
}
private void changeStatusMessage(final int previous_result_code) {
@@ -515,6 +482,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
protected void onReceiveResult(int resultCode, Bundle resultData){
super.onReceiveResult(resultCode, resultData);
String request = resultData.getString(EIP.REQUEST_TAG);
+ if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus);
if (request.equalsIgnoreCase(EIP.ACTION_IS_EIP_RUNNING)){
if (resultCode == Activity.RESULT_OK){
@@ -534,6 +502,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
case ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL: eipStatus.setText(R.string.succesful_authentication_message); break;
case ProviderAPI.SRP_AUTHENTICATION_FAILED: eipStatus.setText(R.string.authentication_failed_message); break;
+ case ProviderAPI.SRP_REGISTRATION_FAILED: eipStatus.setText(R.string.registration_failed_message); break;
case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: break;
case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.incorrectly_downloaded_certificate_message); break;
case ProviderAPI.LOGOUT_SUCCESSFUL: eipStatus.setText(R.string.logged_out_message); break;
@@ -547,6 +516,14 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
eipIsRunning(eip_status_receiver);
}
+ private void hideProgressBar() {
+ if(mProgressBar == null)
+ mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
+
+ mProgressBar.setProgress(0);
+ mProgressBar.setVisibility(ProgressBar.GONE);
+ }
+
/**
* For retrieving the base application Context in classes that don't extend
* Android's Activity class
@@ -558,17 +535,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
}
- @Override
+ @Override
public void startActivityForResult(Intent intent, int requestCode) {
intent.putExtra(Dashboard.REQUEST_CODE, requestCode);
super.startActivityForResult(intent, requestCode);
}
- /**
- * Send a command to EIP
- *
- * @param action A valid String constant from EIP class representing an Intent
- * filter for the EIP class
- */
+
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 eip_intent = new Intent(this, EIP.class);
@@ -577,30 +549,19 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
startService(eip_intent);
}
- /**
- * Send a command to EIP
- *
- */
- private void eipStop(){
- // TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
- Intent eip_intent = new Intent(this, EIP.class);
- eip_intent.setAction(EIP.ACTION_STOP_EIP);
- // eip_intent.putExtra(EIP.RECEIVER_TAG, eip_receiver);fi
- startService(eip_intent);
-
- }
-
- private void eipStart(){
- Intent eip_intent = new Intent(this, EIP.class);
- eip_intent.setAction(EIP.ACTION_START_EIP);
- eip_intent.putExtra(EIP.RECEIVER_TAG, EipServiceFragment.getReceiver());
- startService(eip_intent);
+ private void eipStop(){
+ EipServiceFragment eipFragment = (EipServiceFragment) getFragmentManager().findFragmentByTag(EipServiceFragment.TAG);
+ eipFragment.stopEIP();
+ }
+ private void eipStart() {
+ EipServiceFragment eipFragment = (EipServiceFragment) getFragmentManager().findFragmentByTag(EipServiceFragment.TAG);
+ eipFragment.startEipFromScratch();
}
- protected void setProgressBarVisibility(int visibility) {
+ protected void showProgressBar() {
if(mProgressBar == null)
mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
- mProgressBar.setVisibility(visibility);
+ mProgressBar.setVisibility(ProgressBar.VISIBLE);
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/EIP.java b/app/src/main/java/se/leap/bitmaskclient/EIP.java
index 43fe0b7c..2f06def3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EIP.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EIP.java
@@ -16,35 +16,23 @@
*/
package se.leap.bitmaskclient;
-
-
-
-
import android.app.Activity;
import android.app.IntentService;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.ServiceConnection;
import android.content.SharedPreferences;
-import android.drm.DrmStore.Action;
import android.os.Bundle;
-import android.os.IBinder;
import android.os.ResultReceiver;
import android.util.Log;
import de.blinkt.openvpn.LaunchVPN;
import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.activities.DisconnectVPN;
-import de.blinkt.openvpn.core.ConfigParser.ConfigParseError;
import de.blinkt.openvpn.core.ConfigParser;
-import de.blinkt.openvpn.core.OpenVpnManagementThread;
-import de.blinkt.openvpn.core.OpenVPNService.LocalBinder;
-import de.blinkt.openvpn.core.OpenVPNService;
+import de.blinkt.openvpn.core.ConfigParser.ConfigParseError;
import de.blinkt.openvpn.core.ProfileManager;
import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
import java.io.IOException;
import java.io.StringReader;
-import java.lang.StringBuffer;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
@@ -99,17 +87,13 @@ public final class EIP extends IntentService {
public final static String SERVICE_API_PATH = "config/eip-service.json";
public final static String RECEIVER_TAG = "receiverTag";
public final static String REQUEST_TAG = "requestTag";
- public final static String TAG = "se.leap.bitmaskclient.EIP";
+ public final static String TAG = EIP.class.getSimpleName();
+ private static SharedPreferences preferences;
- public final static SimpleDateFormat certificate_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US);
-
private static Context context;
private static ResultReceiver mReceiver;
private static boolean mBound = false;
- // Used to store actions to "resume" onServiceConnection
- private static String mPending = null;
- private static int parsedEipSerial;
private static JSONObject eipDefinition = null;
private static OVPNGateway activeGateway = null;
@@ -118,6 +102,7 @@ public final class EIP extends IntentService {
protected static boolean mIsDisconnecting = false;
protected static boolean mIsStarting = false;
+ public static SimpleDateFormat certificate_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US);
public EIP(){
super("LEAPEIP");
}
@@ -127,8 +112,8 @@ public final class EIP extends IntentService {
super.onCreate();
context = getApplicationContext();
-
- updateEIPService();
+
+ preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE);
}
@Override
@@ -140,59 +125,137 @@ public final class EIP extends IntentService {
}
- @Override
- protected void onHandleIntent(Intent intent) {
- String action = intent.getAction();
- mReceiver = intent.getParcelableExtra(RECEIVER_TAG);
-
- if ( action == ACTION_IS_EIP_RUNNING )
- this.isRunning();
- if ( action == ACTION_UPDATE_EIP_SERVICE )
- this.updateEIPService();
- else if ( action == ACTION_START_EIP )
- this.startEIP();
- else if ( action == ACTION_STOP_EIP )
- this.stopEIP();
- else if ( action == ACTION_CHECK_CERT_VALIDITY )
- this.checkCertValidity();
- else if ( action == ACTION_REBUILD_PROFILES ) {
- this.updateGateways();
- }
- }
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ String action = intent.getAction();
+ mReceiver = intent.getParcelableExtra(RECEIVER_TAG);
- /**
- * 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.
- */
+ if ( action == ACTION_START_EIP )
+ startEIP();
+ else if ( action == ACTION_STOP_EIP )
+ stopEIP();
+ else if ( action == ACTION_IS_EIP_RUNNING )
+ isRunning();
+ else if ( action == ACTION_UPDATE_EIP_SERVICE )
+ updateEIPService();
+ else if ( action == ACTION_CHECK_CERT_VALIDITY )
+ checkCertValidity();
+ else if ( action == ACTION_REBUILD_PROFILES )
+ updateGateways();
+ }
- private void isRunning() {
- Bundle resultData = new Bundle();
- resultData.putString(REQUEST_TAG, ACTION_IS_EIP_RUNNING);
- int resultCode = Activity.RESULT_CANCELED;
- boolean is_connected = isConnected();
+ /**
+ * Initiates an EIP connection by selecting a gateway and preparing and sending an
+ * Intent to {@link se.leap.openvpn.LaunchVPN}.
+ * It also sets up early routes.
+ */
+ private void startEIP() {
+ earlyRoutes();
+ activeGateway = selectGateway();
+
+ if(activeGateway != null && activeGateway.mVpnProfile != null) {
+ mReceiver = EipServiceFragment.getReceiver();
+ launchActiveGateway();
+ }
+ }
- resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
-
- if (mReceiver != null){
- mReceiver.send(resultCode, resultData);
- }
+ /**
+ * Early routes are routes that block traffic until a new
+ * 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);
+ }
+
+ /**
+ * Choose a gateway to connect to based on timezone from system locale data
+ *
+ * @return The gateway to connect to
+ */
+ private OVPNGateway selectGateway() {
+ String closest_location = closestGateway();
+ String chosen_host = chooseHost(closest_location);
+
+ return new OVPNGateway(chosen_host);
+ }
- Log.d(TAG, "isRunning() = " + is_connected);
- }
+ private String closestGateway() {
+ TreeMap<Integer, Set<String>> offsets = calculateOffsets();
+ return offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next();
+ }
+
+ private TreeMap<Integer, Set<String>> calculateOffsets() {
+ TreeMap<Integer, Set<String>> offsets = new TreeMap<Integer, Set<String>>();
- /**
- * Initiates an EIP connection by selecting a gateway and preparing and sending an
- * Intent to {@link se.leap.openvpn.LaunchVPN}
- */
- private void startEIP() {
- activeGateway = selectGateway();
+ int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000;
+
+ JSONObject locations = availableLocations();
+ Iterator<String> locations_names = locations.keys();
+ while(locations_names.hasNext()) {
+ try {
+ String location_name = locations_names.next();
+ JSONObject location = locations.getJSONObject(location_name);
+
+ int dist = timezoneDistance(localOffset, location.optInt("timezone"));
+
+ Set<String> set = (offsets.get(dist) != null) ?
+ offsets.get(dist) : new HashSet<String>();
- if(activeGateway != null && activeGateway.mVpnProfile != null) {
- launchActiveGateway();
- }
+ set.add(location_name);
+ offsets.put(dist, set);
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ return offsets;
+ }
+
+ private JSONObject availableLocations() {
+ JSONObject locations = null;
+ try {
+ if(eipDefinition == null) updateEIPService();
+ locations = eipDefinition.getJSONObject("locations");
+ } catch (JSONException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
}
+ return locations;
+ }
+
+ 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;
+ }
+
+ private String chooseHost(String location) {
+ String chosen_host = "";
+ try {
+ JSONArray gateways = eipDefinition.getJSONArray("gateways");
+ for (int i = 0; i < gateways.length(); i++) {
+ JSONObject gw = gateways.getJSONObject(i);
+ if ( gw.getString("location").equalsIgnoreCase(location) || location.isEmpty()){
+ chosen_host = eipDefinition.getJSONObject("locations").getJSONObject(gw.getString("location")).getString("name");
+ break;
+ }
+ }
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return chosen_host;
+ }
+
private void launchActiveGateway() {
Intent intent = new Intent(this,LaunchVPN.class);
intent.setAction(Intent.ACTION_MAIN);
@@ -202,30 +265,48 @@ public final class EIP extends IntentService {
intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true);
intent.putExtra(RECEIVER_TAG, mReceiver);
startActivity(intent);
- mPending = ACTION_START_EIP;
}
-
- /**
- * Disconnects the EIP connection gracefully through the bound service or forcefully
- * if there is no bound service. Sends a message to the requesting ResultReceiver.
- */
- private void stopEIP() {
- if(isConnected()) {
- Intent disconnect_vpn = new Intent(this, DisconnectVPN.class);
- disconnect_vpn.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(disconnect_vpn);
- mIsDisconnecting = true;
- lastConnectionStatusLevel = ConnectionStatus.UNKNOWN_LEVEL; // Wait for the decision of the user
- Log.d(TAG, "mIsDisconnecting = true");
- }
+
+ /**
+ * Disconnects the EIP connection gracefully through the bound service or forcefully
+ * if there is no bound service. Sends a message to the requesting ResultReceiver.
+ */
+ private void stopEIP() {
+ if(isConnected()) {
+ Intent disconnect_vpn = new Intent(this, DisconnectVPN.class);
+ disconnect_vpn.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(disconnect_vpn);
+ mIsDisconnecting = true;
+ lastConnectionStatusLevel = ConnectionStatus.UNKNOWN_LEVEL; // Wait for the decision of the user
+ Log.d(TAG, "mIsDisconnecting = true");
+ }
- if (mReceiver != null){
- Bundle resultData = new Bundle();
- resultData.putString(REQUEST_TAG, ACTION_STOP_EIP);
- mReceiver.send(Activity.RESULT_OK, resultData);
- }
+ tellToReceiver(ACTION_STOP_EIP, Activity.RESULT_OK);
+ }
+
+ private void tellToReceiver(String action, int resultCode) {
+ if (mReceiver != null){
+ Bundle resultData = new Bundle();
+ resultData.putString(REQUEST_TAG, action);
+ mReceiver.send(resultCode, resultData);
}
+ }
+
+ /**
+ * 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() {
+ int resultCode = Activity.RESULT_CANCELED;
+ boolean is_connected = isConnected();
+ resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
+
+ tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode);
+ }
+
protected static boolean isConnected() {
return lastConnectionStatusLevel != null && lastConnectionStatusLevel.equals(ConnectionStatus.LEVEL_CONNECTED) && !mIsDisconnecting;
}
@@ -237,89 +318,23 @@ public final class EIP extends IntentService {
*/
private void updateEIPService() {
try {
- eipDefinition = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(KEY, ""));
- parsedEipSerial = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getInt(PARSED_SERIAL, 0);
+ String eip_definition_string = preferences.getString(KEY, "");
+ if(eip_definition_string.isEmpty() == false) {
+ eipDefinition = new JSONObject(eip_definition_string);
+ }
+ deleteAllVpnProfiles();
+ updateGateways();
+ if(mReceiver != null) mReceiver.send(Activity.RESULT_OK, Bundle.EMPTY);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
- if(parsedEipSerial == 0) {
- deleteAllVpnProfiles();
- }
- if (eipDefinition != null && eipDefinition.optInt("serial") > parsedEipSerial)
- updateGateways();
}
private void deleteAllVpnProfiles() {
ProfileManager vpl = ProfileManager.getInstance(context);
- VpnProfile[] profiles = (VpnProfile[]) vpl.getProfiles().toArray(new VpnProfile[vpl.getProfiles().size()]);
- for (int current_profile = 0; current_profile < profiles.length; current_profile++){
- vpl.removeProfile(context, profiles[current_profile]);
- }
- }
- /**
- * Choose a gateway to connect to based on timezone from system locale data
- *
- * @return The gateway to connect to
- */
- private OVPNGateway selectGateway() {
- String closestLocation = closestGateway();
-
- JSONArray gateways = null;
- String chosenHost = null;
- try {
- gateways = eipDefinition.getJSONArray("gateways");
- for (int i = 0; i < gateways.length(); i++) {
- JSONObject gw = gateways.getJSONObject(i);
- if ( gw.getString("location").equalsIgnoreCase(closestLocation) || closestLocation.isEmpty()){
- chosenHost = eipDefinition.getJSONObject("locations").getJSONObject(gw.getString("location")).getString("name");
- break;
- }
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- return new OVPNGateway(chosenHost);
- }
-
- private String closestGateway() {
- Calendar cal = Calendar.getInstance();
- int localOffset = cal.get(Calendar.ZONE_OFFSET) / 3600000;
- TreeMap<Integer, Set<String>> offsets = new TreeMap<Integer, Set<String>>();
- JSONObject locationsObjects = null;
- Iterator<String> locations = null;
- try {
- locationsObjects = eipDefinition.getJSONObject("locations");
- locations = locationsObjects.keys();
- } catch (JSONException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
-
- while (locations.hasNext()) {
- String locationName = locations.next();
- JSONObject location = null;
- try {
- location = locationsObjects.getJSONObject(locationName);
-
- // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12
- int dist = Math.abs(localOffset - location.optInt("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.
-
- Set<String> set = offsets.get(dist);
- if (set == null) set = new HashSet<String>();
- set.add(locationName);
- offsets.put(dist, set);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- return offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next();
+ Collection<VpnProfile> profiles = vpl.getProfiles();
+ profiles.removeAll(profiles);
}
/**
@@ -329,8 +344,8 @@ public final class EIP extends IntentService {
*/
private void updateGateways(){
JSONArray gatewaysDefined = null;
-
try {
+ if(eipDefinition == null) updateEIPService();
gatewaysDefined = eipDefinition.getJSONArray("gateways");
for ( int i=0 ; i < gatewaysDefined.length(); i++ ){
JSONObject gw = null;
@@ -343,43 +358,54 @@ public final class EIP extends IntentService {
// TODO Auto-generated catch block
e.printStackTrace();
}
-
- getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putInt(PARSED_SERIAL, eipDefinition.optInt(Provider.API_RETURN_SERIAL)).commit();
+ preferences.edit().putInt(PARSED_SERIAL, eipDefinition.optInt(Provider.API_RETURN_SERIAL)).commit();
}
private void checkCertValidity() {
- String certificate_string = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(CERTIFICATE, "");
- if(!certificate_string.isEmpty()) {
- String date_from_certificate_string = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(DATE_FROM_CERTIFICATE, certificate_date_format.format(Calendar.getInstance().getTime()).toString());
- X509Certificate certificate_x509 = ConfigHelper.parseX509CertificateFromString(certificate_string);
+ String certificate = preferences.getString(CERTIFICATE, "");
+ checkCertValidity(certificate);
+ }
- Calendar offset_date = Calendar.getInstance();
- try {
- Date date_from_certificate = certificate_date_format.parse(date_from_certificate_string);
- long difference = Math.abs(date_from_certificate.getTime() - certificate_x509.getNotAfter().getTime())/2;
- long current_date_millis = offset_date.getTimeInMillis();
- offset_date.setTimeInMillis(current_date_millis + difference);
- Log.d(TAG, "certificate not after = " + certificate_x509.getNotAfter());
- } catch(ParseException e) {
- e.printStackTrace();
- }
-
- Bundle result_data = new Bundle();
- result_data.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY);
+ private void checkCertValidity(String certificate_string) {
+ if(!certificate_string.isEmpty()) {
+ X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificate_string);
+
+ Calendar offset_date = calculateOffsetCertificateValidity(certificate);
+ Bundle result = new Bundle();
+ result.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY);
try {
Log.d(TAG, "offset_date = " + offset_date.getTime().toString());
- certificate_x509.checkValidity(offset_date.getTime());
- mReceiver.send(Activity.RESULT_OK, result_data);
+ certificate.checkValidity(offset_date.getTime());
+ mReceiver.send(Activity.RESULT_OK, result);
Log.d(TAG, "Valid certificate");
} catch(CertificateExpiredException e) {
- mReceiver.send(Activity.RESULT_CANCELED, result_data);
+ mReceiver.send(Activity.RESULT_CANCELED, result);
Log.d(TAG, "Updating certificate");
} catch(CertificateNotYetValidException e) {
- mReceiver.send(Activity.RESULT_CANCELED, result_data);
+ mReceiver.send(Activity.RESULT_CANCELED, result);
}
}
}
+ private Calendar calculateOffsetCertificateValidity(X509Certificate certificate) {
+ String current_date = certificate_date_format.format(Calendar.getInstance().getTime()).toString();
+
+ String date_string = preferences.getString(DATE_FROM_CERTIFICATE, current_date);
+
+ Calendar offset_date = Calendar.getInstance();
+ try {
+ Date date = certificate_date_format.parse(date_string);
+ long difference = Math.abs(date.getTime() - certificate.getNotAfter().getTime())/2;
+ long current_date_millis = offset_date.getTimeInMillis();
+ offset_date.setTimeInMillis(current_date_millis + difference);
+ Log.d(TAG, "certificate not after = " + certificate.getNotAfter());
+ } catch(ParseException e) {
+ e.printStackTrace();
+ }
+
+ return offset_date;
+ }
+
/**
* OVPNGateway provides objects defining gateways and their options and metadata.
* Each instance contains a VpnProfile for OpenVPN specific data and member
@@ -460,17 +486,19 @@ public final class EIP extends IntentService {
protected void createVPNProfile(){
try {
ConfigParser cp = new ConfigParser();
- cp.parseConfig(new StringReader(configFromEipServiceDotJson()));
- cp.parseConfig(new StringReader(caSecretFromSharedPreferences()));
- cp.parseConfig(new StringReader(keySecretFromSharedPreferences()));
- cp.parseConfig(new StringReader(certSecretFromSharedPreferences()));
- cp.parseConfig(new StringReader("remote-cert-tls server"));
- cp.parseConfig(new StringReader("persist-tun"));
- VpnProfile vp = cp.convertProfile();
- //vp.mAuthenticationType=VpnProfile.TYPE_STATICKEYS;
- mVpnProfile = vp;
+
+ JSONObject openvpn_configuration = eipDefinition.getJSONObject("openvpn_configuration");
+ VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(preferences, openvpn_configuration, mGateway);
+ String configuration = vpn_configuration_generator.generate();
+
+ cp.parseConfig(new StringReader(configuration));
+ mVpnProfile = cp.convertProfile();
mVpnProfile.mName = mName = locationAsName();
Log.v(TAG,"Created VPNProfile");
+
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
} catch (ConfigParseError e) {
// FIXME We didn't get a VpnProfile! Error handling! and log level
Log.v(TAG,"Error creating VPNProfile");
@@ -482,124 +510,6 @@ public final class EIP extends IntentService {
}
}
- /**
- * Parses data from eip-service.json to a section of the openvpn config file
- */
- private String configFromEipServiceDotJson() {
- String parsed_configuration = "";
-
- String location_key = "location";
- String locations = "locations";
-
- parsed_configuration += extractCommonOptionsFromEipServiceDotJson();
- parsed_configuration += extractRemotesFromEipServiceDotJson();
-
- return parsed_configuration;
- }
-
- private String extractCommonOptionsFromEipServiceDotJson() {
- String common_options = "";
- try {
- String common_options_key = "openvpn_configuration";
- JSONObject openvpn_configuration = eipDefinition.getJSONObject(common_options_key);
- Iterator keys = openvpn_configuration.keys();
- Vector<Vector<String>> value = new Vector<Vector<String>>();
- while ( keys.hasNext() ){
- String key = keys.next().toString();
-
- common_options += key + " ";
- for ( String word : openvpn_configuration.getString(key).split(" ") )
- common_options += word + " ";
- common_options += System.getProperty("line.separator");
-
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- common_options += "client" + System.getProperty("line.separator");
-
- return common_options;
- }
-
-
- private String extractRemotesFromEipServiceDotJson() {
- String remotes = "";
-
- String remote = "ip_address";
- String remote_openvpn_keyword = "remote";
- String ports = "ports";
- String protos = "protocols";
- String capabilities = "capabilities";
- String udp = "udp";
-
- try {
- JSONArray protocolsJSON = mGateway.getJSONObject(capabilities).getJSONArray(protos);
- for ( int i=0; i<protocolsJSON.length(); i++ ) {
- String remote_line = remote_openvpn_keyword;
- remote_line += " " + mGateway.getString(remote);
- remote_line += " " + mGateway.getJSONObject(capabilities).getJSONArray(ports).optString(0);
- remote_line += " " + protocolsJSON.optString(i);
- if(remote_line.endsWith(udp))
- remotes = remotes.replaceFirst(remote_openvpn_keyword, remote_line + System.getProperty("line.separator") + remote_openvpn_keyword);
- else
- remotes += remote_line;
- remotes += System.getProperty("line.separator");
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- Log.d(TAG, "remotes = " + remotes);
- return remotes;
- }
-
- private String caSecretFromSharedPreferences() {
- String secret_lines = "";
- SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, context.MODE_PRIVATE);
-
- System.getProperty("line.separator");
- secret_lines += "<ca>";
- secret_lines += System.getProperty("line.separator");
- secret_lines += preferences.getString(Provider.CA_CERT, "");
- secret_lines += System.getProperty("line.separator");
- secret_lines += "</ca>";
-
- return secret_lines;
- }
-
- private String keySecretFromSharedPreferences() {
- String secret_lines = "";
- SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, context.MODE_PRIVATE);
-
- secret_lines += System.getProperty("line.separator");
- secret_lines +="<key>";
- secret_lines += System.getProperty("line.separator");
- secret_lines += preferences.getString(EIP.PRIVATE_KEY, "");
- secret_lines += System.getProperty("line.separator");
- secret_lines += "</key>";
- secret_lines += System.getProperty("line.separator");
-
- return secret_lines;
- }
-
- private String certSecretFromSharedPreferences() {
- String secret_lines = "";
- SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, context.MODE_PRIVATE);
-
- secret_lines += System.getProperty("line.separator");
- secret_lines +="<cert>";
- secret_lines += System.getProperty("line.separator");
- secret_lines += preferences.getString(EIP.CERTIFICATE, "");
- secret_lines += System.getProperty("line.separator");
- secret_lines += "</cert>";
- secret_lines += System.getProperty("line.separator");
-
- return secret_lines;
- }
-
public String locationAsName() {
try {
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java
index 18ee0262..6d223dd6 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java
@@ -85,8 +85,8 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
super.onResume();
VpnStatus.addStateListener(this);
-
- eipCommand(EIP.ACTION_CHECK_CERT_VALIDITY);
+
+ eipCommand(EIP.ACTION_CHECK_CERT_VALIDITY);
}
@Override
@@ -146,7 +146,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
private boolean canLogInToStartEIP() {
boolean isAllowedRegistered = Dashboard.preferences.getBoolean(EIP.ALLOWED_REGISTERED, false);
- boolean isLoggedIn = Dashboard.preferences.getBoolean(EIP.AUTHED_EIP, false);
+ boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty();
Log.d(TAG, "Allow registered? " + isAllowedRegistered);
Log.d(TAG, "Is logged in? " + isLoggedIn);
return isAllowedRegistered && !isLoggedIn && !EIP.mIsStarting && !EIP.isConnected();
@@ -195,7 +195,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
eipCommand(EIP.ACTION_START_EIP);
}
- private void stopEIP() {
+ protected void stopEIP() {
EIP.mIsStarting = false;
View eipProgressBar = getActivity().findViewById(R.id.eipProgress);
if(eipProgressBar != null)
@@ -236,7 +236,8 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
} else if(justDecidedOnDisconnect && level == ConnectionStatus.LEVEL_CONNECTED) {
EIP.lastConnectionStatusLevel = ConnectionStatus.LEVEL_NOTCONNECTED;
updateState(state, logmessage, localizedResId, level);
- }
+ } // else if(isNewLevel || level == ConnectionStatus.LEVEL_AUTH_FAILED)
+ // handleNewState(state, logmessage, localizedResId, level);
}
private void handleNewState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
@@ -248,6 +249,8 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
setNoServerReplyUI(localizedResId, logmessage);
else if (level == ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED)
setServerReplyUI(state, localizedResId, logmessage);
+ // else if (level == ConnectionStatus.LEVEL_AUTH_FAILED)
+ // handleSwitchOn();
}
private boolean isDisconnectedLevel(final ConnectionStatus level) {
@@ -380,19 +383,24 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
case Activity.RESULT_CANCELED:
Dashboard dashboard = (Dashboard) getActivity();
- dashboard.setProgressBarVisibility(ProgressBar.VISIBLE);
+ dashboard.showProgressBar();
String status = getResources().getString(R.string.updating_certificate_message);
setEipStatus(status);
-
- Intent provider_API_command = new Intent(getActivity(), ProviderAPI.class);
- if(dashboard.providerAPI_result_receiver == null) {
- dashboard.providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- dashboard.providerAPI_result_receiver.setReceiver(dashboard);
- }
-
- provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE);
- provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, dashboard.providerAPI_result_receiver);
- getActivity().startService(provider_API_command);
+
+ if(LeapSRPSession.getToken().isEmpty() && !Dashboard.preferences.getBoolean(EIP.ALLOWED_ANON, false)) {
+ dashboard.logInDialog(Bundle.EMPTY);
+ } else {
+
+ Intent provider_API_command = new Intent(getActivity(), ProviderAPI.class);
+ if (dashboard.providerAPI_result_receiver == null) {
+ dashboard.providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
+ dashboard.providerAPI_result_receiver.setReceiver(dashboard);
+ }
+
+ provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE);
+ provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, dashboard.providerAPI_result_receiver);
+ getActivity().startService(provider_API_command);
+ }
break;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java b/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java
new file mode 100644
index 00000000..c4844be9
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java
@@ -0,0 +1,51 @@
+/**
+ * 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.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+
+public class FragmentManagerEnhanced {
+
+ private FragmentManager generic_fragment_manager;
+
+ public FragmentManagerEnhanced(FragmentManager 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;
+ }
+
+ public void replace(int containerViewId, Fragment fragment, String tag) {
+ FragmentTransaction transaction = generic_fragment_manager.beginTransaction();
+
+ transaction.replace(containerViewId, fragment, tag).commit();
+ }
+
+ public Fragment findFragmentByTag(String tag) {
+ return generic_fragment_manager.findFragmentByTag(tag);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapHttpClient.java b/app/src/main/java/se/leap/bitmaskclient/LeapHttpClient.java
deleted file mode 100644
index 885b5105..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/LeapHttpClient.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * 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 java.security.KeyStore;
-
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.SingleClientConnManager;
-import android.content.Context;
-
-/**
- * Implements an HTTP client, enabling LEAP Android app to manage its own runtime keystore or bypass default Android security measures.
- *
- * @author rafa
- *
- */
-public class LeapHttpClient extends DefaultHttpClient {
-
- private static LeapHttpClient client;
-
- /**
- * If the class scope client is null, it creates one and imports, if existing, the main certificate from Shared Preferences.
- * @param context
- * @return the new client.
- */
- public static LeapHttpClient getInstance(String cert_string) {
- if(client == null) {
- if(cert_string != null) {
- ConfigHelper.addTrustedCertificate("provider_ca_certificate", cert_string);
- }
- }
- return client;
- }
-
- @Override
- protected ClientConnectionManager createClientConnectionManager() {
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
- registry.register(new Scheme("https", newSslSocketFactory(), 443));
-
- return new SingleClientConnManager(getParams(), registry);
- }
-
- /**
- * Uses keystore from ConfigHelper for the SSLSocketFactory.
- * @return
- */
- private SSLSocketFactory newSslSocketFactory() {
- try {
- KeyStore trusted = ConfigHelper.getKeystore();
- SSLSocketFactory sf = new SSLSocketFactory(trusted);
-
- return sf;
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
index 29b429d1..a953a710 100644
--- a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
+++ b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
@@ -63,15 +63,16 @@ public class LeapSRPSession {
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, SRPParameters params)
+ public LeapSRPSession(String username, String password)
{
- this(username, password, params, null);
+ this(username, password, null);
}
/** Creates a new SRP server session object from the username, password
@@ -81,9 +82,9 @@ public class LeapSRPSession {
@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, SRPParameters params,
- byte[] abytes) {
- this.params = params;
+ 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);
@@ -159,7 +160,7 @@ public class LeapSRPSession {
public byte[] calculateNewSalt() {
try {
BigInteger salt = new BigInteger(64, SecureRandom.getInstance("SHA1PRNG"));
- return salt.toByteArray();
+ return ConfigHelper.trim(salt.toByteArray());
} catch(NoSuchAlgorithmException e) {
e.printStackTrace();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java
index 45d3a373..5a0c9a6d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java
@@ -42,15 +42,10 @@ import android.widget.TextView;
* @author parmegv
*
*/
-public class LogInDialog extends DialogFragment {
+public class LogInDialog extends SessionDialogInterface {
- final public static String TAG = "logInDialog";
- final public static String VERB = "log in";
- 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";
+ final public static String TAG = LogInDialog.class.getSimpleName();
private static boolean is_eip_pending = false;
@@ -93,7 +88,7 @@ public class LogInDialog extends DialogFragment {
String username = username_field.getText().toString();
String password = password_field.getText().toString();
dialog.dismiss();
- interface_with_Dashboard.authenticate(username, password);
+ interface_with_Dashboard.logIn(username, password);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@@ -120,7 +115,7 @@ public class LogInDialog extends DialogFragment {
*
*/
public interface LogInDialogInterface {
- public void authenticate(String username, String password);
+ public void logIn(String username, String password);
public void cancelAuthedEipOn();
public void signUp(String username, String password);
public void cancelLoginOrSignup();
@@ -149,8 +144,8 @@ public class LogInDialog extends DialogFragment {
@Override
public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
if(is_eip_pending)
interface_with_Dashboard.cancelAuthedEipOn();
- super.onCancel(dialog);
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java
index 5326709f..8d6385e0 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java
@@ -52,6 +52,7 @@ public final class Provider implements Serializable {
KEY = "provider",
CA_CERT = "ca_cert",
CA_CERT_URI = "ca_cert_uri",
+ CA_CERT_FINGERPRINT = "ca_cert_fingerprint",
NAME = "name",
DESCRIPTION = "description",
DOMAIN = "domain",
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
index 7b256124..7e4e95d3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
@@ -14,7 +14,7 @@
* 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 android.os.Bundle;
import android.os.Handler;
diff --git a/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java b/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java
new file mode 100644
index 00000000..7b08a4d1
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java
@@ -0,0 +1,39 @@
+/**
+ * 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.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+/**
+ * @author parmegv
+ */
+public abstract class SessionDialogInterface extends DialogFragment {
+ 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";
+
+ @Override
+ public void onAttach(Activity activity) { super.onAttach(activity); }
+
+ @Override
+ public void onCancel(DialogInterface dialog) { super.onCancel(dialog); }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java
index 120d4eec..3cb41f4f 100644
--- a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java
@@ -42,14 +42,9 @@ import android.widget.TextView;
* @author parmegv
*
*/
-public class SignUpDialog extends DialogFragment {
-
- final public static String TAG = "signUpDialog";
- final public static String VERB = "log in";
- 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 class SignUpDialog extends SessionDialogInterface {
+
+ final public static String TAG = SignUpDialog.class.getSimpleName();
private static boolean is_eip_pending = false;
diff --git a/app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java b/app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java
new file mode 100644
index 00000000..3b286fbf
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java
@@ -0,0 +1,37 @@
+package se.leap.bitmaskclient;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.VpnService;
+import android.os.Bundle;
+
+public class VoidVpnLauncher extends Activity {
+
+ private static final int VPN_USER_PERMISSION = 71;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ 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);
+ }
+ }
+
+ 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(VoidVpnService.START_BLOCKING_VPN_PROFILE);
+ startService(void_vpn_service);
+ }
+ }
+ finish();
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java
new file mode 100644
index 00000000..7b597554
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java
@@ -0,0 +1,36 @@
+package se.leap.bitmaskclient;
+
+import android.content.Intent;
+import android.os.Process;
+import android.net.VpnService;
+import android.util.Log;
+
+public class VoidVpnService extends VpnService {
+
+ static final String START_BLOCKING_VPN_PROFILE = "se.leap.bitmaskclient.START_BLOCKING_VPN_PROFILE";
+ static final String TAG = VoidVpnService.class.getSimpleName();
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ String action = intent.getAction();
+ if (action == 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 {
+ builder.establish();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ android.util.Log.d(TAG, "VoidVpnService set up");
+ }
+ }).run();
+ }
+ return 0;
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java
new file mode 100644
index 00000000..ef049a3c
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java
@@ -0,0 +1,146 @@
+/**
+ * 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.content.SharedPreferences;
+import android.util.Log;
+import java.util.Iterator;
+import java.util.Vector;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.json.JSONException;
+
+import se.leap.bitmaskclient.Provider;
+import se.leap.bitmaskclient.EIP;
+
+public class VpnConfigGenerator {
+
+ private JSONObject general_configuration;
+ private JSONObject gateway;
+
+ private static SharedPreferences preferences;
+ public final static String TAG = VpnConfigGenerator.class.getSimpleName();
+ private final String new_line = System.getProperty("line.separator"); // Platform new line
+
+ public VpnConfigGenerator(SharedPreferences preferences, JSONObject general_configuration, JSONObject gateway) {
+ this.general_configuration = general_configuration;
+ this.gateway = gateway;
+ this.preferences = preferences;
+ }
+
+ public String generate() {
+ return
+ generalConfiguration()
+ + new_line
+ + gatewayConfiguration()
+ + new_line
+ + secretsConfiguration()
+ + new_line
+ + androidCustomizations();
+ }
+
+ private String generalConfiguration() {
+ String common_options = "";
+ try {
+ Iterator keys = general_configuration.keys();
+ Vector<Vector<String>> value = new Vector<Vector<String>>();
+ 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 remote = "ip_address";
+ String remote_openvpn_keyword = "remote";
+ String ports = "ports";
+ String protos = "protocols";
+ String capabilities = "capabilities";
+ String udp = "udp";
+
+ try {
+ JSONArray protocolsJSON = gateway.getJSONObject(capabilities).getJSONArray(protos);
+ for ( int i=0; i<protocolsJSON.length(); i++ ) {
+ String remote_line = remote_openvpn_keyword;
+ remote_line += " " + gateway.getString(remote);
+ remote_line += " " + gateway.getJSONObject(capabilities).getJSONArray(ports).optString(0);
+ remote_line += " " + protocolsJSON.optString(i);
+ if(remote_line.endsWith(udp))
+ remotes = remotes.replaceFirst(remote_openvpn_keyword, remote_line + new_line + remote_openvpn_keyword);
+ else
+ remotes += remote_line;
+ remotes += new_line;
+ }
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ Log.d(TAG, "remotes = " + remotes);
+ return remotes;
+ }
+
+ private String secretsConfiguration() {
+
+ String ca =
+ "<ca>"
+ + new_line
+ + preferences.getString(Provider.CA_CERT, "")
+ + new_line
+ + "</ca>";
+
+ String key =
+ "<key>"
+ + new_line
+ + preferences.getString(EIP.PRIVATE_KEY, "")
+ + new_line
+ + "</key>";
+
+ String openvpn_cert =
+ "<cert>"
+ + new_line
+ + preferences.getString(EIP.CERTIFICATE, "")
+ + new_line
+ + "</cert>";
+
+ return ca + new_line + key + new_line + openvpn_cert;
+ }
+
+ private String androidCustomizations() {
+ return
+ "remote-cert-tls server"
+ + new_line
+ + "persist-tun"
+ + new_line
+ + "auth-retry nointeract";
+ }
+}