summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java3
-rw-r--r--app/src/fatweb/assets/public.pgp118
-rw-r--r--app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadService.java6
-rw-r--r--app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java12
-rw-r--r--app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/UpdateDownloadManager.java53
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java9
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java76
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java2
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java44
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java48
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java7
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java7
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java6
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java18
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java3
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java25
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java38
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java66
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java144
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java89
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java18
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java143
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/HoppingConfig.java (renamed from app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingConfig.java)30
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/KcpConfig.java39
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/Obfs4Options.java (renamed from app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java)8
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java35
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java31
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java11
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java21
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java30
-rw-r--r--app/src/main/res/layout-xlarge/f_about.xml34
-rw-r--r--app/src/main/res/layout/d_obfuscation_proxy.xml2
-rw-r--r--app/src/main/res/layout/f_about.xml30
-rw-r--r--app/src/main/res/values/untranslatable.xml30
-rw-r--r--app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java37
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java14
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java17
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java4
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java4
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java39
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java2
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java2
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java10
-rw-r--r--app/src/test/resources/preconfigured/riseup.net.pem40
-rw-r--r--app/src/test/resources/ptdemo.bitmask.eip-service-obfsvpn1.0.0.json64
-rw-r--r--app/src/test/resources/ptdemo_kcp_gateways.json6
-rw-r--r--app/src/test/resources/ptdemo_misconfigured_ipv4ipv6.json3
-rw-r--r--app/src/test/resources/ptdemo_misconfigured_tcp2.json (renamed from app/src/test/resources/ptdemo_misconfigured_udp2.json)2
-rw-r--r--app/src/test/resources/ptdemo_misconfigured_udptcp.json3
-rw-r--r--app/src/test/resources/ptdemo_obfs4hop_tcp_gateways.json3
-rw-r--r--app/src/test/resources/ptdemo_three_mixed_gateways.json4
-rw-r--r--app/src/test/resources/riseup.net.pem40
-rw-r--r--app/src/test/resources/v4/generictest.cert49
-rw-r--r--app/src/test/resources/v4/riseup.net.cert76
-rw-r--r--app/src/test/resources/v4/riseup_eipservice_for_geoip_v4.json15
59 files changed, 737 insertions, 954 deletions
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java
index dedb40d7..133b834b 100644
--- a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java
+++ b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java
@@ -31,6 +31,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
+import org.junit.Assume;
import se.leap.bitmaskclient.base.MainActivity;
import se.leap.bitmaskclient.base.StartActivity;
@@ -69,6 +70,8 @@ public class ProviderSetupTest {
@Test
public void test01_setupProviderDefault() {
+ // Assume the branding is not "custom" to skip this test when it is.
+ Assume.assumeFalse("custom".equals(BuildConfig.FLAVOR_branding));
startSetupActivity();
ProviderSetupUtils.runProviderSetup(device, true, false, InstrumentationRegistry.getInstrumentation().getTargetContext());
}
diff --git a/app/src/fatweb/assets/public.pgp b/app/src/fatweb/assets/public.pgp
index 6964df42..d1b26518 100644
--- a/app/src/fatweb/assets/public.pgp
+++ b/app/src/fatweb/assets/public.pgp
@@ -418,41 +418,83 @@ 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
-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
-=9gOD
------END PGP PUBLIC KEY BLOCK-----
+idhhJKwG7YrfHtIRjfdHNHjk5IK9nDLpEiZeAZm5iUPlnsdeiQJUBBMBCgA+AhsD
+BQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAFiEEHkU7LOh77i99/plmHjShgo4geQEF
+AmVE5pUFCRnVvjgACgkQHjShgo4geQEaPxAAinAVEP+IDI5kQhK7KjeS+m+b1IQI
+Wvl9JmFP4aey6oDFOm1EySU9i999ma7o4HK9b93MUyI86TNyDxPmo0PSp3OOwWi2
+Moy/WRtifZiRZobChq7KQyBzJrxio0WkHjM6pZv/tEtKZJq6cY0h/pCi4nJQ/yBR
+RorwPJsmK8wxi83Fhg525hCJxdipT5XNYPNpNcjAufepUEnvBC9k92sliU8lryvm
+vcVAd/ghfkYI4zkdsxZ68RP+r8rG9h+lM+ifI3AbkfvayBIpYo82wur4P0uQggdB
+BJIsVOuCyK/MafTmz0qTpopc0mXRan2eO3bPuDRnWDWUQi8shOPwZODyhFG7Kvx9
+/1KRrGSo2+vEYfD+liFmHMHwz5c22f7f+++dt4k54C8zxZjVYGITpvTiD5PgxZPh
+tNe7G7S3HGKIV6hSOw+qWUJkMfRi3qAuTq1K8xDXCsc5/0btEMQRxrFJ9DclF4ur
+Elrat5zgMA9e3C3efU0YDI84vA6AwZ6XEmsfzIbzhRw8I3ivXxXTM1DqllcpLEHK
+b4Zu7H6FTRpmpb1Jltn2wZAkOJcaKrDTTq9hpdpOzldSM5UrdX+67sXnqkkna40F
+m81nFCHBZlfpH9aDsjfAqJQelZVt20DSiNKS+EpEqZM90/5ZO7exe3UXaP0VY98u
+s96hlmfrHQt2GoW5Ag0EURLC3QEQANxa8Po+h/THBCIv4I4hsL8ZyHRnPDHFnIZx
+aTlr3YU1vdOer/sttg6Cm1C40/JPvBs7kUNMaeFcAgta191BMcHHnM8xrPrUiriB
+poNRC8oLGjmR3UATSxj75/k2TRpWmFz5UKO5vGIVxh8IEK3Sso3BQ+cZzh8XvfNS
+06viEOo1WIYaO/0IpPa1RNVx8aDn2L5zWSQ9HBXX/TnF+O2KKpjOLGWDzKDpiqFU
+E7AAEOdu8M++NgXekqboagaXRMOmIgmMRKKOZAWNyIT9y+Tk0uLc4TpHX9cZYVkp
+whROzZD3CuqPq+qgnFKkRlfY0cCPeyZTynoBB2Fryw+EpN9aVovDWdLaFP56kb8W
+4YbR8bjX943gAM8UAYRlYtAvyAa+L6shaphB6/ScSGtw01fMP2tGOIV9m3My/WNX
+Aep/KjgOvGgJ/sXqyXEjq6EyCYfNw/+zoLnsRhmKGQQ71+nVoLn/LnRT3mKSb5E+
+k0mBfVNCaVU7ZQjbrY0nFDtrmlffrg6gAp4MKm8wU4y/FLnAJXlXBXzouPMnqZzn
+ddWBWMW8PvwXKizYYtXj9gGhsSIF20fPLRfTgtEl2gh/tWdW22pTpkDWLLTr/QW7
+B71u5j4F9sYcqA5FUVmjQEKAy25ya+IIvXA/P5EDM3ZRjs7dorLf/sbnm5VybOUz
+jvNEcPgBABEBAAGJAiUEGAEKAA8CGwwFAlN2ZdEFCQRE1kEACgkQHjShgo4geQFc
+nxAAmTf3BD3xxkU9l0j0uxkizVIWsh4jp+GNVhD80r1QZ6XUfQWlNZS0w8wQAymf
+cD8u5EQEnkIegaBecEIVBTAcXxuSqWECaqD2L7S+A8J37gKK+wQ8TPQu+hQivGnR
+5STjI/dWZ9iqyR5ZLrvK38obeoylsdRMOncIgJ1J5/ZOyH4IoAEbIwabrfJ/vZ/2
+R/lQXnoE9cu/095pECwHR5AUHl+FcG7B5KPYoY25cI8ZLMn2b9Nl3aK8/b4lVnJY
+N9X6c7xcyKhcoUOW1KffVR9X7iiqWuLaZQVV4HX+flxsG6WrmQvGwzXcbcW0/AQA
+4Rgd8Rz3X+5zvg2YbdjUMedC1C+nYJ4/nKQGm0uhA+p59jvQX95E2+Bsh4YTw5/v
+GqHKRj2IOhROfXEPUtNLIoFbviR/uIEGaaXdhY/XIXn9AemJFXtwV4kBCmqbgou5
+DCKh5MVL8aq6cKfYUhDmlqk2fS7ONVUoMUdan4Ntz9COmCNT6Mdcv9jaZIjhkqzV
+OW4cQnMGweTNFGnr9unHxztDA9pXrjyINcEZcqCEXNNEYoha0RQdZvEZzzed+65Y
+IgwVvcx0n4doOiJmCI0WNPns1mhzKxDqLz8IfcpxWC1oCCFGP8is7Fgs0UPXoHem
+1IsTue7PnRUH7PIWANg464yLlTCqr+hLhsLGjw7D0BR98zCJAlMEKAEKAD0FAlOH
+ing2HQNTaWduaW5nLW9ubHkga2V5LCByZXZva2luZyBlbmNyeXB0aW9uIGNhcGFi
+bGUgc3Via2V5AAoJEB40oYKOIHkBnhsP/3y8OQl0Sf2qs/KoBLSNvvTvicYeviYq
+sru3GK0cHLk0C1FwI5BN2az0Zlhhyi9sbLIXzuA9kdiglO3ostSdFlryazEHurv4
+PK8iV9vbZuK7d9C+VZ/okzprOrx52g88yvyqWcq0TTJSIRWiYT2J8fedLilZ8hew
+UmyiKgt54AKWbq+EDeaAL/Vv9PazEidhiDF2vTKPuH5A4mfHKBwcssQZm6K/CGLG
+iws/2Srk+0RwW4fZrd0tniGu/TOxldPuJTNsIvoZj2KAPPzYL/tOIbqzTa74I+r4
+9Sx/qqRGfs0HR+EHK0GFyjv9UAlxSigJPAkMPpRhhXAnK8FYBn85vmUxktDsSYV6
+LB2/gbHX4dvX3sQogFjB/ZkrDVpqOeeGUEnZoTknugmmKA0g2/v/hQ6rs18CVmY0
+2GHs+pWx5Ce4nD6OSBm98cY7Fwe76wzlkiKjabbGkQUo0LYbF/DVA/AAv6nkhCu2
+C9Cd7W7sAWFM90DeSZN55mYvliwR2/Rs+l67qFDeQqdD2ZmIi0I6VPmTadjW9n1T
+Wfxbq0h4LtvFWTd3xXVu7EOf5qAS1j//CivsjFqSegI+detnTi9PuNcvcPrvnMR7
+hGbDlxYsYLmxXJY4qUwzUX3hzWZbMrlrm8GH4hzAhYAK5LXRUZ5rQwJ4w6kzpPBD
+SsQn4FkqGc7XuQGNBGVE5lIBDADrRDJ2Mv9M1dw1oCsoXRL5zP/ZBuc0mxnwmLy8
+/6ltsR1lmuuAZtZCX6C/gBaaFKUBjZTjY1aiJZU2D3a+gr8TRL7AU/WiVwk4a8MG
+Wi/rn3LXiJ/07iOac619xCFscVqfThHVzVz0IhyLn2yYGJxyBW3dmfyOb4NrlgCK
+ix+OyWUGN36v9LBI8xKsu4S5cl5tTpVjgek1B3JuedMoVWYQjshPPOEMb0fptZzo
+TqDIg0uz/XJtiacKUuEMvXXB2OdRO2KT2+gmigVMKVs38Qu8S5PXoSemGkmGB+KG
+QCSfhinDhlqhIh8TDoNRD/An3p4ZmQjQ4IbV9fmvXk7souxnklq/3mfQB+Wm8QrQ
++0q7mB3is6yocl47bul+z5mjFu1IAMeBhQV5BdNR3ChdhWGm+LP1bm9jwpIN2qiQ
+AZFhwRSuLzVxSPtPbXdN5Gh7Zt6cA4f8auqDy7ZvCwnqF13Ui7ztaYjai9NN3l+6
+fJCIfELl//ocuppPOlqjivCPsvUAEQEAAYkD8gQYAQoAJhYhBB5FOyzoe+4vff6Z
+Zh40oYKOIHkBBQJlROZSAhsCBQkFo5qAAcAJEB40oYKOIHkBwPQgBBkBCgAdFiEE
+pAz4fnbrax/7JfpTg2ArqfTmfSUFAmVE5lIACgkQg2ArqfTmfSU+UQwAy0dFFVN9
+Tpl5qaxT0Cyu1Y1lcVLHV5ZvqGJl55wkCZeaHMpoNPDH0RZPsvlMWax4bG6IPpXs
+OSHTdjDWJjQFy5ULw9KRSizxqG8OZ6XCoePqEmjW7ioPT9AQC4MucsejBx9IVlEH
++LrcBWasw4ZVh9rtaQnTVHtbIeeYstamb5WV7CxaPMAZcPKSLW6ZHj62/MS62TuX
+xgNA08yDKFSZ7bB5M2DAOp3j4wj0/1m+U1I44itzgkWaXA8nGtctpUMDx/6Uvfqt
+SXIZb238xkDmCljyXe4wDrSQr1yQ5yAV8R5W6AcYI1DfRMu/TzAC1yI72xQIX3A6
+aJXbN1hm8kjtUUu+LR+HhVAencZrUgmtcUBIIYKfv3DUzHQ10Gu9KBk0rQugxLIW
+6U+rWhy/aJFRycn71rnwBVw8jLT6oTE2JTXt7hvpg87Z6Y9Hyg73eduVFGYsrhAD
+RndrueFfMJbcSER+IOrxFTK6JbpqBZRqN2lZO6qS/7hI7YqpinBAG010IZgQAIli
+KCjcLP/4qcUJW49VEioUogUufI8pVL0Asmw6s2/KC2J1StleQA9/JKxFkL0MdoSp
+gRCDCzlb1RRCt/q70gkcYMt1AKkaeR9ebJsIoDY8ExgDFIL+oJ/QQjv1mnuUbMWH
+g6Pf1fMzl2r8y/abpLAiahAT3KYR5grOGxzrHPoimkFiJhI9Z94b+Xw77OkHQdIG
+QjlecshPG84nPyFMjGchobAPeDxdjticHH/FCoiCQk7UDy62EYYMxjZ1derc4AYN
+B6umvyZVYkqTVwbSZMyCAt227KDFK9gs1kImefUqfDJowGzOHUpCAqviXV2bER/r
+c3Xa4C+99XK0ppw4pCnf6+YnapfgoVk00/1/U948v8eXaaO4Sjwl3+ooUjqw5vWT
+jaMbgeWBiRs4mirnbhXqF+M0ODCgF8GXdPnWinc++j0JhZxHyNsllblKaLubca4u
+93oducUiidsN2paV2sI1uLRIv5l/v0GX33q7ydctq0cC07MURk6/KH8nW1eaH378
+BlYVQCtuJPj7huM0WFgkJ062iqd/01RtLgHSp8TyEkHGLZpnnJAhP8stHCMtIcwS
+kdwc/mtKQfTNIVIe1hj1Pt99ivOHIa4ofLUieJbh2FTT7AeC/yVGtxrlgpOqmyHX
+ruhVNojbqQtgGEL7eBpnuGl4WxIF6KTaMSOtLyE3
+=42o2
+-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadService.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadService.java
index 46c0457b..9fd3dfb3 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadService.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadService.java
@@ -60,6 +60,12 @@ public class DownloadService extends JobIntentService implements UpdateDownloadM
updateDownloadManager.handleIntent(intent);
}
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ updateDownloadManager.onDestroy();
+ }
+
/**
* Convenience method for enqueuing work in to this service.
*/
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java
index 92291a43..b0e6b392 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java
@@ -75,8 +75,16 @@ public class InstallActivity extends Activity {
if (resultCode == RESULT_OK) {
installUpdate();
} else {
- Toast.makeText(this, getString(R.string.version_update_error_permissions), Toast.LENGTH_LONG).show();
- finish();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ if (this.getPackageManager().canRequestPackageInstalls()) {
+ installUpdate();
+ } else {
+ Toast.makeText(this, getString(R.string.version_update_error_permissions), Toast.LENGTH_LONG).show();
+ finish();
+ }
+ } else {
+ finish();
+ }
}
}
}
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/UpdateDownloadManager.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/UpdateDownloadManager.java
index 109164c5..5907b8fa 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/UpdateDownloadManager.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/UpdateDownloadManager.java
@@ -16,21 +16,6 @@
*/
package se.leap.bitmaskclient.appUpdate;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.ResultReceiver;
-import android.util.Log;
-
-import java.io.File;
-
-import okhttp3.OkHttpClient;
-import pgpverify.Logger;
-import pgpverify.PgpVerifier;
-import se.leap.bitmaskclient.BuildConfig;
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator;
-
import static android.text.TextUtils.isEmpty;
import static se.leap.bitmaskclient.appUpdate.DownloadService.DOWNLOAD_FAILED;
import static se.leap.bitmaskclient.appUpdate.DownloadService.DOWNLOAD_PROGRESS;
@@ -52,6 +37,22 @@ import static se.leap.bitmaskclient.providersetup.ProviderAPI.DELAY;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.PARAMETERS;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.RECEIVER_KEY;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.ResultReceiver;
+import android.util.Log;
+
+import java.io.File;
+
+import de.blinkt.openvpn.core.VpnStatus;
+import okhttp3.OkHttpClient;
+import pgpverify.Logger;
+import pgpverify.PgpVerifier;
+import se.leap.bitmaskclient.BuildConfig;
+import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator;
+
public class UpdateDownloadManager implements Logger, DownloadConnector.DownloadProgress {
@@ -63,7 +64,7 @@ public class UpdateDownloadManager implements Logger, DownloadConnector.Download
private Context context;
- private PgpVerifier pgpVerifier;
+ private final PgpVerifier pgpVerifier;
private DownloadServiceCallback serviceCallback;
OkHttpClientGenerator clientGenerator;
@@ -76,10 +77,17 @@ public class UpdateDownloadManager implements Logger, DownloadConnector.Download
serviceCallback = callback;
}
+ public void onDestroy() {
+ serviceCallback = null;
+ context = null;
+ }
+
//pgpverify Logger interface
@Override
public void log(String s) {
-
+ if (BuildConfig.DEBUG_MODE) {
+ VpnStatus.logInfo("[PGP VERIFY] " + s);
+ }
}
@Override
@@ -106,23 +114,26 @@ public class UpdateDownloadManager implements Logger, DownloadConnector.Download
}
Bundle result = new Bundle();
+ if (action == null) {
+ return;
+ }
switch (action) {
- case CHECK_VERSION_FILE:
+ case CHECK_VERSION_FILE -> {
result = checkVersionFile(result);
if (result.getBoolean(BROADCAST_RESULT_KEY)) {
sendToReceiverOrBroadcast(receiver, UPDATE_FOUND, result);
} else {
sendToReceiverOrBroadcast(receiver, UPDATE_NOT_FOUND, result);
}
- break;
- case DOWNLOAD_UPDATE:
+ }
+ case DOWNLOAD_UPDATE -> {
result = downloadUpdate(result);
if (result.getBoolean(BROADCAST_RESULT_KEY)) {
sendToReceiverOrBroadcast(receiver, UPDATE_DOWNLOADED, result);
} else {
sendToReceiverOrBroadcast(receiver, UPDATE_DOWNLOAD_FAILED, result);
}
- break;
+ }
}
}
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 ff27a5a2..6a5b016e 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
@@ -5,8 +5,6 @@
package de.blinkt.openvpn.core;
-import static de.blinkt.openvpn.core.connection.Connection.TransportType.PT;
-
import android.os.Build;
import android.text.TextUtils;
@@ -27,9 +25,8 @@ import java.util.Vector;
import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.core.connection.Connection;
import de.blinkt.openvpn.core.connection.Obfs4Connection;
-import de.blinkt.openvpn.core.connection.Obfs4HopConnection;
import de.blinkt.openvpn.core.connection.OpenvpnConnection;
-import se.leap.bitmaskclient.pluggableTransports.Obfs4Options;
+import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
//! Openvpn Config FIle Parser, probably not 100% accurate but close enough
@@ -808,12 +805,10 @@ public class ConfigParser {
}
else {
switch (transportType) {
+ case OBFS4_HOP:
case OBFS4:
conn = new Obfs4Connection(obfs4Options);
break;
- case OBFS4_HOP:
- conn = new Obfs4HopConnection(obfs4Options);
- break;
case OPENVPN:
conn = new OpenvpnConnection();
break;
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 506b04a6..c8ac965f 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -10,7 +10,6 @@ import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED;
import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
import static de.blinkt.openvpn.core.NetworkSpace.IpAddress;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE;
-import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
import android.Manifest.permission;
import android.app.Notification;
@@ -53,9 +52,7 @@ import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.eip.EipStatus;
import se.leap.bitmaskclient.eip.VpnNotificationManager;
import se.leap.bitmaskclient.firewall.FirewallManager;
-import se.leap.bitmaskclient.pluggableTransports.PtClientBuilder;
-import se.leap.bitmaskclient.pluggableTransports.PtClientInterface;
-import se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient;
+import se.leap.bitmaskclient.pluggableTransports.ObfsvpnClient;
public class OpenVPNService extends VpnService implements StateListener, Callback, ByteCountListener, IOpenVPNServiceInternal, VpnNotificationManager.VpnServiceCallback {
@@ -91,8 +88,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private Toast mlastToast;
private Runnable mOpenVPNThread;
private VpnNotificationManager notificationManager;
- private ShapeshifterClient shapeshifter;
- private PtClientInterface obfsVpnClient;
+ private ObfsvpnClient obfsVpnClient;
private FirewallManager firewallManager;
private final IBinder mBinder = new IOpenVPNServiceInternal.Stub() {
@@ -187,7 +183,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mProcessThread = null;
}
VpnStatus.removeByteCountListener(this);
- unregisterDeviceStateReceiver();
+ unregisterDeviceStateReceiver(mDeviceStateReceiver);
+ mDeviceStateReceiver = null;
mOpenVPNThread = null;
if (!mStarting) {
stopForeground(!mNotificationAlwaysVisible);
@@ -200,35 +197,31 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
firewallManager.stop();
}
- synchronized void registerDeviceStateReceiver(OpenVPNManagement magnagement) {
+ synchronized void registerDeviceStateReceiver(DeviceStateReceiver newDeviceStateReceiver) {
// Registers BroadcastReceiver to track network connection changes.
IntentFilter filter = new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
- mDeviceStateReceiver = new DeviceStateReceiver(magnagement);
// Fetch initial network state
- mDeviceStateReceiver.networkStateChange(this);
-
- registerReceiver(mDeviceStateReceiver, filter);
- VpnStatus.addByteCountListener(mDeviceStateReceiver);
+ newDeviceStateReceiver.networkStateChange(this);
+ registerReceiver(newDeviceStateReceiver, filter);
+ VpnStatus.addByteCountListener(newDeviceStateReceiver);
}
- synchronized void unregisterDeviceStateReceiver() {
+ synchronized void unregisterDeviceStateReceiver(DeviceStateReceiver deviceStateReceiver) {
if (mDeviceStateReceiver != null)
try {
- VpnStatus.removeByteCountListener(mDeviceStateReceiver);
- this.unregisterReceiver(mDeviceStateReceiver);
+ VpnStatus.removeByteCountListener(deviceStateReceiver);
+ this.unregisterReceiver(deviceStateReceiver);
} catch (IllegalArgumentException iae) {
// I don't know why this happens:
// java.lang.IllegalArgumentException: Receiver not registered: de.blinkt.openvpn.NetworkSateReceiver@41a61a10
// Ignore for now ...
iae.printStackTrace();
}
- mDeviceStateReceiver = null;
-
}
@Override
@@ -242,10 +235,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if(isVpnRunning()) {
if (getManagement() != null && getManagement().stopVPN(replaceConnection)) {
if (!replaceConnection) {
- if (shapeshifter != null) {
- shapeshifter.stop();
- shapeshifter = null;
- } else if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
+ if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
obfsVpnClient.stop();
obfsVpnClient = null;
}
@@ -419,21 +409,15 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mStarting = false;
Connection.TransportType transportType = connection.getTransportType();
if (mProfile.usePluggableTransports() && transportType.isPluggableTransport()) {
- if (useObfsVpn()) {
- if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
- obfsVpnClient.stop();
- }
- obfsVpnClient = PtClientBuilder.getPtClient(connection);
- int runningSocksPort = obfsVpnClient.start();
- if (connection.getTransportType() == Connection.TransportType.OBFS4) {
- connection.setProxyPort(String.valueOf(runningSocksPort));
- }
- } else if (shapeshifter == null) {
- shapeshifter = new ShapeshifterClient(((Obfs4Connection) connection).getObfs4Options());
- shapeshifter.start();
+ if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
+ obfsVpnClient.stop();
}
+ obfsVpnClient = new ObfsvpnClient(((Obfs4Connection) connection).getObfs4Options());
+ obfsVpnClient.start();
+ Log.d(TAG, "obfsvpn client started");
}
+
// Start a new session by creating a new thread.
boolean useOpenVPN3 = VpnProfile.doUseOpenVPN3(this);
@@ -469,14 +453,16 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mProcessThread.start();
}
- new Handler(getMainLooper()).post(() -> {
- if (mDeviceStateReceiver != null) {
- unregisterDeviceStateReceiver();
- }
- registerDeviceStateReceiver(mManagement);
- }
+ final DeviceStateReceiver oldDeviceStateReceiver = mDeviceStateReceiver;
+ final DeviceStateReceiver newDeviceStateReceiver = new DeviceStateReceiver(mManagement);
- );
+ guiHandler.post(() -> {
+ if (oldDeviceStateReceiver != null)
+ unregisterDeviceStateReceiver(oldDeviceStateReceiver);
+
+ registerDeviceStateReceiver(newDeviceStateReceiver);
+ mDeviceStateReceiver = newDeviceStateReceiver;
+ });
}
private void stopOldOpenVPNProcess() {
@@ -485,12 +471,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if (mOpenVPNThread != null)
((OpenVPNThread) mOpenVPNThread).setReplaceConnection();
if (mManagement.stopVPN(true)) {
- // an old was asked to exit, wait 1s
- if (shapeshifter != null) {
- Log.d(TAG, "-> stop shapeshifter");
- shapeshifter.stop();
- shapeshifter = null;
- } else if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
+ if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
Log.d(TAG, "-> stop obfsvpnClient");
obfsVpnClient.stop();
obfsVpnClient = null;
@@ -538,6 +519,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
@Override
public void onCreate() {
super.onCreate();
+ guiHandler = new Handler(getMainLooper());
notificationManager = new VpnNotificationManager(this);
firewallManager = new FirewallManager(this, true);
}
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 ecc03a19..73616ba4 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
@@ -223,7 +223,7 @@ public class VpnStatus {
public enum ErrorType {
UNKNOWN,
- SHAPESHIFTER
+ OBFSVPN
}
// keytool -printcert -jarfile de.blinkt.openvpn_85.apk
diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
index 19ea180d..0fe6bff2 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
@@ -1,12 +1,7 @@
package de.blinkt.openvpn.core.connection;
-import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
-import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_IP;
-import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_PORT;
-
-import se.leap.bitmaskclient.pluggableTransports.HoppingObfsVpnClient;
-import se.leap.bitmaskclient.pluggableTransports.Obfs4Options;
-import se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient;
+import se.leap.bitmaskclient.pluggableTransports.ObfsvpnClient;
+import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
/**
@@ -19,33 +14,12 @@ public class Obfs4Connection extends Connection {
private Obfs4Options options;
public Obfs4Connection(Obfs4Options options) {
- if (useObfsVpn()) {
- setServerName(options.gatewayIP);
- setServerPort(options.transport.getPorts()[0]);
- setProxyName(ObfsVpnClient.SOCKS_IP);
- setProxyType(ProxyType.SOCKS5);
- switch (options.transport.getTransportType()) {
- case OBFS4:
- setUseUdp(false);
- setProxyPort(String.valueOf(ObfsVpnClient.SOCKS_PORT.get()));
- break;
- case OBFS4_HOP:
- setUseUdp(true);
- setProxyPort(String.valueOf(HoppingObfsVpnClient.PORT));
- break;
- default:break;
- }
- } else {
- setServerName(DISPATCHER_IP);
- setServerPort(DISPATCHER_PORT);
- setProxyName("");
- setProxyPort("");
- setProxyType(ProxyType.NONE);
-
- // while udp/kcp might be used on the wire,
- // we don't use udp for openvpn in case of a obfs4 connection
- setUseUdp(false);
- }
+ setServerName(ObfsvpnClient.IP);
+ setServerPort(String.valueOf(ObfsvpnClient.PORT));
+ setUseUdp(true);
+ setProxyType(ProxyType.NONE);
+ setProxyName("");
+ setProxyPort("");
setProxyAuthUser(null);
setProxyAuthPassword(null);
setUseProxyAuth(false);
@@ -61,7 +35,7 @@ public class Obfs4Connection extends Connection {
@Override
public TransportType getTransportType() {
- return TransportType.OBFS4;
+ return options.transport.getTransportType();
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java
deleted file mode 100644
index f983ae20..00000000
--- a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package de.blinkt.openvpn.core.connection;
-
-import se.leap.bitmaskclient.pluggableTransports.HoppingObfsVpnClient;
-import se.leap.bitmaskclient.pluggableTransports.Obfs4Options;
-
-
-/**
- * Created by cyberta on 08.03.19.
- */
-
-public class Obfs4HopConnection extends Connection {
-
- private static final String TAG = Obfs4HopConnection.class.getName();
- private Obfs4Options options;
-
- public Obfs4HopConnection(Obfs4Options options) {
- setServerName(HoppingObfsVpnClient.IP);
- setServerPort(String.valueOf(HoppingObfsVpnClient.PORT));
- setProxyName("");
- setProxyPort("");
- setProxyType(ProxyType.NONE);
-
-
- setUseUdp(true);
- setProxyAuthUser(null);
- setProxyAuthPassword(null);
- setUseProxyAuth(false);
- this.options = options;
- }
-
- @Override
- public Connection clone() throws CloneNotSupportedException {
- Obfs4HopConnection connection = (Obfs4HopConnection) super.clone();
- connection.options = this.options;
- return connection;
- }
-
- @Override
- public TransportType getTransportType() {
- return TransportType.OBFS4_HOP;
- }
-
-
- public Obfs4Options getObfs4Options() {
- return options;
- }
-
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java
index 21fc81e4..5363f16e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java
@@ -51,6 +51,7 @@ import se.leap.bitmaskclient.base.models.ProviderObservable;
import se.leap.bitmaskclient.base.utils.DateHelper;
import se.leap.bitmaskclient.base.utils.PreferenceHelper;
import se.leap.bitmaskclient.eip.EipCommand;
+import se.leap.bitmaskclient.providersetup.ProviderSetupObservable;
import se.leap.bitmaskclient.providersetup.activities.SetupActivity;
/**
@@ -178,9 +179,10 @@ public class StartActivity extends Activity{
if ((hasNewFeature(FeatureVersionCode.CALYX_PROVIDER_LILYPAD_UPDATE) && (
getPackageName().equals("org.calyxinstitute.vpn") ||
ProviderObservable.getInstance().getCurrentProvider().getDomain().equals("calyx.net"))) ||
- hasNewFeature(FeatureVersionCode.RISEUP_PROVIDER_LILYPAD_UPDATE) && (
+ (hasNewFeature(FeatureVersionCode.RISEUP_PROVIDER_LILYPAD_UPDATE) || hasNewFeature(FeatureVersionCode.RISEUP_PROVIDER_LILYPAD_UPDATE_v2)
+ && (
getPackageName().equals("se.leap.riseupvpn") ||
- ProviderObservable.getInstance().getCurrentProvider().getDomain().equals("riseup.net"))) {
+ ProviderObservable.getInstance().getCurrentProvider().getDomain().equals("riseup.net")))) {
// deletion of current configured provider so that a new provider setup is triggered
Provider provider = ProviderObservable.getInstance().getCurrentProvider();
if (provider != null && !provider.isDefault()) {
@@ -267,6 +269,7 @@ public class StartActivity extends Activity{
}
private void showNextActivity(Provider provider) {
+ ProviderSetupObservable.cancel();
if (provider.shouldShowMotdSeen()) {
try {
IMessages messages = Motd.newMessages(provider.getMotdJsonString());
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
index d7b62de2..51bce6d4 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
@@ -8,7 +8,6 @@ import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP;
import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES;
import static se.leap.bitmaskclient.base.models.Constants.USE_IPv6_FIREWALL;
import static se.leap.bitmaskclient.base.models.Constants.USE_OBFUSCATION_PINNING;
-import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
import static se.leap.bitmaskclient.base.utils.ConfigHelper.isCalyxOSWithTetheringSupport;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.allowExperimentalTransports;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getExcludedApps;
@@ -225,7 +224,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh
private void initGatewayPinningEntry(View rootView) {
IconTextEntry gatewayPinning = rootView.findViewById(R.id.gateway_pinning);
- if (!BuildConfig.BUILD_TYPE.equals("debug")) {
+ if (!BuildConfig.DEBUG_MODE) {
gatewayPinning.setVisibility(GONE);
return;
}
@@ -261,7 +260,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh
public void initObfuscationPinningEntry(View rootView) {
IconSwitchEntry obfuscationPinning = rootView.findViewById(R.id.obfuscation_proxy_pinning);
- if (!BuildConfig.BUILD_TYPE.equals("debug") || !useObfsVpn()) {
+ if (!BuildConfig.DEBUG_MODE) {
obfuscationPinning.setVisibility(GONE);
return;
}
@@ -302,7 +301,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh
public void initExperimentalTransportsEntry(View rootView) {
IconSwitchEntry experimentalTransports = rootView.findViewById(R.id.experimental_transports);
- if (useObfsVpn() && ProviderObservable.getInstance().getCurrentProvider().supportsExperimentalPluggableTransports()) {
+ if (ProviderObservable.getInstance().getCurrentProvider().supportsExperimentalPluggableTransports()) {
experimentalTransports.setVisibility(VISIBLE);
experimentalTransports.setChecked(allowExperimentalTransports());
experimentalTransports.setOnCheckedChangeListener((buttonView, isChecked) -> {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java b/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java
index 8b78c966..1771f0b0 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java
@@ -5,6 +5,7 @@ public interface FeatureVersionCode {
int GEOIP_SERVICE = 148;
int CALYX_PROVIDER_LILYPAD_UPDATE = 165000;
int RISEUP_PROVIDER_LILYPAD_UPDATE = 165000;
+ int RISEUP_PROVIDER_LILYPAD_UPDATE_v2 = 172000;
int ENCRYPTED_SHARED_PREFS = 170000;
int NOTIFICATION_PREMISSION_API_UPDATE = 170000;
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
index cb9bd520..64e57cda 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
@@ -28,7 +28,6 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOWED_REGIS
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOW_ANONYMOUS;
import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT;
import static se.leap.bitmaskclient.base.models.Constants.TYPE;
-import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
import static se.leap.bitmaskclient.base.utils.RSAHelper.parseRsaKeyFromString;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS;
@@ -190,10 +189,7 @@ public final class Provider implements Parcelable {
}
public boolean supportsPluggableTransports() {
- if (useObfsVpn()) {
- return supportsTransports(new Pair[]{new Pair<>(OBFS4, TCP), new Pair<>(OBFS4, KCP), new Pair<>(OBFS4_HOP, TCP), new Pair<>(OBFS4_HOP, KCP)});
- }
- return supportsTransports(new Pair[]{new Pair<>(OBFS4, TCP)});
+ return supportsTransports(new Pair[]{new Pair<>(OBFS4, TCP), new Pair<>(OBFS4, KCP), new Pair<>(OBFS4_HOP, TCP), new Pair<>(OBFS4_HOP, KCP)});
}
public boolean supportsExperimentalPluggableTransports() {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java
index 33fbbf7a..c2590012 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java
@@ -14,18 +14,18 @@ import java.io.Serializable;
import de.blinkt.openvpn.core.connection.Connection;
public class Transport implements Serializable {
- private String type;
- private String[] protocols;
+ private final String type;
+ private final String[] protocols;
@Nullable
- private String[] ports;
+ private final String[] ports;
@Nullable
- private Options options;
+ private final Options options;
public Transport(String type, String[] protocols, String[] ports, String cert) {
this(type, protocols, ports, new Options(cert, "0"));
}
- public Transport(String type, String[] protocols, String[] ports, Options options) {
+ public Transport(String type, String[] protocols, @Nullable String[] ports, @Nullable Options options) {
this.type = type;
this.protocols = protocols;
this.ports = ports;
@@ -69,9 +69,9 @@ public class Transport implements Serializable {
public static class Options implements Serializable {
@Nullable
- private String cert;
+ private final String cert;
@SerializedName("iatMode")
- private String iatMode;
+ private final String iatMode;
@Nullable
private Endpoint[] endpoints;
@@ -136,8 +136,8 @@ public class Transport implements Serializable {
public static class Endpoint implements Serializable {
- private String ip;
- private String cert;
+ private final String ip;
+ private final String cert;
public Endpoint(String ip, String cert) {
this.ip = ip;
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java
index e1f65b5e..22af1bfb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java
@@ -11,7 +11,6 @@ import se.leap.bitmaskclient.BuildConfig;
public class BuildConfigHelper {
public interface BuildConfigHelperInterface {
- boolean useObfsVpn();
boolean hasObfuscationPinningDefaults();
String obfsvpnIP();
String obfsvpnPort();
@@ -21,10 +20,6 @@ public class BuildConfigHelper {
}
public static class DefaultBuildConfigHelper implements BuildConfigHelperInterface {
- @Override
- public boolean useObfsVpn() {
- return BuildConfig.use_obfsvpn;
- }
@Override
public boolean hasObfuscationPinningDefaults() {
@@ -72,10 +67,6 @@ public class BuildConfigHelper {
instance = helperInterface;
}
- public static boolean useObfsVpn() {
- return instance.useObfsVpn();
- }
-
public static boolean hasObfuscationPinningDefaults() {
return instance.hasObfuscationPinningDefaults();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java
index f1d86876..9d29911b 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java
@@ -70,7 +70,7 @@ public class FileHelper {
}
reader.close();
return sb.toString();
- } catch (IOException errabi) {
+ } catch (NullPointerException | IOException errabi) {
return null;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java
index eee3bfb2..8d1f21e5 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java
@@ -513,8 +513,7 @@ public class PreferenceHelper {
}
public static boolean useObfuscationPinning() {
- return BuildConfigHelper.useObfsVpn() &&
- getUseBridges() &&
+ return getUseBridges() &&
getBoolean(USE_OBFUSCATION_PINNING, false) &&
!TextUtils.isEmpty(getObfuscationPinningIP()) &&
!TextUtils.isEmpty(getObfuscationPinningCert()) &&
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java
index ed95b75c..bd626ce5 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java
@@ -81,7 +81,6 @@ import se.leap.bitmaskclient.base.utils.PreferenceHelper;
import se.leap.bitmaskclient.providersetup.ProviderAPI;
import se.leap.bitmaskclient.providersetup.ProviderAPICommand;
import se.leap.bitmaskclient.providersetup.ProviderSetupObservable;
-import se.leap.bitmaskclient.providersetup.activities.SetupActivity;
import se.leap.bitmaskclient.tor.TorServiceCommand;
import se.leap.bitmaskclient.tor.TorStatusObservable;
@@ -245,10 +244,8 @@ public class EipSetupObserver extends BroadcastReceiver implements VpnStatus.Sta
Log.d(TAG, "PROVIDER OK - FETCH SUCCESSFUL");
//no break, continue with next case
case CORRECTLY_DOWNLOADED_VPN_CERTIFICATE:
- if (ProviderSetupObservable.getProgress() > 0 && !activityForeground.get()) {
- Intent activityIntent = new Intent(appContext, SetupActivity.class);
- activityIntent.setAction(Intent.ACTION_MAIN);
- appContext.startActivity(activityIntent);
+ if (ProviderSetupObservable.isSetupRunning() && !activityForeground.get()) {
+ ProviderSetupObservable.storeLastResult(resultCode, resultData);
}
break;
case TOR_TIMEOUT:
@@ -270,6 +267,8 @@ public class EipSetupObserver extends BroadcastReceiver implements VpnStatus.Sta
for (EipSetupListener listener : listeners) {
listener.handleProviderApiEvent(intent);
}
+
+
}
private void maybeStartEipService(Bundle resultData) {
@@ -451,22 +450,6 @@ public class EipSetupObserver extends BroadcastReceiver implements VpnStatus.Sta
if (BuildConfig.DEBUG) {
Log.e("ERROR", logItem.getString(appContext));
}
- switch (logItem.getErrorType()) {
- case SHAPESHIFTER:
- VpnProfile profile = VpnStatus.getLastConnectedVpnProfile();
- if (profile == null) {
- EipCommand.startVPN(appContext, false, 0);
- } else {
- GatewaysManager gatewaysManager = new GatewaysManager(appContext);
- int position = gatewaysManager.getPosition(profile);
- setupNClosestGateway.set(position >= 0 ? position : 0);
- selectNextGateway();
- }
- break;
- default:
- break;
-
- }
}
}
}
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 4c8fa797..8cbc4289 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
@@ -30,9 +30,6 @@ import static se.leap.bitmaskclient.base.models.Constants.REMOTE;
import static se.leap.bitmaskclient.base.models.Constants.TCP;
import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT;
import static se.leap.bitmaskclient.base.models.Constants.UDP;
-import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
-import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_IP;
-import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_PORT;
import androidx.annotation.VisibleForTesting;
@@ -52,11 +49,12 @@ import de.blinkt.openvpn.core.ConfigParser;
import de.blinkt.openvpn.core.VpnStatus;
import de.blinkt.openvpn.core.connection.Connection;
import de.blinkt.openvpn.core.connection.Connection.TransportType;
+import de.blinkt.openvpn.core.connection.Obfs4Connection;
import se.leap.bitmaskclient.base.models.Provider;
import se.leap.bitmaskclient.base.models.Transport;
import se.leap.bitmaskclient.base.utils.ConfigHelper;
-import se.leap.bitmaskclient.pluggableTransports.HoppingObfsVpnClient;
-import se.leap.bitmaskclient.pluggableTransports.Obfs4Options;
+import se.leap.bitmaskclient.pluggableTransports.ObfsvpnClient;
+import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
public class VpnConfigGenerator {
private final JSONObject generalConfiguration;
@@ -384,28 +382,12 @@ public class VpnConfigGenerator {
}
stringBuilder.append(getRouteString(ipAddress, transport));
- stringBuilder.append(getRemoteString(ipAddress, transport));
- stringBuilder.append(getExtraOptions(transport));
- }
-
- public String getRemoteString(String ipAddress, Transport transport) {
- if (useObfsVpn()) {
- if (useObfuscationPinning) {
- return REMOTE + " " + obfuscationPinningIP + " " + obfuscationPinningPort + " tcp" + newLine;
- }
- switch (transport.getTransportType()) {
- case OBFS4:
- return REMOTE + " " + ipAddress + " " + transport.getPorts()[0] + " tcp" + newLine;
- case OBFS4_HOP:
- return REMOTE + " " + HoppingObfsVpnClient.IP + " " + HoppingObfsVpnClient.PORT + " udp" + newLine;
- default:
- VpnStatus.logError("Unexpected pluggable transport type " + transport.getType() + " for gateway " + ipAddress);
- return "";
- }
- }
- return REMOTE + " " + DISPATCHER_IP + " " + DISPATCHER_PORT + " tcp" + newLine;
+ String transparentProxyRemote = REMOTE + " " + ObfsvpnClient.IP + " " + ObfsvpnClient.PORT + " udp" + newLine;
+ stringBuilder.append(transparentProxyRemote);
}
+ // TODO: figure out if any of these configs still make sense (
+ @Deprecated
public String getExtraOptions(Transport transport) {
if (transport.getTransportType() == OBFS4_HOP) {
return "replay-window 65535" + newLine +
@@ -437,7 +419,7 @@ public class VpnConfigGenerator {
return "";
}
- // While openvpn in TCP mode is required for obfs4, openvpn in UDP mode is required for obfs4-hop
+ // With obfsvpn 1.0.0 openvpn is always required to run in UDP to work with any obfs4 based pluggable transport.
private boolean openvpnModeSupportsPt(Transport transport, String ipAddress) {
if (useObfuscationPinning) {
// we don't know if the manually pinned bridge points to a openvpn gateway with the right
@@ -457,14 +439,14 @@ public class VpnConfigGenerator {
return false;
}
- String requiredProtocol = transport.getTransportType() == OBFS4_HOP ? UDP : TCP;
+ String requiredProtocol = UDP;
for (String protocol : protocols) {
if (protocol.equals(requiredProtocol)) {
return true;
}
}
- VpnStatus.logError("Misconfigured provider: " + transport.getTransportType().toString() + " currently only allows openvpn in " + requiredProtocol + " mode! Skipping config for ip " + ipAddress);
+ VpnStatus.logError("Provider - client incompatibility: obfuscation protocol " + transport.getTransportType().toString() + " currently only allows OpenVPN in " + requiredProtocol + " mode! Skipping config for ip " + ipAddress);
return false;
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java
deleted file mode 100644
index 751208ba..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package se.leap.bitmaskclient.pluggableTransports;
-
-import client.Client;
-import client.HopClient;
-import de.blinkt.openvpn.core.VpnStatus;
-import se.leap.bitmaskclient.base.models.Constants;
-
-public class HoppingObfsVpnClient implements PtClientInterface {
-
- public static final int PORT = 8080;
- public static final String IP = "127.0.0.1";
-
- public final HopClient client;
-
- public HoppingObfsVpnClient(Obfs4Options options) throws IllegalStateException {
-
- //FIXME: use a different strategy here
- //Basically we would want to track if the more performant transport protocol (KCP?/TCP?) usage was successful
- //if so, we stick to it, otherwise we flip the flag
- boolean kcp = Constants.KCP.equals(options.transport.getProtocols()[0]);
-
- HoppingConfig hoppingConfig = new HoppingConfig(kcp,IP+":"+PORT, options, 10, 10);
- try {
- client = Client.newFFIHopClient(hoppingConfig.toString());
- } catch (Exception e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public int start() {
- try {
- client.setEventLogger(this);
- return client.start() ? PORT : 0;
- } catch (Exception e) {
- e.printStackTrace();
- return 0;
- }
- }
-
- @Override
- public void stop() {
- try {
- client.stop();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- client.setEventLogger(null);
- }
- }
-
- @Override
- public boolean isStarted() {
- return client.isStarted();
- }
-
- @Override
- public void error(String s) {
- VpnStatus.logError("[hopping-obfs4] " + s);
- }
-
- @Override
- public void log(String state, String message) {
- VpnStatus.logDebug("[hopping-obfs4] " + state + ": " + message);
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java
deleted file mode 100644
index 685349ed..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package se.leap.bitmaskclient.pluggableTransports;
-
-import static se.leap.bitmaskclient.base.models.Constants.KCP;
-
-import android.util.Log;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.Observable;
-import java.util.Observer;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import client.Client;
-import de.blinkt.openvpn.core.ConnectionStatus;
-import de.blinkt.openvpn.core.VpnStatus;
-import se.leap.bitmaskclient.eip.EipStatus;
-
-public class ObfsVpnClient implements PropertyChangeListener, PtClientInterface {
-
- public static final AtomicInteger SOCKS_PORT = new AtomicInteger(4430);
- public static final String SOCKS_IP = "127.0.0.1";
- private static final String ERR_BIND = "bind: address already in use";
-
- private static final String TAG = ObfsVpnClient.class.getSimpleName();
- private volatile boolean noNetwork;
- private final AtomicBoolean pendingNetworkErrorHandling = new AtomicBoolean(false);
- private final AtomicInteger reconnectRetry = new AtomicInteger(0);
- private static final int MAX_RETRY = 5;
-
- private final client.Client_ obfsVpnClient;
- private final Object LOCK = new Object();
-
- public ObfsVpnClient(Obfs4Options options) throws IllegalStateException{
- //FIXME: use a different strategy here
- //Basically we would want to track if the more performant transport protocol (KCP?/TCP?) usage was successful
- //if so, we stick to it, otherwise we flip the flag
- boolean kcp = KCP.equals(options.transport.getProtocols()[0]);
-
- if (options.transport.getOptions().getCert() == null) {
- throw new IllegalStateException("No cert found to establish a obfs4 connection");
- }
-
- obfsVpnClient = Client.newClient(kcp, SOCKS_IP+":"+SOCKS_PORT.get(), options.transport.getOptions().getCert());
- }
-
- /**
- * starts the client
- * @return the port ObfsVpn is running on
- */
- public int start() {
- synchronized (LOCK) {
- obfsVpnClient.setEventLogger(this);
- Log.d(TAG, "aquired LOCK");
- new Thread(this::startSync).start();
- waitUntilStarted();
- Log.d(TAG, "returning LOCK after " + (reconnectRetry.get() + 1) * 200 +" ms");
- }
- return SOCKS_PORT.get();
- }
-
- // We're waiting here until the obfsvpn client has found a unbound port and started
- private void waitUntilStarted() {
- int count = -1;
- try {
- while (count < reconnectRetry.get() && reconnectRetry.get() < MAX_RETRY) {
- Thread.sleep(200);
- count++;
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- private void startSync() {
- try {
- obfsVpnClient.start();
- } catch (Exception e) {
- Log.e(TAG, "[obfsvpn] exception: " + e.getLocalizedMessage());
- VpnStatus.logError("[obfsvpn] " + e.getLocalizedMessage());
- if (e.getLocalizedMessage() != null && e.getLocalizedMessage().contains(ERR_BIND) && reconnectRetry.get() < MAX_RETRY) {
- reconnectRetry.addAndGet(1);
- SOCKS_PORT.addAndGet(1);
- obfsVpnClient.setSocksAddr(SOCKS_IP+":"+SOCKS_PORT.get());
- Log.d(TAG, "[obfsvpn] reconnecting on different port... " + SOCKS_PORT.get());
- VpnStatus.logDebug("[obfsvpn] reconnecting on different port... " + SOCKS_PORT.get());
- startSync();
- } else if (noNetwork) {
- pendingNetworkErrorHandling.set(true);
- }
- }
- }
-
- public void stop() {
- synchronized (LOCK) {
- Log.d(TAG, "stopping obfsVpnClient...");
- try {
- obfsVpnClient.stop();
- reconnectRetry.set(0);
- SOCKS_PORT.set(4430);
- Thread.sleep(100);
- } catch (Exception e) {
- e.printStackTrace();
- VpnStatus.logError("[obfsvpn] " + e.getLocalizedMessage());
- } finally {
- obfsVpnClient.setEventLogger(null);
- }
- pendingNetworkErrorHandling.set(false);
- Log.d(TAG, "stopping obfsVpnClient releasing LOCK ...");
- }
- }
-
- public boolean isStarted() {
- return obfsVpnClient.isStarted();
- }
-
- // TODO: register observer!
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
- EipStatus status = (EipStatus) evt.getNewValue();
- if (status.getLevel() == ConnectionStatus.LEVEL_NONETWORK) {
- noNetwork = true;
- } else {
- noNetwork = false;
- if (pendingNetworkErrorHandling.getAndSet(false)) {
- stop();
- start();
- }
- }
- }
- }
-
- @Override
- public void error(String s) {
- VpnStatus.logError("[obfsvpn] " + s);
- }
-
- @Override
- public void log(String state, String message) {
- VpnStatus.logDebug("[obfsvpn] " + state + " " + message);
- }
-
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java
new file mode 100644
index 00000000..bf030a0f
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java
@@ -0,0 +1,89 @@
+package se.leap.bitmaskclient.pluggableTransports;
+
+import android.util.Log;
+
+import client.Client;
+import client.Client_;
+import client.EventLogger;
+import de.blinkt.openvpn.core.VpnStatus;
+import de.blinkt.openvpn.core.connection.Connection;
+import se.leap.bitmaskclient.base.models.Constants;
+import se.leap.bitmaskclient.pluggableTransports.models.HoppingConfig;
+import se.leap.bitmaskclient.pluggableTransports.models.KcpConfig;
+import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
+import se.leap.bitmaskclient.pluggableTransports.models.ObfsvpnConfig;
+
+public class ObfsvpnClient implements EventLogger {
+
+ public static final int PORT = 8080;
+ public static final String IP = "127.0.0.1";
+ private final Object LOCK = new Object();
+
+
+ private static final String TAG = ObfsvpnClient.class.getSimpleName();
+
+ public final Client_ client;
+
+ public ObfsvpnClient(Obfs4Options options) throws IllegalStateException {
+
+ //FIXME: use a different strategy here
+ //Basically we would want to track if the more performant transport protocol (KCP?/TCP?) usage was successful
+ //if so, we stick to it, otherwise we flip the flag
+ boolean kcpEnabled = Constants.KCP.equals(options.transport.getProtocols()[0]);
+ boolean hoppingEnabled = options.transport.getTransportType() == Connection.TransportType.OBFS4_HOP;
+ if (!hoppingEnabled && (options.transport.getPorts() == null || options.transport.getPorts().length == 0)) {
+ throw new IllegalStateException("obf4 based transport has no bridge ports configured");
+ }
+ KcpConfig kcpConfig = new KcpConfig(kcpEnabled);
+ HoppingConfig hoppingConfig = new HoppingConfig(hoppingEnabled,IP+":"+PORT, options, 10, 10);
+ ObfsvpnConfig obfsvpnConfig = new ObfsvpnConfig(IP+":"+PORT, hoppingConfig, kcpConfig, options.bridgeIP, options.transport.getPorts()[0], options.transport.getOptions().getCert() );
+ try {
+ Log.d(TAG, obfsvpnConfig.toString());
+ client = Client.newFFIClient(obfsvpnConfig.toString());
+ client.setEventLogger(this);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public int start() {
+
+ synchronized (LOCK) {
+ new Thread(() -> {
+ try {
+ client.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }).start();
+ return PORT;
+ }
+ }
+
+ public void stop() {
+ synchronized (LOCK) {
+ try {
+ client.stop();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ client.setEventLogger(null);
+ }
+ }
+ }
+
+ public boolean isStarted() {
+ return client.isStarted();
+ }
+
+ @Override
+ public void error(String s) {
+ VpnStatus.logError("[obfs4-client] " + s);
+
+ }
+
+ @Override
+ public void log(String state, String message) {
+ VpnStatus.logDebug("[obfs4-client] " + state + ": " + message);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java
deleted file mode 100644
index 945e3d7a..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package se.leap.bitmaskclient.pluggableTransports;
-
-import de.blinkt.openvpn.core.connection.Connection;
-import de.blinkt.openvpn.core.connection.Obfs4Connection;
-import de.blinkt.openvpn.core.connection.Obfs4HopConnection;
-
-public class PtClientBuilder {
- public static PtClientInterface getPtClient(Connection connection) throws IllegalStateException {
- switch (connection.getTransportType()) {
- case OBFS4:
- return new ObfsVpnClient(((Obfs4Connection) connection).getObfs4Options());
- case OBFS4_HOP:
- return new HoppingObfsVpnClient(((Obfs4HopConnection) connection).getObfs4Options());
- default:
- throw new IllegalStateException("Unexpected pluggable transport " + connection.getTransportType());
- }
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java
deleted file mode 100644
index 28d19a97..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package se.leap.bitmaskclient.pluggableTransports;
-
-import client.EventLogger;
-
-public interface PtClientInterface extends EventLogger {
- int start();
- void stop();
- boolean isStarted();
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java
deleted file mode 100644
index e57401f8..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- * Copyright (c) 2020 LEAP Encryption Access Project and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package se.leap.bitmaskclient.pluggableTransports;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-
-import de.blinkt.openvpn.core.ConnectionStatus;
-import de.blinkt.openvpn.core.VpnStatus;
-import se.leap.bitmaskclient.eip.EipStatus;
-
-public class ShapeshifterClient implements PropertyChangeListener {
-
- public static final String DISPATCHER_PORT = "4430";
- public static final String DISPATCHER_IP = "127.0.0.1";
- private static final int MAX_RETRY = 5;
- private static final int RETRY_TIME = 4000;
- private static final String TAG = ShapeshifterClient.class.getSimpleName();
-
- private final shapeshifter.Shapeshifter_ shapeShifter;
- private boolean isErrorHandling;
- private boolean noNetwork;
- private int retry = 0;
- private final Handler reconnectHandler;
-
- @Deprecated
- public class ShapeshifterLogger implements shapeshifter.Logger {
- @Override
- public void log(String s) {
- Log.e(TAG, "SHAPESHIFTER ERROR: " + s);
- VpnStatus.logError(s);
- isErrorHandling = true;
- close();
-
- if (retry < MAX_RETRY && !noNetwork) {
- retry++;
- reconnectHandler.postDelayed(ShapeshifterClient.this::reconnect, RETRY_TIME);
- } else {
- VpnStatus.logError(VpnStatus.ErrorType.SHAPESHIFTER);
- }
- }
- }
-
- public ShapeshifterClient(Obfs4Options options) {
- shapeShifter = new shapeshifter.Shapeshifter_();
- shapeShifter.setLogger(new ShapeshifterLogger());
- setup(options);
- Looper.prepare();
- reconnectHandler = new Handler();
- EipStatus.getInstance().addObserver(this);
- Log.d(TAG, "shapeshifter initialized with: \n" + shapeShifter.toString());
- }
-
- private void setup(Obfs4Options options) {
- shapeShifter.setSocksAddr(DISPATCHER_IP+":"+DISPATCHER_PORT);
- shapeShifter.setTarget(options.gatewayIP +":"+options.transport.getPorts()[0]);
- shapeShifter.setCert(options.transport.getOptions().getCert());
- }
-
- public void setOptions(Obfs4Options options) {
- setup(options);
- }
-
- public void start() {
- try {
- shapeShifter.open();
- } catch (Exception e) {
- e.printStackTrace();
- Log.e(TAG, "SHAPESHIFTER ERROR: " + e.getLocalizedMessage());
- VpnStatus.logError(VpnStatus.ErrorType.SHAPESHIFTER);
- VpnStatus.logError(e.getLocalizedMessage());
- }
- }
-
- private void close() {
- try {
- shapeShifter.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private void reconnect() {
- try {
- shapeShifter.open();
- retry = 0;
- isErrorHandling = false;
- } catch (Exception e) {
- e.printStackTrace();
- Log.e(TAG, "SHAPESHIFTER RECONNECTION ERROR: " + e.getLocalizedMessage());
- VpnStatus.logError("Unable to reconnect shapeshifter: " + e.getLocalizedMessage());
- }
- }
-
- public boolean stop() {
- try {
- shapeShifter.close();
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- VpnStatus.logError(e.getLocalizedMessage());
- }
- EipStatus.getInstance().deleteObserver(this);
- return false;
- }
-
-
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
- EipStatus status = (EipStatus) evt.getNewValue();
- if (status.getLevel() == ConnectionStatus.LEVEL_NONETWORK) {
- noNetwork = true;
- } else {
- noNetwork = false;
- if (isErrorHandling) {
- isErrorHandling = false;
- close();
- start();
- }
- }
- }
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingConfig.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/HoppingConfig.java
index 3780b7dc..96b8c460 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingConfig.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/HoppingConfig.java
@@ -1,4 +1,4 @@
-package se.leap.bitmaskclient.pluggableTransports;
+package se.leap.bitmaskclient.pluggableTransports.models;
import androidx.annotation.NonNull;
@@ -9,35 +9,47 @@ import com.google.gson.GsonBuilder;
import se.leap.bitmaskclient.base.models.Transport;
public class HoppingConfig {
- final boolean kcp;
+
+ /**
+ * Enabled bool `json:"enabled"`
+ * Remotes []string `json:"remotes"`
+ * Obfs4Certs []string `json:"obfs4_certs"`
+ * PortSeed int64 `json:"port_seed"`
+ * PortCount uint `json:"port_count"`
+ * MinHopSeconds uint `json:"min_hop_seconds"`
+ * HopJitter uint `json:"hop_jitter"`
+ * }
+ */
+
+ final boolean enabled;
final String proxyAddr;
final String[] remotes;
- final String[] certs;
+ final String[] obfs4Certs;
final int portSeed;
final int portCount;
final int minHopSeconds;
final int hopJitter;
- public HoppingConfig(boolean kcp,
+ public HoppingConfig(boolean enabled,
String proxyAddr,
Obfs4Options options,
int minHopSeconds,
int hopJitter) {
- this.kcp = kcp;
+ this.enabled = enabled;
this.proxyAddr = proxyAddr;
Transport transport = options.transport;
Transport.Endpoint[] endpoints = transport.getOptions().getEndpoints();
if (endpoints == null) {
// only port hopping, we assume the gateway IP as hopping PT's IP
- this.remotes = new String[]{ options.gatewayIP };
- this.certs = new String[] { transport.getOptions().getCert() };
+ this.remotes = new String[]{ options.bridgeIP };
+ this.obfs4Certs = new String[] { transport.getOptions().getCert() };
} else {
// port+ip hopping
this.remotes = new String[endpoints.length];
- this.certs = new String[endpoints.length];
+ this.obfs4Certs = new String[endpoints.length];
for (int i = 0; i < remotes.length; i++) {
remotes[i] = endpoints[i].getIp();
- certs[i] = endpoints[i].getCert();
+ obfs4Certs[i] = endpoints[i].getCert();
}
}
this.portSeed = transport.getOptions().getPortSeed();
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/KcpConfig.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/KcpConfig.java
new file mode 100644
index 00000000..255e7dd7
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/KcpConfig.java
@@ -0,0 +1,39 @@
+package se.leap.bitmaskclient.pluggableTransports.models;
+
+import androidx.annotation.NonNull;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public class KcpConfig {
+
+ // check OpenVPN's --sndbuf size and --rcvbuf size
+ public static final int DEFAULT_KCP_SEND_WINDOW_SIZE = 32;
+ public static final int DEFAULT_KCP_RECEIVE_WINDOW_SIZE = 32;
+ public static final int DEFAULT_KCP_READ_BUFFER = 16 * 1024 * 1024;
+ public static final int DEFAULT_KCP_WRITE_BUFFER = 16 * 1024 * 1024;
+
+ final boolean enabled;
+ final int sendWindowSize;
+ final int receiveWindowSize;
+ final int readBuffer;
+ final int writeBuffer;
+
+ public KcpConfig(boolean enabled) {
+ this.enabled = enabled;
+ this.sendWindowSize = DEFAULT_KCP_SEND_WINDOW_SIZE;
+ this.receiveWindowSize = DEFAULT_KCP_RECEIVE_WINDOW_SIZE;
+ this.readBuffer = DEFAULT_KCP_READ_BUFFER;
+ this.writeBuffer = DEFAULT_KCP_WRITE_BUFFER;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ Gson gson = new GsonBuilder()
+ .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
+ .create();
+ return gson.toJson(this);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/Obfs4Options.java
index 0dd81eb8..1eec376a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/Obfs4Options.java
@@ -1,16 +1,16 @@
-package se.leap.bitmaskclient.pluggableTransports;
+package se.leap.bitmaskclient.pluggableTransports.models;
import java.io.Serializable;
import se.leap.bitmaskclient.base.models.Transport;
public class Obfs4Options implements Serializable {
- public String gatewayIP;
+ public String bridgeIP;
public Transport transport;
- public Obfs4Options(String gatewayIP,
+ public Obfs4Options(String bridgeIP,
Transport transport) {
- this.gatewayIP = gatewayIP;
+ this.bridgeIP = bridgeIP;
this.transport = transport;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java
new file mode 100644
index 00000000..9f85c4a0
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java
@@ -0,0 +1,35 @@
+package se.leap.bitmaskclient.pluggableTransports.models;
+
+import androidx.annotation.NonNull;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public class ObfsvpnConfig {
+
+ final String proxyAddr;
+ final HoppingConfig hoppingConfig;
+ final KcpConfig kcpConfig;
+ final String remoteIp;
+ final String remotePort;
+ final String obfs4Cert;
+
+ public ObfsvpnConfig(String proxyAddress, HoppingConfig hoppingConfig, KcpConfig kcpConfig, String remoteIP, String remotePort, String obfsv4Cert) {
+ this.proxyAddr = proxyAddress;
+ this.hoppingConfig = hoppingConfig;
+ this.kcpConfig = kcpConfig;
+ this.remoteIp = remoteIP;
+ this.remotePort = remotePort;
+ this.obfs4Cert = obfsv4Cert;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ Gson gson = new GsonBuilder()
+ .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
+ .create();
+ return gson.toJson(this);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java
index c882b0bb..237f5bd2 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java
@@ -16,6 +16,8 @@ package se.leap.bitmaskclient.providersetup;
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import android.os.Bundle;
+
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
@@ -45,13 +47,15 @@ public class ProviderSetupObservable {
public static final String PROPERTY_CHANGE = "ProviderSetupObservable";
private final HandlerInterface handler;
private long lastUpdate = 0;
+ private int resultCode = 0;
+ private Bundle resultData;
private ProviderSetupObservable() {
handler = HandlerProvider.get();
changeSupport = new PropertyChangeSupport(this);
-
+ resultData = new Bundle();
}
public void addObserver(PropertyChangeListener propertyChangeListener) {
@@ -70,6 +74,14 @@ public class ProviderSetupObservable {
return instance;
}
+ public static void storeLastResult(int resultCode, Bundle resultData) {
+ if (getInstance().canceled) {
+ return;
+ }
+ getInstance().resultCode = resultCode;
+ getInstance().resultData = resultData;
+ }
+
public static void updateProgress(int progress) {
if (getInstance().canceled) {
return;
@@ -105,8 +117,14 @@ public class ProviderSetupObservable {
return getInstance().progress;
}
+ public static boolean isSetupRunning() {
+ return getInstance().progress > 0;
+ }
+
public static void reset() {
getInstance().progress = 0;
+ getInstance().resultCode = 0;
+ getInstance().resultData = new Bundle();
getInstance().changeSupport.firePropertyChange(PROPERTY_CHANGE, null, getInstance());
}
@@ -121,5 +139,16 @@ public class ProviderSetupObservable {
public static void startSetup() {
getInstance().canceled = false;
+ getInstance().resultCode = 0;
+ getInstance().progress = 1;
+ getInstance().resultData = new Bundle();
+ }
+
+ public static int getResultCode() {
+ return getInstance().resultCode;
+ }
+
+ public static Bundle getResultData() {
+ return getInstance().resultData;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java
index 9235daad..9a0bf7b7 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java
@@ -3,6 +3,7 @@ package se.leap.bitmaskclient.providersetup.activities;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static androidx.appcompat.app.ActionBar.DISPLAY_SHOW_CUSTOM;
+import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.deleteProviderDetailsFromPreferences;
import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.CONFIGURE_PROVIDER_FRAGMENT;
@@ -139,7 +140,7 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal
});
binding.viewPager.setAdapter(adapter);
binding.viewPager.setUserInputEnabled(false);
- binding.viewPager.setCurrentItem(currentPosition, false);
+
binding.setupNextButton.setOnClickListener(v -> {
int currentPos = binding.viewPager.getCurrentItem();
@@ -153,6 +154,14 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal
cancel();
});
setupActionBar();
+
+ if (ProviderSetupObservable.isSetupRunning()) {
+ provider = ProviderSetupObservable.getResultData().getParcelable(PROVIDER_KEY);
+ if (provider != null) {
+ currentPosition = adapter.getFragmentPostion(CONFIGURE_PROVIDER_FRAGMENT);
+ }
+ }
+ binding.viewPager.setCurrentItem(currentPosition, false);
}
@Override
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java
index cdb255fc..621cb41a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java
@@ -132,8 +132,12 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Prop
binding.progressSpinner.update(ProviderSetupObservable.getProgress());
setupActivityCallback.setNavigationButtonHidden(true);
setupActivityCallback.setCancelButtonHidden(false);
- ProviderSetupObservable.startSetup();
- ProviderAPICommand.execute(getContext(), SET_UP_PROVIDER, setupActivityCallback.getSelectedProvider());
+ if (ProviderSetupObservable.isSetupRunning()) {
+ handleResult(ProviderSetupObservable.getResultCode(), ProviderSetupObservable.getResultData(), true);
+ } else {
+ ProviderSetupObservable.startSetup();
+ ProviderAPICommand.execute(getContext(), SET_UP_PROVIDER, setupActivityCallback.getSelectedProvider());
+ }
}
protected void showConnectionDetails() {
@@ -203,16 +207,21 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Prop
if (resultData == null) {
resultData = Bundle.EMPTY;
}
+ handleResult(resultCode, resultData, false);
+ }
+
+ private void handleResult(int resultCode, Bundle resultData, boolean resumeSetup) {
Provider provider = resultData.getParcelable(PROVIDER_KEY);
if (ignoreProviderAPIUpdates ||
provider == null ||
(setupActivityCallback.getSelectedProvider() != null &&
- !setupActivityCallback.getSelectedProvider().getMainUrlString().equals(provider.getMainUrlString()))) {
+ !setupActivityCallback.getSelectedProvider().getMainUrlString().equals(provider.getMainUrlString()))) {
return;
}
switch (resultCode) {
case PROVIDER_OK:
+ setupActivityCallback.onProviderSelected(provider);
if (provider.allowsAnonymous()) {
ProviderAPICommand.execute(this.getContext(), DOWNLOAD_VPN_CERTIFICATE, provider);
} else {
@@ -223,11 +232,13 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Prop
setupActivityCallback.onProviderSelected(provider);
handler.postDelayed(() -> {
if (!ProviderSetupObservable.isCanceled()) {
- if (setupActivityCallback != null) {
+ try {
setupActivityCallback.onConfigurationSuccess();
+ } catch (NullPointerException npe) {
+ // callback disappeared in the meanwhile
}
}
- }, 750);
+ }, resumeSetup ? 0 : 750);
break;
case PROVIDER_NOK:
case INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE:
diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java b/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java
index f13eb70e..b7909865 100644
--- a/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java
+++ b/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java
@@ -1,6 +1,6 @@
package se.leap.bitmaskclient.tor;
/**
- * Copyright (c) 2021 LEAP Encryption Access Project and contributors
+ * Copyright (c) 2024 LEAP Encryption Access Project and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -66,6 +66,7 @@ public class ClientTransportPlugin implements ClientTransportPluginInterface, Pr
this.contextRef = new WeakReference<>(context);
handlerThread = new HandlerThread("clientTransportPlugin", Thread.MIN_PRIORITY);
loadCdnFronts(context);
+ IPtProxy.setStateLocation(context.getApplicationContext().getCacheDir() + "/pt_state");
}
@Override
@@ -96,18 +97,39 @@ public class ClientTransportPlugin implements ClientTransportPluginInterface, Pr
private void startConnectionAttempt(boolean useAmpCache, @NonNull String logfilePath) {
//this is using the current, default Tor snowflake infrastructure
String target = getCdnFront("snowflake-target");
- String front = getCdnFront("snowflake-front");
+ String fronts = getCdnFront("snowflake-fronts");
String stunServer = getCdnFront("snowflake-stun");
String ampCache = null;
if (useAmpCache) {
target = "https://snowflake-broker.torproject.net/";
ampCache = "https://cdn.ampproject.org/";
- front = "www.google.com";
+ fronts = "www.google.com";
}
- snowflakePort = IPtProxy.startSnowflake(stunServer, target, front, ampCache, logfilePath, false, false, true, 5);
+
+ snowflakePort = startSnowflake(stunServer, target, fronts, ampCache, null, null, logfilePath, false, false, false, 5);
Log.d(TAG, "startSnowflake running on port: " + snowflakePort);
}
+/**
+ StartSnowflake - Start IPtProxy's Snowflake client.
+ @param ice Comma-separated list of ICE servers.
+ @param url URL of signaling broker.
+ @param fronts Comma-separated list of front domains.
+ @param ampCache OPTIONAL. URL of AMP cache to use as a proxy for signaling.
+ Only needed when you want to do the rendezvous over AMP instead of a domain fronted server.
+ @param sqsQueueURL OPTIONAL. URL of SQS Queue to use as a proxy for signaling.
+ @param sqsCredsStr OPTIONAL. Credentials to access SQS Queue
+ @param logFile Name of log file. OPTIONAL. Defaults to no log.
+ @param logToStateDir Resolve the log file relative to Tor's PT state dir.
+ @param keepLocalAddresses Keep local LAN address ICE candidates.
+ @param unsafeLogging Prevent logs from being scrubbed.
+ @param maxPeers Capacity for number of multiplexed WebRTC peers. DEFAULTs to 1 if less than that.
+ @return Port number where Snowflake will listen on, if no error happens during start up.
+ */
+ private long startSnowflake(String ice, String url, String fronts, String ampCache, String sqsQueueURL, String sqsCredsStr, String logFile, boolean logToStateDir, boolean keepLocalAddresses, boolean unsafeLogging, long maxPeers) {
+ return IPtProxy.startSnowflake(ice, url, fronts, ampCache, sqsQueueURL, sqsCredsStr, logFile, logToStateDir, keepLocalAddresses, unsafeLogging, maxPeers);
+ }
+
private void retryConnectionAttempt(boolean useAmpCache) {
Log.d(TAG, ">> retryConnectionAttempt - " + (useAmpCache ? "amp cache" : "http domain fronting"));
stopConnectionAttempt();
diff --git a/app/src/main/res/layout-xlarge/f_about.xml b/app/src/main/res/layout-xlarge/f_about.xml
index 4e0d7342..cfdf2f40 100644
--- a/app/src/main/res/layout-xlarge/f_about.xml
+++ b/app/src/main/res/layout-xlarge/f_about.xml
@@ -190,23 +190,6 @@
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/shapeshifter_library"
- android:textSize="24sp"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textSize="18sp"
- android:text="@string/copyright_shapeshifter_library" />
-
- <Space
- android:layout_width="match_parent"
- android:layout_height="20dp" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:text="@string/obfs4"
android:textSize="24sp"
android:textAppearance="?android:attr/textAppearanceMedium" />
@@ -224,23 +207,6 @@
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/shapeshifter_transports"
- android:textSize="24sp"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textSize="18sp"
- android:text="@string/copyright_shapeshifter_transports" />
-
- <Space
- android:layout_width="match_parent"
- android:layout_height="20dp" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:text="@string/circleImageView"
android:textSize="24sp"
android:textAppearance="?android:attr/textAppearanceMedium" />
diff --git a/app/src/main/res/layout/d_obfuscation_proxy.xml b/app/src/main/res/layout/d_obfuscation_proxy.xml
index 2ce9d7b3..7b8fcaa7 100644
--- a/app/src/main/res/layout/d_obfuscation_proxy.xml
+++ b/app/src/main/res/layout/d_obfuscation_proxy.xml
@@ -81,7 +81,7 @@
android:layout_height="wrap_content"
android:text="Use defaults"
android:background="@drawable/cust_button_secondary"
- android:textColor="@color/color_font_btn_secondary"
+ android:textColor="@color/color_font_btn"
android:layout_marginHorizontal="@dimen/stdpadding"
/>
<androidx.appcompat.widget.LinearLayoutCompat
diff --git a/app/src/main/res/layout/f_about.xml b/app/src/main/res/layout/f_about.xml
index 28f89adf..b4d46694 100644
--- a/app/src/main/res/layout/f_about.xml
+++ b/app/src/main/res/layout/f_about.xml
@@ -186,21 +186,6 @@
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/shapeshifter_library"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/copyright_shapeshifter_library" />
-
- <Space
- android:layout_width="match_parent"
- android:layout_height="20dp" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:text="@string/obfs4"
android:textAppearance="?android:attr/textAppearanceMedium" />
@@ -216,21 +201,6 @@
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/shapeshifter_transports"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/copyright_shapeshifter_transports" />
-
- <Space
- android:layout_width="match_parent"
- android:layout_height="20dp" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:text="@string/circleImageView"
android:textAppearance="?android:attr/textAppearanceMedium" />
diff --git a/app/src/main/res/values/untranslatable.xml b/app/src/main/res/values/untranslatable.xml
index 957788a5..80cbf7f3 100644
--- a/app/src/main/res/values/untranslatable.xml
+++ b/app/src/main/res/values/untranslatable.xml
@@ -1,14 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="notifcation_title_bitmask" translatable="false">%s - %s</string>
- <string name="copyright_leapgui" translatable="false">Copyright (c) 2012-2022\nLEAP Encryption Access Project &lt;info@leap.se></string>
- <string name="opevpn_copyright" translatable="false">Copyright (c) 2002-2019 OpenVPN Technologies, Inc. &lt;sales@openvpn.net>\n
- "OpenVPN" is a trademark of OpenVPN Technologies, Inc.</string>
- <string name="lzo_copyright" translatable="false">Copyright (c) 1996 - 2011 Markus Franz Xaver Johannes Oberhumer</string>
- <string name="copyright_openssl" translatable="false"> Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.\n\n
+ <string name="copyright_leapgui" translatable="false">Copyright (c) 2012-2024\nLEAP Encryption Access Project &lt;info@leap.se></string>
+ <string name="opevpn_copyright" translatable="false">Copyright (C) 2002-2024 OpenVPN Inc &lt;sales@openvpn.net></string>
+ <string name="lzo_copyright" translatable="false">Copyright (c) 1996 - 2011 Markus Franz Xaver Johannes Oberhumer.\nCopyright (C) 2002-2024 OpenVPN Inc &lt;sales@openvpn.net></string>
+ <string name="copyright_openssl" translatable="false"> Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.\n\n
This product includes cryptographic software written by Eric Young (eay@cryptsoft.com)\n
Copyright 1995-1998 Eric Young (eay@cryptsoft.com) All rights reserved.</string>
- <string name="copyright_okhttp" translatable="false">Copyright (c) 2022 Square, Inc.</string>
+ <string name="copyright_okhttp" translatable="false">Copyright (c) 2024 Square, Inc.</string>
<string name="okhttp" translatable="false">OkHttp</string>
<string name="openvpn" translatable="false">OpenVPN</string>
<string name="lzo" translatable="false">LZO</string>
@@ -18,12 +17,11 @@
https://github.com/schwabe/polarssl/blob/icsopenvpn_270/apache-2.0.txt
</string>
<string name="asio" translatable="false">Asio</string>
- <string name="copyright_asio" translatable="false">Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com).\n\nDistributed under the Boost Software License, Version 1.0.</string>
+ <string name="copyright_asio" translatable="false">Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com).\n\nDistributed under the Boost Software License, Version 1.0.</string>
<string name="openvpn3" translatable="false">OpenVPN 3</string>
- <string name="copyright_openvpn3" translatable="false">GNU AFFERO GENERAL PUBLIC LICENSE\n
- Version 3, 19 November 2007</string>
+ <string name="copyright_openvpn3" translatable="false">Copyright (C) 2012-2024 OpenVPN Inc.</string>
<string name="unknown_state" translatable="false">Unknown state</string>
- <string name="copyright_blinktgui" translatable="false">Copyright (c) 2012-2022 Arne Schwabe &lt;arne@rfc2549.org></string>
+ <string name="copyright_blinktgui" translatable="false">Copyright (c) 2012-2024 Arne Schwabe &lt;arne@rfc2549.org></string>
<string name="defaultserver" translatable="false">openvpn.uni-paderborn.de</string>
<string name="defaultport" translatable="false">1194</string>
<string name="copyright_file_dialog" translatable="false">File Dialog based on work by Alexander Ponomarev</string>
@@ -35,22 +33,18 @@
<string name="state_user_vpn_password" translatable="false">Waiting for user VPN password</string>
<string name="state_user_vpn_password_cancelled" translatable="false">VPN password input dialog cancelled</string>
<string name="state_user_vpn_permission_cancelled" translatable="false">VPN API permission dialog cancelled</string>
- <string name="shapeshifter_library" translatable="false">Shapeshifter Library</string>
- <string name="copyright_shapeshifter_library" translatable="false">Copyright (c) 2022, LEAP Encryption Access Project (info@leap.se)</string>
- <string name="shapeshifter_transports" translatable="false">Shapeshifter Transports</string>
- <string name="copyright_shapeshifter_transports" translatable="false">Copyright (c) 2020 Operator Foundation. Distributed under MIT license.</string>
<string name="obfs4" translatable="false">obfs4 - The obfourscator</string>
<string name="copyright_obfs4" translatable="false">Copyright (c) 2014, Yawning Angel \n yawning at schwanenlied dot me \n All rights reserved.</string>
<string name="snowflake" translatable="false">Snowflake</string>
- <string name="copyright_snowflake" translatable="false">Copyright (c) 2016, Serene Han, Arlo Breault \n Copyright (c) 2019-2020, The Tor Project, Inc.\nDistributed under 3-clause BSD license.</string>
+ <string name="copyright_snowflake" translatable="false">Copyright (c) 2016, Serene Han, Arlo Breault \n Copyright (c) 2019-2024, The Tor Project, Inc.\nDistributed under 3-clause BSD license.</string>
<string name="iptproxy" translatable="false">IPtProxy</string>
- <string name="copyright_iptproxy" translatable="false">Copyright (c) 2020 - 2021 Benjamin Erhart (berhart@netzarchitekten.com). Distributed under the MIT License</string>
+ <string name="copyright_iptproxy" translatable="false">Copyright (c) 2020 - 2024 Benjamin Erhart (berhart@netzarchitekten.com). Distributed under the MIT License</string>
<string name="tor" translatable="false">Tor</string>
- <string name="copyright_tor" translatable="false">Copyright (c) 2001-2004, Roger Dingledine \n Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson \n Copyright (c) 2007-2019, The Tor Project, Inc. \n Distributed under the 3-clause BSD license</string>
+ <string name="copyright_tor" translatable="false">Copyright (c) 2001-2004, Roger Dingledine \n Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson \n Copyright (c) 2007-2024, The Tor Project, Inc. \n Distributed under the 3-clause BSD license</string>
<string name="tor_android" translatable="false">Tor Android</string>
<string name="copyright_tor_android" translatable="false">Copyright (c) 2009-2010, Nathan Freitas, The Guardian Project. Distributed under the 3-clause BSD license.</string>
<string name="circleImageView" translatable="false">CircleImageView</string>
- <string name="copyright_circleImageView" translatable="false">Copyright 2014 - 2022 Henning Dodenhof. Licensed under the Apache License, Version 2.0 </string>
+ <string name="copyright_circleImageView" translatable="false">Copyright 2014 - 2024 Henning Dodenhof. Licensed under the Apache License, Version 2.0 </string>
<!-- gateway selector, move to strings.xml, once the wording is clear -->
<string name="no_location" translatable="false">---</string>
diff --git a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
index ad42ffde..43df146b 100644
--- a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
+++ b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
@@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4;
@@ -25,22 +26,22 @@ import de.blinkt.openvpn.core.connection.Obfs4Connection;
import de.blinkt.openvpn.core.connection.OpenvpnConnection;
import se.leap.bitmaskclient.base.models.Transport;
import se.leap.bitmaskclient.base.utils.BuildConfigHelper;
-import se.leap.bitmaskclient.pluggableTransports.Obfs4Options;
+import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
@RunWith(PowerMockRunner.class)
@PrepareForTest({UUID.class, BuildConfigHelper.class})
public class VpnProfileTest {
private static final String OPENVPNCONNECTION_PROFILE = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mUseUdp\":false,\"mServerName\":\"openvpn.example.com\",\"mProxyType\":\"NONE\",\"mProxyPort\":\"8080\",\"mUseCustomConfig\":false,\"mConnectTimeout\":0,\"mProxyName\":\"proxy.example.com\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.OpenvpnConnection\",\"mServerPort\":\"1194\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":1,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}";
- private static final String OBFS4CONNECTION_PROFILE = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"127.0.0.1\",\"mProxyType\":\"NONE\",\"mConnectTimeout\":0,\"mServerPort\":\"4430\",\"mUseUdp\":false,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"gatewayIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":0,\"iatMode\":\"0\",\"cert\":\"CERT\",\"experimental\":false,\"portSeed\":0},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}";
- private static final String OBFS4CONNECTION_PROFILE_OBFSVPN = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"192.168.0.1\",\"mProxyType\":\"SOCKS5\",\"mConnectTimeout\":0,\"mServerPort\":\"1234\",\"mUseUdp\":false,\"mProxyPort\":\"4430\",\"mUseCustomConfig\":false,\"options\":{\"gatewayIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":0,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":false,\"portSeed\":0},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"127.0.0.1\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}";
- private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_KCP = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"192.168.0.1\",\"mProxyType\":\"SOCKS5\",\"mConnectTimeout\":0,\"mServerPort\":\"1234\",\"mUseUdp\":false,\"mProxyPort\":\"4430\",\"mUseCustomConfig\":false,\"options\":{\"gatewayIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":0,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":false,\"portSeed\":0},\"type\":\"obfs4\",\"protocols\":[\"kcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"127.0.0.1\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
+ private static final String OBFS4CONNECTION_PROFILE = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"127.0.0.1\",\"mProxyType\":\"NONE\",\"mConnectTimeout\":0,\"mServerPort\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":0,\"iatMode\":\"0\",\"cert\":\"CERT\",\"experimental\":false,\"portSeed\":0},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}";
+ private static final String OBFS4CONNECTION_PROFILE_OBFSVPN = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"127.0.0.1\",\"mProxyType\":\"NONE\",\"mConnectTimeout\":0,\"mServerPort\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":0,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":false,\"portSeed\":0},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}";
+ private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_KCP = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"127.0.0.1\",\"mProxyType\":\"NONE\",\"mConnectTimeout\":0,\"mServerPort\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":0,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":false,\"portSeed\":0},\"type\":\"obfs4\",\"protocols\":[\"kcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
- private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_HOP = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"192.168.0.1\",\"mProxyType\":\"SOCKS5\",\"mConnectTimeout\":0,\"mServerPort\":\"1234\",\"mUseUdp\":false,\"mProxyPort\":\"4430\",\"mUseCustomConfig\":false,\"options\":{\"gatewayIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":100,\"endpoints\":[{\"ip\":\"1.1.1.1\",\"cert\":\"CERT1\"},{\"ip\":\"2.2.2.2\",\"cert\":\"CERT2\"}],\"iatMode\":\"1\",\"experimental\":true,\"portSeed\":200},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"127.0.0.1\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
+ private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_HOP = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"127.0.0.1\",\"mProxyType\":\"NONE\",\"mConnectTimeout\":0,\"mServerPort\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":100,\"endpoints\":[{\"ip\":\"1.1.1.1\",\"cert\":\"CERT1\"},{\"ip\":\"2.2.2.2\",\"cert\":\"CERT2\"}],\"iatMode\":\"1\",\"experimental\":true,\"portSeed\":200},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
- private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_HOP_KCP = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"192.168.0.1\",\"mProxyType\":\"SOCKS5\",\"mConnectTimeout\":0,\"mServerPort\":\"1234\",\"mUseUdp\":false,\"mProxyPort\":\"4430\",\"mUseCustomConfig\":false,\"options\":{\"gatewayIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":100,\"endpoints\":[{\"ip\":\"1.1.1.1\",\"cert\":\"CERT1\"},{\"ip\":\"2.2.2.2\",\"cert\":\"CERT2\"}],\"iatMode\":\"1\",\"experimental\":true,\"portSeed\":2500},\"type\":\"obfs4\",\"protocols\":[\"kcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"127.0.0.1\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
+ private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_HOP_KCP = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"127.0.0.1\",\"mProxyType\":\"NONE\",\"mConnectTimeout\":0,\"mServerPort\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":100,\"endpoints\":[{\"ip\":\"1.1.1.1\",\"cert\":\"CERT1\"},{\"ip\":\"2.2.2.2\",\"cert\":\"CERT2\"}],\"iatMode\":\"1\",\"experimental\":true,\"portSeed\":2500},\"type\":\"obfs4\",\"protocols\":[\"kcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
- private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_PORTHOPPING = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"192.168.0.1\",\"mProxyType\":\"SOCKS5\",\"mConnectTimeout\":0,\"mServerPort\":\"1234\",\"mUseUdp\":true,\"mProxyPort\":\"8080\",\"mUseCustomConfig\":false,\"options\":{\"gatewayIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":100,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":true,\"portSeed\":200},\"type\":\"obfs4-hop\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"127.0.0.1\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
+ private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_PORTHOPPING = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"127.0.0.1\",\"mProxyType\":\"NONE\",\"mConnectTimeout\":0,\"mServerPort\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":100,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":true,\"portSeed\":200},\"type\":\"obfs4-hop\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
@Before
public void setup() {
@@ -77,8 +78,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(false);
-
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4);
Transport transport = new Transport(OBFS4.toString(), new String[]{"tcp"}, new String[]{"1234"}, "CERT");
@@ -96,7 +95,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4_obfsvpn() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4);
Transport.Options options = new Transport.Options("CERT", "1");
Transport transport = new Transport(OBFS4.toString(), new String[]{"tcp"}, new String[]{"1234"}, options);
@@ -114,7 +112,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4_obfsvpn_kcp() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4);
Transport.Options options = new Transport.Options("CERT", "1");
@@ -133,7 +130,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4hop_kcp() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
@@ -154,7 +150,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4hop_portHopping() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
@@ -175,7 +170,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4hop() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
Transport.Options options = new Transport.Options("1", new Transport.Endpoint[]{new Transport.Endpoint("1.1.1.1", "CERT1"), new Transport.Endpoint("2.2.2.2", "CERT2")}, 200, 100, true);
@@ -195,13 +189,12 @@ public class VpnProfileTest {
@Test
public void fromJson_obfs4() {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(false);
VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE);
assertNotNull(mockVpnProfile);
assertNotNull(mockVpnProfile.mConnections);
assertNotNull(mockVpnProfile.mConnections[0]);
- assertFalse(mockVpnProfile.mConnections[0].isUseUdp());
+ assertTrue(mockVpnProfile.mConnections[0].isUseUdp());
Obfs4Connection obfs4Connection = (Obfs4Connection) mockVpnProfile.mConnections[0];
assertEquals(OBFS4, obfs4Connection.getTransportType());
String[] protocols = obfs4Connection.getObfs4Options().transport.getProtocols();
@@ -210,45 +203,43 @@ public class VpnProfileTest {
}
assertEquals("CERT", obfs4Connection.getObfs4Options().transport.getOptions().getCert());
assertEquals("0", obfs4Connection.getObfs4Options().transport.getOptions().getIatMode());
- assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().gatewayIP);
+ assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().bridgeIP);
assertEquals("1234", obfs4Connection.getObfs4Options().transport.getPorts()[0]);
assertEquals(1, obfs4Connection.getObfs4Options().transport.getPorts().length);
}
@Test
public void fromJson_obfs4_obfsvpn() {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN);
assertNotNull(mockVpnProfile);
assertNotEquals(null, mockVpnProfile.mConnections);
assertNotNull(mockVpnProfile.mConnections[0]);
- assertFalse(mockVpnProfile.mConnections[0].isUseUdp());
+ assertTrue(mockVpnProfile.mConnections[0].isUseUdp());
Obfs4Connection obfs4Connection = (Obfs4Connection) mockVpnProfile.mConnections[0];
assertEquals(OBFS4, obfs4Connection.getTransportType());
assertEquals("tcp", obfs4Connection.getObfs4Options().transport.getProtocols()[0]);
assertEquals("CERT", obfs4Connection.getObfs4Options().transport.getOptions().getCert());
assertEquals("1", obfs4Connection.getObfs4Options().transport.getOptions().getIatMode());
- assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().gatewayIP);
+ assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().bridgeIP);
assertEquals("1234", obfs4Connection.getObfs4Options().transport.getPorts()[0]);
assertEquals(1, obfs4Connection.getObfs4Options().transport.getPorts().length);
}
@Test
public void fromJson_obfs4_obfsvpn_kcp() {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN_KCP);
assertNotNull(mockVpnProfile);
assertNotNull(mockVpnProfile.mConnections);
assertNotNull(mockVpnProfile.mConnections[0]);
- assertFalse(mockVpnProfile.mConnections[0].isUseUdp());
+ assertTrue(mockVpnProfile.mConnections[0].isUseUdp());
Obfs4Connection obfs4Connection = (Obfs4Connection) mockVpnProfile.mConnections[0];
assertEquals(OBFS4, obfs4Connection.getTransportType());
assertEquals("kcp", obfs4Connection.getObfs4Options().transport.getProtocols()[0]);
assertEquals("CERT", obfs4Connection.getObfs4Options().transport.getOptions().getCert());
assertEquals("1", obfs4Connection.getObfs4Options().transport.getOptions().getIatMode());
- assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().gatewayIP);
+ assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().bridgeIP);
assertEquals("1234", obfs4Connection.getObfs4Options().transport.getPorts()[0]);
}
} \ No newline at end of file
diff --git a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java
index 4fcc6bac..ee6cd30f 100644
--- a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java
@@ -118,20 +118,6 @@ public class ProviderTest {
}
@Test
- public void testSupportsPluggableTransports_Obfs4Kcp_noObsvpn_returnsFalse() throws Exception {
- Provider p1 = TestSetupHelper.getProvider(
- "https://pt.demo.bitmask.net",
- null,
- null,
- null,
- null,
- null,
- "ptdemo_only_experimental_transports_gateways.json",
- null);
- assertFalse(p1.supportsPluggableTransports());
- }
-
- @Test
public void testSupportsPluggableTransports_Obfs4Kcp_obsvpn_returnsTrue() throws Exception {
BuildConfigHelper helper = MockHelper.mockBuildConfigHelper(true);
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
index d66fedbe..9286a787 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
@@ -3,6 +3,7 @@ package se.leap.bitmaskclient.eip;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4;
import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN;
@@ -23,6 +24,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
+import org.junit.function.ThrowingRunnable;
import org.mockito.Answers;
import org.mockito.Mock;
@@ -120,6 +122,21 @@ public class GatewaysManagerTest {
}
@Test
+ public void TestGetPosition_IncompatibleProviderBridges_returnParseError() throws JSONException, ConfigParser.ConfigParseError, IOException {
+ Provider provider = getProvider(null, null, null, null, null, null, "ptdemo.bitmask.eip-service.json", null);
+ JSONObject eipServiceJson = provider.getEipServiceJson();
+ JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0);
+ providerObservable.updateProvider(provider);
+ GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
+
+ VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
+ configuration.apiVersion = 3;
+ configuration.remoteGatewayIP = "37.218.247.60";
+ VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, configuration);
+ assertThrows(ConfigParser.ConfigParseError.class, () -> configGenerator.createProfile(OBFS4));
+ }
+
+ @Test
public void TestGetPosition_VpnProfileExistingObfs4FromPresortedList_returnsPositionOne() throws JSONException, ConfigParser.ConfigParseError, IOException {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json");
JSONObject eipServiceJson = provider.getEipServiceJson();
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java
index e78db39c..b8c6d0c9 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java
@@ -172,7 +172,7 @@ public class ProviderApiManagerTest {
mockContext = mockContext();
mockResources = mockResources(getClass().getClassLoader().getResourceAsStream("error_messages.json"));
HandlerProvider handlerProvider = new HandlerProvider((r, delay) -> new Thread(r).start());
- BuildConfigHelper buildConfigHelper = mockBuildConfigHelper(true, true);
+ BuildConfigHelper buildConfigHelper = mockBuildConfigHelper(true);
TorStatusObservable torStatusObservable = TorStatusObservable.getInstance();
TorStatusObservable.setProxyPort(-1);
TorStatusObservable.setLastError(null);
@@ -461,7 +461,7 @@ public class ProviderApiManagerTest {
ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_CASE_MICONFIGURED_PROVIDER);
CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- BuildConfigHelper buildConfigHelper = mockBuildConfigHelper(true, false);
+ BuildConfigHelper buildConfigHelper = mockBuildConfigHelper(false);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java
index a951f144..09e831dd 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java
@@ -25,7 +25,7 @@ public class VpnCertificateValidatorTest {
@Test
public void test_isValid() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
- Calendar c = new Calendar.Builder().setDate(2018, 1, 1).setCalendarType("gregorian").build();
+ Calendar c = new Calendar.Builder().setDate(2024, 11, 2).setCalendarType("gregorian").build();
CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
@@ -35,7 +35,7 @@ public class VpnCertificateValidatorTest {
@Test
public void test_isValid_lessThan1day_returnFalse() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
- Calendar c = new Calendar.Builder().setDate(2024, 3, 28).setCalendarType("gregorian").build();
+ Calendar c = new Calendar.Builder().setDate(2026, 11, 2).setCalendarType("gregorian").build();
CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
index 4b9e5d65..7581a395 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
@@ -24,7 +24,6 @@ import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.core.ConfigParser;
import de.blinkt.openvpn.core.connection.Connection;
import de.blinkt.openvpn.core.connection.Obfs4Connection;
-import de.blinkt.openvpn.core.connection.Obfs4HopConnection;
import se.leap.bitmaskclient.base.models.ProviderObservable;
import se.leap.bitmaskclient.base.utils.BuildConfigHelper;
import se.leap.bitmaskclient.base.utils.PreferenceHelper;
@@ -256,7 +255,7 @@ public class VpnConfigGeneratorTest {
"connect-retry 2 300\n" +
"resolv-retry 60\n" +
"dev tun\n" +
- "remote 127.0.0.1 4430 tcp-client\n" +
+ "remote 127.0.0.1 8080 udp\n" +
"<ca>\n" +
"-----BEGIN CERTIFICATE-----\n" +
"MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\n" +
@@ -352,7 +351,7 @@ public class VpnConfigGeneratorTest {
"connect-retry 2 300\n" +
"resolv-retry 60\n" +
"dev tun\n" +
- "remote 37.218.247.60 23049 tcp-client\n" +
+ "remote 127.0.0.1 8080 udp\n" +
"<ca>\n" +
"-----BEGIN CERTIFICATE-----\n" +
"MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\n" +
@@ -1218,7 +1217,6 @@ public class VpnConfigGeneratorTest {
"management-external-key nopadding pkcs1 pss digest\n" +
//"# crl-verify file missing in config profile\n" +
"route 192.81.208.164 255.255.255.255 net_gateway\n"+
- "tun-mtu 48000\n"+
"nobind\n"+
"remote-cert-tls server\n" +
"data-ciphers AES-256-GCM\n" +
@@ -1234,12 +1232,10 @@ public class VpnConfigGeneratorTest {
"# You are on your on own here :)\n" +
"# These options found in the config file do not map to config settings:\n" +
"keepalive 10 30 \n" +
- "replay-window 65535 \n" +
+ "tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 \n" +
"sndbuf 0 \n" +
"rcvbuf 0 \n" +
- "tls-version-min 1.2 \n" +
- "ping-restart 300 \n" +
- "tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 \n";
+ "tls-version-min 1.2 \n";
String expectedVPNConfig_hopping_pt_portAndIpHopping = "# Config for OpenVPN 2.x\n" +
"# Enables connection to GUI\n" +
@@ -1324,7 +1320,6 @@ public class VpnConfigGeneratorTest {
"route 192.81.208.164 255.255.255.255 net_gateway\n"+
"route 192.81.208.165 255.255.255.255 net_gateway\n"+
"route 192.81.208.166 255.255.255.255 net_gateway\n"+
- "tun-mtu 48000\n"+
"nobind\n"+
"remote-cert-tls server\n" +
"data-ciphers AES-256-GCM\n" +
@@ -1340,9 +1335,6 @@ public class VpnConfigGeneratorTest {
"# You are on your on own here :)\n" +
"# These options found in the config file do not map to config settings:\n" +
"keepalive 10 30 \n" +
- "replay-window 65535 \n" +
- "sndbuf 0 \n" +
- "rcvbuf 0 \n" +
"tls-version-min 1.2 \n" +
"ping-restart 300 \n" +
"tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 \n";
@@ -1409,7 +1401,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_v3_obfs4() throws Exception {
BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(false);
- gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0);
+ gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service-obfsvpn1.0.0.json"))).getJSONArray("gateways").getJSONObject(0);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
configuration.apiVersion = 3;
vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration);
@@ -1423,7 +1415,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_v3_obfs4_obfsvpn() throws Exception {
BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true);
- gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0);
+ gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service-obfsvpn1.0.0.json"))).getJSONArray("gateways").getJSONObject(0);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
configuration.apiVersion = 3;
vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration);
@@ -1558,12 +1550,12 @@ public class VpnConfigGeneratorTest {
}
/**
- * obfs4 cannot be used with UDP, openvpn needs to support TCP
+ * obfs4 cannot be used with UDP (only TCP or KCP), openvpn needs to support UDP
*/
@Test
- public void testGenerateVpnProfile_v3_obfs4TCP_openvpnUDP_skip() throws Exception {
- gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_udp2.json"))).getJSONArray("gateways").getJSONObject(0);
- generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_udp2.json"))).getJSONObject(OPENVPN_CONFIGURATION);
+ public void testGenerateVpnProfile_v3_obfs4TCP_openvpnTCP_skip() throws Exception {
+ gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_tcp2.json"))).getJSONArray("gateways").getJSONObject(0);
+ generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_tcp2.json"))).getJSONObject(OPENVPN_CONFIGURATION);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
configuration.apiVersion = 3;
vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration);
@@ -1583,7 +1575,6 @@ public class VpnConfigGeneratorTest {
assertTrue(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.containsKey(OPENVPN));
assertEquals(1, vpnProfiles.get(OBFS4).mConnections.length);
- assertFalse(vpnProfiles.get(OBFS4).mConnections[0].isUseUdp());
}
@Test
@@ -1676,7 +1667,7 @@ public class VpnConfigGeneratorTest {
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertFalse("has openvpn profile", vpnProfiles.containsKey(OPENVPN));
assertTrue("has obfs4 profile", vpnProfiles.containsKey(OBFS4));
- assertTrue("bridge is pinned one", vpnProfiles.get(OBFS4).getTransportType() == OBFS4 && !vpnProfiles.get(OBFS4).mConnections[0].isUseUdp() );
+ assertTrue("bridge is pinned one", vpnProfiles.get(OBFS4).getTransportType() == OBFS4 && vpnProfiles.get(OBFS4).mConnections[0].isUseUdp());
assertTrue("bridge is running TCP", ((Obfs4Connection) vpnProfiles.get(OBFS4).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
}
@@ -1709,7 +1700,7 @@ public class VpnConfigGeneratorTest {
configuration.experimentalTransports = true;
vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
- assertTrue(vpnProfiles.containsKey(OBFS4_HOP) && ((Obfs4HopConnection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
+ assertTrue(vpnProfiles.containsKey(OBFS4_HOP) && ((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
assertTrue(vpnProfiles.containsKey(OPENVPN));
}
@@ -1722,7 +1713,7 @@ public class VpnConfigGeneratorTest {
configuration.experimentalTransports = true;
vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
- assertTrue(vpnProfiles.containsKey(OBFS4_HOP) && ((Obfs4HopConnection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("kcp"));
+ assertTrue(vpnProfiles.containsKey(OBFS4_HOP) && ((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("kcp"));
assertTrue(vpnProfiles.containsKey(OPENVPN));
}
@@ -1779,7 +1770,7 @@ public class VpnConfigGeneratorTest {
vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4_HOP));
- assertTrue(((Obfs4HopConnection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
+ assertTrue(((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
assertFalse(vpnProfiles.containsKey(OPENVPN));
assertFalse(vpnProfiles.containsKey(OBFS4));
}
@@ -1813,7 +1804,7 @@ public class VpnConfigGeneratorTest {
vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4_HOP));
- assertTrue(((Obfs4HopConnection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
+ assertTrue(((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
assertFalse(vpnProfiles.containsKey(OPENVPN));
assertFalse(vpnProfiles.containsKey(OBFS4));
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java
index bbbed821..dfdae967 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java
@@ -59,7 +59,7 @@ public class NoErrorBackendResponseAPIv4 implements ProviderApiConnector.Provide
return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
} else if (url.contains("/cert")) {
// download vpn key and cert
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.cert"));
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/generictest.cert"));
}
return null;
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java
index 45dd36e4..76f6bea4 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java
@@ -73,7 +73,7 @@ public class TorFallbackBackendResponse implements ProviderApiConnector.Provider
throw new UnknownHostException("DNS blocked by censor ;)");
}
// download vpn certificate for authentication
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.cert"));
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/generictest.cert"));
}
return null;
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
index a7d3e19c..1b94042e 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
@@ -190,16 +190,12 @@ public class MockHelper {
}
- public static BuildConfigHelper mockBuildConfigHelper(boolean useObfsvpn) {
- return mockBuildConfigHelper(useObfsvpn, true);
+ public static BuildConfigHelper mockBuildConfigHelper() {
+ return mockBuildConfigHelper(true);
}
- public static BuildConfigHelper mockBuildConfigHelper(boolean useObfsvpn, boolean isDefaultBitmask) {
+ public static BuildConfigHelper mockBuildConfigHelper(boolean isDefaultBitmask) {
return new BuildConfigHelper(new BuildConfigHelper.BuildConfigHelperInterface() {
- @Override
- public boolean useObfsVpn() {
- return useObfsvpn;
- }
@Override
public boolean hasObfuscationPinningDefaults() {
diff --git a/app/src/test/resources/preconfigured/riseup.net.pem b/app/src/test/resources/preconfigured/riseup.net.pem
index c890aff4..4f801cc1 100644
--- a/app/src/test/resources/preconfigured/riseup.net.pem
+++ b/app/src/test/resources/preconfigured/riseup.net.pem
@@ -1,32 +1,10 @@
-----BEGIN CERTIFICATE-----
-MIIFjTCCA3WgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBZMRgwFgYDVQQKDA9SaXNl
-dXAgTmV0d29ya3MxGzAZBgNVBAsMEmh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UE
-AwwXUmlzZXVwIE5ldHdvcmtzIFJvb3QgQ0EwHhcNMTQwNDI4MDAwMDAwWhcNMjQw
-NDI4MDAwMDAwWjBZMRgwFgYDVQQKDA9SaXNldXAgTmV0d29ya3MxGzAZBgNVBAsM
-Emh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UEAwwXUmlzZXVwIE5ldHdvcmtzIFJv
-b3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC76J4ciMJ8Sg0m
-TP7DF2DT9zNe0Csk4myoMFC57rfJeqsAlJCv1XMzBmXrw8wq/9z7XHv6n/0sWU7a
-7cF2hLR33ktjwODlx7vorU39/lXLndo492ZBhXQtG1INMShyv+nlmzO6GT7ESfNE
-LliFitEzwIegpMqxCIHXFuobGSCWF4N0qLHkq/SYUMoOJ96O3hmPSl1kFDRMtWXY
-iw1SEKjUvpyDJpVs3NGxeLCaA7bAWhDY5s5Yb2fA1o8ICAqhowurowJpW7n5ZuLK
-5VNTlNy6nZpkjt1QycYvNycffyPOFm/Q/RKDlvnorJIrihPkyniV3YY5cGgP+Qkx
-HUOT0uLA6LHtzfiyaOqkXwc4b0ZcQD5Vbf6Prd20Ppt6ei0zazkUPwxld3hgyw58
-m/4UIjG3PInWTNf293GngK2Bnz8Qx9e/6TueMSAn/3JBLem56E0WtmbLVjvko+LF
-PM5xA+m0BmuSJtrD1MUCXMhqYTtiOvgLBlUm5zkNxALzG+cXB28k6XikXt6MRG7q
-hzIPG38zwkooM55yy5i1YfcIi5NjMH6A+t4IJxxwb67MSb6UFOwg5kFokdONZcwj
-shczHdG9gLKSBIvrKa03Nd3W2dF9hMbRu//STcQxOailDBQCnXXfAATj9pYzdY4k
-ha8VCAREGAKTDAex9oXf1yRuktES4QIDAQABo2AwXjAdBgNVHQ4EFgQUC4tdmLVu
-f9hwfK4AGliaet5KkcgwDgYDVR0PAQH/BAQDAgIEMAwGA1UdEwQFMAMBAf8wHwYD
-VR0jBBgwFoAUC4tdmLVuf9hwfK4AGliaet5KkcgwDQYJKoZIhvcNAQENBQADggIB
-AGzL+GRnYu99zFoy0bXJKOGCF5XUXP/3gIXPRDqQf5g7Cu/jYMID9dB3No4Zmf7v
-qHjiSXiS8jx1j/6/Luk6PpFbT7QYm4QLs1f4BlfZOti2KE8r7KRDPIecUsUXW6P/
-3GJAVYH/+7OjA39za9AieM7+H5BELGccGrM5wfl7JeEz8in+V2ZWDzHQO4hMkiTQ
-4ZckuaL201F68YpiItBNnJ9N5nHr1MRiGyApHmLXY/wvlrOpclh95qn+lG6/2jk7
-3AmihLOKYMlPwPakJg4PYczm3icFLgTpjV5sq2md9bRyAg3oPGfAuWHmKj2Ikqch
-Td5CHKGxEEWbGUWEMP0s1A/JHWiCbDigc4Cfxhy56CWG4q0tYtnc2GMw8OAUO6Wf
-Xu5pYKNkzKSEtT/MrNJt44tTZWbKV/Pi/N2Fx36my7TgTUj7g3xcE9eF4JV2H/sg
-tsK3pwE0FEqGnT4qMFbixQmc8bGyuakr23wjMvfO7eZUxBuWYR2SkcP26sozF9PF
-tGhbZHQVGZUTVPyvwahMUEhbPGVerOW0IYpxkm0x/eaWdTc4vPpf/rIlgbAjarnJ
-UN9SaWRlWKSdP4haujnzCoJbM7dU9bjvlGZNyXEekgeT0W2qFeGGp+yyUWw8tNsp
-0BuC1b7uW/bBn/xKm319wXVDvBgZgcktMolak39V7DVO
------END CERTIFICATE----- \ No newline at end of file
+MIIBYjCCAQigAwIBAgIBATAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxMRUFQIFJv
+b3QgQ0EwHhcNMjExMTAyMTkwNTM3WhcNMjYxMTAyMTkxMDM3WjAXMRUwEwYDVQQD
+EwxMRUFQIFJvb3QgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQxOXBGu+gf
+pjHzVteGTWL6XnFxtEnKMFpKaJkA/VOHmESzoLsZRQxt88GssxaqC01J17idQiqv
+zgNpedmtvFtyo0UwQzAOBgNVHQ8BAf8EBAMCAqQwEgYDVR0TAQH/BAgwBgEB/wIB
+ATAdBgNVHQ4EFgQUZdoUlJrCIUNFrpffAq+LQjnwEz4wCgYIKoZIzj0EAwIDSAAw
+RQIgfr3w4tnRG+NdI3LsGPlsRktGK20xHTzsB3orB0yC6cICIQCB+/9y8nmSStfN
+VUMUyk2hNd7/kC8nL222TTD7VZUtsg==
+-----END CERTIFICATE-----
diff --git a/app/src/test/resources/ptdemo.bitmask.eip-service-obfsvpn1.0.0.json b/app/src/test/resources/ptdemo.bitmask.eip-service-obfsvpn1.0.0.json
new file mode 100644
index 00000000..2b3d7fd7
--- /dev/null
+++ b/app/src/test/resources/ptdemo.bitmask.eip-service-obfsvpn1.0.0.json
@@ -0,0 +1,64 @@
+{
+ "gateways":[
+ {
+ "capabilities":{
+ "adblock":false,
+ "filter_dns":false,
+ "limited":false,
+ "transport":[
+ {
+ "type":"obfs4",
+ "protocols":[
+ "tcp"
+ ],
+ "ports":[
+ "23049"
+ ],
+ "options": {
+ "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1",
+ "iatMode": "0"
+ }
+ },
+ {
+ "type":"openvpn",
+ "protocols":[
+ "udp"
+ ],
+ "ports":[
+ "1195"
+ ]
+ }
+ ],
+ "user_ips":false
+ },
+ "host":"pt.demo.bitmask.net",
+ "ip_address":"37.218.247.60",
+ "location":"Amsterdam"
+ }
+ ],
+ "locations":{
+ "Amsterdam":{
+ "country_code":"NL",
+ "hemisphere":"N",
+ "name":"Amsterdam",
+ "timezone":"-1"
+ }
+ },
+ "openvpn_configuration":{
+ "auth":"SHA1",
+ "cipher":"AES-256-CBC",
+ "keepalive":"10 30",
+ "tls-cipher":"DHE-RSA-AES128-SHA",
+ "tun-ipv6":true,
+ "dev" : "tun",
+ "sndbuf" : "0",
+ "rcvbuf" : "0",
+ "nobind" : true,
+ "persist-key" : true,
+ "comp-lzo" : true,
+ "key-direction" : "1",
+ "verb" : "3"
+ },
+ "serial":2,
+ "version":3
+} \ No newline at end of file
diff --git a/app/src/test/resources/ptdemo_kcp_gateways.json b/app/src/test/resources/ptdemo_kcp_gateways.json
index 8c2c9d32..afd7db69 100644
--- a/app/src/test/resources/ptdemo_kcp_gateways.json
+++ b/app/src/test/resources/ptdemo_kcp_gateways.json
@@ -22,7 +22,8 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "tcp",
+ "udp"
],
"ports":[
"1195"
@@ -57,7 +58,8 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "tcp",
+ "udp"
],
"ports":[
"1195"
diff --git a/app/src/test/resources/ptdemo_misconfigured_ipv4ipv6.json b/app/src/test/resources/ptdemo_misconfigured_ipv4ipv6.json
index 5c913c14..9412e099 100644
--- a/app/src/test/resources/ptdemo_misconfigured_ipv4ipv6.json
+++ b/app/src/test/resources/ptdemo_misconfigured_ipv4ipv6.json
@@ -22,7 +22,8 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "tcp",
+ "udp"
],
"ports":[
"1195"
diff --git a/app/src/test/resources/ptdemo_misconfigured_udp2.json b/app/src/test/resources/ptdemo_misconfigured_tcp2.json
index d2a54cef..5c913c14 100644
--- a/app/src/test/resources/ptdemo_misconfigured_udp2.json
+++ b/app/src/test/resources/ptdemo_misconfigured_tcp2.json
@@ -22,7 +22,7 @@
{
"type":"openvpn",
"protocols":[
- "udp"
+ "tcp"
],
"ports":[
"1195"
diff --git a/app/src/test/resources/ptdemo_misconfigured_udptcp.json b/app/src/test/resources/ptdemo_misconfigured_udptcp.json
index 42d55de9..016d45da 100644
--- a/app/src/test/resources/ptdemo_misconfigured_udptcp.json
+++ b/app/src/test/resources/ptdemo_misconfigured_udptcp.json
@@ -23,7 +23,8 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "tcp",
+ "udp"
],
"ports":[
"1195"
diff --git a/app/src/test/resources/ptdemo_obfs4hop_tcp_gateways.json b/app/src/test/resources/ptdemo_obfs4hop_tcp_gateways.json
index 34bcecb3..1d234ce2 100644
--- a/app/src/test/resources/ptdemo_obfs4hop_tcp_gateways.json
+++ b/app/src/test/resources/ptdemo_obfs4hop_tcp_gateways.json
@@ -22,7 +22,8 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "tcp",
+ "udp"
],
"ports":[
"1195"
diff --git a/app/src/test/resources/ptdemo_three_mixed_gateways.json b/app/src/test/resources/ptdemo_three_mixed_gateways.json
index 9b04cab4..e48e6cca 100644
--- a/app/src/test/resources/ptdemo_three_mixed_gateways.json
+++ b/app/src/test/resources/ptdemo_three_mixed_gateways.json
@@ -22,7 +22,7 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "udp"
],
"ports":[
"1195"
@@ -57,7 +57,7 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "udp"
],
"ports":[
"1195"
diff --git a/app/src/test/resources/riseup.net.pem b/app/src/test/resources/riseup.net.pem
index c890aff4..4f801cc1 100644
--- a/app/src/test/resources/riseup.net.pem
+++ b/app/src/test/resources/riseup.net.pem
@@ -1,32 +1,10 @@
-----BEGIN CERTIFICATE-----
-MIIFjTCCA3WgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBZMRgwFgYDVQQKDA9SaXNl
-dXAgTmV0d29ya3MxGzAZBgNVBAsMEmh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UE
-AwwXUmlzZXVwIE5ldHdvcmtzIFJvb3QgQ0EwHhcNMTQwNDI4MDAwMDAwWhcNMjQw
-NDI4MDAwMDAwWjBZMRgwFgYDVQQKDA9SaXNldXAgTmV0d29ya3MxGzAZBgNVBAsM
-Emh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UEAwwXUmlzZXVwIE5ldHdvcmtzIFJv
-b3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC76J4ciMJ8Sg0m
-TP7DF2DT9zNe0Csk4myoMFC57rfJeqsAlJCv1XMzBmXrw8wq/9z7XHv6n/0sWU7a
-7cF2hLR33ktjwODlx7vorU39/lXLndo492ZBhXQtG1INMShyv+nlmzO6GT7ESfNE
-LliFitEzwIegpMqxCIHXFuobGSCWF4N0qLHkq/SYUMoOJ96O3hmPSl1kFDRMtWXY
-iw1SEKjUvpyDJpVs3NGxeLCaA7bAWhDY5s5Yb2fA1o8ICAqhowurowJpW7n5ZuLK
-5VNTlNy6nZpkjt1QycYvNycffyPOFm/Q/RKDlvnorJIrihPkyniV3YY5cGgP+Qkx
-HUOT0uLA6LHtzfiyaOqkXwc4b0ZcQD5Vbf6Prd20Ppt6ei0zazkUPwxld3hgyw58
-m/4UIjG3PInWTNf293GngK2Bnz8Qx9e/6TueMSAn/3JBLem56E0WtmbLVjvko+LF
-PM5xA+m0BmuSJtrD1MUCXMhqYTtiOvgLBlUm5zkNxALzG+cXB28k6XikXt6MRG7q
-hzIPG38zwkooM55yy5i1YfcIi5NjMH6A+t4IJxxwb67MSb6UFOwg5kFokdONZcwj
-shczHdG9gLKSBIvrKa03Nd3W2dF9hMbRu//STcQxOailDBQCnXXfAATj9pYzdY4k
-ha8VCAREGAKTDAex9oXf1yRuktES4QIDAQABo2AwXjAdBgNVHQ4EFgQUC4tdmLVu
-f9hwfK4AGliaet5KkcgwDgYDVR0PAQH/BAQDAgIEMAwGA1UdEwQFMAMBAf8wHwYD
-VR0jBBgwFoAUC4tdmLVuf9hwfK4AGliaet5KkcgwDQYJKoZIhvcNAQENBQADggIB
-AGzL+GRnYu99zFoy0bXJKOGCF5XUXP/3gIXPRDqQf5g7Cu/jYMID9dB3No4Zmf7v
-qHjiSXiS8jx1j/6/Luk6PpFbT7QYm4QLs1f4BlfZOti2KE8r7KRDPIecUsUXW6P/
-3GJAVYH/+7OjA39za9AieM7+H5BELGccGrM5wfl7JeEz8in+V2ZWDzHQO4hMkiTQ
-4ZckuaL201F68YpiItBNnJ9N5nHr1MRiGyApHmLXY/wvlrOpclh95qn+lG6/2jk7
-3AmihLOKYMlPwPakJg4PYczm3icFLgTpjV5sq2md9bRyAg3oPGfAuWHmKj2Ikqch
-Td5CHKGxEEWbGUWEMP0s1A/JHWiCbDigc4Cfxhy56CWG4q0tYtnc2GMw8OAUO6Wf
-Xu5pYKNkzKSEtT/MrNJt44tTZWbKV/Pi/N2Fx36my7TgTUj7g3xcE9eF4JV2H/sg
-tsK3pwE0FEqGnT4qMFbixQmc8bGyuakr23wjMvfO7eZUxBuWYR2SkcP26sozF9PF
-tGhbZHQVGZUTVPyvwahMUEhbPGVerOW0IYpxkm0x/eaWdTc4vPpf/rIlgbAjarnJ
-UN9SaWRlWKSdP4haujnzCoJbM7dU9bjvlGZNyXEekgeT0W2qFeGGp+yyUWw8tNsp
-0BuC1b7uW/bBn/xKm319wXVDvBgZgcktMolak39V7DVO
------END CERTIFICATE----- \ No newline at end of file
+MIIBYjCCAQigAwIBAgIBATAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxMRUFQIFJv
+b3QgQ0EwHhcNMjExMTAyMTkwNTM3WhcNMjYxMTAyMTkxMDM3WjAXMRUwEwYDVQQD
+EwxMRUFQIFJvb3QgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQxOXBGu+gf
+pjHzVteGTWL6XnFxtEnKMFpKaJkA/VOHmESzoLsZRQxt88GssxaqC01J17idQiqv
+zgNpedmtvFtyo0UwQzAOBgNVHQ8BAf8EBAMCAqQwEgYDVR0TAQH/BAgwBgEB/wIB
+ATAdBgNVHQ4EFgQUZdoUlJrCIUNFrpffAq+LQjnwEz4wCgYIKoZIzj0EAwIDSAAw
+RQIgfr3w4tnRG+NdI3LsGPlsRktGK20xHTzsB3orB0yC6cICIQCB+/9y8nmSStfN
+VUMUyk2hNd7/kC8nL222TTD7VZUtsg==
+-----END CERTIFICATE-----
diff --git a/app/src/test/resources/v4/generictest.cert b/app/src/test/resources/v4/generictest.cert
new file mode 100644
index 00000000..a06b2921
--- /dev/null
+++ b/app/src/test/resources/v4/generictest.cert
@@ -0,0 +1,49 @@
+-----BEGIN CERTIFICATE-----
+MIIDbzCCAlegAwIBAgIRAJ13v8he4G1gJrAmxoaq9V4wDQYJKoZIhvcNAQELBQAw
+FjEUMBIGA1UEAwwLRWFzeS1SU0EgQ0EwHhcNMjQwNjI0MjIyMzAxWhcNMjYwOTI3
+MjIyMzAxWjArMSkwJwYDVQQDDCB5UnhiNmQwdnRiZW1UYW51NHJ2MkVIMHEzSEhZ
+ZzBxNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMdIIe89GksectVQ
+i52g660W4Fvs7fQ6DecXxiEbTu4kfxo3WmxmsdI6h4BFf+3SOiUHVWYNf1IjKR+V
+mG5oCybSjz0GFzcBj+SjkhM4lggkQKhRPzjqWDL2GTTrGoKHWdcV6tCcphCB3Zgz
+o5ObuW0SEYACHJ535H9QrDvB75mMervd0ZHdmDCtJgxze6rwrNMGrU28CIOUFIM7
+uhobdcNvFFlZ/kTzPC0/UTNWS7TwT8IhAlSYN7A7hX5cb1H/PK7TrBzux37VvRt4
+TUPiMpiUi0Ha6pNxnNtNX0jbQhPJMFA69ZD3R+ViiET63/J2ZdC5w+t3JkYxJj+K
+9PcjRX8CAwEAAaOBojCBnzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRD9M3aA0xwS49h
+tPZ5cBIIZUVNqDBRBgNVHSMESjBIgBQfgnyX5vtKuv9mzvmKnXmTH8Cc2KEapBgw
+FjEUMBIGA1UEAwwLRWFzeS1SU0EgQ0GCFFgV0SauPQ7erBxVTSSB8oskg1EPMBMG
+A1UdJQQMMAoGCCsGAQUFBwMCMAsGA1UdDwQEAwIHgDANBgkqhkiG9w0BAQsFAAOC
+AQEAPmlNsl5Z5qeRzUDhzddw5c4fOacTgmHbS0jces6suoE81A8al6lbpY0g3vZa
+nDK7V/U/+M3XLzyQg4WQTR/bRSX1flDEy7KABUjt9N2m3fAirRnErJhEWPT+s4N6
+HpfRWQJ+z6H0Pp0uh6U+13KjuYVG1q/+MJ+7cF5UvLW1WZQ2eDOjf1Glt7tUW2ZZ
+TOfKfeyRHZlnU2ChfqOK2IoN7u3Ofe3ve6ZYSTKXVdaDUMJ9AxOU5m7SqBPEexBM
+tCXkJuFyPufFDwgmRzI/ohVHF8ZJUIat5jYnrHEJPaneoFdT+2QtkfLLzaGHiRnE
+Od22VQH8UFSKu7odZF8sHBGSVA==
+-----END CERTIFICATE-----
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDHSCHvPRpLHnLV
+UIudoOutFuBb7O30Og3nF8YhG07uJH8aN1psZrHSOoeARX/t0jolB1VmDX9SIykf
+lZhuaAsm0o89Bhc3AY/ko5ITOJYIJECoUT846lgy9hk06xqCh1nXFerQnKYQgd2Y
+M6OTm7ltEhGAAhyed+R/UKw7we+ZjHq73dGR3ZgwrSYMc3uq8KzTBq1NvAiDlBSD
+O7oaG3XDbxRZWf5E8zwtP1EzVku08E/CIQJUmDewO4V+XG9R/zyu06wc7sd+1b0b
+eE1D4jKYlItB2uqTcZzbTV9I20ITyTBQOvWQ90flYohE+t/ydmXQucPrdyZGMSY/
+ivT3I0V/AgMBAAECggEADxlOhOdexiFE9xeWtHc8VA1/K0fc0ZvScNdyyhBdHxsB
+zFU0UzFGuNR5bsUVR8odYK/ZDxXntyv10jBN79OPQL5EXw3GlYLXSa4BA9bOO0iv
+43Dgdun+i8Hsr/8+L3Sc4HiHJY4w4OBOD1meQ7FRT8vGKqo+S91uoRzWJ+LuSfZh
+8d7vMCvd1qX2p2wLW/GEB8UPim/6elnoXtr0iqjfZzZHKuMoWp0HYuyjdN6OC/UK
+38GyFtix2soIUDSP5hHk2vLVUq0RbEuNwz4Gf7W7YLMWAjUBK8qh3WM2HaPFwqv6
+yppN7jCzOc0Wi41C8sEbo7Ct0WqLrkG2qQ2Eo8/y1QKBgQD5vsoI0jl6wfjvlrjL
+3fR7u9joFGbXRBtu5QPwqozIXnxU5VBZvZ5Q/mgG9XfSWrUizOTHZP7qViPsHTqB
+f3paY53946wVrx2H2aDl8HagblDfJMxKVDBvSqoXfyVTQYYzk+EzyAQnddzArcQ4
+Egpl5Sa3qruEgs4/nZDsWcw17QKBgQDMRc2JVGBlYLDlx/NOYwTNjCdwVmjDG57C
+z5DUNHqX1vRTlxQsY8pCcYbrtr2pwz7e3IK9mg2gluhyNejTXhC7lWN/5n5QTQBO
+RbF40SCAVJFUjofW++g8fUZTREpKJ7qMAT/6NoZSmWvUSr2TvkoBEJnNHjKXfPDd
+KJRbFjU7mwKBgQCb8om/xl3EDLmAChKsopUWam8ARDUPeGTU80ZpkmXEfFOQw3xP
+/TqNgr68kazXenKfH2hAJg2TkGRv/LRaxppFNO0j63W6OJXtDXUOAABjH196Z0T1
+qOpxpCLf9zH8ce716AJ4zg3iAhPtcNQU2xcJF3T8vSzIitF1IdOr8kq05QKBgQCN
+keL8xkl4eSagWY86SE3P1s6OgJRihAXnpcsOBsDf8s2qEQ6eJRrMKboEKsYPnY05
+D0Jc/SNspKm8XbhapNqb5tDql2f7ZyJLHOn+fZE032dJXu6uBC/TnE7c7ns+IYKb
+/VHFq3w0Srf8jUAN4NeRHVw6WC9f5etYmwMWjbGe+QKBgQCJKVPdIy3dkjwdul3Y
+BEBDYkxDj34dGDWlfwddtMgCaVBbSlvwkb4h/HgaD7gBf/GhgYR1UAXafoRCQCE0
+tq/bQhRZ+Xin7qhVHi4FS4ig91TQHUwFaYQVrpEbWZSCgE6NGAbsbkp4uKOY1WDd
+igAuQb29cbkbSO5F7lsQjRrmAw==
+-----END PRIVATE KEY-----
diff --git a/app/src/test/resources/v4/riseup.net.cert b/app/src/test/resources/v4/riseup.net.cert
index 5181a66b..68f1a31d 100644
--- a/app/src/test/resources/v4/riseup.net.cert
+++ b/app/src/test/resources/v4/riseup.net.cert
@@ -1,43 +1,43 @@
-----BEGIN RSA PRIVATE KEY-----
-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
+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
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
-MIICdjCCAh2gAwIBAgIQEvFlsBeZpYERAhfR59N3ijAKBggqhkjOPQQDAjAzMTEw
+MIICdzCCAh2gAwIBAgIQAh39shpuOn8d0h0Ce/7QdDAKBggqhkjOPQQDAjAzMTEw
LwYDVQQDDChMRUFQIFJvb3QgQ0EgKGNsaWVudCBjZXJ0aWZpY2F0ZXMgb25seSEp
-MB4XDTI0MDIxNzE2MDgxNVoXDTI0MDMyMzE2MDgxNVowFDESMBAGA1UEAxMJVU5M
-SU1JVEVEMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoubdIK609+1L
-geOFWDt++yaizzQRgmYWGfV7MtK3H5FB4BG9dE0Y6Psfs1T9wgtZ1qf4gI0njpS7
-m5PlwDFkBCbbQ+frhSVwi9tJoQo8Npvc9VU8+0h1JTyySPNgKKrXzOTtkRgnVenf
-5HLJoBsMOyqlFkcoV3Rw3ca+n/pw87iriCyYHdQkh/i/psCG46s+p1O/C41dRoO4
-DQonCB68K0kA/EUM9KpTHxAw0f2Ug0X31st/z1apnCJn2LdzlW3qcgkrJgWJ0VkX
-1tImjuepfqYHme0m1yalavgUW27Hargl/MjY420BDA+hVyxfq0BpXCDUb8JmHvL5
-j7g+7SR4BwIDAQABo2cwZTAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYB
-BQUHAwIwHQYDVR0OBBYEFIPsBEktjxealc2usc6QdNNK2xHFMB8GA1UdIwQYMBaA
-FH1KYtj/K0nEebaisdyOPmMHXKj+MAoGCCqGSM49BAMCA0cAMEQCIHMF70zfZQ7Y
-lcz0IDjFbHO/Xd+Mh0QSdcz6lU4OdXO4AiABPaZ/DUa2qBX8AWO4itwTEQYroeF8
-0onH42V60UWxEA==
+MB4XDTI0MDQwODEwNDI0OFoXDTI0MDUxMzEwNDI0OFowFDESMBAGA1UEAxMJVU5M
+SU1JVEVEMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0OFWdcdiZtUf
+FQuADyIZyuFcIS5HIJIVaVY+D9g5bNqeqp6SxvtxTxykmm4A68Huwp99J20FWVUe
+NcPkscjtDxyWAcN9QcDFpgiYd0cQAsSDWX86sFd9pTzrWzO19kDfoHyMRlOEh0PA
+ND5g/qTUPCDQzBudnf+0KwsxsoZUguRpWl7JjApGSWkuVH9gUmHSZFTX4U5jTgs3
+OVs9uih8aGtUlJPrH+1vlcQPMCSFopnziwq8OlTrunwUl7E2JN8E304vxZb6OrVo
+3VBqaVcY0emI0BFgqLDRokeDfhJfeLFV9IzXmI+e7K9e18Wx/8Ne8z2NfZx1usDE
+zT0PKZVHqQIDAQABo2cwZTAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYB
+BQUHAwIwHQYDVR0OBBYEFETwjXTp5v7YT0/Xp9Nt2HpZcOzfMB8GA1UdIwQYMBaA
+FH1KYtj/K0nEebaisdyOPmMHXKj+MAoGCCqGSM49BAMCA0gAMEUCIQCMavb+KPlg
+gdx7YX0wllm3hP/06rdnGsljxCwJAtBztgIgd1EHzAYmWQ2pmcW3/8utGdCj+41x
+fOUCgjLYY1ww/Sw=
-----END CERTIFICATE-----
diff --git a/app/src/test/resources/v4/riseup_eipservice_for_geoip_v4.json b/app/src/test/resources/v4/riseup_eipservice_for_geoip_v4.json
index 76fbea52..f3ce4b5f 100644
--- a/app/src/test/resources/v4/riseup_eipservice_for_geoip_v4.json
+++ b/app/src/test/resources/v4/riseup_eipservice_for_geoip_v4.json
@@ -9,7 +9,8 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "tcp",
+ "udp"
],
"ports":[
"443"
@@ -44,7 +45,8 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "tcp",
+ "udp"
],
"ports":[
"443"
@@ -66,7 +68,8 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "tcp",
+ "udp"
],
"ports":[
"443"
@@ -88,7 +91,8 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "tcp",
+ "udp"
],
"ports":[
"443"
@@ -123,7 +127,8 @@
{
"type":"openvpn",
"protocols":[
- "tcp"
+ "tcp",
+ "udp"
],
"ports":[
"443"