Skip to content

Commit 2bb04a1

Browse files
committed
Allow setting remote control apps via managed configuration
Closes ##1610 Signed-off-by: Arne Schwabe <arne@rfc2549.org>
1 parent 8bb986f commit 2bb04a1

File tree

6 files changed

+152
-44
lines changed

6 files changed

+152
-44
lines changed

main/src/main/java/de/blinkt/openvpn/api/AppRestrictions.java

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import de.blinkt.openvpn.VpnProfile;
1616
import de.blinkt.openvpn.core.ConfigParser;
17+
import de.blinkt.openvpn.core.OpenVPNService;
1718
import de.blinkt.openvpn.core.Preferences;
1819
import de.blinkt.openvpn.core.ProfileManager;
1920
import de.blinkt.openvpn.core.VpnStatus;
@@ -93,12 +94,61 @@ private void applyRestrictions(Context c) {
9394
VpnStatus.logError(String.format(Locale.US, "App restriction version %s does not match expected version %d", configVersion, CONFIG_VERSION));
9495
return;
9596
}
96-
Parcelable[] profileList = restrictions.getParcelableArray(("vpn_configuration_list"));
97+
Parcelable[] profileList = restrictions.getParcelableArray("vpn_configuration_list");
9798
if (profileList == null) {
9899
VpnStatus.logError("App restriction does not contain a profile list (vpn_configuration_list)");
99100
return;
100101
}
101102

103+
importVPNProfiles(c, restrictions, profileList);
104+
setAllowedRemoteControl(c, restrictions);
105+
106+
setMiscSettings(c, restrictions);
107+
}
108+
109+
private void setAllowedRemoteControl(Context c, Bundle restrictions) {
110+
Parcelable[] allowedApps = restrictions.getParcelableArray("allowed_remote_access");
111+
ExternalAppDatabase extapps = new ExternalAppDatabase(c);
112+
113+
if (allowedApps == null)
114+
{
115+
extapps.setFlagManagedConfiguration(false);
116+
return;
117+
}
118+
119+
HashSet<String> restrictionApps = new HashSet<>();
120+
121+
for (Parcelable allowedApp: allowedApps) {
122+
if (!(allowedApp instanceof Bundle)) {
123+
VpnStatus.logError("App restriction allowed app has wrong type");
124+
continue;
125+
}
126+
String package_name = ((Bundle) allowedApp).getString("package_name");
127+
restrictionApps.add(package_name);
128+
}
129+
130+
extapps.setFlagManagedConfiguration(true);
131+
extapps.clearAllApiApps();
132+
133+
if(!extapps.getExtAppList().equals(restrictionApps))
134+
{
135+
extapps.setAllowedApps(restrictionApps);
136+
}
137+
}
138+
139+
private static void setMiscSettings(Context c, Bundle restrictions) {
140+
SharedPreferences defaultPrefs = Preferences.getDefaultSharedPreferences(c);
141+
142+
if(restrictions.containsKey("screenoffpausevpn"))
143+
{
144+
boolean pauseVPN = restrictions.getBoolean("screenoffpausevpn");
145+
SharedPreferences.Editor editor = defaultPrefs.edit();
146+
editor.putBoolean("screenoff", pauseVPN);
147+
editor.apply();
148+
}
149+
}
150+
151+
private void importVPNProfiles(Context c, Bundle restrictions, Parcelable[] profileList) {
102152
Set<String> provisionedUuids = new HashSet<>();
103153

104154
String defaultprofile = restrictions.getString("defaultprofile", null);
@@ -117,14 +167,16 @@ private void applyRestrictions(Context c) {
117167
String name = p.getString("name");
118168
String certAlias = p.getString("certificate_alias");
119169

120-
if (uuid == null || ovpn == null || name == null) {
170+
if (TextUtils.isEmpty(uuid) || TextUtils.isEmpty(ovpn) || TextUtils.isEmpty(name)) {
121171
VpnStatus.logError("App restriction profile misses uuid, ovpn or name key");
122172
continue;
123173
}
124174

125175
/* we always use lower case uuid since Android UUID class will use present
126176
* them that way */
127177
uuid = uuid.toLowerCase(Locale.US);
178+
if (defaultprofile != null)
179+
defaultprofile = defaultprofile.toLowerCase(Locale.US);
128180

129181
if (uuid.equals(defaultprofile))
130182
defaultprofileProvisioned = true;
@@ -178,14 +230,6 @@ private void applyRestrictions(Context c) {
178230
}
179231
}
180232
}
181-
182-
if(restrictions.containsKey("screenoffpausevpn"))
183-
{
184-
boolean pauseVPN = restrictions.getBoolean("screenoffpausevpn");
185-
SharedPreferences.Editor editor = defaultPrefs.edit();
186-
editor.putBoolean("screenoff", pauseVPN);
187-
editor.apply();
188-
}
189233
}
190234

191235
/**
@@ -196,6 +240,9 @@ private void addCertificateAlias(VpnProfile vpnProfile, String certAlias, Contex
196240
if (vpnProfile == null)
197241
return;
198242

243+
if (certAlias == null)
244+
certAlias = "";
245+
199246
int oldType = vpnProfile.mAuthenticationType;
200247
String oldAlias = vpnProfile.mAlias;
201248

main/src/main/java/de/blinkt/openvpn/api/ExternalAppDatabase.java

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
import android.content.pm.ApplicationInfo;
1414
import android.content.pm.PackageManager;
1515
import android.os.Binder;
16+
import android.widget.Toast;
1617

1718
import java.util.HashSet;
1819
import java.util.Set;
1920

2021
import de.blinkt.openvpn.core.Preferences;
22+
import de.blinkt.openvpn.core.VpnStatus;
2123

2224
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
2325

@@ -30,12 +32,34 @@ public ExternalAppDatabase(Context c) {
3032
}
3133

3234
private final static String PREFERENCES_KEY = "allowed_apps";
35+
private final static String PREFERENCES_KEY_MANAGED_CONFIG = "allowed_apps_managed";
36+
37+
public void setFlagManagedConfiguration(boolean managed)
38+
{
39+
SharedPreferences prefs = Preferences.getDefaultSharedPreferences(mContext);
40+
Editor prefedit = prefs.edit();
41+
42+
prefedit.putBoolean(PREFERENCES_KEY_MANAGED_CONFIG, managed);
43+
increaseWorkaroundCounter(prefs, prefedit);
44+
prefedit.apply();
45+
}
46+
47+
public boolean isManagedConfiguration()
48+
{
49+
SharedPreferences prefs = Preferences.getDefaultSharedPreferences(mContext);
50+
return prefs.getBoolean(PREFERENCES_KEY_MANAGED_CONFIG, false);
51+
}
52+
53+
private static void increaseWorkaroundCounter(SharedPreferences prefs, Editor prefedit) {
54+
// Workaround for bug
55+
int counter = prefs.getInt("counter", 0);
56+
prefedit.putInt("counter", counter + 1);
57+
}
3358

3459
boolean isAllowed(String packagename) {
3560
Set<String> allowedapps = getExtAppList();
3661

37-
return allowedapps.contains(packagename);
38-
62+
return allowedapps.contains(packagename);
3963
}
4064

4165
public Set<String> getExtAppList() {
@@ -50,14 +74,22 @@ public void addApp(String packagename)
5074
saveExtAppList(allowedapps);
5175
}
5276

77+
public boolean checkAllowingModifyingRemoteControl(Context c) {
78+
if (isManagedConfiguration()) {
79+
Toast.makeText(c, "Remote control apps are manged by managed configuration, cannot change", Toast.LENGTH_LONG).show();
80+
VpnStatus.logError("Remote control apps are manged by managed configuration, cannot change");
81+
return false;
82+
}
83+
return true;
84+
}
85+
5386
private void saveExtAppList( Set<String> allowedapps) {
5487
SharedPreferences prefs = Preferences.getDefaultSharedPreferences(mContext);
5588
Editor prefedit = prefs.edit();
5689

5790
// Workaround for bug
5891
prefedit.putStringSet(PREFERENCES_KEY, allowedapps);
59-
int counter = prefs.getInt("counter", 0);
60-
prefedit.putInt("counter", counter + 1);
92+
increaseWorkaroundCounter(prefs, prefedit);
6193
prefedit.apply();
6294
}
6395

@@ -83,9 +115,9 @@ public String checkOpenVPNPermission(PackageManager pm) throws SecurityRemoteExc
83115
}
84116
} catch (PackageManager.NameNotFoundException e) {
85117
// App not found. Remove it from the list
86-
removeApp(appPackage);
118+
if (!isManagedConfiguration())
119+
removeApp(appPackage);
87120
}
88-
89121
}
90122
throw new SecurityException("Unauthorized OpenVPN API Caller");
91123
}
@@ -105,4 +137,8 @@ public boolean checkRemoteActionPermission(Context c, String callingPackage) {
105137
return false;
106138
}
107139
}
140+
141+
public void setAllowedApps(Set<String> restrictionApps) {
142+
saveExtAppList(restrictionApps);
143+
}
108144
}

main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,14 @@ public static String humanReadableByteCount(long bytes, boolean speed, Resources
180180
}
181181
}
182182

183+
184+
183185
@Override
184186
public void addAllowedExternalApp(String packagename) throws RemoteException {
185187
ExternalAppDatabase extapps = new ExternalAppDatabase(OpenVPNService.this);
186-
extapps.addApp(packagename);
188+
if(extapps.checkAllowingModifyingRemoteControl(this)) {
189+
extapps.addApp(packagename);
190+
}
187191
}
188192

189193
@Override

main/src/main/res/values/untranslatable.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@
8585
<string name="faq_title_ncp">Failed to negotiate cipher with server</string>
8686
<string name="import_from_URL">URL</string>
8787
<string name="restriction_pausevpn">Pause VPN when screen is off and less than 64 kB transferred data in 60s</string>
88+
<string name="apprest_aidl_list">List of apps that are allowed to use the remote AIDL. If this list is in the restrictions, the app will not allowe any changes to the list by the user.</string>
89+
<string name="apprest_remoteapi_package">Package name of the allow app (e.g. de.blinkt.openvpn.remoteapp)</string>
90+
<string name="apprest_remoteapi_package_title">Package</string>
91+
<string name="apprest_allowed_aidl_app">Allowed remote access app</string>
92+
<string name="apprest_remoteaidl">Remote API access</string>
8893

8994
<string-array name="tls_profile_values" translatable="false">
9095
<item>insecure</item>
Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,52 @@
1-
<?xml version="1.0" encoding="utf-8"?>
2-
<!--
1+
<?xml version="1.0" encoding="utf-8"?><!--
32
~ Copyright (c) 2012-2018 Arne Schwabe
43
~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
54
-->
65

76
<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
87
<restriction
98

9+
android:defaultValue="1"
1010
android:key="version"
11-
android:title="@string/apprest_ver"
1211
android:restrictionType="string"
13-
android:defaultValue="1"
14-
/>
12+
android:title="@string/apprest_ver" />
1513

1614
<restriction
1715
android:key="vpn_configuration_list"
18-
android:title="@string/apprest_vpnlist"
19-
android:restrictionType="bundle_array">
16+
android:restrictionType="bundle_array"
17+
android:title="@string/apprest_vpnlist">
2018

2119
<restriction
22-
android:title="@string/apprest_vpnconf"
2320
android:key="vpn_configuration"
24-
android:restrictionType="bundle">
21+
android:restrictionType="bundle"
22+
android:title="@string/apprest_vpnconf">
2523

2624
<restriction
25+
android:description="@string/apprest_uuid_desc"
2726
android:key="uuid"
2827
android:restrictionType="string"
29-
android:description="@string/apprest_uuid_desc"
30-
android:title="@string/apprest_uuid"
31-
/>
28+
android:title="@string/apprest_uuid" />
3229

3330
<restriction
31+
android:description="@string/apprest_name_desc"
3432
android:key="name"
3533
android:restrictionType="string"
3634
android:title="@string/apprest_name"
37-
android:description="@string/apprest_name_desc"
3835

39-
/>
36+
/>
4037

4138
<restriction
42-
android:key="ovpn"
43-
android:title="@string/apprest_ovpn"
4439
android:description="@string/apprest_ovpn_desc"
45-
android:restrictionType="string"/>
40+
android:key="ovpn"
41+
android:restrictionType="string"
42+
android:title="@string/apprest_ovpn" />
4643

4744
<restriction
48-
android:key="certificate_alias"
49-
android:title="@string/apprest_certalias"
5045
android:defaultValue=""
5146
android:description="@string/apprest_certalias_desc"
52-
android:restrictionType="string"/>
47+
android:key="certificate_alias"
48+
android:restrictionType="string"
49+
android:title="@string/apprest_certalias" />
5350
<!--
5451
<restriction
5552
android:key="ovpn_list"
@@ -67,14 +64,29 @@
6764
</restriction>
6865
<restriction
6966

67+
android:defaultValue=""
7068
android:key="defaultprofile"
71-
android:title="@string/apprest_defprof"
7269
android:restrictionType="string"
73-
android:defaultValue=""
74-
/>
70+
android:title="@string/apprest_defprof" />
7571
<restriction
76-
android:key="screenoffpausevpn"
77-
android:title="@string/restriction_pausevpn"
78-
android:restrictionType="bool"
79-
/>
72+
android:key="screenoffpausevpn"
73+
android:restrictionType="bool"
74+
android:title="@string/restriction_pausevpn" />
75+
<restriction
76+
android:description="@string/apprest_aidl_list"
77+
android:key="allowed_remote_access"
78+
android:restrictionType="bundle_array"
79+
android:title="@string/apprest_remoteaidl">
80+
<restriction
81+
android:key="allowed_app"
82+
android:restrictionType="bundle"
83+
android:title="@string/apprest_allowed_aidl_app">
84+
<restriction
85+
android:description="@string/apprest_remoteapi_package"
86+
android:key="package_name"
87+
android:restrictionType="string"
88+
android:title="@string/apprest_remoteapi_package_title" />
89+
</restriction>
90+
91+
</restriction>
8092
</restrictions>

main/src/ui/java/de/blinkt/openvpn/fragments/GeneralSettings.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ class GeneralSettings : PreferenceFragmentCompat(), Preference.OnPreferenceClick
176176
File("/system/lib/modules/tun.ko").length() > 10
177177

178178
override fun onPreferenceClick(preference: Preference): Boolean {
179+
if (!mExtapp.checkAllowingModifyingRemoteControl(requireContext()))
180+
{
181+
return false;
182+
}
179183
if (preference.key == "clearapi") {
180184
val builder = AlertDialog.Builder(
181185
requireContext()

0 commit comments

Comments
 (0)