Merge "Resolve UidRange dependency between NMS and CS module" am: c3806f72b7
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1495869 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I2e55c3c4bed3d71eb48242428c179809aae00a1f
This commit is contained in:
@@ -320,16 +320,6 @@ interface INetworkManagementService
|
||||
void setFirewallUidRules(int chain, in int[] uids, in int[] rules);
|
||||
void setFirewallChainEnabled(int chain, boolean enable);
|
||||
|
||||
/**
|
||||
* Set all packets from users in ranges to go through VPN specified by netId.
|
||||
*/
|
||||
void addVpnUidRanges(int netId, in UidRange[] ranges);
|
||||
|
||||
/**
|
||||
* Clears the special VPN rules for users in ranges and VPN specified by netId.
|
||||
*/
|
||||
void removeVpnUidRanges(int netId, in UidRange[] ranges);
|
||||
|
||||
/**
|
||||
* Start listening for mobile activity state changes.
|
||||
*/
|
||||
@@ -361,7 +351,5 @@ interface INetworkManagementService
|
||||
void removeInterfaceFromLocalNetwork(String iface);
|
||||
int removeRoutesFromLocalNetwork(in List<RouteInfo> routes);
|
||||
|
||||
void setAllowOnlyVpnForUids(boolean enable, in UidRange[] uidRanges);
|
||||
|
||||
boolean isNetworkRestricted(int uid);
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ import android.net.RouteInfoParcel;
|
||||
import android.net.SocketKeepalive;
|
||||
import android.net.TetheringManager;
|
||||
import android.net.UidRange;
|
||||
import android.net.UidRangeParcel;
|
||||
import android.net.Uri;
|
||||
import android.net.VpnManager;
|
||||
import android.net.VpnService;
|
||||
@@ -5152,7 +5153,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
loge("Starting user already has a VPN");
|
||||
return;
|
||||
}
|
||||
userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId, mKeyStore);
|
||||
userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId, mKeyStore);
|
||||
mVpns.put(userId, userVpn);
|
||||
if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
|
||||
updateLockdownVpn();
|
||||
@@ -6622,6 +6623,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
&& (lp.hasIpv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute());
|
||||
}
|
||||
|
||||
private static UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
|
||||
final UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.size()];
|
||||
int index = 0;
|
||||
for (UidRange range : ranges) {
|
||||
stableRanges[index] = new UidRangeParcel(range.start, range.stop);
|
||||
index++;
|
||||
}
|
||||
return stableRanges;
|
||||
}
|
||||
|
||||
private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
|
||||
NetworkCapabilities newNc) {
|
||||
Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids();
|
||||
@@ -6641,14 +6652,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// removing old range works because, unlike the filtering rules below, it's possible to
|
||||
// add duplicate UID routing rules.
|
||||
if (!newRanges.isEmpty()) {
|
||||
final UidRange[] addedRangesArray = new UidRange[newRanges.size()];
|
||||
newRanges.toArray(addedRangesArray);
|
||||
mNMS.addVpnUidRanges(nai.network.getNetId(), addedRangesArray);
|
||||
mNetd.networkAddUidRanges(nai.network.netId, toUidRangeStableParcels(newRanges));
|
||||
}
|
||||
if (!prevRanges.isEmpty()) {
|
||||
final UidRange[] removedRangesArray = new UidRange[prevRanges.size()];
|
||||
prevRanges.toArray(removedRangesArray);
|
||||
mNMS.removeVpnUidRanges(nai.network.getNetId(), removedRangesArray);
|
||||
mNetd.networkRemoveUidRanges(
|
||||
nai.network.netId, toUidRangeStableParcels(prevRanges));
|
||||
}
|
||||
final boolean wasFiltering = requiresVpnIsolation(nai, prevNc, nai.linkProperties);
|
||||
final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties);
|
||||
|
||||
@@ -60,7 +60,6 @@ import android.net.NetworkStack;
|
||||
import android.net.NetworkStats;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.TetherStatsParcel;
|
||||
import android.net.UidRange;
|
||||
import android.net.UidRangeParcel;
|
||||
import android.net.shared.NetdUtils;
|
||||
import android.net.shared.RouteUtils;
|
||||
@@ -1393,38 +1392,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private static UidRangeParcel makeUidRangeParcel(int start, int stop) {
|
||||
UidRangeParcel range = new UidRangeParcel();
|
||||
range.start = start;
|
||||
range.stop = stop;
|
||||
return range;
|
||||
}
|
||||
|
||||
private static UidRangeParcel[] toStableParcels(UidRange[] ranges) {
|
||||
UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.length];
|
||||
for (int i = 0; i < ranges.length; i++) {
|
||||
stableRanges[i] = makeUidRangeParcel(ranges[i].start, ranges[i].stop);
|
||||
}
|
||||
return stableRanges;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
|
||||
throws ServiceSpecificException {
|
||||
NetworkStack.checkNetworkStackPermission(mContext);
|
||||
try {
|
||||
mNetdService.networkRejectNonSecureVpn(add, toStableParcels(uidRanges));
|
||||
} catch (ServiceSpecificException e) {
|
||||
Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
|
||||
+ ": netd command failed", e);
|
||||
throw e;
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
|
||||
+ ": netd command failed", e);
|
||||
throw e.rethrowAsRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private void applyUidCleartextNetworkPolicy(int uid, int policy) {
|
||||
final int policyValue;
|
||||
switch (policy) {
|
||||
@@ -1552,27 +1519,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
|
||||
return stats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVpnUidRanges(int netId, UidRange[] ranges) {
|
||||
NetworkStack.checkNetworkStackPermission(mContext);
|
||||
|
||||
try {
|
||||
mNetdService.networkAddUidRanges(netId, toStableParcels(ranges));
|
||||
} catch (RemoteException | ServiceSpecificException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeVpnUidRanges(int netId, UidRange[] ranges) {
|
||||
NetworkStack.checkNetworkStackPermission(mContext);
|
||||
try {
|
||||
mNetdService.networkRemoveUidRanges(netId, toStableParcels(ranges));
|
||||
} catch (RemoteException | ServiceSpecificException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFirewallEnabled(boolean enabled) {
|
||||
enforceSystemUid();
|
||||
@@ -1616,7 +1562,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
|
||||
ranges = new UidRangeParcel[] {
|
||||
// TODO: is there a better way of finding all existing users? If so, we could
|
||||
// specify their ranges here.
|
||||
makeUidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
|
||||
new UidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
|
||||
};
|
||||
// ... except for the UIDs that have allow rules.
|
||||
synchronized (mRulesLock) {
|
||||
@@ -1647,7 +1593,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
|
||||
for (int i = 0; i < ranges.length; i++) {
|
||||
if (rules.valueAt(i) == FIREWALL_RULE_DENY) {
|
||||
int uid = rules.keyAt(i);
|
||||
ranges[numUids] = makeUidRangeParcel(uid, uid);
|
||||
ranges[numUids] = new UidRangeParcel(uid, uid);
|
||||
numUids++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.DnsResolver;
|
||||
import android.net.INetd;
|
||||
import android.net.INetworkManagementEventObserver;
|
||||
import android.net.Ikev2VpnProfile;
|
||||
import android.net.IpPrefix;
|
||||
@@ -68,6 +69,7 @@ import android.net.NetworkProvider;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.UidRange;
|
||||
import android.net.UidRangeParcel;
|
||||
import android.net.VpnManager;
|
||||
import android.net.VpnService;
|
||||
import android.net.ipsec.ike.ChildSessionCallback;
|
||||
@@ -188,7 +190,8 @@ public class Vpn {
|
||||
|
||||
private PendingIntent mStatusIntent;
|
||||
private volatile boolean mEnableTeardown = true;
|
||||
private final INetworkManagementService mNetd;
|
||||
private final INetworkManagementService mNms;
|
||||
private final INetd mNetd;
|
||||
@VisibleForTesting
|
||||
protected VpnConfig mConfig;
|
||||
private final NetworkProvider mNetworkProvider;
|
||||
@@ -234,7 +237,7 @@ public class Vpn {
|
||||
* @see mLockdown
|
||||
*/
|
||||
@GuardedBy("this")
|
||||
private final Set<UidRange> mBlockedUidsAsToldToNetd = new ArraySet<>();
|
||||
private final Set<UidRangeParcel> mBlockedUidsAsToldToNetd = new ArraySet<>();
|
||||
|
||||
// The user id of initiating VPN.
|
||||
private final int mUserId;
|
||||
@@ -363,22 +366,23 @@ public class Vpn {
|
||||
}
|
||||
}
|
||||
|
||||
public Vpn(Looper looper, Context context, INetworkManagementService netService,
|
||||
public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd,
|
||||
@UserIdInt int userId, @NonNull KeyStore keyStore) {
|
||||
this(looper, context, new Dependencies(), netService, userId, keyStore,
|
||||
this(looper, context, new Dependencies(), netService, netd, userId, keyStore,
|
||||
new SystemServices(context), new Ikev2SessionCreator());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected Vpn(Looper looper, Context context, Dependencies deps,
|
||||
INetworkManagementService netService,
|
||||
INetworkManagementService netService, INetd netd,
|
||||
int userId, @NonNull KeyStore keyStore, SystemServices systemServices,
|
||||
Ikev2SessionCreator ikev2SessionCreator) {
|
||||
mContext = context;
|
||||
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
|
||||
mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
|
||||
mDeps = deps;
|
||||
mNetd = netService;
|
||||
mNms = netService;
|
||||
mNetd = netd;
|
||||
mUserId = userId;
|
||||
mLooper = looper;
|
||||
mSystemServices = systemServices;
|
||||
@@ -912,7 +916,7 @@ public class Vpn {
|
||||
}
|
||||
|
||||
try {
|
||||
mNetd.denyProtect(mOwnerUID);
|
||||
mNms.denyProtect(mOwnerUID);
|
||||
} catch (Exception e) {
|
||||
Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e);
|
||||
}
|
||||
@@ -922,7 +926,7 @@ public class Vpn {
|
||||
mOwnerUID = getAppUid(newPackage, mUserId);
|
||||
mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage);
|
||||
try {
|
||||
mNetd.allowProtect(mOwnerUID);
|
||||
mNms.allowProtect(mOwnerUID);
|
||||
} catch (Exception e) {
|
||||
Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e);
|
||||
}
|
||||
@@ -1579,24 +1583,25 @@ public class Vpn {
|
||||
exemptedPackages = new ArrayList<>(mLockdownAllowlist);
|
||||
exemptedPackages.add(mPackage);
|
||||
}
|
||||
final Set<UidRange> rangesToTellNetdToRemove = new ArraySet<>(mBlockedUidsAsToldToNetd);
|
||||
final Set<UidRangeParcel> rangesToTellNetdToRemove =
|
||||
new ArraySet<>(mBlockedUidsAsToldToNetd);
|
||||
|
||||
final Set<UidRange> rangesToTellNetdToAdd;
|
||||
final Set<UidRangeParcel> rangesToTellNetdToAdd;
|
||||
if (enforce) {
|
||||
final Set<UidRange> rangesThatShouldBeBlocked =
|
||||
final Set<UidRange> restrictedProfilesRanges =
|
||||
createUserAndRestrictedProfilesRanges(mUserId,
|
||||
/* allowedApplications */ null,
|
||||
/* disallowedApplications */ exemptedPackages);
|
||||
/* allowedApplications */ null,
|
||||
/* disallowedApplications */ exemptedPackages);
|
||||
final Set<UidRangeParcel> rangesThatShouldBeBlocked = new ArraySet<>();
|
||||
|
||||
// The UID range of the first user (0-99999) would block the IPSec traffic, which comes
|
||||
// directly from the kernel and is marked as uid=0. So we adjust the range to allow
|
||||
// it through (b/69873852).
|
||||
for (UidRange range : rangesThatShouldBeBlocked) {
|
||||
if (range.start == 0) {
|
||||
rangesThatShouldBeBlocked.remove(range);
|
||||
if (range.stop != 0) {
|
||||
rangesThatShouldBeBlocked.add(new UidRange(1, range.stop));
|
||||
}
|
||||
for (UidRange range : restrictedProfilesRanges) {
|
||||
if (range.start == 0 && range.stop != 0) {
|
||||
rangesThatShouldBeBlocked.add(new UidRangeParcel(1, range.stop));
|
||||
} else if (range.start != 0) {
|
||||
rangesThatShouldBeBlocked.add(new UidRangeParcel(range.start, range.stop));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1628,13 +1633,13 @@ public class Vpn {
|
||||
* including added ranges that already existed or removed ones that didn't.
|
||||
*/
|
||||
@GuardedBy("this")
|
||||
private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRange> ranges) {
|
||||
private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRangeParcel> ranges) {
|
||||
if (ranges.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
final UidRange[] rangesArray = ranges.toArray(new UidRange[ranges.size()]);
|
||||
final UidRangeParcel[] stableRanges = ranges.toArray(new UidRangeParcel[ranges.size()]);
|
||||
try {
|
||||
mNetd.setAllowOnlyVpnForUids(enforce, rangesArray);
|
||||
mNetd.networkRejectNonSecureVpn(enforce, stableRanges);
|
||||
} catch (RemoteException | RuntimeException e) {
|
||||
Log.e(TAG, "Updating blocked=" + enforce
|
||||
+ " for UIDs " + Arrays.toString(ranges.toArray()) + " failed", e);
|
||||
@@ -1849,10 +1854,20 @@ public class Vpn {
|
||||
if (mNetworkInfo.isConnected()) {
|
||||
return !appliesToUid(uid);
|
||||
} else {
|
||||
return UidRange.containsUid(mBlockedUidsAsToldToNetd, uid);
|
||||
return containsUid(mBlockedUidsAsToldToNetd, uid);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean containsUid(Collection<UidRangeParcel> ranges, int uid) {
|
||||
if (ranges == null) return false;
|
||||
for (UidRangeParcel range : ranges) {
|
||||
if (range.start <= uid && uid <= range.stop) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateAlwaysOnNotification(DetailedState networkState) {
|
||||
final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED);
|
||||
|
||||
@@ -2495,7 +2510,7 @@ public class Vpn {
|
||||
address /* unused */,
|
||||
address /* unused */,
|
||||
network);
|
||||
mNetd.setInterfaceUp(mTunnelIface.getInterfaceName());
|
||||
mNms.setInterfaceUp(mTunnelIface.getInterfaceName());
|
||||
|
||||
mSession = mIkev2SessionCreator.createIkeSession(
|
||||
mContext,
|
||||
|
||||
@@ -188,6 +188,7 @@ import android.net.RouteInfo;
|
||||
import android.net.RouteInfoParcel;
|
||||
import android.net.SocketKeepalive;
|
||||
import android.net.UidRange;
|
||||
import android.net.UidRangeParcel;
|
||||
import android.net.Uri;
|
||||
import android.net.VpnManager;
|
||||
import android.net.metrics.IpConnectivityLog;
|
||||
@@ -1055,7 +1056,7 @@ public class ConnectivityServiceTest {
|
||||
|
||||
public MockVpn(int userId) {
|
||||
super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
|
||||
userId, mock(KeyStore.class));
|
||||
mMockNetd, userId, mock(KeyStore.class));
|
||||
mConfig = new VpnConfig();
|
||||
}
|
||||
|
||||
@@ -1094,10 +1095,11 @@ public class ConnectivityServiceTest {
|
||||
mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
|
||||
mNetworkCapabilities);
|
||||
mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
|
||||
verify(mNetworkManagementService, times(1))
|
||||
.addVpnUidRanges(eq(mMockVpn.getNetId()), eq(uids.toArray(new UidRange[0])));
|
||||
verify(mNetworkManagementService, never())
|
||||
.removeVpnUidRanges(eq(mMockVpn.getNetId()), any());
|
||||
|
||||
verify(mMockNetd, times(1)).networkAddUidRanges(eq(mMockVpn.getNetId()),
|
||||
eq(toUidRangeStableParcels(uids)));
|
||||
verify(mMockNetd, never())
|
||||
.networkRemoveUidRanges(eq(mMockVpn.getNetId()), any());
|
||||
mAgentRegistered = true;
|
||||
mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
|
||||
mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
|
||||
@@ -1169,6 +1171,11 @@ public class ConnectivityServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
|
||||
return ranges.stream().map(
|
||||
r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
|
||||
}
|
||||
|
||||
private void mockVpn(int uid) {
|
||||
synchronized (mService.mVpns) {
|
||||
int userId = UserHandle.getUserId(uid);
|
||||
|
||||
@@ -58,6 +58,7 @@ import android.content.pm.ServiceInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.INetd;
|
||||
import android.net.Ikev2VpnProfile;
|
||||
import android.net.InetAddresses;
|
||||
import android.net.IpPrefix;
|
||||
@@ -70,6 +71,7 @@ import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo.DetailedState;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.UidRange;
|
||||
import android.net.UidRangeParcel;
|
||||
import android.net.VpnManager;
|
||||
import android.net.VpnService;
|
||||
import android.net.ipsec.ike.IkeSessionCallback;
|
||||
@@ -172,11 +174,13 @@ public class VpnTest {
|
||||
mPackages.put(PKGS[i], PKG_UIDS[i]);
|
||||
}
|
||||
}
|
||||
private static final UidRange PRI_USER_RANGE = UidRange.createForUser(primaryUser.id);
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
|
||||
@Mock private UserManager mUserManager;
|
||||
@Mock private PackageManager mPackageManager;
|
||||
@Mock private INetworkManagementService mNetService;
|
||||
@Mock private INetd mNetd;
|
||||
@Mock private AppOpsManager mAppOps;
|
||||
@Mock private NotificationManager mNotificationManager;
|
||||
@Mock private Vpn.SystemServices mSystemServices;
|
||||
@@ -256,8 +260,7 @@ public class VpnTest {
|
||||
null, null);
|
||||
|
||||
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
|
||||
UidRange.createForUser(primaryUser.id),
|
||||
UidRange.createForUser(restrictedProfileA.id)
|
||||
PRI_USER_RANGE, UidRange.createForUser(restrictedProfileA.id)
|
||||
})), ranges);
|
||||
}
|
||||
|
||||
@@ -269,9 +272,7 @@ public class VpnTest {
|
||||
final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
|
||||
null, null);
|
||||
|
||||
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
|
||||
UidRange.createForUser(primaryUser.id)
|
||||
})), ranges);
|
||||
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -282,15 +283,13 @@ public class VpnTest {
|
||||
final Set<UidRange> ranges = new ArraySet<>();
|
||||
vpn.addUserToRanges(ranges, primaryUser.id, null, null);
|
||||
|
||||
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
|
||||
UidRange.createForUser(primaryUser.id)
|
||||
})), ranges);
|
||||
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUidAllowAndDenylist() throws Exception {
|
||||
final Vpn vpn = createVpn(primaryUser.id);
|
||||
final UidRange user = UidRange.createForUser(primaryUser.id);
|
||||
final UidRange user = PRI_USER_RANGE;
|
||||
final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
|
||||
|
||||
// Allowed list
|
||||
@@ -339,62 +338,67 @@ public class VpnTest {
|
||||
@Test
|
||||
public void testLockdownChangingPackage() throws Exception {
|
||||
final Vpn vpn = createVpn(primaryUser.id);
|
||||
final UidRange user = UidRange.createForUser(primaryUser.id);
|
||||
final UidRange user = PRI_USER_RANGE;
|
||||
|
||||
// Default state.
|
||||
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
|
||||
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1],
|
||||
user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
|
||||
|
||||
// Set always-on without lockdown.
|
||||
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null, mKeyStore));
|
||||
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
|
||||
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1],
|
||||
user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
|
||||
|
||||
// Set always-on with lockdown.
|
||||
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null, mKeyStore));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||
new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||
}));
|
||||
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
|
||||
|
||||
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2],
|
||||
user.start + PKG_UIDS[3]);
|
||||
assertUnblocked(vpn, user.start + PKG_UIDS[1]);
|
||||
|
||||
// Switch to another app.
|
||||
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
||||
new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||
}));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||
new UidRange(user.start, user.start + PKG_UIDS[3] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
|
||||
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
|
||||
}));
|
||||
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
|
||||
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1],
|
||||
user.start + PKG_UIDS[2]);
|
||||
assertUnblocked(vpn, user.start + PKG_UIDS[3]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockdownAllowlist() throws Exception {
|
||||
final Vpn vpn = createVpn(primaryUser.id);
|
||||
final UidRange user = UidRange.createForUser(primaryUser.id);
|
||||
final UidRange user = PRI_USER_RANGE;
|
||||
|
||||
// Set always-on with lockdown and allow app PKGS[2] from lockdown.
|
||||
assertTrue(vpn.setAlwaysOnPackage(
|
||||
PKGS[1], true, Collections.singletonList(PKGS[2]), mKeyStore));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||
new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
|
||||
}));
|
||||
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
|
||||
assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
|
||||
|
||||
// Change allowed app list to PKGS[3].
|
||||
assertTrue(vpn.setAlwaysOnPackage(
|
||||
PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
||||
new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
|
||||
}));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||
new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
|
||||
}));
|
||||
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2]);
|
||||
assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]);
|
||||
@@ -402,25 +406,25 @@ public class VpnTest {
|
||||
// Change the VPN app.
|
||||
assertTrue(vpn.setAlwaysOnPackage(
|
||||
PKGS[0], true, Collections.singletonList(PKGS[3]), mKeyStore));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
||||
new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1)
|
||||
}));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||
new UidRange(user.start, user.start + PKG_UIDS[0] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start, user.start + PKG_UIDS[0] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1)
|
||||
}));
|
||||
assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
|
||||
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
|
||||
|
||||
// Remove the list of allowed packages.
|
||||
assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
||||
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
|
||||
}));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||
new UidRange(user.start + PKG_UIDS[0] + 1, user.stop),
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop),
|
||||
}));
|
||||
assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2],
|
||||
user.start + PKG_UIDS[3]);
|
||||
@@ -429,12 +433,12 @@ public class VpnTest {
|
||||
// Add the list of allowed packages.
|
||||
assertTrue(vpn.setAlwaysOnPackage(
|
||||
PKGS[0], true, Collections.singletonList(PKGS[1]), mKeyStore));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
||||
new UidRange(user.start + PKG_UIDS[0] + 1, user.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop)
|
||||
}));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||
}));
|
||||
assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
|
||||
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]);
|
||||
@@ -447,13 +451,13 @@ public class VpnTest {
|
||||
// allowed package should change from PGKS[1] to PKGS[2].
|
||||
assertTrue(vpn.setAlwaysOnPackage(
|
||||
PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"), mKeyStore));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[]{
|
||||
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[]{
|
||||
new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
|
||||
}));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[]{
|
||||
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[]{
|
||||
new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -467,86 +471,86 @@ public class VpnTest {
|
||||
restrictedProfileA.flags);
|
||||
tempProfile.restrictedProfileParentId = primaryUser.id;
|
||||
|
||||
final UidRange user = UidRange.createForUser(primaryUser.id);
|
||||
final UidRange user = PRI_USER_RANGE;
|
||||
final UidRange profile = UidRange.createForUser(tempProfile.id);
|
||||
|
||||
// Set lockdown.
|
||||
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore));
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||
new UidRange(user.start, user.start + PKG_UIDS[3] - 1),
|
||||
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1),
|
||||
new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
|
||||
}));
|
||||
|
||||
// Verify restricted user isn't affected at first.
|
||||
assertUnblocked(vpn, profile.start + PKG_UIDS[0]);
|
||||
|
||||
// Add the restricted user.
|
||||
setMockedUsers(primaryUser, tempProfile);
|
||||
vpn.onUserAdded(tempProfile.id);
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
|
||||
new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1),
|
||||
new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1),
|
||||
new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop)
|
||||
}));
|
||||
|
||||
// Remove the restricted user.
|
||||
tempProfile.partial = true;
|
||||
vpn.onUserRemoved(tempProfile.id);
|
||||
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
|
||||
new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1),
|
||||
new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop)
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
|
||||
new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1),
|
||||
new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop)
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockdownRuleRepeatability() throws Exception {
|
||||
final Vpn vpn = createVpn(primaryUser.id);
|
||||
|
||||
final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] {
|
||||
new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)};
|
||||
// Given legacy lockdown is already enabled,
|
||||
vpn.setLockdown(true);
|
||||
verify(mNetService, times(1)).setAllowOnlyVpnForUids(
|
||||
eq(true), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)}));
|
||||
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(primaryUserRangeParcel));
|
||||
|
||||
// Enabling legacy lockdown twice should do nothing.
|
||||
vpn.setLockdown(true);
|
||||
verify(mNetService, times(1)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class));
|
||||
verify(mNetd, times(1))
|
||||
.networkRejectNonSecureVpn(anyBoolean(), any(UidRangeParcel[].class));
|
||||
|
||||
// And disabling should remove the rules exactly once.
|
||||
vpn.setLockdown(false);
|
||||
verify(mNetService, times(1)).setAllowOnlyVpnForUids(
|
||||
eq(false), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)}));
|
||||
verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(primaryUserRangeParcel));
|
||||
|
||||
// Removing the lockdown again should have no effect.
|
||||
vpn.setLockdown(false);
|
||||
verify(mNetService, times(2)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class));
|
||||
verify(mNetd, times(2)).networkRejectNonSecureVpn(
|
||||
anyBoolean(), any(UidRangeParcel[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockdownRuleReversibility() throws Exception {
|
||||
final Vpn vpn = createVpn(primaryUser.id);
|
||||
|
||||
final UidRange[] entireUser = {
|
||||
UidRange.createForUser(primaryUser.id)
|
||||
final UidRangeParcel[] entireUser = {
|
||||
new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)
|
||||
};
|
||||
final UidRange[] exceptPkg0 = {
|
||||
new UidRange(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1),
|
||||
new UidRange(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop)
|
||||
final UidRangeParcel[] exceptPkg0 = {
|
||||
new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1),
|
||||
new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop)
|
||||
};
|
||||
|
||||
final InOrder order = inOrder(mNetService);
|
||||
final InOrder order = inOrder(mNetd);
|
||||
|
||||
// Given lockdown is enabled with no package (legacy VPN),
|
||||
vpn.setLockdown(true);
|
||||
order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser));
|
||||
order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(entireUser));
|
||||
|
||||
// When a new VPN package is set the rules should change to cover that package.
|
||||
vpn.prepare(null, PKGS[0], VpnManager.TYPE_VPN_SERVICE);
|
||||
order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(entireUser));
|
||||
order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(exceptPkg0));
|
||||
order.verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(entireUser));
|
||||
order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(exceptPkg0));
|
||||
|
||||
// When that VPN package is unset, everything should be undone again in reverse.
|
||||
vpn.prepare(null, VpnConfig.LEGACY_VPN, VpnManager.TYPE_VPN_SERVICE);
|
||||
order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(exceptPkg0));
|
||||
order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser));
|
||||
order.verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(exceptPkg0));
|
||||
order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(entireUser));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1186,7 +1190,7 @@ public class VpnTest {
|
||||
.thenReturn(asUserContext);
|
||||
final TestLooper testLooper = new TestLooper();
|
||||
final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService,
|
||||
userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
|
||||
mNetd, userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
|
||||
verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat(
|
||||
provider -> provider.getName().contains("VpnNetworkProvider")
|
||||
));
|
||||
|
||||
Reference in New Issue
Block a user