diff --git a/main/src/main/java/de/blinkt/openvpn/api/AppRestrictions.java b/main/src/main/java/de/blinkt/openvpn/api/AppRestrictions.java index 9e3764e30..9133ca0be 100644 --- a/main/src/main/java/de/blinkt/openvpn/api/AppRestrictions.java +++ b/main/src/main/java/de/blinkt/openvpn/api/AppRestrictions.java @@ -61,13 +61,22 @@ private void removeChangesListener(Context c) { c.unregisterReceiver(mRestrictionsReceiver); } - private String hashConfig(String rawconfig) { + private String hashConfig(String rawconfig, String allowedApps) { String config = prepare(rawconfig); MessageDigest digest; + + if (allowedApps == null) + allowedApps = ""; + + + try { digest = MessageDigest.getInstance("SHA1"); byte[] utf8_bytes = config.getBytes(StandardCharsets.UTF_8); digest.update(utf8_bytes, 0, utf8_bytes.length); + + byte[] apps_bytes = allowedApps.getBytes(StandardCharsets.UTF_8); + digest.update(apps_bytes, 0, apps_bytes.length); return new BigInteger(1, digest.digest()).toString(16); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); @@ -181,6 +190,7 @@ private void importVPNProfiles(Context c, Bundle restrictions, Parcelable[] prof String ovpn = p.getString("ovpn"); String name = p.getString("name"); String certAlias = p.getString("certificate_alias"); + String allowedApps = p.getString("allowed_apps"); if (TextUtils.isEmpty(uuid) || TextUtils.isEmpty(ovpn) || TextUtils.isEmpty(name)) { VpnStatus.logError("App restriction profile misses uuid, ovpn or name key"); @@ -196,13 +206,13 @@ private void importVPNProfiles(Context c, Bundle restrictions, Parcelable[] prof if (uuid.equals(defaultprofile)) defaultprofileProvisioned = true; - String ovpnHash = hashConfig(ovpn); + String ovpnHash = hashConfig(ovpn, allowedApps); provisionedUuids.add(uuid.toLowerCase(Locale.ENGLISH)); // Check if the profile already exists VpnProfile vpnProfile = ProfileManager.get(c, uuid); - + HashSet oldAllowedPackages = null; if (vpnProfile != null) { // Profile exists, check if need to update it if (ovpnHash.equals(vpnProfile.importedProfileHash)) { @@ -211,9 +221,35 @@ private void importVPNProfiles(Context c, Bundle restrictions, Parcelable[] prof // not modified skip to next profile continue; } + oldAllowedPackages = vpnProfile.mAllowedAppsVpn; + } + vpnProfile = addProfile(c, ovpn, uuid, name, vpnProfile, ovpnHash); + if (vpnProfile == null) + { + continue; } - vpnProfile = addProfile(c, ovpn, uuid, name, vpnProfile); + addCertificateAlias(vpnProfile, certAlias, c); + HashSet allowedAppsSet = new HashSet<>(); + if (allowedApps != null && vpnProfile != null){ + for (String app:allowedApps.split("[,: \n\r]")){ + if (!TextUtils.isEmpty(app)) + allowedAppsSet.add(app); + } + if (!allowedAppsSet.equals(vpnProfile.mAllowedAppsVpn)) + { + vpnProfile.mAllowedAppsVpn = allowedAppsSet; + vpnProfile.mAllowedAppsVpnAreDisallowed = false; + pm.saveProfile(c, vpnProfile); + } + + } + if (TextUtils.isEmpty(allowedApps) && oldAllowedPackages != null) + { + vpnProfile.mAllowedAppsVpn = oldAllowedPackages; + pm.saveProfile(c, vpnProfile); + } + } Vector profilesToRemove = new Vector<>(); @@ -318,7 +354,7 @@ private String prepare(String config) { ; - VpnProfile addProfile(Context c, String config, String uuid, String name, VpnProfile vpnProfile) { + VpnProfile addProfile(Context c, String config, String uuid, String name, VpnProfile vpnProfile, String ovpnHash) { config = prepare(config); ConfigParser cp = new ConfigParser(); try { @@ -331,7 +367,7 @@ VpnProfile addProfile(Context c, String config, String uuid, String name, VpnPro vp.mName = name; vp.setUUID(UUID.fromString(uuid)); - vp.importedProfileHash = hashConfig(config); + vp.importedProfileHash = ovpnHash; ProfileManager pm = ProfileManager.getInstance(c); diff --git a/main/src/main/res/values/untranslatable.xml b/main/src/main/res/values/untranslatable.xml index 5caa853db..560acaae9 100644 --- a/main/src/main/res/values/untranslatable.xml +++ b/main/src/main/res/values/untranslatable.xml @@ -86,6 +86,8 @@ URL Pause VPN when screen is off and less than 64 kB transferred data in 60s Enable the workaround to use an on boot receiver to start the VPN if the Always On VPN functionality is not available + Apps using the VPN + List of packages name (e.g. com.google.chrome) that are should be used with the VPN. Separated by comma, space or newlines Keep the VPN connected even when no network is detected, e.g. when reverse tethering over USB using adb List of apps that are allowed to use the remote AIDL. If this list is in the restrictions, the app will not allowed any changes to the list by the user. Package names of allowed apps separated by comma, space or newlines Remote API access diff --git a/main/src/main/res/xml/app_restrictions.xml b/main/src/main/res/xml/app_restrictions.xml index 9843fada0..d97891322 100644 --- a/main/src/main/res/xml/app_restrictions.xml +++ b/main/src/main/res/xml/app_restrictions.xml @@ -47,6 +47,11 @@ android:key="certificate_alias" android:restrictionType="string" android:title="@string/apprest_certalias" /> +