diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java index 46e7dac845..59d73783dd 100644 --- a/tests/unit/java/com/android/server/connectivity/VpnTest.java +++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java @@ -27,9 +27,11 @@ import static android.content.pm.UserInfo.FLAG_RESTRICTED; import static android.net.ConnectivityManager.NetworkCallback; import static android.net.INetd.IF_STATE_DOWN; import static android.net.INetd.IF_STATE_UP; +import static android.os.Build.VERSION_CODES.S_V2; import static android.os.UserHandle.PER_USER_RANGE; import static com.android.modules.utils.build.SdkLevel.isAtLeastT; +import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import static com.android.testutils.MiscAsserts.assertThrows; import static org.junit.Assert.assertArrayEquals; @@ -83,8 +85,11 @@ import android.net.LinkAddress; import android.net.LinkProperties; import android.net.LocalSocket; import android.net.Network; +import android.net.NetworkAgent; +import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo.DetailedState; +import android.net.NetworkProvider; import android.net.RouteInfo; import android.net.UidRangeParcel; import android.net.VpnManager; @@ -96,6 +101,7 @@ import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.ConditionVariable; import android.os.INetworkManagementService; +import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.UserHandle; @@ -113,12 +119,15 @@ import com.android.internal.R; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; +import com.android.internal.util.HexDump; import com.android.modules.utils.build.SdkLevel; import com.android.server.IpSecService; +import com.android.server.vcn.util.PersistableBundleUtils; import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRunner; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.AdditionalAnswers; @@ -154,10 +163,13 @@ import java.util.stream.Stream; */ @RunWith(DevSdkIgnoreRunner.class) @SmallTest -@DevSdkIgnoreRule.IgnoreUpTo(VERSION_CODES.S_V2) +@IgnoreUpTo(VERSION_CODES.S_V2) public class VpnTest { private static final String TAG = "VpnTest"; + @Rule + public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); + // Mock users static final UserInfo primaryUser = new UserInfo(27, "Primary", FLAG_ADMIN | FLAG_PRIMARY); static final UserInfo secondaryUser = new UserInfo(15, "Secondary", FLAG_ADMIN); @@ -181,13 +193,15 @@ public class VpnTest { private static final String TEST_IFACE_NAME = "TEST_IFACE"; private static final int TEST_TUNNEL_RESOURCE_ID = 0x2345; private static final long TEST_TIMEOUT_MS = 500L; - + private static final String PRIMARY_USER_APP_EXCLUDE_KEY = + "VPN_APP_EXCLUDED_27_com.testvpn.vpn"; /** * Names and UIDs for some fake packages. Important points: * - UID is ordered increasing. * - One pair of packages have consecutive UIDs. */ static final String[] PKGS = {"com.example", "org.example", "net.example", "web.vpn"}; + static final String PKGS_BYTES = getPackageByteString(List.of(PKGS)); static final int[] PKG_UIDS = {10066, 10077, 10078, 10400}; // Mock packages @@ -296,6 +310,17 @@ public class VpnTest { return new Range(start, stop); } + private static String getPackageByteString(List packages) { + try { + return HexDump.toHexString( + PersistableBundleUtils.toDiskStableBytes(PersistableBundleUtils.fromList( + packages, PersistableBundleUtils.STRING_SERIALIZER)), + true /* upperCase */); + } catch (IOException e) { + return null; + } + } + @Test public void testRestrictedProfilesAreAddedToVpn() { setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB); @@ -749,6 +774,47 @@ public class VpnTest { } } + private Vpn prepareVpnForVerifyAppExclusionList() throws Exception { + final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); + when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) + .thenReturn(mVpnProfile.encode()); + when(mVpnProfileStore.get(PRIMARY_USER_APP_EXCLUDE_KEY)) + .thenReturn(HexDump.hexStringToByteArray(PKGS_BYTES)); + + vpn.startVpnProfile(TEST_VPN_PKG); + verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); + vpn.mNetworkAgent = new NetworkAgent(mContext, Looper.getMainLooper(), TAG, + new NetworkCapabilities.Builder().build(), new LinkProperties(), 10 /* score */, + new NetworkAgentConfig.Builder().build(), + new NetworkProvider(mContext, Looper.getMainLooper(), TAG)) {}; + return vpn; + } + + @Test @IgnoreUpTo(S_V2) + public void testSetAndGetAppExclusionList() throws Exception { + final Vpn vpn = prepareVpnForVerifyAppExclusionList(); + verify(mVpnProfileStore, never()).put(eq(PRIMARY_USER_APP_EXCLUDE_KEY), any()); + vpn.setAppExclusionList(TEST_VPN_PKG, Arrays.asList(PKGS)); + verify(mVpnProfileStore) + .put(eq(PRIMARY_USER_APP_EXCLUDE_KEY), + eq(HexDump.hexStringToByteArray(PKGS_BYTES))); + assertEquals(vpn.createUserAndRestrictedProfilesRanges( + primaryUser.id, null, Arrays.asList(PKGS)), + vpn.mNetworkCapabilities.getUids()); + assertEquals(Arrays.asList(PKGS), vpn.getAppExclusionList(TEST_VPN_PKG)); + } + + @Test @IgnoreUpTo(S_V2) + public void testSetAndGetAppExclusionListRestrictedUser() throws Exception { + final Vpn vpn = prepareVpnForVerifyAppExclusionList(); + // Mock it to restricted profile + when(mUserManager.getUserInfo(anyInt())).thenReturn(restrictedProfileA); + // Restricted users cannot configure VPNs + assertThrows(SecurityException.class, + () -> vpn.setAppExclusionList(TEST_VPN_PKG, new ArrayList<>())); + assertThrows(SecurityException.class, () -> vpn.getAppExclusionList(TEST_VPN_PKG)); + } + @Test public void testProvisionVpnProfilePreconsented() throws Exception { final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);