1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.connectivity; 18 19 import static android.Manifest.permission.BIND_VPN_SERVICE; 20 import static android.Manifest.permission.CONTROL_VPN; 21 import static android.content.pm.PackageManager.PERMISSION_DENIED; 22 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 23 import static android.content.pm.UserInfo.FLAG_ADMIN; 24 import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; 25 import static android.content.pm.UserInfo.FLAG_PRIMARY; 26 import static android.content.pm.UserInfo.FLAG_RESTRICTED; 27 import static android.net.ConnectivityManager.NetworkCallback; 28 import static android.net.INetd.IF_STATE_DOWN; 29 import static android.net.INetd.IF_STATE_UP; 30 import static android.net.VpnManager.TYPE_VPN_PLATFORM; 31 import static android.os.Build.VERSION_CODES.S_V2; 32 import static android.os.UserHandle.PER_USER_RANGE; 33 34 import static com.android.modules.utils.build.SdkLevel.isAtLeastT; 35 import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; 36 import static com.android.testutils.MiscAsserts.assertThrows; 37 38 import static org.junit.Assert.assertArrayEquals; 39 import static org.junit.Assert.assertEquals; 40 import static org.junit.Assert.assertFalse; 41 import static org.junit.Assert.assertNotNull; 42 import static org.junit.Assert.assertTrue; 43 import static org.junit.Assert.fail; 44 import static org.junit.Assume.assumeTrue; 45 import static org.mockito.ArgumentMatchers.any; 46 import static org.mockito.ArgumentMatchers.anyBoolean; 47 import static org.mockito.ArgumentMatchers.anyInt; 48 import static org.mockito.ArgumentMatchers.anyLong; 49 import static org.mockito.ArgumentMatchers.anyString; 50 import static org.mockito.ArgumentMatchers.argThat; 51 import static org.mockito.ArgumentMatchers.eq; 52 import static org.mockito.Mockito.after; 53 import static org.mockito.Mockito.atLeastOnce; 54 import static org.mockito.Mockito.doAnswer; 55 import static org.mockito.Mockito.doCallRealMethod; 56 import static org.mockito.Mockito.doNothing; 57 import static org.mockito.Mockito.doReturn; 58 import static org.mockito.Mockito.inOrder; 59 import static org.mockito.Mockito.mock; 60 import static org.mockito.Mockito.never; 61 import static org.mockito.Mockito.reset; 62 import static org.mockito.Mockito.timeout; 63 import static org.mockito.Mockito.times; 64 import static org.mockito.Mockito.verify; 65 import static org.mockito.Mockito.when; 66 67 import android.annotation.NonNull; 68 import android.annotation.UserIdInt; 69 import android.app.AppOpsManager; 70 import android.app.NotificationManager; 71 import android.app.PendingIntent; 72 import android.content.Context; 73 import android.content.Intent; 74 import android.content.pm.ApplicationInfo; 75 import android.content.pm.PackageManager; 76 import android.content.pm.ResolveInfo; 77 import android.content.pm.ServiceInfo; 78 import android.content.pm.UserInfo; 79 import android.content.res.Resources; 80 import android.net.ConnectivityManager; 81 import android.net.INetd; 82 import android.net.Ikev2VpnProfile; 83 import android.net.InetAddresses; 84 import android.net.InterfaceConfigurationParcel; 85 import android.net.IpPrefix; 86 import android.net.IpSecManager; 87 import android.net.IpSecTunnelInterfaceResponse; 88 import android.net.LinkAddress; 89 import android.net.LinkProperties; 90 import android.net.LocalSocket; 91 import android.net.Network; 92 import android.net.NetworkAgent; 93 import android.net.NetworkAgentConfig; 94 import android.net.NetworkCapabilities; 95 import android.net.NetworkInfo.DetailedState; 96 import android.net.NetworkProvider; 97 import android.net.RouteInfo; 98 import android.net.UidRangeParcel; 99 import android.net.VpnManager; 100 import android.net.VpnProfileState; 101 import android.net.VpnService; 102 import android.net.VpnTransportInfo; 103 import android.net.ipsec.ike.IkeSessionCallback; 104 import android.net.ipsec.ike.exceptions.IkeException; 105 import android.net.ipsec.ike.exceptions.IkeNetworkLostException; 106 import android.net.ipsec.ike.exceptions.IkeNonProtocolException; 107 import android.net.ipsec.ike.exceptions.IkeProtocolException; 108 import android.net.ipsec.ike.exceptions.IkeTimeoutException; 109 import android.os.Build.VERSION_CODES; 110 import android.os.Bundle; 111 import android.os.ConditionVariable; 112 import android.os.INetworkManagementService; 113 import android.os.Looper; 114 import android.os.ParcelFileDescriptor; 115 import android.os.PowerWhitelistManager; 116 import android.os.Process; 117 import android.os.UserHandle; 118 import android.os.UserManager; 119 import android.os.test.TestLooper; 120 import android.provider.Settings; 121 import android.security.Credentials; 122 import android.util.ArrayMap; 123 import android.util.ArraySet; 124 import android.util.Range; 125 126 import androidx.test.filters.SmallTest; 127 128 import com.android.internal.R; 129 import com.android.internal.net.LegacyVpnInfo; 130 import com.android.internal.net.VpnConfig; 131 import com.android.internal.net.VpnProfile; 132 import com.android.internal.util.HexDump; 133 import com.android.modules.utils.build.SdkLevel; 134 import com.android.server.DeviceIdleInternal; 135 import com.android.server.IpSecService; 136 import com.android.server.vcn.util.PersistableBundleUtils; 137 import com.android.testutils.DevSdkIgnoreRule; 138 import com.android.testutils.DevSdkIgnoreRunner; 139 140 import org.junit.After; 141 import org.junit.Before; 142 import org.junit.Rule; 143 import org.junit.Test; 144 import org.junit.runner.RunWith; 145 import org.mockito.AdditionalAnswers; 146 import org.mockito.Answers; 147 import org.mockito.ArgumentCaptor; 148 import org.mockito.InOrder; 149 import org.mockito.Mock; 150 import org.mockito.MockitoAnnotations; 151 152 import java.io.BufferedWriter; 153 import java.io.File; 154 import java.io.FileDescriptor; 155 import java.io.FileWriter; 156 import java.io.IOException; 157 import java.net.Inet4Address; 158 import java.net.InetAddress; 159 import java.net.UnknownHostException; 160 import java.util.ArrayList; 161 import java.util.Arrays; 162 import java.util.Collections; 163 import java.util.HashMap; 164 import java.util.List; 165 import java.util.Map; 166 import java.util.Set; 167 import java.util.concurrent.CompletableFuture; 168 import java.util.concurrent.TimeUnit; 169 import java.util.stream.Stream; 170 171 /** 172 * Tests for {@link Vpn}. 173 * 174 * Build, install and run with: 175 * runtest frameworks-net -c com.android.server.connectivity.VpnTest 176 */ 177 @RunWith(DevSdkIgnoreRunner.class) 178 @SmallTest 179 @IgnoreUpTo(VERSION_CODES.S_V2) 180 public class VpnTest { 181 private static final String TAG = "VpnTest"; 182 183 @Rule 184 public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); 185 186 // Mock users 187 static final UserInfo primaryUser = new UserInfo(27, "Primary", FLAG_ADMIN | FLAG_PRIMARY); 188 static final UserInfo secondaryUser = new UserInfo(15, "Secondary", FLAG_ADMIN); 189 static final UserInfo restrictedProfileA = new UserInfo(40, "RestrictedA", FLAG_RESTRICTED); 190 static final UserInfo restrictedProfileB = new UserInfo(42, "RestrictedB", FLAG_RESTRICTED); 191 static final UserInfo managedProfileA = new UserInfo(45, "ManagedA", FLAG_MANAGED_PROFILE); 192 static { 193 restrictedProfileA.restrictedProfileParentId = primaryUser.id; 194 restrictedProfileB.restrictedProfileParentId = secondaryUser.id; 195 managedProfileA.profileGroupId = primaryUser.id; 196 } 197 198 static final Network EGRESS_NETWORK = new Network(101); 199 static final String EGRESS_IFACE = "wlan0"; 200 static final String TEST_VPN_PKG = "com.testvpn.vpn"; 201 private static final String TEST_VPN_SERVER = "1.2.3.4"; 202 private static final String TEST_VPN_IDENTITY = "identity"; 203 private static final byte[] TEST_VPN_PSK = "psk".getBytes(); 204 205 private static final Network TEST_NETWORK = new Network(Integer.MAX_VALUE); 206 private static final String TEST_IFACE_NAME = "TEST_IFACE"; 207 private static final int TEST_TUNNEL_RESOURCE_ID = 0x2345; 208 private static final long TEST_TIMEOUT_MS = 500L; 209 private static final String PRIMARY_USER_APP_EXCLUDE_KEY = 210 "VPNAPPEXCLUDED_27_com.testvpn.vpn"; 211 /** 212 * Names and UIDs for some fake packages. Important points: 213 * - UID is ordered increasing. 214 * - One pair of packages have consecutive UIDs. 215 */ 216 static final String[] PKGS = {"com.example", "org.example", "net.example", "web.vpn"}; 217 static final String PKGS_BYTES = getPackageByteString(List.of(PKGS)); 218 static final int[] PKG_UIDS = {10066, 10077, 10078, 10400}; 219 220 // Mock packages 221 static final Map<String, Integer> mPackages = new ArrayMap<>(); 222 static { 223 for (int i = 0; i < PKGS.length; i++) { mPackages.put(PKGS[i], PKG_UIDS[i])224 mPackages.put(PKGS[i], PKG_UIDS[i]); 225 } 226 } 227 private static final Range<Integer> PRI_USER_RANGE = uidRangeForUser(primaryUser.id); 228 229 @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; 230 @Mock private UserManager mUserManager; 231 @Mock private PackageManager mPackageManager; 232 @Mock private INetworkManagementService mNetService; 233 @Mock private INetd mNetd; 234 @Mock private AppOpsManager mAppOps; 235 @Mock private NotificationManager mNotificationManager; 236 @Mock private Vpn.SystemServices mSystemServices; 237 @Mock private Vpn.Ikev2SessionCreator mIkev2SessionCreator; 238 @Mock private ConnectivityManager mConnectivityManager; 239 @Mock private IpSecService mIpSecService; 240 @Mock private VpnProfileStore mVpnProfileStore; 241 @Mock DeviceIdleInternal mDeviceIdleInternal; 242 private final VpnProfile mVpnProfile; 243 244 private IpSecManager mIpSecManager; 245 VpnTest()246 public VpnTest() throws Exception { 247 // Build an actual VPN profile that is capable of being converted to and from an 248 // Ikev2VpnProfile 249 final Ikev2VpnProfile.Builder builder = 250 new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY); 251 builder.setAuthPsk(TEST_VPN_PSK); 252 mVpnProfile = builder.build().toVpnProfile(); 253 } 254 255 @Before setUp()256 public void setUp() throws Exception { 257 MockitoAnnotations.initMocks(this); 258 259 mIpSecManager = new IpSecManager(mContext, mIpSecService); 260 261 when(mContext.getPackageManager()).thenReturn(mPackageManager); 262 setMockedPackages(mPackages); 263 264 when(mContext.getPackageName()).thenReturn(TEST_VPN_PKG); 265 when(mContext.getOpPackageName()).thenReturn(TEST_VPN_PKG); 266 mockService(UserManager.class, Context.USER_SERVICE, mUserManager); 267 mockService(AppOpsManager.class, Context.APP_OPS_SERVICE, mAppOps); 268 mockService(NotificationManager.class, Context.NOTIFICATION_SERVICE, mNotificationManager); 269 mockService(ConnectivityManager.class, Context.CONNECTIVITY_SERVICE, mConnectivityManager); 270 mockService(IpSecManager.class, Context.IPSEC_SERVICE, mIpSecManager); 271 when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)) 272 .thenReturn(Resources.getSystem().getString( 273 R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)); 274 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) 275 .thenReturn(true); 276 277 // Used by {@link Notification.Builder} 278 ApplicationInfo applicationInfo = new ApplicationInfo(); 279 applicationInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT; 280 when(mContext.getApplicationInfo()).thenReturn(applicationInfo); 281 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 282 .thenReturn(applicationInfo); 283 284 doNothing().when(mNetService).registerObserver(any()); 285 286 // Deny all appops by default. 287 when(mAppOps.noteOpNoThrow(anyString(), anyInt(), anyString(), any(), any())) 288 .thenReturn(AppOpsManager.MODE_IGNORED); 289 290 // Setup IpSecService 291 final IpSecTunnelInterfaceResponse tunnelResp = 292 new IpSecTunnelInterfaceResponse( 293 IpSecManager.Status.OK, TEST_TUNNEL_RESOURCE_ID, TEST_IFACE_NAME); 294 when(mIpSecService.createTunnelInterface(any(), any(), any(), any(), any())) 295 .thenReturn(tunnelResp); 296 // The unit test should know what kind of permission it needs and set the permission by 297 // itself, so set the default value of Context#checkCallingOrSelfPermission to 298 // PERMISSION_DENIED. 299 doReturn(PERMISSION_DENIED).when(mContext).checkCallingOrSelfPermission(any()); 300 } 301 302 @After tearDown()303 public void tearDown() throws Exception { 304 doReturn(PERMISSION_DENIED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN); 305 } 306 mockService(Class<T> clazz, String name, T service)307 private <T> void mockService(Class<T> clazz, String name, T service) { 308 doReturn(service).when(mContext).getSystemService(name); 309 doReturn(name).when(mContext).getSystemServiceName(clazz); 310 if (mContext.getSystemService(clazz).getClass().equals(Object.class)) { 311 // Test is using mockito-extended (mContext uses Answers.RETURNS_DEEP_STUBS and returned 312 // a mock object on a final method) 313 doCallRealMethod().when(mContext).getSystemService(clazz); 314 } 315 } 316 rangeSet(Range<Integer> .... ranges)317 private Set<Range<Integer>> rangeSet(Range<Integer> ... ranges) { 318 final Set<Range<Integer>> range = new ArraySet<>(); 319 for (Range<Integer> r : ranges) range.add(r); 320 321 return range; 322 } 323 uidRangeForUser(int userId)324 private static Range<Integer> uidRangeForUser(int userId) { 325 return new Range<Integer>(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1); 326 } 327 uidRange(int start, int stop)328 private Range<Integer> uidRange(int start, int stop) { 329 return new Range<Integer>(start, stop); 330 } 331 getPackageByteString(List<String> packages)332 private static String getPackageByteString(List<String> packages) { 333 try { 334 return HexDump.toHexString( 335 PersistableBundleUtils.toDiskStableBytes(PersistableBundleUtils.fromList( 336 packages, PersistableBundleUtils.STRING_SERIALIZER)), 337 true /* upperCase */); 338 } catch (IOException e) { 339 return null; 340 } 341 } 342 343 @Test testRestrictedProfilesAreAddedToVpn()344 public void testRestrictedProfilesAreAddedToVpn() { 345 setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB); 346 347 final Vpn vpn = createVpn(primaryUser.id); 348 349 // Assume the user can have restricted profiles. 350 doReturn(true).when(mUserManager).canHaveRestrictedProfile(); 351 final Set<Range<Integer>> ranges = 352 vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); 353 354 assertEquals(rangeSet(PRI_USER_RANGE, uidRangeForUser(restrictedProfileA.id)), ranges); 355 } 356 357 @Test testManagedProfilesAreNotAddedToVpn()358 public void testManagedProfilesAreNotAddedToVpn() { 359 setMockedUsers(primaryUser, managedProfileA); 360 361 final Vpn vpn = createVpn(primaryUser.id); 362 final Set<Range<Integer>> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, 363 null, null); 364 365 assertEquals(rangeSet(PRI_USER_RANGE), ranges); 366 } 367 368 @Test testAddUserToVpnOnlyAddsOneUser()369 public void testAddUserToVpnOnlyAddsOneUser() { 370 setMockedUsers(primaryUser, restrictedProfileA, managedProfileA); 371 372 final Vpn vpn = createVpn(primaryUser.id); 373 final Set<Range<Integer>> ranges = new ArraySet<>(); 374 vpn.addUserToRanges(ranges, primaryUser.id, null, null); 375 376 assertEquals(rangeSet(PRI_USER_RANGE), ranges); 377 } 378 379 @Test testUidAllowAndDenylist()380 public void testUidAllowAndDenylist() throws Exception { 381 final Vpn vpn = createVpn(primaryUser.id); 382 final Range<Integer> user = PRI_USER_RANGE; 383 final int userStart = user.getLower(); 384 final int userStop = user.getUpper(); 385 final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; 386 387 // Allowed list 388 final Set<Range<Integer>> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, 389 Arrays.asList(packages), null /* disallowedApplications */); 390 assertEquals(rangeSet( 391 uidRange(userStart + PKG_UIDS[0], userStart + PKG_UIDS[0]), 392 uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2]), 393 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[0]), 394 Process.toSdkSandboxUid(userStart + PKG_UIDS[0])), 395 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[1]), 396 Process.toSdkSandboxUid(userStart + PKG_UIDS[2]))), 397 allow); 398 399 // Denied list 400 final Set<Range<Integer>> disallow = 401 vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, 402 null /* allowedApplications */, Arrays.asList(packages)); 403 assertEquals(rangeSet( 404 uidRange(userStart, userStart + PKG_UIDS[0] - 1), 405 uidRange(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), 406 /* Empty range between UIDS[1] and UIDS[2], should be excluded, */ 407 uidRange(userStart + PKG_UIDS[2] + 1, 408 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 409 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 410 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 411 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop)), 412 disallow); 413 } 414 verifyPowerSaveTempWhitelistApp(String packageName)415 private void verifyPowerSaveTempWhitelistApp(String packageName) { 416 verify(mDeviceIdleInternal).addPowerSaveTempWhitelistApp(anyInt(), eq(packageName), 417 anyLong(), anyInt(), eq(false), eq(PowerWhitelistManager.REASON_VPN), 418 eq("VpnManager event")); 419 } 420 421 @Test testGetAlwaysAndOnGetLockDown()422 public void testGetAlwaysAndOnGetLockDown() throws Exception { 423 final Vpn vpn = createVpn(primaryUser.id); 424 425 // Default state. 426 assertFalse(vpn.getAlwaysOn()); 427 assertFalse(vpn.getLockdown()); 428 429 // Set always-on without lockdown. 430 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList())); 431 assertTrue(vpn.getAlwaysOn()); 432 assertFalse(vpn.getLockdown()); 433 434 // Set always-on with lockdown. 435 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList())); 436 assertTrue(vpn.getAlwaysOn()); 437 assertTrue(vpn.getLockdown()); 438 439 // Remove always-on configuration. 440 assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList())); 441 assertFalse(vpn.getAlwaysOn()); 442 assertFalse(vpn.getLockdown()); 443 } 444 445 @Test testLockdownChangingPackage()446 public void testLockdownChangingPackage() throws Exception { 447 final Vpn vpn = createVpn(primaryUser.id); 448 final Range<Integer> user = PRI_USER_RANGE; 449 final int userStart = user.getLower(); 450 final int userStop = user.getUpper(); 451 // Set always-on without lockdown. 452 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null)); 453 454 // Set always-on with lockdown. 455 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null)); 456 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 457 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), 458 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, 459 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 460 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) 461 })); 462 463 // Switch to another app. 464 assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null)); 465 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 466 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), 467 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, 468 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 469 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) 470 })); 471 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 472 new UidRangeParcel(userStart, userStart + PKG_UIDS[3] - 1), 473 new UidRangeParcel(userStart + PKG_UIDS[3] + 1, 474 Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)), 475 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop) 476 })); 477 } 478 479 @Test testLockdownAllowlist()480 public void testLockdownAllowlist() throws Exception { 481 final Vpn vpn = createVpn(primaryUser.id); 482 final Range<Integer> user = PRI_USER_RANGE; 483 final int userStart = user.getLower(); 484 final int userStop = user.getUpper(); 485 // Set always-on with lockdown and allow app PKGS[2] from lockdown. 486 assertTrue(vpn.setAlwaysOnPackage( 487 PKGS[1], true, Collections.singletonList(PKGS[2]))); 488 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 489 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), 490 new UidRangeParcel(userStart + PKG_UIDS[2] + 1, 491 Process.toSdkSandboxUid(userStart + PKG_UIDS[1]) - 1), 492 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop) 493 })); 494 // Change allowed app list to PKGS[3]. 495 assertTrue(vpn.setAlwaysOnPackage( 496 PKGS[1], true, Collections.singletonList(PKGS[3]))); 497 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 498 new UidRangeParcel(userStart + PKG_UIDS[2] + 1, 499 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 500 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop) 501 })); 502 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 503 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1), 504 new UidRangeParcel(userStart + PKG_UIDS[3] + 1, 505 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 506 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), 507 Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)), 508 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop) 509 })); 510 511 // Change the VPN app. 512 assertTrue(vpn.setAlwaysOnPackage( 513 PKGS[0], true, Collections.singletonList(PKGS[3]))); 514 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 515 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), 516 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1), 517 new UidRangeParcel(userStart + PKG_UIDS[3] + 1, 518 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 519 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), 520 Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)) 521 })); 522 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 523 new UidRangeParcel(userStart, userStart + PKG_UIDS[0] - 1), 524 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1), 525 new UidRangeParcel(userStart + PKG_UIDS[3] + 1, 526 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 527 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 528 Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)) 529 })); 530 531 // Remove the list of allowed packages. 532 assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null)); 533 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 534 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1), 535 new UidRangeParcel(userStart + PKG_UIDS[3] + 1, 536 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 537 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 538 Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)), 539 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop) 540 })); 541 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 542 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, 543 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 544 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), userStop), 545 })); 546 547 // Add the list of allowed packages. 548 assertTrue(vpn.setAlwaysOnPackage( 549 PKGS[0], true, Collections.singletonList(PKGS[1]))); 550 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 551 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, 552 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 553 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), userStop), 554 })); 555 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 556 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), 557 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, 558 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 559 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 560 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 561 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) 562 })); 563 564 // Try allowing a package with a comma, should be rejected. 565 assertFalse(vpn.setAlwaysOnPackage( 566 PKGS[0], true, Collections.singletonList("a.b,c.d"))); 567 568 // Pass a non-existent packages in the allowlist, they (and only they) should be ignored. 569 // allowed package should change from PGKS[1] to PKGS[2]. 570 assertTrue(vpn.setAlwaysOnPackage( 571 PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"))); 572 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 573 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), 574 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, 575 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 576 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 577 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 578 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) 579 })); 580 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 581 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[2] - 1), 582 new UidRangeParcel(userStart + PKG_UIDS[2] + 1, 583 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 584 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 585 Process.toSdkSandboxUid(userStart + PKG_UIDS[2] - 1)), 586 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop) 587 })); 588 } 589 590 @Test testLockdownRuleRepeatability()591 public void testLockdownRuleRepeatability() throws Exception { 592 final Vpn vpn = createVpn(primaryUser.id); 593 final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] { 594 new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper())}; 595 // Given legacy lockdown is already enabled, 596 vpn.setLockdown(true); 597 verify(mConnectivityManager, times(1)).setRequireVpnForUids(true, 598 toRanges(primaryUserRangeParcel)); 599 600 // Enabling legacy lockdown twice should do nothing. 601 vpn.setLockdown(true); 602 verify(mConnectivityManager, times(1)).setRequireVpnForUids(anyBoolean(), any()); 603 604 // And disabling should remove the rules exactly once. 605 vpn.setLockdown(false); 606 verify(mConnectivityManager, times(1)).setRequireVpnForUids(false, 607 toRanges(primaryUserRangeParcel)); 608 609 // Removing the lockdown again should have no effect. 610 vpn.setLockdown(false); 611 verify(mConnectivityManager, times(2)).setRequireVpnForUids(anyBoolean(), any()); 612 } 613 toRanges(UidRangeParcel[] ranges)614 private ArrayList<Range<Integer>> toRanges(UidRangeParcel[] ranges) { 615 ArrayList<Range<Integer>> rangesArray = new ArrayList<>(ranges.length); 616 for (int i = 0; i < ranges.length; i++) { 617 rangesArray.add(new Range<>(ranges[i].start, ranges[i].stop)); 618 } 619 return rangesArray; 620 } 621 622 @Test testLockdownRuleReversibility()623 public void testLockdownRuleReversibility() throws Exception { 624 doReturn(PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN); 625 final Vpn vpn = createVpn(primaryUser.id); 626 final UidRangeParcel[] entireUser = { 627 new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper()) 628 }; 629 final UidRangeParcel[] exceptPkg0 = { 630 new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), 631 new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1, 632 Process.toSdkSandboxUid(entireUser[0].start + PKG_UIDS[0] - 1)), 633 new UidRangeParcel(Process.toSdkSandboxUid(entireUser[0].start + PKG_UIDS[0] + 1), 634 entireUser[0].stop), 635 }; 636 637 final InOrder order = inOrder(mConnectivityManager); 638 639 // Given lockdown is enabled with no package (legacy VPN), 640 vpn.setLockdown(true); 641 order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(entireUser)); 642 643 // When a new VPN package is set the rules should change to cover that package. 644 vpn.prepare(null, PKGS[0], VpnManager.TYPE_VPN_SERVICE); 645 order.verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(entireUser)); 646 order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(exceptPkg0)); 647 648 // When that VPN package is unset, everything should be undone again in reverse. 649 vpn.prepare(null, VpnConfig.LEGACY_VPN, VpnManager.TYPE_VPN_SERVICE); 650 order.verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(exceptPkg0)); 651 order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(entireUser)); 652 } 653 654 @Test testPrepare_throwSecurityExceptionWhenGivenPackageDoesNotBelongToTheCaller()655 public void testPrepare_throwSecurityExceptionWhenGivenPackageDoesNotBelongToTheCaller() 656 throws Exception { 657 assumeTrue(isAtLeastT()); 658 final Vpn vpn = createVpnAndSetupUidChecks(); 659 assertThrows(SecurityException.class, 660 () -> vpn.prepare("com.not.vpn.owner", null, VpnManager.TYPE_VPN_SERVICE)); 661 assertThrows(SecurityException.class, 662 () -> vpn.prepare(null, "com.not.vpn.owner", VpnManager.TYPE_VPN_SERVICE)); 663 assertThrows(SecurityException.class, 664 () -> vpn.prepare("com.not.vpn.owner1", "com.not.vpn.owner2", 665 VpnManager.TYPE_VPN_SERVICE)); 666 } 667 668 @Test testPrepare_bothOldPackageAndNewPackageAreNull()669 public void testPrepare_bothOldPackageAndNewPackageAreNull() throws Exception { 670 final Vpn vpn = createVpnAndSetupUidChecks(); 671 assertTrue(vpn.prepare(null, null, VpnManager.TYPE_VPN_SERVICE)); 672 673 } 674 675 @Test testIsAlwaysOnPackageSupported()676 public void testIsAlwaysOnPackageSupported() throws Exception { 677 final Vpn vpn = createVpn(primaryUser.id); 678 679 ApplicationInfo appInfo = new ApplicationInfo(); 680 when(mPackageManager.getApplicationInfoAsUser(eq(PKGS[0]), anyInt(), eq(primaryUser.id))) 681 .thenReturn(appInfo); 682 683 ServiceInfo svcInfo = new ServiceInfo(); 684 ResolveInfo resInfo = new ResolveInfo(); 685 resInfo.serviceInfo = svcInfo; 686 when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA), 687 eq(primaryUser.id))) 688 .thenReturn(Collections.singletonList(resInfo)); 689 690 // null package name should return false 691 assertFalse(vpn.isAlwaysOnPackageSupported(null)); 692 693 // Pre-N apps are not supported 694 appInfo.targetSdkVersion = VERSION_CODES.M; 695 assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); 696 697 // N+ apps are supported by default 698 appInfo.targetSdkVersion = VERSION_CODES.N; 699 assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0])); 700 701 // Apps that opt out explicitly are not supported 702 appInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT; 703 Bundle metaData = new Bundle(); 704 metaData.putBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, false); 705 svcInfo.metaData = metaData; 706 assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); 707 } 708 709 @Test testNotificationShownForAlwaysOnApp()710 public void testNotificationShownForAlwaysOnApp() throws Exception { 711 final UserHandle userHandle = UserHandle.of(primaryUser.id); 712 final Vpn vpn = createVpn(primaryUser.id); 713 setMockedUsers(primaryUser); 714 715 final InOrder order = inOrder(mNotificationManager); 716 717 // Don't show a notification for regular disconnected states. 718 vpn.updateState(DetailedState.DISCONNECTED, TAG); 719 order.verify(mNotificationManager, atLeastOnce()).cancel(anyString(), anyInt()); 720 721 // Start showing a notification for disconnected once always-on. 722 vpn.setAlwaysOnPackage(PKGS[0], false, null); 723 order.verify(mNotificationManager).notify(anyString(), anyInt(), any()); 724 725 // Stop showing the notification once connected. 726 vpn.updateState(DetailedState.CONNECTED, TAG); 727 order.verify(mNotificationManager).cancel(anyString(), anyInt()); 728 729 // Show the notification if we disconnect again. 730 vpn.updateState(DetailedState.DISCONNECTED, TAG); 731 order.verify(mNotificationManager).notify(anyString(), anyInt(), any()); 732 733 // Notification should be cleared after unsetting always-on package. 734 vpn.setAlwaysOnPackage(null, false, null); 735 order.verify(mNotificationManager).cancel(anyString(), anyInt()); 736 } 737 738 /** 739 * The profile name should NOT change between releases for backwards compatibility 740 * 741 * <p>If this is changed between releases, the {@link Vpn#getVpnProfilePrivileged()} method MUST 742 * be updated to ensure backward compatibility. 743 */ 744 @Test testGetProfileNameForPackage()745 public void testGetProfileNameForPackage() throws Exception { 746 final Vpn vpn = createVpn(primaryUser.id); 747 setMockedUsers(primaryUser); 748 749 final String expected = Credentials.PLATFORM_VPN + primaryUser.id + "_" + TEST_VPN_PKG; 750 assertEquals(expected, vpn.getProfileNameForPackage(TEST_VPN_PKG)); 751 } 752 createVpnAndSetupUidChecks(String... grantedOps)753 private Vpn createVpnAndSetupUidChecks(String... grantedOps) throws Exception { 754 return createVpnAndSetupUidChecks(primaryUser, grantedOps); 755 } 756 createVpnAndSetupUidChecks(UserInfo user, String... grantedOps)757 private Vpn createVpnAndSetupUidChecks(UserInfo user, String... grantedOps) throws Exception { 758 final Vpn vpn = createVpn(user.id); 759 setMockedUsers(user); 760 761 when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt())) 762 .thenReturn(Process.myUid()); 763 764 for (final String opStr : grantedOps) { 765 when(mAppOps.noteOpNoThrow(opStr, Process.myUid(), TEST_VPN_PKG, 766 null /* attributionTag */, null /* message */)) 767 .thenReturn(AppOpsManager.MODE_ALLOWED); 768 } 769 770 return vpn; 771 } 772 checkProvisionVpnProfile(Vpn vpn, boolean expectedResult, String... checkedOps)773 private void checkProvisionVpnProfile(Vpn vpn, boolean expectedResult, String... checkedOps) { 774 assertEquals(expectedResult, vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile)); 775 776 // The profile should always be stored, whether or not consent has been previously granted. 777 verify(mVpnProfileStore) 778 .put( 779 eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)), 780 eq(mVpnProfile.encode())); 781 782 for (final String checkedOpStr : checkedOps) { 783 verify(mAppOps).noteOpNoThrow(checkedOpStr, Process.myUid(), TEST_VPN_PKG, 784 null /* attributionTag */, null /* message */); 785 } 786 } 787 788 @Test testProvisionVpnProfileNoIpsecTunnels()789 public void testProvisionVpnProfileNoIpsecTunnels() throws Exception { 790 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) 791 .thenReturn(false); 792 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 793 794 try { 795 checkProvisionVpnProfile( 796 vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 797 fail("Expected exception due to missing feature"); 798 } catch (UnsupportedOperationException expected) { 799 } 800 } 801 prepareVpnForVerifyAppExclusionList()802 private Vpn prepareVpnForVerifyAppExclusionList() throws Exception { 803 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 804 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 805 .thenReturn(mVpnProfile.encode()); 806 when(mVpnProfileStore.get(PRIMARY_USER_APP_EXCLUDE_KEY)) 807 .thenReturn(HexDump.hexStringToByteArray(PKGS_BYTES)); 808 809 vpn.startVpnProfile(TEST_VPN_PKG); 810 verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); 811 vpn.mNetworkAgent = new NetworkAgent(mContext, Looper.getMainLooper(), TAG, 812 new NetworkCapabilities.Builder().build(), new LinkProperties(), 10 /* score */, 813 new NetworkAgentConfig.Builder().build(), 814 new NetworkProvider(mContext, Looper.getMainLooper(), TAG)) {}; 815 return vpn; 816 } 817 818 @Test @IgnoreUpTo(S_V2) testSetAndGetAppExclusionList()819 public void testSetAndGetAppExclusionList() throws Exception { 820 final Vpn vpn = prepareVpnForVerifyAppExclusionList(); 821 verify(mVpnProfileStore, never()).put(eq(PRIMARY_USER_APP_EXCLUDE_KEY), any()); 822 vpn.setAppExclusionList(TEST_VPN_PKG, Arrays.asList(PKGS)); 823 verify(mVpnProfileStore) 824 .put(eq(PRIMARY_USER_APP_EXCLUDE_KEY), 825 eq(HexDump.hexStringToByteArray(PKGS_BYTES))); 826 assertEquals(vpn.createUserAndRestrictedProfilesRanges( 827 primaryUser.id, null, Arrays.asList(PKGS)), 828 vpn.mNetworkCapabilities.getUids()); 829 assertEquals(Arrays.asList(PKGS), vpn.getAppExclusionList(TEST_VPN_PKG)); 830 } 831 832 @Test @IgnoreUpTo(S_V2) testSetAndGetAppExclusionListRestrictedUser()833 public void testSetAndGetAppExclusionListRestrictedUser() throws Exception { 834 final Vpn vpn = prepareVpnForVerifyAppExclusionList(); 835 // Mock it to restricted profile 836 when(mUserManager.getUserInfo(anyInt())).thenReturn(restrictedProfileA); 837 // Restricted users cannot configure VPNs 838 assertThrows(SecurityException.class, 839 () -> vpn.setAppExclusionList(TEST_VPN_PKG, new ArrayList<>())); 840 841 assertEquals(Arrays.asList(PKGS), vpn.getAppExclusionList(TEST_VPN_PKG)); 842 } 843 844 @Test testProvisionVpnProfilePreconsented()845 public void testProvisionVpnProfilePreconsented() throws Exception { 846 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 847 848 checkProvisionVpnProfile( 849 vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 850 } 851 852 @Test testProvisionVpnProfileNotPreconsented()853 public void testProvisionVpnProfileNotPreconsented() throws Exception { 854 final Vpn vpn = createVpnAndSetupUidChecks(); 855 856 // Expect that both the ACTIVATE_VPN and ACTIVATE_PLATFORM_VPN were tried, but the caller 857 // had neither. 858 checkProvisionVpnProfile(vpn, false /* expectedResult */, 859 AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN, AppOpsManager.OPSTR_ACTIVATE_VPN); 860 } 861 862 @Test testProvisionVpnProfileVpnServicePreconsented()863 public void testProvisionVpnProfileVpnServicePreconsented() throws Exception { 864 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN); 865 866 checkProvisionVpnProfile(vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_VPN); 867 } 868 869 @Test testProvisionVpnProfileTooLarge()870 public void testProvisionVpnProfileTooLarge() throws Exception { 871 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 872 873 final VpnProfile bigProfile = new VpnProfile(""); 874 bigProfile.name = new String(new byte[Vpn.MAX_VPN_PROFILE_SIZE_BYTES + 1]); 875 876 try { 877 vpn.provisionVpnProfile(TEST_VPN_PKG, bigProfile); 878 fail("Expected IAE due to profile size"); 879 } catch (IllegalArgumentException expected) { 880 } 881 } 882 883 @Test testProvisionVpnProfileRestrictedUser()884 public void testProvisionVpnProfileRestrictedUser() throws Exception { 885 final Vpn vpn = 886 createVpnAndSetupUidChecks( 887 restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 888 889 try { 890 vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile); 891 fail("Expected SecurityException due to restricted user"); 892 } catch (SecurityException expected) { 893 } 894 } 895 896 @Test testDeleteVpnProfile()897 public void testDeleteVpnProfile() throws Exception { 898 final Vpn vpn = createVpnAndSetupUidChecks(); 899 900 vpn.deleteVpnProfile(TEST_VPN_PKG); 901 902 verify(mVpnProfileStore) 903 .remove(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); 904 } 905 906 @Test testDeleteVpnProfileRestrictedUser()907 public void testDeleteVpnProfileRestrictedUser() throws Exception { 908 final Vpn vpn = 909 createVpnAndSetupUidChecks( 910 restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 911 912 try { 913 vpn.deleteVpnProfile(TEST_VPN_PKG); 914 fail("Expected SecurityException due to restricted user"); 915 } catch (SecurityException expected) { 916 } 917 } 918 919 @Test testGetVpnProfilePrivileged()920 public void testGetVpnProfilePrivileged() throws Exception { 921 final Vpn vpn = createVpnAndSetupUidChecks(); 922 923 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 924 .thenReturn(new VpnProfile("").encode()); 925 926 vpn.getVpnProfilePrivileged(TEST_VPN_PKG); 927 928 verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); 929 } 930 verifyPlatformVpnIsActivated(String packageName)931 private void verifyPlatformVpnIsActivated(String packageName) { 932 verify(mAppOps).noteOpNoThrow( 933 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), 934 eq(Process.myUid()), 935 eq(packageName), 936 eq(null) /* attributionTag */, 937 eq(null) /* message */); 938 verify(mAppOps).startOp( 939 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER), 940 eq(Process.myUid()), 941 eq(packageName), 942 eq(null) /* attributionTag */, 943 eq(null) /* message */); 944 } 945 verifyPlatformVpnIsDeactivated(String packageName)946 private void verifyPlatformVpnIsDeactivated(String packageName) { 947 // Add a small delay to double confirm that finishOp is only called once. 948 verify(mAppOps, after(100)).finishOp( 949 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER), 950 eq(Process.myUid()), 951 eq(packageName), 952 eq(null) /* attributionTag */); 953 } 954 955 @Test testStartVpnProfile()956 public void testStartVpnProfile() throws Exception { 957 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 958 959 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 960 .thenReturn(mVpnProfile.encode()); 961 962 vpn.startVpnProfile(TEST_VPN_PKG); 963 964 verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); 965 verifyPlatformVpnIsActivated(TEST_VPN_PKG); 966 } 967 968 @Test testStartVpnProfileVpnServicePreconsented()969 public void testStartVpnProfileVpnServicePreconsented() throws Exception { 970 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN); 971 972 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 973 .thenReturn(mVpnProfile.encode()); 974 975 vpn.startVpnProfile(TEST_VPN_PKG); 976 977 // Verify that the ACTIVATE_VPN appop was checked, but no error was thrown. 978 verify(mAppOps).noteOpNoThrow(AppOpsManager.OPSTR_ACTIVATE_VPN, Process.myUid(), 979 TEST_VPN_PKG, null /* attributionTag */, null /* message */); 980 } 981 982 @Test testStartVpnProfileNotConsented()983 public void testStartVpnProfileNotConsented() throws Exception { 984 final Vpn vpn = createVpnAndSetupUidChecks(); 985 986 try { 987 vpn.startVpnProfile(TEST_VPN_PKG); 988 fail("Expected failure due to no user consent"); 989 } catch (SecurityException expected) { 990 } 991 992 // Verify both appops were checked. 993 verify(mAppOps) 994 .noteOpNoThrow( 995 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), 996 eq(Process.myUid()), 997 eq(TEST_VPN_PKG), 998 eq(null) /* attributionTag */, 999 eq(null) /* message */); 1000 verify(mAppOps).noteOpNoThrow(AppOpsManager.OPSTR_ACTIVATE_VPN, Process.myUid(), 1001 TEST_VPN_PKG, null /* attributionTag */, null /* message */); 1002 1003 // Keystore should never have been accessed. 1004 verify(mVpnProfileStore, never()).get(any()); 1005 } 1006 1007 @Test testStartVpnProfileMissingProfile()1008 public void testStartVpnProfileMissingProfile() throws Exception { 1009 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1010 1011 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))).thenReturn(null); 1012 1013 try { 1014 vpn.startVpnProfile(TEST_VPN_PKG); 1015 fail("Expected failure due to missing profile"); 1016 } catch (IllegalArgumentException expected) { 1017 } 1018 1019 verify(mVpnProfileStore).get(vpn.getProfileNameForPackage(TEST_VPN_PKG)); 1020 verify(mAppOps) 1021 .noteOpNoThrow( 1022 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), 1023 eq(Process.myUid()), 1024 eq(TEST_VPN_PKG), 1025 eq(null) /* attributionTag */, 1026 eq(null) /* message */); 1027 } 1028 1029 @Test testStartVpnProfileRestrictedUser()1030 public void testStartVpnProfileRestrictedUser() throws Exception { 1031 final Vpn vpn = 1032 createVpnAndSetupUidChecks( 1033 restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1034 1035 try { 1036 vpn.startVpnProfile(TEST_VPN_PKG); 1037 fail("Expected SecurityException due to restricted user"); 1038 } catch (SecurityException expected) { 1039 } 1040 } 1041 1042 @Test testStopVpnProfileRestrictedUser()1043 public void testStopVpnProfileRestrictedUser() throws Exception { 1044 final Vpn vpn = 1045 createVpnAndSetupUidChecks( 1046 restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1047 1048 try { 1049 vpn.stopVpnProfile(TEST_VPN_PKG); 1050 fail("Expected SecurityException due to restricted user"); 1051 } catch (SecurityException expected) { 1052 } 1053 } 1054 1055 @Test testStartOpAndFinishOpWillBeCalledWhenPlatformVpnIsOnAndOff()1056 public void testStartOpAndFinishOpWillBeCalledWhenPlatformVpnIsOnAndOff() throws Exception { 1057 assumeTrue(SdkLevel.isAtLeastT()); 1058 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1059 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1060 .thenReturn(mVpnProfile.encode()); 1061 vpn.startVpnProfile(TEST_VPN_PKG); 1062 verifyPlatformVpnIsActivated(TEST_VPN_PKG); 1063 // Add a small delay to make sure that startOp is only called once. 1064 verify(mAppOps, after(100).times(1)).startOp( 1065 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER), 1066 eq(Process.myUid()), 1067 eq(TEST_VPN_PKG), 1068 eq(null) /* attributionTag */, 1069 eq(null) /* message */); 1070 // Check that the startOp is not called with OPSTR_ESTABLISH_VPN_SERVICE. 1071 verify(mAppOps, never()).startOp( 1072 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE), 1073 eq(Process.myUid()), 1074 eq(TEST_VPN_PKG), 1075 eq(null) /* attributionTag */, 1076 eq(null) /* message */); 1077 vpn.stopVpnProfile(TEST_VPN_PKG); 1078 verifyPlatformVpnIsDeactivated(TEST_VPN_PKG); 1079 } 1080 1081 @Test testStartOpWithSeamlessHandover()1082 public void testStartOpWithSeamlessHandover() throws Exception { 1083 assumeTrue(SdkLevel.isAtLeastT()); 1084 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN); 1085 assertTrue(vpn.prepare(TEST_VPN_PKG, null, VpnManager.TYPE_VPN_SERVICE)); 1086 final VpnConfig config = new VpnConfig(); 1087 config.user = "VpnTest"; 1088 config.addresses.add(new LinkAddress("192.0.2.2/32")); 1089 config.mtu = 1450; 1090 final ResolveInfo resolveInfo = new ResolveInfo(); 1091 final ServiceInfo serviceInfo = new ServiceInfo(); 1092 serviceInfo.permission = BIND_VPN_SERVICE; 1093 resolveInfo.serviceInfo = serviceInfo; 1094 when(mPackageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo); 1095 when(mContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true); 1096 vpn.establish(config); 1097 verify(mAppOps, times(1)).startOp( 1098 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE), 1099 eq(Process.myUid()), 1100 eq(TEST_VPN_PKG), 1101 eq(null) /* attributionTag */, 1102 eq(null) /* message */); 1103 // Call establish() twice with the same config, it should match seamless handover case and 1104 // startOp() shouldn't be called again. 1105 vpn.establish(config); 1106 verify(mAppOps, times(1)).startOp( 1107 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE), 1108 eq(Process.myUid()), 1109 eq(TEST_VPN_PKG), 1110 eq(null) /* attributionTag */, 1111 eq(null) /* message */); 1112 } 1113 verifyVpnManagerEvent(String sessionKey, String category, int errorClass, int errorCode, VpnProfileState... profileState)1114 private void verifyVpnManagerEvent(String sessionKey, String category, int errorClass, 1115 int errorCode, VpnProfileState... profileState) { 1116 final Context userContext = 1117 mContext.createContextAsUser(UserHandle.of(primaryUser.id), 0 /* flags */); 1118 final ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); 1119 1120 final int verifyTimes = (profileState == null) ? 1 : profileState.length; 1121 verify(userContext, times(verifyTimes)).startService(intentArgumentCaptor.capture()); 1122 1123 for (int i = 0; i < verifyTimes; i++) { 1124 final Intent intent = intentArgumentCaptor.getAllValues().get(i); 1125 assertEquals(sessionKey, intent.getStringExtra(VpnManager.EXTRA_SESSION_KEY)); 1126 final Set<String> categories = intent.getCategories(); 1127 assertTrue(categories.contains(category)); 1128 assertEquals(errorClass, 1129 intent.getIntExtra(VpnManager.EXTRA_ERROR_CLASS, -1 /* defaultValue */)); 1130 assertEquals(errorCode, 1131 intent.getIntExtra(VpnManager.EXTRA_ERROR_CODE, -1 /* defaultValue */)); 1132 if (profileState != null) { 1133 assertEquals(profileState[i], intent.getParcelableExtra( 1134 VpnManager.EXTRA_VPN_PROFILE_STATE, VpnProfileState.class)); 1135 } 1136 } 1137 reset(userContext); 1138 } 1139 1140 @Test testVpnManagerEventForUserDeactivated()1141 public void testVpnManagerEventForUserDeactivated() throws Exception { 1142 assumeTrue(SdkLevel.isAtLeastT()); 1143 // For security reasons, Vpn#prepare() will check that oldPackage and newPackage are either 1144 // null or the package of the caller. This test will call Vpn#prepare() to pretend the old 1145 // VPN is replaced by a new one. But only Settings can change to some other packages, and 1146 // this is checked with CONTROL_VPN so simulate holding CONTROL_VPN in order to pass the 1147 // security checks. 1148 doReturn(PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN); 1149 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1150 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1151 .thenReturn(mVpnProfile.encode()); 1152 1153 // Test the case that the user deactivates the vpn in vpn app. 1154 final String sessionKey1 = vpn.startVpnProfile(TEST_VPN_PKG); 1155 verifyPlatformVpnIsActivated(TEST_VPN_PKG); 1156 vpn.stopVpnProfile(TEST_VPN_PKG); 1157 verifyPlatformVpnIsDeactivated(TEST_VPN_PKG); 1158 verifyPowerSaveTempWhitelistApp(TEST_VPN_PKG); 1159 reset(mDeviceIdleInternal); 1160 // CATEGORY_EVENT_DEACTIVATED_BY_USER is not an error event, so both of errorClass and 1161 // errorCode won't be set. 1162 verifyVpnManagerEvent(sessionKey1, VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, 1163 -1 /* errorClass */, -1 /* errorCode */, null /* profileState */); 1164 reset(mAppOps); 1165 1166 // Test the case that the user chooses another vpn and the original one is replaced. 1167 final String sessionKey2 = vpn.startVpnProfile(TEST_VPN_PKG); 1168 verifyPlatformVpnIsActivated(TEST_VPN_PKG); 1169 vpn.prepare(TEST_VPN_PKG, "com.new.vpn" /* newPackage */, TYPE_VPN_PLATFORM); 1170 verifyPlatformVpnIsDeactivated(TEST_VPN_PKG); 1171 verifyPowerSaveTempWhitelistApp(TEST_VPN_PKG); 1172 reset(mDeviceIdleInternal); 1173 // CATEGORY_EVENT_DEACTIVATED_BY_USER is not an error event, so both of errorClass and 1174 // errorCode won't be set. 1175 verifyVpnManagerEvent(sessionKey2, VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, 1176 -1 /* errorClass */, -1 /* errorCode */, null /* profileState */); 1177 } 1178 1179 @Test testVpnManagerEventForAlwaysOnChanged()1180 public void testVpnManagerEventForAlwaysOnChanged() throws Exception { 1181 assumeTrue(SdkLevel.isAtLeastT()); 1182 // Calling setAlwaysOnPackage() needs to hold CONTROL_VPN. 1183 doReturn(PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN); 1184 final Vpn vpn = createVpn(primaryUser.id); 1185 // Enable VPN always-on for PKGS[1]. 1186 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false /* lockdown */, 1187 null /* lockdownAllowlist */)); 1188 verifyPowerSaveTempWhitelistApp(PKGS[1]); 1189 reset(mDeviceIdleInternal); 1190 verifyVpnManagerEvent(null /* sessionKey */, 1191 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */, 1192 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1193 null /* sessionKey */, true /* alwaysOn */, false /* lockdown */)); 1194 1195 // Enable VPN lockdown for PKGS[1]. 1196 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true /* lockdown */, 1197 null /* lockdownAllowlist */)); 1198 verifyPowerSaveTempWhitelistApp(PKGS[1]); 1199 reset(mDeviceIdleInternal); 1200 verifyVpnManagerEvent(null /* sessionKey */, 1201 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */, 1202 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1203 null /* sessionKey */, true /* alwaysOn */, true /* lockdown */)); 1204 1205 // Disable VPN lockdown for PKGS[1]. 1206 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false /* lockdown */, 1207 null /* lockdownAllowlist */)); 1208 verifyPowerSaveTempWhitelistApp(PKGS[1]); 1209 reset(mDeviceIdleInternal); 1210 verifyVpnManagerEvent(null /* sessionKey */, 1211 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */, 1212 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1213 null /* sessionKey */, true /* alwaysOn */, false /* lockdown */)); 1214 1215 // Disable VPN always-on. 1216 assertTrue(vpn.setAlwaysOnPackage(null, false /* lockdown */, 1217 null /* lockdownAllowlist */)); 1218 verifyPowerSaveTempWhitelistApp(PKGS[1]); 1219 reset(mDeviceIdleInternal); 1220 verifyVpnManagerEvent(null /* sessionKey */, 1221 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */, 1222 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1223 null /* sessionKey */, false /* alwaysOn */, false /* lockdown */)); 1224 1225 // Enable VPN always-on for PKGS[1] again. 1226 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false /* lockdown */, 1227 null /* lockdownAllowlist */)); 1228 verifyPowerSaveTempWhitelistApp(PKGS[1]); 1229 reset(mDeviceIdleInternal); 1230 verifyVpnManagerEvent(null /* sessionKey */, 1231 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */, 1232 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1233 null /* sessionKey */, true /* alwaysOn */, false /* lockdown */)); 1234 1235 // Enable VPN always-on for PKGS[2]. 1236 assertTrue(vpn.setAlwaysOnPackage(PKGS[2], false /* lockdown */, 1237 null /* lockdownAllowlist */)); 1238 verifyPowerSaveTempWhitelistApp(PKGS[2]); 1239 reset(mDeviceIdleInternal); 1240 // PKGS[1] is replaced with PKGS[2]. 1241 // Pass 2 VpnProfileState objects to verifyVpnManagerEvent(), the first one is sent to 1242 // PKGS[1] to notify PKGS[1] that the VPN always-on is disabled, the second one is sent to 1243 // PKGS[2] to notify PKGS[2] that the VPN always-on is enabled. 1244 verifyVpnManagerEvent(null /* sessionKey */, 1245 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */, 1246 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1247 null /* sessionKey */, false /* alwaysOn */, false /* lockdown */), 1248 new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1249 null /* sessionKey */, true /* alwaysOn */, false /* lockdown */)); 1250 } 1251 1252 @Test testSetPackageAuthorizationVpnService()1253 public void testSetPackageAuthorizationVpnService() throws Exception { 1254 final Vpn vpn = createVpnAndSetupUidChecks(); 1255 1256 assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_SERVICE)); 1257 verify(mAppOps) 1258 .setMode( 1259 eq(AppOpsManager.OPSTR_ACTIVATE_VPN), 1260 eq(Process.myUid()), 1261 eq(TEST_VPN_PKG), 1262 eq(AppOpsManager.MODE_ALLOWED)); 1263 } 1264 1265 @Test testSetPackageAuthorizationPlatformVpn()1266 public void testSetPackageAuthorizationPlatformVpn() throws Exception { 1267 final Vpn vpn = createVpnAndSetupUidChecks(); 1268 1269 assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, TYPE_VPN_PLATFORM)); 1270 verify(mAppOps) 1271 .setMode( 1272 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), 1273 eq(Process.myUid()), 1274 eq(TEST_VPN_PKG), 1275 eq(AppOpsManager.MODE_ALLOWED)); 1276 } 1277 1278 @Test testSetPackageAuthorizationRevokeAuthorization()1279 public void testSetPackageAuthorizationRevokeAuthorization() throws Exception { 1280 final Vpn vpn = createVpnAndSetupUidChecks(); 1281 1282 assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_NONE)); 1283 verify(mAppOps) 1284 .setMode( 1285 eq(AppOpsManager.OPSTR_ACTIVATE_VPN), 1286 eq(Process.myUid()), 1287 eq(TEST_VPN_PKG), 1288 eq(AppOpsManager.MODE_IGNORED)); 1289 verify(mAppOps) 1290 .setMode( 1291 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), 1292 eq(Process.myUid()), 1293 eq(TEST_VPN_PKG), 1294 eq(AppOpsManager.MODE_IGNORED)); 1295 } 1296 triggerOnAvailableAndGetCallback()1297 private NetworkCallback triggerOnAvailableAndGetCallback() throws Exception { 1298 final ArgumentCaptor<NetworkCallback> networkCallbackCaptor = 1299 ArgumentCaptor.forClass(NetworkCallback.class); 1300 verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)) 1301 .requestNetwork(any(), networkCallbackCaptor.capture()); 1302 1303 // onAvailable() will trigger onDefaultNetworkChanged(), so NetdUtils#setInterfaceUp will be 1304 // invoked. Set the return value of INetd#interfaceGetCfg to prevent NullPointerException. 1305 final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel(); 1306 config.flags = new String[] {IF_STATE_DOWN}; 1307 when(mNetd.interfaceGetCfg(anyString())).thenReturn(config); 1308 final NetworkCallback cb = networkCallbackCaptor.getValue(); 1309 cb.onAvailable(TEST_NETWORK); 1310 return cb; 1311 } 1312 verifyInterfaceSetCfgWithFlags(String flag)1313 private void verifyInterfaceSetCfgWithFlags(String flag) throws Exception { 1314 // Add a timeout for waiting for interfaceSetCfg to be called. 1315 verify(mNetd, timeout(TEST_TIMEOUT_MS)).interfaceSetCfg(argThat( 1316 config -> Arrays.asList(config.flags).contains(flag))); 1317 } 1318 doTestPlatformVpnWithException(IkeException exception, String category, int errorType, int errorCode)1319 private void doTestPlatformVpnWithException(IkeException exception, 1320 String category, int errorType, int errorCode) throws Exception { 1321 final ArgumentCaptor<IkeSessionCallback> captor = 1322 ArgumentCaptor.forClass(IkeSessionCallback.class); 1323 1324 final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1325 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1326 .thenReturn(mVpnProfile.encode()); 1327 1328 final String sessionKey = vpn.startVpnProfile(TEST_VPN_PKG); 1329 final NetworkCallback cb = triggerOnAvailableAndGetCallback(); 1330 1331 verifyInterfaceSetCfgWithFlags(IF_STATE_UP); 1332 1333 // Wait for createIkeSession() to be called before proceeding in order to ensure consistent 1334 // state 1335 verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS)) 1336 .createIkeSession(any(), any(), any(), any(), captor.capture(), any()); 1337 reset(mIkev2SessionCreator); 1338 final IkeSessionCallback ikeCb = captor.getValue(); 1339 ikeCb.onClosedWithException(exception); 1340 1341 verifyPowerSaveTempWhitelistApp(TEST_VPN_PKG); 1342 reset(mDeviceIdleInternal); 1343 verifyVpnManagerEvent(sessionKey, category, errorType, errorCode, null /* profileState */); 1344 if (errorType == VpnManager.ERROR_CLASS_NOT_RECOVERABLE) { 1345 verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)) 1346 .unregisterNetworkCallback(eq(cb)); 1347 } else if (errorType == VpnManager.ERROR_CLASS_RECOVERABLE) { 1348 // To prevent spending much time to test the retry function, only retry 2 times here. 1349 int retryIndex = 0; 1350 verify(mIkev2SessionCreator, 1351 timeout(((TestDeps) vpn.mDeps).getNextRetryDelaySeconds(retryIndex++) * 1000 1352 + TEST_TIMEOUT_MS)) 1353 .createIkeSession(any(), any(), any(), any(), captor.capture(), any()); 1354 1355 // Capture a new IkeSessionCallback to get the latest token. 1356 reset(mIkev2SessionCreator); 1357 final IkeSessionCallback ikeCb2 = captor.getValue(); 1358 ikeCb2.onClosedWithException(exception); 1359 verify(mIkev2SessionCreator, 1360 timeout(((TestDeps) vpn.mDeps).getNextRetryDelaySeconds(retryIndex++) * 1000 1361 + TEST_TIMEOUT_MS)) 1362 .createIkeSession(any(), any(), any(), any(), captor.capture(), any()); 1363 reset(mIkev2SessionCreator); 1364 } 1365 } 1366 1367 @Test testStartPlatformVpnAuthenticationFailed()1368 public void testStartPlatformVpnAuthenticationFailed() throws Exception { 1369 final IkeProtocolException exception = mock(IkeProtocolException.class); 1370 final int errorCode = IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED; 1371 when(exception.getErrorType()).thenReturn(errorCode); 1372 doTestPlatformVpnWithException(exception, 1373 VpnManager.CATEGORY_EVENT_IKE_ERROR, VpnManager.ERROR_CLASS_NOT_RECOVERABLE, 1374 errorCode); 1375 } 1376 1377 @Test testStartPlatformVpnFailedWithRecoverableError()1378 public void testStartPlatformVpnFailedWithRecoverableError() throws Exception { 1379 final IkeProtocolException exception = mock(IkeProtocolException.class); 1380 final int errorCode = IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE; 1381 when(exception.getErrorType()).thenReturn(errorCode); 1382 doTestPlatformVpnWithException(exception, 1383 VpnManager.CATEGORY_EVENT_IKE_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, errorCode); 1384 } 1385 1386 @Test testStartPlatformVpnFailedWithUnknownHostException()1387 public void testStartPlatformVpnFailedWithUnknownHostException() throws Exception { 1388 final IkeNonProtocolException exception = mock(IkeNonProtocolException.class); 1389 final UnknownHostException unknownHostException = new UnknownHostException(); 1390 final int errorCode = VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST; 1391 when(exception.getCause()).thenReturn(unknownHostException); 1392 doTestPlatformVpnWithException(exception, 1393 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, 1394 errorCode); 1395 } 1396 1397 @Test testStartPlatformVpnFailedWithIkeTimeoutException()1398 public void testStartPlatformVpnFailedWithIkeTimeoutException() throws Exception { 1399 final IkeNonProtocolException exception = mock(IkeNonProtocolException.class); 1400 final IkeTimeoutException ikeTimeoutException = 1401 new IkeTimeoutException("IkeTimeoutException"); 1402 final int errorCode = VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT; 1403 when(exception.getCause()).thenReturn(ikeTimeoutException); 1404 doTestPlatformVpnWithException(exception, 1405 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, 1406 errorCode); 1407 } 1408 1409 @Test testStartPlatformVpnFailedWithIkeNetworkLostException()1410 public void testStartPlatformVpnFailedWithIkeNetworkLostException() throws Exception { 1411 final IkeNetworkLostException exception = new IkeNetworkLostException( 1412 new Network(100)); 1413 doTestPlatformVpnWithException(exception, 1414 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, 1415 VpnManager.ERROR_CODE_NETWORK_LOST); 1416 } 1417 1418 @Test testStartPlatformVpnFailedWithIOException()1419 public void testStartPlatformVpnFailedWithIOException() throws Exception { 1420 final IkeNonProtocolException exception = mock(IkeNonProtocolException.class); 1421 final IOException ioException = new IOException(); 1422 final int errorCode = VpnManager.ERROR_CODE_NETWORK_IO; 1423 when(exception.getCause()).thenReturn(ioException); 1424 doTestPlatformVpnWithException(exception, 1425 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, 1426 errorCode); 1427 } 1428 1429 @Test testStartPlatformVpnIllegalArgumentExceptionInSetup()1430 public void testStartPlatformVpnIllegalArgumentExceptionInSetup() throws Exception { 1431 when(mIkev2SessionCreator.createIkeSession(any(), any(), any(), any(), any(), any())) 1432 .thenThrow(new IllegalArgumentException()); 1433 final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), mVpnProfile); 1434 final NetworkCallback cb = triggerOnAvailableAndGetCallback(); 1435 1436 verifyInterfaceSetCfgWithFlags(IF_STATE_UP); 1437 1438 // Wait for createIkeSession() to be called before proceeding in order to ensure consistent 1439 // state 1440 verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb)); 1441 assertEquals(LegacyVpnInfo.STATE_FAILED, vpn.getLegacyVpnInfo().state); 1442 } 1443 1444 @Test testVpnManagerEventWillNotBeSentToSettingsVpn()1445 public void testVpnManagerEventWillNotBeSentToSettingsVpn() throws Exception { 1446 startLegacyVpn(createVpn(primaryUser.id), mVpnProfile); 1447 triggerOnAvailableAndGetCallback(); 1448 1449 verifyInterfaceSetCfgWithFlags(IF_STATE_UP); 1450 1451 final IkeNonProtocolException exception = mock(IkeNonProtocolException.class); 1452 final IkeTimeoutException ikeTimeoutException = 1453 new IkeTimeoutException("IkeTimeoutException"); 1454 when(exception.getCause()).thenReturn(ikeTimeoutException); 1455 1456 final ArgumentCaptor<IkeSessionCallback> captor = 1457 ArgumentCaptor.forClass(IkeSessionCallback.class); 1458 verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS)) 1459 .createIkeSession(any(), any(), any(), any(), captor.capture(), any()); 1460 final IkeSessionCallback ikeCb = captor.getValue(); 1461 ikeCb.onClosedWithException(exception); 1462 1463 // userContext is the same Context that VPN is using, see createVpn(). 1464 final Context userContext = 1465 mContext.createContextAsUser(UserHandle.of(primaryUser.id), 0 /* flags */); 1466 verify(userContext, never()).startService(any()); 1467 } 1468 setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled)1469 private void setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled) { 1470 assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, lockdownEnabled, null)); 1471 1472 verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); 1473 verify(mAppOps).setMode( 1474 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), eq(uid), eq(TEST_VPN_PKG), 1475 eq(AppOpsManager.MODE_ALLOWED)); 1476 1477 verify(mSystemServices).settingsSecurePutStringForUser( 1478 eq(Settings.Secure.ALWAYS_ON_VPN_APP), eq(TEST_VPN_PKG), eq(primaryUser.id)); 1479 verify(mSystemServices).settingsSecurePutIntForUser( 1480 eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN), eq(lockdownEnabled ? 1 : 0), 1481 eq(primaryUser.id)); 1482 verify(mSystemServices).settingsSecurePutStringForUser( 1483 eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST), eq(""), eq(primaryUser.id)); 1484 } 1485 1486 @Test testSetAndStartAlwaysOnVpn()1487 public void testSetAndStartAlwaysOnVpn() throws Exception { 1488 final Vpn vpn = createVpn(primaryUser.id); 1489 setMockedUsers(primaryUser); 1490 1491 // UID checks must return a different UID; otherwise it'll be treated as already prepared. 1492 final int uid = Process.myUid() + 1; 1493 when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt())) 1494 .thenReturn(uid); 1495 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1496 .thenReturn(mVpnProfile.encode()); 1497 1498 setAndVerifyAlwaysOnPackage(vpn, uid, false); 1499 assertTrue(vpn.startAlwaysOnVpn()); 1500 1501 // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in 1502 // a subsequent CL. 1503 } 1504 startLegacyVpn(final Vpn vpn, final VpnProfile vpnProfile)1505 private Vpn startLegacyVpn(final Vpn vpn, final VpnProfile vpnProfile) throws Exception { 1506 setMockedUsers(primaryUser); 1507 1508 // Dummy egress interface 1509 final LinkProperties lp = new LinkProperties(); 1510 lp.setInterfaceName(EGRESS_IFACE); 1511 1512 final RouteInfo defaultRoute = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), 1513 InetAddresses.parseNumericAddress("192.0.2.0"), EGRESS_IFACE); 1514 lp.addRoute(defaultRoute); 1515 1516 vpn.startLegacyVpn(vpnProfile, EGRESS_NETWORK, lp); 1517 return vpn; 1518 } 1519 1520 @Test testStartPlatformVpn()1521 public void testStartPlatformVpn() throws Exception { 1522 startLegacyVpn(createVpn(primaryUser.id), mVpnProfile); 1523 // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in 1524 // a subsequent patch. 1525 } 1526 1527 @Test testStartRacoonNumericAddress()1528 public void testStartRacoonNumericAddress() throws Exception { 1529 startRacoon("1.2.3.4", "1.2.3.4"); 1530 } 1531 1532 @Test testStartRacoonHostname()1533 public void testStartRacoonHostname() throws Exception { 1534 startRacoon("hostname", "5.6.7.8"); // address returned by deps.resolve 1535 } 1536 1537 @Test testStartPptp()1538 public void testStartPptp() throws Exception { 1539 startPptp(true /* useMppe */); 1540 } 1541 1542 @Test testStartPptp_NoMppe()1543 public void testStartPptp_NoMppe() throws Exception { 1544 startPptp(false /* useMppe */); 1545 } 1546 assertTransportInfoMatches(NetworkCapabilities nc, int type)1547 private void assertTransportInfoMatches(NetworkCapabilities nc, int type) { 1548 assertNotNull(nc); 1549 VpnTransportInfo ti = (VpnTransportInfo) nc.getTransportInfo(); 1550 assertNotNull(ti); 1551 assertEquals(type, ti.getType()); 1552 } 1553 startPptp(boolean useMppe)1554 private void startPptp(boolean useMppe) throws Exception { 1555 final VpnProfile profile = new VpnProfile("testProfile" /* key */); 1556 profile.type = VpnProfile.TYPE_PPTP; 1557 profile.name = "testProfileName"; 1558 profile.username = "userName"; 1559 profile.password = "thePassword"; 1560 profile.server = "192.0.2.123"; 1561 profile.mppe = useMppe; 1562 1563 doReturn(new Network[] { new Network(101) }).when(mConnectivityManager).getAllNetworks(); 1564 doReturn(new Network(102)).when(mConnectivityManager).registerNetworkAgent(any(), any(), 1565 any(), any(), any(), any(), anyInt()); 1566 1567 final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), profile); 1568 final TestDeps deps = (TestDeps) vpn.mDeps; 1569 1570 // TODO: use import when this is merged in all branches and there's no merge conflict 1571 com.android.testutils.Cleanup.testAndCleanup(() -> { 1572 final String[] mtpdArgs = deps.mtpdArgs.get(10, TimeUnit.SECONDS); 1573 final String[] argsPrefix = new String[]{ 1574 EGRESS_IFACE, "pptp", profile.server, "1723", "name", profile.username, 1575 "password", profile.password, "linkname", "vpn", "refuse-eap", "nodefaultroute", 1576 "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270" 1577 }; 1578 assertArrayEquals(argsPrefix, Arrays.copyOf(mtpdArgs, argsPrefix.length)); 1579 if (useMppe) { 1580 assertEquals(argsPrefix.length + 2, mtpdArgs.length); 1581 assertEquals("+mppe", mtpdArgs[argsPrefix.length]); 1582 assertEquals("-pap", mtpdArgs[argsPrefix.length + 1]); 1583 } else { 1584 assertEquals(argsPrefix.length + 1, mtpdArgs.length); 1585 assertEquals("nomppe", mtpdArgs[argsPrefix.length]); 1586 } 1587 1588 verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(), 1589 any(), any(), any(), any(), anyInt()); 1590 }, () -> { // Cleanup 1591 vpn.mVpnRunner.exitVpnRunner(); 1592 deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier 1593 vpn.mVpnRunner.join(10_000); // wait for up to 10s for the runner to die and cleanup 1594 }); 1595 } 1596 startRacoon(final String serverAddr, final String expectedAddr)1597 public void startRacoon(final String serverAddr, final String expectedAddr) 1598 throws Exception { 1599 final ConditionVariable legacyRunnerReady = new ConditionVariable(); 1600 final VpnProfile profile = new VpnProfile("testProfile" /* key */); 1601 profile.type = VpnProfile.TYPE_L2TP_IPSEC_PSK; 1602 profile.name = "testProfileName"; 1603 profile.username = "userName"; 1604 profile.password = "thePassword"; 1605 profile.server = serverAddr; 1606 profile.ipsecIdentifier = "id"; 1607 profile.ipsecSecret = "secret"; 1608 profile.l2tpSecret = "l2tpsecret"; 1609 1610 when(mConnectivityManager.getAllNetworks()) 1611 .thenReturn(new Network[] { new Network(101) }); 1612 1613 when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(), 1614 any(), any(), anyInt())).thenAnswer(invocation -> { 1615 // The runner has registered an agent and is now ready. 1616 legacyRunnerReady.open(); 1617 return new Network(102); 1618 }); 1619 final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), profile); 1620 final TestDeps deps = (TestDeps) vpn.mDeps; 1621 try { 1622 // udppsk and 1701 are the values for TYPE_L2TP_IPSEC_PSK 1623 assertArrayEquals( 1624 new String[] { EGRESS_IFACE, expectedAddr, "udppsk", 1625 profile.ipsecIdentifier, profile.ipsecSecret, "1701" }, 1626 deps.racoonArgs.get(10, TimeUnit.SECONDS)); 1627 // literal values are hardcoded in Vpn.java for mtpd args 1628 assertArrayEquals( 1629 new String[] { EGRESS_IFACE, "l2tp", expectedAddr, "1701", profile.l2tpSecret, 1630 "name", profile.username, "password", profile.password, 1631 "linkname", "vpn", "refuse-eap", "nodefaultroute", "usepeerdns", 1632 "idle", "1800", "mtu", "1270", "mru", "1270" }, 1633 deps.mtpdArgs.get(10, TimeUnit.SECONDS)); 1634 1635 // Now wait for the runner to be ready before testing for the route. 1636 ArgumentCaptor<LinkProperties> lpCaptor = ArgumentCaptor.forClass(LinkProperties.class); 1637 ArgumentCaptor<NetworkCapabilities> ncCaptor = 1638 ArgumentCaptor.forClass(NetworkCapabilities.class); 1639 verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(), 1640 lpCaptor.capture(), ncCaptor.capture(), any(), any(), anyInt()); 1641 1642 // In this test the expected address is always v4 so /32. 1643 // Note that the interface needs to be specified because RouteInfo objects stored in 1644 // LinkProperties objects always acquire the LinkProperties' interface. 1645 final RouteInfo expectedRoute = new RouteInfo(new IpPrefix(expectedAddr + "/32"), 1646 null, EGRESS_IFACE, RouteInfo.RTN_THROW); 1647 final List<RouteInfo> actualRoutes = lpCaptor.getValue().getRoutes(); 1648 assertTrue("Expected throw route (" + expectedRoute + ") not found in " + actualRoutes, 1649 actualRoutes.contains(expectedRoute)); 1650 1651 assertTransportInfoMatches(ncCaptor.getValue(), VpnManager.TYPE_VPN_LEGACY); 1652 } finally { 1653 // Now interrupt the thread, unblock the runner and clean up. 1654 vpn.mVpnRunner.exitVpnRunner(); 1655 deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier 1656 vpn.mVpnRunner.join(10_000); // wait for up to 10s for the runner to die and cleanup 1657 } 1658 } 1659 1660 private final class TestDeps extends Vpn.Dependencies { 1661 public final CompletableFuture<String[]> racoonArgs = new CompletableFuture(); 1662 public final CompletableFuture<String[]> mtpdArgs = new CompletableFuture(); 1663 public final File mStateFile; 1664 1665 private final HashMap<String, Boolean> mRunningServices = new HashMap<>(); 1666 TestDeps()1667 TestDeps() { 1668 try { 1669 mStateFile = File.createTempFile("vpnTest", ".tmp"); 1670 mStateFile.deleteOnExit(); 1671 } catch (final IOException e) { 1672 throw new RuntimeException(e); 1673 } 1674 } 1675 1676 @Override isCallerSystem()1677 public boolean isCallerSystem() { 1678 return true; 1679 } 1680 1681 @Override startService(final String serviceName)1682 public void startService(final String serviceName) { 1683 mRunningServices.put(serviceName, true); 1684 } 1685 1686 @Override stopService(final String serviceName)1687 public void stopService(final String serviceName) { 1688 mRunningServices.put(serviceName, false); 1689 } 1690 1691 @Override isServiceRunning(final String serviceName)1692 public boolean isServiceRunning(final String serviceName) { 1693 return mRunningServices.getOrDefault(serviceName, false); 1694 } 1695 1696 @Override isServiceStopped(final String serviceName)1697 public boolean isServiceStopped(final String serviceName) { 1698 return !isServiceRunning(serviceName); 1699 } 1700 1701 @Override getStateFile()1702 public File getStateFile() { 1703 return mStateFile; 1704 } 1705 1706 @Override getIntentForStatusPanel(Context context)1707 public PendingIntent getIntentForStatusPanel(Context context) { 1708 return null; 1709 } 1710 1711 @Override sendArgumentsToDaemon( final String daemon, final LocalSocket socket, final String[] arguments, final Vpn.RetryScheduler interruptChecker)1712 public void sendArgumentsToDaemon( 1713 final String daemon, final LocalSocket socket, final String[] arguments, 1714 final Vpn.RetryScheduler interruptChecker) throws IOException { 1715 if ("racoon".equals(daemon)) { 1716 racoonArgs.complete(arguments); 1717 } else if ("mtpd".equals(daemon)) { 1718 writeStateFile(arguments); 1719 mtpdArgs.complete(arguments); 1720 } else { 1721 throw new UnsupportedOperationException("Unsupported daemon : " + daemon); 1722 } 1723 } 1724 writeStateFile(final String[] arguments)1725 private void writeStateFile(final String[] arguments) throws IOException { 1726 mStateFile.delete(); 1727 mStateFile.createNewFile(); 1728 mStateFile.deleteOnExit(); 1729 final BufferedWriter writer = new BufferedWriter( 1730 new FileWriter(mStateFile, false /* append */)); 1731 writer.write(EGRESS_IFACE); 1732 writer.write("\n"); 1733 // addresses 1734 writer.write("10.0.0.1/24\n"); 1735 // routes 1736 writer.write("192.168.6.0/24\n"); 1737 // dns servers 1738 writer.write("192.168.6.1\n"); 1739 // search domains 1740 writer.write("vpn.searchdomains.com\n"); 1741 // endpoint - intentionally empty 1742 writer.write("\n"); 1743 writer.flush(); 1744 writer.close(); 1745 } 1746 1747 @Override 1748 @NonNull resolve(final String endpoint)1749 public InetAddress resolve(final String endpoint) { 1750 try { 1751 // If a numeric IP address, return it. 1752 return InetAddress.parseNumericAddress(endpoint); 1753 } catch (IllegalArgumentException e) { 1754 // Otherwise, return some token IP to test for. 1755 return InetAddress.parseNumericAddress("5.6.7.8"); 1756 } 1757 } 1758 1759 @Override isInterfacePresent(final Vpn vpn, final String iface)1760 public boolean isInterfacePresent(final Vpn vpn, final String iface) { 1761 return true; 1762 } 1763 1764 @Override adoptFd(Vpn vpn, int mtu)1765 public ParcelFileDescriptor adoptFd(Vpn vpn, int mtu) { 1766 return new ParcelFileDescriptor(new FileDescriptor()); 1767 } 1768 1769 @Override jniCreate(Vpn vpn, int mtu)1770 public int jniCreate(Vpn vpn, int mtu) { 1771 // Pick a random positive number as fd to return. 1772 return 345; 1773 } 1774 1775 @Override jniGetName(Vpn vpn, int fd)1776 public String jniGetName(Vpn vpn, int fd) { 1777 return TEST_IFACE_NAME; 1778 } 1779 1780 @Override jniSetAddresses(Vpn vpn, String interfaze, String addresses)1781 public int jniSetAddresses(Vpn vpn, String interfaze, String addresses) { 1782 if (addresses == null) return 0; 1783 // Return the number of addresses. 1784 return addresses.split(" ").length; 1785 } 1786 1787 @Override setBlocking(FileDescriptor fd, boolean blocking)1788 public void setBlocking(FileDescriptor fd, boolean blocking) {} 1789 1790 @Override getDeviceIdleInternal()1791 public DeviceIdleInternal getDeviceIdleInternal() { 1792 return mDeviceIdleInternal; 1793 } 1794 getNextRetryDelaySeconds(int retryCount)1795 public long getNextRetryDelaySeconds(int retryCount) { 1796 // Simply return retryCount as the delay seconds for retrying. 1797 return retryCount; 1798 } 1799 } 1800 1801 /** 1802 * Mock some methods of vpn object. 1803 */ createVpn(@serIdInt int userId)1804 private Vpn createVpn(@UserIdInt int userId) { 1805 final Context asUserContext = mock(Context.class, AdditionalAnswers.delegatesTo(mContext)); 1806 doReturn(UserHandle.of(userId)).when(asUserContext).getUser(); 1807 when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt())) 1808 .thenReturn(asUserContext); 1809 final TestLooper testLooper = new TestLooper(); 1810 final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService, 1811 mNetd, userId, mVpnProfileStore, mSystemServices, mIkev2SessionCreator); 1812 verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat( 1813 provider -> provider.getName().contains("VpnNetworkProvider") 1814 )); 1815 return vpn; 1816 } 1817 1818 /** 1819 * Populate {@link #mUserManager} with a list of fake users. 1820 */ setMockedUsers(UserInfo... users)1821 private void setMockedUsers(UserInfo... users) { 1822 final Map<Integer, UserInfo> userMap = new ArrayMap<>(); 1823 for (UserInfo user : users) { 1824 userMap.put(user.id, user); 1825 } 1826 1827 /** 1828 * @see UserManagerService#getUsers(boolean) 1829 */ 1830 doAnswer(invocation -> { 1831 final ArrayList<UserInfo> result = new ArrayList<>(users.length); 1832 for (UserInfo ui : users) { 1833 if (ui.isEnabled() && !ui.partial) { 1834 result.add(ui); 1835 } 1836 } 1837 return result; 1838 }).when(mUserManager).getAliveUsers(); 1839 1840 doAnswer(invocation -> { 1841 final int id = (int) invocation.getArguments()[0]; 1842 return userMap.get(id); 1843 }).when(mUserManager).getUserInfo(anyInt()); 1844 } 1845 1846 /** 1847 * Populate {@link #mPackageManager} with a fake packageName-to-UID mapping. 1848 */ setMockedPackages(final Map<String, Integer> packages)1849 private void setMockedPackages(final Map<String, Integer> packages) { 1850 try { 1851 doAnswer(invocation -> { 1852 final String appName = (String) invocation.getArguments()[0]; 1853 final int userId = (int) invocation.getArguments()[1]; 1854 Integer appId = packages.get(appName); 1855 if (appId == null) throw new PackageManager.NameNotFoundException(appName); 1856 return UserHandle.getUid(userId, appId); 1857 }).when(mPackageManager).getPackageUidAsUser(anyString(), anyInt()); 1858 } catch (Exception e) { 1859 } 1860 } 1861 setMockedNetworks(final Map<Network, NetworkCapabilities> networks)1862 private void setMockedNetworks(final Map<Network, NetworkCapabilities> networks) { 1863 doAnswer(invocation -> { 1864 final Network network = (Network) invocation.getArguments()[0]; 1865 return networks.get(network); 1866 }).when(mConnectivityManager).getNetworkCapabilities(any()); 1867 } 1868 1869 // Need multiple copies of this, but Java's Stream objects can't be reused or 1870 // duplicated. publicIpV4Routes()1871 private Stream<String> publicIpV4Routes() { 1872 return Stream.of( 1873 "0.0.0.0/5", "8.0.0.0/7", "11.0.0.0/8", "12.0.0.0/6", "16.0.0.0/4", 1874 "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/3", "160.0.0.0/5", "168.0.0.0/6", 1875 "172.0.0.0/12", "172.32.0.0/11", "172.64.0.0/10", "172.128.0.0/9", 1876 "173.0.0.0/8", "174.0.0.0/7", "176.0.0.0/4", "192.0.0.0/9", "192.128.0.0/11", 1877 "192.160.0.0/13", "192.169.0.0/16", "192.170.0.0/15", "192.172.0.0/14", 1878 "192.176.0.0/12", "192.192.0.0/10", "193.0.0.0/8", "194.0.0.0/7", 1879 "196.0.0.0/6", "200.0.0.0/5", "208.0.0.0/4"); 1880 } 1881 publicIpV6Routes()1882 private Stream<String> publicIpV6Routes() { 1883 return Stream.of( 1884 "::/1", "8000::/2", "c000::/3", "e000::/4", "f000::/5", "f800::/6", 1885 "fe00::/8", "2605:ef80:e:af1d::/64"); 1886 } 1887 } 1888