Disable restricted VPN actions onResume

Otherwise it's pretty easy to circumvent any future restrictions by
keeping VPN settings for a particular app open and continuing to use
it even after DISALLOW_CONFIG_VPN is applied.

Two checks:
 1) in onResume (catches almost every case)
 2) in setAlwaysOn (catches every remaining case)

Bug: 28733079
Change-Id: I1c67bb14891ef620df5ed65fbd32678e417b4a65
This commit is contained in:
Robin Lee
2016-05-20 15:44:08 +01:00
committed by Victor Chang
parent 36522e8854
commit 52541536d0

View File

@@ -15,21 +15,15 @@
*/ */
package com.android.settings.vpn2; package com.android.settings.vpn2;
import android.annotation.NonNull;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.app.Dialog; import android.app.Dialog;
import android.app.DialogFragment; import android.app.DialogFragment;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
@@ -42,16 +36,17 @@ import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnConfig;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.RestrictedPreference; import com.android.settingslib.RestrictedPreference;
import com.android.settings.Utils;
import java.util.List; import java.util.List;
import static android.app.AppOpsManager.OP_ACTIVATE_VPN; import static android.app.AppOpsManager.OP_ACTIVATE_VPN;
public class AppManagementFragment extends SettingsPreferenceFragment public class AppManagementFragment extends SettingsPreferenceFragment
implements Preference.OnPreferenceClickListener { implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
private static final String TAG = "AppManagementFragment"; private static final String TAG = "AppManagementFragment";
@@ -116,7 +111,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
mPreferenceAlwaysOn = (RestrictedSwitchPreference) findPreference(KEY_ALWAYS_ON_VPN); mPreferenceAlwaysOn = (RestrictedSwitchPreference) findPreference(KEY_ALWAYS_ON_VPN);
mPreferenceForget = (RestrictedPreference) findPreference(KEY_FORGET_VPN); mPreferenceForget = (RestrictedPreference) findPreference(KEY_FORGET_VPN);
mPreferenceAlwaysOn.setOnPreferenceClickListener(this); mPreferenceAlwaysOn.setOnPreferenceChangeListener(this);
mPreferenceForget.setOnPreferenceClickListener(this); mPreferenceForget.setOnPreferenceClickListener(this);
} }
@@ -140,53 +135,78 @@ public class AppManagementFragment extends SettingsPreferenceFragment
switch (key) { switch (key) {
case KEY_FORGET_VPN: case KEY_FORGET_VPN:
return onForgetVpnClick(); return onForgetVpnClick();
case KEY_ALWAYS_ON_VPN:
return onAlwaysOnVpnClick();
default: default:
Log.w(TAG, "unknown key is clicked: " + key); Log.w(TAG, "unknown key is clicked: " + key);
return false; return false;
} }
} }
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
switch (preference.getKey()) {
case KEY_ALWAYS_ON_VPN:
return onAlwaysOnVpnClick((Boolean) newValue);
default:
Log.w(TAG, "unknown key is clicked: " + preference.getKey());
return false;
}
}
@Override @Override
protected int getMetricsCategory() { protected int getMetricsCategory() {
return MetricsEvent.VPN; return MetricsEvent.VPN;
} }
private boolean onForgetVpnClick() { private boolean onForgetVpnClick() {
updateRestrictions();
if (!mPreferenceForget.isEnabled()) {
return false;
}
AppDialogFragment.show(this, mForgetVpnDialogFragmentListener, mPackageInfo, mVpnLabel, AppDialogFragment.show(this, mForgetVpnDialogFragmentListener, mPackageInfo, mVpnLabel,
true /* editing */, true); true /* editing */, true);
return true; return true;
} }
private boolean onAlwaysOnVpnClick() { private boolean onAlwaysOnVpnClick(final boolean isChecked) {
final boolean isChecked = mPreferenceAlwaysOn.isChecked();
if (isChecked && isLegacyVpnLockDownOrAnotherPackageAlwaysOn()) { if (isChecked && isLegacyVpnLockDownOrAnotherPackageAlwaysOn()) {
// Show dialog if user replace always-on-vpn package and show not checked first // Show dialog if user replace always-on-vpn package and show not checked first
mPreferenceAlwaysOn.setChecked(false);
ReplaceExistingVpnFragment.show(this); ReplaceExistingVpnFragment.show(this);
return false;
} else { } else {
setAlwaysOnVpnByUI(isChecked); return setAlwaysOnVpnByUI(isChecked);
} }
return true;
} }
private void setAlwaysOnVpnByUI(boolean isEnabled) { private boolean setAlwaysOnVpnByUI(boolean isEnabled) {
updateRestrictions();
if (!mPreferenceAlwaysOn.isEnabled()) {
return false;
}
// Only clear legacy lockdown vpn in system user. // Only clear legacy lockdown vpn in system user.
if (mUserId == UserHandle.USER_SYSTEM) { if (mUserId == UserHandle.USER_SYSTEM) {
VpnUtils.clearLockdownVpn(getContext()); VpnUtils.clearLockdownVpn(getContext());
} }
mConnectivityManager.setAlwaysOnVpnPackageForUser(mUserId, isEnabled ? mPackageName : null, final boolean success = mConnectivityManager.setAlwaysOnVpnPackageForUser(mUserId,
/* lockdownEnabled */ false); isEnabled ? mPackageName : null, /* lockdownEnabled */ false);
if (isEnabled && !isVpnAlwaysOn()) { if (isEnabled && (!success || !isVpnAlwaysOn())) {
CannotConnectFragment.show(this, mVpnLabel); CannotConnectFragment.show(this, mVpnLabel);
} }
updateUI(); return success;
} }
private void updateUI() { private void updateUI() {
if (isAdded()) { if (isAdded()) {
mPreferenceAlwaysOn.setChecked(isVpnAlwaysOn()); mPreferenceAlwaysOn.setChecked(isVpnAlwaysOn());
updateRestrictions();
}
}
private void updateRestrictions() {
if (isAdded()) {
mPreferenceAlwaysOn.checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_VPN,
mUserId);
mPreferenceForget.checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_VPN,
mUserId);
} }
} }
@@ -300,7 +320,10 @@ public class AppManagementFragment extends SettingsPreferenceFragment
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
if (getTargetFragment() instanceof AppManagementFragment) { if (getTargetFragment() instanceof AppManagementFragment) {
((AppManagementFragment) getTargetFragment()).setAlwaysOnVpnByUI(true); final AppManagementFragment target = (AppManagementFragment) getTargetFragment();
if (target.setAlwaysOnVpnByUI(true)) {
target.updateUI();
}
} }
} }
} }