diff options
Diffstat (limited to 'app/src/main/java/se')
8 files changed, 659 insertions, 608 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 52b22695..afe1a638 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -17,37 +17,21 @@ package se.leap.bitmaskclient; import android.annotation.SuppressLint; -import android.app.Activity; -import android.app.AlertDialog; -import android.app.DialogFragment; -import android.app.FragmentTransaction; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; +import android.app.*; +import android.content.*; import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Bundle; -import android.os.Handler; -import android.os.ResultReceiver; +import android.os.*; import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.widget.ProgressBar; -import android.widget.TextView; +import android.view.*; +import android.widget.*; import org.jetbrains.annotations.NotNull; -import org.json.JSONException; -import org.json.JSONObject; +import org.json.*; +import java.net.*; -import java.net.MalformedURLException; -import java.net.URL; - -import butterknife.ButterKnife; -import butterknife.InjectView; -import de.blinkt.openvpn.activities.LogWindow; -import se.leap.bitmaskclient.eip.Constants; -import se.leap.bitmaskclient.eip.EIP; -import se.leap.bitmaskclient.eip.EipStatus; +import butterknife.*; +import de.blinkt.openvpn.activities.*; +import se.leap.bitmaskclient.eip.*; /** * The main user facing Activity of Bitmask Android, consisting of status, controls, @@ -58,16 +42,16 @@ import se.leap.bitmaskclient.eip.EipStatus; */ public class Dashboard extends Activity implements SessionDialog.SessionDialogInterface, ProviderAPIResultReceiver.Receiver { - protected static final int CONFIGURE_LEAP = 0; - protected static final int SWITCH_PROVIDER = 1; + protected static final int CONFIGURE_LEAP = 0; + protected static final int SWITCH_PROVIDER = 1; - final public static String TAG = Dashboard.class.getSimpleName(); - final public static String SHARED_PREFERENCES = "LEAPPreferences"; - final public static String ACTION_QUIT = "quit"; + public static final String TAG = Dashboard.class.getSimpleName(); + public static final String SHARED_PREFERENCES = "LEAPPreferences"; + public static final String ACTION_QUIT = "quit"; public static final String REQUEST_CODE = "request_code"; public static final String PARAMETERS = "dashboard parameters"; public static final String START_ON_BOOT = "dashboard start on boot"; - final public static String ON_BOOT = "dashboard on boot"; + public static final String ON_BOOT = "dashboard on boot"; public static final String APP_VERSION = "bitmask version"; private static Context app; @@ -81,6 +65,26 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn private Provider provider; private static boolean authed_eip; public ProviderAPIResultReceiver providerAPI_result_receiver; + private boolean switching_provider; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + app = this; + + PRNGFixes.apply(); + + preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); + handleVersion(); + + provider = getSavedProvider(savedInstanceState); + if (provider == null || provider.getName().isEmpty()) + startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); + else + buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false)); + } @Override protected void onSaveInstanceState(@NotNull Bundle outState) { @@ -89,25 +93,6 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn super.onSaveInstanceState(outState); } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - app = this; - - PRNGFixes.apply(); - - preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); - fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); - handleVersion(); - - provider = getSavedProvider(savedInstanceState); - if (provider == null || provider.getName().isEmpty()) - startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); - else - buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false)); - } - private Provider getSavedProvider(Bundle savedInstanceState) { Provider provider = null; if(savedInstanceState != null) @@ -123,120 +108,111 @@ 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 | JSONException e) { + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (JSONException e) { e.printStackTrace(); } return provider; } - 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(); - Log.d("Dashboard", "detected version code: " + versionCode); - Log.d("Dashboard", "last detected version code: " + lastDetectedVersion); switch(versionCode) { case 91: // 0.6.0 without Bug #5999 case 101: // 0.8.0 - if(!preferences.getString(Constants.KEY, "").isEmpty()) { - Intent rebuildVpnProfiles = new Intent(getApplicationContext(), EIP.class); - rebuildVpnProfiles.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); - startService(rebuildVpnProfiles); - } + if(!preferences.getString(Constants.KEY, "").isEmpty()) + eip_fragment.updateEipService(); break; } } catch (NameNotFoundException e) { - Log.d(TAG, "Handle version didn't find any " + getPackageName() + " package"); + Log.d(TAG, "Handle version didn't find any " + getPackageName() + " package"); } } - - @SuppressLint("CommitPrefEdits") + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ - Log.d(TAG, "onActivityResult: requestCode = " + requestCode); if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) { - if ( resultCode == RESULT_OK ) { - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); - updateEipService(); - - if (data.hasExtra(Provider.KEY)) { + if ( resultCode == RESULT_OK && data.hasExtra(Provider.KEY)) { provider = data.getParcelableExtra(Provider.KEY); - preferences.edit().putBoolean(Constants.PROVIDER_CONFIGURED, true).commit(); - preferences.edit().putString(Provider.MAIN_URL, provider.mainUrl().toString()).apply(); - preferences.edit().putString(Provider.KEY, provider.definition().toString()).apply(); - } - buildDashboard(false); - invalidateOptionsMenu(); - if (data.hasExtra(SessionDialog.TAG)) { - logInDialog(Bundle.EMPTY); - } - } else if (resultCode == RESULT_CANCELED && data.hasExtra(ACTION_QUIT)) { + providerToPreferences(provider); + + buildDashboard(false); + invalidateOptionsMenu(); + if (data.hasExtra(SessionDialog.TAG)) { + sessionDialog(Bundle.EMPTY); + } + + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); + } else if (resultCode == RESULT_CANCELED && data.hasExtra(ACTION_QUIT)) { finish(); - } else + } else configErrorDialog(); } else if(requestCode == EIP.DISCONNECT) { EipStatus.getInstance().setConnectedOrDisconnected(); } } - /** - * Dialog shown when encountering a configuration error. Such errors require - * reconfiguring LEAP or aborting the application. - */ - 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(); - } + @SuppressLint("CommitPrefEdits") + private void providerToPreferences(Provider provider) { + preferences.edit().putBoolean(Constants.PROVIDER_CONFIGURED, true).commit(); + preferences.edit().putString(Provider.MAIN_URL, provider.mainUrl().toString()).apply(); + preferences.edit().putString(Provider.KEY, provider.definition().toString()).apply(); + } + + 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(); + } - /** - * 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); + /** + * 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); 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 (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(); + } } + } @Override public boolean onPrepareOptionsMenu(Menu menu) { @@ -267,114 +243,107 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn } return true; } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.client_dashboard, menu); + return true; + } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - 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: - if (provider.hasEIP()){ - if (preferences.getBoolean(Constants.AUTHED_EIP, false)) { - logOut(); - } - eip_fragment.askToStopEIP(); - } - preferences.edit().clear().apply(); - startActivityForResult(new Intent(this,ConfigurationWizard.class), SWITCH_PROVIDER); - return true; - case R.id.login_button: - logInDialog(Bundle.EMPTY); - return true; - case R.id.logout_button: - logOut(); - return true; - case R.id.signup_button: - signUpDialog(Bundle.EMPTY); - return true; - default: - return super.onOptionsItemSelected(item); - } - + @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); } - - protected Intent prepareProviderAPICommand() { - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); - - Intent command = new Intent(this, ProviderAPI.class); - - 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(SessionDialog.TAG); - DialogFragment newFragment = SessionDialog.newInstance(); - if(resultData != null && !resultData.isEmpty() && fragment_manager.findFragmentByTag(SessionDialog.TAG) == null) - newFragment.setArguments(resultData); - newFragment.show(transaction, SessionDialog.TAG); + @Override + public void signUp(String username, String password) { + Bundle parameters = bundleParameters(username, password); + providerApiCommand(parameters, R.string.signingup_message, ProviderAPI.SRP_REGISTER); } @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(SessionDialog.USERNAME, username); - parameters.putString(SessionDialog.PASSWORD, password); + Bundle parameters = bundleParameters(username, password); + providerApiCommand(parameters, R.string.authenticating_message, ProviderAPI.SRP_AUTH); + } + + public void logOut() { + providerApiCommand(Bundle.EMPTY, R.string.logout_message, ProviderAPI.LOG_OUT); + } + + protected void downloadVpnCertificate() { + boolean is_authenticated = !LeapSRPSession.getToken().isEmpty(); + boolean allowed_anon = preferences.getBoolean(Constants.ALLOWED_ANON, false); + if(allowed_anon || is_authenticated) + providerApiCommand(Bundle.EMPTY, R.string.downloading_certificate_message, ProviderAPI.DOWNLOAD_CERTIFICATE); + else + sessionDialog(Bundle.EMPTY); - if(eip_fragment != null) { - eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE); - eip_fragment.status_message.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 cancelLoginOrSignup() { - EipStatus.getInstance().setConnectedOrDisconnected(); + private Bundle bundleParameters(String username, String password) { + Bundle parameters = new Bundle(); + if(!username.isEmpty() && !password.isEmpty()) { + parameters.putString(SessionDialog.USERNAME, username); + parameters.putString(SessionDialog.PASSWORD, password); + } + return parameters; } - - /** - * Asks ProviderAPI to log out. - */ - public void logOut() { - Intent provider_API_command = prepareProviderAPICommand(); - if(eip_fragment != null) { + protected void providerApiCommand(Bundle parameters, int progressbar_message_resId, String providerApi_action) { + if(eip_fragment != null && progressbar_message_resId != 0) { eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE); - eip_fragment.status_message.setText(R.string.logout_message); + setStatusMessage(progressbar_message_resId); } - provider_API_command.setAction(ProviderAPI.LOG_OUT); - startService(provider_API_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; + } + + public void cancelLoginOrSignup() { + EipStatus.getInstance().setConnectedOrDisconnected(); } - /** - * Shows the sign up dialog. - */ - public void signUpDialog(Bundle resultData) { + public void sessionDialog(Bundle resultData) { FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG); DialogFragment newFragment = SessionDialog.newInstance(); @@ -384,160 +353,111 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn newFragment.show(transaction, SessionDialog.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(SessionDialog.USERNAME, username); - parameters.putString(SessionDialog.PASSWORD, password); - if(eip_fragment != null) { - eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE); - eip_fragment.status_message.setText(R.string.signingup_message); - } - provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); - provider_API_command.setAction(ProviderAPI.SRP_REGISTER); - startService(provider_API_command); + private void switchProvider() { + if (provider.hasEIP()) eip_fragment.askToStopEIP(); + + preferences.edit().clear().apply(); + switching_provider = false; + startActivityForResult(new Intent(this, ConfigurationWizard.class), SWITCH_PROVIDER); } - /** - * Asks ProviderAPI to download an authenticated OpenVPN certificate. - */ - private void downloadAuthedUserCertificate() { - 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(ConfigurationWizard.TYPE_OF_CERTIFICATE, ConfigurationWizard.AUTHED_CERTIFICATE); - - provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE); - provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); - provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - - startService(provider_API_command); + @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); + } + } - @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) { - changeStatusMessage(resultCode); - hideProgressBar(); - - signUpDialog(resultData); - } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGIN) { - changeStatusMessage(resultCode); - hideProgressBar(); - - invalidateOptionsMenu(); - - authed_eip = true; - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); - - downloadAuthedUserCertificate(); - } else if(resultCode == ProviderAPI.FAILED_LOGIN) { - changeStatusMessage(resultCode); - hideProgressBar(); - - logInDialog(resultData); - } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGOUT) { - changeStatusMessage(resultCode); - hideProgressBar(); - - invalidateOptionsMenu(); - - authed_eip = false; - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); - - } 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); - - updateEipService(); - } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { - changeStatusMessage(resultCode); - hideProgressBar(); - setResult(RESULT_CANCELED); - } - else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE) { - setResult(RESULT_OK); - - updateEipService(); - } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE) { - setResult(RESULT_CANCELED); + private void updateViewHidingProgressBar(int resultCode) { + changeStatusMessage(resultCode); + hideProgressBar(); + invalidateOptionsMenu(); } - } - private void updateEipService() { - Intent updateEIP = new Intent(getApplicationContext(), EIP.class); - updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); - ResultReceiver receiver = new ResultReceiver(new Handler()) { - protected void onReceiveResult(int resultCode, Bundle resultData) { + 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_UPDATE_EIP_SERVICE)) { - if(resultCode == Activity.RESULT_OK) { - if(authed_eip && eip_fragment != null) eip_fragment.startEipFromScratch(); + 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; + } } } + } }; - //updateEIP.putExtra(Constants.RECEIVER_TAG, receiver); - startService(updateEIP); + eipIsRunning(status_receiver); } - private void changeStatusMessage(final int previous_result_code) { - // TODO Auto-generated method stub - ResultReceiver eip_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: eip_fragment.status_message.setText(R.string.succesful_authentication_message); break; - case ProviderAPI.FAILED_LOGIN: eip_fragment.status_message.setText(R.string.authentication_failed_message); break; - case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: eip_fragment.status_message.setText(R.string.authed_secured_status); break; - case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eip_fragment.status_message.setText(R.string.incorrectly_downloaded_certificate_message); break; - case ProviderAPI.SUCCESSFUL_LOGOUT: eip_fragment.status_message.setText(R.string.logged_out_message); break; - case ProviderAPI.LOGOUT_FAILED: eip_fragment.status_message.setText(R.string.log_out_failed_message); break; - - } - } - else if(resultCode == Activity.RESULT_CANCELED){ - - switch(previous_result_code){ - - case ProviderAPI.SUCCESSFUL_LOGIN: eip_fragment.status_message.setText(R.string.succesful_authentication_message); break; - case ProviderAPI.FAILED_LOGIN: eip_fragment.status_message.setText(R.string.authentication_failed_message); break; - case ProviderAPI.FAILED_SIGNUP: eip_fragment.status_message.setText(R.string.registration_failed_message); break; - case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: break; - case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eip_fragment.status_message.setText(R.string.incorrectly_downloaded_certificate_message); break; - case ProviderAPI.SUCCESSFUL_LOGOUT: eip_fragment.status_message.setText(R.string.logged_out_message); break; - case ProviderAPI.LOGOUT_FAILED: eip_fragment.status_message.setText(R.string.log_out_failed_message); break; - } - } - } - - } - }; - eipIsRunning(eip_status_receiver); - } + private void setStatusMessage(int 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); + } private void hideProgressBar() { if(eip_fragment != null) { @@ -546,28 +466,13 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn } } - /** - * For retrieving the base application Context in classes that don't extend - * Android's Activity class - * - * @return Application Context as defined by <code>this</code> for Dashboard instance - */ - public static Context getAppContext() { - return app; - } - - + public static Context getAppContext() { + return app; + } + @Override public void startActivityForResult(Intent intent, int requestCode) { intent.putExtra(Dashboard.REQUEST_CODE, requestCode); super.startActivityForResult(intent, requestCode); } - - 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); - eip_intent.setAction(Constants.ACTION_IS_EIP_RUNNING); - eip_intent.putExtra(Constants.RECEIVER_TAG, eip_receiver); - startService(eip_intent); - } } diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 420da7a1..588b137b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -37,7 +37,6 @@ public class EipFragment extends Fragment implements Observer { protected static final String STATUS_MESSAGE = TAG + ".status_message"; public static final String START_ON_BOOT = "start on boot"; - private View view; @InjectView(R.id.eipSwitch) Switch eip_switch; @InjectView(R.id.status_message) @@ -45,20 +44,18 @@ public class EipFragment extends Fragment implements Observer { @InjectView(R.id.eipProgress) ProgressBar progress_bar; - private static Activity parent_activity; + private static Dashboard dashboard; private static EIPReceiver mEIPReceiver; private static EipStatus eip_status; private boolean is_starting_to_connect; + private boolean wants_to_connect; @Override public void onAttach(Activity activity) { super.onAttach(activity); - parent_activity = activity; - Dashboard dashboard = (Dashboard) parent_activity; - Intent provider_API_command = dashboard.prepareProviderAPICommand(); - provider_API_command.setAction(ProviderAPI.DOWNLOAD_EIP_SERVICE); - parent_activity.startService(provider_API_command); + dashboard = (Dashboard) activity; + dashboard.providerApiCommand(Bundle.EMPTY, 0, ProviderAPI.DOWNLOAD_EIP_SERVICE); } @Override @@ -71,7 +68,7 @@ public class EipFragment extends Fragment implements Observer { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - 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()) @@ -110,15 +107,10 @@ public class EipFragment extends Fragment implements Observer { super.onSaveInstanceState(outState); } - protected void saveEipStatus() { - boolean eip_is_on = false; - Log.d(TAG, "saveEipStatus"); - if(eip_switch.isChecked()) { - eip_is_on = true; - } - - if(parent_activity != null) - Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, eip_is_on).commit(); + 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(); } @OnCheckedChanged(R.id.eipSwitch) @@ -128,18 +120,17 @@ public class EipFragment extends Fragment implements Observer { else handleSwitchOff(); - saveEipStatus(); + saveStatus(); } private void handleSwitchOn() { if(canStartEIP()) startEipFromScratch(); else if(canLogInToStartEIP()) { - Log.d(TAG, "Can Log In to start EIP"); - Dashboard dashboard = (Dashboard) parent_activity; + wants_to_connect = true; Bundle bundle = new Bundle(); bundle.putBoolean(IS_PENDING, true); - dashboard.logInDialog(bundle); + dashboard.sessionDialog(bundle); } } @@ -166,16 +157,16 @@ public class EipFragment extends Fragment implements Observer { } private void askPendingStartCancellation() { - AlertDialog.Builder alertBuilder = new AlertDialog.Builder(parent_activity); - alertBuilder.setTitle(parent_activity.getString(R.string.eip_cancel_connect_title)) - .setMessage(parent_activity.getString(R.string.eip_cancel_connect_text)) + 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(parent_activity.getString(R.string.no), new DialogInterface.OnClickListener() { + .setNegativeButton(dashboard.getString(R.string.no), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { eip_switch.setChecked(true); @@ -185,34 +176,40 @@ public class EipFragment extends Fragment implements Observer { } public void startEipFromScratch() { + wants_to_connect = false; is_starting_to_connect = true; progress_bar.setVisibility(View.VISIBLE); eip_switch.setVisibility(View.VISIBLE); - String status = parent_activity.getString(R.string.eip_status_start_pending); + String status = dashboard.getString(R.string.eip_status_start_pending); status_message.setText(status); if(!eip_switch.isChecked()) { eip_switch.setChecked(true); - saveEipStatus(); } + saveStatus(); eipCommand(Constants.ACTION_START_EIP); } private void stopEIP() { if(eip_status.isConnecting()) VoidVpnService.stop(); - Intent disconnect_vpn = new Intent(parent_activity, DisconnectVPN.class); - parent_activity.startActivityForResult(disconnect_vpn, EIP.DISCONNECT); + Intent disconnect_vpn = new Intent(dashboard, DisconnectVPN.class); + dashboard.startActivityForResult(disconnect_vpn, EIP.DISCONNECT); eip_status.setDisconnecting(); } protected void askToStopEIP() { hideProgressBar(); - String status = parent_activity.getString(R.string.eip_state_not_connected); + String status = dashboard.getString(R.string.eip_state_not_connected); status_message.setText(status); + eipCommand(Constants.ACTION_STOP_EIP); } + + protected void updateEipService() { + eipCommand(Constants.ACTION_UPDATE_EIP_SERVICE); + } /** * Send a command to EIP @@ -222,10 +219,10 @@ public class EipFragment extends Fragment implements Observer { */ 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(parent_activity.getApplicationContext(), EIP.class); + Intent vpn_intent = new Intent(dashboard.getApplicationContext(), EIP.class); vpn_intent.setAction(action); vpn_intent.putExtra(Constants.RECEIVER_TAG, mEIPReceiver); - parent_activity.startService(vpn_intent); + dashboard.startService(vpn_intent); } @Override @@ -233,7 +230,7 @@ public class EipFragment extends Fragment implements Observer { if(observable instanceof EipStatus) { eip_status = (EipStatus) observable; final EipStatus eip_status = (EipStatus) observable; - parent_activity.runOnUiThread(new Runnable() { + dashboard.runOnUiThread(new Runnable() { @Override public void run() { handleNewState(eip_status); @@ -259,13 +256,13 @@ public class EipFragment extends Fragment implements Observer { Log.d(TAG, "setConnectedUi? " + eip_status.isConnected()); adjustSwitch(); is_starting_to_connect = false; - status_message.setText(parent_activity.getString(R.string.eip_state_connected)); + status_message.setText(dashboard.getString(R.string.eip_state_connected)); } private void setDisconnectedUI(){ hideProgressBar(); adjustSwitch(); - status_message.setText(parent_activity.getString(R.string.eip_state_not_connected)); + status_message.setText(dashboard.getString(R.string.eip_state_not_connected)); } private void adjustSwitch() { @@ -286,13 +283,18 @@ public class EipFragment extends Fragment implements Observer { private void setInProgressUI(EipStatus eip_status) { int localizedResId = eip_status.getLocalizedResId(); String logmessage = eip_status.getLogMessage(); - String prefix = parent_activity.getString(localizedResId); + String prefix = dashboard.getString(localizedResId); status_message.setText(prefix + " " + logmessage); is_starting_to_connect = false; adjustSwitch(); } + private void updatingCertificateUI() { + progress_bar.setVisibility(View.VISIBLE); + status_message.setText(getString(R.string.updating_certificate_message)); + } + private void hideProgressBar() { if(progress_bar != null) progress_bar.setVisibility(View.GONE); @@ -338,20 +340,21 @@ public class EipFragment extends Fragment implements Observer { case Activity.RESULT_OK: break; case Activity.RESULT_CANCELED: - Dashboard dashboard = (Dashboard) parent_activity; - - progress_bar.setVisibility(View.VISIBLE); - status_message.setText(getString(R.string.updating_certificate_message)); - if(LeapSRPSession.getToken().isEmpty() && !Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false)) { - dashboard.logInDialog(Bundle.EMPTY); - } else { - Intent provider_API_command = dashboard.prepareProviderAPICommand(); - provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE); - parent_activity.startService(provider_API_command); - } + 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; + } + } } } diff --git a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java index 07ed6c8f..96b87085 100644 --- a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java +++ b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java @@ -3,22 +3,29 @@ 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 se.leap.bitmaskclient.eip.Constants; public class OnBootReceiver extends BroadcastReceiver { - // Debug: am broadcast -a android.intent.action.BOOT_COMPLETED - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { - if (!context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE).getString(Provider.KEY, "").isEmpty() && context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE).getBoolean(Dashboard.START_ON_BOOT, false)) { - 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); - } - } + 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); } + } } 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 3d3070c8..3b72a486 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -16,38 +16,17 @@ */ package se.leap.bitmaskclient.eip; -import android.app.Activity; -import android.app.IntentService; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.os.ResultReceiver; +import android.app.*; +import android.content.*; +import android.os.*; import android.util.Log; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import de.blinkt.openvpn.LaunchVPN; -import de.blinkt.openvpn.VpnProfile; -import de.blinkt.openvpn.core.ProfileManager; -import se.leap.bitmaskclient.Dashboard; -import se.leap.bitmaskclient.EipFragment; - -import static se.leap.bitmaskclient.eip.Constants.ACTION_CHECK_CERT_VALIDITY; -import static se.leap.bitmaskclient.eip.Constants.ACTION_IS_EIP_RUNNING; -import static se.leap.bitmaskclient.eip.Constants.ACTION_START_EIP; -import static se.leap.bitmaskclient.eip.Constants.ACTION_STOP_EIP; -import static se.leap.bitmaskclient.eip.Constants.ACTION_UPDATE_EIP_SERVICE; -import static se.leap.bitmaskclient.eip.Constants.CERTIFICATE; -import static se.leap.bitmaskclient.eip.Constants.KEY; -import static se.leap.bitmaskclient.eip.Constants.RECEIVER_TAG; -import static se.leap.bitmaskclient.eip.Constants.REQUEST_TAG; +import org.json.*; + +import de.blinkt.openvpn.*; +import se.leap.bitmaskclient.*; + +import static se.leap.bitmaskclient.eip.Constants.*; /** * EIP is the abstract base class for interacting with and managing the Encrypted @@ -71,25 +50,24 @@ public final class EIP extends IntentService { private static SharedPreferences preferences; private static JSONObject eip_definition; - private static List<Gateway> gateways = new ArrayList<Gateway>(); - private static ProfileManager profile_manager; + 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(); + @Override + public void onCreate() { + super.onCreate(); - context = getApplicationContext(); - profile_manager = ProfileManager.getInstance(context); + context = getApplicationContext(); + preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); + eip_definition = eipDefinitionFromPreferences(); + if(gateways_manager.isEmpty()) + gatewaysFromPreferences(); + } - preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); - refreshEipDefinition(); - } - @Override protected void onHandleIntent(Intent intent) { String action = intent.getAction(); @@ -101,7 +79,7 @@ public final class EIP extends IntentService { stopEIP(); else if (action.equals(ACTION_IS_EIP_RUNNING)) isRunning(); - else if (action.equals(ACTION_UPDATE_EIP_SERVICE)) + else if (action.equals(ACTION_UPDATE_EIP_SERVICE)) updateEIPService(); else if (action.equals(ACTION_CHECK_CERT_VALIDITY)) checkCertValidity(); @@ -113,17 +91,17 @@ public final class EIP extends IntentService { * It also sets up early routes. */ private void startEIP() { - if(gateways.isEmpty()) + if(gateways_manager.isEmpty()) updateEIPService(); earlyRoutes(); - GatewaySelector gateway_selector = new GatewaySelector(gateways); - gateway = gateway_selector.select(); + gateway = gateways_manager.select(); if(gateway != null && gateway.getProfile() != null) { mReceiver = EipFragment.getReceiver(); launchActiveGateway(); - } - tellToReceiver(ACTION_START_EIP, Activity.RESULT_OK); + tellToReceiver(ACTION_START_EIP, Activity.RESULT_OK); + } else + tellToReceiver(ACTION_START_EIP, Activity.RESULT_CANCELED); } /** @@ -147,7 +125,6 @@ public final class EIP extends IntentService { private void stopEIP() { EipStatus eip_status = EipStatus.getInstance(); - Log.d(TAG, "stopEip(): eip is connected? " + eip_status.isConnected()); int result_code = Activity.RESULT_CANCELED; if(eip_status.isConnected() || eip_status.isConnecting()) result_code = Activity.RESULT_OK; @@ -173,69 +150,46 @@ public final class EIP extends IntentService { * TODO Implement API call to refresh eip-service.json from the provider */ private void updateEIPService() { - refreshEipDefinition(); - deleteAllVpnProfiles(); - updateGateways(); + eip_definition = eipDefinitionFromPreferences(); + if(eip_definition.length() > 0) + updateGateways(); tellToReceiver(ACTION_UPDATE_EIP_SERVICE, Activity.RESULT_OK); } - private void refreshEipDefinition() { + private JSONObject eipDefinitionFromPreferences() { + JSONObject result = new JSONObject(); try { String eip_definition_string = preferences.getString(KEY, ""); if(!eip_definition_string.isEmpty()) { - eip_definition = new JSONObject(eip_definition_string); + result = new JSONObject(eip_definition_string); } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } + return result; } - - private void deleteAllVpnProfiles() { - Collection<VpnProfile> profiles = profile_manager.getProfiles(); - profiles.removeAll(profiles); - gateways.clear(); - } - - /** - * Walk the list of gateways defined in eip-service.json and parse them into - * Gateway objects. - * TODO Store the Gateways (as Serializable) in SharedPreferences - */ + private void updateGateways(){ - try { - if(eip_definition != null) { - JSONArray gatewaysDefined = eip_definition.getJSONArray("gateways"); - for (int i = 0; i < gatewaysDefined.length(); i++) { - JSONObject gw = gatewaysDefined.getJSONObject(i); - if (isOpenVpnGateway(gw)) { - addGateway(new Gateway(eip_definition, context, gw)); - } - } - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + gateways_manager.fromEipServiceJson(eip_definition); + gatewaysToPreferences(); } - private boolean isOpenVpnGateway(JSONObject gateway) { - try { - String transport = gateway.getJSONObject("capabilities").getJSONArray("transport").toString(); - return transport.contains("openvpn"); - } catch (JSONException e) { - return false; - } + private void gatewaysFromPreferences() { + String gateways_string = preferences.getString(Gateway.TAG, ""); + gateways_manager = new GatewaysManager(context, preferences); + gateways_manager.addFromString(gateways_string); + preferences.edit().remove(Gateway.TAG).apply(); } - private void addGateway(Gateway gateway) { - profile_manager.addProfile(gateway.getProfile()); - gateways.add(gateway); + private void gatewaysToPreferences() { + String gateways_string = gateways_manager.toString(); + preferences.edit().putString(Gateway.TAG, gateways_string).commit(); } private void checkCertValidity() { - VpnCertificateValidator validator = new VpnCertificateValidator(); - int resultCode = validator.isValid(preferences.getString(CERTIFICATE, "")) ? + VpnCertificateValidator validator = new VpnCertificateValidator(preferences.getString(CERTIFICATE, "")); + int resultCode = validator.isValid() ? Activity.RESULT_OK : Activity.RESULT_CANCELED; tellToReceiver(ACTION_CHECK_CERT_VALIDITY, resultCode); 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 3ee9443c..0d8a2f7b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -17,21 +17,19 @@ package se.leap.bitmaskclient.eip; import android.app.Activity; -import android.content.Context; import android.content.SharedPreferences; import android.util.Log; +import com.google.gson.Gson; + import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.StringReader; -import java.util.Collection; -import java.util.Iterator; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; -import de.blinkt.openvpn.core.ProfileManager; import se.leap.bitmaskclient.Dashboard; /** @@ -44,48 +42,30 @@ import se.leap.bitmaskclient.Dashboard; */ public class Gateway { - private String TAG = Gateway.class.getSimpleName(); - + public final static String TAG = Gateway.class.getSimpleName(); + + private JSONObject general_configuration; + private JSONObject secrets; + private JSONObject gateway; + private String mName; private int timezone; - private JSONObject general_configuration; - private Context context; private VpnProfile mVpnProfile; - private JSONObject mGateway; - /** * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json * and create a VpnProfile belonging to it. - * - * @param gateway The JSON OpenVPN gateway definition to parse */ - protected Gateway(JSONObject eip_definition, Context context, JSONObject gateway){ + public Gateway(JSONObject eip_definition, JSONObject secrets, JSONObject gateway){ + + this.gateway = gateway; + this.secrets = secrets; - mGateway = gateway; - - this.context = context; general_configuration = getGeneralConfiguration(eip_definition); timezone = getTimezone(eip_definition); mName = locationAsName(eip_definition); - // Currently deletes VpnProfile for host, if there already is one, and builds new - ProfileManager vpl = ProfileManager.getInstance(context); - Collection<VpnProfile> profiles = vpl.getProfiles(); - for (Iterator<VpnProfile> it = profiles.iterator(); it.hasNext(); ){ - VpnProfile p = it.next(); - - if ( p.mName.equalsIgnoreCase( mName ) ) { - it.remove(); - vpl.removeProfile(context, p); - } - } - mVpnProfile = createVPNProfile(); mVpnProfile.mName = mName; - - vpl.addProfile(mVpnProfile); - vpl.saveProfile(context, mVpnProfile); - vpl.saveProfileList(context); } private JSONObject getGeneralConfiguration(JSONObject eip_definition) { @@ -110,7 +90,7 @@ public class Gateway { try { JSONObject locations = eip_definition.getJSONObject("locations"); - return locations.getJSONObject(mGateway.getString("location")); + return locations.getJSONObject(gateway.getString("location")); } catch (JSONException e) { return new JSONObject(); } @@ -123,8 +103,7 @@ public class Gateway { try { ConfigParser cp = new ConfigParser(); - SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE); - VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(preferences, general_configuration, mGateway); + VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(general_configuration, secrets, gateway); String configuration = vpn_configuration_generator.generate(); cp.parseConfig(new StringReader(configuration)); @@ -153,4 +132,9 @@ public class Gateway { public int getTimezone() { return timezone; } + + @Override + public String toString() { + return new Gson().toJson(this, Gateway.class); + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java new file mode 100644 index 00000000..b1aa5a2f --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2013, 2014, 2015 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.eip; + +import android.content.*; +import android.util.Log; + +import com.google.gson.*; +import com.google.gson.reflect.*; + +import org.json.*; + +import java.lang.reflect.*; +import java.util.*; + +import de.blinkt.openvpn.*; +import de.blinkt.openvpn.core.*; +import se.leap.bitmaskclient.*; + +/** + * @author parmegv + */ +public class GatewaysManager { + + private Context context; + private SharedPreferences preferences; + private List<Gateway> gateways = new ArrayList<>(); + private ProfileManager profile_manager; + private Type list_type = new TypeToken<ArrayList<Gateway>>() {}.getType(); + + 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(); + } + + public boolean isEmpty() { + return gateways.isEmpty(); + } + + public int size() { + return gateways.size(); + } + + public void addFromString(String gateways) { + List<Gateway> gateways_list = new ArrayList<Gateway>(); + try { + gateways_list = new Gson().fromJson(gateways, list_type); + } catch(JsonSyntaxException e) { + gateways_list.add(new Gson().fromJson(gateways, Gateway.class)); + } + + if(gateways_list != null) { + for (Gateway gateway : gateways_list) + removeDuplicatedGateway(gateway); + this.gateways.addAll(gateways_list); + } else + Log.d("GatewaysManager", "No gateways added"); + } + + @Override + public String toString() { + return new Gson().toJson(gateways, list_type); + } + + 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(); + } + } + + private boolean isOpenVpnGateway(JSONObject gateway) { + try { + String transport = gateway.getJSONObject("capabilities").getJSONArray("transport").toString(); + return transport.contains("openvpn"); + } catch (JSONException e) { + return false; + } + } + + private JSONObject secretsConfiguration() { + JSONObject result = new JSONObject(); + try { + result.put(Provider.CA_CERT, preferences.getString(Provider.CA_CERT, "")); + result.put(Constants.PRIVATE_KEY, preferences.getString(Constants.PRIVATE_KEY, "")); + result.put(Constants.CERTIFICATE, preferences.getString(Constants.CERTIFICATE, "")); + } catch (JSONException e) { + e.printStackTrace(); + } + return result; + } + + private boolean containsProfileWithSecrets(VpnProfile profile) { + boolean result = false; + + Collection<VpnProfile> profiles = profile_manager.getProfiles(); + for(VpnProfile aux : profiles) { + result = result || sameConnections(profile.mConnections, aux.mConnections) + && profile.mClientCertFilename.equalsIgnoreCase(aux.mClientCertFilename) + && profile.mClientKeyFilename.equalsIgnoreCase(aux.mClientKeyFilename); + } + return result; + } + + private void addGateway(Gateway gateway) { + removeDuplicatedGateway(gateway); + + gateways.add(gateway); + + VpnProfile profile = gateway.getProfile(); + profile_manager.addProfile(profile); + //profile_manager.saveProfile(context, profile); + //profile_manager.saveProfileList(context); + } + + private void removeDuplicatedGateway(Gateway gateway) { + Iterator<Gateway> it = gateways.iterator(); + List<Gateway> gateways_to_remove = new ArrayList<>(); + while(it.hasNext()) { + Gateway aux = it.next(); + if(sameConnections(aux.getProfile().mConnections, gateway.getProfile().mConnections)) { + gateways_to_remove.add(aux); + } + } + gateways.removeAll(gateways_to_remove); + removeDuplicatedProfiles(gateway.getProfile()); + } + + private void removeDuplicatedProfiles(VpnProfile original) { + 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 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)) { + same_connections++; + break; + } + } + return c1.length == c2.length && c1.length == same_connections; + } +} 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 6487f6c1..0bbe9db4 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java @@ -28,7 +28,13 @@ import se.leap.bitmaskclient.ConfigHelper; public class VpnCertificateValidator { public final static String TAG = VpnCertificateValidator.class.getSimpleName(); - public boolean isValid(String certificate) { + private String certificate; + + public VpnCertificateValidator(String certificate) { + this.certificate = certificate; + } + + public boolean isValid() { if(!certificate.isEmpty()) { X509Certificate certificate_x509 = ConfigHelper.parseX509CertificateFromString(certificate); return isValid(certificate_x509); 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 0c8e9a04..6f260f55 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -31,15 +31,15 @@ public class VpnConfigGenerator { private JSONObject general_configuration; private JSONObject gateway; - - private static SharedPreferences preferences; + private JSONObject secrets; + 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) { + public VpnConfigGenerator(JSONObject general_configuration, JSONObject secrets, JSONObject gateway) { this.general_configuration = general_configuration; this.gateway = gateway; - VpnConfigGenerator.preferences = preferences; + this.secrets = secrets; } public String generate() { @@ -79,59 +79,67 @@ public class VpnConfigGenerator { private String gatewayConfiguration() { String remotes = ""; - String remote = "ip_address"; - String remote_openvpn_keyword = "remote"; - String ports = "ports"; - String protos = "protocols"; - String capabilities = "capabilities"; + 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 { - 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; + 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(); } - 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(Constants.PRIVATE_KEY, "") - + new_line - + "</key>"; - - String openvpn_cert = - "<cert>" - + new_line - + preferences.getString(Constants.CERTIFICATE, "") - + new_line - + "</cert>"; + try { + String ca = + "<ca>" + + new_line + + secrets.getString(Provider.CA_CERT) + + new_line + + "</ca>"; + + String key = + "<key>" + + new_line + + secrets.getString(Constants.PRIVATE_KEY) + + new_line + + "</key>"; + + String openvpn_cert = + "<cert>" + + new_line + + secrets.getString(Constants.CERTIFICATE) + + new_line + + "</cert>"; - return ca + new_line + key + new_line + openvpn_cert; + return ca + new_line + key + new_line + openvpn_cert; + } catch(JSONException e) { + e.printStackTrace(); + return ""; + } } private String androidCustomizations() { |