From 967caeefc314e4f5b944b0e90c47f1f3b09f5a27 Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Sun, 6 Oct 2013 15:10:56 +0200 Subject: Update Xposed module to allow arbitrary VPN apps --- vpndialogxposed/src/main/AndroidManifest.xml | 14 +- .../blinkt/vpndialogxposed/VpnDialogPatcher.java | 31 ++++- .../blinkt/vpndialogxposed/allowedVPNsChooser.java | 150 +++++++++++++++++++++ .../src/main/res/layout/vpnapplayout.xml | 34 +++++ 4 files changed, 223 insertions(+), 6 deletions(-) create mode 100644 vpndialogxposed/src/main/java/de/blinkt/vpndialogxposed/allowedVPNsChooser.java create mode 100644 vpndialogxposed/src/main/res/layout/vpnapplayout.xml (limited to 'vpndialogxposed/src') diff --git a/vpndialogxposed/src/main/AndroidManifest.xml b/vpndialogxposed/src/main/AndroidManifest.xml index 2942105e..2a58277d 100644 --- a/vpndialogxposed/src/main/AndroidManifest.xml +++ b/vpndialogxposed/src/main/AndroidManifest.xml @@ -1,8 +1,6 @@ + package="de.blinkt.vpndialogxposed" > + + + + + + + + + diff --git a/vpndialogxposed/src/main/java/de/blinkt/vpndialogxposed/VpnDialogPatcher.java b/vpndialogxposed/src/main/java/de/blinkt/vpndialogxposed/VpnDialogPatcher.java index d87b2d89..9cf22d0c 100644 --- a/vpndialogxposed/src/main/java/de/blinkt/vpndialogxposed/VpnDialogPatcher.java +++ b/vpndialogxposed/src/main/java/de/blinkt/vpndialogxposed/VpnDialogPatcher.java @@ -8,11 +8,26 @@ import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; +import de.robv.android.xposed.XSharedPreferences; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; +import de.robv.android.xposed.IXposedHookZygoteInit; + import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Set; + +public class VpnDialogPatcher implements IXposedHookLoadPackage, IXposedHookZygoteInit { + public static final String MY_PACKAGE_NAME = AllowedVPNsChooser.class.getPackage().getName(); + private static XSharedPreferences pref; + + + @Override + public void initZygote(StartupParam startupParam) throws Throwable { + pref = new XSharedPreferences(MY_PACKAGE_NAME, "AllowedVPNsChooser"); + + } -public class VpnDialogPatcher implements IXposedHookLoadPackage { @Override public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { if (!lpparam.packageName.equals("com.android.vpndialogs")) @@ -52,11 +67,21 @@ public class VpnDialogPatcher implements IXposedHookLoadPackage { if((Boolean) XposedHelpers.callMethod(mService,"prepareVpn",prepareVPNsignature, mPackage,(String)null)) return; - if (mPackage.equals("de.blinkt.openvpn")) { + + HashSet blinktapp = new HashSet(); + blinktapp.add("de.blinkt.openvpn"); + // blinktapp.add("de.blinkt.nothingset"); + + pref.reload(); + Set allowedApps = pref.getStringSet("allowedApps",blinktapp); + + //Toast.makeText((Context)param.thisObject, "Allowed apps: " + allowedApps, Toast.LENGTH_LONG).show(); + + if (allowedApps.contains(mPackage)) { //mService.prepareVpn(null, mPackage); XposedHelpers.callMethod(mService,"prepareVpn",prepareVPNsignature, (String)null,mPackage); ((Activity) param.thisObject).setResult(Activity.RESULT_OK); - Toast.makeText((Context)param.thisObject,"Allowed de.blinkt.openvpn",Toast.LENGTH_LONG).show(); + Toast.makeText((Context)param.thisObject,"Allowed VpnService app: " + mPackage,Toast.LENGTH_LONG).show(); ((Activity) param.thisObject).finish(); } diff --git a/vpndialogxposed/src/main/java/de/blinkt/vpndialogxposed/allowedVPNsChooser.java b/vpndialogxposed/src/main/java/de/blinkt/vpndialogxposed/allowedVPNsChooser.java new file mode 100644 index 00000000..199f23fb --- /dev/null +++ b/vpndialogxposed/src/main/java/de/blinkt/vpndialogxposed/allowedVPNsChooser.java @@ -0,0 +1,150 @@ +package de.blinkt.vpndialogxposed; + +import android.Manifest; +import android.app.ListActivity; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.*; +import android.os.Bundle; +import android.widget.AbsListView; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; + + +/** + * Created by arne on 06.10.13. + */ +public class AllowedVPNsChooser extends ListActivity { + + public static final String ALLOWED_APPS = "allowedApps"; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Collection vpnApps = getVpnAppList(); + ListAdapter la = new ArrayAdapter(this, android.R.layout.simple_list_item_multiple_choice, vpnApps.toArray(new VpnApp[vpnApps.size()])); + setListAdapter(la); + setContentView(R.layout.vpnapplayout); + getListView().setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); + + + Collection allowedapps = getAllowedApps(); + for(int i=0; i < vpnApps.size(); i++) { + VpnApp va= (VpnApp) getListView().getItemAtPosition(i); + boolean allowed = allowedapps.contains(va.mPkg); + getListView().setItemChecked(i,allowed); + } + + } + + + + private Collection getAllowedApps(){ + SharedPreferences prefs = getPreferences(MODE_WORLD_READABLE); + HashSet defaultapps = new HashSet(); + defaultapps.add("de.blinkt.openvpn"); + return prefs.getStringSet(ALLOWED_APPS,defaultapps ); + } + + private void saveAllowedApps(Set allowedApps) + { + SharedPreferences prefs = getPreferences(MODE_WORLD_READABLE); + prefs.edit().putStringSet(ALLOWED_APPS,allowedApps) + .putInt("random",new Random().nextInt()).apply(); + } + + + @Override + protected void onStop() { + super.onStop(); + + HashSet allowedPkgs= new HashSet(); + for(int i=0;i < getListView().getChildCount();i++) { + if(getListView().getCheckedItemPositions().get(i)) { + allowedPkgs.add(((VpnApp)getListView().getItemAtPosition(i)).mPkg); + } + } + saveAllowedApps(allowedPkgs); + } + + private Collection getVpnAppList() { + PackageManager pm = getPackageManager(); + Intent vpnOpen = new Intent(); + vpnOpen.setAction("android.net.VpnService"); + Vector vpnApps = new Vector(); + + // Hack but should work + for(PackageInfo pkg : pm.getInstalledPackages(PackageManager.GET_SERVICES)) { + if (pkg.services != null) { + for(ServiceInfo serviceInfo:pkg.services) { + if(Manifest.permission.BIND_VPN_SERVICE.equals(serviceInfo.permission)) + vpnApps.add(new VpnApp(pkg.applicationInfo.loadLabel(pm), pkg.packageName)); + } + } + } + + + /* public abstract List queryIntentServicesAsUser(Intent intent, + int flags, int userId); + */ + + /* This does not work ... */ + /* + Class[] queryIntentServicesAsUserSignature = {Intent.class, int.class, int.class}; + try { + Method queryIntentServicesAsUser = pm.getClass().getMethod("queryIntentServicesAsUser", queryIntentServicesAsUserSignature); + + List installedApps = pm.getInstalledApplications(0); + + + + for (ApplicationInfo app : installedApps) { + + List apps; + if (app.packageName.equals(getPackageName())) { + apps = pm.queryIntentServices(vpnOpen, 0); + } else { + apps = (List) queryIntentServicesAsUser.invoke(pm, vpnOpen, 0, app.uid); + } + + + + for (ResolveInfo ri : apps) { + vpnApps.add(new VpnApp(ri.toString())); + } + } + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + */ + + return vpnApps; + } + + static class VpnApp { + + private final String mPkg; + private CharSequence mName; + + public VpnApp(CharSequence name, String pkg) { + mName = name; + mPkg = pkg; + } + + @Override + public String toString() { + return mName.toString(); + } + } +} diff --git a/vpndialogxposed/src/main/res/layout/vpnapplayout.xml b/vpndialogxposed/src/main/res/layout/vpnapplayout.xml new file mode 100644 index 00000000..3042ee2b --- /dev/null +++ b/vpndialogxposed/src/main/res/layout/vpnapplayout.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3