From 582758a34f6fd82ad1071bf9a196f0fa048689e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 15 Dec 2014 11:30:28 +0100 Subject: Working on Android 5. Beware! https://code.google.com/p/android/issues/detail?id=80074: Wrong VpnService.prepare() behavior after re-installation of the VPN app on Android 5.0 "The following steps will cause incorrect behavior of the VpnService.prepare(): 1. Establish VPN connection using any VPN app. VpnService.prepare() will return an intent for the "Connection request" system activity. Once user accepts it, VPN connection can be established successfully. 2. Uninstall VPN app. 3. Re-install the same VPN app. 4. Now VpnService.prepare() returns null, as if the VPN service has been already prepared. 5. Now VpnService.protect() returns false and VPN connection fails. Device reboot is needed in order to be able to establish VPN connection again." --- .../java/se/leap/bitmaskclient/ProviderAPI.java | 20 +++--- .../main/java/se/leap/bitmaskclient/Dashboard.java | 72 +++++++++++++--------- .../se/leap/bitmaskclient/EipServiceFragment.java | 21 ++----- .../java/se/leap/bitmaskclient/eip/Constants.java | 1 - .../main/java/se/leap/bitmaskclient/eip/EIP.java | 28 ++++----- .../java/se/leap/bitmaskclient/ProviderAPI.java | 21 +++---- 6 files changed, 80 insertions(+), 83 deletions(-) (limited to 'app/src') diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java index 9ac5ff66..f47510bc 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java @@ -62,11 +62,11 @@ public class ProviderAPI extends IntentService { ; final public static int - SRP_AUTHENTICATION_SUCCESSFUL = 3, - SRP_AUTHENTICATION_FAILED = 4, - SRP_REGISTRATION_SUCCESSFUL = 5, - SRP_REGISTRATION_FAILED = 6, - LOGOUT_SUCCESSFUL = 7, + SUCCESSFUL_LOGIN = 3, + FAILED_LOGIN = 4, + SUCCESSFUL_SIGNUP = 5, + FAILED_SIGNUP = 6, + SUCCESSFUL_LOGOUT = 7, LOGOUT_FAILED = 8, CORRECTLY_DOWNLOADED_CERTIFICATE = 9, INCORRECTLY_DOWNLOADED_CERTIFICATE = 10, @@ -142,20 +142,20 @@ public class ProviderAPI extends IntentService { } else if (action.equalsIgnoreCase(SRP_REGISTER)) { Bundle session_id_bundle = tryToRegister(parameters); if(session_id_bundle.getBoolean(RESULT_KEY)) { - receiver.send(SRP_REGISTRATION_SUCCESSFUL, session_id_bundle); + receiver.send(SUCCESSFUL_SIGNUP, session_id_bundle); } else { - receiver.send(SRP_REGISTRATION_FAILED, session_id_bundle); + receiver.send(FAILED_SIGNUP, session_id_bundle); } } else if (action.equalsIgnoreCase(SRP_AUTH)) { Bundle session_id_bundle = tryToAuthenticate(parameters); if(session_id_bundle.getBoolean(RESULT_KEY)) { - receiver.send(SRP_AUTHENTICATION_SUCCESSFUL, session_id_bundle); + receiver.send(SUCCESSFUL_LOGIN, session_id_bundle); } else { - receiver.send(SRP_AUTHENTICATION_FAILED, session_id_bundle); + receiver.send(FAILED_LOGIN, session_id_bundle); } } else if (action.equalsIgnoreCase(LOG_OUT)) { if(logOut()) { - receiver.send(LOGOUT_SUCCESSFUL, Bundle.EMPTY); + receiver.send(SUCCESSFUL_LOGOUT, Bundle.EMPTY); } else { receiver.send(LOGOUT_FAILED, Bundle.EMPTY); } diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 3ecf5e52..862086eb 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -16,6 +16,7 @@ */ package se.leap.bitmaskclient; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.DialogFragment; @@ -34,6 +35,7 @@ import android.view.MenuItem; import android.widget.ProgressBar; import android.widget.TextView; +import org.jetbrains.annotations.NotNull; import org.json.JSONException; import org.json.JSONObject; @@ -48,7 +50,7 @@ import se.leap.bitmaskclient.eip.EIP; import se.leap.bitmaskclient.eip.EipStatus; /** - * The main user facing Activity of LEAP Android, consisting of status, controls, + * The main user facing Activity of Bitmask Android, consisting of status, controls, * and access to preferences. * * @author Sean Leonard @@ -81,7 +83,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn public ProviderAPIResultReceiver providerAPI_result_receiver; @Override - protected void onSaveInstanceState(Bundle outState) { + protected void onSaveInstanceState(@NotNull Bundle outState) { if(provider != null) outState.putParcelable(Provider.KEY, provider); super.onSaveInstanceState(outState); @@ -99,24 +101,36 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); handleVersion(); - if(savedInstanceState != null) - provider = savedInstanceState.getParcelable(Provider.KEY); - if(provider == null && preferences.getBoolean(Constants.PROVIDER_CONFIGURED, false)) - try { - provider = new Provider(new URL(preferences.getString(Provider.MAIN_URL, ""))); - provider.define(new JSONObject(preferences.getString(Provider.KEY, ""))); - } catch (MalformedURLException e) { - e.printStackTrace(); - } catch (JSONException e) { - e.printStackTrace(); - } - + 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) + provider = savedInstanceState.getParcelable(Provider.KEY); + else if(preferences.getBoolean(Constants.PROVIDER_CONFIGURED, false)) + provider = getSavedProviderFromSharedPreferences(); + + return provider; + } + + private Provider getSavedProviderFromSharedPreferences() { + Provider provider = null; + try { + provider = new Provider(new URL(preferences.getString(Provider.MAIN_URL, ""))); + provider.define(new JSONObject(preferences.getString(Provider.KEY, ""))); + } catch (MalformedURLException | JSONException e) { + e.printStackTrace(); + } + + return provider; + } + + private void handleVersion() { try { int versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; @@ -140,13 +154,12 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn } } + @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) { - // It should be equivalent: if ( (requestCode == CONFIGURE_LEAP) || (data!= null && data.hasExtra(STOP_FIRST))) { if ( resultCode == RESULT_OK ) { - preferences.edit().putInt(Constants.PARSED_SERIAL, 0).apply(); preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); updateEipService(); @@ -205,7 +218,6 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn ButterKnife.inject(this); provider_name.setText(provider.getDomain()); - if ( provider.hasEIP()){ fragment_manager.removePreviousFragment(EipServiceFragment.TAG); @@ -412,16 +424,16 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn @Override public void onReceiveResult(int resultCode, Bundle resultData) { Log.d(TAG, "onReceiveResult"); - if(resultCode == ProviderAPI.SRP_REGISTRATION_SUCCESSFUL) { + if(resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) { String username = resultData.getString(SessionDialog.USERNAME); String password = resultData.getString(SessionDialog.PASSWORD); logIn(username, password); - } else if(resultCode == ProviderAPI.SRP_REGISTRATION_FAILED) { + } else if(resultCode == ProviderAPI.FAILED_SIGNUP) { changeStatusMessage(resultCode); hideProgressBar(); signUpDialog(resultData); - } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL) { + } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGIN) { changeStatusMessage(resultCode); hideProgressBar(); @@ -431,12 +443,12 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); downloadAuthedUserCertificate(); - } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_FAILED) { + } else if(resultCode == ProviderAPI.FAILED_LOGIN) { changeStatusMessage(resultCode); hideProgressBar(); logInDialog(resultData); - } else if(resultCode == ProviderAPI.LOGOUT_SUCCESSFUL) { + } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGOUT) { changeStatusMessage(resultCode); hideProgressBar(); @@ -477,7 +489,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn } } }; - updateEIP.putExtra(Constants.RECEIVER_TAG, receiver); + //updateEIP.putExtra(Constants.RECEIVER_TAG, receiver); startService(updateEIP); } @@ -491,11 +503,11 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn if (resultCode == Activity.RESULT_OK){ switch(previous_result_code){ - case ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL: eip_fragment.status_message.setText(R.string.succesful_authentication_message); break; - case ProviderAPI.SRP_AUTHENTICATION_FAILED: eip_fragment.status_message.setText(R.string.authentication_failed_message); break; + 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.LOGOUT_SUCCESSFUL: eip_fragment.status_message.setText(R.string.logged_out_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; } @@ -504,12 +516,12 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn switch(previous_result_code){ - case ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL: eip_fragment.status_message.setText(R.string.succesful_authentication_message); break; - case ProviderAPI.SRP_AUTHENTICATION_FAILED: eip_fragment.status_message.setText(R.string.authentication_failed_message); break; - case ProviderAPI.SRP_REGISTRATION_FAILED: eip_fragment.status_message.setText(R.string.registration_failed_message); break; + 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.LOGOUT_SUCCESSFUL: eip_fragment.status_message.setText(R.string.logged_out_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; } } diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java index 904aa31d..acfc967b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java @@ -139,7 +139,7 @@ public class EipServiceFragment extends Fragment implements Observer { private boolean canStartEIP() { boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty(); boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false); - return (isAllowedAnon || certificateExists) && !eip_status.isConnected(); + return (isAllowedAnon || certificateExists) && !eip_status.isConnected() && !eip_status.isConnecting(); } private boolean canLogInToStartEIP() { @@ -275,19 +275,13 @@ public class EipServiceFragment extends Fragment implements Observer { adjustSwitch(); } - protected void setStatusMessage(String status) { - if(status_message == null) - status_message = (TextView) parent_activity.findViewById(R.id.status_message); - status_message.setText(status); - } - private void hideProgressBar() { if(progress_bar != null) progress_bar.setVisibility(View.GONE); } protected class EIPReceiver extends ResultReceiver { - + protected EIPReceiver(Handler handler){ super(handler); } @@ -295,17 +289,14 @@ public class EipServiceFragment extends Fragment implements Observer { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); - + String request = resultData.getString(Constants.REQUEST_TAG); if (request.equals(Constants.ACTION_START_EIP)) { switch (resultCode){ case Activity.RESULT_OK: - Log.d(TAG, "Action start eip = Result OK"); - progress_bar.setVisibility(View.VISIBLE); break; case Activity.RESULT_CANCELED: - progress_bar.setVisibility(View.GONE); break; } } else if (request.equals(Constants.ACTION_STOP_EIP)) { @@ -336,13 +327,13 @@ public class EipServiceFragment extends Fragment implements Observer { 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 { + } else { Intent provider_API_command = new Intent(parent_activity, 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); parent_activity.startService(provider_API_command); @@ -352,7 +343,7 @@ public class EipServiceFragment extends Fragment implements Observer { } } } - + public static EIPReceiver getReceiver() { return mEIPReceiver; diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java index 01a83d5f..12c2e015 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java @@ -39,7 +39,6 @@ public interface Constants { public final static String CERTIFICATE = "cert"; public final static String PRIVATE_KEY = TAG + ".PRIVATE_KEY"; public final static String KEY = TAG + ".KEY"; - public final static String PARSED_SERIAL = TAG + ".PARSED_SERIAL"; public final static String RECEIVER_TAG = TAG + ".RECEIVER_TAG"; public final static String REQUEST_TAG = TAG + ".REQUEST_TAG"; public final static String START_BLOCKING_VPN_PROFILE = TAG + ".START_BLOCKING_VPN_PROFILE"; 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 4363dd13..0713e521 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; +import android.os.Handler; import android.os.ResultReceiver; import android.util.Log; @@ -38,7 +39,6 @@ import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ProfileManager; import se.leap.bitmaskclient.Dashboard; import se.leap.bitmaskclient.EipServiceFragment; -import se.leap.bitmaskclient.Provider; import static se.leap.bitmaskclient.eip.Constants.ACTION_CHECK_CERT_VALIDITY; import static se.leap.bitmaskclient.eip.Constants.ACTION_IS_EIP_RUNNING; @@ -65,20 +65,19 @@ public final class EIP extends IntentService { public final static String TAG = EIP.class.getSimpleName(); public final static String SERVICE_API_PATH = "config/eip-service.json"; - public static final int DISCONNECT = 15; private static Context context; private static ResultReceiver mReceiver; private static SharedPreferences preferences; - private static JSONObject eip_definition = null; + private static JSONObject eip_definition; private static List gateways = new ArrayList(); private static ProfileManager profile_manager; - private static Gateway activeGateway = null; + private static Gateway gateway; public EIP(){ - super("LEAPEIP"); + super(TAG); } @Override @@ -117,13 +116,15 @@ public final class EIP extends IntentService { private void startEIP() { if(gateways.isEmpty()) updateEIPService(); - GatewaySelector gateway_selector = new GatewaySelector(gateways); - activeGateway = gateway_selector.select(); - if(activeGateway != null && activeGateway.getProfile() != null) { + earlyRoutes(); + + GatewaySelector gateway_selector = new GatewaySelector(gateways); + gateway = gateway_selector.select(); + if(gateway != null && gateway.getProfile() != null) { mReceiver = EipServiceFragment.getReceiver(); launchActiveGateway(); } - earlyRoutes(); + tellToReceiver(ACTION_START_EIP, Activity.RESULT_OK); } /** @@ -140,16 +141,11 @@ public final class EIP extends IntentService { Intent intent = new Intent(this,LaunchVPN.class); intent.setAction(Intent.ACTION_MAIN); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.getProfile().getName() ); + intent.putExtra(LaunchVPN.EXTRA_NAME, gateway.getProfile().getName()); intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true); - intent.putExtra(RECEIVER_TAG, mReceiver); startActivity(intent); } - - /** - * 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() { EipStatus eip_status = EipStatus.getInstance(); Log.d(TAG, "stopEip(): eip is connected? " + eip_status.isConnected()); diff --git a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java index f5f27247..f1cb84d6 100644 --- a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java @@ -63,12 +63,11 @@ public class ProviderAPI extends IntentService { ; final public static int - CUSTOM_PROVIDER_ADDED = 0, - SRP_AUTHENTICATION_SUCCESSFUL = 3, - SRP_AUTHENTICATION_FAILED = 4, - SRP_REGISTRATION_SUCCESSFUL = 5, - SRP_REGISTRATION_FAILED = 6, - LOGOUT_SUCCESSFUL = 7, + SUCCESSFUL_LOGIN = 3, + FAILED_LOGIN = 4, + SUCCESSFUL_SIGNUP = 5, + FAILED_SIGNUP = 6, + SUCCESSFUL_LOGOUT = 7, LOGOUT_FAILED = 8, CORRECTLY_DOWNLOADED_CERTIFICATE = 9, INCORRECTLY_DOWNLOADED_CERTIFICATE = 10, @@ -140,20 +139,20 @@ public class ProviderAPI extends IntentService { } else if (action.equalsIgnoreCase(SRP_REGISTER)) { Bundle result = tryToRegister(parameters); if(result.getBoolean(RESULT_KEY)) { - receiver.send(SRP_REGISTRATION_SUCCESSFUL, result); + receiver.send(SUCCESSFUL_SIGNUP, result); } else { - receiver.send(SRP_REGISTRATION_FAILED, result); + receiver.send(FAILED_SIGNUP, result); } } else if (action.equalsIgnoreCase(SRP_AUTH)) { Bundle result = tryToAuthenticate(parameters); if(result.getBoolean(RESULT_KEY)) { - receiver.send(SRP_AUTHENTICATION_SUCCESSFUL, result); + receiver.send(SUCCESSFUL_LOGIN, result); } else { - receiver.send(SRP_AUTHENTICATION_FAILED, result); + receiver.send(FAILED_LOGIN, result); } } else if (action.equalsIgnoreCase(LOG_OUT)) { if(logOut()) { - receiver.send(LOGOUT_SUCCESSFUL, Bundle.EMPTY); + receiver.send(SUCCESSFUL_LOGOUT, Bundle.EMPTY); } else { receiver.send(LOGOUT_FAILED, Bundle.EMPTY); } -- cgit v1.2.3