diff options
author | Parménides GV <parmegv@sdf.org> | 2014-11-25 13:19:21 +0100 |
---|---|---|
committer | Parménides GV <parmegv@sdf.org> | 2014-11-25 13:19:21 +0100 |
commit | 576b0c26baf9b5b1418650a572604325ca7fb3af (patch) | |
tree | 8b2986d66ed4e6bdf5a3253c81f32cc5a8e53b99 /app/src | |
parent | bbf877a099112acbf34589b01503c3f5ee135dc0 (diff) | |
parent | 48cd0f2fa3094b5a6b7b07d6413d77bdbc9bbc20 (diff) |
Merge branch 'develop'0.8.0
Diffstat (limited to 'app/src')
77 files changed, 2972 insertions, 2392 deletions
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboard.java b/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboard.java index fdf4f135..1af17fe6 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboard.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/test/testDashboard.java @@ -123,4 +123,31 @@ public class testDashboard extends ActivityInstrumentationTestCase2<Dashboard> { solo.waitForActivity(ConfigurationWizard.class); solo.goBack(); } + + public void testUpdateExpiredCertificate() { + String certificate = "-----BEGIN CERTIFICATE-----" + + "MIIEnDCCAoSgAwIBAgIRAOBkcbMKR0Jlw+xNalHn7aIwDQYJKoZIhvcNAQELBQAwdTEYMBYGA1UE" + + "CgwPUmlzZXVwIE5ldHdvcmtzMRswGQYDVQQLDBJodHRwczovL3Jpc2V1cC5uZXQxPDA6BgNVBAMM" + + "M1Jpc2V1cCBOZXR3b3JrcyBSb290IENBIChjbGllbnQgY2VydGlmaWNhdGVzIG9ubHkhKTAeFw0x" + + "NDA5MTkwMDAwMDBaFw0xNDExMTkwMDAwMDBaMC0xKzApBgNVBAMMIlVOTElNSVRFRDcwZWhxZG9l" + + "ZXQ2Z243bmc3eWx3ZWNxeGwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdaKQHSwg2" + + "Q2Uz9t5mae9BfV9Jkk+WSU6jXixsTbtLAr8gvuNcVuI0lKm2zXVqoS8aRCSsCt12vhjU/WBTSv0t" + + "vwTaT2HQYFQ1GlVUBKssJEUpaVyQKL6LN9BA5ZODBpbhefRIX8z+02afxmNWdnOQfDtLU6nHSQLL" + + "IUBSmgu+Y2Q3SdIBojIl9Kj0Zt6uZkhtOXZqkwLBiMr+/ukSidpcmNgbAN0eXSfVouaduzsDPQ6M" + + "eCJTz2lhUvC0/57h5mlkNLzEjyb/pAVTtnK4zdiH6XAuCxU/AkF0yzhaiQWMG0RQb4vEx/UHjkDU" + + "+K0GDy/qx1BmBB7C4vHLauqSXOs1AgMBAAGjbzBtMB0GA1UdDgQWBBQioBn7DdhjmtBKgQKpx/aW" + + "XHYkGjALBgNVHQ8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwIwCQYDVR0TBAIwADAfBgNVHSME" + + "GDAWgBQX9BvV5SoBAU1rol02CikJlmWARjANBgkqhkiG9w0BAQsFAAOCAgEAV7q102FQ62IOX84o" + + "pPvUL3hJkGtZ5chgQwZhfl2fGtEdeqpU27Hx1jLP9o3n1z9XYaZg/d8xYhpY6Mm4rFl6hA4gk81Z" + + "yg/A3QeUgIjOsA0Xp+RNB5ACaLjCPUtWNk5brfuelDdFHjl1noC2P3vQ9ErhUna6TKVsxxrueimO" + + "nc3sV7YMGiVfPC7wEmhERuyhQxftIUHUy2kDCY5QgXtru6IZmc3SP4FcM8LUSC49kqmU9if2GTLo" + + "wQZmz6T7+N5PIJWIOiDh9PyoojRo7ep9szeIZpzgxcsoE/9ed84tg36JLOWi0GOyrdzVExv0rQQt" + + "q/NpqAe1mX5XQVbY8nwgaJ8eWIWIXIn+5RB7b+fm5ZFeM4eFyWeDk99bvS8jdH6uQP5WusL55+ft" + + "ADtESsmBvzUEGqxk5GL4lmmeqE+vsR5TesqGjZ+yH67rR+1+Uy2mhbqJBP0E0LHwWCCPYEVfngHj" + + "aZkDF1UVQdfc9Amc5u5J5YliWrEG80BNeJF7740Gwx69DHEIhElN+BBeeqLLYIZTKmt28/9iWbKL" + + "vhCrz/29wLYksL1bXmyHzvzyAcDHPpO9sQrKYiP1mGRDmXJmZU3i3cgeqQFZ8+lr55wcYdMGJOcx" + + "bz+jL0VkHdnoZdzGzelrAhZtgMtsJ/kgWYRgtFmhpYF1Xtj2MYrpBDxgQck=" + + "-----END CERTIFICATE-----"; + + } } diff --git a/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java b/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java index c405d06f..78fcda56 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ConfigurationWizard.java @@ -1,281 +1,376 @@ -/**
- * 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.DialogFragment;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.content.res.AssetManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.util.Log;
-import android.view.Display;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View.MeasureSpec;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.ProgressBar;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import java.io.IOException;
+/** + * 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.DialogFragment; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.content.res.AssetManager; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.Display; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View.MeasureSpec; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.ProgressBar; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.util.Iterator;
-import org.json.JSONException;
-import org.json.JSONObject;
+import java.util.Iterator; +import org.json.JSONException; +import org.json.JSONObject; + import se.leap.bitmaskclient.DownloadFailedDialog.DownloadFailedDialogInterface; import se.leap.bitmaskclient.NewProviderDialog.NewProviderDialogInterface; import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver; import se.leap.bitmaskclient.ProviderDetailFragment.ProviderDetailFragmentInterface; import se.leap.bitmaskclient.ProviderListContent.ProviderItem; +import se.leap.bitmaskclient.FragmentManagerEnhanced; + import se.leap.bitmaskclient.R; -
-/**
- * Activity that builds and shows the list of known available providers.
- *
- * It also allows the user to enter custom providers with a button.
- *
- * @author parmegv
- *
- */
-public class ConfigurationWizard extends Activity
-implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver {
-
- private ProgressBar mProgressBar;
- private TextView progressbar_description;
- private ProviderListFragment provider_list_fragment;
- private Intent mConfigState = new Intent();
-
- final public static String TAG = "se.leap.bitmaskclient.ConfigurationWizard";
- final public static String TYPE_OF_CERTIFICATE = "type_of_certificate";
- final public static String ANON_CERTIFICATE = "anon_certificate";
- final public static String AUTHED_CERTIFICATE = "authed_certificate";
-
- final protected static String PROVIDER_SET = "PROVIDER SET";
- final protected static String SERVICES_RETRIEVED = "SERVICES RETRIEVED";
+ +/** + * Activity that builds and shows the list of known available providers. + * + * It also allows the user to enter custom providers with a button. + * + * @author parmegv + * + */ +public class ConfigurationWizard extends Activity +implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver { + + private ProgressBar mProgressBar; + private TextView progressbar_description; + private ProviderListFragment provider_list_fragment; + private Intent mConfigState = new Intent(); + + final public static String TAG = ConfigurationWizard.class.getSimpleName(); + final public static String TYPE_OF_CERTIFICATE = "type_of_certificate"; + final public static String ANON_CERTIFICATE = "anon_certificate"; + final public static String AUTHED_CERTIFICATE = "authed_certificate"; + + final protected static String PROVIDER_SET = "PROVIDER SET"; + final protected static String SERVICES_RETRIEVED = "SERVICES RETRIEVED"; final protected static String ASSETS_URL_FOLDER = "urls"; -
- public ProviderAPIResultReceiver providerAPI_result_receiver;
+ + public ProviderAPIResultReceiver providerAPI_result_receiver; private ProviderAPIBroadcastReceiver_Update providerAPI_broadcast_receiver_update; - private static SharedPreferences preferences;
+ private static SharedPreferences preferences; + FragmentManagerEnhanced fragment_manager; private static boolean setting_up_provider = false; -
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); -
- setContentView(R.layout.configuration_wizard_activity);
- mProgressBar = (ProgressBar) findViewById(R.id.progressbar_configuration_wizard);
- mProgressBar.setVisibility(ProgressBar.INVISIBLE);
- progressbar_description = (TextView) findViewById(R.id.progressbar_description);
- progressbar_description.setVisibility(TextView.INVISIBLE);
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- providerAPI_result_receiver.setReceiver(this);
- providerAPI_broadcast_receiver_update = new ProviderAPIBroadcastReceiver_Update();
- IntentFilter update_intent_filter = new IntentFilter(ProviderAPI.UPDATE_PROGRESSBAR);
- update_intent_filter.addCategory(Intent.CATEGORY_DEFAULT);
- registerReceiver(providerAPI_broadcast_receiver_update, update_intent_filter);
-
- loadPreseededProviders();
-
- // Only create our fragments if we're not restoring a saved instance
- if ( savedInstanceState == null ){
- // TODO Some welcome screen?
- // We will need better flow control when we have more Fragments (e.g. user auth)
- provider_list_fragment = ProviderListFragment.newInstance();
- Bundle arguments = new Bundle();
- int configuration_wizard_request_code = getIntent().getIntExtra(Dashboard.REQUEST_CODE, -1);
- if(configuration_wizard_request_code == Dashboard.SWITCH_PROVIDER) {
- arguments.putBoolean(ProviderListFragment.SHOW_ALL_PROVIDERS, true);
- }
- provider_list_fragment.setArguments(arguments);
-
- FragmentManager fragmentManager = getFragmentManager();
- fragmentManager.beginTransaction()
- .replace(R.id.configuration_wizard_layout, provider_list_fragment, ProviderListFragment.TAG)
- .commit();
- }
-
- // TODO: If exposing deep links into your app, handle intents here.
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- unregisterReceiver(providerAPI_broadcast_receiver_update);
- }
-
- public void refreshProviderList(int top_padding) {
- ProviderListFragment new_provider_list_fragment = new ProviderListFragment();
- Bundle top_padding_bundle = new Bundle();
- top_padding_bundle.putInt(ProviderListFragment.TOP_PADDING, top_padding);
- new_provider_list_fragment.setArguments(top_padding_bundle);
-
- FragmentManager fragmentManager = getFragmentManager();
- fragmentManager.beginTransaction()
- .replace(R.id.configuration_wizard_layout, new_provider_list_fragment, ProviderListFragment.TAG)
- .commit();
- }
-
- @Override
- public void onReceiveResult(int resultCode, Bundle resultData) {
- if(resultCode == ProviderAPI.PROVIDER_OK) {
- mConfigState.setAction(PROVIDER_SET);
-
- if (preferences.getBoolean(EIP.ALLOWED_ANON, false)){
- mConfigState.putExtra(SERVICES_RETRIEVED, true);
- downloadAnonCert();
- } else {
- mProgressBar.incrementProgressBy(1);
- mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE);
- setResult(RESULT_OK); - showProviderDetails(getCurrentFocus());
- } - } else if(resultCode == ProviderAPI.PROVIDER_NOK) {
- //refreshProviderList(0); - String reason_to_fail = resultData.getString(ProviderAPI.ERRORS);
- showDownloadFailedDialog(getCurrentFocus(), reason_to_fail);
- mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE); - preferences.edit().remove(Provider.KEY).commit();
- setting_up_provider = false; - setResult(RESULT_CANCELED, mConfigState);
- }
- else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
- mProgressBar.incrementProgressBy(1);
- mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE);
- //refreshProviderList(0);
- setResult(RESULT_OK);
- showProviderDetails(getCurrentFocus());
- } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
- //refreshProviderList(0);
- mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE);
- //Toast.makeText(getApplicationContext(), R.string.incorrectly_downloaded_certificate_message, Toast.LENGTH_LONG).show();
- setResult(RESULT_CANCELED, mConfigState);
- } else if(resultCode == AboutActivity.VIEWED) { - // Do nothing, right now - // I need this for CW to wait for the About activity to end before going back to Dashboard. - } - }
-
- /**
- * Callback method from {@link ProviderListFragment.Callbacks}
- * indicating that the item with the given ID was selected.
- */
- @Override
- public void onItemSelected(String id) {
- //TODO Code 2 pane view
- // resetOldConnection();
- ProviderItem selected_provider = getProvider(id);
- int provider_index = getProviderIndex(id);
- - - startProgressBar(provider_index+1); - provider_list_fragment.hideAllBut(provider_index); - - boolean danger_on = true; - if(preferences.contains(ProviderItem.DANGER_ON)) - danger_on = preferences.getBoolean(ProviderItem.DANGER_ON, false); - setUpProvider(selected_provider.providerMainUrl(), danger_on); - }
-
- @Override
- public void onBackPressed() {
+ fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); + + setUpInitialUI(); + + loadPreseededProviders(); + + setUpProviderAPIResultReceiver(); + + // Only create our fragments if we're not restoring a saved instance + if ( savedInstanceState == null ){ + // TODO Some welcome screen? + // We will need better flow control when we have more Fragments (e.g. user auth) + setUpProviderList(); + } + + // TODO: If exposing deep links into your app, handle intents here. + } + + private void setUpInitialUI() { + setContentView(R.layout.configuration_wizard_activity); + + hideProgressBar(); + } + + private void hideProgressBar() { + mProgressBar = (ProgressBar) findViewById(R.id.progressbar_configuration_wizard); + mProgressBar.setVisibility(ProgressBar.INVISIBLE); + + progressbar_description = (TextView) findViewById(R.id.progressbar_description); + progressbar_description.setVisibility(TextView.INVISIBLE); + } + + private void setUpProviderList() { + provider_list_fragment = ProviderListFragment.newInstance(); + + Bundle arguments = new Bundle(); + int configuration_wizard_request_code = getIntent().getIntExtra(Dashboard.REQUEST_CODE, -1); + if(configuration_wizard_request_code == Dashboard.SWITCH_PROVIDER) + arguments.putBoolean(ProviderListFragment.SHOW_ALL_PROVIDERS, true); + + provider_list_fragment.setArguments(arguments); + + putProviderListFragment(provider_list_fragment); + } + + private void putProviderListFragment(ProviderListFragment fragment) { + + fragment_manager.replace(R.id.configuration_wizard_layout, provider_list_fragment, ProviderListFragment.TAG); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(providerAPI_broadcast_receiver_update); + } + + private void setUpProviderAPIResultReceiver() { + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); + providerAPI_broadcast_receiver_update = new ProviderAPIBroadcastReceiver_Update(); + + IntentFilter update_intent_filter = new IntentFilter(ProviderAPI.UPDATE_PROGRESSBAR); + update_intent_filter.addCategory(Intent.CATEGORY_DEFAULT); + registerReceiver(providerAPI_broadcast_receiver_update, update_intent_filter); + } + + @Override + public void onReceiveResult(int resultCode, Bundle resultData) { + if(resultCode == ProviderAPI.PROVIDER_OK) { + mConfigState.setAction(PROVIDER_SET); + + if (preferences.getBoolean(EIP.ALLOWED_ANON, false)){ + mConfigState.putExtra(SERVICES_RETRIEVED, true); + + downloadAnonCert(); + } else { + mProgressBar.incrementProgressBy(1); + hideProgressBar(); + + setResult(RESULT_OK); + + showProviderDetails(); + } + } else if(resultCode == ProviderAPI.PROVIDER_NOK) { + hideProgressBar(); + preferences.edit().remove(Provider.KEY).commit(); + setting_up_provider = false; + + setResult(RESULT_CANCELED, mConfigState); + + String reason_to_fail = resultData.getString(ProviderAPI.ERRORS); + showDownloadFailedDialog(getCurrentFocus(), reason_to_fail); + } + else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { + mProgressBar.incrementProgressBy(1); + hideProgressBar(); + + setResult(RESULT_OK); + + showProviderDetails(); + } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { + hideProgressBar(); + + setResult(RESULT_CANCELED, mConfigState); + } else if(resultCode == AboutActivity.VIEWED) { + // Do nothing, right now + // I need this for CW to wait for the About activity to end before going back to Dashboard. + } + } + + /** + * Callback method from {@link ProviderListFragment.Callbacks} + * indicating that the item with the given ID was selected. + */ + @Override + public void onItemSelected(String id) { + //TODO Code 2 pane view + ProviderItem selected_provider = getProvider(id); + int provider_index = getProviderIndex(id); + + startProgressBar(provider_index+1); + provider_list_fragment.hideAllBut(provider_index); + + boolean danger_on = true; + if(preferences.contains(ProviderItem.DANGER_ON)) + danger_on = preferences.getBoolean(ProviderItem.DANGER_ON, false); + setUpProvider(selected_provider.providerMainUrl(), danger_on); + } + + @Override + public void onBackPressed() { if(setting_up_provider) { stopSettingUpProvider(); - } else {
+ } else { usualBackButton(); } } -
- private void stopSettingUpProvider() {
- ProviderAPI.stop();
- mProgressBar.setVisibility(ProgressBar.GONE);
- mProgressBar.setProgress(0);
- progressbar_description.setVisibility(TextView.GONE);
- preferences.edit().remove(Provider.KEY).commit();
- setting_up_provider = false;
+ + private void stopSettingUpProvider() { + ProviderAPI.stop(); + mProgressBar.setVisibility(ProgressBar.GONE); + mProgressBar.setProgress(0); + progressbar_description.setVisibility(TextView.GONE); + preferences.edit().remove(Provider.KEY).commit(); + setting_up_provider = false; showAllProviders(); - }
-
- private void usualBackButton() {
- try {
- boolean is_provider_set_up = new JSONObject(preferences.getString(Provider.KEY, "no provider")) != null ? true : false;
- boolean is_provider_set_up_truly = new JSONObject(preferences.getString(Provider.KEY, "no provider")).length() != 0 ? true : false;
- if(!is_provider_set_up || !is_provider_set_up_truly) {
- askDashboardToQuitApp();
- } else {
- setResult(RESULT_OK);
- }
- } catch (JSONException e) {
- askDashboardToQuitApp();
- super.onBackPressed();
- e.printStackTrace();
- }
- super.onBackPressed();
- }
- private void askDashboardToQuitApp() {
- Intent ask_quit = new Intent();
- ask_quit.putExtra(Dashboard.ACTION_QUIT, Dashboard.ACTION_QUIT);
- setResult(RESULT_CANCELED, ask_quit);
- }
-
- private ProviderItem getProvider(String name) {
- Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
- while(providers_iterator.hasNext()) {
- ProviderItem provider = providers_iterator.next();
- if(provider.name().equalsIgnoreCase(name)) {
- return provider;
- }
- }
- return null;
- }
-
- private String getId(String provider_main_url_string) { + } + + private void usualBackButton() { + try { + boolean is_provider_set_up = new JSONObject(preferences.getString(Provider.KEY, "no provider")) != null ? true : false; + boolean is_provider_set_up_truly = new JSONObject(preferences.getString(Provider.KEY, "no provider")).length() != 0 ? true : false; + if(!is_provider_set_up || !is_provider_set_up_truly) { + askDashboardToQuitApp(); + } else { + setResult(RESULT_OK); + } + } catch (JSONException e) { + askDashboardToQuitApp(); + super.onBackPressed(); + e.printStackTrace(); + } + super.onBackPressed(); + } + private void askDashboardToQuitApp() { + Intent ask_quit = new Intent(); + ask_quit.putExtra(Dashboard.ACTION_QUIT, Dashboard.ACTION_QUIT); + setResult(RESULT_CANCELED, ask_quit); + } + + private ProviderItem getProvider(String name) { + Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator(); + while(providers_iterator.hasNext()) { + ProviderItem provider = providers_iterator.next(); + if(provider.name().equalsIgnoreCase(name)) { + return provider; + } + } + return null; + } + + private void startProgressBar() { + mProgressBar.setVisibility(ProgressBar.VISIBLE); + progressbar_description.setVisibility(TextView.VISIBLE); + mProgressBar.setProgress(0); + mProgressBar.setMax(3); + } + + private void startProgressBar(int list_item_index) { + startProgressBar(); + int measured_height = listItemHeight(list_item_index); + mProgressBar.setTranslationY(measured_height); + progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight()); + } + + private int getProviderIndex(String id) { + int index = 0; + Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator(); + while(providers_iterator.hasNext()) { + ProviderItem provider = providers_iterator.next(); + if(provider.name().equalsIgnoreCase(id)) { + break; + } else index++; + } + return index; + } + + private int listItemHeight(int list_item_index) { + ListView provider_list_view = (ListView)findViewById(android.R.id.list); + ListAdapter provider_list_adapter = provider_list_view.getAdapter(); + View listItem = provider_list_adapter.getView(0, null, provider_list_view); + listItem.setLayoutParams(new RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.WRAP_CONTENT, + RelativeLayout.LayoutParams.WRAP_CONTENT)); + WindowManager wm = (WindowManager) getApplicationContext() + .getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + int screenWidth = display.getWidth(); // deprecated + + int listViewWidth = screenWidth - 10 - 10; + int widthSpec = MeasureSpec.makeMeasureSpec(listViewWidth, + MeasureSpec.AT_MOST); + listItem.measure(widthSpec, 0); + + return listItem.getMeasuredHeight(); +} + + /** + * Loads providers data from url files contained in the assets folder + * @return true if the files were correctly read + */ + private boolean loadPreseededProviders() { + boolean loaded_preseeded_providers = true; + try { + //TODO Put that folder in a better place (also inside the "for") + String[] urls_filepaths = getAssets().list(ASSETS_URL_FOLDER); + for(String url_filepath : urls_filepaths) { + addNewProviderToList(url_filepath); + } + } catch (IOException e) { + loaded_preseeded_providers = false; + } + + return loaded_preseeded_providers; + } + + private void addNewProviderToList(String url_filepath) { + String provider_main_url = extractProviderMainUrlFromAssetsFile(ASSETS_URL_FOLDER + "/" + url_filepath); + if(getId(provider_main_url).isEmpty()) { + String provider_name = url_filepath.subSequence(0, url_filepath.lastIndexOf(".")).toString(); + ProviderListContent.addItem(new ProviderItem(provider_name, provider_main_url)); + } + } + + private String extractProviderMainUrlFromAssetsFile(String filepath) { + String provider_main_url = ""; + try { + InputStream input_stream_file_contents = getAssets().open(filepath); + byte[] urls_file_bytes = new byte[input_stream_file_contents.available()]; + input_stream_file_contents.read(urls_file_bytes); + String urls_file_content = new String(urls_file_bytes); + JSONObject file_contents = new JSONObject(urls_file_content); + provider_main_url = file_contents.getString(Provider.MAIN_URL); + } catch (JSONException e) { + } catch (IOException e) { + } + return provider_main_url; + } + + private String getId(String provider_main_url) { try { - URL provider_url = new URL(provider_main_url_string); - URL aux_provider_url; + URL provider_url = new URL(provider_main_url); Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator(); while(providers_iterator.hasNext()) { ProviderItem provider = providers_iterator.next(); - aux_provider_url = new URL(provider.providerMainUrl()); + URL aux_provider_url = new URL(provider.providerMainUrl()); if(isSameURL(provider_url, aux_provider_url)) { return provider.name(); } @@ -284,7 +379,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD e.printStackTrace(); } return ""; - }
+ } /** * Checks, whether 2 urls are pointing to the same location. @@ -306,218 +401,109 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD } return true; } -
- private void startProgressBar() {
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- mProgressBar.setProgress(0);
- mProgressBar.setMax(3);
- }
-
- private void startProgressBar(int list_item_index) {
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- progressbar_description.setVisibility(TextView.VISIBLE);
- mProgressBar.setProgress(0);
- mProgressBar.setMax(3);
- int measured_height = listItemHeight(list_item_index);
- mProgressBar.setTranslationY(measured_height);
- progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight());
- }
-
- private int getProviderIndex(String id) {
- int index = 0;
- Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
- while(providers_iterator.hasNext()) {
- ProviderItem provider = providers_iterator.next();
- if(provider.name().equalsIgnoreCase(id)) {
- break;
- } else index++; - }
- return index;
- }
-
- private int listItemHeight(int list_item_index) {
- ListView provider_list_view = (ListView)findViewById(android.R.id.list);
- ListAdapter provider_list_adapter = provider_list_view.getAdapter();
- View listItem = provider_list_adapter.getView(0, null, provider_list_view);
- listItem.setLayoutParams(new RelativeLayout.LayoutParams(
- RelativeLayout.LayoutParams.WRAP_CONTENT,
- RelativeLayout.LayoutParams.WRAP_CONTENT));
- WindowManager wm = (WindowManager) getApplicationContext()
- .getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- int screenWidth = display.getWidth(); // deprecated
-
- int listViewWidth = screenWidth - 10 - 10;
- int widthSpec = MeasureSpec.makeMeasureSpec(listViewWidth,
- MeasureSpec.AT_MOST);
- listItem.measure(widthSpec, 0);
-
- return listItem.getMeasuredHeight();
-}
-
- /** - * Loads providers data from url files contained in the assets folder - * @return true if the files were correctly read - */ - private boolean loadPreseededProviders() { - boolean loaded_preseeded_providers = false; - String[] urls_filepaths = null; - try { - //TODO Put that folder in a better place (also inside the "for") - urls_filepaths = getAssets().list(ASSETS_URL_FOLDER); - String provider_name = ""; - for(String url_filepath : urls_filepaths) { - provider_name = url_filepath.subSequence(0, url_filepath.lastIndexOf(".")).toString(); - String provider_main_url = extractProviderMainUrlFromAssetsFile(ASSETS_URL_FOLDER + "/" + url_filepath); - if(getId(provider_main_url).isEmpty()) - ProviderListContent.addItem(new ProviderItem(provider_name, provider_main_url)); - loaded_preseeded_providers = true;
- } - } catch (IOException e) { - loaded_preseeded_providers = false; + + /** + * Asks ProviderAPI to download an anonymous (anon) VPN certificate. + */ + private void downloadAnonCert() { + Intent provider_API_command = new Intent(this, ProviderAPI.class); + + Bundle parameters = new Bundle(); + + parameters.putString(TYPE_OF_CERTIFICATE, ANON_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); } - return loaded_preseeded_providers; - } + /** + * Open the new provider dialog + */ + public void addAndSelectNewProvider() { + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); + DialogFragment newFragment = NewProviderDialog.newInstance(); + newFragment.show(fragment_transaction, NewProviderDialog.TAG); + } + + /** + * Open the new provider dialog with data + */ + public void addAndSelectNewProvider(String main_url, boolean danger_on) { + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); + + DialogFragment newFragment = NewProviderDialog.newInstance(); + Bundle data = new Bundle(); + data.putString(Provider.MAIN_URL, main_url); + data.putBoolean(ProviderItem.DANGER_ON, danger_on); + newFragment.setArguments(data); + newFragment.show(fragment_transaction, NewProviderDialog.TAG); + } + + /** + * Once selected a provider, this fragment offers the user to log in, + * use it anonymously (if possible) + * or cancel his/her election pressing the back button. + * @param view + * @param reason_to_fail + */ + public void showDownloadFailedDialog(View view, String reason_to_fail) { + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(DownloadFailedDialog.TAG); + + DialogFragment newFragment = DownloadFailedDialog.newInstance(reason_to_fail); + newFragment.show(fragment_transaction, DownloadFailedDialog.TAG); + } + + /** + * Once selected a provider, this fragment offers the user to log in, + * use it anonymously (if possible) + * or cancel his/her election pressing the back button. + */ + private void showProviderDetails() { + if(setting_up_provider) { + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(ProviderDetailFragment.TAG); - private String extractProviderMainUrlFromAssetsFile(String filepath) { - String provider_main_url = ""; - try { - InputStream input_stream_file_contents = getAssets().open(filepath); - byte[] urls_file_bytes = new byte[input_stream_file_contents.available()]; - input_stream_file_contents.read(urls_file_bytes); - String urls_file_content = new String(urls_file_bytes); - JSONObject file_contents = new JSONObject(urls_file_content); - provider_main_url = file_contents.getString(Provider.MAIN_URL); - } catch (JSONException e) { - } catch (IOException e) { + DialogFragment newFragment = ProviderDetailFragment.newInstance(); + newFragment.show(fragment_transaction, ProviderDetailFragment.TAG); + } } - return provider_main_url; - } - - /**
- * Asks ProviderAPI to download an anonymous (anon) VPN certificate.
- */
- private void downloadAnonCert() {
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle parameters = new Bundle();
-
- parameters.putString(TYPE_OF_CERTIFICATE, ANON_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);
- }
-
- /**
- * Open the new provider dialog
- */
- public void addAndSelectNewProvider() {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(NewProviderDialog.TAG);
- if (previous_new_provider_dialog != null) {
- fragment_transaction.remove(previous_new_provider_dialog);
- }
- fragment_transaction.addToBackStack(null);
-
- DialogFragment newFragment = NewProviderDialog.newInstance();
- newFragment.show(fragment_transaction, NewProviderDialog.TAG);
- }
-
- /**
- * Open the new provider dialog with data
- */
- public void addAndSelectNewProvider(String main_url, boolean danger_on) {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(NewProviderDialog.TAG);
- if (previous_new_provider_dialog != null) {
- fragment_transaction.remove(previous_new_provider_dialog);
- }
-
- DialogFragment newFragment = NewProviderDialog.newInstance();
- Bundle data = new Bundle();
- data.putString(Provider.MAIN_URL, main_url);
- data.putBoolean(ProviderItem.DANGER_ON, danger_on);
- newFragment.setArguments(data);
- newFragment.show(fragment_transaction, NewProviderDialog.TAG);
- }
-
- /**
- * Once selected a provider, this fragment offers the user to log in,
- * use it anonymously (if possible)
- * or cancel his/her election pressing the back button.
- * @param view
- * @param reason_to_fail
- */
- public void showDownloadFailedDialog(View view, String reason_to_fail) {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_provider_details_dialog = getFragmentManager().findFragmentByTag(DownloadFailedDialog.TAG);
- if (previous_provider_details_dialog != null) {
- fragment_transaction.remove(previous_provider_details_dialog);
- }
- fragment_transaction.addToBackStack(null);
-
- DialogFragment newFragment = DownloadFailedDialog.newInstance(reason_to_fail);
- newFragment.show(fragment_transaction, DownloadFailedDialog.TAG);
- }
-
- /**
- * Once selected a provider, this fragment offers the user to log in,
- * use it anonymously (if possible)
- * or cancel his/her election pressing the back button.
- * @param view
- */
- public void showProviderDetails(View view) {
- if(setting_up_provider) {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_provider_details_dialog = getFragmentManager().findFragmentByTag(ProviderDetailFragment.TAG);
- if (previous_provider_details_dialog != null) {
- fragment_transaction.remove(previous_provider_details_dialog);
- }
- fragment_transaction.addToBackStack(null);
-
- DialogFragment newFragment = ProviderDetailFragment.newInstance();
- newFragment.show(fragment_transaction, ProviderDetailFragment.TAG);
- }
- }
-
- public void showAndSelectProvider(String provider_main_url, boolean danger_on) {
+ + public void showAndSelectProvider(String provider_main_url, boolean danger_on) { if(getId(provider_main_url).isEmpty()) - showProvider(provider_main_url, danger_on);
+ showProvider(provider_main_url, danger_on); autoSelectProvider(provider_main_url, danger_on); - }
-
- private void showProvider(final String provider_main_url, final boolean danger_on) {
- String provider_name = provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("\\/", "_");
- ProviderItem added_provider = new ProviderItem(provider_name, provider_main_url);
- provider_list_fragment.addItem(added_provider);
- }
-
- private void autoSelectProvider(String provider_main_url, boolean danger_on) {
- preferences.edit().putBoolean(ProviderItem.DANGER_ON, danger_on).commit();
- onItemSelected(getId(provider_main_url));
- }
-
- /**
- * Asks ProviderAPI to download a new provider.json file
- * @param provider_name
- * @param provider_main_url
- * @param danger_on tells if HTTPS client should bypass certificate errors
- */
- public void setUpProvider(String provider_main_url, boolean danger_on) {
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
- Bundle parameters = new Bundle();
- parameters.putString(Provider.MAIN_URL, provider_main_url);
- parameters.putBoolean(ProviderItem.DANGER_ON, danger_on);
-
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
+ } + + private void showProvider(final String provider_main_url, final boolean danger_on) { + String provider_name = provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("\\/", "_"); + ProviderItem added_provider = new ProviderItem(provider_name, provider_main_url); + provider_list_fragment.addItem(added_provider); + } + + private void autoSelectProvider(String provider_main_url, boolean danger_on) { + preferences.edit().putBoolean(ProviderItem.DANGER_ON, danger_on).commit(); + onItemSelected(getId(provider_main_url)); + } + + /** + * Asks ProviderAPI to download a new provider.json file + * @param provider_name + * @param provider_main_url + * @param danger_on tells if HTTPS client should bypass certificate errors + */ + public void setUpProvider(String provider_main_url, boolean danger_on) { + Intent provider_API_command = new Intent(this, ProviderAPI.class); + Bundle parameters = new Bundle(); + parameters.putString(Provider.MAIN_URL, provider_main_url); + parameters.putBoolean(ProviderItem.DANGER_ON, danger_on); + + provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER); + provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - startService(provider_API_command);
+ startService(provider_API_command); setting_up_provider = true; } @@ -534,62 +520,62 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD startService(provider_API_command); } } - @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item){
- switch (item.getItemId()){
+ @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item){ + switch (item.getItemId()){ case R.id.about_leap: startActivityForResult(new Intent(this, AboutActivity.class), 0); return true; - case R.id.new_provider:
- addAndSelectNewProvider();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- public void showAllProviders() {
- provider_list_fragment = (ProviderListFragment) getFragmentManager().findFragmentByTag(ProviderListFragment.TAG);
- if(provider_list_fragment != null)
- provider_list_fragment.unhideAll();
- }
-
- public void cancelSettingUpProvider() {
- provider_list_fragment = (ProviderListFragment) getFragmentManager().findFragmentByTag(ProviderListFragment.TAG);
- if(provider_list_fragment != null && preferences.contains(ProviderItem.DANGER_ON)) {
- provider_list_fragment.removeLastItem();
- }
- preferences.edit().remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit();
- }
-
- @Override
- public void login() {
- Intent ask_login = new Intent();
- ask_login.putExtra(LogInDialog.VERB, LogInDialog.VERB);
- setResult(RESULT_OK, ask_login);
- setting_up_provider = false;
- finish();
- }
-
- @Override
- public void use_anonymously() {
- setResult(RESULT_OK);
- setting_up_provider = false;
- finish();
- }
-
- public class ProviderAPIBroadcastReceiver_Update extends BroadcastReceiver {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- int update = intent.getIntExtra(ProviderAPI.CURRENT_PROGRESS, 0);
- mProgressBar.setProgress(update);
- }
- }
-}
+ case R.id.new_provider: + addAndSelectNewProvider(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + public void showAllProviders() { + provider_list_fragment = (ProviderListFragment) fragment_manager.findFragmentByTag(ProviderListFragment.TAG); + if(provider_list_fragment != null) + provider_list_fragment.unhideAll(); + } + + public void cancelSettingUpProvider() { + provider_list_fragment = (ProviderListFragment) fragment_manager.findFragmentByTag(ProviderListFragment.TAG); + if(provider_list_fragment != null && preferences.contains(ProviderItem.DANGER_ON)) { + provider_list_fragment.removeLastItem(); + } + preferences.edit().remove(Provider.KEY).remove(ProviderItem.DANGER_ON).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit(); + } + + @Override + public void login() { + Intent ask_login = new Intent(); + ask_login.putExtra(LogInDialog.TAG, LogInDialog.TAG); + setResult(RESULT_OK, ask_login); + setting_up_provider = false; + finish(); + } + + @Override + public void use_anonymously() { + setResult(RESULT_OK); + setting_up_provider = false; + finish(); + } + + public class ProviderAPIBroadcastReceiver_Update extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + int update = intent.getIntExtra(ProviderAPI.CURRENT_PROGRESS, 0); + mProgressBar.setProgress(update); + } + } +} diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java index e729d0bc..52645631 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java @@ -14,12 +14,12 @@ * 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.app.IntentService; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; -import android.os.Handler; import android.os.ResultReceiver; import android.util.Base64; import android.util.Log; @@ -43,6 +43,7 @@ import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.CertificateEncodingException; @@ -65,7 +66,6 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import org.apache.http.client.ClientProtocolException; -import org.jboss.security.srp.SRPParameters; import org.json.JSONException; import org.json.JSONObject; import se.leap.bitmaskclient.ProviderListContent.ProviderItem; @@ -83,8 +83,6 @@ import se.leap.bitmaskclient.R; */ public class ProviderAPI extends IntentService { - private Handler mHandler; - final public static String SET_UP_PROVIDER = "setUpProvider", DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON", @@ -95,12 +93,10 @@ public class ProviderAPI extends IntentService { PARAMETERS = "parameters", RESULT_KEY = "result", RECEIVER_KEY = "receiver", - SESSION_ID_COOKIE_KEY = "session_id_cookie_key", - SESSION_ID_KEY = "session_id", ERRORS = "errors", UPDATE_PROGRESSBAR = "update_progressbar", CURRENT_PROGRESS = "current_progress", - TAG = "provider_api_tag" + TAG = ProviderAPI.class.getSimpleName(); ; final public static int @@ -128,6 +124,8 @@ public class ProviderAPI extends IntentService { private static String last_provider_main_url; private static boolean last_danger_on = false; private static boolean setting_up_provider = true; + private static SharedPreferences preferences; + private static String provider_api_url; public static void stop() { setting_up_provider = false; @@ -138,12 +136,13 @@ public class ProviderAPI extends IntentService { Log.v("ClassName", "Provider API"); } - @Override - public void onCreate() { - super.onCreate(); - mHandler = new Handler(); - CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER) ); - } + @Override + public void onCreate() { + super.onCreate(); + + preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); + CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER) ); + } public static String lastProviderMainUrl() { return last_provider_main_url; @@ -162,7 +161,15 @@ public class ProviderAPI extends IntentService { final ResultReceiver receiver = command.getParcelableExtra(RECEIVER_KEY); String action = command.getAction(); Bundle parameters = command.getBundleExtra(PARAMETERS); - setting_up_provider = true; + if(provider_api_url == null) { + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "no provider")); + provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); + } catch (JSONException e) { + } + } + + setting_up_provider = true; if(action.equalsIgnoreCase(SET_UP_PROVIDER)) { Bundle result = setUpProvider(parameters); @@ -174,21 +181,21 @@ public class ProviderAPI extends IntentService { } } } else if (action.equalsIgnoreCase(SRP_REGISTER)) { - Bundle session_id_bundle = registerWithSRP(parameters); + Bundle session_id_bundle = tryToRegister(parameters); if(session_id_bundle.getBoolean(RESULT_KEY)) { receiver.send(SRP_REGISTRATION_SUCCESSFUL, session_id_bundle); } else { receiver.send(SRP_REGISTRATION_FAILED, session_id_bundle); } } else if (action.equalsIgnoreCase(SRP_AUTH)) { - Bundle session_id_bundle = authenticateBySRP(parameters); + Bundle session_id_bundle = tryToAuthenticate(parameters); if(session_id_bundle.getBoolean(RESULT_KEY)) { receiver.send(SRP_AUTHENTICATION_SUCCESSFUL, session_id_bundle); } else { receiver.send(SRP_AUTHENTICATION_FAILED, session_id_bundle); } } else if (action.equalsIgnoreCase(LOG_OUT)) { - if(logOut(parameters)) { + if(logOut()) { receiver.send(LOGOUT_SUCCESSFUL, Bundle.EMPTY); } else { receiver.send(LOGOUT_FAILED, Bundle.EMPTY); @@ -202,108 +209,113 @@ public class ProviderAPI extends IntentService { } } - private Bundle registerWithSRP(Bundle task) { + private Bundle tryToRegister(Bundle task) { Bundle session_id_bundle = new Bundle(); int progress = 0; - String username = (String) task.get(LogInDialog.USERNAME); - String password = (String) task.get(LogInDialog.PASSWORD); - String authentication_server = (String) task.get(Provider.API_URL); + String username = (String) task.get(SessionDialogInterface.USERNAME); + String password = (String) task.get(SessionDialogInterface.PASSWORD); + if(validUserLoginData(username, password)) { - - SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256"); - LeapSRPSession client = new LeapSRPSession(username, password, params); - byte[] salt = ConfigHelper.trim(client.calculateNewSalt()); - // byte[] salted_password = client.calculatePasswordHash(username, password, salt); - /* Calculate password verifier */ - BigInteger password_verifier = client.calculateV(username, password, salt); - /* Send to the server */ - JSONObject result = sendNewUserDataToSRPServer(authentication_server, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16)); - if(result.has(ERRORS)) - session_id_bundle = authFailedNotification(result, username); - else { - session_id_bundle.putString(LogInDialog.USERNAME, username); - session_id_bundle.putString(LogInDialog.PASSWORD, password); - session_id_bundle.putBoolean(RESULT_KEY, true); - } - Log.d(TAG, result.toString()); + session_id_bundle = register(username, password); broadcast_progress(progress++); } else { if(!wellFormedPassword(password)) { session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putString(LogInDialog.USERNAME, username); - session_id_bundle.putBoolean(LogInDialog.PASSWORD_INVALID_LENGTH, true); + session_id_bundle.putString(SessionDialogInterface.USERNAME, username); + session_id_bundle.putBoolean(SessionDialogInterface.PASSWORD_INVALID_LENGTH, true); } if(username.isEmpty()) { session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putBoolean(LogInDialog.USERNAME_MISSING, true); + session_id_bundle.putBoolean(SessionDialogInterface.USERNAME_MISSING, true); } } return session_id_bundle; } + + private Bundle register(String username, String password) { + LeapSRPSession client = new LeapSRPSession(username, password); + byte[] salt = client.calculateNewSalt(); + + BigInteger password_verifier = client.calculateV(username, password, salt); + + JSONObject api_result = sendNewUserDataToSRPServer(provider_api_url, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16)); + + Bundle result = new Bundle(); + if(api_result.has(ERRORS)) + result = authFailedNotification(api_result, username); + else { + result.putString(SessionDialogInterface.USERNAME, username); + result.putString(SessionDialogInterface.PASSWORD, password); + result.putBoolean(RESULT_KEY, true); + } + + return result; + } /** * Starts the authentication process using SRP protocol. * * @param task containing: username, password and api url. * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if authentication was successful. */ - private Bundle authenticateBySRP(Bundle task) { - Bundle session_id_bundle = new Bundle(); + private Bundle tryToAuthenticate(Bundle task) { + Bundle result = new Bundle(); int progress = 0; - String username = (String) task.get(LogInDialog.USERNAME); - String password = (String) task.get(LogInDialog.PASSWORD); - if(validUserLoginData(username, password)) { - - String authentication_server = (String) task.get(Provider.API_URL); - JSONObject authentication_step_result = new JSONObject(); - - SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256"); - LeapSRPSession client = new LeapSRPSession(username, password, params); - byte[] A = client.exponential(); - broadcast_progress(progress++); - authentication_step_result = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); - try { - String salt = authentication_step_result.getString(LeapSRPSession.SALT); - broadcast_progress(progress++); - byte[] Bbytes = new BigInteger(authentication_step_result.getString("B"), 16).toByteArray(); - byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); - if(M1 != null) { - broadcast_progress(progress++); - authentication_step_result = sendM1ToSRPServer(authentication_server, username, M1); - setTokenIfAvailable(authentication_step_result); - byte[] M2 = new BigInteger(authentication_step_result.getString(LeapSRPSession.M2), 16).toByteArray(); - if(client.verify(M2)) { - session_id_bundle.putBoolean(RESULT_KEY, true); - broadcast_progress(progress++); - } else { - authFailedNotification(authentication_step_result, username); - } - } else { - session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putString(LogInDialog.USERNAME, username); - session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message)); - } - } catch (JSONException e) { - session_id_bundle = authFailedNotification(authentication_step_result, username); - e.printStackTrace(); - } + String username = (String) task.get(SessionDialogInterface.USERNAME); + String password = (String) task.get(SessionDialogInterface.PASSWORD); + if(validUserLoginData(username, password)) { + result = authenticate(username, password); broadcast_progress(progress++); } else { if(!wellFormedPassword(password)) { - session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putString(LogInDialog.USERNAME, username); - session_id_bundle.putBoolean(LogInDialog.PASSWORD_INVALID_LENGTH, true); + result.putBoolean(RESULT_KEY, false); + result.putString(SessionDialogInterface.USERNAME, username); + result.putBoolean(SessionDialogInterface.PASSWORD_INVALID_LENGTH, true); } if(username.isEmpty()) { - session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putBoolean(LogInDialog.USERNAME_MISSING, true); + result.putBoolean(RESULT_KEY, false); + result.putBoolean(SessionDialogInterface.USERNAME_MISSING, true); } } - return session_id_bundle; + return result; + } + + + private Bundle authenticate(String username, String password) { + Bundle result = new Bundle(); + + LeapSRPSession client = new LeapSRPSession(username, password); + byte[] A = client.exponential(); + + JSONObject step_result = sendAToSRPServer(provider_api_url, username, new BigInteger(1, A).toString(16)); + try { + String salt = step_result.getString(LeapSRPSession.SALT); + byte[] Bbytes = new BigInteger(step_result.getString("B"), 16).toByteArray(); + byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); + if(M1 != null) { + step_result = sendM1ToSRPServer(provider_api_url, username, M1); + setTokenIfAvailable(step_result); + byte[] M2 = new BigInteger(step_result.getString(LeapSRPSession.M2), 16).toByteArray(); + if(client.verify(M2)) { + result.putBoolean(RESULT_KEY, true); + } else { + authFailedNotification(step_result, username); + } + } else { + result.putBoolean(RESULT_KEY, false); + result.putString(SessionDialogInterface.USERNAME, username); + result.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message)); + } + } catch (JSONException e) { + result = authFailedNotification(step_result, username); + e.printStackTrace(); } + + return result; + } private boolean setTokenIfAvailable(JSONObject authentication_step_result) { try { @@ -325,7 +337,7 @@ public class ProviderAPI extends IntentService { } catch(JSONException e) {} if(!username.isEmpty()) - user_notification_bundle.putString(LogInDialog.USERNAME, username); + user_notification_bundle.putString(SessionDialogInterface.USERNAME, username); user_notification_bundle.putBoolean(RESULT_KEY, false); return user_notification_bundle; @@ -369,13 +381,6 @@ public class ProviderAPI extends IntentService { * @param username * @param clientA First SRP parameter sent * @return response from authentication server - * @throws ClientProtocolException - * @throws IOException - * @throws JSONException - * @throws CertificateException - * @throws NoSuchAlgorithmException - * @throws KeyStoreException - * @throws KeyManagementException */ private JSONObject sendAToSRPServer(String server_url, String username, String clientA) { Map<String, String> parameters = new HashMap<String, String>(); @@ -390,13 +395,6 @@ public class ProviderAPI extends IntentService { * @param username * @param m1 Second SRP parameter sent * @return response from authentication server - * @throws ClientProtocolException - * @throws IOException - * @throws JSONException - * @throws CertificateException - * @throws NoSuchAlgorithmException - * @throws KeyStoreException - * @throws KeyManagementException */ private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) { Map<String, String> parameters = new HashMap<String, String>(); @@ -412,13 +410,6 @@ public class ProviderAPI extends IntentService { * @param salted_password * @param password_verifier * @return response from authentication server - * @throws ClientProtocolException - * @throws IOException - * @throws JSONException - * @throws CertificateException - * @throws NoSuchAlgorithmException - * @throws KeyStoreException - * @throws KeyManagementException */ private JSONObject sendNewUserDataToSRPServer(String server_url, String username, String salt, String password_verifier) { Map<String, String> parameters = new HashMap<String, String>(); @@ -563,12 +554,12 @@ public class ProviderAPI extends IntentService { private Bundle downloadCACert(boolean danger_on) { Bundle result = new Bundle(); try { - JSONObject provider_json = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.KEY, "")); + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); String ca_cert_url = provider_json.getString(Provider.CA_CERT_URI); String cert_string = downloadWithCommercialCA(ca_cert_url, danger_on); if(validCertificate(cert_string) && setting_up_provider) { - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(Provider.CA_CERT, cert_string).commit(); + preferences.edit().putString(Provider.CA_CERT, cert_string).commit(); result.putBoolean(RESULT_KEY, true); } else { String reason_to_fail = pickErrorMessage(cert_string); @@ -584,26 +575,47 @@ public class ProviderAPI extends IntentService { return result; } - public static boolean caCertDownloaded() { return CA_CERT_DOWNLOADED; } - private boolean validCertificate(String cert_string) { - boolean result = false; - if(!ConfigHelper.checkErroneousDownload(cert_string)) { - X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(cert_string); - try { - Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT); - result = true; - } catch (CertificateEncodingException e) { - Log.d(TAG, e.getLocalizedMessage()); - } - } + private boolean validCertificate(String cert_string) { + boolean result = false; + if(!ConfigHelper.checkErroneousDownload(cert_string)) { + X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string); + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + String fingerprint = provider_json.getString(Provider.CA_CERT_FINGERPRINT); + String encoding = fingerprint.split(":")[0]; + String expected_fingerprint = fingerprint.split(":")[1]; + String real_fingerprint = base64toHex(Base64.encodeToString( + MessageDigest.getInstance(encoding).digest(certificate.getEncoded()), + Base64.DEFAULT)); + + result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim()); + } catch (JSONException e) { + result = false; + } catch (NoSuchAlgorithmException e) { + result = false; + } catch (CertificateEncodingException e) { + result = false; + } + } - return result; + return result; + } + + private String base64toHex(String base64_input) { + byte[] byteArray = Base64.decode(base64_input, Base64.DEFAULT); + int readBytes = byteArray.length; + StringBuffer hexData = new StringBuffer(); + int onebyte; + for (int i=0; i < readBytes; i++) { + onebyte = ((0x000000ff & byteArray[i]) | 0xffffff00); + hexData.append(Integer.toHexString(onebyte).substring(6)); } - + return hexData.toString(); + } private Bundle getAndSetProviderJson(String provider_main_url, boolean danger_on) { Bundle result = new Bundle(); @@ -612,12 +624,13 @@ public class ProviderAPI extends IntentService { try { JSONObject provider_json = new JSONObject(provider_dot_json_string); + provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); String name = provider_json.getString(Provider.NAME); //TODO setProviderName(name); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(Provider.KEY, provider_json.toString()).commit(); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putBoolean(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON)).commit(); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putBoolean(EIP.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_REGISTERED)).commit(); + preferences.edit().putString(Provider.KEY, provider_json.toString()).commit(); + preferences.edit().putBoolean(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON)).commit(); + preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_REGISTERED)).commit(); result.putBoolean(RESULT_KEY, true); } catch (JSONException e) { @@ -630,24 +643,18 @@ public class ProviderAPI extends IntentService { return result; } - - - public static boolean providerJsonDownloaded() { - return PROVIDER_JSON_DOWNLOADED; - } - private Bundle getAndSetEipServiceJson() { Bundle result = new Bundle(); String eip_service_json_string = ""; if(setting_up_provider) { try { - JSONObject provider_json = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.KEY, "")); + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); String eip_service_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH; eip_service_json_string = downloadWithProviderCA(eip_service_url, true); JSONObject eip_service_json = new JSONObject(eip_service_json_string); eip_service_json.getInt(Provider.API_RETURN_SERIAL); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.KEY, eip_service_json.toString()).commit(); + preferences.edit().putString(EIP.KEY, eip_service_json.toString()).commit(); result.putBoolean(RESULT_KEY, true); } catch (JSONException e) { @@ -658,10 +665,6 @@ public class ProviderAPI extends IntentService { } return result; } - - public static boolean eipServiceDownloaded() { - return EIP_SERVICE_JSON_DOWNLOADED; - } /** * Interprets the error message as a JSON object and extract the "errors" keyword pair. @@ -748,6 +751,7 @@ public class ProviderAPI extends IntentService { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnknownHostException e) { + e.printStackTrace(); json_file_content = formatErrorMessage(R.string.server_unreachable_message); } catch (IOException e) { // The downloaded certificate doesn't validate our https connection. @@ -766,13 +770,14 @@ public class ProviderAPI extends IntentService { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchElementException e) { + e.printStackTrace(); json_file_content = formatErrorMessage(R.string.server_unreachable_message); } return json_file_content; } private javax.net.ssl.SSLSocketFactory getProviderSSLSocketFactory() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException { - String provider_cert_string = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.CA_CERT,""); + String provider_cert_string = preferences.getString(Provider.CA_CERT,""); java.security.cert.Certificate provider_certificate = ConfigHelper.parseX509CertificateFromString(provider_cert_string); @@ -853,125 +858,115 @@ public class ProviderAPI extends IntentService { * @param task containing api url from which the user will log out * @return true if there were no exceptions */ - private boolean logOut(Bundle task) { - try { - String delete_url = task.getString(Provider.API_URL) + "/logout"; - int progress = 0; + private boolean logOut() { + try { + String delete_url = provider_api_url + "/logout"; + int progress = 0; - HttpsURLConnection urlConnection = (HttpsURLConnection)new URL(delete_url).openConnection(); - urlConnection.setRequestMethod("DELETE"); - urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); + HttpsURLConnection urlConnection = (HttpsURLConnection)new URL(delete_url).openConnection(); + urlConnection.setRequestMethod("DELETE"); + urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); - int responseCode = urlConnection.getResponseCode(); - broadcast_progress(progress++); - LeapSRPSession.setToken(""); - Log.d(TAG, Integer.toString(responseCode)); - } catch (ClientProtocolException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } catch (IndexOutOfBoundsException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } catch (KeyManagementException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (KeyStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return true; + int responseCode = urlConnection.getResponseCode(); + broadcast_progress(progress++); + LeapSRPSession.setToken(""); + Log.d(TAG, Integer.toString(responseCode)); + } catch (ClientProtocolException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (IndexOutOfBoundsException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (KeyManagementException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } + return true; + } private boolean updateVpnCertificate() { getNewCert(); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putInt(EIP.PARSED_SERIAL, 0).commit(); Intent updateEIP = new Intent(getApplicationContext(), EIP.class); updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE); startService(updateEIP); return true; } - /** - * Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate. - * - * @return true if certificate was downloaded correctly, false if provider.json or danger_on flag are not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error. - */ - private boolean getNewCert() { - - try { - JSONObject provider_json = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.KEY, "")); + + /** + * Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate. + * + * @return true if certificate was downloaded correctly, false if provider.json or danger_on flag are not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error. + */ + private boolean getNewCert() { + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - String provider_main_url = provider_json.getString(Provider.API_URL); - URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.CERTIFICATE); + String provider_main_url = provider_json.getString(Provider.API_URL); + URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.CERTIFICATE); - boolean danger_on = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getBoolean(ProviderItem.DANGER_ON, false); + boolean danger_on = preferences.getBoolean(ProviderItem.DANGER_ON, false); - String cert_string = downloadWithProviderCA(new_cert_string_url.toString(), danger_on); - if(!cert_string.isEmpty()) { - if(ConfigHelper.checkErroneousDownload(cert_string)) { - String reason_to_fail = provider_json.getString(ERRORS); - //result.putString(ConfigHelper.ERRORS_KEY, reason_to_fail); - //result.putBoolean(ConfigHelper.RESULT_KEY, false); - return false; - } else { - - // API returns concatenated cert & key. Split them for OpenVPN options - String certificateString = null, keyString = null; - String[] certAndKey = cert_string.split("(?<=-\n)"); - for (int i=0; i < certAndKey.length-1; i++){ - if ( certAndKey[i].contains("KEY") ) { - keyString = certAndKey[i++] + certAndKey[i]; - } - else if ( certAndKey[i].contains("CERTIFICATE") ) { - certificateString = certAndKey[i++] + certAndKey[i]; - } - } - try { - RSAPrivateKey keyCert = ConfigHelper.parseRsaKeyFromString(keyString); - keyString = Base64.encodeToString( keyCert.getEncoded(), Base64.DEFAULT ); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit(); - - X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(certificateString); - certificateString = Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit(); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit(); - - return true; - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } - } - } else { - return false; - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } /*catch (URISyntaxException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - }*/ + String cert_string = downloadWithProviderCA(new_cert_string_url.toString(), danger_on); + + if(cert_string.isEmpty() || ConfigHelper.checkErroneousDownload(cert_string)) + return false; + else + return loadCertificate(cert_string); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + } + + private boolean loadCertificate(String cert_string) { + try { + // API returns concatenated cert & key. Split them for OpenVPN options + String certificateString = null, keyString = null; + String[] certAndKey = cert_string.split("(?<=-\n)"); + for (int i=0; i < certAndKey.length-1; i++){ + if ( certAndKey[i].contains("KEY") ) { + keyString = certAndKey[i++] + certAndKey[i]; + } + else if ( certAndKey[i].contains("CERTIFICATE") ) { + certificateString = certAndKey[i++] + certAndKey[i]; + } + } + RSAPrivateKey keyCert = ConfigHelper.parseRsaKeyFromString(keyString); + keyString = Base64.encodeToString( keyCert.getEncoded(), Base64.DEFAULT ); + preferences.edit().putString(EIP.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit(); + + X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(certificateString); + certificateString = Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT); + preferences.edit().putString(EIP.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit(); + preferences.edit().putString(EIP.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit(); + return true; + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; } + } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 423293b6..d5081b8d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,8 +17,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="se.leap.bitmaskclient" - android:versionCode="93" - android:versionName="0.7.0" > + android:versionCode="102" + android:versionName="0.8.0" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> @@ -36,6 +36,14 @@ android:label="@string/app" > <service + android:name="se.leap.bitmaskclient.VoidVpnService" + android:permission="android.permission.BIND_VPN_SERVICE"> + <intent-filter> + <action android:name="android.net.VpnService" /> + </intent-filter> + </service> + + <service android:name="de.blinkt.openvpn.core.OpenVPNService" android:permission="android.permission.BIND_VPN_SERVICE"> <intent-filter> @@ -53,6 +61,8 @@ </intent-filter> </receiver> + <activity + android:name="se.leap.bitmaskclient.VoidVpnLauncher" /> <activity android:theme="@android:style/Theme.DeviceDefault.Light.Dialog" android:name="de.blinkt.openvpn.activities.DisconnectVPN" /> diff --git a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java index a424a489..d7f3e110 100644 --- a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java +++ b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn; import se.leap.bitmaskclient.R; @@ -113,27 +118,25 @@ public class LaunchVPN extends Activity { } } - @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - if(requestCode==START_VPN_PROFILE) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - boolean showlogwindow = prefs.getBoolean("showlogwindow", true); - - if(!mhideLog && showlogwindow) - showLogWindow(); - new startOpenVpnThread().start(); - } else if (resultCode == Activity.RESULT_CANCELED) { - // User does not want us to start, so we just vanish - VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled, - ConnectionStatus.LEVEL_NOTCONNECTED); - - finish(); - } + super.onActivityResult(requestCode, resultCode, data); + + if(requestCode==START_VPN_PROFILE) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + boolean showLogWindow = prefs.getBoolean("showlogwindow", true); + + if(!mhideLog && showLogWindow) + showLogWindow(); + new startOpenVpnThread().start(); + } else if (resultCode == Activity.RESULT_CANCELED) { + // User does not want us to start, so we just vanish + VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled, + ConnectionStatus.LEVEL_NOTCONNECTED); + + finish(); + } } - void showLogWindow() { Intent startLW = new Intent(getBaseContext(),LogWindow.class); diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index 6fec5f46..65214c4f 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn; import se.leap.bitmaskclient.R; @@ -40,6 +45,7 @@ import java.util.Collection; import java.util.Locale; import java.util.UUID; import java.util.Vector; +import java.util.concurrent.Future; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; @@ -166,6 +172,12 @@ public class VpnProfile implements Serializable { return VpnProfile.MININONPIEVPN; } + public static String[] replacePieWithNoPie(String[] mArgv) + { + mArgv[0] = mArgv[0].replace(MINIPIEVPN, MININONPIEVPN); + return mArgv; + } + public static String openVpnEscape(String unescaped) { if (unescaped == null) return null; @@ -174,7 +186,8 @@ public class VpnProfile implements Serializable { escapedString = escapedString.replace("\n", "\\n"); if (escapedString.equals(unescaped) && !escapedString.contains(" ") && - !escapedString.contains("#") && !escapedString.contains(";")) + !escapedString.contains("#") && !escapedString.contains(";") + && !escapedString.equals("")) return unescaped; else return '"' + escapedString + '"'; @@ -579,21 +592,15 @@ public class VpnProfile implements Serializable { - public Intent prepareIntent(Context context) { - String prefix = context.getPackageName(); + public Intent prepareStartService(Context context) { + Intent intent = getStartServiceIntent(context); - Intent intent = new Intent(context, OpenVPNService.class); if (mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) { if (getKeyStoreCertificates(context) == null) return null; } - intent.putExtra(prefix + ".ARGV", buildOpenvpnArgv(context.getCacheDir())); - intent.putExtra(prefix + ".profileUUID", mUuid.toString()); - - ApplicationInfo info = context.getApplicationInfo(); - intent.putExtra(prefix + ".nativelib", info.nativeLibraryDir); try { FileWriter cfg = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE); @@ -607,6 +614,18 @@ public class VpnProfile implements Serializable { return intent; } + public Intent getStartServiceIntent(Context context) { + String prefix = context.getPackageName(); + + Intent intent = new Intent(context, OpenVPNService.class); + intent.putExtra(prefix + ".ARGV", buildOpenvpnArgv(context.getCacheDir())); + intent.putExtra(prefix + ".profileUUID", mUuid.toString()); + + ApplicationInfo info = context.getApplicationInfo(); + intent.putExtra(prefix + ".nativelib", info.nativeLibraryDir); + return intent; + } + public String[] getKeyStoreCertificates(Context context) { return getKeyStoreCertificates(context, 5); } @@ -635,6 +654,21 @@ public class VpnProfile implements Serializable { return false; } + public void checkForRestart(final Context context) { + /* This method is called when OpenVPNService is restarted */ + + if ((mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) + && mPrivateKey==null) { + new Thread( new Runnable() { + @Override + public void run() { + getKeyStoreCertificates(context); + + } + }).start(); + } + } + class NoCertReturnedException extends Exception { public NoCertReturnedException (String msg) { @@ -841,21 +875,23 @@ public class VpnProfile implements Serializable { return false; } - public int needUserPWInput() { + public int needUserPWInput(boolean ignoreTransient) { if ((mAuthenticationType == TYPE_PKCS12 || mAuthenticationType == TYPE_USERPASS_PKCS12) && (mPKCS12Password == null || mPKCS12Password.equals(""))) { - if (mTransientPCKS12PW == null) + if (ignoreTransient || mTransientPCKS12PW == null) return R.string.pkcs12_file_encryption_key; } if (mAuthenticationType == TYPE_CERTIFICATES || mAuthenticationType == TYPE_USERPASS_CERTIFICATES) { if (requireTLSKeyPassword() && TextUtils.isEmpty(mKeyPassword)) - if (mTransientPCKS12PW == null) { + if (ignoreTransient || mTransientPCKS12PW == null) { return R.string.private_key_password; } } - if (isUserPWAuth() && !(!TextUtils.isEmpty(mUsername) && (!TextUtils.isEmpty(mPassword) || mTransientPW != null))) { + if (isUserPWAuth() && + (TextUtils.isEmpty(mUsername) || + (TextUtils.isEmpty(mPassword) && (mTransientPW == null || ignoreTransient)))) { return R.string.password; } return 0; diff --git a/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java b/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java index 5910173a..e6b73a48 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.activities; import android.app.Activity; diff --git a/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java b/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java index 7ed09dd2..5e4f9517 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.activities; import android.app.Activity; diff --git a/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java b/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java index 960e7d11..ac9a8ccb 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java +++ b/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import java.util.Locale; diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java index 9c3621e0..0d8230b7 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import java.io.BufferedReader; @@ -553,8 +558,13 @@ public class ConfigParser { noauthtypeset=false; } + Vector<String> cryptoapicert = getOption("cryptoapicert",1,1); + if(cryptoapicert!=null) { + np.mAuthenticationType = VpnProfile.TYPE_KEYSTORE; + noauthtypeset=false; + } - Vector<String> compatnames = getOption("compat-names",1,2); + Vector<String> compatnames = getOption("compat-names",1,2); Vector<String> nonameremapping = getOption("no-name-remapping",1,1); Vector<String> tlsremote = getOption("tls-remote",1,1); if(tlsremote!=null){ diff --git a/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java b/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java index 0126d08e..0d75ae51 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java +++ b/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.content.BroadcastReceiver; diff --git a/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java b/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java index 485e5369..83e760ca 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.app.Application; diff --git a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java index a2c4796d..6d7ffdf2 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java +++ b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import java.security.InvalidKeyException; diff --git a/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java b/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java index 8c6cb1f5..35f46513 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java +++ b/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.os.Build; diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java index a5a3e9f4..e90c16d1 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; public interface OpenVPNManagement { diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java index 743e7cc5..ada065ba 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.Manifest.permission; @@ -19,6 +24,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.preference.PreferenceManager; import android.text.TextUtils; +import android.util.Log; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -309,26 +315,32 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac return START_REDELIVER_INTENT; } - String UUID = "UUID"; + /* The intent is null when the service has been restarted */ if (intent == null) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - android.util.Log.d("bitmaskclient", "UUID is " + prefs.getString(UUID, "")); - mProfile = ProfileManager.get(this, prefs.getString(UUID, "")); - android.util.Log.d("bitmaskclient", "mProfile is null? " + (mProfile == null)); - if(mProfile != null) - intent = mProfile.prepareIntent(getBaseContext()); - else + mProfile = ProfileManager.getLastConnectedProfile(this, false); + + /* Got no profile, just stop */ + if (mProfile==null) { + Log.d("OpenVPN", "Got no last connected profile on null intent. Stopping"); + stopSelf(startId); return START_NOT_STICKY; - } - if(mProfile != null) - android.util.Log.d("bitmaskclient", "mProfile != null"); + } + /* Do the asynchronous keychain certificate stuff */ + mProfile.checkForRestart(this); + + /* Recreate the intent */ + intent = mProfile.getStartServiceIntent(this); + + } else { + String profileUUID = intent.getStringExtra(getPackageName() + ".profileUUID"); + mProfile = ProfileManager.get(this, profileUUID); + } + + // Extract information from the intent. String prefix = getPackageName(); String[] argv = intent.getStringArrayExtra(prefix + ".ARGV"); - String nativelibdir = intent.getStringExtra(prefix + ".nativelib"); - String profileUUID = intent.getStringExtra(prefix + ".profileUUID"); - - mProfile = ProfileManager.get(this, profileUUID); + String nativeLibraryDirectory = intent.getStringExtra(prefix + ".nativelib"); String startTitle = getString(R.string.start_vpn_title, mProfile.mName); String startTicker = getString(R.string.start_vpn_ticker, mProfile.mName); @@ -361,13 +373,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac // Start a new session by creating a new thread. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - + mOvpn3 = prefs.getBoolean("ovpn3", false); if (!"ovpn3".equals(BuildConfig.FLAVOR)) mOvpn3 = false; - prefs.edit().putString(UUID, profileUUID).commit(); // Open the Management Interface if (!mOvpn3) { @@ -395,7 +406,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac } else { HashMap<String, String> env = new HashMap<String, String>(); - processThread = new OpenVPNThread(this, argv, env, nativelibdir); + processThread = new OpenVPNThread(this, argv, env, nativeLibraryDirectory); } synchronized (mProcessLock) { @@ -409,11 +420,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac ProfileManager.setConnectedVpnProfile(this, mProfile); + /* TODO: At the moment we have no way to handle asynchronous PW input + * Fixing will also allow to handle challenge/responsee authentication */ + if (mProfile.needUserPWInput(true) != 0) + return START_NOT_STICKY; - if (mProfile.mPersistTun) - return START_STICKY; - else - return START_NOT_STICKY; + return START_STICKY; } private OpenVPNManagement instantiateOpenVPN3Core() { @@ -517,7 +529,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if ((Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !release.startsWith("4.4.3") && !release.startsWith("4.4.4") && !release.startsWith("4.4.5") && !release.startsWith("4.4.6")) && mMtu < 1280) { - VpnStatus.logInfo(String.format("Forcing MTU to 1280 instead of %d to workaround Android Bug #70916", mMtu)); + VpnStatus.logInfo(String.format(Locale.US, "Forcing MTU to 1280 instead of %d to workaround Android Bug #70916", mMtu)); builder.setMtu(1280); } else { builder.setMtu(mMtu); @@ -690,7 +702,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.logWarning(R.string.ip_not_cidr, local, netmask, mode); } } - if (("p2p".equals(mode)) && mLocalIP.len < 32 || "net30".equals("net30") && mLocalIP.len < 30) { + if (("p2p".equals(mode) && mLocalIP.len < 32) || ("net30".equals(mode) && mLocalIP.len < 30)) { VpnStatus.logWarning(R.string.ip_looks_like_subnet, local, netmask, mode); } @@ -738,7 +750,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac String ticker = msg; showNotification(msg, ticker, lowpriority , 0, level); return; - } else { + } else { mDisplayBytecount = false; } diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java index 5fa2ab9e..e3c60854 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.util.Log; @@ -25,6 +30,7 @@ import de.blinkt.openvpn.core.VpnStatus.LogItem; public class OpenVPNThread implements Runnable { private static final String DUMP_PATH_STRING = "Dump path: "; + private static final String BROKEN_PIE_SUPPORT = "/data/data/de.blinkt.openvpn/cache/pievpn[1]: syntax error:"; private static final String TAG = "OpenVPN"; public static final int M_FATAL = (1 << 4); public static final int M_NONFATAL = (1 << 5); @@ -36,8 +42,9 @@ public class OpenVPNThread implements Runnable { private OpenVPNService mService; private String mDumpPath; private Map<String, String> mProcessEnv; + private boolean mBrokenPie=false; - public OpenVPNThread(OpenVPNService service,String[] argv, Map<String,String> processEnv, String nativelibdir) + public OpenVPNThread(OpenVPNService service,String[] argv, Map<String,String> processEnv, String nativelibdir) { mArgv = argv; mNativeDir = nativelibdir; @@ -68,8 +75,22 @@ public class OpenVPNThread implements Runnable { } catch (InterruptedException ie) { VpnStatus.logError("InterruptedException: " + ie.getLocalizedMessage()); } - if( exitvalue != 0) - VpnStatus.logError("Process exited with exit value " + exitvalue); + if( exitvalue != 0) { + VpnStatus.logError("Process exited with exit value " + exitvalue); + if (mBrokenPie) { + String[] noPieArgv = VpnProfile.replacePieWithNoPie(mArgv); + + // We are already noPIE, nothing to gain + if (!noPieArgv.equals(mArgv)) { + mArgv = noPieArgv; + VpnStatus.logInfo("PIE Version could not be executed. Trying no PIE version"); + run(); + return; + } + + } + + } VpnStatus.updateStateString("NOPROCESS", "No process running.", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); if(mDumpPath!=null) { @@ -123,6 +144,9 @@ public class OpenVPNThread implements Runnable { if (logline.startsWith(DUMP_PATH_STRING)) mDumpPath = logline.substring(DUMP_PATH_STRING.length()); + + if (logline.startsWith(BROKEN_PIE_SUPPORT)) + mBrokenPie = true; // 1380308330.240114 18000002 Send to HTTP proxy: 'X-Online-Host: bla.blabla.com' diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java index e200f210..37094a1b 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.content.Context; diff --git a/app/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java b/app/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java index dd420371..bca0a4ab 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java +++ b/app/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core;/* * This software is provided 'as-is', without any express or implied * warranty. In no event will Google be held liable for any damages diff --git a/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java b/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java index 4cfbcc8e..2a26152e 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import java.io.FileNotFoundException; @@ -23,7 +28,7 @@ public class ProfileManager { - private static final String ONBOOTPROFILE = "onBootProfile"; + private static final String LAST_CONNECTED_PROFILE = "lastConnectedProfile"; @@ -65,7 +70,7 @@ public class ProfileManager { public static void setConntectedVpnProfileDisconnected(Context c) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); Editor prefsedit = prefs.edit(); - prefsedit.putString(ONBOOTPROFILE, null); + prefsedit.putString(LAST_CONNECTED_PROFILE, null); prefsedit.apply(); } @@ -74,21 +79,23 @@ public class ProfileManager { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); Editor prefsedit = prefs.edit(); - prefsedit.putString(ONBOOTPROFILE, connectedrofile.getUUIDString()); + prefsedit.putString(LAST_CONNECTED_PROFILE, connectedrofile.getUUIDString()); prefsedit.apply(); mLastConnectedVpn=connectedrofile; } - public static VpnProfile getOnBootProfile(Context c) { + public static VpnProfile getLastConnectedProfile(Context c, boolean onBoot) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); boolean useStartOnBoot = prefs.getBoolean("restartvpnonboot", false); + if (onBoot && !useStartOnBoot) + return null; - String mBootProfileUUID = prefs.getString(ONBOOTPROFILE,null); - if(useStartOnBoot && mBootProfileUUID!=null) - return get(c, mBootProfileUUID); + String lastConnectedProfile = prefs.getString(LAST_CONNECTED_PROFILE, null); + if(lastConnectedProfile!=null) + return get(c, lastConnectedProfile); else return null; } diff --git a/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java b/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java index 47d88279..cf953863 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import java.net.InetSocketAddress; diff --git a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java index 57a94ee7..40f9742b 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.content.Context; @@ -70,7 +75,7 @@ public class VPNLaunchHelper { VpnStatus.logInfo(R.string.building_configration); - Intent startVPN = startprofile.prepareIntent(context); + Intent startVPN = startprofile.prepareStartService(context); if(startVPN!=null) context.startService(startVPN); diff --git a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java index c19daeb0..25558f13 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.annotation.SuppressLint; diff --git a/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java b/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java index 35e53c08..ff383e0f 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java +++ b/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.content.Context; diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java index ca850533..77fc21e6 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.fragments; import se.leap.bitmaskclient.R; diff --git a/app/src/main/java/de/blinkt/openvpn/views/SeekBarTicks.java b/app/src/main/java/de/blinkt/openvpn/views/SeekBarTicks.java index 88e8e164..e25c2859 100644 --- a/app/src/main/java/de/blinkt/openvpn/views/SeekBarTicks.java +++ b/app/src/main/java/de/blinkt/openvpn/views/SeekBarTicks.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.views; import android.content.Context; 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"; + } +} diff --git a/app/src/main/res/layout-sw600dp-port/log_fragment.xml b/app/src/main/res/layout-sw600dp-port/log_fragment.xml index ddf0506b..2f5c774d 100644 --- a/app/src/main/res/layout-sw600dp-port/log_fragment.xml +++ b/app/src/main/res/layout-sw600dp-port/log_fragment.xml @@ -1,4 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" diff --git a/app/src/main/res/layout-sw600dp/log_fragment.xml b/app/src/main/res/layout-sw600dp/log_fragment.xml index c4e1355c..b8997982 100644 --- a/app/src/main/res/layout-sw600dp/log_fragment.xml +++ b/app/src/main/res/layout-sw600dp/log_fragment.xml @@ -1,4 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" diff --git a/app/src/main/res/layout/log_fragment.xml b/app/src/main/res/layout/log_fragment.xml index 0b428070..2cc4759e 100644 --- a/app/src/main/res/layout/log_fragment.xml +++ b/app/src/main/res/layout/log_fragment.xml @@ -1,4 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" diff --git a/app/src/main/res/layout/log_silders.xml b/app/src/main/res/layout/log_silders.xml index 0ecb5daa..3fcbd85a 100644 --- a/app/src/main/res/layout/log_silders.xml +++ b/app/src/main/res/layout/log_silders.xml @@ -1,6 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> + <LinearLayout xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" diff --git a/app/src/main/res/layout/log_window.xml b/app/src/main/res/layout/log_window.xml index 56c3e349..d7576ca3 100644 --- a/app/src/main/res/layout/log_window.xml +++ b/app/src/main/res/layout/log_window.xml @@ -1,3 +1,8 @@ +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> + <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" diff --git a/app/src/main/res/layout/vpnstatus.xml b/app/src/main/res/layout/vpnstatus.xml index eb7c53ee..2fd65b4c 100644 --- a/app/src/main/res/layout/vpnstatus.xml +++ b/app/src/main/res/layout/vpnstatus.xml @@ -1,4 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> + <merge xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android"> diff --git a/app/src/main/res/menu/logmenu.xml b/app/src/main/res/menu/logmenu.xml index c8c9e815..a1d2a7b5 100644 --- a/app/src/main/res/menu/logmenu.xml +++ b/app/src/main/res/menu/logmenu.xml @@ -1,4 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> + <menu xmlns:android="http://schemas.android.com/apk/res/android"> diff --git a/app/src/main/res/values-ca/strings-icsopenvpn.xml b/app/src/main/res/values-ca/strings-icsopenvpn.xml index 7e74c198..b18766ca 100755 --- a/app/src/main/res/values-ca/strings-icsopenvpn.xml +++ b/app/src/main/res/values-ca/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> diff --git a/app/src/main/res/values-cs/strings-icsopenvpn.xml b/app/src/main/res/values-cs/strings-icsopenvpn.xml index b13bfcdd..6ae5a3f0 100755 --- a/app/src/main/res/values-cs/strings-icsopenvpn.xml +++ b/app/src/main/res/values-cs/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> @@ -319,4 +323,9 @@ <string name="files_missing_hint">NÄ›které soubory nemohly být nalezeny. ProsÃm vyber profil, který chceÅ¡ importovat:</string> <string name="openvpn_is_no_free_vpn">Pro použÃvánà této aplikace je potÅ™eba VPN poskytovatel/brána, která podporuje OpenVPN (Äasto je to zamÄ›stnavatel). Pro vÃce informacà a návod na nastavenà OpenVPN serveru navÅ¡tiv http://community.openvpn.net/</string> <string name="import_log">Import logu:</string> + <string name="ip_looks_like_subnet">Vpn topologie \"%3$s\" soecifikována, ale ifconfig %1$s %2$s vypadá spÃÅ¡e jako IP adresa se sÃÅ¥ovou maskou. PÅ™edpokládám \"podsÃÅ¥ovou\" topologii.</string> + <string name="mssfix_invalid_value">mssfix hodnota musà být celé ÄÃslo mezi 0 a 9000</string> + <string name="mssfix_value_dialog">Oznámit TCP sezenÃm běžÃcÃm skrze tunel, že majà limitovat velikost odesÃlaných paketů tak, aby poté, co je OpenVPN zabalÃ, byla výsledná velikost UDP paketu, které OpenVPN posÃlá menÅ¡Ã než tento poÄet bytů. (výchozà je 1450)</string> + <string name="mssfix_checkbox">PÅ™epsat hodnotu MSS pro TCP obsah</string> + <string name="mssfix_dialogtitle">Nastavit MSS pro TCP obsah</string> </resources> diff --git a/app/src/main/res/values-de/strings-icsopenvpn.xml b/app/src/main/res/values-de/strings-icsopenvpn.xml index 5ece9326..cebb9646 100755 --- a/app/src/main/res/values-de/strings-icsopenvpn.xml +++ b/app/src/main/res/values-de/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> @@ -319,4 +323,9 @@ <string name="files_missing_hint">Einige Dateien konnten nicht gefunden werden. Bitte wählen Sie diese manuell aus:</string> <string name="openvpn_is_no_free_vpn">Um diese Anwendung nutzen zu können brauchen Sie einen OpenVPN fähigen Server. Diese werden häufig von Ihrer Firma oder Universität bereitgestellt. Besuchen Sie http://community.openvpn.net/ um mehr über OpenVPN zu erfahren und wie Sie Ihren eigenen Server aufsetzen können.</string> <string name="import_log">Import-Protokoll:</string> + <string name="ip_looks_like_subnet">VPN-Topologie \"%3$s\" wurde angegeben, die Interface Konfiguration \'ifconfig %1$s %2$s sieht wie eine IP-Adresse mit einer Netzwerkmaske. Topologie \"subnet\" wird angenommen.</string> + <string name="mssfix_invalid_value">mssfix Wert muss eine Zahl zwischen 0 und 9000 sein</string> + <string name="mssfix_value_dialog">Ändere TCP-Verbindungen, die über den Tunnel laufen, so dass die resultierende UDP-Paketgröße nach der Enkapsulierung durch OpenVPN auf diesen Wert beschränkt bleibt. (Standardwert ist 1450)</string> + <string name="mssfix_checkbox">Ãœberschreiben des MSS-Wert von TCP-Nutzlast</string> + <string name="mssfix_dialogtitle">Setze MSS von TCP-Nutzlast</string> </resources> diff --git a/app/src/main/res/values-es/strings-icsopenvpn.xml b/app/src/main/res/values-es/strings-icsopenvpn.xml index 399392bf..92995c6f 100755 --- a/app/src/main/res/values-es/strings-icsopenvpn.xml +++ b/app/src/main/res/values-es/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> @@ -319,4 +323,8 @@ <string name="files_missing_hint">Algunos archivos no se pudo encontrar. Por favor, seleccione los archivos que desea importar el perfil:</string> <string name="openvpn_is_no_free_vpn">Para utilizar esta aplicación usted necesita un proveedor de servicio VPN / es un apoyo OpenVPN (a menudo proporcionados por su empleador). Echa un vistazo a http://community.openvpn.net/ para más información sobre OpenVPN y cómo configurar su propio servidor OpenVPN.</string> <string name="import_log">Importar registros:</string> + <string name="ip_looks_like_subnet">TopologÃa de VPN \"%3$s\" especificado pero ifconfig %1$s %2$s se parece más a una dirección IP con una máscara de red. Asumiendo una topologÃa de \"subred\".</string> + <string name="mssfix_invalid_value">El valor de mssfix debe ser un número entero entre 0 y 9000</string> + <string name="mssfix_checkbox">Reemplazar el valor MSS de la carga TCP</string> + <string name="mssfix_dialogtitle">Establecer MSS de la carga TCP</string> </resources> diff --git a/app/src/main/res/values-et/strings-icsopenvpn.xml b/app/src/main/res/values-et/strings-icsopenvpn.xml index 478483ec..7761726e 100755 --- a/app/src/main/res/values-et/strings-icsopenvpn.xml +++ b/app/src/main/res/values-et/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> @@ -319,4 +323,9 @@ <string name="files_missing_hint">Mõningaid faile ei leitud. Palun valige importimiseks profiili failid:</string> <string name="openvpn_is_no_free_vpn">Selle rakenduse kasutamiseks vajate OpenVPN toega VPN teenusepakkujat/VPN lüüsi (mida sageli pakub teie tööandja). Lisainfo saamiseks OpenVPN kohta ja oma isikliku OpenVPN serveri seadistamise kohta tutvuge veebilehega http://community.openvpn.net/ .</string> <string name="import_log">Impordi logi:</string> + <string name="ip_looks_like_subnet">Valitud on \"%3$s\" Vpn topoloogia, kuid ifconfig %1$s %2$s sarnaneb rohkem maskiga IP aadressile. Määratakse \"alamvõrgu\" topoloogia.</string> + <string name="mssfix_invalid_value">mssfix väärtus peab olema täisarv vahemikus 0 kuni 9000</string> + <string name="mssfix_value_dialog">Informeeri tunneldatud TCP sessioone et nad piiraksid saadetavate pakettide suuruse nii, et peale OpenVPN kapseldatud paketi partnerile saatmist ei oleks saadud UDP pakett suurem kui ette antud baitide arv. (vaikeväärtus on 1450)</string> + <string name="mssfix_checkbox">Ignoreeri TCP lasti MSS väärtust</string> + <string name="mssfix_dialogtitle">Sea TCP lasti MSS väärtus</string> </resources> diff --git a/app/src/main/res/values-fr/strings-icsopenvpn.xml b/app/src/main/res/values-fr/strings-icsopenvpn.xml index a26ce445..15bc7aa4 100755 --- a/app/src/main/res/values-fr/strings-icsopenvpn.xml +++ b/app/src/main/res/values-fr/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> @@ -216,7 +220,6 @@ Sur certaines images, cette notification joue un son.\nAndroid à introduit ces <string name="vpn_import_hint">"Utilisez l\'icône <img src=\"ic_menu_archive\"/> pour importer un fichier profil (.opvpn ou .conf) de votre carte SD."</string> <string name="faq_hint">"Veillez également à consulter la FAQ. Il s\'y trouve un guide de démarrage rapide."</string> <string name="faq_routing_title">"Redirections / Configuration de l\'interface"</string> - <string name="faq_routing">The Routing and interface configuration is not done via traditional ifconfig/route commands but by using the VPNService API. This results in a different routing configuration than on other OSes. The configuration for the VPN tunnel consists of the IP address and the networks that should be routed over this interface. Especially no peer partner address or gateway address is needed. Special routes to reach the VPN Server (for example added when using redirect-gateway) are not needed either. The application will consequently ignore these settings when importing a configuration. The app ensures with the VPNService API that the connection to the server is not routed through the VPN tunnel. Only specifying networks to be routed via tunnel is supported. The app tries to detect networks that should not be routed over tunnel (e.g. route x.x.x.x y.y.y.y net_gateway) and calculates a route set that excludes this routes to emulate the behaviour of other platforms. The log windows shows the configuration of the VPNService upon establishing a connection.</string> <string name="persisttun_summary">Ne pas couper la connexion VPN lors de la reconnexion d\'OpenVPN.</string> <string name="persistent_tun_title">Persistance de l\'interface TUN</string> <string name="openvpn_log">Log OpenVPN</string> diff --git a/app/src/main/res/values-hu/strings-icsopenvpn.xml b/app/src/main/res/values-hu/strings-icsopenvpn.xml index 99c5201f..504ab893 100755 --- a/app/src/main/res/values-hu/strings-icsopenvpn.xml +++ b/app/src/main/res/values-hu/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> diff --git a/app/src/main/res/values-in/strings-icsopenvpn.xml b/app/src/main/res/values-in/strings-icsopenvpn.xml index ccb60754..c111cbb5 100755 --- a/app/src/main/res/values-in/strings-icsopenvpn.xml +++ b/app/src/main/res/values-in/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> @@ -85,6 +89,7 @@ <string name="use_default_title">Gunakan rute standar</string> <string name="custom_route_message">Masukkan rute butan sendiri. Masukkan tujuan dalam format CIDR. \"10.0.0.0/8 2002:: / 16\" akan mengarahkan jaringan 10.0.0.0/8 dan 2002:: / 16 melalui jaringan VPN</string> <string name="custom_routes_title">Rute buatan sendiri</string> + <string name="custom_routes_title_excluded">Jaringan Dikecualikan</string> <string name="log_verbosity_level">Tingkat rincian catatan</string> <string name="float_summary">Ijinkan paket terotentifikasi dari semua IP</string> <string name="float_title">Ijinkan server mengambang</string> diff --git a/app/src/main/res/values-it/strings-icsopenvpn.xml b/app/src/main/res/values-it/strings-icsopenvpn.xml index 61d09818..29d48904 100755 --- a/app/src/main/res/values-it/strings-icsopenvpn.xml +++ b/app/src/main/res/values-it/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> @@ -86,6 +90,7 @@ <string name="custom_route_message">Inserisci instradamenti personalizzati. Usare il formato CIDR. \"10.0.0.0/8 2002::/16\" reindirizza le reti 10.0.0.0/8 e 2002::/16 sulla VPN.</string> <string name="custom_route_message_excluded">Itinerari che dovrebbero non essere instradati su VPN. Utilizzare la stessa sintassi per quanto riguarda le rotte incluse.</string> <string name="custom_routes_title">Routing personalizzati</string> + <string name="custom_routes_title_excluded">Reti escluse</string> <string name="log_verbosity_level">Livello di dettaglio del registro</string> <string name="float_summary">Permette pacchetti autenticati da qualsiasi IP (consente che l\'IP del server possa cambiare)</string> <string name="float_title">Modalità float</string> @@ -99,6 +104,9 @@ <string name="last_openvpn_tun_config">Apertura interfaccia tun in corso:</string> <string name="local_ip_info">Indirizzi locali - IPv4: %1$s/%2$d IPv6: %3$s MTU: %4$d</string> <string name="dns_server_info">DNS Server: %1$s, Dominio: %2$s</string> + <string name="routes_info_incl">Instradamenti: %1$s %2$s</string> + <string name="routes_info_excl">Instradamenti esclusi: %1$s %2$s</string> + <string name="routes_debug">Instradamenti VpnService installati: %1$s %2$s</string> <string name="ip_not_cidr">Ottenute le informazioni sulle interfacce %1$s e %2$s, assumendo che il secondo indirizzo sia il peer remoto. Utilizzata la maschera /32 per l\'IP locale. La modalità impostata da OpenVPN è \"%3$s\".</string> <string name="route_not_cidr">Impossibile utilizzare %1$s e %2$s come reindirizzamenti IP con la maschera CIDR, è stata quindi usata la maschera /32.</string> <string name="route_not_netip">Instradamento %1$s/%2$s corretto con %3$s/%2$s</string> @@ -213,6 +221,7 @@ Effettuata la lettura del file di configurazione</string> <string name="vpn_import_hint">Usa l\'icona <img src=\"ic_menu_archive\"/> per importare il profilo (.ovpn o .conf) dalla tua scheda SD.</string> <string name="faq_hint">Si raccomanda di leggere anche le FAQ. C\'è anche una guida rapida.</string> <string name="faq_routing_title">Configurazione dei reindirizzamenti e dell\'interfaccia</string> + <string name="faq_routing">Il routing e la configurazione dell\'interfaccia non vengono fatti tramite i comandi ifconfig/route tradizionali ma utilizzando l\'API VPNService. Ciò si traduce in una configurazione di routing diversa rispetto ad altri sistemi operativi. La configurazione del tunnel VPN è composta dall\'indirizzo IP e dalle reti che devono essere instradate su tale interfaccia. Soprattutto non è necessario alcun indirizzo peer o gateway. Percorsi speciali per raggiungere il server VPN (ad esempio aggiunti quando si utilizza redirect-gateway) non sono neanche necessari. L\'applicazione pertanto ignorerà queste impostazioni durante l\'importazione di una configurazione. L\'applicazione garantisce con l\'API VPNService che la connessione al server non venga instradata attraverso il tunnel VPN. E\' supportato solo la specifica delle reti che devono essere instradate tramite il tunnel. L\'applicazione cerca di rilevare le reti che non devono essere instradate sul tunnel (ad esempio, route x.x.x.x y.y.y.y net_gateway) e calcola una serie di itinerari che escludono questi percorsi per emulare il comportamento di altre piattaforme. Le schermate del registro mostrano la configurazione del VPNService finché si stabilisce una connessione.</string> <string name="persisttun_summary">Non passa allo stato di \"Nessuna connessione VPN\" quando OpenVPN sta eseguendo un tentativo di riconnessione.</string> <string name="persistent_tun_title">tun persistente</string> <string name="openvpn_log">Log di OpenVPN</string> @@ -307,5 +316,13 @@ Effettuata la lettura del file di configurazione</string> <string name="logview_options">Visualizza opzioni</string> <string name="unhandled_exception">Eccezione non gestita: %1$s\n\n%2$s</string> <string name="unhandled_exception_context">%3$s: %1$s\n\n%2$s</string> + <string name="faq_system_dialog_xposed">Se il tuo dispositivo Android ha il root allora è possibile installare il <a href=\"http://xposed.info/\">framework Xposed</a> e il <a href=\"http://repo.xposed.info/module/de.blinkt.vpndialogxposed\">modulo di conferma VPN Dialog</a> a proprio rischio e pericolo\"</string> <string name="full_licenses">Licenze complete</string> + <string name="blocklocal_summary">Le reti direttamente collegate alle interfacce locali non verranno instradate attraverso la VPN. Deselezionando questa opzione si inoltrerà tutto il traffico dalle reti locali alla VPN.</string> + <string name="blocklocal_title">Ignora VPN per le reti locali</string> + <string name="userpw_file">File nome utente/password</string> + <string name="imported_from_file">[Importato da: %s]</string> + <string name="files_missing_hint">Alcuni file non possono essere trovati. Si prega di selezionare i file da importare nel profilo:</string> + <string name="openvpn_is_no_free_vpn">Per utilizzare questa applicazione è necessario un provider VPN/gateway VPN che supportino OpenVPN (spesso forniti dal datore di lavoro). Vai a http://community.openvpn.net/ per ulteriori informazioni su OpenVPN e come configurare il proprio server OpenVPN.</string> + <string name="import_log">Registro importazione:</string> </resources> diff --git a/app/src/main/res/values-ja/strings-icsopenvpn.xml b/app/src/main/res/values-ja/strings-icsopenvpn.xml index d537e3d8..79474f2d 100755 --- a/app/src/main/res/values-ja/strings-icsopenvpn.xml +++ b/app/src/main/res/values-ja/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> @@ -23,7 +27,7 @@ <string name="vpn_list_title">プãƒãƒ•ã‚¡ã‚¤ãƒ«</string> <string name="vpn_type">種別</string> <string name="pkcs12pwquery">PKCS12ã®ãƒ‘スワード</string> - <string name="file_select">é¸æŠž</string> + <string name="file_select">é¸æŠž…</string> <string name="file_nothing_selected">ファイルをé¸æŠžã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚</string> <string name="useTLSAuth">TLSèªè¨¼ã‚’使用ã—ã¾ã™ã€‚</string> <string name="tls_direction">TLS Direction</string> @@ -99,7 +103,7 @@ <string name="dns_server_info">DNSサーãƒ: %1$s, ドメイン: %2$s</string> <string name="routes_info_incl">経路: %1$s %2$s</string> <string name="routes_info_excl">除外ã•ã‚ŒãŸçµŒè·¯: %1$s %2$s</string> - <string name="ip_not_cidr">ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ãƒ¼ã‚¹æƒ…å ±ã¨ã—ã¦[%1$s]ã¨[%2$s]ã‚’å–å¾—ã—ã¾ã—ãŸã€‚2ã¤ã‚ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ãƒªãƒ¢ãƒ¼ãƒˆå´ã®ãƒ”アアドレスã§ã™ã€‚32ビットマスクをãƒãƒ¼ã‚«ãƒ«IPã«ä½¿ç”¨ã—ã¾ã™ã€‚ OpenVPNã®ãƒ¢ãƒ¼ãƒ‰ã¯[%3$s]ã§ã™ã€‚</string> + <string name="ip_not_cidr">ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ãƒ¼ã‚¹æƒ…å ±ã¨ã—㦠%1$s 㨠%2$s ã‚’å–å¾—ã—ã¾ã—ãŸã€‚2ã¤ç›®ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ãƒªãƒ¢ãƒ¼ãƒˆå´ã®ãƒ”アアドレスã§ã™ã€‚32ビットマスクをãƒãƒ¼ã‚«ãƒ«IPã«ä½¿ç”¨ã—ã¾ã™ã€‚ OpenVPNã®ãƒ¢ãƒ¼ãƒ‰ã¯ \"%3$s\" ã§ã™ã€‚</string> <string name="route_not_cidr">%1$sã¨%2$sã§ã¯CIDRå½¢å¼ã®IPçµŒè·¯æƒ…å ±ã¨ã—ã¦æ„味をãªã—ã¾ã›ã‚“。32ビットマスクを使用ã—ã¾ã™ã€‚</string> <string name="route_not_netip">çµŒè·¯æƒ…å ±%1$s/%2$sã‚’%3$s/%2$sã«ä¿®æ£ã—ã¾ã—ãŸã€‚</string> <string name="keychain_access">Androidã®è¨¼æ˜Žæ›¸ç®¡ç†ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。(ファームウェアã®æ›´æ–°ã€ã‚¢ãƒ—リケーションã¾ãŸã¯ãã®è¨å®šã®ãƒªã‚¹ãƒˆã‚¢ã«ã‚ˆã£ã¦ç™ºç”Ÿã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™)。VPNã®è¨å®šã§è¨¼æ˜Žæ›¸ã®é¸æŠžã‚’å†åº¦è¡Œã£ã¦ãã ã•ã„。</string> @@ -107,12 +111,11 @@ <string name="send_logfile">ãƒã‚° ファイルをé€ä¿¡ã—ã¾ã™ã€‚</string> <string name="send">é€ä¿¡</string> <string name="ics_openvpn_log_file">ICS OpenVPN ãƒã‚° ファイル</string> - <string name="copied_entry">クリップ ボードã«ã‚³ãƒ”ーã•ã‚ŒãŸãƒã‚° エントリ</string> + <string name="copied_entry">ãƒã‚° エントリをクリップボードã«ã‚³ãƒ”ーã—ã¾ã—ãŸ</string> <string name="tap_mode">TAPモード</string> <string name="faq_tap_mode">TAPモードã¯éžroot化環境ã§ã¯å‹•ä½œã—ã¾ã›ã‚“。よã£ã¦ã“ã®ã‚¢ãƒ—リケーションã§ã¯TAPをサãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“。</string> <string name="tap_faq2">ã¾ãŸã§ã™ã‹ï¼ŸTAPモードã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“ã—ã€ã‚µãƒãƒ¼ãƒˆã•ã‚Œã‚‹ã‹ã©ã†ã‹ãƒ¡ãƒ¼ãƒ«ã‚’é€ã‚‹ã“ã¨ã¯ä½•ã®å½¹ã«ã‚‚ç«‹ã¡ã¾ã›ã‚“。</string> - <string name="tap_faq3">3回目ã§ã™ã€‚本当ã®ã¨ã“ã‚ã€TUN上ã§å‹•ãレイヤ2エミュレータを書ãã“ã¨ã¯ã§ãã¾ã—ãŸã€‚(é€ä¿¡æ™‚ã®æƒ…å ±è¿½åŠ ã¨å—信時ã®æƒ…å ±å‰Šé™¤ã§)。ã—ã‹ã—ã“ã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã¯ARPã‚„ãŠãらãã¯DHCPをも実装ã—ãªã‘ã‚Œã°ãªã‚‰ãªã„ã§ã—ょã†ã€‚誰もã“ã®ã“ã¨ã«æ°—ãŒã¤ã„ã¦ã„ã¾ã›ã‚“。もã—ã‚ãªãŸãŒã“ã®æ©Ÿèƒ½ã‚’作る気ã«ãªã£ãŸã®ã§ã‚ã‚Œã°ã€ã©ã†ãžç§ã«é€£çµ¡ã—ã¦ãã ã•ã„。 -</string> + <string name="tap_faq3">3回目ã§ã™ã€‚本当ã®ã¨ã“ã‚ã€TUN上ã§å‹•ãレイヤ2エミュレータを書ãã“ã¨ã¯ã§ãã¾ã—ãŸã€‚(é€ä¿¡æ™‚ã®æƒ…å ±è¿½åŠ ã¨å—信時ã®æƒ…å ±å‰Šé™¤ã§)。ã—ã‹ã—ã“ã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã¯ARPã‚„ãŠãらãã¯DHCPをも実装ã—ãªã‘ã‚Œã°ãªã‚‰ãªã„ã§ã—ょã†ã€‚誰もã“ã®ã“ã¨ã«æ°—ãŒã¤ã„ã¦ã„ã¾ã›ã‚“。もã—ã‚ãªãŸãŒã“ã®æ©Ÿèƒ½ã‚’作る気ã«ãªã£ãŸã®ã§ã‚ã‚Œã°ã€ã©ã†ãžç§ã«é€£çµ¡ã—ã¦ãã ã•ã„。</string> <string name="faq">よãã‚る質å•</string> <string name="copying_log_entries">ãƒã‚° エントリã®ã‚³ãƒ”ー</string> <string name="faq_copying">1è¡Œã®ãƒã‚°ã‚¨ãƒ³ãƒˆãƒªã‚’コピーã™ã‚‹ã«ã¯ã€ãã®ã‚¨ãƒ³ãƒˆãƒªã‚’タッãƒã—続ã‘ã¾ã™ã€‚コピーï¼é€ä¿¡ã™ã‚‹ã«ã¯ã€Œãƒã‚°ã‚¨ãƒ³ãƒˆãƒªã‚’é€ä¿¡ã€ã‚’使用ã—ã¾ã™ã€‚GUIã§è¡¨ç¤ºã•ã‚Œãªã„å ´åˆã¯ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ãƒœã‚¿ãƒ³ã‚’使用ã—ã¦ãã ã•ã„。</string> @@ -138,7 +141,7 @@ <string name="import_could_not_open">インãƒãƒ¼ãƒˆã•ã‚ŒãŸæ§‹æˆãƒ•ã‚¡ã‚¤ãƒ«ã«è¨˜è¼‰ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ« %1$s ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</string> <string name="importing_config">構æˆãƒ•ã‚¡ã‚¤ãƒ«ã‚’%1$sã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚</string> <string name="import_warning_custom_options">ユーザインターフェースã«ãƒžãƒƒãƒ”ングã•ã‚Œã¦ã„ãªã„ã„ãã¤ã‹ã®è¨å®šé …ç›®ãŒã‚ã‚Šã¾ã™ã€‚ãれらã®è¨å®šã¯ã‚«ã‚¹ã‚¿ãƒ オプションã¨ã—ã¦è¿½åŠ ã•ã‚Œã¾ã™ã€‚カスタムオプションを以下ã«è¡¨ç¤ºã—ã¾ã™ã€‚</string> - <string name="import_done">構æˆãƒ•ã‚¡ã‚¤ãƒ«ã®èªã¿å–り終了。</string> + <string name="import_done">構æˆãƒ•ã‚¡ã‚¤ãƒ«ã®èªã¿è¾¼ã¿ã‚’完了ã—ã¾ã—ãŸã€‚</string> <string name="nobind_summary">ãƒãƒ¼ã‚«ãƒ« アドレスã¨ãƒãƒ¼ãƒˆã«ãƒã‚¤ãƒ³ãƒ‰ã‚’è¡Œã„ã¾ã›ã‚“。</string> <string name="no_bind">ãƒãƒ¼ã‚«ãƒ«ãƒã‚¤ãƒ³ãƒ‰ã—ãªã„</string> <string name="import_configuration_file">構æˆãƒ•ã‚¡ã‚¤ãƒ«ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ</string> @@ -200,8 +203,7 @@ Androidã¯ã‚ãªãŸè‡ªèº«ã®å®‰å…¨æ€§ã®ãŸã‚ã«ã€ã“れらを迂回ã§ããªã <p>ã‚‚ã—ファイルãŒè¶³ã‚Šãªã„ã¨ã„ã†ã‚¨ãƒ©ãƒ¼ãŒè¡¨ç¤ºã•ã‚ŒãŸã‚‰ã€è¶³ã‚Šãªã‹ã£ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’SDカード上ã«æ ¼ç´ã—ã¦ãã ã•ã„。</p> <p>インãƒãƒ¼ãƒˆã•ã‚ŒãŸVPNè¨å®šã‚’リストã«è¿½åŠ ã™ã‚‹ã«ã¯ã€ä¿å˜ã‚¢ã‚¤ã‚³ãƒ³ã‚’クリックã—ã¾ã™ã€‚</p> <p>VPNを接続ã™ã‚‹ã«ã¯ã€VPNã®å称をクリックã—ã¾ã™ã€‚</p> -<p>ã‚‚ã—è¦å‘Šã‚„エラーãŒãƒã‚°ã‚¨ãƒ³ãƒˆãƒªã«è¡¨ç¤ºã•ã‚ŒãŸã‚‰ã€ãれらを調ã¹ã¦è§£æ±ºã—ã¦ãã ã•ã„。</p> -</string> +<p>ã‚‚ã—è¦å‘Šã‚„エラーãŒãƒã‚°ã‚¨ãƒ³ãƒˆãƒªã«è¡¨ç¤ºã•ã‚ŒãŸã‚‰ã€ãれらを調ã¹ã¦è§£æ±ºã—ã¦ãã ã•ã„。</p></string> <string name="faq_howto_title">クイックスタート</string> <string name="setting_loadtun_summary">接続ã®è©¦è¡Œå‰ã«TUNデãƒã‚¤ã‚¹ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«(tun.ko)ã‚’èªã¿è¾¼ã¿ã¾ã™ã€‚デãƒã‚¤ã‚¹ã®root化ãŒå¿…è¦ã§ã™ã€‚</string> <string name="setting_loadtun">TUNモジュールをãƒãƒ¼ãƒ‰</string> @@ -217,8 +219,7 @@ Androidã¯ã‚ãªãŸè‡ªèº«ã®å®‰å…¨æ€§ã®ãŸã‚ã«ã€ã“れらを迂回ã§ããªã <string name="restart">å†èµ·å‹•</string> <string name="restart_vpn_after_change">è¨å®šã®å¤‰æ›´ã¯VPNã®å†èµ·å‹•å¾Œã«åæ˜ ã•ã‚Œã¾ã™ã€‚VPNã‚’(å†)èµ·å‹•ã—ã¾ã™ã‹ï¼Ÿ</string> <string name="configuration_changed">è¨å®šãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸ</string> - <string name="log_no_last_vpn">編集ã•ã‚ŒãŸãŸã‚ã€æœ€å¾Œã«æŽ¥ç¶šã—ãŸãƒ—ãƒãƒ•ã‚¡ã‚¤ãƒ«ã‚’確èªã§ãã¾ã›ã‚“ã§ã—㟠-</string> + <string name="log_no_last_vpn">編集ã•ã‚ŒãŸãŸã‚ã€æœ€å¾Œã«æŽ¥ç¶šã—ãŸãƒ—ãƒãƒ•ã‚¡ã‚¤ãƒ«ã‚’確èªã§ãã¾ã›ã‚“ã§ã—ãŸ</string> <string name="faq_duplicate_notification_title">é‡è¤‡ã—ãŸé€šçŸ¥</string> <string name="faq_duplicate_notification">ã‚‚ã—AndroidãŒãƒ¡ãƒ¢ãƒªä¸è¶³ã«é™¥ã£ãŸå ´åˆã€ãã®æ™‚点ã§å¿…è¦ã¨ã•ã‚Œãªã„アプリケーションやサービスã¯ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªãƒ¡ãƒ¢ãƒªã‹ã‚‰æŽ’除ã•ã‚Œã¾ã™ã€‚ ã“ã®å‡¦ç†ã«ä¼´ã„ã€VPN接続ã¯çµ‚了ã•ã‚Œã¾ã™ã€‚ @@ -292,7 +293,7 @@ OpenVPNã®æŽ¥ç¶šã‚’ä¿è¨¼ã™ã‚‹ãŸã‚ã«ã¯ã€ã‚¢ãƒ—リケーションを高ã„å <string name="allowed_apps">許å¯ã‚¢ãƒ—リ: %s</string> <string name="clearappsdialog">許å¯ã‚¢ãƒ—リã®ä¸€è¦§ã‚’クリアã—ã¾ã™ã‹?\nç¾åœ¨ã®è¨±å¯ã‚¢ãƒ—リ一覧:\n\n%s</string> <string name="screenoff_summary">スクリーンãŒã‚ªãƒ•ã‹ã¤60秒ã§64kB以下ã®ãƒ‡ãƒ¼ã‚¿è»¢é€é‡ã®å ´åˆã€VPN通信をä¸æ–ã—ã¾ã™ã€‚「永続的ãªTUNã€è¨å®šãŒæœ‰åŠ¹ãªå ´åˆã€VPN接続ãŒä¸æ–ã•ã‚Œã‚‹ã¨é€šä¿¡ãŒã§ããªããªã‚Šã¾ã™ã€‚「永続的ãªTUNã€ã‚’無効ã«ã™ã‚‹ã¨ã€VPNã«ã‚ˆã‚‹æŽ¥ç¶šä¿è·ã¯è¡Œã‚ã‚Œãªããªã‚Šã¾ã™ã€‚</string> - <string name="screenoff_title">ç”»é¢ã‚ªãƒ•å¾Œã«VPN接続をä¸æ–ã™ã‚‹</string> + <string name="screenoff_title">ç”»é¢ã‚ªãƒ•å¾Œã«VPN接続をä¸æ–</string> <string name="screen_nopersistenttun">è¦å‘Š: ã“ã®VPN接続ã«ã¯æ°¸ç¶šçš„ãªTUNãŒè¨å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。スクリーンオフ後ã®é€šä¿¡ã¯é€šå¸¸ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆæŽ¥ç¶šã‚’使用ã—ã¾ã™ã€‚</string> <string name="save_password">パスワードをä¿å˜</string> <string name="pauseVPN">VPN一時åœæ¢</string> @@ -322,10 +323,10 @@ OpenVPNã®æŽ¥ç¶šã‚’ä¿è¨¼ã™ã‚‹ãŸã‚ã«ã¯ã€ã‚¢ãƒ—リケーションを高ã„å <string name="unhandled_exception">未処ç†ã®ä¾‹å¤–: %1$s\n\n%2$s</string> <string name="unhandled_exception_context">%3$s: %1$s\n\n%2$s</string> <string name="faq_system_dialog_xposed">ã‚‚ã—ã‚ãªãŸãŒãƒ‡ãƒã‚¤ã‚¹ã‚’root化ã—ã¦ã„ã‚‹ã®ã§ã‚ã‚Œã°ã€ <a href=\"http://xposed.info/\">Xposed framework</a>ã¨<a href=\"http://repo.xposed.info/module/de.blinkt.vpndialogxposed\">VPN Dialog confirm module</a> を自己責任ã«ãŠã„ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ãã¾ã™</string> - <string name="full_licenses">フルライセンス</string> + <string name="full_licenses">完全ãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹å‘ŠçŸ¥</string> <string name="blocklocal_summary">ãƒãƒ¼ã‚«ãƒ«ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã«ç›´æŽ¥æŽ¥ç¶šã•ã‚Œã¦ã„ã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¯VPNを経由ã—ã¾ã›ã‚“。 ã“ã®ã‚ªãƒ—ションを外ã™ã¨ãƒãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å®›ã®ã™ã¹ã¦ã®é€šä¿¡ã‚’VPNã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã—ã¾ã™ã€‚</string> - <string name="blocklocal_title">ãƒãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¯VPNを経由ã—ãªã„</string> + <string name="blocklocal_title">ãƒãƒ¼ã‚«ãƒ«ã¯VPNを経由ã—ãªã„</string> <string name="userpw_file">ユーザーå/パスワードファイル</string> <string name="imported_from_file">[インãƒãƒ¼ãƒˆå…ƒ: %s]</string> <string name="files_missing_hint">ã„ãã¤ã‹ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚プãƒãƒ•ã‚¡ã‚¤ãƒ«ã‚’インãƒãƒ¼ãƒˆã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„:</string> diff --git a/app/src/main/res/values-ko/strings-icsopenvpn.xml b/app/src/main/res/values-ko/strings-icsopenvpn.xml index cd8bc176..b05e4f51 100755 --- a/app/src/main/res/values-ko/strings-icsopenvpn.xml +++ b/app/src/main/res/values-ko/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> diff --git a/app/src/main/res/values-nl/strings-icsopenvpn.xml b/app/src/main/res/values-nl/strings-icsopenvpn.xml index f553449b..2a000195 100755 --- a/app/src/main/res/values-nl/strings-icsopenvpn.xml +++ b/app/src/main/res/values-nl/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> diff --git a/app/src/main/res/values-no/strings-icsopenvpn.xml b/app/src/main/res/values-no/strings-icsopenvpn.xml index 7a7dd124..66391eb5 100755 --- a/app/src/main/res/values-no/strings-icsopenvpn.xml +++ b/app/src/main/res/values-no/strings-icsopenvpn.xml @@ -1,11 +1,16 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> <string name="address">Server adresse:</string> <string name="port">Server port:</string> <string name="location">Plassering</string> + <string name="cant_read_folder">Kan ikke lese katalogen</string> <string name="select">velg</string> <string name="cancel">Avbryt</string> <string name="no_data">Ingen Data</string> @@ -15,32 +20,54 @@ <string name="client_key_title">Klientsertifikat nøkkel</string> <string name="client_pkcs12_title">PKCS12 fil</string> <string name="ca_title">CA-sertifikat</string> + <string name="no_certificate">Du mÃ¥ velge et sertifikat</string> + <string name="copyright_guicode">Kildekode og problemsøkersporing er tilgjengelig pÃ¥ http://code.google.com/p/ics-openvpn/</string> + <string name="copyright_others">Dette programmet bruker følgende komponenter; se kildekoden for detaljer om lisensene</string> <string name="about">Om</string> + <string name="vpn_list_title">Profiler</string> <string name="vpn_type">Type</string> <string name="pkcs12pwquery">PKCS12 passord</string> <string name="file_select">Velg…</string> + <string name="file_nothing_selected">Du mÃ¥ velge en fil</string> <string name="useTLSAuth">Bruke TLS-godkjenning</string> <string name="tls_direction">TLS-retning</string> <string name="ipv6_dialog_tile">Angi IPv6-adresse/nettmaske i CIDR format (f.eks 2000:dd::23/64)</string> <string name="ipv4_dialog_title">Angi IPv6-adresse/nettmaske i CIDR format (f.eks 1.2.3.4/24)</string> <string name="ipv4_address">IPv4-adresse</string> <string name="ipv6_address">IPv6-adresse</string> + <string name="custom_option_warning">Angi egendefinerte OpenVPN-alternativer. Bør brukes med forsiktighet. Vær ogsÃ¥ oppmerksom pÃ¥ at mange av de tun-relaterte OpenVPN-innstillingene ikke støttes i henhold til utformingen av VPNSettings. Hvis du tror at et viktig alternativ mangler kan du kontakte forfatteren</string> <string name="auth_username">Brukernavn</string> <string name="auth_pwquery">Passord</string> + <string name="static_keys_info">For den statiske konfigurasjonen vil TLS Auth Keys-ene bli brukt som statiske nøkler</string> <string name="configure_the_vpn">Konfigurer VPN</string> <string name="menu_add_profile">Legge til profil</string> <string name="add_profile_name_prompt">Angi et navn som identifiserer den nye profilen</string> + <string name="duplicate_profile_name">Skriv inn et unikt profilnavn</string> <string name="profilename">Profilnavn</string> + <string name="no_keystore_cert_selected">Du mÃ¥ velge et brukersertifikat</string> <string name="no_error_found">Ingen feil funnet</string> <string name="config_error_found">Feil i konfigurasjonen</string> + <string name="ipv4_format_error">Feil ved analyse av IPv4-adressen</string> + <string name="custom_route_format_error">Feil ved analyse av egendefinerte ruter</string> + <string name="pw_query_hint">(La stÃ¥ tomt for Ã¥ søke pÃ¥ forespørsel)</string> <string name="vpn_shortcut">OpenVPN snarvei</string> <string name="vpn_launch_title">Koble til VPN</string> + <string name="shortcut_profile_notfound">Profilen som er angitt i snarveien ble ikke funnet</string> <string name="random_host_prefix">Tilfeldig vert prefiks</string> + <string name="random_host_summary">Legger til 6 tilfeldige tegn foran vertsnavn</string> <string name="custom_config_title">Aktiver egendefinerte valg</string> + <string name="custom_config_summary">Angi egendefinerte alternativer. Brukes med forsiktighet!</string> + <string name="route_rejected">Route avvist av Android</string> <string name="cancel_connection">Koble fra</string> + <string name="cancel_connection_long">Koble fra VPN</string> <string name="clear_log">Tøm logg</string> <string name="title_cancel">Avbryt bekreftelse</string> + <string name="cancel_connection_query">Koble fra tilkoblet VPN-forbindelse / avbryt oppkoblingsforsøket ?</string> <string name="remove_vpn">Fjern VPN</string> + <string name="check_remote_tlscert">Kontrollerer om tjeneren bruker et sertifikat med TLS-servertillegg (--remote-cert-TLS-server)</string> + <string name="check_remote_tlscert_title">Forvent TLS-serversertifikat</string> + <string name="remote_tlscn_check_summary">Kontrollerer eksternt tjenersertifikatemne DN</string> + <string name="remote_tlscn_check_title">Sjekk av vertsnavn i sertifikat</string> <string name="tls_auth_file">TLS-Auth-fil</string> <string name="dns">DNS</string> <string name="dns_override_summary">Bruk din egen DNS-server</string> diff --git a/app/src/main/res/values-pl/strings-icsopenvpn.xml b/app/src/main/res/values-pl/strings-icsopenvpn.xml index d628da6c..495eb00e 100755 --- a/app/src/main/res/values-pl/strings-icsopenvpn.xml +++ b/app/src/main/res/values-pl/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> diff --git a/app/src/main/res/values-pt/strings-icsopenvpn.xml b/app/src/main/res/values-pt/strings-icsopenvpn.xml index 30bf569e..d0058c68 100755 --- a/app/src/main/res/values-pt/strings-icsopenvpn.xml +++ b/app/src/main/res/values-pt/strings-icsopenvpn.xml @@ -1,139 +1,255 @@ <?xml version="1.0" encoding="utf-8"?> <!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> <string name="address">Endereço do Servidor:</string> - <string name="port">Porta:</string> + <string name="port">Porta do Servidor:</string> <string name="location">Localização</string> - <string name="cant_read_folder">Não foi possÃvel ler o diretório</string> + <string name="cant_read_folder">Não é possÃvel ler o diretório</string> <string name="select">Selecionar</string> <string name="cancel">Cancelar</string> <string name="no_data">Não há dados</string> <string name="useLZO">Compressão LZO</string> - <string name="client_no_certificate">Sem Certificado</string> - <string name="client_certificate_title">Certificado do Cliente</string> - <string name="client_key_title">Chave do Certificado do Cliente</string> - <string name="client_pkcs12_title">Arquivo PKCS12</string> - <string name="ca_title">Certificado CA</string> - <string name="no_certificate">Você deve selecionar um certificado</string> - <string name="copyright_guicode">O código fonte e o rastreamento de incidentes estão disponÃveis em http://code.google.com/p/ics-openvpn/</string> - <string name="copyright_others">Este programa utiliza os seguintes componentes; veja o código fonte para mais detalhes das licenças</string> + <string name="client_no_certificate">Nenhum certificado</string> + <string name="client_certificate_title">Certificado de cliente</string> + <string name="client_key_title">Chave de certificado de cliente</string> + <string name="client_pkcs12_title">Ficheiro PKCS12</string> + <string name="ca_title">Certificado de CA</string> + <string name="no_certificate">Deve selecionar um certificado</string> + <string name="copyright_guicode">Código fonte e controlo de problemas disponÃvel em http://code.google.com/p/ics-openvpn/</string> + <string name="copyright_others">Este programa utiliza os seguintes componentes; Para mais detalhes sobre as licenças consultar o código-fonte</string> <string name="about">Sobre</string> <string name="vpn_list_title">Perfis</string> <string name="vpn_type">Tipo</string> - <string name="pkcs12pwquery">Senha do PKCS12</string> + <string name="pkcs12pwquery">Password PKCS12</string> <string name="file_select">Selecionar…</string> - <string name="file_nothing_selected">Você deve selecionar um arquivo</string> - <string name="useTLSAuth">Utilizar Autenticação TLS</string> + <string name="file_nothing_selected">É necessário selecionar um ficheiro</string> + <string name="useTLSAuth">Usar autenticação TLS</string> <string name="tls_direction">Direção TLS</string> - <string name="ipv6_dialog_tile">Entre o Endereço IPv6/CIDR (ex: 2000:dd::23/64)</string> - <string name="ipv4_dialog_title">Entre o endereço IPv4/CIDR (ex: 1.2.3.4/24)</string> + <string name="ipv6_dialog_tile">Digite o endereço de IPv6/máscara de rede no formato CIDR (por exemplo, 2000:dd::23 / 64)</string> + <string name="ipv4_dialog_title">Digite o endereço de IPv4/máscara de rede no formato CIDR (por exemplo, 1.2.3.4/24)</string> <string name="ipv4_address">Endereço IPv4</string> <string name="ipv6_address">Endereço IPv6</string> - <string name="custom_option_warning">Insira as opções personalizadas para o OpenVPN. Utilize com cuidado. Observe também que muitas das opções relacionadas ao tun do OpenVPN não podem ser suportadas pelo design do VPNSettings. Contate o autor se você acha que uma opção importante está faltando.</string> - <string name="auth_username">Usuário</string> - <string name="auth_pwquery">Senha</string> - <string name="static_keys_info">Para a configuração estática as chaves de autenticação de TLS serão utilizadas como chaves estáticas</string> - <string name="configure_the_vpn">Configurar VPN</string> - <string name="menu_add_profile">Adicionar Perfil</string> - <string name="add_profile_name_prompt">Digite um nome que identifica o novo perfil</string> - <string name="duplicate_profile_name">Por favor, digite um nome de perfil único</string> + <string name="custom_option_warning">Insira opções personalizadas para a ligação OpenVPN. Este opções devem ser usadas com precaução. Note-se também que muitas das opções para OpenVPN relacionados com tun não não suportadas propositadamente. Se achar que uma opção importante está falta entre em contato com o autor</string> + <string name="auth_username">Utilizador</string> + <string name="auth_pwquery">Password</string> + <string name="static_keys_info">Para a configuração estática as chaves de autenticação TLS serão usadas como chaves estáticas</string> + <string name="configure_the_vpn">Configurar a VPN</string> + <string name="menu_add_profile">Adicionar perfil</string> + <string name="add_profile_name_prompt">Digite um nome que identifique o novo perfil</string> + <string name="duplicate_profile_name">Por favor, digite um nome de perfil que não esteja já em uso</string> <string name="profilename">Nome do perfil</string> - <string name="no_keystore_cert_selected">Você deve selecionar um certificado de usuário</string> + <string name="no_keystore_cert_selected">Tem de selecionar um certificado de utilizador</string> <string name="no_error_found">Nenhum erro encontrado</string> <string name="config_error_found">Erro na configuração</string> <string name="ipv4_format_error">Erro ao analisar o endereço IPv4</string> <string name="custom_route_format_error">Erro ao analisar as rotas personalizadas</string> - <string name="pw_query_hint">(deixe em branco para consulta sob demanda)</string> + <string name="pw_query_hint">(deixe em branco para consulta a pedido)</string> <string name="vpn_shortcut">Atalho do OpenVPN</string> - <string name="vpn_launch_title">Conectar a VPN</string> - <string name="shortcut_profile_notfound">O perfil especificado no atalho não foi encontrado</string> + <string name="vpn_launch_title">Ligar à VPN</string> + <string name="shortcut_profile_notfound">Perfil especificado no atalho não encontrado</string> <string name="random_host_prefix">Prefixo de Host aleatório</string> - <string name="random_host_summary">Adiciona 6 caracteres aleatórios na frente do hostname</string> - <string name="custom_config_title">Habilitar opções personalizadas</string> - <string name="custom_config_summary">Opções personalizadas. Use com cuidado!</string> + <string name="random_host_summary">Adiciona 6 caracteres aleatórios ao nome do host</string> + <string name="custom_config_title">Ativar opções personalizadas</string> + <string name="custom_config_summary">Especifique as opções personalizadas. Use com cuidado!</string> <string name="route_rejected">Rota rejeitada pelo Android</string> <string name="cancel_connection">Desconectar</string> <string name="cancel_connection_long">Desconectar VPN</string> - <string name="clear_log">limpar log</string> - <string name="title_cancel">Cancelar confirmação</string> - <string name="cancel_connection_query">Desconectar a VPN conectada/cancelar a tentativa de conexão?</string> + <string name="clear_log">Limpar registo</string> + <string name="title_cancel">Cancelar Confirmação</string> <string name="remove_vpn">Remover VPN</string> - <string name="check_remote_tlscert">Verifica se o servidor usa um certificado com as extensões de servidor TLS (- servidor remoto-cert-TLS)</string> <string name="check_remote_tlscert_title">Esperar certificado do servidor TLS</string> - <string name="remote_tlscn_check_summary">Verifica o DN Subject do certificado do servidor remoto</string> - <string name="remote_tlscn_check_title">Verificar o Hostname do Certificado</string> - <string name="enter_tlscn_dialog">Especificar a conta usada para verificar o certificado remoto DN (por exemplo, C = DE, L = Paderborn, UO = aviária operadoras IP, CN=openvpn.blinkt.de)\n\Especificar o DN completo ou o RDN (openvpn.blinkt.de no exemplo) ou um prefixo RDN para verification.\n\nWhen usando o prefixo RDN \"Servidor\" corresponde a \"Server-1\" e \"Server-2\" \n\nDeixando vazio, o campo de texto irá verificar o RDN contra o servidor hostname.\n\nPara mais detalhes consulte a página principal do 2.3.1+ OpenVPN sob — verificar-X509-nome</string> - <string name="enter_tlscn_title">Subject do certificado remoto</string> - <string name="tls_key_auth">Permite a Autenticação de Chave TLS</string> - <string name="tls_auth_file">Arquivo de Auth TLS</string> - <string name="pull_on_summary">Solicitações de endereços de IP, rotas e opções de sincronização do servidor.</string> - <string name="pull_off_summary">Nenhuma informação é solicitada do servidor. Configurações precisam ser especificadas abaixo.</string> + <string name="remote_tlscn_check_title">Verificar nome de host do certificado</string> + <string name="enter_tlscn_title">Assunto do certificado remoto</string> + <string name="tls_key_auth">Ativa a autenticação de chave TLS</string> + <string name="tls_auth_file">Ficheiro de autenticação TLS</string> + <string name="pull_on_summary">Solicita endereços IP, rotas e tempo do servidor.</string> <string name="use_pull">Obter Configurações</string> <string name="dns">DNS</string> - <string name="override_dns">Substituir as configurações de DNS pelo servidor</string> - <string name="dns_override_summary">Use seus próprios servidores de DNS</string> + <string name="override_dns">Substituir configurações de DNS pelo servidor</string> + <string name="dns_override_summary">Use seus próprios servidores DNS</string> <string name="searchdomain">DomÃnio de pesquisa</string> - <string name="dns1_summary">Servidor DNS a ser usado.</string> + <string name="dns1_summary">Servidor de DNS a utilizar.</string> <string name="dns_server">Servidor DNS</string> <string name="secondary_dns_message">Servidor DNS secundário utilizado caso o servidor primário esteja inacessÃvel.</string> <string name="backup_dns">Servidor DNS alternativo</string> - <string name="ignored_pushed_routes">Ignorar rotas empurradas</string> - <string name="ignore_routes_summary">Ignorar rota empurrada pelo servidor.</string> <string name="default_route_summary">Redireccionar todo o tráfego pela VPN</string> <string name="use_default_title">Usar rota padrão</string> - <string name="custom_route_message">Digite rotas personalizadas. Apenas indique destino em formato CIDR. \"10.0.0.0 / 8 2002 :: / 16\" iria dirigir as redes 10.0.0.0 / 8 e 2002 :: / 16 sobre a VPN.</string> - <string name="custom_route_message_excluded">As rotas que não devem ser encaminhados pelo VPN. Use a mesma sintaxe para rotas incluÃdas.</string> <string name="custom_routes_title">Rotas personalizadas</string> <string name="custom_routes_title_excluded">Redes excluÃdas</string> - <string name="log_verbosity_level">NÃvel de complexidade do log</string> - <string name="float_summary">Permite pacotes autenticados a partir de qualquer IP</string> + <string name="log_verbosity_level">NÃvel de verbosidade do log</string> <string name="float_title">Permitir servidor flutuante</string> <string name="custom_options_title">Opções personalizadas</string> - <string name="edit_vpn">Editar configurações de VPN</string> - <string name="remove_vpn_query">Remover o perfil VPN \'%s\'?</string> - <string name="tun_error_helpful">Em algumas imagens ICS personalizado a permissão em / dev / tun pode estar errada, ou o módulo tun pode estar faltando completamente. Para imagens CM9 tente a opção correção propriedade sobre as configurações gerais</string> - <string name="tun_open_error">Falha ao abrir a interface de tun</string> - <string name="error">"Erro:"</string> - <string name="clear">Claro</string> - <string name="last_openvpn_tun_config">Abrindo a interface tun:</string> - <string name="local_ip_info">Local IPv4: %1$s/%2$d IPv6:%3$s MTU:%4$d</string> - <string name="dns_server_info">Servidor DNS: %1$s, domÃnio: %2$s</string> + <string name="edit_vpn">Editar definições VPN</string> + <string name="remove_vpn_query">Remova o perfil VPN \'%s\'?</string> + <string name="tun_open_error">Falha ao abrir a interface tun</string> + <string name="error">"Erro: "</string> + <string name="clear">Limpar</string> + <string name="last_openvpn_tun_config">A abrir a interface tun:</string> + <string name="local_ip_info">Local IPv4: %1$s/%2$d IPv6: %3$s MTU: %4$d</string> + <string name="dns_server_info">Servidor DNS: %1$s, Dominio: %2$s</string> <string name="routes_info_incl">Rotas: %1$s %2$s</string> <string name="routes_info_excl">Rotas excluÃdas: %1$s %2$s</string> - <string name="routes_debug">Rotas VpnService instaladas: %1$s %2$s</string> + <string name="routes_debug">Rotas VpnService instaladas: %1$s %2$s</string> <string name="ip_not_cidr">Existem múltiplas informações de interface, %1$s e %2$s, a aplicação assume que o segundo endereço é um endereço \'peer\' do endereço remoto. Será usada uma máscara de rede /32 para o IP local. O modo estabelecido pela OpenVPN é \"%3$s\".</string> - <string name="route_not_cidr">Não consigo entender %1$s e %2$s como uma rota IP com máscara de rede CIDR, usando /32 como máscara de rede.</string> + <string name="route_not_cidr">não é possÃvel fazer sentido de %1$s e %2$s como rotas de IP, com máscara de rede CIDR, será usada uma máscara de rede /32.</string> <string name="route_not_netip">A rota %1$s/%2$s foi corrigida para %3$s/%2$s</string> - <string name="keychain_access">Não é possÃvel aceder aos certificados \'Keychain Android\'. Isso pode ter sido causado por uma atualização de firmware ou uma restauração das configurações da app/app. Será necessário editar o perfil VPN e selecionar novamente o certificado nas configurações básicas para recriar a permissão e possibilitar o acesso ao certificado.</string> + <string name="keychain_access">Não é possÃvel aceder aos certificados \'Keychain Android\'. Isto pode ser causado por uma atualização de firmware ou um restauro das configurações da app/app. Será necessário editar o perfil VPN e selecionar novamente o certificado nas configurações básicas para recriar a permissão e possibilitar o acesso ao certificado.</string> <string name="version_info">%1$s %2$s</string> - <string name="send_logfile">Enviar arquivo de log</string> + <string name="send_logfile">Enviar o ficheiro de registo</string> <string name="send">Enviar</string> <string name="ics_openvpn_log_file">Ficheiro de registo do ICS OpenVPN</string> <string name="copied_entry">Entrada de registo copiada para a área de transferência</string> - <string name="tap_mode">Entrada de registo copiada para a área de transferência</string> + <string name="tap_mode">Modo Tap</string> <string name="faq_tap_mode">A API VPN não permite o modo Tap em dispositivos sem acesso root. Desta forma não é possÃvel oferecer suporte Tap nesta aplicação</string> - <string name="tap_faq2">Novamente? Você está brincando? Não, o modo tap não é suportado de maneira nenhuma e enviar mais emails a perguntar se eventualmente será, não irá ajudar.</string> - <string name="faq">Perguntas frequentes</string> + <string name="tap_faq2">Novamente? Estamos a brincar? Não, o modo tap não é suportado de maneira nenhuma e enviar mais emails a perguntar se eventualmente será, não ai ajudar a que seja.</string> + <string name="tap_faq3">Uma terceira vez? Na verdade, se poderia escrever um um emulador de torneira baseado no tun que adicionar layer2 informações sobre envio e tira informações layer2 em receber. Mas este emulador de torneira também teria que implementar ARP e, possivelmente, um cliente DHCP. Eu não conheço ninguém fazer nenhum trabalho nesse sentido. Contacte-me se você deseja iniciar a codificação sobre isso. Mas este emulador tap também teria que implementar ARP e, possivelmente, um cliente DHCP. Eu não conheço ninguém a fazer nenhum trabalho nesse sentido. Contacte-me se conhece alguém ou deseja a escrever código nesse sentido.</string> + <string name="faq">Perguntas Frequentes</string> + <string name="copying_log_entries">Copia entradas de registo</string> + <string name="faq_copying">Para copiar uma única entrada do registo selecione e mantenha seleciona a respetiva entrada. Para copiar/enviar o registo completo use a opção enviar registo. Use o botão de menu do equipamento caso não esteja visÃvel no GUI.</string> + <string name="faq_shortcut">Atalho para iniciar</string> + <string name="no_vpn_support_image">A imagem não suporta a API VPNService, lamentamos :(</string> <string name="encryption">Encriptação</string> + <string name="cipher_dialog_title">Digite o método de encriptação</string> + <string name="settings_auth">Autenticação/encriptação</string> + <string name="file_explorer_tab">Explorador de ficheiros</string> + <string name="inline_file_tab">Ficheiro embutido</string> + <string name="error_importing_file">Erro ao importar ficheiro</string> + <string name="import_error_message">Não foi possÃvel importar o ficheiro</string> + <string name="inline_file_data">[[Dados do ficheiro embutido]]</string> + <string name="opentun_no_ipaddr">ImpossÃvel abrir dispositivo tun sem informações de IP</string> + <string name="menu_import">Importar Perfil a partir de um ficheiro ovpn</string> <string name="menu_import_short">Importar</string> + <string name="import_content_resolve_error">Não foi possÃvel ler o perfil a importação</string> + <string name="error_reading_config_file">Erro ao ler o ficheiro de configuração</string> + <string name="add_profile">Adicionar perfil</string> + <string name="import_could_not_open">Não foi possÃvel encontrar o ficheiro %1$s mencionado no ficheiro de configuração importado</string> + <string name="importing_config">A importar ficheiro configuração a partir de %1$s</string> + <string name="import_done">Terminou a leitura do ficheiro de configuração.</string> + <string name="nobind_summary">Não ligar a endereço e porta local</string> + <string name="no_bind">Não permitir ligações \'locais\'</string> + <string name="import_configuration_file">Importar o ficheiro de configuração</string> + <string name="faq_security_title">Considerações de segurança</string> + <string name="faq_security">"Como OpenVPN é segurança sensÃveis algumas notas sobre segurança são sensatas. Todos os dados no sdcard é inerentemente inseguro. Cada aplicativo pode lê-lo (por exemplo, este programa não requer direitos especiais cartão SD). Os dados desta aplicação só pode ser lido pelo próprio aplicativo. Ao usar a opção de importação para cacert / cert / chave no diálogo os dados do arquivo é armazenado no perfil de VPN. Os perfis de VPN são acessÃveis apenas por esta aplicação. (Não se esqueça de apagar as cópias no sd cartão depois). Mesmo com acesso apenas por este aplicativo os dados ainda não é criptografado. torcendo por telefone ou outros exploits pode ser possÃvel recuperar os dados. senhas salvas são armazenadas em texto simples assim. Para arquivos PKCS12 é altamente recomendável que você importá-los para o armazenamento de chaves android. "</string> <string name="import_vpn">Importar</string> <string name="ipv4">IPv4</string> <string name="ipv6">IPv6</string> + <string name="speed_waiting">A esperar mensagem de estado...</string> + <string name="converted_profile">perfil importado</string> + <string name="converted_profile_i">Perfil importado %d</string> + <string name="broken_images">Imagens quebradas</string> + <string name="private_key_password">Senha de chave privada</string> <string name="password">Senha</string> + <string name="file_icon">Ãcone de ficheiro</string> + <string name="tls_authentication">Autenticação TLS</string> + <string name="generated_config">Config gerado</string> <string name="generalsettings">Configurações</string> + <string name="owner_fix">Corrija a propriedade de /dev/tun</string> + <string name="edit_profile_title">A editar \"%s\"</string> + <string name="building_configration">A preparar a configuração...</string> + <string name="netchange">Volte a ligar na mudança de rede</string> + <string name="netstatus">Estado da rede: %s</string> + <string name="select_file">Selecione</string> + <string name="show_log_window">Mostrar a janela de log</string> + <string name="faq_system_dialogs_title">Aviso de ligação e som de notificação</string> + <string name="ipdns">IP e DNS</string> + <string name="basic">Básico</string> + <string name="routing">Encaminhamento</string> <string name="advanced">Avançado</string> + <string name="faq_howto_title">InÃcio Rápido</string> + <string name="using_proxy">A utilizar proxy %1$s %2$d</string> + <string name="use_system_proxy">Usar a proxy do sistema</string> + <string name="onbootrestart">Volte a ligar na reinicialização</string> <string name="ignore">Ignorar</string> <string name="restart">Reiniciar</string> - <string name="state_connecting">Conectando</string> + <string name="restart_vpn_after_change">As alterações de configuração são aplicadas depois de reiniciar a VPN. Reiniciar a VPN agora?</string> + <string name="configuration_changed">Configuração alterada</string> + <string name="faq_duplicate_notification_title">Notificações duplicadas</string> + <string name="no_vpn_profiles_defined">Não há perfis de VPN definidos.</string> + <string name="add_new_vpn_hint">Use o < img src = \"ic_menu_add\" / > Ãcone para adicionar uma nova VPN</string> + <string name="vpn_import_hint">Use o < img src = \"ic_menu_archive\" / > Ãcone para importar um perfil existente (ovpn ou conf) do seu sdcard.</string> + <string name="faq_routing_title">Configuração de roteamento/Interface</string> + <string name="persistent_tun_title">Tun Persistente</string> + <string name="openvpn_log">OpenVPN Log</string> + <string name="import_config">Importar configuração OpenVPN</string> + <string name="battery_consumption_title">Consumo de bateria</string> + <string name="vpn_tethering_title">VPN e Tethering</string> + <string name="connection_retries">Tentativas de ligação</string> + <string name="reconnection_settings">Configurações de religação</string> + <string name="connectretrywait">Segundos entre ligações</string> + <string name="send_minidump">Enviar Minidump para desenvolvedor</string> + <string name="notifcation_title">OpenVPN - %s</string> + <string name="session_ipv4string">%1$s - %2$s</string> + <string name="session_ipv6string">%1$s - %3$s, %2$s</string> + <string name="state_connecting">A ligar</string> + <string name="state_wait">A esperar pela resposta do servidor</string> <string name="state_auth">Autenticando</string> - <string name="state_connected">Conectado</string> - <string name="add">Add</string> - <string name="pauseVPN">Pausa VPN</string> + <string name="state_get_config">A obter a configuração do cliente</string> + <string name="state_assign_ip">Atribuindo endereços IP</string> + <string name="state_add_routes">Adicionando rotas</string> + <string name="state_connected">Ligado</string> + <string name="state_disconnected">Desligado</string> + <string name="state_reconnecting">A religar</string> + <string name="state_exiting">A sair</string> + <string name="state_noprocess">Parado</string> + <string name="state_resolve">A resolver nomes de host</string> + <string name="state_tcp_connect">A ligar (TCP)</string> + <string name="state_auth_failed">Falha na autenticação</string> + <string name="state_nonetwork">A aguardar rede utilizável</string> + <string name="statusline_bytecount">↓%2$s/s %1$s - ↑%4$s/s %3$s</string> + <string name="notifcation_title_notconnect">Não ligado</string> + <string name="start_vpn_title">A ligar a VPN %s</string> + <string name="start_vpn_ticker">A ligar a VPN %s</string> + <string name="encryption_cipher">Cifra de encriptação</string> + <string name="packet_auth">Autenticação de pacotes</string> + <string name="auth_dialog_title">Selecione o método de autenticação de pacotes</string> + <string name="built_by">Feito por %s</string> + <string name="debug_build">compilação de debug</string> + <string name="official_build">compilação oficial</string> + <string name="make_selection_inline">Copiar para o perfil</string> + <string name="crashdump">Crashdump</string> + <string name="add">Adicionar</string> + <string name="send_config">Enviar ficheiro de configuração</string> + <string name="complete_dn">DN completo</string> + <string name="rdn">RDN (nome comum)</string> + <string name="rdn_prefix">Prefixo RDN</string> + <string name="tls_remote_deprecated">TLS-remoto (obsoleto)</string> + <string name="help_translate">Pode ajudar a traduzir, visite http://crowdin.net/project/ics-openvpn/invite</string> + <string name="prompt">%1$s tenta controlar %2$s</string> + <string name="remote_trust">Confio nesta aplicação.</string> + <string name="no_external_app_allowed">Nenhuma app pode usar a API externa</string> + <string name="allowed_apps">Aplicações permitidas:%s</string> + <string name="save_password">Guardar senha</string> + <string name="pauseVPN">Pausar VPN</string> <string name="resumevpn">Retomar VPN</string> - <string name="uploaded_data">Upload</string> - <string name="downloaded_data">Download</string> - <string name="vpn_status">Vpn Status</string> - <string name="logview_options">Ver opções</string> + <string name="state_userpause">VPN pausado por solicitação do utilizador</string> + <string name="cannotparsecert">Não é possÃvel mostrar as informações de certificado</string> + <string name="appbehaviour">Comportamento da aplicação</string> + <string name="vpnbehaviour">Comportamento VPN</string> + <string name="allow_vpn_changes">Permitir alterações aos perfis de VPN</string> + <string name="donatePlayStore">Como alternativa, pode enviar uma doação pela Play Store:</string> + <string name="thanks_for_donation">Obrigado por doar %s!</string> + <string name="logCleared">Log limpo.</string> + <string name="show_password">Mostrar a senha</string> + <string name="keyChainAccessError">Erro de acesso à s chaves: %s</string> + <string name="timestamp_short">Curto</string> + <string name="timestamp_iso">ISO</string> + <string name="timestamps">Carimbos de hora</string> + <string name="timestamps_none">Nenhum</string> + <string name="uploaded_data">Fazer upload</string> + <string name="downloaded_data">Transferir</string> + <string name="vpn_status">Estado da VPN</string> + <string name="logview_options">Opções de visualização</string> + <string name="unhandled_exception">Unhandled exception: %1$s\n\n%2$s</string> + <string name="unhandled_exception_context">%3$s: %1$s\n\n%2$s</string> + <string name="full_licenses">Licenças completas</string> + <string name="blocklocal_title">Ignorar VPN para redes locais</string> + <string name="userpw_file">Ficheiro de utilizador/senha</string> + <string name="imported_from_file">[Importado de: %s]</string> + <string name="import_log">Log de importação:</string> </resources> diff --git a/app/src/main/res/values-ro/strings-icsopenvpn.xml b/app/src/main/res/values-ro/strings-icsopenvpn.xml index 8ae2770e..ef4e3a75 100755 --- a/app/src/main/res/values-ro/strings-icsopenvpn.xml +++ b/app/src/main/res/values-ro/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> diff --git a/app/src/main/res/values-ru/strings-icsopenvpn.xml b/app/src/main/res/values-ru/strings-icsopenvpn.xml index 400269ec..e2bc930c 100755 --- a/app/src/main/res/values-ru/strings-icsopenvpn.xml +++ b/app/src/main/res/values-ru/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> diff --git a/app/src/main/res/values-sv/strings-icsopenvpn.xml b/app/src/main/res/values-sv/strings-icsopenvpn.xml index 1e4f3635..9b974522 100755 --- a/app/src/main/res/values-sv/strings-icsopenvpn.xml +++ b/app/src/main/res/values-sv/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> diff --git a/app/src/main/res/values-tr/strings-icsopenvpn.xml b/app/src/main/res/values-tr/strings-icsopenvpn.xml index a40df5bf..90ad068d 100755 --- a/app/src/main/res/values-tr/strings-icsopenvpn.xml +++ b/app/src/main/res/values-tr/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> @@ -86,6 +90,7 @@ <string name="use_default_title">Varsayılan Yolu kullan</string> <string name="custom_route_message">Özel yolları girin. CIDR biçimde tek hedef girin. \"10.0.0.0 / 8 2002 :: / 16\" aÄŸlar VPN üzerinden 10.0.0.0 / 8 ve 2002 :: / 16 doÄŸrudan.</string> <string name="custom_routes_title">Özel Yollar</string> + <string name="custom_routes_title_excluded">Dışlanan AÄŸlar</string> <string name="log_verbosity_level">Ayrıntı düzeyi Log</string> <string name="float_summary">Herhangi bir IP kimlik doÄŸrulaması paketlerini saÄŸlar</string> <string name="float_title">Herhangi bir IP kimlik doÄŸrulaması paketlerini saÄŸlar</string> diff --git a/app/src/main/res/values-uk/strings-icsopenvpn.xml b/app/src/main/res/values-uk/strings-icsopenvpn.xml index 97a1e9a4..92637b74 100755 --- a/app/src/main/res/values-uk/strings-icsopenvpn.xml +++ b/app/src/main/res/values-uk/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> diff --git a/app/src/main/res/values-zh-rCN/strings-icsopenvpn.xml b/app/src/main/res/values-zh-rCN/strings-icsopenvpn.xml index e49a2240..93e0cbb1 100755 --- a/app/src/main/res/values-zh-rCN/strings-icsopenvpn.xml +++ b/app/src/main/res/values-zh-rCN/strings-icsopenvpn.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> @@ -23,7 +27,7 @@ <string name="vpn_list_title">é…置文件</string> <string name="vpn_type">类型</string> <string name="pkcs12pwquery">PKCS12 密ç </string> - <string name="file_select">请选择...</string> + <string name="file_select">请选择…</string> <string name="file_nothing_selected">您必须选择一个文件</string> <string name="useTLSAuth">使用 TLS 身份验è¯</string> <string name="tls_direction">TLS æ–¹å‘</string> @@ -85,7 +89,6 @@ <string name="use_default_title">使用默认路由</string> <string name="custom_route_message">输入自定义路由。输入 CIDR æ ¼å¼åœ°å€ã€‚</string> <string name="custom_routes_title">自定义路由</string> - <string name="custom_routes_title_excluded">just</string> <string name="log_verbosity_level">日志详细级别</string> <string name="float_summary">å…许æ¥è‡ªä»»ä½• IP 的认è¯æ•°æ®åŒ…</string> <string name="float_title">å…许浮æœåŠ¡å™¨</string> @@ -100,7 +103,6 @@ <string name="local_ip_info">本地 IPv4: %1$s/%2$d IPv6: %3$s MTU: %4$d</string> <string name="dns_server_info">DNS æœåŠ¡å™¨: %1$s, 域å: %2$s</string> <string name="routes_info_excl">排除的路由: %1$s %2$s</string> - <string name="routes_debug">China</string> <string name="ip_not_cidr">已获得接å£ä¿¡æ¯ %1$s ä»¥åŠ %2$s,将第二个地å€ä½œä¸ºè¿œç¨‹åœ°å€ã€‚使用 /32 作为本地掩ç 。OpenVPN 给出的模å¼æ˜¯ \"%3$s\"。</string> <string name="route_not_cidr">æ— æ³•å°† %1$s å’Œ %2$s 作为 CIDR å½¢å¼çš„路由,将使用 /32 çš„å网掩ç 。</string> <string name="route_not_netip">çº æ£è·¯ç”± %1$s/%2$s 为 %3$s/%2$s</string> @@ -292,7 +294,7 @@ <string name="thanks_for_donation">æ„Ÿè°¢æèµ %sï¼</string> <string name="logCleared">日志已清除。</string> <string name="show_password">显示密ç </string> - <string name="keyChainAccessError">钥匙串访问错误: ï¼…s</string> + <string name="keyChainAccessError">钥匙串访问错误: %s</string> <string name="timestamp_short">çŸ</string> <string name="timestamp_iso">ISO</string> <string name="timestamps">时间戳</string> diff --git a/app/src/main/res/values-zh-rTW/strings-icsopenvpn.xml b/app/src/main/res/values-zh-rTW/strings-icsopenvpn.xml index e467dd5b..bd155362 100755 --- a/app/src/main/res/values-zh-rTW/strings-icsopenvpn.xml +++ b/app/src/main/res/values-zh-rTW/strings-icsopenvpn.xml @@ -1,5 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> -<!--Generated by crowdin.net--> +<!--Generated by crowdin.com--> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> +<!-- Generated by crowdin.net --> <resources> <string name="address">伺æœå™¨åœ°å€:</string> @@ -19,9 +24,10 @@ <string name="copyright_guicode">å–得原始碼與個案追蹤,å¯ä¸Š http://code.google.com/p/ics-openvpn/</string> <string name="copyright_others">本程åºä½¿ç”¨äº†ä»¥ä¸‹å…ƒä»¶ï¼Œå…¶ä½œè€…和授權資訊如下</string> <string name="about">關於</string> + <string name="vpn_list_title">è¨å®šæª”</string> <string name="vpn_type">é¡žåž‹</string> <string name="pkcs12pwquery">PKCS12 密碼</string> - <string name="file_select">é¸æ“‡â€¦</string> + <string name="file_select">é¸æ“‡…</string> <string name="file_nothing_selected">ä½ å¿…é ˆé¸æ“‡ä¸€å€‹æª”案</string> <string name="useTLSAuth">使用傳輸層防ç«ç‰†(TLS-Auth)</string> <string name="tls_direction">TLSæ–¹å‘</string> @@ -43,19 +49,22 @@ <string name="ipv4_format_error">解æžIPv4地å€æ™‚發生錯誤</string> <string name="custom_route_format_error">解æžè‡ªè¨‚路由時發生錯誤</string> <string name="vpn_shortcut">OpenVPNæ·å¾‘</string> - <string name="vpn_launch_title">連接到VPN</string> + <string name="vpn_launch_title">連線到VPN</string> <string name="shortcut_profile_notfound">在快æ·æ–¹å¼æ‰¾ä¸åˆ°æŒ‡å®šçš„è¨å®šæª”</string> <string name="random_host_prefix">隨機主機å稱å—首</string> <string name="random_host_summary">在主機å稱å‰åŠ å…¥6個隨機å—符</string> <string name="custom_config_title">啟用自訂é¸é …</string> <string name="custom_config_summary">自訂é¸é …,使用時請å°å¿ƒï¼</string> <string name="route_rejected">路由被Android拒絕</string> - <string name="cancel_connection">æ–·ç·š</string> + <string name="cancel_connection">ä¸æ–·é€£ç·š</string> + <string name="cancel_connection_long">ä¸æ–·VPN連線</string> <string name="clear_log">清除記錄檔</string> <string name="title_cancel">確èªå–消</string> + <string name="cancel_connection_query">ä¸æ–·å·²é€£æŽ¥çš„VPN/å–消æ£åœ¨å˜—試的連線?</string> <string name="remove_vpn">移除VPN</string> - <string name="check_remote_tlscert">檢查å°æ–¹å‡ºç¤ºçš„是å¦TLS伺æœå™¨æ†‘è‰</string> - <string name="check_remote_tlscert_title">é 期å°æ–¹å‡ºç¤ºTLS伺æœå™¨æ†‘è‰</string> + <string name="check_remote_tlscert_title">é 計TLSæœå‹™å™¨è‰æ›¸</string> + <string name="remote_tlscn_check_summary">檢查é 程æœå‹™å™¨è‰æ›¸çš„主題DN</string> + <string name="remote_tlscn_check_title">è‰æ›¸çš„主機å檢查</string> <string name="tls_key_auth">啟用傳輸層防ç«ç‰†(TLS-Auth)</string> <string name="tls_auth_file">TLSé©—è‰æª”</string> <string name="pull_on_summary">å‘伺æœå™¨è«‹æ±‚IP地å€, 路由和時間資訊</string> @@ -117,7 +126,9 @@ <string name="import_vpn">匯入</string> <string name="ipv4">IPv4</string> <string name="ipv6">IPv6</string> - <string name="speed_waiting">ç‰å¾…狀態訊æ¯â€¦</string> + <string name="speed_waiting">ç‰å¾…狀態訊毅</string> + <string name="converted_profile">匯入è¨å®šæª”</string> + <string name="converted_profile_i">匯入è¨å®šæª”%d</string> <string name="pkcs12_file_encryption_key">PKCS12æª”åŠ å¯†é‡‘é‘°</string> <string name="private_key_password">ç§å¯†é‡‘鑰密碼</string> <string name="password">密碼</string> @@ -128,45 +139,55 @@ <string name="owner_fix">ä¿®æ£ /dev/tun çš„æ“有者</string> <string name="generated_config_summary">顯示本程åºç”Ÿæˆçš„è¨å®šæª”</string> <string name="edit_profile_title">æ£åœ¨ç·¨è¼¯\"%s\"</string> - <string name="building_configration">æ£åœ¨ç”Ÿæˆè¨å®šæª”…</string> - <string name="netchange_summary">當網絡狀æ³è®Šæ›´æ™‚強制é‡æ–°é€£æŽ¥(例如從WiFi變æˆæ‰‹æ©Ÿç¶²çµ¡ï¼Œå之亦然)</string> - <string name="netchange">網絡異動時é‡æ–°é€£æŽ¥</string> + <string name="building_configration">æ£åœ¨ç”Ÿæˆè¨å®šæª”…</string> + <string name="netchange_summary">若切æ›æ¤é¸é …當網絡狀æ³è®Šæ›´æ™‚將強制é‡æ–°é€£ç·š(例如從WiFi變æˆæ‰‹æ©Ÿç¶²çµ¡ï¼Œå之亦然)</string> + <string name="netchange">網絡異動時é‡æ–°é€£ç·š</string> <string name="netstatus">網絡狀態: %s</string> <string name="select_file">é¸æ“‡</string> + <string name="show_log_summary">連接時顯示記錄檔視窗。記錄檔視窗å¯ä»¥éš¨æ™‚從通知欄ä¸é€²å…¥ã€‚</string> <string name="show_log_window">顯示記錄視窗</string> <string name="mobile_info">æ–¼ %1$s (%2$s) %3$s 上é‹è¡Œ, Android API 版本: %4$d</string> <string name="faq_system_dialogs_title">連線è¦å‘Šå’Œé€šçŸ¥æ™‚發出音效</string> - <string name="translationby">ç¹é«”ä¸æ–‡ ç”± 羊羊@è‡ªç”±ç¶²çµ¡ç ”ç©¶ä¸å¿ƒ <sora8964@gmail.com> ç¿»è¯</string> + <string name="translationby">ç¹é«”ä¸æ–‡</string> <string name="ipdns">IPå’ŒDNS</string> <string name="basic">基本</string> <string name="routing">路由</string> <string name="obscure">鮮為人知的OpenVPNè¨å®šï¼Œä¸€èˆ¬æƒ…æ³ä¸‹ä¸éœ€è¦æ´¾ä¸Šç”¨å ´ã€‚</string> <string name="advanced">進階</string> <string name="export_config_title">ICS Openvpn è¨å®š</string> - <string name="warn_no_dns">沒有任何DNS伺æœå™¨å¯ç”¨ï¼Œå¯èƒ½ç„¡æ³•é€²è¡Œç¶²åŸŸå稱解æžã€‚請考慮è¨ç½®è‡ªè¨‚çš„DNS伺æœå™¨</string> <string name="faq_howto_title">快速入門</string> <string name="setting_loadtun_summary">在連線å‰å˜—試載入Tun模組,需è¦Root。</string> <string name="setting_loadtun">載入Tun模組</string> <string name="getproxy_error">å–得代ç†ä¼ºæœå™¨è³‡è¨Šæ™‚發生錯誤: %s</string> <string name="using_proxy">使用代ç†ä¼ºæœå™¨ %1$s %2$d</string> <string name="use_system_proxy">使用系統代ç†</string> - <string name="use_system_proxy_summary">使用系統é…置的 HTTP/HTTPS 代ç†ä¼ºæœå™¨é€²è¡Œé€£æŽ¥ã€‚</string> + <string name="use_system_proxy_summary">使用系統é…置的 HTTP/HTTPS 代ç†ä¼ºæœå™¨é€²è¡Œé€£ç·šã€‚</string> <string name="donatewithpaypal">ä½ å¯ä»¥é€éŽ <a href=\"https://www.paypal.com/cgi-bin/webscr?hosted_button_id=R2M6ZP9AF25LS&amp;cmd=_s-xclick\">PayPal</a> æä¾›æ助</string> - <string name="onbootrestartsummary">如果在é‡æ–°é–‹æ©Ÿæˆ–關機å‰æ£é€£æŽ¥VPN,開機時自動é‡æ–°é€£æŽ¥ã€‚在使用這個é¸é …之å‰è«‹å…ˆé–±è®€é€£ç·šè¦å‘ŠFAQ。</string> - <string name="onbootrestart">開機時é‡æ–°é€£æŽ¥</string> + <string name="onbootrestartsummary">如果在é‡æ–°é–‹æ©Ÿæˆ–關機å‰æ£é€£ç·šVPN,開機時自動é‡æ–°é€£ç·šã€‚在使用這個é¸é …之å‰è«‹å…ˆé–±è®€é€£ç·šè¦å‘ŠFAQ。</string> + <string name="onbootrestart">開機時é‡æ–°é€£ç·š</string> <string name="ignore">忽略</string> <string name="restart">é‡ç½®</string> <string name="restart_vpn_after_change">é…置變更åªæœƒåœ¨é‡æ–°å•Ÿå‹•VPN時æ‰ç”Ÿæ•ˆï¼Œç¾åœ¨è¦(é‡æ–°)å•Ÿå‹•VPN嗎?</string> <string name="configuration_changed">è¨å®šå·²è®Šæ›´</string> + <string name="log_no_last_vpn">無法判斷最後一次連線使用的è¨å®šæª”ï¼Œå› æ¤ç„¡æ³•ç·¨è¼¯è¨å®šæª”。</string> <string name="faq_duplicate_notification_title">é‡è¤‡çš„通知</string> <string name="faq_routing_title">路由/ç¶²çµ¡ä»‹é¢ è¨å®š</string> <string name="openvpn_log">OpenVPN é‹ä½œè¨˜éŒ„</string> <string name="import_config">匯入 OpenVPN é…ç½®</string> <string name="battery_consumption_title">é›»æ± æ¶ˆè€—</string> <string name="vpn_tethering_title">VPN與å¯æ”œå¼ç„¡ç·šåŸºåœ°å°</string> - <string name="connection_retries">連線é‡è©¦æ¬¡æ•¸</string> - <string name="connectretrymessage">嘗試é‡æ–°é€£ç·šä¹‹é–“çš„ç‰å¾…秒數</string> - <string name="connectretrywait">é‡æ–°é€£æŽ¥é–“隔時間</string> + <string name="connection_retries">é‡æ–°é€£ç·šæ¬¡æ•¸</string> + <string name="reconnection_settings">é‡æ–°é€£ç·šè¨å®š</string> + <string name="connectretrymessage">嘗試é‡æ–°é€£ç·šä¹‹é–“çš„ç‰å¾…秒數。</string> + <string name="connectretrywait">é‡æ–°é€£ç·šçš„間隔時間</string> <string name="minidump_generated">OpenVPNéžé æœŸåœ°å´©æ½°ï¼Œä½ æˆ–è€…æœƒè€ƒæ…®åœ¨ä¸»é¸å–®ä¸‹å‚³é€Minidump給開發人員。</string> <string name="send_minidump">å‘開發人員傳é€Minidump</string> + <string name="state_connecting">連線ä¸</string> + <string name="state_connected">已連線</string> + <string name="state_disconnected">ä¸æ–·é€£ç·š</string> + <string name="state_reconnecting">æ£åœ¨é‡æ–°é€£ç·š</string> + <string name="state_tcp_connect">é€£ç·šä¸ (TCP)</string> + <string name="notifcation_title_notconnect">未連線</string> + <string name="start_vpn_title">æ£åœ¨é€£æŽ¥è‡³ VPN %s</string> + <string name="start_vpn_ticker">æ£åœ¨é€£æŽ¥è‡³ VPN %s</string> </resources> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 4f325078..9a53fe4c 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -1,4 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> + <resources> <dimen name="paddingItemsSidebarLog">20dp</dimen> <dimen name="stdpadding">8dp</dimen> diff --git a/app/src/main/res/values/strings-icsopenvpn.xml b/app/src/main/res/values/strings-icsopenvpn.xml index aadbff32..15bf8142 100755 --- a/app/src/main/res/values/strings-icsopenvpn.xml +++ b/app/src/main/res/values/strings-icsopenvpn.xml @@ -1,4 +1,7 @@ -<?xml version="1.0" encoding="utf-8"?> <!-- Generated by crowdin.net --> +<?xml version="1.0" encoding="utf-8"?> <!-- + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <!-- Generated by crowdin.net --> <resources> @@ -323,5 +326,7 @@ <string name="mssfix_value_dialog">Announce to TCP sessions running over the tunnel that they should limit their send packet sizes such that after OpenVPN has encapsulated them, the resulting UDP packet size that OpenVPN sends to its peer will not exceed this number of bytes. (default is 1450)</string> <string name="mssfix_checkbox">Override MSS value of TCP payload</string> <string name="mssfix_dialogtitle">Set MSS of TCP payload</string> + <string name="client_behaviour">Client behaviour</string> + <string name="clear_external_apps">Clear allowed external apps</string> </resources> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8c815786..3666b39c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -63,6 +63,7 @@ <string name="log_out_failed_message">Didn\'t logged out.</string> <string name="succesful_authentication_message">Authentication succeeded.</string> <string name="authentication_failed_message">Authentication failed.</string> + <string name="registration_failed_message">Registration failed..</string> <string name="successful_authed_cert_downloaded_message">Your own cert has been correctly downloaded.</string> <string name="authed_cert_download_failed_message">Your own cert has incorrectly been downloaded.</string> <string name="eip_status_start_pending">Initiating connection</string> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 95e709b3..7b26a4a7 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,20 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2011 The Android Open Source Project - Copyright (C) 2012 Arne Schwabe - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> + ~ Copyright (c) 2012-2014 Arne Schwabe + ~ Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + --> <resources> diff --git a/app/src/main/res/values/untranslatable.xml b/app/src/main/res/values/untranslatable.xml index b45d5ae7..619a550f 100644 --- a/app/src/main/res/values/untranslatable.xml +++ b/app/src/main/res/values/untranslatable.xml @@ -2450,4 +2450,24 @@ + + + + + + + + + + + + + + + + + + + + </resources>
\ No newline at end of file diff --git a/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java b/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java index b5a57234..03930c61 100644 --- a/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java +++ b/app/src/release/java/se/leap/bitmaskclient/ConfigurationWizard.java @@ -1,278 +1,372 @@ -/**
- * 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.DialogFragment;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.content.res.AssetManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.util.Log;
-import android.view.Display;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View.MeasureSpec;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.ProgressBar;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import java.io.IOException;
+/** + * 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.DialogFragment; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.content.res.AssetManager; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.Display; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View.MeasureSpec; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.ProgressBar; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.util.Iterator;
-import org.json.JSONException;
-import org.json.JSONObject;
+import java.util.Iterator; +import org.json.JSONException; +import org.json.JSONObject; + import se.leap.bitmaskclient.DownloadFailedDialog.DownloadFailedDialogInterface; import se.leap.bitmaskclient.NewProviderDialog.NewProviderDialogInterface; import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver; import se.leap.bitmaskclient.ProviderDetailFragment.ProviderDetailFragmentInterface; import se.leap.bitmaskclient.ProviderListContent.ProviderItem; +import se.leap.bitmaskclient.FragmentManagerEnhanced; + import se.leap.bitmaskclient.R; -
-/**
- * Activity that builds and shows the list of known available providers.
- *
- * It also allows the user to enter custom providers with a button.
- *
- * @author parmegv
- *
- */
-public class ConfigurationWizard extends Activity
-implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver {
-
- private ProgressBar mProgressBar;
- private TextView progressbar_description;
- private ProviderListFragment provider_list_fragment;
- private Intent mConfigState = new Intent();
-
- final public static String TAG = "se.leap.bitmaskclient.ConfigurationWizard";
- final public static String TYPE_OF_CERTIFICATE = "type_of_certificate";
- final public static String ANON_CERTIFICATE = "anon_certificate";
- final public static String AUTHED_CERTIFICATE = "authed_certificate";
-
- final protected static String PROVIDER_SET = "PROVIDER SET";
- final protected static String SERVICES_RETRIEVED = "SERVICES RETRIEVED";
+ +/** + * Activity that builds and shows the list of known available providers. + * + * It also allows the user to enter custom providers with a button. + * + * @author parmegv + * + */ +public class ConfigurationWizard extends Activity +implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderDetailFragmentInterface, DownloadFailedDialogInterface, Receiver { + + private ProgressBar mProgressBar; + private TextView progressbar_description; + private ProviderListFragment provider_list_fragment; + private Intent mConfigState = new Intent(); + + final public static String TAG = ConfigurationWizard.class.getSimpleName(); + final public static String TYPE_OF_CERTIFICATE = "type_of_certificate"; + final public static String ANON_CERTIFICATE = "anon_certificate"; + final public static String AUTHED_CERTIFICATE = "authed_certificate"; + + final protected static String PROVIDER_SET = "PROVIDER SET"; + final protected static String SERVICES_RETRIEVED = "SERVICES RETRIEVED"; final protected static String ASSETS_URL_FOLDER = "urls"; -
- public ProviderAPIResultReceiver providerAPI_result_receiver;
+ + public ProviderAPIResultReceiver providerAPI_result_receiver; private ProviderAPIBroadcastReceiver_Update providerAPI_broadcast_receiver_update; - private static SharedPreferences preferences;
+ private static SharedPreferences preferences; + FragmentManagerEnhanced fragment_manager; private static boolean setting_up_provider = false; -
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE);
-
- setContentView(R.layout.configuration_wizard_activity);
- mProgressBar = (ProgressBar) findViewById(R.id.progressbar_configuration_wizard);
- mProgressBar.setVisibility(ProgressBar.INVISIBLE);
- progressbar_description = (TextView) findViewById(R.id.progressbar_description);
- progressbar_description.setVisibility(TextView.INVISIBLE);
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- providerAPI_result_receiver.setReceiver(this);
- providerAPI_broadcast_receiver_update = new ProviderAPIBroadcastReceiver_Update();
- IntentFilter update_intent_filter = new IntentFilter(ProviderAPI.UPDATE_PROGRESSBAR);
- update_intent_filter.addCategory(Intent.CATEGORY_DEFAULT);
- registerReceiver(providerAPI_broadcast_receiver_update, update_intent_filter);
-
- loadPreseededProviders();
-
- // Only create our fragments if we're not restoring a saved instance
- if ( savedInstanceState == null ){
- // TODO Some welcome screen?
- // We will need better flow control when we have more Fragments (e.g. user auth)
- provider_list_fragment = ProviderListFragment.newInstance();
- Bundle arguments = new Bundle();
- int configuration_wizard_request_code = getIntent().getIntExtra(Dashboard.REQUEST_CODE, -1);
- if(configuration_wizard_request_code == Dashboard.SWITCH_PROVIDER) {
- arguments.putBoolean(ProviderListFragment.SHOW_ALL_PROVIDERS, true);
- }
- provider_list_fragment.setArguments(arguments);
-
- FragmentManager fragmentManager = getFragmentManager();
- fragmentManager.beginTransaction()
- .replace(R.id.configuration_wizard_layout, provider_list_fragment, ProviderListFragment.TAG)
- .commit();
- }
-
- // TODO: If exposing deep links into your app, handle intents here.
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- unregisterReceiver(providerAPI_broadcast_receiver_update);
- }
-
- public void refreshProviderList(int top_padding) {
- ProviderListFragment new_provider_list_fragment = new ProviderListFragment();
- Bundle top_padding_bundle = new Bundle();
- top_padding_bundle.putInt(ProviderListFragment.TOP_PADDING, top_padding);
- new_provider_list_fragment.setArguments(top_padding_bundle);
-
- FragmentManager fragmentManager = getFragmentManager();
- fragmentManager.beginTransaction()
- .replace(R.id.configuration_wizard_layout, new_provider_list_fragment, ProviderListFragment.TAG)
- .commit();
- }
-
- @Override
- public void onReceiveResult(int resultCode, Bundle resultData) {
- if(resultCode == ProviderAPI.PROVIDER_OK) {
- mConfigState.setAction(PROVIDER_SET);
-
- if (preferences.getBoolean(EIP.ALLOWED_ANON, false)){
- mConfigState.putExtra(SERVICES_RETRIEVED, true);
- downloadAnonCert();
- } else {
- mProgressBar.incrementProgressBy(1);
- mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE);
- setResult(RESULT_OK); - showProviderDetails(getCurrentFocus());
- } - } else if(resultCode == ProviderAPI.PROVIDER_NOK) {
- //refreshProviderList(0); - String reason_to_fail = resultData.getString(ProviderAPI.ERRORS);
- showDownloadFailedDialog(getCurrentFocus(), reason_to_fail);
- mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE); - preferences.edit().remove(Provider.KEY).commit();
- setting_up_provider = false; - setResult(RESULT_CANCELED, mConfigState);
- }
- else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
- mProgressBar.incrementProgressBy(1);
- mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE);
- //refreshProviderList(0);
- setResult(RESULT_OK);
- showProviderDetails(getCurrentFocus());
- } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
- //refreshProviderList(0);
- mProgressBar.setVisibility(ProgressBar.GONE);
- progressbar_description.setVisibility(TextView.GONE);
- //Toast.makeText(getApplicationContext(), R.string.incorrectly_downloaded_certificate_message, Toast.LENGTH_LONG).show();
- setResult(RESULT_CANCELED, mConfigState);
- } else if(resultCode == AboutActivity.VIEWED) { - // Do nothing, right now - // I need this for CW to wait for the About activity to end before going back to Dashboard. - } - }
-
- /**
- * Callback method from {@link ProviderListFragment.Callbacks}
- * indicating that the item with the given ID was selected.
- */
- @Override
- public void onItemSelected(String id) {
- //TODO Code 2 pane view
- // resetOldConnection();
- ProviderItem selected_provider = getProvider(id);
- int provider_index = getProviderIndex(id);
- - - startProgressBar(provider_index+1); - provider_list_fragment.hideAllBut(provider_index); - - setUpProvider(selected_provider.providerMainUrl()); - }
-
- @Override
- public void onBackPressed() {
+ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); + fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); + + setUpInitialUI(); + + loadPreseededProviders(); + + setUpProviderAPIResultReceiver(); + + // Only create our fragments if we're not restoring a saved instance + if ( savedInstanceState == null ) { + // TODO Some welcome screen? + // We will need better flow control when we have more Fragments (e.g. user auth) + setUpProviderList(); + } + + // TODO: If exposing deep links into your app, handle intents here. + } + + private void setUpInitialUI() { + setContentView(R.layout.configuration_wizard_activity); + + hideProgressBar(); + } + + private void hideProgressBar() { + mProgressBar = (ProgressBar) findViewById(R.id.progressbar_configuration_wizard); + mProgressBar.setVisibility(ProgressBar.INVISIBLE); + + progressbar_description = (TextView) findViewById(R.id.progressbar_description); + progressbar_description.setVisibility(TextView.INVISIBLE); + } + + private void setUpProviderList() { + provider_list_fragment = ProviderListFragment.newInstance(); + + Bundle arguments = new Bundle(); + int configuration_wizard_request_code = getIntent().getIntExtra(Dashboard.REQUEST_CODE, -1); + if(configuration_wizard_request_code == Dashboard.SWITCH_PROVIDER) + arguments.putBoolean(ProviderListFragment.SHOW_ALL_PROVIDERS, true); + + provider_list_fragment.setArguments(arguments); + + putProviderListFragment(provider_list_fragment); + } + + private void putProviderListFragment(ProviderListFragment fragment) { + fragment_manager.replace(R.id.configuration_wizard_layout, provider_list_fragment, ProviderListFragment.TAG); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(providerAPI_broadcast_receiver_update); + } + + private void setUpProviderAPIResultReceiver() { + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); + providerAPI_broadcast_receiver_update = new ProviderAPIBroadcastReceiver_Update(); + + IntentFilter update_intent_filter = new IntentFilter(ProviderAPI.UPDATE_PROGRESSBAR); + update_intent_filter.addCategory(Intent.CATEGORY_DEFAULT); + registerReceiver(providerAPI_broadcast_receiver_update, update_intent_filter); + } + + @Override + public void onReceiveResult(int resultCode, Bundle resultData) { + if(resultCode == ProviderAPI.PROVIDER_OK) { + mConfigState.setAction(PROVIDER_SET); + + if (preferences.getBoolean(EIP.ALLOWED_ANON, false)){ + mConfigState.putExtra(SERVICES_RETRIEVED, true); + + downloadAnonCert(); + } else { + mProgressBar.incrementProgressBy(1); + hideProgressBar(); + + setResult(RESULT_OK); + + showProviderDetails(); + } + } else if(resultCode == ProviderAPI.PROVIDER_NOK) { + hideProgressBar(); + preferences.edit().remove(Provider.KEY).commit(); + setting_up_provider = false; + + setResult(RESULT_CANCELED, mConfigState); + + String reason_to_fail = resultData.getString(ProviderAPI.ERRORS); + showDownloadFailedDialog(getCurrentFocus(), reason_to_fail); + } + else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { + mProgressBar.incrementProgressBy(1); + hideProgressBar(); + + setResult(RESULT_OK); + + showProviderDetails(); + } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { + hideProgressBar(); + + setResult(RESULT_CANCELED, mConfigState); + } else if(resultCode == AboutActivity.VIEWED) { + // Do nothing, right now + // I need this for CW to wait for the About activity to end before going back to Dashboard. + } + } + + /** + * Callback method from {@link ProviderListFragment.Callbacks} + * indicating that the item with the given ID was selected. + */ + @Override + public void onItemSelected(String id) { + //TODO Code 2 pane view + ProviderItem selected_provider = getProvider(id); + int provider_index = getProviderIndex(id); + + startProgressBar(provider_index+1); + provider_list_fragment.hideAllBut(provider_index); + + setUpProvider(selected_provider.providerMainUrl()); + } + + @Override + public void onBackPressed() { if(setting_up_provider) { stopSettingUpProvider(); - } else {
+ } else { usualBackButton(); } } -
- private void stopSettingUpProvider() {
- ProviderAPI.stop();
- mProgressBar.setVisibility(ProgressBar.GONE);
- mProgressBar.setProgress(0);
- progressbar_description.setVisibility(TextView.GONE);
- preferences.edit().remove(Provider.KEY).commit();
- setting_up_provider = false;
+ + private void stopSettingUpProvider() { + ProviderAPI.stop(); + mProgressBar.setVisibility(ProgressBar.GONE); + mProgressBar.setProgress(0); + progressbar_description.setVisibility(TextView.GONE); + preferences.edit().remove(Provider.KEY).commit(); + setting_up_provider = false; showAllProviders(); - }
-
- private void usualBackButton() {
- try {
- boolean is_provider_set_up = new JSONObject(preferences.getString(Provider.KEY, "no provider")) != null ? true : false;
- boolean is_provider_set_up_truly = new JSONObject(preferences.getString(Provider.KEY, "no provider")).length() != 0 ? true : false;
- if(!is_provider_set_up || !is_provider_set_up_truly) {
- askDashboardToQuitApp();
- } else {
- setResult(RESULT_OK);
- }
- } catch (JSONException e) {
- askDashboardToQuitApp();
- super.onBackPressed();
- e.printStackTrace();
- }
- super.onBackPressed();
- }
- private void askDashboardToQuitApp() {
- Intent ask_quit = new Intent();
- ask_quit.putExtra(Dashboard.ACTION_QUIT, Dashboard.ACTION_QUIT);
- setResult(RESULT_CANCELED, ask_quit);
- }
-
- private ProviderItem getProvider(String name) {
- Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
- while(providers_iterator.hasNext()) {
- ProviderItem provider = providers_iterator.next();
- if(provider.name().equalsIgnoreCase(name)) {
- return provider;
- }
- }
- return null;
- }
-
- private String getId(String provider_main_url_string) { + } + + private void usualBackButton() { + try { + boolean is_provider_set_up = new JSONObject(preferences.getString(Provider.KEY, "no provider")) != null ? true : false; + boolean is_provider_set_up_truly = new JSONObject(preferences.getString(Provider.KEY, "no provider")).length() != 0 ? true : false; + if(!is_provider_set_up || !is_provider_set_up_truly) { + askDashboardToQuitApp(); + } else { + setResult(RESULT_OK); + } + } catch (JSONException e) { + askDashboardToQuitApp(); + super.onBackPressed(); + e.printStackTrace(); + } + super.onBackPressed(); + } + private void askDashboardToQuitApp() { + Intent ask_quit = new Intent(); + ask_quit.putExtra(Dashboard.ACTION_QUIT, Dashboard.ACTION_QUIT); + setResult(RESULT_CANCELED, ask_quit); + } + + private ProviderItem getProvider(String name) { + Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator(); + while(providers_iterator.hasNext()) { + ProviderItem provider = providers_iterator.next(); + if(provider.name().equalsIgnoreCase(name)) { + return provider; + } + } + return null; + } + + private void startProgressBar() { + mProgressBar.setVisibility(ProgressBar.VISIBLE); + progressbar_description.setVisibility(TextView.VISIBLE); + mProgressBar.setProgress(0); + mProgressBar.setMax(3); + } + + private void startProgressBar(int list_item_index) { + startProgressBar(); + int measured_height = listItemHeight(list_item_index); + mProgressBar.setTranslationY(measured_height); + progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight()); + } + + private int getProviderIndex(String id) { + int index = 0; + Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator(); + while(providers_iterator.hasNext()) { + ProviderItem provider = providers_iterator.next(); + if(provider.name().equalsIgnoreCase(id)) { + break; + } else index++; + } + return index; + } + + private int listItemHeight(int list_item_index) { + ListView provider_list_view = (ListView)findViewById(android.R.id.list); + ListAdapter provider_list_adapter = provider_list_view.getAdapter(); + View listItem = provider_list_adapter.getView(0, null, provider_list_view); + listItem.setLayoutParams(new RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.WRAP_CONTENT, + RelativeLayout.LayoutParams.WRAP_CONTENT)); + WindowManager wm = (WindowManager) getApplicationContext() + .getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + int screenWidth = display.getWidth(); // deprecated + + int listViewWidth = screenWidth - 10 - 10; + int widthSpec = MeasureSpec.makeMeasureSpec(listViewWidth, + MeasureSpec.AT_MOST); + listItem.measure(widthSpec, 0); + + return listItem.getMeasuredHeight(); +} + + /** + * Loads providers data from url files contained in the assets folder + * @return true if the files were correctly read + */ + private boolean loadPreseededProviders() { + boolean loaded_preseeded_providers = true; + try { + //TODO Put that folder in a better place (also inside the "for") + String[] urls_filepaths = getAssets().list(ASSETS_URL_FOLDER); + for(String url_filepath : urls_filepaths) { + addNewProviderToList(url_filepath); + } + } catch (IOException e) { + loaded_preseeded_providers = false; + } + + return loaded_preseeded_providers; + } + + private void addNewProviderToList(String url_filepath) { + String provider_main_url = extractProviderMainUrlFromAssetsFile(ASSETS_URL_FOLDER + "/" + url_filepath); + if(getId(provider_main_url).isEmpty()) { + String provider_name = url_filepath.subSequence(0, url_filepath.lastIndexOf(".")).toString(); + ProviderListContent.addItem(new ProviderItem(provider_name, provider_main_url)); + } + } + + private String extractProviderMainUrlFromAssetsFile(String filepath) { + String provider_main_url = ""; + try { + InputStream input_stream_file_contents = getAssets().open(filepath); + byte[] urls_file_bytes = new byte[input_stream_file_contents.available()]; + input_stream_file_contents.read(urls_file_bytes); + String urls_file_content = new String(urls_file_bytes); + JSONObject file_contents = new JSONObject(urls_file_content); + provider_main_url = file_contents.getString(Provider.MAIN_URL); + } catch (JSONException e) { + } catch (IOException e) { + } + return provider_main_url; + } + + private String getId(String provider_main_url) { try { - URL provider_url = new URL(provider_main_url_string); - URL aux_provider_url; + URL provider_url = new URL(provider_main_url); Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator(); while(providers_iterator.hasNext()) { ProviderItem provider = providers_iterator.next(); - aux_provider_url = new URL(provider.providerMainUrl()); + URL aux_provider_url = new URL(provider.providerMainUrl()); if(isSameURL(provider_url, aux_provider_url)) { return provider.name(); } @@ -281,7 +375,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD e.printStackTrace(); } return ""; - }
+ } /** * Checks, whether 2 urls are pointing to the same location. @@ -303,214 +397,106 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD } return true; } -
- private void startProgressBar() {
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- mProgressBar.setProgress(0);
- mProgressBar.setMax(3);
- }
-
- private void startProgressBar(int list_item_index) {
- mProgressBar.setVisibility(ProgressBar.VISIBLE);
- progressbar_description.setVisibility(TextView.VISIBLE);
- mProgressBar.setProgress(0);
- mProgressBar.setMax(3);
- int measured_height = listItemHeight(list_item_index);
- mProgressBar.setTranslationY(measured_height);
- progressbar_description.setTranslationY(measured_height + mProgressBar.getHeight());
- }
-
- private int getProviderIndex(String id) {
- int index = 0;
- Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
- while(providers_iterator.hasNext()) {
- ProviderItem provider = providers_iterator.next();
- if(provider.name().equalsIgnoreCase(id)) {
- break;
- } else index++; - }
- return index;
- }
-
- private int listItemHeight(int list_item_index) {
- ListView provider_list_view = (ListView)findViewById(android.R.id.list);
- ListAdapter provider_list_adapter = provider_list_view.getAdapter();
- View listItem = provider_list_adapter.getView(0, null, provider_list_view);
- listItem.setLayoutParams(new RelativeLayout.LayoutParams(
- RelativeLayout.LayoutParams.WRAP_CONTENT,
- RelativeLayout.LayoutParams.WRAP_CONTENT));
- WindowManager wm = (WindowManager) getApplicationContext()
- .getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- int screenWidth = display.getWidth(); // deprecated
-
- int listViewWidth = screenWidth - 10 - 10;
- int widthSpec = MeasureSpec.makeMeasureSpec(listViewWidth,
- MeasureSpec.AT_MOST);
- listItem.measure(widthSpec, 0);
-
- return listItem.getMeasuredHeight();
-}
-
- /** - * Loads providers data from url files contained in the assets folder - * @return true if the files were correctly read - */ - private boolean loadPreseededProviders() { - boolean loaded_preseeded_providers = false; - String[] urls_filepaths = null; - try { - //TODO Put that folder in a better place (also inside the "for") - urls_filepaths = getAssets().list(ASSETS_URL_FOLDER); - String provider_name = ""; - for(String url_filepath : urls_filepaths) { - provider_name = url_filepath.subSequence(0, url_filepath.lastIndexOf(".")).toString(); - String provider_main_url = extractProviderMainUrlFromAssetsFile(ASSETS_URL_FOLDER + "/" + url_filepath); - if(getId(provider_main_url).isEmpty()) - ProviderListContent.addItem(new ProviderItem(provider_name, provider_main_url)); - loaded_preseeded_providers = true;
- } - } catch (IOException e) { - loaded_preseeded_providers = false; + + /** + * Asks ProviderAPI to download an anonymous (anon) VPN certificate. + */ + private void downloadAnonCert() { + Intent provider_API_command = new Intent(this, ProviderAPI.class); + + Bundle parameters = new Bundle(); + + parameters.putString(TYPE_OF_CERTIFICATE, ANON_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); } - return loaded_preseeded_providers; - } - - private String extractProviderMainUrlFromAssetsFile(String filepath) { - String provider_main_url = ""; - try { - InputStream input_stream_file_contents = getAssets().open(filepath); - byte[] urls_file_bytes = new byte[input_stream_file_contents.available()]; - input_stream_file_contents.read(urls_file_bytes); - String urls_file_content = new String(urls_file_bytes); - JSONObject file_contents = new JSONObject(urls_file_content); - provider_main_url = file_contents.getString(Provider.MAIN_URL); - } catch (JSONException e) { - } catch (IOException e) { + /** + * Open the new provider dialog + */ + public void addAndSelectNewProvider() { + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); + DialogFragment newFragment = NewProviderDialog.newInstance(); + newFragment.show(fragment_transaction, NewProviderDialog.TAG); } - return provider_main_url; - } - - /**
- * Asks ProviderAPI to download an anonymous (anon) VPN certificate.
- */
- private void downloadAnonCert() {
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
-
- Bundle parameters = new Bundle();
-
- parameters.putString(TYPE_OF_CERTIFICATE, ANON_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);
- }
-
- /**
- * Open the new provider dialog
- */
- public void addAndSelectNewProvider() {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(NewProviderDialog.TAG);
- if (previous_new_provider_dialog != null) {
- fragment_transaction.remove(previous_new_provider_dialog);
- }
- fragment_transaction.addToBackStack(null);
-
- DialogFragment newFragment = NewProviderDialog.newInstance();
- newFragment.show(fragment_transaction, NewProviderDialog.TAG);
- }
-
- /**
- * Open the new provider dialog with data
- */
+ + /** + * Open the new provider dialog with data + */ public void addAndSelectNewProvider(String main_url) { - FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(NewProviderDialog.TAG);
- if (previous_new_provider_dialog != null) {
- fragment_transaction.remove(previous_new_provider_dialog);
- }
-
- DialogFragment newFragment = NewProviderDialog.newInstance();
- Bundle data = new Bundle();
- data.putString(Provider.MAIN_URL, main_url);
- newFragment.setArguments(data);
- newFragment.show(fragment_transaction, NewProviderDialog.TAG);
- }
-
- /**
- * Once selected a provider, this fragment offers the user to log in,
- * use it anonymously (if possible)
- * or cancel his/her election pressing the back button.
- * @param view
- * @param reason_to_fail
- */
- public void showDownloadFailedDialog(View view, String reason_to_fail) {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_provider_details_dialog = getFragmentManager().findFragmentByTag(DownloadFailedDialog.TAG);
- if (previous_provider_details_dialog != null) {
- fragment_transaction.remove(previous_provider_details_dialog);
- }
- fragment_transaction.addToBackStack(null);
-
- DialogFragment newFragment = DownloadFailedDialog.newInstance(reason_to_fail);
- newFragment.show(fragment_transaction, DownloadFailedDialog.TAG);
- }
-
- /**
- * Once selected a provider, this fragment offers the user to log in,
- * use it anonymously (if possible)
- * or cancel his/her election pressing the back button.
- * @param view
- */
- public void showProviderDetails(View view) {
- if(setting_up_provider) {
- FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
- Fragment previous_provider_details_dialog = getFragmentManager().findFragmentByTag(ProviderDetailFragment.TAG);
- if (previous_provider_details_dialog != null) {
- fragment_transaction.remove(previous_provider_details_dialog);
- }
- fragment_transaction.addToBackStack(null);
-
- DialogFragment newFragment = ProviderDetailFragment.newInstance();
- newFragment.show(fragment_transaction, ProviderDetailFragment.TAG);
- }
- }
-
- public void showAndSelectProvider(String provider_main_url) {
+ FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(NewProviderDialog.TAG); + + DialogFragment newFragment = NewProviderDialog.newInstance(); + Bundle data = new Bundle(); + data.putString(Provider.MAIN_URL, main_url); + newFragment.setArguments(data); + newFragment.show(fragment_transaction, NewProviderDialog.TAG); + } + + /** + * Once selected a provider, this fragment offers the user to log in, + * use it anonymously (if possible) + * or cancel his/her election pressing the back button. + * @param view + * @param reason_to_fail + */ + public void showDownloadFailedDialog(View view, String reason_to_fail) { + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(DownloadFailedDialog.TAG); + + DialogFragment newFragment = DownloadFailedDialog.newInstance(reason_to_fail); + newFragment.show(fragment_transaction, DownloadFailedDialog.TAG); + } + + /** + * Once selected a provider, this fragment offers the user to log in, + * use it anonymously (if possible) + * or cancel his/her election pressing the back button. + * @param view + */ + private void showProviderDetails() { + if(setting_up_provider) { + FragmentTransaction fragment_transaction = fragment_manager.removePreviousFragment(ProviderDetailFragment.TAG); + + DialogFragment newFragment = ProviderDetailFragment.newInstance(); + newFragment.show(fragment_transaction, ProviderDetailFragment.TAG); + } + } + + public void showAndSelectProvider(String provider_main_url) { if(getId(provider_main_url).isEmpty()) - showProvider(provider_main_url);
+ showProvider(provider_main_url); autoSelectProvider(provider_main_url); - }
-
+ } + private void showProvider(final String provider_main_url) { - String provider_name = provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("\\/", "_");
- ProviderItem added_provider = new ProviderItem(provider_name, provider_main_url);
- provider_list_fragment.addItem(added_provider);
- }
-
+ String provider_name = provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("\\/", "_"); + ProviderItem added_provider = new ProviderItem(provider_name, provider_main_url); + provider_list_fragment.addItem(added_provider); + } + private void autoSelectProvider(String provider_main_url) { - onItemSelected(getId(provider_main_url));
- }
-
- /**
- * Asks ProviderAPI to download a new provider.json file
- * @param provider_name
- * @param provider_main_url
- */
- public void setUpProvider(String provider_main_url) {
- Intent provider_API_command = new Intent(this, ProviderAPI.class);
- Bundle parameters = new Bundle();
- parameters.putString(Provider.MAIN_URL, provider_main_url);
-
- provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER);
- provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
+ onItemSelected(getId(provider_main_url)); + } + + /** + * Asks ProviderAPI to download a new provider.json file + * @param provider_name + * @param provider_main_url + */ + public void setUpProvider(String provider_main_url) { + Intent provider_API_command = new Intent(this, ProviderAPI.class); + Bundle parameters = new Bundle(); + parameters.putString(Provider.MAIN_URL, provider_main_url); + + provider_API_command.setAction(ProviderAPI.SET_UP_PROVIDER); + provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - startService(provider_API_command);
+ startService(provider_API_command); setting_up_provider = true; } @@ -527,62 +513,62 @@ implements ProviderListFragment.Callbacks, NewProviderDialogInterface, ProviderD startService(provider_API_command); } } - @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item){
- switch (item.getItemId()){
+ @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.configuration_wizard_activity, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item){ + switch (item.getItemId()){ case R.id.about_leap: startActivityForResult(new Intent(this, AboutActivity.class), 0); return true; - case R.id.new_provider:
- addAndSelectNewProvider();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- public void showAllProviders() {
- provider_list_fragment = (ProviderListFragment) getFragmentManager().findFragmentByTag(ProviderListFragment.TAG);
- if(provider_list_fragment != null)
- provider_list_fragment.unhideAll();
- }
-
- public void cancelSettingUpProvider() {
- provider_list_fragment = (ProviderListFragment) getFragmentManager().findFragmentByTag(ProviderListFragment.TAG);
+ case R.id.new_provider: + addAndSelectNewProvider(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + public void showAllProviders() { + provider_list_fragment = (ProviderListFragment) fragment_manager.findFragmentByTag(ProviderListFragment.TAG); + if(provider_list_fragment != null) + provider_list_fragment.unhideAll(); + } + + public void cancelSettingUpProvider() { + provider_list_fragment = (ProviderListFragment) fragment_manager.findFragmentByTag(ProviderListFragment.TAG); if(provider_list_fragment != null) { - provider_list_fragment.removeLastItem();
- }
- preferences.edit().remove(Provider.KEY).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit();
- }
-
- @Override
- public void login() {
- Intent ask_login = new Intent();
- ask_login.putExtra(LogInDialog.VERB, LogInDialog.VERB);
- setResult(RESULT_OK, ask_login);
- setting_up_provider = false;
- finish();
- }
-
- @Override
- public void use_anonymously() {
- setResult(RESULT_OK);
- setting_up_provider = false;
- finish();
- }
-
- public class ProviderAPIBroadcastReceiver_Update extends BroadcastReceiver {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- int update = intent.getIntExtra(ProviderAPI.CURRENT_PROGRESS, 0);
- mProgressBar.setProgress(update);
- }
- }
-}
+ provider_list_fragment.removeLastItem(); + } + preferences.edit().remove(Provider.KEY).remove(EIP.ALLOWED_ANON).remove(EIP.KEY).commit(); + } + + @Override + public void login() { + Intent ask_login = new Intent(); + ask_login.putExtra(LogInDialog.TAG, LogInDialog.TAG); + setResult(RESULT_OK, ask_login); + setting_up_provider = false; + finish(); + } + + @Override + public void use_anonymously() { + setResult(RESULT_OK); + setting_up_provider = false; + finish(); + } + + public class ProviderAPIBroadcastReceiver_Update extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + int update = intent.getIntExtra(ProviderAPI.CURRENT_PROGRESS, 0); + mProgressBar.setProgress(update); + } + } +} diff --git a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java index ab05bc51..f419afaf 100644 --- a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java @@ -14,18 +14,25 @@ * 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.app.IntentService; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.ResultReceiver; +import android.util.Base64; +import android.util.Log; import java.io.DataOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.math.BigInteger; +import java.net.ConnectException; import java.net.CookieHandler; import java.net.CookieManager; import java.net.CookiePolicy; -import java.net.ConnectException; import java.net.MalformedURLException; import java.net.SocketTimeoutException; import java.net.URISyntaxException; @@ -33,10 +40,10 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.net.UnknownHostException; -import javax.net.ssl.SSLHandshakeException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.CertificateEncodingException; @@ -47,32 +54,21 @@ import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.Scanner; import java.util.NoSuchElementException; - +import java.util.Scanner; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; - import org.apache.http.client.ClientProtocolException; -import org.jboss.security.srp.SRPParameters; import org.json.JSONException; import org.json.JSONObject; - import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.ProviderListContent.ProviderItem; -import android.app.IntentService; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.os.ResultReceiver; -import android.util.Base64; -import android.util.Log; /** @@ -86,8 +82,6 @@ import android.util.Log; */ public class ProviderAPI extends IntentService { - private Handler mHandler; - final public static String SET_UP_PROVIDER = "setUpProvider", DOWNLOAD_NEW_PROVIDER_DOTJSON = "downloadNewProviderDotJSON", @@ -98,12 +92,10 @@ public class ProviderAPI extends IntentService { PARAMETERS = "parameters", RESULT_KEY = "result", RECEIVER_KEY = "receiver", - SESSION_ID_COOKIE_KEY = "session_id_cookie_key", - SESSION_ID_KEY = "session_id", ERRORS = "errors", UPDATE_PROGRESSBAR = "update_progressbar", CURRENT_PROGRESS = "current_progress", - TAG = "provider_api_tag" + TAG = ProviderAPI.class.getSimpleName(); ; final public static int @@ -130,6 +122,8 @@ public class ProviderAPI extends IntentService { private static String last_provider_main_url; private static boolean setting_up_provider = true; + private static SharedPreferences preferences; + private static String provider_api_url; public static void stop() { setting_up_provider = false; @@ -140,12 +134,18 @@ public class ProviderAPI extends IntentService { Log.v("ClassName", "Provider API"); } - @Override - public void onCreate() { - super.onCreate(); - mHandler = new Handler(); - CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER) ); + @Override + public void onCreate() { + super.onCreate(); + preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); + CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER)); + if(provider_api_url == null && preferences.contains(Provider.KEY)) { + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); + } catch (JSONException e) {} } + } public static String lastProviderMainUrl() { return last_provider_main_url; @@ -172,27 +172,26 @@ public class ProviderAPI extends IntentService { } } } else if (action.equalsIgnoreCase(SRP_REGISTER)) { - Bundle session_id_bundle = registerWithSRP(parameters); - if(session_id_bundle.getBoolean(RESULT_KEY)) { - receiver.send(SRP_REGISTRATION_SUCCESSFUL, session_id_bundle); + Bundle result = tryToRegister(parameters); + if(result.getBoolean(RESULT_KEY)) { + receiver.send(SRP_REGISTRATION_SUCCESSFUL, result); } else { - receiver.send(SRP_REGISTRATION_FAILED, session_id_bundle); + receiver.send(SRP_REGISTRATION_FAILED, result); } } else if (action.equalsIgnoreCase(SRP_AUTH)) { - Bundle session_id_bundle = authenticateBySRP(parameters); - if(session_id_bundle.getBoolean(RESULT_KEY)) { - receiver.send(SRP_AUTHENTICATION_SUCCESSFUL, session_id_bundle); - } else { - receiver.send(SRP_AUTHENTICATION_FAILED, session_id_bundle); - } + Bundle result = tryToAuthenticate(parameters); + if(result.getBoolean(RESULT_KEY)) { + receiver.send(SRP_AUTHENTICATION_SUCCESSFUL, result); + } else { + receiver.send(SRP_AUTHENTICATION_FAILED, result); + } } else if (action.equalsIgnoreCase(LOG_OUT)) { - if(logOut(parameters)) { + if(logOut()) { receiver.send(LOGOUT_SUCCESSFUL, Bundle.EMPTY); } else { receiver.send(LOGOUT_FAILED, Bundle.EMPTY); } } else if (action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)) { - Log.d(TAG, "action.equalsIgnoreCase(DOWNLOAD_CERTIFICATE)"); if(updateVpnCertificate()) { receiver.send(CORRECTLY_DOWNLOADED_CERTIFICATE, Bundle.EMPTY); } else { @@ -201,46 +200,50 @@ public class ProviderAPI extends IntentService { } } - private Bundle registerWithSRP(Bundle task) { + private Bundle tryToRegister(Bundle task) { Bundle session_id_bundle = new Bundle(); int progress = 0; - String username = (String) task.get(LogInDialog.USERNAME); - String password = (String) task.get(LogInDialog.PASSWORD); - String authentication_server = (String) task.get(Provider.API_URL); + String username = (String) task.get(SessionDialogInterface.USERNAME); + String password = (String) task.get(SessionDialogInterface.PASSWORD); + if(validUserLoginData(username, password)) { - - SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256"); - LeapSRPSession client = new LeapSRPSession(username, password, params); - byte[] salt = ConfigHelper.trim(client.calculateNewSalt()); - // byte[] salted_password = client.calculatePasswordHash(username, password, salt); - /* Calculate password verifier */ - BigInteger password_verifier = client.calculateV(username, password, salt); - /* Send to the server */ - JSONObject result = sendNewUserDataToSRPServer(authentication_server, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16)); - if(result.has(ERRORS)) - session_id_bundle = authFailedNotification(result, username); - else { - session_id_bundle.putString(LogInDialog.USERNAME, username); - session_id_bundle.putString(LogInDialog.PASSWORD, password); - session_id_bundle.putBoolean(RESULT_KEY, true); - } - Log.d(TAG, result.toString()); + session_id_bundle = register(username, password); broadcast_progress(progress++); } else { if(!wellFormedPassword(password)) { session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putString(LogInDialog.USERNAME, username); - session_id_bundle.putBoolean(LogInDialog.PASSWORD_INVALID_LENGTH, true); + session_id_bundle.putString(SessionDialogInterface.USERNAME, username); + session_id_bundle.putBoolean(SessionDialogInterface.PASSWORD_INVALID_LENGTH, true); } if(username.isEmpty()) { session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putBoolean(LogInDialog.USERNAME_MISSING, true); + session_id_bundle.putBoolean(SessionDialogInterface.USERNAME_MISSING, true); } } return session_id_bundle; } + + private Bundle register(String username, String password) { + LeapSRPSession client = new LeapSRPSession(username, password); + byte[] salt = client.calculateNewSalt(); + + BigInteger password_verifier = client.calculateV(username, password, salt); + + JSONObject api_result = sendNewUserDataToSRPServer(provider_api_url, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16)); + + Bundle result = new Bundle(); + if(api_result.has(ERRORS)) + result = authFailedNotification(api_result, username); + else { + result.putString(SessionDialogInterface.USERNAME, username); + result.putString(SessionDialogInterface.PASSWORD, password); + result.putBoolean(RESULT_KEY, true); + } + + return result; + } /** * Starts the authentication process using SRP protocol. @@ -248,63 +251,63 @@ public class ProviderAPI extends IntentService { * @param task containing: username, password and api url. * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if authentication was successful. */ - private Bundle authenticateBySRP(Bundle task) { - Bundle session_id_bundle = new Bundle(); + private Bundle tryToAuthenticate(Bundle task) { + Bundle result = new Bundle(); int progress = 0; - String username = (String) task.get(LogInDialog.USERNAME); - String password = (String) task.get(LogInDialog.PASSWORD); + String username = (String) task.get(SessionDialogInterface.USERNAME); + String password = (String) task.get(SessionDialogInterface.PASSWORD); if(validUserLoginData(username, password)) { - - String authentication_server = (String) task.get(Provider.API_URL); - JSONObject authentication_step_result = new JSONObject(); - - SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256"); - LeapSRPSession client = new LeapSRPSession(username, password, params); - byte[] A = client.exponential(); - broadcast_progress(progress++); - authentication_step_result = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); - try { - String salt = authentication_step_result.getString(LeapSRPSession.SALT); - broadcast_progress(progress++); - byte[] Bbytes = new BigInteger(authentication_step_result.getString("B"), 16).toByteArray(); - byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); - if(M1 != null) { - broadcast_progress(progress++); - authentication_step_result = sendM1ToSRPServer(authentication_server, username, M1); - setTokenIfAvailable(authentication_step_result); - byte[] M2 = new BigInteger(authentication_step_result.getString(LeapSRPSession.M2), 16).toByteArray(); - if(client.verify(M2)) { - session_id_bundle.putBoolean(RESULT_KEY, true); - broadcast_progress(progress++); - } else { - authFailedNotification(authentication_step_result, username); - } - } else { - session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putString(LogInDialog.USERNAME, username); - session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message)); - } - } catch (JSONException e) { - session_id_bundle = authFailedNotification(authentication_step_result, username); - e.printStackTrace(); - } + result = authenticate(username, password); broadcast_progress(progress++); } else { if(!wellFormedPassword(password)) { - session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putString(LogInDialog.USERNAME, username); - session_id_bundle.putBoolean(LogInDialog.PASSWORD_INVALID_LENGTH, true); + result.putBoolean(RESULT_KEY, false); + result.putString(SessionDialogInterface.USERNAME, username); + result.putBoolean(SessionDialogInterface.PASSWORD_INVALID_LENGTH, true); } if(username.isEmpty()) { - session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putBoolean(LogInDialog.USERNAME_MISSING, true); + result.putBoolean(RESULT_KEY, false); + result.putBoolean(SessionDialogInterface.USERNAME_MISSING, true); } } - return session_id_bundle; + return result; } + private Bundle authenticate(String username, String password) { + Bundle result = new Bundle(); + + LeapSRPSession client = new LeapSRPSession(username, password); + byte[] A = client.exponential(); + + JSONObject step_result = sendAToSRPServer(provider_api_url, username, new BigInteger(1, A).toString(16)); + try { + String salt = step_result.getString(LeapSRPSession.SALT); + byte[] Bbytes = new BigInteger(step_result.getString("B"), 16).toByteArray(); + byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); + if(M1 != null) { + step_result = sendM1ToSRPServer(provider_api_url, username, M1); + setTokenIfAvailable(step_result); + byte[] M2 = new BigInteger(step_result.getString(LeapSRPSession.M2), 16).toByteArray(); + if(client.verify(M2)) { + result.putBoolean(RESULT_KEY, true); + } else { + authFailedNotification(step_result, username); + } + } else { + result.putBoolean(RESULT_KEY, false); + result.putString(SessionDialogInterface.USERNAME, username); + result.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message)); + } + } catch (JSONException e) { + result = authFailedNotification(step_result, username); + e.printStackTrace(); + } + + return result; + } + private boolean setTokenIfAvailable(JSONObject authentication_step_result) { try { LeapSRPSession.setToken(authentication_step_result.getString(LeapSRPSession.TOKEN)); @@ -325,7 +328,7 @@ public class ProviderAPI extends IntentService { } catch(JSONException e) {} if(!username.isEmpty()) - user_notification_bundle.putString(LogInDialog.USERNAME, username); + user_notification_bundle.putString(SessionDialogInterface.USERNAME, username); user_notification_bundle.putBoolean(RESULT_KEY, false); return user_notification_bundle; @@ -369,13 +372,6 @@ public class ProviderAPI extends IntentService { * @param username * @param clientA First SRP parameter sent * @return response from authentication server - * @throws ClientProtocolException - * @throws IOException - * @throws JSONException - * @throws CertificateException - * @throws NoSuchAlgorithmException - * @throws KeyStoreException - * @throws KeyManagementException */ private JSONObject sendAToSRPServer(String server_url, String username, String clientA) { Map<String, String> parameters = new HashMap<String, String>(); @@ -390,13 +386,6 @@ public class ProviderAPI extends IntentService { * @param username * @param m1 Second SRP parameter sent * @return response from authentication server - * @throws ClientProtocolException - * @throws IOException - * @throws JSONException - * @throws CertificateException - * @throws NoSuchAlgorithmException - * @throws KeyStoreException - * @throws KeyManagementException */ private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) { Map<String, String> parameters = new HashMap<String, String>(); @@ -411,13 +400,6 @@ public class ProviderAPI extends IntentService { * @param salted_password * @param password_verifier * @return response from authentication server - * @throws ClientProtocolException - * @throws IOException - * @throws JSONException - * @throws CertificateException - * @throws NoSuchAlgorithmException - * @throws KeyStoreException - * @throws KeyManagementException */ private JSONObject sendNewUserDataToSRPServer(String server_url, String username, String salt, String password_verifier) { Map<String, String> parameters = new HashMap<String, String>(); @@ -435,13 +417,6 @@ public class ProviderAPI extends IntentService { * @param request_method * @param parameters * @return response from authentication server - * @throws IOException - * @throws JSONException - * @throws MalformedURLException - * @throws CertificateException - * @throws NoSuchAlgorithmException - * @throws KeyStoreException - * @throws KeyManagementException */ private JSONObject sendToServer(String url, String request_method, Map<String, String> parameters) { JSONObject json_response; @@ -527,9 +502,6 @@ public class ProviderAPI extends IntentService { return result.toString(); } - - - /** * Downloads a provider.json from a given URL, adding a new provider using the given name. * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider, the provider name and its provider.json url. @@ -545,7 +517,7 @@ public class ProviderAPI extends IntentService { } if(!PROVIDER_JSON_DOWNLOADED) - current_download = getAndSetProviderJson(last_provider_main_url); + current_download = getAndSetProviderJson(last_provider_main_url); if(PROVIDER_JSON_DOWNLOADED || (current_download.containsKey(RESULT_KEY) && current_download.getBoolean(RESULT_KEY))) { broadcast_progress(progress++); PROVIDER_JSON_DOWNLOADED = true; @@ -569,13 +541,13 @@ public class ProviderAPI extends IntentService { private Bundle downloadCACert() { Bundle result = new Bundle(); try { - JSONObject provider_json = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.KEY, "")); + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); String ca_cert_url = provider_json.getString(Provider.CA_CERT_URI); String cert_string = downloadWithCommercialCA(ca_cert_url); result.putBoolean(RESULT_KEY, true); if(validCertificate(cert_string) && setting_up_provider) { - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(Provider.CA_CERT, cert_string).commit(); + preferences.edit().putString(Provider.CA_CERT, cert_string).commit(); result.putBoolean(RESULT_KEY, true); } else { String reason_to_fail = pickErrorMessage(cert_string); @@ -596,20 +568,43 @@ public class ProviderAPI extends IntentService { return CA_CERT_DOWNLOADED; } - private boolean validCertificate(String cert_string) { - boolean result = false; - if(!ConfigHelper.checkErroneousDownload(cert_string)) { - X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(cert_string); - try { - Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT); - result = true; - } catch (CertificateEncodingException e) { - Log.d(TAG, e.getLocalizedMessage()); - } - } + private boolean validCertificate(String cert_string) { + boolean result = false; + if(!ConfigHelper.checkErroneousDownload(cert_string)) { + X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(cert_string); + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + String fingerprint = provider_json.getString(Provider.CA_CERT_FINGERPRINT); + String encoding = fingerprint.split(":")[0]; + String expected_fingerprint = fingerprint.split(":")[1]; + String real_fingerprint = base64toHex(Base64.encodeToString( + MessageDigest.getInstance(encoding).digest(certificate.getEncoded()), + Base64.DEFAULT)); + + result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim()); + } catch (JSONException e) { + result = false; + } catch (NoSuchAlgorithmException e) { + result = false; + } catch (CertificateEncodingException e) { + result = false; + } + } - return result; + return result; + } + + private String base64toHex(String base64_input) { + byte[] byteArray = Base64.decode(base64_input, Base64.DEFAULT); + int readBytes = byteArray.length; + StringBuffer hexData = new StringBuffer(); + int onebyte; + for (int i=0; i < readBytes; i++) { + onebyte = ((0x000000ff & byteArray[i]) | 0xffffff00); + hexData.append(Integer.toHexString(onebyte).substring(6)); } + return hexData.toString(); + } private Bundle getAndSetProviderJson(String provider_main_url) { Bundle result = new Bundle(); @@ -619,12 +614,13 @@ public class ProviderAPI extends IntentService { try { JSONObject provider_json = new JSONObject(provider_dot_json_string); + provider_api_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION); String name = provider_json.getString(Provider.NAME); //TODO setProviderName(name); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(Provider.KEY, provider_json.toString()).commit(); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putBoolean(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON)).commit(); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putBoolean(EIP.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_REGISTERED)).commit(); + preferences.edit().putString(Provider.KEY, provider_json.toString()).commit(); + preferences.edit().putBoolean(EIP.ALLOWED_ANON, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_ANON)).commit(); + preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, provider_json.getJSONObject(Provider.SERVICE).getBoolean(EIP.ALLOWED_REGISTERED)).commit(); result.putBoolean(RESULT_KEY, true); } catch (JSONException e) { @@ -637,24 +633,18 @@ public class ProviderAPI extends IntentService { return result; } - - - public static boolean providerJsonDownloaded() { - return PROVIDER_JSON_DOWNLOADED; - } - private Bundle getAndSetEipServiceJson() { Bundle result = new Bundle(); String eip_service_json_string = ""; if(setting_up_provider) { try { - JSONObject provider_json = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.KEY, "")); + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); String eip_service_url = provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH; eip_service_json_string = downloadWithProviderCA(eip_service_url); JSONObject eip_service_json = new JSONObject(eip_service_json_string); eip_service_json.getInt(Provider.API_RETURN_SERIAL); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.KEY, eip_service_json.toString()).commit(); + preferences.edit().putString(EIP.KEY, eip_service_json.toString()).commit(); result.putBoolean(RESULT_KEY, true); } catch (JSONException e) { @@ -665,10 +655,6 @@ public class ProviderAPI extends IntentService { } return result; } - - public static boolean eipServiceDownloaded() { - return EIP_SERVICE_JSON_DOWNLOADED; - } /** * Interprets the error message as a JSON object and extract the "errors" keyword pair. @@ -754,6 +740,7 @@ public class ProviderAPI extends IntentService { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnknownHostException e) { + e.printStackTrace(); json_file_content = formatErrorMessage(R.string.server_unreachable_message); } catch (IOException e) { // The downloaded certificate doesn't validate our https connection. @@ -768,13 +755,14 @@ public class ProviderAPI extends IntentService { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchElementException e) { + e.printStackTrace(); json_file_content = formatErrorMessage(R.string.server_unreachable_message); } return json_file_content; } private javax.net.ssl.SSLSocketFactory getProviderSSLSocketFactory() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException { - String provider_cert_string = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.CA_CERT,""); + String provider_cert_string = preferences.getString(Provider.CA_CERT,""); java.security.cert.Certificate provider_certificate = ConfigHelper.parseX509CertificateFromString(provider_cert_string); @@ -852,12 +840,11 @@ public class ProviderAPI extends IntentService { /** * Logs out from the api url retrieved from the task. - * @param task containing api url from which the user will log out * @return true if there were no exceptions */ - private boolean logOut(Bundle task) { + private boolean logOut() { try { - String delete_url = task.getString(Provider.API_URL) + "/logout"; + String delete_url = provider_api_url + "/logout"; int progress = 0; HttpsURLConnection urlConnection = (HttpsURLConnection)new URL(delete_url).openConnection(); @@ -899,7 +886,6 @@ public class ProviderAPI extends IntentService { private boolean updateVpnCertificate() { getNewCert(); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putInt(EIP.PARSED_SERIAL, 0).commit(); Intent updateEIP = new Intent(getApplicationContext(), EIP.class); updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE); startService(updateEIP); @@ -913,65 +899,55 @@ public class ProviderAPI extends IntentService { * @return true if certificate was downloaded correctly, false if provider.json is not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error. */ private boolean getNewCert() { - - try { - JSONObject provider_json = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.KEY, "")); + try { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - String provider_main_url = provider_json.getString(Provider.API_URL); - URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.CERTIFICATE); + String provider_main_url = provider_json.getString(Provider.API_URL); + URL new_cert_string_url = new URL(provider_main_url + "/" + provider_json.getString(Provider.API_VERSION) + "/" + EIP.CERTIFICATE); - String cert_string = downloadWithProviderCA(new_cert_string_url.toString()); + String cert_string = downloadWithProviderCA(new_cert_string_url.toString()); - if(!cert_string.isEmpty()) { - if(ConfigHelper.checkErroneousDownload(cert_string)) { - String reason_to_fail = provider_json.getString(ERRORS); - //result.putString(ConfigHelper.ERRORS_KEY, reason_to_fail); - //result.putBoolean(ConfigHelper.RESULT_KEY, false); - return false; - } else { - - // API returns concatenated cert & key. Split them for OpenVPN options - String certificateString = null, keyString = null; - String[] certAndKey = cert_string.split("(?<=-\n)"); - for (int i=0; i < certAndKey.length-1; i++){ - if ( certAndKey[i].contains("KEY") ) { - keyString = certAndKey[i++] + certAndKey[i]; - } - else if ( certAndKey[i].contains("CERTIFICATE") ) { - certificateString = certAndKey[i++] + certAndKey[i]; - } - } - try { - RSAPrivateKey keyCert = ConfigHelper.parseRsaKeyFromString(keyString); - keyString = Base64.encodeToString( keyCert.getEncoded(), Base64.DEFAULT ); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit(); - - X509Certificate certCert = ConfigHelper.parseX509CertificateFromString(certificateString); - certificateString = Base64.encodeToString( certCert.getEncoded(), Base64.DEFAULT); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit(); - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putString(EIP.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit(); - return true; - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } - } - } else { - return false; - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - } /*catch (URISyntaxException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; - }*/ + if(cert_string.isEmpty() || ConfigHelper.checkErroneousDownload(cert_string)) + return false; + else + return loadCertificate(cert_string); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } } + + private boolean loadCertificate(String cert_string) { + try { + // API returns concatenated cert & key. Split them for OpenVPN options + String certificateString = null, keyString = null; + String[] certAndKey = cert_string.split("(?<=-\n)"); + for (int i=0; i < certAndKey.length-1; i++){ + if ( certAndKey[i].contains("KEY") ) { + keyString = certAndKey[i++] + certAndKey[i]; + } + else if ( certAndKey[i].contains("CERTIFICATE") ) { + certificateString = certAndKey[i++] + certAndKey[i]; + } + } + RSAPrivateKey key = ConfigHelper.parseRsaKeyFromString(keyString); + keyString = Base64.encodeToString(key.getEncoded(), Base64.DEFAULT); + preferences.edit().putString(EIP.PRIVATE_KEY, "-----BEGIN RSA PRIVATE KEY-----\n"+keyString+"-----END RSA PRIVATE KEY-----").commit(); + + X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificateString); + certificateString = Base64.encodeToString(certificate.getEncoded(), Base64.DEFAULT); + preferences.edit().putString(EIP.CERTIFICATE, "-----BEGIN CERTIFICATE-----\n"+certificateString+"-----END CERTIFICATE-----").commit(); + preferences.edit().putString(EIP.DATE_FROM_CERTIFICATE, EIP.certificate_date_format.format(Calendar.getInstance().getTime())).commit(); + return true; + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + } } |