diff options
author | Arne Schwabe <arne@rfc2549.org> | 2013-10-06 15:10:56 +0200 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2013-10-06 15:10:56 +0200 |
commit | 967caeefc314e4f5b944b0e90c47f1f3b09f5a27 (patch) | |
tree | d3e7ac539af5641cf52a0fea13d395b71e3e4075 /vpndialogxposed/src/main/java | |
parent | 911f3855f184ecdb1339c1d8383ea19e86fe918e (diff) |
Update Xposed module to allow arbitrary VPN apps
Diffstat (limited to 'vpndialogxposed/src/main/java')
-rw-r--r-- | vpndialogxposed/src/main/java/de/blinkt/vpndialogxposed/VpnDialogPatcher.java | 31 | ||||
-rw-r--r-- | vpndialogxposed/src/main/java/de/blinkt/vpndialogxposed/allowedVPNsChooser.java | 150 |
2 files changed, 178 insertions, 3 deletions
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<String> blinktapp = new HashSet<String>(); + blinktapp.add("de.blinkt.openvpn"); + // blinktapp.add("de.blinkt.nothingset"); + + pref.reload(); + Set<String> 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<VpnApp> vpnApps = getVpnAppList(); + ListAdapter la = new ArrayAdapter<VpnApp>(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<String> 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<String> getAllowedApps(){ + SharedPreferences prefs = getPreferences(MODE_WORLD_READABLE); + HashSet<String> defaultapps = new HashSet<String>(); + defaultapps.add("de.blinkt.openvpn"); + return prefs.getStringSet(ALLOWED_APPS,defaultapps ); + } + + private void saveAllowedApps(Set<String> 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<String> allowedPkgs= new HashSet<String>(); + for(int i=0;i < getListView().getChildCount();i++) { + if(getListView().getCheckedItemPositions().get(i)) { + allowedPkgs.add(((VpnApp)getListView().getItemAtPosition(i)).mPkg); + } + } + saveAllowedApps(allowedPkgs); + } + + private Collection<VpnApp> getVpnAppList() { + PackageManager pm = getPackageManager(); + Intent vpnOpen = new Intent(); + vpnOpen.setAction("android.net.VpnService"); + Vector<VpnApp> vpnApps = new Vector<VpnApp>(); + + // 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<ResolveInfo> 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<ApplicationInfo> installedApps = pm.getInstalledApplications(0); + + + + for (ApplicationInfo app : installedApps) { + + List<ResolveInfo> apps; + if (app.packageName.equals(getPackageName())) { + apps = pm.queryIntentServices(vpnOpen, 0); + } else { + apps = (List<ResolveInfo>) 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(); + } + } +} |