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.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback; 24 import static android.net.ConnectivityDiagnosticsManager.DataStallReport; 25 import static android.net.ConnectivityManager.NetworkCallback; 26 import static android.net.INetd.IF_STATE_DOWN; 27 import static android.net.INetd.IF_STATE_UP; 28 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; 29 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; 30 import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; 31 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 32 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 33 import static android.net.RouteInfo.RTN_UNREACHABLE; 34 import static android.net.VpnManager.TYPE_VPN_PLATFORM; 35 import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS; 36 import static android.net.cts.util.IkeSessionTestUtils.TEST_IDENTITY; 37 import static android.net.cts.util.IkeSessionTestUtils.TEST_KEEPALIVE_TIMEOUT_UNSET; 38 import static android.net.cts.util.IkeSessionTestUtils.getTestIkeSessionParams; 39 import static android.net.ipsec.ike.IkeSessionConfiguration.EXTENSION_TYPE_MOBIKE; 40 import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_AUTO; 41 import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_NONE; 42 import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_UDP; 43 import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_AUTO; 44 import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_IPV4; 45 import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_IPV6; 46 import static android.os.Build.VERSION_CODES.S_V2; 47 import static android.os.UserHandle.PER_USER_RANGE; 48 import static android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL; 49 import static android.telephony.CarrierConfigManager.KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT; 50 import static android.telephony.CarrierConfigManager.KEY_PREFERRED_IKE_PROTOCOL_INT; 51 52 import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU; 53 import static com.android.server.connectivity.Vpn.AUTOMATIC_KEEPALIVE_DELAY_SECONDS; 54 import static com.android.server.connectivity.Vpn.DEFAULT_LONG_LIVED_TCP_CONNS_EXPENSIVE_TIMEOUT_SEC; 55 import static com.android.server.connectivity.Vpn.DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT; 56 import static com.android.server.connectivity.Vpn.PREFERRED_IKE_PROTOCOL_AUTO; 57 import static com.android.server.connectivity.Vpn.PREFERRED_IKE_PROTOCOL_IPV4_UDP; 58 import static com.android.server.connectivity.Vpn.PREFERRED_IKE_PROTOCOL_IPV6_ESP; 59 import static com.android.server.connectivity.Vpn.PREFERRED_IKE_PROTOCOL_IPV6_UDP; 60 import static com.android.testutils.Cleanup.testAndCleanup; 61 import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; 62 import static com.android.testutils.MiscAsserts.assertThrows; 63 64 import static org.junit.Assert.assertArrayEquals; 65 import static org.junit.Assert.assertEquals; 66 import static org.junit.Assert.assertFalse; 67 import static org.junit.Assert.assertNotNull; 68 import static org.junit.Assert.assertNull; 69 import static org.junit.Assert.assertTrue; 70 import static org.junit.Assert.fail; 71 import static org.mockito.ArgumentMatchers.any; 72 import static org.mockito.ArgumentMatchers.anyBoolean; 73 import static org.mockito.ArgumentMatchers.anyInt; 74 import static org.mockito.ArgumentMatchers.anyLong; 75 import static org.mockito.ArgumentMatchers.anyString; 76 import static org.mockito.ArgumentMatchers.argThat; 77 import static org.mockito.ArgumentMatchers.eq; 78 import static org.mockito.ArgumentMatchers.longThat; 79 import static org.mockito.Mockito.after; 80 import static org.mockito.Mockito.atLeastOnce; 81 import static org.mockito.Mockito.doAnswer; 82 import static org.mockito.Mockito.doCallRealMethod; 83 import static org.mockito.Mockito.doNothing; 84 import static org.mockito.Mockito.doReturn; 85 import static org.mockito.Mockito.inOrder; 86 import static org.mockito.Mockito.mock; 87 import static org.mockito.Mockito.never; 88 import static org.mockito.Mockito.reset; 89 import static org.mockito.Mockito.spy; 90 import static org.mockito.Mockito.timeout; 91 import static org.mockito.Mockito.times; 92 import static org.mockito.Mockito.verify; 93 import static org.mockito.Mockito.when; 94 95 import android.annotation.NonNull; 96 import android.annotation.UserIdInt; 97 import android.app.AppOpsManager; 98 import android.app.NotificationManager; 99 import android.app.PendingIntent; 100 import android.content.Context; 101 import android.content.Intent; 102 import android.content.pm.ApplicationInfo; 103 import android.content.pm.PackageManager; 104 import android.content.pm.ResolveInfo; 105 import android.content.pm.ServiceInfo; 106 import android.content.pm.UserInfo; 107 import android.content.res.Resources; 108 import android.net.ConnectivityDiagnosticsManager; 109 import android.net.ConnectivityManager; 110 import android.net.INetd; 111 import android.net.Ikev2VpnProfile; 112 import android.net.InetAddresses; 113 import android.net.InterfaceConfigurationParcel; 114 import android.net.IpPrefix; 115 import android.net.IpSecConfig; 116 import android.net.IpSecManager; 117 import android.net.IpSecTransform; 118 import android.net.IpSecTunnelInterfaceResponse; 119 import android.net.LinkAddress; 120 import android.net.LinkProperties; 121 import android.net.LocalSocket; 122 import android.net.Network; 123 import android.net.NetworkAgent; 124 import android.net.NetworkAgentConfig; 125 import android.net.NetworkCapabilities; 126 import android.net.NetworkInfo.DetailedState; 127 import android.net.RouteInfo; 128 import android.net.TelephonyNetworkSpecifier; 129 import android.net.UidRangeParcel; 130 import android.net.VpnManager; 131 import android.net.VpnProfileState; 132 import android.net.VpnService; 133 import android.net.VpnTransportInfo; 134 import android.net.ipsec.ike.ChildSessionCallback; 135 import android.net.ipsec.ike.ChildSessionConfiguration; 136 import android.net.ipsec.ike.IkeFqdnIdentification; 137 import android.net.ipsec.ike.IkeSessionCallback; 138 import android.net.ipsec.ike.IkeSessionConfiguration; 139 import android.net.ipsec.ike.IkeSessionConnectionInfo; 140 import android.net.ipsec.ike.IkeSessionParams; 141 import android.net.ipsec.ike.IkeTrafficSelector; 142 import android.net.ipsec.ike.IkeTunnelConnectionParams; 143 import android.net.ipsec.ike.exceptions.IkeException; 144 import android.net.ipsec.ike.exceptions.IkeNetworkLostException; 145 import android.net.ipsec.ike.exceptions.IkeNonProtocolException; 146 import android.net.ipsec.ike.exceptions.IkeProtocolException; 147 import android.net.ipsec.ike.exceptions.IkeTimeoutException; 148 import android.net.vcn.VcnTransportInfo; 149 import android.net.wifi.WifiInfo; 150 import android.os.Build.VERSION_CODES; 151 import android.os.Bundle; 152 import android.os.ConditionVariable; 153 import android.os.INetworkManagementService; 154 import android.os.ParcelFileDescriptor; 155 import android.os.PersistableBundle; 156 import android.os.PowerWhitelistManager; 157 import android.os.Process; 158 import android.os.UserHandle; 159 import android.os.UserManager; 160 import android.os.test.TestLooper; 161 import android.provider.Settings; 162 import android.security.Credentials; 163 import android.telephony.CarrierConfigManager; 164 import android.telephony.SubscriptionInfo; 165 import android.telephony.SubscriptionManager; 166 import android.telephony.TelephonyManager; 167 import android.util.ArrayMap; 168 import android.util.ArraySet; 169 import android.util.Pair; 170 import android.util.Range; 171 172 import androidx.test.filters.SmallTest; 173 174 import com.android.internal.R; 175 import com.android.internal.net.LegacyVpnInfo; 176 import com.android.internal.net.VpnConfig; 177 import com.android.internal.net.VpnProfile; 178 import com.android.internal.util.HexDump; 179 import com.android.internal.util.IndentingPrintWriter; 180 import com.android.server.DeviceIdleInternal; 181 import com.android.server.IpSecService; 182 import com.android.server.VpnTestBase; 183 import com.android.server.vcn.util.PersistableBundleUtils; 184 import com.android.testutils.DevSdkIgnoreRule; 185 import com.android.testutils.DevSdkIgnoreRunner; 186 187 import org.junit.Before; 188 import org.junit.Rule; 189 import org.junit.Test; 190 import org.junit.runner.RunWith; 191 import org.mockito.AdditionalAnswers; 192 import org.mockito.Answers; 193 import org.mockito.ArgumentCaptor; 194 import org.mockito.InOrder; 195 import org.mockito.Mock; 196 import org.mockito.MockitoAnnotations; 197 198 import java.io.BufferedWriter; 199 import java.io.File; 200 import java.io.FileDescriptor; 201 import java.io.FileWriter; 202 import java.io.IOException; 203 import java.io.StringWriter; 204 import java.net.Inet4Address; 205 import java.net.Inet6Address; 206 import java.net.InetAddress; 207 import java.net.UnknownHostException; 208 import java.util.ArrayList; 209 import java.util.Arrays; 210 import java.util.Collections; 211 import java.util.HashMap; 212 import java.util.List; 213 import java.util.Map; 214 import java.util.Set; 215 import java.util.SortedSet; 216 import java.util.TreeSet; 217 import java.util.concurrent.CompletableFuture; 218 import java.util.concurrent.ScheduledFuture; 219 import java.util.concurrent.ScheduledThreadPoolExecutor; 220 import java.util.concurrent.TimeUnit; 221 import java.util.regex.Matcher; 222 import java.util.regex.Pattern; 223 import java.util.stream.Stream; 224 225 /** 226 * Tests for {@link Vpn}. 227 * 228 * Build, install and run with: 229 * runtest frameworks-net -c com.android.server.connectivity.VpnTest 230 */ 231 @RunWith(DevSdkIgnoreRunner.class) 232 @SmallTest 233 @IgnoreUpTo(S_V2) 234 public class VpnTest extends VpnTestBase { 235 private static final String TAG = "VpnTest"; 236 237 @Rule 238 public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); 239 240 static final Network EGRESS_NETWORK = new Network(101); 241 static final String EGRESS_IFACE = "wlan0"; 242 private static final String TEST_VPN_CLIENT = "2.4.6.8"; 243 private static final String TEST_VPN_SERVER = "1.2.3.4"; 244 private static final String TEST_VPN_IDENTITY = "identity"; 245 private static final byte[] TEST_VPN_PSK = "psk".getBytes(); 246 247 private static final int IP4_PREFIX_LEN = 32; 248 private static final int IP6_PREFIX_LEN = 64; 249 private static final int MIN_PORT = 0; 250 private static final int MAX_PORT = 65535; 251 252 private static final InetAddress TEST_VPN_CLIENT_IP = 253 InetAddresses.parseNumericAddress(TEST_VPN_CLIENT); 254 private static final InetAddress TEST_VPN_SERVER_IP = 255 InetAddresses.parseNumericAddress(TEST_VPN_SERVER); 256 private static final InetAddress TEST_VPN_CLIENT_IP_2 = 257 InetAddresses.parseNumericAddress("192.0.2.200"); 258 private static final InetAddress TEST_VPN_SERVER_IP_2 = 259 InetAddresses.parseNumericAddress("192.0.2.201"); 260 private static final InetAddress TEST_VPN_INTERNAL_IP = 261 InetAddresses.parseNumericAddress("198.51.100.10"); 262 private static final InetAddress TEST_VPN_INTERNAL_IP6 = 263 InetAddresses.parseNumericAddress("2001:db8::1"); 264 private static final InetAddress TEST_VPN_INTERNAL_DNS = 265 InetAddresses.parseNumericAddress("8.8.8.8"); 266 private static final InetAddress TEST_VPN_INTERNAL_DNS6 = 267 InetAddresses.parseNumericAddress("2001:4860:4860::8888"); 268 269 private static final IkeTrafficSelector IN_TS = 270 new IkeTrafficSelector(MIN_PORT, MAX_PORT, TEST_VPN_INTERNAL_IP, TEST_VPN_INTERNAL_IP); 271 private static final IkeTrafficSelector IN_TS6 = 272 new IkeTrafficSelector( 273 MIN_PORT, MAX_PORT, TEST_VPN_INTERNAL_IP6, TEST_VPN_INTERNAL_IP6); 274 private static final IkeTrafficSelector OUT_TS = 275 new IkeTrafficSelector(MIN_PORT, MAX_PORT, 276 InetAddresses.parseNumericAddress("0.0.0.0"), 277 InetAddresses.parseNumericAddress("255.255.255.255")); 278 private static final IkeTrafficSelector OUT_TS6 = 279 new IkeTrafficSelector( 280 MIN_PORT, 281 MAX_PORT, 282 InetAddresses.parseNumericAddress("::"), 283 InetAddresses.parseNumericAddress("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); 284 285 private static final Network TEST_NETWORK = new Network(Integer.MAX_VALUE); 286 private static final Network TEST_NETWORK_2 = new Network(Integer.MAX_VALUE - 1); 287 private static final String TEST_IFACE_NAME = "TEST_IFACE"; 288 private static final int TEST_TUNNEL_RESOURCE_ID = 0x2345; 289 private static final long TEST_TIMEOUT_MS = 500L; 290 private static final long TIMEOUT_CROSSTHREAD_MS = 20_000L; 291 private static final String PRIMARY_USER_APP_EXCLUDE_KEY = 292 "VPNAPPEXCLUDED_27_com.testvpn.vpn"; 293 static final String PKGS_BYTES = getPackageByteString(List.of(PKGS)); 294 private static final Range<Integer> PRIMARY_USER_RANGE = uidRangeForUser(PRIMARY_USER.id); 295 private static final int TEST_KEEPALIVE_TIMER = 800; 296 private static final int TEST_SUB_ID = 1234; 297 private static final String TEST_MCCMNC = "12345"; 298 299 @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; 300 @Mock private UserManager mUserManager; 301 @Mock private PackageManager mPackageManager; 302 @Mock private INetworkManagementService mNetService; 303 @Mock private INetd mNetd; 304 @Mock private AppOpsManager mAppOps; 305 @Mock private NotificationManager mNotificationManager; 306 @Mock private Vpn.SystemServices mSystemServices; 307 @Mock private Vpn.IkeSessionWrapper mIkeSessionWrapper; 308 @Mock private Vpn.Ikev2SessionCreator mIkev2SessionCreator; 309 @Mock private Vpn.VpnNetworkAgentWrapper mMockNetworkAgent; 310 @Mock private ConnectivityManager mConnectivityManager; 311 @Mock private ConnectivityDiagnosticsManager mCdm; 312 @Mock private TelephonyManager mTelephonyManager; 313 @Mock private TelephonyManager mTmPerSub; 314 @Mock private CarrierConfigManager mConfigManager; 315 @Mock private SubscriptionManager mSubscriptionManager; 316 @Mock private IpSecService mIpSecService; 317 @Mock private VpnProfileStore mVpnProfileStore; 318 private final TestExecutor mExecutor; 319 @Mock DeviceIdleInternal mDeviceIdleInternal; 320 private final VpnProfile mVpnProfile; 321 322 private IpSecManager mIpSecManager; 323 private TestDeps mTestDeps; 324 325 public static class TestExecutor extends ScheduledThreadPoolExecutor { 326 public static final long REAL_DELAY = -1; 327 328 // For the purposes of the test, run all scheduled tasks after 10ms to save 329 // execution time, unless overridden by the specific test. Set to REAL_DELAY 330 // to actually wait for the delay specified by the real call to schedule(). 331 public long delayMs = 10; 332 // If this is true, execute() will call the runnable inline. This is useful because 333 // super.execute() calls schedule(), which messes with checks that scheduled() is 334 // called a given number of times. 335 public boolean executeDirect = false; 336 TestExecutor()337 public TestExecutor() { 338 super(1); 339 } 340 341 @Override execute(final Runnable command)342 public void execute(final Runnable command) { 343 // See |executeDirect| for why this is necessary. 344 if (executeDirect) { 345 command.run(); 346 } else { 347 super.execute(command); 348 } 349 } 350 351 @Override schedule(final Runnable command, final long delay, TimeUnit unit)352 public ScheduledFuture<?> schedule(final Runnable command, final long delay, 353 TimeUnit unit) { 354 if (0 == delay || delayMs == REAL_DELAY) { 355 // super.execute() calls schedule() with 0, so use the real delay if it's 0. 356 return super.schedule(command, delay, unit); 357 } else { 358 return super.schedule(command, delayMs, TimeUnit.MILLISECONDS); 359 } 360 } 361 } 362 VpnTest()363 public VpnTest() throws Exception { 364 // Build an actual VPN profile that is capable of being converted to and from an 365 // Ikev2VpnProfile 366 final Ikev2VpnProfile.Builder builder = 367 new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY); 368 builder.setAuthPsk(TEST_VPN_PSK); 369 builder.setBypassable(true /* isBypassable */); 370 mExecutor = spy(new TestExecutor()); 371 mVpnProfile = builder.build().toVpnProfile(); 372 } 373 374 @Before setUp()375 public void setUp() throws Exception { 376 MockitoAnnotations.initMocks(this); 377 378 mIpSecManager = new IpSecManager(mContext, mIpSecService); 379 mTestDeps = spy(new TestDeps()); 380 doReturn(IPV6_MIN_MTU) 381 .when(mTestDeps) 382 .calculateVpnMtu(any(), anyInt(), anyInt(), anyBoolean()); 383 doReturn(1500).when(mTestDeps).getJavaNetworkInterfaceMtu(any(), anyInt()); 384 385 when(mContext.getPackageManager()).thenReturn(mPackageManager); 386 setMockedPackages(sPackages); 387 388 when(mContext.getPackageName()).thenReturn(TEST_VPN_PKG); 389 when(mContext.getOpPackageName()).thenReturn(TEST_VPN_PKG); 390 mockService(UserManager.class, Context.USER_SERVICE, mUserManager); 391 mockService(AppOpsManager.class, Context.APP_OPS_SERVICE, mAppOps); 392 mockService(NotificationManager.class, Context.NOTIFICATION_SERVICE, mNotificationManager); 393 mockService(ConnectivityManager.class, Context.CONNECTIVITY_SERVICE, mConnectivityManager); 394 mockService(IpSecManager.class, Context.IPSEC_SERVICE, mIpSecManager); 395 mockService(ConnectivityDiagnosticsManager.class, Context.CONNECTIVITY_DIAGNOSTICS_SERVICE, 396 mCdm); 397 mockService(TelephonyManager.class, Context.TELEPHONY_SERVICE, mTelephonyManager); 398 mockService(CarrierConfigManager.class, Context.CARRIER_CONFIG_SERVICE, mConfigManager); 399 mockService(SubscriptionManager.class, Context.TELEPHONY_SUBSCRIPTION_SERVICE, 400 mSubscriptionManager); 401 doReturn(mTmPerSub).when(mTelephonyManager).createForSubscriptionId(anyInt()); 402 when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)) 403 .thenReturn(Resources.getSystem().getString( 404 R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)); 405 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) 406 .thenReturn(true); 407 408 // Used by {@link Notification.Builder} 409 ApplicationInfo applicationInfo = new ApplicationInfo(); 410 applicationInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT; 411 when(mContext.getApplicationInfo()).thenReturn(applicationInfo); 412 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 413 .thenReturn(applicationInfo); 414 415 doNothing().when(mNetService).registerObserver(any()); 416 417 // Deny all appops by default. 418 when(mAppOps.noteOpNoThrow(anyString(), anyInt(), anyString(), any(), any())) 419 .thenReturn(AppOpsManager.MODE_IGNORED); 420 421 // Setup IpSecService 422 final IpSecTunnelInterfaceResponse tunnelResp = 423 new IpSecTunnelInterfaceResponse( 424 IpSecManager.Status.OK, TEST_TUNNEL_RESOURCE_ID, TEST_IFACE_NAME); 425 when(mIpSecService.createTunnelInterface(any(), any(), any(), any(), any())) 426 .thenReturn(tunnelResp); 427 doReturn(new LinkProperties()).when(mConnectivityManager).getLinkProperties(any()); 428 429 // The unit test should know what kind of permission it needs and set the permission by 430 // itself, so set the default value of Context#checkCallingOrSelfPermission to 431 // PERMISSION_DENIED. 432 doReturn(PERMISSION_DENIED).when(mContext).checkCallingOrSelfPermission(any()); 433 434 // Set up mIkev2SessionCreator and mExecutor 435 resetIkev2SessionCreator(mIkeSessionWrapper); 436 } 437 resetIkev2SessionCreator(Vpn.IkeSessionWrapper ikeSession)438 private void resetIkev2SessionCreator(Vpn.IkeSessionWrapper ikeSession) { 439 reset(mIkev2SessionCreator); 440 when(mIkev2SessionCreator.createIkeSession(any(), any(), any(), any(), any(), any())) 441 .thenReturn(ikeSession); 442 } 443 mockService(Class<T> clazz, String name, T service)444 private <T> void mockService(Class<T> clazz, String name, T service) { 445 doReturn(service).when(mContext).getSystemService(name); 446 doReturn(name).when(mContext).getSystemServiceName(clazz); 447 if (mContext.getSystemService(clazz).getClass().equals(Object.class)) { 448 // Test is using mockito-extended (mContext uses Answers.RETURNS_DEEP_STUBS and returned 449 // a mock object on a final method) 450 doCallRealMethod().when(mContext).getSystemService(clazz); 451 } 452 } 453 rangeSet(Range<Integer> .... ranges)454 private Set<Range<Integer>> rangeSet(Range<Integer> ... ranges) { 455 final Set<Range<Integer>> range = new ArraySet<>(); 456 for (Range<Integer> r : ranges) range.add(r); 457 458 return range; 459 } 460 uidRangeForUser(int userId)461 private static Range<Integer> uidRangeForUser(int userId) { 462 return new Range<Integer>(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1); 463 } 464 uidRange(int start, int stop)465 private Range<Integer> uidRange(int start, int stop) { 466 return new Range<Integer>(start, stop); 467 } 468 getPackageByteString(List<String> packages)469 private static String getPackageByteString(List<String> packages) { 470 try { 471 return HexDump.toHexString( 472 PersistableBundleUtils.toDiskStableBytes(PersistableBundleUtils.fromList( 473 packages, PersistableBundleUtils.STRING_SERIALIZER)), 474 true /* upperCase */); 475 } catch (IOException e) { 476 return null; 477 } 478 } 479 480 @Test testRestrictedProfilesAreAddedToVpn()481 public void testRestrictedProfilesAreAddedToVpn() { 482 setMockedUsers(PRIMARY_USER, SECONDARY_USER, RESTRICTED_PROFILE_A, RESTRICTED_PROFILE_B); 483 484 final Vpn vpn = createVpn(PRIMARY_USER.id); 485 486 // Assume the user can have restricted profiles. 487 doReturn(true).when(mUserManager).canHaveRestrictedProfile(); 488 final Set<Range<Integer>> ranges = 489 vpn.createUserAndRestrictedProfilesRanges(PRIMARY_USER.id, null, null); 490 491 assertEquals(rangeSet(PRIMARY_USER_RANGE, uidRangeForUser(RESTRICTED_PROFILE_A.id)), 492 ranges); 493 } 494 495 @Test testManagedProfilesAreNotAddedToVpn()496 public void testManagedProfilesAreNotAddedToVpn() { 497 setMockedUsers(PRIMARY_USER, MANAGED_PROFILE_A); 498 499 final Vpn vpn = createVpn(PRIMARY_USER.id); 500 final Set<Range<Integer>> ranges = vpn.createUserAndRestrictedProfilesRanges( 501 PRIMARY_USER.id, null, null); 502 503 assertEquals(rangeSet(PRIMARY_USER_RANGE), ranges); 504 } 505 506 @Test testAddUserToVpnOnlyAddsOneUser()507 public void testAddUserToVpnOnlyAddsOneUser() { 508 setMockedUsers(PRIMARY_USER, RESTRICTED_PROFILE_A, MANAGED_PROFILE_A); 509 510 final Vpn vpn = createVpn(PRIMARY_USER.id); 511 final Set<Range<Integer>> ranges = new ArraySet<>(); 512 vpn.addUserToRanges(ranges, PRIMARY_USER.id, null, null); 513 514 assertEquals(rangeSet(PRIMARY_USER_RANGE), ranges); 515 } 516 517 @Test testUidAllowAndDenylist()518 public void testUidAllowAndDenylist() throws Exception { 519 final Vpn vpn = createVpn(PRIMARY_USER.id); 520 final Range<Integer> user = PRIMARY_USER_RANGE; 521 final int userStart = user.getLower(); 522 final int userStop = user.getUpper(); 523 final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; 524 525 // Allowed list 526 final Set<Range<Integer>> allow = vpn.createUserAndRestrictedProfilesRanges(PRIMARY_USER.id, 527 Arrays.asList(packages), null /* disallowedApplications */); 528 assertEquals(rangeSet( 529 uidRange(userStart + PKG_UIDS[0], userStart + PKG_UIDS[0]), 530 uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2]), 531 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[0]), 532 Process.toSdkSandboxUid(userStart + PKG_UIDS[0])), 533 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[1]), 534 Process.toSdkSandboxUid(userStart + PKG_UIDS[2]))), 535 allow); 536 537 // Denied list 538 final Set<Range<Integer>> disallow = 539 vpn.createUserAndRestrictedProfilesRanges(PRIMARY_USER.id, 540 null /* allowedApplications */, Arrays.asList(packages)); 541 assertEquals(rangeSet( 542 uidRange(userStart, userStart + PKG_UIDS[0] - 1), 543 uidRange(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), 544 /* Empty range between UIDS[1] and UIDS[2], should be excluded, */ 545 uidRange(userStart + PKG_UIDS[2] + 1, 546 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 547 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 548 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 549 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop)), 550 disallow); 551 } 552 verifyPowerSaveTempWhitelistApp(String packageName)553 private void verifyPowerSaveTempWhitelistApp(String packageName) { 554 verify(mDeviceIdleInternal, timeout(TEST_TIMEOUT_MS)).addPowerSaveTempWhitelistApp( 555 anyInt(), eq(packageName), anyLong(), anyInt(), eq(false), 556 eq(PowerWhitelistManager.REASON_VPN), eq("VpnManager event")); 557 } 558 559 @Test testGetAlwaysAndOnGetLockDown()560 public void testGetAlwaysAndOnGetLockDown() throws Exception { 561 final Vpn vpn = createVpn(PRIMARY_USER.id); 562 563 // Default state. 564 assertFalse(vpn.getAlwaysOn()); 565 assertFalse(vpn.getLockdown()); 566 567 // Set always-on without lockdown. 568 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList())); 569 assertTrue(vpn.getAlwaysOn()); 570 assertFalse(vpn.getLockdown()); 571 572 // Set always-on with lockdown. 573 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList())); 574 assertTrue(vpn.getAlwaysOn()); 575 assertTrue(vpn.getLockdown()); 576 577 // Remove always-on configuration. 578 assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList())); 579 assertFalse(vpn.getAlwaysOn()); 580 assertFalse(vpn.getLockdown()); 581 } 582 583 @Test testLockdownChangingPackage()584 public void testLockdownChangingPackage() throws Exception { 585 final Vpn vpn = createVpn(PRIMARY_USER.id); 586 final Range<Integer> user = PRIMARY_USER_RANGE; 587 final int userStart = user.getLower(); 588 final int userStop = user.getUpper(); 589 // Set always-on without lockdown. 590 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null)); 591 592 // Set always-on with lockdown. 593 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null)); 594 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 595 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), 596 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, 597 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 598 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) 599 })); 600 601 // Switch to another app. 602 assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null)); 603 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 604 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), 605 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, 606 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 607 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) 608 })); 609 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 610 new UidRangeParcel(userStart, userStart + PKG_UIDS[3] - 1), 611 new UidRangeParcel(userStart + PKG_UIDS[3] + 1, 612 Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)), 613 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop) 614 })); 615 } 616 617 @Test testLockdownAllowlist()618 public void testLockdownAllowlist() throws Exception { 619 final Vpn vpn = createVpn(PRIMARY_USER.id); 620 final Range<Integer> user = PRIMARY_USER_RANGE; 621 final int userStart = user.getLower(); 622 final int userStop = user.getUpper(); 623 // Set always-on with lockdown and allow app PKGS[2] from lockdown. 624 assertTrue(vpn.setAlwaysOnPackage( 625 PKGS[1], true, Collections.singletonList(PKGS[2]))); 626 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 627 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), 628 new UidRangeParcel(userStart + PKG_UIDS[2] + 1, 629 Process.toSdkSandboxUid(userStart + PKG_UIDS[1]) - 1), 630 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop) 631 })); 632 // Change allowed app list to PKGS[3]. 633 assertTrue(vpn.setAlwaysOnPackage( 634 PKGS[1], true, Collections.singletonList(PKGS[3]))); 635 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 636 new UidRangeParcel(userStart + PKG_UIDS[2] + 1, 637 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 638 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop) 639 })); 640 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 641 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1), 642 new UidRangeParcel(userStart + PKG_UIDS[3] + 1, 643 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 644 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), 645 Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)), 646 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop) 647 })); 648 649 // Change the VPN app. 650 assertTrue(vpn.setAlwaysOnPackage( 651 PKGS[0], true, Collections.singletonList(PKGS[3]))); 652 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 653 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), 654 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1), 655 new UidRangeParcel(userStart + PKG_UIDS[3] + 1, 656 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 657 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), 658 Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)) 659 })); 660 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 661 new UidRangeParcel(userStart, userStart + PKG_UIDS[0] - 1), 662 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1), 663 new UidRangeParcel(userStart + PKG_UIDS[3] + 1, 664 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 665 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 666 Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)) 667 })); 668 669 // Remove the list of allowed packages. 670 assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null)); 671 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 672 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1), 673 new UidRangeParcel(userStart + PKG_UIDS[3] + 1, 674 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 675 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 676 Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)), 677 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop) 678 })); 679 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 680 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, 681 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 682 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), userStop), 683 })); 684 685 // Add the list of allowed packages. 686 assertTrue(vpn.setAlwaysOnPackage( 687 PKGS[0], true, Collections.singletonList(PKGS[1]))); 688 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 689 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, 690 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 691 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), userStop), 692 })); 693 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 694 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), 695 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, 696 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 697 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 698 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 699 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) 700 })); 701 702 // Try allowing a package with a comma, should be rejected. 703 assertFalse(vpn.setAlwaysOnPackage( 704 PKGS[0], true, Collections.singletonList("a.b,c.d"))); 705 706 // Pass a non-existent packages in the allowlist, they (and only they) should be ignored. 707 // allowed package should change from PGKS[1] to PKGS[2]. 708 assertTrue(vpn.setAlwaysOnPackage( 709 PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"))); 710 verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { 711 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), 712 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, 713 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 714 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 715 Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), 716 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) 717 })); 718 verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { 719 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[2] - 1), 720 new UidRangeParcel(userStart + PKG_UIDS[2] + 1, 721 Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), 722 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), 723 Process.toSdkSandboxUid(userStart + PKG_UIDS[2] - 1)), 724 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop) 725 })); 726 } 727 728 @Test testLockdownRuleRepeatability()729 public void testLockdownRuleRepeatability() throws Exception { 730 final Vpn vpn = createVpn(PRIMARY_USER.id); 731 final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] { 732 new UidRangeParcel(PRIMARY_USER_RANGE.getLower(), PRIMARY_USER_RANGE.getUpper())}; 733 // Given legacy lockdown is already enabled, 734 vpn.setLockdown(true); 735 verify(mConnectivityManager, times(1)).setRequireVpnForUids(true, 736 toRanges(primaryUserRangeParcel)); 737 738 // Enabling legacy lockdown twice should do nothing. 739 vpn.setLockdown(true); 740 verify(mConnectivityManager, times(1)).setRequireVpnForUids(anyBoolean(), any()); 741 742 // And disabling should remove the rules exactly once. 743 vpn.setLockdown(false); 744 verify(mConnectivityManager, times(1)).setRequireVpnForUids(false, 745 toRanges(primaryUserRangeParcel)); 746 747 // Removing the lockdown again should have no effect. 748 vpn.setLockdown(false); 749 verify(mConnectivityManager, times(2)).setRequireVpnForUids(anyBoolean(), any()); 750 } 751 toRanges(UidRangeParcel[] ranges)752 private ArrayList<Range<Integer>> toRanges(UidRangeParcel[] ranges) { 753 ArrayList<Range<Integer>> rangesArray = new ArrayList<>(ranges.length); 754 for (int i = 0; i < ranges.length; i++) { 755 rangesArray.add(new Range<>(ranges[i].start, ranges[i].stop)); 756 } 757 return rangesArray; 758 } 759 760 @Test testLockdownRuleReversibility()761 public void testLockdownRuleReversibility() throws Exception { 762 doReturn(PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN); 763 final Vpn vpn = createVpn(PRIMARY_USER.id); 764 final UidRangeParcel[] entireUser = { 765 new UidRangeParcel(PRIMARY_USER_RANGE.getLower(), PRIMARY_USER_RANGE.getUpper()) 766 }; 767 final UidRangeParcel[] exceptPkg0 = { 768 new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), 769 new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1, 770 Process.toSdkSandboxUid(entireUser[0].start + PKG_UIDS[0] - 1)), 771 new UidRangeParcel(Process.toSdkSandboxUid(entireUser[0].start + PKG_UIDS[0] + 1), 772 entireUser[0].stop), 773 }; 774 775 final InOrder order = inOrder(mConnectivityManager); 776 777 // Given lockdown is enabled with no package (legacy VPN), 778 vpn.setLockdown(true); 779 order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(entireUser)); 780 781 // When a new VPN package is set the rules should change to cover that package. 782 vpn.prepare(null, PKGS[0], VpnManager.TYPE_VPN_SERVICE); 783 order.verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(entireUser)); 784 order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(exceptPkg0)); 785 786 // When that VPN package is unset, everything should be undone again in reverse. 787 vpn.prepare(null, VpnConfig.LEGACY_VPN, VpnManager.TYPE_VPN_SERVICE); 788 order.verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(exceptPkg0)); 789 order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(entireUser)); 790 } 791 792 @Test testPrepare_throwSecurityExceptionWhenGivenPackageDoesNotBelongToTheCaller()793 public void testPrepare_throwSecurityExceptionWhenGivenPackageDoesNotBelongToTheCaller() 794 throws Exception { 795 mTestDeps.mIgnoreCallingUidChecks = false; 796 final Vpn vpn = createVpn(); 797 assertThrows(SecurityException.class, 798 () -> vpn.prepare("com.not.vpn.owner", null, VpnManager.TYPE_VPN_SERVICE)); 799 assertThrows(SecurityException.class, 800 () -> vpn.prepare(null, "com.not.vpn.owner", VpnManager.TYPE_VPN_SERVICE)); 801 assertThrows(SecurityException.class, 802 () -> vpn.prepare("com.not.vpn.owner1", "com.not.vpn.owner2", 803 VpnManager.TYPE_VPN_SERVICE)); 804 } 805 806 @Test testPrepare_bothOldPackageAndNewPackageAreNull()807 public void testPrepare_bothOldPackageAndNewPackageAreNull() throws Exception { 808 final Vpn vpn = createVpn(); 809 assertTrue(vpn.prepare(null, null, VpnManager.TYPE_VPN_SERVICE)); 810 811 } 812 813 @Test testIsAlwaysOnPackageSupported()814 public void testIsAlwaysOnPackageSupported() throws Exception { 815 final Vpn vpn = createVpn(PRIMARY_USER.id); 816 817 ApplicationInfo appInfo = new ApplicationInfo(); 818 when(mPackageManager.getApplicationInfoAsUser(eq(PKGS[0]), anyInt(), eq(PRIMARY_USER.id))) 819 .thenReturn(appInfo); 820 821 ServiceInfo svcInfo = new ServiceInfo(); 822 ResolveInfo resInfo = new ResolveInfo(); 823 resInfo.serviceInfo = svcInfo; 824 when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA), 825 eq(PRIMARY_USER.id))) 826 .thenReturn(Collections.singletonList(resInfo)); 827 828 // null package name should return false 829 assertFalse(vpn.isAlwaysOnPackageSupported(null)); 830 831 // Pre-N apps are not supported 832 appInfo.targetSdkVersion = VERSION_CODES.M; 833 assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); 834 835 // N+ apps are supported by default 836 appInfo.targetSdkVersion = VERSION_CODES.N; 837 assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0])); 838 839 // Apps that opt out explicitly are not supported 840 appInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT; 841 Bundle metaData = new Bundle(); 842 metaData.putBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, false); 843 svcInfo.metaData = metaData; 844 assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); 845 } 846 847 @Test testNotificationShownForAlwaysOnApp()848 public void testNotificationShownForAlwaysOnApp() throws Exception { 849 final UserHandle userHandle = UserHandle.of(PRIMARY_USER.id); 850 final Vpn vpn = createVpn(PRIMARY_USER.id); 851 setMockedUsers(PRIMARY_USER); 852 853 final InOrder order = inOrder(mNotificationManager); 854 855 // Don't show a notification for regular disconnected states. 856 vpn.updateState(DetailedState.DISCONNECTED, TAG); 857 order.verify(mNotificationManager, atLeastOnce()).cancel(anyString(), anyInt()); 858 859 // Start showing a notification for disconnected once always-on. 860 vpn.setAlwaysOnPackage(PKGS[0], false, null); 861 order.verify(mNotificationManager).notify(anyString(), anyInt(), any()); 862 863 // Stop showing the notification once connected. 864 vpn.updateState(DetailedState.CONNECTED, TAG); 865 order.verify(mNotificationManager).cancel(anyString(), anyInt()); 866 867 // Show the notification if we disconnect again. 868 vpn.updateState(DetailedState.DISCONNECTED, TAG); 869 order.verify(mNotificationManager).notify(anyString(), anyInt(), any()); 870 871 // Notification should be cleared after unsetting always-on package. 872 vpn.setAlwaysOnPackage(null, false, null); 873 order.verify(mNotificationManager).cancel(anyString(), anyInt()); 874 } 875 876 /** 877 * The profile name should NOT change between releases for backwards compatibility 878 * 879 * <p>If this is changed between releases, the {@link Vpn#getVpnProfilePrivileged()} method MUST 880 * be updated to ensure backward compatibility. 881 */ 882 @Test testGetProfileNameForPackage()883 public void testGetProfileNameForPackage() throws Exception { 884 final Vpn vpn = createVpn(PRIMARY_USER.id); 885 setMockedUsers(PRIMARY_USER); 886 887 final String expected = Credentials.PLATFORM_VPN + PRIMARY_USER.id + "_" + TEST_VPN_PKG; 888 assertEquals(expected, vpn.getProfileNameForPackage(TEST_VPN_PKG)); 889 } 890 createVpn(String... grantedOps)891 private Vpn createVpn(String... grantedOps) throws Exception { 892 return createVpn(PRIMARY_USER, grantedOps); 893 } 894 createVpn(UserInfo user, String... grantedOps)895 private Vpn createVpn(UserInfo user, String... grantedOps) throws Exception { 896 final Vpn vpn = createVpn(user.id); 897 setMockedUsers(user); 898 899 for (final String opStr : grantedOps) { 900 when(mAppOps.noteOpNoThrow(opStr, Process.myUid(), TEST_VPN_PKG, 901 null /* attributionTag */, null /* message */)) 902 .thenReturn(AppOpsManager.MODE_ALLOWED); 903 } 904 905 return vpn; 906 } 907 checkProvisionVpnProfile(Vpn vpn, boolean expectedResult, String... checkedOps)908 private void checkProvisionVpnProfile(Vpn vpn, boolean expectedResult, String... checkedOps) { 909 assertEquals(expectedResult, vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile)); 910 911 // The profile should always be stored, whether or not consent has been previously granted. 912 verify(mVpnProfileStore) 913 .put( 914 eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)), 915 eq(mVpnProfile.encode())); 916 917 for (final String checkedOpStr : checkedOps) { 918 verify(mAppOps).noteOpNoThrow(checkedOpStr, Process.myUid(), TEST_VPN_PKG, 919 null /* attributionTag */, null /* message */); 920 } 921 } 922 923 @Test testProvisionVpnProfileNoIpsecTunnels()924 public void testProvisionVpnProfileNoIpsecTunnels() throws Exception { 925 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) 926 .thenReturn(false); 927 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 928 929 try { 930 checkProvisionVpnProfile( 931 vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 932 fail("Expected exception due to missing feature"); 933 } catch (UnsupportedOperationException expected) { 934 } 935 } 936 prepareVpnForVerifyAppExclusionList()937 private Vpn prepareVpnForVerifyAppExclusionList() throws Exception { 938 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 939 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 940 .thenReturn(mVpnProfile.encode()); 941 when(mVpnProfileStore.get(PRIMARY_USER_APP_EXCLUDE_KEY)) 942 .thenReturn(HexDump.hexStringToByteArray(PKGS_BYTES)); 943 944 vpn.startVpnProfile(TEST_VPN_PKG); 945 verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); 946 vpn.mNetworkAgent = mMockNetworkAgent; 947 return vpn; 948 } 949 950 @Test testSetAndGetAppExclusionList()951 public void testSetAndGetAppExclusionList() throws Exception { 952 final Vpn vpn = prepareVpnForVerifyAppExclusionList(); 953 verify(mVpnProfileStore, never()).put(eq(PRIMARY_USER_APP_EXCLUDE_KEY), any()); 954 vpn.setAppExclusionList(TEST_VPN_PKG, Arrays.asList(PKGS)); 955 verify(mVpnProfileStore) 956 .put(eq(PRIMARY_USER_APP_EXCLUDE_KEY), 957 eq(HexDump.hexStringToByteArray(PKGS_BYTES))); 958 assertEquals(vpn.createUserAndRestrictedProfilesRanges( 959 PRIMARY_USER.id, null, Arrays.asList(PKGS)), 960 vpn.mNetworkCapabilities.getUids()); 961 assertEquals(Arrays.asList(PKGS), vpn.getAppExclusionList(TEST_VPN_PKG)); 962 } 963 964 @Test testRefreshPlatformVpnAppExclusionList_updatesExcludedUids()965 public void testRefreshPlatformVpnAppExclusionList_updatesExcludedUids() throws Exception { 966 final Vpn vpn = prepareVpnForVerifyAppExclusionList(); 967 vpn.setAppExclusionList(TEST_VPN_PKG, Arrays.asList(PKGS)); 968 verify(mMockNetworkAgent).doSendNetworkCapabilities(any()); 969 assertEquals(Arrays.asList(PKGS), vpn.getAppExclusionList(TEST_VPN_PKG)); 970 971 reset(mMockNetworkAgent); 972 973 // Remove one of the package 974 List<Integer> newExcludedUids = toList(PKG_UIDS); 975 newExcludedUids.remove((Integer) PKG_UIDS[0]); 976 sPackages.remove(PKGS[0]); 977 vpn.refreshPlatformVpnAppExclusionList(); 978 979 // List in keystore is not changed, but UID for the removed packages is no longer exempted. 980 assertEquals(Arrays.asList(PKGS), vpn.getAppExclusionList(TEST_VPN_PKG)); 981 assertEquals(makeVpnUidRange(PRIMARY_USER.id, newExcludedUids), 982 vpn.mNetworkCapabilities.getUids()); 983 ArgumentCaptor<NetworkCapabilities> ncCaptor = 984 ArgumentCaptor.forClass(NetworkCapabilities.class); 985 verify(mMockNetworkAgent).doSendNetworkCapabilities(ncCaptor.capture()); 986 assertEquals(makeVpnUidRange(PRIMARY_USER.id, newExcludedUids), 987 ncCaptor.getValue().getUids()); 988 989 reset(mMockNetworkAgent); 990 991 // Add the package back 992 newExcludedUids.add(PKG_UIDS[0]); 993 sPackages.put(PKGS[0], PKG_UIDS[0]); 994 vpn.refreshPlatformVpnAppExclusionList(); 995 996 // List in keystore is not changed and the uid list should be updated in the net cap. 997 assertEquals(Arrays.asList(PKGS), vpn.getAppExclusionList(TEST_VPN_PKG)); 998 assertEquals(makeVpnUidRange(PRIMARY_USER.id, newExcludedUids), 999 vpn.mNetworkCapabilities.getUids()); 1000 verify(mMockNetworkAgent).doSendNetworkCapabilities(ncCaptor.capture()); 1001 assertEquals(makeVpnUidRange(PRIMARY_USER.id, newExcludedUids), 1002 ncCaptor.getValue().getUids()); 1003 } 1004 makeVpnUidRange(int userId, List<Integer> excludedList)1005 private Set<Range<Integer>> makeVpnUidRange(int userId, List<Integer> excludedList) { 1006 final SortedSet<Integer> list = new TreeSet<>(); 1007 1008 final int userBase = userId * UserHandle.PER_USER_RANGE; 1009 for (int uid : excludedList) { 1010 final int applicationUid = UserHandle.getUid(userId, uid); 1011 list.add(applicationUid); 1012 list.add(Process.toSdkSandboxUid(applicationUid)); // Add Sdk Sandbox UID 1013 } 1014 1015 final int minUid = userBase; 1016 final int maxUid = userBase + UserHandle.PER_USER_RANGE - 1; 1017 final Set<Range<Integer>> ranges = new ArraySet<>(); 1018 1019 // Iterate the list to create the ranges between each uid. 1020 int start = minUid; 1021 for (int uid : list) { 1022 if (uid == start) { 1023 start++; 1024 } else { 1025 ranges.add(new Range<>(start, uid - 1)); 1026 start = uid + 1; 1027 } 1028 } 1029 1030 // Create the range between last uid and max uid. 1031 if (start <= maxUid) { 1032 ranges.add(new Range<>(start, maxUid)); 1033 } 1034 1035 return ranges; 1036 } 1037 1038 @Test testSetAndGetAppExclusionListRestrictedUser()1039 public void testSetAndGetAppExclusionListRestrictedUser() throws Exception { 1040 final Vpn vpn = prepareVpnForVerifyAppExclusionList(); 1041 1042 // Mock it to restricted profile 1043 when(mUserManager.getUserInfo(anyInt())).thenReturn(RESTRICTED_PROFILE_A); 1044 1045 // Restricted users cannot configure VPNs 1046 assertThrows(SecurityException.class, 1047 () -> vpn.setAppExclusionList(TEST_VPN_PKG, new ArrayList<>())); 1048 1049 assertEquals(Arrays.asList(PKGS), vpn.getAppExclusionList(TEST_VPN_PKG)); 1050 } 1051 1052 @Test testProvisionVpnProfilePreconsented()1053 public void testProvisionVpnProfilePreconsented() throws Exception { 1054 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1055 1056 checkProvisionVpnProfile( 1057 vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1058 } 1059 1060 @Test testProvisionVpnProfileNotPreconsented()1061 public void testProvisionVpnProfileNotPreconsented() throws Exception { 1062 final Vpn vpn = createVpn(); 1063 1064 // Expect that both the ACTIVATE_VPN and ACTIVATE_PLATFORM_VPN were tried, but the caller 1065 // had neither. 1066 checkProvisionVpnProfile(vpn, false /* expectedResult */, 1067 AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN, AppOpsManager.OPSTR_ACTIVATE_VPN); 1068 } 1069 1070 @Test testProvisionVpnProfileVpnServicePreconsented()1071 public void testProvisionVpnProfileVpnServicePreconsented() throws Exception { 1072 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_VPN); 1073 1074 checkProvisionVpnProfile(vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_VPN); 1075 } 1076 1077 @Test testProvisionVpnProfileTooLarge()1078 public void testProvisionVpnProfileTooLarge() throws Exception { 1079 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1080 1081 final VpnProfile bigProfile = new VpnProfile(""); 1082 bigProfile.name = new String(new byte[Vpn.MAX_VPN_PROFILE_SIZE_BYTES + 1]); 1083 1084 try { 1085 vpn.provisionVpnProfile(TEST_VPN_PKG, bigProfile); 1086 fail("Expected IAE due to profile size"); 1087 } catch (IllegalArgumentException expected) { 1088 } 1089 } 1090 1091 @Test testProvisionVpnProfileRestrictedUser()1092 public void testProvisionVpnProfileRestrictedUser() throws Exception { 1093 final Vpn vpn = 1094 createVpn( 1095 RESTRICTED_PROFILE_A, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1096 1097 try { 1098 vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile); 1099 fail("Expected SecurityException due to restricted user"); 1100 } catch (SecurityException expected) { 1101 } 1102 } 1103 1104 @Test testDeleteVpnProfile()1105 public void testDeleteVpnProfile() throws Exception { 1106 final Vpn vpn = createVpn(); 1107 1108 vpn.deleteVpnProfile(TEST_VPN_PKG); 1109 1110 verify(mVpnProfileStore) 1111 .remove(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); 1112 } 1113 1114 @Test testDeleteVpnProfileRestrictedUser()1115 public void testDeleteVpnProfileRestrictedUser() throws Exception { 1116 final Vpn vpn = 1117 createVpn( 1118 RESTRICTED_PROFILE_A, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1119 1120 try { 1121 vpn.deleteVpnProfile(TEST_VPN_PKG); 1122 fail("Expected SecurityException due to restricted user"); 1123 } catch (SecurityException expected) { 1124 } 1125 } 1126 1127 @Test testGetVpnProfilePrivileged()1128 public void testGetVpnProfilePrivileged() throws Exception { 1129 final Vpn vpn = createVpn(); 1130 1131 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1132 .thenReturn(new VpnProfile("").encode()); 1133 1134 vpn.getVpnProfilePrivileged(TEST_VPN_PKG); 1135 1136 verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); 1137 } 1138 verifyPlatformVpnIsActivated(String packageName)1139 private void verifyPlatformVpnIsActivated(String packageName) { 1140 verify(mAppOps).noteOpNoThrow( 1141 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), 1142 eq(Process.myUid()), 1143 eq(packageName), 1144 eq(null) /* attributionTag */, 1145 eq(null) /* message */); 1146 verify(mAppOps).startOp( 1147 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER), 1148 eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())), 1149 eq(packageName), 1150 eq(null) /* attributionTag */, 1151 eq(null) /* message */); 1152 } 1153 verifyPlatformVpnIsDeactivated(String packageName)1154 private void verifyPlatformVpnIsDeactivated(String packageName) { 1155 // Add a small delay to double confirm that finishOp is only called once. 1156 verify(mAppOps, after(100)).finishOp( 1157 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER), 1158 eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())), 1159 eq(packageName), 1160 eq(null) /* attributionTag */); 1161 } 1162 1163 @Test testStartVpnProfile()1164 public void testStartVpnProfile() throws Exception { 1165 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1166 1167 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1168 .thenReturn(mVpnProfile.encode()); 1169 1170 vpn.startVpnProfile(TEST_VPN_PKG); 1171 1172 verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); 1173 verifyPlatformVpnIsActivated(TEST_VPN_PKG); 1174 } 1175 1176 @Test testStartVpnProfileVpnServicePreconsented()1177 public void testStartVpnProfileVpnServicePreconsented() throws Exception { 1178 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_VPN); 1179 1180 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1181 .thenReturn(mVpnProfile.encode()); 1182 1183 vpn.startVpnProfile(TEST_VPN_PKG); 1184 1185 // Verify that the ACTIVATE_VPN appop was checked, but no error was thrown. 1186 verify(mAppOps).noteOpNoThrow(AppOpsManager.OPSTR_ACTIVATE_VPN, Process.myUid(), 1187 TEST_VPN_PKG, null /* attributionTag */, null /* message */); 1188 } 1189 1190 @Test testStartVpnProfileNotConsented()1191 public void testStartVpnProfileNotConsented() throws Exception { 1192 final Vpn vpn = createVpn(); 1193 1194 try { 1195 vpn.startVpnProfile(TEST_VPN_PKG); 1196 fail("Expected failure due to no user consent"); 1197 } catch (SecurityException expected) { 1198 } 1199 1200 // Verify both appops were checked. 1201 verify(mAppOps) 1202 .noteOpNoThrow( 1203 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), 1204 eq(Process.myUid()), 1205 eq(TEST_VPN_PKG), 1206 eq(null) /* attributionTag */, 1207 eq(null) /* message */); 1208 verify(mAppOps).noteOpNoThrow(AppOpsManager.OPSTR_ACTIVATE_VPN, Process.myUid(), 1209 TEST_VPN_PKG, null /* attributionTag */, null /* message */); 1210 1211 // Keystore should never have been accessed. 1212 verify(mVpnProfileStore, never()).get(any()); 1213 } 1214 1215 @Test testStartVpnProfileMissingProfile()1216 public void testStartVpnProfileMissingProfile() throws Exception { 1217 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1218 1219 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))).thenReturn(null); 1220 1221 try { 1222 vpn.startVpnProfile(TEST_VPN_PKG); 1223 fail("Expected failure due to missing profile"); 1224 } catch (IllegalArgumentException expected) { 1225 } 1226 1227 verify(mVpnProfileStore).get(vpn.getProfileNameForPackage(TEST_VPN_PKG)); 1228 verify(mAppOps) 1229 .noteOpNoThrow( 1230 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), 1231 eq(Process.myUid()), 1232 eq(TEST_VPN_PKG), 1233 eq(null) /* attributionTag */, 1234 eq(null) /* message */); 1235 } 1236 1237 @Test testStartVpnProfileRestrictedUser()1238 public void testStartVpnProfileRestrictedUser() throws Exception { 1239 final Vpn vpn = createVpn(RESTRICTED_PROFILE_A, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1240 1241 try { 1242 vpn.startVpnProfile(TEST_VPN_PKG); 1243 fail("Expected SecurityException due to restricted user"); 1244 } catch (SecurityException expected) { 1245 } 1246 } 1247 1248 @Test testStopVpnProfileRestrictedUser()1249 public void testStopVpnProfileRestrictedUser() throws Exception { 1250 final Vpn vpn = createVpn(RESTRICTED_PROFILE_A, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1251 1252 try { 1253 vpn.stopVpnProfile(TEST_VPN_PKG); 1254 fail("Expected SecurityException due to restricted user"); 1255 } catch (SecurityException expected) { 1256 } 1257 } 1258 1259 @Test testStartOpAndFinishOpWillBeCalledWhenPlatformVpnIsOnAndOff()1260 public void testStartOpAndFinishOpWillBeCalledWhenPlatformVpnIsOnAndOff() throws Exception { 1261 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1262 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1263 .thenReturn(mVpnProfile.encode()); 1264 vpn.startVpnProfile(TEST_VPN_PKG); 1265 verifyPlatformVpnIsActivated(TEST_VPN_PKG); 1266 // Add a small delay to make sure that startOp is only called once. 1267 verify(mAppOps, after(100).times(1)).startOp( 1268 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER), 1269 eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())), 1270 eq(TEST_VPN_PKG), 1271 eq(null) /* attributionTag */, 1272 eq(null) /* message */); 1273 // Check that the startOp is not called with OPSTR_ESTABLISH_VPN_SERVICE. 1274 verify(mAppOps, never()).startOp( 1275 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE), 1276 eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())), 1277 eq(TEST_VPN_PKG), 1278 eq(null) /* attributionTag */, 1279 eq(null) /* message */); 1280 vpn.stopVpnProfile(TEST_VPN_PKG); 1281 verifyPlatformVpnIsDeactivated(TEST_VPN_PKG); 1282 } 1283 1284 @Test testStartOpWithSeamlessHandover()1285 public void testStartOpWithSeamlessHandover() throws Exception { 1286 // Create with SYSTEM_USER so that establish() will match the user ID when checking 1287 // against Binder.getCallerUid 1288 final Vpn vpn = createVpn(SYSTEM_USER, AppOpsManager.OPSTR_ACTIVATE_VPN); 1289 assertTrue(vpn.prepare(TEST_VPN_PKG, null, VpnManager.TYPE_VPN_SERVICE)); 1290 final VpnConfig config = new VpnConfig(); 1291 config.user = "VpnTest"; 1292 config.addresses.add(new LinkAddress("192.0.2.2/32")); 1293 config.mtu = 1450; 1294 final ResolveInfo resolveInfo = new ResolveInfo(); 1295 final ServiceInfo serviceInfo = new ServiceInfo(); 1296 serviceInfo.permission = BIND_VPN_SERVICE; 1297 resolveInfo.serviceInfo = serviceInfo; 1298 when(mPackageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo); 1299 when(mContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true); 1300 vpn.establish(config); 1301 verify(mAppOps, times(1)).startOp( 1302 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE), 1303 eq(Process.myUid()), 1304 eq(TEST_VPN_PKG), 1305 eq(null) /* attributionTag */, 1306 eq(null) /* message */); 1307 // Call establish() twice with the same config, it should match seamless handover case and 1308 // startOp() shouldn't be called again. 1309 vpn.establish(config); 1310 verify(mAppOps, times(1)).startOp( 1311 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE), 1312 eq(Process.myUid()), 1313 eq(TEST_VPN_PKG), 1314 eq(null) /* attributionTag */, 1315 eq(null) /* message */); 1316 } 1317 verifyVpnManagerEvent(String sessionKey, String category, int errorClass, int errorCode, String[] packageName, @NonNull VpnProfileState... profileState)1318 private void verifyVpnManagerEvent(String sessionKey, String category, int errorClass, 1319 int errorCode, String[] packageName, @NonNull VpnProfileState... profileState) { 1320 final Context userContext = 1321 mContext.createContextAsUser(UserHandle.of(PRIMARY_USER.id), 0 /* flags */); 1322 final ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); 1323 1324 final int verifyTimes = profileState.length; 1325 verify(userContext, times(verifyTimes)).startService(intentArgumentCaptor.capture()); 1326 1327 for (int i = 0; i < verifyTimes; i++) { 1328 final Intent intent = intentArgumentCaptor.getAllValues().get(i); 1329 assertEquals(packageName[i], intent.getPackage()); 1330 assertEquals(sessionKey, intent.getStringExtra(VpnManager.EXTRA_SESSION_KEY)); 1331 final Set<String> categories = intent.getCategories(); 1332 assertTrue(categories.contains(category)); 1333 assertEquals(1, categories.size()); 1334 assertEquals(errorClass, 1335 intent.getIntExtra(VpnManager.EXTRA_ERROR_CLASS, -1 /* defaultValue */)); 1336 assertEquals(errorCode, 1337 intent.getIntExtra(VpnManager.EXTRA_ERROR_CODE, -1 /* defaultValue */)); 1338 // CATEGORY_EVENT_DEACTIVATED_BY_USER & CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED won't 1339 // send NetworkCapabilities & LinkProperties to VPN app. 1340 // For ERROR_CODE_NETWORK_LOST, the NetworkCapabilities & LinkProperties of underlying 1341 // network will be cleared. So the VPN app will receive null for those 2 extra values. 1342 if (category.equals(VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER) 1343 || category.equals(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED) 1344 || errorCode == VpnManager.ERROR_CODE_NETWORK_LOST) { 1345 assertNull(intent.getParcelableExtra( 1346 VpnManager.EXTRA_UNDERLYING_NETWORK_CAPABILITIES)); 1347 assertNull(intent.getParcelableExtra(VpnManager.EXTRA_UNDERLYING_LINK_PROPERTIES)); 1348 } else { 1349 assertNotNull(intent.getParcelableExtra( 1350 VpnManager.EXTRA_UNDERLYING_NETWORK_CAPABILITIES)); 1351 assertNotNull(intent.getParcelableExtra( 1352 VpnManager.EXTRA_UNDERLYING_LINK_PROPERTIES)); 1353 } 1354 1355 assertEquals(profileState[i], intent.getParcelableExtra( 1356 VpnManager.EXTRA_VPN_PROFILE_STATE, VpnProfileState.class)); 1357 } 1358 reset(userContext); 1359 } 1360 verifyDeactivatedByUser(String sessionKey, String[] packageName)1361 private void verifyDeactivatedByUser(String sessionKey, String[] packageName) { 1362 // CATEGORY_EVENT_DEACTIVATED_BY_USER is not an error event, so both of errorClass and 1363 // errorCode won't be set. 1364 verifyVpnManagerEvent(sessionKey, VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, 1365 -1 /* errorClass */, -1 /* errorCode */, packageName, 1366 // VPN NetworkAgnet does not switch to CONNECTED in the test, and the state is not 1367 // important here. Verify that the state as it is, i.e. CONNECTING state. 1368 new VpnProfileState(VpnProfileState.STATE_CONNECTING, 1369 sessionKey, false /* alwaysOn */, false /* lockdown */)); 1370 } 1371 verifyAlwaysOnStateChanged(String[] packageName, VpnProfileState... profileState)1372 private void verifyAlwaysOnStateChanged(String[] packageName, VpnProfileState... profileState) { 1373 verifyVpnManagerEvent(null /* sessionKey */, 1374 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */, 1375 -1 /* errorCode */, packageName, profileState); 1376 } 1377 1378 @Test testVpnManagerEventForUserDeactivated()1379 public void testVpnManagerEventForUserDeactivated() throws Exception { 1380 // For security reasons, Vpn#prepare() will check that oldPackage and newPackage are either 1381 // null or the package of the caller. This test will call Vpn#prepare() to pretend the old 1382 // VPN is replaced by a new one. But only Settings can change to some other packages, and 1383 // this is checked with CONTROL_VPN so simulate holding CONTROL_VPN in order to pass the 1384 // security checks. 1385 doReturn(PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN); 1386 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1387 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1388 .thenReturn(mVpnProfile.encode()); 1389 1390 // Test the case that the user deactivates the vpn in vpn app. 1391 final String sessionKey1 = vpn.startVpnProfile(TEST_VPN_PKG); 1392 verifyPlatformVpnIsActivated(TEST_VPN_PKG); 1393 vpn.stopVpnProfile(TEST_VPN_PKG); 1394 verifyPlatformVpnIsDeactivated(TEST_VPN_PKG); 1395 verifyPowerSaveTempWhitelistApp(TEST_VPN_PKG); 1396 reset(mDeviceIdleInternal); 1397 verifyDeactivatedByUser(sessionKey1, new String[] {TEST_VPN_PKG}); 1398 reset(mAppOps); 1399 1400 // Test the case that the user chooses another vpn and the original one is replaced. 1401 final String sessionKey2 = vpn.startVpnProfile(TEST_VPN_PKG); 1402 verifyPlatformVpnIsActivated(TEST_VPN_PKG); 1403 vpn.prepare(TEST_VPN_PKG, "com.new.vpn" /* newPackage */, TYPE_VPN_PLATFORM); 1404 verifyPlatformVpnIsDeactivated(TEST_VPN_PKG); 1405 verifyPowerSaveTempWhitelistApp(TEST_VPN_PKG); 1406 reset(mDeviceIdleInternal); 1407 verifyDeactivatedByUser(sessionKey2, new String[] {TEST_VPN_PKG}); 1408 } 1409 1410 @Test testVpnManagerEventForAlwaysOnChanged()1411 public void testVpnManagerEventForAlwaysOnChanged() throws Exception { 1412 // Calling setAlwaysOnPackage() needs to hold CONTROL_VPN. 1413 doReturn(PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN); 1414 final Vpn vpn = createVpn(PRIMARY_USER.id); 1415 // Enable VPN always-on for PKGS[1]. 1416 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false /* lockdown */, 1417 null /* lockdownAllowlist */)); 1418 verifyPowerSaveTempWhitelistApp(PKGS[1]); 1419 reset(mDeviceIdleInternal); 1420 verifyAlwaysOnStateChanged(new String[] {PKGS[1]}, 1421 new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1422 null /* sessionKey */, true /* alwaysOn */, false /* lockdown */)); 1423 1424 // Enable VPN lockdown for PKGS[1]. 1425 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true /* lockdown */, 1426 null /* lockdownAllowlist */)); 1427 verifyPowerSaveTempWhitelistApp(PKGS[1]); 1428 reset(mDeviceIdleInternal); 1429 verifyAlwaysOnStateChanged(new String[] {PKGS[1]}, 1430 new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1431 null /* sessionKey */, true /* alwaysOn */, true /* lockdown */)); 1432 1433 // Disable VPN lockdown for PKGS[1]. 1434 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false /* lockdown */, 1435 null /* lockdownAllowlist */)); 1436 verifyPowerSaveTempWhitelistApp(PKGS[1]); 1437 reset(mDeviceIdleInternal); 1438 verifyAlwaysOnStateChanged(new String[] {PKGS[1]}, 1439 new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1440 null /* sessionKey */, true /* alwaysOn */, false /* lockdown */)); 1441 1442 // Disable VPN always-on. 1443 assertTrue(vpn.setAlwaysOnPackage(null, false /* lockdown */, 1444 null /* lockdownAllowlist */)); 1445 verifyPowerSaveTempWhitelistApp(PKGS[1]); 1446 reset(mDeviceIdleInternal); 1447 verifyAlwaysOnStateChanged(new String[] {PKGS[1]}, 1448 new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1449 null /* sessionKey */, false /* alwaysOn */, false /* lockdown */)); 1450 1451 // Enable VPN always-on for PKGS[1] again. 1452 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false /* lockdown */, 1453 null /* lockdownAllowlist */)); 1454 verifyPowerSaveTempWhitelistApp(PKGS[1]); 1455 reset(mDeviceIdleInternal); 1456 verifyAlwaysOnStateChanged(new String[] {PKGS[1]}, 1457 new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1458 null /* sessionKey */, true /* alwaysOn */, false /* lockdown */)); 1459 1460 // Enable VPN always-on for PKGS[2]. 1461 assertTrue(vpn.setAlwaysOnPackage(PKGS[2], false /* lockdown */, 1462 null /* lockdownAllowlist */)); 1463 verifyPowerSaveTempWhitelistApp(PKGS[2]); 1464 reset(mDeviceIdleInternal); 1465 // PKGS[1] is replaced with PKGS[2]. 1466 // Pass 2 VpnProfileState objects to verifyVpnManagerEvent(), the first one is sent to 1467 // PKGS[1] to notify PKGS[1] that the VPN always-on is disabled, the second one is sent to 1468 // PKGS[2] to notify PKGS[2] that the VPN always-on is enabled. 1469 verifyAlwaysOnStateChanged(new String[] {PKGS[1], PKGS[2]}, 1470 new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1471 null /* sessionKey */, false /* alwaysOn */, false /* lockdown */), 1472 new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, 1473 null /* sessionKey */, true /* alwaysOn */, false /* lockdown */)); 1474 } 1475 1476 @Test testReconnectVpnManagerVpnWithAlwaysOnEnabled()1477 public void testReconnectVpnManagerVpnWithAlwaysOnEnabled() throws Exception { 1478 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1479 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1480 .thenReturn(mVpnProfile.encode()); 1481 vpn.startVpnProfile(TEST_VPN_PKG); 1482 verifyPlatformVpnIsActivated(TEST_VPN_PKG); 1483 1484 // Enable VPN always-on for TEST_VPN_PKG. 1485 assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, false /* lockdown */, 1486 null /* lockdownAllowlist */)); 1487 1488 // Reset to verify next startVpnProfile. 1489 reset(mAppOps); 1490 1491 vpn.stopVpnProfile(TEST_VPN_PKG); 1492 1493 // Reconnect the vpn with different package will cause exception. 1494 assertThrows(SecurityException.class, () -> vpn.startVpnProfile(PKGS[0])); 1495 1496 // Reconnect the vpn again with the vpn always on package w/o exception. 1497 vpn.startVpnProfile(TEST_VPN_PKG); 1498 verifyPlatformVpnIsActivated(TEST_VPN_PKG); 1499 } 1500 1501 @Test testLockdown_enableDisableWhileConnected()1502 public void testLockdown_enableDisableWhileConnected() throws Exception { 1503 final PlatformVpnSnapshot vpnSnapShot = verifySetupPlatformVpn( 1504 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */)); 1505 1506 final InOrder order = inOrder(mTestDeps); 1507 order.verify(mTestDeps, timeout(TIMEOUT_CROSSTHREAD_MS)) 1508 .newNetworkAgent(any(), any(), any(), any(), any(), any(), 1509 argThat(config -> config.allowBypass), any(), any()); 1510 1511 // Make VPN lockdown. 1512 assertTrue(vpnSnapShot.vpn.setAlwaysOnPackage(TEST_VPN_PKG, true /* lockdown */, 1513 null /* lockdownAllowlist */)); 1514 1515 order.verify(mTestDeps, timeout(TIMEOUT_CROSSTHREAD_MS)) 1516 .newNetworkAgent(any(), any(), any(), any(), any(), any(), 1517 argThat(config -> !config.allowBypass), any(), any()); 1518 1519 // Disable lockdown. 1520 assertTrue(vpnSnapShot.vpn.setAlwaysOnPackage(TEST_VPN_PKG, false /* lockdown */, 1521 null /* lockdownAllowlist */)); 1522 1523 order.verify(mTestDeps, timeout(TIMEOUT_CROSSTHREAD_MS)) 1524 .newNetworkAgent(any(), any(), any(), any(), any(), any(), 1525 argThat(config -> config.allowBypass), any(), any()); 1526 } 1527 1528 @Test testSetPackageAuthorizationVpnService()1529 public void testSetPackageAuthorizationVpnService() throws Exception { 1530 final Vpn vpn = createVpn(); 1531 1532 assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_SERVICE)); 1533 verify(mAppOps) 1534 .setMode( 1535 eq(AppOpsManager.OPSTR_ACTIVATE_VPN), 1536 eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())), 1537 eq(TEST_VPN_PKG), 1538 eq(AppOpsManager.MODE_ALLOWED)); 1539 } 1540 1541 @Test testSetPackageAuthorizationPlatformVpn()1542 public void testSetPackageAuthorizationPlatformVpn() throws Exception { 1543 final Vpn vpn = createVpn(); 1544 1545 assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, TYPE_VPN_PLATFORM)); 1546 verify(mAppOps) 1547 .setMode( 1548 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), 1549 eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())), 1550 eq(TEST_VPN_PKG), 1551 eq(AppOpsManager.MODE_ALLOWED)); 1552 } 1553 1554 @Test testSetPackageAuthorizationRevokeAuthorization()1555 public void testSetPackageAuthorizationRevokeAuthorization() throws Exception { 1556 final Vpn vpn = createVpn(); 1557 1558 assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_NONE)); 1559 verify(mAppOps) 1560 .setMode( 1561 eq(AppOpsManager.OPSTR_ACTIVATE_VPN), 1562 eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())), 1563 eq(TEST_VPN_PKG), 1564 eq(AppOpsManager.MODE_IGNORED)); 1565 verify(mAppOps) 1566 .setMode( 1567 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), 1568 eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())), 1569 eq(TEST_VPN_PKG), 1570 eq(AppOpsManager.MODE_IGNORED)); 1571 } 1572 triggerOnAvailableAndGetCallback()1573 private NetworkCallback triggerOnAvailableAndGetCallback() throws Exception { 1574 return triggerOnAvailableAndGetCallback(new NetworkCapabilities.Builder().build()); 1575 } 1576 triggerOnAvailableAndGetCallback( @onNull final NetworkCapabilities caps)1577 private NetworkCallback triggerOnAvailableAndGetCallback( 1578 @NonNull final NetworkCapabilities caps) throws Exception { 1579 final ArgumentCaptor<NetworkCallback> networkCallbackCaptor = 1580 ArgumentCaptor.forClass(NetworkCallback.class); 1581 verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)) 1582 .registerSystemDefaultNetworkCallback(networkCallbackCaptor.capture(), any()); 1583 1584 // onAvailable() will trigger onDefaultNetworkChanged(), so NetdUtils#setInterfaceUp will be 1585 // invoked. Set the return value of INetd#interfaceGetCfg to prevent NullPointerException. 1586 final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel(); 1587 config.flags = new String[] {IF_STATE_DOWN}; 1588 when(mNetd.interfaceGetCfg(anyString())).thenReturn(config); 1589 final NetworkCallback cb = networkCallbackCaptor.getValue(); 1590 cb.onAvailable(TEST_NETWORK); 1591 // Trigger onCapabilitiesChanged() and onLinkPropertiesChanged() so the test can verify that 1592 // if NetworkCapabilities and LinkProperties of underlying network will be sent/cleared or 1593 // not. 1594 // See verifyVpnManagerEvent(). 1595 cb.onCapabilitiesChanged(TEST_NETWORK, caps); 1596 cb.onLinkPropertiesChanged(TEST_NETWORK, new LinkProperties()); 1597 return cb; 1598 } 1599 verifyInterfaceSetCfgWithFlags(String flag)1600 private void verifyInterfaceSetCfgWithFlags(String flag) throws Exception { 1601 // Add a timeout for waiting for interfaceSetCfg to be called. 1602 verify(mNetd, timeout(TEST_TIMEOUT_MS)).interfaceSetCfg(argThat( 1603 config -> Arrays.asList(config.flags).contains(flag))); 1604 } 1605 doTestPlatformVpnWithException(IkeException exception, String category, int errorType, int errorCode)1606 private void doTestPlatformVpnWithException(IkeException exception, 1607 String category, int errorType, int errorCode) throws Exception { 1608 final ArgumentCaptor<IkeSessionCallback> captor = 1609 ArgumentCaptor.forClass(IkeSessionCallback.class); 1610 1611 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1612 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1613 .thenReturn(mVpnProfile.encode()); 1614 1615 doReturn(new NetworkCapabilities()).when(mConnectivityManager) 1616 .getRedactedNetworkCapabilitiesForPackage(any(), anyInt(), anyString()); 1617 doReturn(new LinkProperties()).when(mConnectivityManager) 1618 .getRedactedLinkPropertiesForPackage(any(), anyInt(), anyString()); 1619 1620 final String sessionKey = vpn.startVpnProfile(TEST_VPN_PKG); 1621 final NetworkCallback cb = triggerOnAvailableAndGetCallback(); 1622 1623 verifyInterfaceSetCfgWithFlags(IF_STATE_UP); 1624 1625 // Wait for createIkeSession() to be called before proceeding in order to ensure consistent 1626 // state 1627 verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS)) 1628 .createIkeSession(any(), any(), any(), any(), captor.capture(), any()); 1629 reset(mIkev2SessionCreator); 1630 // For network lost case, the process should be triggered by calling onLost(), which is the 1631 // same process with the real case. 1632 if (errorCode == VpnManager.ERROR_CODE_NETWORK_LOST) { 1633 cb.onLost(TEST_NETWORK); 1634 verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), anyLong(), any()); 1635 } else { 1636 final IkeSessionCallback ikeCb = captor.getValue(); 1637 ikeCb.onClosedWithException(exception); 1638 } 1639 1640 verifyPowerSaveTempWhitelistApp(TEST_VPN_PKG); 1641 reset(mDeviceIdleInternal); 1642 verifyVpnManagerEvent(sessionKey, category, errorType, errorCode, 1643 // VPN NetworkAgnet does not switch to CONNECTED in the test, and the state is not 1644 // important here. Verify that the state as it is, i.e. CONNECTING state. 1645 new String[] {TEST_VPN_PKG}, new VpnProfileState(VpnProfileState.STATE_CONNECTING, 1646 sessionKey, false /* alwaysOn */, false /* lockdown */)); 1647 if (errorType == VpnManager.ERROR_CLASS_NOT_RECOVERABLE) { 1648 verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)) 1649 .unregisterNetworkCallback(eq(cb)); 1650 } else if (errorType == VpnManager.ERROR_CLASS_RECOVERABLE 1651 // Vpn won't retry when there is no usable underlying network. 1652 && errorCode != VpnManager.ERROR_CODE_NETWORK_LOST) { 1653 int retryIndex = 0; 1654 final IkeSessionCallback ikeCb2 = verifyRetryAndGetNewIkeCb(retryIndex++); 1655 1656 ikeCb2.onClosedWithException(exception); 1657 verifyRetryAndGetNewIkeCb(retryIndex++); 1658 } 1659 } 1660 verifyRetryAndGetNewIkeCb(int retryIndex)1661 private IkeSessionCallback verifyRetryAndGetNewIkeCb(int retryIndex) { 1662 final ArgumentCaptor<IkeSessionCallback> ikeCbCaptor = 1663 ArgumentCaptor.forClass(IkeSessionCallback.class); 1664 1665 // Verify retry is scheduled 1666 final long expectedDelayMs = mTestDeps.getNextRetryDelayMs(retryIndex); 1667 final ArgumentCaptor<Long> delayCaptor = ArgumentCaptor.forClass(Long.class); 1668 verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), delayCaptor.capture(), 1669 eq(TimeUnit.MILLISECONDS)); 1670 final List<Long> delays = delayCaptor.getAllValues(); 1671 assertEquals(expectedDelayMs, (long) delays.get(delays.size() - 1)); 1672 1673 verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS + expectedDelayMs)) 1674 .createIkeSession(any(), any(), any(), any(), ikeCbCaptor.capture(), any()); 1675 1676 // Forget the mIkev2SessionCreator#createIkeSession call and mExecutor#schedule call 1677 // for the next retry verification 1678 resetIkev2SessionCreator(mIkeSessionWrapper); 1679 1680 return ikeCbCaptor.getValue(); 1681 } 1682 1683 @Test testStartPlatformVpnAuthenticationFailed()1684 public void testStartPlatformVpnAuthenticationFailed() throws Exception { 1685 final IkeProtocolException exception = mock(IkeProtocolException.class); 1686 final int errorCode = IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED; 1687 when(exception.getErrorType()).thenReturn(errorCode); 1688 doTestPlatformVpnWithException(exception, 1689 VpnManager.CATEGORY_EVENT_IKE_ERROR, VpnManager.ERROR_CLASS_NOT_RECOVERABLE, 1690 errorCode); 1691 } 1692 1693 @Test testStartPlatformVpnFailedWithRecoverableError()1694 public void testStartPlatformVpnFailedWithRecoverableError() throws Exception { 1695 final IkeProtocolException exception = mock(IkeProtocolException.class); 1696 final int errorCode = IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE; 1697 when(exception.getErrorType()).thenReturn(errorCode); 1698 doTestPlatformVpnWithException(exception, 1699 VpnManager.CATEGORY_EVENT_IKE_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, errorCode); 1700 } 1701 1702 @Test testStartPlatformVpnFailedWithUnknownHostException()1703 public void testStartPlatformVpnFailedWithUnknownHostException() throws Exception { 1704 final IkeNonProtocolException exception = mock(IkeNonProtocolException.class); 1705 final UnknownHostException unknownHostException = new UnknownHostException(); 1706 final int errorCode = VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST; 1707 when(exception.getCause()).thenReturn(unknownHostException); 1708 doTestPlatformVpnWithException(exception, 1709 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, 1710 errorCode); 1711 } 1712 1713 @Test testStartPlatformVpnFailedWithIkeTimeoutException()1714 public void testStartPlatformVpnFailedWithIkeTimeoutException() throws Exception { 1715 final IkeNonProtocolException exception = mock(IkeNonProtocolException.class); 1716 final IkeTimeoutException ikeTimeoutException = 1717 new IkeTimeoutException("IkeTimeoutException"); 1718 final int errorCode = VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT; 1719 when(exception.getCause()).thenReturn(ikeTimeoutException); 1720 doTestPlatformVpnWithException(exception, 1721 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, 1722 errorCode); 1723 } 1724 1725 @Test testStartPlatformVpnFailedWithIkeNetworkLostException()1726 public void testStartPlatformVpnFailedWithIkeNetworkLostException() throws Exception { 1727 final IkeNetworkLostException exception = new IkeNetworkLostException( 1728 new Network(100)); 1729 doTestPlatformVpnWithException(exception, 1730 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, 1731 VpnManager.ERROR_CODE_NETWORK_LOST); 1732 } 1733 1734 @Test testStartPlatformVpnFailedWithIOException()1735 public void testStartPlatformVpnFailedWithIOException() throws Exception { 1736 final IkeNonProtocolException exception = mock(IkeNonProtocolException.class); 1737 final IOException ioException = new IOException(); 1738 final int errorCode = VpnManager.ERROR_CODE_NETWORK_IO; 1739 when(exception.getCause()).thenReturn(ioException); 1740 doTestPlatformVpnWithException(exception, 1741 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, 1742 errorCode); 1743 } 1744 1745 @Test testStartPlatformVpnIllegalArgumentExceptionInSetup()1746 public void testStartPlatformVpnIllegalArgumentExceptionInSetup() throws Exception { 1747 when(mIkev2SessionCreator.createIkeSession(any(), any(), any(), any(), any(), any())) 1748 .thenThrow(new IllegalArgumentException()); 1749 final Vpn vpn = startLegacyVpn(createVpn(PRIMARY_USER.id), mVpnProfile); 1750 final NetworkCallback cb = triggerOnAvailableAndGetCallback(); 1751 1752 verifyInterfaceSetCfgWithFlags(IF_STATE_UP); 1753 1754 // Wait for createIkeSession() to be called before proceeding in order to ensure consistent 1755 // state 1756 verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb)); 1757 assertEquals(LegacyVpnInfo.STATE_FAILED, vpn.getLegacyVpnInfo().state); 1758 } 1759 1760 @Test testVpnManagerEventWillNotBeSentToSettingsVpn()1761 public void testVpnManagerEventWillNotBeSentToSettingsVpn() throws Exception { 1762 startLegacyVpn(createVpn(PRIMARY_USER.id), mVpnProfile); 1763 triggerOnAvailableAndGetCallback(); 1764 1765 verifyInterfaceSetCfgWithFlags(IF_STATE_UP); 1766 1767 final IkeNonProtocolException exception = mock(IkeNonProtocolException.class); 1768 final IkeTimeoutException ikeTimeoutException = 1769 new IkeTimeoutException("IkeTimeoutException"); 1770 when(exception.getCause()).thenReturn(ikeTimeoutException); 1771 1772 final ArgumentCaptor<IkeSessionCallback> captor = 1773 ArgumentCaptor.forClass(IkeSessionCallback.class); 1774 verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS)) 1775 .createIkeSession(any(), any(), any(), any(), captor.capture(), any()); 1776 final IkeSessionCallback ikeCb = captor.getValue(); 1777 ikeCb.onClosedWithException(exception); 1778 1779 final Context userContext = 1780 mContext.createContextAsUser(UserHandle.of(PRIMARY_USER.id), 0 /* flags */); 1781 verify(userContext, never()).startService(any()); 1782 } 1783 setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled)1784 private void setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled) { 1785 assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, lockdownEnabled, null)); 1786 1787 verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); 1788 verify(mAppOps).setMode( 1789 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), eq(uid), eq(TEST_VPN_PKG), 1790 eq(AppOpsManager.MODE_ALLOWED)); 1791 1792 verify(mSystemServices).settingsSecurePutStringForUser( 1793 eq(Settings.Secure.ALWAYS_ON_VPN_APP), eq(TEST_VPN_PKG), eq(PRIMARY_USER.id)); 1794 verify(mSystemServices).settingsSecurePutIntForUser( 1795 eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN), eq(lockdownEnabled ? 1 : 0), 1796 eq(PRIMARY_USER.id)); 1797 verify(mSystemServices).settingsSecurePutStringForUser( 1798 eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST), eq(""), eq(PRIMARY_USER.id)); 1799 } 1800 1801 @Test testSetAndStartAlwaysOnVpn()1802 public void testSetAndStartAlwaysOnVpn() throws Exception { 1803 final Vpn vpn = createVpn(PRIMARY_USER.id); 1804 setMockedUsers(PRIMARY_USER); 1805 1806 // UID checks must return a different UID; otherwise it'll be treated as already prepared. 1807 final int uid = Process.myUid() + 1; 1808 when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt())) 1809 .thenReturn(uid); 1810 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1811 .thenReturn(mVpnProfile.encode()); 1812 1813 setAndVerifyAlwaysOnPackage(vpn, uid, false); 1814 assertTrue(vpn.startAlwaysOnVpn()); 1815 1816 // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in 1817 // a subsequent CL. 1818 } 1819 startLegacyVpn(final Vpn vpn, final VpnProfile vpnProfile)1820 private Vpn startLegacyVpn(final Vpn vpn, final VpnProfile vpnProfile) throws Exception { 1821 setMockedUsers(PRIMARY_USER); 1822 1823 // Dummy egress interface 1824 final LinkProperties lp = new LinkProperties(); 1825 lp.setInterfaceName(EGRESS_IFACE); 1826 1827 final RouteInfo defaultRoute = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), 1828 InetAddresses.parseNumericAddress("192.0.2.0"), EGRESS_IFACE); 1829 lp.addRoute(defaultRoute); 1830 1831 vpn.startLegacyVpn(vpnProfile, EGRESS_NETWORK, lp); 1832 return vpn; 1833 } 1834 createIkeConnectInfo()1835 private IkeSessionConnectionInfo createIkeConnectInfo() { 1836 return new IkeSessionConnectionInfo(TEST_VPN_CLIENT_IP, TEST_VPN_SERVER_IP, TEST_NETWORK); 1837 } 1838 createIkeConnectInfo_2()1839 private IkeSessionConnectionInfo createIkeConnectInfo_2() { 1840 return new IkeSessionConnectionInfo( 1841 TEST_VPN_CLIENT_IP_2, TEST_VPN_SERVER_IP_2, TEST_NETWORK_2); 1842 } 1843 createIkeConfig( IkeSessionConnectionInfo ikeConnectInfo, boolean isMobikeEnabled)1844 private IkeSessionConfiguration createIkeConfig( 1845 IkeSessionConnectionInfo ikeConnectInfo, boolean isMobikeEnabled) { 1846 final IkeSessionConfiguration.Builder builder = 1847 new IkeSessionConfiguration.Builder(ikeConnectInfo); 1848 1849 if (isMobikeEnabled) { 1850 builder.addIkeExtension(EXTENSION_TYPE_MOBIKE); 1851 } 1852 1853 return builder.build(); 1854 } 1855 createChildConfig()1856 private ChildSessionConfiguration createChildConfig() { 1857 return new ChildSessionConfiguration.Builder( 1858 Arrays.asList(IN_TS, IN_TS6), Arrays.asList(OUT_TS, OUT_TS6)) 1859 .addInternalAddress(new LinkAddress(TEST_VPN_INTERNAL_IP, IP4_PREFIX_LEN)) 1860 .addInternalAddress(new LinkAddress(TEST_VPN_INTERNAL_IP6, IP6_PREFIX_LEN)) 1861 .addInternalDnsServer(TEST_VPN_INTERNAL_DNS) 1862 .addInternalDnsServer(TEST_VPN_INTERNAL_DNS6) 1863 .build(); 1864 } 1865 createIpSecTransform()1866 private IpSecTransform createIpSecTransform() { 1867 return new IpSecTransform(mContext, new IpSecConfig()); 1868 } 1869 verifyApplyTunnelModeTransforms(int expectedTimes)1870 private void verifyApplyTunnelModeTransforms(int expectedTimes) throws Exception { 1871 verify(mIpSecService, times(expectedTimes)).applyTunnelModeTransform( 1872 eq(TEST_TUNNEL_RESOURCE_ID), eq(IpSecManager.DIRECTION_IN), 1873 anyInt(), anyString()); 1874 verify(mIpSecService, times(expectedTimes)).applyTunnelModeTransform( 1875 eq(TEST_TUNNEL_RESOURCE_ID), eq(IpSecManager.DIRECTION_OUT), 1876 anyInt(), anyString()); 1877 } 1878 verifyCreateIkeAndCaptureCbs()1879 private Pair<IkeSessionCallback, ChildSessionCallback> verifyCreateIkeAndCaptureCbs() 1880 throws Exception { 1881 final ArgumentCaptor<IkeSessionCallback> ikeCbCaptor = 1882 ArgumentCaptor.forClass(IkeSessionCallback.class); 1883 final ArgumentCaptor<ChildSessionCallback> childCbCaptor = 1884 ArgumentCaptor.forClass(ChildSessionCallback.class); 1885 1886 verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS)).createIkeSession( 1887 any(), any(), any(), any(), ikeCbCaptor.capture(), childCbCaptor.capture()); 1888 1889 return new Pair<>(ikeCbCaptor.getValue(), childCbCaptor.getValue()); 1890 } 1891 1892 private static class PlatformVpnSnapshot { 1893 public final Vpn vpn; 1894 public final NetworkCallback nwCb; 1895 public final IkeSessionCallback ikeCb; 1896 public final ChildSessionCallback childCb; 1897 PlatformVpnSnapshot(Vpn vpn, NetworkCallback nwCb, IkeSessionCallback ikeCb, ChildSessionCallback childCb)1898 PlatformVpnSnapshot(Vpn vpn, NetworkCallback nwCb, 1899 IkeSessionCallback ikeCb, ChildSessionCallback childCb) { 1900 this.vpn = vpn; 1901 this.nwCb = nwCb; 1902 this.ikeCb = ikeCb; 1903 this.childCb = childCb; 1904 } 1905 } 1906 verifySetupPlatformVpn(IkeSessionConfiguration ikeConfig)1907 private PlatformVpnSnapshot verifySetupPlatformVpn(IkeSessionConfiguration ikeConfig) 1908 throws Exception { 1909 return verifySetupPlatformVpn(ikeConfig, true); 1910 } 1911 verifySetupPlatformVpn( IkeSessionConfiguration ikeConfig, boolean mtuSupportsIpv6)1912 private PlatformVpnSnapshot verifySetupPlatformVpn( 1913 IkeSessionConfiguration ikeConfig, boolean mtuSupportsIpv6) throws Exception { 1914 return verifySetupPlatformVpn(mVpnProfile, ikeConfig, mtuSupportsIpv6); 1915 } 1916 verifySetupPlatformVpn(VpnProfile vpnProfile, IkeSessionConfiguration ikeConfig, boolean mtuSupportsIpv6)1917 private PlatformVpnSnapshot verifySetupPlatformVpn(VpnProfile vpnProfile, 1918 IkeSessionConfiguration ikeConfig, boolean mtuSupportsIpv6) throws Exception { 1919 return verifySetupPlatformVpn(vpnProfile, ikeConfig, 1920 new NetworkCapabilities.Builder().build() /* underlying network caps */, 1921 mtuSupportsIpv6, false /* areLongLivedTcpConnectionsExpensive */); 1922 } 1923 verifySetupPlatformVpn(VpnProfile vpnProfile, IkeSessionConfiguration ikeConfig, @NonNull final NetworkCapabilities underlyingNetworkCaps, boolean mtuSupportsIpv6, boolean areLongLivedTcpConnectionsExpensive)1924 private PlatformVpnSnapshot verifySetupPlatformVpn(VpnProfile vpnProfile, 1925 IkeSessionConfiguration ikeConfig, 1926 @NonNull final NetworkCapabilities underlyingNetworkCaps, 1927 boolean mtuSupportsIpv6, 1928 boolean areLongLivedTcpConnectionsExpensive) throws Exception { 1929 if (!mtuSupportsIpv6) { 1930 doReturn(IPV6_MIN_MTU - 1).when(mTestDeps).calculateVpnMtu(any(), anyInt(), anyInt(), 1931 anyBoolean()); 1932 } 1933 1934 doReturn(mMockNetworkAgent).when(mTestDeps) 1935 .newNetworkAgent( 1936 any(), any(), anyString(), any(), any(), any(), any(), any(), any()); 1937 doReturn(TEST_NETWORK).when(mMockNetworkAgent).getNetwork(); 1938 1939 final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); 1940 when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) 1941 .thenReturn(vpnProfile.encode()); 1942 1943 vpn.startVpnProfile(TEST_VPN_PKG); 1944 final NetworkCallback nwCb = triggerOnAvailableAndGetCallback(underlyingNetworkCaps); 1945 verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), anyLong(), any()); 1946 reset(mExecutor); 1947 1948 // Mock the setup procedure by firing callbacks 1949 final Pair<IkeSessionCallback, ChildSessionCallback> cbPair = 1950 verifyCreateIkeAndCaptureCbs(); 1951 final IkeSessionCallback ikeCb = cbPair.first; 1952 final ChildSessionCallback childCb = cbPair.second; 1953 1954 ikeCb.onOpened(ikeConfig); 1955 childCb.onIpSecTransformCreated(createIpSecTransform(), IpSecManager.DIRECTION_IN); 1956 childCb.onIpSecTransformCreated(createIpSecTransform(), IpSecManager.DIRECTION_OUT); 1957 childCb.onOpened(createChildConfig()); 1958 1959 // Verification VPN setup 1960 verifyApplyTunnelModeTransforms(1); 1961 1962 ArgumentCaptor<LinkProperties> lpCaptor = ArgumentCaptor.forClass(LinkProperties.class); 1963 ArgumentCaptor<NetworkCapabilities> ncCaptor = 1964 ArgumentCaptor.forClass(NetworkCapabilities.class); 1965 ArgumentCaptor<NetworkAgentConfig> nacCaptor = 1966 ArgumentCaptor.forClass(NetworkAgentConfig.class); 1967 verify(mTestDeps).newNetworkAgent( 1968 any(), any(), anyString(), ncCaptor.capture(), lpCaptor.capture(), 1969 any(), nacCaptor.capture(), any(), any()); 1970 verify(mIkeSessionWrapper).setUnderpinnedNetwork(TEST_NETWORK); 1971 // Check LinkProperties 1972 final LinkProperties lp = lpCaptor.getValue(); 1973 final List<RouteInfo> expectedRoutes = 1974 new ArrayList<>( 1975 Arrays.asList( 1976 new RouteInfo( 1977 new IpPrefix(Inet4Address.ANY, 0), 1978 null /* gateway */, 1979 TEST_IFACE_NAME, 1980 RouteInfo.RTN_UNICAST))); 1981 final List<LinkAddress> expectedAddresses = 1982 new ArrayList<>( 1983 Arrays.asList(new LinkAddress(TEST_VPN_INTERNAL_IP, IP4_PREFIX_LEN))); 1984 final List<InetAddress> expectedDns = new ArrayList<>(Arrays.asList(TEST_VPN_INTERNAL_DNS)); 1985 1986 if (mtuSupportsIpv6) { 1987 expectedRoutes.add( 1988 new RouteInfo( 1989 new IpPrefix(Inet6Address.ANY, 0), 1990 null /* gateway */, 1991 TEST_IFACE_NAME, 1992 RouteInfo.RTN_UNICAST)); 1993 expectedAddresses.add(new LinkAddress(TEST_VPN_INTERNAL_IP6, IP6_PREFIX_LEN)); 1994 expectedDns.add(TEST_VPN_INTERNAL_DNS6); 1995 } else { 1996 expectedRoutes.add( 1997 new RouteInfo( 1998 new IpPrefix(Inet6Address.ANY, 0), 1999 null /* gateway */, 2000 TEST_IFACE_NAME, 2001 RTN_UNREACHABLE)); 2002 } 2003 2004 assertEquals(expectedRoutes, lp.getRoutes()); 2005 assertEquals(expectedAddresses, lp.getLinkAddresses()); 2006 assertEquals(expectedDns, lp.getDnsServers()); 2007 2008 // Check NetworkCapabilities 2009 assertEquals(Arrays.asList(TEST_NETWORK), ncCaptor.getValue().getUnderlyingNetworks()); 2010 2011 // Check if allowBypass is set or not. 2012 assertTrue(nacCaptor.getValue().isBypassableVpn()); 2013 final VpnTransportInfo info = (VpnTransportInfo) ncCaptor.getValue().getTransportInfo(); 2014 assertTrue(info.isBypassable()); 2015 assertEquals(areLongLivedTcpConnectionsExpensive, 2016 info.areLongLivedTcpConnectionsExpensive()); 2017 return new PlatformVpnSnapshot(vpn, nwCb, ikeCb, childCb); 2018 } 2019 2020 @Test testStartPlatformVpn()2021 public void testStartPlatformVpn() throws Exception { 2022 final PlatformVpnSnapshot vpnSnapShot = verifySetupPlatformVpn( 2023 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */)); 2024 vpnSnapShot.vpn.mVpnRunner.exitVpnRunner(); 2025 } 2026 2027 @Test testMigrateIkeSession_FromIkeTunnConnParams_AutoTimerNoTimer()2028 public void testMigrateIkeSession_FromIkeTunnConnParams_AutoTimerNoTimer() throws Exception { 2029 doTestMigrateIkeSession_FromIkeTunnConnParams( 2030 false /* isAutomaticIpVersionSelectionEnabled */, 2031 true /* isAutomaticNattKeepaliveTimerEnabled */, 2032 TEST_KEEPALIVE_TIMEOUT_UNSET /* keepaliveInProfile */, 2033 ESP_IP_VERSION_AUTO /* ipVersionInProfile */, 2034 ESP_ENCAP_TYPE_AUTO /* encapTypeInProfile */); 2035 } 2036 2037 @Test testMigrateIkeSession_FromIkeTunnConnParams_AutoTimerTimerSet()2038 public void testMigrateIkeSession_FromIkeTunnConnParams_AutoTimerTimerSet() throws Exception { 2039 doTestMigrateIkeSession_FromIkeTunnConnParams( 2040 false /* isAutomaticIpVersionSelectionEnabled */, 2041 true /* isAutomaticNattKeepaliveTimerEnabled */, 2042 TEST_KEEPALIVE_TIMER /* keepaliveInProfile */, 2043 ESP_IP_VERSION_AUTO /* ipVersionInProfile */, 2044 ESP_ENCAP_TYPE_AUTO /* encapTypeInProfile */); 2045 } 2046 2047 @Test testMigrateIkeSession_FromIkeTunnConnParams_AutoIp()2048 public void testMigrateIkeSession_FromIkeTunnConnParams_AutoIp() throws Exception { 2049 doTestMigrateIkeSession_FromIkeTunnConnParams( 2050 true /* isAutomaticIpVersionSelectionEnabled */, 2051 false /* isAutomaticNattKeepaliveTimerEnabled */, 2052 TEST_KEEPALIVE_TIMEOUT_UNSET /* keepaliveInProfile */, 2053 ESP_IP_VERSION_AUTO /* ipVersionInProfile */, 2054 ESP_ENCAP_TYPE_AUTO /* encapTypeInProfile */); 2055 } 2056 2057 @Test testMigrateIkeSession_FromIkeTunnConnParams_AssignedIpProtocol()2058 public void testMigrateIkeSession_FromIkeTunnConnParams_AssignedIpProtocol() throws Exception { 2059 doTestMigrateIkeSession_FromIkeTunnConnParams( 2060 false /* isAutomaticIpVersionSelectionEnabled */, 2061 false /* isAutomaticNattKeepaliveTimerEnabled */, 2062 TEST_KEEPALIVE_TIMEOUT_UNSET /* keepaliveInProfile */, 2063 ESP_IP_VERSION_IPV4 /* ipVersionInProfile */, 2064 ESP_ENCAP_TYPE_UDP /* encapTypeInProfile */); 2065 } 2066 2067 @Test testMigrateIkeSession_FromNotIkeTunnConnParams_AutoTimer()2068 public void testMigrateIkeSession_FromNotIkeTunnConnParams_AutoTimer() throws Exception { 2069 doTestMigrateIkeSession_FromNotIkeTunnConnParams( 2070 false /* isAutomaticIpVersionSelectionEnabled */, 2071 true /* isAutomaticNattKeepaliveTimerEnabled */); 2072 } 2073 2074 @Test testMigrateIkeSession_FromNotIkeTunnConnParams_AutoIp()2075 public void testMigrateIkeSession_FromNotIkeTunnConnParams_AutoIp() throws Exception { 2076 doTestMigrateIkeSession_FromNotIkeTunnConnParams( 2077 true /* isAutomaticIpVersionSelectionEnabled */, 2078 false /* isAutomaticNattKeepaliveTimerEnabled */); 2079 } 2080 doTestMigrateIkeSession_FromNotIkeTunnConnParams( boolean isAutomaticIpVersionSelectionEnabled, boolean isAutomaticNattKeepaliveTimerEnabled)2081 private void doTestMigrateIkeSession_FromNotIkeTunnConnParams( 2082 boolean isAutomaticIpVersionSelectionEnabled, 2083 boolean isAutomaticNattKeepaliveTimerEnabled) throws Exception { 2084 final Ikev2VpnProfile ikeProfile = 2085 new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY) 2086 .setAuthPsk(TEST_VPN_PSK) 2087 .setBypassable(true /* isBypassable */) 2088 .setAutomaticNattKeepaliveTimerEnabled(isAutomaticNattKeepaliveTimerEnabled) 2089 .setAutomaticIpVersionSelectionEnabled(isAutomaticIpVersionSelectionEnabled) 2090 .build(); 2091 2092 final int expectedKeepalive = isAutomaticNattKeepaliveTimerEnabled 2093 ? AUTOMATIC_KEEPALIVE_DELAY_SECONDS 2094 : DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT; 2095 doTestMigrateIkeSession(ikeProfile.toVpnProfile(), 2096 expectedKeepalive, 2097 ESP_IP_VERSION_AUTO /* expectedIpVersion */, 2098 ESP_ENCAP_TYPE_AUTO /* expectedEncapType */, 2099 new NetworkCapabilities.Builder().build()); 2100 } 2101 makeIkeV2VpnProfile( boolean isAutomaticIpVersionSelectionEnabled, boolean isAutomaticNattKeepaliveTimerEnabled, int keepaliveInProfile, int ipVersionInProfile, int encapTypeInProfile)2102 private Ikev2VpnProfile makeIkeV2VpnProfile( 2103 boolean isAutomaticIpVersionSelectionEnabled, 2104 boolean isAutomaticNattKeepaliveTimerEnabled, 2105 int keepaliveInProfile, 2106 int ipVersionInProfile, 2107 int encapTypeInProfile) { 2108 // TODO: Update helper function in IkeSessionTestUtils to support building IkeSessionParams 2109 // with IP version and encap type when mainline-prod branch support these two APIs. 2110 final IkeSessionParams params = getTestIkeSessionParams(true /* testIpv6 */, 2111 new IkeFqdnIdentification(TEST_IDENTITY), keepaliveInProfile); 2112 final IkeSessionParams ikeSessionParams = new IkeSessionParams.Builder(params) 2113 .setIpVersion(ipVersionInProfile) 2114 .setEncapType(encapTypeInProfile) 2115 .build(); 2116 2117 final IkeTunnelConnectionParams tunnelParams = 2118 new IkeTunnelConnectionParams(ikeSessionParams, CHILD_PARAMS); 2119 return new Ikev2VpnProfile.Builder(tunnelParams) 2120 .setBypassable(true) 2121 .setAutomaticNattKeepaliveTimerEnabled(isAutomaticNattKeepaliveTimerEnabled) 2122 .setAutomaticIpVersionSelectionEnabled(isAutomaticIpVersionSelectionEnabled) 2123 .build(); 2124 } 2125 doTestMigrateIkeSession_FromIkeTunnConnParams( boolean isAutomaticIpVersionSelectionEnabled, boolean isAutomaticNattKeepaliveTimerEnabled, int keepaliveInProfile, int ipVersionInProfile, int encapTypeInProfile)2126 private void doTestMigrateIkeSession_FromIkeTunnConnParams( 2127 boolean isAutomaticIpVersionSelectionEnabled, 2128 boolean isAutomaticNattKeepaliveTimerEnabled, 2129 int keepaliveInProfile, 2130 int ipVersionInProfile, 2131 int encapTypeInProfile) throws Exception { 2132 doTestMigrateIkeSession_FromIkeTunnConnParams(isAutomaticIpVersionSelectionEnabled, 2133 isAutomaticNattKeepaliveTimerEnabled, keepaliveInProfile, ipVersionInProfile, 2134 encapTypeInProfile, new NetworkCapabilities.Builder().build()); 2135 } 2136 doTestMigrateIkeSession_FromIkeTunnConnParams( boolean isAutomaticIpVersionSelectionEnabled, boolean isAutomaticNattKeepaliveTimerEnabled, int keepaliveInProfile, int ipVersionInProfile, int encapTypeInProfile, @NonNull final NetworkCapabilities nc)2137 private void doTestMigrateIkeSession_FromIkeTunnConnParams( 2138 boolean isAutomaticIpVersionSelectionEnabled, 2139 boolean isAutomaticNattKeepaliveTimerEnabled, 2140 int keepaliveInProfile, 2141 int ipVersionInProfile, 2142 int encapTypeInProfile, 2143 @NonNull final NetworkCapabilities nc) throws Exception { 2144 final Ikev2VpnProfile ikeProfile = makeIkeV2VpnProfile( 2145 isAutomaticIpVersionSelectionEnabled, 2146 isAutomaticNattKeepaliveTimerEnabled, 2147 keepaliveInProfile, 2148 ipVersionInProfile, 2149 encapTypeInProfile); 2150 2151 final IkeSessionParams ikeSessionParams = 2152 ikeProfile.getIkeTunnelConnectionParams().getIkeSessionParams(); 2153 final int expectedKeepalive = isAutomaticNattKeepaliveTimerEnabled 2154 ? AUTOMATIC_KEEPALIVE_DELAY_SECONDS 2155 : ikeSessionParams.getNattKeepAliveDelaySeconds(); 2156 final int expectedIpVersion = isAutomaticIpVersionSelectionEnabled 2157 ? ESP_IP_VERSION_AUTO 2158 : ikeSessionParams.getIpVersion(); 2159 final int expectedEncapType = isAutomaticIpVersionSelectionEnabled 2160 ? ESP_ENCAP_TYPE_AUTO 2161 : ikeSessionParams.getEncapType(); 2162 doTestMigrateIkeSession(ikeProfile.toVpnProfile(), expectedKeepalive, 2163 expectedIpVersion, expectedEncapType, nc); 2164 } 2165 2166 @Test doTestMigrateIkeSession_Vcn()2167 public void doTestMigrateIkeSession_Vcn() throws Exception { 2168 final int expectedKeepalive = 2097; // Any unlikely number will do 2169 final NetworkCapabilities vcnNc = new NetworkCapabilities.Builder() 2170 .addTransportType(TRANSPORT_CELLULAR) 2171 .setTransportInfo(new VcnTransportInfo(TEST_SUB_ID, expectedKeepalive)) 2172 .build(); 2173 final Ikev2VpnProfile ikev2VpnProfile = makeIkeV2VpnProfile( 2174 true /* isAutomaticIpVersionSelectionEnabled */, 2175 true /* isAutomaticNattKeepaliveTimerEnabled */, 2176 234 /* keepaliveInProfile */, // Should be ignored, any value will do 2177 ESP_IP_VERSION_IPV4, // Should be ignored 2178 ESP_ENCAP_TYPE_UDP // Should be ignored 2179 ); 2180 doTestMigrateIkeSession( 2181 ikev2VpnProfile.toVpnProfile(), 2182 expectedKeepalive, 2183 ESP_IP_VERSION_AUTO /* expectedIpVersion */, 2184 ESP_ENCAP_TYPE_AUTO /* expectedEncapType */, 2185 vcnNc); 2186 } 2187 doTestMigrateIkeSession( @onNull final VpnProfile profile, final int expectedKeepalive, final int expectedIpVersion, final int expectedEncapType, @NonNull final NetworkCapabilities caps)2188 private void doTestMigrateIkeSession( 2189 @NonNull final VpnProfile profile, 2190 final int expectedKeepalive, 2191 final int expectedIpVersion, 2192 final int expectedEncapType, 2193 @NonNull final NetworkCapabilities caps) throws Exception { 2194 final PlatformVpnSnapshot vpnSnapShot = 2195 verifySetupPlatformVpn(profile, 2196 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */), 2197 caps /* underlying network capabilities */, 2198 false /* mtuSupportsIpv6 */, 2199 expectedKeepalive < DEFAULT_LONG_LIVED_TCP_CONNS_EXPENSIVE_TIMEOUT_SEC); 2200 // Simulate a new network coming up 2201 vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2); 2202 verify(mIkeSessionWrapper, never()).setNetwork(any(), anyInt(), anyInt(), anyInt()); 2203 2204 vpnSnapShot.nwCb.onCapabilitiesChanged(TEST_NETWORK_2, caps); 2205 // Verify MOBIKE is triggered 2206 verify(mIkeSessionWrapper, timeout(TEST_TIMEOUT_MS)).setNetwork(TEST_NETWORK_2, 2207 expectedIpVersion, expectedEncapType, expectedKeepalive); 2208 2209 vpnSnapShot.vpn.mVpnRunner.exitVpnRunner(); 2210 } 2211 2212 @Test testLinkPropertiesUpdateTriggerReevaluation()2213 public void testLinkPropertiesUpdateTriggerReevaluation() throws Exception { 2214 final boolean hasV6 = true; 2215 2216 mockCarrierConfig(TEST_SUB_ID, TelephonyManager.SIM_STATE_LOADED, TEST_KEEPALIVE_TIMER, 2217 PREFERRED_IKE_PROTOCOL_IPV6_ESP); 2218 final IkeSessionParams params = getTestIkeSessionParams(hasV6, 2219 new IkeFqdnIdentification(TEST_IDENTITY), TEST_KEEPALIVE_TIMER); 2220 final IkeTunnelConnectionParams tunnelParams = 2221 new IkeTunnelConnectionParams(params, CHILD_PARAMS); 2222 final Ikev2VpnProfile ikeProfile = new Ikev2VpnProfile.Builder(tunnelParams) 2223 .setBypassable(true) 2224 .setAutomaticNattKeepaliveTimerEnabled(false) 2225 .setAutomaticIpVersionSelectionEnabled(true) 2226 .build(); 2227 final PlatformVpnSnapshot vpnSnapShot = 2228 verifySetupPlatformVpn(ikeProfile.toVpnProfile(), 2229 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */), 2230 new NetworkCapabilities.Builder().build() /* underlying network caps */, 2231 hasV6 /* mtuSupportsIpv6 */, 2232 false /* areLongLivedTcpConnectionsExpensive */); 2233 reset(mExecutor); 2234 2235 // Simulate a new network coming up 2236 final LinkProperties lp = new LinkProperties(); 2237 lp.addLinkAddress(new LinkAddress("192.0.2.2/32")); 2238 2239 // Have the executor use the real delay to make sure schedule() was called only 2240 // once for all calls. Also, arrange for execute() not to call schedule() to avoid 2241 // messing with the checks for schedule(). 2242 mExecutor.delayMs = TestExecutor.REAL_DELAY; 2243 mExecutor.executeDirect = true; 2244 vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2); 2245 vpnSnapShot.nwCb.onCapabilitiesChanged( 2246 TEST_NETWORK_2, new NetworkCapabilities.Builder().build()); 2247 vpnSnapShot.nwCb.onLinkPropertiesChanged(TEST_NETWORK_2, new LinkProperties(lp)); 2248 verify(mExecutor).schedule(any(Runnable.class), longThat(it -> it > 0), any()); 2249 reset(mExecutor); 2250 2251 final InOrder order = inOrder(mIkeSessionWrapper); 2252 2253 // Verify the network is started 2254 order.verify(mIkeSessionWrapper, timeout(TIMEOUT_CROSSTHREAD_MS)).setNetwork(TEST_NETWORK_2, 2255 ESP_IP_VERSION_AUTO, ESP_ENCAP_TYPE_AUTO, TEST_KEEPALIVE_TIMER); 2256 2257 // Send the same properties, check that no migration is scheduled 2258 vpnSnapShot.nwCb.onLinkPropertiesChanged(TEST_NETWORK_2, new LinkProperties(lp)); 2259 verify(mExecutor, never()).schedule(any(Runnable.class), anyLong(), any()); 2260 2261 // Add v6 address, verify MOBIKE is triggered 2262 lp.addLinkAddress(new LinkAddress("2001:db8::1/64")); 2263 vpnSnapShot.nwCb.onLinkPropertiesChanged(TEST_NETWORK_2, new LinkProperties(lp)); 2264 order.verify(mIkeSessionWrapper, timeout(TIMEOUT_CROSSTHREAD_MS)).setNetwork(TEST_NETWORK_2, 2265 ESP_IP_VERSION_AUTO, ESP_ENCAP_TYPE_AUTO, TEST_KEEPALIVE_TIMER); 2266 2267 // Add another v4 address, verify MOBIKE is triggered 2268 final LinkProperties stacked = new LinkProperties(); 2269 stacked.setInterfaceName("v4-" + lp.getInterfaceName()); 2270 stacked.addLinkAddress(new LinkAddress("192.168.0.1/32")); 2271 lp.addStackedLink(stacked); 2272 vpnSnapShot.nwCb.onLinkPropertiesChanged(TEST_NETWORK_2, new LinkProperties(lp)); 2273 order.verify(mIkeSessionWrapper, timeout(TIMEOUT_CROSSTHREAD_MS)).setNetwork(TEST_NETWORK_2, 2274 ESP_IP_VERSION_AUTO, ESP_ENCAP_TYPE_AUTO, TEST_KEEPALIVE_TIMER); 2275 2276 vpnSnapShot.vpn.mVpnRunner.exitVpnRunner(); 2277 } 2278 mockCarrierConfig(int subId, int simStatus, int keepaliveTimer, int ikeProtocol)2279 private void mockCarrierConfig(int subId, int simStatus, int keepaliveTimer, int ikeProtocol) { 2280 final SubscriptionInfo subscriptionInfo = mock(SubscriptionInfo.class); 2281 doReturn(subId).when(subscriptionInfo).getSubscriptionId(); 2282 doReturn(List.of(subscriptionInfo)).when(mSubscriptionManager) 2283 .getActiveSubscriptionInfoList(); 2284 2285 doReturn(simStatus).when(mTmPerSub).getSimApplicationState(); 2286 doReturn(TEST_MCCMNC).when(mTmPerSub).getSimOperator(subId); 2287 2288 final PersistableBundle persistableBundle = new PersistableBundle(); 2289 persistableBundle.putInt(KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT, keepaliveTimer); 2290 persistableBundle.putInt(KEY_PREFERRED_IKE_PROTOCOL_INT, ikeProtocol); 2291 // For CarrierConfigManager.isConfigForIdentifiedCarrier check 2292 persistableBundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true); 2293 doReturn(persistableBundle).when(mConfigManager).getConfigForSubId(subId); 2294 } 2295 getCarrierConfigListener()2296 private CarrierConfigManager.CarrierConfigChangeListener getCarrierConfigListener() { 2297 final ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerCaptor = 2298 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class); 2299 2300 verify(mConfigManager).registerCarrierConfigChangeListener(any(), listenerCaptor.capture()); 2301 2302 return listenerCaptor.getValue(); 2303 } 2304 2305 @Test testNattKeepaliveTimerFromCarrierConfig_noSubId()2306 public void testNattKeepaliveTimerFromCarrierConfig_noSubId() throws Exception { 2307 doTestReadCarrierConfig(new NetworkCapabilities(), 2308 TelephonyManager.SIM_STATE_LOADED, 2309 PREFERRED_IKE_PROTOCOL_IPV4_UDP, 2310 AUTOMATIC_KEEPALIVE_DELAY_SECONDS /* expectedKeepaliveTimer */, 2311 ESP_IP_VERSION_AUTO /* expectedIpVersion */, 2312 ESP_ENCAP_TYPE_AUTO /* expectedEncapType */, 2313 false /* expectedReadFromCarrierConfig*/, 2314 true /* areLongLivedTcpConnectionsExpensive */); 2315 } 2316 2317 @Test testNattKeepaliveTimerFromCarrierConfig_simAbsent()2318 public void testNattKeepaliveTimerFromCarrierConfig_simAbsent() throws Exception { 2319 doTestReadCarrierConfig(new NetworkCapabilities.Builder().build(), 2320 TelephonyManager.SIM_STATE_ABSENT, 2321 PREFERRED_IKE_PROTOCOL_IPV4_UDP, 2322 AUTOMATIC_KEEPALIVE_DELAY_SECONDS /* expectedKeepaliveTimer */, 2323 ESP_IP_VERSION_AUTO /* expectedIpVersion */, 2324 ESP_ENCAP_TYPE_AUTO /* expectedEncapType */, 2325 false /* expectedReadFromCarrierConfig*/, 2326 true /* areLongLivedTcpConnectionsExpensive */); 2327 } 2328 2329 @Test testNattKeepaliveTimerFromCarrierConfig()2330 public void testNattKeepaliveTimerFromCarrierConfig() throws Exception { 2331 doTestReadCarrierConfig(createTestCellNc(), 2332 TelephonyManager.SIM_STATE_LOADED, 2333 PREFERRED_IKE_PROTOCOL_AUTO, 2334 TEST_KEEPALIVE_TIMER /* expectedKeepaliveTimer */, 2335 ESP_IP_VERSION_AUTO /* expectedIpVersion */, 2336 ESP_ENCAP_TYPE_AUTO /* expectedEncapType */, 2337 true /* expectedReadFromCarrierConfig*/, 2338 false /* areLongLivedTcpConnectionsExpensive */); 2339 } 2340 2341 @Test testNattKeepaliveTimerFromCarrierConfig_NotCell()2342 public void testNattKeepaliveTimerFromCarrierConfig_NotCell() throws Exception { 2343 final NetworkCapabilities nc = new NetworkCapabilities.Builder() 2344 .addTransportType(TRANSPORT_WIFI) 2345 .setTransportInfo(new WifiInfo.Builder().build()) 2346 .build(); 2347 doTestReadCarrierConfig(nc, 2348 TelephonyManager.SIM_STATE_LOADED, 2349 PREFERRED_IKE_PROTOCOL_IPV4_UDP, 2350 AUTOMATIC_KEEPALIVE_DELAY_SECONDS /* expectedKeepaliveTimer */, 2351 ESP_IP_VERSION_AUTO /* expectedIpVersion */, 2352 ESP_ENCAP_TYPE_AUTO /* expectedEncapType */, 2353 false /* expectedReadFromCarrierConfig*/, 2354 true /* areLongLivedTcpConnectionsExpensive */); 2355 } 2356 2357 @Test testPreferredIpProtocolFromCarrierConfig_v4UDP()2358 public void testPreferredIpProtocolFromCarrierConfig_v4UDP() throws Exception { 2359 doTestReadCarrierConfig(createTestCellNc(), 2360 TelephonyManager.SIM_STATE_LOADED, 2361 PREFERRED_IKE_PROTOCOL_IPV4_UDP, 2362 TEST_KEEPALIVE_TIMER /* expectedKeepaliveTimer */, 2363 ESP_IP_VERSION_IPV4 /* expectedIpVersion */, 2364 ESP_ENCAP_TYPE_UDP /* expectedEncapType */, 2365 true /* expectedReadFromCarrierConfig*/, 2366 false /* areLongLivedTcpConnectionsExpensive */); 2367 } 2368 2369 @Test testPreferredIpProtocolFromCarrierConfig_v6ESP()2370 public void testPreferredIpProtocolFromCarrierConfig_v6ESP() throws Exception { 2371 doTestReadCarrierConfig(createTestCellNc(), 2372 TelephonyManager.SIM_STATE_LOADED, 2373 PREFERRED_IKE_PROTOCOL_IPV6_ESP, 2374 TEST_KEEPALIVE_TIMER /* expectedKeepaliveTimer */, 2375 ESP_IP_VERSION_IPV6 /* expectedIpVersion */, 2376 ESP_ENCAP_TYPE_NONE /* expectedEncapType */, 2377 true /* expectedReadFromCarrierConfig*/, 2378 false /* areLongLivedTcpConnectionsExpensive */); 2379 } 2380 2381 @Test testPreferredIpProtocolFromCarrierConfig_v6UDP()2382 public void testPreferredIpProtocolFromCarrierConfig_v6UDP() throws Exception { 2383 doTestReadCarrierConfig(createTestCellNc(), 2384 TelephonyManager.SIM_STATE_LOADED, 2385 PREFERRED_IKE_PROTOCOL_IPV6_UDP, 2386 TEST_KEEPALIVE_TIMER /* expectedKeepaliveTimer */, 2387 ESP_IP_VERSION_IPV6 /* expectedIpVersion */, 2388 ESP_ENCAP_TYPE_UDP /* expectedEncapType */, 2389 true /* expectedReadFromCarrierConfig*/, 2390 false /* areLongLivedTcpConnectionsExpensive */); 2391 } 2392 createTestCellNc()2393 private NetworkCapabilities createTestCellNc() { 2394 return new NetworkCapabilities.Builder() 2395 .addTransportType(TRANSPORT_CELLULAR) 2396 .setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder() 2397 .setSubscriptionId(TEST_SUB_ID) 2398 .build()) 2399 .build(); 2400 } 2401 doTestReadCarrierConfig(NetworkCapabilities nc, int simState, int preferredIpProto, int expectedKeepaliveTimer, int expectedIpVersion, int expectedEncapType, boolean expectedReadFromCarrierConfig, boolean areLongLivedTcpConnectionsExpensive)2402 private void doTestReadCarrierConfig(NetworkCapabilities nc, int simState, int preferredIpProto, 2403 int expectedKeepaliveTimer, int expectedIpVersion, int expectedEncapType, 2404 boolean expectedReadFromCarrierConfig, 2405 boolean areLongLivedTcpConnectionsExpensive) 2406 throws Exception { 2407 final Ikev2VpnProfile ikeProfile = 2408 new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY) 2409 .setAuthPsk(TEST_VPN_PSK) 2410 .setBypassable(true /* isBypassable */) 2411 .setAutomaticNattKeepaliveTimerEnabled(true) 2412 .setAutomaticIpVersionSelectionEnabled(true) 2413 .build(); 2414 2415 final PlatformVpnSnapshot vpnSnapShot = 2416 verifySetupPlatformVpn(ikeProfile.toVpnProfile(), 2417 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */), 2418 new NetworkCapabilities.Builder().build() /* underlying network caps */, 2419 false /* mtuSupportsIpv6 */, 2420 true /* areLongLivedTcpConnectionsExpensive */); 2421 2422 final CarrierConfigManager.CarrierConfigChangeListener listener = 2423 getCarrierConfigListener(); 2424 2425 // Simulate a new network coming up 2426 vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2); 2427 // Migration will not be started until receiving network capabilities change. 2428 verify(mIkeSessionWrapper, never()).setNetwork(any(), anyInt(), anyInt(), anyInt()); 2429 2430 reset(mIkeSessionWrapper); 2431 mockCarrierConfig(TEST_SUB_ID, simState, TEST_KEEPALIVE_TIMER, preferredIpProto); 2432 vpnSnapShot.nwCb.onCapabilitiesChanged(TEST_NETWORK_2, nc); 2433 verify(mIkeSessionWrapper, timeout(TEST_TIMEOUT_MS)).setNetwork(TEST_NETWORK_2, 2434 expectedIpVersion, expectedEncapType, expectedKeepaliveTimer); 2435 if (expectedReadFromCarrierConfig) { 2436 final ArgumentCaptor<NetworkCapabilities> ncCaptor = 2437 ArgumentCaptor.forClass(NetworkCapabilities.class); 2438 verify(mMockNetworkAgent).doSendNetworkCapabilities(ncCaptor.capture()); 2439 2440 final VpnTransportInfo info = 2441 (VpnTransportInfo) ncCaptor.getValue().getTransportInfo(); 2442 assertEquals(areLongLivedTcpConnectionsExpensive, 2443 info.areLongLivedTcpConnectionsExpensive()); 2444 } else { 2445 verify(mMockNetworkAgent, never()).doSendNetworkCapabilities(any()); 2446 } 2447 2448 reset(mExecutor); 2449 reset(mIkeSessionWrapper); 2450 reset(mMockNetworkAgent); 2451 2452 // Trigger carrier config change 2453 listener.onCarrierConfigChanged(1 /* logicalSlotIndex */, TEST_SUB_ID, 2454 -1 /* carrierId */, -1 /* specificCarrierId */); 2455 verify(mIkeSessionWrapper).setNetwork(TEST_NETWORK_2, 2456 expectedIpVersion, expectedEncapType, expectedKeepaliveTimer); 2457 // Expect no NetworkCapabilities change. 2458 // Call to doSendNetworkCapabilities() will not be triggered. 2459 verify(mMockNetworkAgent, never()).doSendNetworkCapabilities(any()); 2460 } 2461 2462 @Test testStartPlatformVpn_mtuDoesNotSupportIpv6()2463 public void testStartPlatformVpn_mtuDoesNotSupportIpv6() throws Exception { 2464 final PlatformVpnSnapshot vpnSnapShot = 2465 verifySetupPlatformVpn( 2466 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */), 2467 false /* mtuSupportsIpv6 */); 2468 vpnSnapShot.vpn.mVpnRunner.exitVpnRunner(); 2469 } 2470 2471 @Test testStartPlatformVpnMobility_mobikeEnabled()2472 public void testStartPlatformVpnMobility_mobikeEnabled() throws Exception { 2473 final PlatformVpnSnapshot vpnSnapShot = verifySetupPlatformVpn( 2474 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */)); 2475 2476 // Set new MTU on a different network 2477 final int newMtu = IPV6_MIN_MTU + 1; 2478 doReturn(newMtu).when(mTestDeps).calculateVpnMtu(any(), anyInt(), anyInt(), anyBoolean()); 2479 2480 // Mock network loss and verify a cleanup task is scheduled 2481 vpnSnapShot.nwCb.onLost(TEST_NETWORK); 2482 verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), anyLong(), any()); 2483 2484 // Mock new network comes up and the cleanup task is cancelled 2485 vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2); 2486 verify(mIkeSessionWrapper, never()).setNetwork(any(), anyInt(), anyInt(), anyInt()); 2487 2488 vpnSnapShot.nwCb.onCapabilitiesChanged(TEST_NETWORK_2, 2489 new NetworkCapabilities.Builder().build()); 2490 // Verify MOBIKE is triggered 2491 verify(mIkeSessionWrapper, timeout(TEST_TIMEOUT_MS)).setNetwork(eq(TEST_NETWORK_2), 2492 eq(ESP_IP_VERSION_AUTO) /* ipVersion */, 2493 eq(ESP_ENCAP_TYPE_AUTO) /* encapType */, 2494 eq(DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT) /* keepaliveDelay */); 2495 2496 // Mock the MOBIKE procedure 2497 vpnSnapShot.ikeCb.onIkeSessionConnectionInfoChanged(createIkeConnectInfo_2()); 2498 vpnSnapShot.childCb.onIpSecTransformsMigrated( 2499 createIpSecTransform(), createIpSecTransform()); 2500 2501 verify(mIpSecService).setNetworkForTunnelInterface( 2502 eq(TEST_TUNNEL_RESOURCE_ID), eq(TEST_NETWORK_2), anyString()); 2503 2504 // Expect 2 times: one for initial setup and one for MOBIKE 2505 verifyApplyTunnelModeTransforms(2); 2506 2507 // Verify mNetworkCapabilities and mNetworkAgent are updated 2508 assertEquals( 2509 Collections.singletonList(TEST_NETWORK_2), 2510 vpnSnapShot.vpn.mNetworkCapabilities.getUnderlyingNetworks()); 2511 verify(mMockNetworkAgent) 2512 .doSetUnderlyingNetworks(Collections.singletonList(TEST_NETWORK_2)); 2513 verify(mMockNetworkAgent).doSendLinkProperties(argThat(lp -> lp.getMtu() == newMtu)); 2514 verify(mMockNetworkAgent, never()).unregister(); 2515 2516 vpnSnapShot.vpn.mVpnRunner.exitVpnRunner(); 2517 } 2518 2519 @Test testStartPlatformVpnMobility_mobikeEnabledMtuDoesNotSupportIpv6()2520 public void testStartPlatformVpnMobility_mobikeEnabledMtuDoesNotSupportIpv6() throws Exception { 2521 final PlatformVpnSnapshot vpnSnapShot = 2522 verifySetupPlatformVpn( 2523 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */)); 2524 2525 // Set MTU below 1280 2526 final int newMtu = IPV6_MIN_MTU - 1; 2527 doReturn(newMtu).when(mTestDeps).calculateVpnMtu(any(), anyInt(), anyInt(), anyBoolean()); 2528 2529 // Mock new network available & MOBIKE procedures 2530 vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2); 2531 vpnSnapShot.ikeCb.onIkeSessionConnectionInfoChanged(createIkeConnectInfo_2()); 2532 vpnSnapShot.childCb.onIpSecTransformsMigrated( 2533 createIpSecTransform(), createIpSecTransform()); 2534 2535 // Verify removal of IPv6 addresses and routes triggers a network agent restart 2536 final ArgumentCaptor<LinkProperties> lpCaptor = 2537 ArgumentCaptor.forClass(LinkProperties.class); 2538 verify(mTestDeps, times(2)) 2539 .newNetworkAgent(any(), any(), anyString(), any(), lpCaptor.capture(), any(), any(), 2540 any(), any()); 2541 verify(mMockNetworkAgent).unregister(); 2542 // mMockNetworkAgent is an old NetworkAgent, so it won't update LinkProperties after 2543 // unregistering. 2544 verify(mMockNetworkAgent, never()).doSendLinkProperties(any()); 2545 2546 final LinkProperties lp = lpCaptor.getValue(); 2547 2548 for (LinkAddress addr : lp.getLinkAddresses()) { 2549 if (addr.isIpv6()) { 2550 fail("IPv6 address found on VPN with MTU < IPv6 minimum MTU"); 2551 } 2552 } 2553 2554 for (InetAddress dnsAddr : lp.getDnsServers()) { 2555 if (dnsAddr instanceof Inet6Address) { 2556 fail("IPv6 DNS server found on VPN with MTU < IPv6 minimum MTU"); 2557 } 2558 } 2559 2560 for (RouteInfo routeInfo : lp.getRoutes()) { 2561 if (routeInfo.getDestinationLinkAddress().isIpv6() 2562 && !routeInfo.isIPv6UnreachableDefault()) { 2563 fail("IPv6 route found on VPN with MTU < IPv6 minimum MTU"); 2564 } 2565 } 2566 2567 assertEquals(newMtu, lp.getMtu()); 2568 2569 vpnSnapShot.vpn.mVpnRunner.exitVpnRunner(); 2570 } 2571 2572 @Test testStartPlatformVpnReestablishes_mobikeDisabled()2573 public void testStartPlatformVpnReestablishes_mobikeDisabled() throws Exception { 2574 final PlatformVpnSnapshot vpnSnapShot = verifySetupPlatformVpn( 2575 createIkeConfig(createIkeConnectInfo(), false /* isMobikeEnabled */)); 2576 2577 // Forget the first IKE creation to be prepared to capture callbacks of the second 2578 // IKE session 2579 resetIkev2SessionCreator(mock(Vpn.IkeSessionWrapper.class)); 2580 2581 // Mock network switch 2582 vpnSnapShot.nwCb.onLost(TEST_NETWORK); 2583 vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2); 2584 // The old IKE Session will not be killed until receiving network capabilities change. 2585 verify(mIkeSessionWrapper, never()).kill(); 2586 2587 vpnSnapShot.nwCb.onCapabilitiesChanged( 2588 TEST_NETWORK_2, new NetworkCapabilities.Builder().build()); 2589 // Verify the old IKE Session is killed 2590 verify(mIkeSessionWrapper, timeout(TEST_TIMEOUT_MS)).kill(); 2591 2592 // Capture callbacks of the new IKE Session 2593 final Pair<IkeSessionCallback, ChildSessionCallback> cbPair = 2594 verifyCreateIkeAndCaptureCbs(); 2595 final IkeSessionCallback ikeCb = cbPair.first; 2596 final ChildSessionCallback childCb = cbPair.second; 2597 2598 // Mock the IKE Session setup 2599 ikeCb.onOpened(createIkeConfig(createIkeConnectInfo_2(), false /* isMobikeEnabled */)); 2600 2601 childCb.onIpSecTransformCreated(createIpSecTransform(), IpSecManager.DIRECTION_IN); 2602 childCb.onIpSecTransformCreated(createIpSecTransform(), IpSecManager.DIRECTION_OUT); 2603 childCb.onOpened(createChildConfig()); 2604 2605 // Expect 2 times since there have been two Session setups 2606 verifyApplyTunnelModeTransforms(2); 2607 2608 // Verify mNetworkCapabilities and mNetworkAgent are updated 2609 assertEquals( 2610 Collections.singletonList(TEST_NETWORK_2), 2611 vpnSnapShot.vpn.mNetworkCapabilities.getUnderlyingNetworks()); 2612 verify(mMockNetworkAgent) 2613 .doSetUnderlyingNetworks(Collections.singletonList(TEST_NETWORK_2)); 2614 2615 vpnSnapShot.vpn.mVpnRunner.exitVpnRunner(); 2616 } 2617 getDump(@onNull final Vpn vpn)2618 private String getDump(@NonNull final Vpn vpn) { 2619 final StringWriter sw = new StringWriter(); 2620 final IndentingPrintWriter writer = new IndentingPrintWriter(sw, ""); 2621 vpn.dump(writer); 2622 writer.flush(); 2623 return sw.toString(); 2624 } 2625 countMatches(@onNull final Pattern regexp, @NonNull final String string)2626 private int countMatches(@NonNull final Pattern regexp, @NonNull final String string) { 2627 final Matcher m = regexp.matcher(string); 2628 int i = 0; 2629 while (m.find()) ++i; 2630 return i; 2631 } 2632 2633 @Test testNCEventChanges()2634 public void testNCEventChanges() throws Exception { 2635 final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder() 2636 .addTransportType(TRANSPORT_CELLULAR) 2637 .addCapability(NET_CAPABILITY_INTERNET) 2638 .addCapability(NET_CAPABILITY_NOT_RESTRICTED) 2639 .setLinkDownstreamBandwidthKbps(1000) 2640 .setLinkUpstreamBandwidthKbps(500); 2641 2642 final Ikev2VpnProfile ikeProfile = 2643 new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY) 2644 .setAuthPsk(TEST_VPN_PSK) 2645 .setBypassable(true /* isBypassable */) 2646 .setAutomaticNattKeepaliveTimerEnabled(true) 2647 .setAutomaticIpVersionSelectionEnabled(true) 2648 .build(); 2649 2650 final PlatformVpnSnapshot vpnSnapShot = 2651 verifySetupPlatformVpn(ikeProfile.toVpnProfile(), 2652 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */), 2653 ncBuilder.build(), false /* mtuSupportsIpv6 */, 2654 true /* areLongLivedTcpConnectionsExpensive */); 2655 2656 // Calls to onCapabilitiesChanged will be thrown to the executor for execution ; by 2657 // default this will incur a 10ms delay before it's executed, messing with the timing 2658 // of the log and having the checks for counts in equals() below flake. 2659 mExecutor.executeDirect = true; 2660 2661 // First nc changed triggered by verifySetupPlatformVpn 2662 final Pattern pattern = Pattern.compile("Cap changed from", Pattern.MULTILINE); 2663 final String stage1 = getDump(vpnSnapShot.vpn); 2664 assertEquals(1, countMatches(pattern, stage1)); 2665 2666 vpnSnapShot.nwCb.onCapabilitiesChanged(TEST_NETWORK, ncBuilder.build()); 2667 final String stage2 = getDump(vpnSnapShot.vpn); 2668 // Was the same caps, there should still be only 1 match 2669 assertEquals(1, countMatches(pattern, stage2)); 2670 2671 ncBuilder.setLinkDownstreamBandwidthKbps(1200) 2672 .setLinkUpstreamBandwidthKbps(300); 2673 vpnSnapShot.nwCb.onCapabilitiesChanged(TEST_NETWORK, ncBuilder.build()); 2674 final String stage3 = getDump(vpnSnapShot.vpn); 2675 // Was not an important change, should not be logged, still only 1 match 2676 assertEquals(1, countMatches(pattern, stage3)); 2677 2678 ncBuilder.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); 2679 vpnSnapShot.nwCb.onCapabilitiesChanged(TEST_NETWORK, ncBuilder.build()); 2680 final String stage4 = getDump(vpnSnapShot.vpn); 2681 // Change to caps is important, should cause a new match 2682 assertEquals(2, countMatches(pattern, stage4)); 2683 2684 ncBuilder.removeCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); 2685 ncBuilder.setLinkDownstreamBandwidthKbps(600); 2686 vpnSnapShot.nwCb.onCapabilitiesChanged(TEST_NETWORK, ncBuilder.build()); 2687 final String stage5 = getDump(vpnSnapShot.vpn); 2688 // Change to caps is important, should cause a new match even with the unimportant change 2689 assertEquals(3, countMatches(pattern, stage5)); 2690 } 2691 // TODO : beef up event logs tests 2692 verifyHandlingNetworkLoss(PlatformVpnSnapshot vpnSnapShot)2693 private void verifyHandlingNetworkLoss(PlatformVpnSnapshot vpnSnapShot) throws Exception { 2694 // Forget the #sendLinkProperties during first setup. 2695 reset(mMockNetworkAgent); 2696 2697 // Mock network loss 2698 vpnSnapShot.nwCb.onLost(TEST_NETWORK); 2699 2700 // Mock the grace period expires 2701 verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), anyLong(), any()); 2702 2703 final ArgumentCaptor<LinkProperties> lpCaptor = 2704 ArgumentCaptor.forClass(LinkProperties.class); 2705 verify(mMockNetworkAgent, timeout(TEST_TIMEOUT_MS)) 2706 .doSendLinkProperties(lpCaptor.capture()); 2707 final LinkProperties lp = lpCaptor.getValue(); 2708 2709 assertNull(lp.getInterfaceName()); 2710 final List<RouteInfo> expectedRoutes = Arrays.asList( 2711 new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null /* gateway */, 2712 null /* iface */, RTN_UNREACHABLE), 2713 new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null /* gateway */, 2714 null /* iface */, RTN_UNREACHABLE)); 2715 assertEquals(expectedRoutes, lp.getRoutes()); 2716 2717 verify(mMockNetworkAgent).unregister(); 2718 } 2719 2720 @Test testStartPlatformVpnHandlesNetworkLoss_mobikeEnabled()2721 public void testStartPlatformVpnHandlesNetworkLoss_mobikeEnabled() throws Exception { 2722 final PlatformVpnSnapshot vpnSnapShot = verifySetupPlatformVpn( 2723 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */)); 2724 verifyHandlingNetworkLoss(vpnSnapShot); 2725 } 2726 2727 @Test testStartPlatformVpnHandlesNetworkLoss_mobikeDisabled()2728 public void testStartPlatformVpnHandlesNetworkLoss_mobikeDisabled() throws Exception { 2729 final PlatformVpnSnapshot vpnSnapShot = verifySetupPlatformVpn( 2730 createIkeConfig(createIkeConnectInfo(), false /* isMobikeEnabled */)); 2731 verifyHandlingNetworkLoss(vpnSnapShot); 2732 } 2733 getConnectivityDiagCallback()2734 private ConnectivityDiagnosticsCallback getConnectivityDiagCallback() { 2735 final ArgumentCaptor<ConnectivityDiagnosticsCallback> cdcCaptor = 2736 ArgumentCaptor.forClass(ConnectivityDiagnosticsCallback.class); 2737 verify(mCdm).registerConnectivityDiagnosticsCallback( 2738 any(), any(), cdcCaptor.capture()); 2739 return cdcCaptor.getValue(); 2740 } 2741 createDataStallReport()2742 private DataStallReport createDataStallReport() { 2743 return new DataStallReport(TEST_NETWORK, 1234 /* reportTimestamp */, 2744 1 /* detectionMethod */, new LinkProperties(), new NetworkCapabilities(), 2745 new PersistableBundle()); 2746 } 2747 verifyMobikeTriggered(List<Network> expected, int retryIndex)2748 private void verifyMobikeTriggered(List<Network> expected, int retryIndex) { 2749 // Verify retry is scheduled 2750 final long expectedDelaySec = mTestDeps.getValidationFailRecoverySeconds(retryIndex); 2751 final ArgumentCaptor<Long> delayCaptor = ArgumentCaptor.forClass(Long.class); 2752 verify(mExecutor, times(retryIndex + 1)).schedule( 2753 any(Runnable.class), delayCaptor.capture(), eq(TimeUnit.SECONDS)); 2754 final List<Long> delays = delayCaptor.getAllValues(); 2755 assertEquals(expectedDelaySec, (long) delays.get(delays.size() - 1)); 2756 2757 final ArgumentCaptor<Network> networkCaptor = ArgumentCaptor.forClass(Network.class); 2758 // TODO: Make the timeout shorter if real timeout will be used 2759 verify(mIkeSessionWrapper, timeout(TEST_TIMEOUT_MS + expectedDelaySec * 1000)) 2760 .setNetwork(networkCaptor.capture(), anyInt() /* ipVersion */, 2761 anyInt() /* encapType */, anyInt() /* keepaliveDelay */); 2762 assertEquals(expected, Collections.singletonList(networkCaptor.getValue())); 2763 } 2764 2765 @Test testDataStallInIkev2VpnMobikeDisabled()2766 public void testDataStallInIkev2VpnMobikeDisabled() throws Exception { 2767 final PlatformVpnSnapshot vpnSnapShot = verifySetupPlatformVpn( 2768 createIkeConfig(createIkeConnectInfo(), false /* isMobikeEnabled */)); 2769 2770 doReturn(TEST_NETWORK).when(mMockNetworkAgent).getNetwork(); 2771 ((Vpn.IkeV2VpnRunner) vpnSnapShot.vpn.mVpnRunner).onValidationStatus( 2772 NetworkAgent.VALIDATION_STATUS_NOT_VALID); 2773 2774 // Should not trigger MOBIKE if MOBIKE is not enabled 2775 verify(mIkeSessionWrapper, never()).setNetwork(any() /* network */, 2776 anyInt() /* ipVersion */, anyInt() /* encapType */, anyInt() /* keepaliveDelay */); 2777 } 2778 2779 @Test testDataStallInIkev2VpnRecoveredByMobike()2780 public void testDataStallInIkev2VpnRecoveredByMobike() throws Exception { 2781 final PlatformVpnSnapshot vpnSnapShot = verifySetupPlatformVpn( 2782 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */)); 2783 2784 doReturn(TEST_NETWORK).when(mMockNetworkAgent).getNetwork(); 2785 ((Vpn.IkeV2VpnRunner) vpnSnapShot.vpn.mVpnRunner).onValidationStatus( 2786 NetworkAgent.VALIDATION_STATUS_NOT_VALID); 2787 // Verify MOBIKE is triggered 2788 verifyMobikeTriggered(vpnSnapShot.vpn.mNetworkCapabilities.getUnderlyingNetworks(), 2789 0 /* retryIndex */); 2790 2791 reset(mIkev2SessionCreator); 2792 2793 // Send validation status update. 2794 // Recovered and get network validated. It should not trigger the ike session reset. 2795 ((Vpn.IkeV2VpnRunner) vpnSnapShot.vpn.mVpnRunner).onValidationStatus( 2796 NetworkAgent.VALIDATION_STATUS_VALID); 2797 verify(mIkev2SessionCreator, never()).createIkeSession( 2798 any(), any(), any(), any(), any(), any()); 2799 } 2800 2801 @Test testDataStallInIkev2VpnNotRecoveredByMobike()2802 public void testDataStallInIkev2VpnNotRecoveredByMobike() throws Exception { 2803 final PlatformVpnSnapshot vpnSnapShot = verifySetupPlatformVpn( 2804 createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */)); 2805 2806 int retry = 0; 2807 doReturn(TEST_NETWORK).when(mMockNetworkAgent).getNetwork(); 2808 ((Vpn.IkeV2VpnRunner) vpnSnapShot.vpn.mVpnRunner).onValidationStatus( 2809 NetworkAgent.VALIDATION_STATUS_NOT_VALID); 2810 verifyMobikeTriggered(vpnSnapShot.vpn.mNetworkCapabilities.getUnderlyingNetworks(), 2811 retry++); 2812 2813 reset(mIkev2SessionCreator); 2814 2815 // Second validation status update. 2816 ((Vpn.IkeV2VpnRunner) vpnSnapShot.vpn.mVpnRunner).onValidationStatus( 2817 NetworkAgent.VALIDATION_STATUS_NOT_VALID); 2818 verifyMobikeTriggered(vpnSnapShot.vpn.mNetworkCapabilities.getUnderlyingNetworks(), 2819 retry++); 2820 2821 // Use real delay to verify reset session will not be performed if there is an existing 2822 // recovery for resetting the session. 2823 mExecutor.delayMs = TestExecutor.REAL_DELAY; 2824 mExecutor.executeDirect = true; 2825 // Send validation status update should result in ike session reset. 2826 ((Vpn.IkeV2VpnRunner) vpnSnapShot.vpn.mVpnRunner).onValidationStatus( 2827 NetworkAgent.VALIDATION_STATUS_NOT_VALID); 2828 2829 // Verify session reset is scheduled 2830 long expectedDelay = mTestDeps.getValidationFailRecoverySeconds(retry++); 2831 final ArgumentCaptor<Long> delayCaptor = ArgumentCaptor.forClass(Long.class); 2832 verify(mExecutor, times(retry)).schedule(any(Runnable.class), delayCaptor.capture(), 2833 eq(TimeUnit.SECONDS)); 2834 final List<Long> delays = delayCaptor.getAllValues(); 2835 assertEquals(expectedDelay, (long) delays.get(delays.size() - 1)); 2836 2837 // Another invalid status reported should not trigger other scheduled recovery. 2838 expectedDelay = mTestDeps.getValidationFailRecoverySeconds(retry++); 2839 ((Vpn.IkeV2VpnRunner) vpnSnapShot.vpn.mVpnRunner).onValidationStatus( 2840 NetworkAgent.VALIDATION_STATUS_NOT_VALID); 2841 verify(mExecutor, never()).schedule( 2842 any(Runnable.class), eq(expectedDelay), eq(TimeUnit.SECONDS)); 2843 2844 // Verify that session being reset 2845 verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS + expectedDelay * 1000)) 2846 .createIkeSession(any(), any(), any(), any(), any(), any()); 2847 } 2848 2849 @Test testStartRacoonNumericAddress()2850 public void testStartRacoonNumericAddress() throws Exception { 2851 startRacoon("1.2.3.4", "1.2.3.4"); 2852 } 2853 2854 @Test testStartRacoonHostname()2855 public void testStartRacoonHostname() throws Exception { 2856 startRacoon("hostname", "5.6.7.8"); // address returned by deps.resolve 2857 } 2858 2859 @Test testStartPptp()2860 public void testStartPptp() throws Exception { 2861 startPptp(true /* useMppe */); 2862 } 2863 2864 @Test testStartPptp_NoMppe()2865 public void testStartPptp_NoMppe() throws Exception { 2866 startPptp(false /* useMppe */); 2867 } 2868 assertTransportInfoMatches(NetworkCapabilities nc, int type)2869 private void assertTransportInfoMatches(NetworkCapabilities nc, int type) { 2870 assertNotNull(nc); 2871 VpnTransportInfo ti = (VpnTransportInfo) nc.getTransportInfo(); 2872 assertNotNull(ti); 2873 assertEquals(type, ti.getType()); 2874 } 2875 startPptp(boolean useMppe)2876 private void startPptp(boolean useMppe) throws Exception { 2877 final VpnProfile profile = new VpnProfile("testProfile" /* key */); 2878 profile.type = VpnProfile.TYPE_PPTP; 2879 profile.name = "testProfileName"; 2880 profile.username = "userName"; 2881 profile.password = "thePassword"; 2882 profile.server = "192.0.2.123"; 2883 profile.mppe = useMppe; 2884 2885 doReturn(new Network[] { new Network(101) }).when(mConnectivityManager).getAllNetworks(); 2886 doReturn(new Network(102)).when(mConnectivityManager).registerNetworkAgent(any(), any(), 2887 any(), any(), any(), any(), anyInt()); 2888 2889 final Vpn vpn = startLegacyVpn(createVpn(PRIMARY_USER.id), profile); 2890 final TestDeps deps = (TestDeps) vpn.mDeps; 2891 2892 testAndCleanup(() -> { 2893 final String[] mtpdArgs = deps.mtpdArgs.get(10, TimeUnit.SECONDS); 2894 final String[] argsPrefix = new String[]{ 2895 EGRESS_IFACE, "pptp", profile.server, "1723", "name", profile.username, 2896 "password", profile.password, "linkname", "vpn", "refuse-eap", "nodefaultroute", 2897 "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270" 2898 }; 2899 assertArrayEquals(argsPrefix, Arrays.copyOf(mtpdArgs, argsPrefix.length)); 2900 if (useMppe) { 2901 assertEquals(argsPrefix.length + 2, mtpdArgs.length); 2902 assertEquals("+mppe", mtpdArgs[argsPrefix.length]); 2903 assertEquals("-pap", mtpdArgs[argsPrefix.length + 1]); 2904 } else { 2905 assertEquals(argsPrefix.length + 1, mtpdArgs.length); 2906 assertEquals("nomppe", mtpdArgs[argsPrefix.length]); 2907 } 2908 2909 verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(), 2910 any(), any(), any(), any(), anyInt()); 2911 }, () -> { // Cleanup 2912 vpn.mVpnRunner.exitVpnRunner(); 2913 deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier 2914 vpn.mVpnRunner.join(10_000); // wait for up to 10s for the runner to die and cleanup 2915 }); 2916 } 2917 startRacoon(final String serverAddr, final String expectedAddr)2918 public void startRacoon(final String serverAddr, final String expectedAddr) 2919 throws Exception { 2920 final ConditionVariable legacyRunnerReady = new ConditionVariable(); 2921 final VpnProfile profile = new VpnProfile("testProfile" /* key */); 2922 profile.type = VpnProfile.TYPE_L2TP_IPSEC_PSK; 2923 profile.name = "testProfileName"; 2924 profile.username = "userName"; 2925 profile.password = "thePassword"; 2926 profile.server = serverAddr; 2927 profile.ipsecIdentifier = "id"; 2928 profile.ipsecSecret = "secret"; 2929 profile.l2tpSecret = "l2tpsecret"; 2930 2931 when(mConnectivityManager.getAllNetworks()) 2932 .thenReturn(new Network[] { new Network(101) }); 2933 2934 when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(), 2935 any(), any(), anyInt())).thenAnswer(invocation -> { 2936 // The runner has registered an agent and is now ready. 2937 legacyRunnerReady.open(); 2938 return new Network(102); 2939 }); 2940 final Vpn vpn = startLegacyVpn(createVpn(PRIMARY_USER.id), profile); 2941 final TestDeps deps = (TestDeps) vpn.mDeps; 2942 try { 2943 // udppsk and 1701 are the values for TYPE_L2TP_IPSEC_PSK 2944 assertArrayEquals( 2945 new String[] { EGRESS_IFACE, expectedAddr, "udppsk", 2946 profile.ipsecIdentifier, profile.ipsecSecret, "1701" }, 2947 deps.racoonArgs.get(10, TimeUnit.SECONDS)); 2948 // literal values are hardcoded in Vpn.java for mtpd args 2949 assertArrayEquals( 2950 new String[] { EGRESS_IFACE, "l2tp", expectedAddr, "1701", profile.l2tpSecret, 2951 "name", profile.username, "password", profile.password, 2952 "linkname", "vpn", "refuse-eap", "nodefaultroute", "usepeerdns", 2953 "idle", "1800", "mtu", "1270", "mru", "1270" }, 2954 deps.mtpdArgs.get(10, TimeUnit.SECONDS)); 2955 2956 // Now wait for the runner to be ready before testing for the route. 2957 ArgumentCaptor<LinkProperties> lpCaptor = ArgumentCaptor.forClass(LinkProperties.class); 2958 ArgumentCaptor<NetworkCapabilities> ncCaptor = 2959 ArgumentCaptor.forClass(NetworkCapabilities.class); 2960 verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(), 2961 lpCaptor.capture(), ncCaptor.capture(), any(), any(), anyInt()); 2962 2963 // In this test the expected address is always v4 so /32. 2964 // Note that the interface needs to be specified because RouteInfo objects stored in 2965 // LinkProperties objects always acquire the LinkProperties' interface. 2966 final RouteInfo expectedRoute = new RouteInfo(new IpPrefix(expectedAddr + "/32"), 2967 null, EGRESS_IFACE, RouteInfo.RTN_THROW); 2968 final List<RouteInfo> actualRoutes = lpCaptor.getValue().getRoutes(); 2969 assertTrue("Expected throw route (" + expectedRoute + ") not found in " + actualRoutes, 2970 actualRoutes.contains(expectedRoute)); 2971 2972 assertTransportInfoMatches(ncCaptor.getValue(), VpnManager.TYPE_VPN_LEGACY); 2973 } finally { 2974 // Now interrupt the thread, unblock the runner and clean up. 2975 vpn.mVpnRunner.exitVpnRunner(); 2976 deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier 2977 vpn.mVpnRunner.join(10_000); // wait for up to 10s for the runner to die and cleanup 2978 } 2979 } 2980 2981 // Make it public and un-final so as to spy it 2982 public class TestDeps extends Vpn.Dependencies { 2983 public final CompletableFuture<String[]> racoonArgs = new CompletableFuture(); 2984 public final CompletableFuture<String[]> mtpdArgs = new CompletableFuture(); 2985 public final File mStateFile; 2986 2987 private final HashMap<String, Boolean> mRunningServices = new HashMap<>(); 2988 TestDeps()2989 TestDeps() { 2990 try { 2991 mStateFile = File.createTempFile("vpnTest", ".tmp"); 2992 mStateFile.deleteOnExit(); 2993 } catch (final IOException e) { 2994 throw new RuntimeException(e); 2995 } 2996 } 2997 2998 @Override isCallerSystem()2999 public boolean isCallerSystem() { 3000 return true; 3001 } 3002 3003 @Override startService(final String serviceName)3004 public void startService(final String serviceName) { 3005 mRunningServices.put(serviceName, true); 3006 } 3007 3008 @Override stopService(final String serviceName)3009 public void stopService(final String serviceName) { 3010 mRunningServices.put(serviceName, false); 3011 } 3012 3013 @Override isServiceRunning(final String serviceName)3014 public boolean isServiceRunning(final String serviceName) { 3015 return mRunningServices.getOrDefault(serviceName, false); 3016 } 3017 3018 @Override isServiceStopped(final String serviceName)3019 public boolean isServiceStopped(final String serviceName) { 3020 return !isServiceRunning(serviceName); 3021 } 3022 3023 @Override getStateFile()3024 public File getStateFile() { 3025 return mStateFile; 3026 } 3027 3028 @Override getIntentForStatusPanel(Context context)3029 public PendingIntent getIntentForStatusPanel(Context context) { 3030 return null; 3031 } 3032 3033 @Override sendArgumentsToDaemon( final String daemon, final LocalSocket socket, final String[] arguments, final Vpn.RetryScheduler interruptChecker)3034 public void sendArgumentsToDaemon( 3035 final String daemon, final LocalSocket socket, final String[] arguments, 3036 final Vpn.RetryScheduler interruptChecker) throws IOException { 3037 if ("racoon".equals(daemon)) { 3038 racoonArgs.complete(arguments); 3039 } else if ("mtpd".equals(daemon)) { 3040 writeStateFile(arguments); 3041 mtpdArgs.complete(arguments); 3042 } else { 3043 throw new UnsupportedOperationException("Unsupported daemon : " + daemon); 3044 } 3045 } 3046 writeStateFile(final String[] arguments)3047 private void writeStateFile(final String[] arguments) throws IOException { 3048 mStateFile.delete(); 3049 mStateFile.createNewFile(); 3050 mStateFile.deleteOnExit(); 3051 final BufferedWriter writer = new BufferedWriter( 3052 new FileWriter(mStateFile, false /* append */)); 3053 writer.write(EGRESS_IFACE); 3054 writer.write("\n"); 3055 // addresses 3056 writer.write("10.0.0.1/24\n"); 3057 // routes 3058 writer.write("192.168.6.0/24\n"); 3059 // dns servers 3060 writer.write("192.168.6.1\n"); 3061 // search domains 3062 writer.write("vpn.searchdomains.com\n"); 3063 // endpoint - intentionally empty 3064 writer.write("\n"); 3065 writer.flush(); 3066 writer.close(); 3067 } 3068 3069 @Override 3070 @NonNull resolve(final String endpoint)3071 public InetAddress resolve(final String endpoint) { 3072 try { 3073 // If a numeric IP address, return it. 3074 return InetAddress.parseNumericAddress(endpoint); 3075 } catch (IllegalArgumentException e) { 3076 // Otherwise, return some token IP to test for. 3077 return InetAddress.parseNumericAddress("5.6.7.8"); 3078 } 3079 } 3080 3081 @Override isInterfacePresent(final Vpn vpn, final String iface)3082 public boolean isInterfacePresent(final Vpn vpn, final String iface) { 3083 return true; 3084 } 3085 3086 @Override adoptFd(Vpn vpn, int mtu)3087 public ParcelFileDescriptor adoptFd(Vpn vpn, int mtu) { 3088 return new ParcelFileDescriptor(new FileDescriptor()); 3089 } 3090 3091 @Override jniCreate(Vpn vpn, int mtu)3092 public int jniCreate(Vpn vpn, int mtu) { 3093 // Pick a random positive number as fd to return. 3094 return 345; 3095 } 3096 3097 @Override jniGetName(Vpn vpn, int fd)3098 public String jniGetName(Vpn vpn, int fd) { 3099 return TEST_IFACE_NAME; 3100 } 3101 3102 @Override jniSetAddresses(Vpn vpn, String interfaze, String addresses)3103 public int jniSetAddresses(Vpn vpn, String interfaze, String addresses) { 3104 if (addresses == null) return 0; 3105 // Return the number of addresses. 3106 return addresses.split(" ").length; 3107 } 3108 3109 @Override setBlocking(FileDescriptor fd, boolean blocking)3110 public void setBlocking(FileDescriptor fd, boolean blocking) {} 3111 3112 @Override getDeviceIdleInternal()3113 public DeviceIdleInternal getDeviceIdleInternal() { 3114 return mDeviceIdleInternal; 3115 } 3116 3117 @Override getNextRetryDelayMs(int retryCount)3118 public long getNextRetryDelayMs(int retryCount) { 3119 // Simply return retryCount as the delay seconds for retrying. 3120 return retryCount * 1000; 3121 } 3122 3123 @Override getValidationFailRecoverySeconds(int retryCount)3124 public long getValidationFailRecoverySeconds(int retryCount) { 3125 // Simply return retryCount as the delay seconds for retrying. 3126 return retryCount; 3127 } 3128 3129 @Override newScheduledThreadPoolExecutor()3130 public ScheduledThreadPoolExecutor newScheduledThreadPoolExecutor() { 3131 return mExecutor; 3132 } 3133 3134 public boolean mIgnoreCallingUidChecks = true; 3135 @Override verifyCallingUidAndPackage(Context context, String packageName, int userId)3136 public void verifyCallingUidAndPackage(Context context, String packageName, int userId) { 3137 if (!mIgnoreCallingUidChecks) { 3138 super.verifyCallingUidAndPackage(context, packageName, userId); 3139 } 3140 } 3141 } 3142 3143 /** 3144 * Mock some methods of vpn object. 3145 */ createVpn(@serIdInt int userId)3146 private Vpn createVpn(@UserIdInt int userId) { 3147 final Context asUserContext = mock(Context.class, AdditionalAnswers.delegatesTo(mContext)); 3148 doReturn(UserHandle.of(userId)).when(asUserContext).getUser(); 3149 when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt())) 3150 .thenReturn(asUserContext); 3151 final TestLooper testLooper = new TestLooper(); 3152 final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, mTestDeps, mNetService, 3153 mNetd, userId, mVpnProfileStore, mSystemServices, mIkev2SessionCreator); 3154 verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat( 3155 provider -> provider.getName().contains("VpnNetworkProvider") 3156 )); 3157 return vpn; 3158 } 3159 3160 /** 3161 * Populate {@link #mUserManager} with a list of fake users. 3162 */ setMockedUsers(UserInfo... users)3163 private void setMockedUsers(UserInfo... users) { 3164 final Map<Integer, UserInfo> userMap = new ArrayMap<>(); 3165 for (UserInfo user : users) { 3166 userMap.put(user.id, user); 3167 } 3168 3169 /** 3170 * @see UserManagerService#getUsers(boolean) 3171 */ 3172 doAnswer(invocation -> { 3173 final ArrayList<UserInfo> result = new ArrayList<>(users.length); 3174 for (UserInfo ui : users) { 3175 if (ui.isEnabled() && !ui.partial) { 3176 result.add(ui); 3177 } 3178 } 3179 return result; 3180 }).when(mUserManager).getAliveUsers(); 3181 3182 doAnswer(invocation -> { 3183 final int id = (int) invocation.getArguments()[0]; 3184 return userMap.get(id); 3185 }).when(mUserManager).getUserInfo(anyInt()); 3186 } 3187 3188 /** 3189 * Populate {@link #mPackageManager} with a fake packageName-to-UID mapping. 3190 */ setMockedPackages(final Map<String, Integer> packages)3191 private void setMockedPackages(final Map<String, Integer> packages) { 3192 try { 3193 doAnswer(invocation -> { 3194 final String appName = (String) invocation.getArguments()[0]; 3195 final int userId = (int) invocation.getArguments()[1]; 3196 Integer appId = packages.get(appName); 3197 if (appId == null) throw new PackageManager.NameNotFoundException(appName); 3198 return UserHandle.getUid(userId, appId); 3199 }).when(mPackageManager).getPackageUidAsUser(anyString(), anyInt()); 3200 } catch (Exception e) { 3201 } 3202 } 3203 setMockedNetworks(final Map<Network, NetworkCapabilities> networks)3204 private void setMockedNetworks(final Map<Network, NetworkCapabilities> networks) { 3205 doAnswer(invocation -> { 3206 final Network network = (Network) invocation.getArguments()[0]; 3207 return networks.get(network); 3208 }).when(mConnectivityManager).getNetworkCapabilities(any()); 3209 } 3210 3211 // Need multiple copies of this, but Java's Stream objects can't be reused or 3212 // duplicated. publicIpV4Routes()3213 private Stream<String> publicIpV4Routes() { 3214 return Stream.of( 3215 "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", 3216 "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", 3217 "172.0.0.0/12", "172.32.0.0/11", "172.64.0.0/10", "172.128.0.0/9", 3218 "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", 3219 "192.160.0.0/13", "192.169.0.0/16", "192.170.0.0/15", "192.172.0.0/14", 3220 "192.176.0.0/12", "192.192.0.0/10", "193.0.0.0/8", "194.0.0.0/7", 3221 "196.0.0.0/6", "200.0.0.0/5", "208.0.0.0/4"); 3222 } 3223 publicIpV6Routes()3224 private Stream<String> publicIpV6Routes() { 3225 return Stream.of( 3226 "::/1", "8000::/2", "c000::/3", "e000::/4", "f000::/5", "f800::/6", 3227 "fe00::/8", "2605:ef80:e:af1d::/64"); 3228 } 3229 } 3230