From e4b49fb3cfb1e69cc4617bfcc5b20cbc22df4f8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 22 Dec 2014 11:22:29 +0100 Subject: Check for null certificate on validCertificate --- .../java/se/leap/bitmaskclient/ProviderAPI.java | 21 ++++++++++++--------- .../java/se/leap/bitmaskclient/ProviderAPI.java | 22 +++++++++++++--------- 2 files changed, 25 insertions(+), 18 deletions(-) (limited to 'app') diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java index 886d70a0..ce13d322 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java @@ -554,15 +554,18 @@ public class ProviderAPI extends IntentService { 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()); + if(certificate != null) { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + String fingerprint = provider_json.getString(Provider.CA_CERT_FINGERPRINT); + String encoding = fingerprint.split(":")[0]; + String expected_fingerprint = fingerprint.split(":")[1]; + String real_fingerprint = base64toHex(Base64.encodeToString( + MessageDigest.getInstance(encoding).digest(certificate.getEncoded()), + Base64.DEFAULT)); + + result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim()); + } else + result = false; } catch (JSONException e) { result = false; } catch (NoSuchAlgorithmException e) { diff --git a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java index 9d0b4db6..8b8cabdf 100644 --- a/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/release/java/se/leap/bitmaskclient/ProviderAPI.java @@ -547,15 +547,19 @@ public class ProviderAPI extends IntentService { 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()); + if(certificate != null) { + JSONObject provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); + String fingerprint = provider_json.getString(Provider.CA_CERT_FINGERPRINT); + String encoding = fingerprint.split(":")[0]; + String expected_fingerprint = fingerprint.split(":")[1]; + String real_fingerprint = base64toHex(Base64.encodeToString( + MessageDigest.getInstance(encoding).digest(certificate.getEncoded()), + Base64.DEFAULT)); + + result = real_fingerprint.trim().equalsIgnoreCase(expected_fingerprint.trim()); + } + else + result = false; } catch (JSONException e) { result = false; } catch (NoSuchAlgorithmException e) { -- cgit v1.2.3 From deb2cfdeb174822e5550924ac1000f30d948c1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 22 Dec 2014 11:45:56 +0100 Subject: New SessionDialog if any argument previously --- app/src/main/java/se/leap/bitmaskclient/SessionDialog.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java index 22e0f128..a8226d30 100644 --- a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java @@ -129,15 +129,15 @@ public class SessionDialog extends DialogFragment{ SessionDialogInterface interface_with_Dashboard; - /** - * @return a new instance of this DialogFragment. - */ - public static DialogFragment newInstance() { - if(dialog == null) - dialog = new SessionDialog(); + /** + * @return a new instance of this DialogFragment. + */ + public static DialogFragment newInstance() { + if(dialog == null || dialog.getArguments() != null) + dialog = new SessionDialog(); return dialog; - } + } @Override public void onAttach(Activity activity) { -- cgit v1.2.3 From 58f4ae104c189cdf258bfb05e3795fbca8dac2cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 22 Dec 2014 12:10:01 +0100 Subject: Revert deb2cfd & avoid arguments if previous fragment != null --- app/src/main/java/se/leap/bitmaskclient/Dashboard.java | 4 ++-- app/src/main/java/se/leap/bitmaskclient/SessionDialog.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index e32dbdee..52b22695 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -329,7 +329,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG); DialogFragment newFragment = SessionDialog.newInstance(); - if(resultData != null && !resultData.isEmpty()) + if(resultData != null && !resultData.isEmpty() && fragment_manager.findFragmentByTag(SessionDialog.TAG) == null) newFragment.setArguments(resultData); newFragment.show(transaction, SessionDialog.TAG); } @@ -378,7 +378,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG); DialogFragment newFragment = SessionDialog.newInstance(); - if(resultData != null && !resultData.isEmpty()) { + if(resultData != null && !resultData.isEmpty() && fragment_manager.findFragmentByTag(SessionDialog.TAG) == null) { newFragment.setArguments(resultData); } newFragment.show(transaction, SessionDialog.TAG); diff --git a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java index a8226d30..fd9ca851 100644 --- a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java @@ -133,8 +133,8 @@ public class SessionDialog extends DialogFragment{ * @return a new instance of this DialogFragment. */ public static DialogFragment newInstance() { - if(dialog == null || dialog.getArguments() != null) - dialog = new SessionDialog(); + if(dialog == null) + dialog = new SessionDialog(); return dialog; } -- cgit v1.2.3 From 2d07852eb6f89f9c5c8650201741bce0259e1699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 22 Dec 2014 12:17:02 +0100 Subject: 0.8.2 changelog and version number&code --- app/src/main/AndroidManifest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4893ce4c..2a9f6b60 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,8 +17,8 @@ + android:versionCode="108" + android:versionName="0.8.2" > -- cgit v1.2.3 From a3e93c14fbd82d7f4229f30bbcb622e5ddb71983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 18 Dec 2014 16:40:07 +0100 Subject: Log out before starting Configuration Wizard. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 28 +++++++++++++--------- .../java/se/leap/bitmaskclient/EipFragment.java | 1 + 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 52b22695..cf65c9b8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -81,6 +81,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn private Provider provider; private static boolean authed_eip; public ProviderAPIResultReceiver providerAPI_result_receiver; + private boolean switching_provider; @Override protected void onSaveInstanceState(@NotNull Bundle outState) { @@ -288,15 +289,11 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn startActivity(startLW); return true; case R.id.switch_provider: - if (provider.hasEIP()){ - if (preferences.getBoolean(Constants.AUTHED_EIP, false)) { - logOut(); - } - eip_fragment.askToStopEIP(); - } - preferences.edit().clear().apply(); - startActivityForResult(new Intent(this,ConfigurationWizard.class), SWITCH_PROVIDER); - return true; + switching_provider = true; + if (preferences.getBoolean(Constants.AUTHED_EIP, false)) { + logOut(); + } else switchProvider(); + return true; case R.id.login_button: logInDialog(Bundle.EMPTY); return true; @@ -307,7 +304,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn signUpDialog(Bundle.EMPTY); return true; default: - return super.onOptionsItemSelected(item); + return super.onOptionsItemSelected(item); } } @@ -402,6 +399,13 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn startService(provider_API_command); } + private void switchProvider() { + if (provider.hasEIP()) eip_fragment.askToStopEIP(); + preferences.edit().clear().apply(); + switching_provider = false; + startActivityForResult(new Intent(this,ConfigurationWizard.class), SWITCH_PROVIDER); + } + /** * Asks ProviderAPI to download an authenticated OpenVPN certificate. */ @@ -456,7 +460,9 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn authed_eip = false; preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); - + + if(switching_provider) switchProvider(); + } else if(resultCode == ProviderAPI.LOGOUT_FAILED) { changeStatusMessage(resultCode); hideProgressBar(); diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 420da7a1..59e9ca5a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -211,6 +211,7 @@ public class EipFragment extends Fragment implements Observer { String status = parent_activity.getString(R.string.eip_state_not_connected); status_message.setText(status); + eipCommand(Constants.ACTION_STOP_EIP); } -- cgit v1.2.3 From 20049d1dbca7c032f2f88824098d9b39c71712d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 23 Dec 2014 19:46:58 +0100 Subject: -100 lines on Dashboard, gradle fix. Gradle doesn't invoke updateIcsOpenVpn task unless the task is explicitly invoked. I needed to put all the related tasks into the configuration phase, rather than on the execution one. --- app/build.gradle | 21 +- .../main/java/se/leap/bitmaskclient/Dashboard.java | 635 +++++++++------------ .../java/se/leap/bitmaskclient/EipFragment.java | 10 +- app/src/main/res/values/strings.xml | 6 +- 4 files changed, 289 insertions(+), 383 deletions(-) (limited to 'app') diff --git a/app/build.gradle b/app/build.gradle index 7d6d0a2c..dc020813 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -52,7 +52,8 @@ def processFileInplace(file, Closure processText) { } -task checkoutStrippedIcsOpenVPN ( type: Copy ) { +task checkoutStrippedIcsOpenVPN ( type: Copy ) << { + println "checkoutStrippedIcsOpenVPN" //FIXME Checkout ics-openvpn-stripped from branch "ics-openvpn-upstream" //grgit = Grgit.open(project.file('../')) @@ -60,7 +61,8 @@ task checkoutStrippedIcsOpenVPN ( type: Copy ) { into '../ics-openvpn-stripped' } -task copyIcsOpenVPNClasses( type: Copy ) { +task copyIcsOpenVPNClasses( type: Copy ) << { + println "copyIcsOpenVPNClasses" from ('../ics-openvpn-stripped/main/') { include '**/*.java' include '**/*.aidl' @@ -79,7 +81,8 @@ task copyIcsOpenVPNClasses( type: Copy ) { } into '.' } -task copyIcsOpenVPNXml( type: Copy ) { +task copyIcsOpenVPNXml( type: Copy ) << { + println "copyIcsOpenVPNXml" from ('../ics-openvpn-stripped/main/') { include '**/strings.xml' include '**/log_*.xml' @@ -97,7 +100,8 @@ task copyIcsOpenVPNXml( type: Copy ) { } into '.' } -task copyIcsOpenVPNImages( type: Copy ) { +task copyIcsOpenVPNImages( type: Copy ) << { + println "copyIcsOpenVPNImages" from ('../ics-openvpn-stripped/main/') { include '**/ic_filter*.png' include '**/ic_delete*.png' @@ -107,7 +111,8 @@ task copyIcsOpenVPNImages( type: Copy ) { } into '.' } -task copyIcsOpenVPNFiles( type: Copy, dependsOn: 'checkoutStrippedIcsOpenVPN' ) { +task copyIcsOpenVPNFiles( type: Copy, dependsOn: 'checkoutStrippedIcsOpenVPN' ) << { + println "copyIcsOpenVPNFiles" copyIcsOpenVPNClasses.execute() copyIcsOpenVPNXml.execute() copyIcsOpenVPNImages.execute() @@ -115,6 +120,7 @@ task copyIcsOpenVPNFiles( type: Copy, dependsOn: 'checkoutStrippedIcsOpenVPN' ) // thanks to http://pleac.sourceforge.net/pleac_groovy/fileaccess.html task removeDuplicatedStrings( dependsOn: 'copyIcsOpenVPNFiles' ) << { + println "removeDuplicatedStrings" new File('app').eachFileRecurse { if(it.name.equals('strings.xml')) { def ics_openvpn_file = file(it.absolutePath.replace('strings.xml', 'strings-icsopenvpn.xml')) @@ -132,7 +138,8 @@ task removeDuplicatedStrings( dependsOn: 'copyIcsOpenVPNFiles' ) << { } } -task mergeUntranslatable( type: Copy, dependsOn: 'removeDuplicatedStrings') { +task mergeUntranslatable( type: Copy, dependsOn: 'removeDuplicatedStrings') << { + println "mergeUntranslatable" from ('../ics-openvpn-stripped/main/') { include '**/untranslatable.xml' rename 'untranslatable.xml', 'untranslatable-icsopenvpn.xml' @@ -165,6 +172,7 @@ task mergeUntranslatable( type: Copy, dependsOn: 'removeDuplicatedStrings') { } task updateIcsOpenVpn( type: Copy, dependsOn: 'mergeUntranslatable') << { + println "updateIcsOpenVpn" from('../ics-openvpn-stripped/main/src/') { include 'openvpn/**' include 'openssl/**' @@ -177,6 +185,7 @@ task updateIcsOpenVpn( type: Copy, dependsOn: 'mergeUntranslatable') << { } task buildNative ( type: Exec ) { + println "buildNative" commandLine 'sh', 'misc/build-native.sh', 'USE_BREAKPAD=0', '-j 8' } diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index cf65c9b8..659cd22c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -17,37 +17,21 @@ package se.leap.bitmaskclient; import android.annotation.SuppressLint; -import android.app.Activity; -import android.app.AlertDialog; -import android.app.DialogFragment; -import android.app.FragmentTransaction; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; +import android.app.*; +import android.content.*; import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Bundle; -import android.os.Handler; -import android.os.ResultReceiver; +import android.os.*; import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.widget.ProgressBar; -import android.widget.TextView; +import android.view.*; +import android.widget.*; import org.jetbrains.annotations.NotNull; -import org.json.JSONException; -import org.json.JSONObject; +import org.json.*; +import java.net.*; -import java.net.MalformedURLException; -import java.net.URL; - -import butterknife.ButterKnife; -import butterknife.InjectView; -import de.blinkt.openvpn.activities.LogWindow; -import se.leap.bitmaskclient.eip.Constants; -import se.leap.bitmaskclient.eip.EIP; -import se.leap.bitmaskclient.eip.EipStatus; +import butterknife.*; +import de.blinkt.openvpn.activities.*; +import se.leap.bitmaskclient.eip.*; /** * The main user facing Activity of Bitmask Android, consisting of status, controls, @@ -58,16 +42,16 @@ import se.leap.bitmaskclient.eip.EipStatus; */ public class Dashboard extends Activity implements SessionDialog.SessionDialogInterface, ProviderAPIResultReceiver.Receiver { - protected static final int CONFIGURE_LEAP = 0; - protected static final int SWITCH_PROVIDER = 1; + protected static final int CONFIGURE_LEAP = 0; + protected static final int SWITCH_PROVIDER = 1; - final public static String TAG = Dashboard.class.getSimpleName(); - final public static String SHARED_PREFERENCES = "LEAPPreferences"; - final public static String ACTION_QUIT = "quit"; + public static final String TAG = Dashboard.class.getSimpleName(); + public static final String SHARED_PREFERENCES = "LEAPPreferences"; + public static final String ACTION_QUIT = "quit"; public static final String REQUEST_CODE = "request_code"; public static final String PARAMETERS = "dashboard parameters"; public static final String START_ON_BOOT = "dashboard start on boot"; - final public static String ON_BOOT = "dashboard on boot"; + public static final String ON_BOOT = "dashboard on boot"; public static final String APP_VERSION = "bitmask version"; private static Context app; @@ -83,6 +67,25 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn public ProviderAPIResultReceiver providerAPI_result_receiver; private boolean switching_provider; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + app = this; + + PRNGFixes.apply(); + + preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); + handleVersion(); + + provider = getSavedProvider(savedInstanceState); + if (provider == null || provider.getName().isEmpty()) + startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); + else + buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false)); + } + @Override protected void onSaveInstanceState(@NotNull Bundle outState) { if(provider != null) @@ -90,25 +93,6 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn super.onSaveInstanceState(outState); } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - app = this; - - PRNGFixes.apply(); - - preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); - fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); - handleVersion(); - - provider = getSavedProvider(savedInstanceState); - if (provider == null || provider.getName().isEmpty()) - startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); - else - buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false)); - } - private Provider getSavedProvider(Bundle savedInstanceState) { Provider provider = null; if(savedInstanceState != null) @@ -131,113 +115,100 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn return provider; } - private void handleVersion() { try { int versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; int lastDetectedVersion = preferences.getInt(APP_VERSION, 0); preferences.edit().putInt(APP_VERSION, versionCode).apply(); - Log.d("Dashboard", "detected version code: " + versionCode); - Log.d("Dashboard", "last detected version code: " + lastDetectedVersion); switch(versionCode) { case 91: // 0.6.0 without Bug #5999 case 101: // 0.8.0 - if(!preferences.getString(Constants.KEY, "").isEmpty()) { - Intent rebuildVpnProfiles = new Intent(getApplicationContext(), EIP.class); - rebuildVpnProfiles.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); - startService(rebuildVpnProfiles); - } + if(!preferences.getString(Constants.KEY, "").isEmpty()) + updateEipService(); break; } } catch (NameNotFoundException e) { - Log.d(TAG, "Handle version didn't find any " + getPackageName() + " package"); + Log.d(TAG, "Handle version didn't find any " + getPackageName() + " package"); } } @SuppressLint("CommitPrefEdits") @Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ - Log.d(TAG, "onActivityResult: requestCode = " + requestCode); if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) { if ( resultCode == RESULT_OK ) { - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); - updateEipService(); - - if (data.hasExtra(Provider.KEY)) { - provider = data.getParcelableExtra(Provider.KEY); - preferences.edit().putBoolean(Constants.PROVIDER_CONFIGURED, true).commit(); - preferences.edit().putString(Provider.MAIN_URL, provider.mainUrl().toString()).apply(); - preferences.edit().putString(Provider.KEY, provider.definition().toString()).apply(); - } - buildDashboard(false); - invalidateOptionsMenu(); - if (data.hasExtra(SessionDialog.TAG)) { - logInDialog(Bundle.EMPTY); - } - } else if (resultCode == RESULT_CANCELED && data.hasExtra(ACTION_QUIT)) { + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); + updateEipService(); + + if (data.hasExtra(Provider.KEY)) { + provider = data.getParcelableExtra(Provider.KEY); + preferences.edit().putBoolean(Constants.PROVIDER_CONFIGURED, true).commit(); + preferences.edit().putString(Provider.MAIN_URL, provider.mainUrl().toString()).apply(); + preferences.edit().putString(Provider.KEY, provider.definition().toString()).apply(); + } + buildDashboard(false); + invalidateOptionsMenu(); + if (data.hasExtra(SessionDialog.TAG)) { + sessionDialog(Bundle.EMPTY); + } + } else if (resultCode == RESULT_CANCELED && data.hasExtra(ACTION_QUIT)) { finish(); - } else + } else configErrorDialog(); } else if(requestCode == EIP.DISCONNECT) { EipStatus.getInstance().setConnectedOrDisconnected(); } } - /** - * Dialog shown when encountering a configuration error. Such errors require - * reconfiguring LEAP or aborting the application. - */ - private void configErrorDialog() { - AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getAppContext()); - alertBuilder.setTitle(getResources().getString(R.string.setup_error_title)); - alertBuilder - .setMessage(getResources().getString(R.string.setup_error_text)) - .setCancelable(false) - .setPositiveButton(getResources().getString(R.string.setup_error_configure_button), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - startActivityForResult(new Intent(getAppContext(),ConfigurationWizard.class),CONFIGURE_LEAP); - } - }) - .setNegativeButton(getResources().getString(R.string.setup_error_close_button), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - preferences.edit().remove(Provider.KEY).remove(Constants.PROVIDER_CONFIGURED).apply(); - finish(); - } - }) - .show(); - } + private void configErrorDialog() { + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getAppContext()); + alertBuilder.setTitle(getResources().getString(R.string.setup_error_title)); + alertBuilder + .setMessage(getResources().getString(R.string.setup_error_text)) + .setCancelable(false) + .setPositiveButton(getResources().getString(R.string.setup_error_configure_button), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + startActivityForResult(new Intent(getAppContext(),ConfigurationWizard.class),CONFIGURE_LEAP); + } + }) + .setNegativeButton(getResources().getString(R.string.setup_error_close_button), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + preferences.edit().remove(Provider.KEY).remove(Constants.PROVIDER_CONFIGURED).apply(); + finish(); + } + }) + .show(); + } - /** - * Inflates permanent UI elements of the View and contains logic for what - * service dependent UI elements to include. - */ - private void buildDashboard(boolean hide_and_turn_on_eip) { - setContentView(R.layout.dashboard); + /** + * Inflates permanent UI elements of the View and contains logic for what + * service dependent UI elements to include. + */ + private void buildDashboard(boolean hide_and_turn_on_eip) { + setContentView(R.layout.dashboard); ButterKnife.inject(this); - provider_name.setText(provider.getDomain()); - if ( provider.hasEIP()){ - + provider_name.setText(provider.getDomain()); + if ( provider.hasEIP()){ fragment_manager.removePreviousFragment(EipFragment.TAG); eip_fragment = new EipFragment(); - if (hide_and_turn_on_eip) { - preferences.edit().remove(Dashboard.START_ON_BOOT).apply(); - Bundle arguments = new Bundle(); - arguments.putBoolean(EipFragment.START_ON_BOOT, true); + if (hide_and_turn_on_eip) { + preferences.edit().remove(Dashboard.START_ON_BOOT).apply(); + Bundle arguments = new Bundle(); + arguments.putBoolean(EipFragment.START_ON_BOOT, true); if(eip_fragment != null) eip_fragment.setArguments(arguments); - } + } fragment_manager.replace(R.id.servicesCollection, eip_fragment, EipFragment.TAG); - - if (hide_and_turn_on_eip) { - onBackPressed(); - } - } + if (hide_and_turn_on_eip) { + onBackPressed(); + } } + } @Override public boolean onPrepareOptionsMenu(Menu menu) { @@ -268,110 +239,104 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn } return true; } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.client_dashboard, menu); + return true; + } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.client_dashboard, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item){ - Intent intent; - switch (item.getItemId()){ - case R.id.about_leap: - intent = new Intent(this, AboutActivity.class); - startActivity(intent); - return true; - case R.id.log_window: - Intent startLW = new Intent(getAppContext(), LogWindow.class); - startLW.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - startActivity(startLW); - return true; - case R.id.switch_provider: - switching_provider = true; - if (preferences.getBoolean(Constants.AUTHED_EIP, false)) { - logOut(); - } else switchProvider(); - return true; - case R.id.login_button: - logInDialog(Bundle.EMPTY); - return true; - case R.id.logout_button: - logOut(); - return true; - case R.id.signup_button: - signUpDialog(Bundle.EMPTY); - return true; - default: - return super.onOptionsItemSelected(item); - } - + @Override + public boolean onOptionsItemSelected(MenuItem item){ + Intent intent; + switch (item.getItemId()){ + case R.id.about_leap: + intent = new Intent(this, AboutActivity.class); + startActivity(intent); + return true; + case R.id.log_window: + Intent startLW = new Intent(getAppContext(), LogWindow.class); + startLW.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + startActivity(startLW); + return true; + case R.id.switch_provider: + switching_provider = true; + if (preferences.getBoolean(Constants.AUTHED_EIP, false)) logOut(); + else switchProvider(); + return true; + case R.id.login_button: + sessionDialog(Bundle.EMPTY); + return true; + case R.id.logout_button: + logOut(); + return true; + case R.id.signup_button: + sessionDialog(Bundle.EMPTY); + return true; + default: + return super.onOptionsItemSelected(item); } - - protected Intent prepareProviderAPICommand() { - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); - - Intent command = new Intent(this, ProviderAPI.class); - - command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - return command; } - - /** - * Shows the log in dialog. - */ - public void logInDialog(Bundle resultData) { - FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG); - DialogFragment newFragment = SessionDialog.newInstance(); - if(resultData != null && !resultData.isEmpty() && fragment_manager.findFragmentByTag(SessionDialog.TAG) == null) - newFragment.setArguments(resultData); - newFragment.show(transaction, SessionDialog.TAG); + @Override + public void signUp(String username, String password) { + Bundle parameters = bundleParameters(username, password); + providerApiCommand(parameters, R.string.signingup_message, ProviderAPI.SRP_REGISTER); } @Override public void logIn(String username, String password) { - Intent provider_API_command = prepareProviderAPICommand(); - Bundle parameters = provider_API_command.getExtras().getBundle(ProviderAPI.PARAMETERS); - if(parameters == null) - parameters = new Bundle(); - - parameters.putString(SessionDialog.USERNAME, username); - parameters.putString(SessionDialog.PASSWORD, password); + Bundle parameters = bundleParameters(username, password); + providerApiCommand(parameters, R.string.authenticating_message, ProviderAPI.SRP_AUTH); + } + + public void logOut() { + providerApiCommand(Bundle.EMPTY, R.string.logout_message, ProviderAPI.LOG_OUT); + } + + private void downloadAuthedUserCertificate() { + Bundle parameters = new Bundle(); + parameters.putString(ConfigurationWizard.TYPE_OF_CERTIFICATE, ConfigurationWizard.AUTHED_CERTIFICATE); + + providerApiCommand(parameters, R.string.downloading_certificate_message, ProviderAPI.DOWNLOAD_CERTIFICATE); + } + + private Bundle bundleParameters(String username, String password) { + Bundle parameters = new Bundle(); + if(!username.isEmpty() && !password.isEmpty()) { + parameters.putString(SessionDialog.USERNAME, username); + parameters.putString(SessionDialog.PASSWORD, password); + } + return parameters; + } + private void providerApiCommand(Bundle parameters, int progressbar_message_resId, String providerApi_action) { if(eip_fragment != null) { eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE); - eip_fragment.status_message.setText(R.string.authenticating_message); + setStatusMessage(progressbar_message_resId); } - provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); - provider_API_command.setAction(ProviderAPI.SRP_AUTH); - startService(provider_API_command); + + Intent command = prepareProviderAPICommand(parameters, providerApi_action); + startService(command); } - public void cancelLoginOrSignup() { - EipStatus.getInstance().setConnectedOrDisconnected(); - } + protected Intent prepareProviderAPICommand(Bundle parameters, String action) { + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); - /** - * Asks ProviderAPI to log out. - */ - public void logOut() { - Intent provider_API_command = prepareProviderAPICommand(); - if(eip_fragment != null) { + Intent command = new Intent(this, ProviderAPI.class); + + command.putExtra(ProviderAPI.PARAMETERS, parameters); + command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); + command.setAction(action); + return command; + } - eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE); - eip_fragment.status_message.setText(R.string.logout_message); - } - provider_API_command.setAction(ProviderAPI.LOG_OUT); - startService(provider_API_command); + public void cancelLoginOrSignup() { + EipStatus.getInstance().setConnectedOrDisconnected(); } - /** - * Shows the sign up dialog. - */ - public void signUpDialog(Bundle resultData) { + public void sessionDialog(Bundle resultData) { FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG); DialogFragment newFragment = SessionDialog.newInstance(); @@ -381,169 +346,118 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn newFragment.show(transaction, SessionDialog.TAG); } - @Override - public void signUp(String username, String password) { - Intent provider_API_command = prepareProviderAPICommand(); - Bundle parameters = provider_API_command.getExtras().getBundle(ProviderAPI.PARAMETERS); - if(parameters == null) - parameters = new Bundle(); - - parameters.putString(SessionDialog.USERNAME, username); - parameters.putString(SessionDialog.PASSWORD, password); - if(eip_fragment != null) { - eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE); - eip_fragment.status_message.setText(R.string.signingup_message); - } - provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); - provider_API_command.setAction(ProviderAPI.SRP_REGISTER); - startService(provider_API_command); - } - private void switchProvider() { if (provider.hasEIP()) eip_fragment.askToStopEIP(); + preferences.edit().clear().apply(); switching_provider = false; - startActivityForResult(new Intent(this,ConfigurationWizard.class), SWITCH_PROVIDER); + startActivityForResult(new Intent(this, ConfigurationWizard.class), SWITCH_PROVIDER); } - /** - * Asks ProviderAPI to download an authenticated OpenVPN certificate. - */ - private void downloadAuthedUserCertificate() { - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); - - Intent provider_API_command = new Intent(this, ProviderAPI.class); - - Bundle parameters = new Bundle(); - parameters.putString(ConfigurationWizard.TYPE_OF_CERTIFICATE, ConfigurationWizard.AUTHED_CERTIFICATE); - - provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE); - provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); - provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - - startService(provider_API_command); + @Override + public void onReceiveResult(int resultCode, Bundle resultData) { + Log.d(TAG, "onReceiveResult"); + if(resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) { + String username = resultData.getString(SessionDialog.USERNAME); + String password = resultData.getString(SessionDialog.PASSWORD); + logIn(username, password); + } else if(resultCode == ProviderAPI.FAILED_SIGNUP) { + updateViewHidingProgressBar(resultCode); + sessionDialog(resultData); + } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGIN) { + authed_eip = true; + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); + + updateViewHidingProgressBar(resultCode); + downloadAuthedUserCertificate(); + } else if(resultCode == ProviderAPI.FAILED_LOGIN) { + updateViewHidingProgressBar(resultCode); + sessionDialog(resultData); + } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGOUT) { + authed_eip = false; + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); + + updateViewHidingProgressBar(resultCode); + if(switching_provider) switchProvider(); + } else if(resultCode == ProviderAPI.LOGOUT_FAILED) { + updateViewHidingProgressBar(resultCode); + setResult(RESULT_CANCELED); + } else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { + updateViewHidingProgressBar(resultCode); + updateEipService(); + setResult(RESULT_OK); + } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { + updateViewHidingProgressBar(resultCode); + setResult(RESULT_CANCELED); } + else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE) { + setResult(RESULT_OK); - @Override - public void onReceiveResult(int resultCode, Bundle resultData) { - Log.d(TAG, "onReceiveResult"); - if(resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) { - String username = resultData.getString(SessionDialog.USERNAME); - String password = resultData.getString(SessionDialog.PASSWORD); - logIn(username, password); - } else if(resultCode == ProviderAPI.FAILED_SIGNUP) { - changeStatusMessage(resultCode); - hideProgressBar(); - - signUpDialog(resultData); - } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGIN) { - changeStatusMessage(resultCode); - hideProgressBar(); - - invalidateOptionsMenu(); - - authed_eip = true; - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); - - downloadAuthedUserCertificate(); - } else if(resultCode == ProviderAPI.FAILED_LOGIN) { - changeStatusMessage(resultCode); - hideProgressBar(); - - logInDialog(resultData); - } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGOUT) { - changeStatusMessage(resultCode); - hideProgressBar(); - - invalidateOptionsMenu(); - - authed_eip = false; - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); - - if(switching_provider) switchProvider(); - - } else if(resultCode == ProviderAPI.LOGOUT_FAILED) { - changeStatusMessage(resultCode); - hideProgressBar(); - - setResult(RESULT_CANCELED); - } else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { - changeStatusMessage(resultCode); - hideProgressBar(); - - setResult(RESULT_OK); - - updateEipService(); - } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { - changeStatusMessage(resultCode); - hideProgressBar(); - setResult(RESULT_CANCELED); - } - else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE) { - setResult(RESULT_OK); + updateEipService(); + } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE) { + setResult(RESULT_CANCELED); + } + } - updateEipService(); - } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE) { - setResult(RESULT_CANCELED); + private void updateViewHidingProgressBar(int resultCode) { + changeStatusMessage(resultCode); + hideProgressBar(); + invalidateOptionsMenu(); } - } private void updateEipService() { Intent updateEIP = new Intent(getApplicationContext(), EIP.class); updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); - ResultReceiver receiver = new ResultReceiver(new Handler()) { - protected void onReceiveResult(int resultCode, Bundle resultData) { + startService(updateEIP); + } + + private void changeStatusMessage(final int previous_result_code) { + ResultReceiver status_receiver = new ResultReceiver(new Handler()){ + protected void onReceiveResult(int resultCode, Bundle resultData){ + super.onReceiveResult(resultCode, resultData); String request = resultData.getString(Constants.REQUEST_TAG); - if(request.equalsIgnoreCase(Constants.ACTION_UPDATE_EIP_SERVICE)) { - if(resultCode == Activity.RESULT_OK) { - if(authed_eip && eip_fragment != null) eip_fragment.startEipFromScratch(); + if (request.equalsIgnoreCase(Constants.ACTION_IS_EIP_RUNNING)){ + if (resultCode == Activity.RESULT_OK){ + switch(previous_result_code){ + case ProviderAPI.SUCCESSFUL_LOGIN: setStatusMessage(R.string.succesful_authentication_message); break; + case ProviderAPI.FAILED_LOGIN: setStatusMessage(R.string.authentication_failed_message); break; + case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: setStatusMessage(R.string.authed_secured_status); break; + case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: setStatusMessage(R.string.incorrectly_downloaded_certificate_message); break; + case ProviderAPI.SUCCESSFUL_LOGOUT: setStatusMessage(R.string.logged_out_message); break; + case ProviderAPI.LOGOUT_FAILED: setStatusMessage(R.string.log_out_failed_message); break; + + } + } + else if(resultCode == Activity.RESULT_CANCELED){ + switch(previous_result_code){ + case ProviderAPI.SUCCESSFUL_LOGIN: setStatusMessage(R.string.succesful_authentication_message); break; + case ProviderAPI.FAILED_LOGIN: setStatusMessage(R.string.authentication_failed_message); break; + case ProviderAPI.FAILED_SIGNUP: setStatusMessage(R.string.registration_failed_message); break; + case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: break; + case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: setStatusMessage(R.string.incorrectly_downloaded_certificate_message); break; + case ProviderAPI.SUCCESSFUL_LOGOUT: setStatusMessage(R.string.logged_out_message); break; + case ProviderAPI.LOGOUT_FAILED: setStatusMessage(R.string.log_out_failed_message); break; + } } } + } }; - //updateEIP.putExtra(Constants.RECEIVER_TAG, receiver); - startService(updateEIP); + eipIsRunning(status_receiver); } - private void changeStatusMessage(final int previous_result_code) { - // TODO Auto-generated method stub - ResultReceiver eip_status_receiver = new ResultReceiver(new Handler()){ - protected void onReceiveResult(int resultCode, Bundle resultData){ - super.onReceiveResult(resultCode, resultData); - String request = resultData.getString(Constants.REQUEST_TAG); - if (request.equalsIgnoreCase(Constants.ACTION_IS_EIP_RUNNING)){ - if (resultCode == Activity.RESULT_OK){ - - switch(previous_result_code){ - case ProviderAPI.SUCCESSFUL_LOGIN: eip_fragment.status_message.setText(R.string.succesful_authentication_message); break; - case ProviderAPI.FAILED_LOGIN: eip_fragment.status_message.setText(R.string.authentication_failed_message); break; - case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: eip_fragment.status_message.setText(R.string.authed_secured_status); break; - case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eip_fragment.status_message.setText(R.string.incorrectly_downloaded_certificate_message); break; - case ProviderAPI.SUCCESSFUL_LOGOUT: eip_fragment.status_message.setText(R.string.logged_out_message); break; - case ProviderAPI.LOGOUT_FAILED: eip_fragment.status_message.setText(R.string.log_out_failed_message); break; - - } - } - else if(resultCode == Activity.RESULT_CANCELED){ - - switch(previous_result_code){ - - case ProviderAPI.SUCCESSFUL_LOGIN: eip_fragment.status_message.setText(R.string.succesful_authentication_message); break; - case ProviderAPI.FAILED_LOGIN: eip_fragment.status_message.setText(R.string.authentication_failed_message); break; - case ProviderAPI.FAILED_SIGNUP: eip_fragment.status_message.setText(R.string.registration_failed_message); break; - case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: break; - case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eip_fragment.status_message.setText(R.string.incorrectly_downloaded_certificate_message); break; - case ProviderAPI.SUCCESSFUL_LOGOUT: eip_fragment.status_message.setText(R.string.logged_out_message); break; - case ProviderAPI.LOGOUT_FAILED: eip_fragment.status_message.setText(R.string.log_out_failed_message); break; - } - } - } - - } - }; - eipIsRunning(eip_status_receiver); - } + private void setStatusMessage(int string_resId) { + if(eip_fragment != null && eip_fragment.status_message != null) + eip_fragment.status_message.setText(string_resId); + } + + private void eipIsRunning(ResultReceiver eip_receiver){ + // TODO validate "action"...how do we get the list of intent-filters for a class via Android API? + Intent intent = new Intent(this, EIP.class); + intent.setAction(Constants.ACTION_IS_EIP_RUNNING); + intent.putExtra(Constants.RECEIVER_TAG, eip_receiver); + startService(intent); + } private void hideProgressBar() { if(eip_fragment != null) { @@ -552,28 +466,13 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn } } - /** - * For retrieving the base application Context in classes that don't extend - * Android's Activity class - * - * @return Application Context as defined by this for Dashboard instance - */ - public static Context getAppContext() { - return app; - } - - + public static Context getAppContext() { + return app; + } + @Override public void startActivityForResult(Intent intent, int requestCode) { intent.putExtra(Dashboard.REQUEST_CODE, requestCode); super.startActivityForResult(intent, requestCode); } - - private void eipIsRunning(ResultReceiver eip_receiver){ - // TODO validate "action"...how do we get the list of intent-filters for a class via Android API? - Intent eip_intent = new Intent(this, EIP.class); - eip_intent.setAction(Constants.ACTION_IS_EIP_RUNNING); - eip_intent.putExtra(Constants.RECEIVER_TAG, eip_receiver); - startService(eip_intent); - } } diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index 59e9ca5a..27c70c43 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -56,8 +56,7 @@ public class EipFragment extends Fragment implements Observer { parent_activity = activity; Dashboard dashboard = (Dashboard) parent_activity; - Intent provider_API_command = dashboard.prepareProviderAPICommand(); - provider_API_command.setAction(ProviderAPI.DOWNLOAD_EIP_SERVICE); + Intent provider_API_command = dashboard.prepareProviderAPICommand(Bundle.EMPTY, ProviderAPI.DOWNLOAD_EIP_SERVICE); parent_activity.startService(provider_API_command); } @@ -139,7 +138,7 @@ public class EipFragment extends Fragment implements Observer { Dashboard dashboard = (Dashboard) parent_activity; Bundle bundle = new Bundle(); bundle.putBoolean(IS_PENDING, true); - dashboard.logInDialog(bundle); + dashboard.sessionDialog(bundle); } } @@ -344,10 +343,9 @@ public class EipFragment extends Fragment implements Observer { progress_bar.setVisibility(View.VISIBLE); status_message.setText(getString(R.string.updating_certificate_message)); if(LeapSRPSession.getToken().isEmpty() && !Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false)) { - dashboard.logInDialog(Bundle.EMPTY); + dashboard.sessionDialog(Bundle.EMPTY); } else { - Intent provider_API_command = dashboard.prepareProviderAPICommand(); - provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE); + Intent provider_API_command = dashboard.prepareProviderAPICommand(Bundle.EMPTY, ProviderAPI.DOWNLOAD_CERTIFICATE); parent_activity.startService(provider_API_command); } break; diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 68e71886..7d03c221 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,7 +15,6 @@ Bitmask Provider: No provider configured - Access EIP connection settings Status unknown. Connection secure using an anonymous certificate. Connection secure using your own certificate. @@ -55,7 +54,8 @@ Service is down. Configuring provider Your anon cert was not downloaded - Updating EIP certificate + Downloading VPN certificate + Updating VPN certificate Logging in Signing up Logging out from this session. @@ -63,7 +63,7 @@ Didn\'t log out. Authentication succeeded. Authentication failed. - Registration failed.. + Registration failed. Your own cert has been correctly downloaded. Your own cert has incorrectly been downloaded. Initiating connection -- cgit v1.2.3 From b1219330faf64b2cd4330d44390fdec137b659b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 17 Dec 2014 19:08:53 +0100 Subject: Add remotes for each port, udp before tcp in each. --- .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 38 ++++++++++++---------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'app') diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java index 0c8e9a04..a320bee5 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -79,32 +79,36 @@ public class VpnConfigGenerator { private String gatewayConfiguration() { String remotes = ""; - String remote = "ip_address"; - String remote_openvpn_keyword = "remote"; - String ports = "ports"; - String protos = "protocols"; - String capabilities = "capabilities"; + String ip_address_keyword = "ip_address"; + String remote_keyword = "remote"; + String ports_keyword = "ports"; + String protocol_keyword = "protocols"; + String capabilities_keyword = "capabilities"; String udp = "udp"; try { - JSONArray protocolsJSON = gateway.getJSONObject(capabilities).getJSONArray(protos); - for ( int i=0; i config-version.h.tmp; \ - echo "#define CONFIGURE_GIT_FLAGS \"${CONFIGURE_GIT_CHFILES}${CONFIGURE_GIT_UNCOMMITTED}\"" >> config-version.h.tmp - - if ! [ -f config-version.h ] || ! cmp -s config-version.h.tmp config-version.h; then \ - echo "replacing config-version.h" - mv config-version.h.tmp config-version.h - else - rm -f config-version.h.tmp - fi - cd .. -fi - -if [ "x$1" = "x" ]; then - ndk-build APP_API=all -j 8 -else - ndk-build $@ -fi - -if [ $? = 0 ]; then - rm -rf ovpnlibs/ - - cd libs - mkdir -p ../ovpnlibs/assets - for i in $(find * -type d) - do - cp -v $i/minivpn ../ovpnlibs/assets/minivpn.$i - done - # Removed compiled openssl libs, will use platform so libs - # Reduces size of apk - rm -v */libcrypto.so */libssl.so - - for arch in $(find * -type d) - do - builddir=../ovpnlibs/jniLibs/$arch - mkdir -p $builddir - cp -v $arch/*.so $builddir - done -else - exit $? -fi diff --git a/app/build.gradle b/app/build.gradle index dc020813..f0ea5ac1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,6 +66,8 @@ task copyIcsOpenVPNClasses( type: Copy ) << { from ('../ics-openvpn-stripped/main/') { include '**/*.java' include '**/*.aidl' + includeEmptyDirs = false + filter { line -> line.replaceAll('de.blinkt.openvpn.R', 'se.leap.bitmaskclient.R') } @@ -92,7 +94,9 @@ task copyIcsOpenVPNXml( type: Copy ) << { include '**/refs.xml' include '**/colours.xml' include '**/logmenu.xml' - + include '**/white_rect.xml' + includeEmptyDirs = false + rename 'strings.xml', 'strings-icsopenvpn.xml' filter { line -> line.replaceAll('.*name="app".*', '') @@ -108,6 +112,8 @@ task copyIcsOpenVPNImages( type: Copy ) << { include '**/ic_share*.png' include '**/ic_close*.png' include '**/ic_edit*.png' + + includeEmptyDirs = false } into '.' } @@ -172,16 +178,16 @@ task mergeUntranslatable( type: Copy, dependsOn: 'removeDuplicatedStrings') << { } task updateIcsOpenVpn( type: Copy, dependsOn: 'mergeUntranslatable') << { - println "updateIcsOpenVpn" from('../ics-openvpn-stripped/main/src/') { - include 'openvpn/**' - include 'openssl/**' - include 'lzo/**' - include 'jni/**' - include 'misc/**' - include 'ovpn3/**' - include 'snappy/**' - } into '.' + include 'openvpn/**/*' + include 'openssl/**/*' + include 'lzo/**/**' + include 'jni/**/*' + include 'misc/**/*' + include 'ovpn3/**/*' + include 'snappy/**/*' + + } into './' } task buildNative ( type: Exec ) { diff --git a/app/fix_entensions.sh b/app/fix_entensions.sh deleted file mode 100755 index 37578786..00000000 --- a/app/fix_entensions.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -ln -s sha512-armv4.s openssl/crypto/sha/asm/sha512-armv4.S -ln -s sha256-armv4.s openssl/crypto/sha/asm/sha256-armv4.S -ln -s sha1-armv4-large.s openssl/crypto/sha/asm/sha1-armv4-large.S -ln -s armv4-mont.s openssl/crypto/bn/asm/armv4-mont.S -ln -s aes-armv4.s openssl/crypto/aes/asm/aes-armv4.S diff --git a/app/jni/Android.mk b/app/jni/Android.mk index 90074b0f..df8cbb34 100644 --- a/app/jni/Android.mk +++ b/app/jni/Android.mk @@ -49,8 +49,9 @@ LOCAL_PATH := $(JNI_DIR) # The only real JNI library include $(CLEAR_VARS) LOCAL_LDLIBS := -llog -lz +LOCAL_CFLAGS = --std=c99 LOCAL_C_INCLUDES := openssl/include openssl/crypto openssl -LOCAL_SRC_FILES:= jniglue.c jbcrypto.cpp +LOCAL_SRC_FILES:= jniglue.c jbcrypto.cpp scan_ifs.c LOCAL_MODULE = opvpnutil LOCAL_SHARED_LIBRARIES := libcrypto include $(BUILD_SHARED_LIBRARY) diff --git a/app/jni/jniglue.c b/app/jni/jniglue.c index 36ad8fe7..d446f78c 100644 --- a/app/jni/jniglue.c +++ b/app/jni/jniglue.c @@ -1,7 +1,8 @@ #include #include #include -#include +#include + #include "jniglue.h" diff --git a/app/jni/jniglue.h b/app/jni/jniglue.h index a86d52da..8f813b64 100644 --- a/app/jni/jniglue.h +++ b/app/jni/jniglue.h @@ -10,3 +10,12 @@ #define xcopenvpn_jniglue_h void android_openvpn_log(int level,const char* prefix,const char* prefix_sep,const char* m1); #endif + +#ifdef __cplusplus +extern "C" { +#endif + int jniThrowException(JNIEnv* env, const char* className, const char* msg); + +#ifdef __cplusplus +} +#endif diff --git a/app/jni/scan_ifs.c b/app/jni/scan_ifs.c new file mode 100644 index 00000000..e0024c54 --- /dev/null +++ b/app/jni/scan_ifs.c @@ -0,0 +1,109 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jniglue.h" + +jobjectArray Java_de_blinkt_openvpn_core_NativeUtils_getIfconfig(JNIEnv* env) +{ + + int sd; + if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { + __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "Opening socket for intface get failed"); + //jniThrowException(env, "java/lang/IllegalArgumentException", "Opening socket for intface get failed"); + return NULL; + } + + struct ifreq ifs[23]; + + struct ifconf ifc; + ifc.ifc_req = ifs; + ifc.ifc_len = sizeof (ifs); + + if (ioctl (sd, SIOCGIFCONF, &ifc) < 0) { + __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "IOCTL for intface get failed"); + //jniThrowException(env, "java/lang/IllegalArgumentException", "IOTCL socket for intface get failed"); + return NULL; + } + + + + + char buf[NI_MAXHOST]; + + int ji=0; + + /* + jtmp = (*env)->NewStringUTF(env, "HALLO WELT"); + (*env)->SetObjectArrayElement(env, ret, ji++, jtmp); + */ + + size_t num_intf=ifc.ifc_len / sizeof(struct ifreq); + jobjectArray ret= (jobjectArray) (*env)->NewObjectArray(env, num_intf*3,(*env)->FindClass(env, "java/lang/String"), NULL); + + for (struct ifreq* ifr = ifc.ifc_req; ifr < ifs + num_intf; ifr++) { + + if (ifr->ifr_addr.sa_family != AF_INET) { + __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "NOT AF_INET: %s", ifr->ifr_name); + continue; + } + + /* get interface addr, prefilled by SIOGIFCONF */ + + int err; + if (err=getnameinfo(&ifr->ifr_addr, sizeof(struct sockaddr_in), buf, NI_MAXHOST, NULL, 0, + NI_NUMERICHOST) !=0) { + __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "getnameinfo failed for %s: %s", ifr->ifr_name, gai_strerror(err)); + continue; + } + jstring jaddr = (*env)->NewStringUTF(env, buf); + jstring jname = (*env)->NewStringUTF(env, ifr->ifr_name); + + + struct ifreq ifreq; + strncpy (ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name)); + + /* interface is up */ + if (ioctl (sd, SIOCGIFFLAGS, &ifreq) < 0) { + __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "SIOCGIFFLAGS failed for %s: %s", ifr->ifr_name, strerror(errno)); + continue; + } + + if (!(ifreq.ifr_flags & IFF_UP)) { + __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "IFF_UP failed for %s", ifr->ifr_name); + continue; + } + + /* interface netmask */ + if (ioctl (sd, SIOCGIFNETMASK, &ifreq) < 0) { + __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "SIOCIFNETMASK failed for %s: %s", ifr->ifr_name, strerror(errno)); + continue; + } + + if (err=getnameinfo(&ifreq.ifr_netmask, sizeof(struct sockaddr_in), buf, NI_MAXHOST, NULL, 0, + NI_NUMERICHOST) !=0) { + __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "getnameinfo failed for %s: %s", ifr->ifr_name, gai_strerror(err)); + continue; + } + jstring jnetmask = (*env)->NewStringUTF(env, buf); + + (*env)->SetObjectArrayElement(env, ret, ji++, jname); + (*env)->SetObjectArrayElement(env, ret, ji++, jaddr); + (*env)->SetObjectArrayElement(env, ret, ji++, jnetmask); + } + if (sd >= 0) + close (sd); + + return ret; +} + diff --git a/app/lint.xml b/app/lint.xml deleted file mode 100644 index ee0eead5..00000000 --- a/app/lint.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/app/misc/genFAQ.py b/app/misc/genFAQ.py index 09381caa..9a0c9af5 100755 --- a/app/misc/genFAQ.py +++ b/app/misc/genFAQ.py @@ -4,6 +4,7 @@ import codecs import xml.dom.minidom as dom import os.path +import re faqpath = "/Users/arne/oss/ics-openvpn.wiki" @@ -29,7 +30,22 @@ def getString(strid,lang): ostr = ostr.replace("\\n","

") return ostr -def genPage(faqdom,lang): +def genPage(javafile, lang): + #{R.string.faq_howto_title, R.string.faq_howto}, + out ="" + out+= header + for l in javafile: + m = re.search("\{.*R.string.([a-z_]+),.*R.string.([a-z_]+)\}", l) + if m: + (title, body) = m.groups() + + out += "== %s ==\n" % getString(title,lang) + out += "%s\n" % getString(body,lang) + if body == "faq_system_dialogs_title": + out += "%s\n" % getString("faq_system_dialog_xposed",lang) + return out + +def genPageXML(faqdom,lang): out ="" #out+="#summary %s\n" % getString("faq_summary",lang) @@ -75,13 +91,14 @@ def main(): loadstrres("src/main/res/values/strings.xml","default") - faqdom = dom.parse("src/main/res/layout/faq.xml") + #faqdom = dom.parse("src/main/res/layout/faq.xml") + faqdom = open("src/main/java/de/blinkt/openvpn/fragments/FaqFragment.java").readlines() faq= genPage(faqdom,"default") open(faqpath + "/FAQ.wiki","w").write(faq) for directory in os.listdir("src/main/res"): - if directory.startswith("values-") and directory.find("-sw")==-1: + if directory.startswith("values-") and directory.find("-sw")==-1 and not directory.startswith("values-v"): lang = directory.split("-",1)[1] print lang loadstrres("src/main/res/values-%s/strings.xml" % lang,lang) diff --git a/app/openssl/Crypto-config-host.mk b/app/openssl/Crypto-config-host.mk index 1e94f10b..61df350e 100644 --- a/app/openssl/Crypto-config-host.mk +++ b/app/openssl/Crypto-config-host.mk @@ -184,7 +184,6 @@ common_src_files := \ crypto/conf/conf_mall.c \ crypto/conf/conf_mod.c \ crypto/conf/conf_sap.c \ - crypto/constant_time_locl.h \ crypto/cpt_err.c \ crypto/cryptlib.c \ crypto/cversion.c \ diff --git a/app/openssl/Crypto-config-target.mk b/app/openssl/Crypto-config-target.mk index 43de9567..17fe4bf5 100644 --- a/app/openssl/Crypto-config-target.mk +++ b/app/openssl/Crypto-config-target.mk @@ -184,7 +184,6 @@ common_src_files := \ crypto/conf/conf_mall.c \ crypto/conf/conf_mod.c \ crypto/conf/conf_sap.c \ - crypto/constant_time_locl.h \ crypto/cpt_err.c \ crypto/cryptlib.c \ crypto/cversion.c \ diff --git a/app/openvpn/config-version.h b/app/openvpn/config-version.h index 1fca2b7a..f89c974f 100644 --- a/app/openvpn/config-version.h +++ b/app/openvpn/config-version.h @@ -1,2 +1,2 @@ -#define CONFIGURE_GIT_REVISION "icsopenvpn_621-b603913ee5d54ab8" +#define CONFIGURE_GIT_REVISION "icsopenvpn_625-af9eb9424047f9f5" #define CONFIGURE_GIT_FLAGS "" diff --git a/app/openvpn/configure.ac b/app/openvpn/configure.ac index 608ab6d1..ddaa2b2e 100644 --- a/app/openvpn/configure.ac +++ b/app/openvpn/configure.ac @@ -73,7 +73,7 @@ AC_ARG_ENABLE( AC_ARG_ENABLE( [ofb-cfb], - [AS_HELP_STRING([--enable-ofb-cfb], [enable support for OFB and CFB cipher modes @<:@default=yes@:>@])], + [AS_HELP_STRING([--disable-ofb-cfb], [disable support for OFB and CFB cipher modes @<:@default=yes@:>@])], , [enable_crypto_ofb_cfb="yes"] ) @@ -157,14 +157,14 @@ AC_ARG_ENABLE( AC_ARG_ENABLE( [small], - [AS_HELP_STRING([--enable-small], [enable smaller executable size (disable OCC, usage message, and verb 4 parm list) @<:@default=yes@:>@])], + [AS_HELP_STRING([--enable-small], [enable smaller executable size (disable OCC, usage message, and verb 4 parm list) @<:@default=no@:>@])], , [enable_small="no"] ) AC_ARG_ENABLE( [password-save], - [AS_HELP_STRING([--enable-password-save], [allow --askpass and --auth-user-pass passwords to be read from a file @<:@default=yes@:>@])], + [AS_HELP_STRING([--enable-password-save], [allow --askpass and --auth-user-pass passwords to be read from a file @<:@default=no@:>@])], , [enable_password_save="no"] ) diff --git a/app/openvpn/distro/Makefile.am b/app/openvpn/distro/Makefile.am index 2dd6a6ee..bd65b79b 100644 --- a/app/openvpn/distro/Makefile.am +++ b/app/openvpn/distro/Makefile.am @@ -13,3 +13,5 @@ MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in SUBDIRS = rpm + +EXTRA_DIST = systemd/openvpn-client@.service systemd/openvpn-server@.service diff --git a/app/openvpn/distro/systemd/openvpn-client@.service b/app/openvpn/distro/systemd/openvpn-client@.service new file mode 100644 index 00000000..56d93a93 --- /dev/null +++ b/app/openvpn/distro/systemd/openvpn-client@.service @@ -0,0 +1,20 @@ +[Unit] +Description=OpenVPN tunnel for %I +After=syslog.target network-online.target +Wants=network-online.target +Documentation=man:openvpn(8) +Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage +Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO + +[Service] +PrivateTmp=true +Type=forking +PIDFile=/var/run/openvpn/client_%i.pid +ExecStart=/usr/sbin/openvpn --cd /etc/openvpn/client --config %i.conf --daemon --writepid /var/run/openvpn/client_%i.pid +CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH +LimitNPROC=10 +DeviceAllow=/dev/null rw +DeviceAllow=/dev/net/tun rw + +[Install] +WantedBy=multi-user.target diff --git a/app/openvpn/distro/systemd/openvpn-server@.service b/app/openvpn/distro/systemd/openvpn-server@.service new file mode 100644 index 00000000..c4c9a123 --- /dev/null +++ b/app/openvpn/distro/systemd/openvpn-server@.service @@ -0,0 +1,19 @@ +[Unit] +Description=OpenVPN service for %I +After=syslog.target network.target +Documentation=man:openvpn(8) +Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage +Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO + +[Service] +PrivateTmp=true +Type=forking +PIDFile=/var/run/openvpn/server_%i.pid +ExecStart=/usr/sbin/openvpn --cd /etc/openvpn/server --status /var/run/openvpn/server_%i-status.log --status-version 2 --config %i.conf --daemon --writepid /var/run/openvpn/server_%i.pid +CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH +LimitNPROC=10 +DeviceAllow=/dev/null rw +DeviceAllow=/dev/net/tun rw + +[Install] +WantedBy=multi-user.target diff --git a/app/openvpn/doc/doxygen/doc_data_crypto.h b/app/openvpn/doc/doxygen/doc_data_crypto.h index ee72b8cd..640203f4 100644 --- a/app/openvpn/doc/doxygen/doc_data_crypto.h +++ b/app/openvpn/doc/doxygen/doc_data_crypto.h @@ -69,7 +69,5 @@ * * @par Crypto algorithms * This module uses the crypto algorithm implementations of the external - * OpenSSL library. More precisely, it uses the OpenSSL library's \c - * EVP_Cipher* and \c HMAC_* set of functions to perform cryptographic - * operations on data channel packets. + * crypto library (currently either OpenSSL (default), or PolarSSL). */ diff --git a/app/openvpn/doc/doxygen/doc_mainpage.h b/app/openvpn/doc/doxygen/doc_mainpage.h index 821b2e87..ed8e324e 100644 --- a/app/openvpn/doc/doxygen/doc_mainpage.h +++ b/app/openvpn/doc/doxygen/doc_mainpage.h @@ -29,7 +29,7 @@ */ /** - * @mainpage OpenVPN v2.1 source code documentation + * @mainpage OpenVPN source code documentation * * This documentation describes the internal structure of OpenVPN. It was * automatically generated from specially formatted comment blocks in diff --git a/app/openvpn/doc/doxygen/doc_protocol_overview.h b/app/openvpn/doc/doxygen/doc_protocol_overview.h index 26fed331..9edafcfb 100644 --- a/app/openvpn/doc/doxygen/doc_protocol_overview.h +++ b/app/openvpn/doc/doxygen/doc_protocol_overview.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2010 Fox Crypto B.V. + * Copyright (C) 2010-2014 Fox Crypto B.V. * * * This program is free software; you can redistribute it and/or modify @@ -61,24 +61,26 @@ * following describes the various opcodes available. * * - Control channel messages: - * - \c P_CONTROL_HARD_RESET_CLIENT_V1 -- %Key method 1, initial %key + * - \ref P_CONTROL_HARD_RESET_CLIENT_V1 -- %Key method 1, initial %key * from client, forget previous state. - * - \c P_CONTROL_HARD_RESET_SERVER_V1 -- %Key method 1, initial %key + * - \ref P_CONTROL_HARD_RESET_SERVER_V1 -- %Key method 1, initial %key * from server, forget previous state. - * - \c P_CONTROL_HARD_RESET_CLIENT_V2 -- %Key method 2, initial %key + * - \ref P_CONTROL_HARD_RESET_CLIENT_V2 -- %Key method 2, initial %key * from client, forget previous state. - * - \c P_CONTROL_HARD_RESET_SERVER_V2 -- %Key method 2, initial %key + * - \ref P_CONTROL_HARD_RESET_SERVER_V2 -- %Key method 2, initial %key * from server, forget previous state. - * - \c P_CONTROL_SOFT_RESET_V1 -- New %key, with a graceful + * - \ref P_CONTROL_SOFT_RESET_V1 -- New %key, with a graceful * transition from old to new %key in the sense that a transition * window exists where both the old or new key_id can be used. - * - \c P_CONTROL_V1 -- Control channel packet (usually TLS + * - \ref P_CONTROL_V1 -- Control channel packet (usually TLS * ciphertext). - * - \c P_ACK_V1 -- Acknowledgement for control channel packets + * - \ref P_ACK_V1 -- Acknowledgement for control channel packets * received. * - Data channel messages: - * - \c P_DATA_V1 -- Data channel packet containing data channel + * - \ref P_DATA_V1 -- Data channel packet containing data channel * ciphertext. + * - \ref P_DATA_V2 -- Data channel packet containing peer-id and data + * channel ciphertext. * * @subsection network_protocol_external_key_id Session IDs and Key IDs * @@ -139,10 +141,10 @@ * channel is used to exchange random %key material for bidirectional * cipher and HMAC keys which will be used to secure data channel packets. * OpenVPN currently implements two %key methods. %Key method 1 directly - * derives keys using random bits obtained from the \c RAND_bytes() - * OpenSSL function. %Key method 2 mixes random %key material from both - * sides of the connection using the TLS PRF mixing function. %Key method - * 2 is the preferred method and is the default for OpenVPN 2.0. + * derives keys using random bits obtained from the \c rand_bytes() function. + * %Key method 2 mixes random %key material from both sides of the connection + * using the TLS PRF mixing function. %Key method 2 is the preferred method and + * is the default for OpenVPN 2.0+. * * The @ref key_generation "Data channel key generation" related page * describes the %key methods in more detail. @@ -173,27 +175,22 @@ * * @section network_protocol_data Structure of data channel messages * - * @subsection network_protocol_data_ciphertext Structure of ciphertext data channel messages - * - * The P_DATA_* payload represents encrypted, encapsulated tunnel packets - * which tend to be either IP packets or Ethernet frames. This is - * essentially the "payload" of the VPN. - * - * Data channel packets in ciphertext form consist of the following parts: - * - HMAC of ciphertext IV + ciphertext (if not disabled by \c --auth - * none). - * - Ciphertext IV (size is cipher-dependent, if not disabled by \c - * --no-iv). - * - Tunnel packet ciphertext. - * - * @subsection network_protocol_data_plaintext Structure of plaintext data channel messages - * - * Data channel packets in plaintext form consist of the following parts: - * - packet-id (4 or 8 bytes, if not disabled by --no-replay). - * - In TLS mode, 4 bytes are used because the implementation can - * force a TLS renegotation before \c 2^32 packets are sent. - * - In pre-shared %key mode, 8 bytes are used (sequence number and \c - * time_t value) to allow long-term %key usage without packet-id - * collisions. - * - User plaintext (n bytes). + * The P_DATA_* payload represents encapsulated tunnel packets which tend to be + * either IP packets or Ethernet frames. This is essentially the "payload" of + * the VPN. Data channel packets consist of a data channel header, and a + * payload. There are two possible formats: + * + * @par P_DATA_V1 + * P_DATA_V1 packets have a 1-byte header, carrying the \ref P_DATA_V1 \c opcode + * and \c key_id, followed by the payload:\n + * [ 5-bit opcode | 3-bit key_id ] [ payload ] + * + * @par P_DATA_V2 + * P_DATA_V2 packets have the same 1-byte opcode/key_id, but carrying the \ref + * P_DATA_V2 opcode, followed by a 3-byte peer-id, which uniquely identifies + * the peer:\n + * [ 5-bit opcode | 3-bit key_id ] [ 24-bit peer-id ] [ payload ] + * + * See @ref data_crypto for details on the data channel payload format. + * */ diff --git a/app/openvpn/doc/openvpn.8 b/app/openvpn/doc/openvpn.8 index f2911c0e..532eda5c 100644 --- a/app/openvpn/doc/openvpn.8 +++ b/app/openvpn/doc/openvpn.8 @@ -1437,6 +1437,7 @@ Currently defaults to 100. Limit bandwidth of outgoing tunnel data to .B n bytes per second on the TCP/UDP port. +Note that this will only work if mode is set to p2p. If you want to limit the bandwidth in both directions, use this option on both peers. @@ -4330,6 +4331,11 @@ and version is not recognized, we will only accept the highest TLS version supported by the local SSL implementation. .\"********************************************************* .TP +.B \-\-tls-version-max version +Set the maximum TLS version we will use (default is the highest version +supported). Examples for version include "1.0", "1.1", or "1.2". +.\"********************************************************* +.TP .B \-\-pkcs12 file Specify a PKCS #12 file containing local private key, local certificate, and root CA certificate. @@ -4603,26 +4609,11 @@ bearing an incorrect HMAC signature can be dropped immediately without response. .B file -(required) is a key file which can be in one of two formats: - -.B (1) -An OpenVPN static key file generated by +(required) is a file in OpenVPN static key format which can be generated by .B \-\-genkey -(required if -.B direction -parameter is used). - -.B (2) -A freeform passphrase file. In this case the HMAC key will -be derived by taking a secure hash of this file, similar to -the -.BR md5sum (1) -or -.BR sha1sum (1) -commands. -OpenVPN will first try format (1), and if the file fails to parse as -a static key file, format (2) will be used. +Older versions (up to 2.3) supported a freeform passphrase file. +This is no longer supported in newer versions (2.4+). See the .B \-\-secret diff --git a/app/openvpn/sample/sample-config-files/client.conf b/app/openvpn/sample/sample-config-files/client.conf index 58b2038b..050ef600 100644 --- a/app/openvpn/sample/sample-config-files/client.conf +++ b/app/openvpn/sample/sample-config-files/client.conf @@ -89,18 +89,19 @@ ca ca.crt cert client.crt key client.key -# Verify server certificate by checking -# that the certicate has the nsCertType -# field set to "server". This is an -# important precaution to protect against +# Verify server certificate by checking that the +# certicate has the correct key usage set. +# This is an important precaution to protect against # a potential attack discussed here: # http://openvpn.net/howto.html#mitm # # To use this feature, you will need to generate -# your server certificates with the nsCertType -# field set to "server". The build-key-server -# script in the easy-rsa folder will do this. -ns-cert-type server +# your server certificates with the keyUsage set to +# digitalSignature, keyEncipherment +# and the extendedKeyUsage to +# serverAuth +# EasyRSA can do this for you. +remote-cert-tls server # If a tls-auth key is used on the server # then every client must also have the key. diff --git a/app/openvpn/sample/sample-config-files/loopback-client b/app/openvpn/sample/sample-config-files/loopback-client index d7f59e69..ebbd1cf4 100644 --- a/app/openvpn/sample/sample-config-files/loopback-client +++ b/app/openvpn/sample/sample-config-files/loopback-client @@ -17,9 +17,9 @@ dev null verb 3 reneg-sec 10 tls-client +remote-cert-tls server ca sample-keys/ca.crt key sample-keys/client.key cert sample-keys/client.crt -cipher DES-EDE3-CBC ping 1 inactive 120 10000000 diff --git a/app/openvpn/sample/sample-config-files/loopback-server b/app/openvpn/sample/sample-config-files/loopback-server index 9d21bcec..8cb97be0 100644 --- a/app/openvpn/sample/sample-config-files/loopback-server +++ b/app/openvpn/sample/sample-config-files/loopback-server @@ -17,10 +17,9 @@ dev null verb 3 reneg-sec 10 tls-server -dh sample-keys/dh1024.pem +dh sample-keys/dh2048.pem ca sample-keys/ca.crt key sample-keys/server.key cert sample-keys/server.crt -cipher DES-EDE3-CBC ping 1 inactive 120 10000000 diff --git a/app/openvpn/sample/sample-config-files/server.conf b/app/openvpn/sample/sample-config-files/server.conf index 467d5b8a..701be3cc 100644 --- a/app/openvpn/sample/sample-config-files/server.conf +++ b/app/openvpn/sample/sample-config-files/server.conf @@ -81,10 +81,8 @@ key server.key # This file should be kept secret # Diffie hellman parameters. # Generate your own with: -# openssl dhparam -out dh1024.pem 1024 -# Substitute 2048 for 1024 if you are using -# 2048 bit keys. -dh dh1024.pem +# openssl dhparam -out dh2048.pem 2048 +dh dh2048.pem # Network topology # Should be subnet (addressing via IP) diff --git a/app/openvpn/sample/sample-config-files/tls-office.conf b/app/openvpn/sample/sample-config-files/tls-office.conf index f790f469..d1961444 100644 --- a/app/openvpn/sample/sample-config-files/tls-office.conf +++ b/app/openvpn/sample/sample-config-files/tls-office.conf @@ -26,7 +26,7 @@ up ./office.up tls-server # Diffie-Hellman Parameters (tls-server only) -dh dh1024.pem +dh dh2048.pem # Certificate Authority file ca my-ca.crt diff --git a/app/openvpn/sample/sample-keys/README b/app/openvpn/sample/sample-keys/README index 9f4f9187..66dd9454 100644 --- a/app/openvpn/sample/sample-keys/README +++ b/app/openvpn/sample/sample-keys/README @@ -1,14 +1,19 @@ Sample RSA and EC keys. +Run ./gen-sample-keys.sh to generate fresh test keys. + See the examples section of the man page for usage examples. NOTE: THESE KEYS ARE FOR TESTING PURPOSES ONLY. DON'T USE THEM FOR ANY REAL WORK BECAUSE THEY ARE TOTALLY INSECURE! -ca.{crt,key} -- sample CA key/cert -client.{crt,key} -- sample client key/cert -server.{crt,key} -- sample server key/cert (nsCertType=server) -pass.{crt,key} -- sample client key/cert with password-encrypted key - password = "password" -ec-*.{crt,key} -- sample elliptic curve variants of the above +ca.{crt,key} -- sample CA key/cert +server.{crt,key} -- sample server key/cert +client.{crt,key} -- sample client key/cert +client-pass.key -- sample client key with password-encrypted key + password = "password" +client.p12 -- sample client pkcs12 bundle + password = "password" +client-ec.{crt,key} -- sample elliptic curve client key/cert +server-ec.{crt,key} -- sample elliptic curve server key/cert diff --git a/app/openvpn/sample/sample-keys/ca.crt b/app/openvpn/sample/sample-keys/ca.crt index e063ccce..a11bafa7 100644 --- a/app/openvpn/sample/sample-keys/ca.crt +++ b/app/openvpn/sample/sample-keys/ca.crt @@ -1,19 +1,35 @@ -----BEGIN CERTIFICATE----- -MIIDBjCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJLRzEL +MIIGKDCCBBCgAwIBAgIJAKFO3vqQ8q6BMA0GCSqGSIb3DQEBCwUAMGYxCzAJBgNV +BAYTAktHMQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UEChMM +T3BlblZQTi1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4w +HhcNMTQxMDIyMjE1OTUyWhcNMjQxMDE5MjE1OTUyWjBmMQswCQYDVQQGEwJLRzEL MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t -VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTA0MTEy -NTE0NDA1NVoXDTE0MTEyMzE0NDA1NVowZjELMAkGA1UEBhMCS0cxCzAJBgNVBAgT -Ak5BMRAwDgYDVQQHEwdCSVNIS0VLMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxITAf -BgkqhkiG9w0BCQEWEm1lQG15aG9zdC5teWRvbWFpbjCBnzANBgkqhkiG9w0BAQEF -AAOBjQAwgYkCgYEAqPjWJnesPu6bR/iec4FMz3opVaPdBHxg+ORKNmrnVZPh0t8/ -ZT34KXkYoI9B82scurp8UlZVXG8JdUsz+yai8ti9+g7vcuyKUtcCIjn0HLgmdPu5 -gFX25lB0pXw+XIU031dOfPvtROdG5YZN5yCErgCy7TE7zntLnkEDuRmyU6cCAwEA -AaOBwzCBwDAdBgNVHQ4EFgQUiaZg47rqPq/8ZH9MvYzSSI3gzEYwgZAGA1UdIwSB -iDCBhYAUiaZg47rqPq/8ZH9MvYzSSI3gzEahaqRoMGYxCzAJBgNVBAYTAktHMQsw -CQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UEChMMT3BlblZQTi1U -RVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW6CAQAwDAYDVR0T -BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBfJoiWYrYdjM0mKPEzUQk0nLYTovBP -I0es/2rfGrin1zbcFY+4dhVBd1E/StebnG+CP8r7QeEIwu7x8gYDdOLLsZn+2vBL -e4jNU1ClI6Q0L7jrzhhunQ5mAaZztVyYwFB15odYcdN2iO0tP7jtEsvrRqxICNy3 -8itzViPTf5W4sA== +VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsJVPCqt3vtoDW2U0DII1QIh2Qs0dqh88 +8nivxAIm2LTq93e9fJhsq3P/UVYAYSeCIrekXypR0EQgSgcNTvGBMe20BoHO5yvb +GjKPmjfLj6XRotCOGy8EDl/hLgRY9efiA8wsVfuvF2q/FblyJQPR/gPiDtTmUiqF +qXa7AJmMrqFsnWppOuGd7Qc6aTsae4TF1e/gUTCTraa7NeHowDaKhdyFmEEnCYR5 +CeUsx2JlFWAH8PCrxBpHYbmGyvS0kH3+rQkaSM/Pzc2bS4ayHaOYRK5XsGq8XiNG +KTTLnSaCdPeHsI+3xMHmEh+u5Og2DFGgvyD22gde6W2ezvEKCUDrzR7bsnYqqyUy +n7LxnkPXGyvR52T06G8KzLKQRmDlPIXhzKMO07qkHmIonXTdF7YI1azwHpAtN4dS +rUe1bvjiTSoEsQPfOAyvD0RMK/CBfgEZUzAB50e/IlbZ84c0DJfUMOm4xCyft1HF +YpYeyCf5dxoIjweCPOoP426+aTXM7kqq0ieIr6YxnKV6OGGLKEY+VNZh1DS7enqV +HP5i8eimyuUYPoQhbK9xtDGMgghnc6Hn8BldPMcvz98HdTEH4rBfA3yNuCxLSNow +4jJuLjNXh2QeiUtWtkXja7ec+P7VqKTduJoRaX7cs+8E3ImigiRnvmK+npk7Nt1y +YE9hBRhSoLsCAwEAAaOB2DCB1TAdBgNVHQ4EFgQUK0DlyX319JY46S/jL9lAZMmO +BZswgZgGA1UdIwSBkDCBjYAUK0DlyX319JY46S/jL9lAZMmOBZuhaqRoMGYxCzAJ +BgNVBAYTAktHMQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UE +ChMMT3BlblZQTi1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21h +aW6CCQChTt76kPKugTAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG +9w0BAQsFAAOCAgEABc77f4C4P8fIS+V8qCJmVNSDU44UZBc+D+J6ZTgW8JeOHUIj +Bh++XDg3gwat7pIWQ8AU5R7h+fpBI9n3dadyIsMHGwSogHY9Gw7di2RVtSFajEth +rvrq0JbzpwoYedMh84sJ2qI/DGKW9/Is9+O52fR+3z3dY3gNRDPQ5675BQ5CQW9I +AJgLOqzD8Q0qrXYi7HaEqzNx6p7RDTuhFgvTd+vS5d5+28Z5fm2umnq+GKHF8W5P +ylp2Js119FTVO7brusAMKPe5emc7tC2ov8OFFemQvfHR41PLryap2VD81IOgmt/J +kX/j/y5KGux5HZ3lxXqdJbKcAq4NKYQT0mCkRD4l6szaCEJ+k0SiM9DdTcBDefhR +9q+pCOyMh7d8QjQ1075mF7T+PGkZQUW1DUjEfrZhICnKgq+iEoUmM0Ee5WtRqcnu +5BTGQ2mSfc6rV+Vr+eYXqcg7Nxb3vFXYSTod1UhefonVqwdmyJ2sC79zp36Tbo2+ +65NW2WJK7KzPUyOJU0U9bcu0utvDOvGWmG+aHbymJgcoFzvZmlXqMXn97pSFn4jV +y3SLRgJXOw1QLXL2Y5abcuoBVr4gCOxxk2vBeVxOMRXNqSWZOFIF1bu/PxuDA+Sa +hEi44aHbPXt9opdssz/hdGfd8Wo7vEJrbg7c6zR6C/Akav1Rzy9oohIdgOw= -----END CERTIFICATE----- diff --git a/app/openvpn/sample/sample-keys/ca.key b/app/openvpn/sample/sample-keys/ca.key index b4bf792a..8b11bc22 100644 --- a/app/openvpn/sample/sample-keys/ca.key +++ b/app/openvpn/sample/sample-keys/ca.key @@ -1,15 +1,52 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQCo+NYmd6w+7ptH+J5zgUzPeilVo90EfGD45Eo2audVk+HS3z9l -PfgpeRigj0Hzaxy6unxSVlVcbwl1SzP7JqLy2L36Du9y7IpS1wIiOfQcuCZ0+7mA -VfbmUHSlfD5chTTfV058++1E50blhk3nIISuALLtMTvOe0ueQQO5GbJTpwIDAQAB -AoGAQuVREyWp4bhhbZr2UFBOco2ws6EOLWp4kdD/uI+WSoEjlHKiDJj+GJ1CrL5K -o+4yD5MpCQf4/4FOQ0ukprfjJpDwDinTG6vzuWSLTHNiTgvksW3vy7IsNMJx97hT -4D2QOOl9HhA50Qqg70teMPYXOgLRMVsdCIV7p7zDNy4nM+ECQQDX8m5ZcQmPtUDA -38dPTfpL4U7kMB94FItJYH/Lk5kMW1/J33xymNhL+BHaG064ol9n2ubGW4XEO5t2 -qE1IOsVpAkEAyE/x/OBVSI1s75aYGlEwMd87p3qaDdtXT7WzujjRY7r8Y1ynkMU6 -GtMeneBX/lk4BY/6I+5bhAzce+hqhaXejwJBAL5Wg+c4GApf41xdogqHm7doNyYw -OHyZ9w9NDDc+uGbI30xLPSCxEe0cEXgiG6foDpm2uzRZFTWaqHPU8pFYpAkCQGNX -cpWM0/7VVK9Fqk1y8knpgfY/UWOJ4jU/0dCLGR0ywLSuYNPlXDmtdkOp3TnhGW14 -x/9F2NEWZ8pzq1B4wHUCQQC5ztD4m/rpiIpinoewUJODoeBJXYBKqx1+mdrALCq6 -ESvK1WRiusMaY3xmsdv4J2TB5iUPryELbn3jU12WGcQc ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCwlU8Kq3e+2gNb +ZTQMgjVAiHZCzR2qHzzyeK/EAibYtOr3d718mGyrc/9RVgBhJ4Iit6RfKlHQRCBK +Bw1O8YEx7bQGgc7nK9saMo+aN8uPpdGi0I4bLwQOX+EuBFj15+IDzCxV+68Xar8V +uXIlA9H+A+IO1OZSKoWpdrsAmYyuoWydamk64Z3tBzppOxp7hMXV7+BRMJOtprs1 +4ejANoqF3IWYQScJhHkJ5SzHYmUVYAfw8KvEGkdhuYbK9LSQff6tCRpIz8/NzZtL +hrIdo5hErlewarxeI0YpNMudJoJ094ewj7fEweYSH67k6DYMUaC/IPbaB17pbZ7O +8QoJQOvNHtuydiqrJTKfsvGeQ9cbK9HnZPTobwrMspBGYOU8heHMow7TuqQeYiid +dN0XtgjVrPAekC03h1KtR7Vu+OJNKgSxA984DK8PREwr8IF+ARlTMAHnR78iVtnz +hzQMl9Qw6bjELJ+3UcVilh7IJ/l3GgiPB4I86g/jbr5pNczuSqrSJ4ivpjGcpXo4 +YYsoRj5U1mHUNLt6epUc/mLx6KbK5Rg+hCFsr3G0MYyCCGdzoefwGV08xy/P3wd1 +MQfisF8DfI24LEtI2jDiMm4uM1eHZB6JS1a2ReNrt5z4/tWopN24mhFpftyz7wTc +iaKCJGe+Yr6emTs23XJgT2EFGFKguwIDAQABAoICAQCEYPqnihI0PqZjnwQdGIQp +g+P8gl7pyY9cS0OhUueicEbyDI8+V9qn0kcmx61zKDY0Jq4QNd6tnlUCijTc6Mot +DwF2G1xsC4GvKxZiy89MOkhloanXETEeQZzDbbjvaM4UgL0AHLWPfZQRCjxbKXkE +0A5phgvAr2YSvBLHCVXhGN0fScXnwXouVsvgVdGtpcTWdIUa+KrNdQBGDbz6VCkW +31I76SQFy40d8PPX6ZjUJHDvnM14LycySO6XOkofRIVnXTqaOUiVBb2VKj5fX+Ro +ILdWZz4d6J3RiGXYwyTr4SGVKLjgxWfgUGZB7x+NrqgugNzuaLYrkuWKSEN42nWq +yoP6x6xtbAsmB6Fvdqwm/d8BmLhUweaVc0L7AYzXNsOBuT3kubJHMmu3Jv4xgyWk +l/MAGJQc7i7QQweGgsYZgR8WlbkWkSFpUcgQBDzDibb6nsD2jnYijQrnrrmiEjEI +R7MO551V+nFw9utiM8U9WIWwqzY0d98ujWkGjVe7uz9ZBVyg0DEAEj/zRi9T54aG +1V6CB2Cjyw+HzzsDw7yWroWzo4U9YfjbPKCoBsXlqQFLFwY8oL6mEZ7UOobaV1Zl +WtuHyYw3UNFxuSGPPyxJkFePIQLLvfKvh2R+V0DrT3UJRoKKlt9RejRSN0tOh0Cm +2YD6d7T/DXnQHomIQKhKEQKCAQEA3sgsDg0eKDK8pUyVE+9wW5kql12nTzpBtnCM +eg5J9OJcXKhCD/NIyUTIMXoMvZQpLwGUAYLgu4gE04zKWHDouf7MRSFltD5LJ7F2 +7nuYKHZXk0BhgMhdnQot3FKcOMrKCnZcM+RWX9ZJa8wO6whCaYCw7DtS0SSVODQk +9EwAgX6/Hq60V7ujPZJCyNd3o0bIdAA/0AQRTZUADP3AHgUzh71aysYJt+UKt1v0 +Xc7l6hn7Dn7Ewzpf+WdZ2pV7d3JUSBVKiTDxLV904nDBNOxjMhz0rW01ojR6bzpn +XhkFPqnmh+yEYGRgfSAAzkvSsSJEAtBFSicupA/6n83Lo2YvswKCAQEAyumuxP4Z +a7s8x8DFba7vuQ+KVxpkKgEz1sxnGRNQJm18/ss/Y5JiaLFYT3E72VkQfBQ2ngu+ +GrJL3OhiNhzy1KLGS6mrwULtKiuud5MMQDL0Pvkncr9NTy4rBnWzhp2XyPeETu8n +JpL2i2OK6lY/lgpBckXuap9gAl0fXk+y+BkZ71OoYaGnKpPjs+Xcq/qgPgZ7O3NW +1g+Bd2AVPSxQpXjuy5rgtQURCN733vkNBzFedKREx7Z6l8UPlK/Exuc7BMIHfn5V +dd0R3Th+82fkMNVJz6MKmHJ6CJI53M7co/YdAvIkxOFRIPGbO3arL2R69nRgAZBE +zLawx1JJTRIG2QKCAQATtZXgMFzopYR3A011FAvWrrhL5+czZS4HG/Hxom38kkIl +mGUv0BAybjlf1zJlW0RBelxDvfZv4Nq8dIo6RNLyEY601v2OcqxneJXTB3AwtDeP +OXTm1dMiX5IrGcvkYlx5jHsfxCW4GNcqCEWRmYt2lgIRBDaRdjEVZdeXHVo2GqaB +6mbeFCWe/t+VsSpOcaauTI9YseNt/66fd5uVjFRAwAnWQqr9b/AAxMvbuMAyc9X4 +NFLoCrQO9ovGgM8JhD3cmrWbaY8MupM2rU8KhZdJCbLD3ROPpCDo0jvu4TvLjXBt +ugkEFh1LNJedqKudLDDkJtTaeJjxvtAnbyeC7zltAoIBAC9TIyzUqq8io0FfZ2x2 +cXiy9CvuftABKcr+L0l85KOhw5ZVZvpdKNCMFDGrEi9WA28886QWzwbA8Mqb9FP0 +mnoXYLJC50kSx+ee+nju9dt/RtHtIFM15N0DwosmJnHODZmUiOo0AuiPPCs0UzDm +Xrwqtirlvn5ln2nNuEQxyGbuy8qys0HaBvf6OBA8GySNNpRgxJsQAn+4bBSgdzOm +Q0TkmKUqASCXBusPvbXmVjCIRiRkL5p4p8z/6+tct0NAqNYqPr80zc/IeKMkyw8P ++vucszNXLmBxyp53JEGoiXNAMnH+ca7tchOB5hePTMun3rneWInk0PcB4OcL/QaZ +nrkCggEBAN67+SvcWtM1BoLXSz5/apFAE+DicCv94PrvMBOhfvu1oBrElR1rBjiN +2B83SktkF4WhCXr10GP+RUpjaqPBtT7NW4r3fL5B8EPsHeabL+pg9e6wG1rH8GqG +toWecmfC9uqK7l1A59h5Oveq5K19bZTRZRjQtv2e4KQknlJR6cwy+TGUU5kAUlMt +vcivyjzxc0UQwq7zKktJq+xW/TZiSLgd3B32p0sXX378qFUJ4SO2UZ1OCh8R7PY1 +Fx25K/89Q1yGdbYiXb/Dx0a2WB9rP+b6alMl/dxPdqDKj2QXXkdh8+yvhVpQTyZw +B1RaqQXwzqrCH0F/vw3lRceYhcQvzcQ= +-----END PRIVATE KEY----- diff --git a/app/openvpn/sample/sample-keys/client-ec.crt b/app/openvpn/sample/sample-keys/client-ec.crt new file mode 100644 index 00000000..759dabae --- /dev/null +++ b/app/openvpn/sample/sample-keys/client-ec.crt @@ -0,0 +1,85 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4 (0x4) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=KG, ST=NA, L=BISHKEK, O=OpenVPN-TEST/emailAddress=me@myhost.mydomain + Validity + Not Before: Oct 22 21:59:53 2014 GMT + Not After : Oct 19 21:59:53 2024 GMT + Subject: C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Client-EC/emailAddress=me@myhost.mydomain + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:3b:ce:62:5d:6f:87:82:75:24:c2:58:f5:0e:88: + 4d:57:0d:06:b2:71:88:87:58:19:bb:de:5f:7f:52: + 62:51:a2:48:91:83:48:91:90:3e:87:02:0f:15:51: + f9:68:97:12:0a:fd:d2:3c:87:83:4b:65:54:00:44: + 8d:28:76:49:05 + ASN1 OID: secp256k1 + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Key Identifier: + 64:F6:49:88:E7:74:C1:AB:A5:FA:4F:2B:71:3C:25:13:3D:C8:94:C5 + X509v3 Authority Key Identifier: + keyid:2B:40:E5:C9:7D:F5:F4:96:38:E9:2F:E3:2F:D9:40:64:C9:8E:05:9B + DirName:/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain + serial:A1:4E:DE:FA:90:F2:AE:81 + + Signature Algorithm: sha256WithRSAEncryption + 32:3d:f0:08:67:dd:03:73:76:cc:76:52:0a:f6:97:d1:c6:fa: + 5f:d3:e6:28:c9:75:a7:08:a8:34:49:69:cf:eb:ab:da:86:b3: + 2e:65:17:ee:7e:b6:b5:6b:15:0b:dc:11:3a:b9:5a:b3:80:b8: + bb:f4:6c:cf:88:3a:10:83:7e:10:a0:82:87:6e:06:ec:78:62: + d4:d1:44:27:dd:2c:19:d8:1a:a1:ae:f4:a0:00:7f:53:5a:40: + 8a:c2:83:77:4b:26:7d:53:b0:d3:0f:2f:7c:28:70:ef:74:58: + 5b:de:81:94:4c:63:19:f0:79:cb:6c:b2:ec:32:1b:4b:e4:62: + 22:4f:ad:ac:4a:6f:a9:6e:c4:2a:8d:8a:88:19:09:fd:88:93: + 3c:27:4d:91:95:ff:57:84:13:fd:4a:68:db:20:df:10:e6:81: + 1d:fd:e7:1d:35:fb:19:02:dd:b5:5f:a0:c1:07:ec:74:b4:ef: + 8b:f9:33:9a:f2:a6:3b:6e:b6:4a:52:ab:5d:99:76:64:62:c4: + d5:3a:c6:81:8d:eb:c8:4b:02:af:e1:ca:60:e9:8d:c7:a9:2b: + ea:4f:56:31:d3:9a:11:c2:9c:83:5c:a2:8d:98:fe:cc:a5:ad: + 1f:51:c4:6e:cf:ff:a0:51:64:c8:7f:7f:32:05:4c:8d:7f:bf: + b8:ed:e5:81:5f:81:bd:1d:9b:3f:8a:83:27:26:b4:69:84:8b: + e5:d9:ea:fd:08:a8:aa:e4:3a:dc:29:4d:80:6c:13:f7:45:ce: + 92:f2:a9:f3:5f:90:83:d6:23:0f:50:e5:40:09:4c:6b:f2:73: + aa:d8:49:a7:a9:81:6e:bb:f2:e4:a5:7f:19:39:1d:65:f3:11: + 97:b1:2b:7c:2f:36:77:7f:75:fd:88:44:90:7c:f2:33:8d:cd: + 2c:f6:76:60:33:d3:f4:b3:8c:81:d7:85:89:cc:d7:d5:2c:94: + a9:31:3f:d3:63:a7:dc:82:3f:0a:d8:c5:71:97:69:3b:c1:69: + cb:f0:1b:be:15:c0:be:aa:fd:e8:13:2c:0c:3f:72:7b:7d:9c: + 3b:7f:b8:82:36:4b:ad:4d:16:19:b9:1c:b3:2d:d7:5f:8b:f8: + 14:ce:d4:13:e5:82:7a:1d:40:28:08:65:4a:19:d7:7a:35:09: + db:36:48:4b:96:44:bd:1f:12:b2:39:08:1e:5b:66:25:9b:e0: + 16:d3:79:05:e3:f6:90:da:95:95:33:a1:53:a8:3c:a9:f0:b2: + f5:d0:aa:80:a0:96:ca:8c:45:62:c2:74:04:91:68:27:fb:e9: + 97:be:3a:87:8a:85:28:2d:6e:a9:60:9b:63:ba:65:98:5e:bb: + 02:ee:ac:ba:be:f6:42:26 +-----BEGIN CERTIFICATE----- +MIIESTCCAjGgAwIBAgIBBDANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJLRzEL +MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t +VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTE0MTAy +MjIxNTk1M1oXDTI0MTAxOTIxNTk1M1owbTELMAkGA1UEBhMCS0cxCzAJBgNVBAgT +Ak5BMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxFzAVBgNVBAMTDlRlc3QtQ2xpZW50 +LUVDMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wVjAQBgcqhkjO +PQIBBgUrgQQACgNCAAQ7zmJdb4eCdSTCWPUOiE1XDQaycYiHWBm73l9/UmJRokiR +g0iRkD6HAg8VUflolxIK/dI8h4NLZVQARI0odkkFo4HIMIHFMAkGA1UdEwQCMAAw +HQYDVR0OBBYEFGT2SYjndMGrpfpPK3E8JRM9yJTFMIGYBgNVHSMEgZAwgY2AFCtA +5cl99fSWOOkv4y/ZQGTJjgWboWqkaDBmMQswCQYDVQQGEwJLRzELMAkGA1UECBMC +TkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4tVEVTVDEhMB8G +CSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluggkAoU7e+pDyroEwDQYJKoZI +hvcNAQELBQADggIBADI98Ahn3QNzdsx2Ugr2l9HG+l/T5ijJdacIqDRJac/rq9qG +sy5lF+5+trVrFQvcETq5WrOAuLv0bM+IOhCDfhCggoduBux4YtTRRCfdLBnYGqGu +9KAAf1NaQIrCg3dLJn1TsNMPL3wocO90WFvegZRMYxnwectssuwyG0vkYiJPraxK +b6luxCqNiogZCf2IkzwnTZGV/1eEE/1KaNsg3xDmgR395x01+xkC3bVfoMEH7HS0 +74v5M5rypjtutkpSq12ZdmRixNU6xoGN68hLAq/hymDpjcepK+pPVjHTmhHCnINc +oo2Y/sylrR9RxG7P/6BRZMh/fzIFTI1/v7jt5YFfgb0dmz+KgycmtGmEi+XZ6v0I +qKrkOtwpTYBsE/dFzpLyqfNfkIPWIw9Q5UAJTGvyc6rYSaepgW678uSlfxk5HWXz +EZexK3wvNnd/df2IRJB88jONzSz2dmAz0/SzjIHXhYnM19UslKkxP9Njp9yCPwrY +xXGXaTvBacvwG74VwL6q/egTLAw/cnt9nDt/uII2S61NFhm5HLMt11+L+BTO1BPl +gnodQCgIZUoZ13o1Cds2SEuWRL0fErI5CB5bZiWb4BbTeQXj9pDalZUzoVOoPKnw +svXQqoCglsqMRWLCdASRaCf76Ze+OoeKhSgtbqlgm2O6ZZheuwLurLq+9kIm +-----END CERTIFICATE----- diff --git a/app/openvpn/sample/sample-keys/client-ec.key b/app/openvpn/sample/sample-keys/client-ec.key new file mode 100644 index 00000000..81313800 --- /dev/null +++ b/app/openvpn/sample/sample-keys/client-ec.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQg2RVk/d0yok086M9bLPIi +eu4DfcBUwphOnkje1/7VSY+hRANCAAQ7zmJdb4eCdSTCWPUOiE1XDQaycYiHWBm7 +3l9/UmJRokiRg0iRkD6HAg8VUflolxIK/dI8h4NLZVQARI0odkkF +-----END PRIVATE KEY----- diff --git a/app/openvpn/sample/sample-keys/client-pass.key b/app/openvpn/sample/sample-keys/client-pass.key new file mode 100644 index 00000000..2bb8d4e9 --- /dev/null +++ b/app/openvpn/sample/sample-keys/client-pass.key @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,ECC1F209896FC2621233FFF6F1FFD045 + +i6t7VKTyNNELTvrBO464e02nFg9rvYwumxd0sfqcPtaKmRK2mrZmEd/Xh0Nv1WyB +PyuJo78qQixAtxObRbkSNINzTr5C8IDrE6+wQYCJinvO54U0o+ksv0tsyLngz1cb +is8ZqHXrRgJ3qGFQWmFRtFKFQvSXOTDX3fLkEB53HfeblQCxBCnJ82Sp7ivnVR/j +Q8qQRy1RMbzIN0trEGf0Zi4tHEvXL1u7Y+olQzSlmWWaQt20hhXUOMLhMtlRsAo7 +AwjlE94JjAfJ1q1dwIcRN4c9Lk8GkiX6w7nDpRACDpk2S8ifCqi69eGe4+g7owhL +74bgs64PmM9a2sNXy1v6WE3c/t6sSrZiMvrGsqMo4sBlrQ9WXe0Naon7heBkPcdS +px0YJjnyBXHMIH+ASmALSJ5JXq9vt2xRFf0dOsGapxhP+7bZJ5Pwyk/yUu5uHFbM +/aBemlrZJzlKeYiiwpwx2whQAtDwN41zMG+r27EzSU/AaDV40NPiwwycpWt/Bp1e +z1ag0JuS0an+PK4jmREtzT5U5BeAVM91x8YttOPpmUIpahAa1zwdYPRAIkbmPJ4z +ZH+9YoPH4hoBQKdIhshYktjdI++xNiKXAUGUz5YoX8S68SsLdmKvhnQ7fu5VvOkA +2pb7taXGy7zfn+a/fWauhuceV9HPlAXMIu3GsssODoNly3vpcFeiMySKppygJ3Eg +A3o9n8UepD+jXflKG/R/t7U3hT6LqSIvQWqBqYMEVFMCNzSsJ/ce/4veFvx343zT +qdxuzYqyiXM74cynpfqHdVa9SFICTesNdVDI0FdOXhSQ4bHJc7Xp9FFJdS0lMRw4 +ACwKxvs8lo4Gx1WFyCqH5OxosKtDHQYzdUJfSWVJlhhOFR3GncR9qSe3O5fkhJfs +TALnC+xTJyCkSB2k0/bxVLIhlkPdCwzsrN/B6X2CDBdg0mQIo0LaPzGF8VneM20d +XebYn751XSiL3HKyq8G5AEFwj9AO3Q8gKuP2fPoWdngJ2GT+mt1m2fIw9Igu39J0 +ZMegyUN0wSIiA5AkgryK9U+PJEiJmLzOJ/NGr7E5tPF18eZWapK4KZ8TXC4RNiye +g+apGa+xZJz2VQp/Mrcdj9D4UDJFQjrvKaS0PXJDoYUXFBoMv3rxijzRVxlhhuJY +yZ0At+UqZD5wpuWW6DRrgJIpy0HNhbaLmgsU0Co0HKviB0x8hvMJbi/uCoPTOdPz +sPB7CN2i3oXe7xw1HfSTSFWb4leqjlKwNgfV42ox0QUjkkADeeuY+56g/B2+QmdE +vXrc6sDwfNUwRUzeMn8yfum/aW1y/wrqF/qPTBQqFd85vlzS+NfXIKDg04cAljTu ++2BLzvizh9Bb68iG4PykNXbjbAir1EbQG1tCzq1eKhERjgrxdv6+XqAmvchMCeL5 +L6hvfQFBPCo/4xnMpU5wooFarO/kGdKlGr5rXOydgfL618Td18BIX+FHQFb3zzVU +y2NR4++DslJAZgAU+512zzpW1m3JtaRoyqyoLE2YFPlW804Xc1PBB3Ix6Wyzcegy +D4qMk5qxjBkXEsBBSCYfVbWoMBeMhnvxkz0b9wkPtAW/jEJCB2Kkn/5yMC0DkePO +-----END RSA PRIVATE KEY----- diff --git a/app/openvpn/sample/sample-keys/client.crt b/app/openvpn/sample/sample-keys/client.crt index c0474461..1744cb22 100644 --- a/app/openvpn/sample/sample-keys/client.crt +++ b/app/openvpn/sample/sample-keys/client.crt @@ -2,64 +2,102 @@ Certificate: Data: Version: 3 (0x2) Serial Number: 2 (0x2) - Signature Algorithm: md5WithRSAEncryption + Signature Algorithm: sha256WithRSAEncryption Issuer: C=KG, ST=NA, L=BISHKEK, O=OpenVPN-TEST/emailAddress=me@myhost.mydomain Validity - Not Before: Nov 25 14:46:49 2004 GMT - Not After : Nov 23 14:46:49 2014 GMT + Not Before: Oct 22 21:59:53 2014 GMT + Not After : Oct 19 21:59:53 2024 GMT Subject: C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Client/emailAddress=me@myhost.mydomain Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public Key: (1024 bit) - Modulus (1024 bit): - 00:d2:12:5c:c6:4d:13:34:ae:cf:fa:ab:fe:cb:de: - 8c:f1:4b:4a:95:28:60:87:82:2c:b8:c1:e5:8e:c6: - 5d:11:58:61:a4:a5:f1:42:d7:86:74:6c:9d:9c:7a: - f0:3a:5c:29:e6:53:3b:5e:6d:d8:f0:45:06:2c:23: - ee:09:bc:02:8f:0e:b8:d5:33:1f:c3:4a:11:02:48: - 0b:cc:4b:ad:6e:74:e0:a2:53:b1:d6:cc:89:b9:e2: - 6f:db:15:b3:19:1e:57:04:79:48:3a:da:76:31:fc: - bf:d3:34:21:e7:32:d8:9e:06:4e:be:f3:e3:79:b0: - 54:fd:d1:42:32:aa:3e:7a:c1 + Public-Key: (2048 bit) + Modulus: + 00:ec:65:8f:e9:12:c2:1a:5b:e6:56:2a:08:a9:82: + 3a:2d:44:78:a3:00:3b:b0:9f:e7:27:10:40:93:ef: + f1:cc:3e:a0:aa:04:a2:80:1b:13:a9:e6:fe:81:d6: + 70:90:a8:d8:d4:de:30:d8:35:00:d2:be:62:f0:48: + da:fc:15:8d:c4:c6:6d:0b:99:f1:2b:83:00:0a:d3: + 2a:23:0b:e5:cd:f9:35:df:43:61:15:72:ad:95:98: + f6:73:21:41:5e:a0:dd:47:27:a0:d5:9a:d4:41:a8: + 1c:1d:57:20:71:17:8f:f7:28:9e:3e:07:ce:ec:d5: + 0e:42:4f:1e:74:47:8e:47:9d:d2:14:28:27:2c:14: + 10:f5:d1:96:b5:93:74:84:ef:f9:04:de:8d:4a:6f: + df:77:ab:ea:d1:58:d3:44:fe:5a:04:01:ff:06:7a: + 97:f7:fd:e3:57:48:e1:f0:df:40:13:9f:66:23:5a: + e3:55:54:3d:54:39:ee:00:f9:12:f1:d2:df:74:2e: + ba:d7:f0:8d:c6:dd:18:58:1c:93:22:0b:75:fa:a8: + d6:e0:b5:2f:2d:b9:d4:fe:b9:4f:86:e2:75:48:16: + 60:fb:3f:c9:b4:30:42:29:fb:3b:b3:2b:b9:59:81: + 6a:46:f3:45:83:bf:fd:d5:1a:ff:37:0c:6f:5b:fd: + 61:f1 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE - Netscape Comment: - OpenSSL Generated Certificate X509v3 Subject Key Identifier: - 17:B7:3F:C7:62:A0:A9:FD:A4:31:0E:58:D7:D9:94:7B:4B:3F:CB:56 + D2:B4:36:0F:B1:FC:DD:A5:EA:2A:F7:C7:23:89:FA:E3:FA:7A:44:1D X509v3 Authority Key Identifier: - keyid:89:A6:60:E3:BA:EA:3E:AF:FC:64:7F:4C:BD:8C:D2:48:8D:E0:CC:46 + keyid:2B:40:E5:C9:7D:F5:F4:96:38:E9:2F:E3:2F:D9:40:64:C9:8E:05:9B DirName:/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain - serial:00 + serial:A1:4E:DE:FA:90:F2:AE:81 - Signature Algorithm: md5WithRSAEncryption - 61:c6:d1:fa:24:0f:c7:be:09:3b:d8:04:17:63:31:17:07:f9: - 56:99:af:4c:67:fa:db:cb:94:cf:55:a5:7b:16:20:8b:42:64: - 13:23:62:45:28:93:5e:36:f7:db:02:95:a1:e9:fd:e3:0f:8d: - 73:a1:7b:0e:55:78:4d:a5:c4:b7:22:12:a0:ee:55:e0:b8:0e: - c9:9b:12:e3:b0:ef:9b:68:93:57:6e:6c:ad:16:68:8e:8d:30: - 33:fe:2a:1b:c3:03:8f:b6:0a:2d:0c:b1:3c:bb:f9:58:3f:8c: - 81:59:6b:14:dd:62:b5:c2:93:ed:5d:c6:19:0f:9b:4b:52:b3: - 7c:78 + Signature Algorithm: sha256WithRSAEncryption + 7f:e0:fe:84:a7:ec:df:62:a5:cd:3c:c1:e6:42:b1:31:12:f0: + b9:da:a7:9e:3f:bd:96:52:b6:fc:55:74:64:3e:e4:ff:7e:aa: + f7:3e:06:18:5f:73:85:f8:c8:e0:67:1b:4d:97:ca:05:d0:37: + 07:33:64:9b:e6:78:77:14:9a:55:bb:2a:ac:c3:7f:c9:15:08: + 83:5c:c8:c2:61:d3:71:4c:05:0b:2b:cb:a3:87:6d:a0:32:ed: + b0:b3:27:97:4a:55:8d:01:2a:30:56:68:ab:f2:da:5c:10:73: + c9:aa:0a:9c:4b:4c:a0:5b:51:6e:0a:7e:6c:53:80:b0:00:e1: + 1e:9a:4c:0a:37:9e:20:89:bc:c5:e5:79:58:b7:45:ff:d3:c4: + a1:fd:d9:78:3d:45:16:74:df:82:44:1d:1d:81:50:5a:b9:32: + 4c:e2:4f:3f:0e:3a:65:5a:64:83:3b:29:31:c4:99:88:bc:c5: + 84:39:f2:19:12:e1:66:d0:ea:fb:75:b1:d2:27:be:91:59:a3: + 2b:09:d5:5c:bf:46:8e:d6:67:d6:0b:ec:da:ab:f0:80:19:87: + 64:07:a9:77:b1:5e:0c:e2:c5:1d:6a:ac:5d:23:f3:30:75:36: + 4e:ca:c3:4e:b0:4d:8c:2c:ce:52:61:63:de:d5:f5:ef:ef:0a: + 6b:23:25:26:3c:3a:f2:c3:c2:16:19:3f:a9:32:ba:68:f9:c9: + 12:3c:3e:c6:1f:ff:9b:4e:f4:90:b0:63:f5:d1:33:00:30:5a: + e8:24:fa:35:44:9b:6a:80:f3:a6:cc:7b:3c:73:5f:50:c4:30: + 71:d8:74:90:27:0a:01:4e:a5:5e:b1:f8:da:c2:61:81:11:ae: + 29:a3:8f:fa:7e:4c:4e:62:b1:00:de:92:e3:8f:6a:2e:da:d9: + 38:5d:6b:7c:0d:e4:01:aa:c8:c6:6d:8b:cd:c0:c8:6e:e4:57: + 21:8a:f6:46:30:d9:ad:51:a1:87:96:a6:53:c9:1e:c6:bb:c3: + eb:55:fe:8c:d6:5c:d5:c6:f3:ca:b0:60:d2:d4:2a:1f:88:94: + d3:4c:1a:da:0c:94:fe:c1:5d:0d:2a:db:99:29:5d:f6:dd:16: + c4:c8:4d:74:9e:80:d9:d0:aa:ed:7b:e3:30:e4:47:d8:f5:15: + c1:71:b8:c6:fd:ee:fc:9e:b2:5f:b5:b7:92:ed:ff:ca:37:f6: + c7:82:b4:54:13:9b:83:cd:87:8b:7e:64:f6:2e:54:3a:22:b1: + c5:c1:f4:a5:25:53:9a:4d:a8:0f:e7:35:4b:89:df:19:83:66: + 64:d9:db:d1:61:2b:24:1b:1d:44:44:fb:49:30:87:b7:49:23: + 08:02:8a:e0:25:f3:f4:43 -----BEGIN CERTIFICATE----- -MIIDNTCCAp6gAwIBAgIBAjANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJLRzEL +MIIFFDCCAvygAwIBAgIBAjANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJLRzEL MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t -VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTA0MTEy -NTE0NDY0OVoXDTE0MTEyMzE0NDY0OVowajELMAkGA1UEBhMCS0cxCzAJBgNVBAgT +VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTE0MTAy +MjIxNTk1M1oXDTI0MTAxOTIxNTk1M1owajELMAkGA1UEBhMCS0cxCzAJBgNVBAgT Ak5BMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxFDASBgNVBAMTC1Rlc3QtQ2xpZW50 -MSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBANISXMZNEzSuz/qr/svejPFLSpUoYIeCLLjB5Y7GXRFY -YaSl8ULXhnRsnZx68DpcKeZTO15t2PBFBiwj7gm8Ao8OuNUzH8NKEQJIC8xLrW50 -4KJTsdbMibnib9sVsxkeVwR5SDradjH8v9M0Iecy2J4GTr7z43mwVP3RQjKqPnrB -AgMBAAGjge4wgeswCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBH -ZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFBe3P8dioKn9pDEOWNfZlHtL -P8tWMIGQBgNVHSMEgYgwgYWAFImmYOO66j6v/GR/TL2M0kiN4MxGoWqkaDBmMQsw -CQYDVQQGEwJLRzELMAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNV -BAoTDE9wZW5WUE4tVEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9t -YWluggEAMA0GCSqGSIb3DQEBBAUAA4GBAGHG0fokD8e+CTvYBBdjMRcH+VaZr0xn -+tvLlM9VpXsWIItCZBMjYkUok14299sClaHp/eMPjXOhew5VeE2lxLciEqDuVeC4 -DsmbEuOw75tok1dubK0WaI6NMDP+KhvDA4+2Ci0MsTy7+Vg/jIFZaxTdYrXCk+1d -xhkPm0tSs3x4 +MSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDsZY/pEsIaW+ZWKgipgjotRHijADuwn+cnEECT +7/HMPqCqBKKAGxOp5v6B1nCQqNjU3jDYNQDSvmLwSNr8FY3Exm0LmfErgwAK0yoj +C+XN+TXfQ2EVcq2VmPZzIUFeoN1HJ6DVmtRBqBwdVyBxF4/3KJ4+B87s1Q5CTx50 +R45HndIUKCcsFBD10Za1k3SE7/kE3o1Kb993q+rRWNNE/loEAf8Gepf3/eNXSOHw +30ATn2YjWuNVVD1UOe4A+RLx0t90LrrX8I3G3RhYHJMiC3X6qNbgtS8tudT+uU+G +4nVIFmD7P8m0MEIp+zuzK7lZgWpG80WDv/3VGv83DG9b/WHxAgMBAAGjgcgwgcUw +CQYDVR0TBAIwADAdBgNVHQ4EFgQU0rQ2D7H83aXqKvfHI4n64/p6RB0wgZgGA1Ud +IwSBkDCBjYAUK0DlyX319JY46S/jL9lAZMmOBZuhaqRoMGYxCzAJBgNVBAYTAktH +MQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UEChMMT3BlblZQ +Ti1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW6CCQChTt76 +kPKugTANBgkqhkiG9w0BAQsFAAOCAgEAf+D+hKfs32KlzTzB5kKxMRLwudqnnj+9 +llK2/FV0ZD7k/36q9z4GGF9zhfjI4GcbTZfKBdA3BzNkm+Z4dxSaVbsqrMN/yRUI +g1zIwmHTcUwFCyvLo4dtoDLtsLMnl0pVjQEqMFZoq/LaXBBzyaoKnEtMoFtRbgp+ +bFOAsADhHppMCjeeIIm8xeV5WLdF/9PEof3ZeD1FFnTfgkQdHYFQWrkyTOJPPw46 +ZVpkgzspMcSZiLzFhDnyGRLhZtDq+3Wx0ie+kVmjKwnVXL9GjtZn1gvs2qvwgBmH +ZAepd7FeDOLFHWqsXSPzMHU2TsrDTrBNjCzOUmFj3tX17+8KayMlJjw68sPCFhk/ +qTK6aPnJEjw+xh//m070kLBj9dEzADBa6CT6NUSbaoDzpsx7PHNfUMQwcdh0kCcK +AU6lXrH42sJhgRGuKaOP+n5MTmKxAN6S449qLtrZOF1rfA3kAarIxm2LzcDIbuRX +IYr2RjDZrVGhh5amU8kexrvD61X+jNZc1cbzyrBg0tQqH4iU00wa2gyU/sFdDSrb +mSld9t0WxMhNdJ6A2dCq7XvjMORH2PUVwXG4xv3u/J6yX7W3ku3/yjf2x4K0VBOb +g82Hi35k9i5UOiKxxcH0pSVTmk2oD+c1S4nfGYNmZNnb0WErJBsdRET7STCHt0kj +CAKK4CXz9EM= -----END CERTIFICATE----- diff --git a/app/openvpn/sample/sample-keys/client.key b/app/openvpn/sample/sample-keys/client.key index 17b95091..6d31489a 100644 --- a/app/openvpn/sample/sample-keys/client.key +++ b/app/openvpn/sample/sample-keys/client.key @@ -1,15 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDSElzGTRM0rs/6q/7L3ozxS0qVKGCHgiy4weWOxl0RWGGkpfFC -14Z0bJ2cevA6XCnmUztebdjwRQYsI+4JvAKPDrjVMx/DShECSAvMS61udOCiU7HW -zIm54m/bFbMZHlcEeUg62nYx/L/TNCHnMtieBk6+8+N5sFT90UIyqj56wQIDAQAB -AoGBAK8RoIGekCfym99DYYfTg9A/t/tQeAnWYaDj7oSrKbqf1lgZ91OGPEZgkoVr -KzLnxf9uU+bhUs8CJx+4HdO8/L9rAJA+oD9QNuMp0elN4AKuEGE1Eq3a0e3cmgPI -+VIoXM6WVAGgK9I03Zu/UerYQ/DdXWGOIsKhFe8qyQoG9pKxAkEA9ld6O9MHQt3d -JAjJkgCNn4psozxjrfLWy2huXd3H3CRqGMjLITDGzdkVSgXjHokBYroi0+TZTu4M -ulJSJaWwBQJBANpO2DAexH2zRHw5Z6QyeEVxz7B3/FzU4GgJx9BH+FSBh+F0G5Ln -ir5Vst8vZ/LGcgpYjHQLNAvZVgUjiQ4Y6I0CQGvwMJL+CHR4GmmroAblTyjU0n1D -/Lk/anZ+L73Za7U+D28ErFzCrpmLwRRKOBYtGfpUbOZDpCQ9kj4hy/TLALECQCcL -9ysUNbzt9Y/qjJkX1d9F7gn4TBEmmkTBixW76bTjvjQbGlt6Qpyso2O8DPGlgPxM -vkJ7RoHgC7y7kGYPGnkCQBVxSNGIjLx4NQBgN4HD0y4+fars1PTUGnckBcS4npb9 -onLNyerBlWdBwbARyBS7WPIbyyf5VCrn3yIqWxaARO0= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDsZY/pEsIaW+ZW +KgipgjotRHijADuwn+cnEECT7/HMPqCqBKKAGxOp5v6B1nCQqNjU3jDYNQDSvmLw +SNr8FY3Exm0LmfErgwAK0yojC+XN+TXfQ2EVcq2VmPZzIUFeoN1HJ6DVmtRBqBwd +VyBxF4/3KJ4+B87s1Q5CTx50R45HndIUKCcsFBD10Za1k3SE7/kE3o1Kb993q+rR +WNNE/loEAf8Gepf3/eNXSOHw30ATn2YjWuNVVD1UOe4A+RLx0t90LrrX8I3G3RhY +HJMiC3X6qNbgtS8tudT+uU+G4nVIFmD7P8m0MEIp+zuzK7lZgWpG80WDv/3VGv83 +DG9b/WHxAgMBAAECggEBAIOdaCpUD02trOh8LqZxowJhBOl7z7/ex0uweMPk67LT +i5AdVHwOlzwZJ8oSIknoOBEMRBWcLQEojt1JMuL2/R95emzjIKshHHzqZKNulFvB +TIUpdnwChTKtH0mqUkLlPU3Ienty4IpNlpmfUKimfbkWHERdBJBHbtDsTABhdo3X +9pCF/yRKqJS2Fy/Mkl3gv1y/NB1OL4Jhl7vQbf+kmgfQN2qdOVe2BOKQ8NlPUDmE +/1XNIDaE3s6uvUaoFfwowzsCCwN2/8QrRMMKkjvV+lEVtNmQdYxj5Xj5IwS0vkK0 +6icsngW87cpZxxc1zsRWcSTloy5ohub4FgKhlolmigECgYEA+cBlxzLvaMzMlBQY +kCac9KQMvVL+DIFHlZA5i5L/9pRVp4JJwj3GUoehFJoFhsxnKr8HZyLwBKlCmUVm +VxnshRWiAU18emUmeAtSGawlAS3QXhikVZDdd/L20YusLT+DXV81wlKR97/r9+17 +klQOLkSdPm9wcMDOWMNHX8bUg8kCgYEA8k+hQv6+TR/+Beao2IIctFtw/EauaJiJ +wW5ql1cpCLPMAOQUvjs0Km3zqctfBF8mUjdkcyJ4uhL9FZtfywY22EtRIXOJ/8VR +we65mVo6RLR8YVM54sihanuFOnlyF9LIBWB+9pUfh1/Y7DSebh7W73uxhAxQhi3Y +QwfIQIFd8OkCgYBalH4VXhLYhpaYCiXSej6ot6rrK2N6c5Tb2MAWMA1nh+r84tMP +gMoh+pDgYPAqMI4mQbxUmqZEeoLuBe6VHpDav7rPECRaW781AJ4ZM4cEQ3Jz/inz +4qOAMn10CF081/Ez9ykPPlU0bsYNWHNd4eB2xWnmUBKOwk7UgJatVPaUiQKBgQCI +f18CVGpzG9CHFnaK8FCnMNOm6VIaTcNcGY0mD81nv5Dt943P054BQMsAHTY7SjZW +HioRyZtkhonXAB2oSqnekh7zzxgv4sG5k3ct8evdBCcE1FNJc2eqikZ0uDETRoOy +s7cRxNNr+QxDkyikM+80HOPU1PMPgwfOSrX90GJQ8QKBgEBKohGMV/sNa4t14Iau +qO8aagoqh/68K9GFXljsl3/iCSa964HIEREtW09Qz1w3dotEgp2w8bsDa+OwWrLy +0SY7T5jRViM3cDWRlUBLrGGiL0FiwsfqiRiji60y19erJgrgyGVIb1kIgIBRkgFM +2MMweASzTmZcri4PA/5C0HYb +-----END PRIVATE KEY----- diff --git a/app/openvpn/sample/sample-keys/client.p12 b/app/openvpn/sample/sample-keys/client.p12 new file mode 100644 index 00000000..8458c797 Binary files /dev/null and b/app/openvpn/sample/sample-keys/client.p12 differ diff --git a/app/openvpn/sample/sample-keys/dh2048.pem b/app/openvpn/sample/sample-keys/dh2048.pem new file mode 100644 index 00000000..8eda59aa --- /dev/null +++ b/app/openvpn/sample/sample-keys/dh2048.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEArdnA32xujHPlPI+jPffHSoMUZ+b5gRz1H1Lw9//Gugm5TAsRiYrB +t2BDSsMKvAjyqN+i5SJv4TOk98kRRKB27iPvyXmiL945VaDQl/UehCySjYlGFUjW +9nuo+JwQxeSbw0TLiSYoYJZQ8X1CxPl9mgJl277O4cW1Gc8I/bWa+ipU/4K5wv3h +GI8nt+6A0jN3M/KebotMP101G4k0l0qsY4oRMTmP+z3oAP0qU9NZ1jiuMFVzRlNp +5FdYF7ctrH+tBF+QmyT4SRKSED4wE4oX6gp420NaBhIEQifIj75wlMDtxQlpkN+x +QkjsEbPlaPKHGQ4uupssChVUi8IM2yq5EwIBAg== +-----END DH PARAMETERS----- diff --git a/app/openvpn/sample/sample-keys/gen-sample-keys.sh b/app/openvpn/sample/sample-keys/gen-sample-keys.sh new file mode 100755 index 00000000..414687eb --- /dev/null +++ b/app/openvpn/sample/sample-keys/gen-sample-keys.sh @@ -0,0 +1,75 @@ +#!/bin/sh +# +# Run this script to set up a test CA, and test key-certificate pair for a +# server, and various clients. +# +# Copyright (C) 2014 Steffan Karger +set -eu + +command -v openssl >/dev/null 2>&1 || { echo >&2 "Unable to find openssl. Please make sure openssl is installed and in your path."; exit 1; } + +if [ ! -f openssl.cnf ] +then + echo "Please run this script from the sample directory" + exit 1 +fi + +# Create required directories and files +mkdir -p sample-ca +rm -f sample-ca/index.txt +touch sample-ca/index.txt +echo "01" > sample-ca/serial + +# Generate CA key and cert +openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 \ + -extensions easyrsa_ca -keyout sample-ca/ca.key -out sample-ca/ca.crt \ + -subj "/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain" \ + -config openssl.cnf + +# Create server key and cert +openssl req -new -nodes -config openssl.cnf -extensions server \ + -keyout sample-ca/server.key -out sample-ca/server.csr \ + -subj "/C=KG/ST=NA/O=OpenVPN-TEST/CN=Test-Server/emailAddress=me@myhost.mydomain" +openssl ca -batch -config openssl.cnf -extensions server \ + -out sample-ca/server.crt -in sample-ca/server.csr + +# Create client key and cert +openssl req -new -nodes -config openssl.cnf \ + -keyout sample-ca/client.key -out sample-ca/client.csr \ + -subj "/C=KG/ST=NA/O=OpenVPN-TEST/CN=Test-Client/emailAddress=me@myhost.mydomain" +openssl ca -batch -config openssl.cnf \ + -out sample-ca/client.crt -in sample-ca/client.csr + +# Create password protected key file +openssl rsa -aes256 -passout pass:password \ + -in sample-ca/client.key -out sample-ca/client-pass.key + +# Create pkcs#12 client bundle +openssl pkcs12 -export -nodes -password pass:password \ + -out sample-ca/client.p12 -inkey sample-ca/client.key \ + -in sample-ca/client.crt -certfile sample-ca/ca.crt + + +# Create EC server and client cert (signed by 'regular' RSA CA) +openssl ecparam -out sample-ca/secp256k1.pem -name secp256k1 + +openssl req -new -newkey ec:sample-ca/secp256k1.pem -nodes -config openssl.cnf \ + -extensions server \ + -keyout sample-ca/server-ec.key -out sample-ca/server-ec.csr \ + -subj "/C=KG/ST=NA/O=OpenVPN-TEST/CN=Test-Server-EC/emailAddress=me@myhost.mydomain" +openssl ca -batch -config openssl.cnf -extensions server \ + -out sample-ca/server-ec.crt -in sample-ca/server-ec.csr + +openssl req -new -newkey ec:sample-ca/secp256k1.pem -nodes -config openssl.cnf \ + -keyout sample-ca/client-ec.key -out sample-ca/client-ec.csr \ + -subj "/C=KG/ST=NA/O=OpenVPN-TEST/CN=Test-Client-EC/emailAddress=me@myhost.mydomain" +openssl ca -batch -config openssl.cnf \ + -out sample-ca/client-ec.crt -in sample-ca/client-ec.csr + +# Generate DH parameters +openssl dhparam -out dh2048.pem 2048 + +# Copy keys and certs to working directory +cp sample-ca/*.key . +cp sample-ca/*.crt . +cp sample-ca/*.p12 . diff --git a/app/openvpn/sample/sample-keys/openssl.cnf b/app/openvpn/sample/sample-keys/openssl.cnf new file mode 100644 index 00000000..aabfd48f --- /dev/null +++ b/app/openvpn/sample/sample-keys/openssl.cnf @@ -0,0 +1,139 @@ +# Heavily borrowed from EasyRSA 3, for use with OpenSSL 1.0.* + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = sample-ca # Where everything is kept +certs = $dir # Where the issued certs are kept +crl_dir = $dir # Where the issued crl are kept +database = $dir/index.txt # database index file. +new_certs_dir = $dir # default place for new certs. + +certificate = $dir/ca.crt # The CA certificate +serial = $dir/serial # The current serial number +crl = $dir/crl.pem # The current CRL +private_key = $dir/ca.key # The private key +RANDFILE = $dir/.rand # private random number file + +x509_extensions = basic_exts # The extentions to add to the cert + +# This allows a V2 CRL. Ancient browsers don't like it, but anything Easy-RSA +# is designed for will. In return, we get the Issuer attached to CRLs. +crl_extensions = crl_ext + +default_days = 3650 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha256 # use public key default MD +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_anything + +# For the 'anything' policy, which defines allowed DN fields +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +name = optional +emailAddress = optional + +#################################################################### +# Easy-RSA request handling +# We key off $DN_MODE to determine how to format the DN +[ req ] +default_bits = 2048 +default_keyfile = privkey.pem +default_md = sha256 +distinguished_name = cn_only +x509_extensions = easyrsa_ca # The extentions to add to the self signed cert + +# A placeholder to handle the $EXTRA_EXTS feature: +#%EXTRA_EXTS% # Do NOT remove or change this line as $EXTRA_EXTS support requires it + +#################################################################### +# Easy-RSA DN (Subject) handling + +# Easy-RSA DN for cn_only support: +[ cn_only ] +commonName = Common Name (eg: your user, host, or server name) +commonName_max = 64 +commonName_default = changeme + +# Easy-RSA DN for org support: +[ org ] +countryName = Country Name (2 letter code) +countryName_default = KG +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = NA + +localityName = Locality Name (eg, city) +localityName_default = BISHKEK + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenVPN-TEST + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = + +commonName = Common Name (eg: your user, host, or server name) +commonName_max = 64 +commonName_default = + +emailAddress = Email Address +emailAddress_default = me@myhost.mydomain +emailAddress_max = 64 + +#################################################################### + +[ basic_exts ] +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always + +# The Easy-RSA CA extensions +[ easyrsa_ca ] + +# PKIX recommendations: + +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer:always + +# This could be marked critical, but it's nice to support reading by any +# broken clients who attempt to do so. +basicConstraints = CA:true + +# Limit key usage to CA tasks. If you really want to use the generated pair as +# a self-signed cert, comment this out. +keyUsage = cRLSign, keyCertSign + +# CRL extensions. +[ crl_ext ] + +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + + +# Server extensions. +[ server ] + +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +extendedKeyUsage = serverAuth +keyUsage = digitalSignature, keyEncipherment diff --git a/app/openvpn/sample/sample-keys/server-ec.crt b/app/openvpn/sample/sample-keys/server-ec.crt new file mode 100644 index 00000000..7c7645a5 --- /dev/null +++ b/app/openvpn/sample/sample-keys/server-ec.crt @@ -0,0 +1,96 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=KG, ST=NA, L=BISHKEK, O=OpenVPN-TEST/emailAddress=me@myhost.mydomain + Validity + Not Before: Oct 22 21:59:53 2014 GMT + Not After : Oct 19 21:59:53 2024 GMT + Subject: C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server-EC/emailAddress=me@myhost.mydomain + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:21:09:ac:27:e6:00:3a:57:f4:f6:c7:78:a9:b1: + f4:d7:d7:45:59:39:e4:a3:d3:2c:94:f9:61:4a:e6: + b9:e9:87:57:c8:0f:88:03:a0:56:ee:34:e7:e4:4e: + 20:63:6c:c1:6e:c1:04:ac:b9:2f:a9:76:69:d3:7d: + 49:ff:f1:34:cb + ASN1 OID: secp256k1 + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Cert Type: + SSL Server + Netscape Comment: + OpenSSL Generated Server Certificate + X509v3 Subject Key Identifier: + 33:1A:42:61:9E:88:08:3F:6F:1F:98:88:3A:DD:2D:C7:07:3D:F6:9B + X509v3 Authority Key Identifier: + keyid:2B:40:E5:C9:7D:F5:F4:96:38:E9:2F:E3:2F:D9:40:64:C9:8E:05:9B + DirName:/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain + serial:A1:4E:DE:FA:90:F2:AE:81 + + X509v3 Extended Key Usage: + TLS Web Server Authentication + X509v3 Key Usage: + Digital Signature, Key Encipherment + Signature Algorithm: sha256WithRSAEncryption + 9d:89:f6:7e:0b:43:05:22:63:e5:b3:45:a8:d9:ef:33:3c:b7: + 19:37:28:87:27:43:43:86:a3:3f:b9:23:27:0f:96:4f:de:01: + 80:38:6b:d9:c8:94:77:1f:06:08:34:65:77:ad:57:0c:23:99: + f1:51:12:5f:32:d8:9c:7c:93:f1:f6:72:2a:05:61:ff:62:aa: + 33:aa:ef:a3:4d:d6:93:56:40:ff:38:2e:73:1c:69:fb:71:a1: + fa:64:19:6a:04:1c:8b:20:a8:ee:a5:18:63:f8:84:f4:ca:84: + 8e:b6:05:48:c6:f3:f7:81:90:4d:9e:00:cd:4a:92:83:d4:93: + 67:05:dc:16:8b:78:fa:b1:82:48:c6:86:74:44:b1:06:7e:8a: + c8:64:0b:82:3a:e2:f5:56:60:ea:50:70:03:da:9f:fc:28:20: + 6b:7d:04:e0:eb:8d:e2:f1:be:82:2f:ba:51:50:2b:6c:d2:fc: + 11:cd:69:85:3b:9e:14:19:dd:bc:14:cf:61:b0:7a:07:cb:e8: + e0:fc:c3:1f:a4:cb:cf:c1:e9:62:0f:d2:53:f8:ce:06:f4:f8: + 2f:55:13:aa:67:44:b6:b8:e8:3e:82:af:66:f5:f0:7c:fe:41: + e6:9d:c0:9f:78:fd:00:85:02:40:63:37:fa:00:e6:3c:a6:9f: + 35:4f:1d:a6:f1:cb:8b:04:e0:67:98:56:d1:87:58:b6:39:f6: + d3:fe:a8:40:50:80:7f:e6:4a:36:d0:c0:a5:61:64:1d:3a:87: + ad:78:72:c9:3f:98:44:35:f9:cf:32:b2:18:4c:b0:72:fa:5e: + 6c:62:1e:d4:31:0c:c8:9b:74:f0:00:9e:70:c3:1e:c7:a4:9d: + 03:a4:ac:1a:09:1f:86:23:65:51:34:50:86:68:1e:68:4d:9a: + 4b:78:10:1c:bd:51:09:bb:fe:16:a3:c7:19:b4:05:44:a1:e6: + c6:23:76:d5:b8:3a:eb:a5:17:1d:2b:2e:fe:85:7c:88:4f:f1: + e8:34:32:e0:c5:96:87:c3:e8:c9:5f:89:24:10:0e:1e:07:0b: + 2c:f8:d0:49:1b:63:5e:63:44:e9:2a:43:e2:9c:d6:f2:43:99: + 47:f8:9b:49:1a:a7:d1:e0:53:67:1d:cb:14:b6:b0:2c:4d:b3: + f2:c5:62:c2:a6:09:7a:c0:6c:59:3e:73:83:0c:6c:de:30:77: + 4d:1b:ed:b0:7f:77:87:8d:55:1d:d3:ed:f7:66:bd:06:2a:f8: + fd:00:e7:c0:31:e2:ff:53:9e:25:97:c6:64:84:9d:8d:61:8e: + c9:1f:6c:55:a1:7c:59:aa:eb:e8:2a:b2:2d:c7:09:cd:b5:3d: + d8:74:4f:6e:9c:3b:d5:6d +-----BEGIN CERTIFICATE----- +MIIEtTCCAp2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJLRzEL +MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t +VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTE0MTAy +MjIxNTk1M1oXDTI0MTAxOTIxNTk1M1owbTELMAkGA1UEBhMCS0cxCzAJBgNVBAgT +Ak5BMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxFzAVBgNVBAMTDlRlc3QtU2VydmVy +LUVDMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wVjAQBgcqhkjO +PQIBBgUrgQQACgNCAAQhCawn5gA6V/T2x3ipsfTX10VZOeSj0yyU+WFK5rnph1fI +D4gDoFbuNOfkTiBjbMFuwQSsuS+pdmnTfUn/8TTLo4IBMzCCAS8wCQYDVR0TBAIw +ADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2Vu +ZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUMxpCYZ6ICD9vH5iI +Ot0txwc99pswgZgGA1UdIwSBkDCBjYAUK0DlyX319JY46S/jL9lAZMmOBZuhaqRo +MGYxCzAJBgNVBAYTAktHMQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEV +MBMGA1UEChMMT3BlblZQTi1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3Qu +bXlkb21haW6CCQChTt76kPKugTATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8E +BAMCBaAwDQYJKoZIhvcNAQELBQADggIBAJ2J9n4LQwUiY+WzRajZ7zM8txk3KIcn +Q0OGoz+5IycPlk/eAYA4a9nIlHcfBgg0ZXetVwwjmfFREl8y2Jx8k/H2cioFYf9i +qjOq76NN1pNWQP84LnMcaftxofpkGWoEHIsgqO6lGGP4hPTKhI62BUjG8/eBkE2e +AM1KkoPUk2cF3BaLePqxgkjGhnREsQZ+ishkC4I64vVWYOpQcAPan/woIGt9BODr +jeLxvoIvulFQK2zS/BHNaYU7nhQZ3bwUz2GwegfL6OD8wx+ky8/B6WIP0lP4zgb0 ++C9VE6pnRLa46D6Cr2b18Hz+QeadwJ94/QCFAkBjN/oA5jymnzVPHabxy4sE4GeY +VtGHWLY59tP+qEBQgH/mSjbQwKVhZB06h614csk/mEQ1+c8yshhMsHL6XmxiHtQx +DMibdPAAnnDDHseknQOkrBoJH4YjZVE0UIZoHmhNmkt4EBy9UQm7/hajxxm0BUSh +5sYjdtW4OuulFx0rLv6FfIhP8eg0MuDFlofD6MlfiSQQDh4HCyz40EkbY15jROkq +Q+Kc1vJDmUf4m0kap9HgU2cdyxS2sCxNs/LFYsKmCXrAbFk+c4MMbN4wd00b7bB/ +d4eNVR3T7fdmvQYq+P0A58Ax4v9TniWXxmSEnY1hjskfbFWhfFmq6+gqsi3HCc21 +Pdh0T26cO9Vt +-----END CERTIFICATE----- diff --git a/app/openvpn/sample/sample-keys/server-ec.key b/app/openvpn/sample/sample-keys/server-ec.key new file mode 100644 index 00000000..8f2c914e --- /dev/null +++ b/app/openvpn/sample/sample-keys/server-ec.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgLHGYqSlzoRaogmJfrC+E +ozTothB9bORaQ1C/3FmeQ6ehRANCAAQhCawn5gA6V/T2x3ipsfTX10VZOeSj0yyU ++WFK5rnph1fID4gDoFbuNOfkTiBjbMFuwQSsuS+pdmnTfUn/8TTL +-----END PRIVATE KEY----- diff --git a/app/openvpn/sample/sample-keys/server.crt b/app/openvpn/sample/sample-keys/server.crt index 28bb4d94..76b40448 100644 --- a/app/openvpn/sample/sample-keys/server.crt +++ b/app/openvpn/sample/sample-keys/server.crt @@ -2,25 +2,34 @@ Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) - Signature Algorithm: md5WithRSAEncryption + Signature Algorithm: sha256WithRSAEncryption Issuer: C=KG, ST=NA, L=BISHKEK, O=OpenVPN-TEST/emailAddress=me@myhost.mydomain Validity - Not Before: Nov 25 14:42:22 2004 GMT - Not After : Nov 23 14:42:22 2014 GMT + Not Before: Oct 22 21:59:52 2014 GMT + Not After : Oct 19 21:59:52 2024 GMT Subject: C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server/emailAddress=me@myhost.mydomain Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public Key: (1024 bit) - Modulus (1024 bit): - 00:cb:4e:ac:f9:83:57:f6:69:d2:32:29:b4:bc:ad: - e6:f7:26:21:89:33:30:43:40:a3:35:d9:de:26:01: - d6:b4:f0:bc:0a:19:55:99:3b:f1:4c:91:60:b6:fd: - 74:34:8d:5a:c7:62:ec:ce:f2:d6:02:ce:57:32:f4: - 35:8c:71:a0:6d:65:2a:e7:80:ae:29:59:cf:36:73: - f8:7c:4a:73:90:fc:30:28:d5:46:7d:35:a4:4e:c9: - 9f:90:7b:e2:09:21:36:c5:a8:ec:85:82:9a:32:b4: - 91:3b:c1:d6:4f:9f:d1:f8:6f:68:f4:1d:d2:06:91: - 32:cc:9a:48:fd:cd:98:7f:2f + Public-Key: (2048 bit) + Modulus: + 00:a5:b8:a2:ee:ce:b1:a6:0f:6a:b2:9f:d3:22:17: + 79:de:09:98:71:78:fa:a7:ce:36:51:54:57:c7:31: + 99:56:d1:8a:d6:c5:fd:52:e6:88:0e:7b:f9:ea:27: + 7a:bf:3f:14:ec:aa:d2:ff:8b:56:58:ac:ca:51:77: + c5:3c:b6:e4:83:6f:22:06:2d:5b:eb:e7:59:d4:ab: + 42:c8:d5:a9:87:73:b3:73:36:51:2f:a5:d0:90:a2: + 87:64:54:6c:12:d3:b8:76:47:69:af:ae:8f:00:b3: + 70:b9:e7:67:3f:8c:6a:3d:79:5f:81:27:a3:0e:aa: + a7:3d:81:48:10:b1:18:6c:38:2e:8f:7a:7b:c5:3d: + 21:c8:f9:a0:7f:17:2b:88:4f:ba:f2:ec:6d:24:8e: + 6c:f1:0a:5c:d9:5b:b1:b0:fc:49:cb:4a:d2:58:c6: + 2a:25:b0:97:84:c3:9e:ff:34:8c:10:46:7f:0f:fb: + 3c:59:7a:a6:29:0c:ae:8e:50:3a:f2:53:84:40:2d: + d5:91:7b:0a:37:8e:82:77:ce:66:2f:34:77:5c:a5: + 45:3b:00:19:a7:07:d1:92:e6:66:b9:3b:4e:e9:63: + fc:33:98:1a:ae:7b:08:7d:0a:df:7a:ba:aa:59:6d: + 86:82:0a:64:2b:da:59:a7:4c:4e:ef:3d:bd:04:a2: + 4b:31 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: @@ -30,38 +39,75 @@ Certificate: Netscape Comment: OpenSSL Generated Server Certificate X509v3 Subject Key Identifier: - 69:11:FE:E7:9F:89:7B:71:34:69:C0:DC:82:F8:D0:5D:4D:FB:78:DF + B3:9D:81:E6:16:92:64:C4:86:87:F5:29:10:1B:5E:2F:74:F7:ED:B1 X509v3 Authority Key Identifier: - keyid:89:A6:60:E3:BA:EA:3E:AF:FC:64:7F:4C:BD:8C:D2:48:8D:E0:CC:46 + keyid:2B:40:E5:C9:7D:F5:F4:96:38:E9:2F:E3:2F:D9:40:64:C9:8E:05:9B DirName:/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain - serial:00 + serial:A1:4E:DE:FA:90:F2:AE:81 - Signature Algorithm: md5WithRSAEncryption - 35:5c:75:da:57:ef:b5:79:f2:a2:db:36:e4:75:e8:c7:bc:73: - 26:cf:30:36:4b:2e:51:46:37:60:2f:4e:2b:f6:71:a2:23:db: - 8e:d8:5c:d5:af:2e:22:28:dd:30:a8:89:66:3a:cc:5b:3c:0f: - 96:12:20:de:5e:41:52:74:35:ed:4c:26:40:19:ca:73:df:54: - b1:30:96:9c:a5:14:d0:38:28:3f:ab:30:07:d7:de:98:d2:7f: - 7f:90:b2:52:1d:e5:95:88:ed:ba:8a:6a:14:85:66:76:ec:75: - 30:e8:ae:94:f4:e1:76:fa:4b:0e:f1:53:d7:95:be:fb:69:fa: - 3d:32 + X509v3 Extended Key Usage: + TLS Web Server Authentication + X509v3 Key Usage: + Digital Signature, Key Encipherment + Signature Algorithm: sha256WithRSAEncryption + 4e:25:80:1b:cb:b0:42:ff:bb:3f:e8:0d:58:c1:80:db:cf:d0: + 90:df:ca:c1:e6:41:e1:48:7f:a7:1e:c7:35:9f:9c:6d:7c:3e: + 82:e8:de:7e:ae:82:16:00:33:0f:02:23:f1:9d:fe:2b:06:16: + 05:55:16:89:dc:63:ac:5f:1a:31:13:79:21:a3:6e:60:28:e8: + e7:6b:54:00:22:a1:b7:69:5a:17:31:ce:0f:c2:a6:dd:a3:6f: + de:ea:19:6c:d2:d2:cb:35:9d:dd:87:51:33:68:cd:c3:9b:90: + 55:f1:80:3d:5c:b8:09:b6:e1:3c:13:a4:5d:4a:ce:a5:11:9e: + f9:08:ee:be:e3:54:1d:06:4c:bb:1b:72:13:ee:7d:a0:45:cc: + fe:d1:3b:02:03:c1:d4:ea:45:2d:a8:c9:97:e7:f3:8a:7a:a0: + 2f:dd:48:3a:75:c9:42:28:94:fc:af:44:52:16:68:98:d6:ad: + a8:65:b1:cd:ac:60:41:70:e5:44:e8:5a:f2:e7:fc:3b:fe:45: + 89:17:1d:6d:85:c6:f0:fc:69:87:d1:1d:07:f3:cb:7b:54:8d: + aa:a3:cc:e3:c6:fc:d6:05:76:35:d0:26:63:8e:d1:a8:b7:ff: + 61:42:8a:2c:63:1f:d4:ec:14:47:6b:1e:e3:81:61:12:3b:8c: + 16:b5:cf:87:6a:2d:42:21:83:9c:0e:3a:90:3a:1e:c1:36:61: + 41:f9:fb:4e:5d:ea:f4:df:23:92:33:2b:9b:14:9f:a0:f5:d3: + c4:f8:1f:2f:9c:11:36:af:2a:22:61:95:32:0b:c4:1c:2d:b1: + c1:0a:2a:97:c0:43:4a:6c:3e:db:00:cd:29:15:9e:7e:41:75: + 36:a8:56:86:8c:82:9e:46:20:e5:06:1e:60:d2:03:5f:9f:9e: + 69:bb:bf:c2:b4:43:e2:7d:85:17:83:18:41:b0:cb:a9:04:1b: + 18:52:9f:89:8b:76:9f:94:59:81:4f:60:5b:33:18:fc:c7:52: + d0:d2:69:fc:0b:a2:63:32:75:43:99:e9:d7:f8:6d:c7:55:31: + 0c:f3:ef:1a:71:e1:0a:57:e1:9d:13:b2:1e:fe:1d:ef:e4:f1: + 51:d9:95:b3:fd:28:28:93:91:4a:29:c5:37:0e:ab:d8:85:6a: + fe:a8:83:1f:7b:80:5d:1f:04:79:b7:a9:08:6e:0d:d6:2e:aa: + 7c:f6:63:7d:41:de:70:13:32:ce:dd:58:cc:a6:73:d4:72:7e: + d7:ac:74:a8:35:ba:c3:1b:2a:64:d7:5a:37:97:56:94:34:2b: + 2a:71:60:bc:69:ab:00:85:b9:4f:67:32:17:51:c3:da:57:3a: + 37:89:66:c4:7a:51:da:5f -----BEGIN CERTIFICATE----- -MIIDUTCCArqgAwIBAgIBATANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJLRzEL +MIIFgDCCA2igAwIBAgIBATANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJLRzEL MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t -VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTA0MTEy -NTE0NDIyMloXDTE0MTEyMzE0NDIyMlowajELMAkGA1UEBhMCS0cxCzAJBgNVBAgT +VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTE0MTAy +MjIxNTk1MloXDTI0MTAxOTIxNTk1MlowajELMAkGA1UEBhMCS0cxCzAJBgNVBAgT Ak5BMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxFDASBgNVBAMTC1Rlc3QtU2VydmVy -MSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBAMtOrPmDV/Zp0jIptLyt5vcmIYkzMENAozXZ3iYB1rTw -vAoZVZk78UyRYLb9dDSNWsdi7M7y1gLOVzL0NYxxoG1lKueArilZzzZz+HxKc5D8 -MCjVRn01pE7Jn5B74gkhNsWo7IWCmjK0kTvB1k+f0fhvaPQd0gaRMsyaSP3NmH8v -AgMBAAGjggEJMIIBBTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDAzBglg -hkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmljYXRl -MB0GA1UdDgQWBBRpEf7nn4l7cTRpwNyC+NBdTft43zCBkAYDVR0jBIGIMIGFgBSJ -pmDjuuo+r/xkf0y9jNJIjeDMRqFqpGgwZjELMAkGA1UEBhMCS0cxCzAJBgNVBAgT -Ak5BMRAwDgYDVQQHEwdCSVNIS0VLMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxITAf -BgkqhkiG9w0BCQEWEm1lQG15aG9zdC5teWRvbWFpboIBADANBgkqhkiG9w0BAQQF -AAOBgQA1XHXaV++1efKi2zbkdejHvHMmzzA2Sy5RRjdgL04r9nGiI9uO2FzVry4i -KN0wqIlmOsxbPA+WEiDeXkFSdDXtTCZAGcpz31SxMJacpRTQOCg/qzAH196Y0n9/ -kLJSHeWViO26imoUhWZ27HUw6K6U9OF2+ksO8VPXlb77afo9Mg== +MSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCluKLuzrGmD2qyn9MiF3neCZhxePqnzjZRVFfH +MZlW0YrWxf1S5ogOe/nqJ3q/PxTsqtL/i1ZYrMpRd8U8tuSDbyIGLVvr51nUq0LI +1amHc7NzNlEvpdCQoodkVGwS07h2R2mvro8As3C552c/jGo9eV+BJ6MOqqc9gUgQ +sRhsOC6PenvFPSHI+aB/FyuIT7ry7G0kjmzxClzZW7Gw/EnLStJYxiolsJeEw57/ +NIwQRn8P+zxZeqYpDK6OUDryU4RALdWRewo3joJ3zmYvNHdcpUU7ABmnB9GS5ma5 +O07pY/wzmBquewh9Ct96uqpZbYaCCmQr2lmnTE7vPb0EoksxAgMBAAGjggEzMIIB +LzAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDAzBglghkgBhvhCAQ0EJhYk +T3BlblNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmljYXRlMB0GA1UdDgQWBBSz +nYHmFpJkxIaH9SkQG14vdPftsTCBmAYDVR0jBIGQMIGNgBQrQOXJffX0ljjpL+Mv +2UBkyY4Fm6FqpGgwZjELMAkGA1UEBhMCS0cxCzAJBgNVBAgTAk5BMRAwDgYDVQQH +EwdCSVNIS0VLMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxITAfBgkqhkiG9w0BCQEW +Em1lQG15aG9zdC5teWRvbWFpboIJAKFO3vqQ8q6BMBMGA1UdJQQMMAoGCCsGAQUF +BwMBMAsGA1UdDwQEAwIFoDANBgkqhkiG9w0BAQsFAAOCAgEATiWAG8uwQv+7P+gN +WMGA28/QkN/KweZB4Uh/px7HNZ+cbXw+gujefq6CFgAzDwIj8Z3+KwYWBVUWidxj +rF8aMRN5IaNuYCjo52tUACKht2laFzHOD8Km3aNv3uoZbNLSyzWd3YdRM2jNw5uQ +VfGAPVy4CbbhPBOkXUrOpRGe+QjuvuNUHQZMuxtyE+59oEXM/tE7AgPB1OpFLajJ +l+fzinqgL91IOnXJQiiU/K9EUhZomNatqGWxzaxgQXDlROha8uf8O/5FiRcdbYXG +8Pxph9EdB/PLe1SNqqPM48b81gV2NdAmY47RqLf/YUKKLGMf1OwUR2se44FhEjuM +FrXPh2otQiGDnA46kDoewTZhQfn7Tl3q9N8jkjMrmxSfoPXTxPgfL5wRNq8qImGV +MgvEHC2xwQoql8BDSmw+2wDNKRWefkF1NqhWhoyCnkYg5QYeYNIDX5+eabu/wrRD +4n2FF4MYQbDLqQQbGFKfiYt2n5RZgU9gWzMY/MdS0NJp/AuiYzJ1Q5np1/htx1Ux +DPPvGnHhClfhnROyHv4d7+TxUdmVs/0oKJORSinFNw6r2IVq/qiDH3uAXR8Eebep +CG4N1i6qfPZjfUHecBMyzt1YzKZz1HJ+16x0qDW6wxsqZNdaN5dWlDQrKnFgvGmr +AIW5T2cyF1HD2lc6N4lmxHpR2l8= -----END CERTIFICATE----- diff --git a/app/openvpn/sample/sample-keys/server.key b/app/openvpn/sample/sample-keys/server.key index 976acabf..011df12e 100644 --- a/app/openvpn/sample/sample-keys/server.key +++ b/app/openvpn/sample/sample-keys/server.key @@ -1,15 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQDLTqz5g1f2adIyKbS8reb3JiGJMzBDQKM12d4mAda08LwKGVWZ -O/FMkWC2/XQ0jVrHYuzO8tYCzlcy9DWMcaBtZSrngK4pWc82c/h8SnOQ/DAo1UZ9 -NaROyZ+Qe+IJITbFqOyFgpoytJE7wdZPn9H4b2j0HdIGkTLMmkj9zZh/LwIDAQAB -AoGBAKP1ljA/iY/zNY447kZ/5NWKzd7tBk4mcbl7M9no/7O6tZtbZRoIKoi6cYoC -C1ZabUyBbkNTud5XdCFmq0zRUjOWvoFMZ9VZfd2kRPvl4TGczBtJAq65b+EYMGui -q6T9p61xPdtzu0vM+Ecj127pAMk5XcJyxu8XQK7lZWmG5UoJAkEA8CxXNZN+A3qD -bMBPI3VdwKCNSjNVEQEnygMbNgw7VLdxPpspzZziqJEGdzsM4dsnOBwKxIWFLN2h -lbGBOquAswJBANi0atGWM8VUxDjvqqHCTS9RUXWgnvYhee4/xraJBQPBSivjC9P0 -vKT7PjBHU6djtKSLKGaHn1vHqmyY7PCMjZUCQQCNVSqExqSzG1dXmdt4PErNXi2G -6qo2dX2arTVIGu6XLdQgSWLSMm5XT/CEHWW5SyPLKwVTHFeATXQXCPvJML9tAkEA -k0yXax0g1ZoXwufN4SQUmPw6Va03P/BjU/nP1ZVvbiz9gLVU/d7WN4J7tA9XomkY -idv5OzAmtxkSE70jGSNAvQJAWhCf9+iHkzOHRyKKOYlh1DHUwDfSEp+hlZYg9H03 -P2sraQzUxgWDY/DIY63KvW78ny863baFz7onz21MYGgJXg== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCluKLuzrGmD2qy +n9MiF3neCZhxePqnzjZRVFfHMZlW0YrWxf1S5ogOe/nqJ3q/PxTsqtL/i1ZYrMpR +d8U8tuSDbyIGLVvr51nUq0LI1amHc7NzNlEvpdCQoodkVGwS07h2R2mvro8As3C5 +52c/jGo9eV+BJ6MOqqc9gUgQsRhsOC6PenvFPSHI+aB/FyuIT7ry7G0kjmzxClzZ +W7Gw/EnLStJYxiolsJeEw57/NIwQRn8P+zxZeqYpDK6OUDryU4RALdWRewo3joJ3 +zmYvNHdcpUU7ABmnB9GS5ma5O07pY/wzmBquewh9Ct96uqpZbYaCCmQr2lmnTE7v +Pb0EoksxAgMBAAECggEAPMOMin+jR75TYxeTNObiunVOPh0b2zeTVxLT9KfND7ZZ +cBK8pg79SEJRCnhbW5BnvbeNEkIm8PC6ZlDCM1bkRwUStq0fDUqQ95esLzOYq5/S +5qW98viblszhU/pYfja/Zi8dI1uf96PT63Zbt0NnGQ9N42+DLDeKhtTGdchZqiQA +LeSR0bQanY4tUUtCNYvBT8E3pzhoIsUzVwzIK53oovRpcOX3pMXVYZsmNhXdFFRy +YkjMXpj7fGyaAJK0QsC+PsgrKuhXDzDttsG2lI/mq9+7RXB3d/pzhmBVWynVH2lw +iQ7ONkSz7akDz/4I4WmxJep+FfQJYgK6rnLAlQqauQKBgQDammSAprnvDvNhSEp8 +W+xt7jQnFqaENbGgP0/D/OZMXc4khgexqlKFmSnBCRDmQ6JvLTWqDXC4+aqAbFQz +zAIjiKaT+so8xvFRob+rBMJY5JLYKNa+zUUanfORUNYLFJPvFqnrWGaJ9uufdaM7 +0a5bu95PN74NXee3DBbpBv8HLwKBgQDCEk+IjNbjMT+Neq0ywUeM5rFrUKi92abe +AgsVpjbighRV+6jA2lZFJcize+xYJ9wiOR1/TEI9PZ2OtBkqpwVdvTEHTagRLcvd +NfGcptREDnNLoNWA22buQpztiEduutACWQsrd+JQmqbUicUdW4zw86/oCMbYCW3V +QmYOLns7nwKBgHHUX20WZE91S4pmqFKlUzHTDdkk1ESX6Qx2q0R01j8BwawHFs6O +0DW9EZ7w55nfsh+OPRl1sjK/3ubMgfQO0TZLm+IGf3Sya0qEnVeiPMkpDMX+TgRA +wzEe+ou6uho+9uFSvdxMxeglaYA5M2ycvNwLsbEyZ4ZyVYxdgTiKahYFAoGAcIfP +iD0qKQiYcj/tB94cz+3AeJqHjbYT1O1YYhBECOkmQ4kuG80+cs/q5W/45lEOiuWV +Xgfo7Lu6jVGOujWoneci87oqtvNYH4e09oGh2WiLoBG9Wv9dWtBTUERSLzmxfXsG +SAk2uEhEbj8IhfJc8iZLHH9iVUh6YEslBBodqL8CgYEAlAhvcqAvw5SzsfBR5Mcu +4Nql6mXEVhHCvS4hdFCGaNF0z9A6eBORKJpdLWnqhpquDQDsghWE+Ga4QKSNFIi1 +fnAaykmZuY3ToqNOIaVlYM6HpMEz0wHQbTWfDLGcTFcElLZgMAk7VlDyiYVOco+E +QX9lXOO1PGpLzXhlDxSe63Y= +-----END PRIVATE KEY----- diff --git a/app/openvpn/src/openvpn/crypto.c b/app/openvpn/src/openvpn/crypto.c index 69df29de..eaef9643 100644 --- a/app/openvpn/src/openvpn/crypto.c +++ b/app/openvpn/src/openvpn/crypto.c @@ -223,30 +223,6 @@ err: return; } -int verify_hmac(struct buffer *buf, struct key_ctx *ctx, int offset) -{ - uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ - int hmac_len = 0; - - hmac_ctx_reset(ctx->hmac); - /* Assume the length of the input HMAC */ - hmac_len = hmac_ctx_size (ctx->hmac); - - /* Authentication fails if insufficient data in packet for HMAC */ - if (buf->len - offset < hmac_len) - return 0; - - hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len + offset, - BLEN (buf) - hmac_len - offset); - hmac_ctx_final (ctx->hmac, local_hmac); - - /* Compare locally computed HMAC with packet HMAC */ - if (memcmp_constant_time (local_hmac, BPTR (buf) + offset, hmac_len) == 0) - return hmac_len; - - return 0; -} - /* * If (opt->flags & CO_USE_IV) is not NULL, we will read an IV from the packet. * @@ -273,9 +249,25 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, /* Verify the HMAC */ if (ctx->hmac) { - int hmac_len = verify_hmac(buf, ctx, 0); - if (hmac_len == 0) + int hmac_len; + uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ + + hmac_ctx_reset(ctx->hmac); + + /* Assume the length of the input HMAC */ + hmac_len = hmac_ctx_size (ctx->hmac); + + /* Authentication fails if insufficient data in packet for HMAC */ + if (buf->len < hmac_len) + CRYPT_ERROR ("missing authentication info"); + + hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len, BLEN (buf) - hmac_len); + hmac_ctx_final (ctx->hmac, local_hmac); + + /* Compare locally computed HMAC with packet HMAC */ + if (memcmp_constant_time (local_hmac, BPTR (buf), hmac_len)) CRYPT_ERROR ("packet HMAC authentication failed"); + ASSERT (buf_advance (buf, hmac_len)); } @@ -399,28 +391,6 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, return false; } -/* - * This verifies if a packet and its HMAC fit to a crypto context. - * - * On success true is returned. - */ -bool -crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt) -{ - if (buf->len > 0 && opt->key_ctx_bi) - { - struct key_ctx *ctx = &opt->key_ctx_bi->decrypt; - - /* Verify the HMAC */ - if (ctx->hmac) - { - /* sizeof(uint32_t) comes from peer_id (3 bytes) and opcode (1 byte) */ - return verify_hmac(buf, ctx, sizeof(uint32_t)) != 0; - } - } - return false; -} - /* * How many bytes will we add to frame buffer for a given * set of crypto options? @@ -800,22 +770,13 @@ get_tls_handshake_key (const struct key_type *key_type, } else { - int hash_size; - CLEAR (key2); - /* failed, now try to get hash from a freeform file */ - hash_size = read_passphrase_hash (passphrase_file, - kt.digest, - key2.keys[0].hmac, - MAX_HMAC_KEY_LENGTH); - ASSERT (hash_size == kt.hmac_length); - - /* suceeded */ - key2.n = 1; + /* failed, now bail out */ - msg (M_INFO, - "Control Channel Authentication: using '%s' as a free-form passphrase file", + msg (M_ERR, + "Control Channel Authentication: File '%s' does not have OpenVPN Static Key format. " + "Using free-form passphrase file is not supported anymore", passphrase_file); } } @@ -1042,54 +1003,6 @@ read_key_file (struct key2 *key2, const char *file, const unsigned int flags) gc_free (&gc); } -int -read_passphrase_hash (const char *passphrase_file, - const md_kt_t *digest, - uint8_t *output, - int len) -{ - md_ctx_t md; - - ASSERT (len >= md_kt_size(digest)); - memset (output, 0, len); - - md_ctx_init(&md, digest); - - /* read passphrase file */ - { - const int min_passphrase_size = 8; - uint8_t buf[64]; - int total_size = 0; - int fd = platform_open (passphrase_file, O_RDONLY, 0); - - if (fd == -1) - msg (M_ERR, "Cannot open passphrase file: '%s'", passphrase_file); - - for (;;) - { - int size = read (fd, buf, sizeof (buf)); - if (size == 0) - break; - if (size == -1) - msg (M_ERR, "Read error on passphrase file: '%s'", - passphrase_file); - md_ctx_update(&md, buf, size); - total_size += size; - } - close (fd); - - warn_if_group_others_accessible (passphrase_file); - - if (total_size < min_passphrase_size) - msg (M_FATAL, - "Passphrase file '%s' is too small (must have at least %d characters)", - passphrase_file, min_passphrase_size); - } - md_ctx_final(&md, output); - md_ctx_cleanup(&md); - return md_kt_size(digest); -} - /* * Write key to file, return number of random bits * written. diff --git a/app/openvpn/src/openvpn/crypto.h b/app/openvpn/src/openvpn/crypto.h index 3c4e59d7..e4898278 100644 --- a/app/openvpn/src/openvpn/crypto.h +++ b/app/openvpn/src/openvpn/crypto.h @@ -6,7 +6,7 @@ * packet compression. * * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. - * Copyright (C) 2010 Fox Crypto B.V. + * Copyright (C) 2010-2014 Fox Crypto B.V. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -25,6 +25,76 @@ /** * @file Data Channel Cryptography Module + * + * @addtogroup data_crypto Data Channel Crypto module + * + * @par Crypto packet formats + * The Data Channel Crypto module supports a number of crypto modes and + * configurable options. The actual packet format depends on these options. A + * Data Channel packet can consist of: + * - \b Opcode, one byte specifying the packet type (see @ref network_protocol + * "Network protocol"). + * - \b Peer-id, if using the v2 data channel packet format (see @ref + * network_protocol "Network protocol"). + * - \b HMAC, covering the ciphertext IV + ciphertext. The HMAC size depends + * on the \c \-\-auth option. If \c \-\-auth \c none is specified, there is no + * HMAC at all. + * - \b Ciphertext \b IV, if not disabled by \c \-\-no-iv. The IV size depends on + * the \c \-\-cipher option. + * - \b Packet \b ID, a 32-bit incrementing packet counter that provides replay + * protection (if not disabled by \c \-\-no-replay). + * - \b Timestamp, a 32-bit timestamp of the current time. + * - \b Payload, the plain text network packet to be encrypted (unless + * encryption is disabled by using \c \-\-cipher \c none). The payload might + * already be compressed (see @ref compression "Compression module"). + * + * @par + * This section does not discuss the opcode and peer-id, since those do not + * depend on the data channel crypto. See @ref network_protocol + * "Network protocol" for more information on those. + * + * @par + * \e Legenda \n + * [ xxx ] = unprotected \n + * [ - xxx - ] = authenticated \n + * [ * xxx * ] = encrypted and authenticated + * + * @par + * CBC data channel cypto format \n + * In CBC mode, both TLS-mode and static key mode are supported. The IV + * consists of random bits to provide unpredictable IVs. \n + * CBC IV format: \n + * [ - random - ] \n + * CBC data channel crypto format in TLS-mode: \n + * [ HMAC ] [ - IV - ] [ * packet ID * ] [ * packet payload * ] \n + * CBC data channel crypto format in static key mode: \n + * [ HMAC ] [ - IV - ] [ * packet ID * ] [ * timestamp * ] + * [ * packet payload * ] + * + * @par + * CFB/OFB data channel crypto format \n + * CFB and OFB modes are only supported in TLS mode. In these modes, the IV + * consists of the packet counter and a timestamp. If the IV is more than 8 + * bytes long, the remaining space is filled with zeroes. The packet counter may + * not roll over within a single TLS sessions. This results in a unique IV for + * each packet, as required by the CFB and OFB cipher modes. + * + * @par + * CFB/OFB IV format: \n + * [ - packet ID - ] [ - timestamp - ] [ - opt: zero-padding - ] \n + * CFB/OFB data channel crypto format: \n + * [ HMAC ] [ - IV - ] [ * packet payload * ] + * + * @par + * No-crypto data channel format \n + * In no-crypto mode (\c \-\-cipher \c none is specified), both TLS-mode and + * static key mode are supported. No encryption will be performed on the packet, + * but packets can still be authenticated. This mode does not require an IV.\n + * No-crypto data channel crypto format in TLS-mode: \n + * [ HMAC ] [ - packet ID - ] [ - packet payload - ] \n + * No-crypto data channel crypto format in static key mode: \n + * [ HMAC ] [ - packet ID - ] [ - timestamp - ] [ - packet payload - ] + * */ #ifndef CRYPTO_H @@ -275,9 +345,6 @@ bool openvpn_decrypt (struct buffer *buf, struct buffer work, const struct crypto_options *opt, const struct frame* frame); - -bool crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt); - /** @} name Functions for performing security operations on data channel packets */ void crypto_adjust_frame_parameters(struct frame *frame, diff --git a/app/openvpn/src/openvpn/crypto_backend.h b/app/openvpn/src/openvpn/crypto_backend.h index 87498785..4e45df00 100644 --- a/app/openvpn/src/openvpn/crypto_backend.h +++ b/app/openvpn/src/openvpn/crypto_backend.h @@ -237,8 +237,7 @@ int cipher_kt_mode (const cipher_kt_t *cipher_kt); * * @return true iff the cipher is a CBC mode cipher. */ -bool cipher_kt_mode_cbc(const cipher_kt_t *cipher) - __attribute__((nonnull)); +bool cipher_kt_mode_cbc(const cipher_kt_t *cipher); /** * Check if the supplied cipher is a supported OFB or CFB mode cipher. @@ -247,8 +246,7 @@ bool cipher_kt_mode_cbc(const cipher_kt_t *cipher) * * @return true iff the cipher is a OFB or CFB mode cipher. */ -bool cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher) - __attribute__((nonnull)); +bool cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher); /** diff --git a/app/openvpn/src/openvpn/forward.c b/app/openvpn/src/openvpn/forward.c index 0bbdedb0..5709ee51 100644 --- a/app/openvpn/src/openvpn/forward.c +++ b/app/openvpn/src/openvpn/forward.c @@ -722,20 +722,11 @@ read_incoming_link (struct context *c) perf_pop (); } -/* - * Input: c->c2.buf - * Output: c->c2.to_tun - */ - -void -process_incoming_link (struct context *c) +bool +process_incoming_link_part1 (struct context *c, struct link_socket_info *lsi, bool floated) { struct gc_arena gc = gc_new (); - bool decrypt_status; - struct link_socket_info *lsi = get_link_socket_info (c); - const uint8_t *orig_buf = c->c2.buf.data; - - perf_push (PERF_PROC_IN_LINK); + bool decrypt_status = false; if (c->c2.buf.len > 0) { @@ -805,7 +796,7 @@ process_incoming_link (struct context *c) * will load crypto_options with the correct encryption key * and return false. */ - if (tls_pre_decrypt (c->c2.tls_multi, &c->c2.from, &c->c2.buf, &c->c2.crypto_options)) + if (tls_pre_decrypt (c->c2.tls_multi, &c->c2.from, &c->c2.buf, &c->c2.crypto_options, floated)) { interval_action (&c->c2.tmp_int); @@ -832,11 +823,25 @@ process_incoming_link (struct context *c) /* decryption errors are fatal in TCP mode */ register_signal (c, SIGUSR1, "decryption-error"); /* SOFT-SIGUSR1 -- decryption error in TCP mode */ msg (D_STREAM_ERRORS, "Fatal decryption error (process_incoming_link), restarting"); - goto done; } - +#else /* ENABLE_CRYPTO */ + decrypt_status = true; #endif /* ENABLE_CRYPTO */ + } + else + { + buf_reset (&c->c2.to_tun); + } + gc_free (&gc); + return decrypt_status; +} + +void +process_incoming_link_part2 (struct context *c, struct link_socket_info *lsi, const uint8_t *orig_buf) +{ + if (c->c2.buf.len > 0) + { #ifdef ENABLE_FRAGMENT if (c->c2.fragment) fragment_incoming (c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment); @@ -903,9 +908,20 @@ process_incoming_link (struct context *c) { buf_reset (&c->c2.to_tun); } - done: +} + +void +process_incoming_link (struct context *c) +{ + perf_push (PERF_PROC_IN_LINK); + + struct link_socket_info *lsi = get_link_socket_info (c); + const uint8_t *orig_buf = c->c2.buf.data; + + process_incoming_link_part1(c, lsi, false); + process_incoming_link_part2(c, lsi, orig_buf); + perf_pop (); - gc_free (&gc); } /* diff --git a/app/openvpn/src/openvpn/forward.h b/app/openvpn/src/openvpn/forward.h index 1830a00b..af3b0a67 100644 --- a/app/openvpn/src/openvpn/forward.h +++ b/app/openvpn/src/openvpn/forward.h @@ -127,12 +127,11 @@ void encrypt_sign (struct context *c, bool comp_frag); */ void read_incoming_link (struct context *c); - /** - * Process a packet read from the external network interface. + * Starts processing a packet read from the external network interface. * @ingroup external_multiplexer * - * This function controls the processing of a data channel packet which + * This function starts the processing of a data channel packet which * has come out of a VPN tunnel. It's high-level structure is as follows: * - Verify that a nonzero length packet has been received from a valid * source address for the given context \a c. @@ -146,6 +145,25 @@ void read_incoming_link (struct context *c); * - Call \c openvpn_decrypt() of the \link data_crypto Data Channel * Crypto module\endlink to authenticate and decrypt the packet using * the security parameters loaded by \c tls_pre_decrypt() above. + * + * @param c - The context structure of the VPN tunnel associated with the + * packet. + * @param lsi - link_socket_info obtained from context before processing. + * @param floated - Flag indicates that peer has floated. + * + * @return true if packet is authenticated, false otherwise. + */ +bool process_incoming_link_part1 (struct context *c, struct link_socket_info *lsi, bool floated); + +/** + * Continues processing a packet read from the external network interface. + * @ingroup external_multiplexer + * + * This function continues the processing of a data channel packet which + * has come out of a VPN tunnel. It must be called after + * \c process_incoming_link_part1() function. + * + * It's high-level structure is as follows: * - Call \c fragment_incoming() of the \link fragmentation Data Channel * Fragmentation module\endlink to reassemble the packet if it's * fragmented. @@ -158,9 +176,11 @@ void read_incoming_link (struct context *c); * * @param c - The context structure of the VPN tunnel associated with the * packet. + * @param lsi - link_socket_info obtained from context before processing. + * @param orig_buf - Pointer to a buffer data. + * */ -void process_incoming_link (struct context *c); - +void process_incoming_link_part2 (struct context *c, struct link_socket_info *lsi, const uint8_t *orig_buf); /** * Write a packet to the external network interface. diff --git a/app/openvpn/src/openvpn/helper.c b/app/openvpn/src/openvpn/helper.c index 0ed0b2ba..339e2aea 100644 --- a/app/openvpn/src/openvpn/helper.c +++ b/app/openvpn/src/openvpn/helper.c @@ -534,7 +534,7 @@ helper_tcp_nodelay (struct options *o) } else { - ASSERT (0); + o->sockflags |= SF_TCP_NODELAY; } } #endif diff --git a/app/openvpn/src/openvpn/init.c b/app/openvpn/src/openvpn/init.c index 7cec8d9b..b5c81f87 100644 --- a/app/openvpn/src/openvpn/init.c +++ b/app/openvpn/src/openvpn/init.c @@ -1797,12 +1797,14 @@ do_deferred_options (struct context *c, const unsigned int found) if (found & OPT_P_SETENV) msg (D_PUSH, "OPTIONS IMPORT: environment modified"); +#ifdef ENABLE_SSL if (found & OPT_P_PEER_ID) { msg (D_PUSH, "OPTIONS IMPORT: peer-id set"); c->c2.tls_multi->use_peer_id = true; c->c2.tls_multi->peer_id = c->options.peer_id; } +#endif } /* diff --git a/app/openvpn/src/openvpn/mtu.c b/app/openvpn/src/openvpn/mtu.c index 13f3f6c6..3665a34d 100644 --- a/app/openvpn/src/openvpn/mtu.c +++ b/app/openvpn/src/openvpn/mtu.c @@ -158,8 +158,7 @@ set_mtu_discover_type (int sd, int mtu_type) if (mtu_type >= 0) { #if defined(HAVE_SETSOCKOPT) && defined(SOL_IP) && defined(IP_MTU_DISCOVER) - if (setsockopt - (sd, SOL_IP, IP_MTU_DISCOVER, &mtu_type, sizeof (mtu_type))) + if (setsockopt (sd, SOL_IP, IP_MTU_DISCOVER, (void *) &mtu_type, sizeof (mtu_type))) msg (M_ERR, "Error setting IP_MTU_DISCOVER type=%d on TCP/UDP socket", mtu_type); #else @@ -288,7 +287,7 @@ void set_sock_extended_error_passing (int sd) { int on = 1; - if (setsockopt (sd, SOL_IP, IP_RECVERR, &on, sizeof (on))) + if (setsockopt (sd, SOL_IP, IP_RECVERR, (void *) &on, sizeof (on))) msg (M_WARN | M_ERRNO, "Note: enable extended error passing on TCP/UDP socket failed (IP_RECVERR)"); } diff --git a/app/openvpn/src/openvpn/mudp.c b/app/openvpn/src/openvpn/mudp.c index 51227a90..3e3f7508 100644 --- a/app/openvpn/src/openvpn/mudp.c +++ b/app/openvpn/src/openvpn/mudp.c @@ -33,59 +33,11 @@ #if P2MP_SERVER #include "multi.h" +#include #include "forward-inline.h" #include "memdbg.h" -/* - * Update instance with new peer address - */ -void -update_floated(struct multi_context *m, struct multi_instance *mi, - struct mroute_addr real, uint32_t hv) -{ - struct mroute_addr real_old; - - real_old = mi->real; - generate_prefix (mi); - - /* remove before modifying mi->real, since it also modifies key in hash */ - hash_remove(m->hash, &real_old); - hash_remove(m->iter, &real_old); - - /* update address */ - memcpy(&mi->real, &real, sizeof(real)); - - mi->context.c2.from = m->top.c2.from; - mi->context.c2.to_link_addr = &mi->context.c2.from; - - /* switch to new log prefix */ - generate_prefix (mi); - /* inherit buffers */ - mi->context.c2.buffers = m->top.c2.buffers; - - /* inherit parent link_socket and link_socket_info */ - mi->context.c2.link_socket = m->top.c2.link_socket; - mi->context.c2.link_socket_info->lsa->actual = m->top.c2.from; - - /* fix remote_addr in tls structure */ - tls_update_remote_addr (mi->context.c2.tls_multi, &mi->context.c2.from); - mi->did_open_context = true; - - hash_add(m->hash, &mi->real, mi, false); - hash_add(m->iter, &mi->real, mi, false); - - mi->did_real_hash = true; -#ifdef MANAGEMENT_DEF_AUTH - hash_remove (m->cid_hash, &mi->context.c2.mda_context.cid); - hash_add (m->cid_hash, &mi->context.c2.mda_context.cid, mi, false); -#endif - -#ifdef MANAGEMENT_DEF_AUTH - mi->did_cid_hash = true; -#endif -} - /* * Get a client instance based on real address. If * the instance doesn't exist, create it while @@ -93,7 +45,7 @@ update_floated(struct multi_context *m, struct multi_instance *mi, */ struct multi_instance * -multi_get_create_instance_udp (struct multi_context *m) +multi_get_create_instance_udp (struct multi_context *m, bool *floated) { struct gc_arena gc = gc_new (); struct mroute_addr real; @@ -108,32 +60,25 @@ multi_get_create_instance_udp (struct multi_context *m) uint8_t* ptr = BPTR(&m->top.c2.buf); uint8_t op = ptr[0] >> P_OPCODE_SHIFT; uint32_t peer_id; - bool hmac_mismatch = false; + int i; - if (op == P_DATA_V2) + /* make sure buffer has enough length to read opcode (1 byte) and peer-id (3 bytes) */ + if (op == P_DATA_V2 && m->top.c2.buf.len >= (1 + 3)) { - peer_id = ntohl((*(uint32_t*)ptr)) & 0xFFFFFF; + peer_id = ntohl(*(uint32_t*)ptr) & 0xFFFFFF; if ((peer_id < m->max_clients) && (m->instances[peer_id])) { mi = m->instances[peer_id]; - if (!link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from)) - { - msg(D_MULTI_MEDIUM, "float from %s to %s", - print_link_socket_actual (&mi->context.c2.from, &gc), print_link_socket_actual (&m->top.c2.from, &gc)); + *floated = !link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from); - /* peer-id is not trusted, so check hmac */ - hmac_mismatch = !(crypto_test_hmac(&m->top.c2.buf, &mi->context.c2.crypto_options)); - if (hmac_mismatch) - { - mi = NULL; - msg (D_MULTI_MEDIUM, "HMAC mismatch for peer-id %d", peer_id); - } - else - { - update_floated(m, mi, real, hv); - } - } + if (*floated) + { + /* reset prefix, since here we are not sure peer is the one it claims to be */ + ungenerate_prefix(mi); + msg (D_MULTI_ERRORS, "Untrusted peer %" PRIu32 " wants to float to %s", peer_id, + mroute_addr_print (&real, &gc)); + } } } else @@ -144,7 +89,7 @@ multi_get_create_instance_udp (struct multi_context *m) mi = (struct multi_instance *) he->value; } } - if (!mi && !hmac_mismatch) + if (!mi) { if (!m->top.c2.tls_auth_standalone || tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf)) @@ -157,8 +102,7 @@ multi_get_create_instance_udp (struct multi_context *m) hash_add_fast (hash, bucket, &mi->real, hv, mi); mi->did_real_hash = true; - int i; - for (i = 0; i < m->max_clients; ++ i) + for (i = 0; i < m->max_clients; ++i) { if (!m->instances[i]) { @@ -167,6 +111,10 @@ multi_get_create_instance_udp (struct multi_context *m) break; } } + + /* should not really end up here, since multi_create_instance returns null + * if amount of clients exceeds max_clients */ + ASSERT(i < m->max_clients); } } else diff --git a/app/openvpn/src/openvpn/mudp.h b/app/openvpn/src/openvpn/mudp.h index 97f961b3..1f15d9d2 100644 --- a/app/openvpn/src/openvpn/mudp.h +++ b/app/openvpn/src/openvpn/mudp.h @@ -65,7 +65,7 @@ void tunnel_server_udp (struct context *top); * packet's source address or if one was a newly created successfully. * NULL if one did not yet exist and a new one was not created. */ -struct multi_instance *multi_get_create_instance_udp (struct multi_context *m); +struct multi_instance *multi_get_create_instance_udp (struct multi_context *m, bool *floated); #endif #endif diff --git a/app/openvpn/src/openvpn/multi.c b/app/openvpn/src/openvpn/multi.c index bd5948c8..90b3d2dc 100644 --- a/app/openvpn/src/openvpn/multi.c +++ b/app/openvpn/src/openvpn/multi.c @@ -39,6 +39,7 @@ #include "gremlin.h" #include "mstats.h" #include "ssl_verify.h" +#include #include "memdbg.h" @@ -402,7 +403,7 @@ multi_instance_string (const struct multi_instance *mi, bool null, struct gc_are { if (mi) { - struct buffer out = alloc_buf_gc (256, gc); + struct buffer out = alloc_buf_gc (MULTI_PREFIX_MAX_LENGTH, gc); const char *cn = tls_common_name (mi->context.c2.tls_multi, true); if (cn) @@ -419,21 +420,27 @@ multi_instance_string (const struct multi_instance *mi, bool null, struct gc_are void generate_prefix (struct multi_instance *mi) { - mi->msg_prefix = multi_instance_string (mi, true, &mi->gc); + struct gc_arena gc = gc_new(); + const char *prefix = multi_instance_string (mi, true, &gc); + if (prefix) + strncpynt(mi->msg_prefix, prefix, sizeof(mi->msg_prefix)); + else + mi->msg_prefix[0] = '\0'; set_prefix (mi); + gc_free(&gc); } void ungenerate_prefix (struct multi_instance *mi) { - mi->msg_prefix = NULL; + mi->msg_prefix[0] = '\0'; set_prefix (mi); } static const char * mi_prefix (const struct multi_instance *mi) { - if (mi && mi->msg_prefix) + if (mi && mi->msg_prefix[0]) return mi->msg_prefix; else return "UNDEF_I"; @@ -814,8 +821,8 @@ multi_print_status (struct multi_context *m, struct status_output *so, const int */ status_printf (so, "TITLE%c%s", sep, title_string); status_printf (so, "TIME%c%s%c%u", sep, time_string (now, 0, false, &gc_top), sep, (unsigned int)now); - status_printf (so, "HEADER%cCLIENT_LIST%cCommon Name%cReal Address%cVirtual Address%cVirtual IPv6 Address%cBytes Received%cBytes Sent%cConnected Since%cConnected Since (time_t)%cUsername%cClient ID", - sep, sep, sep, sep, sep, sep, sep, sep, sep, sep, sep); + status_printf (so, "HEADER%cCLIENT_LIST%cCommon Name%cReal Address%cVirtual Address%cVirtual IPv6 Address%cBytes Received%cBytes Sent%cConnected Since%cConnected Since (time_t)%cUsername%cClient ID%cPeer ID", + sep, sep, sep, sep, sep, sep, sep, sep, sep, sep, sep, sep); hash_iterator_init (m->hash, &hi); while ((he = hash_iterator_next (&hi))) { @@ -826,10 +833,11 @@ multi_print_status (struct multi_context *m, struct status_output *so, const int { status_printf (so, "CLIENT_LIST%c%s%c%s%c%s%c%s%c" counter_format "%c" counter_format "%c%s%c%u%c%s%c" #ifdef MANAGEMENT_DEF_AUTH - "%lu", + "%lu" #else - "", + "" #endif + "%c%"PRIu32, sep, tls_common_name (mi->context.c2.tls_multi, false), sep, mroute_addr_print (&mi->real, &gc), sep, print_in_addr_t (mi->reporting_addr, IA_EMPTY_IF_UNDEF, &gc), @@ -840,10 +848,11 @@ multi_print_status (struct multi_context *m, struct status_output *so, const int sep, (unsigned int)mi->created, sep, tls_username (mi->context.c2.tls_multi, false), #ifdef MANAGEMENT_DEF_AUTH - sep, mi->context.c2.mda_context.cid); + sep, mi->context.c2.mda_context.cid, #else - sep); + sep, #endif + sep, mi->context.c2.tls_multi ? mi->context.c2.tls_multi->peer_id : UINT32_MAX); } gc_free (&gc); } @@ -2104,6 +2113,70 @@ multi_process_post (struct multi_context *m, struct multi_instance *mi, const un return ret; } +void multi_process_float (struct multi_context* m, struct multi_instance* mi) +{ + struct mroute_addr real; + struct hash *hash = m->hash; + struct gc_arena gc = gc_new (); + + if (!mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true)) + goto done; + + const uint32_t hv = hash_value (hash, &real); + struct hash_bucket *bucket = hash_bucket (hash, hv); + + struct hash_element *he = hash_lookup_fast (hash, bucket, &real, hv); + if (he) + { + struct multi_instance *ex_mi = (struct multi_instance *) he->value; + + const char *cn = tls_common_name (mi->context.c2.tls_multi, true); + const char *ex_cn = tls_common_name (ex_mi->context.c2.tls_multi, true); + if (cn && ex_cn && strcmp (cn, ex_cn)) + { + msg (D_MULTI_MEDIUM, "prevent float to %s", + multi_instance_string (ex_mi, false, &gc)); + + mi->context.c2.buf.len = 0; + + goto done; + } + + msg (D_MULTI_MEDIUM, "closing instance %s", multi_instance_string (ex_mi, false, &gc)); + multi_close_instance(m, ex_mi, false); + } + + msg (D_MULTI_MEDIUM, "peer %" PRIu32 " floated from %s to %s", mi->context.c2.tls_multi->peer_id, + mroute_addr_print (&mi->real, &gc), print_link_socket_actual (&m->top.c2.from, &gc)); + + ASSERT (hash_remove(m->hash, &mi->real)); + ASSERT (hash_remove(m->iter, &mi->real)); + + /* change external network address of the remote peer */ + mi->real = real; + generate_prefix (mi); + + mi->context.c2.from = m->top.c2.from; + mi->context.c2.to_link_addr = &mi->context.c2.from; + + /* inherit parent link_socket and link_socket_info */ + mi->context.c2.link_socket = m->top.c2.link_socket; + mi->context.c2.link_socket_info->lsa->actual = m->top.c2.from; + + tls_update_remote_addr (mi->context.c2.tls_multi, &mi->context.c2.from); + + ASSERT (hash_add (m->hash, &mi->real, mi, false)); + ASSERT (hash_add (m->iter, &mi->real, mi, false)); + +#ifdef MANAGEMENT_DEF_AUTH + hash_remove (m->cid_hash, &mi->context.c2.mda_context.cid); + hash_add (m->cid_hash, &mi->context.c2.mda_context.cid, mi, false); +#endif + +done: + gc_free (&gc); +} + /* * Process packets in the TCP/UDP socket -> TUN/TAP interface direction, * i.e. client -> server direction. @@ -2118,6 +2191,7 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins unsigned int mroute_flags; struct multi_instance *mi; bool ret = true; + bool floated = false; if (m->pending) return true; @@ -2127,7 +2201,7 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins #ifdef MULTI_DEBUG_EVENT_LOOP printf ("TCP/UDP -> TUN [%d]\n", BLEN (&m->top.c2.buf)); #endif - multi_set_pending (m, multi_get_create_instance_udp (m)); + multi_set_pending (m, multi_get_create_instance_udp (m, &floated)); } else multi_set_pending (m, instance); @@ -2145,13 +2219,30 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins c->c2.buf = m->top.c2.buf; /* transfer from-addr from top-level context buffer to instance */ - c->c2.from = m->top.c2.from; + if (!floated) + c->c2.from = m->top.c2.from; } if (BLEN (&c->c2.buf) > 0) { + struct link_socket_info *lsi; + const uint8_t *orig_buf; + /* decrypt in instance context */ - process_incoming_link (c); + + perf_push (PERF_PROC_IN_LINK); + lsi = get_link_socket_info (c); + orig_buf = c->c2.buf.data; + if (process_incoming_link_part1(c, lsi, floated)) + { + if (floated) + { + multi_process_float (m, m->pending); + } + + process_incoming_link_part2(c, lsi, orig_buf); + } + perf_pop (); if (TUNNEL_TYPE (m->top.c1.tuntap) == DEV_TYPE_TUN) { diff --git a/app/openvpn/src/openvpn/multi.h b/app/openvpn/src/openvpn/multi.h index 0446fbfc..32b89d25 100644 --- a/app/openvpn/src/openvpn/multi.h +++ b/app/openvpn/src/openvpn/multi.h @@ -42,6 +42,8 @@ #include "mtcp.h" #include "perf.h" +#define MULTI_PREFIX_MAX_LENGTH 256 + /* * Walk (don't run) through the routing table, * deleting old entries, and possibly multi_instance @@ -80,7 +82,7 @@ struct multi_instance { struct mroute_addr real; /**< External network address of the * remote peer. */ ifconfig_pool_handle vaddr_handle; - const char *msg_prefix; + char msg_prefix[MULTI_PREFIX_MAX_LENGTH]; /* queued outgoing data in Server/TCP mode */ unsigned int tcp_rwflags; @@ -125,7 +127,8 @@ struct multi_context { # define MC_WORK_THREAD (MC_MULTI_THREADED_WORKER|MC_MULTI_THREADED_SCHEDULER) int thread_mode; - struct multi_instance** instances; + struct multi_instance** instances; /**< Array of multi_instances. An instance can be + * accessed using peer-id as an index. */ struct hash *hash; /**< VPN tunnel instances indexed by real * address of the remote peer. */ @@ -220,6 +223,16 @@ void multi_close_instance (struct multi_context *m, struct multi_instance *mi, b bool multi_process_timeout (struct multi_context *m, const unsigned int mpp_flags); +/** + * Handles peer floating. + * + * If peer is floated to a taken address, either drops packet + * (if peer that owns address has different CN) or disconnects + * existing peer. Updates multi_instance with new address, + * updates hashtables in multi_context. + */ +void multi_process_float (struct multi_context* m, struct multi_instance* mi); + #define MPP_PRE_SELECT (1<<0) #define MPP_CONDITIONAL_PRE_SELECT (1<<1) #define MPP_CLOSE_ON_SIGNAL (1<<2) @@ -420,6 +433,12 @@ multi_route_defined (const struct multi_context *m, return true; } +/* + * Takes prefix away from multi_instance. + */ +void +ungenerate_prefix (struct multi_instance *mi); + /* * Set a msg() function prefix with our current client instance ID. */ @@ -428,10 +447,10 @@ static inline void set_prefix (struct multi_instance *mi) { #ifdef MULTI_DEBUG_EVENT_LOOP - if (mi->msg_prefix) + if (mi->msg_prefix[0]) printf ("[%s]\n", mi->msg_prefix); #endif - msg_set_prefix (mi->msg_prefix); + msg_set_prefix (mi->msg_prefix[0] ? mi->msg_prefix : NULL); } static inline void diff --git a/app/openvpn/src/openvpn/options.c b/app/openvpn/src/openvpn/options.c index 1ca4ad57..763e2cbc 100644 --- a/app/openvpn/src/openvpn/options.c +++ b/app/openvpn/src/openvpn/options.c @@ -570,6 +570,7 @@ static const char usage_message[] = "--tls-version-min ['or-highest'] : sets the minimum TLS version we\n" " will accept from the peer. If version is unrecognized and 'or-highest'\n" " is specified, require max TLS version supported by SSL implementation.\n" + "--tls-version-max : sets the maximum TLS version we will use.\n" #ifndef ENABLE_CRYPTO_POLARSSL "--pkcs12 file : PKCS#12 file containing local private key, local certificate\n" " and optionally the root CA certificate.\n" @@ -1976,9 +1977,6 @@ options_postprocess_verify_ce (const struct options *options, const struct conne if (ce->proto == PROTO_TCP_SERVER && (options->connection_list->len > 1)) msg (M_USAGE, "TCP server mode allows at most one --remote address"); - if (options->routes && ((options->routes->flags & RG_BLOCK_LOCAL) && (options->routes->flags & RG_UNBLOCK_LOCAL))) - msg (M_USAGE, "unblock-local and block-local options of redirect-gateway/redirect-private are mutatlly exclusive"); - #if P2MP_SERVER /* @@ -2038,7 +2036,6 @@ options_postprocess_verify_ce (const struct options *options, const struct conne #endif if (options->routes && (options->routes->flags & RG_ENABLE)) msg (M_USAGE, "--redirect-gateway cannot be used with --mode server (however --push \"redirect-gateway\" is fine)"); - if (options->route_delay_defined) msg (M_USAGE, "--route-delay cannot be used with --mode server"); if (options->up_delay) @@ -2106,7 +2103,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne if (options->ssl_flags & SSLF_OPT_VERIFY) msg (M_USAGE, "--opt-verify requires --mode server"); if (options->server_flags & SF_TCP_NODELAY_HELPER) - msg (M_USAGE, "--tcp-nodelay requires --mode server"); + msg (M_WARN, "WARNING: setting tcp-nodelay on the client side will not " + "affect the server. To have TCP_NODELAY in both direction use " + "tcp-nodelay in the server configuration instead."); if (options->auth_user_pass_verify_script) msg (M_USAGE, "--auth-user-pass-verify requires --mode server"); #if PORT_SHARE @@ -3898,8 +3897,7 @@ apply_push_options (struct options *options, struct buffer *buf, unsigned int permission_mask, unsigned int *option_types_found, - struct env_set *es, - struct tls_multi *tls_multi) + struct env_set *es) { char line[OPTION_PARM_SIZE]; int line_num = 0; @@ -5325,8 +5323,6 @@ add_option (struct options *options, options->routes->flags |= RG_BYPASS_DNS; else if (streq (p[j], "block-local")) options->routes->flags |= RG_BLOCK_LOCAL; - else if (streq (p[j], "unblock-local")) - options->routes->flags |= RG_UNBLOCK_LOCAL; else { msg (msglevel, "unknown --%s flag: %s", p[0], p[j]); @@ -6568,14 +6564,29 @@ add_option (struct options *options, { int ver; VERIFY_PERMISSION (OPT_P_GENERAL); - ver = tls_version_min_parse(p[1], p[2]); + ver = tls_version_parse(p[1], p[2]); if (ver == TLS_VER_BAD) { msg (msglevel, "unknown tls-version-min parameter: %s", p[1]); goto err; } - options->ssl_flags &= ~(SSLF_TLS_VERSION_MASK << SSLF_TLS_VERSION_SHIFT); - options->ssl_flags |= (ver << SSLF_TLS_VERSION_SHIFT); + options->ssl_flags &= + ~(SSLF_TLS_VERSION_MIN_MASK << SSLF_TLS_VERSION_MIN_SHIFT); + options->ssl_flags |= (ver << SSLF_TLS_VERSION_MIN_SHIFT); + } + else if (streq (p[0], "tls-version-max") && p[1]) + { + int ver; + VERIFY_PERMISSION (OPT_P_GENERAL); + ver = tls_version_parse(p[1], NULL); + if (ver == TLS_VER_BAD) + { + msg (msglevel, "unknown tls-version-max parameter: %s", p[1]); + goto err; + } + options->ssl_flags &= + ~(SSLF_TLS_VERSION_MAX_MASK << SSLF_TLS_VERSION_MAX_SHIFT); + options->ssl_flags |= (ver << SSLF_TLS_VERSION_MAX_SHIFT); } #ifndef ENABLE_CRYPTO_POLARSSL else if (streq (p[0], "pkcs12") && p[1]) diff --git a/app/openvpn/src/openvpn/options.h b/app/openvpn/src/openvpn/options.h index d5f7e95d..a51b8ab5 100644 --- a/app/openvpn/src/openvpn/options.h +++ b/app/openvpn/src/openvpn/options.h @@ -716,13 +716,11 @@ void options_postprocess (struct options *options); void pre_pull_save (struct options *o); void pre_pull_restore (struct options *o, struct gc_arena *gc); -struct tls_multi; bool apply_push_options (struct options *options, struct buffer *buf, unsigned int permission_mask, unsigned int *option_types_found, - struct env_set *es, - struct tls_multi* tls_multi); + struct env_set *es); void options_detach (struct options *o); diff --git a/app/openvpn/src/openvpn/push.c b/app/openvpn/src/openvpn/push.c index c7844499..385be1d5 100644 --- a/app/openvpn/src/openvpn/push.c +++ b/app/openvpn/src/openvpn/push.c @@ -475,8 +475,7 @@ process_incoming_push_msg (struct context *c, &buf, permission_mask, option_types_found, - c->c2.es, - c->c2.tls_multi)) + c->c2.es)) switch (c->options.push_continuation) { case 0: diff --git a/app/openvpn/src/openvpn/route.c b/app/openvpn/src/openvpn/route.c index c330169a..1cb98c03 100644 --- a/app/openvpn/src/openvpn/route.c +++ b/app/openvpn/src/openvpn/route.c @@ -277,7 +277,7 @@ init_route (struct route_ipv4 *r, /* get_special_addr replaces specialaddr with a special ip addr like gw. getaddrinfo is called to convert a a addrinfo struct */ - if(get_special_addr (rl, ro->network, &special.s_addr, &status)) + if(get_special_addr (rl, ro->network, (in_addr_t *) &special.s_addr, &status)) { special.s_addr = htonl(special.s_addr); ret = openvpn_getaddrinfo(0, inet_ntoa(special), NULL, 0, NULL, @@ -519,51 +519,6 @@ add_block_local_item (struct route_list *rl, } } -static void -add_unblock_local (struct route_list *rl) -{ - const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED); - - if (rl->flags & RG_UNBLOCK_LOCAL - && (rl->rgi.flags & rgi_needed) == rgi_needed) - { - /* unblock access to local subnet */ - struct route_ipv4 *r; - - ALLOC_OBJ_GC (r, struct route_ipv4, &rl->gc); - int i; - - CLEAR(*r); - r->flags = RT_DEFINED; - r->network = rl->rgi.gateway.addr & rl->rgi.gateway.netmask; - r->netmask = rl->rgi.gateway.netmask; - r->gateway = rl->rgi.gateway.addr; - r->next = rl->routes; - rl->routes = r; - - /* Additional local networks */ - for (i = 0; i < rl->rgi.n_addrs; ++i) - { - const struct route_gateway_address *gwa = &rl->rgi.addrs[i]; - - /* omit the add/subnet in &rl->rgi which we processed above */ - if (!((rl->rgi.gateway.addr & rl->rgi.gateway.netmask) == (gwa->addr & gwa->netmask) - && rl->rgi.gateway.netmask == gwa->netmask)) - { - ALLOC_OBJ_GC (r, struct route_ipv4, &rl->gc); - CLEAR(*r); - r->flags = RT_DEFINED; - r->network = gwa->addr & gwa->netmask; - r->netmask = gwa->netmask; - r->gateway = gwa->addr; - r->next = rl->routes; - rl->routes=r; - } - } - } -} - - static void add_block_local (struct route_list *rl) { @@ -595,8 +550,6 @@ add_block_local (struct route_list *rl) } } - - bool init_route_list (struct route_list *rl, const struct route_option_list *opt, @@ -665,8 +618,6 @@ init_route_list (struct route_list *rl, } } - - add_unblock_local (rl); if (rl->flags & RG_ENABLE) { add_block_local (rl); @@ -863,12 +814,10 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u { msg (M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err); } -#ifndef TARGET_ANDROID else if (!(rl->rgi.flags & RGI_ADDR_DEFINED)) { msg (M_WARN, "%s Cannot read current default gateway from system", err); } -#endif else if (!(rl->spec.flags & RTSA_REMOTE_HOST)) { msg (M_WARN, "%s Cannot obtain current remote host address", err); @@ -2538,6 +2487,7 @@ get_default_gateway (struct route_gateway_info *rgi) CLEAR(*rgi); +#ifndef TARGET_ANDROID /* get default gateway IP addr */ { FILE *fp = fopen ("/proc/net/route", "r"); @@ -2594,6 +2544,12 @@ get_default_gateway (struct route_gateway_info *rgi) } } } +#else + /* Android, set some pseudo GW, addr is in host byte order */ + rgi->gateway.addr = 127 << 24 | 'd' << 16 | 'g' << 8 | 'w'; + rgi->flags |= RGI_ADDR_DEFINED; + strcpy(best_name, "android-gw"); +#endif /* scan adapter list */ if (rgi->flags & RGI_ADDR_DEFINED) diff --git a/app/openvpn/src/openvpn/route.h b/app/openvpn/src/openvpn/route.h index 2b1ae3e8..f3c01501 100644 --- a/app/openvpn/src/openvpn/route.h +++ b/app/openvpn/src/openvpn/route.h @@ -88,7 +88,6 @@ struct route_option { #define RG_REROUTE_GW (1<<5) #define RG_AUTO_LOCAL (1<<6) #define RG_BLOCK_LOCAL (1<<7) -#define RG_UNBLOCK_LOCAL (1<<8) struct route_option_list { unsigned int flags; /* RG_x flags */ diff --git a/app/openvpn/src/openvpn/socket.c b/app/openvpn/src/openvpn/socket.c index c649d627..331a9d9f 100644 --- a/app/openvpn/src/openvpn/socket.c +++ b/app/openvpn/src/openvpn/socket.c @@ -729,7 +729,7 @@ static inline void socket_set_mark (int sd, int mark) { #if defined(TARGET_LINUX) && HAVE_DECL_SO_MARK - if (mark && setsockopt (sd, SOL_SOCKET, SO_MARK, &mark, sizeof (mark)) != 0) + if (mark && setsockopt (sd, SOL_SOCKET, SO_MARK, (void *) &mark, sizeof (mark)) != 0) msg (M_WARN, "NOTE: setsockopt SO_MARK=%d failed", mark); #endif } @@ -1081,6 +1081,14 @@ socket_listen_accept (socket_descriptor_t sd, return new_sd; } +/* older mingw versions and WinXP do not have this define, + * but Vista and up support the functionality - just define it here + */ +#ifdef WIN32 +# ifndef IPV6_V6ONLY +# define IPV6_V6ONLY 27 +# endif +#endif void socket_bind (socket_descriptor_t sd, struct addrinfo *local, @@ -1117,7 +1125,7 @@ socket_bind (socket_descriptor_t sd, int v6only = ipv6only ? 1: 0; /* setsockopt must have an "int" */ msg (M_INFO, "setsockopt(IPV6_V6ONLY=%d)", v6only); - if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only))) + if (setsockopt (sd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &v6only, sizeof(v6only))) { msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY=%d failed", v6only); } @@ -1211,7 +1219,7 @@ openvpn_connect (socket_descriptor_t sd, } } #else - status = connect (sd, &remote->addr.sa, af_addr_size(remote->addr.sa.sa_family)); + status = connect (sd, remote, af_addr_size(remote->sa_family)); if (status) status = openvpn_errno (); #endif @@ -2658,7 +2666,7 @@ proto_is_tcp(int proto) { if (proto < 0 || proto >= PROTO_N) ASSERT(0); - return proto == PROTO_TCP_CLIENT || proto == PROTO_TCP_SERVER || proto == PROTO_TCP_CLIENT; + return proto == PROTO_TCP_CLIENT || proto == PROTO_TCP_SERVER; } int @@ -2916,6 +2924,7 @@ link_socket_read_udp_posix (struct link_socket *sock, #endif buf->len = recvfrom (sock->sd, BPTR (buf), maxsize, 0, &from->dest.addr.sa, &fromlen); + /* FIXME: won't do anything when sock->info.af == AF_UNSPEC */ if (buf->len >= 0 && expectedlen && fromlen != expectedlen) bad_address_length (fromlen, expectedlen); return buf->len; @@ -3060,10 +3069,7 @@ socket_recv_queue (struct link_socket *sock, int maxsize) if (proto_is_udp(sock->info.proto)) { sock->reads.addr_defined = true; - if (sock->info.af == AF_INET) - sock->reads.addrlen = sizeof (sock->reads.addr); - else - sock->reads.addrlen = sizeof (sock->reads.addr6); + sock->reads.addrlen = sizeof (sock->reads.addr6); status = WSARecvFrom( sock->sd, wsabuf, @@ -3095,9 +3101,10 @@ socket_recv_queue (struct link_socket *sock, int maxsize) if (!status) /* operation completed immediately? */ { - int addrlen = af_addr_size(sock->info.lsa->local.addr.sa.sa_family); - if (sock->reads.addr_defined && sock->reads.addrlen != addrlen) - bad_address_length (sock->reads.addrlen, addrlen); + /* FIXME: won't do anything when sock->info.af == AF_UNSPEC */ + int af_len = af_addr_size (sock->info.af); + if (sock->reads.addr_defined && af_len && sock->reads.addrlen != af_len) + bad_address_length (sock->reads.addrlen, af_len); sock->reads.iostate = IOSTATE_IMMEDIATE_RETURN; /* since we got an immediate return, we must signal the event object ourselves */ @@ -3159,7 +3166,7 @@ socket_send_queue (struct link_socket *sock, struct buffer *buf, const struct li { /* set destination address for UDP writes */ sock->writes.addr_defined = true; - if (sock->info.af == AF_INET6) + if (to->dest.addr.sa.sa_family == AF_INET6) { sock->writes.addr6 = to->dest.addr.in6; sock->writes.addrlen = sizeof (sock->writes.addr6); diff --git a/app/openvpn/src/openvpn/ssl.c b/app/openvpn/src/openvpn/ssl.c index f79f42d9..cdc8eb19 100644 --- a/app/openvpn/src/openvpn/ssl.c +++ b/app/openvpn/src/openvpn/ssl.c @@ -454,7 +454,7 @@ ssl_put_auth_challenge (const char *cr_str) * return tls_version_max(). */ int -tls_version_min_parse(const char *vstr, const char *extra) +tls_version_parse(const char *vstr, const char *extra) { const int max_version = tls_version_max(); if (!strcmp(vstr, "1.0") && TLS_VER_1_0 <= max_version) @@ -2036,7 +2036,11 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi ASSERT (session->opt->key_method == 2); /* discard leading uint32 */ - ASSERT (buf_advance (buf, 4)); + if (!buf_advance (buf, 4)) { + msg (D_TLS_ERRORS, "TLS ERROR: Plaintext buffer too short (%d bytes).", + buf->len); + goto error; + } /* get key method */ key_method_flags = buf_read_u8 (buf); @@ -2773,7 +2777,8 @@ bool tls_pre_decrypt (struct tls_multi *multi, const struct link_socket_actual *from, struct buffer *buf, - struct crypto_options *opt) + struct crypto_options *opt, + bool floated) { struct gc_arena gc = gc_new (); bool ret = false; @@ -2817,7 +2822,7 @@ tls_pre_decrypt (struct tls_multi *multi, #ifdef ENABLE_DEF_AUTH && !ks->auth_deferred #endif - && link_socket_actual_match (from, &ks->remote_addr)) + && (floated || link_socket_actual_match (from, &ks->remote_addr))) { /* return appropriate data channel decrypt key in opt */ opt->key_ctx_bi = &ks->key; @@ -3492,27 +3497,30 @@ tls_rec_payload (struct tls_multi *multi, return ret; } -/* Update the remote_addr, needed if a client floats. */ void -tls_update_remote_addr (struct tls_multi *multi, -const struct link_socket_actual *from) +tls_update_remote_addr (struct tls_multi *multi, const struct link_socket_actual *addr) { struct gc_arena gc = gc_new (); - int i; + int i, j; - for (i = 0; i < KEY_SCAN_SIZE; ++i) + for (i = 0; i < TM_SIZE; ++i) { - struct key_state *ks = multi->key_scan[i]; - if (DECRYPT_KEY_ENABLED (multi, ks) && ks->authenticated && link_socket_actual_defined(&ks->remote_addr)) - { - if (link_socket_actual_match (from, &ks->remote_addr)) - continue; - dmsg (D_TLS_KEYSELECT, - "TLS: tls_update_remote_addr from IP=%s to IP=%s", + struct tls_session *session = &multi->session[i]; + + for (j = 0; j < KS_SIZE; ++j) + { + struct key_state *ks = &session->key[j]; + + if (!link_socket_actual_defined(&ks->remote_addr) || + link_socket_actual_match (addr, &ks->remote_addr)) + continue; + + dmsg (D_TLS_KEYSELECT, "TLS: tls_update_remote_addr from IP=%s to IP=%s", print_link_socket_actual (&ks->remote_addr, &gc), - print_link_socket_actual (from, &gc)); - memcpy(&ks->remote_addr, from, sizeof(*from)); - } + print_link_socket_actual (addr, &gc)); + + ks->remote_addr = *addr; + } } gc_free (&gc); } diff --git a/app/openvpn/src/openvpn/ssl.h b/app/openvpn/src/openvpn/ssl.h index a338745e..7e5a203e 100644 --- a/app/openvpn/src/openvpn/ssl.h +++ b/app/openvpn/src/openvpn/ssl.h @@ -306,7 +306,8 @@ int tls_multi_process (struct tls_multi *multi, bool tls_pre_decrypt (struct tls_multi *multi, const struct link_socket_actual *from, struct buffer *buf, - struct crypto_options *opt); + struct crypto_options *opt, + bool floated); /**************************************************************************/ @@ -431,11 +432,14 @@ bool tls_send_payload (struct tls_multi *multi, bool tls_rec_payload (struct tls_multi *multi, struct buffer *buf); -/* - * Update remote address of a tls_multi structure +/** + * Updates remote address in TLS sessions. + * + * @param multi - Tunnel to update + * @param addr - new address */ void tls_update_remote_addr (struct tls_multi *multi, - const struct link_socket_actual *from); + const struct link_socket_actual *addr); #ifdef MANAGEMENT_DEF_AUTH static inline char * diff --git a/app/openvpn/src/openvpn/ssl_backend.h b/app/openvpn/src/openvpn/ssl_backend.h index bfd15496..b0777bf5 100644 --- a/app/openvpn/src/openvpn/ssl_backend.h +++ b/app/openvpn/src/openvpn/ssl_backend.h @@ -109,11 +109,12 @@ void tls_clear_error(); * @return One of the TLS_VER_x constants or TLS_VER_BAD * if a parse error should be flagged. */ -#define TLS_VER_BAD -1 -#define TLS_VER_1_0 0 /* default */ -#define TLS_VER_1_1 1 -#define TLS_VER_1_2 2 -int tls_version_min_parse(const char *vstr, const char *extra); +#define TLS_VER_BAD -1 +#define TLS_VER_UNSPEC 0 /* default */ +#define TLS_VER_1_0 1 +#define TLS_VER_1_1 2 +#define TLS_VER_1_2 3 +int tls_version_parse(const char *vstr, const char *extra); /** * Return the maximum TLS version (as a TLS_VER_x constant) diff --git a/app/openvpn/src/openvpn/ssl_common.h b/app/openvpn/src/openvpn/ssl_common.h index cb0ba628..6222bd67 100644 --- a/app/openvpn/src/openvpn/ssl_common.h +++ b/app/openvpn/src/openvpn/ssl_common.h @@ -296,8 +296,10 @@ struct tls_options # define SSLF_AUTH_USER_PASS_OPTIONAL (1<<2) # define SSLF_OPT_VERIFY (1<<4) # define SSLF_CRL_VERIFY_DIR (1<<5) -# define SSLF_TLS_VERSION_SHIFT 6 -# define SSLF_TLS_VERSION_MASK 0xF /* (uses bit positions 6 to 9) */ +# define SSLF_TLS_VERSION_MIN_SHIFT 6 +# define SSLF_TLS_VERSION_MIN_MASK 0xF /* (uses bit positions 6 to 9) */ +# define SSLF_TLS_VERSION_MAX_SHIFT 10 +# define SSLF_TLS_VERSION_MAX_MASK 0xF /* (uses bit positions 10 to 13) */ unsigned int ssl_flags; #ifdef MANAGEMENT_DEF_AUTH diff --git a/app/openvpn/src/openvpn/ssl_openssl.c b/app/openvpn/src/openvpn/ssl_openssl.c index adf3ae6f..6782a953 100644 --- a/app/openvpn/src/openvpn/ssl_openssl.c +++ b/app/openvpn/src/openvpn/ssl_openssl.c @@ -184,15 +184,23 @@ tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags) /* process SSL options including minimum TLS version we will accept from peer */ { long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; - const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK; - if (tls_version_min > TLS_VER_1_0) + int tls_ver_max = TLS_VER_UNSPEC; + const int tls_ver_min = + (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK; + + tls_ver_max = + (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK; + if (tls_ver_max <= TLS_VER_UNSPEC) + tls_ver_max = tls_version_max(); + + if (tls_ver_min > TLS_VER_1_0 || tls_ver_max < TLS_VER_1_0) sslopt |= SSL_OP_NO_TLSv1; #ifdef SSL_OP_NO_TLSv1_1 - if (tls_version_min > TLS_VER_1_1) + if (tls_ver_min > TLS_VER_1_1 || tls_ver_max < TLS_VER_1_1) sslopt |= SSL_OP_NO_TLSv1_1; #endif #ifdef SSL_OP_NO_TLSv1_2 - if (tls_version_min > TLS_VER_1_2) + if (tls_ver_min > TLS_VER_1_2 || tls_ver_max < TLS_VER_1_2) sslopt |= SSL_OP_NO_TLSv1_2; #endif SSL_CTX_set_options (ctx->ctx, sslopt); diff --git a/app/openvpn/src/openvpn/ssl_polarssl.c b/app/openvpn/src/openvpn/ssl_polarssl.c index 387e6369..20368857 100644 --- a/app/openvpn/src/openvpn/ssl_polarssl.c +++ b/app/openvpn/src/openvpn/ssl_polarssl.c @@ -685,6 +685,40 @@ tls_version_max(void) #endif } +/** + * Convert an OpenVPN tls-version variable to PolarSSl format (i.e. a major and + * minor ssl version number). + * + * @param tls_ver The tls-version variable to convert. + * @param major Returns the TLS major version in polarssl format. + * Must be a valid pointer. + * @param minor Returns the TLS minor version in polarssl format. + * Must be a valid pointer. + */ +static void tls_version_to_major_minor(int tls_ver, int *major, int *minor) { + ASSERT(major); + ASSERT(minor); + + switch (tls_ver) + { + case TLS_VER_1_0: + *major = SSL_MAJOR_VERSION_3; + *minor = SSL_MINOR_VERSION_1; + break; + case TLS_VER_1_1: + *major = SSL_MAJOR_VERSION_3; + *minor = SSL_MINOR_VERSION_2; + break; + case TLS_VER_1_2: + *major = SSL_MAJOR_VERSION_3; + *minor = SSL_MINOR_VERSION_3; + break; + default: + msg(M_FATAL, "%s: invalid TLS version %d", __func__, tls_ver); + break; + } +} + void key_state_ssl_init(struct key_state_ssl *ks_ssl, const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session) { @@ -743,30 +777,32 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl, /* Initialize minimum TLS version */ { - const int tls_version_min = (session->opt->ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK; - int polar_major; - int polar_minor; - switch (tls_version_min) + const int tls_version_min = + (session->opt->ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & + SSLF_TLS_VERSION_MIN_MASK; + + /* default to TLS 1.0 */ + int major = SSL_MAJOR_VERSION_3; + int minor = SSL_MINOR_VERSION_1; + + if (tls_version_min > TLS_VER_UNSPEC) + tls_version_to_major_minor(tls_version_min, &major, &minor); + + ssl_set_min_version(ks_ssl->ctx, major, minor); + } + + /* Initialize maximum TLS version */ + { + const int tls_version_max = + (session->opt->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & + SSLF_TLS_VERSION_MAX_MASK; + + if (tls_version_max > TLS_VER_UNSPEC) { - case TLS_VER_1_0: - default: - polar_major = SSL_MAJOR_VERSION_3; - polar_minor = SSL_MINOR_VERSION_1; - break; -#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_2) - case TLS_VER_1_1: - polar_major = SSL_MAJOR_VERSION_3; - polar_minor = SSL_MINOR_VERSION_2; - break; -#endif -#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_3) - case TLS_VER_1_2: - polar_major = SSL_MAJOR_VERSION_3; - polar_minor = SSL_MINOR_VERSION_3; - break; -#endif + int major, minor; + tls_version_to_major_minor(tls_version_max, &major, &minor); + ssl_set_max_version(ks_ssl->ctx, major, minor); } - ssl_set_min_version(ks_ssl->ctx, polar_major, polar_minor); } /* Initialise BIOs */ @@ -810,8 +846,8 @@ key_state_write_plaintext (struct key_state_ssl *ks, struct buffer *buf) if (0 == buf->len) { - return 0; perf_pop (); + return 0; } retval = ssl_write(ks->ctx, BPTR(buf), buf->len); diff --git a/app/openvpn/src/plugins/down-root/down-root.c b/app/openvpn/src/plugins/down-root/down-root.c index d51d0e55..6931becf 100644 --- a/app/openvpn/src/plugins/down-root/down-root.c +++ b/app/openvpn/src/plugins/down-root/down-root.c @@ -5,7 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. + * Copyright (C) 2002-2013 OpenVPN Technologies, Inc. + * Copyright (C) 2013 David Sommerseth * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -40,14 +41,16 @@ #include #include #include +#include +#include #include #define DEBUG(verb) ((verb) >= 7) /* Command codes for foreground -> background communication */ -#define COMMAND_RUN_SCRIPT 0 -#define COMMAND_EXIT 1 +#define COMMAND_RUN_SCRIPT 1 +#define COMMAND_EXIT 2 /* Response codes for background -> foreground communication */ #define RESPONSE_INIT_SUCCEEDED 10 @@ -56,24 +59,24 @@ #define RESPONSE_SCRIPT_FAILED 13 /* Background process function */ -static void down_root_server (const int fd, char *command, const char *argv[], const char *envp[], const int verb); +static void down_root_server (const int fd, char * const * argv, char * const *envp, const int verb); /* * Plugin state, used by foreground */ struct down_root_context { - /* Foreground's socket to background process */ - int foreground_fd; + /* Foreground's socket to background process */ + int foreground_fd; - /* Process ID of background process */ - pid_t background_pid; + /* Process ID of background process */ + pid_t background_pid; - /* Verbosity level of OpenVPN */ - int verb; + /* Verbosity level of OpenVPN */ + int verb; - /* down command */ - char *command; + /* down command */ + char **command; }; /* @@ -84,21 +87,21 @@ struct down_root_context static const char * get_env (const char *name, const char *envp[]) { - if (envp) + if (envp) { - int i; - const int namelen = strlen (name); - for (i = 0; envp[i]; ++i) - { - if (!strncmp (envp[i], name, namelen)) - { - const char *cp = envp[i] + namelen; - if (*cp == '=') - return cp + 1; - } - } + int i; + const int namelen = strlen (name); + for (i = 0; envp[i]; ++i) + { + if (!strncmp (envp[i], name, namelen)) + { + const char *cp = envp[i] + namelen; + if (*cp == '=') + return cp + 1; + } + } } - return NULL; + return NULL; } /* @@ -107,13 +110,13 @@ get_env (const char *name, const char *envp[]) static int string_array_len (const char *array[]) { - int i = 0; - if (array) + int i = 0; + if (array) { - while (array[i]) - ++i; + while (array[i]) + ++i; } - return i; + return i; } /* @@ -123,23 +126,23 @@ string_array_len (const char *array[]) static int recv_control (int fd) { - unsigned char c; - const ssize_t size = read (fd, &c, sizeof (c)); - if (size == sizeof (c)) - return c; - else - return -1; + unsigned char c; + const ssize_t size = read (fd, &c, sizeof (c)); + if (size == sizeof (c)) + return c; + else + return -1; } static int send_control (int fd, int code) { - unsigned char c = (unsigned char) code; - const ssize_t size = write (fd, &c, sizeof (c)); - if (size == sizeof (c)) - return (int) size; - else - return -1; + unsigned char c = (unsigned char) code; + const ssize_t size = write (fd, &c, sizeof (c)); + if (size == sizeof (c)) + return (int) size; + else + return -1; } /* @@ -150,22 +153,22 @@ send_control (int fd, int code) static void daemonize (const char *envp[]) { - const char *daemon_string = get_env ("daemon", envp); - if (daemon_string && daemon_string[0] == '1') + const char *daemon_string = get_env ("daemon", envp); + if (daemon_string && daemon_string[0] == '1') { - const char *log_redirect = get_env ("daemon_log_redirect", envp); - int fd = -1; - if (log_redirect && log_redirect[0] == '1') - fd = dup (2); - if (daemon (0, 0) < 0) - { - fprintf (stderr, "DOWN-ROOT: daemonization failed\n"); - } - else if (fd >= 3) - { - dup2 (fd, 2); - close (fd); - } + const char *log_redirect = get_env ("daemon_log_redirect", envp); + int fd = -1; + if (log_redirect && log_redirect[0] == '1') + fd = dup (2); + if (daemon (0, 0) < 0) + { + warn ("DOWN-ROOT: daemonization failed"); + } + else if (fd >= 3) + { + dup2 (fd, 2); + close (fd); + } } } @@ -182,12 +185,12 @@ daemonize (const char *envp[]) static void close_fds_except (int keep) { - int i; - closelog (); - for (i = 3; i <= 100; ++i) + int i; + closelog (); + for (i = 3; i <= 100; ++i) { - if (i != keep) - close (i); + if (i != keep) + close (i); } } @@ -198,254 +201,261 @@ close_fds_except (int keep) static void set_signals (void) { - signal (SIGTERM, SIG_DFL); + signal (SIGTERM, SIG_DFL); - signal (SIGINT, SIG_IGN); - signal (SIGHUP, SIG_IGN); - signal (SIGUSR1, SIG_IGN); - signal (SIGUSR2, SIG_IGN); - signal (SIGPIPE, SIG_IGN); + signal (SIGINT, SIG_IGN); + signal (SIGHUP, SIG_IGN); + signal (SIGUSR1, SIG_IGN); + signal (SIGUSR2, SIG_IGN); + signal (SIGPIPE, SIG_IGN); } -/* - * convert system() return into a success/failure value - */ -int -system_ok (int stat) + +static void +free_context (struct down_root_context *context) { -#ifdef WIN32 - return stat == 0; -#else - return stat != -1 && WIFEXITED (stat) && WEXITSTATUS (stat) == 0; -#endif + if (context) + { + if (context->command) + { + free (context->command); + } + free (context); + } } -static char * -build_command_line (const char *argv[]) +/* Run the script using execve(). As execve() replaces the + * current process with the new one, do a fork first before + * calling execve() + */ +static int +run_script(char * const *argv, char * const *envp) { - int size = 0; - int n = 0; - int i; - char *string; + pid_t pid; + int ret = 0; - /* precompute size */ - if (argv) + pid = fork(); + if (pid == (pid_t)0) /* child side */ { - for (i = 0; argv[i]; ++i) - { - size += (strlen (argv[i]) + 1); /* string length plus trailing space */ - ++n; - } + execve(argv[0], argv, envp); + /* If execve() fails to run, exit child with exit code 127 */ + err(127, "DOWN-ROOT: Failed execute: %s", argv[0]); } - ++size; /* for null terminator */ - - /* allocate memory */ - string = (char *) malloc (size); - if (!string) + else if (pid < (pid_t)0 ) { - fprintf (stderr, "DOWN-ROOT: out of memory\n"); - exit (1); + warn ("DOWN-ROOT: Failed to fork child to run %s", argv[0]); + return -1; } - string[0] = '\0'; - - /* build string */ - for (i = 0; i < n; ++i) + else /* parent side */ { - strcat (string, argv[i]); - if (i + 1 < n) - strcat (string, " "); + if( waitpid (pid, &ret, 0) != pid ) + { + /* waitpid does not return error information via errno */ + fprintf(stderr, "DOWN-ROOT: waitpid() failed, don't know exit code of child (%s)\n", argv[0]); + return -1; + } } - return string; + return ret; } -static void -free_context (struct down_root_context *context) +OPENVPN_EXPORT openvpn_plugin_handle_t +openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[]) { - if (context) + struct down_root_context *context; + int i = 0; + + /* + * Allocate our context + */ + context = (struct down_root_context *) calloc (1, sizeof (struct down_root_context)); + if (!context) { - if (context->command) - free (context->command); - free (context); + warn ("DOWN-ROOT: Could not allocate memory for plug-in context"); + goto error; + } + context->foreground_fd = -1; + + /* + * Intercept the --up and --down callbacks + */ + *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) | OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN); + + /* + * Make sure we have two string arguments: the first is the .so name, + * the second is the script command. + */ + if (string_array_len (argv) < 2) + { + fprintf (stderr, "DOWN-ROOT: need down script command\n"); + goto error; } -} -OPENVPN_EXPORT openvpn_plugin_handle_t -openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[]) -{ - struct down_root_context *context; - - /* - * Allocate our context - */ - context = (struct down_root_context *) calloc (1, sizeof (struct down_root_context)); - if (!context) - goto error; - context->foreground_fd = -1; - - /* - * Intercept the --up and --down callbacks - */ - *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) | OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN); - - /* - * Make sure we have two string arguments: the first is the .so name, - * the second is the script command. - */ - if (string_array_len (argv) < 2) + /* + * Save the arguments in our context + */ + context->command = calloc(string_array_len(argv), sizeof(char *)); + if (!context->command) + { + warn ("DOWN-ROOT: Could not allocate memory for command array"); + goto error; + } + + /* Ignore argv[0], as it contains just the plug-in file name */ + for (i = 1; i < string_array_len(argv); i++) + { + context->command[i-1] = (char *) argv[i]; + } + + /* + * Get verbosity level from environment + */ { - fprintf (stderr, "DOWN-ROOT: need down script command\n"); - goto error; + const char *verb_string = get_env ("verb", envp); + if (verb_string) + context->verb = atoi (verb_string); } - /* - * Save our argument in context - */ - context->command = build_command_line (&argv[1]); - - /* - * Get verbosity level from environment - */ - { - const char *verb_string = get_env ("verb", envp); - if (verb_string) - context->verb = atoi (verb_string); - } - - return (openvpn_plugin_handle_t) context; - - error: - free_context (context); - return NULL; + return (openvpn_plugin_handle_t) context; + +error: + free_context (context); + return NULL; } OPENVPN_EXPORT int openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[]) { - struct down_root_context *context = (struct down_root_context *) handle; + struct down_root_context *context = (struct down_root_context *) handle; - if (type == OPENVPN_PLUGIN_UP && context->foreground_fd == -1) /* fork off a process to hold onto root */ + if (type == OPENVPN_PLUGIN_UP && context->foreground_fd == -1) /* fork off a process to hold onto root */ { - pid_t pid; - int fd[2]; - - /* - * Make a socket for foreground and background processes - * to communicate. - */ - if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1) - { - fprintf (stderr, "DOWN-ROOT: socketpair call failed\n"); - return OPENVPN_PLUGIN_FUNC_ERROR; - } - - /* - * Fork off the privileged process. It will remain privileged - * even after the foreground process drops its privileges. - */ - pid = fork (); - - if (pid) - { - int status; - - /* - * Foreground Process - */ - - context->background_pid = pid; - - /* close our copy of child's socket */ - close (fd[1]); - - /* don't let future subprocesses inherit child socket */ - if (fcntl (fd[0], F_SETFD, FD_CLOEXEC) < 0) - fprintf (stderr, "DOWN-ROOT: Set FD_CLOEXEC flag on socket file descriptor failed\n"); - - /* wait for background child process to initialize */ - status = recv_control (fd[0]); - if (status == RESPONSE_INIT_SUCCEEDED) - { - context->foreground_fd = fd[0]; - return OPENVPN_PLUGIN_FUNC_SUCCESS; - } - } - else - { - /* - * Background Process - */ - - /* close all parent fds except our socket back to parent */ - close_fds_except (fd[1]); - - /* Ignore most signals (the parent will receive them) */ - set_signals (); - - /* Daemonize if --daemon option is set. */ - daemonize (envp); - - /* execute the event loop */ - down_root_server (fd[1], context->command, argv, envp, context->verb); - - close (fd[1]); - exit (0); - return 0; /* NOTREACHED */ - } + pid_t pid; + int fd[2]; + + /* + * Make a socket for foreground and background processes + * to communicate. + */ + if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1) + { + warn ("DOWN-ROOT: socketpair call failed"); + return OPENVPN_PLUGIN_FUNC_ERROR; + } + + /* + * Fork off the privileged process. It will remain privileged + * even after the foreground process drops its privileges. + */ + pid = fork (); + + if (pid) + { + int status; + + /* + * Foreground Process + */ + + context->background_pid = pid; + + /* close our copy of child's socket */ + close (fd[1]); + + /* don't let future subprocesses inherit child socket */ + if (fcntl (fd[0], F_SETFD, FD_CLOEXEC) < 0) + { + warn ("DOWN-ROOT: Set FD_CLOEXEC flag on socket file descriptor failed"); + } + + /* wait for background child process to initialize */ + status = recv_control (fd[0]); + if (status == RESPONSE_INIT_SUCCEEDED) + { + context->foreground_fd = fd[0]; + return OPENVPN_PLUGIN_FUNC_SUCCESS; + } + } + else + { + /* + * Background Process + */ + + /* close all parent fds except our socket back to parent */ + close_fds_except (fd[1]); + + /* Ignore most signals (the parent will receive them) */ + set_signals (); + + /* Daemonize if --daemon option is set. */ + daemonize (envp); + + /* execute the event loop */ + down_root_server (fd[1], context->command, (char * const *) envp, context->verb); + + close (fd[1]); + exit (0); + return 0; /* NOTREACHED */ + } } - else if (type == OPENVPN_PLUGIN_DOWN && context->foreground_fd >= 0) + else if (type == OPENVPN_PLUGIN_DOWN && context->foreground_fd >= 0) { - if (send_control (context->foreground_fd, COMMAND_RUN_SCRIPT) == -1) - { - fprintf (stderr, "DOWN-ROOT: Error sending script execution signal to background process\n"); - } - else - { - const int status = recv_control (context->foreground_fd); - if (status == RESPONSE_SCRIPT_SUCCEEDED) - return OPENVPN_PLUGIN_FUNC_SUCCESS; - if (status == -1) - fprintf (stderr, "DOWN-ROOT: Error receiving script execution confirmation from background process\n"); - } + if (send_control (context->foreground_fd, COMMAND_RUN_SCRIPT) == -1) + { + warn ("DOWN-ROOT: Error sending script execution signal to background process"); + } + else + { + const int status = recv_control (context->foreground_fd); + if (status == RESPONSE_SCRIPT_SUCCEEDED) + return OPENVPN_PLUGIN_FUNC_SUCCESS; + if (status == -1) + { + warn ("DOWN-ROOT: Error receiving script execution confirmation from background process"); + } + } } - return OPENVPN_PLUGIN_FUNC_ERROR; + return OPENVPN_PLUGIN_FUNC_ERROR; } OPENVPN_EXPORT void openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle) { - struct down_root_context *context = (struct down_root_context *) handle; + struct down_root_context *context = (struct down_root_context *) handle; - if (DEBUG (context->verb)) - fprintf (stderr, "DOWN-ROOT: close\n"); + if (DEBUG (context->verb)) + fprintf (stderr, "DOWN-ROOT: close\n"); - if (context->foreground_fd >= 0) + if (context->foreground_fd >= 0) { - /* tell background process to exit */ - if (send_control (context->foreground_fd, COMMAND_EXIT) == -1) - fprintf (stderr, "DOWN-ROOT: Error signaling background process to exit\n"); - - /* wait for background process to exit */ - if (context->background_pid > 0) - waitpid (context->background_pid, NULL, 0); - - close (context->foreground_fd); - context->foreground_fd = -1; + /* tell background process to exit */ + if (send_control (context->foreground_fd, COMMAND_EXIT) == -1) + { + warn ("DOWN-ROOT: Error signalling background process to exit"); + } + + /* wait for background process to exit */ + if (context->background_pid > 0) + waitpid (context->background_pid, NULL, 0); + + close (context->foreground_fd); + context->foreground_fd = -1; } - free_context (context); + free_context (context); } OPENVPN_EXPORT void openvpn_plugin_abort_v1 (openvpn_plugin_handle_t handle) { - struct down_root_context *context = (struct down_root_context *) handle; + struct down_root_context *context = (struct down_root_context *) handle; - if (context && context->foreground_fd >= 0) + if (context && context->foreground_fd >= 0) { - /* tell background process to exit */ - send_control (context->foreground_fd, COMMAND_EXIT); - close (context->foreground_fd); - context->foreground_fd = -1; + /* tell background process to exit */ + send_control (context->foreground_fd, COMMAND_EXIT); + close (context->foreground_fd); + context->foreground_fd = -1; } } @@ -453,105 +463,85 @@ openvpn_plugin_abort_v1 (openvpn_plugin_handle_t handle) * Background process -- runs with privilege. */ static void -down_root_server (const int fd, char *command, const char *argv[], const char *envp[], const int verb) +down_root_server (const int fd, char * const *argv, char * const *envp, const int verb) { - const char *p[3]; - char *command_line = NULL; - char *argv_cat = NULL; - int i; - - /* - * Do initialization - */ - if (DEBUG (verb)) - fprintf (stderr, "DOWN-ROOT: BACKGROUND: INIT command='%s'\n", command); - - /* - * Tell foreground that we initialized successfully - */ - if (send_control (fd, RESPONSE_INIT_SUCCEEDED) == -1) + /* + * Do initialization + */ + if (DEBUG (verb)) + fprintf (stderr, "DOWN-ROOT: BACKGROUND: INIT command='%s'\n", argv[0]); + + /* + * Tell foreground that we initialized successfully + */ + if (send_control (fd, RESPONSE_INIT_SUCCEEDED) == -1) { - fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [1]\n"); - goto done; + warn ("DOWN-ROOT: BACKGROUND: write error on response socket [1]"); + goto done; } - /* - * Build command line - */ - if (string_array_len (argv) >= 2) - argv_cat = build_command_line (&argv[1]); - else - argv_cat = build_command_line (NULL); - p[0] = command; - p[1] = argv_cat; - p[2] = NULL; - command_line = build_command_line (p); - - /* - * Save envp in environment - */ - for (i = 0; envp[i]; ++i) + /* + * Event loop + */ + while (1) { - putenv ((char *)envp[i]); + int command_code; + int exit_code = -1; + + /* get a command from foreground process */ + command_code = recv_control (fd); + + if (DEBUG (verb)) + fprintf (stderr, "DOWN-ROOT: BACKGROUND: received command code: %d\n", command_code); + + switch (command_code) + { + case COMMAND_RUN_SCRIPT: + if ( (exit_code = run_script(argv, envp)) == 0 ) /* Succeeded */ + { + if (send_control (fd, RESPONSE_SCRIPT_SUCCEEDED) == -1) + { + warn ("DOWN-ROOT: BACKGROUND: write error on response socket [2]"); + goto done; + } + } + else /* Failed */ + { + fprintf(stderr, "DOWN-ROOT: BACKGROUND: %s exited with exit code %i\n", argv[0], exit_code); + if (send_control (fd, RESPONSE_SCRIPT_FAILED) == -1) + { + warn ("DOWN-ROOT: BACKGROUND: write error on response socket [3]"); + goto done; + } + } + break; + + case COMMAND_EXIT: + goto done; + + case -1: + warn ("DOWN-ROOT: BACKGROUND: read error on command channel"); + goto done; + + default: + fprintf (stderr, "DOWN-ROOT: BACKGROUND: unknown command code: code=%d, exiting\n", + command_code); + goto done; + } } - /* - * Event loop - */ - while (1) - { - int command_code; - int status; - - /* get a command from foreground process */ - command_code = recv_control (fd); - - if (DEBUG (verb)) - fprintf (stderr, "DOWN-ROOT: BACKGROUND: received command code: %d\n", command_code); - - switch (command_code) - { - case COMMAND_RUN_SCRIPT: - status = system (command_line); - if (system_ok (status)) /* Succeeded */ - { - if (send_control (fd, RESPONSE_SCRIPT_SUCCEEDED) == -1) - { - fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [2]\n"); - goto done; - } - } - else /* Failed */ - { - if (send_control (fd, RESPONSE_SCRIPT_FAILED) == -1) - { - fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [3]\n"); - goto done; - } - } - break; - - case COMMAND_EXIT: - goto done; - - case -1: - fprintf (stderr, "DOWN-ROOT: BACKGROUND: read error on command channel\n"); - goto done; - - default: - fprintf (stderr, "DOWN-ROOT: BACKGROUND: unknown command code: code=%d, exiting\n", - command_code); - goto done; - } - } +done: + if (DEBUG (verb)) + fprintf (stderr, "DOWN-ROOT: BACKGROUND: EXIT\n"); - done: - if (argv_cat) - free (argv_cat); - if (command_line) - free (command_line); - if (DEBUG (verb)) - fprintf (stderr, "DOWN-ROOT: BACKGROUND: EXIT\n"); - - return; + return; } + + +/* +Local variables: +c-file-style: "bsd" +c-basic-offset: 4 +indent-tabs-mode: nil +End: +*/ diff --git a/app/openvpn/tests/t_lpback.sh b/app/openvpn/tests/t_lpback.sh index 8f88ad92..d7792cd3 100755 --- a/app/openvpn/tests/t_lpback.sh +++ b/app/openvpn/tests/t_lpback.sh @@ -35,6 +35,9 @@ CIPHERS=$(${top_builddir}/src/openvpn/openvpn --show-ciphers | \ # GD, 2014-07-06 do not test RC5-* either (fails on NetBSD w/o libcrypto_rc5) CIPHERS=$(echo "$CIPHERS" | egrep -v '^(DES-EDE3-CFB1|DES-CFB1|RC5-)' ) +# Also test cipher 'none' +CIPHERS=${CIPHERS}$(printf "\nnone") + "${top_builddir}/src/openvpn/openvpn" --genkey --secret key.$$ set +e diff --git a/app/remoteExample/src/main/res/values/strings-icsopenvpn.xml b/app/remoteExample/src/main/res/values/strings-icsopenvpn.xml deleted file mode 100644 index bbaee226..00000000 --- a/app/remoteExample/src/main/res/values/strings-icsopenvpn.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - OpenVPN Remote - Hello world! - Settings - Allows another app to control OpenVPN - No Status yet - Not now - Show my IP - Disconnect - Start embedded profile - - - diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4893ce4c..cd04f68a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -35,7 +35,7 @@ android:icon="@drawable/icon" android:logo="@drawable/icon" android:label="@string/app" - android:theme="@style/appstyle"> + android:theme="@style/blinkt"> mAllowedAppsVpn = new HashSet(); + public boolean mAllowedAppsVpnAreDisallowed = true; + + + /* Options no long used in new profiles */ + public String mServerName = "openvpn.blinkt.de"; + public String mServerPort = "1194"; + public boolean mUseUdp = true; @@ -159,6 +169,9 @@ public class VpnProfile implements Serializable { mUuid = UUID.randomUUID(); mName = name; mProfileVersion = CURRENT_PROFILE_VERSION; + + mConnections = new Connection[1]; + mConnections[0] = new Connection(); } public static String openVpnEscape(String unescaped) { @@ -206,7 +219,30 @@ public class VpnProfile implements Serializable { mAllowLocalLAN = Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT; } + if (mProfileVersion < 4) { + moveOptionsToConnection(); + mAllowedAppsVpnAreDisallowed=true; + } + if (mAllowedAppsVpn==null) + mAllowedAppsVpn = new HashSet(); + if (mConnections ==null) + mConnections = new Connection[0]; + mProfileVersion= CURRENT_PROFILE_VERSION; + + } + + private void moveOptionsToConnection() { + mConnections = new Connection[1]; + Connection conn = new Connection(); + + conn.mServerName = mServerName; + conn.mServerPort = mServerPort; + conn.mUseUdp = mUseUdp; + conn.mCustomConfiguration = ""; + + mConnections[0] = conn; + } public String getConfigFile(Context context, boolean configForOvpn3) { @@ -267,15 +303,27 @@ public class VpnProfile implements Serializable { // We cannot use anything else than tun cfg += "dev tun\n"; - // Server Address - cfg += "remote "; - cfg += mServerName; - cfg += " "; - cfg += mServerPort; - if (mUseUdp) - cfg += " udp\n"; - else - cfg += " tcp-client\n"; + + boolean canUsePlainRemotes = true; + + if (mConnections.length==1) { + cfg += mConnections[0].getConnectionBlock(); + } else { + for (Connection conn : mConnections) { + canUsePlainRemotes = canUsePlainRemotes && conn.isOnlyRemote(); + } + + if (mRemoteRandom) + cfg+="remote-random\n"; + + if (canUsePlainRemotes) { + for (Connection conn : mConnections) { + if (conn.mEnabled) { + cfg += conn.getConnectionBlock(); + } + } + } + } switch (mAuthenticationType) { @@ -365,11 +413,6 @@ public class VpnProfile implements Serializable { } } - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT && !mAllowLocalLAN) - cfg+="redirect-private block-local\n"; - else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && mAllowLocalLAN) - cfg+="redirect-private unblock-local\n"; - if (mUseDefaultRoutev6) cfg += "route-ipv6 ::/0\n"; @@ -405,7 +448,7 @@ public class VpnProfile implements Serializable { if (mAuthenticationType != TYPE_STATICKEYS) { if (mCheckRemoteCN) { if (mRemoteCN == null || mRemoteCN.equals("")) - cfg += "verify-x509-name " + mServerName + " name\n"; + cfg += "verify-x509-name " + mConnections[0].mServerName + " name\n"; else switch (mX509AuthType) { @@ -470,6 +513,19 @@ public class VpnProfile implements Serializable { } + if (!canUsePlainRemotes) { + cfg += "# Connection Options are at the end to allow global options (and global custom options) to influence connection blocks\n"; + for (Connection conn : mConnections) { + if (conn.mEnabled) { + cfg += "\n"; + cfg += conn.getConnectionBlock(); + cfg += "\n"; + } + } + } + + + return cfg; } @@ -639,6 +695,27 @@ public class VpnProfile implements Serializable { } } + @Override + protected VpnProfile clone() throws CloneNotSupportedException { + VpnProfile copy = (VpnProfile) super.clone(); + copy.mUuid = UUID.randomUUID(); + copy.mConnections = mConnections.clone(); + copy.mAllowedAppsVpn = (HashSet) mAllowedAppsVpn.clone(); + return copy; + } + + public VpnProfile copy(String name) { + try { + VpnProfile copy = (VpnProfile) clone(); + copy.mName = name; + return copy; + + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + return null; + } + } + class NoCertReturnedException extends Exception { public NoCertReturnedException (String msg) { @@ -769,6 +846,14 @@ public class VpnProfile implements Serializable { if (!mUseDefaultRoute && (getCustomRoutes(mCustomRoutes) == null || getCustomRoutes(mExcludedRoutes) ==null)) return R.string.custom_route_format_error; + boolean noRemoteEnabled = true; + for (Connection c : mConnections) + if (c.mEnabled) + noRemoteEnabled = false; + + if(noRemoteEnabled) + return R.string.remote_no_server_selected; + // Everything okay return R.string.no_error_found; 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 4940d5d6..dfd815e4 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.activities; 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 5e4f9517..45f09c8e 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.activities; 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 ac9a8ccb..e525abd5 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java +++ b/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core; 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 0d8230b7..5dc96bbc 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java @@ -1,13 +1,17 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core; +import android.text.TextUtils; +import android.util.Pair; + import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; +import java.io.StringReader; import java.util.Collections; import java.util.HashMap; import java.util.Locale; @@ -28,48 +32,49 @@ public class ConfigParser { private HashMap>> options = new HashMap>>(); private HashMap> meta = new HashMap>(); - - private boolean extraRemotesAsCustom=false; - public void parseConfig(Reader reader) throws IOException, ConfigParseError { - BufferedReader br =new BufferedReader(reader); + BufferedReader br = new BufferedReader(reader); - int lineno=0; - while (true){ - String line = br.readLine(); - lineno++; - if(line==null) - break; + int lineno = 0; + try { + while (true) { + String line = br.readLine(); + lineno++; + if (line == null) + break; - if (lineno==1 && (line.startsWith("PK\003\004") - || (line.startsWith("PK\007\008")))) + if (lineno == 1 && (line.startsWith("PK\003\004") + || (line.startsWith("PK\007\008")))) throw new ConfigParseError("Input looks like a ZIP Archive. Import is only possible for OpenVPN config files (.ovpn/.conf)"); - // Check for OpenVPN Access Server Meta information - if (line.startsWith("# OVPN_ACCESS_SERVER_")) { - Vector metaarg = parsemeta(line); - meta.put(metaarg.get(0),metaarg); - continue; - } - Vector args = parseline(line); + // Check for OpenVPN Access Server Meta information + if (line.startsWith("# OVPN_ACCESS_SERVER_")) { + Vector metaarg = parsemeta(line); + meta.put(metaarg.get(0), metaarg); + continue; + } + Vector args = parseline(line); - if(args.size() ==0) - continue; + if (args.size() == 0) + continue; - if(args.get(0).startsWith("--")) - args.set(0, args.get(0).substring(2)); + if (args.get(0).startsWith("--")) + args.set(0, args.get(0).substring(2)); - checkinlinefile(args,br); + checkinlinefile(args, br); - String optionname = args.get(0); - if(!options.containsKey(optionname)) { - options.put(optionname, new Vector>()); - } - options.get(optionname).add(args); - } + String optionname = args.get(0); + if (!options.containsKey(optionname)) { + options.put(optionname, new Vector>()); + } + options.get(optionname).add(args); + } + } catch (java.lang.OutOfMemoryError memoryError) { + throw new ConfigParseError("File too large to parse: " + memoryError.getLocalizedMessage()); + } } private Vector parsemeta(String line) { @@ -98,7 +103,7 @@ public class ConfigParser { break; else { inlinefile+=line; - inlinefile+= "\n"; + inlinefile+= "\n"; } } while(true); @@ -132,7 +137,7 @@ public class ConfigParser { // adapted openvpn's parse function to java private Vector parseline(String line) throws ConfigParseError { - Vector parameters = new Vector(); + Vector parameters = new Vector(); if (line.length()==0) return parameters; @@ -145,12 +150,12 @@ public class ConfigParser { int pos=0; String currentarg=""; - do { + do { // Emulate the c parsing ... char in; if(pos < line.length()) in = line.charAt(pos); - else + else in = '\0'; if (!backslash && in == '\\' && state != linestate.readin_single_quote) @@ -228,10 +233,7 @@ public class ConfigParser { } - final String[] unsupportedOptions = { "config", - "connection", - "proto-force", - "remote-random", + final String[] unsupportedOptions = { "config", "tls-server" }; @@ -299,7 +301,7 @@ public class ConfigParser { "remote", "float", "port", -// "connect-retry", + "connect-retry", "connect-timeout", "connect-retry-max", "link-mtu", @@ -325,7 +327,7 @@ public class ConfigParser { // This method is far too long @SuppressWarnings("ConstantConditions") - public VpnProfile convertProfile() throws ConfigParseError{ + public VpnProfile convertProfile() throws ConfigParseError, IOException { boolean noauthtypeset=true; VpnProfile np = new VpnProfile(CONVERTED_PROFILE); // Pull, client, tls-client @@ -338,7 +340,7 @@ public class ConfigParser { } Vector secret = getOption("secret", 1, 2); - if(secret!=null) + if(secret!=null) { np.mAuthenticationType=VpnProfile.TYPE_STATICKEYS; noauthtypeset=false; @@ -362,7 +364,7 @@ public class ConfigParser { if (route.size() >= 4) gateway = route.get(3); - String net = route.get(1); + String net = route.get(1); try { CIDRIP cidr = new CIDRIP(net, netmask); if (gateway.equals("net_gateway")) @@ -398,7 +400,7 @@ public class ConfigParser { Vector> tlsauthoptions = getAllOption("tls-auth", 1, 2); if(tlsauthoptions!=null) { for(Vector tlsauth:tlsauthoptions) { - if(tlsauth!=null) + if(tlsauth!=null) { if(!tlsauth.get(1).equals("[inline]")) { np.mTLSAuthFilename=tlsauth.get(1); @@ -458,36 +460,6 @@ public class ConfigParser { throw new ConfigParseError("Invalid mode for --mode specified, need p2p"); } - Vector port = getOption("port", 1,1); - if(port!=null){ - np.mServerPort = port.get(1); - } - - Vector rport = getOption("rport", 1,1); - if(rport!=null){ - np.mServerPort = rport.get(1); - } - - Vector proto = getOption("proto", 1,1); - if(proto!=null){ - np.mUseUdp=isUdpProto(proto.get(1)); - } - - // Parse remote config - Vector> remotes = getAllOption("remote",1,3); - - if(remotes!=null && remotes.size()>=1 ) { - Vector remote = remotes.get(0); - switch (remote.size()) { - case 4: - np.mUseUdp=isUdpProto(remote.get(3)); - case 3: - np.mServerPort = remote.get(2); - case 2: - np.mServerName = remote.get(1); - } - } - Vector> dhcpoptions = getAllOption("dhcp-option", 2, 2); @@ -581,18 +553,18 @@ public class ConfigParser { if(verifyx509name!=null){ np.mRemoteCN = verifyx509name.get(1); np.mCheckRemoteCN=true; - if(verifyx509name.size()>2) { + if(verifyx509name.size()>2) { if (verifyx509name.get(2).equals("name")) np.mX509AuthType=VpnProfile.X509_VERIFY_TLSREMOTE_RDN; else if (verifyx509name.get(2).equals("name-prefix")) np.mX509AuthType=VpnProfile.X509_VERIFY_TLSREMOTE_RDN_PREFIX; - else + else throw new ConfigParseError("Unknown parameter to x509-verify-name: " + verifyx509name.get(2) ); } else { np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_DN; } - } + } Vector verb = getOption("verb",1,1); @@ -615,7 +587,7 @@ public class ConfigParser { if(connectretrymax!=null) np.mConnectRetryMax =connectretrymax.get(1); - Vector> remotetls = getAllOption("remote-cert-tls", 1, 1); + Vector> remotetls = getAllOption("remote-cert-tls", 1, 1); if(remotetls!=null) if(remotetls.get(0).get(1).equals("server")) np.mExpectTLSCert=true; @@ -632,14 +604,55 @@ public class ConfigParser { np.mAuthenticationType=VpnProfile.TYPE_USERPASS_KEYSTORE; } if(authuser.size()>1) { - // Set option value to password get to get cance to embed later. + // Set option value to password get to embed later. np.mUsername=null; - np.mPassword=authuser.get(1); - useEmbbedUserAuth(np,authuser.get(1)); + useEmbbedUserAuth(np, authuser.get(1)); } } - // Parse OpenVPN Access Server extra + Pair conns = parseConnectionOptions(null); + np.mConnections =conns.second; + + Vector> connectionBlocks = getAllOption("connection", 1, 1); + + if (np.mConnections.length > 0 && connectionBlocks !=null ) { + throw new ConfigParseError("Using a block and --remote is not allowed."); + } + + if (connectionBlocks!=null) { + np.mConnections = new Connection[connectionBlocks.size()]; + + int connIndex = 0; + for (Vector conn : connectionBlocks) { + Pair connectionBlockConnection = + parseConnection(conn.get(1), conns.first); + + if (connectionBlockConnection.second.length != 1) + throw new ConfigParseError("A block must have exactly one remote"); + np.mConnections[connIndex] = connectionBlockConnection.second[0]; + connIndex++; + } + } + if(getOption("remote-random", 0, 0) != null) + np.mRemoteRandom=true; + + Vector protoforce = getOption("proto-force", 1, 1); + if(protoforce!=null) { + boolean disableUDP; + String protoToDisable = protoforce.get(1); + if (protoToDisable.equals("udp")) + disableUDP=true; + else if (protoToDisable.equals("tcp")) + disableUDP=false; + else + throw new ConfigParseError(String.format("Unknown protocol %s in proto-force", protoToDisable)); + + for (Connection conn:np.mConnections) + if(conn.mUseUdp==disableUDP) + conn.mEnabled=false; + } + + // Parse OpenVPN Access Server extra Vector friendlyname = meta.get("FRIENDLY_NAME"); if(friendlyname !=null && friendlyname.size() > 1) np.mName=friendlyname.get(1); @@ -649,20 +662,95 @@ public class ConfigParser { if(ocusername !=null && ocusername.size() > 1) np.mUsername=ocusername.get(1); - // Check the other options - if(remotes !=null && remotes.size()>1 && extraRemotesAsCustom) { - // first is already added - remotes.remove(0); - np.mCustomConfigOptions += getOptionStrings(remotes); - np.mUseCustomConfig=true; - - } - checkIgnoreAndInvalidOptions(np); + checkIgnoreAndInvalidOptions(np); fixup(np); return np; } + private Pair parseConnection(String connection, Connection defaultValues) throws IOException, ConfigParseError { + // Parse a connection Block as a new configuration file + + + ConfigParser connectionParser = new ConfigParser(); + StringReader reader = new StringReader(connection.substring(VpnProfile.INLINE_TAG.length())); + connectionParser.parseConfig(reader); + + Pair conn = connectionParser.parseConnectionOptions(defaultValues); + + return conn; + } + + private Pair parseConnectionOptions(Connection connDefault) throws ConfigParseError { + Connection conn; + if (connDefault!=null) + try { + conn = connDefault.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + return null; + } + else + conn = new Connection(); + + Vector port = getOption("port", 1,1); + if(port!=null){ + conn.mServerPort = port.get(1); + } + + Vector rport = getOption("rport", 1,1); + if(rport!=null){ + conn.mServerPort = rport.get(1); + } + + Vector proto = getOption("proto", 1,1); + if(proto!=null){ + conn.mUseUdp=isUdpProto(proto.get(1)); + } + + + // Parse remote config + Vector> remotes = getAllOption("remote",1,3); + + + // Assume that we need custom options if connectionDefault are set + if(connDefault!=null) { + for (Vector> option : options.values()) { + + conn.mCustomConfiguration += getOptionStrings(option); + + } + if (!TextUtils.isEmpty(conn.mCustomConfiguration)) + conn.mUseCustomConfig = true; + } + // Make remotes empty to simplify code + if (remotes==null) + remotes = new Vector>(); + + Connection[] connections = new Connection[remotes.size()]; + + + int i=0; + for (Vector remote: remotes) { + try { + connections[i] = conn.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + switch (remote.size()) { + case 4: + connections[i].mUseUdp=isUdpProto(remote.get(3)); + case 3: + connections[i].mServerPort = remote.get(2); + case 2: + connections[i].mServerName = remote.get(1); + } + i++; + } + return Pair.create(conn, connections); + + } + private void checkRedirectParameters(VpnProfile np, Vector> defgw) { for (Vector redirect: defgw) for (int i=1;i { private BigInteger netAddress; public int networkMask; @@ -198,6 +200,13 @@ public class NetworkSpace { mIpAddresses.add(new ipAddress(cidrIp, include)); } + public void addIPSplit(CIDRIP cidrIp, boolean include) { + ipAddress newIP = new ipAddress(cidrIp, include); + ipAddress[] splitIps = newIP.split(); + for (ipAddress split: splitIps) + mIpAddresses.add(split); + } + void addIPv6(Inet6Address address, int mask, boolean included) { mIpAddresses.add(new ipAddress(address, mask, included)); } 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 e90c16d1..1f28c77d 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core; 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 d9830955..578d95e7 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core; @@ -14,7 +14,9 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.net.ConnectivityManager; +import android.net.NetworkRequest; import android.net.VpnService; import android.os.Binder; import android.os.Build; @@ -23,6 +25,7 @@ import android.os.IBinder; import android.os.Message; import android.os.ParcelFileDescriptor; import android.preference.PreferenceManager; +import android.system.OsConstants; import android.text.TextUtils; import android.util.Log; @@ -81,6 +84,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac private String mLastTunCfg; private String mRemoteGW; private final Object mProcessLock = new Object(); + private LollipopDeviceStateListener mLollipopDeviceStateListener; // From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java public static String humanReadableByteCount(long bytes, boolean mbit) { @@ -266,6 +270,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac mDeviceStateReceiver = new DeviceStateReceiver(magnagement); registerReceiver(mDeviceStateReceiver, filter); VpnStatus.addByteCountListener(mDeviceStateReceiver); + + /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + addLollipopCMListener(); */ } synchronized void unregisterDeviceStateReceiver() { @@ -280,6 +287,10 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac iae.printStackTrace(); } mDeviceStateReceiver = null; + + /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + removeLollipopCMListener();*/ + } public void userPause(boolean shouldBePaused) { @@ -320,7 +331,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac mProfile = ProfileManager.getLastConnectedProfile(this, false); /* Got no profile, just stop */ - if (mProfile==null) { + if (mProfile == null) { Log.d("OpenVPN", "Got no last connected profile on null intent. Stopping"); stopSelf(startId); return START_NOT_STICKY; @@ -431,7 +442,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac private OpenVPNManagement instantiateOpenVPN3Core() { try { Class cl = Class.forName("de.blinkt.openvpn.core.OpenVPNThreadv3"); - return (OpenVPNManagement) cl.getConstructor(OpenVPNService.class,VpnProfile.class).newInstance(this,mProfile); + return (OpenVPNManagement) cl.getConstructor(OpenVPNService.class, VpnProfile.class).newInstance(this, mProfile); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InstantiationException e) { @@ -474,6 +485,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if (mLocalIPv6 != null) cfg += mLocalIPv6; + cfg += "routes: " + TextUtils.join("|", mRoutes.getNetworks(true)) + TextUtils.join("|", mRoutesv6.getNetworks(true)); cfg += "excl. routes:" + TextUtils.join("|", mRoutes.getNetworks(false)) + TextUtils.join("|", mRoutesv6.getNetworks(false)); cfg += "dns: " + TextUtils.join("|", mDnslist); @@ -490,6 +502,10 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.logInfo(R.string.last_openvpn_tun_config); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mProfile.mAllowLocalLAN) + { + allowAllAFFamilies(builder); + } if (mLocalIP == null && mLocalIPv6 == null) { VpnStatus.logError(getString(R.string.opentun_no_ipaddr)); @@ -497,6 +513,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac } if (mLocalIP != null) { + addLocalNetworksToRoutes(); try { builder.addAddress(mLocalIP.mIp, mLocalIP.len); } catch (IllegalArgumentException iae) { @@ -527,7 +544,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac String release = Build.VERSION.RELEASE; 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")) + && !release.startsWith("4.4.4") && !release.startsWith("4.4.5") && !release.startsWith("4.4.6")) && mMtu < 1280) { VpnStatus.logInfo(String.format(Locale.US, "Forcing MTU to 1280 instead of %d to workaround Android Bug #70916", mMtu)); builder.setMtu(1280); @@ -560,8 +577,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.logInfo(R.string.local_ip_info, mLocalIP.mIp, mLocalIP.len, mLocalIPv6, mMtu); VpnStatus.logInfo(R.string.dns_server_info, TextUtils.join(", ", mDnslist), mDomain); VpnStatus.logInfo(R.string.routes_info_incl, TextUtils.join(", ", mRoutes.getNetworks(true)), TextUtils.join(", ", mRoutesv6.getNetworks(true))); - VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(", ", mRoutes.getNetworks(false)),TextUtils.join(", ", mRoutesv6.getNetworks(false))); + VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(", ", mRoutes.getNetworks(false)), TextUtils.join(", ", mRoutesv6.getNetworks(false))); VpnStatus.logDebug(R.string.routes_debug, TextUtils.join(", ", positiveIPv4Routes), TextUtils.join(", ", positiveIPv6Routes)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + setAllowedVpnPackages(builder); + } + String session = mProfile.mName; if (mLocalIP != null && mLocalIPv6 != null) @@ -601,6 +622,82 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac } + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private void allowAllAFFamilies(Builder builder) { + builder.allowFamily(OsConstants.AF_INET); + builder.allowFamily(OsConstants.AF_INET6); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + void removeLollipopCMListener() { + ConnectivityManager cm = (ConnectivityManager) getBaseContext().getSystemService(CONNECTIVITY_SERVICE); + cm.unregisterNetworkCallback(mLollipopDeviceStateListener); + mLollipopDeviceStateListener = null; + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + void addLollipopCMListener() { + ConnectivityManager cm = (ConnectivityManager) getBaseContext().getSystemService(CONNECTIVITY_SERVICE); + NetworkRequest.Builder nrb = new NetworkRequest.Builder(); + + mLollipopDeviceStateListener = new LollipopDeviceStateListener(); + cm.registerNetworkCallback(nrb.build(), mLollipopDeviceStateListener); + } + + private void addLocalNetworksToRoutes() { + + // Add local network interfaces + String[] localRoutes = NativeUtils.getIfconfig(); + + // The format of mLocalRoutes is kind of broken because I don't really like JNI + for (int i = 0; i < localRoutes.length; i += 3) { + String intf = localRoutes[i]; + String ipAddr = localRoutes[i + 1]; + String netMask = localRoutes[i + 2]; + + if (intf == null || intf.equals("lo") || + intf.startsWith("tun") || intf.startsWith("rmnet")) + continue; + + if (ipAddr==null || netMask == null) { + VpnStatus.logError("Local routes are broken?! (Report to author) " + TextUtils.join("|", localRoutes)); + continue; + } + + if (ipAddr.equals(mLocalIP.mIp)) + continue; + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT && !mProfile.mAllowLocalLAN) { + mRoutes.addIPSplit(new CIDRIP(ipAddr, netMask), true); + + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && mProfile.mAllowLocalLAN) + mRoutes.addIP(new CIDRIP(ipAddr, netMask), false); + } + } + + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private void setAllowedVpnPackages(Builder builder) { + for (String pkg : mProfile.mAllowedAppsVpn) { + try { + if (mProfile.mAllowedAppsVpnAreDisallowed) { + builder.addDisallowedApplication(pkg); + } else { + builder.addAllowedApplication(pkg); + } + } catch (PackageManager.NameNotFoundException e) { + mProfile.mAllowedAppsVpn.remove(pkg); + VpnStatus.logInfo(R.string.app_no_longer_exists, pkg); + } + } + + if (mProfile.mAllowedAppsVpnAreDisallowed) { + VpnStatus.logDebug(R.string.disallowed_vpn_apps_info, TextUtils.join(", ", mProfile.mAllowedAppsVpn)); + } else { + VpnStatus.logDebug(R.string.allowed_vpn_apps_info, TextUtils.join(", ", mProfile.mAllowedAppsVpn)); + } + } + public void addDNS(String dns) { mDnslist.add(dns); } @@ -611,28 +708,30 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac } } - /** Route that is always included, used by the v3 core */ - public void addRoute (CIDRIP route) { + /** + * Route that is always included, used by the v3 core + */ + public void addRoute(CIDRIP route) { mRoutes.addIP(route, true); } - public void addRoute (String dest, String mask, String gateway, String device) { + public void addRoute(String dest, String mask, String gateway, String device) { CIDRIP route = new CIDRIP(dest, mask); boolean include = isAndroidTunDevice(device); - NetworkSpace.ipAddress gatewayIP = new NetworkSpace.ipAddress(new CIDRIP(gateway, 32),false); + NetworkSpace.ipAddress gatewayIP = new NetworkSpace.ipAddress(new CIDRIP(gateway, 32), false); - if (mLocalIP==null) { + if (mLocalIP == null) { VpnStatus.logError("Local IP address unset but adding route?! This is broken! Please contact author with log"); return; } - NetworkSpace.ipAddress localNet = new NetworkSpace.ipAddress(mLocalIP,true); + NetworkSpace.ipAddress localNet = new NetworkSpace.ipAddress(mLocalIP, true); if (localNet.containsNet(gatewayIP)) - include=true; + include = true; - if (gateway!= null && + if (gateway != null && (gateway.equals("255.255.255.255") || gateway.equals(mRemoteGW))) - include=true; + include = true; if (route.len == 32 && !mask.equals("255.255.255.255")) { @@ -664,7 +763,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac } private boolean isAndroidTunDevice(String device) { - return device!=null && + return device != null && (device.startsWith("tun") || "(null)".equals(device) || "vpnservice-tun".equals(device)); } @@ -679,7 +778,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac public void setLocalIP(String local, String netmask, int mtu, String mode) { mLocalIP = new CIDRIP(local, netmask); mMtu = mtu; - mRemoteGW=null; + mRemoteGW = null; long netMaskAsInt = CIDRIP.getInt(netmask); @@ -687,14 +786,17 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac // get the netmask as IP int masklen; - if ("net30".equals(mode)) + long mask; + if ("net30".equals(mode)) { masklen = 30; - else + mask = 0xfffffffc; + } else { masklen = 31; + mask = 0xfffffffe; + } - int mask = ~( 1 << (32 - (mLocalIP.len +1))); // Netmask is Ip address +/-1, assume net30/p2p with small net - if ((netMaskAsInt & mask) == (mLocalIP.getInt() & mask )) { + if ((netMaskAsInt & mask) == (mLocalIP.getInt() & mask)) { mLocalIP.len = masklen; } else { mLocalIP.len = 32; @@ -702,13 +804,18 @@ 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(mode) && 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); } + /* Workaround for Lollipop, it does not route traffic to the VPNs own network mask */ + if (mLocalIP.len <= 31 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + addRoute(mLocalIP); + + // Configurations are sometimes really broken... - mRemoteGW=netmask; + mRemoteGW = netmask; } public void setLocalIPv6(String ipv6addr) { @@ -810,7 +917,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac } else { String release = Build.VERSION.RELEASE; 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")) + && !release.startsWith("4.4.4") && !release.startsWith("4.4.5") && !release.startsWith("4.4.6")) // There will be probably no 4.4.4 or 4.4.5 version, so don't waste effort to do parsing here return "OPEN_AFTER_CLOSE"; else 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 e36a5b8a..298a6c40 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core; 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 37094a1b..1c3b3362 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core; @@ -157,7 +157,7 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } } catch (IOException e) { - if (!e.getMessage().equals("socket closed")) + if (!e.getMessage().equals("socket closed") && !e.getMessage().equals("Connection reset by peer")) VpnStatus.logException(e); } synchronized (active) { 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 bca0a4ab..a788426a 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java +++ b/app/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core;/* 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 2a26152e..1ebc0a57 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core; 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 cf953863..6e2abb13 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core; 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 208aa359..73ed05bc 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core; @@ -76,7 +76,6 @@ public class VPNLaunchHelper { args.add("--config"); args.add(c.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE); - return args.toArray(new String[args.size()]); } 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 25558f13..ffc8097d 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core; @@ -480,7 +480,11 @@ public class VpnStatus { newLogItem(new LogItem(LogLevel.INFO, message)); } - public static void logInfo(int resourceId, Object... args) { + public static void logDebug(String message) { + newLogItem(new LogItem(LogLevel.DEBUG, message)); + } + + public static void logInfo(int resourceId, Object... args) { newLogItem(new LogItem(LogLevel.INFO, resourceId, args)); } 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 ff383e0f..0786967b 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java +++ b/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.core; 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 77fc21e6..199caa63 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.fragments; 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 e25c2859..82378b00 100644 --- a/app/src/main/java/de/blinkt/openvpn/views/SeekBarTicks.java +++ b/app/src/main/java/de/blinkt/openvpn/views/SeekBarTicks.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt */ package de.blinkt.openvpn.views; diff --git a/app/src/main/res/drawable-hdpi/ic_delete_grey600_24dp.png b/app/src/main/res/drawable-hdpi/ic_delete_grey600_24dp.png new file mode 100644 index 00000000..b72a9f3c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_delete_grey600_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_delete_grey600_24dp.png b/app/src/main/res/drawable-mdpi/ic_delete_grey600_24dp.png new file mode 100644 index 00000000..e757fdb0 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_delete_grey600_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_delete_grey600_24dp.png b/app/src/main/res/drawable-xhdpi/ic_delete_grey600_24dp.png new file mode 100644 index 00000000..c6bb43e8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_delete_grey600_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_delete_grey600_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_delete_grey600_24dp.png new file mode 100644 index 00000000..4886ab1e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_delete_grey600_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_delete_grey600_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_delete_grey600_24dp.png new file mode 100644 index 00000000..e4e21812 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_delete_grey600_24dp.png differ diff --git a/app/src/main/res/drawable/white_rect.xml b/app/src/main/res/drawable/white_rect.xml new file mode 100644 index 00000000..5ead4b9b --- /dev/null +++ b/app/src/main/res/drawable/white_rect.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file 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 2f5c774d..1fb9fa54 100644 --- a/app/src/main/res/layout-sw600dp-port/log_fragment.xml +++ b/app/src/main/res/layout-sw600dp-port/log_fragment.xml @@ -1,7 +1,7 @@ @@ -33,10 +35,6 @@ android:layout_weight="1"/> - - - - - +

diff --git a/app/src/main/res/values-ca/strings-icsopenvpn.xml b/app/src/main/res/values-ca/strings-icsopenvpn.xml index b18766ca..ce7b8919 100755 --- a/app/src/main/res/values-ca/strings-icsopenvpn.xml +++ b/app/src/main/res/values-ca/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-cs/strings-icsopenvpn.xml b/app/src/main/res/values-cs/strings-icsopenvpn.xml index 6ae5a3f0..87a6bed1 100755 --- a/app/src/main/res/values-cs/strings-icsopenvpn.xml +++ b/app/src/main/res/values-cs/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + @@ -328,4 +329,23 @@ 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) Přepsat hodnotu MSS pro TCP obsah Nastavit MSS pro TCP obsah + Chování klienta + Zrušit povolené externí aplikace + Načítání… + Povolené VPN aplikace: %1$s + Zakázané VPN aplikace: %1$s + Balíček %s již není nainstalován, odstraňuji ho ze seznamu povolených/zakázaných aplikací + VPN je používaná pro všechny aplikace, kromě + VPN je používaná je pro vybrané aplikace + Odstranit položku vzdáleného serveru? + Zachovat + Smazat + Přidat nové vzdálené místo + Použít položky k připojení v náhodném pořadí + Je potřeba definovat a povolit alespoň jeden vzdálený server. + Seznam serverů + Povolené aplikace + Pokročilé nastavení + Možnosti dat + Nastevení TLS diff --git a/app/src/main/res/values-de/strings-icsopenvpn.xml b/app/src/main/res/values-de/strings-icsopenvpn.xml index cebb9646..ba667502 100755 --- a/app/src/main/res/values-de/strings-icsopenvpn.xml +++ b/app/src/main/res/values-de/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + @@ -328,4 +329,26 @@ Ä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) Überschreiben des MSS-Wert von TCP-Nutzlast Setze MSS von TCP-Nutzlast + Client-Verhalten + Widerrufe Berechtigungen OpenVPN zu steuern + Wird geladen… + Apps erlaubt für das VPN: %1$s + Apps, die nicht das VPN nutzen: %1$s + Anwendung mit Paketnamen \'%s\' ist nicht mehr installiert, wird von der Liste der erlaubten/nicht erlaubten VPN Anwendungen gelöscht. + VPN für alle Anwendung ausgenommen den ausgewählten + VPN nur für die ausgewählten Anwendungen + Servereintrag entfernen? + Behalten + Entfernen + Neuen Server hinzufügen + Beim Verbinden Servereinträge in zufälliger Reihenfolge verwenden + Sie müssen mindestens einen Server definieren und aktivieren. + Serverliste + Erlaubte Anwendungen + Erweiterte Einstellungen + Nutzlast-Optionen + TLS-Einstellungen + Keine Server definiert + VPN Profil duplizieren + VPN Profil duplizieren: %s diff --git a/app/src/main/res/values-es/strings-icsopenvpn.xml b/app/src/main/res/values-es/strings-icsopenvpn.xml index 92995c6f..4cbb152d 100755 --- a/app/src/main/res/values-es/strings-icsopenvpn.xml +++ b/app/src/main/res/values-es/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + @@ -147,7 +148,7 @@ Su configuración tiene algunas opciones de configuración que no están establecidas en la interfaz de usuario . Estas opciones fueron agregadas como opciones de configuración personalizadas. A continuación se muestra la configuración personalizada: Se termino de leer el archivo de configuración. No enlazar con el puerto y la dirección local - Ningún enlace local + No enlazar localmente Importar archivo de configuracion Consideraciones de seguridad "Como OpenVPN es sensible a la seguridad, son razonables algunas notas acerca de seguridad. Todos los datos en la tarjeta SD son inherentemente inseguros. Cualquier aplicación puede leerla (por ejemplo, esta aplicación no requiere ningún permiso especial sobre la tarjeta SD). Los datos de esta aplicación sólo pueden ser leidos por la misma aplicación. Al utilizar la opción importar para el certificado de la CA/certificado/llave, en la ventana de diálogo para selección de archivos, los datos se almacenan en el perfil de la VPN. Los perfiles de VPN sólo son accesibles por esta aplicación. (No olvide después borrar las copias de la tarjeta SD). Aunque sólo sea accesible por esta aplicación, los datos aún están sin encriptar. Al acceder el dispositivo portátil como root u otro medio, es posible recuperar estos datos. Las contraseñas guardadas son almacenadas también en texto plano. Para archivos pkcs12 es muy recomendable que los importe al repositorio de llaves de Android." @@ -173,7 +174,8 @@ Muestra el archivo de configuración OpenVPN generado Editando \"%s\" Construyendo configuracion… - Turning this option on will force a reconnect if the network state is changed (e.g. WiFi to/from mobile) + Activando esta opción forzara una reconexión si el estado de la red es cambiado (Ej. De/hacia WIFi +hacia/de Móvil) Reconectar en cambio de red Estado de la red: %s El certificado de la CA usualmente es recuperado del almacén de claves de Android. Especifique un certificado diferente si obtiene errores de verificación de certificado. @@ -185,7 +187,7 @@ Error al firmar con la llave del almacén de llaves de Android %1$s: %2$s El aviso de conectividad VPN que esta aplicación puede interceptar todo el trafico esta impuesta por el sistema para evitar abusos de la API VPNService.\nLa notificación de conectividad (El símbolo de llave) también esta impuesta por el sistema Android para notificar una conexión VPN en curso. En algunas imágenes, esta notificación también emite un sonido.\nAndroid ha introducido estos diálogos de sistema para su seguridad e se ha asegurado que no pueden ser evitados. (En algunas imágenes, esto incluye la notificación sonora) Advertencia de conexión y sonido de notificación - Traducción al español por José Luis Bandala Perez<luis.449bp@gmail.com> + Traducción al español por José Luis Bandala Pérez<luis.449bp@gmail.com> IP y DNS Básico Enrutamiento @@ -274,7 +276,7 @@ RDN (nombre comun) Prefijo RDN tls-remote (OBSOLETO) - Tu puedes ayudar traduciendo visitando http://crowdin.net/project/ics-openvpn/invite + Tu puedes ayudar a traducir visitando http://crowdin.net/project/ics-openvpn/invite %1$s intentos de controlar %2$s Al proceder, le estás proporcionando permiso a la aplicación para controlar completamente OpenVPN for Android e interceptar todo el tráfico de la red.NO aceptar a menos que confíes en la aplicación. De otro modo, corres el riesgo de que tus datos se vean comprometidos por software malicioso.\" Confío en esta aplicación. @@ -317,7 +319,7 @@ Si ha rooteado su dispositivo Android, puede instalar el <a href=\"http://xposed.info/\">framework Xposed</a> y añadir el <a href=\"http://repo.xposed.info/module/de.blinkt.vpndialogxposed\">módulo de confirmación de Diálogo VPN</a> bajo su propio riesgo\" Licencias completas Las redes conectadas directamente a los interfaces locales no serán enrutadas a través de la VPN. Al desmarcar esta opción, todo el tráfico previsto para las redes locales será redirigido a la VPN. - Evitar la VPN para las redes locales + Saltarse la VPN en redes locales Archivo de Usuario/Contraseña [Importado de:%s] Algunos archivos no se pudo encontrar. Por favor, seleccione los archivos que desea importar el perfil: @@ -325,6 +327,29 @@ Importar registros: 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\". El valor de mssfix debe ser un número entero entre 0 y 9000 + Anunciar a las sesiones TCP ejecutandose sobre el túnel que deben limitar su tamaño de paquetes enviados de tal manera que después de que OpenVPN los hay encapsulado, el tamaño del paquete UDP resultante enviado a su par no exceda este numero de bytes. (Por defecto es 1450) Reemplazar el valor MSS de la carga TCP Establecer MSS de la carga TCP + Comportamiento del cliente + Borrar aplicaciones externas permitidas + Cargando… + Aplicaciones VPN permitidas: %1$s + Aplicaciones VPN no permitidas: %1$s + El paquete %s ya no está instalado, sacándolo de la lista de apps permitidas/no permitidas + La VPN es usada por todas las aplicaciones, excepto por las seleccionadas + La VPN es utilizada únicamente por las aplicaciones seleccionadas + ¿Eliminar entrada del servidor remoto? + Mantener + Eliminar + Añadir nuevo acceso remoto + Utiliza las entradas de conexión en orden aleatorio en la conexión + Es necesario definir y habilitar al menos un servidor remoto. + Lista de servidores + Aplicaciones permitidas + Opciones Avanzadas + Opciones de carga útil + Configuración TLS + Servidor remoto no definido + Duplicar perfil VPN + Duplicando Perfil: %s diff --git a/app/src/main/res/values-et/strings-icsopenvpn.xml b/app/src/main/res/values-et/strings-icsopenvpn.xml index 7761726e..c5174284 100755 --- a/app/src/main/res/values-et/strings-icsopenvpn.xml +++ b/app/src/main/res/values-et/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + @@ -328,4 +329,26 @@ 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) Ignoreeri TCP lasti MSS väärtust Sea TCP lasti MSS väärtus + Kliendi toimimine + Nulli lubatud välised programmid + Laadimine… + Lubatud VPN programmid: %1$s + Keelatud VPN programmid: %1$s + Programm %s on seadmest eemaldatud, see kustutatakse ka lubatud/keelatud programmide nimistust + VPN on kõigi, välja arvatud märgitud, programmide puhul kasutuses + VPN on kasutuses ainult märgitud programmide puhul + Kas eemaldada kaugserveri kirje? + Säilita + Eemalda + Uue kaugserveri lisamine + Ühendumisel kasuta ühenduskirjeid juhuslikus järjekorras + Peate määrama vähemalt ühe kaugserveri. + Serverite Nimistu + Lubatud Programmid + Täpsemad seaded + Nimikoormuse valikud + TLS Seaded + Kaugserverid määramata + Dubleeritud VPN profiil + Duplitseeritakse profiili: %s diff --git a/app/src/main/res/values-fr/strings-icsopenvpn.xml b/app/src/main/res/values-fr/strings-icsopenvpn.xml index 15bc7aa4..657646c8 100755 --- a/app/src/main/res/values-fr/strings-icsopenvpn.xml +++ b/app/src/main/res/values-fr/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-hu/strings-icsopenvpn.xml b/app/src/main/res/values-hu/strings-icsopenvpn.xml index 504ab893..2efdcf5f 100755 --- a/app/src/main/res/values-hu/strings-icsopenvpn.xml +++ b/app/src/main/res/values-hu/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-in/strings-icsopenvpn.xml b/app/src/main/res/values-in/strings-icsopenvpn.xml index c111cbb5..3dac7c71 100755 --- a/app/src/main/res/values-in/strings-icsopenvpn.xml +++ b/app/src/main/res/values-in/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-it/strings-icsopenvpn.xml b/app/src/main/res/values-it/strings-icsopenvpn.xml index 29d48904..36198678 100755 --- a/app/src/main/res/values-it/strings-icsopenvpn.xml +++ b/app/src/main/res/values-it/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + @@ -325,4 +326,16 @@ Effettuata la lettura del file di configurazione Alcuni file non possono essere trovati. Si prega di selezionare i file da importare nel profilo: 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. Registro importazione: + Sovrascrivi il valore del MSS nel payload TCP + Setta il valore del MSS nel payload TCP + Comportamento Client + Caricando… + Mantieni + Elimina + Lista Server + Impostazioni Avanzate + Opzioni Payload + Impostazioni TLS + Profilo VPN duplicato + Duplicazione del profilo: %s diff --git a/app/src/main/res/values-ja/strings-icsopenvpn.xml b/app/src/main/res/values-ja/strings-icsopenvpn.xml index 79474f2d..792e6200 100755 --- a/app/src/main/res/values-ja/strings-icsopenvpn.xml +++ b/app/src/main/res/values-ja/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-ko/strings-icsopenvpn.xml b/app/src/main/res/values-ko/strings-icsopenvpn.xml index b05e4f51..9266a36c 100755 --- a/app/src/main/res/values-ko/strings-icsopenvpn.xml +++ b/app/src/main/res/values-ko/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-nl/strings-icsopenvpn.xml b/app/src/main/res/values-nl/strings-icsopenvpn.xml index 2a000195..b486706e 100755 --- a/app/src/main/res/values-nl/strings-icsopenvpn.xml +++ b/app/src/main/res/values-nl/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-no/strings-icsopenvpn.xml b/app/src/main/res/values-no/strings-icsopenvpn.xml index 66391eb5..501b18df 100755 --- a/app/src/main/res/values-no/strings-icsopenvpn.xml +++ b/app/src/main/res/values-no/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-pl/strings-icsopenvpn.xml b/app/src/main/res/values-pl/strings-icsopenvpn.xml index 495eb00e..052b0135 100755 --- a/app/src/main/res/values-pl/strings-icsopenvpn.xml +++ b/app/src/main/res/values-pl/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-pt/strings-icsopenvpn.xml b/app/src/main/res/values-pt/strings-icsopenvpn.xml index d0058c68..ec7d2534 100755 --- a/app/src/main/res/values-pt/strings-icsopenvpn.xml +++ b/app/src/main/res/values-pt/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-ro/strings-icsopenvpn.xml b/app/src/main/res/values-ro/strings-icsopenvpn.xml index ef4e3a75..3821f964 100755 --- a/app/src/main/res/values-ro/strings-icsopenvpn.xml +++ b/app/src/main/res/values-ro/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-ru/strings-icsopenvpn.xml b/app/src/main/res/values-ru/strings-icsopenvpn.xml index e2bc930c..5db415df 100755 --- a/app/src/main/res/values-ru/strings-icsopenvpn.xml +++ b/app/src/main/res/values-ru/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-sv/strings-icsopenvpn.xml b/app/src/main/res/values-sv/strings-icsopenvpn.xml index 9b974522..151742a5 100755 --- a/app/src/main/res/values-sv/strings-icsopenvpn.xml +++ b/app/src/main/res/values-sv/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-sw600dp/dimens.xml b/app/src/main/res/values-sw600dp/dimens.xml index b83bb856..94a120d1 100644 --- a/app/src/main/res/values-sw600dp/dimens.xml +++ b/app/src/main/res/values-sw600dp/dimens.xml @@ -1,4 +1,9 @@ + + true diff --git a/app/src/main/res/values-sw600dp/styles.xml b/app/src/main/res/values-sw600dp/styles.xml index de0bb55d..c320388d 100644 --- a/app/src/main/res/values-sw600dp/styles.xml +++ b/app/src/main/res/values-sw600dp/styles.xml @@ -1,4 +1,9 @@ + + 16dp diff --git a/app/src/main/res/values-tr/strings-icsopenvpn.xml b/app/src/main/res/values-tr/strings-icsopenvpn.xml index 90ad068d..ea81d3ed 100755 --- a/app/src/main/res/values-tr/strings-icsopenvpn.xml +++ b/app/src/main/res/values-tr/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + @@ -11,7 +12,7 @@ Sunucu Portu: Konum Dizin Okunamıyor - Seçin + Seç İptal Veri Yok LZO sıkıştırma @@ -316,4 +317,20 @@ Kullanıcı adı / Şifre dosyası [Buradan içeri aktar: %s] Kaydı içe aktar: + İstemci davranışı + Yükleniyor… + Izin verilen VPN uygulamaları: %1$s + İzin verilmeyen VPN uygulamaları: %1$s + %s adlı paket artık yüklü değil, izin listesinden çıkarılıyor + Seçilen uygulamar dışındaki tüm uygulamalar için VPN kullanılır + Sadece seçilen uygulamar için VPN kullanılır + Uzak sunucu girişi kaldırılsın mı? + Sakla + Sil + Yenı uzak sunucu ekle + En az bir uzak sunucu tanımlamalı ve etkinleştirmelisiniz. + Sunucu Listesi + İzin verilen uygulamalar + Gelişmiş Ayarlar + TLS Ayarları diff --git a/app/src/main/res/values-uk/strings-icsopenvpn.xml b/app/src/main/res/values-uk/strings-icsopenvpn.xml index 92637b74..dbbc65a0 100755 --- a/app/src/main/res/values-uk/strings-icsopenvpn.xml +++ b/app/src/main/res/values-uk/strings-icsopenvpn.xml @@ -1,9 +1,10 @@ - + + diff --git a/app/src/main/res/values-v21/colours.xml b/app/src/main/res/values-v21/colours.xml new file mode 100644 index 00000000..1fedf7b9 --- /dev/null +++ b/app/src/main/res/values-v21/colours.xml @@ -0,0 +1,9 @@ + + + + + #5C6BC0 + \ No newline at end of file diff --git a/app/src/main/res/values-v21/refs.xml b/app/src/main/res/values-v21/refs.xml index 0d5d271a..d29d04ed 100644 --- a/app/src/main/res/values-v21/refs.xml +++ b/app/src/main/res/values-v21/refs.xml @@ -1,7 +1,7 @@ @@ -9,5 +9,7 @@ @drawable/ic_share_white_24dp @drawable/ic_filter_list_white_24dp @drawable/ic_delete_white_24dp + @drawable/ic_delete_grey600_24dp + @drawable/ic_edit_white_24dp diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml index 892b6cb0..4379dd6d 100644 --- a/app/src/main/res/values-v21/styles.xml +++ b/app/src/main/res/values-v21/styles.xml @@ -1,13 +1,15 @@ + + + + +