summaryrefslogtreecommitdiff
path: root/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Constants.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/utils/FirewallHelper.java177
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java29
4 files changed, 133 insertions, 76 deletions
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 724fd0fd..766dc925 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -518,7 +518,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
super.onCreate();
notificationManager = new VpnNotificationManager(this, this);
notificationManager.createOpenVpnNotificationChannel();
- firewallHelper = new FirewallHelper();
+ firewallHelper = new FirewallHelper(this);
}
@Override
diff --git a/app/src/main/java/se/leap/bitmaskclient/Constants.java b/app/src/main/java/se/leap/bitmaskclient/Constants.java
index d3c09f08..0cbf82e1 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Constants.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Constants.java
@@ -15,6 +15,7 @@ public interface Constants {
String LAST_USED_PROFILE = "last_used_profile";
String EXCLUDED_APPS = "excluded_apps";
String USE_PLUGGABLE_TRANSPORTS = "usePluggableTransports";
+ String SU_PERMISSION = "su_permission";
//////////////////////////////////////////////
diff --git a/app/src/main/java/se/leap/bitmaskclient/utils/FirewallHelper.java b/app/src/main/java/se/leap/bitmaskclient/utils/FirewallHelper.java
index 43a5296f..8b80f1f0 100644
--- a/app/src/main/java/se/leap/bitmaskclient/utils/FirewallHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/utils/FirewallHelper.java
@@ -16,17 +16,20 @@ package se.leap.bitmaskclient.utils;
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import android.content.Context;
import android.os.AsyncTask;
-import android.text.TextUtils;
import android.util.Log;
import java.lang.ref.WeakReference;
+import de.blinkt.openvpn.core.VpnStatus;
+
import static se.leap.bitmaskclient.utils.Cmd.runBlockingCmd;
interface FirewallCallback {
void onFirewallStarted(boolean success);
void onFirewallStopped(boolean success);
+ void onSuRequested(boolean success);
}
@@ -34,64 +37,92 @@ public class FirewallHelper implements FirewallCallback {
private static String BITMASK_CHAIN = "bitmask_fw";
private static final String TAG = FirewallHelper.class.getSimpleName();
+ private Context context;
+
+ public FirewallHelper(Context context) {
+ this.context = context;
+ }
+
@Override
public void onFirewallStarted(boolean success) {
- Log.d(TAG, "Firewall started " + success);
+ if (success) {
+ VpnStatus.logInfo("[FIREWALL] custom rules established");
+ } else {
+ VpnStatus.logError("[FIREWALL] could not establish custom rules.");
+ }
}
@Override
public void onFirewallStopped(boolean success) {
- Log.d(TAG, "Firewall stopped " + success);
+ if (success) {
+ VpnStatus.logInfo("[FIREWALL] custom rules deleted");
+ } else {
+ VpnStatus.logError("[FIREWALL] could not delete custom rules");
+ }
}
+ @Override
+ public void onSuRequested(boolean success) {
+ PreferenceHelper.setSuPermission(context, success);
+ if (!success) {
+ VpnStatus.logError("[FIREWALL] Bitmask needs root permission to execute custom firewall rules.");
+ }
+ }
- static class StartFirewallTask extends AsyncTask<Void, Boolean, Boolean> {
+
+ private static class StartFirewallTask extends AsyncTask<Void, Boolean, Boolean> {
WeakReference<FirewallCallback> callbackWeakReference;
- public StartFirewallTask(FirewallCallback callback) {
+ StartFirewallTask(FirewallCallback callback) {
callbackWeakReference = new WeakReference<>(callback);
}
@Override
protected Boolean doInBackground(Void... voids) {
- if (requestSU()) {
- Log.d(TAG, "su acquired");
- StringBuilder log = new StringBuilder();
- String[] bitmaskChain = new String[]{
- "su",
- "ip6tables --list " + BITMASK_CHAIN };
+ StringBuilder log = new StringBuilder();
+ String[] bitmaskChain = new String[]{
+ "su",
+ "id",
+ "ip6tables --list " + BITMASK_CHAIN };
+
+
+ try {
+ boolean hasBitmaskChain = runBlockingCmd(bitmaskChain, log) == 0;
+ boolean allowSu = log.toString().contains("uid=0");
try {
- boolean hasBitmaskChain = runBlockingCmd(bitmaskChain, log) == 0;
+ callbackWeakReference.get().onSuRequested(allowSu);
+ Thread.sleep(1000);
+ } catch (Exception e) {
+ //ignore
+ }
+
+ boolean success;
+ log = new StringBuilder();
+ if (!hasBitmaskChain) {
+ String[] createChainAndRules = new String[]{
+ "su",
+ "ip6tables --new-chain " + BITMASK_CHAIN,
+ "ip6tables --insert OUTPUT --jump " + BITMASK_CHAIN,
+ "ip6tables --append " + BITMASK_CHAIN + " -p tcp --jump REJECT",
+ "ip6tables --append " + BITMASK_CHAIN + " -p udp --jump REJECT"
+ };
+ success = runBlockingCmd(createChainAndRules, log) == 0;
+ Log.d(TAG, "added " + BITMASK_CHAIN + " to ip6tables: " + success);
Log.d(TAG, log.toString());
- if (!hasBitmaskChain) {
- String[] createChain = new String[]{
- "su",
- "ip6tables --new-chain " + BITMASK_CHAIN,
- "ip6tables --insert OUTPUT --jump " + BITMASK_CHAIN };
- log = new StringBuilder();
- int success = runBlockingCmd(createChain, log);
- Log.d(TAG, "added " + BITMASK_CHAIN + " to ip6tables: " + success);
- Log.d(TAG, log.toString());
- if (success != 0) {
- return false;
- }
- }
-
- log = new StringBuilder();
+ return success;
+ } else {
String[] addRules = new String[] {
"su",
"ip6tables --append " + BITMASK_CHAIN + " -p tcp --jump REJECT",
"ip6tables --append " + BITMASK_CHAIN + " -p udp --jump REJECT" };
- boolean successResult = runBlockingCmd(addRules, log) == 0;
- Log.d(TAG, log.toString());
- return successResult;
- } catch (Exception e) {
- e.printStackTrace();
- Log.e(TAG, log.toString());
+ return runBlockingCmd(addRules, log) == 0;
}
- };
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(TAG, log.toString());
+ }
return false;
}
@@ -105,29 +136,49 @@ public class FirewallHelper implements FirewallCallback {
}
}
- static class ShutdownFirewallTask extends AsyncTask<Void, Boolean, Boolean> {
+ private static class ShutdownFirewallTask extends AsyncTask<Void, Boolean, Boolean> {
+
+ WeakReference<FirewallCallback> callbackWeakReference;
+
+ ShutdownFirewallTask(FirewallCallback callback) {
+ callbackWeakReference = new WeakReference<>(callback);
+ }
@Override
protected Boolean doInBackground(Void... voids) {
+ boolean success;
+ StringBuilder log = new StringBuilder();
+ String[] deleteChain = new String[]{
+ "su",
+ "id",
+ "ip6tables --delete OUTPUT --jump " + BITMASK_CHAIN,
+ "ip6tables --flush " + BITMASK_CHAIN,
+ "ip6tables --delete-chain " + BITMASK_CHAIN
+ };
+ try {
+ success = runBlockingCmd(deleteChain, log) == 0;
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(TAG, log.toString());
+ return false;
+ }
- if (requestSU()) {
- StringBuilder log = new StringBuilder();
- String[] deleteChain = new String[]{
- "su",
- "ip6tables --delete OUTPUT --jump " + BITMASK_CHAIN,
- "ip6tables --flush " + BITMASK_CHAIN,
- "ip6tables --delete-chain " + BITMASK_CHAIN
- };
- try {
- runBlockingCmd(deleteChain, log);
- } catch (Exception e) {
- e.printStackTrace();
- Log.e(TAG, log.toString());
- }
-
+ try {
+ boolean allowSu = log.toString().contains("uid=0");
+ callbackWeakReference.get().onSuRequested(allowSu);
+ } catch (Exception e) {
+ //ignore
}
+ return success;
+ }
- return null;
+ @Override
+ protected void onPostExecute(Boolean result) {
+ super.onPostExecute(result);
+ FirewallCallback callback = callbackWeakReference.get();
+ if (callback != null) {
+ callback.onFirewallStopped(result);
+ }
}
}
@@ -138,30 +189,8 @@ public class FirewallHelper implements FirewallCallback {
}
public void shutdownFirewall() {
- ShutdownFirewallTask task = new ShutdownFirewallTask();
+ ShutdownFirewallTask task = new ShutdownFirewallTask(this);
task.execute();
}
- public static boolean hasSU() {
- StringBuilder log = new StringBuilder();
-
- try {
- String suCommand = "su -v";
- runBlockingCmd(new String[]{suCommand}, log);
- } catch (Exception e) {
- return false;
- }
-
- return !TextUtils.isEmpty(log) && !log.toString().contains("su: not found");
- }
-
- public static boolean requestSU() {
- try {
- String suCommand = "su";
- return runBlockingCmd(new String[]{suCommand}, null) == 0;
- } catch (Exception e) {
- return false;
- }
- }
-
}
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 9eac7187..bf97b5c5 100644
--- a/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/utils/PreferenceHelper.java
@@ -31,6 +31,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.SU_PERMISSION;
import static se.leap.bitmaskclient.Constants.USE_PLUGGABLE_TRANSPORTS;
import static se.leap.bitmaskclient.Constants.EXCLUDED_APPS;
@@ -214,6 +215,14 @@ public class PreferenceHelper {
apply();
}
+ public static boolean hasSuPermission(Context context) {
+ return getBoolean(context, SU_PERMISSION, false);
+ }
+
+ public static void setSuPermission(Context context, boolean allowed) {
+ putBoolean(context, SU_PERMISSION, allowed);
+ }
+
public static boolean getUsePluggableTransports(Context context) {
if (context == null) {
return false;
@@ -296,9 +305,27 @@ public class PreferenceHelper {
return preferences.getString(key, defValue);
}
- public static void putString(Context context, String key, String value){
+ public static void putString(Context context, String key, String value) {
SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
preferences.edit().putString(key, value).apply();
}
+ public static Boolean getBoolean(Context context, String key, Boolean defValue) {
+ if (context == null) {
+ return false;
+ }
+
+ SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
+ return preferences.getBoolean(key, defValue);
+ }
+
+ public static void putBoolean(Context context, String key, Boolean value) {
+ if (context == null) {
+ return;
+ }
+
+ SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
+ preferences.edit().putBoolean(key, value).apply();
+ }
+
}