From db1e1a2045a2e6456d54765be3cf95186ce987f7 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 24 May 2019 18:01:03 +0200 Subject: squashed commit for Pluggable Transports * implement handling of different provider API version (v1 and v2) * detect provider's obfs support * shapeshifter-dispatcher installation * necessary changes to control shapeshifter-dispatcher from Bitmask * route openvpn traffic over shapeshifter-dispatcher --- .../custom/assets/ptdemo.bitmask.eip-service.json | 64 +++ app/src/custom/assets/ptdemo.bitmask.net.json | 41 ++ app/src/custom/assets/ptdemo.bitmask.secrets.json | 5 + .../main/java/de/blinkt/openvpn/VpnProfile.java | 33 +- .../java/de/blinkt/openvpn/core/ConfigParser.java | 56 ++- .../blinkt/openvpn/core/ConnectionInterface.java | 15 + .../java/de/blinkt/openvpn/core/NativeUtils.java | 13 +- .../de/blinkt/openvpn/core/OpenVPNService.java | 44 +- .../openvpn/core/OpenVpnManagementThread.java | 16 +- .../blinkt/openvpn/core/connection/Connection.java | 207 +++++++++ .../openvpn/core/connection/Obfs4Connection.java | 83 ++++ .../openvpn/core/connection/OpenvpnConnection.java | 13 + .../main/java/se/leap/bitmaskclient/Constants.java | 18 + .../java/se/leap/bitmaskclient/StartActivity.java | 85 +++- .../java/se/leap/bitmaskclient/eip/Gateway.java | 73 +-- .../se/leap/bitmaskclient/eip/GatewaySelector.java | 2 +- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 41 +- .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 177 ++++++-- .../pluggableTransports/BinaryInstaller.java | 204 +++++++++ .../pluggableTransports/Dispatcher.java | 229 ++++++++++ .../testutils/TestSetupHelper.java | 3 + .../bitmaskclient/eip/VpnConfigGeneratorTest.java | 501 ++++++++++++++++++++- .../leap/bitmaskclient/testutils/MockHelper.java | 12 + app/src/test/resources/openvpnConfigs/tcp_udp.ovpn | 117 +++++ app/src/test/resources/openvpnConfigs/udp_tcp.ovpn | 117 +++++ .../test/resources/ptdemo.bitmask.eip-service.json | 64 +++ .../resources/ptdemo_pt_tcp_udp.eip-service.json | 65 +++ .../resources/ptdemo_pt_udp_tcp.eip-service.json | 65 +++ 28 files changed, 2218 insertions(+), 145 deletions(-) create mode 100644 app/src/custom/assets/ptdemo.bitmask.eip-service.json create mode 100644 app/src/custom/assets/ptdemo.bitmask.net.json create mode 100644 app/src/custom/assets/ptdemo.bitmask.secrets.json create mode 100644 app/src/main/java/de/blinkt/openvpn/core/ConnectionInterface.java create mode 100644 app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java create mode 100644 app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java create mode 100644 app/src/main/java/de/blinkt/openvpn/core/connection/OpenvpnConnection.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/pluggableTransports/BinaryInstaller.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java create mode 100644 app/src/test/resources/openvpnConfigs/tcp_udp.ovpn create mode 100644 app/src/test/resources/openvpnConfigs/udp_tcp.ovpn create mode 100644 app/src/test/resources/ptdemo.bitmask.eip-service.json create mode 100644 app/src/test/resources/ptdemo_pt_tcp_udp.eip-service.json create mode 100644 app/src/test/resources/ptdemo_pt_udp_tcp.eip-service.json (limited to 'app/src') diff --git a/app/src/custom/assets/ptdemo.bitmask.eip-service.json b/app/src/custom/assets/ptdemo.bitmask.eip-service.json new file mode 100644 index 00000000..22bcb605 --- /dev/null +++ b/app/src/custom/assets/ptdemo.bitmask.eip-service.json @@ -0,0 +1,64 @@ +{ + "gateways":[ + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"obfs4", + "protocols":[ + "tcp" + ], + "ports":[ + "23049" + ], + "options": { + "cert": "2p8QUt36lBAJxj2x8XLj5NYOuenqi6w7RUr88LIcZVSgADXipj1tMs9mzLKzgDMbx02ERA", + "iat-mode": "0" + } + }, + { + "type":"openvpn", + "protocols":[ + "tcp" + ], + "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":2 +} \ No newline at end of file diff --git a/app/src/custom/assets/ptdemo.bitmask.net.json b/app/src/custom/assets/ptdemo.bitmask.net.json new file mode 100644 index 00000000..ff6a9620 --- /dev/null +++ b/app/src/custom/assets/ptdemo.bitmask.net.json @@ -0,0 +1,41 @@ +{ + "api_uri": "https://api.demo.bitmask.net:4430", + "api_version": "1", + "ca_cert_fingerprint": "SHA256: 0f17c033115f6b76ff67871872303ff65034efe7dd1b910062ca323eb4da5c7e", + "ca_cert_uri": "https://demo.bitmask.net/ca.crt", + "default_language": "en", + "description": { + "el": "demo.bitmask.net allows you to test the Bitmask application. User accounts may be periodically deleted.", + "en": "demo.bitmask.net allows you to test the Bitmask application. User accounts may be periodically deleted.", + "es": "demo.bitmask.net allows you to test the Bitmask application. User accounts may be periodically deleted." + }, + "domain": "demo.bitmask.net", + "enrollment_policy": "open", + "languages": [ + "de", + "en" + ], + "name": { + "de": "Bitmask Pluggable Transports", + "en": "Bitmask Pluggable Transports" + }, + "service": { + "allow_anonymous": true, + "allow_free": true, + "allow_limited_bandwidth": false, + "allow_paid": false, + "allow_registration": true, + "allow_unlimited_bandwidth": true, + "bandwidth_limit": 102400, + "default_service_level": 1, + "levels": { + "1": { + "description": "Please donate.", + "name": "free" + } + } + }, + "services": [ + "openvpn" + ] +} \ No newline at end of file diff --git a/app/src/custom/assets/ptdemo.bitmask.secrets.json b/app/src/custom/assets/ptdemo.bitmask.secrets.json new file mode 100644 index 00000000..4f81b16b --- /dev/null +++ b/app/src/custom/assets/ptdemo.bitmask.secrets.json @@ -0,0 +1,5 @@ +{ + "ca_cert":"-----BEGIN CERTIFICATE-----\nMIID9zCCAt+gAwIBAgIJAN0nU8cxAj3EMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV\nBAsTAlBUMRswGQYDVQQDExJjaG9sbGEuYml0bWFzay5uZXQxCzAJBgNVBCkTAlBU\nMSEwHwYJKoZIhvcNAQkBFhJrd2Fkcm9uYXV0QGxlYXAuc2UwHhcNMTkwMjE5MDk0\nMDQ4WhcNMjAwMjE5MDk0MDQ4WjBaMQswCQYDVQQLEwJQVDEbMBkGA1UEAxMSY2hv\nbGxhLmJpdG1hc2submV0MQswCQYDVQQpEwJQVDEhMB8GCSqGSIb3DQEJARYSa3dh\nZHJvbmF1dEBsZWFwLnNlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\ny3mhthCb6tunc4HWsX4UWgBld7H6WSOmJHOCEBjy4WZUTI9/AWA/j9pwf1WD8HKV\nxCND2Cg1j1Xc3wfTt0wJTbBPO7/chDpNlStW1KpcbiZPfkIumkqq5XNUTjOrleEm\neqqCtPvqVUyuYnGlE5dWIO3i9w1/cxhx6vi8zlsCoS1VWPdCDJvMW+9jPBL+kFe4\nF7k12lGy8t29/i4/mbzLkjAV0ZfR+S0w2hWZ1jXvzJdJQ+PP9L63hVxHQ5sUSDn9\n3SWUV7y39rHwXZdlttOE0aswvvfPlqrbD7n42mhlgySkpvXyMBkBrwIh5TnGXZ/B\nTtkPjnYCaiRXseZGrNnWhwIDAQABo4G/MIG8MB0GA1UdDgQWBBQKWWxEDacg7JAg\nuu4OJn2ZCLt69DCBjAYDVR0jBIGEMIGBgBQKWWxEDacg7JAguu4OJn2ZCLt69KFe\npFwwWjELMAkGA1UECxMCUFQxGzAZBgNVBAMTEmNob2xsYS5iaXRtYXNrLm5ldDEL\nMAkGA1UEKRMCUFQxITAfBgkqhkiG9w0BCQEWEmt3YWRyb25hdXRAbGVhcC5zZYIJ\nAN0nU8cxAj3EMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ2L7xwP\nkushZPh1l3hpfs/Em0j18oSEkvsPnm8C/o7MSqWR8zN4ehJBzUdjl7HGZGNL+AEO\nO57TDRyQ6MOATnG3DIi+6mud+XjKIPnKK3+ZeB/+UIeScB7PmiDdlXlM27s+d2mK\nEszgtBnzvI3+NRi8ub3IaeYqKnsEWNki/wJFx04fWqvjQXbGsJfWgwJi9jpJm2BT\nJ9gztPM4Hz1pTEWLqNxjyKmq9uMj8itGIiKWwbMXCuCk096U9UXM/fzs5LsL3bC7\n2oZ61s2Z2Z2BWObEMhtl8PgKX08t6ljhKBTN1l6O8VvyNwB45z8x+XEKw8SMDCeB\nS7HFRYge19Wm5hA=\n-----END CERTIFICATE-----\n", + "cert":"-----BEGIN CERTIFICATE-----\nMIIC6jCCAdICCQDcV1xCQ6eNYDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQLEwJQ\nVDEbMBkGA1UEAxMSY2hvbGxhLmJpdG1hc2submV0MQswCQYDVQQpEwJQVDEhMB8G\nCSqGSIb3DQEJARYSa3dhZHJvbmF1dEBsZWFwLnNlMB4XDTE5MDIxOTEwMTUxOVoX\nDTIxMTIxMDEwMTUxOVowFDESMBAGA1UEAwwJVU5MSU1JVEVEMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmm4WGL3Rf9keZU8AIfBPoDZ81t747UkBeW5y\nskTixdcw8ryP11Lx2LdN6C2srYN1U6ss8qq0FnQDCZK7+kP5fr3qgR8OI+nrbgaP\nBwcpX3S5E1LK2ho9NUp9wDkZgD7oX3GhvEOrTdGGLSS9DdnUEyZqR6WhQ4MyKbQY\nbRJdslnXyrVW0ZR2XzcSXe8SfPhgmTj1b/rQfPdZ+C8FuuTbb+AWHV7sLlPfcx3/\nahk9bZ42/nhU1v1l1k7stKJLpK426/CpP1tzpbwKClPodntdIGgnyJk/QSTheIN+\nOjeB1MJ8VglQ/RRxnhZf4BF2UVq32SQAY+hY6WiUDDtIljkhmQIDAQABMA0GCSqG\nSIb3DQEBCwUAA4IBAQAo6BGmPdqeqkIMtrxE+NpvVIdInAw1weOKdnOcI0vVcWDF\nZ6gm7VAlb6DVN52JqOAkafrwzIMLH2/7AyQ9pHpL5pf8php9yzwLWjtWW1HO2R61\nS0RAdSJbpoksRKR0BBd7mOjqMLfU7a9mnXBMT/DFyOexX94UIcj+f8kuJZDziURN\nPIoHgxX14synhgKFZ7Xae9F3l/B48QWilrMqKXvgk09LJDEJ1jem7rYZ/9pwKXmx\nkMMk/vsCmUpd4bJFBK4RLeieUG6NBAaxz8IHha4J+8PyKjHs4GnIFtrFKv313g2b\niStrXOHaFBslotZEJsRKYV++/z6ttBbExKx2M+9V\n-----END CERTIFICATE-----\n", + "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAmm4WGL3Rf9keZU8AIfBPoDZ81t747UkBeW5yskTixdcw8ryP\n11Lx2LdN6C2srYN1U6ss8qq0FnQDCZK7+kP5fr3qgR8OI+nrbgaPBwcpX3S5E1LK\n2ho9NUp9wDkZgD7oX3GhvEOrTdGGLSS9DdnUEyZqR6WhQ4MyKbQYbRJdslnXyrVW\n0ZR2XzcSXe8SfPhgmTj1b/rQfPdZ+C8FuuTbb+AWHV7sLlPfcx3/ahk9bZ42/nhU\n1v1l1k7stKJLpK426/CpP1tzpbwKClPodntdIGgnyJk/QSTheIN+OjeB1MJ8VglQ\n/RRxnhZf4BF2UVq32SQAY+hY6WiUDDtIljkhmQIDAQABAoIBAQCZ4iLgqp2NMTRJ\nrUwrhYRC2KjTkEIqaLowX6+pFl2G2STsbJtE7GEUG6xlNMZB7KHIKuVSNmnXiejQ\n7EemXX/LHMIFwoVboie4bo6taSR/+xbFO5XpeYYOiVj/Z6aSlZ0GJnwM1r1ngOac\nK2S73ZinMHttQ42LcbtVtSE15rw5ECNG7I0LF1SUOntorWPFh/wO6o2qDHEMoo/2\nvWc4C9TT79md2dTGs/jQql5sVwiKu+1EQdIY4ihmZ6eA3dww7Irk0KUVgt/2X0Al\nBlLvwGkDZxUAl91/7eLj5P+nKS8FzDSxmQQsz8hBUljWDJTJ3kQx5A0IzS9HTb98\nDuZELQ+RAoGBAMvMVsoJ2XtC3Q8TIjvxEqt1qD43MIgDSqAGCNnkcICuNlMbdxZu\nqoHB6ray1e6ydQKlvwtcehADLK1UCvQHQ2UqFfOy4/gTadBVYnGVu9/RNHlXXbQY\nNbyKRr2IuMBTBgCFyabSqbOZiWsrWoA3eVpbf1OmnBxnrv6OOz/AgecFAoGBAMH8\nhw9d7CHKskVLMmW9L20Roewq9rN1IgQu1ZAkg73EPGfG4iD5AVyTjlnM+HBKrTx7\n4ezLLN2EAswXCpyR2qbZx8KNCws/uHp1GGII3Vd7QVZcE5YC7nd/9lugI0HCe63Y\nl3uimjvN8xW0F/vPlUTDLCsTccBHI7FzbBsHDmyFAoGACMwYTv5f2fdH7Zeo2aeN\nY8NfcNgXCzgBJ6k7BpTa2mMqyymbWWeLirBhPmO34mbnsCaReZ8TUc+hRRYkpuYN\nXbeUXQGy34mO/sRAzKBnDMFOH5LK47RL1Yiuhw3406yBzNH5o27ijnMpQGwNqw05\n+tGKTIUbpgo/vpNLMXRQ5zUCgYAgKO53NLn+DC2r4UCUr12adm7iyWim7cda7CzJ\nvdP9dPgSuF0q3D1GjMvvxVR2wVqhCWS2LiTdAJK6JSPEO0YFnVtJvLpU/hZmbt1A\n+3k+lJeLaq5wk0HXm+ZK4GyX7Vc1xg+vFpD9UzJ2qanEPHDhun2rEoksOF8Jfzov\n7OaORQKBgHGPL8kp2v0IVwkY2a6Llr8i0HBBHNtgF/hgqP0qGO2u3F6Yi4Ly6Mng\n/odnAGV5KZIlis/MaDvPP4MohCgwuDq96V4yUQcG6iQlJa++p6owj5TUXMSdsYTi\n6IJ+tJLLlHg59oxhBBCKORxres2ht3d0gw12N52OvdoIg/bUbW0m\n-----END RSA PRIVATE KEY-----" +} \ No newline at end of file diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index 7b9003aa..9f18b8ed 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -5,6 +5,11 @@ package de.blinkt.openvpn; +import de.blinkt.openvpn.core.connection.Connection; +import de.blinkt.openvpn.core.connection.OpenvpnConnection; +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.BuildConfig; + import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; @@ -189,7 +194,7 @@ public class VpnProfile implements Serializable, Cloneable { mProfileVersion = CURRENT_PROFILE_VERSION; mConnections = new Connection[1]; - mConnections[0] = new Connection(); + mConnections[0] = new OpenvpnConnection(); mLastUsed = System.currentTimeMillis(); } @@ -314,8 +319,8 @@ public class VpnProfile implements Serializable, Cloneable { } if (mProfileVersion < 7) { for (Connection c : mConnections) - if (c.mProxyType == null) - c.mProxyType = Connection.ProxyType.NONE; + if (c.getProxyType() == null) + c.setProxyType(Connection.ProxyType.NONE); } mProfileVersion = CURRENT_PROFILE_VERSION; @@ -324,12 +329,12 @@ public class VpnProfile implements Serializable, Cloneable { private void moveOptionsToConnection() { mConnections = new Connection[1]; - Connection conn = new Connection(); + Connection conn = new OpenvpnConnection(); - conn.mServerName = mServerName; - conn.mServerPort = mServerPort; - conn.mUseUdp = mUseUdp; - conn.mCustomConfiguration = ""; + conn.setServerName(mServerName); + conn.setServerPort(mServerPort); + conn.setUseUdp(mUseUdp); + conn.setCustomConfiguration(""); mConnections[0] = conn; @@ -425,7 +430,7 @@ public class VpnProfile implements Serializable, Cloneable { if (canUsePlainRemotes) { for (Connection conn : mConnections) { - if (conn.mEnabled) { + if (conn.isEnabled()) { cfg.append(conn.getConnectionBlock(configForOvpn3)); } } @@ -586,7 +591,7 @@ public class VpnProfile implements Serializable, Cloneable { if (mAuthenticationType != TYPE_STATICKEYS) { if (mCheckRemoteCN) { if (mRemoteCN == null || mRemoteCN.equals("")) - cfg.append("verify-x509-name ").append(openVpnEscape(mConnections[0].mServerName)).append(" name\n"); + cfg.append("verify-x509-name ").append(openVpnEscape(mConnections[0].getServerName())).append(" name\n"); else switch (mX509AuthType) { @@ -660,7 +665,7 @@ public class VpnProfile implements Serializable, Cloneable { if (!canUsePlainRemotes) { cfg.append("# Connection Options are at the end to allow global options (and global custom options) to influence connection blocks\n"); for (Connection conn : mConnections) { - if (conn.mEnabled) { + if (conn.isEnabled()) { cfg.append("\n"); cfg.append(conn.getConnectionBlock(configForOvpn3)); cfg.append("\n"); @@ -985,7 +990,7 @@ public class VpnProfile implements Serializable, Cloneable { boolean noRemoteEnabled = true; for (Connection c : mConnections) { - if (c.mEnabled) + if (c.isEnabled()) noRemoteEnabled = false; } @@ -1000,12 +1005,12 @@ public class VpnProfile implements Serializable, Cloneable { return R.string.openvpn3_pkcs12; } for (Connection conn : mConnections) { - if (conn.mProxyType == Connection.ProxyType.ORBOT || conn.mProxyType == Connection.ProxyType.SOCKS5) + if (conn.getProxyType() == Connection.ProxyType.ORBOT || conn.getProxyType() == Connection.ProxyType.SOCKS5) return R.string.openvpn3_socksproxy; } } for (Connection c : mConnections) { - if (c.mProxyType == Connection.ProxyType.ORBOT) { + if (c.getProxyType() == Connection.ProxyType.ORBOT) { if (usesExtraProxyOptions()) return R.string.error_orbot_and_proxy_options; if (!OrbotHelper.checkTorReceier(context)) 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 0148bfb7..0e9b1bc4 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java @@ -6,16 +6,24 @@ package de.blinkt.openvpn.core; import android.os.Build; -import android.support.v4.util.Pair; import android.text.TextUtils; +import android.support.v4.util.Pair; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.io.StringReader; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Vector; import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.connection.Connection; +import de.blinkt.openvpn.core.connection.OpenvpnConnection; //! Openvpn Config FIle Parser, probably not 100% accurate but close enough @@ -142,9 +150,9 @@ public class ConfigParser { String data = VpnProfile.getEmbeddedContent(inlinedata); String[] parts = data.split("\n"); if (parts.length >= 2) { - c.mProxyAuthUser = parts[0]; - c.mProxyAuthPassword = parts[1]; - c.mUseProxyAuth = true; + c.setProxyAuthUser(parts[0]); + c.setProxyAuthPassword(parts[1]); + c.setUseProxyAuth(true); } } @@ -605,7 +613,7 @@ public class ConfigParser { } - if (getOption("nobind", 0, 0) != null) + if (getOption("nobind", 0, 1) != null) np.mNobind = true; if (getOption("persist-tun", 0, 0) != null) @@ -713,8 +721,8 @@ public class ConfigParser { throw new ConfigParseError(String.format("Unknown protocol %s in proto-force", protoToDisable)); for (Connection conn : np.mConnections) - if (conn.mUseUdp == disableUDP) - conn.mEnabled = false; + if (conn.isUseUdp() == disableUDP) + conn.setEnabled(false); } // Parse OpenVPN Access Server extra @@ -763,27 +771,27 @@ public class ConfigParser { return null; } else - conn = new Connection(); + conn = new OpenvpnConnection(); Vector port = getOption("port", 1, 1); if (port != null) { - conn.mServerPort = port.get(1); + conn.setServerPort(port.get(1)); } Vector rport = getOption("rport", 1, 1); if (rport != null) { - conn.mServerPort = rport.get(1); + conn.setServerPort(rport.get(1)); } Vector proto = getOption("proto", 1, 1); if (proto != null) { - conn.mUseUdp = isUdpProto(proto.get(1)); + conn.setUseUdp(isUdpProto(proto.get(1))); } Vector connectTimeout = getOption("connect-timeout", 1, 1); if (connectTimeout != null) { try { - conn.mConnectTimeout = Integer.parseInt(connectTimeout.get(1)); + conn.setConnectTimeout(Integer.parseInt(connectTimeout.get(1))); } catch (NumberFormatException nfe) { throw new ConfigParseError(String.format("Argument to connect-timeout (%s) must to be an integer: %s", connectTimeout.get(1), nfe.getLocalizedMessage())); @@ -797,16 +805,16 @@ public class ConfigParser { if (proxy != null) { if (proxy.get(0).equals("socks-proxy")) { - conn.mProxyType = Connection.ProxyType.SOCKS5; + conn.setProxyType(Connection.ProxyType.SOCKS5); // socks defaults to 1080, http always sets port - conn.mProxyPort = "1080"; + conn.setProxyPort("1080"); } else { - conn.mProxyType = Connection.ProxyType.HTTP; + conn.setProxyType(Connection.ProxyType.HTTP); } - conn.mProxyName = proxy.get(1); + conn.setProxyName(proxy.get(1)); if (proxy.size() >= 3) - conn.mProxyPort = proxy.get(2); + conn.setProxyPort(proxy.get(2)); } Vector httpproxyauthhttp = getOption("http-proxy-user-pass", 1, 1); @@ -823,15 +831,15 @@ public class ConfigParser { // Assume that we need custom options if connectionDefault are set or in the connection specific set for (Map.Entry>> option : options.entrySet()) { if (connDefault != null || connectionOptionsSet.contains(option.getKey())) { - conn.mCustomConfiguration += getOptionStrings(option.getValue()); + conn.setCustomConfiguration(conn.getCustomConfiguration() + getOptionStrings(option.getValue())); optionsToRemove.add(option.getKey()); } } for (String o: optionsToRemove) options.remove(o); - if (!(conn.mCustomConfiguration == null || "".equals(conn.mCustomConfiguration.trim()))) - conn.mUseCustomConfig = true; + if (!(conn.getCustomConfiguration() == null || "".equals(conn.getCustomConfiguration().trim()))) + conn.setUseCustomConfig(true); // Make remotes empty to simplify code if (remotes == null) @@ -849,11 +857,11 @@ public class ConfigParser { } switch (remote.size()) { case 4: - connections[i].mUseUdp = isUdpProto(remote.get(3)); + connections[i].setUseUdp(isUdpProto(remote.get(3))); case 3: - connections[i].mServerPort = remote.get(2); + connections[i].setServerPort(remote.get(2)); case 2: - connections[i].mServerName = remote.get(1); + connections[i].setServerName(remote.get(1)); } i++; } diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConnectionInterface.java b/app/src/main/java/de/blinkt/openvpn/core/ConnectionInterface.java new file mode 100644 index 00000000..70b4b4ec --- /dev/null +++ b/app/src/main/java/de/blinkt/openvpn/core/ConnectionInterface.java @@ -0,0 +1,15 @@ +package de.blinkt.openvpn.core; + +import java.io.Serializable; + +/** + * Created by cyberta on 11.03.19. + */ + +public interface ConnectionInterface { + + String getConnectionBlock(boolean isOpenVPN3); + boolean usesExtraProxyOptions(); + boolean isOnlyRemote(); + int getTimeout(); +} diff --git a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java index 6b633c34..a66b7b51 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java +++ b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java @@ -20,6 +20,8 @@ public class NativeUtils { { if (isRoboUnitTest()) return "ROBO"; + else if (isUnitTest()) + return "JUNIT"; else return getJNIAPI(); } @@ -34,7 +36,7 @@ public class NativeUtils { public static native double[] getOpenSSLSpeed(String algorithm, int testnum); static { - if (!isRoboUnitTest()) { + if (!isRoboUnitTest() && !isUnitTest()) { System.loadLibrary("opvpnutil"); if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) System.loadLibrary("jbcrypto"); @@ -44,4 +46,13 @@ public class NativeUtils { public static boolean isRoboUnitTest() { return "robolectric".equals(Build.FINGERPRINT); } + + public static boolean isUnitTest() { + try { + Class.forName("se.leap.bitmaskclient.testutils.MockHelper"); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } } 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 82c4e1df..55a92cb0 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -42,9 +42,13 @@ import java.util.Vector; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.VpnStatus.ByteCountListener; import de.blinkt.openvpn.core.VpnStatus.StateListener; +import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.VpnNotificationManager; +import se.leap.bitmaskclient.pluggableTransports.Dispatcher; +import de.blinkt.openvpn.core.connection.Obfs4Connection; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; 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; @@ -52,6 +56,7 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_PROFILE; public class OpenVPNService extends VpnService implements StateListener, Callback, ByteCountListener, IOpenVPNServiceInternal, VpnNotificationManager.VpnServiceCallback { + public static final String TAG = OpenVPNService.class.getSimpleName(); public static final String START_SERVICE = "de.blinkt.openvpn.START_SERVICE"; public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY"; public static final String ALWAYS_SHOW_NOTIFICATION = "de.blinkt.openvpn.NOTIFICATION_ALWAYS_VISIBLE"; @@ -85,6 +90,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac private Toast mlastToast; private Runnable mOpenVPNThread; private VpnNotificationManager notificationManager; + private Dispatcher dispatcher; private static final int PRIORITY_MIN = -2; private static final int PRIORITY_DEFAULT = 0; @@ -242,6 +248,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if(isVpnRunning()) { if (getManagement() != null && getManagement().stopVPN(replaceConnection)) { if (!replaceConnection) { + if (dispatcher.isRunning()) { + dispatcher.stop(); + } VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); } return true; @@ -249,6 +258,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac return false; } else { if (!replaceConnection) { + if (dispatcher.isRunning()) { + dispatcher.stop(); + } VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); return true; } @@ -366,6 +378,36 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac /** * see change above (l. 292 ff) */ + //TODO: investigate how connections[n] with n>0 get called during vpn setup (on connection refused?) + // Do we need to check if there's any obfs4 connection in mProfile.mConnections and start + // the dispatcher here? Can we start the dispatcher at a later point of execution, e.g. when + // connections[n], n>0 gets choosen? + + VpnStatus.logInfo("Setting up dispatcher."); + Connection connection = mProfile.mConnections[0]; + + if (connection.getTransportType() == OBFS4) { + Obfs4Connection obfs4Connection = (Obfs4Connection) connection; + dispatcher = new Dispatcher(this, + obfs4Connection.getmObfs4RemoteProxyName(), + obfs4Connection.getmObfs4RemoteProxyPort(), + obfs4Connection.getmObfs4Certificate(), + obfs4Connection.getmObfs4IatMode()); + dispatcher.initSync(); + + if (dispatcher.getPort() != null && dispatcher.getPort().length() > 0) { + connection.setServerPort(dispatcher.getPort()); + Log.d(TAG, "Dispatcher running. Profile server name and port: " + + connection.getServerName() + ":" + connection.getServerPort()); + VpnStatus.logInfo("Dispatcher running. Profile server name and port: " + + connection.getServerName() + ":" + connection.getServerPort()); + } else { + Log.e(TAG, "Cannot initialize dispatcher for obfs4 connection. Shutting down."); + VpnStatus.logError("Cannot initialize dispatcher for obfs4 connection. Shutting down."); + } + } + + VpnStatus.logInfo(R.string.building_configration); VpnStatus.updateStateString("VPN_GENERATE_CONFIG", "", R.string.building_configration, ConnectionStatus.LEVEL_START); @@ -743,7 +785,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac boolean profileUsesOrBot = false; for (Connection c : mProfile.mConnections) { - if (c.mProxyType == Connection.ProxyType.ORBOT) + if (c.getProxyType() == Connection.ProxyType.ORBOT) profileUsesOrBot = true; } diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java index 4f7a5bda..91cc66bc 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -15,9 +15,10 @@ import android.os.Handler; import android.os.ParcelFileDescriptor; import android.support.annotation.NonNull; import android.support.annotation.RequiresApi; -import android.system.ErrnoException; import android.system.Os; import android.util.Log; + +import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; @@ -452,10 +453,10 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { if (mProfile.mConnections.length > connectionEntryNumber) { Connection connection = mProfile.mConnections[connectionEntryNumber]; - proxyType = connection.mProxyType; - proxyname = connection.mProxyName; - proxyport = connection.mProxyPort; - proxyUseAuth = connection.mUseProxyAuth; + proxyType = connection.getProxyType(); + proxyname = connection.getProxyName(); + proxyport = connection.getProxyPort(); + proxyUseAuth = connection.isUseProxyAuth(); // Use transient variable to remember http user/password mCurrentProxyConnection = connection; @@ -696,8 +697,8 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } else if (needed.equals("HTTP Proxy")) { if( mCurrentProxyConnection != null) { - pw = mCurrentProxyConnection.mProxyAuthPassword; - username = mCurrentProxyConnection.mProxyAuthUser; + pw = mCurrentProxyConnection.getProxyAuthPassword(); + username = mCurrentProxyConnection.getProxyAuthUser(); } } if (pw != null) { @@ -782,7 +783,6 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { boolean stopSucceed = stopOpenVPN(); if (stopSucceed) { mShuttingDown = true; - } return stopSucceed; } diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java new file mode 100644 index 00000000..f333a13e --- /dev/null +++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2012-2016 Arne Schwabe + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt + */ + +package de.blinkt.openvpn.core.connection; + +import android.text.TextUtils; + +import java.io.Serializable; +import java.util.Locale; + +public abstract class Connection implements Serializable, Cloneable { + private String mServerName = "openvpn.example.com"; + private String mServerPort = "1194"; + private boolean mUseUdp = true; + private String mCustomConfiguration = ""; + private boolean mUseCustomConfig = false; + private boolean mEnabled = true; + private int mConnectTimeout = 0; + private static final int CONNECTION_DEFAULT_TIMEOUT = 120; + private ProxyType mProxyType = ProxyType.NONE; + private String mProxyName = "proxy.example.com"; + private String mProxyPort = "8080"; + + private boolean mUseProxyAuth; + private String mProxyAuthUser = null; + private String mProxyAuthPassword = null; + + public enum ProxyType { + NONE, + HTTP, + SOCKS5, + ORBOT + } + + public enum TransportType { + OBFS4, + OPENVPN + } + + private static final long serialVersionUID = 92031902903829089L; + + + public String getConnectionBlock(boolean isOpenVPN3) { + String cfg = ""; + + // Server Address + cfg += "remote "; + cfg += mServerName; + cfg += " "; + cfg += mServerPort; + if (mUseUdp) + cfg += " udp\n"; + else + cfg += " tcp-client\n"; + + if (mConnectTimeout != 0) + cfg += String.format(Locale.US, " connect-timeout %d\n", mConnectTimeout); + + // OpenVPN 2.x manages proxy connection via management interface + if ((isOpenVPN3 || usesExtraProxyOptions()) && mProxyType == ProxyType.HTTP) + { + cfg+=String.format(Locale.US,"http-proxy %s %s\n", mProxyName, mProxyPort); + if (mUseProxyAuth) + cfg+=String.format(Locale.US, "\n%s\n%s\n\n", mProxyAuthUser, mProxyAuthPassword); + } + if (usesExtraProxyOptions() && mProxyType == ProxyType.SOCKS5) { + cfg+=String.format(Locale.US,"socks-proxy %s %s\n", mProxyName, mProxyPort); + } + + if (!TextUtils.isEmpty(mCustomConfiguration) && mUseCustomConfig) { + cfg += mCustomConfiguration; + cfg += "\n"; + } + + + return cfg; + } + + public boolean usesExtraProxyOptions() { + return (mUseCustomConfig && mCustomConfiguration.contains("http-proxy-option ")); + } + + + @Override + public Connection clone() throws CloneNotSupportedException { + return (Connection) super.clone(); + } + + public boolean isOnlyRemote() { + return TextUtils.isEmpty(mCustomConfiguration) || !mUseCustomConfig; + } + + public int getTimeout() { + if (mConnectTimeout <= 0) + return CONNECTION_DEFAULT_TIMEOUT; + else + return mConnectTimeout; + } + + public String getServerName() { + return mServerName; + } + + public void setServerName(String mServerName) { + this.mServerName = mServerName; + } + + public String getServerPort() { + return mServerPort; + } + + public void setServerPort(String serverPort) { + this.mServerPort = serverPort; + } + + public boolean isUseUdp() { + return mUseUdp; + } + + public void setUseUdp(boolean useUdp) { + this.mUseUdp = useUdp; + } + + public String getCustomConfiguration() { + return mCustomConfiguration; + } + + public void setCustomConfiguration(String customConfiguration) { + this.mCustomConfiguration = customConfiguration; + } + + public boolean isUseCustomConfig() { + return mUseCustomConfig; + } + + public void setUseCustomConfig(boolean useCustomConfig) { + this.mUseCustomConfig = useCustomConfig; + } + + public boolean isEnabled() { + return mEnabled; + } + + public void setEnabled(boolean enabled) { + this.mEnabled = enabled; + } + + public int getConnectTimeout() { + return mConnectTimeout; + } + + public void setConnectTimeout(int connectTimeout) { + this.mConnectTimeout = connectTimeout; + } + + public ProxyType getProxyType() { + return mProxyType; + } + + public void setProxyType(ProxyType proxyType) { + this.mProxyType = proxyType; + } + + public String getProxyName() { + return mProxyName; + } + + public void setProxyName(String proxyName) { + this.mProxyName = proxyName; + } + + public String getProxyPort() { + return mProxyPort; + } + + public void setProxyPort(String proxyPort) { + this.mProxyPort = proxyPort; + } + + public boolean isUseProxyAuth() { + return mUseProxyAuth; + } + + public void setUseProxyAuth(boolean useProxyAuth) { + this.mUseProxyAuth = useProxyAuth; + } + + public String getProxyAuthUser() { + return mProxyAuthUser; + } + + public void setProxyAuthUser(String proxyAuthUser) { + this.mProxyAuthUser = proxyAuthUser; + } + + public String getProxyAuthPassword() { + return mProxyAuthPassword; + } + + public void setProxyAuthPassword(String proxyAuthPassword) { + this.mProxyAuthPassword = proxyAuthPassword; + } + + public abstract TransportType getTransportType(); +} 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 new file mode 100644 index 00000000..790b8b1a --- /dev/null +++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java @@ -0,0 +1,83 @@ +package de.blinkt.openvpn.core.connection; + +import org.json.JSONObject; + +/** + * Created by cyberta on 08.03.19. + */ + +public class Obfs4Connection extends Connection { + + private static final String TAG = Obfs4Connection.class.getName(); + + + private String mObfs4RemoteProxyName = ""; + private String mObfs4RemoteProxyPort = ""; + private String mObfs4Certificate = ""; + private String mObfs4IatMode = ""; + + public Obfs4Connection() { + setDefaults(); + } + + public Obfs4Connection(Connection connection) { + mObfs4RemoteProxyName = connection.getServerName(); + setConnectTimeout(connection.getConnectTimeout()); + setCustomConfiguration(connection.getCustomConfiguration()); + setUseCustomConfig(connection.isUseCustomConfig()); + + setDefaults(); + } + + private void setDefaults() { + setUseUdp(false); + setServerName("127.0.0.1"); + setServerPort(""); + setProxyName(""); + setProxyPort(""); + setProxyAuthUser(null); + setProxyAuthPassword(null); + setProxyType(ProxyType.NONE); + setUseProxyAuth(false); + } + + public void setTransportOptions(JSONObject jsonObject) { + mObfs4Certificate = jsonObject.optString("cert"); + mObfs4IatMode = jsonObject.optString("iat-mode"); + } + + @Override + public Connection clone() throws CloneNotSupportedException { + return super.clone(); + } + + @Override + public TransportType getTransportType() { + return TransportType.OBFS4; + } + + public String getmObfs4RemoteProxyName() { + return mObfs4RemoteProxyName; + } + + public void setObfs4RemoteProxyName(String mObfs4RemoteProxyName) { + this.mObfs4RemoteProxyName = mObfs4RemoteProxyName; + } + + public String getmObfs4RemoteProxyPort() { + return mObfs4RemoteProxyPort; + } + + public void setObfs4RemoteProxyPort(String mObfs4RemoteProxyPort) { + this.mObfs4RemoteProxyPort = mObfs4RemoteProxyPort; + } + + public String getmObfs4Certificate() { + return mObfs4Certificate; + } + + public String getmObfs4IatMode() { + return mObfs4IatMode; + } + +} diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/OpenvpnConnection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/OpenvpnConnection.java new file mode 100644 index 00000000..3a3fd0c3 --- /dev/null +++ b/app/src/main/java/de/blinkt/openvpn/core/connection/OpenvpnConnection.java @@ -0,0 +1,13 @@ +package de.blinkt.openvpn.core.connection; + +/** + * Created by cyberta on 11.03.19. + */ + +public class OpenvpnConnection extends Connection { + + @Override + public TransportType getTransportType() { + return TransportType.OPENVPN; + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/Constants.java b/app/src/main/java/se/leap/bitmaskclient/Constants.java index 42df6d1d..7503d29f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/Constants.java @@ -113,4 +113,22 @@ public interface Constants { String FIRST_TIME_USER_DATE = "first_time_user_date"; + ////////////////////////////////////////////// + // JSON KEYS + ///////////////////////////////////////////// + String IP_ADDRESS = "ip_address"; + String REMOTE = "remote"; + String PORTS = "ports"; + String PROTOCOLS = "protocols"; + String CAPABILITIES = "capabilities"; + String TRANSPORT = "transport"; + String TYPE = "type"; + String OPTIONS = "options"; + String VERSION = "version"; + String NAME = "name"; + String TIMEZONE = "timezone"; + String LOCATIONS = "locations"; + String LOCATION = "location"; + String OPENVPN_CONFIGURATION = "openvpn_configuration"; + String GATEWAYS = "gateways"; } diff --git a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java index d8aca351..945429fd 100644 --- a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java @@ -25,20 +25,36 @@ import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.util.Log; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import de.blinkt.openvpn.core.Preferences; import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.eip.EipCommand; +import se.leap.bitmaskclient.utils.PreferenceHelper; +import static se.leap.bitmaskclient.BuildConfig.useDemoConfig; import static se.leap.bitmaskclient.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT; import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION; +import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED; import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION; import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; +import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY; +import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.MainActivity.ACTION_SHOW_VPN_FRAGMENT; +import static se.leap.bitmaskclient.Provider.CA_CERT; +import static se.leap.bitmaskclient.Provider.MAIN_URL; import static se.leap.bitmaskclient.utils.ConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.utils.PreferenceHelper.getSavedProviderFromSharedPreferences; import static se.leap.bitmaskclient.utils.PreferenceHelper.providerInSharedPreferences; @@ -90,6 +106,10 @@ public class StartActivity extends Activity{ // initialize app necessities VpnStatus.initLogCache(getApplicationContext().getCacheDir()); + if (useDemoConfig) { + demoSetup(); + } + prepareEIP(); } @@ -162,8 +182,8 @@ public class StartActivity extends Activity{ } private void prepareEIP() { - boolean provider_exists = providerInSharedPreferences(preferences); - if (provider_exists) { + boolean providerExists = providerInSharedPreferences(preferences); + if (providerExists) { Provider provider = getSavedProviderFromSharedPreferences(preferences); if(!provider.isConfigured()) { configureLeapProvider(); @@ -216,4 +236,65 @@ public class StartActivity extends Activity{ finish(); } + private String getInputAsString(InputStream fileAsInputStream) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(fileAsInputStream)); + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + while (line != null) { + sb.append(line); + line = br.readLine(); + } + + return sb.toString(); + } + + private void demoSetup() { + try { + //set demo data + String demoEipServiceJson = getInputAsString(getAssets().open("ptdemo.bitmask.eip-service.json")); + String secrets = getInputAsString(getAssets().open("ptdemo.bitmask.secrets.json")); + String provider = getInputAsString(getAssets().open("ptdemo.bitmask.net.json")); + + Log.d(TAG, "setup provider: " + provider); + Log.d(TAG, "setup eip json: " + demoEipServiceJson); + JSONObject secretsJson = new JSONObject(secrets); + + preferences.edit().putString(PROVIDER_EIP_DEFINITION+".demo.bitmask.net", demoEipServiceJson). + putString(PROVIDER_EIP_DEFINITION, demoEipServiceJson). + putString(CA_CERT, secretsJson.getString(CA_CERT)). + putString(PROVIDER_PRIVATE_KEY, secretsJson.getString(PROVIDER_PRIVATE_KEY)). + putString(PROVIDER_VPN_CERTIFICATE, secretsJson.getString(PROVIDER_VPN_CERTIFICATE)). + putString(Provider.KEY, provider). + putString(MAIN_URL, "https://demo.bitmask.net"). + putBoolean(PROVIDER_CONFIGURED, true).commit(); + + PreferenceHelper.getSavedProviderFromSharedPreferences(preferences); + ProviderObservable.getInstance().updateProvider(PreferenceHelper.getSavedProviderFromSharedPreferences(preferences)); + + // remove last used profiles + SharedPreferences prefs = Preferences.getDefaultSharedPreferences(this); + SharedPreferences.Editor prefsedit = prefs.edit(); + prefsedit.remove("lastConnectedProfile").commit(); + File f = new File(this.getCacheDir().getAbsolutePath() + "/android.conf"); + if (f.exists()) { + Log.d(TAG, "android.conf exists -> delete:" + f.delete()); + } + + File filesDirectory = new File(this.getFilesDir().getAbsolutePath()); + if (filesDirectory.exists() && filesDirectory.isDirectory()) { + File[] filesInDirectory = filesDirectory.listFiles(); + for (File file : filesInDirectory) { + Log.d(TAG, "delete profile: " + file.getName() + ": "+ file.delete()); + + } + } else Log.d(TAG, "file folder doesn't exist"); + + } catch (IOException e) { + e.printStackTrace(); + } catch (JSONException e) { + e.printStackTrace(); + } + + } + } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java index 55ade1ae..b1554af0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -22,11 +22,17 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; -import java.io.StringReader; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; +import static se.leap.bitmaskclient.Constants.LOCATION; +import static se.leap.bitmaskclient.Constants.LOCATIONS; +import static se.leap.bitmaskclient.Constants.NAME; +import static se.leap.bitmaskclient.Constants.OPENVPN_CONFIGURATION; +import static se.leap.bitmaskclient.Constants.TIMEZONE; +import static se.leap.bitmaskclient.Constants.VERSION; + /** * Gateway provides objects defining gateways and their metadata. * Each instance contains a VpnProfile for OpenVPN specific data and member @@ -34,6 +40,7 @@ import de.blinkt.openvpn.core.ConfigParser; * * @author Sean Leonard * @author Parménides GV + * @author cyberta */ public class Gateway { @@ -44,50 +51,57 @@ public class Gateway { private JSONObject secrets; private JSONObject gateway; - private String mName; + private String name; private int timezone; - private VpnProfile mVpnProfile; + private int apiVersion; + private VpnProfile vpnProfile; /** * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json * and create a VpnProfile belonging to it. */ - public Gateway(JSONObject eip_definition, JSONObject secrets, JSONObject gateway) { + public Gateway(JSONObject eipDefinition, JSONObject secrets, JSONObject gateway) { this.gateway = gateway; this.secrets = secrets; - generalConfiguration = getGeneralConfiguration(eip_definition); - timezone = getTimezone(eip_definition); - mName = locationAsName(eip_definition); - - mVpnProfile = createVPNProfile(); - mVpnProfile.mName = mName; + generalConfiguration = getGeneralConfiguration(eipDefinition); + timezone = getTimezone(eipDefinition); + name = locationAsName(eipDefinition); + apiVersion = getApiVersion(eipDefinition); + vpnProfile = createVPNProfile(); + if (vpnProfile != null) { + vpnProfile.mName = name; + } } - private JSONObject getGeneralConfiguration(JSONObject eip_definition) { + private JSONObject getGeneralConfiguration(JSONObject eipDefinition) { try { - return eip_definition.getJSONObject("openvpn_configuration"); + return eipDefinition.getJSONObject(OPENVPN_CONFIGURATION); } catch (JSONException e) { return new JSONObject(); } } - private int getTimezone(JSONObject eip_definition) { - JSONObject location = getLocationInfo(eip_definition); - return location.optInt("timezone"); + private int getTimezone(JSONObject eipDefinition) { + JSONObject location = getLocationInfo(eipDefinition); + return location.optInt(TIMEZONE); + } + + private int getApiVersion(JSONObject eipDefinition) { + return eipDefinition.optInt(VERSION); } - private String locationAsName(JSONObject eip_definition) { - JSONObject location = getLocationInfo(eip_definition); - return location.optString("name"); + private String locationAsName(JSONObject eipDefinition) { + JSONObject location = getLocationInfo(eipDefinition); + return location.optString(NAME); } private JSONObject getLocationInfo(JSONObject eipDefinition) { try { - JSONObject locations = eipDefinition.getJSONObject("locations"); + JSONObject locations = eipDefinition.getJSONObject(LOCATIONS); - return locations.getJSONObject(gateway.getString("location")); + return locations.getJSONObject(gateway.getString(LOCATION)); } catch (JSONException e) { return new JSONObject(); } @@ -98,18 +112,9 @@ public class Gateway { */ private VpnProfile createVPNProfile() { try { - ConfigParser cp = new ConfigParser(); - - VpnConfigGenerator vpnConfigurationGenerator = new VpnConfigGenerator(generalConfiguration, secrets, gateway); - String configuration = vpnConfigurationGenerator.generate(); - - cp.parseConfig(new StringReader(configuration)); - return cp.convertProfile(); - } catch (ConfigParser.ConfigParseError e) { - // FIXME We didn't get a VpnProfile! Error handling! and log level - e.printStackTrace(); - return null; - } catch (IOException e) { + VpnConfigGenerator vpnConfigurationGenerator = new VpnConfigGenerator(generalConfiguration, secrets, gateway, apiVersion); + return vpnConfigurationGenerator.generateVpnProfile(); + } catch (ConfigParser.ConfigParseError | IOException | CloneNotSupportedException | JSONException e) { // FIXME We didn't get a VpnProfile! Error handling! and log level e.printStackTrace(); return null; @@ -117,11 +122,11 @@ public class Gateway { } public String getName() { - return mName; + return name; } public VpnProfile getProfile() { - return mVpnProfile; + return vpnProfile; } public int getTimezone() { diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java index 2bd666bf..0ba0f207 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java @@ -36,7 +36,7 @@ public class GatewaySelector { } } - Log.e(TAG, "There are less than " + nClosest + " Gateways available."); + Log.e(TAG, "There are less than " + (nClosest + 1) + " Gateways available."); return null; } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java index 060843fd..c650938c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -30,11 +30,18 @@ import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.Provider; import se.leap.bitmaskclient.utils.PreferenceHelper; +import static se.leap.bitmaskclient.Constants.CAPABILITIES; +import static se.leap.bitmaskclient.Constants.GATEWAYS; import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.Constants.TRANSPORT; +import static se.leap.bitmaskclient.Constants.TYPE; +import static se.leap.bitmaskclient.Constants.VERSION; /** * @author parmegv @@ -88,10 +95,11 @@ public class GatewaysManager { */ void fromEipServiceJson(JSONObject eipDefinition) { try { - JSONArray gatewaysDefined = eipDefinition.getJSONArray("gateways"); + JSONArray gatewaysDefined = eipDefinition.getJSONArray(GATEWAYS); + int apiVersion = eipDefinition.getInt(VERSION); for (int i = 0; i < gatewaysDefined.length(); i++) { JSONObject gw = gatewaysDefined.getJSONObject(i); - if (isOpenVpnGateway(gw)) { + if (isOpenVpnGateway(gw, apiVersion)) { JSONObject secrets = secretsConfiguration(); Gateway aux = new Gateway(eipDefinition, secrets, gw); if (!gateways.contains(aux)) { @@ -110,12 +118,29 @@ public class GatewaysManager { * @param gateway to check * @return true if gateway is an OpenVpn gateway otherwise false */ - private boolean isOpenVpnGateway(JSONObject gateway) { - try { - String transport = gateway.getJSONObject("capabilities").getJSONArray("transport").toString(); - return transport.contains("openvpn"); - } catch (JSONException e) { - return false; + private boolean isOpenVpnGateway(JSONObject gateway, int apiVersion) { + switch (apiVersion) { + default: + case 1: + try { + String transport = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT).toString(); + return transport.contains("openvpn"); + } catch (JSONException e) { + return false; + } + case 2: + try { + JSONArray transports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT); + for (int i = 0; i < transports.length(); i++) { + JSONObject transport = transports.getJSONObject(i); + if (transport.optString(TYPE).equals("openvpn")) { + return true; + } + } + return false; + } catch (JSONException e) { + return false; + } } } 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 6f0ccf18..7f09d21e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -20,48 +20,133 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import java.io.IOException; +import java.io.StringReader; import java.util.Iterator; +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 se.leap.bitmaskclient.Provider; +import static se.leap.bitmaskclient.Constants.CAPABILITIES; +import static se.leap.bitmaskclient.Constants.IP_ADDRESS; +import static se.leap.bitmaskclient.Constants.OPTIONS; +import static se.leap.bitmaskclient.Constants.PORTS; +import static se.leap.bitmaskclient.Constants.PROTOCOLS; import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.Constants.REMOTE; +import static se.leap.bitmaskclient.Constants.TRANSPORT; +import static se.leap.bitmaskclient.Constants.TYPE; public class VpnConfigGenerator { - private JSONObject general_configuration; + private JSONObject generalConfiguration; private JSONObject gateway; private JSONObject secrets; + private JSONObject obfs4Transport; + private int apiVersion; + + private ConfigParser icsOpenvpnConfigParser = new ConfigParser(); + public final static String TAG = VpnConfigGenerator.class.getSimpleName(); private final String newLine = System.getProperty("line.separator"); // Platform new line - public VpnConfigGenerator(JSONObject general_configuration, JSONObject secrets, JSONObject gateway) { - this.general_configuration = general_configuration; + public VpnConfigGenerator(JSONObject generalConfiguration, JSONObject secrets, JSONObject gateway, int apiVersion) { + this.generalConfiguration = generalConfiguration; this.gateway = gateway; this.secrets = secrets; + this.apiVersion = apiVersion; + checkCapabilities(); } - public String generate() { - return - generalConfiguration() + public void checkCapabilities() { + + try { + switch (apiVersion) { + case 2: + JSONArray supportedTransports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT); + for (int i = 0; i < supportedTransports.length(); i++) { + JSONObject transport = supportedTransports.getJSONObject(i); + if (transport.getString(TYPE).equals("obfs4")) { + obfs4Transport = transport; + } + } + break; + default: + break; + } + + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public VpnProfile generateVpnProfile() throws IllegalStateException, + IOException, + ConfigParser.ConfigParseError, + CloneNotSupportedException, + JSONException, + NumberFormatException { + + VpnProfile profile = createOvpnProfile(); + if (supportsObfs4()) { + addPluggableTransportConnections(profile); + } + return profile; + } + + private boolean supportsObfs4(){ + return obfs4Transport != null; + } + + private void addPluggableTransportConnections(VpnProfile profile) throws JSONException, CloneNotSupportedException { + JSONArray ports = obfs4Transport.getJSONArray(PORTS); + Connection[] updatedConnections = new Connection[profile.mConnections.length + ports.length()]; + + for (int i = 0; i < ports.length(); i++) { + String port = ports.getString(i); + Obfs4Connection obfs4Connection = new Obfs4Connection(); + obfs4Connection.setObfs4RemoteProxyName(gateway.getString(IP_ADDRESS)); + obfs4Connection.setObfs4RemoteProxyPort(port); + obfs4Connection.setTransportOptions(obfs4Transport.optJSONObject(OPTIONS)); + updatedConnections[i] = obfs4Connection; + } + int k = 0; + for (int i = ports.length(); i < updatedConnections.length; i++, k++) { + updatedConnections[i] = profile.mConnections[k].clone(); + } + profile.mConnections = updatedConnections; + } + + private String getConfigurationString() { + return generalConfiguration() + newLine - + gatewayConfiguration() + + ovpnGatewayConfiguration() + newLine + secretsConfiguration() + newLine + androidCustomizations(); } + private VpnProfile createOvpnProfile() throws IOException, ConfigParser.ConfigParseError { + String configuration = getConfigurationString(); + icsOpenvpnConfigParser.parseConfig(new StringReader(configuration)); + return icsOpenvpnConfigParser.convertProfile(); + } + private String generalConfiguration() { String commonOptions = ""; try { - Iterator keys = general_configuration.keys(); + Iterator keys = generalConfiguration.keys(); while (keys.hasNext()) { String key = keys.next().toString(); commonOptions += key + " "; - for (String word : String.valueOf(general_configuration.get(key)).split(" ")) + for (String word : String.valueOf(generalConfiguration.get(key)).split(" ")) commonOptions += word + " "; commonOptions += newLine; @@ -76,41 +161,73 @@ public class VpnConfigGenerator { return commonOptions; } - private String gatewayConfiguration() { + private String ovpnGatewayConfiguration() { String remotes = ""; - String ipAddressKeyword = "ip_address"; - String remoteKeyword = "remote"; - String portsKeyword = "ports"; - String protocolKeyword = "protocols"; - String capabilitiesKeyword = "capabilities"; - + StringBuilder stringBuilder = new StringBuilder(); try { - String ip_address = gateway.getString(ipAddressKeyword); - JSONObject capabilities = gateway.getJSONObject(capabilitiesKeyword); - JSONArray ports = capabilities.getJSONArray(portsKeyword); - for (int i = 0; i < ports.length(); i++) { - String port_specific_remotes = ""; - int port = ports.getInt(i); - JSONArray protocols = capabilities.getJSONArray(protocolKeyword); - for (int j = 0; j < protocols.length(); j++) { - String protocol = protocols.optString(j); - String new_remote = remoteKeyword + " " + ip_address + " " + port + " " + protocol + newLine; - - port_specific_remotes += new_remote; - } - remotes += port_specific_remotes; + String ipAddress = gateway.getString(IP_ADDRESS); + JSONObject capabilities = gateway.getJSONObject(CAPABILITIES); + JSONArray transports = capabilities.getJSONArray(TRANSPORT); + switch (apiVersion) { + default: + case 1: + ovpnGatewayConfigApiv1(stringBuilder, ipAddress, capabilities); + break; + case 2: + ovpnGatewayConfigApiv2(stringBuilder, ipAddress, transports); + break; } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } + + remotes = stringBuilder.toString(); if (remotes.endsWith(newLine)) { remotes = remotes.substring(0, remotes.lastIndexOf(newLine)); } return remotes; } + private void ovpnGatewayConfigApiv1(StringBuilder stringBuilder, String ipAddress, JSONObject capabilities) throws JSONException { + int port; + String protocol; + + JSONArray ports = capabilities.getJSONArray(PORTS); + for (int i = 0; i < ports.length(); i++) { + port = ports.getInt(i); + JSONArray protocols = capabilities.getJSONArray(PROTOCOLS); + for (int j = 0; j < protocols.length(); j++) { + protocol = protocols.optString(j); + String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine; + stringBuilder.append(newRemote); + } + } + } + + private void ovpnGatewayConfigApiv2(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { + String port; + String protocol; + for (int i = 0; i < transports.length(); i++) { + JSONObject transport = transports.getJSONObject(i); + if (!transport.getString(TYPE).equals("openvpn")) { + continue; + } + JSONArray ports = transport.getJSONArray(PORTS); + for (int j = 0; j < ports.length(); j++) { + port = ports.getString(j); + JSONArray protocols = transport.getJSONArray(PROTOCOLS); + for (int k = 0; k < protocols.length(); k++) { + protocol = protocols.optString(k); + String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine; + stringBuilder.append(newRemote); + } + } + } + } + + private String secretsConfiguration() { try { String ca = diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/BinaryInstaller.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/BinaryInstaller.java new file mode 100644 index 00000000..0d6aa61e --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/BinaryInstaller.java @@ -0,0 +1,204 @@ +/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */ +/* See LICENSE for licensing information */ + +package se.leap.bitmaskclient.pluggableTransports; + +import android.content.Context; +import android.util.Log; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.TimeoutException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class BinaryInstaller { + + File installFolder; + Context context; + + public BinaryInstaller(Context context, File installFolder) + { + this.installFolder = installFolder; + + this.context = context; + } + + public void deleteDirectory(File file) { + if( file.exists() ) { + if (file.isDirectory()) { + File[] files = file.listFiles(); + for(int i=0; i 0) + { + + stmOut.write(buffer, 0, bytecount); + + } + + stmOut.close(); + stm.close(); + + if (zis != null) + zis.close(); + + + return true; + + } + + //copy the file from inputstream to File output - alternative impl + public static boolean copyFile (InputStream is, File outputFile) + { + + try { + if (outputFile.exists()) + outputFile.delete(); + + boolean newFile = outputFile.createNewFile(); + DataOutputStream out = new DataOutputStream(new FileOutputStream(outputFile)); + DataInputStream in = new DataInputStream(is); + + int b = -1; + byte[] data = new byte[1024]; + + while ((b = in.read(data)) != -1) { + out.write(data); + } + + if (b == -1); //rejoice + + // + out.flush(); + out.close(); + in.close(); + // chmod? + + return newFile; + + + } catch (IOException ex) { + Log.e("Binaryinstaller", "error copying binary", ex); + return false; + } + + } + + /** + * Copies a raw resource file, given its ID to the given location + * @param ctx context + * @param resid resource id + * @param file destination file + * @param mode file permissions (E.g.: "755") + * @throws IOException on error + * @throws InterruptedException when interrupted + */ + public static void copyRawFile(Context ctx, int resid, File file, String mode, boolean isZipd) throws IOException, InterruptedException + { + final String abspath = file.getAbsolutePath(); + // Write the iptables binary + final FileOutputStream out = new FileOutputStream(file); + InputStream is = ctx.getResources().openRawResource(resid); + + if (isZipd) + { + ZipInputStream zis = new ZipInputStream(is); + ZipEntry ze = zis.getNextEntry(); + is = zis; + } + + byte buf[] = new byte[1024]; + int len; + while ((len = is.read(buf)) > 0) { + out.write(buf, 0, len); + } + out.close(); + is.close(); + // Change the permissions + Runtime.getRuntime().exec("chmod "+mode+" "+abspath).waitFor(); + } + + + private void setExecutable(File fileBin) { + fileBin.setReadable(true); + fileBin.setExecutable(true); + fileBin.setWritable(false); + fileBin.setWritable(true, true); + } + +} diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java new file mode 100644 index 00000000..ac846fd9 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java @@ -0,0 +1,229 @@ +/** + * Copyright (c) 2019 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package se.leap.bitmaskclient.pluggableTransports; + +import android.content.Context; +import android.support.annotation.WorkerThread; +import android.util.Log; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.util.StringTokenizer; + + +/** + * Created by cyberta on 22.02.19. + */ + +public class Dispatcher { + private static final String ASSET_KEY = "piedispatcher"; + private static final String TAG = Dispatcher.class.getName(); + private final String remoteIP; + private final String remotePort; + private final String certificate; + private final String iatMode; + private File fileDispatcher; + private Context context; + private String port = ""; + private Thread dispatcherThread = null; + private int dipatcherPid = -1; + + public Dispatcher(Context context, String remoteIP, String remotePort, String certificate, String iatMode) { + this.context = context.getApplicationContext(); + this.remoteIP = remoteIP; + this.remotePort = remotePort; + this.certificate = certificate; + this.iatMode = iatMode; + } + + @WorkerThread + public void initSync() { + try { + fileDispatcher = installDispatcher(); + + // start dispatcher + dispatcherThread = new Thread(() -> { + try { + StringBuilder dispatcherLog = new StringBuilder(); + String dispatcherCommand = fileDispatcher.getCanonicalPath() + + " -transparent" + + " -client" + + " -state " + context.getFilesDir().getCanonicalPath() + "/state" + + " -target " + remoteIP + ":" + remotePort + + " -transports obfs4" + + " -options \"" + String.format("{\\\"cert\\\": \\\"%s\\\", \\\"iatMode\\\": \\\"%s\\\"}\"", certificate, iatMode) + + " -logLevel DEBUG -enableLogging"; + + runBlockingCmd(new String[]{dispatcherCommand}, dispatcherLog); + } catch (IOException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + }); + dispatcherThread.start(); + + // get pid of dispatcher + StringBuilder log = new StringBuilder(); + String pidCommand = "ps | grep " + fileDispatcher.getCanonicalPath(); + runBlockingCmd(new String[]{pidCommand}, log); + String output = log.toString(); + StringTokenizer st = new StringTokenizer(output, " "); + st.nextToken(); // proc owner + dipatcherPid = Integer.parseInt(st.nextToken().trim()); + + // get open port of dispatcher + String getPortCommand = "cat " + context.getFilesDir().getCanonicalPath() + "/state/dispatcher.log | grep \"obfs4 - registered listener\""; + long timeout = System.currentTimeMillis() + 5000; + int i = 1; + while (this.port.length() == 0 && System.currentTimeMillis() < timeout) { + log = new StringBuilder(); + Log.d(TAG, i + ". try to get port"); + runBlockingCmd(new String[]{getPortCommand}, log); + output = log.toString(); + if (output.length() > 0) { + Log.d(TAG, "dispatcher log: \n =================\n" + output); + } + + String dispatcherLog[] = output.split(" "); + if (dispatcherLog.length > 0) { + String localAddressAndPort = dispatcherLog[dispatcherLog.length - 1]; + if (localAddressAndPort.contains(":")) { + this.port = localAddressAndPort.split(":")[1].replace(System.getProperty("line.separator"), ""); + Log.d(TAG, "local port is: " + this.port); + } + } + i += 1; + } + + } catch(Exception e){ + if (dispatcherThread.isAlive()) { + Log.e(TAG, e.getMessage() + ". Shutting down Dispatcher thread."); + stop(); + } + } + } + + public String getPort() { + return port; + } + + public void stop() { + Log.d(TAG, "Shutting down Dispatcher thread."); + if (dispatcherThread != null && dispatcherThread.isAlive()) { + try { + killProcess(dipatcherPid); + } catch (Exception e) { + e.printStackTrace(); + } + dispatcherThread.interrupt(); + } + } + + private void killProcess(int pid) throws Exception { + String killPid = "kill -9 " + pid; + runCmd(new String[]{killPid}, null, false); + } + + public boolean isRunning() { + return dispatcherThread != null && dispatcherThread.isAlive(); + } + + private File installDispatcher(){ + File fileDispatcher = null; + BinaryInstaller bi = new BinaryInstaller(context,context.getFilesDir()); + + String arch = System.getProperty("os.arch"); + if (arch.contains("arm")) + arch = "arm"; + else + arch = "x86"; + + try { + fileDispatcher = bi.installResource(arch, ASSET_KEY, false); + } catch (Exception ioe) { + Log.d(TAG,"Couldn't install dispatcher: " + ioe); + } + + return fileDispatcher; + } + + @WorkerThread + private void runBlockingCmd(String[] cmds, StringBuilder log) throws Exception { + runCmd(cmds, log, true); + } + + @WorkerThread + private int runCmd(String[] cmds, StringBuilder log, + boolean waitFor) throws Exception { + + int exitCode = -1; + Process proc = Runtime.getRuntime().exec("sh"); + OutputStreamWriter out = new OutputStreamWriter(proc.getOutputStream()); + + try { + for (String cmd : cmds) { + Log.d(TAG, "executing CMD: " + cmd); + out.write(cmd); + out.write("\n"); + } + + out.flush(); + out.write("exit\n"); + out.flush(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + out.close(); + } + + if (waitFor) { + // Consume the "stdout" + InputStreamReader reader = new InputStreamReader(proc.getInputStream()); + readToLogString(reader, log); + + // Consume the "stderr" + reader = new InputStreamReader(proc.getErrorStream()); + readToLogString(reader, log); + + try { + exitCode = proc.waitFor(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + return exitCode; + } + + private void readToLogString(InputStreamReader reader, StringBuilder log) throws IOException { + final char buf[] = new char[10]; + int read = 0; + try { + while ((read = reader.read(buf)) != -1) { + if (log != null) + log.append(buf, 0, read); + } + } catch (IOException e) { + reader.close(); + throw new IOException(e); + } + reader.close(); + } +} diff --git a/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java b/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java index 8835b75d..02a575ea 100644 --- a/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java +++ b/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java @@ -40,6 +40,9 @@ public class TestSetupHelper { while (line != null) { sb.append(line); line = br.readLine(); + if (line != null) { + sb.append("\n"); + } } return sb.toString(); 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 8c8cdb61..20a5968d 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java @@ -1,31 +1,304 @@ package se.leap.bitmaskclient.eip; +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.text.TextUtils; +import android.util.Log; + import org.json.JSONObject; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.io.File; +import de.blinkt.openvpn.VpnProfile; +import se.leap.bitmaskclient.testutils.MockHelper; import se.leap.bitmaskclient.testutils.TestSetupHelper; import static junit.framework.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.when; +import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils; /** * Created by cyberta on 03.10.17. */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Log.class, TextUtils.class, PreferenceManager.class}) public class VpnConfigGeneratorTest { + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + Context context; + private VpnConfigGenerator vpnConfigGenerator; private JSONObject generalConfig; private JSONObject gateway; private JSONObject secrets; - String expectedVPNConfig_tcp_udp = "cipher AES-128-CBC \n" + - "auth SHA1 \n" + - "tun-ipv6 true \n" + + String expectedVPNConfig_tcp_udp = "# Config for OpenVPN 2.x\n" + + "# Enables connection to GUI\n" + + "management /data/data/se.leap.bitmask/mgmtsocket unix\n" + + "management-client\n" + + "management-query-passwords\n" + + "management-hold\n" + + "\n" + + "setenv IV_GUI_VER \"se.leap.bitmaskclient 0.9.10\" \n" + + "setenv IV_PLAT_VER \"0 null JUNIT null null null\"\n" + + "machine-readable-output\n" + + "allow-recursive-routing\n" + + "ifconfig-nowarn\n" + + "client\n" + + "verb 4\n" + + "connect-retry 2 300\n" + + "resolv-retry 60\n" + + "dev tun\n" + + "remote 198.252.153.84 443 tcp-client\n" + + "remote 198.252.153.84 443 udp\n" + + "\n" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\n" + + "YXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNVBAsME2h0dHBzOi8v\n" + + "Yml0bWFzay5uZXQwHhcNMTIxMTA2MDAwMDAwWhcNMjIxMTA2MDAwMDAwWjBKMRgw\n" + + "FgYDVQQDDA9CaXRtYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNV\n" + + "BAsME2h0dHBzOi8vYml0bWFzay5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\n" + + "ggIKAoICAQC1eV4YvayaU+maJbWrD4OHo3d7S1BtDlcvkIRS1Fw3iYDjsyDkZxai\n" + + "dHp4EUasfNQ+EVtXUvtk6170EmLco6Elg8SJBQ27trE6nielPRPCfX3fQzETRfvB\n" + + "7tNvGw4Jn2YKiYoMD79kkjgyZjkJ2r/bEHUSevmR09BRp86syHZerdNGpXYhcQ84\n" + + "CA1+V+603GFIHnrP+uQDdssW93rgDNYu+exT+Wj6STfnUkugyjmPRPjL7wh0tzy+\n" + + "znCeLl4xiV3g9sjPnc7r2EQKd5uaTe3j71sDPF92KRk0SSUndREz+B1+Dbe/RGk4\n" + + "MEqGFuOzrtsgEhPIX0hplhb0Tgz/rtug+yTT7oJjBa3u20AAOQ38/M99EfdeJvc4\n" + + "lPFF1XBBLh6X9UKF72an2NuANiX6XPySnJgZ7nZ09RiYZqVwu/qt3DfvLfhboq+0\n" + + "bQvLUPXrVDr70onv5UDjpmEA/cLmaIqqrduuTkFZOym65/PfAPvpGnt7crQj/Ibl\n" + + "DEDYZQmP7AS+6zBjoOzNjUGE5r40zWAR1RSi7zliXTu+yfsjXUIhUAWmYR6J3KxB\n" + + "lfsiHBQ+8dn9kC3YrUexWoOqBiqJOAJzZh5Y1tqgzfh+2nmHSB2dsQRs7rDRRlyy\n" + + "YMbkpzL9ZsOUO2eTP1mmar6YjCN+rggYjRrX71K2SpBG6b1zZxOG+wIDAQABo2Aw\n" + + "XjAdBgNVHQ4EFgQUuYGDLL2sswnYpHHvProt1JU+D48wDgYDVR0PAQH/BAQDAgIE\n" + + "MAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUuYGDLL2sswnYpHHvProt1JU+D48w\n" + + "DQYJKoZIhvcNAQENBQADggIBADeG67vaFcbITGpi51264kHPYPEWaXUa5XYbtmBl\n" + + "cXYyB6hY5hv/YNuVGJ1gWsDmdeXEyj0j2icGQjYdHRfwhrbEri+h1EZOm1cSBDuY\n" + + "k/P5+ctHyOXx8IE79DBsZ6IL61UKIaKhqZBfLGYcWu17DVV6+LT+AKtHhOrv3TSj\n" + + "RnAcKnCbKqXLhUPXpK0eTjPYS2zQGQGIhIy9sQXVXJJJsGrPgMxna1Xw2JikBOCG\n" + + "htD/JKwt6xBmNwktH0GI/LVtVgSp82Clbn9C4eZN9E5YbVYjLkIEDhpByeC71QhX\n" + + "EIQ0ZR56bFuJA/CwValBqV/G9gscTPQqd+iETp8yrFpAVHOW+YzSFbxjTEkBte1J\n" + + "aF0vmbqdMAWLk+LEFPQRptZh0B88igtx6tV5oVd+p5IVRM49poLhuPNJGPvMj99l\n" + + "mlZ4+AeRUnbOOeAEuvpLJbel4rhwFzmUiGoeTVoPZyMevWcVFq6BMkS+jRR2w0jK\n" + + "G6b0v5XDHlcFYPOgUrtsOBFJVwbutLvxdk6q37kIFnWCd8L3kmES5q4wjyFK47Co\n" + + "Ja8zlx64jmMZPg/t3wWqkZgXZ14qnbyG5/lGsj5CwVtfDljrhN0oCWK1FZaUmW3d\n" + + "69db12/g4f6phldhxiWuGC/W6fCW5kre7nmhshcltqAJJuU47iX+DarBFiIj816e\n" + + "yV8e\n" + + "-----END CERTIFICATE-----\n" + + "\n" + + "\n" + + "\n" + + "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDUTYWeGgsHS+fjijmziniNqw6h\n" + + "MBpyK4S/cM6PxV28C33VuOWPTMcIYesctjZANWFCggfFTQSjV5Qaxq9UK4i27tayLbCdlVS6hpbl\n" + + "Vf4DuI3Gj1Pv1rtITBShtvCf3T7yBnjW4wVpOpsUAAOViKUSvUU3kPPMFWhiGQw8yHYr82ts6XMo\n" + + "jwMoonW5Ml4e7C7Cr22QesC63q7emNcpUd0pZGT9C33RgDAHZDMrlyjo4HEp1JbUfB0gbmXElJbE\n" + + "1TNdZ62HhgmMjzTUN1GGrQ1t91AEoEQwaK65o4YSj+yFv6KXZZz5OWaz94tKiN9v26EXtBFmRlyb\n" + + "6+D9ynSd9LghAgMBAAECggEBANPHLRXkhsHVj1EkzqBx7gXr8CEMmiTvknFh9zvltrZhhDoRQjWr\n" + + "chPDkcRHY2Cznvy4N0YyqQDD2ULIlZdSAgPxxothFoBruWSD47yMBmLx08ORsDpcqt/YvPAATJI8\n" + + "IpFNsXcyaXBp/M57oRemgnxp/8UJPJmFdWX99H4hvffh/jdj7POgYiWUaAl37XTYZKZ4nzKU2wpL\n" + + "EDLj9RKPz9gG7CYp2zrLC9LaAsrXVrKwPBw6g+XwbClaqFj97db3mrY4lr6mTo89qmus1AU+fBDH\n" + + "3Xlpmc8JwB+30TvhRNKrpLx9cEjuEj7K1gm8Y4dWCjPi+lNbtAyUBcgPJFa/81ECgYEA7pLoBU/Y\n" + + "ZYjyHFca8FvDBcBh6haHfqJr9doXWtgjDrbi3o2n5wHqfKhFWOH6vPEQozkOVeX1ze6HOiRmGBpW\n" + + "r+r7x8TD25L7I6HJw3M351RWOAfkF0w/RTVdetcTgduQtfN1u6BDhYSVceXMjyQYx7MhfETWI8Gh\n" + + "KSYm8OEDYiUCgYEA489fmbrCcUnXzpTsbswJ5NmSoEXbcX8cLxnQuzE0z9GHhQdrMjOpXR76reTW\n" + + "6jcuudarNcwRUYSWWhjCDKHhpx4HhasWPaHgr7jIzcRw8yZSJRSxKr8sl1qh6g7s47JcmfXOMWLt\n" + + "yuyE933XrT19Th4ODZHY40Uv35mPjMi9d00CgYEAyRNAQtndBRa7GG/B4Ls2T+6pl+aNJIo4e+no\n" + + "rURlp800wWabEPRocdBRQmyULBLxduBr2LIMzhgwGSz8b2wji/l9ZA3PFY135bxClVzSzUIjuO3N\n" + + "rGUzHl2wAAyuAFDSUshzfkPBJRNt8aVBF5PQ3t93ZYmPAmv8LPZe875yX5ECgYEAsUEcwK/ZNW7g\n" + + "dQPZR4iJNkC4Xu6cBZ6Cnn92swBheEYvLSoNlX0vDZ7aLE3/jzQqrjzC8NP8sbH5jtbuvgeDXZX3\n" + + "AmGRp5j6C6A61ihAPmEVz3ZfN8SSfJ3vl//PAIg6lyz0J+cy4Q7RkwSeuVQ72Hl4M8TEvmmKC3Af\n" + + "ispy6Y0CgYEAgl1o2lo+ACyk+oVQPaaPqK3d7WOBFp4eR2nXFor/vsx9igQOlZUgzRDQsR8jo1o9\n" + + "efOSBf87igrZGgssys89pWa2dnXnz5PMmzkKr6bw4D9Ez6u6Puc9UZhGw/8wDYg6fSosdB9utspm\n" + + "M698ycef7jBNMDgmhpSvfw5GctoNQ4s=\n" + + "-----END RSA PRIVATE KEY-----\n" + + "\n" + + "\n" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIEjDCCAnSgAwIBAgIQG6MBp/cd9DlY+7cdvp3R3jANBgkqhkiG9w0BAQsFADBmMRAwDgYDVQQK\n" + + "DAdCaXRtYXNrMRwwGgYDVQQLDBNodHRwczovL2JpdG1hc2submV0MTQwMgYDVQQDDCtCaXRtYXNr\n" + + "IFJvb3QgQ0EgKGNsaWVudCBjZXJ0aWZpY2F0ZXMgb25seSEpMB4XDTE0MTIwNTAwMDAwMFoXDTE1\n" + + "MDMwNTAwMDAwMFowLTErMCkGA1UEAwwiVU5MSU1JVEVEZDBwZDdkMzE4eTNtOHNkeXllaTFqYmZl\n" + + "eDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANRNhZ4aCwdL5+OKObOKeI2rDqEwGnIr\n" + + "hL9wzo/FXbwLfdW45Y9Mxwhh6xy2NkA1YUKCB8VNBKNXlBrGr1QriLbu1rItsJ2VVLqGluVV/gO4\n" + + "jcaPU+/Wu0hMFKG28J/dPvIGeNbjBWk6mxQAA5WIpRK9RTeQ88wVaGIZDDzIdivza2zpcyiPAyii\n" + + "dbkyXh7sLsKvbZB6wLrert6Y1ylR3SlkZP0LfdGAMAdkMyuXKOjgcSnUltR8HSBuZcSUlsTVM11n\n" + + "rYeGCYyPNNQ3UYatDW33UASgRDBorrmjhhKP7IW/opdlnPk5ZrP3i0qI32/boRe0EWZGXJvr4P3K\n" + + "dJ30uCECAwEAAaNvMG0wHQYDVR0OBBYEFK8bMVAM4GBB5sHptoIOAaIvlYueMAsGA1UdDwQEAwIH\n" + + "gDATBgNVHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFId+E7bsWFsUWah9\n" + + "vZuPvZ7O+aJsMA0GCSqGSIb3DQEBCwUAA4ICAQAQOX81csVhvP422NKkZH7+g3npBpl+sEHedaGR\n" + + "xYPOu4HrA4TVF9h44sljRoRJyenGNdBZCXcLKHg889eePTf8Z5K3lTojp6hvwyA6tgxOMHT1kESW\n" + + "PfqnRw8mHfHJuE3g+4YNUMwggzwc/VZATdV/7M33sarVN9AUOHou9n9BizgCC+UnYlS+F2POumE3\n" + + "FbOhKo5uubI02MwBYlN2JVO2TBt1Q20w8wc6cU07Xi5Epp+1mkgFiOShkNtPcJmEyBWJhxDtSDOW\n" + + "2doqWYNqH2kq7B5R/kyyfcpFJqAnBTV7xs+C5rTS1mW7LpxfdCUMbYuLCpyxpO3A/DhAm8n47tUH\n" + + "lBtmo8Avdb8VdFpYiGBpB0o9kTFcsWFb2GkWFBduGfSEB8jUI7QtqhgZqocAKK/cweSRV8FwyUcn\n" + + "R0prRm3QEi9fbXqEddzjSY9y/lqWYzT7u+IOAQpKroeZ4wzgYperDNOUFuYk1rP7yuvjP2pV5rcN\n" + + "yPoBP60TPVWMRM4WJm6nTogAz2qBrFsf/XwT/ajzbsjT6HNB7QbRE+wkFkqspoXG5Agp7KQ8lW3L\n" + + "SKCDGOQJz7VIE85pD0tg7QEXBEw8oaRZtMjQ0Gvs25mxXAKka4wGasaWfYH6d0E+iKYcWn86V1rH\n" + + "K2ZoknT+Nno5jgjFuUR3fZseNizEfx7BteooKQ==\n" + + "-----END CERTIFICATE-----\n" + + "\n" + + "crl-verify file missing in config profile\n" + + "remote-cert-tls server\n" + + "cipher AES-128-CBC\n" + + "auth SHA1\n" + + "persist-tun\n" + + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + + "preresolve\n" + + "# Custom configuration options\n" + + "# 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" + - "tls-cipher DHE-RSA-AES128-SHA \n" + + "tls-cipher DHE-RSA-AES128-SHA"; + + String expectedVPNConfig_udp_tcp = "# Config for OpenVPN 2.x\n" + + "# Enables connection to GUI\n" + + "management /data/data/se.leap.bitmask/mgmtsocket unix\n" + + "management-client\n" + + "management-query-passwords\n" + + "management-hold\n" + + "\n" + + "setenv IV_GUI_VER \"se.leap.bitmaskclient 0.9.10\" \n" + + "setenv IV_PLAT_VER \"0 null JUNIT null null null\"\n" + + "machine-readable-output\n" + + "allow-recursive-routing\n" + + "ifconfig-nowarn\n" + "client\n" + - "remote 198.252.153.84 443 tcp\n" + + "verb 4\n" + + "connect-retry 2 300\n" + + "resolv-retry 60\n" + + "dev tun\n" + "remote 198.252.153.84 443 udp\n" + + "remote 198.252.153.84 443 tcp-client\n" + + "\n" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\n" + + "YXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNVBAsME2h0dHBzOi8v\n" + + "Yml0bWFzay5uZXQwHhcNMTIxMTA2MDAwMDAwWhcNMjIxMTA2MDAwMDAwWjBKMRgw\n" + + "FgYDVQQDDA9CaXRtYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNV\n" + + "BAsME2h0dHBzOi8vYml0bWFzay5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\n" + + "ggIKAoICAQC1eV4YvayaU+maJbWrD4OHo3d7S1BtDlcvkIRS1Fw3iYDjsyDkZxai\n" + + "dHp4EUasfNQ+EVtXUvtk6170EmLco6Elg8SJBQ27trE6nielPRPCfX3fQzETRfvB\n" + + "7tNvGw4Jn2YKiYoMD79kkjgyZjkJ2r/bEHUSevmR09BRp86syHZerdNGpXYhcQ84\n" + + "CA1+V+603GFIHnrP+uQDdssW93rgDNYu+exT+Wj6STfnUkugyjmPRPjL7wh0tzy+\n" + + "znCeLl4xiV3g9sjPnc7r2EQKd5uaTe3j71sDPF92KRk0SSUndREz+B1+Dbe/RGk4\n" + + "MEqGFuOzrtsgEhPIX0hplhb0Tgz/rtug+yTT7oJjBa3u20AAOQ38/M99EfdeJvc4\n" + + "lPFF1XBBLh6X9UKF72an2NuANiX6XPySnJgZ7nZ09RiYZqVwu/qt3DfvLfhboq+0\n" + + "bQvLUPXrVDr70onv5UDjpmEA/cLmaIqqrduuTkFZOym65/PfAPvpGnt7crQj/Ibl\n" + + "DEDYZQmP7AS+6zBjoOzNjUGE5r40zWAR1RSi7zliXTu+yfsjXUIhUAWmYR6J3KxB\n" + + "lfsiHBQ+8dn9kC3YrUexWoOqBiqJOAJzZh5Y1tqgzfh+2nmHSB2dsQRs7rDRRlyy\n" + + "YMbkpzL9ZsOUO2eTP1mmar6YjCN+rggYjRrX71K2SpBG6b1zZxOG+wIDAQABo2Aw\n" + + "XjAdBgNVHQ4EFgQUuYGDLL2sswnYpHHvProt1JU+D48wDgYDVR0PAQH/BAQDAgIE\n" + + "MAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUuYGDLL2sswnYpHHvProt1JU+D48w\n" + + "DQYJKoZIhvcNAQENBQADggIBADeG67vaFcbITGpi51264kHPYPEWaXUa5XYbtmBl\n" + + "cXYyB6hY5hv/YNuVGJ1gWsDmdeXEyj0j2icGQjYdHRfwhrbEri+h1EZOm1cSBDuY\n" + + "k/P5+ctHyOXx8IE79DBsZ6IL61UKIaKhqZBfLGYcWu17DVV6+LT+AKtHhOrv3TSj\n" + + "RnAcKnCbKqXLhUPXpK0eTjPYS2zQGQGIhIy9sQXVXJJJsGrPgMxna1Xw2JikBOCG\n" + + "htD/JKwt6xBmNwktH0GI/LVtVgSp82Clbn9C4eZN9E5YbVYjLkIEDhpByeC71QhX\n" + + "EIQ0ZR56bFuJA/CwValBqV/G9gscTPQqd+iETp8yrFpAVHOW+YzSFbxjTEkBte1J\n" + + "aF0vmbqdMAWLk+LEFPQRptZh0B88igtx6tV5oVd+p5IVRM49poLhuPNJGPvMj99l\n" + + "mlZ4+AeRUnbOOeAEuvpLJbel4rhwFzmUiGoeTVoPZyMevWcVFq6BMkS+jRR2w0jK\n" + + "G6b0v5XDHlcFYPOgUrtsOBFJVwbutLvxdk6q37kIFnWCd8L3kmES5q4wjyFK47Co\n" + + "Ja8zlx64jmMZPg/t3wWqkZgXZ14qnbyG5/lGsj5CwVtfDljrhN0oCWK1FZaUmW3d\n" + + "69db12/g4f6phldhxiWuGC/W6fCW5kre7nmhshcltqAJJuU47iX+DarBFiIj816e\n" + + "yV8e\n" + + "-----END CERTIFICATE-----\n" + + "\n" + + "\n" + + "\n" + + "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDUTYWeGgsHS+fjijmziniNqw6h\n" + + "MBpyK4S/cM6PxV28C33VuOWPTMcIYesctjZANWFCggfFTQSjV5Qaxq9UK4i27tayLbCdlVS6hpbl\n" + + "Vf4DuI3Gj1Pv1rtITBShtvCf3T7yBnjW4wVpOpsUAAOViKUSvUU3kPPMFWhiGQw8yHYr82ts6XMo\n" + + "jwMoonW5Ml4e7C7Cr22QesC63q7emNcpUd0pZGT9C33RgDAHZDMrlyjo4HEp1JbUfB0gbmXElJbE\n" + + "1TNdZ62HhgmMjzTUN1GGrQ1t91AEoEQwaK65o4YSj+yFv6KXZZz5OWaz94tKiN9v26EXtBFmRlyb\n" + + "6+D9ynSd9LghAgMBAAECggEBANPHLRXkhsHVj1EkzqBx7gXr8CEMmiTvknFh9zvltrZhhDoRQjWr\n" + + "chPDkcRHY2Cznvy4N0YyqQDD2ULIlZdSAgPxxothFoBruWSD47yMBmLx08ORsDpcqt/YvPAATJI8\n" + + "IpFNsXcyaXBp/M57oRemgnxp/8UJPJmFdWX99H4hvffh/jdj7POgYiWUaAl37XTYZKZ4nzKU2wpL\n" + + "EDLj9RKPz9gG7CYp2zrLC9LaAsrXVrKwPBw6g+XwbClaqFj97db3mrY4lr6mTo89qmus1AU+fBDH\n" + + "3Xlpmc8JwB+30TvhRNKrpLx9cEjuEj7K1gm8Y4dWCjPi+lNbtAyUBcgPJFa/81ECgYEA7pLoBU/Y\n" + + "ZYjyHFca8FvDBcBh6haHfqJr9doXWtgjDrbi3o2n5wHqfKhFWOH6vPEQozkOVeX1ze6HOiRmGBpW\n" + + "r+r7x8TD25L7I6HJw3M351RWOAfkF0w/RTVdetcTgduQtfN1u6BDhYSVceXMjyQYx7MhfETWI8Gh\n" + + "KSYm8OEDYiUCgYEA489fmbrCcUnXzpTsbswJ5NmSoEXbcX8cLxnQuzE0z9GHhQdrMjOpXR76reTW\n" + + "6jcuudarNcwRUYSWWhjCDKHhpx4HhasWPaHgr7jIzcRw8yZSJRSxKr8sl1qh6g7s47JcmfXOMWLt\n" + + "yuyE933XrT19Th4ODZHY40Uv35mPjMi9d00CgYEAyRNAQtndBRa7GG/B4Ls2T+6pl+aNJIo4e+no\n" + + "rURlp800wWabEPRocdBRQmyULBLxduBr2LIMzhgwGSz8b2wji/l9ZA3PFY135bxClVzSzUIjuO3N\n" + + "rGUzHl2wAAyuAFDSUshzfkPBJRNt8aVBF5PQ3t93ZYmPAmv8LPZe875yX5ECgYEAsUEcwK/ZNW7g\n" + + "dQPZR4iJNkC4Xu6cBZ6Cnn92swBheEYvLSoNlX0vDZ7aLE3/jzQqrjzC8NP8sbH5jtbuvgeDXZX3\n" + + "AmGRp5j6C6A61ihAPmEVz3ZfN8SSfJ3vl//PAIg6lyz0J+cy4Q7RkwSeuVQ72Hl4M8TEvmmKC3Af\n" + + "ispy6Y0CgYEAgl1o2lo+ACyk+oVQPaaPqK3d7WOBFp4eR2nXFor/vsx9igQOlZUgzRDQsR8jo1o9\n" + + "efOSBf87igrZGgssys89pWa2dnXnz5PMmzkKr6bw4D9Ez6u6Puc9UZhGw/8wDYg6fSosdB9utspm\n" + + "M698ycef7jBNMDgmhpSvfw5GctoNQ4s=\n" + + "-----END RSA PRIVATE KEY-----\n" + + "\n" + + "\n" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIEjDCCAnSgAwIBAgIQG6MBp/cd9DlY+7cdvp3R3jANBgkqhkiG9w0BAQsFADBmMRAwDgYDVQQK\n" + + "DAdCaXRtYXNrMRwwGgYDVQQLDBNodHRwczovL2JpdG1hc2submV0MTQwMgYDVQQDDCtCaXRtYXNr\n" + + "IFJvb3QgQ0EgKGNsaWVudCBjZXJ0aWZpY2F0ZXMgb25seSEpMB4XDTE0MTIwNTAwMDAwMFoXDTE1\n" + + "MDMwNTAwMDAwMFowLTErMCkGA1UEAwwiVU5MSU1JVEVEZDBwZDdkMzE4eTNtOHNkeXllaTFqYmZl\n" + + "eDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANRNhZ4aCwdL5+OKObOKeI2rDqEwGnIr\n" + + "hL9wzo/FXbwLfdW45Y9Mxwhh6xy2NkA1YUKCB8VNBKNXlBrGr1QriLbu1rItsJ2VVLqGluVV/gO4\n" + + "jcaPU+/Wu0hMFKG28J/dPvIGeNbjBWk6mxQAA5WIpRK9RTeQ88wVaGIZDDzIdivza2zpcyiPAyii\n" + + "dbkyXh7sLsKvbZB6wLrert6Y1ylR3SlkZP0LfdGAMAdkMyuXKOjgcSnUltR8HSBuZcSUlsTVM11n\n" + + "rYeGCYyPNNQ3UYatDW33UASgRDBorrmjhhKP7IW/opdlnPk5ZrP3i0qI32/boRe0EWZGXJvr4P3K\n" + + "dJ30uCECAwEAAaNvMG0wHQYDVR0OBBYEFK8bMVAM4GBB5sHptoIOAaIvlYueMAsGA1UdDwQEAwIH\n" + + "gDATBgNVHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFId+E7bsWFsUWah9\n" + + "vZuPvZ7O+aJsMA0GCSqGSIb3DQEBCwUAA4ICAQAQOX81csVhvP422NKkZH7+g3npBpl+sEHedaGR\n" + + "xYPOu4HrA4TVF9h44sljRoRJyenGNdBZCXcLKHg889eePTf8Z5K3lTojp6hvwyA6tgxOMHT1kESW\n" + + "PfqnRw8mHfHJuE3g+4YNUMwggzwc/VZATdV/7M33sarVN9AUOHou9n9BizgCC+UnYlS+F2POumE3\n" + + "FbOhKo5uubI02MwBYlN2JVO2TBt1Q20w8wc6cU07Xi5Epp+1mkgFiOShkNtPcJmEyBWJhxDtSDOW\n" + + "2doqWYNqH2kq7B5R/kyyfcpFJqAnBTV7xs+C5rTS1mW7LpxfdCUMbYuLCpyxpO3A/DhAm8n47tUH\n" + + "lBtmo8Avdb8VdFpYiGBpB0o9kTFcsWFb2GkWFBduGfSEB8jUI7QtqhgZqocAKK/cweSRV8FwyUcn\n" + + "R0prRm3QEi9fbXqEddzjSY9y/lqWYzT7u+IOAQpKroeZ4wzgYperDNOUFuYk1rP7yuvjP2pV5rcN\n" + + "yPoBP60TPVWMRM4WJm6nTogAz2qBrFsf/XwT/ajzbsjT6HNB7QbRE+wkFkqspoXG5Agp7KQ8lW3L\n" + + "SKCDGOQJz7VIE85pD0tg7QEXBEw8oaRZtMjQ0Gvs25mxXAKka4wGasaWfYH6d0E+iKYcWn86V1rH\n" + + "K2ZoknT+Nno5jgjFuUR3fZseNizEfx7BteooKQ==\n" + + "-----END CERTIFICATE-----\n" + + "\n" + + "crl-verify file missing in config profile\n" + + "remote-cert-tls server\n" + + "cipher AES-128-CBC\n" + + "auth SHA1\n" + + "persist-tun\n" + + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + + "preresolve\n" + + "# Custom configuration options\n" + + "# 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" + + "tls-cipher DHE-RSA-AES128-SHA"; + + String expectedVPNConfig_pt_tcp = "# Config for OpenVPN 2.x\n" + + "# Enables connection to GUI\n" + + "management /data/data/se.leap.bitmask/mgmtsocket unix\n" + + "management-client\n" + + "management-query-passwords\n" + + "management-hold\n" + + "\n" + + "setenv IV_GUI_VER \"se.leap.bitmaskclient 0.9.10\" \n" + + "setenv IV_PLAT_VER \"0 null JUNIT null null null\"\n" + + "machine-readable-output\n" + + "allow-recursive-routing\n" + + "ifconfig-nowarn\n" + + "client\n" + + "verb 4\n" + + "connect-retry 2 300\n" + + "resolv-retry 60\n" + + "dev tun\n" + + "remote 127.0.0.1 1234 tcp-client\n" + + "remote 37.218.247.60 1195 tcp-client\n" + "\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\n" + @@ -112,18 +385,158 @@ public class VpnConfigGeneratorTest { "K2ZoknT+Nno5jgjFuUR3fZseNizEfx7BteooKQ==\n" + "-----END CERTIFICATE-----\n" + "\n" + + "crl-verify file missing in config profile\n" + "remote-cert-tls server\n" + + "cipher AES-128-CBC\n" + + "auth SHA1\n" + "persist-tun\n" + - "auth-retry nointeract"; + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + + "preresolve\n" + + "# Custom configuration options\n" + + "# 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" + + "tls-cipher DHE-RSA-AES128-SHA \n"; - String expectedVPNConfig_udp_tcp = "cipher AES-128-CBC \n" + - "auth SHA1 \n" + - "tun-ipv6 true \n" + + String expectedVPNConfig_pt_tcp_udp = "# Config for OpenVPN 2.x\n" + + "# Enables connection to GUI\n" + + "management /data/data/se.leap.bitmask/mgmtsocket unix\n" + + "management-client\n" + + "management-query-passwords\n" + + "management-hold\n" + + "\n" + + "setenv IV_GUI_VER \"se.leap.bitmaskclient 0.9.10\" \n" + + "setenv IV_PLAT_VER \"0 null JUNIT null null null\"\n" + + "machine-readable-output\n" + + "allow-recursive-routing\n" + + "ifconfig-nowarn\n" + + "client\n" + + "verb 4\n" + + "connect-retry 2 300\n" + + "resolv-retry 60\n" + + "dev tun\n" + + "remote 127.0.0.1 1234 tcp-client\n" + + "remote 37.218.247.60 1195 tcp-client\n" + + "remote 37.218.247.60 1195 udp\n" + + "\n" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\n" + + "YXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNVBAsME2h0dHBzOi8v\n" + + "Yml0bWFzay5uZXQwHhcNMTIxMTA2MDAwMDAwWhcNMjIxMTA2MDAwMDAwWjBKMRgw\n" + + "FgYDVQQDDA9CaXRtYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNV\n" + + "BAsME2h0dHBzOi8vYml0bWFzay5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\n" + + "ggIKAoICAQC1eV4YvayaU+maJbWrD4OHo3d7S1BtDlcvkIRS1Fw3iYDjsyDkZxai\n" + + "dHp4EUasfNQ+EVtXUvtk6170EmLco6Elg8SJBQ27trE6nielPRPCfX3fQzETRfvB\n" + + "7tNvGw4Jn2YKiYoMD79kkjgyZjkJ2r/bEHUSevmR09BRp86syHZerdNGpXYhcQ84\n" + + "CA1+V+603GFIHnrP+uQDdssW93rgDNYu+exT+Wj6STfnUkugyjmPRPjL7wh0tzy+\n" + + "znCeLl4xiV3g9sjPnc7r2EQKd5uaTe3j71sDPF92KRk0SSUndREz+B1+Dbe/RGk4\n" + + "MEqGFuOzrtsgEhPIX0hplhb0Tgz/rtug+yTT7oJjBa3u20AAOQ38/M99EfdeJvc4\n" + + "lPFF1XBBLh6X9UKF72an2NuANiX6XPySnJgZ7nZ09RiYZqVwu/qt3DfvLfhboq+0\n" + + "bQvLUPXrVDr70onv5UDjpmEA/cLmaIqqrduuTkFZOym65/PfAPvpGnt7crQj/Ibl\n" + + "DEDYZQmP7AS+6zBjoOzNjUGE5r40zWAR1RSi7zliXTu+yfsjXUIhUAWmYR6J3KxB\n" + + "lfsiHBQ+8dn9kC3YrUexWoOqBiqJOAJzZh5Y1tqgzfh+2nmHSB2dsQRs7rDRRlyy\n" + + "YMbkpzL9ZsOUO2eTP1mmar6YjCN+rggYjRrX71K2SpBG6b1zZxOG+wIDAQABo2Aw\n" + + "XjAdBgNVHQ4EFgQUuYGDLL2sswnYpHHvProt1JU+D48wDgYDVR0PAQH/BAQDAgIE\n" + + "MAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUuYGDLL2sswnYpHHvProt1JU+D48w\n" + + "DQYJKoZIhvcNAQENBQADggIBADeG67vaFcbITGpi51264kHPYPEWaXUa5XYbtmBl\n" + + "cXYyB6hY5hv/YNuVGJ1gWsDmdeXEyj0j2icGQjYdHRfwhrbEri+h1EZOm1cSBDuY\n" + + "k/P5+ctHyOXx8IE79DBsZ6IL61UKIaKhqZBfLGYcWu17DVV6+LT+AKtHhOrv3TSj\n" + + "RnAcKnCbKqXLhUPXpK0eTjPYS2zQGQGIhIy9sQXVXJJJsGrPgMxna1Xw2JikBOCG\n" + + "htD/JKwt6xBmNwktH0GI/LVtVgSp82Clbn9C4eZN9E5YbVYjLkIEDhpByeC71QhX\n" + + "EIQ0ZR56bFuJA/CwValBqV/G9gscTPQqd+iETp8yrFpAVHOW+YzSFbxjTEkBte1J\n" + + "aF0vmbqdMAWLk+LEFPQRptZh0B88igtx6tV5oVd+p5IVRM49poLhuPNJGPvMj99l\n" + + "mlZ4+AeRUnbOOeAEuvpLJbel4rhwFzmUiGoeTVoPZyMevWcVFq6BMkS+jRR2w0jK\n" + + "G6b0v5XDHlcFYPOgUrtsOBFJVwbutLvxdk6q37kIFnWCd8L3kmES5q4wjyFK47Co\n" + + "Ja8zlx64jmMZPg/t3wWqkZgXZ14qnbyG5/lGsj5CwVtfDljrhN0oCWK1FZaUmW3d\n" + + "69db12/g4f6phldhxiWuGC/W6fCW5kre7nmhshcltqAJJuU47iX+DarBFiIj816e\n" + + "yV8e\n" + + "-----END CERTIFICATE-----\n" + + "\n" + + "\n" + + "\n" + + "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDUTYWeGgsHS+fjijmziniNqw6h\n" + + "MBpyK4S/cM6PxV28C33VuOWPTMcIYesctjZANWFCggfFTQSjV5Qaxq9UK4i27tayLbCdlVS6hpbl\n" + + "Vf4DuI3Gj1Pv1rtITBShtvCf3T7yBnjW4wVpOpsUAAOViKUSvUU3kPPMFWhiGQw8yHYr82ts6XMo\n" + + "jwMoonW5Ml4e7C7Cr22QesC63q7emNcpUd0pZGT9C33RgDAHZDMrlyjo4HEp1JbUfB0gbmXElJbE\n" + + "1TNdZ62HhgmMjzTUN1GGrQ1t91AEoEQwaK65o4YSj+yFv6KXZZz5OWaz94tKiN9v26EXtBFmRlyb\n" + + "6+D9ynSd9LghAgMBAAECggEBANPHLRXkhsHVj1EkzqBx7gXr8CEMmiTvknFh9zvltrZhhDoRQjWr\n" + + "chPDkcRHY2Cznvy4N0YyqQDD2ULIlZdSAgPxxothFoBruWSD47yMBmLx08ORsDpcqt/YvPAATJI8\n" + + "IpFNsXcyaXBp/M57oRemgnxp/8UJPJmFdWX99H4hvffh/jdj7POgYiWUaAl37XTYZKZ4nzKU2wpL\n" + + "EDLj9RKPz9gG7CYp2zrLC9LaAsrXVrKwPBw6g+XwbClaqFj97db3mrY4lr6mTo89qmus1AU+fBDH\n" + + "3Xlpmc8JwB+30TvhRNKrpLx9cEjuEj7K1gm8Y4dWCjPi+lNbtAyUBcgPJFa/81ECgYEA7pLoBU/Y\n" + + "ZYjyHFca8FvDBcBh6haHfqJr9doXWtgjDrbi3o2n5wHqfKhFWOH6vPEQozkOVeX1ze6HOiRmGBpW\n" + + "r+r7x8TD25L7I6HJw3M351RWOAfkF0w/RTVdetcTgduQtfN1u6BDhYSVceXMjyQYx7MhfETWI8Gh\n" + + "KSYm8OEDYiUCgYEA489fmbrCcUnXzpTsbswJ5NmSoEXbcX8cLxnQuzE0z9GHhQdrMjOpXR76reTW\n" + + "6jcuudarNcwRUYSWWhjCDKHhpx4HhasWPaHgr7jIzcRw8yZSJRSxKr8sl1qh6g7s47JcmfXOMWLt\n" + + "yuyE933XrT19Th4ODZHY40Uv35mPjMi9d00CgYEAyRNAQtndBRa7GG/B4Ls2T+6pl+aNJIo4e+no\n" + + "rURlp800wWabEPRocdBRQmyULBLxduBr2LIMzhgwGSz8b2wji/l9ZA3PFY135bxClVzSzUIjuO3N\n" + + "rGUzHl2wAAyuAFDSUshzfkPBJRNt8aVBF5PQ3t93ZYmPAmv8LPZe875yX5ECgYEAsUEcwK/ZNW7g\n" + + "dQPZR4iJNkC4Xu6cBZ6Cnn92swBheEYvLSoNlX0vDZ7aLE3/jzQqrjzC8NP8sbH5jtbuvgeDXZX3\n" + + "AmGRp5j6C6A61ihAPmEVz3ZfN8SSfJ3vl//PAIg6lyz0J+cy4Q7RkwSeuVQ72Hl4M8TEvmmKC3Af\n" + + "ispy6Y0CgYEAgl1o2lo+ACyk+oVQPaaPqK3d7WOBFp4eR2nXFor/vsx9igQOlZUgzRDQsR8jo1o9\n" + + "efOSBf87igrZGgssys89pWa2dnXnz5PMmzkKr6bw4D9Ez6u6Puc9UZhGw/8wDYg6fSosdB9utspm\n" + + "M698ycef7jBNMDgmhpSvfw5GctoNQ4s=\n" + + "-----END RSA PRIVATE KEY-----\n" + + "\n" + + "\n" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIEjDCCAnSgAwIBAgIQG6MBp/cd9DlY+7cdvp3R3jANBgkqhkiG9w0BAQsFADBmMRAwDgYDVQQK\n" + + "DAdCaXRtYXNrMRwwGgYDVQQLDBNodHRwczovL2JpdG1hc2submV0MTQwMgYDVQQDDCtCaXRtYXNr\n" + + "IFJvb3QgQ0EgKGNsaWVudCBjZXJ0aWZpY2F0ZXMgb25seSEpMB4XDTE0MTIwNTAwMDAwMFoXDTE1\n" + + "MDMwNTAwMDAwMFowLTErMCkGA1UEAwwiVU5MSU1JVEVEZDBwZDdkMzE4eTNtOHNkeXllaTFqYmZl\n" + + "eDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANRNhZ4aCwdL5+OKObOKeI2rDqEwGnIr\n" + + "hL9wzo/FXbwLfdW45Y9Mxwhh6xy2NkA1YUKCB8VNBKNXlBrGr1QriLbu1rItsJ2VVLqGluVV/gO4\n" + + "jcaPU+/Wu0hMFKG28J/dPvIGeNbjBWk6mxQAA5WIpRK9RTeQ88wVaGIZDDzIdivza2zpcyiPAyii\n" + + "dbkyXh7sLsKvbZB6wLrert6Y1ylR3SlkZP0LfdGAMAdkMyuXKOjgcSnUltR8HSBuZcSUlsTVM11n\n" + + "rYeGCYyPNNQ3UYatDW33UASgRDBorrmjhhKP7IW/opdlnPk5ZrP3i0qI32/boRe0EWZGXJvr4P3K\n" + + "dJ30uCECAwEAAaNvMG0wHQYDVR0OBBYEFK8bMVAM4GBB5sHptoIOAaIvlYueMAsGA1UdDwQEAwIH\n" + + "gDATBgNVHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFId+E7bsWFsUWah9\n" + + "vZuPvZ7O+aJsMA0GCSqGSIb3DQEBCwUAA4ICAQAQOX81csVhvP422NKkZH7+g3npBpl+sEHedaGR\n" + + "xYPOu4HrA4TVF9h44sljRoRJyenGNdBZCXcLKHg889eePTf8Z5K3lTojp6hvwyA6tgxOMHT1kESW\n" + + "PfqnRw8mHfHJuE3g+4YNUMwggzwc/VZATdV/7M33sarVN9AUOHou9n9BizgCC+UnYlS+F2POumE3\n" + + "FbOhKo5uubI02MwBYlN2JVO2TBt1Q20w8wc6cU07Xi5Epp+1mkgFiOShkNtPcJmEyBWJhxDtSDOW\n" + + "2doqWYNqH2kq7B5R/kyyfcpFJqAnBTV7xs+C5rTS1mW7LpxfdCUMbYuLCpyxpO3A/DhAm8n47tUH\n" + + "lBtmo8Avdb8VdFpYiGBpB0o9kTFcsWFb2GkWFBduGfSEB8jUI7QtqhgZqocAKK/cweSRV8FwyUcn\n" + + "R0prRm3QEi9fbXqEddzjSY9y/lqWYzT7u+IOAQpKroeZ4wzgYperDNOUFuYk1rP7yuvjP2pV5rcN\n" + + "yPoBP60TPVWMRM4WJm6nTogAz2qBrFsf/XwT/ajzbsjT6HNB7QbRE+wkFkqspoXG5Agp7KQ8lW3L\n" + + "SKCDGOQJz7VIE85pD0tg7QEXBEw8oaRZtMjQ0Gvs25mxXAKka4wGasaWfYH6d0E+iKYcWn86V1rH\n" + + "K2ZoknT+Nno5jgjFuUR3fZseNizEfx7BteooKQ==\n" + + "-----END CERTIFICATE-----\n" + + "\n" + + "crl-verify file missing in config profile\n" + + "remote-cert-tls server\n" + + "cipher AES-128-CBC\n" + + "auth SHA1\n" + + "persist-tun\n" + + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + + "preresolve\n" + + "# Custom configuration options\n" + + "# 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" + - "tls-cipher DHE-RSA-AES128-SHA \n" + + "tls-cipher DHE-RSA-AES128-SHA \n"; + + String expectedVPNConfig_pt_udp_tcp = "# Config for OpenVPN 2.x\n" + + "# Enables connection to GUI\n" + + "management /data/data/se.leap.bitmask/mgmtsocket unix\n" + + "management-client\n" + + "management-query-passwords\n" + + "management-hold\n" + + "\n" + + "setenv IV_GUI_VER \"se.leap.bitmaskclient 0.9.10\" \n" + + "setenv IV_PLAT_VER \"0 null JUNIT null null null\"\n" + + "machine-readable-output\n" + + "allow-recursive-routing\n" + + "ifconfig-nowarn\n" + "client\n" + - "remote 198.252.153.84 443 udp\n" + - "remote 198.252.153.84 443 tcp\n" + + "verb 4\n" + + "connect-retry 2 300\n" + + "resolv-retry 60\n" + + "dev tun\n" + + "remote 127.0.0.1 1234 tcp-client\n" + + "remote 37.218.247.60 1195 udp\n" + + "remote 37.218.247.60 1195 tcp-client\n" + "\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\n" + @@ -210,33 +623,77 @@ public class VpnConfigGeneratorTest { "K2ZoknT+Nno5jgjFuUR3fZseNizEfx7BteooKQ==\n" + "-----END CERTIFICATE-----\n" + "\n" + + "crl-verify file missing in config profile\n" + "remote-cert-tls server\n" + + "cipher AES-128-CBC\n" + + "auth SHA1\n" + "persist-tun\n" + - "auth-retry nointeract"; + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + + "preresolve\n" + + "# Custom configuration options\n" + + "# 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" + + "tls-cipher DHE-RSA-AES128-SHA \n"; @Before public void setUp() throws Exception { generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("general_configuration.json"))); secrets = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("secrets.json"))); + mockStatic(Log.class); + context = MockHelper.mockContext(); + mockTextUtils(); + mockStatic(PreferenceManager.class); + SharedPreferences preferences = mock(SharedPreferences.class, RETURNS_DEEP_STUBS); + when(PreferenceManager.getDefaultSharedPreferences(any(Context.class))).thenReturn(preferences); + when(context.getCacheDir()).thenReturn(new File("/data/data/se.leap.bitmask")); } + @Test - public void testGenerate_tcp_udp() throws Exception { + public void testGenerateVpnProfile_v1_tcp_udp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_tcp_udp.json"))); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway); - - String vpnConfig = vpnConfigGenerator.generate(); - assertTrue(vpnConfig.equals(expectedVPNConfig_tcp_udp)); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1); + VpnProfile vpnProfile = vpnConfigGenerator.generateVpnProfile(); + assertTrue(vpnProfile.getConfigFile(context, false).trim().equals(expectedVPNConfig_tcp_udp.trim())); } @Test - public void testGenerate_udp_tcp() throws Exception { + public void testGenerateVpnProfile_v1_udp_tcp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_udp_tcp.json"))); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1); + VpnProfile vpnConfig = vpnConfigGenerator.generateVpnProfile(); + assertTrue(vpnConfig.getConfigFile(context, false).trim().equals(expectedVPNConfig_udp_tcp.trim())); + } - String vpnConfig = vpnConfigGenerator.generate(); - assertTrue(vpnConfig.equals(expectedVPNConfig_udp_tcp)); + @Test + public void testGenerateVpnProfile_v2_pt_tcp() throws Exception { + gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2); + VpnProfile vpnProfile = vpnConfigGenerator.generateVpnProfile(); + vpnProfile.mConnections[0].setServerPort("1234"); + System.out.println(vpnProfile.getConfigFile(context, false)); + assertTrue(vpnProfile.getConfigFile(context, false).trim().equals(expectedVPNConfig_pt_tcp.trim())); } + @Test + public void testGenerateVpnProfile_v2_pt_tcp_udp() throws Exception { + gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_tcp_udp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2); + VpnProfile vpnProfile = vpnConfigGenerator.generateVpnProfile(); + vpnProfile.mConnections[0].setServerPort("1234"); + System.out.println(vpnProfile.getConfigFile(context, false)); + assertTrue(vpnProfile.getConfigFile(context, false).trim().equals(expectedVPNConfig_pt_tcp_udp.trim())); + } + + @Test + public void testGenerateVpnProfile_v2_pt_udp_tcp() throws Exception { + gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_udp_tcp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2); + VpnProfile vpnProfile = vpnConfigGenerator.generateVpnProfile(); + vpnProfile.mConnections[0].setServerPort("1234"); + System.out.println(vpnProfile.getConfigFile(context, false)); + assertTrue(vpnProfile.getConfigFile(context, false).trim().equals(expectedVPNConfig_pt_udp_tcp.trim())); + } } \ No newline at end of file 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 fa9f9252..24801b58 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java @@ -1,7 +1,10 @@ package se.leap.bitmaskclient.testutils; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.Bundle; import android.os.Parcelable; @@ -460,4 +463,13 @@ public class MockHelper { thenReturn("Bitmask"); return mockedResources; } + + public static Context mockContext() throws PackageManager.NameNotFoundException { + Context context = mock(Context.class, RETURNS_DEEP_STUBS); + when(context.getPackageName()).thenReturn("se.leap.bitmaskclient"); + PackageInfo mockPackageInfo = new PackageInfo(); + mockPackageInfo.versionName = "0.9.10"; + when(context.getPackageManager().getPackageInfo(anyString(), anyInt())).thenReturn(mockPackageInfo); + return context; + } } diff --git a/app/src/test/resources/openvpnConfigs/tcp_udp.ovpn b/app/src/test/resources/openvpnConfigs/tcp_udp.ovpn new file mode 100644 index 00000000..875fe606 --- /dev/null +++ b/app/src/test/resources/openvpnConfigs/tcp_udp.ovpn @@ -0,0 +1,117 @@ +# Config for OpenVPN 2.x +# Enables connection to GUI +management /data/data/se.leap.bitmask/mgmtsocket unix +management-client +management-query-passwords +management-hold + +setenv IV_GUI_VER "se.leap.bitmaskclient 0.9.10" +setenv IV_PLAT_VER "0 null JUNIT null null null" +machine-readable-output +allow-recursive-routing +ifconfig-nowarn +client +verb 4 +connect-retry 2 300 +resolv-retry 60 +dev tun +remote 198.252.153.84 443 tcp-client +remote 198.252.153.84 443 udp + +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt +YXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNVBAsME2h0dHBzOi8v +Yml0bWFzay5uZXQwHhcNMTIxMTA2MDAwMDAwWhcNMjIxMTA2MDAwMDAwWjBKMRgw +FgYDVQQDDA9CaXRtYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNV +BAsME2h0dHBzOi8vYml0bWFzay5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQC1eV4YvayaU+maJbWrD4OHo3d7S1BtDlcvkIRS1Fw3iYDjsyDkZxai +dHp4EUasfNQ+EVtXUvtk6170EmLco6Elg8SJBQ27trE6nielPRPCfX3fQzETRfvB +7tNvGw4Jn2YKiYoMD79kkjgyZjkJ2r/bEHUSevmR09BRp86syHZerdNGpXYhcQ84 +CA1+V+603GFIHnrP+uQDdssW93rgDNYu+exT+Wj6STfnUkugyjmPRPjL7wh0tzy+ +znCeLl4xiV3g9sjPnc7r2EQKd5uaTe3j71sDPF92KRk0SSUndREz+B1+Dbe/RGk4 +MEqGFuOzrtsgEhPIX0hplhb0Tgz/rtug+yTT7oJjBa3u20AAOQ38/M99EfdeJvc4 +lPFF1XBBLh6X9UKF72an2NuANiX6XPySnJgZ7nZ09RiYZqVwu/qt3DfvLfhboq+0 +bQvLUPXrVDr70onv5UDjpmEA/cLmaIqqrduuTkFZOym65/PfAPvpGnt7crQj/Ibl +DEDYZQmP7AS+6zBjoOzNjUGE5r40zWAR1RSi7zliXTu+yfsjXUIhUAWmYR6J3KxB +lfsiHBQ+8dn9kC3YrUexWoOqBiqJOAJzZh5Y1tqgzfh+2nmHSB2dsQRs7rDRRlyy +YMbkpzL9ZsOUO2eTP1mmar6YjCN+rggYjRrX71K2SpBG6b1zZxOG+wIDAQABo2Aw +XjAdBgNVHQ4EFgQUuYGDLL2sswnYpHHvProt1JU+D48wDgYDVR0PAQH/BAQDAgIE +MAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUuYGDLL2sswnYpHHvProt1JU+D48w +DQYJKoZIhvcNAQENBQADggIBADeG67vaFcbITGpi51264kHPYPEWaXUa5XYbtmBl +cXYyB6hY5hv/YNuVGJ1gWsDmdeXEyj0j2icGQjYdHRfwhrbEri+h1EZOm1cSBDuY +k/P5+ctHyOXx8IE79DBsZ6IL61UKIaKhqZBfLGYcWu17DVV6+LT+AKtHhOrv3TSj +RnAcKnCbKqXLhUPXpK0eTjPYS2zQGQGIhIy9sQXVXJJJsGrPgMxna1Xw2JikBOCG +htD/JKwt6xBmNwktH0GI/LVtVgSp82Clbn9C4eZN9E5YbVYjLkIEDhpByeC71QhX +EIQ0ZR56bFuJA/CwValBqV/G9gscTPQqd+iETp8yrFpAVHOW+YzSFbxjTEkBte1J +aF0vmbqdMAWLk+LEFPQRptZh0B88igtx6tV5oVd+p5IVRM49poLhuPNJGPvMj99l +mlZ4+AeRUnbOOeAEuvpLJbel4rhwFzmUiGoeTVoPZyMevWcVFq6BMkS+jRR2w0jK +G6b0v5XDHlcFYPOgUrtsOBFJVwbutLvxdk6q37kIFnWCd8L3kmES5q4wjyFK47Co +Ja8zlx64jmMZPg/t3wWqkZgXZ14qnbyG5/lGsj5CwVtfDljrhN0oCWK1FZaUmW3d +69db12/g4f6phldhxiWuGC/W6fCW5kre7nmhshcltqAJJuU47iX+DarBFiIj816e +yV8e +-----END CERTIFICATE----- + + + +-----BEGIN RSA PRIVATE KEY----- +MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDUTYWeGgsHS+fjijmziniNqw6h +MBpyK4S/cM6PxV28C33VuOWPTMcIYesctjZANWFCggfFTQSjV5Qaxq9UK4i27tayLbCdlVS6hpbl +Vf4DuI3Gj1Pv1rtITBShtvCf3T7yBnjW4wVpOpsUAAOViKUSvUU3kPPMFWhiGQw8yHYr82ts6XMo +jwMoonW5Ml4e7C7Cr22QesC63q7emNcpUd0pZGT9C33RgDAHZDMrlyjo4HEp1JbUfB0gbmXElJbE +1TNdZ62HhgmMjzTUN1GGrQ1t91AEoEQwaK65o4YSj+yFv6KXZZz5OWaz94tKiN9v26EXtBFmRlyb +6+D9ynSd9LghAgMBAAECggEBANPHLRXkhsHVj1EkzqBx7gXr8CEMmiTvknFh9zvltrZhhDoRQjWr +chPDkcRHY2Cznvy4N0YyqQDD2ULIlZdSAgPxxothFoBruWSD47yMBmLx08ORsDpcqt/YvPAATJI8 +IpFNsXcyaXBp/M57oRemgnxp/8UJPJmFdWX99H4hvffh/jdj7POgYiWUaAl37XTYZKZ4nzKU2wpL +EDLj9RKPz9gG7CYp2zrLC9LaAsrXVrKwPBw6g+XwbClaqFj97db3mrY4lr6mTo89qmus1AU+fBDH +3Xlpmc8JwB+30TvhRNKrpLx9cEjuEj7K1gm8Y4dWCjPi+lNbtAyUBcgPJFa/81ECgYEA7pLoBU/Y +ZYjyHFca8FvDBcBh6haHfqJr9doXWtgjDrbi3o2n5wHqfKhFWOH6vPEQozkOVeX1ze6HOiRmGBpW +r+r7x8TD25L7I6HJw3M351RWOAfkF0w/RTVdetcTgduQtfN1u6BDhYSVceXMjyQYx7MhfETWI8Gh +KSYm8OEDYiUCgYEA489fmbrCcUnXzpTsbswJ5NmSoEXbcX8cLxnQuzE0z9GHhQdrMjOpXR76reTW +6jcuudarNcwRUYSWWhjCDKHhpx4HhasWPaHgr7jIzcRw8yZSJRSxKr8sl1qh6g7s47JcmfXOMWLt +yuyE933XrT19Th4ODZHY40Uv35mPjMi9d00CgYEAyRNAQtndBRa7GG/B4Ls2T+6pl+aNJIo4e+no +rURlp800wWabEPRocdBRQmyULBLxduBr2LIMzhgwGSz8b2wji/l9ZA3PFY135bxClVzSzUIjuO3N +rGUzHl2wAAyuAFDSUshzfkPBJRNt8aVBF5PQ3t93ZYmPAmv8LPZe875yX5ECgYEAsUEcwK/ZNW7g +dQPZR4iJNkC4Xu6cBZ6Cnn92swBheEYvLSoNlX0vDZ7aLE3/jzQqrjzC8NP8sbH5jtbuvgeDXZX3 +AmGRp5j6C6A61ihAPmEVz3ZfN8SSfJ3vl//PAIg6lyz0J+cy4Q7RkwSeuVQ72Hl4M8TEvmmKC3Af +ispy6Y0CgYEAgl1o2lo+ACyk+oVQPaaPqK3d7WOBFp4eR2nXFor/vsx9igQOlZUgzRDQsR8jo1o9 +efOSBf87igrZGgssys89pWa2dnXnz5PMmzkKr6bw4D9Ez6u6Puc9UZhGw/8wDYg6fSosdB9utspm +M698ycef7jBNMDgmhpSvfw5GctoNQ4s= +-----END RSA PRIVATE KEY----- + + +-----BEGIN CERTIFICATE----- +MIIEjDCCAnSgAwIBAgIQG6MBp/cd9DlY+7cdvp3R3jANBgkqhkiG9w0BAQsFADBmMRAwDgYDVQQK +DAdCaXRtYXNrMRwwGgYDVQQLDBNodHRwczovL2JpdG1hc2submV0MTQwMgYDVQQDDCtCaXRtYXNr +IFJvb3QgQ0EgKGNsaWVudCBjZXJ0aWZpY2F0ZXMgb25seSEpMB4XDTE0MTIwNTAwMDAwMFoXDTE1 +MDMwNTAwMDAwMFowLTErMCkGA1UEAwwiVU5MSU1JVEVEZDBwZDdkMzE4eTNtOHNkeXllaTFqYmZl +eDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANRNhZ4aCwdL5+OKObOKeI2rDqEwGnIr +hL9wzo/FXbwLfdW45Y9Mxwhh6xy2NkA1YUKCB8VNBKNXlBrGr1QriLbu1rItsJ2VVLqGluVV/gO4 +jcaPU+/Wu0hMFKG28J/dPvIGeNbjBWk6mxQAA5WIpRK9RTeQ88wVaGIZDDzIdivza2zpcyiPAyii +dbkyXh7sLsKvbZB6wLrert6Y1ylR3SlkZP0LfdGAMAdkMyuXKOjgcSnUltR8HSBuZcSUlsTVM11n +rYeGCYyPNNQ3UYatDW33UASgRDBorrmjhhKP7IW/opdlnPk5ZrP3i0qI32/boRe0EWZGXJvr4P3K +dJ30uCECAwEAAaNvMG0wHQYDVR0OBBYEFK8bMVAM4GBB5sHptoIOAaIvlYueMAsGA1UdDwQEAwIH +gDATBgNVHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFId+E7bsWFsUWah9 +vZuPvZ7O+aJsMA0GCSqGSIb3DQEBCwUAA4ICAQAQOX81csVhvP422NKkZH7+g3npBpl+sEHedaGR +xYPOu4HrA4TVF9h44sljRoRJyenGNdBZCXcLKHg889eePTf8Z5K3lTojp6hvwyA6tgxOMHT1kESW +PfqnRw8mHfHJuE3g+4YNUMwggzwc/VZATdV/7M33sarVN9AUOHou9n9BizgCC+UnYlS+F2POumE3 +FbOhKo5uubI02MwBYlN2JVO2TBt1Q20w8wc6cU07Xi5Epp+1mkgFiOShkNtPcJmEyBWJhxDtSDOW +2doqWYNqH2kq7B5R/kyyfcpFJqAnBTV7xs+C5rTS1mW7LpxfdCUMbYuLCpyxpO3A/DhAm8n47tUH +lBtmo8Avdb8VdFpYiGBpB0o9kTFcsWFb2GkWFBduGfSEB8jUI7QtqhgZqocAKK/cweSRV8FwyUcn +R0prRm3QEi9fbXqEddzjSY9y/lqWYzT7u+IOAQpKroeZ4wzgYperDNOUFuYk1rP7yuvjP2pV5rcN +yPoBP60TPVWMRM4WJm6nTogAz2qBrFsf/XwT/ajzbsjT6HNB7QbRE+wkFkqspoXG5Agp7KQ8lW3L +SKCDGOQJz7VIE85pD0tg7QEXBEw8oaRZtMjQ0Gvs25mxXAKka4wGasaWfYH6d0E+iKYcWn86V1rH +K2ZoknT+Nno5jgjFuUR3fZseNizEfx7BteooKQ== +-----END CERTIFICATE----- + +crl-verify file missing in config profile +remote-cert-tls server +cipher AES-128-CBC +auth SHA1 +persist-tun +# persist-tun also enables pre resolving to avoid DNS resolve problem +preresolve +# Custom configuration options +# You are on your on own here :) +# These options found in the config file do not map to config settings: +keepalive 10 30 +tls-cipher DHE-RSA-AES128-SHA \ No newline at end of file diff --git a/app/src/test/resources/openvpnConfigs/udp_tcp.ovpn b/app/src/test/resources/openvpnConfigs/udp_tcp.ovpn new file mode 100644 index 00000000..300d265e --- /dev/null +++ b/app/src/test/resources/openvpnConfigs/udp_tcp.ovpn @@ -0,0 +1,117 @@ +# Config for OpenVPN 2.x +# Enables connection to GUI +management /data/data/se.leap.bitmask/mgmtsocket unix +management-client +management-query-passwords +management-hold + +setenv IV_GUI_VER "se.leap.bitmaskclient 0.9.10" +setenv IV_PLAT_VER "0 null JUNIT null null null" +machine-readable-output +allow-recursive-routing +ifconfig-nowarn +client +verb 4 +connect-retry 2 300 +resolv-retry 60 +dev tun +remote 198.252.153.84 443 udp +remote 198.252.153.84 443 tcp-client + +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt +YXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNVBAsME2h0dHBzOi8v +Yml0bWFzay5uZXQwHhcNMTIxMTA2MDAwMDAwWhcNMjIxMTA2MDAwMDAwWjBKMRgw +FgYDVQQDDA9CaXRtYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNV +BAsME2h0dHBzOi8vYml0bWFzay5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQC1eV4YvayaU+maJbWrD4OHo3d7S1BtDlcvkIRS1Fw3iYDjsyDkZxai +dHp4EUasfNQ+EVtXUvtk6170EmLco6Elg8SJBQ27trE6nielPRPCfX3fQzETRfvB +7tNvGw4Jn2YKiYoMD79kkjgyZjkJ2r/bEHUSevmR09BRp86syHZerdNGpXYhcQ84 +CA1+V+603GFIHnrP+uQDdssW93rgDNYu+exT+Wj6STfnUkugyjmPRPjL7wh0tzy+ +znCeLl4xiV3g9sjPnc7r2EQKd5uaTe3j71sDPF92KRk0SSUndREz+B1+Dbe/RGk4 +MEqGFuOzrtsgEhPIX0hplhb0Tgz/rtug+yTT7oJjBa3u20AAOQ38/M99EfdeJvc4 +lPFF1XBBLh6X9UKF72an2NuANiX6XPySnJgZ7nZ09RiYZqVwu/qt3DfvLfhboq+0 +bQvLUPXrVDr70onv5UDjpmEA/cLmaIqqrduuTkFZOym65/PfAPvpGnt7crQj/Ibl +DEDYZQmP7AS+6zBjoOzNjUGE5r40zWAR1RSi7zliXTu+yfsjXUIhUAWmYR6J3KxB +lfsiHBQ+8dn9kC3YrUexWoOqBiqJOAJzZh5Y1tqgzfh+2nmHSB2dsQRs7rDRRlyy +YMbkpzL9ZsOUO2eTP1mmar6YjCN+rggYjRrX71K2SpBG6b1zZxOG+wIDAQABo2Aw +XjAdBgNVHQ4EFgQUuYGDLL2sswnYpHHvProt1JU+D48wDgYDVR0PAQH/BAQDAgIE +MAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUuYGDLL2sswnYpHHvProt1JU+D48w +DQYJKoZIhvcNAQENBQADggIBADeG67vaFcbITGpi51264kHPYPEWaXUa5XYbtmBl +cXYyB6hY5hv/YNuVGJ1gWsDmdeXEyj0j2icGQjYdHRfwhrbEri+h1EZOm1cSBDuY +k/P5+ctHyOXx8IE79DBsZ6IL61UKIaKhqZBfLGYcWu17DVV6+LT+AKtHhOrv3TSj +RnAcKnCbKqXLhUPXpK0eTjPYS2zQGQGIhIy9sQXVXJJJsGrPgMxna1Xw2JikBOCG +htD/JKwt6xBmNwktH0GI/LVtVgSp82Clbn9C4eZN9E5YbVYjLkIEDhpByeC71QhX +EIQ0ZR56bFuJA/CwValBqV/G9gscTPQqd+iETp8yrFpAVHOW+YzSFbxjTEkBte1J +aF0vmbqdMAWLk+LEFPQRptZh0B88igtx6tV5oVd+p5IVRM49poLhuPNJGPvMj99l +mlZ4+AeRUnbOOeAEuvpLJbel4rhwFzmUiGoeTVoPZyMevWcVFq6BMkS+jRR2w0jK +G6b0v5XDHlcFYPOgUrtsOBFJVwbutLvxdk6q37kIFnWCd8L3kmES5q4wjyFK47Co +Ja8zlx64jmMZPg/t3wWqkZgXZ14qnbyG5/lGsj5CwVtfDljrhN0oCWK1FZaUmW3d +69db12/g4f6phldhxiWuGC/W6fCW5kre7nmhshcltqAJJuU47iX+DarBFiIj816e +yV8e +-----END CERTIFICATE----- + + + +-----BEGIN RSA PRIVATE KEY----- +MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDUTYWeGgsHS+fjijmziniNqw6h +MBpyK4S/cM6PxV28C33VuOWPTMcIYesctjZANWFCggfFTQSjV5Qaxq9UK4i27tayLbCdlVS6hpbl +Vf4DuI3Gj1Pv1rtITBShtvCf3T7yBnjW4wVpOpsUAAOViKUSvUU3kPPMFWhiGQw8yHYr82ts6XMo +jwMoonW5Ml4e7C7Cr22QesC63q7emNcpUd0pZGT9C33RgDAHZDMrlyjo4HEp1JbUfB0gbmXElJbE +1TNdZ62HhgmMjzTUN1GGrQ1t91AEoEQwaK65o4YSj+yFv6KXZZz5OWaz94tKiN9v26EXtBFmRlyb +6+D9ynSd9LghAgMBAAECggEBANPHLRXkhsHVj1EkzqBx7gXr8CEMmiTvknFh9zvltrZhhDoRQjWr +chPDkcRHY2Cznvy4N0YyqQDD2ULIlZdSAgPxxothFoBruWSD47yMBmLx08ORsDpcqt/YvPAATJI8 +IpFNsXcyaXBp/M57oRemgnxp/8UJPJmFdWX99H4hvffh/jdj7POgYiWUaAl37XTYZKZ4nzKU2wpL +EDLj9RKPz9gG7CYp2zrLC9LaAsrXVrKwPBw6g+XwbClaqFj97db3mrY4lr6mTo89qmus1AU+fBDH +3Xlpmc8JwB+30TvhRNKrpLx9cEjuEj7K1gm8Y4dWCjPi+lNbtAyUBcgPJFa/81ECgYEA7pLoBU/Y +ZYjyHFca8FvDBcBh6haHfqJr9doXWtgjDrbi3o2n5wHqfKhFWOH6vPEQozkOVeX1ze6HOiRmGBpW +r+r7x8TD25L7I6HJw3M351RWOAfkF0w/RTVdetcTgduQtfN1u6BDhYSVceXMjyQYx7MhfETWI8Gh +KSYm8OEDYiUCgYEA489fmbrCcUnXzpTsbswJ5NmSoEXbcX8cLxnQuzE0z9GHhQdrMjOpXR76reTW +6jcuudarNcwRUYSWWhjCDKHhpx4HhasWPaHgr7jIzcRw8yZSJRSxKr8sl1qh6g7s47JcmfXOMWLt +yuyE933XrT19Th4ODZHY40Uv35mPjMi9d00CgYEAyRNAQtndBRa7GG/B4Ls2T+6pl+aNJIo4e+no +rURlp800wWabEPRocdBRQmyULBLxduBr2LIMzhgwGSz8b2wji/l9ZA3PFY135bxClVzSzUIjuO3N +rGUzHl2wAAyuAFDSUshzfkPBJRNt8aVBF5PQ3t93ZYmPAmv8LPZe875yX5ECgYEAsUEcwK/ZNW7g +dQPZR4iJNkC4Xu6cBZ6Cnn92swBheEYvLSoNlX0vDZ7aLE3/jzQqrjzC8NP8sbH5jtbuvgeDXZX3 +AmGRp5j6C6A61ihAPmEVz3ZfN8SSfJ3vl//PAIg6lyz0J+cy4Q7RkwSeuVQ72Hl4M8TEvmmKC3Af +ispy6Y0CgYEAgl1o2lo+ACyk+oVQPaaPqK3d7WOBFp4eR2nXFor/vsx9igQOlZUgzRDQsR8jo1o9 +efOSBf87igrZGgssys89pWa2dnXnz5PMmzkKr6bw4D9Ez6u6Puc9UZhGw/8wDYg6fSosdB9utspm +M698ycef7jBNMDgmhpSvfw5GctoNQ4s= +-----END RSA PRIVATE KEY----- + + +-----BEGIN CERTIFICATE----- +MIIEjDCCAnSgAwIBAgIQG6MBp/cd9DlY+7cdvp3R3jANBgkqhkiG9w0BAQsFADBmMRAwDgYDVQQK +DAdCaXRtYXNrMRwwGgYDVQQLDBNodHRwczovL2JpdG1hc2submV0MTQwMgYDVQQDDCtCaXRtYXNr +IFJvb3QgQ0EgKGNsaWVudCBjZXJ0aWZpY2F0ZXMgb25seSEpMB4XDTE0MTIwNTAwMDAwMFoXDTE1 +MDMwNTAwMDAwMFowLTErMCkGA1UEAwwiVU5MSU1JVEVEZDBwZDdkMzE4eTNtOHNkeXllaTFqYmZl +eDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANRNhZ4aCwdL5+OKObOKeI2rDqEwGnIr +hL9wzo/FXbwLfdW45Y9Mxwhh6xy2NkA1YUKCB8VNBKNXlBrGr1QriLbu1rItsJ2VVLqGluVV/gO4 +jcaPU+/Wu0hMFKG28J/dPvIGeNbjBWk6mxQAA5WIpRK9RTeQ88wVaGIZDDzIdivza2zpcyiPAyii +dbkyXh7sLsKvbZB6wLrert6Y1ylR3SlkZP0LfdGAMAdkMyuXKOjgcSnUltR8HSBuZcSUlsTVM11n +rYeGCYyPNNQ3UYatDW33UASgRDBorrmjhhKP7IW/opdlnPk5ZrP3i0qI32/boRe0EWZGXJvr4P3K +dJ30uCECAwEAAaNvMG0wHQYDVR0OBBYEFK8bMVAM4GBB5sHptoIOAaIvlYueMAsGA1UdDwQEAwIH +gDATBgNVHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFId+E7bsWFsUWah9 +vZuPvZ7O+aJsMA0GCSqGSIb3DQEBCwUAA4ICAQAQOX81csVhvP422NKkZH7+g3npBpl+sEHedaGR +xYPOu4HrA4TVF9h44sljRoRJyenGNdBZCXcLKHg889eePTf8Z5K3lTojp6hvwyA6tgxOMHT1kESW +PfqnRw8mHfHJuE3g+4YNUMwggzwc/VZATdV/7M33sarVN9AUOHou9n9BizgCC+UnYlS+F2POumE3 +FbOhKo5uubI02MwBYlN2JVO2TBt1Q20w8wc6cU07Xi5Epp+1mkgFiOShkNtPcJmEyBWJhxDtSDOW +2doqWYNqH2kq7B5R/kyyfcpFJqAnBTV7xs+C5rTS1mW7LpxfdCUMbYuLCpyxpO3A/DhAm8n47tUH +lBtmo8Avdb8VdFpYiGBpB0o9kTFcsWFb2GkWFBduGfSEB8jUI7QtqhgZqocAKK/cweSRV8FwyUcn +R0prRm3QEi9fbXqEddzjSY9y/lqWYzT7u+IOAQpKroeZ4wzgYperDNOUFuYk1rP7yuvjP2pV5rcN +yPoBP60TPVWMRM4WJm6nTogAz2qBrFsf/XwT/ajzbsjT6HNB7QbRE+wkFkqspoXG5Agp7KQ8lW3L +SKCDGOQJz7VIE85pD0tg7QEXBEw8oaRZtMjQ0Gvs25mxXAKka4wGasaWfYH6d0E+iKYcWn86V1rH +K2ZoknT+Nno5jgjFuUR3fZseNizEfx7BteooKQ== +-----END CERTIFICATE----- + +crl-verify file missing in config profile +remote-cert-tls server +cipher AES-128-CBC +auth SHA1 +persist-tun +# persist-tun also enables pre resolving to avoid DNS resolve problem +preresolve +# Custom configuration options +# You are on your on own here :) +# These options found in the config file do not map to config settings: +keepalive 10 30 +tls-cipher DHE-RSA-AES128-SHA \ No newline at end of file diff --git a/app/src/test/resources/ptdemo.bitmask.eip-service.json b/app/src/test/resources/ptdemo.bitmask.eip-service.json new file mode 100644 index 00000000..38146a40 --- /dev/null +++ b/app/src/test/resources/ptdemo.bitmask.eip-service.json @@ -0,0 +1,64 @@ +{ + "gateways":[ + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"obfs4", + "protocols":[ + "tcp" + ], + "ports":[ + "23049" + ], + "options": { + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "iat-mode": "0" + } + }, + { + "type":"openvpn", + "protocols":[ + "tcp" + ], + "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":2 +} \ No newline at end of file diff --git a/app/src/test/resources/ptdemo_pt_tcp_udp.eip-service.json b/app/src/test/resources/ptdemo_pt_tcp_udp.eip-service.json new file mode 100644 index 00000000..4337547b --- /dev/null +++ b/app/src/test/resources/ptdemo_pt_tcp_udp.eip-service.json @@ -0,0 +1,65 @@ +{ + "gateways":[ + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"obfs4", + "protocols":[ + "tcp" + ], + "ports":[ + "23049" + ], + "options": { + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "iat-mode": "0" + } + }, + { + "type":"openvpn", + "protocols":[ + "tcp", + "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":2 +} \ No newline at end of file diff --git a/app/src/test/resources/ptdemo_pt_udp_tcp.eip-service.json b/app/src/test/resources/ptdemo_pt_udp_tcp.eip-service.json new file mode 100644 index 00000000..4161fced --- /dev/null +++ b/app/src/test/resources/ptdemo_pt_udp_tcp.eip-service.json @@ -0,0 +1,65 @@ +{ + "gateways":[ + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"obfs4", + "protocols":[ + "tcp" + ], + "ports":[ + "23049" + ], + "options": { + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "iat-mode": "0" + } + }, + { + "type":"openvpn", + "protocols":[ + "udp", + "tcp" + ], + "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":2 +} \ No newline at end of file -- cgit v1.2.3 From 0322a53ca28a96ecbf20b1f63e99b8b31f201316 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 12 Jun 2019 16:46:19 +0200 Subject: update test server setup --- app/src/custom/assets/ptdemo.bitmask.eip-service.json | 6 +++--- app/src/custom/assets/ptdemo.bitmask.secrets.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'app/src') diff --git a/app/src/custom/assets/ptdemo.bitmask.eip-service.json b/app/src/custom/assets/ptdemo.bitmask.eip-service.json index 22bcb605..05dc1447 100644 --- a/app/src/custom/assets/ptdemo.bitmask.eip-service.json +++ b/app/src/custom/assets/ptdemo.bitmask.eip-service.json @@ -12,10 +12,10 @@ "tcp" ], "ports":[ - "23049" + "23042" ], "options": { - "cert": "2p8QUt36lBAJxj2x8XLj5NYOuenqi6w7RUr88LIcZVSgADXipj1tMs9mzLKzgDMbx02ERA", + "cert": "ivF1AFjQupVhFHn7koBPb9lBZJbc+RW/ArzR94hT0SRg3lWSk/mXHHiDQ/tYaT+zgxr1dQ", "iat-mode": "0" } }, @@ -46,7 +46,7 @@ }, "openvpn_configuration":{ "auth":"SHA1", - "cipher":"AES-256-CBC", + "cipher":"AES-128-CBC", "keepalive":"10 30", "tls-cipher":"DHE-RSA-AES128-SHA", "tun-ipv6":true, diff --git a/app/src/custom/assets/ptdemo.bitmask.secrets.json b/app/src/custom/assets/ptdemo.bitmask.secrets.json index 4f81b16b..7d84bd79 100644 --- a/app/src/custom/assets/ptdemo.bitmask.secrets.json +++ b/app/src/custom/assets/ptdemo.bitmask.secrets.json @@ -1,5 +1,5 @@ { - "ca_cert":"-----BEGIN CERTIFICATE-----\nMIID9zCCAt+gAwIBAgIJAN0nU8cxAj3EMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV\nBAsTAlBUMRswGQYDVQQDExJjaG9sbGEuYml0bWFzay5uZXQxCzAJBgNVBCkTAlBU\nMSEwHwYJKoZIhvcNAQkBFhJrd2Fkcm9uYXV0QGxlYXAuc2UwHhcNMTkwMjE5MDk0\nMDQ4WhcNMjAwMjE5MDk0MDQ4WjBaMQswCQYDVQQLEwJQVDEbMBkGA1UEAxMSY2hv\nbGxhLmJpdG1hc2submV0MQswCQYDVQQpEwJQVDEhMB8GCSqGSIb3DQEJARYSa3dh\nZHJvbmF1dEBsZWFwLnNlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\ny3mhthCb6tunc4HWsX4UWgBld7H6WSOmJHOCEBjy4WZUTI9/AWA/j9pwf1WD8HKV\nxCND2Cg1j1Xc3wfTt0wJTbBPO7/chDpNlStW1KpcbiZPfkIumkqq5XNUTjOrleEm\neqqCtPvqVUyuYnGlE5dWIO3i9w1/cxhx6vi8zlsCoS1VWPdCDJvMW+9jPBL+kFe4\nF7k12lGy8t29/i4/mbzLkjAV0ZfR+S0w2hWZ1jXvzJdJQ+PP9L63hVxHQ5sUSDn9\n3SWUV7y39rHwXZdlttOE0aswvvfPlqrbD7n42mhlgySkpvXyMBkBrwIh5TnGXZ/B\nTtkPjnYCaiRXseZGrNnWhwIDAQABo4G/MIG8MB0GA1UdDgQWBBQKWWxEDacg7JAg\nuu4OJn2ZCLt69DCBjAYDVR0jBIGEMIGBgBQKWWxEDacg7JAguu4OJn2ZCLt69KFe\npFwwWjELMAkGA1UECxMCUFQxGzAZBgNVBAMTEmNob2xsYS5iaXRtYXNrLm5ldDEL\nMAkGA1UEKRMCUFQxITAfBgkqhkiG9w0BCQEWEmt3YWRyb25hdXRAbGVhcC5zZYIJ\nAN0nU8cxAj3EMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ2L7xwP\nkushZPh1l3hpfs/Em0j18oSEkvsPnm8C/o7MSqWR8zN4ehJBzUdjl7HGZGNL+AEO\nO57TDRyQ6MOATnG3DIi+6mud+XjKIPnKK3+ZeB/+UIeScB7PmiDdlXlM27s+d2mK\nEszgtBnzvI3+NRi8ub3IaeYqKnsEWNki/wJFx04fWqvjQXbGsJfWgwJi9jpJm2BT\nJ9gztPM4Hz1pTEWLqNxjyKmq9uMj8itGIiKWwbMXCuCk096U9UXM/fzs5LsL3bC7\n2oZ61s2Z2Z2BWObEMhtl8PgKX08t6ljhKBTN1l6O8VvyNwB45z8x+XEKw8SMDCeB\nS7HFRYge19Wm5hA=\n-----END CERTIFICATE-----\n", - "cert":"-----BEGIN CERTIFICATE-----\nMIIC6jCCAdICCQDcV1xCQ6eNYDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQLEwJQ\nVDEbMBkGA1UEAxMSY2hvbGxhLmJpdG1hc2submV0MQswCQYDVQQpEwJQVDEhMB8G\nCSqGSIb3DQEJARYSa3dhZHJvbmF1dEBsZWFwLnNlMB4XDTE5MDIxOTEwMTUxOVoX\nDTIxMTIxMDEwMTUxOVowFDESMBAGA1UEAwwJVU5MSU1JVEVEMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmm4WGL3Rf9keZU8AIfBPoDZ81t747UkBeW5y\nskTixdcw8ryP11Lx2LdN6C2srYN1U6ss8qq0FnQDCZK7+kP5fr3qgR8OI+nrbgaP\nBwcpX3S5E1LK2ho9NUp9wDkZgD7oX3GhvEOrTdGGLSS9DdnUEyZqR6WhQ4MyKbQY\nbRJdslnXyrVW0ZR2XzcSXe8SfPhgmTj1b/rQfPdZ+C8FuuTbb+AWHV7sLlPfcx3/\nahk9bZ42/nhU1v1l1k7stKJLpK426/CpP1tzpbwKClPodntdIGgnyJk/QSTheIN+\nOjeB1MJ8VglQ/RRxnhZf4BF2UVq32SQAY+hY6WiUDDtIljkhmQIDAQABMA0GCSqG\nSIb3DQEBCwUAA4IBAQAo6BGmPdqeqkIMtrxE+NpvVIdInAw1weOKdnOcI0vVcWDF\nZ6gm7VAlb6DVN52JqOAkafrwzIMLH2/7AyQ9pHpL5pf8php9yzwLWjtWW1HO2R61\nS0RAdSJbpoksRKR0BBd7mOjqMLfU7a9mnXBMT/DFyOexX94UIcj+f8kuJZDziURN\nPIoHgxX14synhgKFZ7Xae9F3l/B48QWilrMqKXvgk09LJDEJ1jem7rYZ/9pwKXmx\nkMMk/vsCmUpd4bJFBK4RLeieUG6NBAaxz8IHha4J+8PyKjHs4GnIFtrFKv313g2b\niStrXOHaFBslotZEJsRKYV++/z6ttBbExKx2M+9V\n-----END CERTIFICATE-----\n", - "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAmm4WGL3Rf9keZU8AIfBPoDZ81t747UkBeW5yskTixdcw8ryP\n11Lx2LdN6C2srYN1U6ss8qq0FnQDCZK7+kP5fr3qgR8OI+nrbgaPBwcpX3S5E1LK\n2ho9NUp9wDkZgD7oX3GhvEOrTdGGLSS9DdnUEyZqR6WhQ4MyKbQYbRJdslnXyrVW\n0ZR2XzcSXe8SfPhgmTj1b/rQfPdZ+C8FuuTbb+AWHV7sLlPfcx3/ahk9bZ42/nhU\n1v1l1k7stKJLpK426/CpP1tzpbwKClPodntdIGgnyJk/QSTheIN+OjeB1MJ8VglQ\n/RRxnhZf4BF2UVq32SQAY+hY6WiUDDtIljkhmQIDAQABAoIBAQCZ4iLgqp2NMTRJ\nrUwrhYRC2KjTkEIqaLowX6+pFl2G2STsbJtE7GEUG6xlNMZB7KHIKuVSNmnXiejQ\n7EemXX/LHMIFwoVboie4bo6taSR/+xbFO5XpeYYOiVj/Z6aSlZ0GJnwM1r1ngOac\nK2S73ZinMHttQ42LcbtVtSE15rw5ECNG7I0LF1SUOntorWPFh/wO6o2qDHEMoo/2\nvWc4C9TT79md2dTGs/jQql5sVwiKu+1EQdIY4ihmZ6eA3dww7Irk0KUVgt/2X0Al\nBlLvwGkDZxUAl91/7eLj5P+nKS8FzDSxmQQsz8hBUljWDJTJ3kQx5A0IzS9HTb98\nDuZELQ+RAoGBAMvMVsoJ2XtC3Q8TIjvxEqt1qD43MIgDSqAGCNnkcICuNlMbdxZu\nqoHB6ray1e6ydQKlvwtcehADLK1UCvQHQ2UqFfOy4/gTadBVYnGVu9/RNHlXXbQY\nNbyKRr2IuMBTBgCFyabSqbOZiWsrWoA3eVpbf1OmnBxnrv6OOz/AgecFAoGBAMH8\nhw9d7CHKskVLMmW9L20Roewq9rN1IgQu1ZAkg73EPGfG4iD5AVyTjlnM+HBKrTx7\n4ezLLN2EAswXCpyR2qbZx8KNCws/uHp1GGII3Vd7QVZcE5YC7nd/9lugI0HCe63Y\nl3uimjvN8xW0F/vPlUTDLCsTccBHI7FzbBsHDmyFAoGACMwYTv5f2fdH7Zeo2aeN\nY8NfcNgXCzgBJ6k7BpTa2mMqyymbWWeLirBhPmO34mbnsCaReZ8TUc+hRRYkpuYN\nXbeUXQGy34mO/sRAzKBnDMFOH5LK47RL1Yiuhw3406yBzNH5o27ijnMpQGwNqw05\n+tGKTIUbpgo/vpNLMXRQ5zUCgYAgKO53NLn+DC2r4UCUr12adm7iyWim7cda7CzJ\nvdP9dPgSuF0q3D1GjMvvxVR2wVqhCWS2LiTdAJK6JSPEO0YFnVtJvLpU/hZmbt1A\n+3k+lJeLaq5wk0HXm+ZK4GyX7Vc1xg+vFpD9UzJ2qanEPHDhun2rEoksOF8Jfzov\n7OaORQKBgHGPL8kp2v0IVwkY2a6Llr8i0HBBHNtgF/hgqP0qGO2u3F6Yi4Ly6Mng\n/odnAGV5KZIlis/MaDvPP4MohCgwuDq96V4yUQcG6iQlJa++p6owj5TUXMSdsYTi\n6IJ+tJLLlHg59oxhBBCKORxres2ht3d0gw12N52OvdoIg/bUbW0m\n-----END RSA PRIVATE KEY-----" + "ca_cert":"-----BEGIN CERTIFICATE-----\nMIIFjTCCA3WgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBZMRgwFgYDVQQKDA9SaXNl\ndXAgTmV0d29ya3MxGzAZBgNVBAsMEmh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UE\nAwwXUmlzZXVwIE5ldHdvcmtzIFJvb3QgQ0EwHhcNMTQwNDI4MDAwMDAwWhcNMjQw\nNDI4MDAwMDAwWjBZMRgwFgYDVQQKDA9SaXNldXAgTmV0d29ya3MxGzAZBgNVBAsM\nEmh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UEAwwXUmlzZXVwIE5ldHdvcmtzIFJv\nb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC76J4ciMJ8Sg0m\nTP7DF2DT9zNe0Csk4myoMFC57rfJeqsAlJCv1XMzBmXrw8wq/9z7XHv6n/0sWU7a\n7cF2hLR33ktjwODlx7vorU39/lXLndo492ZBhXQtG1INMShyv+nlmzO6GT7ESfNE\nLliFitEzwIegpMqxCIHXFuobGSCWF4N0qLHkq/SYUMoOJ96O3hmPSl1kFDRMtWXY\niw1SEKjUvpyDJpVs3NGxeLCaA7bAWhDY5s5Yb2fA1o8ICAqhowurowJpW7n5ZuLK\n5VNTlNy6nZpkjt1QycYvNycffyPOFm/Q/RKDlvnorJIrihPkyniV3YY5cGgP+Qkx\nHUOT0uLA6LHtzfiyaOqkXwc4b0ZcQD5Vbf6Prd20Ppt6ei0zazkUPwxld3hgyw58\nm/4UIjG3PInWTNf293GngK2Bnz8Qx9e/6TueMSAn/3JBLem56E0WtmbLVjvko+LF\nPM5xA+m0BmuSJtrD1MUCXMhqYTtiOvgLBlUm5zkNxALzG+cXB28k6XikXt6MRG7q\nhzIPG38zwkooM55yy5i1YfcIi5NjMH6A+t4IJxxwb67MSb6UFOwg5kFokdONZcwj\nshczHdG9gLKSBIvrKa03Nd3W2dF9hMbRu//STcQxOailDBQCnXXfAATj9pYzdY4k\nha8VCAREGAKTDAex9oXf1yRuktES4QIDAQABo2AwXjAdBgNVHQ4EFgQUC4tdmLVu\nf9hwfK4AGliaet5KkcgwDgYDVR0PAQH/BAQDAgIEMAwGA1UdEwQFMAMBAf8wHwYD\nVR0jBBgwFoAUC4tdmLVuf9hwfK4AGliaet5KkcgwDQYJKoZIhvcNAQENBQADggIB\nAGzL+GRnYu99zFoy0bXJKOGCF5XUXP/3gIXPRDqQf5g7Cu/jYMID9dB3No4Zmf7v\nqHjiSXiS8jx1j/6/Luk6PpFbT7QYm4QLs1f4BlfZOti2KE8r7KRDPIecUsUXW6P/\n3GJAVYH/+7OjA39za9AieM7+H5BELGccGrM5wfl7JeEz8in+V2ZWDzHQO4hMkiTQ\n4ZckuaL201F68YpiItBNnJ9N5nHr1MRiGyApHmLXY/wvlrOpclh95qn+lG6/2jk7\n3AmihLOKYMlPwPakJg4PYczm3icFLgTpjV5sq2md9bRyAg3oPGfAuWHmKj2Ikqch\nTd5CHKGxEEWbGUWEMP0s1A/JHWiCbDigc4Cfxhy56CWG4q0tYtnc2GMw8OAUO6Wf\nXu5pYKNkzKSEtT/MrNJt44tTZWbKV/Pi/N2Fx36my7TgTUj7g3xcE9eF4JV2H/sg\ntsK3pwE0FEqGnT4qMFbixQmc8bGyuakr23wjMvfO7eZUxBuWYR2SkcP26sozF9PF\ntGhbZHQVGZUTVPyvwahMUEhbPGVerOW0IYpxkm0x/eaWdTc4vPpf/rIlgbAjarnJ\nUN9SaWRlWKSdP4haujnzCoJbM7dU9bjvlGZNyXEekgeT0W2qFeGGp+yyUWw8tNsp\n0BuC1b7uW/bBn/xKm319wXVDvBgZgcktMolak39V7DVO\n-----END CERTIFICATE-----", + "cert":"-----BEGIN CERTIFICATE-----\nMIIEnDCCAoSgAwIBAgIRAIO8Bvjp207KpTPf+yH071gwDQYJKoZIhvcNAQELBQAwdTEYMBYGA1UE\nCgwPUmlzZXVwIE5ldHdvcmtzMRswGQYDVQQLDBJodHRwczovL3Jpc2V1cC5uZXQxPDA6BgNVBAMM\nM1Jpc2V1cCBOZXR3b3JrcyBSb290IENBIChjbGllbnQgY2VydGlmaWNhdGVzIG9ubHkhKTAeFw0x\nOTA1MTAwMDAwMDBaFw0xOTA4MTAwMDAwMDBaMC0xKzApBgNVBAMMIlVOTElNSVRFRGMwd2ZxOWhp\ndzA1OGthd3pkeTJuc3BnOGgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPG1Iphzfb\nYDwC7fwF7bF2JFGw4Rye/6fDp1U0rUEbSz06d57S/hxNXdEoM9OBtUm97ucSoUsemTNabTvGMc8y\nyidwtzhtzTOkq9S/lBu9UlA7Btsz3bWqvVVdVVB+ZOVh/SJREb0TMPQQCW499D0DMJfHFu9xHl9w\nzr+KZxuHxnWr94p8IG4BhssT2PnwK+TeuS3lBPXvG+ctbXCDipg0GJQU7EnshVS+6ECdcyFmAsK8\nJxH3bYAvKSIKxFXVToTRhHJjx/QjF3tgCBN8QNyLv/1AFZxn9cQq2MF0pqwdqfgARpcW2Cg3DXTW\nQMn2/upsxNrzj594/gmPgj2h3kFLAgMBAAGjbzBtMB0GA1UdDgQWBBTHUj4H4e88Pf69piaRFWpP\nmA1MijALBgNVHQ8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwIwCQYDVR0TBAIwADAfBgNVHSME\nGDAWgBQX9BvV5SoBAU1rol02CikJlmWARjANBgkqhkiG9w0BAQsFAAOCAgEApbPfHKaYV1JJhf3Y\ng8WVQ4Y3FlSSATmWt1dfWqPaEwgR/q5/Wuw1xTnv357F88PQh3xn5BRIDVEPEzd94FXXEjYmzRL3\nWPu36HtqF7IXVwU6qXIIeCZJs5sMUlSjVyaHdTY/IEQarMLUDiLaTZ+9oU/IBBjSpDuyWlnbKYNn\nIM/d1FbOeIZFZpJmw33BcNNa8csjs0jBOmftP9dPIvcFaj3Fb4w5G0rKi5lfA2p4y/faVWFucwcl\nmGlHtwpvoyRPVqVoHrTpcvapOTXORpGSGPzRR4y+Cl1xyeMWor/AF58FGshLkI5gGTXQ0Vth9g+x\nEgeXRJxmSGVw031uGuz1EuUUVDOcYE465PiK7EufPt3zbF7VD76atd7/FdkBcn3pI6BTSWBN0mtw\nt2npAqJuBZhS7tu89FU2SOvj3ieeqzoNuvEPzc55LUEFGTOb1W1KX70AhbaKV9zg3bE11B3B8Byk\nS2el4vw3h3smCyn2wj1TsNZBT0B/htdcHGSPFK8SfgtW209LGlOwqLrCiWKNmhofgZJN3vqettpC\nHD19hUTVfSY1p2AVbTsyJa4mj2tP0++JWfbFbPVtYCIDJxFOeQ+sl4Uqd5l8tr7f89PKgU4dxiol\ndw74HzGJOBTUlv6dozT22y1HQrOIevWMJvvJ4UoJ70nVBZx00jKwevaeook=\n-----END CERTIFICATE-----", + "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDPG1IphzfbYDwC7fwF7bF2JFGw\n4Rye/6fDp1U0rUEbSz06d57S/hxNXdEoM9OBtUm97ucSoUsemTNabTvGMc8yyidwtzhtzTOkq9S/\nlBu9UlA7Btsz3bWqvVVdVVB+ZOVh/SJREb0TMPQQCW499D0DMJfHFu9xHl9wzr+KZxuHxnWr94p8\nIG4BhssT2PnwK+TeuS3lBPXvG+ctbXCDipg0GJQU7EnshVS+6ECdcyFmAsK8JxH3bYAvKSIKxFXV\nToTRhHJjx/QjF3tgCBN8QNyLv/1AFZxn9cQq2MF0pqwdqfgARpcW2Cg3DXTWQMn2/upsxNrzj594\n/gmPgj2h3kFLAgMBAAECggEAOk4EuXA5x2a2PlTlSH38IbhjzxnwxspOXoRzNls4Iwjxec5HRjsH\nmLg6s8izWKbC1de18ca6sSiMDn8F/uvy2ueSZucN2cuVKFy/jheSH6BWuedaOqXGCQU4TQhBmvOo\nqAdta8lEo2x6qTEeeg6SRp2dfQz157CXSdjKj5orY/N3MPUz09IqHifyQFqKZDEl4ZYzFiqeeDnp\nPHNlvtWRp/LaRCr45ppqU2SPCC1y2pGLgJPZOAAsqWA7KiB2wZq2SBFNtspBTZkhG+LBBcZYjnU4\nIuKPnPW1YsSPpAWUZv79Pct6wzwsidPzBmkaJ8Fpkqy8SIbUM4K4am0yFDH14QKBgQD1TfNfwj0Y\nZhC+LOmiU/+Pwfpo1XgU8FQ03diiLNMdcv2G6vXph6/NWBTIVEZoIrz/Y8X4klo/KQ8tyw9d+hYh\nAqJ6S+IFhf+UwbPjk8s8iUZbvn+Nl/DWjq5lu1IYwQl9BzXoptWq9itNSqB8KCyd7WEjn+Tb3Df3\narBAKRYqOQKBgQDYIwNLtR1x9smoVFhI8pFCuyw1h3cO2vn14PVR9P0EEkTzs8+CwU8QYbUpBQpF\nUfmPCJPNcXz5knOxOdtOr+/El3hol+J9XXuZZumjwoFb5fpw+AQxgfAxkJgbR16BJj52MFy8/ymX\n1qzAFf1Cx2sFJkAD9OkqUB0R/Tm3E6hXowKBgQC+Al9d8Ur5tzWI2akvP/lZFVwuEAwvy+it+plv\nJWFyEjwnYaCR/7RBTtTqR70xtJbJDDOw00xsWBWV1xBULv8tGqlYKactuBm81D3PLg/jGEITln+e\n4e5/g42651o0KnJ7EjbDu1cOUhhAimm9QjEtM05nFddkJjSDxXQ4fprYoQKBgFYmDog8lpH4NgS8\nKbxZwwCALmzfo9rt+TfCBMY4Cil3RriEcS/C8UqsR1MkSSW8OOaEGrWGiLPJZge78ef5RG5tmXbH\nI2Wovz0zweid/IWusxYYJUO+cQiwg5BL8CU2Iytkt3I1mlSFIrIlkZ7ucX/J8TYihlVxPUUQU9Lf\nKPhVAoGAd1/wvawIclsAGqXQzINziH4jjRvIV85R59fLEccfTEAqao9blBxDqoMe6biUuodYFQvq\nT+CDj7zzVPNZVbK5FEqu5W6ezIWp+y+tbTWpApdOxhf2lsZZVgm0KtV2uYvNYW0djOW0ci4TaHj5\nfvWaxEkf0ZOSdkEaN4f2mJGIXLM=\n-----END RSA PRIVATE KEY-----" } \ No newline at end of file -- cgit v1.2.3 From 04df0d72d5f085a60e3b75b1b7df6244f04940f0 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 12 Jun 2019 17:39:14 +0200 Subject: define local port to run shapeshifter-dispatcher on startup, fix pid lookup, quick fix architecture for arm --- .../pluggableTransports/Dispatcher.java | 38 +++++----------------- 1 file changed, 8 insertions(+), 30 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java index ac846fd9..05ce2256 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java @@ -24,6 +24,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import java.util.NoSuchElementException; import java.util.StringTokenizer; @@ -33,6 +34,7 @@ import java.util.StringTokenizer; public class Dispatcher { private static final String ASSET_KEY = "piedispatcher"; + private static final String DISPATCHER_PORT = "4430"; private static final String TAG = Dispatcher.class.getName(); private final String remoteIP; private final String remotePort; @@ -40,7 +42,6 @@ public class Dispatcher { private final String iatMode; private File fileDispatcher; private Context context; - private String port = ""; private Thread dispatcherThread = null; private int dipatcherPid = -1; @@ -68,8 +69,10 @@ public class Dispatcher { " -target " + remoteIP + ":" + remotePort + " -transports obfs4" + " -options \"" + String.format("{\\\"cert\\\": \\\"%s\\\", \\\"iatMode\\\": \\\"%s\\\"}\"", certificate, iatMode) + - " -logLevel DEBUG -enableLogging"; + " -logLevel DEBUG -enableLogging" + + " -proxylistenaddr 127.0.0.1:" + DISPATCHER_PORT; + Log.d(TAG, "dispatcher command: " + dispatcherCommand); runBlockingCmd(new String[]{dispatcherCommand}, dispatcherLog); } catch (IOException e) { e.printStackTrace(); @@ -81,37 +84,12 @@ public class Dispatcher { // get pid of dispatcher StringBuilder log = new StringBuilder(); - String pidCommand = "ps | grep " + fileDispatcher.getCanonicalPath(); + String pidCommand = "ps | grep piedispatcher"; runBlockingCmd(new String[]{pidCommand}, log); String output = log.toString(); StringTokenizer st = new StringTokenizer(output, " "); st.nextToken(); // proc owner dipatcherPid = Integer.parseInt(st.nextToken().trim()); - - // get open port of dispatcher - String getPortCommand = "cat " + context.getFilesDir().getCanonicalPath() + "/state/dispatcher.log | grep \"obfs4 - registered listener\""; - long timeout = System.currentTimeMillis() + 5000; - int i = 1; - while (this.port.length() == 0 && System.currentTimeMillis() < timeout) { - log = new StringBuilder(); - Log.d(TAG, i + ". try to get port"); - runBlockingCmd(new String[]{getPortCommand}, log); - output = log.toString(); - if (output.length() > 0) { - Log.d(TAG, "dispatcher log: \n =================\n" + output); - } - - String dispatcherLog[] = output.split(" "); - if (dispatcherLog.length > 0) { - String localAddressAndPort = dispatcherLog[dispatcherLog.length - 1]; - if (localAddressAndPort.contains(":")) { - this.port = localAddressAndPort.split(":")[1].replace(System.getProperty("line.separator"), ""); - Log.d(TAG, "local port is: " + this.port); - } - } - i += 1; - } - } catch(Exception e){ if (dispatcherThread.isAlive()) { Log.e(TAG, e.getMessage() + ". Shutting down Dispatcher thread."); @@ -121,7 +99,7 @@ public class Dispatcher { } public String getPort() { - return port; + return DISPATCHER_PORT; } public void stop() { @@ -151,7 +129,7 @@ public class Dispatcher { String arch = System.getProperty("os.arch"); if (arch.contains("arm")) - arch = "arm"; + arch = "armeabi-v7a"; else arch = "x86"; -- cgit v1.2.3 From 386c580a9a97870f500bf277a1d1ec25a8f4a056 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 12 Jun 2019 17:42:32 +0200 Subject: add null checks for the case shapeshifter-dispatcher is not running --- app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/src') 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 55a92cb0..b775921c 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -248,7 +248,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if(isVpnRunning()) { if (getManagement() != null && getManagement().stopVPN(replaceConnection)) { if (!replaceConnection) { - if (dispatcher.isRunning()) { + if (dispatcher != null && dispatcher.isRunning()) { dispatcher.stop(); } VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); @@ -258,7 +258,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac return false; } else { if (!replaceConnection) { - if (dispatcher.isRunning()) { + if (dispatcher != null && dispatcher.isRunning()) { dispatcher.stop(); } VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); @@ -395,7 +395,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac obfs4Connection.getmObfs4IatMode()); dispatcher.initSync(); - if (dispatcher.getPort() != null && dispatcher.getPort().length() > 0) { + if (dispatcher.isRunning()) { connection.setServerPort(dispatcher.getPort()); Log.d(TAG, "Dispatcher running. Profile server name and port: " + connection.getServerName() + ":" + connection.getServerPort()); -- cgit v1.2.3 From 8f7146a89fba31bcb9a204415a38e796cfa7d403 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 14 Jun 2019 18:18:18 +0200 Subject: * refactor vpn profile generation * fix lzo-comp flag parsing in ConfigParser --- .../main/java/de/blinkt/openvpn/VpnProfile.java | 25 ++-- .../java/de/blinkt/openvpn/core/ConfigParser.java | 43 +++--- .../de/blinkt/openvpn/core/OpenVPNService.java | 9 +- .../blinkt/openvpn/core/connection/Connection.java | 16 ++- .../openvpn/core/connection/Obfs4Connection.java | 74 ++++------- .../java/se/leap/bitmaskclient/eip/Gateway.java | 2 +- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 10 +- .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 145 +++++++++++---------- .../pluggableTransports/Dispatcher.java | 35 +++-- .../pluggableTransports/DispatcherOptions.java | 18 +++ 10 files changed, 200 insertions(+), 177 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java (limited to 'app/src') diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index 9f18b8ed..dc12c6a8 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -5,11 +5,6 @@ package de.blinkt.openvpn; -import de.blinkt.openvpn.core.connection.Connection; -import de.blinkt.openvpn.core.connection.OpenvpnConnection; -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.BuildConfig; - import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; @@ -58,7 +53,6 @@ import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; -import de.blinkt.openvpn.core.Connection; import de.blinkt.openvpn.core.ExtAuthHelper; import de.blinkt.openvpn.core.NativeUtils; import de.blinkt.openvpn.core.OpenVPNService; @@ -68,9 +62,13 @@ import de.blinkt.openvpn.core.Preferences; import de.blinkt.openvpn.core.VPNLaunchHelper; import de.blinkt.openvpn.core.VpnStatus; import de.blinkt.openvpn.core.X509Utils; +import de.blinkt.openvpn.core.connection.Connection; +import de.blinkt.openvpn.core.connection.Obfs4Connection; +import de.blinkt.openvpn.core.connection.OpenvpnConnection; import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; import static se.leap.bitmaskclient.Constants.PROVIDER_PROFILE; public class VpnProfile implements Serializable, Cloneable { @@ -121,7 +119,7 @@ public class VpnProfile implements Serializable, Cloneable { public String mTLSAuthFilename; public String mClientKeyFilename; public String mCaFilename; - public boolean mUseLzo = true; + public boolean mUseLzo = false; public String mPKCS12Filename; public String mPKCS12Password; public boolean mUseTLSAuth = false; @@ -186,16 +184,16 @@ public class VpnProfile implements Serializable, Cloneable { // set members to default values private UUID mUuid; private int mProfileVersion; + public boolean mUsePluggableTransports; - - public VpnProfile(String name) { + public VpnProfile(String name, Connection.TransportType transportType) { mUuid = UUID.randomUUID(); mName = name; mProfileVersion = CURRENT_PROFILE_VERSION; mConnections = new Connection[1]; - mConnections[0] = new OpenvpnConnection(); mLastUsed = System.currentTimeMillis(); + mUsePluggableTransports = transportType == OBFS4; } public static String openVpnEscape(String unescaped) { @@ -297,6 +295,7 @@ public class VpnProfile implements Serializable, Cloneable { return mName; } + @Deprecated public void upgradeProfile() { if (mProfileVersion < 2) { /* default to the behaviour the OS used */ @@ -327,9 +326,10 @@ public class VpnProfile implements Serializable, Cloneable { } + @Deprecated private void moveOptionsToConnection() { mConnections = new Connection[1]; - Connection conn = new OpenvpnConnection(); + Connection conn = mUsePluggableTransports ? new Obfs4Connection() : new OpenvpnConnection(); conn.setServerName(mServerName); conn.setServerPort(mServerPort); @@ -499,7 +499,8 @@ public class VpnProfile implements Serializable, Cloneable { if (!TextUtils.isEmpty(mCrlFilename)) cfg.append(insertFileData("crl-verify", mCrlFilename)); - if (mUseLzo) { + // compression does not work in conjunction with shapeshifter-dispatcher so far + if (mUseLzo && !mUsePluggableTransports) { cfg.append("comp-lzo\n"); } 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 0e9b1bc4..4c53087f 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java @@ -6,8 +6,8 @@ package de.blinkt.openvpn.core; import android.os.Build; -import android.text.TextUtils; import android.support.v4.util.Pair; +import android.text.TextUtils; import java.io.BufferedReader; import java.io.IOException; @@ -23,7 +23,11 @@ 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.OpenvpnConnection; +import se.leap.bitmaskclient.pluggableTransports.DispatcherOptions; + +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; //! Openvpn Config FIle Parser, probably not 100% accurate but close enough @@ -136,6 +140,7 @@ public class ConfigParser { private HashMap>> options = new HashMap<>(); private HashMap> meta = new HashMap>(); private String auth_user_pass_file; + private DispatcherOptions dispatcherOptions; static public void useEmbbedUserAuth(VpnProfile np, String inlinedata) { String data = VpnProfile.getEmbeddedContent(inlinedata); @@ -346,9 +351,9 @@ public class ConfigParser { // This method is far too long @SuppressWarnings("ConstantConditions") - public VpnProfile convertProfile() throws ConfigParseError, IOException { + public VpnProfile convertProfile(Connection.TransportType transportType) throws ConfigParseError, IOException { boolean noauthtypeset = true; - VpnProfile np = new VpnProfile(CONVERTED_PROFILE); + VpnProfile np = new VpnProfile(CONVERTED_PROFILE, transportType); // Pull, client, tls-client np.clearDefaults(); @@ -451,6 +456,7 @@ public class ConfigParser { if (redirectPrivate != null) { checkRedirectParameters(np, redirectPrivate, false); } + Vector dev = getOption("dev", 1, 1); Vector devtype = getOption("dev-type", 1, 1); @@ -476,7 +482,6 @@ public class ConfigParser { } } - Vector tunmtu = getOption("tun-mtu", 1, 1); if (tunmtu != null) { @@ -487,14 +492,12 @@ public class ConfigParser { } } - Vector mode = getOption("mode", 1, 1); if (mode != null) { if (!mode.get(1).equals("p2p")) throw new ConfigParseError("Invalid mode for --mode specified, need p2p"); } - Vector> dhcpoptions = getAllOption("dhcp-option", 2, 2); if (dhcpoptions != null) { for (Vector dhcpoption : dhcpoptions) { @@ -529,8 +532,10 @@ public class ConfigParser { if (getOption("float", 0, 0) != null) np.mUseFloat = true; - if (getOption("comp-lzo", 0, 1) != null) - np.mUseLzo = true; + Vector useLzo = getOption("comp-lzo", 0, 1); + if (useLzo != null) { + np.mUseLzo = Boolean.valueOf(useLzo.get(1)); + } Vector cipher = getOption("cipher", 1, 1); if (cipher != null) @@ -540,7 +545,6 @@ public class ConfigParser { if (auth != null) np.mAuth = auth.get(1); - Vector ca = getOption("ca", 1, 1); if (ca != null) { np.mCaFilename = ca.get(1); @@ -552,6 +556,7 @@ public class ConfigParser { np.mAuthenticationType = VpnProfile.TYPE_CERTIFICATES; noauthtypeset = false; } + Vector key = getOption("key", 1, 1); if (key != null) np.mClientKeyFilename = key.get(1); @@ -612,7 +617,6 @@ public class ConfigParser { np.mVerb = verb.get(1); } - if (getOption("nobind", 0, 1) != null) np.mNobind = true; @@ -682,8 +686,7 @@ public class ConfigParser { } - - Pair conns = parseConnectionOptions(null); + Pair conns = parseConnectionOptions(null, transportType); np.mConnections = conns.second; Vector> connectionBlocks = getAllOption("connection", 1, 1); @@ -706,6 +709,7 @@ public class ConfigParser { connIndex++; } } + if (getOption("remote-random", 0, 0) != null) np.mRemoteRandom = true; @@ -748,20 +752,21 @@ public class ConfigParser { return TextUtils.join(s, str); } + public void setDispatcherOptions(DispatcherOptions dispatcherOptions) { + this.dispatcherOptions = dispatcherOptions; + } + private Pair parseConnection(String connection, Connection defaultValues) throws IOException, ConfigParseError { // Parse a connection Block as a new configuration file - ConfigParser connectionParser = new ConfigParser(); StringReader reader = new StringReader(connection.substring(VpnProfile.INLINE_TAG.length())); connectionParser.parseConfig(reader); - Pair conn = connectionParser.parseConnectionOptions(defaultValues); - - return conn; + return connectionParser.parseConnectionOptions(defaultValues, defaultValues.getTransportType()); } - private Pair parseConnectionOptions(Connection connDefault) throws ConfigParseError { + private Pair parseConnectionOptions(Connection connDefault, Connection.TransportType transportType) throws ConfigParseError { Connection conn; if (connDefault != null) try { @@ -771,7 +776,7 @@ public class ConfigParser { return null; } else - conn = new OpenvpnConnection(); + conn = transportType == OBFS4 ? new Obfs4Connection(dispatcherOptions) : new OpenvpnConnection(); Vector port = getOption("port", 1, 1); if (port != null) { @@ -825,8 +830,6 @@ public class ConfigParser { // Parse remote config Vector> remotes = getAllOption("remote", 1, 3); - - Vector optionsToRemove = new Vector<>(); // Assume that we need custom options if connectionDefault are set or in the connection specific set for (Map.Entry>> option : options.entrySet()) { 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 b775921c..4a33fd49 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -48,7 +48,6 @@ import se.leap.bitmaskclient.VpnNotificationManager; import se.leap.bitmaskclient.pluggableTransports.Dispatcher; import de.blinkt.openvpn.core.connection.Obfs4Connection; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; 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; @@ -386,13 +385,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.logInfo("Setting up dispatcher."); Connection connection = mProfile.mConnections[0]; - if (connection.getTransportType() == OBFS4) { + if (mProfile.mUsePluggableTransports) { Obfs4Connection obfs4Connection = (Obfs4Connection) connection; - dispatcher = new Dispatcher(this, - obfs4Connection.getmObfs4RemoteProxyName(), - obfs4Connection.getmObfs4RemoteProxyPort(), - obfs4Connection.getmObfs4Certificate(), - obfs4Connection.getmObfs4IatMode()); + dispatcher = new Dispatcher(this, obfs4Connection.getDispatcherOptions()); dispatcher.initSync(); if (dispatcher.isRunning()) { diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java index f333a13e..a318e55d 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java +++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java @@ -35,10 +35,22 @@ public abstract class Connection implements Serializable, Cloneable { } public enum TransportType { - OBFS4, - OPENVPN + OBFS4("obfs4"), + OPENVPN("openvpn"); + + String transport; + + TransportType(String transportType) { + this.transport = transportType; + } + + @Override + public String toString() { + return transport; + } } + private static final long serialVersionUID = 92031902903829089L; 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 790b8b1a..4f6be276 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,6 +1,9 @@ package de.blinkt.openvpn.core.connection; -import org.json.JSONObject; +import se.leap.bitmaskclient.pluggableTransports.DispatcherOptions; + +import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_IP; +import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_PORT; /** * Created by cyberta on 08.03.19. @@ -9,46 +12,38 @@ import org.json.JSONObject; public class Obfs4Connection extends Connection { private static final String TAG = Obfs4Connection.class.getName(); + private DispatcherOptions options; - - private String mObfs4RemoteProxyName = ""; - private String mObfs4RemoteProxyPort = ""; - private String mObfs4Certificate = ""; - private String mObfs4IatMode = ""; - - public Obfs4Connection() { - setDefaults(); - } - - public Obfs4Connection(Connection connection) { - mObfs4RemoteProxyName = connection.getServerName(); - setConnectTimeout(connection.getConnectTimeout()); - setCustomConfiguration(connection.getCustomConfiguration()); - setUseCustomConfig(connection.isUseCustomConfig()); - - setDefaults(); - } - - private void setDefaults() { + public Obfs4Connection(DispatcherOptions options) { setUseUdp(false); - setServerName("127.0.0.1"); - setServerPort(""); + setServerName(DISPATCHER_IP); + setServerPort(DISPATCHER_PORT); setProxyName(""); setProxyPort(""); setProxyAuthUser(null); setProxyAuthPassword(null); setProxyType(ProxyType.NONE); setUseProxyAuth(false); + this.options = options; } - public void setTransportOptions(JSONObject jsonObject) { - mObfs4Certificate = jsonObject.optString("cert"); - mObfs4IatMode = jsonObject.optString("iat-mode"); - } + @Deprecated + public Obfs4Connection() { + setUseUdp(false); + setServerName(DISPATCHER_IP); + setServerPort(DISPATCHER_PORT); + setProxyName(""); + setProxyPort(""); + setProxyAuthUser(null); + setProxyAuthPassword(null); + setProxyType(ProxyType.NONE); + setUseProxyAuth(false); } @Override public Connection clone() throws CloneNotSupportedException { - return super.clone(); + Obfs4Connection connection = (Obfs4Connection) super.clone(); + connection.options = this.options; + return connection; } @Override @@ -56,28 +51,9 @@ public class Obfs4Connection extends Connection { return TransportType.OBFS4; } - public String getmObfs4RemoteProxyName() { - return mObfs4RemoteProxyName; - } - - public void setObfs4RemoteProxyName(String mObfs4RemoteProxyName) { - this.mObfs4RemoteProxyName = mObfs4RemoteProxyName; - } - - public String getmObfs4RemoteProxyPort() { - return mObfs4RemoteProxyPort; - } - - public void setObfs4RemoteProxyPort(String mObfs4RemoteProxyPort) { - this.mObfs4RemoteProxyPort = mObfs4RemoteProxyPort; - } - - public String getmObfs4Certificate() { - return mObfs4Certificate; - } - public String getmObfs4IatMode() { - return mObfs4IatMode; + public DispatcherOptions getDispatcherOptions() { + return options; } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java index b1554af0..50fe74b7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -114,7 +114,7 @@ public class Gateway { try { VpnConfigGenerator vpnConfigurationGenerator = new VpnConfigGenerator(generalConfiguration, secrets, gateway, apiVersion); return vpnConfigurationGenerator.generateVpnProfile(); - } catch (ConfigParser.ConfigParseError | IOException | CloneNotSupportedException | JSONException e) { + } catch (ConfigParser.ConfigParseError | IOException | JSONException e) { // FIXME We didn't get a VpnProfile! Error handling! and log level e.printStackTrace(); return null; diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java index c650938c..cd3ec1c6 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -99,12 +99,10 @@ public class GatewaysManager { int apiVersion = eipDefinition.getInt(VERSION); for (int i = 0; i < gatewaysDefined.length(); i++) { JSONObject gw = gatewaysDefined.getJSONObject(i); - if (isOpenVpnGateway(gw, apiVersion)) { - JSONObject secrets = secretsConfiguration(); - Gateway aux = new Gateway(eipDefinition, secrets, gw); - if (!gateways.contains(aux)) { - addGateway(aux); - } + JSONObject secrets = secretsConfiguration(); + Gateway aux = new Gateway(eipDefinition, secrets, gw); + if (!gateways.contains(aux)) { + addGateway(aux); } } } catch (JSONException e) { 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 7f09d21e..a131bdd8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -27,9 +27,11 @@ import java.util.Iterator; 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 se.leap.bitmaskclient.Provider; +import se.leap.bitmaskclient.pluggableTransports.DispatcherOptions; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import static se.leap.bitmaskclient.Constants.CAPABILITIES; import static se.leap.bitmaskclient.Constants.IP_ADDRESS; import static se.leap.bitmaskclient.Constants.OPTIONS; @@ -40,9 +42,10 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.Constants.REMOTE; import static se.leap.bitmaskclient.Constants.TRANSPORT; import static se.leap.bitmaskclient.Constants.TYPE; +import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_IP; +import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_PORT; public class VpnConfigGenerator { - private JSONObject generalConfiguration; private JSONObject gateway; private JSONObject secrets; @@ -66,18 +69,14 @@ public class VpnConfigGenerator { public void checkCapabilities() { try { - switch (apiVersion) { - case 2: - JSONArray supportedTransports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT); - for (int i = 0; i < supportedTransports.length(); i++) { - JSONObject transport = supportedTransports.getJSONObject(i); - if (transport.getString(TYPE).equals("obfs4")) { - obfs4Transport = transport; - } + if (apiVersion == 2) { + JSONArray supportedTransports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT); + for (int i = 0; i < supportedTransports.length(); i++) { + JSONObject transport = supportedTransports.getJSONObject(i); + if (transport.getString(TYPE).equals(OBFS4.toString())) { + obfs4Transport = transport; } - break; - default: - break; + } } } catch (JSONException e) { @@ -88,54 +87,45 @@ public class VpnConfigGenerator { public VpnProfile generateVpnProfile() throws IllegalStateException, IOException, ConfigParser.ConfigParseError, - CloneNotSupportedException, - JSONException, - NumberFormatException { + NumberFormatException, JSONException { - VpnProfile profile = createOvpnProfile(); if (supportsObfs4()) { - addPluggableTransportConnections(profile); + return createProfile(OBFS4); } - return profile; + + return createProfile(OPENVPN); } private boolean supportsObfs4(){ return obfs4Transport != null; } - private void addPluggableTransportConnections(VpnProfile profile) throws JSONException, CloneNotSupportedException { - JSONArray ports = obfs4Transport.getJSONArray(PORTS); - Connection[] updatedConnections = new Connection[profile.mConnections.length + ports.length()]; - - for (int i = 0; i < ports.length(); i++) { - String port = ports.getString(i); - Obfs4Connection obfs4Connection = new Obfs4Connection(); - obfs4Connection.setObfs4RemoteProxyName(gateway.getString(IP_ADDRESS)); - obfs4Connection.setObfs4RemoteProxyPort(port); - obfs4Connection.setTransportOptions(obfs4Transport.optJSONObject(OPTIONS)); - updatedConnections[i] = obfs4Connection; - } - int k = 0; - for (int i = ports.length(); i < updatedConnections.length; i++, k++) { - updatedConnections[i] = profile.mConnections[k].clone(); - } - profile.mConnections = updatedConnections; - } - - private String getConfigurationString() { + private String getConfigurationString(Connection.TransportType transportType) { return generalConfiguration() - + newLine - + ovpnGatewayConfiguration() - + newLine - + secretsConfiguration() - + newLine - + androidCustomizations(); + + newLine + + gatewayConfiguration(transportType) + + newLine + + androidCustomizations() + + newLine + + secretsConfiguration(); } - private VpnProfile createOvpnProfile() throws IOException, ConfigParser.ConfigParseError { - String configuration = getConfigurationString(); + private VpnProfile createProfile(Connection.TransportType transportType) throws IOException, ConfigParser.ConfigParseError, JSONException { + String configuration = getConfigurationString(transportType); icsOpenvpnConfigParser.parseConfig(new StringReader(configuration)); - return icsOpenvpnConfigParser.convertProfile(); + if (transportType == OBFS4) { + icsOpenvpnConfigParser.setDispatcherOptions(getDispatcherOptions()); + } + return icsOpenvpnConfigParser.convertProfile(transportType); + } + + private DispatcherOptions getDispatcherOptions() throws JSONException { + JSONObject transportOptions = obfs4Transport.getJSONObject(OPTIONS); + String iatMode = transportOptions.getString("iat-mode"); + String cert = transportOptions.getString("cert"); + String port = obfs4Transport.getJSONArray(PORTS).getString(0); + String ip = gateway.getString(IP_ADDRESS); + return new DispatcherOptions(ip, port, cert, iatMode); } private String generalConfiguration() { @@ -161,21 +151,21 @@ public class VpnConfigGenerator { return commonOptions; } - private String ovpnGatewayConfiguration() { + private String gatewayConfiguration(Connection.TransportType transportType) { String remotes = ""; StringBuilder stringBuilder = new StringBuilder(); try { String ipAddress = gateway.getString(IP_ADDRESS); JSONObject capabilities = gateway.getJSONObject(CAPABILITIES); - JSONArray transports = capabilities.getJSONArray(TRANSPORT); switch (apiVersion) { default: case 1: - ovpnGatewayConfigApiv1(stringBuilder, ipAddress, capabilities); + gatewayConfigApiv1(stringBuilder, ipAddress, capabilities); break; case 2: - ovpnGatewayConfigApiv2(stringBuilder, ipAddress, transports); + JSONArray transports = capabilities.getJSONArray(TRANSPORT); + gatewayConfigApiv2(transportType, stringBuilder, ipAddress, transports); break; } } catch (JSONException e) { @@ -190,10 +180,17 @@ public class VpnConfigGenerator { return remotes; } - private void ovpnGatewayConfigApiv1(StringBuilder stringBuilder, String ipAddress, JSONObject capabilities) throws JSONException { + private void gatewayConfigApiv2(Connection.TransportType transportType, StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { + if (transportType == OBFS4) { + obfs4GatewayConfigApiv2(stringBuilder, ipAddress, transports); + } else { + ovpnGatewayConfigApi2(stringBuilder, ipAddress, transports); + } + } + + private void gatewayConfigApiv1(StringBuilder stringBuilder, String ipAddress, JSONObject capabilities) throws JSONException { int port; String protocol; - JSONArray ports = capabilities.getJSONArray(PORTS); for (int i = 0; i < ports.length(); i++) { port = ports.getInt(i); @@ -206,27 +203,41 @@ public class VpnConfigGenerator { } } - private void ovpnGatewayConfigApiv2(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { + private void ovpnGatewayConfigApi2(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { String port; String protocol; + JSONObject openvpnTransport = getTransport(transports, OPENVPN); + JSONArray ports = openvpnTransport.getJSONArray(PORTS); + for (int j = 0; j < ports.length(); j++) { + port = ports.getString(j); + JSONArray protocols = openvpnTransport.getJSONArray(PROTOCOLS); + for (int k = 0; k < protocols.length(); k++) { + protocol = protocols.optString(k); + String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine; + stringBuilder.append(newRemote); + } + } + } + + private JSONObject getTransport(JSONArray transports, Connection.TransportType transportType) throws JSONException { + JSONObject selectedTransport = new JSONObject(); for (int i = 0; i < transports.length(); i++) { JSONObject transport = transports.getJSONObject(i); - if (!transport.getString(TYPE).equals("openvpn")) { - continue; - } - JSONArray ports = transport.getJSONArray(PORTS); - for (int j = 0; j < ports.length(); j++) { - port = ports.getString(j); - JSONArray protocols = transport.getJSONArray(PROTOCOLS); - for (int k = 0; k < protocols.length(); k++) { - protocol = protocols.optString(k); - String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine; - stringBuilder.append(newRemote); - } + if (transport.getString(TYPE).equals(transportType.toString())) { + selectedTransport = transport; + break; } } + return selectedTransport; } + private void obfs4GatewayConfigApiv2(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { + JSONObject obfs4Transport = getTransport(transports, OBFS4); + String route = "route " + ipAddress + " 255.255.255.255 net_gateway" + newLine; + stringBuilder.append(route); + String remote = REMOTE + " " + DISPATCHER_IP + " " + DISPATCHER_PORT + " " + obfs4Transport.getJSONArray(PROTOCOLS).getString(0) + newLine; + stringBuilder.append(remote); + } private String secretsConfiguration() { try { diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java index 05ce2256..240dae75 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java @@ -18,13 +18,13 @@ package se.leap.bitmaskclient.pluggableTransports; import android.content.Context; import android.support.annotation.WorkerThread; +import android.text.TextUtils; import android.util.Log; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; -import java.util.NoSuchElementException; import java.util.StringTokenizer; @@ -34,7 +34,8 @@ import java.util.StringTokenizer; public class Dispatcher { private static final String ASSET_KEY = "piedispatcher"; - private static final String DISPATCHER_PORT = "4430"; + public static final String DISPATCHER_PORT = "4430"; + public static final String DISPATCHER_IP = "127.0.0.1"; private static final String TAG = Dispatcher.class.getName(); private final String remoteIP; private final String remotePort; @@ -43,14 +44,14 @@ public class Dispatcher { private File fileDispatcher; private Context context; private Thread dispatcherThread = null; - private int dipatcherPid = -1; + private int dispatcherPid = -1; - public Dispatcher(Context context, String remoteIP, String remotePort, String certificate, String iatMode) { + public Dispatcher(Context context, DispatcherOptions dispatcherOptions) { this.context = context.getApplicationContext(); - this.remoteIP = remoteIP; - this.remotePort = remotePort; - this.certificate = certificate; - this.iatMode = iatMode; + this.remoteIP = dispatcherOptions.remoteIP; + this.remotePort = dispatcherOptions.remotePort; + this.certificate = dispatcherOptions.cert; + this.iatMode = dispatcherOptions.iatMode; } @WorkerThread @@ -70,7 +71,7 @@ public class Dispatcher { " -transports obfs4" + " -options \"" + String.format("{\\\"cert\\\": \\\"%s\\\", \\\"iatMode\\\": \\\"%s\\\"}\"", certificate, iatMode) + " -logLevel DEBUG -enableLogging" + - " -proxylistenaddr 127.0.0.1:" + DISPATCHER_PORT; + " -proxylistenaddr "+ DISPATCHER_IP + ":" + DISPATCHER_PORT; Log.d(TAG, "dispatcher command: " + dispatcherCommand); runBlockingCmd(new String[]{dispatcherCommand}, dispatcherLog); @@ -82,14 +83,22 @@ public class Dispatcher { }); dispatcherThread.start(); - // get pid of dispatcher + // get pid of dispatcher, try several times in case the dispatcher + // process is not spawned yet StringBuilder log = new StringBuilder(); String pidCommand = "ps | grep piedispatcher"; - runBlockingCmd(new String[]{pidCommand}, log); + for (int i = 0; i < 5; i++) { + runBlockingCmd(new String[]{pidCommand}, log); + if (!TextUtils.isEmpty(log)) { + break; + } + Thread.sleep(100); + } + String output = log.toString(); StringTokenizer st = new StringTokenizer(output, " "); st.nextToken(); // proc owner - dipatcherPid = Integer.parseInt(st.nextToken().trim()); + dispatcherPid = Integer.parseInt(st.nextToken().trim()); } catch(Exception e){ if (dispatcherThread.isAlive()) { Log.e(TAG, e.getMessage() + ". Shutting down Dispatcher thread."); @@ -106,7 +115,7 @@ public class Dispatcher { Log.d(TAG, "Shutting down Dispatcher thread."); if (dispatcherThread != null && dispatcherThread.isAlive()) { try { - killProcess(dipatcherPid); + killProcess(dispatcherPid); } catch (Exception e) { e.printStackTrace(); } diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java new file mode 100644 index 00000000..76ccbd79 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java @@ -0,0 +1,18 @@ +package se.leap.bitmaskclient.pluggableTransports; + +import java.io.Serializable; + +public class DispatcherOptions implements Serializable { + public String cert; + public String iatMode; + public String remoteIP; + public String remotePort; + + public DispatcherOptions(String remoteIP, String remotePort, String cert, String iatMode) { + this.cert = cert; + this.iatMode = iatMode; + this.remoteIP = remoteIP; + this.remotePort = remotePort; + } + +} -- cgit v1.2.3 From bdea6b5469d6a3a136e6a847d1097fbd56ee1053 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 27 Jun 2019 15:57:25 +0200 Subject: use api version 3 for pluggable Transports --- app/src/custom/assets/ptdemo.bitmask.eip-service.json | 4 ++-- .../java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'app/src') diff --git a/app/src/custom/assets/ptdemo.bitmask.eip-service.json b/app/src/custom/assets/ptdemo.bitmask.eip-service.json index 05dc1447..590652d3 100644 --- a/app/src/custom/assets/ptdemo.bitmask.eip-service.json +++ b/app/src/custom/assets/ptdemo.bitmask.eip-service.json @@ -59,6 +59,6 @@ "key-direction" : "1", "verb" : "3" }, - "serial":2, - "version":2 + "serial":3, + "version":3 } \ No newline at end of file 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 a131bdd8..2214b592 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -58,7 +58,7 @@ public class VpnConfigGenerator { public final static String TAG = VpnConfigGenerator.class.getSimpleName(); private final String newLine = System.getProperty("line.separator"); // Platform new line - public VpnConfigGenerator(JSONObject generalConfiguration, JSONObject secrets, JSONObject gateway, int apiVersion) { + public VpnConfigGenerator(JSONObject generalConfiguration, JSONObject secrets, JSONObject gateway, int apiVersion) throws ConfigParser.ConfigParseError { this.generalConfiguration = generalConfiguration; this.gateway = gateway; this.secrets = secrets; @@ -66,21 +66,22 @@ public class VpnConfigGenerator { checkCapabilities(); } - public void checkCapabilities() { + public void checkCapabilities() throws ConfigParser.ConfigParseError { try { - if (apiVersion == 2) { + if (apiVersion == 3) { JSONArray supportedTransports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT); for (int i = 0; i < supportedTransports.length(); i++) { JSONObject transport = supportedTransports.getJSONObject(i); if (transport.getString(TYPE).equals(OBFS4.toString())) { obfs4Transport = transport; + break; } } } } catch (JSONException e) { - e.printStackTrace(); + throw new ConfigParser.ConfigParseError("Api version ("+ apiVersion +") did not match required JSON fields"); } } @@ -161,9 +162,10 @@ public class VpnConfigGenerator { switch (apiVersion) { default: case 1: + case 2: gatewayConfigApiv1(stringBuilder, ipAddress, capabilities); break; - case 2: + case 3: JSONArray transports = capabilities.getJSONArray(TRANSPORT); gatewayConfigApiv2(transportType, stringBuilder, ipAddress, transports); break; -- cgit v1.2.3 From 8b890c1d4e546c613e0eec732ccc52964e0eecc7 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 27 Jun 2019 17:15:49 +0200 Subject: * update eip-service.json for pluggable transports demo setup: riseup's openvpn doesn't support compreesion * write readme how to test obfs and plain openvpn connections --- app/src/custom/assets/README_OBFS_OPENVPN_CONF.txt | 8 ++++++++ app/src/custom/assets/ptdemo.bitmask.eip-service.json | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 app/src/custom/assets/README_OBFS_OPENVPN_CONF.txt (limited to 'app/src') diff --git a/app/src/custom/assets/README_OBFS_OPENVPN_CONF.txt b/app/src/custom/assets/README_OBFS_OPENVPN_CONF.txt new file mode 100644 index 00000000..5bc39576 --- /dev/null +++ b/app/src/custom/assets/README_OBFS_OPENVPN_CONF.txt @@ -0,0 +1,8 @@ +obfs proxy is currently running on +"37.218.247.60" + +the openvpn is running on +"5.79.86.180" + +When testing either an obfuscated or a plain openvpn connection you +need to switch the ips in "ptdemo.bitmask.eip-service.json" \ No newline at end of file diff --git a/app/src/custom/assets/ptdemo.bitmask.eip-service.json b/app/src/custom/assets/ptdemo.bitmask.eip-service.json index 590652d3..f1b01fe0 100644 --- a/app/src/custom/assets/ptdemo.bitmask.eip-service.json +++ b/app/src/custom/assets/ptdemo.bitmask.eip-service.json @@ -25,14 +25,14 @@ "tcp" ], "ports":[ - "1195" + "443" ] } ], "user_ips":false }, "host":"pt.demo.bitmask.net", - "ip_address":"37.218.247.60", + "ip_address":"5.79.86.180", "location":"Amsterdam" } ], @@ -55,7 +55,7 @@ "rcvbuf" : "0", "nobind" : true, "persist-key" : true, - "comp-lzo" : true, + "comp-lzo" : false, "key-direction" : "1", "verb" : "3" }, -- cgit v1.2.3 From c1daf5e3e38682fa06bd74c37392b8f2b165ebe9 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 3 Jul 2019 17:59:41 +0200 Subject: update pt openvpn setup readme --- app/src/custom/assets/README_OBFS_OPENVPN_CONF.txt | 2 +- app/src/custom/assets/ptdemo.bitmask.eip-service.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app/src') diff --git a/app/src/custom/assets/README_OBFS_OPENVPN_CONF.txt b/app/src/custom/assets/README_OBFS_OPENVPN_CONF.txt index 5bc39576..ceebe1f1 100644 --- a/app/src/custom/assets/README_OBFS_OPENVPN_CONF.txt +++ b/app/src/custom/assets/README_OBFS_OPENVPN_CONF.txt @@ -2,7 +2,7 @@ obfs proxy is currently running on "37.218.247.60" the openvpn is running on -"5.79.86.180" +"37.218.242.216" When testing either an obfuscated or a plain openvpn connection you need to switch the ips in "ptdemo.bitmask.eip-service.json" \ No newline at end of file diff --git a/app/src/custom/assets/ptdemo.bitmask.eip-service.json b/app/src/custom/assets/ptdemo.bitmask.eip-service.json index f1b01fe0..cb650ada 100644 --- a/app/src/custom/assets/ptdemo.bitmask.eip-service.json +++ b/app/src/custom/assets/ptdemo.bitmask.eip-service.json @@ -32,7 +32,7 @@ "user_ips":false }, "host":"pt.demo.bitmask.net", - "ip_address":"5.79.86.180", + "ip_address":"37.218.242.216", "location":"Amsterdam" } ], -- cgit v1.2.3 From 63d1ccce6173445efba0028cc0fee1562e4540aa Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 3 Jul 2019 19:10:19 +0200 Subject: show a little ghost and extra information in notifications when trying or using an obfuscated connection --- .../de/blinkt/openvpn/core/OpenVPNService.java | 4 ++ .../leap/bitmaskclient/VpnNotificationManager.java | 46 ++++++++++++++++------ app/src/main/res/values/strings.xml | 2 + 3 files changed, 39 insertions(+), 13 deletions(-) (limited to 'app/src') 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 4a33fd49..184cea2c 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -318,6 +318,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.updateStateString("VPN_GENERATE_CONFIG", "", R.string.building_configration, ConnectionStatus.LEVEL_START); notificationManager.buildOpenVpnNotification( mProfile != null ? mProfile.mName : "", + mProfile != null && mProfile.mUsePluggableTransports, VpnStatus.getLastCleanLogMessage(this), VpnStatus.getLastCleanLogMessage(this), ConnectionStatus.LEVEL_START, @@ -988,6 +989,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac // Does not work :( notificationManager.buildOpenVpnNotification( mProfile != null ? mProfile.mName : "", + mProfile != null && mProfile.mUsePluggableTransports, VpnStatus.getLastCleanLogMessage(this), VpnStatus.getLastCleanLogMessage(this), level, @@ -1019,6 +1021,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac humanReadableByteCount(diffOut / OpenVPNManagement.mBytecountInterval, true, getResources())); notificationManager.buildOpenVpnNotification( mProfile != null ? mProfile.mName : "", + mProfile != null && mProfile.mUsePluggableTransports, netstat, null, LEVEL_CONNECTED, @@ -1062,6 +1065,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.updateStateString("NEED", "need " + needed, resid, LEVEL_WAITING_FOR_USER_INPUT); notificationManager.buildOpenVpnNotification( mProfile != null ? mProfile.mName : "", + mProfile != null && mProfile.mUsePluggableTransports, getString(resid), getString(resid), LEVEL_WAITING_FOR_USER_INPUT, diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java b/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java index 9107568c..44a69f5c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java @@ -43,8 +43,8 @@ import static android.support.v4.app.NotificationCompat.PRIORITY_MIN; import static android.text.TextUtils.isEmpty; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP_BLOCKING_VPN; import static se.leap.bitmaskclient.Constants.ASK_TO_CANCEL_VPN; +import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP_BLOCKING_VPN; import static se.leap.bitmaskclient.MainActivity.ACTION_SHOW_VPN_FRAGMENT; /** @@ -83,6 +83,7 @@ public class VpnNotificationManager { buildVpnNotification( context.getString(R.string.void_vpn_title), msg, + null, tickerText, status, VoidVpnService.NOTIFICATION_CHANNEL_NEWSTATUS_ID, @@ -110,8 +111,11 @@ public class VpnNotificationManager { * @param status * @param when */ - public void buildOpenVpnNotification(String profileName, final String msg, String tickerText, ConnectionStatus status, long when, String notificationChannelNewstatusId) { + public void buildOpenVpnNotification(String profileName, boolean isObfuscated, String msg, String tickerText, ConnectionStatus status, long when, String notificationChannelNewstatusId) { String cancelString; + String bigmessage = null; + String ghostIcon = new String(Character.toChars(0x1F47B)); + switch (status) { // show cancel if no connection case LEVEL_START: @@ -119,11 +123,24 @@ public class VpnNotificationManager { case LEVEL_CONNECTING_SERVER_REPLIED: case LEVEL_CONNECTING_NO_SERVER_REPLY_YET: cancelString = context.getString(R.string.cancel); + if (isObfuscated && Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + bigmessage = context.getString(R.string.obfuscated_connection_try) + " " + ghostIcon + "\n" + msg; + } break; + // show disconnect if connection exists + case LEVEL_CONNECTED: + if (isObfuscated && Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + bigmessage = context.getString(R.string.obfuscated_connection) + " " + ghostIcon + "\n" + msg; + } default: cancelString = context.getString(R.string.cancel_connection); } + + if (isObfuscated) { + msg = ghostIcon + " " + msg; + } + NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action. Builder(R.drawable.ic_menu_close_clear_cancel, cancelString, getDisconnectIntent()); String title; @@ -151,6 +168,7 @@ public class VpnNotificationManager { buildVpnNotification( title, msg, + bigmessage, tickerText, status, notificationChannelNewstatusId, @@ -224,28 +242,30 @@ public class VpnNotificationManager { return remoteViews; } - private void buildVpnNotification(String title, final String msg, String tickerText, ConnectionStatus status, String notificationChannelNewstatusId, int priority, long when, PendingIntent contentIntent, NotificationCompat.Action notificationAction) { + private void buildVpnNotification(String title, String message, String bigMessage, String tickerText, ConnectionStatus status, String notificationChannelNewstatusId, int priority, long when, PendingIntent contentIntent, NotificationCompat.Action notificationAction) { NotificationCompat.Builder nCompatBuilder = new NotificationCompat.Builder(context, notificationChannelNewstatusId); int icon = getIconByConnectionStatus(status); // this is a workaround to avoid confusion between the Android's system vpn notification // showing a filled out key icon and the bitmask icon indicating a different state. if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT && - notificationChannelNewstatusId.equals(OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID) && - status != LEVEL_NONETWORK - ) { - // removes the icon from the system status bar - icon = android.R.color.transparent; - // adds the icon to the notification in the notification drawer - nCompatBuilder.setContent(getKitkatCustomRemoteView(status, title, msg)); + notificationChannelNewstatusId.equals(OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID)) { + if (status != LEVEL_NONETWORK) { + // removes the icon from the system status bar + icon = android.R.color.transparent; + // adds the icon to the notification in the notification drawer + nCompatBuilder.setContent(getKitkatCustomRemoteView(status, title, message)); + } } else { - nCompatBuilder.addAction(notificationAction); + nCompatBuilder.setStyle(new NotificationCompat.BigTextStyle(). + setBigContentTitle(title). + bigText(bigMessage)); } - + nCompatBuilder.addAction(notificationAction); nCompatBuilder.setContentTitle(title); nCompatBuilder.setCategory(NotificationCompat.CATEGORY_SERVICE); nCompatBuilder.setLocalOnly(true); - nCompatBuilder.setContentText(msg); + nCompatBuilder.setContentText(message); nCompatBuilder.setOnlyAlertOnce(true); nCompatBuilder.setSmallIcon(icon); nCompatBuilder.setPriority(priority); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1b22592a..698aa91a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -110,4 +110,6 @@ LEAP depends on donations and grants. Please donate today if you value secure communication that is easy for both the end-user and the service provider. Remind me later Donate + Using an obfuscated connection. + Trying an obfuscated connection. -- cgit v1.2.3 From 2a8bb775183dd08388460c711dc650d3110ca76c Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 3 Jul 2019 19:16:43 +0200 Subject: update method name for gateway configuration v3 --- .../java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'app/src') 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 2214b592..18c557dc 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -167,7 +167,7 @@ public class VpnConfigGenerator { break; case 3: JSONArray transports = capabilities.getJSONArray(TRANSPORT); - gatewayConfigApiv2(transportType, stringBuilder, ipAddress, transports); + gatewayConfigApiv3(transportType, stringBuilder, ipAddress, transports); break; } } catch (JSONException e) { @@ -182,11 +182,11 @@ public class VpnConfigGenerator { return remotes; } - private void gatewayConfigApiv2(Connection.TransportType transportType, StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { + private void gatewayConfigApiv3(Connection.TransportType transportType, StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { if (transportType == OBFS4) { - obfs4GatewayConfigApiv2(stringBuilder, ipAddress, transports); + obfs4GatewayConfigApiv3(stringBuilder, ipAddress, transports); } else { - ovpnGatewayConfigApi2(stringBuilder, ipAddress, transports); + ovpnGatewayConfigApi3(stringBuilder, ipAddress, transports); } } @@ -205,7 +205,7 @@ public class VpnConfigGenerator { } } - private void ovpnGatewayConfigApi2(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { + private void ovpnGatewayConfigApi3(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { String port; String protocol; JSONObject openvpnTransport = getTransport(transports, OPENVPN); @@ -233,7 +233,7 @@ public class VpnConfigGenerator { return selectedTransport; } - private void obfs4GatewayConfigApiv2(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { + private void obfs4GatewayConfigApiv3(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException { JSONObject obfs4Transport = getTransport(transports, OBFS4); String route = "route " + ipAddress + " 255.255.255.255 net_gateway" + newLine; stringBuilder.append(route); -- cgit v1.2.3 From 283e7531d551521dc48efa9b010127ff54316326 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 4 Jul 2019 16:44:35 +0200 Subject: create one vpnprofile per transport per gateway. implement basis to switch between obfs4 and plain openvpn connections --- app/src/custom/assets/ptdemo.bitmask.secrets.json | 4 +- .../main/java/de/blinkt/openvpn/VpnProfile.java | 2 + .../de/blinkt/openvpn/core/ProfileManager.java | 0 .../main/java/se/leap/bitmaskclient/eip/EIP.java | 8 +- .../java/se/leap/bitmaskclient/eip/Gateway.java | 37 ++++-- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 50 +------- .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 19 +-- .../se/leap/bitmaskclient/eip/EipStatusTest.java | 6 +- .../bitmaskclient/eip/GatewaysManagerTest.java | 9 ++ .../bitmaskclient/eip/VpnConfigGeneratorTest.java | 89 +++++++++----- .../test/resources/ptdemo.bitmask.eip-service.json | 4 +- .../resources/ptdemo_pt_tcp_udp.eip-service.json | 2 +- .../resources/ptdemo_pt_udp_tcp.eip-service.json | 2 +- .../resources/ptdemo_three_mixed_gateways.json | 133 +++++++++++++++++++++ 14 files changed, 261 insertions(+), 104 deletions(-) create mode 100644 app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java create mode 100644 app/src/test/resources/ptdemo_three_mixed_gateways.json (limited to 'app/src') diff --git a/app/src/custom/assets/ptdemo.bitmask.secrets.json b/app/src/custom/assets/ptdemo.bitmask.secrets.json index 7d84bd79..61f1fe1d 100644 --- a/app/src/custom/assets/ptdemo.bitmask.secrets.json +++ b/app/src/custom/assets/ptdemo.bitmask.secrets.json @@ -1,5 +1,5 @@ { "ca_cert":"-----BEGIN CERTIFICATE-----\nMIIFjTCCA3WgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBZMRgwFgYDVQQKDA9SaXNl\ndXAgTmV0d29ya3MxGzAZBgNVBAsMEmh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UE\nAwwXUmlzZXVwIE5ldHdvcmtzIFJvb3QgQ0EwHhcNMTQwNDI4MDAwMDAwWhcNMjQw\nNDI4MDAwMDAwWjBZMRgwFgYDVQQKDA9SaXNldXAgTmV0d29ya3MxGzAZBgNVBAsM\nEmh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UEAwwXUmlzZXVwIE5ldHdvcmtzIFJv\nb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC76J4ciMJ8Sg0m\nTP7DF2DT9zNe0Csk4myoMFC57rfJeqsAlJCv1XMzBmXrw8wq/9z7XHv6n/0sWU7a\n7cF2hLR33ktjwODlx7vorU39/lXLndo492ZBhXQtG1INMShyv+nlmzO6GT7ESfNE\nLliFitEzwIegpMqxCIHXFuobGSCWF4N0qLHkq/SYUMoOJ96O3hmPSl1kFDRMtWXY\niw1SEKjUvpyDJpVs3NGxeLCaA7bAWhDY5s5Yb2fA1o8ICAqhowurowJpW7n5ZuLK\n5VNTlNy6nZpkjt1QycYvNycffyPOFm/Q/RKDlvnorJIrihPkyniV3YY5cGgP+Qkx\nHUOT0uLA6LHtzfiyaOqkXwc4b0ZcQD5Vbf6Prd20Ppt6ei0zazkUPwxld3hgyw58\nm/4UIjG3PInWTNf293GngK2Bnz8Qx9e/6TueMSAn/3JBLem56E0WtmbLVjvko+LF\nPM5xA+m0BmuSJtrD1MUCXMhqYTtiOvgLBlUm5zkNxALzG+cXB28k6XikXt6MRG7q\nhzIPG38zwkooM55yy5i1YfcIi5NjMH6A+t4IJxxwb67MSb6UFOwg5kFokdONZcwj\nshczHdG9gLKSBIvrKa03Nd3W2dF9hMbRu//STcQxOailDBQCnXXfAATj9pYzdY4k\nha8VCAREGAKTDAex9oXf1yRuktES4QIDAQABo2AwXjAdBgNVHQ4EFgQUC4tdmLVu\nf9hwfK4AGliaet5KkcgwDgYDVR0PAQH/BAQDAgIEMAwGA1UdEwQFMAMBAf8wHwYD\nVR0jBBgwFoAUC4tdmLVuf9hwfK4AGliaet5KkcgwDQYJKoZIhvcNAQENBQADggIB\nAGzL+GRnYu99zFoy0bXJKOGCF5XUXP/3gIXPRDqQf5g7Cu/jYMID9dB3No4Zmf7v\nqHjiSXiS8jx1j/6/Luk6PpFbT7QYm4QLs1f4BlfZOti2KE8r7KRDPIecUsUXW6P/\n3GJAVYH/+7OjA39za9AieM7+H5BELGccGrM5wfl7JeEz8in+V2ZWDzHQO4hMkiTQ\n4ZckuaL201F68YpiItBNnJ9N5nHr1MRiGyApHmLXY/wvlrOpclh95qn+lG6/2jk7\n3AmihLOKYMlPwPakJg4PYczm3icFLgTpjV5sq2md9bRyAg3oPGfAuWHmKj2Ikqch\nTd5CHKGxEEWbGUWEMP0s1A/JHWiCbDigc4Cfxhy56CWG4q0tYtnc2GMw8OAUO6Wf\nXu5pYKNkzKSEtT/MrNJt44tTZWbKV/Pi/N2Fx36my7TgTUj7g3xcE9eF4JV2H/sg\ntsK3pwE0FEqGnT4qMFbixQmc8bGyuakr23wjMvfO7eZUxBuWYR2SkcP26sozF9PF\ntGhbZHQVGZUTVPyvwahMUEhbPGVerOW0IYpxkm0x/eaWdTc4vPpf/rIlgbAjarnJ\nUN9SaWRlWKSdP4haujnzCoJbM7dU9bjvlGZNyXEekgeT0W2qFeGGp+yyUWw8tNsp\n0BuC1b7uW/bBn/xKm319wXVDvBgZgcktMolak39V7DVO\n-----END CERTIFICATE-----", - "cert":"-----BEGIN CERTIFICATE-----\nMIIEnDCCAoSgAwIBAgIRAIO8Bvjp207KpTPf+yH071gwDQYJKoZIhvcNAQELBQAwdTEYMBYGA1UE\nCgwPUmlzZXVwIE5ldHdvcmtzMRswGQYDVQQLDBJodHRwczovL3Jpc2V1cC5uZXQxPDA6BgNVBAMM\nM1Jpc2V1cCBOZXR3b3JrcyBSb290IENBIChjbGllbnQgY2VydGlmaWNhdGVzIG9ubHkhKTAeFw0x\nOTA1MTAwMDAwMDBaFw0xOTA4MTAwMDAwMDBaMC0xKzApBgNVBAMMIlVOTElNSVRFRGMwd2ZxOWhp\ndzA1OGthd3pkeTJuc3BnOGgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPG1Iphzfb\nYDwC7fwF7bF2JFGw4Rye/6fDp1U0rUEbSz06d57S/hxNXdEoM9OBtUm97ucSoUsemTNabTvGMc8y\nyidwtzhtzTOkq9S/lBu9UlA7Btsz3bWqvVVdVVB+ZOVh/SJREb0TMPQQCW499D0DMJfHFu9xHl9w\nzr+KZxuHxnWr94p8IG4BhssT2PnwK+TeuS3lBPXvG+ctbXCDipg0GJQU7EnshVS+6ECdcyFmAsK8\nJxH3bYAvKSIKxFXVToTRhHJjx/QjF3tgCBN8QNyLv/1AFZxn9cQq2MF0pqwdqfgARpcW2Cg3DXTW\nQMn2/upsxNrzj594/gmPgj2h3kFLAgMBAAGjbzBtMB0GA1UdDgQWBBTHUj4H4e88Pf69piaRFWpP\nmA1MijALBgNVHQ8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwIwCQYDVR0TBAIwADAfBgNVHSME\nGDAWgBQX9BvV5SoBAU1rol02CikJlmWARjANBgkqhkiG9w0BAQsFAAOCAgEApbPfHKaYV1JJhf3Y\ng8WVQ4Y3FlSSATmWt1dfWqPaEwgR/q5/Wuw1xTnv357F88PQh3xn5BRIDVEPEzd94FXXEjYmzRL3\nWPu36HtqF7IXVwU6qXIIeCZJs5sMUlSjVyaHdTY/IEQarMLUDiLaTZ+9oU/IBBjSpDuyWlnbKYNn\nIM/d1FbOeIZFZpJmw33BcNNa8csjs0jBOmftP9dPIvcFaj3Fb4w5G0rKi5lfA2p4y/faVWFucwcl\nmGlHtwpvoyRPVqVoHrTpcvapOTXORpGSGPzRR4y+Cl1xyeMWor/AF58FGshLkI5gGTXQ0Vth9g+x\nEgeXRJxmSGVw031uGuz1EuUUVDOcYE465PiK7EufPt3zbF7VD76atd7/FdkBcn3pI6BTSWBN0mtw\nt2npAqJuBZhS7tu89FU2SOvj3ieeqzoNuvEPzc55LUEFGTOb1W1KX70AhbaKV9zg3bE11B3B8Byk\nS2el4vw3h3smCyn2wj1TsNZBT0B/htdcHGSPFK8SfgtW209LGlOwqLrCiWKNmhofgZJN3vqettpC\nHD19hUTVfSY1p2AVbTsyJa4mj2tP0++JWfbFbPVtYCIDJxFOeQ+sl4Uqd5l8tr7f89PKgU4dxiol\ndw74HzGJOBTUlv6dozT22y1HQrOIevWMJvvJ4UoJ70nVBZx00jKwevaeook=\n-----END CERTIFICATE-----", - "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDPG1IphzfbYDwC7fwF7bF2JFGw\n4Rye/6fDp1U0rUEbSz06d57S/hxNXdEoM9OBtUm97ucSoUsemTNabTvGMc8yyidwtzhtzTOkq9S/\nlBu9UlA7Btsz3bWqvVVdVVB+ZOVh/SJREb0TMPQQCW499D0DMJfHFu9xHl9wzr+KZxuHxnWr94p8\nIG4BhssT2PnwK+TeuS3lBPXvG+ctbXCDipg0GJQU7EnshVS+6ECdcyFmAsK8JxH3bYAvKSIKxFXV\nToTRhHJjx/QjF3tgCBN8QNyLv/1AFZxn9cQq2MF0pqwdqfgARpcW2Cg3DXTWQMn2/upsxNrzj594\n/gmPgj2h3kFLAgMBAAECggEAOk4EuXA5x2a2PlTlSH38IbhjzxnwxspOXoRzNls4Iwjxec5HRjsH\nmLg6s8izWKbC1de18ca6sSiMDn8F/uvy2ueSZucN2cuVKFy/jheSH6BWuedaOqXGCQU4TQhBmvOo\nqAdta8lEo2x6qTEeeg6SRp2dfQz157CXSdjKj5orY/N3MPUz09IqHifyQFqKZDEl4ZYzFiqeeDnp\nPHNlvtWRp/LaRCr45ppqU2SPCC1y2pGLgJPZOAAsqWA7KiB2wZq2SBFNtspBTZkhG+LBBcZYjnU4\nIuKPnPW1YsSPpAWUZv79Pct6wzwsidPzBmkaJ8Fpkqy8SIbUM4K4am0yFDH14QKBgQD1TfNfwj0Y\nZhC+LOmiU/+Pwfpo1XgU8FQ03diiLNMdcv2G6vXph6/NWBTIVEZoIrz/Y8X4klo/KQ8tyw9d+hYh\nAqJ6S+IFhf+UwbPjk8s8iUZbvn+Nl/DWjq5lu1IYwQl9BzXoptWq9itNSqB8KCyd7WEjn+Tb3Df3\narBAKRYqOQKBgQDYIwNLtR1x9smoVFhI8pFCuyw1h3cO2vn14PVR9P0EEkTzs8+CwU8QYbUpBQpF\nUfmPCJPNcXz5knOxOdtOr+/El3hol+J9XXuZZumjwoFb5fpw+AQxgfAxkJgbR16BJj52MFy8/ymX\n1qzAFf1Cx2sFJkAD9OkqUB0R/Tm3E6hXowKBgQC+Al9d8Ur5tzWI2akvP/lZFVwuEAwvy+it+plv\nJWFyEjwnYaCR/7RBTtTqR70xtJbJDDOw00xsWBWV1xBULv8tGqlYKactuBm81D3PLg/jGEITln+e\n4e5/g42651o0KnJ7EjbDu1cOUhhAimm9QjEtM05nFddkJjSDxXQ4fprYoQKBgFYmDog8lpH4NgS8\nKbxZwwCALmzfo9rt+TfCBMY4Cil3RriEcS/C8UqsR1MkSSW8OOaEGrWGiLPJZge78ef5RG5tmXbH\nI2Wovz0zweid/IWusxYYJUO+cQiwg5BL8CU2Iytkt3I1mlSFIrIlkZ7ucX/J8TYihlVxPUUQU9Lf\nKPhVAoGAd1/wvawIclsAGqXQzINziH4jjRvIV85R59fLEccfTEAqao9blBxDqoMe6biUuodYFQvq\nT+CDj7zzVPNZVbK5FEqu5W6ezIWp+y+tbTWpApdOxhf2lsZZVgm0KtV2uYvNYW0djOW0ci4TaHj5\nfvWaxEkf0ZOSdkEaN4f2mJGIXLM=\n-----END RSA PRIVATE KEY-----" + "cert":"-----BEGIN CERTIFICATE-----\nMIIEnDCCAoSgAwIBAgIRAMBASoEmbFNubIm2CUzfS7cwDQYJKoZIhvcNAQELBQAwdTEYMBYGA1UE\nCgwPUmlzZXVwIE5ldHdvcmtzMRswGQYDVQQLDBJodHRwczovL3Jpc2V1cC5uZXQxPDA6BgNVBAMM\nM1Jpc2V1cCBOZXR3b3JrcyBSb290IENBIChjbGllbnQgY2VydGlmaWNhdGVzIG9ubHkhKTAeFw0x\nOTA1MTIwMDAwMDBaFw0xOTA4MTIwMDAwMDBaMC0xKzApBgNVBAMMIlVOTElNSVRFRGN2Nnc3NTc5\nNHphdmk4bmxtcnd6MGs0ZzYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKtjI8XcFk\n61loMX2Y3EMKu6Y6/UwUzcxeUNjA19YJgJh85RUGD2NrhVQDSaB38jsX3xRKYGRaZ7k50S1MYv5M\nOLBmPL2pB6Nm5Ki+fRgr1sKSkQqXEZdHnS1/W5odBdO5JnZxVEjVBnM77FHuMyJ4rhAqswHLjrMo\nWBuJc4L3k04DH6t0zB+oRRsnYFze7FAfi9Vy9o409kYCF82ZXLZ0e4fZKaYbteUiMJlos93Esfp/\nWe3gxM/661/e3nL1H433l65+BbKYQp/ojb3VawaK/ZuD5/YhjbiQ9vttt3sWuG0k3PtDQEeBg6GH\n6JsCZ0U+/wmrorcDs007O5QlCgepAgMBAAGjbzBtMB0GA1UdDgQWBBT888ieEhIJhzB9sHkP72+Y\ng6hqFDALBgNVHQ8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwIwCQYDVR0TBAIwADAfBgNVHSME\nGDAWgBQX9BvV5SoBAU1rol02CikJlmWARjANBgkqhkiG9w0BAQsFAAOCAgEAje/LV2Oo/Qz7pGcM\nvQhnlxemL6p+3XI9UpyjkbDG9s45RxZoqEMGyOhqq4aQikoHOBZoasw5ChCVYz0dPCoKvmVuixD+\nzmSfEDfTO1dN1vgCeExbLpZFIMUqifjORPxXqfxCsJOzO5RHF05Q4ywgPJIF8pRIaSjswAbYAxBa\nS+d/2cp3wKj6WjRc0VOf2LZ95jV4PTnOHD5Ls3hyCIXsM4dvjxY2mcaVps4DX/GziaS9S6+wISEe\nx2sGk+uAJs11ixs26zefg4XHU4qDc3RnxG0sLEANTSNgulZAnffE4OQVGrLDJ/lJn77EfnggF9NF\nOBJR4U/xY/0nQNR8fvnjlp+ViebbyBWgn3EcuT1W8jxbUDMcdF+575gLtxbJ6/5EqKp6r2E1EKGW\nYutUgQW4C2c4gfWl1T0hVT3ykqDid1qzZvWiXPQCgE84LdViWaY6I4kuELLMZxWIKEKXo4y19K+z\nOOnlK70+SeOKdx9W9CuCHArlCDSKyWjNVxhf+M6ILLy6+LpJ618bsg18+FJvovdxmWl4jOuQNU6v\n6j4OwKd3sCjQ6zvIZk6CLkRZjxWdDNwwvb3O9YG99PcxXyR0SmX21ycnDKut6Sclk/sqhP+VrZbG\nCPHMcbuS+Jk6t4q5R3BGNmLeBpVMQOHN29++55Snd7qFTXEWUdrBTQUYc+c=\n-----END CERTIFICATE-----", + "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDKtjI8XcFk61loMX2Y3EMKu6Y6\n/UwUzcxeUNjA19YJgJh85RUGD2NrhVQDSaB38jsX3xRKYGRaZ7k50S1MYv5MOLBmPL2pB6Nm5Ki+\nfRgr1sKSkQqXEZdHnS1/W5odBdO5JnZxVEjVBnM77FHuMyJ4rhAqswHLjrMoWBuJc4L3k04DH6t0\nzB+oRRsnYFze7FAfi9Vy9o409kYCF82ZXLZ0e4fZKaYbteUiMJlos93Esfp/We3gxM/661/e3nL1\nH433l65+BbKYQp/ojb3VawaK/ZuD5/YhjbiQ9vttt3sWuG0k3PtDQEeBg6GH6JsCZ0U+/wmrorcD\ns007O5QlCgepAgMBAAECggEBAK6YdPZXjl4c83nxvortk/TnoQqH5oK4qwDFQ5v9iwXONAjGyu/Y\nSzptsOnP/Z2yDkHGS1SwZ18SnY/14b08OmluHklAod63jH7wDYNcfXgs1pOkx2lMpm7xKyHZxQig\nXzbGsRd1j/GjR5diOUMf2d31lkkguzgXZaonETi3PCN9vLEuA6nOhOF9tqyp5URngklF8VILBVs5\nagz5LLsS1jwn5KOhvP01Twi3fESvWdUKUK1aCOBeujsplPtYpl+hdnOzIWbrkBFisrbECvsn67A3\n7TTvld7Qyki/RV00xKO2SymkfL5RFHgpINzrgEY4xPh8pTrYKICOSkzxCL2BUz0CgYEA78pXyIVB\nYEcAfqXZR+5PBB8GeVjk1RusbL87lwZEn+Xp8yxab3Wi/EAkpt3349Y1S4o/kOSV1CZZtfgwI3/5\nX95JAQMgmRvg9Wv6Cm3eR+i1gvw4ONeccIj1Iip7/74Rwb2PGvtuQZPNQvxpU5QzKXdN3/dqaNOD\nvMAC2SqULZMCgYEA2GoxhY5iCnFFJ6LPIh4vd/srF6pR1fNm99coFsEZ9bL/5Fxz2mAOw25T9l5v\nl3YA5nO1r0ZkBmcHzkKl3feAW7DV8eTMFCln8mGpVuqsOEgdLVH0PF+IH2JWXd7agqHZlSPwhEVP\nBinOVC1acEDZ3+/CC1fLdoH4csrtPQmEW1MCgYBV5xEnnsVa7lS5CkUaxb685Th2hGgGCFHu61s3\nsWEoPz9ehEcpouTupTP8K4zArF6PX0mCaMFcLRj6XZ0xOoll1MYmfK5S62/du/7peY6mCDHuaNjj\nVCqRDh9zS/D8H2VRGM2JhwVqrL5d/vrknDTv5/OYBpSyVQPevJLIpb5LzQKBgDQ18nqZLjf8ucVl\nNvmxNJyKoQvVkGbAkS/r3YUX0y5+n9O1JlIh6I3nmSQQBnYRBwiSE9wUbF9LDgwJ8kBJzNLSJ9ty\n6nVWw/gq7ZLFjQULCNb9NaI3Hf0MWW/OKwNnDro3cHhIzFbdUSTnyDDaxHWNP1BDPxf5JTp0kKWw\nHRl3AoGABj4yBH9wqwMu0Hsmv5IZ0mRPj81g5imeQL+TnF4KAoyWe3VjPfWUllu5nMELOXmk69Nb\n2xFP6dp9g6EyuQqwYGHxR0ZhNLnvvj03hYmo3r8rulTY5KqpmQ1mNb/pqShuN9KxdvXpcp2Xj2Hg\nD/J37vgYH7L99/B8hBJqC4arjCk=\n-----END RSA PRIVATE KEY-----" } \ No newline at end of file diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index dc12c6a8..f139fdc9 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -174,6 +174,7 @@ public class VpnProfile implements Serializable, Cloneable { // timestamp when the profile was last used public long mLastUsed; public String importedProfileHash; + //TODO: cleanup here /* Options no longer used in new profiles */ public String mServerName = "openvpn.example.com"; public String mServerPort = "1194"; @@ -184,6 +185,7 @@ public class VpnProfile implements Serializable, Cloneable { // set members to default values private UUID mUuid; private int mProfileVersion; + public String mGatewayIp; public boolean mUsePluggableTransports; public VpnProfile(String name, Connection.TransportType transportType) { diff --git a/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java b/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java new file mode 100644 index 00000000..e69de29b diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index a5434871..1d702ec1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -53,6 +53,8 @@ import se.leap.bitmaskclient.R; import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_OK; import static android.content.Intent.CATEGORY_DEFAULT; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import static se.leap.bitmaskclient.Constants.BROADCAST_EIP_EVENT; import static se.leap.bitmaskclient.Constants.BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT; import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE; @@ -203,7 +205,7 @@ public final class EIP extends JobIntentService implements Observer { GatewaysManager gatewaysManager = gatewaysFromPreferences(); Gateway gateway = gatewaysManager.select(nClosestGateway); - if (gateway != null && gateway.getProfile() != null) { + if (gateway != null && !gateway.getProfiles().isEmpty()) { launchActiveGateway(gateway, nClosestGateway); tellToReceiverOrBroadcast(EIP_ACTION_START, RESULT_OK); } else @@ -218,7 +220,7 @@ public final class EIP extends JobIntentService implements Observer { GatewaysManager gatewaysManager = gatewaysFromPreferences(); Gateway gateway = gatewaysManager.select(0); - if (gateway != null && gateway.getProfile() != null) { + if (gateway != null && !gateway.getProfiles().isEmpty()) { launchActiveGateway(gateway, 0); } else { Log.d(TAG, "startEIPAlwaysOnVpn no active profile available!"); @@ -242,7 +244,7 @@ public final class EIP extends JobIntentService implements Observer { */ private void launchActiveGateway(@NonNull Gateway gateway, int nClosestGateway) { Intent intent = new Intent(BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT); - intent.putExtra(PROVIDER_PROFILE, gateway.getProfile()); + intent.putExtra(PROVIDER_PROFILE, gateway.getProfile(OPENVPN)); intent.putExtra(Gateway.KEY_N_CLOSEST_GATEWAY, nClosestGateway); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java index 50fe74b7..9bc07764 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -16,16 +16,21 @@ */ package se.leap.bitmaskclient.eip; +import android.support.annotation.NonNull; + import com.google.gson.Gson; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; +import java.util.HashMap; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; +import de.blinkt.openvpn.core.connection.Connection; +import static se.leap.bitmaskclient.Constants.IP_ADDRESS; import static se.leap.bitmaskclient.Constants.LOCATION; import static se.leap.bitmaskclient.Constants.LOCATIONS; import static se.leap.bitmaskclient.Constants.NAME; @@ -54,7 +59,7 @@ public class Gateway { private String name; private int timezone; private int apiVersion; - private VpnProfile vpnProfile; + private HashMap vpnProfiles; /** * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json @@ -69,9 +74,13 @@ public class Gateway { timezone = getTimezone(eipDefinition); name = locationAsName(eipDefinition); apiVersion = getApiVersion(eipDefinition); - vpnProfile = createVPNProfile(); - if (vpnProfile != null) { - vpnProfile.mName = name; + vpnProfiles = createVPNProfiles(); + } + + private void addProfileInfos(HashMap profiles) { + for (VpnProfile profile : profiles.values()) { + profile.mName = name; + profile.mGatewayIp = gateway.optString(IP_ADDRESS); } } @@ -92,6 +101,10 @@ public class Gateway { return eipDefinition.optInt(VERSION); } + public String getRemoteIP() { + return gateway.optString(IP_ADDRESS); + } + private String locationAsName(JSONObject eipDefinition) { JSONObject location = getLocationInfo(eipDefinition); return location.optString(NAME); @@ -110,23 +123,29 @@ public class Gateway { /** * Create and attach the VpnProfile to our gateway object */ - private VpnProfile createVPNProfile() { + private @NonNull HashMap createVPNProfiles() { + HashMap profiles = new HashMap<>(); try { VpnConfigGenerator vpnConfigurationGenerator = new VpnConfigGenerator(generalConfiguration, secrets, gateway, apiVersion); - return vpnConfigurationGenerator.generateVpnProfile(); + profiles = vpnConfigurationGenerator.generateVpnProfiles(); + addProfileInfos(profiles); } catch (ConfigParser.ConfigParseError | IOException | JSONException e) { // FIXME We didn't get a VpnProfile! Error handling! and log level e.printStackTrace(); - return null; } + return profiles; } public String getName() { return name; } - public VpnProfile getProfile() { - return vpnProfile; + public HashMap getProfiles() { + return vpnProfiles; + } + + public VpnProfile getProfile(Connection.TransportType transportType) { + return vpnProfiles.get(transportType); } public int getTimezone() { diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java index cd3ec1c6..f7038bab 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -28,20 +28,14 @@ import org.json.JSONObject; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.List; +import java.util.LinkedHashMap; -import de.blinkt.openvpn.VpnProfile; -import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.Provider; import se.leap.bitmaskclient.utils.PreferenceHelper; -import static se.leap.bitmaskclient.Constants.CAPABILITIES; import static se.leap.bitmaskclient.Constants.GATEWAYS; import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.Constants.TRANSPORT; -import static se.leap.bitmaskclient.Constants.TYPE; -import static se.leap.bitmaskclient.Constants.VERSION; /** * @author parmegv @@ -52,7 +46,7 @@ public class GatewaysManager { private Context context; private SharedPreferences preferences; - private List gateways = new ArrayList<>(); + private LinkedHashMap gateways = new LinkedHashMap<>(); private Type listType = new TypeToken>() {}.getType(); GatewaysManager(Context context, SharedPreferences preferences) { @@ -65,7 +59,7 @@ public class GatewaysManager { * @return the n closest Gateway */ public Gateway select(int nClosest) { - GatewaySelector gatewaySelector = new GatewaySelector(gateways); + GatewaySelector gatewaySelector = new GatewaySelector(new ArrayList<>(gateways.values())); return gatewaySelector.select(nClosest); } @@ -96,52 +90,20 @@ public class GatewaysManager { void fromEipServiceJson(JSONObject eipDefinition) { try { JSONArray gatewaysDefined = eipDefinition.getJSONArray(GATEWAYS); - int apiVersion = eipDefinition.getInt(VERSION); for (int i = 0; i < gatewaysDefined.length(); i++) { JSONObject gw = gatewaysDefined.getJSONObject(i); JSONObject secrets = secretsConfiguration(); Gateway aux = new Gateway(eipDefinition, secrets, gw); - if (!gateways.contains(aux)) { + if (gateways.get(aux.getRemoteIP()) == null) { addGateway(aux); } } - } catch (JSONException e) { + } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } - /** - * check if a gateway is an OpenVpn gateway - * @param gateway to check - * @return true if gateway is an OpenVpn gateway otherwise false - */ - private boolean isOpenVpnGateway(JSONObject gateway, int apiVersion) { - switch (apiVersion) { - default: - case 1: - try { - String transport = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT).toString(); - return transport.contains("openvpn"); - } catch (JSONException e) { - return false; - } - case 2: - try { - JSONArray transports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT); - for (int i = 0; i < transports.length(); i++) { - JSONObject transport = transports.getJSONObject(i); - if (transport.optString(TYPE).equals("openvpn")) { - return true; - } - } - return false; - } catch (JSONException e) { - return false; - } - } - } - private JSONObject secretsConfiguration() { JSONObject result = new JSONObject(); try { @@ -160,7 +122,7 @@ public class GatewaysManager { } private void addGateway(Gateway gateway) { - gateways.add(gateway); + gateways.put(gateway.getRemoteIP(), gateway); } /** 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 18c557dc..6b76e8d9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -22,6 +22,7 @@ import org.json.JSONObject; import java.io.IOException; import java.io.StringReader; +import java.util.HashMap; import java.util.Iterator; import de.blinkt.openvpn.VpnProfile; @@ -52,8 +53,6 @@ public class VpnConfigGenerator { private JSONObject obfs4Transport; private int apiVersion; - private ConfigParser icsOpenvpnConfigParser = new ConfigParser(); - public final static String TAG = VpnConfigGenerator.class.getSimpleName(); private final String newLine = System.getProperty("line.separator"); // Platform new line @@ -85,16 +84,17 @@ public class VpnConfigGenerator { } } - public VpnProfile generateVpnProfile() throws IllegalStateException, - IOException, + public HashMap generateVpnProfiles() throws ConfigParser.ConfigParseError, - NumberFormatException, JSONException { - + NumberFormatException, + JSONException, + IOException { + HashMap profiles = new HashMap<>(); + profiles.put(OPENVPN, createProfile(OPENVPN)); if (supportsObfs4()) { - return createProfile(OBFS4); + profiles.put(OBFS4, createProfile(OBFS4)); } - - return createProfile(OPENVPN); + return profiles; } private boolean supportsObfs4(){ @@ -113,6 +113,7 @@ public class VpnConfigGenerator { private VpnProfile createProfile(Connection.TransportType transportType) throws IOException, ConfigParser.ConfigParseError, JSONException { String configuration = getConfigurationString(transportType); + ConfigParser icsOpenvpnConfigParser = new ConfigParser(); icsOpenvpnConfigParser.parseConfig(new StringReader(configuration)); if (transportType == OBFS4) { icsOpenvpnConfigParser.setDispatcherOptions(getDispatcherOptions()); diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/EipStatusTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/EipStatusTest.java index 8495f962..8ba7f5fc 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/EipStatusTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/EipStatusTest.java @@ -10,6 +10,7 @@ import org.powermock.modules.junit4.PowerMockRunner; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.VpnStatus; +import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.testutils.MockHelper; import se.leap.bitmaskclient.testutils.TestSetupHelper; @@ -23,6 +24,7 @@ import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_START; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_VPNPAUSED; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT; import static de.blinkt.openvpn.core.ConnectionStatus.UNKNOWN_LEVEL; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyString; import static org.powermock.api.mockito.PowerMockito.doNothing; @@ -61,7 +63,7 @@ public class EipStatusTest { public void testUpdateState_LEVEL_VPNPAUSED_hasPersistentTun() throws Exception { mockStatic(PreferenceHelper.class); - VpnProfile mockVpnProfile = new VpnProfile("mockProfile"); + VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OPENVPN); mockVpnProfile.mPersistTun = true; doNothing().when(PreferenceHelper.class); VpnStatus.setLastConnectedVpnProfile(null, mockVpnProfile); @@ -74,7 +76,7 @@ public class EipStatusTest { public void testUpdateState_LEVEL_VPNPAUSED_hasNotPersistentTun() throws Exception { mockStatic(PreferenceHelper.class); - VpnProfile mockVpnProfile = new VpnProfile("mockProfile"); + VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OPENVPN); mockVpnProfile.mPersistTun = false; doNothing().when(PreferenceHelper.class); VpnStatus.setLastConnectedVpnProfile(null, mockVpnProfile); 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 160e5ddd..0412b11a 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java @@ -57,6 +57,15 @@ public class GatewaysManagerTest { assertEquals(0, gatewaysManager.size()); } + @Test + public void testFromEipServiceJson_ignoreDuplicateGateways_apiv3() throws Exception { + String eipServiceJson = TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_three_mixed_gateways.json")); + gatewaysManager.fromEipServiceJson(new JSONObject(eipServiceJson)); + assertEquals(3, gatewaysManager.size()); + eipServiceJson = TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json")); + gatewaysManager.fromEipServiceJson(new JSONObject(eipServiceJson)); + assertEquals(3, gatewaysManager.size()); + } @Test public void testFromEipServiceJson_ignoreDuplicateGateways() throws Exception { 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 20a5968d..40da8e43 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java @@ -16,11 +16,16 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import java.io.File; +import java.util.HashMap; import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.testutils.MockHelper; import se.leap.bitmaskclient.testutils.TestSetupHelper; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; +import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; @@ -44,7 +49,7 @@ public class VpnConfigGeneratorTest { private JSONObject gateway; private JSONObject secrets; - String expectedVPNConfig_tcp_udp = "# Config for OpenVPN 2.x\n" + + String expectedVPNConfig_v1_tcp_udp = "# Config for OpenVPN 2.x\n" + "# Enables connection to GUI\n" + "management /data/data/se.leap.bitmask/mgmtsocket unix\n" + "management-client\n" + @@ -162,7 +167,7 @@ public class VpnConfigGeneratorTest { "keepalive 10 30 \n" + "tls-cipher DHE-RSA-AES128-SHA"; - String expectedVPNConfig_udp_tcp = "# Config for OpenVPN 2.x\n" + + String expectedVPNConfig_v1_udp_tcp = "# Config for OpenVPN 2.x\n" + "# Enables connection to GUI\n" + "management /data/data/se.leap.bitmask/mgmtsocket unix\n" + "management-client\n" + @@ -280,7 +285,7 @@ public class VpnConfigGeneratorTest { "keepalive 10 30 \n" + "tls-cipher DHE-RSA-AES128-SHA"; - String expectedVPNConfig_pt_tcp = "# Config for OpenVPN 2.x\n" + + String expectedVPNConfig_v3_obfs4 = "# Config for OpenVPN 2.x\n" + "# Enables connection to GUI\n" + "management /data/data/se.leap.bitmask/mgmtsocket unix\n" + "management-client\n" + @@ -297,8 +302,7 @@ public class VpnConfigGeneratorTest { "connect-retry 2 300\n" + "resolv-retry 60\n" + "dev tun\n" + - "remote 127.0.0.1 1234 tcp-client\n" + - "remote 37.218.247.60 1195 tcp-client\n" + + "remote 127.0.0.1 4430 tcp-client\n" + "\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\n" + @@ -386,6 +390,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "crl-verify file missing in config profile\n" + + "route 37.218.247.60 255.255.255.255 net_gateway\n"+ "remote-cert-tls server\n" + "cipher AES-128-CBC\n" + "auth SHA1\n" + @@ -398,7 +403,7 @@ public class VpnConfigGeneratorTest { "keepalive 10 30 \n" + "tls-cipher DHE-RSA-AES128-SHA \n"; - String expectedVPNConfig_pt_tcp_udp = "# Config for OpenVPN 2.x\n" + + String expectedVPNConfig_v3_ovpn_tcp_udp = "# Config for OpenVPN 2.x\n" + "# Enables connection to GUI\n" + "management /data/data/se.leap.bitmask/mgmtsocket unix\n" + "management-client\n" + @@ -415,7 +420,6 @@ public class VpnConfigGeneratorTest { "connect-retry 2 300\n" + "resolv-retry 60\n" + "dev tun\n" + - "remote 127.0.0.1 1234 tcp-client\n" + "remote 37.218.247.60 1195 tcp-client\n" + "remote 37.218.247.60 1195 udp\n" + "\n" + @@ -517,7 +521,7 @@ public class VpnConfigGeneratorTest { "keepalive 10 30 \n" + "tls-cipher DHE-RSA-AES128-SHA \n"; - String expectedVPNConfig_pt_udp_tcp = "# Config for OpenVPN 2.x\n" + + String expectedVPNConfig_v3_ovpn_udp_tcp = "# Config for OpenVPN 2.x\n" + "# Enables connection to GUI\n" + "management /data/data/se.leap.bitmask/mgmtsocket unix\n" + "management-client\n" + @@ -534,7 +538,6 @@ public class VpnConfigGeneratorTest { "connect-retry 2 300\n" + "resolv-retry 60\n" + "dev tun\n" + - "remote 127.0.0.1 1234 tcp-client\n" + "remote 37.218.247.60 1195 udp\n" + "remote 37.218.247.60 1195 tcp-client\n" + "\n" + @@ -655,45 +658,69 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_v1_tcp_udp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_tcp_udp.json"))); vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1); - VpnProfile vpnProfile = vpnConfigGenerator.generateVpnProfile(); - assertTrue(vpnProfile.getConfigFile(context, false).trim().equals(expectedVPNConfig_tcp_udp.trim())); + HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(vpnProfiles.containsKey(OBFS4)); + assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_tcp_udp.trim())); } @Test public void testGenerateVpnProfile_v1_udp_tcp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_udp_tcp.json"))); vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1); - VpnProfile vpnConfig = vpnConfigGenerator.generateVpnProfile(); - assertTrue(vpnConfig.getConfigFile(context, false).trim().equals(expectedVPNConfig_udp_tcp.trim())); + HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(vpnProfiles.containsKey(OBFS4)); + assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_udp_tcp.trim())); } @Test - public void testGenerateVpnProfile_v2_pt_tcp() throws Exception { - gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); + public void testGenerateVpnProfile_v2_tcp_udp() throws Exception { + gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_tcp_udp.json"))); vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2); - VpnProfile vpnProfile = vpnConfigGenerator.generateVpnProfile(); - vpnProfile.mConnections[0].setServerPort("1234"); - System.out.println(vpnProfile.getConfigFile(context, false)); - assertTrue(vpnProfile.getConfigFile(context, false).trim().equals(expectedVPNConfig_pt_tcp.trim())); + HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(vpnProfiles.containsKey(OBFS4)); + assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_tcp_udp.trim())); } @Test - public void testGenerateVpnProfile_v2_pt_tcp_udp() throws Exception { - gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_tcp_udp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); + public void testGenerateVpnProfile_v2_udp_tcp() throws Exception { + gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_udp_tcp.json"))); vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2); - VpnProfile vpnProfile = vpnConfigGenerator.generateVpnProfile(); - vpnProfile.mConnections[0].setServerPort("1234"); - System.out.println(vpnProfile.getConfigFile(context, false)); - assertTrue(vpnProfile.getConfigFile(context, false).trim().equals(expectedVPNConfig_pt_tcp_udp.trim())); + HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(vpnProfiles.containsKey(OBFS4)); + assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_udp_tcp.trim())); } + @Test - public void testGenerateVpnProfile_v2_pt_udp_tcp() throws Exception { + public void testGenerateVpnProfile_v3_obfs4() throws Exception { + gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3); + HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(vpnProfiles.containsKey(OBFS4)); + assertTrue(vpnProfiles.containsKey(OPENVPN)); + System.out.println(vpnProfiles.get(OBFS4).getConfigFile(context, false)); + assertTrue(vpnProfiles.get(OBFS4).getConfigFile(context, false).trim().equals(expectedVPNConfig_v3_obfs4.trim())); + } + + @Test + public void testGenerateVpnProfile_v3_ovpn_tcp_udp() throws Exception { + gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_tcp_udp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3); + HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(vpnProfiles.containsKey(OBFS4)); + assertTrue(vpnProfiles.containsKey(OPENVPN)); + System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); + assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v3_ovpn_tcp_udp.trim())); + } + + @Test + public void testGenerateVpnProfile_v3_ovpn_udp_tcp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_udp_tcp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2); - VpnProfile vpnProfile = vpnConfigGenerator.generateVpnProfile(); - vpnProfile.mConnections[0].setServerPort("1234"); - System.out.println(vpnProfile.getConfigFile(context, false)); - assertTrue(vpnProfile.getConfigFile(context, false).trim().equals(expectedVPNConfig_pt_udp_tcp.trim())); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3); + HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(vpnProfiles.containsKey(OBFS4)); + assertTrue(vpnProfiles.containsKey(OPENVPN)); + System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); + assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v3_ovpn_udp_tcp.trim())); } } \ No newline at end of file diff --git a/app/src/test/resources/ptdemo.bitmask.eip-service.json b/app/src/test/resources/ptdemo.bitmask.eip-service.json index 38146a40..e5ede239 100644 --- a/app/src/test/resources/ptdemo.bitmask.eip-service.json +++ b/app/src/test/resources/ptdemo.bitmask.eip-service.json @@ -15,7 +15,7 @@ "23049" ], "options": { - "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1", "iat-mode": "0" } }, @@ -60,5 +60,5 @@ "verb" : "3" }, "serial":2, - "version":2 + "version":3 } \ No newline at end of file diff --git a/app/src/test/resources/ptdemo_pt_tcp_udp.eip-service.json b/app/src/test/resources/ptdemo_pt_tcp_udp.eip-service.json index 4337547b..f39a1597 100644 --- a/app/src/test/resources/ptdemo_pt_tcp_udp.eip-service.json +++ b/app/src/test/resources/ptdemo_pt_tcp_udp.eip-service.json @@ -61,5 +61,5 @@ "verb" : "3" }, "serial":2, - "version":2 + "version":3 } \ No newline at end of file diff --git a/app/src/test/resources/ptdemo_pt_udp_tcp.eip-service.json b/app/src/test/resources/ptdemo_pt_udp_tcp.eip-service.json index 4161fced..71c9857a 100644 --- a/app/src/test/resources/ptdemo_pt_udp_tcp.eip-service.json +++ b/app/src/test/resources/ptdemo_pt_udp_tcp.eip-service.json @@ -61,5 +61,5 @@ "verb" : "3" }, "serial":2, - "version":2 + "version":3 } \ No newline at end of file diff --git a/app/src/test/resources/ptdemo_three_mixed_gateways.json b/app/src/test/resources/ptdemo_three_mixed_gateways.json new file mode 100644 index 00000000..f81da6b3 --- /dev/null +++ b/app/src/test/resources/ptdemo_three_mixed_gateways.json @@ -0,0 +1,133 @@ +{ + "gateways":[ + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"obfs4", + "protocols":[ + "tcp" + ], + "ports":[ + "23049" + ], + "options": { + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1", + "iat-mode": "0" + } + }, + { + "type":"openvpn", + "protocols":[ + "tcp" + ], + "ports":[ + "1195" + ] + } + ], + "user_ips":false + }, + "host":"pt.demo.bitmask.net", + "ip_address":"37.218.247.60", + "location":"Amsterdam" + }, + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"obfs4", + "protocols":[ + "tcp" + ], + "ports":[ + "443" + ], + "options": { + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2", + "iat-mode": "0" + } + }, + { + "type":"openvpn", + "protocols":[ + "tcp" + ], + "ports":[ + "1195" + ] + } + ], + "user_ips":false + }, + "host":"moscow.bitmask.net", + "ip_address":"3.21.247.89", + "location":"moscow" + }, + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"openvpn", + "protocols":[ + "tcp", + "udp" + ], + "ports":[ + "1195" + ] + } + ], + "user_ips":false + }, + "host":"manila.bitmask.net", + "ip_address":"37.12.247.10", + "location":"manila" + } + ], + "locations":{ + "Amsterdam":{ + "country_code":"NL", + "hemisphere":"N", + "name":"Amsterdam", + "timezone":"-1" + }, + "moscow": { + "country_code": "RU", + "hemisphere": "N", + "name": "Moscow", + "timezone": "+3" + }, + "manila": { + "country_code": "PH", + "hemisphere": "N", + "name": "Manila", + "timezone": "+8" + } + }, + "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, + "key-direction" : "1", + "verb" : "3" + }, + "serial":2, + "version":3 +} \ No newline at end of file -- cgit v1.2.3 From 2ae968a8cfcfeb51874a206fd1abbf40f06cf98b Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 4 Jul 2019 17:08:29 +0200 Subject: 'using an obfusctation connection' in italic --- app/src/custom/assets/ptdemo.bitmask.eip-service.json | 2 +- .../se/leap/bitmaskclient/VpnNotificationManager.java | 18 ++++++++++++++---- app/src/main/java/se/leap/bitmaskclient/eip/EIP.java | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'app/src') diff --git a/app/src/custom/assets/ptdemo.bitmask.eip-service.json b/app/src/custom/assets/ptdemo.bitmask.eip-service.json index cb650ada..60635ff6 100644 --- a/app/src/custom/assets/ptdemo.bitmask.eip-service.json +++ b/app/src/custom/assets/ptdemo.bitmask.eip-service.json @@ -32,7 +32,7 @@ "user_ips":false }, "host":"pt.demo.bitmask.net", - "ip_address":"37.218.242.216", + "ip_address":"37.218.247.60", "location":"Amsterdam" } ], diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java b/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java index 44a69f5c..abf71803 100644 --- a/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java @@ -24,11 +24,17 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Color; +import android.graphics.Typeface; import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationManagerCompat; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.style.StyleSpan; import android.widget.RemoteViews; import de.blinkt.openvpn.LaunchVPN; @@ -113,7 +119,7 @@ public class VpnNotificationManager { */ public void buildOpenVpnNotification(String profileName, boolean isObfuscated, String msg, String tickerText, ConnectionStatus status, long when, String notificationChannelNewstatusId) { String cancelString; - String bigmessage = null; + CharSequence bigmessage = null; String ghostIcon = new String(Character.toChars(0x1F47B)); switch (status) { @@ -124,14 +130,18 @@ public class VpnNotificationManager { case LEVEL_CONNECTING_NO_SERVER_REPLY_YET: cancelString = context.getString(R.string.cancel); if (isObfuscated && Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { - bigmessage = context.getString(R.string.obfuscated_connection_try) + " " + ghostIcon + "\n" + msg; + Spannable spannable = new SpannableString(context.getString(R.string.obfuscated_connection_try)); + spannable.setSpan(new StyleSpan(Typeface.ITALIC), 0, spannable.length() -1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + bigmessage = TextUtils.concat(spannable, " " + ghostIcon + "\n" + msg); } break; // show disconnect if connection exists case LEVEL_CONNECTED: if (isObfuscated && Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { - bigmessage = context.getString(R.string.obfuscated_connection) + " " + ghostIcon + "\n" + msg; + Spannable spannable = new SpannableString(context.getString(R.string.obfuscated_connection)); + spannable.setSpan(new StyleSpan(Typeface.ITALIC), 0, spannable.length() -1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + bigmessage = TextUtils.concat(spannable, " " + ghostIcon + "\n" + msg); } default: cancelString = context.getString(R.string.cancel_connection); @@ -242,7 +252,7 @@ public class VpnNotificationManager { return remoteViews; } - private void buildVpnNotification(String title, String message, String bigMessage, String tickerText, ConnectionStatus status, String notificationChannelNewstatusId, int priority, long when, PendingIntent contentIntent, NotificationCompat.Action notificationAction) { + private void buildVpnNotification(String title, String message, CharSequence bigMessage, String tickerText, ConnectionStatus status, String notificationChannelNewstatusId, int priority, long when, PendingIntent contentIntent, NotificationCompat.Action notificationAction) { NotificationCompat.Builder nCompatBuilder = new NotificationCompat.Builder(context, notificationChannelNewstatusId); int icon = getIconByConnectionStatus(status); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index 1d702ec1..9b5176e7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -244,7 +244,7 @@ public final class EIP extends JobIntentService implements Observer { */ private void launchActiveGateway(@NonNull Gateway gateway, int nClosestGateway) { Intent intent = new Intent(BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT); - intent.putExtra(PROVIDER_PROFILE, gateway.getProfile(OPENVPN)); + intent.putExtra(PROVIDER_PROFILE, gateway.getProfile(OBFS4)); intent.putExtra(Gateway.KEY_N_CLOSEST_GATEWAY, nClosestGateway); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); -- cgit v1.2.3 From 1d3ecd7bb6cbb9ecac394cc494b095ef830dadee Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sun, 14 Jul 2019 20:11:44 +0200 Subject: remove equals method in Gateway class after rebasing onto latest master --- app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java index 9bc07764..352d6b18 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -157,17 +157,4 @@ public class Gateway { return new Gson().toJson(this, Gateway.class); } - @Override - public boolean equals(Object obj) { - return obj instanceof Gateway && - (this.mVpnProfile != null && - ((Gateway) obj).mVpnProfile != null && - this.mVpnProfile.mConnections != null && - ((Gateway) obj).mVpnProfile != null && - this.mVpnProfile.mConnections.length > 0 && - ((Gateway) obj).mVpnProfile.mConnections.length > 0 && - this.mVpnProfile.mConnections[0].mServerName != null && - this.mVpnProfile.mConnections[0].mServerName.equals(((Gateway) obj).mVpnProfile.mConnections[0].mServerName)) || - this.mVpnProfile == null && ((Gateway) obj).mVpnProfile == null; - } } -- cgit v1.2.3 From 22403d3a7c60f92df38b0178780ce4d3e245c2fd Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sun, 14 Jul 2019 20:12:08 +0200 Subject: remove duplicated line in OpenVPNService --- app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java | 1 - 1 file changed, 1 deletion(-) (limited to 'app/src') 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 184cea2c..32e00f86 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -66,7 +66,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac public final static String ORBOT_PACKAGE_NAME = "org.torproject.android"; private static final String PAUSE_VPN = "de.blinkt.openvpn.PAUSE_VPN"; private static final String RESUME_VPN = "se.leap.bitmaskclient.RESUME_VPN"; - private static final String TAG = OpenVPNService.class.getSimpleName(); private static boolean mNotificationAlwaysVisible = false; private final Vector mDnslist = new Vector<>(); private final NetworkSpace mRoutes = new NetworkSpace(); -- cgit v1.2.3 From 0917317c006b8a3b0a8ee1c991a6287623c9562a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 19 Jul 2019 14:44:05 +0200 Subject: adapt error handling during eip setup: refresh UI if gateway profile could not be started --- .../java/se/leap/bitmaskclient/EipSetupObserver.java | 1 + app/src/main/java/se/leap/bitmaskclient/eip/EIP.java | 19 +++++++++++++------ .../java/se/leap/bitmaskclient/eip/EipStatus.java | 11 +++++++---- 3 files changed, 21 insertions(+), 10 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java b/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java index a8aa2dfb..7327c416 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipSetupObserver.java @@ -168,6 +168,7 @@ class EipSetupObserver extends BroadcastReceiver implements VpnStatus.StateListe if (resultCode == RESULT_CANCELED) { //setup failed finishGatewaySetup(false); + EipStatus.refresh(); } break; default: diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index 9b5176e7..3855fa12 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -43,6 +43,7 @@ import java.util.Observer; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.IOpenVPNServiceInternal; import de.blinkt.openvpn.core.OpenVPNService; @@ -53,7 +54,6 @@ import se.leap.bitmaskclient.R; import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_OK; import static android.content.Intent.CATEGORY_DEFAULT; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import static se.leap.bitmaskclient.Constants.BROADCAST_EIP_EVENT; import static se.leap.bitmaskclient.Constants.BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT; @@ -205,11 +205,11 @@ public final class EIP extends JobIntentService implements Observer { GatewaysManager gatewaysManager = gatewaysFromPreferences(); Gateway gateway = gatewaysManager.select(nClosestGateway); - if (gateway != null && !gateway.getProfiles().isEmpty()) { - launchActiveGateway(gateway, nClosestGateway); + if (launchActiveGateway(gateway, nClosestGateway)) { tellToReceiverOrBroadcast(EIP_ACTION_START, RESULT_OK); - } else + } else { tellToReceiverOrBroadcast(EIP_ACTION_START, RESULT_CANCELED); + } } /** @@ -242,11 +242,18 @@ public final class EIP extends JobIntentService implements Observer { * * @param gateway to connect to */ - private void launchActiveGateway(@NonNull Gateway gateway, int nClosestGateway) { + private boolean launchActiveGateway(Gateway gateway, int nClosestGateway) { + VpnProfile profile; + if (gateway == null || + (profile = gateway.getProfile(OPENVPN)) == null) { + return false; + } + Intent intent = new Intent(BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT); - intent.putExtra(PROVIDER_PROFILE, gateway.getProfile(OBFS4)); + intent.putExtra(PROVIDER_PROFILE, profile); intent.putExtra(Gateway.KEY_N_CLOSEST_GATEWAY, nClosestGateway); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + return true; } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java index 64904816..69fc483a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -78,8 +78,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { currentStatus.setLevel(level); currentStatus.setEipLevel(level); if (tmp != currentStatus.getLevel() || "RECONNECTING".equals(state)) { - currentStatus.setChanged(); - currentStatus.notifyObservers(); + refresh(); } } @@ -174,8 +173,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { default: break; } - currentStatus.setChanged(); - currentStatus.notifyObservers(); + refresh(); } } } @@ -286,4 +284,9 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { return "State: " + state + " Level: " + vpnLevel.toString(); } + public static void refresh() { + currentStatus.setChanged(); + currentStatus.notifyObservers(); + } + } -- cgit v1.2.3 From 1a27e86bb86e70830dc79a210b0efb80fffbb5c7 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 19 Jul 2019 18:39:57 +0200 Subject: add shared preferences for pluggable transport usage --- app/src/main/java/se/leap/bitmaskclient/Constants.java | 1 + .../se/leap/bitmaskclient/utils/PreferenceHelper.java | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/Constants.java b/app/src/main/java/se/leap/bitmaskclient/Constants.java index 7503d29f..0bc3c944 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/Constants.java @@ -13,6 +13,7 @@ public interface Constants { String ALWAYS_ON_SHOW_DIALOG = "DIALOG.ALWAYS_ON_SHOW_DIALOG"; String CLEARLOG = "clearlogconnect"; String LAST_USED_PROFILE = "last_used_profile"; + String USE_PLUGGABLE_TRANSPORTS = "usePluggableTransports"; ////////////////////////////////////////////// diff --git a/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java index f5cf590b..09d941f5 100644 --- a/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java @@ -29,6 +29,7 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION; import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; +import static se.leap.bitmaskclient.Constants.USE_PLUGGABLE_TRANSPORTS; /** * Created by cyberta on 18.03.18. @@ -210,6 +211,22 @@ public class PreferenceHelper { apply(); } + public static boolean getUsePluggableTransports(Context context) { + if (context == null) { + return false; + } + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + return preferences.getBoolean(USE_PLUGGABLE_TRANSPORTS, false); + } + + public static void usePluggableTransports(Context context, boolean isEnabled) { + if (context == null) { + return; + } + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + preferences.edit().putBoolean(USE_PLUGGABLE_TRANSPORTS, isEnabled).apply(); + } + public static void saveBattery(Context context, boolean isEnabled) { if (context == null) { return; -- cgit v1.2.3 From 990c4fa151adf9f91dc729c21b44edb0f0b55ccf Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 19 Jul 2019 18:46:12 +0200 Subject: add simple UI to enable/disable PT usage --- .../leap/bitmaskclient/DrawerSettingsAdapter.java | 1 + .../main/java/se/leap/bitmaskclient/Provider.java | 5 +++ .../drawer/NavigationDrawerFragment.java | 37 ++++++++++++++++++---- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 6 +++- app/src/main/res/values/strings.xml | 1 + 5 files changed, 42 insertions(+), 8 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java b/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java index 89aeb4be..e2b21db9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java +++ b/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java @@ -45,6 +45,7 @@ public class DrawerSettingsAdapter extends BaseAdapter { public static final int BATTERY_SAVER = 3; public static final int ALWAYS_ON = 4; public static final int DONATE = 5; + public static final int PLUGGABLE_TRANSPORTS = 6; //view types public final static int VIEW_SIMPLE_TEXT = 0; diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index c81f5739..561453af 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -119,6 +119,11 @@ public final class Provider implements Parcelable { hasPrivateKey(); } + //TODO: implement me! + public boolean supportsPluggableTransports() { + return true; + } + public void setMainUrl(URL url) { mainUrl.setUrl(url); } diff --git a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java index 640c143a..8c022b98 100644 --- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java @@ -55,10 +55,12 @@ import se.leap.bitmaskclient.FragmentManagerEnhanced; import se.leap.bitmaskclient.MainActivity; import se.leap.bitmaskclient.Provider; import se.leap.bitmaskclient.ProviderListActivity; +import se.leap.bitmaskclient.ProviderObservable; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.fragments.AboutFragment; import se.leap.bitmaskclient.fragments.AlwaysOnDialog; import se.leap.bitmaskclient.fragments.LogFragment; +import se.leap.bitmaskclient.utils.PreferenceHelper; import static android.content.Context.MODE_PRIVATE; import static se.leap.bitmaskclient.BitmaskApp.getRefWatcher; @@ -74,6 +76,7 @@ import static se.leap.bitmaskclient.DrawerSettingsAdapter.DONATE; import static se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem.getSimpleTextInstance; import static se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem.getSwitchInstance; import static se.leap.bitmaskclient.DrawerSettingsAdapter.LOG; +import static se.leap.bitmaskclient.DrawerSettingsAdapter.PLUGGABLE_TRANSPORTS; import static se.leap.bitmaskclient.DrawerSettingsAdapter.SWITCH_PROVIDER; import static se.leap.bitmaskclient.R.string.about_fragment_title; import static se.leap.bitmaskclient.R.string.donate_title; @@ -84,7 +87,9 @@ import static se.leap.bitmaskclient.utils.PreferenceHelper.getProviderName; import static se.leap.bitmaskclient.utils.PreferenceHelper.getSaveBattery; import static se.leap.bitmaskclient.utils.PreferenceHelper.getSavedProviderFromSharedPreferences; import static se.leap.bitmaskclient.utils.PreferenceHelper.getShowAlwaysOnDialog; +import static se.leap.bitmaskclient.utils.PreferenceHelper.getUsePluggableTransports; import static se.leap.bitmaskclient.utils.PreferenceHelper.saveBattery; +import static se.leap.bitmaskclient.utils.PreferenceHelper.usePluggableTransports; /** * Fragment used for managing interactions for and presentation of a navigation drawer. @@ -254,14 +259,26 @@ public class NavigationDrawerFragment extends Fragment { private void setupSettingsListAdapter() { settingsListAdapter = new DrawerSettingsAdapter(getLayoutInflater()); - if (getContext() != null) { + if (getContext() == null) { + return; + } + + Provider currentProvider = ProviderObservable.getInstance().getCurrentProvider(); + if (currentProvider.supportsPluggableTransports()) { settingsListAdapter.addItem(getSwitchInstance(getContext(), - getString(R.string.save_battery), - R.drawable.ic_battery_36, - getSaveBattery(getContext()), - BATTERY_SAVER, - (buttonView, newStateIsChecked) -> onSwitchItemSelected(BATTERY_SAVER, newStateIsChecked))); + getString(R.string.nav_drawer_obfuscated_connection), + R.drawable.ic_bridge_36, + getUsePluggableTransports(getContext()), + PLUGGABLE_TRANSPORTS, + (buttonView, newStateIsChecked) -> onSwitchItemSelected(PLUGGABLE_TRANSPORTS, newStateIsChecked))); } + + settingsListAdapter.addItem(getSwitchInstance(getContext(), + getString(R.string.save_battery), + R.drawable.ic_battery_36, + getSaveBattery(getContext()), + BATTERY_SAVER, + (buttonView, newStateIsChecked) -> onSwitchItemSelected(BATTERY_SAVER, newStateIsChecked))); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { settingsListAdapter.addItem(getSimpleTextInstance(getContext(), getString(R.string.always_on_vpn), R.drawable.ic_always_on_36, ALWAYS_ON)); } @@ -440,10 +457,16 @@ public class NavigationDrawerFragment extends Fragment { if (newStateIsChecked) { showExperimentalFeatureAlert(); } else { - saveBattery(this.getContext(), false); + saveBattery(getContext(), false); disableSwitch(BATTERY_SAVER); } break; + case PLUGGABLE_TRANSPORTS: + if (getUsePluggableTransports(getContext()) == newStateIsChecked) { + //initial ui setup, ignore + return; + } + usePluggableTransports(getContext(), newStateIsChecked); default: break; } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index 3855fa12..9431ef61 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -48,12 +48,14 @@ import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.IOpenVPNServiceInternal; import de.blinkt.openvpn.core.OpenVPNService; import de.blinkt.openvpn.core.VpnStatus; +import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.OnBootReceiver; import se.leap.bitmaskclient.R; import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_OK; import static android.content.Intent.CATEGORY_DEFAULT; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import static se.leap.bitmaskclient.Constants.BROADCAST_EIP_EVENT; import static se.leap.bitmaskclient.Constants.BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT; @@ -76,6 +78,7 @@ import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.MainActivityErrorDialog.DOWNLOAD_ERRORS.ERROR_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.R.string.vpn_certificate_is_invalid; import static se.leap.bitmaskclient.utils.ConfigHelper.ensureNotOnMainThread; +import static se.leap.bitmaskclient.utils.PreferenceHelper.getUsePluggableTransports; /** * EIP is the abstract base class for interacting with and managing the Encrypted @@ -244,8 +247,9 @@ public final class EIP extends JobIntentService implements Observer { */ private boolean launchActiveGateway(Gateway gateway, int nClosestGateway) { VpnProfile profile; + Connection.TransportType transportType = getUsePluggableTransports(this) ? OBFS4 : OPENVPN; if (gateway == null || - (profile = gateway.getProfile(OPENVPN)) == null) { + (profile = gateway.getProfile(transportType)) == null) { return false; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 698aa91a..472a8549 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -112,4 +112,5 @@ Donate Using an obfuscated connection. Trying an obfuscated connection. + Using Bridges -- cgit v1.2.3 From 84d5cf342d8e085be1996980c005b6c014f20379 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 19 Jul 2019 18:46:41 +0200 Subject: minor cleanup in EIP --- app/src/main/java/se/leap/bitmaskclient/eip/EIP.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index 9431ef61..fd498df8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -223,9 +223,7 @@ public final class EIP extends JobIntentService implements Observer { GatewaysManager gatewaysManager = gatewaysFromPreferences(); Gateway gateway = gatewaysManager.select(0); - if (gateway != null && !gateway.getProfiles().isEmpty()) { - launchActiveGateway(gateway, 0); - } else { + if (!launchActiveGateway(gateway, 0)) { Log.d(TAG, "startEIPAlwaysOnVpn no active profile available!"); } } -- cgit v1.2.3 From 2dbca18ebd0ca4de48ad8e04a295daf31ea9083e Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 19 Jul 2019 18:57:11 +0200 Subject: use bridge by night unicode character instead of ghost in notifications --- app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java b/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java index abf71803..b276a402 100644 --- a/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/VpnNotificationManager.java @@ -120,7 +120,7 @@ public class VpnNotificationManager { public void buildOpenVpnNotification(String profileName, boolean isObfuscated, String msg, String tickerText, ConnectionStatus status, long when, String notificationChannelNewstatusId) { String cancelString; CharSequence bigmessage = null; - String ghostIcon = new String(Character.toChars(0x1F47B)); + String ghostIcon = new String(Character.toChars(0x1f309)); switch (status) { // show cancel if no connection -- cgit v1.2.3 From 38d9a0d9ffe7fddb517e4058c4559a84d99e4a21 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 20 Jul 2019 14:04:13 +0200 Subject: add missing bridge icons --- app/src/main/res/drawable-hdpi/ic_bridge_36.png | Bin 0 -> 821 bytes app/src/main/res/drawable-mdpi/ic_bridge_36.png | Bin 0 -> 774 bytes app/src/main/res/drawable-xhdpi/ic_bridge_36.png | Bin 0 -> 1162 bytes app/src/main/res/drawable-xxhdpi/ic_bridge_36.png | Bin 0 -> 1308 bytes app/src/main/res/drawable-xxxhdpi/ic_bridge_36.png | Bin 0 -> 1760 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_bridge_36.png create mode 100644 app/src/main/res/drawable-mdpi/ic_bridge_36.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_bridge_36.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_bridge_36.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_bridge_36.png (limited to 'app/src') diff --git a/app/src/main/res/drawable-hdpi/ic_bridge_36.png b/app/src/main/res/drawable-hdpi/ic_bridge_36.png new file mode 100644 index 00000000..e3acd2d1 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_bridge_36.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_bridge_36.png b/app/src/main/res/drawable-mdpi/ic_bridge_36.png new file mode 100644 index 00000000..6c45a2d8 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_bridge_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_bridge_36.png b/app/src/main/res/drawable-xhdpi/ic_bridge_36.png new file mode 100644 index 00000000..6f89408c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_bridge_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_bridge_36.png b/app/src/main/res/drawable-xxhdpi/ic_bridge_36.png new file mode 100644 index 00000000..d00613b8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_bridge_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_bridge_36.png b/app/src/main/res/drawable-xxxhdpi/ic_bridge_36.png new file mode 100644 index 00000000..8f531f5a Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_bridge_36.png differ -- cgit v1.2.3 From 4f7455bb6ea37928bd44d8579deaa05402975bc5 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 27 Jul 2019 15:13:44 +0200 Subject: update pluggable transports demo setup --- .../custom/assets/ptdemo.bitmask.eip-service.json | 99 +++++++++++----------- app/src/custom/assets/ptdemo.bitmask.net.json | 4 +- app/src/custom/assets/ptdemo.bitmask.secrets.json | 6 +- 3 files changed, 55 insertions(+), 54 deletions(-) (limited to 'app/src') diff --git a/app/src/custom/assets/ptdemo.bitmask.eip-service.json b/app/src/custom/assets/ptdemo.bitmask.eip-service.json index 60635ff6..66148c31 100644 --- a/app/src/custom/assets/ptdemo.bitmask.eip-service.json +++ b/app/src/custom/assets/ptdemo.bitmask.eip-service.json @@ -1,64 +1,63 @@ { - "gateways":[ + "serial": 3, + "version": 3, + "locations": { + "Amsterdam": { + "name": "Amsterdam", + "country_code": "NL", + "hemisphere": "N", + "timezone": "-1" + } + }, + "gateways": [ { - "capabilities":{ - "adblock":false, - "filter_dns":false, - "limited":false, - "transport":[ + "host": "pt.demo.bitmask.net", + "ip_address": "37.218.247.60", + "location": "Amsterdam", + "capabilities": { + "adblock": false, + "filter_dns": false, + "limited": false, + "transport": [ { - "type":"obfs4", - "protocols":[ + "type": "openvpn", + "protocols": [ "tcp" ], - "ports":[ - "23042" - ], - "options": { - "cert": "ivF1AFjQupVhFHn7koBPb9lBZJbc+RW/ArzR94hT0SRg3lWSk/mXHHiDQ/tYaT+zgxr1dQ", - "iat-mode": "0" - } + "ports": [ + "443" + ] }, { - "type":"openvpn", - "protocols":[ + "type": "obfs4", + "protocols": [ "tcp" ], - "ports":[ - "443" + "options": { + "cert": "gZlp9k6br2vn2MLnmjXpNh8D/CrR5wtackwZof/iICv1QzPwkkTUa+7JVOKtPiD0NFwCMw", + "iat-mode": "0" + }, + "ports": [ + "23042" ] } - ], - "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-128-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" : false, - "key-direction" : "1", - "verb" : "3" - }, - "serial":3, - "version":3 + + "openvpn_configuration": { + "auth": "SHA1", + "cipher": "AES-256-CBC", + "dev": "tun", + "keepalive": "10 30", + "key-direction": 1, + "nobind": true, + "persist-key": true, + "rcvbuf": 0, + "sndbuf": 0, + "tls-cipher": "DHE-RSA-AES128-SHA", + "tun-ipv6": true, + "verb": 3 + } } \ No newline at end of file diff --git a/app/src/custom/assets/ptdemo.bitmask.net.json b/app/src/custom/assets/ptdemo.bitmask.net.json index ff6a9620..54b4d8fd 100644 --- a/app/src/custom/assets/ptdemo.bitmask.net.json +++ b/app/src/custom/assets/ptdemo.bitmask.net.json @@ -13,7 +13,9 @@ "enrollment_policy": "open", "languages": [ "de", - "en" + "en", + "es", + "pt" ], "name": { "de": "Bitmask Pluggable Transports", diff --git a/app/src/custom/assets/ptdemo.bitmask.secrets.json b/app/src/custom/assets/ptdemo.bitmask.secrets.json index 61f1fe1d..d93b66eb 100644 --- a/app/src/custom/assets/ptdemo.bitmask.secrets.json +++ b/app/src/custom/assets/ptdemo.bitmask.secrets.json @@ -1,5 +1,5 @@ { - "ca_cert":"-----BEGIN CERTIFICATE-----\nMIIFjTCCA3WgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBZMRgwFgYDVQQKDA9SaXNl\ndXAgTmV0d29ya3MxGzAZBgNVBAsMEmh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UE\nAwwXUmlzZXVwIE5ldHdvcmtzIFJvb3QgQ0EwHhcNMTQwNDI4MDAwMDAwWhcNMjQw\nNDI4MDAwMDAwWjBZMRgwFgYDVQQKDA9SaXNldXAgTmV0d29ya3MxGzAZBgNVBAsM\nEmh0dHBzOi8vcmlzZXVwLm5ldDEgMB4GA1UEAwwXUmlzZXVwIE5ldHdvcmtzIFJv\nb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC76J4ciMJ8Sg0m\nTP7DF2DT9zNe0Csk4myoMFC57rfJeqsAlJCv1XMzBmXrw8wq/9z7XHv6n/0sWU7a\n7cF2hLR33ktjwODlx7vorU39/lXLndo492ZBhXQtG1INMShyv+nlmzO6GT7ESfNE\nLliFitEzwIegpMqxCIHXFuobGSCWF4N0qLHkq/SYUMoOJ96O3hmPSl1kFDRMtWXY\niw1SEKjUvpyDJpVs3NGxeLCaA7bAWhDY5s5Yb2fA1o8ICAqhowurowJpW7n5ZuLK\n5VNTlNy6nZpkjt1QycYvNycffyPOFm/Q/RKDlvnorJIrihPkyniV3YY5cGgP+Qkx\nHUOT0uLA6LHtzfiyaOqkXwc4b0ZcQD5Vbf6Prd20Ppt6ei0zazkUPwxld3hgyw58\nm/4UIjG3PInWTNf293GngK2Bnz8Qx9e/6TueMSAn/3JBLem56E0WtmbLVjvko+LF\nPM5xA+m0BmuSJtrD1MUCXMhqYTtiOvgLBlUm5zkNxALzG+cXB28k6XikXt6MRG7q\nhzIPG38zwkooM55yy5i1YfcIi5NjMH6A+t4IJxxwb67MSb6UFOwg5kFokdONZcwj\nshczHdG9gLKSBIvrKa03Nd3W2dF9hMbRu//STcQxOailDBQCnXXfAATj9pYzdY4k\nha8VCAREGAKTDAex9oXf1yRuktES4QIDAQABo2AwXjAdBgNVHQ4EFgQUC4tdmLVu\nf9hwfK4AGliaet5KkcgwDgYDVR0PAQH/BAQDAgIEMAwGA1UdEwQFMAMBAf8wHwYD\nVR0jBBgwFoAUC4tdmLVuf9hwfK4AGliaet5KkcgwDQYJKoZIhvcNAQENBQADggIB\nAGzL+GRnYu99zFoy0bXJKOGCF5XUXP/3gIXPRDqQf5g7Cu/jYMID9dB3No4Zmf7v\nqHjiSXiS8jx1j/6/Luk6PpFbT7QYm4QLs1f4BlfZOti2KE8r7KRDPIecUsUXW6P/\n3GJAVYH/+7OjA39za9AieM7+H5BELGccGrM5wfl7JeEz8in+V2ZWDzHQO4hMkiTQ\n4ZckuaL201F68YpiItBNnJ9N5nHr1MRiGyApHmLXY/wvlrOpclh95qn+lG6/2jk7\n3AmihLOKYMlPwPakJg4PYczm3icFLgTpjV5sq2md9bRyAg3oPGfAuWHmKj2Ikqch\nTd5CHKGxEEWbGUWEMP0s1A/JHWiCbDigc4Cfxhy56CWG4q0tYtnc2GMw8OAUO6Wf\nXu5pYKNkzKSEtT/MrNJt44tTZWbKV/Pi/N2Fx36my7TgTUj7g3xcE9eF4JV2H/sg\ntsK3pwE0FEqGnT4qMFbixQmc8bGyuakr23wjMvfO7eZUxBuWYR2SkcP26sozF9PF\ntGhbZHQVGZUTVPyvwahMUEhbPGVerOW0IYpxkm0x/eaWdTc4vPpf/rIlgbAjarnJ\nUN9SaWRlWKSdP4haujnzCoJbM7dU9bjvlGZNyXEekgeT0W2qFeGGp+yyUWw8tNsp\n0BuC1b7uW/bBn/xKm319wXVDvBgZgcktMolak39V7DVO\n-----END CERTIFICATE-----", - "cert":"-----BEGIN CERTIFICATE-----\nMIIEnDCCAoSgAwIBAgIRAMBASoEmbFNubIm2CUzfS7cwDQYJKoZIhvcNAQELBQAwdTEYMBYGA1UE\nCgwPUmlzZXVwIE5ldHdvcmtzMRswGQYDVQQLDBJodHRwczovL3Jpc2V1cC5uZXQxPDA6BgNVBAMM\nM1Jpc2V1cCBOZXR3b3JrcyBSb290IENBIChjbGllbnQgY2VydGlmaWNhdGVzIG9ubHkhKTAeFw0x\nOTA1MTIwMDAwMDBaFw0xOTA4MTIwMDAwMDBaMC0xKzApBgNVBAMMIlVOTElNSVRFRGN2Nnc3NTc5\nNHphdmk4bmxtcnd6MGs0ZzYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKtjI8XcFk\n61loMX2Y3EMKu6Y6/UwUzcxeUNjA19YJgJh85RUGD2NrhVQDSaB38jsX3xRKYGRaZ7k50S1MYv5M\nOLBmPL2pB6Nm5Ki+fRgr1sKSkQqXEZdHnS1/W5odBdO5JnZxVEjVBnM77FHuMyJ4rhAqswHLjrMo\nWBuJc4L3k04DH6t0zB+oRRsnYFze7FAfi9Vy9o409kYCF82ZXLZ0e4fZKaYbteUiMJlos93Esfp/\nWe3gxM/661/e3nL1H433l65+BbKYQp/ojb3VawaK/ZuD5/YhjbiQ9vttt3sWuG0k3PtDQEeBg6GH\n6JsCZ0U+/wmrorcDs007O5QlCgepAgMBAAGjbzBtMB0GA1UdDgQWBBT888ieEhIJhzB9sHkP72+Y\ng6hqFDALBgNVHQ8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwIwCQYDVR0TBAIwADAfBgNVHSME\nGDAWgBQX9BvV5SoBAU1rol02CikJlmWARjANBgkqhkiG9w0BAQsFAAOCAgEAje/LV2Oo/Qz7pGcM\nvQhnlxemL6p+3XI9UpyjkbDG9s45RxZoqEMGyOhqq4aQikoHOBZoasw5ChCVYz0dPCoKvmVuixD+\nzmSfEDfTO1dN1vgCeExbLpZFIMUqifjORPxXqfxCsJOzO5RHF05Q4ywgPJIF8pRIaSjswAbYAxBa\nS+d/2cp3wKj6WjRc0VOf2LZ95jV4PTnOHD5Ls3hyCIXsM4dvjxY2mcaVps4DX/GziaS9S6+wISEe\nx2sGk+uAJs11ixs26zefg4XHU4qDc3RnxG0sLEANTSNgulZAnffE4OQVGrLDJ/lJn77EfnggF9NF\nOBJR4U/xY/0nQNR8fvnjlp+ViebbyBWgn3EcuT1W8jxbUDMcdF+575gLtxbJ6/5EqKp6r2E1EKGW\nYutUgQW4C2c4gfWl1T0hVT3ykqDid1qzZvWiXPQCgE84LdViWaY6I4kuELLMZxWIKEKXo4y19K+z\nOOnlK70+SeOKdx9W9CuCHArlCDSKyWjNVxhf+M6ILLy6+LpJ618bsg18+FJvovdxmWl4jOuQNU6v\n6j4OwKd3sCjQ6zvIZk6CLkRZjxWdDNwwvb3O9YG99PcxXyR0SmX21ycnDKut6Sclk/sqhP+VrZbG\nCPHMcbuS+Jk6t4q5R3BGNmLeBpVMQOHN29++55Snd7qFTXEWUdrBTQUYc+c=\n-----END CERTIFICATE-----", - "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDKtjI8XcFk61loMX2Y3EMKu6Y6\n/UwUzcxeUNjA19YJgJh85RUGD2NrhVQDSaB38jsX3xRKYGRaZ7k50S1MYv5MOLBmPL2pB6Nm5Ki+\nfRgr1sKSkQqXEZdHnS1/W5odBdO5JnZxVEjVBnM77FHuMyJ4rhAqswHLjrMoWBuJc4L3k04DH6t0\nzB+oRRsnYFze7FAfi9Vy9o409kYCF82ZXLZ0e4fZKaYbteUiMJlos93Esfp/We3gxM/661/e3nL1\nH433l65+BbKYQp/ojb3VawaK/ZuD5/YhjbiQ9vttt3sWuG0k3PtDQEeBg6GH6JsCZ0U+/wmrorcD\ns007O5QlCgepAgMBAAECggEBAK6YdPZXjl4c83nxvortk/TnoQqH5oK4qwDFQ5v9iwXONAjGyu/Y\nSzptsOnP/Z2yDkHGS1SwZ18SnY/14b08OmluHklAod63jH7wDYNcfXgs1pOkx2lMpm7xKyHZxQig\nXzbGsRd1j/GjR5diOUMf2d31lkkguzgXZaonETi3PCN9vLEuA6nOhOF9tqyp5URngklF8VILBVs5\nagz5LLsS1jwn5KOhvP01Twi3fESvWdUKUK1aCOBeujsplPtYpl+hdnOzIWbrkBFisrbECvsn67A3\n7TTvld7Qyki/RV00xKO2SymkfL5RFHgpINzrgEY4xPh8pTrYKICOSkzxCL2BUz0CgYEA78pXyIVB\nYEcAfqXZR+5PBB8GeVjk1RusbL87lwZEn+Xp8yxab3Wi/EAkpt3349Y1S4o/kOSV1CZZtfgwI3/5\nX95JAQMgmRvg9Wv6Cm3eR+i1gvw4ONeccIj1Iip7/74Rwb2PGvtuQZPNQvxpU5QzKXdN3/dqaNOD\nvMAC2SqULZMCgYEA2GoxhY5iCnFFJ6LPIh4vd/srF6pR1fNm99coFsEZ9bL/5Fxz2mAOw25T9l5v\nl3YA5nO1r0ZkBmcHzkKl3feAW7DV8eTMFCln8mGpVuqsOEgdLVH0PF+IH2JWXd7agqHZlSPwhEVP\nBinOVC1acEDZ3+/CC1fLdoH4csrtPQmEW1MCgYBV5xEnnsVa7lS5CkUaxb685Th2hGgGCFHu61s3\nsWEoPz9ehEcpouTupTP8K4zArF6PX0mCaMFcLRj6XZ0xOoll1MYmfK5S62/du/7peY6mCDHuaNjj\nVCqRDh9zS/D8H2VRGM2JhwVqrL5d/vrknDTv5/OYBpSyVQPevJLIpb5LzQKBgDQ18nqZLjf8ucVl\nNvmxNJyKoQvVkGbAkS/r3YUX0y5+n9O1JlIh6I3nmSQQBnYRBwiSE9wUbF9LDgwJ8kBJzNLSJ9ty\n6nVWw/gq7ZLFjQULCNb9NaI3Hf0MWW/OKwNnDro3cHhIzFbdUSTnyDDaxHWNP1BDPxf5JTp0kKWw\nHRl3AoGABj4yBH9wqwMu0Hsmv5IZ0mRPj81g5imeQL+TnF4KAoyWe3VjPfWUllu5nMELOXmk69Nb\n2xFP6dp9g6EyuQqwYGHxR0ZhNLnvvj03hYmo3r8rulTY5KqpmQ1mNb/pqShuN9KxdvXpcp2Xj2Hg\nD/J37vgYH7L99/B8hBJqC4arjCk=\n-----END RSA PRIVATE KEY-----" + "ca_cert":"-----BEGIN CERTIFICATE-----\nMIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\nYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNVBAsME2h0dHBzOi8v\nYml0bWFzay5uZXQwHhcNMTIxMTA2MDAwMDAwWhcNMjIxMTA2MDAwMDAwWjBKMRgw\nFgYDVQQDDA9CaXRtYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNV\nBAsME2h0dHBzOi8vYml0bWFzay5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\nggIKAoICAQC1eV4YvayaU+maJbWrD4OHo3d7S1BtDlcvkIRS1Fw3iYDjsyDkZxai\ndHp4EUasfNQ+EVtXUvtk6170EmLco6Elg8SJBQ27trE6nielPRPCfX3fQzETRfvB\n7tNvGw4Jn2YKiYoMD79kkjgyZjkJ2r/bEHUSevmR09BRp86syHZerdNGpXYhcQ84\nCA1+V+603GFIHnrP+uQDdssW93rgDNYu+exT+Wj6STfnUkugyjmPRPjL7wh0tzy+\nznCeLl4xiV3g9sjPnc7r2EQKd5uaTe3j71sDPF92KRk0SSUndREz+B1+Dbe/RGk4\nMEqGFuOzrtsgEhPIX0hplhb0Tgz/rtug+yTT7oJjBa3u20AAOQ38/M99EfdeJvc4\nlPFF1XBBLh6X9UKF72an2NuANiX6XPySnJgZ7nZ09RiYZqVwu/qt3DfvLfhboq+0\nbQvLUPXrVDr70onv5UDjpmEA/cLmaIqqrduuTkFZOym65/PfAPvpGnt7crQj/Ibl\nDEDYZQmP7AS+6zBjoOzNjUGE5r40zWAR1RSi7zliXTu+yfsjXUIhUAWmYR6J3KxB\nlfsiHBQ+8dn9kC3YrUexWoOqBiqJOAJzZh5Y1tqgzfh+2nmHSB2dsQRs7rDRRlyy\nYMbkpzL9ZsOUO2eTP1mmar6YjCN+rggYjRrX71K2SpBG6b1zZxOG+wIDAQABo2Aw\nXjAdBgNVHQ4EFgQUuYGDLL2sswnYpHHvProt1JU+D48wDgYDVR0PAQH/BAQDAgIE\nMAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUuYGDLL2sswnYpHHvProt1JU+D48w\nDQYJKoZIhvcNAQENBQADggIBADeG67vaFcbITGpi51264kHPYPEWaXUa5XYbtmBl\ncXYyB6hY5hv/YNuVGJ1gWsDmdeXEyj0j2icGQjYdHRfwhrbEri+h1EZOm1cSBDuY\nk/P5+ctHyOXx8IE79DBsZ6IL61UKIaKhqZBfLGYcWu17DVV6+LT+AKtHhOrv3TSj\nRnAcKnCbKqXLhUPXpK0eTjPYS2zQGQGIhIy9sQXVXJJJsGrPgMxna1Xw2JikBOCG\nhtD/JKwt6xBmNwktH0GI/LVtVgSp82Clbn9C4eZN9E5YbVYjLkIEDhpByeC71QhX\nEIQ0ZR56bFuJA/CwValBqV/G9gscTPQqd+iETp8yrFpAVHOW+YzSFbxjTEkBte1J\naF0vmbqdMAWLk+LEFPQRptZh0B88igtx6tV5oVd+p5IVRM49poLhuPNJGPvMj99l\nmlZ4+AeRUnbOOeAEuvpLJbel4rhwFzmUiGoeTVoPZyMevWcVFq6BMkS+jRR2w0jK\nG6b0v5XDHlcFYPOgUrtsOBFJVwbutLvxdk6q37kIFnWCd8L3kmES5q4wjyFK47Co\nJa8zlx64jmMZPg/t3wWqkZgXZ14qnbyG5/lGsj5CwVtfDljrhN0oCWK1FZaUmW3d\n69db12/g4f6phldhxiWuGC/W6fCW5kre7nmhshcltqAJJuU47iX+DarBFiIj816e\nyV8e\n-----END CERTIFICATE-----", + "cert":"-----BEGIN CERTIFICATE-----\nMIIEjDCCAnSgAwIBAgIQGdkqRKZJAX/CPEtoBlrbWDANBgkqhkiG9w0BAQsFADBm\nMRAwDgYDVQQKDAdCaXRtYXNrMRwwGgYDVQQLDBNodHRwczovL2JpdG1hc2submV0\nMTQwMgYDVQQDDCtCaXRtYXNrIFJvb3QgQ0EgKGNsaWVudCBjZXJ0aWZpY2F0ZXMg\nb25seSEpMB4XDTE5MDYwMTAwMDAwMFoXDTE5MDkyNzAwMDAwMFowLTErMCkGA1UE\nAwwiVU5MSU1JVEVENGVteG96NWk1MHdvbngyYnh6Y2E2eXJmejCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAPF7xypaAfw3IL/YnbT+Xa3fcMQFkV1XGbDI\nZEKiI77pBGgAiWlOfRIX3PFrn5ZCVB4Kw9Gb5ZkPEumKHam4TltffwzLa5CH/TOP\ncA/La1OzeWsSsaaSzIgrUTLG6qrejAt6bHL9B9DBftozdSacLtOSWyi2trXx0N0i\n+UWMpj8wStu0bfOdsjUD9GyWDCwRdfUMFmAZGNqTiiHGkKJ/HL/rPWGFXRVTSsiY\nqkE8101g+4yUKb1YSOQ9QVhYZa0k5ikBV0QwTabVj7o5+PG46+eF7FDTXRetKqDn\nIFV93OfD4h6p2dts32VL00JQz5A3hq5F87IRWy2ntvdinYwUe8MCAwEAAaNvMG0w\nHQYDVR0OBBYEFGgo5UnQ4Qgpl1oOzEkkdJT/MWUNMAsGA1UdDwQEAwIHgDATBgNV\nHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFId+E7bsWFsU\nWah9vZuPvZ7O+aJsMA0GCSqGSIb3DQEBCwUAA4ICAQBlDHpOEqDKjnQORyl1ugP1\nF6YEWtj0v6MC9+gMkaConRtGBZ29UvagycSPX79+Dc1jnDXGwE7AZZM5Nscs1Ehc\nki9L1knbHSxfKNzRAMwVXoJJTkapKYYuYPEQYJRBuyl9j9ay4RaRSsqvQadSBErp\nYFWGJJ1aykwpaaym6JHzytIp9AXAwjj3guMmBXAsS3HdF9EbOBAV6goT6Zf6Euyk\nD7iNnTdaR+Tubm5wm5cE0B8pe9P3VUApSs6LCQ9akDYKrAsAWcEA5OCuhR8nLKF7\nmhCosooqWEsR6CyfVmrF3WyjUCefz3yYzCeG3lID2bzztBjB58PHEbKGpOvqLmW+\n1BNNi754smnd9ySs673hsay71V8r/MEXra6u6auDAuEiGX+SWVU45+jAQ6PUzKlc\n/26e8TX7lL9dltIwfga6b78szO1HGIsaH/3aA1OlAsZfLDXmtmMUoMgpTgsvQLGR\n61KmlWLUZDFASu7tuJYvR327FWJ/OYzsPw85Qg766gGq1jIzVa5tg+QLzKd9d40m\nRUR4FqvpjLTvG2x7R3oGJ1+831jLJ65eq8FxCGc7/mSHwgM6FlnAAKLUtHaFFlnp\n3228F5DdHj9VL1QZIx7lpoL89Zo9xzuE9EvquAjNhBj/JuYduEH+8nFC9Zs+dc6F\n0iOSMBMzFGJnQbjHFOuxjw==\n-----END CERTIFICATE-----", + "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA8XvHKloB/Dcgv9idtP5drd9wxAWRXVcZsMhkQqIjvukEaACJ\naU59Ehfc8WuflkJUHgrD0ZvlmQ8S6YodqbhOW19/DMtrkIf9M49wD8trU7N5axKx\nppLMiCtRMsbqqt6MC3pscv0H0MF+2jN1Jpwu05JbKLa2tfHQ3SL5RYymPzBK27Rt\n852yNQP0bJYMLBF19QwWYBkY2pOKIcaQon8cv+s9YYVdFVNKyJiqQTzXTWD7jJQp\nvVhI5D1BWFhlrSTmKQFXRDBNptWPujn48bjr54XsUNNdF60qoOcgVX3c58PiHqnZ\n22zfZUvTQlDPkDeGrkXzshFbLae292KdjBR7wwIDAQABAoIBAQCdNvOcjArc1Fs6\n62EJU81ThLPaurE/7pPoNx6nDv5srTHUL/1GFPZyUBzlBCda4QX4pROFpJRfCKRM\nbUIQm9BPxqVlhA4cg5yB8/GGJu5SCPeUkRAdnVcRk/oCL+TZp5fPZT2zwy5SZ5cZ\nogS0RVxrG87De+kKHUvYnItjD0WwvpEuQpXVksY/QaoocdVPCKi08GuQip6xTiGH\nRhxC0UxtN+DRYxXGVGLwdqbnQoSbhPRsdnUXRVgsyCPnBNV+/EW3WfO77y4PmW4V\n3ySs0JKYwGlQQ6wUTBt/AoKhMAe7WNb0GP3giz3DN3uMXPSua2EtHTgeV6W9mAaw\nfRcz6vS5AoGBAP+vGiqQWFOHmmVAwB489UcVHMKrGslXzXnlCLGkqeW9ksFKl+1z\nRmMB870JpH5eNtsPZZpbp4Mye/ar+oZ8ieM/grodNEDfHbqakL3UKgcJiQfnVdjg\najbFkbxI1hGDwoqrJUhZmec8pJpT1ZUumsAlE1f0rSxfV2J8TebvFJfPAoGBAPHI\nLsqgMmSfh2slmIPwjN6p7bQ3a1WW2DbbRk0ASJMTSaWJIAtxfF7yqxkvc11O16n1\nGP+58nyvqL9ucuFtznHcBtSOeOcpaZIuLfh5Z2r4W4wPB3KEJNDoBf7fwPuXjaw2\nhEM15NwBGBOw1z/C0Tk6YsxwJLJjsi55V51aeiXNAoGAEzfYIabj3LNumXm6dwth\n7Evb843k34ln+meKtb+Ivan4I+s1bDWj7sEwzt6wrIbsXJ7VpjqJZsUeqDXZCM7H\nlnspmk+jo9ShaWtAweP2nLzMvflXbIvBsAg9ogdff8WFk+K1VLDXbpgSTz9J6IKu\nQw8GWzAa7CDmcpKhUGBcDeUCgYBWNODyIDI3jGXVPz9k87TWg1IcqpHbn4AR9xbW\nx54Yyoy8t+q0Cc+lbvKwdSm2ADGHCLvUGjGqYVtSfgf59pPgJupMiUv0Z+CbXVnI\nuUi1bD3/7y/hldomnkPc/1yol/3MhFeeOy4Rf1ZdVvU4Z7b/p6CoceezrzZNubgS\ng7r/lQKBgEhRAeiJ4NVHaMWu1MKgfbFEya8NvpdrhPiQg7+mezqG5se6ICvkWm8z\nbQKKT1dCX0hJQD/ZRHARqnHvD1sAviqQBYp68V7fm/DpnJe+wMXVo7cGrixEexVo\nozzHdO+CDTeqAm6eO8FpmA7NxDTy16fKDc2su0QIm1oPEOl/Iomn\n-----END RSA PRIVATE KEY-----" } \ No newline at end of file -- cgit v1.2.3 From 5a883a2119500c1d25a7f7dc650f62d5262cb9cc Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 1 Aug 2019 23:16:22 +0200 Subject: add Shapeshifter class managing shapeshifter go library --- .../de/blinkt/openvpn/core/OpenVPNService.java | 32 ++++++++------- .../pluggableTransports/Shapeshifter.java | 48 ++++++++++++++++++++++ 2 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java (limited to 'app/src') 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 32e00f86..6f817323 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -47,6 +47,7 @@ import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.VpnNotificationManager; import se.leap.bitmaskclient.pluggableTransports.Dispatcher; import de.blinkt.openvpn.core.connection.Obfs4Connection; +import se.leap.bitmaskclient.pluggableTransports.Shapeshifter; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT; @@ -88,7 +89,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac private Toast mlastToast; private Runnable mOpenVPNThread; private VpnNotificationManager notificationManager; - private Dispatcher dispatcher; + private Shapeshifter shapeshifter; private static final int PRIORITY_MIN = -2; private static final int PRIORITY_DEFAULT = 0; @@ -246,9 +247,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if(isVpnRunning()) { if (getManagement() != null && getManagement().stopVPN(replaceConnection)) { if (!replaceConnection) { - if (dispatcher != null && dispatcher.isRunning()) { - dispatcher.stop(); + if (shapeshifter != null) { + shapeshifter.stop(); } + /*if (dispatcher != null && dispatcher.isRunning()) { + dispatcher.stop(); + }*/ VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); } return true; @@ -256,9 +260,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac return false; } else { if (!replaceConnection) { - if (dispatcher != null && dispatcher.isRunning()) { - dispatcher.stop(); + if (shapeshifter != null) { + shapeshifter.stop(); } + /*if (dispatcher != null && dispatcher.isRunning()) { + dispatcher.stop(); + }*/ VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); return true; } @@ -387,15 +394,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if (mProfile.mUsePluggableTransports) { Obfs4Connection obfs4Connection = (Obfs4Connection) connection; - dispatcher = new Dispatcher(this, obfs4Connection.getDispatcherOptions()); - dispatcher.initSync(); - - if (dispatcher.isRunning()) { - connection.setServerPort(dispatcher.getPort()); - Log.d(TAG, "Dispatcher running. Profile server name and port: " + - connection.getServerName() + ":" + connection.getServerPort()); - VpnStatus.logInfo("Dispatcher running. Profile server name and port: " + - connection.getServerName() + ":" + connection.getServerPort()); + //dispatcher = new Dispatcher(this, obfs4Connection.getDispatcherOptions()); + //dispatcher.initSync(); + shapeshifter = new Shapeshifter(obfs4Connection.getDispatcherOptions()); + if (shapeshifter.start()) { + // FIXME: we already know the shapeshifter port earlier! + connection.setServerPort(Shapeshifter.DISPATCHER_PORT); } else { Log.e(TAG, "Cannot initialize dispatcher for obfs4 connection. Shutting down."); VpnStatus.logError("Cannot initialize dispatcher for obfs4 connection. Shutting down."); diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java new file mode 100644 index 00000000..513a310e --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java @@ -0,0 +1,48 @@ +package se.leap.bitmaskclient.pluggableTransports; + +import android.util.Log; + +import shapeshifter.ShapeShifter; + +public class Shapeshifter { + + public static final String DISPATCHER_PORT = "4430"; + public static final String DISPATCHER_IP = "127.0.0.1"; + private static final String TAG = Shapeshifter.class.getSimpleName(); + + ShapeShifter shapeShifter; + + public Shapeshifter(DispatcherOptions options) { + shapeShifter = new ShapeShifter(); + shapeShifter.setIatMode(Long.valueOf(options.iatMode)); + shapeShifter.setSocksAddr(DISPATCHER_IP+":"+DISPATCHER_PORT); + shapeShifter.setTarget(options.remoteIP+":"+options.remotePort); + shapeShifter.setCert(options.cert); + Log.d(TAG, "shapeshifter initialized with: iat - " + shapeShifter.getIatMode() + + "; socksAddr - " + shapeShifter.getSocksAddr() + + "; target addr - " + shapeShifter.getTarget() + + "; cert - " + shapeShifter.getCert()); + } + + public boolean start() { + try { + shapeShifter.open(); + Log.d(TAG, "shapeshifter opened"); + return true; + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + public boolean stop() { + try { + shapeShifter.close(); + Log.d(TAG, "shapeshifter closed"); + return true; + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } +} -- cgit v1.2.3 From ec0fe044a8d3cabdc6d1576c870639daaf67beb4 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 1 Aug 2019 23:17:23 +0200 Subject: use strings instead of ints in eip-service demo setup json --- app/src/custom/assets/ptdemo.bitmask.eip-service.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app/src') diff --git a/app/src/custom/assets/ptdemo.bitmask.eip-service.json b/app/src/custom/assets/ptdemo.bitmask.eip-service.json index 66148c31..65b84dd0 100644 --- a/app/src/custom/assets/ptdemo.bitmask.eip-service.json +++ b/app/src/custom/assets/ptdemo.bitmask.eip-service.json @@ -51,13 +51,13 @@ "cipher": "AES-256-CBC", "dev": "tun", "keepalive": "10 30", - "key-direction": 1, + "key-direction": "1", "nobind": true, "persist-key": true, - "rcvbuf": 0, - "sndbuf": 0, + "rcvbuf": "0", + "sndbuf": "0", "tls-cipher": "DHE-RSA-AES128-SHA", "tun-ipv6": true, - "verb": 3 + "verb": "3" } } \ No newline at end of file -- cgit v1.2.3 From f9cc2de8be331cf3eeb1efefea5fa6ecfda41d72 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 1 Aug 2019 23:18:25 +0200 Subject: update secrets for demo setup --- app/src/custom/assets/ptdemo.bitmask.secrets.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/src') diff --git a/app/src/custom/assets/ptdemo.bitmask.secrets.json b/app/src/custom/assets/ptdemo.bitmask.secrets.json index d93b66eb..acf26365 100644 --- a/app/src/custom/assets/ptdemo.bitmask.secrets.json +++ b/app/src/custom/assets/ptdemo.bitmask.secrets.json @@ -1,5 +1,5 @@ { "ca_cert":"-----BEGIN CERTIFICATE-----\nMIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\nYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNVBAsME2h0dHBzOi8v\nYml0bWFzay5uZXQwHhcNMTIxMTA2MDAwMDAwWhcNMjIxMTA2MDAwMDAwWjBKMRgw\nFgYDVQQDDA9CaXRtYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNV\nBAsME2h0dHBzOi8vYml0bWFzay5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\nggIKAoICAQC1eV4YvayaU+maJbWrD4OHo3d7S1BtDlcvkIRS1Fw3iYDjsyDkZxai\ndHp4EUasfNQ+EVtXUvtk6170EmLco6Elg8SJBQ27trE6nielPRPCfX3fQzETRfvB\n7tNvGw4Jn2YKiYoMD79kkjgyZjkJ2r/bEHUSevmR09BRp86syHZerdNGpXYhcQ84\nCA1+V+603GFIHnrP+uQDdssW93rgDNYu+exT+Wj6STfnUkugyjmPRPjL7wh0tzy+\nznCeLl4xiV3g9sjPnc7r2EQKd5uaTe3j71sDPF92KRk0SSUndREz+B1+Dbe/RGk4\nMEqGFuOzrtsgEhPIX0hplhb0Tgz/rtug+yTT7oJjBa3u20AAOQ38/M99EfdeJvc4\nlPFF1XBBLh6X9UKF72an2NuANiX6XPySnJgZ7nZ09RiYZqVwu/qt3DfvLfhboq+0\nbQvLUPXrVDr70onv5UDjpmEA/cLmaIqqrduuTkFZOym65/PfAPvpGnt7crQj/Ibl\nDEDYZQmP7AS+6zBjoOzNjUGE5r40zWAR1RSi7zliXTu+yfsjXUIhUAWmYR6J3KxB\nlfsiHBQ+8dn9kC3YrUexWoOqBiqJOAJzZh5Y1tqgzfh+2nmHSB2dsQRs7rDRRlyy\nYMbkpzL9ZsOUO2eTP1mmar6YjCN+rggYjRrX71K2SpBG6b1zZxOG+wIDAQABo2Aw\nXjAdBgNVHQ4EFgQUuYGDLL2sswnYpHHvProt1JU+D48wDgYDVR0PAQH/BAQDAgIE\nMAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUuYGDLL2sswnYpHHvProt1JU+D48w\nDQYJKoZIhvcNAQENBQADggIBADeG67vaFcbITGpi51264kHPYPEWaXUa5XYbtmBl\ncXYyB6hY5hv/YNuVGJ1gWsDmdeXEyj0j2icGQjYdHRfwhrbEri+h1EZOm1cSBDuY\nk/P5+ctHyOXx8IE79DBsZ6IL61UKIaKhqZBfLGYcWu17DVV6+LT+AKtHhOrv3TSj\nRnAcKnCbKqXLhUPXpK0eTjPYS2zQGQGIhIy9sQXVXJJJsGrPgMxna1Xw2JikBOCG\nhtD/JKwt6xBmNwktH0GI/LVtVgSp82Clbn9C4eZN9E5YbVYjLkIEDhpByeC71QhX\nEIQ0ZR56bFuJA/CwValBqV/G9gscTPQqd+iETp8yrFpAVHOW+YzSFbxjTEkBte1J\naF0vmbqdMAWLk+LEFPQRptZh0B88igtx6tV5oVd+p5IVRM49poLhuPNJGPvMj99l\nmlZ4+AeRUnbOOeAEuvpLJbel4rhwFzmUiGoeTVoPZyMevWcVFq6BMkS+jRR2w0jK\nG6b0v5XDHlcFYPOgUrtsOBFJVwbutLvxdk6q37kIFnWCd8L3kmES5q4wjyFK47Co\nJa8zlx64jmMZPg/t3wWqkZgXZ14qnbyG5/lGsj5CwVtfDljrhN0oCWK1FZaUmW3d\n69db12/g4f6phldhxiWuGC/W6fCW5kre7nmhshcltqAJJuU47iX+DarBFiIj816e\nyV8e\n-----END CERTIFICATE-----", - "cert":"-----BEGIN CERTIFICATE-----\nMIIEjDCCAnSgAwIBAgIQGdkqRKZJAX/CPEtoBlrbWDANBgkqhkiG9w0BAQsFADBm\nMRAwDgYDVQQKDAdCaXRtYXNrMRwwGgYDVQQLDBNodHRwczovL2JpdG1hc2submV0\nMTQwMgYDVQQDDCtCaXRtYXNrIFJvb3QgQ0EgKGNsaWVudCBjZXJ0aWZpY2F0ZXMg\nb25seSEpMB4XDTE5MDYwMTAwMDAwMFoXDTE5MDkyNzAwMDAwMFowLTErMCkGA1UE\nAwwiVU5MSU1JVEVENGVteG96NWk1MHdvbngyYnh6Y2E2eXJmejCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAPF7xypaAfw3IL/YnbT+Xa3fcMQFkV1XGbDI\nZEKiI77pBGgAiWlOfRIX3PFrn5ZCVB4Kw9Gb5ZkPEumKHam4TltffwzLa5CH/TOP\ncA/La1OzeWsSsaaSzIgrUTLG6qrejAt6bHL9B9DBftozdSacLtOSWyi2trXx0N0i\n+UWMpj8wStu0bfOdsjUD9GyWDCwRdfUMFmAZGNqTiiHGkKJ/HL/rPWGFXRVTSsiY\nqkE8101g+4yUKb1YSOQ9QVhYZa0k5ikBV0QwTabVj7o5+PG46+eF7FDTXRetKqDn\nIFV93OfD4h6p2dts32VL00JQz5A3hq5F87IRWy2ntvdinYwUe8MCAwEAAaNvMG0w\nHQYDVR0OBBYEFGgo5UnQ4Qgpl1oOzEkkdJT/MWUNMAsGA1UdDwQEAwIHgDATBgNV\nHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFId+E7bsWFsU\nWah9vZuPvZ7O+aJsMA0GCSqGSIb3DQEBCwUAA4ICAQBlDHpOEqDKjnQORyl1ugP1\nF6YEWtj0v6MC9+gMkaConRtGBZ29UvagycSPX79+Dc1jnDXGwE7AZZM5Nscs1Ehc\nki9L1knbHSxfKNzRAMwVXoJJTkapKYYuYPEQYJRBuyl9j9ay4RaRSsqvQadSBErp\nYFWGJJ1aykwpaaym6JHzytIp9AXAwjj3guMmBXAsS3HdF9EbOBAV6goT6Zf6Euyk\nD7iNnTdaR+Tubm5wm5cE0B8pe9P3VUApSs6LCQ9akDYKrAsAWcEA5OCuhR8nLKF7\nmhCosooqWEsR6CyfVmrF3WyjUCefz3yYzCeG3lID2bzztBjB58PHEbKGpOvqLmW+\n1BNNi754smnd9ySs673hsay71V8r/MEXra6u6auDAuEiGX+SWVU45+jAQ6PUzKlc\n/26e8TX7lL9dltIwfga6b78szO1HGIsaH/3aA1OlAsZfLDXmtmMUoMgpTgsvQLGR\n61KmlWLUZDFASu7tuJYvR327FWJ/OYzsPw85Qg766gGq1jIzVa5tg+QLzKd9d40m\nRUR4FqvpjLTvG2x7R3oGJ1+831jLJ65eq8FxCGc7/mSHwgM6FlnAAKLUtHaFFlnp\n3228F5DdHj9VL1QZIx7lpoL89Zo9xzuE9EvquAjNhBj/JuYduEH+8nFC9Zs+dc6F\n0iOSMBMzFGJnQbjHFOuxjw==\n-----END CERTIFICATE-----", - "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA8XvHKloB/Dcgv9idtP5drd9wxAWRXVcZsMhkQqIjvukEaACJ\naU59Ehfc8WuflkJUHgrD0ZvlmQ8S6YodqbhOW19/DMtrkIf9M49wD8trU7N5axKx\nppLMiCtRMsbqqt6MC3pscv0H0MF+2jN1Jpwu05JbKLa2tfHQ3SL5RYymPzBK27Rt\n852yNQP0bJYMLBF19QwWYBkY2pOKIcaQon8cv+s9YYVdFVNKyJiqQTzXTWD7jJQp\nvVhI5D1BWFhlrSTmKQFXRDBNptWPujn48bjr54XsUNNdF60qoOcgVX3c58PiHqnZ\n22zfZUvTQlDPkDeGrkXzshFbLae292KdjBR7wwIDAQABAoIBAQCdNvOcjArc1Fs6\n62EJU81ThLPaurE/7pPoNx6nDv5srTHUL/1GFPZyUBzlBCda4QX4pROFpJRfCKRM\nbUIQm9BPxqVlhA4cg5yB8/GGJu5SCPeUkRAdnVcRk/oCL+TZp5fPZT2zwy5SZ5cZ\nogS0RVxrG87De+kKHUvYnItjD0WwvpEuQpXVksY/QaoocdVPCKi08GuQip6xTiGH\nRhxC0UxtN+DRYxXGVGLwdqbnQoSbhPRsdnUXRVgsyCPnBNV+/EW3WfO77y4PmW4V\n3ySs0JKYwGlQQ6wUTBt/AoKhMAe7WNb0GP3giz3DN3uMXPSua2EtHTgeV6W9mAaw\nfRcz6vS5AoGBAP+vGiqQWFOHmmVAwB489UcVHMKrGslXzXnlCLGkqeW9ksFKl+1z\nRmMB870JpH5eNtsPZZpbp4Mye/ar+oZ8ieM/grodNEDfHbqakL3UKgcJiQfnVdjg\najbFkbxI1hGDwoqrJUhZmec8pJpT1ZUumsAlE1f0rSxfV2J8TebvFJfPAoGBAPHI\nLsqgMmSfh2slmIPwjN6p7bQ3a1WW2DbbRk0ASJMTSaWJIAtxfF7yqxkvc11O16n1\nGP+58nyvqL9ucuFtznHcBtSOeOcpaZIuLfh5Z2r4W4wPB3KEJNDoBf7fwPuXjaw2\nhEM15NwBGBOw1z/C0Tk6YsxwJLJjsi55V51aeiXNAoGAEzfYIabj3LNumXm6dwth\n7Evb843k34ln+meKtb+Ivan4I+s1bDWj7sEwzt6wrIbsXJ7VpjqJZsUeqDXZCM7H\nlnspmk+jo9ShaWtAweP2nLzMvflXbIvBsAg9ogdff8WFk+K1VLDXbpgSTz9J6IKu\nQw8GWzAa7CDmcpKhUGBcDeUCgYBWNODyIDI3jGXVPz9k87TWg1IcqpHbn4AR9xbW\nx54Yyoy8t+q0Cc+lbvKwdSm2ADGHCLvUGjGqYVtSfgf59pPgJupMiUv0Z+CbXVnI\nuUi1bD3/7y/hldomnkPc/1yol/3MhFeeOy4Rf1ZdVvU4Z7b/p6CoceezrzZNubgS\ng7r/lQKBgEhRAeiJ4NVHaMWu1MKgfbFEya8NvpdrhPiQg7+mezqG5se6ICvkWm8z\nbQKKT1dCX0hJQD/ZRHARqnHvD1sAviqQBYp68V7fm/DpnJe+wMXVo7cGrixEexVo\nozzHdO+CDTeqAm6eO8FpmA7NxDTy16fKDc2su0QIm1oPEOl/Iomn\n-----END RSA PRIVATE KEY-----" + "cert":"-----BEGIN CERTIFICATE-----\nMIIEbDCCAlSgAwIBAgIRALod300UE8xiHL4EEoIhcXowDQYJKoZIhvcNAQELBQAw\nZjEQMA4GA1UECgwHQml0bWFzazEcMBoGA1UECwwTaHR0cHM6Ly9iaXRtYXNrLm5l\ndDE0MDIGA1UEAwwrQml0bWFzayBSb290IENBIChjbGllbnQgY2VydGlmaWNhdGVz\nIG9ubHkhKTAeFw0xOTA3MjMyMjQ5MzZaFw0xOTA4MjcyMjQ5MzZaMBQxEjAQBgNV\nBAMTCVVOTElNSVRFRDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMDS\nujyEVdUUFhGDseh4Jb7HtSgAhgCtEcZwqtcZdqSmt8grSQIelb0YsrX+1/ilffPp\nX3tloKCiv73Ur9fPFyFUgdDuu36aeQTvznHYNZAKbuoDDGfV6zswxSKh7YjMK8IB\nnM290ROl2FZNekh6S0to3pVMSOB5h8nulWB3D/9BeW2cB7XaS88jCZECE+edzw5u\nQ7nhW2F9ndr+0CL6ZLgdTrEOTnyZqTj8YVR4Gq82x3Z+MZNVNuRJz+PK+jpdPIBX\n8+Bxli2JkZmEhIWLA67RCAgmxTUngNb5NUnPtiip+8ABry7zSZX2wFERZkdXpI+v\nUEkYOTyXb4X+PaYZ9vsCAwEAAaNnMGUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM\nMAoGCCsGAQUFBwMCMB0GA1UdDgQWBBSopKH/oCH/thCQqS9YTosheHnCBDAfBgNV\nHSMEGDAWgBSHfhO27FhbFFmofb2bj72ezvmibDANBgkqhkiG9w0BAQsFAAOCAgEA\ngp4Z9U9+l0j+J4yCggyxuGysIrnkS/v2QFpEdqc4uILQjj8usfZBqVhNo+GxFqPx\nCwBh8usYvX1Sxq0LfVTcT/cUXhkMLRvCi+IHWaR011x4Q8N1Ak7rC8Q0O5GnxNd7\n0pfaITAxO1T3uMxa2m3LmKkWlCJNrKh9a5wPd96eAaXCoc+erqddqmQPKXEgIGM3\ng15vPumGvIZUhFB5g8wo6UbFyy8fCWBXUYn72IaMzIBBu4Z+eO1+fokeIxLY78iV\n+WbOld6dp6GMNxG8cxzKTjzcAOmCCdwJk9p1ARS+yrI6Y3Sat1NTc6+W8mM2pSj0\neXsMJuImQotver/rDqpgy9IhvAWRgI8smBXHWrjLNZzdBxF6KaN6z8zm2gXW8EKG\nI/aOBCsokrkQt8xcH4QQ0UjgANhG5ZasNGo8L3pkUrKqPUhtCZJlA2fVtA0LVG0o\naJDT76OxTTVP8F4EHGJRsPo+9swYXGiqDuoOhFXbtX/siU2G9WHL2bLZSGeu9EyP\nzMYFEXh2IuXP/wDN8++QfYLBqjLnj9g0mTS7anEbYVbiGuu3rRLJYqw3LQ+XuH+A\naF6GRT+bofF/Opk57moWwEjtWt40KIOhMYv3+T1cNzlLcrgNEvMwPHcUK7/6ukzv\nF8vICQK6i+exElrH72yWjvckZQlvHjo4bOYIJhZoDtw=\n-----END CERTIFICATE-----", + "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAwNK6PIRV1RQWEYOx6Hglvse1KACGAK0RxnCq1xl2pKa3yCtJ\nAh6VvRiytf7X+KV98+lfe2WgoKK/vdSv188XIVSB0O67fpp5BO/Ocdg1kApu6gMM\nZ9XrOzDFIqHtiMwrwgGczb3RE6XYVk16SHpLS2jelUxI4HmHye6VYHcP/0F5bZwH\ntdpLzyMJkQIT553PDm5DueFbYX2d2v7QIvpkuB1OsQ5OfJmpOPxhVHgarzbHdn4x\nk1U25EnP48r6Ol08gFfz4HGWLYmRmYSEhYsDrtEICCbFNSeA1vk1Sc+2KKn7wAGv\nLvNJlfbAURFmR1ekj69QSRg5PJdvhf49phn2+wIDAQABAoIBAHrvHutsV6jE6Jj8\nBJY425+5hYbeZpDRxq5ksJb41gp9fFhzOFXQmBj6QR4FPz54jEfQtx5eGb2wZVyq\n1/1YO9/1F9rUCdfatmNuXIl6lhOigzpQ/TzKRvHy0wyUfnOj8BX9nzIQ3daP+tBz\nDw5cYdrPHnHDNAdhlDArGzNoVVugEDyNb9rR9jSX2Se5ucm1fZkGK8FUTIdDNjr/\nVQyAmAOGwi9CLtMYm0O5xnS/TfMcUAUYfu9ttjL225dAWR9MjYcpODYo3Yzev+dM\nTZ8ka3+3eURXpl08Tl8TPE98jbDqSmm7D0oVrj5jwq/QbAGvAtF1ljJUtHJ52YJ1\nIPGUyoECgYEA5xUowRbje17aXlq9sne4r+f5KqjKDDzCHSwTwFWtfZR60a10uEvI\nRb1CXdEK8L0M7JVXV4J6pOc229/p23O74j5XmaDi/KBce71TGPTBarY/kKyv0xHe\nL59gRcKCfkCWuRFCbKuhGBElEak8tGaGplqljhjUSk+3WC88gLDUS8ECgYEA1Z1y\nfsjcZqkXk1aM6exZUPu0kupU/U2ZtCXcvi40nmyrLyWzMlOljGivGcHGcNAtDv4L\nBGQQt0XP6lo1KqoLT+e1/PbIBEcHCFstgv+LCCrIz4GLNZPHNw8jR09rSC7N4KVj\ncSsbMkjE9Mrxgr5MH0JGnnzVcTf9P8fX1Ejy4bsCgYEAyo6ynacZmmAH3GOAGvt0\nycT2lZ1FFrr/kKC9Y3/2xrirfDamtJHBKNiAX0pJY8LjnFJAMHYwWXJPlSbOkE3/\nqI7rLMBpl/Zdex32xE5vaMH+MCwfJ05nS6lRs3SP/GlTdUAa0LUVTcphivylOKES\ncKnOqyM6mzULSuKFD21xekECgYEAs9wvBFuBYBst04wDeA7eIVbd8vnFd8Y4Dbv3\nglYLTf03oan/mPdfI7sc+/XxbRmLZt02T4slm/r3Fl6/911Xyv7Rd94eCaP4YuvK\nhUs/ODA2BqoPmZwFF/HyBV/0d8GY7Xa0JRxjeNJWq7qY4TnzhDpclaOMYBkBbguJ\nSZ/miXMCgYAVV8THc0ZnjHJEhQZZHyonBA56n6wp8oj7PpSuBOy+oi54Sxds7wJm\ndLOFWeW1a6mlecga3ooIeyd9aa/mb4EXToUkqbSqmcI1ob86mVu9NM2MOxIcsxYR\nu1u8/52sxMv2umwuviWtn1E/vIuRIMKzo077KfZkHq6yiuIrNO+Ruw==\n-----END RSA PRIVATE KEY-----" } \ No newline at end of file -- cgit v1.2.3 From 3875f27f432c4327f3b4c068622986d13432c80c Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 1 Aug 2019 23:25:01 +0200 Subject: add provider/gateway setup infos to LogView in debug builds --- .../java/se/leap/bitmaskclient/ProviderApiManager.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'app/src') diff --git a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java index 6d9671b1..41c51dc9 100644 --- a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java +++ b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.net.URL; import java.util.List; +import de.blinkt.openvpn.core.VpnStatus; import okhttp3.OkHttpClient; import se.leap.bitmaskclient.eip.EIP; import se.leap.bitmaskclient.utils.ConfigHelper; @@ -134,6 +135,9 @@ public class ProviderApiManager extends ProviderApiManagerBase { return result; } + if (BuildConfig.DEBUG) { + VpnStatus.logDebug("PROVIDER JSON: " + providerDotJsonString); + } try { JSONObject providerJson = new JSONObject(providerDotJsonString); if (provider.define(providerJson)) { @@ -163,7 +167,9 @@ public class ProviderApiManager extends ProviderApiManagerBase { String eipServiceUrl = providerJson.getString(Provider.API_URL) + "/" + providerJson.getString(Provider.API_VERSION) + "/" + EIP.SERVICE_API_PATH; eipServiceJsonString = downloadWithProviderCA(provider.getCaCert(), eipServiceUrl); JSONObject eipServiceJson = new JSONObject(eipServiceJsonString); - + if (BuildConfig.DEBUG) { + VpnStatus.logDebug("EIP SERVICE JSON: " + eipServiceJsonString); + } provider.setEipServiceJson(eipServiceJson); result.putBoolean(BROADCAST_RESULT_KEY, true); @@ -187,6 +193,9 @@ public class ProviderApiManager extends ProviderApiManagerBase { URL newCertStringUrl = new URL(provider.getApiUrlWithVersion() + "/" + PROVIDER_VPN_CERTIFICATE); String certString = downloadWithProviderCA(provider.getCaCert(), newCertStringUrl.toString()); + if (BuildConfig.DEBUG) { + VpnStatus.logDebug("VPN CERT: " + certString); + } if (ConfigHelper.checkErroneousDownload(certString)) { if (certString == null || certString.isEmpty()) { // probably 204 @@ -217,6 +226,9 @@ public class ProviderApiManager extends ProviderApiManagerBase { if (validCertificate(provider, certString)) { provider.setCaCert(certString); preferences.edit().putString(Provider.CA_CERT + "." + providerDomain, certString).apply(); + if (BuildConfig.DEBUG) { + VpnStatus.logDebug("CA CERT: " + certString); + } result.putBoolean(BROADCAST_RESULT_KEY, true); } else { setErrorResult(result, warning_corrupted_provider_cert, ERROR_CERTIFICATE_PINNING.toString()); -- cgit v1.2.3 From 032b687c79fb4b6e8004db342286cb9e9c119142 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 1 Aug 2019 23:51:11 +0200 Subject: add missing import --- app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java | 1 + 1 file changed, 1 insertion(+) (limited to 'app/src') diff --git a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java index 41c51dc9..658e8e15 100644 --- a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java +++ b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java @@ -20,6 +20,7 @@ package se.leap.bitmaskclient; import android.content.SharedPreferences; import android.content.res.Resources; import android.os.Bundle; +import android.support.multidex.BuildConfig; import android.util.Pair; import org.json.JSONException; -- cgit v1.2.3 From 5144166172e3620a5bd9f6df7436222afeb4d133 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 2 Aug 2019 00:46:10 +0200 Subject: rename DispatcherOptions to Obfs4Options --- .../java/de/blinkt/openvpn/core/ConfigParser.java | 10 +++++----- .../openvpn/core/connection/Obfs4Connection.java | 8 ++++---- .../se/leap/bitmaskclient/eip/VpnConfigGenerator.java | 8 ++++---- .../bitmaskclient/pluggableTransports/Dispatcher.java | 10 +++++----- .../pluggableTransports/DispatcherOptions.java | 18 ------------------ .../pluggableTransports/Obfs4Options.java | 18 ++++++++++++++++++ .../pluggableTransports/Shapeshifter.java | 19 ++++++++++++++++++- 7 files changed, 54 insertions(+), 37 deletions(-) delete mode 100644 app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java (limited to 'app/src') 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 4c53087f..5ccd83dd 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java @@ -25,7 +25,7 @@ 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.OpenvpnConnection; -import se.leap.bitmaskclient.pluggableTransports.DispatcherOptions; +import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; @@ -140,7 +140,7 @@ public class ConfigParser { private HashMap>> options = new HashMap<>(); private HashMap> meta = new HashMap>(); private String auth_user_pass_file; - private DispatcherOptions dispatcherOptions; + private Obfs4Options obfs4Options; static public void useEmbbedUserAuth(VpnProfile np, String inlinedata) { String data = VpnProfile.getEmbeddedContent(inlinedata); @@ -752,8 +752,8 @@ public class ConfigParser { return TextUtils.join(s, str); } - public void setDispatcherOptions(DispatcherOptions dispatcherOptions) { - this.dispatcherOptions = dispatcherOptions; + public void setObfs4Options(Obfs4Options obfs4Options) { + this.obfs4Options = obfs4Options; } private Pair parseConnection(String connection, Connection defaultValues) throws IOException, ConfigParseError { @@ -776,7 +776,7 @@ public class ConfigParser { return null; } else - conn = transportType == OBFS4 ? new Obfs4Connection(dispatcherOptions) : new OpenvpnConnection(); + conn = transportType == OBFS4 ? new Obfs4Connection(obfs4Options) : new OpenvpnConnection(); Vector port = getOption("port", 1, 1); if (port != null) { 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 4f6be276..a2f86e05 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,6 +1,6 @@ package de.blinkt.openvpn.core.connection; -import se.leap.bitmaskclient.pluggableTransports.DispatcherOptions; +import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_IP; import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_PORT; @@ -12,9 +12,9 @@ import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_PO public class Obfs4Connection extends Connection { private static final String TAG = Obfs4Connection.class.getName(); - private DispatcherOptions options; + private Obfs4Options options; - public Obfs4Connection(DispatcherOptions options) { + public Obfs4Connection(Obfs4Options options) { setUseUdp(false); setServerName(DISPATCHER_IP); setServerPort(DISPATCHER_PORT); @@ -52,7 +52,7 @@ public class Obfs4Connection extends Connection { } - public DispatcherOptions getDispatcherOptions() { + public Obfs4Options getDispatcherOptions() { return options; } 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 6b76e8d9..d9bf5dd3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -29,7 +29,7 @@ import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.Provider; -import se.leap.bitmaskclient.pluggableTransports.DispatcherOptions; +import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; @@ -116,18 +116,18 @@ public class VpnConfigGenerator { ConfigParser icsOpenvpnConfigParser = new ConfigParser(); icsOpenvpnConfigParser.parseConfig(new StringReader(configuration)); if (transportType == OBFS4) { - icsOpenvpnConfigParser.setDispatcherOptions(getDispatcherOptions()); + icsOpenvpnConfigParser.setObfs4Options(getObfs4Options()); } return icsOpenvpnConfigParser.convertProfile(transportType); } - private DispatcherOptions getDispatcherOptions() throws JSONException { + private Obfs4Options getObfs4Options() throws JSONException { JSONObject transportOptions = obfs4Transport.getJSONObject(OPTIONS); String iatMode = transportOptions.getString("iat-mode"); String cert = transportOptions.getString("cert"); String port = obfs4Transport.getJSONArray(PORTS).getString(0); String ip = gateway.getString(IP_ADDRESS); - return new DispatcherOptions(ip, port, cert, iatMode); + return new Obfs4Options(ip, port, cert, iatMode); } private String generalConfiguration() { diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java index 240dae75..8e787b57 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java @@ -46,12 +46,12 @@ public class Dispatcher { private Thread dispatcherThread = null; private int dispatcherPid = -1; - public Dispatcher(Context context, DispatcherOptions dispatcherOptions) { + public Dispatcher(Context context, Obfs4Options obfs4Options) { this.context = context.getApplicationContext(); - this.remoteIP = dispatcherOptions.remoteIP; - this.remotePort = dispatcherOptions.remotePort; - this.certificate = dispatcherOptions.cert; - this.iatMode = dispatcherOptions.iatMode; + this.remoteIP = obfs4Options.remoteIP; + this.remotePort = obfs4Options.remotePort; + this.certificate = obfs4Options.cert; + this.iatMode = obfs4Options.iatMode; } @WorkerThread diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java deleted file mode 100644 index 76ccbd79..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java +++ /dev/null @@ -1,18 +0,0 @@ -package se.leap.bitmaskclient.pluggableTransports; - -import java.io.Serializable; - -public class DispatcherOptions implements Serializable { - public String cert; - public String iatMode; - public String remoteIP; - public String remotePort; - - public DispatcherOptions(String remoteIP, String remotePort, String cert, String iatMode) { - this.cert = cert; - this.iatMode = iatMode; - this.remoteIP = remoteIP; - this.remotePort = remotePort; - } - -} diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java new file mode 100644 index 00000000..2f9cb732 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java @@ -0,0 +1,18 @@ +package se.leap.bitmaskclient.pluggableTransports; + +import java.io.Serializable; + +public class Obfs4Options implements Serializable { + public String cert; + public String iatMode; + public String remoteIP; + public String remotePort; + + public Obfs4Options(String remoteIP, String remotePort, String cert, String iatMode) { + this.cert = cert; + this.iatMode = iatMode; + this.remoteIP = remoteIP; + this.remotePort = remotePort; + } + +} diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java index 513a310e..175e236a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java @@ -1,3 +1,20 @@ +/** + * Copyright (c) 2019 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 . + */ + package se.leap.bitmaskclient.pluggableTransports; import android.util.Log; @@ -12,7 +29,7 @@ public class Shapeshifter { ShapeShifter shapeShifter; - public Shapeshifter(DispatcherOptions options) { + public Shapeshifter(Obfs4Options options) { shapeShifter = new ShapeShifter(); shapeShifter.setIatMode(Long.valueOf(options.iatMode)); shapeShifter.setSocksAddr(DISPATCHER_IP+":"+DISPATCHER_PORT); -- cgit v1.2.3 From ec891871adb9ad75918fcdf33c45a33cafba044a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 2 Aug 2019 00:46:39 +0200 Subject: cleanup in OpenVPNService --- .../de/blinkt/openvpn/core/OpenVPNService.java | 24 +++++----------------- 1 file changed, 5 insertions(+), 19 deletions(-) (limited to 'app/src') 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 6f817323..e446021f 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -43,10 +43,9 @@ import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.VpnStatus.ByteCountListener; import de.blinkt.openvpn.core.VpnStatus.StateListener; import de.blinkt.openvpn.core.connection.Connection; +import de.blinkt.openvpn.core.connection.Obfs4Connection; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.VpnNotificationManager; -import se.leap.bitmaskclient.pluggableTransports.Dispatcher; -import de.blinkt.openvpn.core.connection.Obfs4Connection; import se.leap.bitmaskclient.pluggableTransports.Shapeshifter; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED; @@ -250,9 +249,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if (shapeshifter != null) { shapeshifter.stop(); } - /*if (dispatcher != null && dispatcher.isRunning()) { - dispatcher.stop(); - }*/ VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); } return true; @@ -263,9 +259,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if (shapeshifter != null) { shapeshifter.stop(); } - /*if (dispatcher != null && dispatcher.isRunning()) { - dispatcher.stop(); - }*/ VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); return true; } @@ -389,28 +382,21 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac // the dispatcher here? Can we start the dispatcher at a later point of execution, e.g. when // connections[n], n>0 gets choosen? - VpnStatus.logInfo("Setting up dispatcher."); Connection connection = mProfile.mConnections[0]; if (mProfile.mUsePluggableTransports) { Obfs4Connection obfs4Connection = (Obfs4Connection) connection; - //dispatcher = new Dispatcher(this, obfs4Connection.getDispatcherOptions()); - //dispatcher.initSync(); shapeshifter = new Shapeshifter(obfs4Connection.getDispatcherOptions()); - if (shapeshifter.start()) { - // FIXME: we already know the shapeshifter port earlier! - connection.setServerPort(Shapeshifter.DISPATCHER_PORT); - } else { - Log.e(TAG, "Cannot initialize dispatcher for obfs4 connection. Shutting down."); - VpnStatus.logError("Cannot initialize dispatcher for obfs4 connection. Shutting down."); + if (!shapeshifter.start()) { + //TODO: implement useful error handling + Log.e(TAG, "Cannot initialize shapeshifter dispatcher for obfs4 connection. Shutting down."); + VpnStatus.logError("Cannot initialize shapeshifter dispatcher for obfs4 connection. Shutting down."); } } - VpnStatus.logInfo(R.string.building_configration); VpnStatus.updateStateString("VPN_GENERATE_CONFIG", "", R.string.building_configration, ConnectionStatus.LEVEL_START); - try { mProfile.writeConfigFile(this); } catch (IOException e) { -- cgit v1.2.3 From fa04548dbdf1403e67682fc984bef9941e2f4c78 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 2 Aug 2019 00:47:26 +0200 Subject: remove unused context from GatewaysManager --- app/src/main/java/se/leap/bitmaskclient/eip/EIP.java | 2 +- app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java | 4 +--- app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index fd498df8..19c539e8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -288,7 +288,7 @@ public final class EIP extends JobIntentService implements Observer { * @return GatewaysManager */ private GatewaysManager gatewaysFromPreferences() { - GatewaysManager gatewaysManager = new GatewaysManager(this, preferences); + GatewaysManager gatewaysManager = new GatewaysManager(preferences); gatewaysManager.configureFromPreferences(); return gatewaysManager; } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java index f7038bab..740df97f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -44,13 +44,11 @@ public class GatewaysManager { private static final String TAG = GatewaysManager.class.getSimpleName(); - private Context context; private SharedPreferences preferences; private LinkedHashMap gateways = new LinkedHashMap<>(); private Type listType = new TypeToken>() {}.getType(); - GatewaysManager(Context context, SharedPreferences preferences) { - this.context = context; + GatewaysManager(SharedPreferences preferences) { this.preferences = preferences; } 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 0412b11a..e4c5f390 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java @@ -48,7 +48,7 @@ public class GatewaysManagerTest { when(sharedPreferences.getString(eq(Constants.PROVIDER_VPN_CERTIFICATE), anyString())).thenReturn(secrets.getString(Constants.PROVIDER_VPN_CERTIFICATE)); - gatewaysManager = new GatewaysManager(mockContext, sharedPreferences); + gatewaysManager = new GatewaysManager(sharedPreferences); } @Test -- cgit v1.2.3 From 37f9cf65b3267f081c4b80c62240fc7754a30325 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 3 Aug 2019 19:00:05 +0200 Subject: create custom UI classes navigation drawer entries --- .../leap/bitmaskclient/views/IconSwitchEntry.java | 96 ++++++++++++++++++++++ .../se/leap/bitmaskclient/views/IconTextEntry.java | 84 +++++++++++++++++++ .../res/layout-xlarge/v_icon_text_list_item.xml | 14 +++- .../main/res/layout-xlarge/v_switch_list_item.xml | 6 ++ app/src/main/res/layout/v_icon_text_list_item.xml | 14 +++- app/src/main/res/layout/v_switch_list_item.xml | 7 ++ app/src/main/res/values/attrs.xml | 13 +++ 7 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/views/IconTextEntry.java (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java b/app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java new file mode 100644 index 00000000..82e02a6e --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java @@ -0,0 +1,96 @@ +package se.leap.bitmaskclient.views; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.support.annotation.DrawableRes; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.support.v7.widget.SwitchCompat; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import se.leap.bitmaskclient.R; + +public class IconSwitchEntry extends LinearLayout { + + private TextView textView; + private ImageView iconView; + private SwitchCompat switchView; + private CompoundButton.OnCheckedChangeListener checkedChangeListener; + + public IconSwitchEntry(Context context) { + super(context); + initLayout(context, null); + } + + public IconSwitchEntry(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initLayout(context, attrs); + } + + public IconSwitchEntry(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initLayout(context, attrs); + } + + @TargetApi(21) + public IconSwitchEntry(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initLayout(context, attrs); + } + + void initLayout(Context context, AttributeSet attrs) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View rootview = inflater.inflate(R.layout.v_switch_list_item, this, true); + textView = rootview.findViewById(android.R.id.text1); + iconView = rootview.findViewById(R.id.material_icon); + switchView = rootview.findViewById(R.id.option_switch); + + if (attrs != null) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.IconSwitchEntry); + + String entryText = typedArray.getString(R.styleable.IconTextEntry_text); + if (entryText != null) { + textView.setText(entryText); + } + + Drawable drawable = typedArray.getDrawable(R.styleable.IconTextEntry_icon); + if (drawable != null) { + iconView.setImageDrawable(drawable); + } + + typedArray.recycle(); + } + } + + public void setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener listener) { + checkedChangeListener = listener; + switchView.setOnCheckedChangeListener(checkedChangeListener); + } + + public void setText(@StringRes int id) { + textView.setText(id); + } + + public void setIcon(@DrawableRes int id) { + iconView.setImageResource(id); + } + + public void setChecked(boolean isChecked) { + switchView.setChecked(isChecked); + } + + public void setCheckedQuietly(boolean isChecked) { + switchView.setOnCheckedChangeListener(null); + switchView.setChecked(isChecked); + switchView.setOnCheckedChangeListener(checkedChangeListener); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/views/IconTextEntry.java b/app/src/main/java/se/leap/bitmaskclient/views/IconTextEntry.java new file mode 100644 index 00000000..5689f429 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/views/IconTextEntry.java @@ -0,0 +1,84 @@ +package se.leap.bitmaskclient.views; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.support.annotation.DrawableRes; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import se.leap.bitmaskclient.R; + + +public class IconTextEntry extends LinearLayout { + + private TextView textView; + private ImageView iconView; + + public IconTextEntry(Context context) { + super(context); + initLayout(context, null); + } + + public IconTextEntry(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initLayout(context, attrs); + } + + public IconTextEntry(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initLayout(context, attrs); + } + + @TargetApi(21) + public IconTextEntry(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initLayout(context, attrs); + } + + void initLayout(Context context, AttributeSet attrs) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View rootview = inflater.inflate(R.layout.v_icon_text_list_item, this, true); + textView = rootview.findViewById(android.R.id.text1); + iconView = rootview.findViewById(R.id.material_icon); + + if (attrs != null) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.IconTextEntry); + + String entryText = typedArray.getString(R.styleable.IconTextEntry_text); + if (entryText != null) { + textView.setText(entryText); + } + + Drawable drawable = typedArray.getDrawable(R.styleable.IconTextEntry_icon); + if (drawable != null) { + iconView.setImageDrawable(drawable); + } + + typedArray.recycle(); + } + + + } + + public void setText(@StringRes int id) { + textView.setText(id); + } + + public void setText(CharSequence text) { + textView.setText(text); + } + + public void setIcon(@DrawableRes int id) { + iconView.setImageResource(id); + } + +} diff --git a/app/src/main/res/layout-xlarge/v_icon_text_list_item.xml b/app/src/main/res/layout-xlarge/v_icon_text_list_item.xml index 0192e080..7ecd32a9 100644 --- a/app/src/main/res/layout-xlarge/v_icon_text_list_item.xml +++ b/app/src/main/res/layout-xlarge/v_icon_text_list_item.xml @@ -1,6 +1,6 @@ - @@ -27,6 +27,14 @@ android:paddingRight="?android:attr/listPreferredItemPaddingRight" android:minHeight="?android:attr/listPreferredItemHeight" tools:text="TEST" + android:layout_toEndOf="@id/material_icon" + android:layout_toRightOf="@+id/material_icon" /> - + + diff --git a/app/src/main/res/layout-xlarge/v_switch_list_item.xml b/app/src/main/res/layout-xlarge/v_switch_list_item.xml index d692070e..68f63dc1 100644 --- a/app/src/main/res/layout-xlarge/v_switch_list_item.xml +++ b/app/src/main/res/layout-xlarge/v_switch_list_item.xml @@ -45,4 +45,10 @@ android:minHeight="?android:attr/listPreferredItemHeight" android:checked="false" tools:text="" /> + \ No newline at end of file diff --git a/app/src/main/res/layout/v_icon_text_list_item.xml b/app/src/main/res/layout/v_icon_text_list_item.xml index 0631b2fc..d34baeb6 100644 --- a/app/src/main/res/layout/v_icon_text_list_item.xml +++ b/app/src/main/res/layout/v_icon_text_list_item.xml @@ -1,6 +1,6 @@ - @@ -26,6 +26,14 @@ android:paddingRight="?android:attr/listPreferredItemPaddingRight" android:minHeight="?android:attr/listPreferredItemHeightSmall" tools:text="TEST" + android:layout_toEndOf="@id/material_icon" + android:layout_toRightOf="@+id/material_icon" /> - + + diff --git a/app/src/main/res/layout/v_switch_list_item.xml b/app/src/main/res/layout/v_switch_list_item.xml index 26060a73..de0e4f36 100644 --- a/app/src/main/res/layout/v_switch_list_item.xml +++ b/app/src/main/res/layout/v_switch_list_item.xml @@ -45,4 +45,11 @@ android:minHeight="?android:attr/listPreferredItemHeightSmall" android:checked="false" tools:text="" /> + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index eb9626bc..66a351ae 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -1,6 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From e45a11bb75d81ed4c395e4a1a9a80226a85b8742 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 3 Aug 2019 19:09:26 +0200 Subject: rewrite Navigation drawer - improves layout on small screens, fixes switch entry UI bug --- .../leap/bitmaskclient/DrawerSettingsAdapter.java | 246 ----------------- .../drawer/NavigationDrawerFragment.java | 302 +++++++++------------ app/src/main/res/layout/f_drawer_main.xml | 142 ++++++---- 3 files changed, 215 insertions(+), 475 deletions(-) delete mode 100644 app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java b/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java deleted file mode 100644 index e2b21db9..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java +++ /dev/null @@ -1,246 +0,0 @@ -/** - * Copyright (c) 2018 LEAP Encryption Access Project and contributers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package se.leap.bitmaskclient; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; -import android.support.v7.widget.SwitchCompat; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.CompoundButton; -import android.widget.ImageView; -import android.widget.TextView; - -import java.util.ArrayList; - -/** - * Created by cyberta on 21.02.18. - */ - -public class DrawerSettingsAdapter extends BaseAdapter { - - //item types - public static final int NONE = -1; - public static final int SWITCH_PROVIDER = 0; - public static final int LOG = 1; - public static final int ABOUT = 2; - public static final int BATTERY_SAVER = 3; - public static final int ALWAYS_ON = 4; - public static final int DONATE = 5; - public static final int PLUGGABLE_TRANSPORTS = 6; - - //view types - public final static int VIEW_SIMPLE_TEXT = 0; - public final static int VIEW_SWITCH = 1; - - public static class DrawerSettingsItem { - private String description = ""; - private int viewType = VIEW_SIMPLE_TEXT; - private boolean isChecked = false; - private int itemType = NONE; - private CompoundButton.OnCheckedChangeListener callback; - private Drawable iconResource; - - private DrawerSettingsItem(Context context, String description, @DrawableRes int iconResource, int viewType, boolean isChecked, int itemType, CompoundButton.OnCheckedChangeListener callback) { - this.description = description; - this.viewType = viewType; - this.isChecked = isChecked; - this.itemType = itemType; - this.callback = callback; - try { - this.iconResource = context.getResources().getDrawable(iconResource); - } catch (RuntimeException e) { - e.printStackTrace(); - } - } - - public static DrawerSettingsItem getSimpleTextInstance(Context context, String description, @DrawableRes int iconResource, int itemType) { - return new DrawerSettingsItem(context, description, iconResource, VIEW_SIMPLE_TEXT, false, itemType, null); - } - - public static DrawerSettingsItem getSwitchInstance(Context context, String description, @DrawableRes int iconResource, boolean isChecked, int itemType, CompoundButton.OnCheckedChangeListener callback) { - return new DrawerSettingsItem(context, description, iconResource, VIEW_SWITCH, isChecked, itemType, callback); - } - - public int getItemType() { - return itemType; - } - - public void setChecked(boolean checked) { - isChecked = checked; - } - - public boolean isChecked() { - return isChecked; - } - } - - private ArrayList mData = new ArrayList<>(); - private LayoutInflater mInflater; - - public DrawerSettingsAdapter(LayoutInflater layoutInflater) { - mInflater = layoutInflater; - } - - public void addItem(final DrawerSettingsItem item) { - mData.add(item); - notifyDataSetChanged(); - } - - @Override - public int getItemViewType(int position) { - DrawerSettingsItem item = mData.get(position); - return item.viewType; - } - - @Override - public int getViewTypeCount() { - boolean hasSwitchItem = false; - for (DrawerSettingsItem item : mData) { - if (item.viewType == VIEW_SWITCH) { - hasSwitchItem = true; - break; - } - } - return hasSwitchItem ? 2 : 1; - } - - @Override - public int getCount() { - return mData.size(); - } - - @Override - public DrawerSettingsItem getItem(int position) { - return mData.get(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - - DrawerSettingsItem drawerSettingsItem = mData.get(position); - ViewHolder holder = null; - int type = getItemViewType(position); - if (convertView == null) { - holder = new ViewHolder(); - switch(type) { - case VIEW_SIMPLE_TEXT: - convertView = initTextViewBinding(holder); - bindSimpleText(drawerSettingsItem, holder); - break; - case VIEW_SWITCH: - convertView = initSwitchBinding(holder); - bindSwitch(drawerSettingsItem, holder); - break; - } - convertView.setTag(holder); - } else { - holder = (ViewHolder)convertView.getTag(); - switch (type) { - case VIEW_SIMPLE_TEXT: - if (holder.isSwitchViewHolder()) { - holder.resetSwitchView(); - convertView = initTextViewBinding(holder); - } - bindSimpleText(drawerSettingsItem, holder); - break; - case VIEW_SWITCH: - if (!holder.isSwitchViewHolder()) { - holder.resetTextView(); - convertView = initSwitchBinding(holder); - } - bindSwitch(drawerSettingsItem, holder); - break; - } - convertView.setTag(holder); - } - return convertView; - } - - private void bindSimpleText(DrawerSettingsItem drawerSettingsItem, ViewHolder holder) { - holder.textView.setText(drawerSettingsItem.description); - if (drawerSettingsItem.iconResource != null) { - holder.iconView.setImageDrawable(drawerSettingsItem.iconResource); - } - } - - private void bindSwitch(DrawerSettingsItem drawerSettingsItem, ViewHolder holder) { - holder.switchView.setChecked(drawerSettingsItem.isChecked); - holder.textView.setText(drawerSettingsItem.description); - holder.switchView.setOnCheckedChangeListener(drawerSettingsItem.callback); - if (drawerSettingsItem.iconResource != null) { - holder.iconView.setImageDrawable(drawerSettingsItem.iconResource); - } - } - - @NonNull - private View initSwitchBinding(ViewHolder holder) { - View convertView = mInflater.inflate(R.layout.v_switch_list_item, null); - holder.switchView = convertView.findViewById(R.id.option_switch); - holder.textView = convertView.findViewById(android.R.id.text1); - holder.iconView = convertView.findViewById(R.id.material_icon); - return convertView; - } - - @NonNull - private View initTextViewBinding(ViewHolder holder) { - View convertView = mInflater.inflate(R.layout.v_icon_text_list_item, null); - holder.textView = convertView.findViewById(android.R.id.text1); - holder.iconView = convertView.findViewById(R.id.material_icon); - return convertView; - } - - public DrawerSettingsItem getDrawerItem(int elementType) { - for (DrawerSettingsItem item : mData) { - if (item.itemType == elementType) { - return item; - } - } - return null; - } - - static class ViewHolder { - TextView textView; - ImageView iconView; - SwitchCompat switchView; - - boolean isSwitchViewHolder() { - return switchView != null; - } - - void resetSwitchView() { - switchView.setOnCheckedChangeListener(null); - switchView = null; - } - - void resetTextView() { - textView = null; - } - } -} - - - diff --git a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java index 8c022b98..380b765e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 LEAP Encryption Access Project and contributers + * Copyright (c) 2019 LEAP Encryption Access Project and contributers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,7 +18,6 @@ package se.leap.bitmaskclient.drawer; import android.app.Activity; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; @@ -44,12 +43,7 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.ListView; -import se.leap.bitmaskclient.DrawerSettingsAdapter; -import se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem; import se.leap.bitmaskclient.EipFragment; import se.leap.bitmaskclient.FragmentManagerEnhanced; import se.leap.bitmaskclient.MainActivity; @@ -60,32 +54,22 @@ import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.fragments.AboutFragment; import se.leap.bitmaskclient.fragments.AlwaysOnDialog; import se.leap.bitmaskclient.fragments.LogFragment; -import se.leap.bitmaskclient.utils.PreferenceHelper; +import se.leap.bitmaskclient.views.IconSwitchEntry; +import se.leap.bitmaskclient.views.IconTextEntry; import static android.content.Context.MODE_PRIVATE; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; import static se.leap.bitmaskclient.BitmaskApp.getRefWatcher; import static se.leap.bitmaskclient.Constants.DONATION_URL; import static se.leap.bitmaskclient.Constants.ENABLE_DONATION; import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_SWITCH_PROVIDER; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; -import static se.leap.bitmaskclient.DrawerSettingsAdapter.ABOUT; -import static se.leap.bitmaskclient.DrawerSettingsAdapter.ALWAYS_ON; -import static se.leap.bitmaskclient.DrawerSettingsAdapter.BATTERY_SAVER; -import static se.leap.bitmaskclient.DrawerSettingsAdapter.DONATE; -import static se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem.getSimpleTextInstance; -import static se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem.getSwitchInstance; -import static se.leap.bitmaskclient.DrawerSettingsAdapter.LOG; -import static se.leap.bitmaskclient.DrawerSettingsAdapter.PLUGGABLE_TRANSPORTS; -import static se.leap.bitmaskclient.DrawerSettingsAdapter.SWITCH_PROVIDER; import static se.leap.bitmaskclient.R.string.about_fragment_title; -import static se.leap.bitmaskclient.R.string.donate_title; import static se.leap.bitmaskclient.R.string.log_fragment_title; -import static se.leap.bitmaskclient.R.string.switch_provider_menu_option; import static se.leap.bitmaskclient.utils.ConfigHelper.isDefaultBitmask; -import static se.leap.bitmaskclient.utils.PreferenceHelper.getProviderName; import static se.leap.bitmaskclient.utils.PreferenceHelper.getSaveBattery; -import static se.leap.bitmaskclient.utils.PreferenceHelper.getSavedProviderFromSharedPreferences; import static se.leap.bitmaskclient.utils.PreferenceHelper.getShowAlwaysOnDialog; import static se.leap.bitmaskclient.utils.PreferenceHelper.getUsePluggableTransports; import static se.leap.bitmaskclient.utils.PreferenceHelper.saveBattery; @@ -114,11 +98,10 @@ public class NavigationDrawerFragment extends Fragment { private DrawerLayout drawerLayout; private View drawerView; - private ListView drawerAccountsListView; private View fragmentContainerView; - private ArrayAdapter accountListAdapter; - private DrawerSettingsAdapter settingsListAdapter; private Toolbar toolbar; + private IconTextEntry account; + private IconSwitchEntry saveBattery; private boolean userLearnedDrawer; private volatile boolean wasPaused; @@ -188,14 +171,8 @@ public class NavigationDrawerFragment extends Fragment { this.drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); toolbar = this.drawerLayout.findViewById(R.id.toolbar); - final ActionBar actionBar = setupActionBar(); - setupSettingsListAdapter(); - setupSettingsListView(); - accountListAdapter = new ArrayAdapter<>(actionBar.getThemedContext(), - R.layout.v_icon_text_list_item, - android.R.id.text1); - refreshAccountListAdapter(); - setupAccountsListView(); + setupActionBar(); + setupEntries(); setupActionBarDrawerToggle(activity); if (!userLearnedDrawer) { @@ -245,51 +222,123 @@ public class NavigationDrawerFragment extends Fragment { }; } - private void setupAccountsListView() { - drawerAccountsListView = drawerView.findViewById(R.id.accountList); - drawerAccountsListView.setAdapter(accountListAdapter); - drawerAccountsListView.setOnItemClickListener((parent, view, position, id) -> selectItem(parent, position)); + private void setupEntries() { + initAccountEntry(); + initSwitchProviderEntry(); + initUseBridgesEntry(); + initSaveBatteryEntry(); + initAlwaysOnVpnEntry(); + initDonateEntry(); + initLogEntry(); + initAboutEntry(); } - private void setupSettingsListView() { - ListView drawerSettingsListView = drawerView.findViewById(R.id.settingsList); - drawerSettingsListView.setOnItemClickListener((parent, view, position, id) -> selectItem(parent, position)); - drawerSettingsListView.setAdapter(settingsListAdapter); + private void initAccountEntry() { + account = drawerView.findViewById(R.id.account); + FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager()); + Provider currentProvider = ProviderObservable.getInstance().getCurrentProvider(); + account.setText(currentProvider.getName()); + account.setOnClickListener((buttonView) -> { + Fragment fragment = new EipFragment(); + Bundle arguments = new Bundle(); + arguments.putParcelable(PROVIDER_KEY, currentProvider); + fragment.setArguments(arguments); + hideActionBarSubTitle(); + fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); + closeDrawer(); + }); } - private void setupSettingsListAdapter() { - settingsListAdapter = new DrawerSettingsAdapter(getLayoutInflater()); - if (getContext() == null) { - return; + private void initSwitchProviderEntry() { + if (isDefaultBitmask()) { + IconTextEntry switchProvider = drawerView.findViewById(R.id.switch_provider); + switchProvider.setVisibility(VISIBLE); + switchProvider.setOnClickListener(v -> + getActivity().startActivityForResult(new Intent(getActivity(), ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER)); } + } - Provider currentProvider = ProviderObservable.getInstance().getCurrentProvider(); - if (currentProvider.supportsPluggableTransports()) { - settingsListAdapter.addItem(getSwitchInstance(getContext(), - getString(R.string.nav_drawer_obfuscated_connection), - R.drawable.ic_bridge_36, - getUsePluggableTransports(getContext()), - PLUGGABLE_TRANSPORTS, - (buttonView, newStateIsChecked) -> onSwitchItemSelected(PLUGGABLE_TRANSPORTS, newStateIsChecked))); + private void initUseBridgesEntry() { + IconSwitchEntry useBridges = drawerView.findViewById(R.id.bridges_switch); + if (ProviderObservable.getInstance().getCurrentProvider().supportsPluggableTransports()) { + useBridges.setVisibility(VISIBLE); + useBridges.setChecked(getUsePluggableTransports(getContext())); + useBridges.setOnCheckedChangeListener((buttonView, isChecked) -> + usePluggableTransports(getContext(), isChecked)); + } else { + useBridges.setVisibility(GONE); } + } - settingsListAdapter.addItem(getSwitchInstance(getContext(), - getString(R.string.save_battery), - R.drawable.ic_battery_36, - getSaveBattery(getContext()), - BATTERY_SAVER, - (buttonView, newStateIsChecked) -> onSwitchItemSelected(BATTERY_SAVER, newStateIsChecked))); + private void initSaveBatteryEntry() { + saveBattery = drawerView.findViewById(R.id.battery_switch); + saveBattery.setChecked(getSaveBattery(getContext())); + saveBattery.setOnCheckedChangeListener(((buttonView, isChecked) -> { + if (isChecked) { + showExperimentalFeatureAlert(); + } else { + saveBattery(getContext(), false); + } + })); + } + + private void initAlwaysOnVpnEntry() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - settingsListAdapter.addItem(getSimpleTextInstance(getContext(), getString(R.string.always_on_vpn), R.drawable.ic_always_on_36, ALWAYS_ON)); - } - if (isDefaultBitmask()) { - settingsListAdapter.addItem(getSimpleTextInstance(getContext(), getString(switch_provider_menu_option), R.drawable.ic_switch_provider_36, SWITCH_PROVIDER)); + IconTextEntry alwaysOnVpn = drawerView.findViewById(R.id.always_on_vpn); + alwaysOnVpn.setVisibility(VISIBLE); + alwaysOnVpn.setOnClickListener((buttonView) -> { + closeDrawer(); + if (getShowAlwaysOnDialog(getContext())) { + showAlwaysOnDialog(); + } else { + Intent intent = new Intent("android.net.vpn.SETTINGS"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + }); } - settingsListAdapter.addItem(getSimpleTextInstance(getContext(), getString(log_fragment_title), R.drawable.ic_log_36, LOG)); + } + + private void initDonateEntry() { if (ENABLE_DONATION) { - settingsListAdapter.addItem(getSimpleTextInstance(getContext(), getString(donate_title), R.drawable.ic_donate_36, DONATE)); + IconTextEntry donate = drawerView.findViewById(R.id.donate); + donate.setVisibility(VISIBLE); + donate.setOnClickListener((buttonView) -> { + closeDrawer(); + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(DONATION_URL)); + startActivity(browserIntent); + + }); + } + } + + private void initLogEntry() { + IconTextEntry log = drawerView.findViewById(R.id.log); + FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager()); + log.setOnClickListener((buttonView) -> { + closeDrawer(); + Fragment fragment = new LogFragment(); + setActionBarTitle(log_fragment_title); + fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); + }); + + } + + private void initAboutEntry() { + IconTextEntry about = drawerView.findViewById(R.id.about); + FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager()); + about.setOnClickListener((buttonView) -> { + closeDrawer(); + Fragment fragment = new AboutFragment(); + setActionBarTitle(about_fragment_title); + fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); + }); + } + + private void closeDrawer() { + if (drawerLayout != null) { + drawerLayout.closeDrawer(fragmentContainerView); } - settingsListAdapter.addItem(getSimpleTextInstance(getContext(), getString(about_fragment_title), R.drawable.ic_about_36, ABOUT)); } private ActionBar setupActionBar() { @@ -337,16 +386,6 @@ public class NavigationDrawerFragment extends Fragment { }, TWO_SECONDS); } - private void selectItem(AdapterView list, int position) { - if (list != null) { - ((ListView) list).setItemChecked(position, true); - } - if (drawerLayout != null) { - drawerLayout.closeDrawer(fragmentContainerView); - } - onTextItemSelected(list, position); - } - @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); @@ -374,17 +413,11 @@ public class NavigationDrawerFragment extends Fragment { .setTitle(activity.getString(R.string.save_battery)) .setMessage(activity.getString(R.string.save_battery_message)) .setPositiveButton((android.R.string.yes), (dialog, which) -> { - DrawerSettingsItem item = settingsListAdapter.getDrawerItem(BATTERY_SAVER); - item.setChecked(true); - settingsListAdapter.notifyDataSetChanged(); - saveBattery(getContext(), item.isChecked()); + saveBattery(getContext(), true); }) - .setNegativeButton(activity.getString(android.R.string.no), (dialog, which) -> disableSwitch(BATTERY_SAVER)).setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - showEnableExperimentalFeature = false; - } - }).setOnCancelListener(dialog -> disableSwitch(BATTERY_SAVER)).show(); + .setNegativeButton(activity.getString(android.R.string.no), (dialog, which) -> saveBattery.setCheckedQuietly(false)) + .setOnDismissListener(dialog -> showEnableExperimentalFeature = false) + .setOnCancelListener(dialog -> saveBattery.setCheckedQuietly(false)).show(); } catch (IllegalStateException e) { e.printStackTrace(); } @@ -447,87 +480,6 @@ public class NavigationDrawerFragment extends Fragment { return ((AppCompatActivity) getActivity()).getSupportActionBar(); } - private void onSwitchItemSelected(int elementType, boolean newStateIsChecked) { - switch (elementType) { - case BATTERY_SAVER: - if (getSaveBattery(getContext()) == newStateIsChecked) { - //initial ui setup, ignore - return; - } - if (newStateIsChecked) { - showExperimentalFeatureAlert(); - } else { - saveBattery(getContext(), false); - disableSwitch(BATTERY_SAVER); - } - break; - case PLUGGABLE_TRANSPORTS: - if (getUsePluggableTransports(getContext()) == newStateIsChecked) { - //initial ui setup, ignore - return; - } - usePluggableTransports(getContext(), newStateIsChecked); - default: - break; - } - } - - private void disableSwitch(int elementType) { - DrawerSettingsItem item = settingsListAdapter.getDrawerItem(elementType); - item.setChecked(false); - settingsListAdapter.notifyDataSetChanged(); - } - - public void onTextItemSelected(AdapterView parent, int position) { - // update the main content by replacing fragments - FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager()); - Fragment fragment = null; - - if (parent == drawerAccountsListView) { - fragment = new EipFragment(); - Bundle arguments = new Bundle(); - Provider currentProvider = getSavedProviderFromSharedPreferences(preferences); - arguments.putParcelable(PROVIDER_KEY, currentProvider); - fragment.setArguments(arguments); - hideActionBarSubTitle(); - } else { - DrawerSettingsItem settingsItem = settingsListAdapter.getItem(position); - switch (settingsItem.getItemType()) { - case SWITCH_PROVIDER: - getActivity().startActivityForResult(new Intent(getActivity(), ProviderListActivity.class), REQUEST_CODE_SWITCH_PROVIDER); - break; - case LOG: - fragment = new LogFragment(); - setActionBarTitle(log_fragment_title); - break; - case ABOUT: - fragment = new AboutFragment(); - setActionBarTitle(about_fragment_title); - break; - case ALWAYS_ON: - if (getShowAlwaysOnDialog(getContext())) { - showAlwaysOnDialog(); - } else { - Intent intent = new Intent("android.net.vpn.SETTINGS"); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - } - break; - case DONATE: - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(DONATION_URL)); - startActivity(browserIntent); - break; - default: - break; - } - } - - if (fragment != null) { - fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG); - } - - } - private void setActionBarTitle(@StringRes int resId) { ActionBar actionBar = getActionBar(); if (actionBar != null) { @@ -542,22 +494,10 @@ public class NavigationDrawerFragment extends Fragment { } } - public void refresh() { - refreshAccountListAdapter(); - accountListAdapter.notifyDataSetChanged(); - drawerAccountsListView.setAdapter(accountListAdapter); - } - - private void refreshAccountListAdapter() { - accountListAdapter.clear(); - String providerName = getProviderName(preferences); - if (providerName == null) { - //TODO: ADD A header to the ListView containing a useful message. - //TODO 2: disable switchProvider - } else { - accountListAdapter.add(providerName); - } + Provider currentProvider = ProviderObservable.getInstance().getCurrentProvider(); + account.setText(currentProvider.getName()); + initUseBridgesEntry(); } } diff --git a/app/src/main/res/layout/f_drawer_main.xml b/app/src/main/res/layout/f_drawer_main.xml index b04d7b87..e4862ca8 100644 --- a/app/src/main/res/layout/f_drawer_main.xml +++ b/app/src/main/res/layout/f_drawer_main.xml @@ -1,70 +1,116 @@ - + android:focusable="true" + android:fillViewport="true" + > - - - - - - + android:layout_height="wrap_content" + android:orientation="vertical" + > - + + + + + + + - - + + - - + app:text="@string/nav_drawer_obfuscated_connection" + app:icon="@drawable/ic_bridge_36" + android:visibility="gone" + /> + + + + + + + + + - + - \ No newline at end of file + -- cgit v1.2.3 From a49be8cf197af87e68aae263d31b3448f8ce379a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 6 Sep 2019 23:43:24 +0200 Subject: update demo setup --- .../custom/assets/ptdemo.bitmask.eip-service.json | 34 +++++++--------------- app/src/custom/assets/ptdemo.bitmask.net.json | 6 ++-- app/src/custom/assets/ptdemo.bitmask.secrets.json | 4 +-- 3 files changed, 15 insertions(+), 29 deletions(-) (limited to 'app/src') diff --git a/app/src/custom/assets/ptdemo.bitmask.eip-service.json b/app/src/custom/assets/ptdemo.bitmask.eip-service.json index 65b84dd0..d804d032 100644 --- a/app/src/custom/assets/ptdemo.bitmask.eip-service.json +++ b/app/src/custom/assets/ptdemo.bitmask.eip-service.json @@ -19,45 +19,31 @@ "filter_dns": false, "limited": false, "transport": [ - { - "type": "openvpn", - "protocols": [ - "tcp" - ], - "ports": [ - "443" - ] + {"type": "openvpn", + "protocols": ["tcp"], + "ports": ["443"] }, - { - "type": "obfs4", - "protocols": [ - "tcp" - ], - "options": { - "cert": "gZlp9k6br2vn2MLnmjXpNh8D/CrR5wtackwZof/iICv1QzPwkkTUa+7JVOKtPiD0NFwCMw", - "iat-mode": "0" - }, - "ports": [ - "23042" - ] + {"type": "obfs4", + "protocols": ["tcp"], + "options": {"cert": "gZlp9k6br2vn2MLnmjXpNh8D/CrR5wtackwZof/iICv1QzPwkkTUa+7JVOKtPiD0NFwCMw", "iat-mode": "0"}, + "ports": ["23042"] } ] } } ], - "openvpn_configuration": { "auth": "SHA1", "cipher": "AES-256-CBC", "dev": "tun", "keepalive": "10 30", "key-direction": "1", - "nobind": true, - "persist-key": true, + "nobind": "True", + "persist-key": "True", "rcvbuf": "0", "sndbuf": "0", "tls-cipher": "DHE-RSA-AES128-SHA", - "tun-ipv6": true, + "tun-ipv6": "True", "verb": "3" } } \ No newline at end of file diff --git a/app/src/custom/assets/ptdemo.bitmask.net.json b/app/src/custom/assets/ptdemo.bitmask.net.json index 54b4d8fd..98afaa54 100644 --- a/app/src/custom/assets/ptdemo.bitmask.net.json +++ b/app/src/custom/assets/ptdemo.bitmask.net.json @@ -1,8 +1,8 @@ { - "api_uri": "https://api.demo.bitmask.net:4430", - "api_version": "1", + "api_uri": "https://leech.demo.bitmask.net:8000", + "api_version": "3", "ca_cert_fingerprint": "SHA256: 0f17c033115f6b76ff67871872303ff65034efe7dd1b910062ca323eb4da5c7e", - "ca_cert_uri": "https://demo.bitmask.net/ca.crt", + "ca_cert_uri": "https://leech.demo.bitmask.net:8000/ca.crt", "default_language": "en", "description": { "el": "demo.bitmask.net allows you to test the Bitmask application. User accounts may be periodically deleted.", diff --git a/app/src/custom/assets/ptdemo.bitmask.secrets.json b/app/src/custom/assets/ptdemo.bitmask.secrets.json index acf26365..85900ea3 100644 --- a/app/src/custom/assets/ptdemo.bitmask.secrets.json +++ b/app/src/custom/assets/ptdemo.bitmask.secrets.json @@ -1,5 +1,5 @@ { "ca_cert":"-----BEGIN CERTIFICATE-----\nMIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\nYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNVBAsME2h0dHBzOi8v\nYml0bWFzay5uZXQwHhcNMTIxMTA2MDAwMDAwWhcNMjIxMTA2MDAwMDAwWjBKMRgw\nFgYDVQQDDA9CaXRtYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNV\nBAsME2h0dHBzOi8vYml0bWFzay5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\nggIKAoICAQC1eV4YvayaU+maJbWrD4OHo3d7S1BtDlcvkIRS1Fw3iYDjsyDkZxai\ndHp4EUasfNQ+EVtXUvtk6170EmLco6Elg8SJBQ27trE6nielPRPCfX3fQzETRfvB\n7tNvGw4Jn2YKiYoMD79kkjgyZjkJ2r/bEHUSevmR09BRp86syHZerdNGpXYhcQ84\nCA1+V+603GFIHnrP+uQDdssW93rgDNYu+exT+Wj6STfnUkugyjmPRPjL7wh0tzy+\nznCeLl4xiV3g9sjPnc7r2EQKd5uaTe3j71sDPF92KRk0SSUndREz+B1+Dbe/RGk4\nMEqGFuOzrtsgEhPIX0hplhb0Tgz/rtug+yTT7oJjBa3u20AAOQ38/M99EfdeJvc4\nlPFF1XBBLh6X9UKF72an2NuANiX6XPySnJgZ7nZ09RiYZqVwu/qt3DfvLfhboq+0\nbQvLUPXrVDr70onv5UDjpmEA/cLmaIqqrduuTkFZOym65/PfAPvpGnt7crQj/Ibl\nDEDYZQmP7AS+6zBjoOzNjUGE5r40zWAR1RSi7zliXTu+yfsjXUIhUAWmYR6J3KxB\nlfsiHBQ+8dn9kC3YrUexWoOqBiqJOAJzZh5Y1tqgzfh+2nmHSB2dsQRs7rDRRlyy\nYMbkpzL9ZsOUO2eTP1mmar6YjCN+rggYjRrX71K2SpBG6b1zZxOG+wIDAQABo2Aw\nXjAdBgNVHQ4EFgQUuYGDLL2sswnYpHHvProt1JU+D48wDgYDVR0PAQH/BAQDAgIE\nMAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUuYGDLL2sswnYpHHvProt1JU+D48w\nDQYJKoZIhvcNAQENBQADggIBADeG67vaFcbITGpi51264kHPYPEWaXUa5XYbtmBl\ncXYyB6hY5hv/YNuVGJ1gWsDmdeXEyj0j2icGQjYdHRfwhrbEri+h1EZOm1cSBDuY\nk/P5+ctHyOXx8IE79DBsZ6IL61UKIaKhqZBfLGYcWu17DVV6+LT+AKtHhOrv3TSj\nRnAcKnCbKqXLhUPXpK0eTjPYS2zQGQGIhIy9sQXVXJJJsGrPgMxna1Xw2JikBOCG\nhtD/JKwt6xBmNwktH0GI/LVtVgSp82Clbn9C4eZN9E5YbVYjLkIEDhpByeC71QhX\nEIQ0ZR56bFuJA/CwValBqV/G9gscTPQqd+iETp8yrFpAVHOW+YzSFbxjTEkBte1J\naF0vmbqdMAWLk+LEFPQRptZh0B88igtx6tV5oVd+p5IVRM49poLhuPNJGPvMj99l\nmlZ4+AeRUnbOOeAEuvpLJbel4rhwFzmUiGoeTVoPZyMevWcVFq6BMkS+jRR2w0jK\nG6b0v5XDHlcFYPOgUrtsOBFJVwbutLvxdk6q37kIFnWCd8L3kmES5q4wjyFK47Co\nJa8zlx64jmMZPg/t3wWqkZgXZ14qnbyG5/lGsj5CwVtfDljrhN0oCWK1FZaUmW3d\n69db12/g4f6phldhxiWuGC/W6fCW5kre7nmhshcltqAJJuU47iX+DarBFiIj816e\nyV8e\n-----END CERTIFICATE-----", - "cert":"-----BEGIN CERTIFICATE-----\nMIIEbDCCAlSgAwIBAgIRALod300UE8xiHL4EEoIhcXowDQYJKoZIhvcNAQELBQAw\nZjEQMA4GA1UECgwHQml0bWFzazEcMBoGA1UECwwTaHR0cHM6Ly9iaXRtYXNrLm5l\ndDE0MDIGA1UEAwwrQml0bWFzayBSb290IENBIChjbGllbnQgY2VydGlmaWNhdGVz\nIG9ubHkhKTAeFw0xOTA3MjMyMjQ5MzZaFw0xOTA4MjcyMjQ5MzZaMBQxEjAQBgNV\nBAMTCVVOTElNSVRFRDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMDS\nujyEVdUUFhGDseh4Jb7HtSgAhgCtEcZwqtcZdqSmt8grSQIelb0YsrX+1/ilffPp\nX3tloKCiv73Ur9fPFyFUgdDuu36aeQTvznHYNZAKbuoDDGfV6zswxSKh7YjMK8IB\nnM290ROl2FZNekh6S0to3pVMSOB5h8nulWB3D/9BeW2cB7XaS88jCZECE+edzw5u\nQ7nhW2F9ndr+0CL6ZLgdTrEOTnyZqTj8YVR4Gq82x3Z+MZNVNuRJz+PK+jpdPIBX\n8+Bxli2JkZmEhIWLA67RCAgmxTUngNb5NUnPtiip+8ABry7zSZX2wFERZkdXpI+v\nUEkYOTyXb4X+PaYZ9vsCAwEAAaNnMGUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM\nMAoGCCsGAQUFBwMCMB0GA1UdDgQWBBSopKH/oCH/thCQqS9YTosheHnCBDAfBgNV\nHSMEGDAWgBSHfhO27FhbFFmofb2bj72ezvmibDANBgkqhkiG9w0BAQsFAAOCAgEA\ngp4Z9U9+l0j+J4yCggyxuGysIrnkS/v2QFpEdqc4uILQjj8usfZBqVhNo+GxFqPx\nCwBh8usYvX1Sxq0LfVTcT/cUXhkMLRvCi+IHWaR011x4Q8N1Ak7rC8Q0O5GnxNd7\n0pfaITAxO1T3uMxa2m3LmKkWlCJNrKh9a5wPd96eAaXCoc+erqddqmQPKXEgIGM3\ng15vPumGvIZUhFB5g8wo6UbFyy8fCWBXUYn72IaMzIBBu4Z+eO1+fokeIxLY78iV\n+WbOld6dp6GMNxG8cxzKTjzcAOmCCdwJk9p1ARS+yrI6Y3Sat1NTc6+W8mM2pSj0\neXsMJuImQotver/rDqpgy9IhvAWRgI8smBXHWrjLNZzdBxF6KaN6z8zm2gXW8EKG\nI/aOBCsokrkQt8xcH4QQ0UjgANhG5ZasNGo8L3pkUrKqPUhtCZJlA2fVtA0LVG0o\naJDT76OxTTVP8F4EHGJRsPo+9swYXGiqDuoOhFXbtX/siU2G9WHL2bLZSGeu9EyP\nzMYFEXh2IuXP/wDN8++QfYLBqjLnj9g0mTS7anEbYVbiGuu3rRLJYqw3LQ+XuH+A\naF6GRT+bofF/Opk57moWwEjtWt40KIOhMYv3+T1cNzlLcrgNEvMwPHcUK7/6ukzv\nF8vICQK6i+exElrH72yWjvckZQlvHjo4bOYIJhZoDtw=\n-----END CERTIFICATE-----", - "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAwNK6PIRV1RQWEYOx6Hglvse1KACGAK0RxnCq1xl2pKa3yCtJ\nAh6VvRiytf7X+KV98+lfe2WgoKK/vdSv188XIVSB0O67fpp5BO/Ocdg1kApu6gMM\nZ9XrOzDFIqHtiMwrwgGczb3RE6XYVk16SHpLS2jelUxI4HmHye6VYHcP/0F5bZwH\ntdpLzyMJkQIT553PDm5DueFbYX2d2v7QIvpkuB1OsQ5OfJmpOPxhVHgarzbHdn4x\nk1U25EnP48r6Ol08gFfz4HGWLYmRmYSEhYsDrtEICCbFNSeA1vk1Sc+2KKn7wAGv\nLvNJlfbAURFmR1ekj69QSRg5PJdvhf49phn2+wIDAQABAoIBAHrvHutsV6jE6Jj8\nBJY425+5hYbeZpDRxq5ksJb41gp9fFhzOFXQmBj6QR4FPz54jEfQtx5eGb2wZVyq\n1/1YO9/1F9rUCdfatmNuXIl6lhOigzpQ/TzKRvHy0wyUfnOj8BX9nzIQ3daP+tBz\nDw5cYdrPHnHDNAdhlDArGzNoVVugEDyNb9rR9jSX2Se5ucm1fZkGK8FUTIdDNjr/\nVQyAmAOGwi9CLtMYm0O5xnS/TfMcUAUYfu9ttjL225dAWR9MjYcpODYo3Yzev+dM\nTZ8ka3+3eURXpl08Tl8TPE98jbDqSmm7D0oVrj5jwq/QbAGvAtF1ljJUtHJ52YJ1\nIPGUyoECgYEA5xUowRbje17aXlq9sne4r+f5KqjKDDzCHSwTwFWtfZR60a10uEvI\nRb1CXdEK8L0M7JVXV4J6pOc229/p23O74j5XmaDi/KBce71TGPTBarY/kKyv0xHe\nL59gRcKCfkCWuRFCbKuhGBElEak8tGaGplqljhjUSk+3WC88gLDUS8ECgYEA1Z1y\nfsjcZqkXk1aM6exZUPu0kupU/U2ZtCXcvi40nmyrLyWzMlOljGivGcHGcNAtDv4L\nBGQQt0XP6lo1KqoLT+e1/PbIBEcHCFstgv+LCCrIz4GLNZPHNw8jR09rSC7N4KVj\ncSsbMkjE9Mrxgr5MH0JGnnzVcTf9P8fX1Ejy4bsCgYEAyo6ynacZmmAH3GOAGvt0\nycT2lZ1FFrr/kKC9Y3/2xrirfDamtJHBKNiAX0pJY8LjnFJAMHYwWXJPlSbOkE3/\nqI7rLMBpl/Zdex32xE5vaMH+MCwfJ05nS6lRs3SP/GlTdUAa0LUVTcphivylOKES\ncKnOqyM6mzULSuKFD21xekECgYEAs9wvBFuBYBst04wDeA7eIVbd8vnFd8Y4Dbv3\nglYLTf03oan/mPdfI7sc+/XxbRmLZt02T4slm/r3Fl6/911Xyv7Rd94eCaP4YuvK\nhUs/ODA2BqoPmZwFF/HyBV/0d8GY7Xa0JRxjeNJWq7qY4TnzhDpclaOMYBkBbguJ\nSZ/miXMCgYAVV8THc0ZnjHJEhQZZHyonBA56n6wp8oj7PpSuBOy+oi54Sxds7wJm\ndLOFWeW1a6mlecga3ooIeyd9aa/mb4EXToUkqbSqmcI1ob86mVu9NM2MOxIcsxYR\nu1u8/52sxMv2umwuviWtn1E/vIuRIMKzo077KfZkHq6yiuIrNO+Ruw==\n-----END RSA PRIVATE KEY-----" + "cert":"-----BEGIN CERTIFICATE-----\nMIIEbDCCAlSgAwIBAgIRAJ079G+cghukAsL/LV5v4c0wDQYJKoZIhvcNAQELBQAw\nZjEQMA4GA1UECgwHQml0bWFzazEcMBoGA1UECwwTaHR0cHM6Ly9iaXRtYXNrLm5l\ndDE0MDIGA1UEAwwrQml0bWFzayBSb290IENBIChjbGllbnQgY2VydGlmaWNhdGVz\nIG9ubHkhKTAeFw0xOTA4MzAyMTI5MjlaFw0xOTEwMDQyMTI5MjlaMBQxEjAQBgNV\nBAMTCVVOTElNSVRFRDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIy\nF+9n1gvkN3iHO7+wmED6WNhx23/XgYGhP8HrUsI1tu61gPEft/eUfo9yA2zOdZoe\nM3xw8Czj3U2gkpFOrq3VBzyOGeNGGD/yfuwO8/vY9kkubq/Um4S10lznPI1qjktB\nVuY3EJl95lAXmFmYE/ilpPSrRNoi1s4nm08rrW9DOrgEFePAXcz0MkNEMxLxniCo\n85lf0rtjmEJGBibQCrNS4c0jYxOJePXJRX+xfIy6RfRdNesCMglf8uTaRbmx7Nl6\n9XzjAqfOucLhopcSqs8yY87l8M81d25hFHtH1uY0iXxpSbMbTaKSL4QBHRnOUXYs\nAkF5PNqRnV2EQ4cTzIMCAwEAAaNnMGUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM\nMAoGCCsGAQUFBwMCMB0GA1UdDgQWBBTViW4hFR4M7hIHxgXq0DRRzMAatDAfBgNV\nHSMEGDAWgBSHfhO27FhbFFmofb2bj72ezvmibDANBgkqhkiG9w0BAQsFAAOCAgEA\njyXlQ0ltw1B3W0hX+Nf/R7ODdgz4pPL5ZlM0LdOQzyLCGS2Z5tlDT+veaF0dzGAF\nZwkdd93T/Hr0CXnN8eC/YYOv8OKwNXskYt+44tnbS8aRh6rJM/zAHpgcYBaD5hRp\nwidn30Q8ypsm+ge5460eFBXHVo1s+B2tQbmVFy4yZ74hWMt51csGutppQpJ6qK6b\nFYI+vApzCSHRDfFr6oly5pdiLsWult+yJ7S4u2OuvM/BNyfuhB39s+QsAa5ocZbk\njX42puhVAUv717dzTWCeJporMPWGG8fkylXwwIfTpys5pVZtQMdHZmhsaud3sLFe\nyomcWfMpKozCvbdLDn9siLjA76TU8bkCGqNVXZHaVRiConX7yLA7LPpX9+E9uqe1\nEtZLeIir4B0oUXKHqP/8qRGANLH1KaSrAdTWbTUHOCcgjxN3iVYYIg23Ns1xLocK\nfBaUrgxa6KYh+bMtwi5/WDEkjqUv3wPS59JZiHpU2WS0jmgJ0ou16wMzXhN3xHNd\nmScW6cwWKoeSjC3ru1TxB35mxNG32WXZUf6CzYNnCi2gJjYbDvWc75XT9CvNwpAJ\nJsU35MS+uVUPtRK2mX6qg9Qxgjr/SfBHio94lfelUt0QnS2uIoeKpaUxFX1ovbKq\nyhegtT3txnpgaC2zk4t7hl5TdBQ5XN6/QMiOWg37N6s=\n-----END CERTIFICATE-----", + "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAwjIX72fWC+Q3eIc7v7CYQPpY2HHbf9eBgaE/wetSwjW27rWA\n8R+395R+j3IDbM51mh4zfHDwLOPdTaCSkU6urdUHPI4Z40YYP/J+7A7z+9j2SS5u\nr9SbhLXSXOc8jWqOS0FW5jcQmX3mUBeYWZgT+KWk9KtE2iLWziebTyutb0M6uAQV\n48BdzPQyQ0QzEvGeIKjzmV/Su2OYQkYGJtAKs1LhzSNjE4l49clFf7F8jLpF9F01\n6wIyCV/y5NpFubHs2Xr1fOMCp865wuGilxKqzzJjzuXwzzV3bmEUe0fW5jSJfGlJ\nsxtNopIvhAEdGc5RdiwCQXk82pGdXYRDhxPMgwIDAQABAoIBAQCWdat30RLVic+0\nscqIPbHpfk5B/Q1dIsLzhdTZUZOAZ4/BqZ0qtTGbQFFCoMqojdouO8IWY4aisTWw\nxH1q2fSbOJdvwoWqQo/dU+wkx30gHzzK/I/D6c1I6HsBgiO3SdzPz+MdYYKZ+iLs\n4SsoF505pFWHP/+LpzyY47UAhU3OCoY5xE48Z5OIU/y66zqpiG9ABiYmgb8lYUlc\nzk/EujRZ8G1Q5yC9KSt8SpJNLl3xQvA49BYD1IHSMfICAZjnH0HZ4vx1aOROdyfX\nnq4o7fGjuFJHHa85rf0XxpzhpHPL26oA51Ba0Gh/HxREfmK0gFaSNeUS7eY4HaEl\nHXZesvGRAoGBAOEAiqmPP0RY75Zx1doKxswaZVk8UAI2SYE8wLhGQtGuzqxyEkwH\nXFiKe3FQALiY7sexee5RFySR5tL1ZYlkB7i26jECigQzltAtxBrmx47tnO5g4PPI\nL4xomVE6d65OLW30/TG6FX/CHrJAYKIOteTsCFA9BjBntvTQvMQAJewLAoGBANzz\nDxWpFsvnKWRrvwQunUrPYO3s9MNFE2ak1/gjfBnS/5oBcGY0gUIrsr/qQOP6kQHx\n21gjZsLq0oHW57dQhs+288YS+hOBkP3pW9X8y38sViu9H4qCbn5AByxdhMNzooHQ\n9AFVx7rU7t8o+8YdNwLmKtuut1tzhoML3b/jU3RpAoGAU7xl3nCnNQJ8N9spoTn9\nfhwct7cQd6JIfMZlWq8bUvnhhJ/3W0AqB/GRuzvw6MJRqxPLsvuOx1ddNgmJvjXy\nAbZhNdgiESo56EQABZr5jaG0k6qOTWuk9nY/CNHflIkXsyJH0GfWdHOEBQacb/NV\nklqdRW9QjFcs6bN9bNw5QL0CgYBRiH/whk0bQVpM7FW4vVrd2Fj0c5R+2mamYf4w\nWyfYf7xCoHVRwd5RBL8ZguAfQL9x8EX46FdrZiv4Lc2kH9sfm2uplCckO5O9nvd8\np6SQcVP7H/cbrbYIcKg0/u2XEnzNWsYwF+90Sk87mmwOV4mNUFJQbtDKtn7UrPRP\ncxvAwQKBgD+wKwZWM/yEBaJKHA6XLbKlTrb27bKDBNTt8Pk8BK0uYcZLryIQtZY5\nokyJniA9rv38R5URRAIRwXXDxxIumuWk69CY92dYA5y1tm0ooPG8OFEbSWTBIh74\n3dKEnhNvHVpNQkUd67LlfWsS51YbMCpwqyxI9YPtRwWMGho8R+Ty\n-----END RSA PRIVATE KEY-----" } \ No newline at end of file -- cgit v1.2.3 From 9044c3fdc13f02b7c21bb181d769fadb71924b75 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 19 Sep 2019 22:41:30 +0200 Subject: add subtitles to navigation drawer items - better explanation for PT --- .../se/leap/bitmaskclient/views/IconSwitchEntry.java | 8 ++++++++ .../se/leap/bitmaskclient/views/IconTextEntry.java | 8 ++++++++ .../main/res/layout-xlarge/v_icon_text_list_item.xml | 19 +++++++++++++++++++ app/src/main/res/layout-xlarge/v_switch_list_item.xml | 19 +++++++++++++++++++ app/src/main/res/layout/f_drawer_main.xml | 2 ++ app/src/main/res/layout/v_icon_text_list_item.xml | 19 +++++++++++++++++++ app/src/main/res/layout/v_switch_list_item.xml | 19 +++++++++++++++++++ app/src/main/res/values/attrs.xml | 3 +++ app/src/main/res/values/strings.xml | 2 ++ 9 files changed, 99 insertions(+) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java b/app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java index 82e02a6e..02347b05 100644 --- a/app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java +++ b/app/src/main/java/se/leap/bitmaskclient/views/IconSwitchEntry.java @@ -21,6 +21,7 @@ import se.leap.bitmaskclient.R; public class IconSwitchEntry extends LinearLayout { private TextView textView; + private TextView subtitleView; private ImageView iconView; private SwitchCompat switchView; private CompoundButton.OnCheckedChangeListener checkedChangeListener; @@ -51,6 +52,7 @@ public class IconSwitchEntry extends LinearLayout { .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View rootview = inflater.inflate(R.layout.v_switch_list_item, this, true); textView = rootview.findViewById(android.R.id.text1); + subtitleView = rootview.findViewById(R.id.subtitle); iconView = rootview.findViewById(R.id.material_icon); switchView = rootview.findViewById(R.id.option_switch); @@ -62,6 +64,12 @@ public class IconSwitchEntry extends LinearLayout { textView.setText(entryText); } + String subtitle = typedArray.getString(R.styleable.IconTextEntry_subtitle); + if (subtitle != null) { + subtitleView.setText(subtitle); + subtitleView.setVisibility(VISIBLE); + } + Drawable drawable = typedArray.getDrawable(R.styleable.IconTextEntry_icon); if (drawable != null) { iconView.setImageDrawable(drawable); diff --git a/app/src/main/java/se/leap/bitmaskclient/views/IconTextEntry.java b/app/src/main/java/se/leap/bitmaskclient/views/IconTextEntry.java index 5689f429..0e86f506 100644 --- a/app/src/main/java/se/leap/bitmaskclient/views/IconTextEntry.java +++ b/app/src/main/java/se/leap/bitmaskclient/views/IconTextEntry.java @@ -21,6 +21,7 @@ public class IconTextEntry extends LinearLayout { private TextView textView; private ImageView iconView; + private TextView subtitleView; public IconTextEntry(Context context) { super(context); @@ -48,6 +49,7 @@ public class IconTextEntry extends LinearLayout { .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View rootview = inflater.inflate(R.layout.v_icon_text_list_item, this, true); textView = rootview.findViewById(android.R.id.text1); + subtitleView = rootview.findViewById(R.id.subtitle); iconView = rootview.findViewById(R.id.material_icon); if (attrs != null) { @@ -58,6 +60,12 @@ public class IconTextEntry extends LinearLayout { textView.setText(entryText); } + String subtitle = typedArray.getString(R.styleable.IconTextEntry_subtitle); + if (subtitle != null) { + subtitleView.setText(subtitle); + subtitleView.setVisibility(VISIBLE); + } + Drawable drawable = typedArray.getDrawable(R.styleable.IconTextEntry_icon); if (drawable != null) { iconView.setImageDrawable(drawable); diff --git a/app/src/main/res/layout-xlarge/v_icon_text_list_item.xml b/app/src/main/res/layout-xlarge/v_icon_text_list_item.xml index 7ecd32a9..798b47e3 100644 --- a/app/src/main/res/layout-xlarge/v_icon_text_list_item.xml +++ b/app/src/main/res/layout-xlarge/v_icon_text_list_item.xml @@ -29,6 +29,25 @@ tools:text="TEST" android:layout_toEndOf="@id/material_icon" android:layout_toRightOf="@+id/material_icon" + android:layout_above="@+id/subtitle" + /> + + + + @@ -81,6 +82,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" app:text="@string/always_on_vpn" + app:subtitle="@string/subtitle_always_on_vpn" app:icon="@drawable/ic_always_on_36" android:visibility="gone" /> diff --git a/app/src/main/res/layout/v_icon_text_list_item.xml b/app/src/main/res/layout/v_icon_text_list_item.xml index d34baeb6..64cc474a 100644 --- a/app/src/main/res/layout/v_icon_text_list_item.xml +++ b/app/src/main/res/layout/v_icon_text_list_item.xml @@ -28,6 +28,25 @@ tools:text="TEST" android:layout_toEndOf="@id/material_icon" android:layout_toRightOf="@+id/material_icon" + android:layout_above="@+id/subtitle" + /> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 472a8549..5ae52ea9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -102,6 +102,7 @@ Save battery Background data connections will hibernate when your phone is inactive. Always-on VPN + Open Android System Settings Do not show again To enable always-on VPN in Android VPN Settings click on the configure icon [img src] and turn the switch on. To protect your privacy optimally, you should also activate the option \"Block connections without VPN\". @@ -113,4 +114,5 @@ Using an obfuscated connection. Trying an obfuscated connection. Using Bridges + Circumvent VPN filtering -- cgit v1.2.3 From 67a2040e96048e164b592fab4b0e8f123a7dd68f Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 20 Sep 2019 00:07:44 +0200 Subject: add supportsPluggableTransports() to Provider class including Tests --- .../main/java/se/leap/bitmaskclient/Provider.java | 24 ++++++++++++++++++++-- .../testutils/TestSetupHelper.java | 22 +++++++++++++------- .../java/se/leap/bitmaskclient/ProviderTest.java | 21 +++++++++++++++++++ .../bitmaskclient/eip/ProviderApiManagerTest.java | 4 ++-- 4 files changed, 60 insertions(+), 11 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index 561453af..067f9b2e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -21,6 +21,7 @@ import android.os.Parcelable; import com.google.gson.Gson; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -28,8 +29,13 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.Locale; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static se.leap.bitmaskclient.Constants.CAPABILITIES; +import static se.leap.bitmaskclient.Constants.GATEWAYS; import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOWED_REGISTERED; import static se.leap.bitmaskclient.Constants.PROVIDER_ALLOW_ANONYMOUS; +import static se.leap.bitmaskclient.Constants.TRANSPORT; +import static se.leap.bitmaskclient.Constants.TYPE; import static se.leap.bitmaskclient.ProviderAPI.ERRORS; /** @@ -119,9 +125,23 @@ public final class Provider implements Parcelable { hasPrivateKey(); } - //TODO: implement me! public boolean supportsPluggableTransports() { - return true; + try { + JSONArray gatewayJsons = eipServiceJson.getJSONArray(GATEWAYS); + for (int i = 0; i < gatewayJsons.length(); i++) { + JSONArray transports = gatewayJsons.getJSONObject(i). + getJSONObject(CAPABILITIES). + getJSONArray(TRANSPORT); + for (int j = 0; j < transports.length(); j++) { + if (OBFS4.toString().equals(transports.getJSONObject(j).getString(TYPE))) { + return true; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; } public void setMainUrl(URL url) { diff --git a/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java b/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java index 02a575ea..669abc84 100644 --- a/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java +++ b/app/src/sharedTest/java/se.leap.bitmaskclient/testutils/TestSetupHelper.java @@ -18,6 +18,7 @@ package se.leap.bitmaskclient.testutils; import org.json.JSONException; +import org.json.JSONObject; import java.io.BufferedReader; import java.io.IOException; @@ -50,25 +51,32 @@ public class TestSetupHelper { public static Provider getConfiguredProvider() throws IOException, JSONException { - return getProvider(null, null, null); + return getProvider(null, null, null, null); } - public static Provider getProvider(String domain, String caCertFile, String jsonFile) { + public static Provider getProvider(String domain, String caCertFile, String providerJson, String eipServiceJson) { if (domain == null) domain = "https://riseup.net"; if (caCertFile == null) caCertFile = "riseup.net.pem"; - if (jsonFile == null) - jsonFile = "riseup.net.json"; + if (providerJson == null) + providerJson = "riseup.net.json"; + if (eipServiceJson == null) { + eipServiceJson = "riseup.service.json"; + } try { - return new Provider( + Provider p = new Provider( new URL(domain), getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(caCertFile)), - getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(jsonFile)) + getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(providerJson)) ); - } catch (IOException e) { + JSONObject eipServiceJsonObject = new JSONObject( + getInputAsString(TestSetupHelper.class.getClassLoader().getResourceAsStream(eipServiceJson))); + p.setEipServiceJson(eipServiceJsonObject); + return p; + } catch (IOException | JSONException e) { e.printStackTrace(); } return null; diff --git a/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java index a141edec..c4b8f65e 100644 --- a/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/ProviderTest.java @@ -46,4 +46,25 @@ public class ProviderTest { assertTrue(defaultProviders.contains(p2)); assertFalse(defaultProviders.contains(p3)); } + + @Test + public void testIsPluggableTransportsSupported_Obfs4_returnsTrue() throws Exception { + Provider p1 = TestSetupHelper.getProvider( + "https://pt.demo.bitmask.net", + null, + null, + "ptdemo.bitmask.eip-service.json"); + assertTrue(p1.supportsPluggableTransports()); + } + + @Test + public void testIsPluggableTransportsSupported_noObfs4_returnsFalse() throws Exception { + Provider p1 = TestSetupHelper.getProvider( + null, + null, + null, + "eip-service-two-gateways.json"); + assertFalse(p1.supportsPluggableTransports()); + } + } 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 3070fc0b..1a2ce49d 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java @@ -267,7 +267,7 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_preseededProviderAndCA_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { - Provider provider = getProvider(null ,"outdated_cert.pem", null); + Provider provider = getProvider(null ,"outdated_cert.pem", null, null); mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); @@ -384,7 +384,7 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_outdatedPreseededProviderAndCA_successfulConfiguration() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { - Provider provider = getProvider(null, null, "riseup_net_outdated_config.json"); + Provider provider = getProvider(null, null, "riseup_net_outdated_config.json", null); mockFingerprintForCertificate(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); mockProviderApiConnector(NO_ERROR); -- cgit v1.2.3 From e52d759c635a25969079503991e825b3f373cbcc Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 20 Sep 2019 00:26:27 +0200 Subject: restart vpn after pluggableTransports was selected or deselected --- .../leap/bitmaskclient/drawer/NavigationDrawerFragment.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java index 380b765e..7d97dfbb 100644 --- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java @@ -44,6 +44,7 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.EipFragment; import se.leap.bitmaskclient.FragmentManagerEnhanced; import se.leap.bitmaskclient.MainActivity; @@ -51,6 +52,7 @@ import se.leap.bitmaskclient.Provider; import se.leap.bitmaskclient.ProviderListActivity; import se.leap.bitmaskclient.ProviderObservable; import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.fragments.AboutFragment; import se.leap.bitmaskclient.fragments.AlwaysOnDialog; import se.leap.bitmaskclient.fragments.LogFragment; @@ -263,8 +265,15 @@ public class NavigationDrawerFragment extends Fragment { if (ProviderObservable.getInstance().getCurrentProvider().supportsPluggableTransports()) { useBridges.setVisibility(VISIBLE); useBridges.setChecked(getUsePluggableTransports(getContext())); - useBridges.setOnCheckedChangeListener((buttonView, isChecked) -> - usePluggableTransports(getContext(), isChecked)); + useBridges.setOnCheckedChangeListener((buttonView, isChecked) -> { + usePluggableTransports(getContext(), isChecked); + if (VpnStatus.isVPNActive()) { + EipCommand.startVPN(getContext(), false); + closeDrawerWithDelay(); + } + }); + + } else { useBridges.setVisibility(GONE); } -- cgit v1.2.3 From 91877ac8ed64927d14c0762cd4402e5ed736fab9 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 27 Sep 2019 12:17:52 +0200 Subject: fix flickering when restarting the vpn --- app/src/main/AndroidManifest.xml | 4 ++-- .../java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java | 4 ++-- app/src/main/res/values/themes.xml | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'app/src') diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a00582cc..9a2b1e43 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -62,10 +62,10 @@ + android:theme="@style/invisibleTheme" /> + android:theme="@style/invisibleTheme" /> { usePluggableTransports(getContext(), isChecked); if (VpnStatus.isVPNActive()) { - EipCommand.startVPN(getContext(), false); - closeDrawerWithDelay(); + EipCommand.startVPN(getContext(), true); + closeDrawer(); } }); diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 51a8ea0e..7e98ccf4 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -20,4 +20,8 @@ @drawable/splash_page + + -- cgit v1.2.3 From eebba26668588d5e644441b0dbcc04eb9f9f3eac Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 27 Sep 2019 16:25:13 +0200 Subject: fix error handling for failing fetch of eip-service.json in production flavor and minor refactorings --- .../se/leap/bitmaskclient/ProviderApiManager.java | 21 ++++++++------------- .../leap/bitmaskclient/ProviderApiManagerBase.java | 7 +++++++ .../se/leap/bitmaskclient/ProviderApiManager.java | 22 ++++++++++------------ 3 files changed, 25 insertions(+), 25 deletions(-) (limited to 'app/src') diff --git a/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java index 1190d382..e79946bf 100644 --- a/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java +++ b/app/src/insecure/java/se/leap/bitmaskclient/ProviderApiManager.java @@ -135,8 +135,8 @@ public class ProviderApiManager extends ProviderApiManagerBase { private Bundle getAndSetProviderJson(Provider provider, boolean dangerOn) { Bundle result = new Bundle(); - JSONObject providerDefinition = provider.getDefinition(); String caCert = provider.getCaCert(); + JSONObject providerDefinition = provider.getDefinition(); String providerMainUrl = provider.getMainUrlString(); String providerDotJsonString; @@ -161,10 +161,9 @@ public class ProviderApiManager extends ProviderApiManagerBase { result.putBoolean(BROADCAST_RESULT_KEY, true); } catch (JSONException e) { - String reason_to_fail = pickErrorMessage(providerDotJsonString); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(BROADCAST_RESULT_KEY, false); + setErrorResult(result, providerDotJsonString); } + //TODO: check why the following line is not in production result.putParcelable(PROVIDER_KEY, provider); return result; } @@ -185,18 +184,15 @@ public class ProviderApiManager extends ProviderApiManagerBase { JSONObject eipServiceJson = new JSONObject(eipServiceJsonString); if (eipServiceJson.has(ERRORS)) { - String reasonToFail = pickErrorMessage(eipServiceJsonString); - result.putString(ERRORS, reasonToFail); - result.putBoolean(BROADCAST_RESULT_KEY, false); + setErrorResult(result, eipServiceJsonString); } else{ provider.setEipServiceJson(eipServiceJson); result.putBoolean(BROADCAST_RESULT_KEY, true); } } catch (NullPointerException | JSONException e) { - String reasonToFail = pickErrorMessage(eipServiceJsonString); - result.putString(ERRORS, reasonToFail); - result.putBoolean(BROADCAST_RESULT_KEY, false); + setErrorResult(result, eipServiceJsonString); } + //TODO: check why the following line is not in production result.putParcelable(PROVIDER_KEY, provider); return result; } @@ -218,9 +214,7 @@ public class ProviderApiManager extends ProviderApiManagerBase { // probably 204 setErrorResult(result, error_io_exception_user_message, null); } else { - String reasonToFail = pickErrorMessage(certString); - result.putString(ERRORS, reasonToFail); - result.putBoolean(BROADCAST_RESULT_KEY, false); + setErrorResult(result, certString); return result; } } @@ -229,6 +223,7 @@ public class ProviderApiManager extends ProviderApiManagerBase { setErrorResult(result, downloading_vpn_certificate_failed, null); e.printStackTrace(); } + //TODO: check why the following line is not in production result.putParcelable(PROVIDER_KEY, provider); return result; } diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index 37adbe93..26f1691c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -750,6 +750,13 @@ public abstract class ProviderApiManagerBase { return result; } + protected Bundle setErrorResult(Bundle result, String stringJsonErrorMessage) { + String reasonToFail = pickErrorMessage(stringJsonErrorMessage); + result.putString(ERRORS, reasonToFail); + result.putBoolean(BROADCAST_RESULT_KEY, false); + return result; + } + Bundle setErrorResult(Bundle result, int errorMessageId, String errorId) { JSONObject errorJson = new JSONObject(); String errorMessage = getProviderFormattedString(resources, errorMessageId); diff --git a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java index 658e8e15..10582cf3 100644 --- a/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java +++ b/app/src/production/java/se/leap/bitmaskclient/ProviderApiManager.java @@ -141,6 +141,7 @@ public class ProviderApiManager extends ProviderApiManagerBase { } try { JSONObject providerJson = new JSONObject(providerDotJsonString); + if (provider.define(providerJson)) { result.putBoolean(BROADCAST_RESULT_KEY, true); } else { @@ -148,9 +149,7 @@ public class ProviderApiManager extends ProviderApiManagerBase { } } catch (JSONException e) { - String reason_to_fail = pickErrorMessage(providerDotJsonString); - result.putString(ERRORS, reason_to_fail); - result.putBoolean(BROADCAST_RESULT_KEY, false); + setErrorResult(result, providerDotJsonString); } return result; } @@ -171,13 +170,14 @@ public class ProviderApiManager extends ProviderApiManagerBase { if (BuildConfig.DEBUG) { VpnStatus.logDebug("EIP SERVICE JSON: " + eipServiceJsonString); } - provider.setEipServiceJson(eipServiceJson); - - result.putBoolean(BROADCAST_RESULT_KEY, true); + if (eipServiceJson.has(ERRORS)) { + setErrorResult(result, eipServiceJsonString); + } else { + provider.setEipServiceJson(eipServiceJson); + result.putBoolean(BROADCAST_RESULT_KEY, true); + } } catch (NullPointerException | JSONException e) { - String reasonToFail = pickErrorMessage(eipServiceJsonString); - result.putString(ERRORS, reasonToFail); - result.putBoolean(BROADCAST_RESULT_KEY, false); + setErrorResult(result, eipServiceJsonString); } return result; } @@ -202,9 +202,7 @@ public class ProviderApiManager extends ProviderApiManagerBase { // probably 204 setErrorResult(result, error_io_exception_user_message, null); } else { - String reasonToFail = pickErrorMessage(certString); - result.putString(ERRORS, reasonToFail); - result.putBoolean(BROADCAST_RESULT_KEY, false); + setErrorResult(result, certString); return result; } } -- cgit v1.2.3 From bc48c48f1fefd1cb95caa7dcf0643ef3cff1c399 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 30 Sep 2019 17:02:22 +0200 Subject: handle SSLPeerUnverifiedException as certificate error --- app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app/src') diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java index 26f1691c..46782802 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderApiManagerBase.java @@ -49,6 +49,7 @@ import java.util.List; import java.util.NoSuchElementException; import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLPeerUnverifiedException; import okhttp3.OkHttpClient; import se.leap.bitmaskclient.Constants.CREDENTIAL_ERRORS; @@ -578,7 +579,7 @@ public abstract class ProviderApiManagerBase { plainResponseBody = formatErrorMessage(server_unreachable_message); } catch (MalformedURLException e) { plainResponseBody = formatErrorMessage(malformed_url); - } catch (SSLHandshakeException e) { + } catch (SSLHandshakeException | SSLPeerUnverifiedException e) { plainResponseBody = formatErrorMessage(certificate_error); } catch (ConnectException e) { plainResponseBody = formatErrorMessage(service_is_down_error); -- cgit v1.2.3 From aadaafd8326d3027d0a4aa448eb9d92920d01154 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 30 Sep 2019 22:39:33 +0200 Subject: add test for failing fetches of eip-service.json --- .../bitmaskclient/eip/ProviderApiManagerTest.java | 23 ++++++ .../BackendMockResponses/BackendMockProvider.java | 3 + ...rivceJsonInvalidCertificateBackendResponse.java | 91 ++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java (limited to 'app/src') 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 1a2ce49d..21781abb 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java @@ -52,6 +52,7 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.ProviderAPI.ERRORS; import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_NOK; import static se.leap.bitmaskclient.ProviderAPI.PROVIDER_OK; +import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID; import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.ERROR_CASE_MICONFIGURED_PROVIDER; import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.ERROR_CASE_UPDATED_CERTIFICATE; import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.NO_ERROR; @@ -403,4 +404,26 @@ public class ProviderApiManagerTest { providerApiManager.handleIntent(providerApiCommand); } + + @Test + public void test_handleIntentSetupProvider_failingEipServiceFetch_failedConfiguration() throws IOException, NoSuchAlgorithmException, CertificateEncodingException { + Provider provider = new Provider("https://riseup.net"); + + mockFingerprintForCertificate("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + mockProviderApiConnector(ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID); + providerApiManager = new ProviderApiManager(mockPreferences, mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); + + Bundle expectedResult = mockBundle(); + expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); + expectedResult.putParcelable(PROVIDER_KEY, provider); + expectedResult.putString(ERRORS, "This is not a trusted Bitmask provider."); + + Intent providerApiCommand = mockIntent(); + + providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); + providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); + providerApiCommand.putExtra(PROVIDER_KEY, provider); + + providerApiManager.handleIntent(providerApiCommand); + } } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java index 307b61fc..a10b1414 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java @@ -31,6 +31,7 @@ public class BackendMockProvider { NO_ERROR, ERROR_CASE_UPDATED_CERTIFICATE, ERROR_CASE_MICONFIGURED_PROVIDER, + ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID, ERROR_NO_RESPONSE_BODY, // => NullPointerException ERROR_DNS_RESOLUTION_ERROR, // => UnkownHostException ERROR_SOCKET_TIMEOUT, // => SocketTimeoutException @@ -59,6 +60,8 @@ public class BackendMockProvider { case ERROR_CASE_MICONFIGURED_PROVIDER: new MisconfiguredProviderBackendResponse(); break; + case ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID: + new EipSerivceJsonInvalidCertificateBackendResponse(); case ERROR_NO_RESPONSE_BODY: break; case ERROR_DNS_RESOLUTION_ERROR: diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java new file mode 100644 index 00000000..b84c5508 --- /dev/null +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2018 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package se.leap.bitmaskclient.testutils.BackendMockResponses; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.io.IOException; + +import javax.net.ssl.SSLHandshakeException; + +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +/** + * Created by cyberta on 10.01.18. + */ + +public class EipSerivceJsonInvalidCertificateBackendResponse extends BaseBackendResponse { + public EipSerivceJsonInvalidCertificateBackendResponse() throws IOException { + super(); + } + + @Override + public Answer getAnswerForRequestStringFromServer() { + return new Answer() { + @Override + public String answer(InvocationOnMock invocation) throws Throwable { + String url = (String) invocation.getArguments()[0]; + String requestMethod = (String) invocation.getArguments()[1]; + String jsonPayload = (String) invocation.getArguments()[2]; + + if (url.contains("/provider.json")) { + //download provider json + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")); + } else if (url.contains("/ca.crt")) { + //download provider ca cert + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); + } else if (url.contains("config/eip-service.json")) { + // download provider service json containing gateways, locations and openvpn settings + throw new SSLHandshakeException("Invalid provider CA certificate"); + } else if (url.contains("/users.json")) { + //create new user + //TODO: implement me + } else if (url.contains("/sessions.json")) { + //srp auth: sendAToSRPServer + //TODO: implement me + } else if (url.contains("/sessions/parmegvtest10.json")){ + //srp auth: sendM1ToSRPServer + //TODO: implement me + } + + return null; + } + }; + } + + @Override + public Answer getAnswerForCanConnect() { + return new Answer() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + return true; + } + }; + } + + @Override + public Answer getAnswerForDelete() { + return new Answer() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + return true; + } + }; + } + +} -- cgit v1.2.3 From dcae74f0e79c02e996a5ad0644349b92ad5caeb8 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 30 Sep 2019 22:40:08 +0200 Subject: improve output for bundle comparisons in tests --- .../leap/bitmaskclient/testutils/matchers/BundleMatcher.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'app/src') diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/matchers/BundleMatcher.java b/app/src/test/java/se/leap/bitmaskclient/testutils/matchers/BundleMatcher.java index 49a44038..0604d5eb 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/matchers/BundleMatcher.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/matchers/BundleMatcher.java @@ -73,7 +73,7 @@ public class BundleMatcher extends BaseMatcher { if (unfoundExpectedInteger.get(key) == null) { description.appendText("\n unfound Integer in actual Bundle: ").appendValue(iterator.next()); } else { - description.appendText("\n expected Integer for key " + key + ": ").appendValue(expectedIntegers.get(key)). + description.appendText("\n expected Integer for key \"" + key + "\": ").appendValue(expectedIntegers.get(key)). appendText("\n found Integer was: ").appendValue(unfoundExpectedInteger.get(key)); } } @@ -85,7 +85,7 @@ public class BundleMatcher extends BaseMatcher { if (unfoundExpectedBoolean.get(key) == null) { description.appendText("\n unfound Boolean in actual Bundle: ").appendValue(iterator.next()); } else { - description.appendText("\n expected Boolean for key " + key + ": ").appendValue(expectedBooleans.get(key)). + description.appendText("\n expected Boolean for key \"" + key + "\": ").appendValue(expectedBooleans.get(key)). appendText("\n found Boolean was: ").appendValue(unfoundExpectedBoolean.get(key)); } } @@ -97,8 +97,8 @@ public class BundleMatcher extends BaseMatcher { if (unfoundExpectedString.get(key) == null) { description.appendText("\n unfound String in actual Bundle: ").appendValue(iterator.next()); } else { - description.appendText("\n expected String for key " + key + ": ").appendValue(expectedStrings.get(key)). - appendText("\n found String was: ").appendValue(unfoundExpectedString.get(key)); + description.appendText("\n expected String for key \"" + key + "\": ").appendValue(expectedStrings.get(key)). + appendText("\n but found String was: ").appendValue(unfoundExpectedString.get(key)); } } } @@ -109,7 +109,7 @@ public class BundleMatcher extends BaseMatcher { if (unfoundExpectedParcelable.get(key) == null) { description.appendText("\n unfound Parcelable in actual Bundle: ").appendValue(iterator.next()); } else { - description.appendText("\n expected Parcelable or key " + key + ": ").appendValue(expectedParcelables.get(key)). + description.appendText("\n expected Parcelable or key \"" + key + "\": ").appendValue(expectedParcelables.get(key)). appendText("\n found Parcelable was: ").appendValue(unfoundExpectedParcelable.get(key)); } } -- cgit v1.2.3 From 685da193ea29f3e7a8a42d55747dfb2f956f23b6 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 30 Sep 2019 23:10:01 +0200 Subject: remove hard coded demo setup, use real pt.demo.bitmask.net demo provider --- .../custom/assets/ptdemo.bitmask.eip-service.json | 49 ------------- app/src/custom/assets/ptdemo.bitmask.net.json | 43 ------------ app/src/custom/assets/ptdemo.bitmask.secrets.json | 5 -- .../java/se/leap/bitmaskclient/StartActivity.java | 82 ---------------------- 4 files changed, 179 deletions(-) delete mode 100644 app/src/custom/assets/ptdemo.bitmask.eip-service.json delete mode 100644 app/src/custom/assets/ptdemo.bitmask.net.json delete mode 100644 app/src/custom/assets/ptdemo.bitmask.secrets.json (limited to 'app/src') diff --git a/app/src/custom/assets/ptdemo.bitmask.eip-service.json b/app/src/custom/assets/ptdemo.bitmask.eip-service.json deleted file mode 100644 index d804d032..00000000 --- a/app/src/custom/assets/ptdemo.bitmask.eip-service.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "serial": 3, - "version": 3, - "locations": { - "Amsterdam": { - "name": "Amsterdam", - "country_code": "NL", - "hemisphere": "N", - "timezone": "-1" - } - }, - "gateways": [ - { - "host": "pt.demo.bitmask.net", - "ip_address": "37.218.247.60", - "location": "Amsterdam", - "capabilities": { - "adblock": false, - "filter_dns": false, - "limited": false, - "transport": [ - {"type": "openvpn", - "protocols": ["tcp"], - "ports": ["443"] - }, - {"type": "obfs4", - "protocols": ["tcp"], - "options": {"cert": "gZlp9k6br2vn2MLnmjXpNh8D/CrR5wtackwZof/iICv1QzPwkkTUa+7JVOKtPiD0NFwCMw", "iat-mode": "0"}, - "ports": ["23042"] - } - ] - } - } - ], - "openvpn_configuration": { - "auth": "SHA1", - "cipher": "AES-256-CBC", - "dev": "tun", - "keepalive": "10 30", - "key-direction": "1", - "nobind": "True", - "persist-key": "True", - "rcvbuf": "0", - "sndbuf": "0", - "tls-cipher": "DHE-RSA-AES128-SHA", - "tun-ipv6": "True", - "verb": "3" - } -} \ No newline at end of file diff --git a/app/src/custom/assets/ptdemo.bitmask.net.json b/app/src/custom/assets/ptdemo.bitmask.net.json deleted file mode 100644 index 98afaa54..00000000 --- a/app/src/custom/assets/ptdemo.bitmask.net.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "api_uri": "https://leech.demo.bitmask.net:8000", - "api_version": "3", - "ca_cert_fingerprint": "SHA256: 0f17c033115f6b76ff67871872303ff65034efe7dd1b910062ca323eb4da5c7e", - "ca_cert_uri": "https://leech.demo.bitmask.net:8000/ca.crt", - "default_language": "en", - "description": { - "el": "demo.bitmask.net allows you to test the Bitmask application. User accounts may be periodically deleted.", - "en": "demo.bitmask.net allows you to test the Bitmask application. User accounts may be periodically deleted.", - "es": "demo.bitmask.net allows you to test the Bitmask application. User accounts may be periodically deleted." - }, - "domain": "demo.bitmask.net", - "enrollment_policy": "open", - "languages": [ - "de", - "en", - "es", - "pt" - ], - "name": { - "de": "Bitmask Pluggable Transports", - "en": "Bitmask Pluggable Transports" - }, - "service": { - "allow_anonymous": true, - "allow_free": true, - "allow_limited_bandwidth": false, - "allow_paid": false, - "allow_registration": true, - "allow_unlimited_bandwidth": true, - "bandwidth_limit": 102400, - "default_service_level": 1, - "levels": { - "1": { - "description": "Please donate.", - "name": "free" - } - } - }, - "services": [ - "openvpn" - ] -} \ No newline at end of file diff --git a/app/src/custom/assets/ptdemo.bitmask.secrets.json b/app/src/custom/assets/ptdemo.bitmask.secrets.json deleted file mode 100644 index 85900ea3..00000000 --- a/app/src/custom/assets/ptdemo.bitmask.secrets.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "ca_cert":"-----BEGIN CERTIFICATE-----\nMIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\nYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNVBAsME2h0dHBzOi8v\nYml0bWFzay5uZXQwHhcNMTIxMTA2MDAwMDAwWhcNMjIxMTA2MDAwMDAwWjBKMRgw\nFgYDVQQDDA9CaXRtYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNV\nBAsME2h0dHBzOi8vYml0bWFzay5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\nggIKAoICAQC1eV4YvayaU+maJbWrD4OHo3d7S1BtDlcvkIRS1Fw3iYDjsyDkZxai\ndHp4EUasfNQ+EVtXUvtk6170EmLco6Elg8SJBQ27trE6nielPRPCfX3fQzETRfvB\n7tNvGw4Jn2YKiYoMD79kkjgyZjkJ2r/bEHUSevmR09BRp86syHZerdNGpXYhcQ84\nCA1+V+603GFIHnrP+uQDdssW93rgDNYu+exT+Wj6STfnUkugyjmPRPjL7wh0tzy+\nznCeLl4xiV3g9sjPnc7r2EQKd5uaTe3j71sDPF92KRk0SSUndREz+B1+Dbe/RGk4\nMEqGFuOzrtsgEhPIX0hplhb0Tgz/rtug+yTT7oJjBa3u20AAOQ38/M99EfdeJvc4\nlPFF1XBBLh6X9UKF72an2NuANiX6XPySnJgZ7nZ09RiYZqVwu/qt3DfvLfhboq+0\nbQvLUPXrVDr70onv5UDjpmEA/cLmaIqqrduuTkFZOym65/PfAPvpGnt7crQj/Ibl\nDEDYZQmP7AS+6zBjoOzNjUGE5r40zWAR1RSi7zliXTu+yfsjXUIhUAWmYR6J3KxB\nlfsiHBQ+8dn9kC3YrUexWoOqBiqJOAJzZh5Y1tqgzfh+2nmHSB2dsQRs7rDRRlyy\nYMbkpzL9ZsOUO2eTP1mmar6YjCN+rggYjRrX71K2SpBG6b1zZxOG+wIDAQABo2Aw\nXjAdBgNVHQ4EFgQUuYGDLL2sswnYpHHvProt1JU+D48wDgYDVR0PAQH/BAQDAgIE\nMAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUuYGDLL2sswnYpHHvProt1JU+D48w\nDQYJKoZIhvcNAQENBQADggIBADeG67vaFcbITGpi51264kHPYPEWaXUa5XYbtmBl\ncXYyB6hY5hv/YNuVGJ1gWsDmdeXEyj0j2icGQjYdHRfwhrbEri+h1EZOm1cSBDuY\nk/P5+ctHyOXx8IE79DBsZ6IL61UKIaKhqZBfLGYcWu17DVV6+LT+AKtHhOrv3TSj\nRnAcKnCbKqXLhUPXpK0eTjPYS2zQGQGIhIy9sQXVXJJJsGrPgMxna1Xw2JikBOCG\nhtD/JKwt6xBmNwktH0GI/LVtVgSp82Clbn9C4eZN9E5YbVYjLkIEDhpByeC71QhX\nEIQ0ZR56bFuJA/CwValBqV/G9gscTPQqd+iETp8yrFpAVHOW+YzSFbxjTEkBte1J\naF0vmbqdMAWLk+LEFPQRptZh0B88igtx6tV5oVd+p5IVRM49poLhuPNJGPvMj99l\nmlZ4+AeRUnbOOeAEuvpLJbel4rhwFzmUiGoeTVoPZyMevWcVFq6BMkS+jRR2w0jK\nG6b0v5XDHlcFYPOgUrtsOBFJVwbutLvxdk6q37kIFnWCd8L3kmES5q4wjyFK47Co\nJa8zlx64jmMZPg/t3wWqkZgXZ14qnbyG5/lGsj5CwVtfDljrhN0oCWK1FZaUmW3d\n69db12/g4f6phldhxiWuGC/W6fCW5kre7nmhshcltqAJJuU47iX+DarBFiIj816e\nyV8e\n-----END CERTIFICATE-----", - "cert":"-----BEGIN CERTIFICATE-----\nMIIEbDCCAlSgAwIBAgIRAJ079G+cghukAsL/LV5v4c0wDQYJKoZIhvcNAQELBQAw\nZjEQMA4GA1UECgwHQml0bWFzazEcMBoGA1UECwwTaHR0cHM6Ly9iaXRtYXNrLm5l\ndDE0MDIGA1UEAwwrQml0bWFzayBSb290IENBIChjbGllbnQgY2VydGlmaWNhdGVz\nIG9ubHkhKTAeFw0xOTA4MzAyMTI5MjlaFw0xOTEwMDQyMTI5MjlaMBQxEjAQBgNV\nBAMTCVVOTElNSVRFRDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIy\nF+9n1gvkN3iHO7+wmED6WNhx23/XgYGhP8HrUsI1tu61gPEft/eUfo9yA2zOdZoe\nM3xw8Czj3U2gkpFOrq3VBzyOGeNGGD/yfuwO8/vY9kkubq/Um4S10lznPI1qjktB\nVuY3EJl95lAXmFmYE/ilpPSrRNoi1s4nm08rrW9DOrgEFePAXcz0MkNEMxLxniCo\n85lf0rtjmEJGBibQCrNS4c0jYxOJePXJRX+xfIy6RfRdNesCMglf8uTaRbmx7Nl6\n9XzjAqfOucLhopcSqs8yY87l8M81d25hFHtH1uY0iXxpSbMbTaKSL4QBHRnOUXYs\nAkF5PNqRnV2EQ4cTzIMCAwEAAaNnMGUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM\nMAoGCCsGAQUFBwMCMB0GA1UdDgQWBBTViW4hFR4M7hIHxgXq0DRRzMAatDAfBgNV\nHSMEGDAWgBSHfhO27FhbFFmofb2bj72ezvmibDANBgkqhkiG9w0BAQsFAAOCAgEA\njyXlQ0ltw1B3W0hX+Nf/R7ODdgz4pPL5ZlM0LdOQzyLCGS2Z5tlDT+veaF0dzGAF\nZwkdd93T/Hr0CXnN8eC/YYOv8OKwNXskYt+44tnbS8aRh6rJM/zAHpgcYBaD5hRp\nwidn30Q8ypsm+ge5460eFBXHVo1s+B2tQbmVFy4yZ74hWMt51csGutppQpJ6qK6b\nFYI+vApzCSHRDfFr6oly5pdiLsWult+yJ7S4u2OuvM/BNyfuhB39s+QsAa5ocZbk\njX42puhVAUv717dzTWCeJporMPWGG8fkylXwwIfTpys5pVZtQMdHZmhsaud3sLFe\nyomcWfMpKozCvbdLDn9siLjA76TU8bkCGqNVXZHaVRiConX7yLA7LPpX9+E9uqe1\nEtZLeIir4B0oUXKHqP/8qRGANLH1KaSrAdTWbTUHOCcgjxN3iVYYIg23Ns1xLocK\nfBaUrgxa6KYh+bMtwi5/WDEkjqUv3wPS59JZiHpU2WS0jmgJ0ou16wMzXhN3xHNd\nmScW6cwWKoeSjC3ru1TxB35mxNG32WXZUf6CzYNnCi2gJjYbDvWc75XT9CvNwpAJ\nJsU35MS+uVUPtRK2mX6qg9Qxgjr/SfBHio94lfelUt0QnS2uIoeKpaUxFX1ovbKq\nyhegtT3txnpgaC2zk4t7hl5TdBQ5XN6/QMiOWg37N6s=\n-----END CERTIFICATE-----", - "Constants.PROVIDER_PRIVATE_KEY":"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAwjIX72fWC+Q3eIc7v7CYQPpY2HHbf9eBgaE/wetSwjW27rWA\n8R+395R+j3IDbM51mh4zfHDwLOPdTaCSkU6urdUHPI4Z40YYP/J+7A7z+9j2SS5u\nr9SbhLXSXOc8jWqOS0FW5jcQmX3mUBeYWZgT+KWk9KtE2iLWziebTyutb0M6uAQV\n48BdzPQyQ0QzEvGeIKjzmV/Su2OYQkYGJtAKs1LhzSNjE4l49clFf7F8jLpF9F01\n6wIyCV/y5NpFubHs2Xr1fOMCp865wuGilxKqzzJjzuXwzzV3bmEUe0fW5jSJfGlJ\nsxtNopIvhAEdGc5RdiwCQXk82pGdXYRDhxPMgwIDAQABAoIBAQCWdat30RLVic+0\nscqIPbHpfk5B/Q1dIsLzhdTZUZOAZ4/BqZ0qtTGbQFFCoMqojdouO8IWY4aisTWw\nxH1q2fSbOJdvwoWqQo/dU+wkx30gHzzK/I/D6c1I6HsBgiO3SdzPz+MdYYKZ+iLs\n4SsoF505pFWHP/+LpzyY47UAhU3OCoY5xE48Z5OIU/y66zqpiG9ABiYmgb8lYUlc\nzk/EujRZ8G1Q5yC9KSt8SpJNLl3xQvA49BYD1IHSMfICAZjnH0HZ4vx1aOROdyfX\nnq4o7fGjuFJHHa85rf0XxpzhpHPL26oA51Ba0Gh/HxREfmK0gFaSNeUS7eY4HaEl\nHXZesvGRAoGBAOEAiqmPP0RY75Zx1doKxswaZVk8UAI2SYE8wLhGQtGuzqxyEkwH\nXFiKe3FQALiY7sexee5RFySR5tL1ZYlkB7i26jECigQzltAtxBrmx47tnO5g4PPI\nL4xomVE6d65OLW30/TG6FX/CHrJAYKIOteTsCFA9BjBntvTQvMQAJewLAoGBANzz\nDxWpFsvnKWRrvwQunUrPYO3s9MNFE2ak1/gjfBnS/5oBcGY0gUIrsr/qQOP6kQHx\n21gjZsLq0oHW57dQhs+288YS+hOBkP3pW9X8y38sViu9H4qCbn5AByxdhMNzooHQ\n9AFVx7rU7t8o+8YdNwLmKtuut1tzhoML3b/jU3RpAoGAU7xl3nCnNQJ8N9spoTn9\nfhwct7cQd6JIfMZlWq8bUvnhhJ/3W0AqB/GRuzvw6MJRqxPLsvuOx1ddNgmJvjXy\nAbZhNdgiESo56EQABZr5jaG0k6qOTWuk9nY/CNHflIkXsyJH0GfWdHOEBQacb/NV\nklqdRW9QjFcs6bN9bNw5QL0CgYBRiH/whk0bQVpM7FW4vVrd2Fj0c5R+2mamYf4w\nWyfYf7xCoHVRwd5RBL8ZguAfQL9x8EX46FdrZiv4Lc2kH9sfm2uplCckO5O9nvd8\np6SQcVP7H/cbrbYIcKg0/u2XEnzNWsYwF+90Sk87mmwOV4mNUFJQbtDKtn7UrPRP\ncxvAwQKBgD+wKwZWM/yEBaJKHA6XLbKlTrb27bKDBNTt8Pk8BK0uYcZLryIQtZY5\nokyJniA9rv38R5URRAIRwXXDxxIumuWk69CY92dYA5y1tm0ooPG8OFEbSWTBIh74\n3dKEnhNvHVpNQkUd67LlfWsS51YbMCpwqyxI9YPtRwWMGho8R+Ty\n-----END RSA PRIVATE KEY-----" -} \ No newline at end of file diff --git a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java index 945429fd..b89363b2 100644 --- a/app/src/main/java/se/leap/bitmaskclient/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/StartActivity.java @@ -25,36 +25,20 @@ import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.util.Log; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import de.blinkt.openvpn.core.Preferences; import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.eip.EipCommand; -import se.leap.bitmaskclient.utils.PreferenceHelper; -import static se.leap.bitmaskclient.BuildConfig.useDemoConfig; import static se.leap.bitmaskclient.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT; import static se.leap.bitmaskclient.Constants.PREFERENCES_APP_VERSION; -import static se.leap.bitmaskclient.Constants.PROVIDER_CONFIGURED; import static se.leap.bitmaskclient.Constants.PROVIDER_EIP_DEFINITION; import static se.leap.bitmaskclient.Constants.PROVIDER_KEY; -import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY; -import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.Constants.REQUEST_CODE_CONFIGURE_LEAP; import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.MainActivity.ACTION_SHOW_VPN_FRAGMENT; -import static se.leap.bitmaskclient.Provider.CA_CERT; -import static se.leap.bitmaskclient.Provider.MAIN_URL; import static se.leap.bitmaskclient.utils.ConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.utils.PreferenceHelper.getSavedProviderFromSharedPreferences; import static se.leap.bitmaskclient.utils.PreferenceHelper.providerInSharedPreferences; @@ -106,10 +90,6 @@ public class StartActivity extends Activity{ // initialize app necessities VpnStatus.initLogCache(getApplicationContext().getCacheDir()); - if (useDemoConfig) { - demoSetup(); - } - prepareEIP(); } @@ -235,66 +215,4 @@ public class StartActivity extends Activity{ startActivity(intent); finish(); } - - private String getInputAsString(InputStream fileAsInputStream) throws IOException { - BufferedReader br = new BufferedReader(new InputStreamReader(fileAsInputStream)); - StringBuilder sb = new StringBuilder(); - String line = br.readLine(); - while (line != null) { - sb.append(line); - line = br.readLine(); - } - - return sb.toString(); - } - - private void demoSetup() { - try { - //set demo data - String demoEipServiceJson = getInputAsString(getAssets().open("ptdemo.bitmask.eip-service.json")); - String secrets = getInputAsString(getAssets().open("ptdemo.bitmask.secrets.json")); - String provider = getInputAsString(getAssets().open("ptdemo.bitmask.net.json")); - - Log.d(TAG, "setup provider: " + provider); - Log.d(TAG, "setup eip json: " + demoEipServiceJson); - JSONObject secretsJson = new JSONObject(secrets); - - preferences.edit().putString(PROVIDER_EIP_DEFINITION+".demo.bitmask.net", demoEipServiceJson). - putString(PROVIDER_EIP_DEFINITION, demoEipServiceJson). - putString(CA_CERT, secretsJson.getString(CA_CERT)). - putString(PROVIDER_PRIVATE_KEY, secretsJson.getString(PROVIDER_PRIVATE_KEY)). - putString(PROVIDER_VPN_CERTIFICATE, secretsJson.getString(PROVIDER_VPN_CERTIFICATE)). - putString(Provider.KEY, provider). - putString(MAIN_URL, "https://demo.bitmask.net"). - putBoolean(PROVIDER_CONFIGURED, true).commit(); - - PreferenceHelper.getSavedProviderFromSharedPreferences(preferences); - ProviderObservable.getInstance().updateProvider(PreferenceHelper.getSavedProviderFromSharedPreferences(preferences)); - - // remove last used profiles - SharedPreferences prefs = Preferences.getDefaultSharedPreferences(this); - SharedPreferences.Editor prefsedit = prefs.edit(); - prefsedit.remove("lastConnectedProfile").commit(); - File f = new File(this.getCacheDir().getAbsolutePath() + "/android.conf"); - if (f.exists()) { - Log.d(TAG, "android.conf exists -> delete:" + f.delete()); - } - - File filesDirectory = new File(this.getFilesDir().getAbsolutePath()); - if (filesDirectory.exists() && filesDirectory.isDirectory()) { - File[] filesInDirectory = filesDirectory.listFiles(); - for (File file : filesInDirectory) { - Log.d(TAG, "delete profile: " + file.getName() + ": "+ file.delete()); - - } - } else Log.d(TAG, "file folder doesn't exist"); - - } catch (IOException e) { - e.printStackTrace(); - } catch (JSONException e) { - e.printStackTrace(); - } - - } - } -- cgit v1.2.3