1 /* 2 * Copyright (C) 2017 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; 18 19 import static android.content.pm.PackageManager.PERMISSION_DENIED; 20 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 21 import static android.net.INetd.IF_STATE_DOWN; 22 import static android.net.INetd.IF_STATE_UP; 23 import static android.net.IpSecManager.DIRECTION_FWD; 24 import static android.net.IpSecManager.DIRECTION_IN; 25 import static android.net.IpSecManager.DIRECTION_OUT; 26 import static android.net.IpSecManager.FEATURE_IPSEC_TUNNEL_MIGRATION; 27 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; 28 import static android.system.OsConstants.AF_INET; 29 import static android.system.OsConstants.AF_INET6; 30 31 import static org.junit.Assert.assertEquals; 32 import static org.junit.Assert.assertNotNull; 33 import static org.junit.Assert.fail; 34 import static org.mockito.ArgumentMatchers.any; 35 import static org.mockito.ArgumentMatchers.anyInt; 36 import static org.mockito.ArgumentMatchers.anyLong; 37 import static org.mockito.ArgumentMatchers.anyString; 38 import static org.mockito.ArgumentMatchers.argThat; 39 import static org.mockito.ArgumentMatchers.eq; 40 import static org.mockito.Matchers.anyInt; 41 import static org.mockito.Matchers.anyString; 42 import static org.mockito.Matchers.eq; 43 import static org.mockito.Mockito.mock; 44 import static org.mockito.Mockito.never; 45 import static org.mockito.Mockito.times; 46 import static org.mockito.Mockito.verify; 47 import static org.mockito.Mockito.when; 48 49 import android.app.AppOpsManager; 50 import android.content.Context; 51 import android.content.pm.PackageManager; 52 import android.net.ConnectivityManager; 53 import android.net.INetd; 54 import android.net.InetAddresses; 55 import android.net.InterfaceConfigurationParcel; 56 import android.net.IpSecAlgorithm; 57 import android.net.IpSecConfig; 58 import android.net.IpSecManager; 59 import android.net.IpSecMigrateInfoParcel; 60 import android.net.IpSecSpiResponse; 61 import android.net.IpSecTransform; 62 import android.net.IpSecTransformResponse; 63 import android.net.IpSecTunnelInterfaceResponse; 64 import android.net.IpSecUdpEncapResponse; 65 import android.net.LinkAddress; 66 import android.net.LinkProperties; 67 import android.net.Network; 68 import android.os.Binder; 69 import android.os.Build; 70 import android.os.ParcelFileDescriptor; 71 import android.os.RemoteException; 72 import android.system.Os; 73 import android.test.mock.MockContext; 74 import android.util.ArraySet; 75 76 import androidx.test.filters.SmallTest; 77 78 import com.android.net.module.util.netlink.xfrm.XfrmNetlinkNewSaMessage; 79 import com.android.server.IpSecService.TunnelInterfaceRecord; 80 import com.android.testutils.DevSdkIgnoreRule; 81 82 import org.junit.Before; 83 import org.junit.Ignore; 84 import org.junit.Rule; 85 import org.junit.Test; 86 import org.junit.runner.RunWith; 87 import org.junit.runners.Parameterized; 88 89 import java.net.Inet4Address; 90 import java.net.InetAddress; 91 import java.net.Socket; 92 import java.util.Arrays; 93 import java.util.Collection; 94 import java.util.Set; 95 96 /** Unit tests for {@link IpSecService}. */ 97 @SmallTest 98 @RunWith(Parameterized.class) 99 public class IpSecServiceParameterizedTest { 100 @Rule 101 public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule( 102 Build.VERSION_CODES.S_V2 /* ignoreClassUpTo */); 103 104 private static final int TEST_SPI = 0xD1201D; 105 106 private final String mSourceAddr; 107 private final String mDestinationAddr; 108 private final LinkAddress mLocalInnerAddress; 109 private final int mFamily; 110 111 private static final int[] ADDRESS_FAMILIES = 112 new int[] {AF_INET, AF_INET6}; 113 114 @Parameterized.Parameters ipSecConfigs()115 public static Collection ipSecConfigs() { 116 return Arrays.asList( 117 new Object[][] { 118 {"1.2.3.4", "8.8.4.4", "10.0.1.1/24", AF_INET}, 119 {"2601::2", "2601::10", "2001:db8::1/64", AF_INET6} 120 }); 121 } 122 123 private static final byte[] AEAD_KEY = { 124 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 125 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 126 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 127 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 128 0x73, 0x61, 0x6C, 0x74 129 }; 130 private static final byte[] CRYPT_KEY = { 131 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 132 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 133 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 134 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F 135 }; 136 private static final byte[] AUTH_KEY = { 137 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 139 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F 141 }; 142 143 private static final String NEW_SRC_ADDRESS = "2001:db8:2::1"; 144 private static final String NEW_DST_ADDRESS = "2001:db8:2::2"; 145 146 AppOpsManager mMockAppOps = mock(AppOpsManager.class); 147 ConnectivityManager mMockConnectivityMgr = mock(ConnectivityManager.class); 148 149 TestContext mTestContext = new TestContext(); 150 151 private class TestContext extends MockContext { 152 private Set<String> mAllowedPermissions = new ArraySet<>(Arrays.asList( 153 android.Manifest.permission.MANAGE_IPSEC_TUNNELS, 154 android.Manifest.permission.NETWORK_STACK, 155 android.Manifest.permission.ACCESS_NETWORK_STATE, 156 PERMISSION_MAINLINE_NETWORK_STACK)); 157 setAllowedPermissions(String... permissions)158 private void setAllowedPermissions(String... permissions) { 159 mAllowedPermissions = new ArraySet<>(permissions); 160 } 161 162 @Override getSystemService(String name)163 public Object getSystemService(String name) { 164 switch(name) { 165 case Context.APP_OPS_SERVICE: 166 return mMockAppOps; 167 case Context.CONNECTIVITY_SERVICE: 168 return mMockConnectivityMgr; 169 default: 170 return null; 171 } 172 } 173 174 @Override getSystemServiceName(Class<?> serviceClass)175 public String getSystemServiceName(Class<?> serviceClass) { 176 if (ConnectivityManager.class == serviceClass) { 177 return Context.CONNECTIVITY_SERVICE; 178 } 179 return null; 180 } 181 182 @Override getPackageManager()183 public PackageManager getPackageManager() { 184 return mMockPkgMgr; 185 } 186 187 @Override enforceCallingOrSelfPermission(String permission, String message)188 public void enforceCallingOrSelfPermission(String permission, String message) { 189 if (mAllowedPermissions.contains(permission)) { 190 return; 191 } else { 192 throw new SecurityException("Unavailable permission requested"); 193 } 194 } 195 196 @Override checkCallingOrSelfPermission(String permission)197 public int checkCallingOrSelfPermission(String permission) { 198 if (mAllowedPermissions.contains(permission)) { 199 return PERMISSION_GRANTED; 200 } else { 201 return PERMISSION_DENIED; 202 } 203 } 204 } 205 makeDependencies()206 private IpSecService.Dependencies makeDependencies() throws RemoteException { 207 final IpSecService.Dependencies deps = mock(IpSecService.Dependencies.class); 208 when(deps.getNetdInstance(mTestContext)).thenReturn(mMockNetd); 209 when(deps.getIpSecXfrmController()).thenReturn(mMockXfrmCtrl); 210 return deps; 211 } 212 213 INetd mMockNetd; 214 PackageManager mMockPkgMgr; 215 IpSecXfrmController mMockXfrmCtrl; 216 IpSecService.Dependencies mDeps; 217 IpSecService mIpSecService; 218 Network fakeNetwork = new Network(0xAB); 219 int mUid = Os.getuid(); 220 221 private static final IpSecAlgorithm AUTH_ALGO = 222 new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4); 223 private static final IpSecAlgorithm CRYPT_ALGO = 224 new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); 225 private static final IpSecAlgorithm AEAD_ALGO = 226 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); 227 private static final int REMOTE_ENCAP_PORT = 4500; 228 229 private static final String BLESSED_PACKAGE = "blessedPackage"; 230 private static final String SYSTEM_PACKAGE = "systemPackage"; 231 private static final String BAD_PACKAGE = "badPackage"; 232 IpSecServiceParameterizedTest( String sourceAddr, String destAddr, String localInnerAddr, int family)233 public IpSecServiceParameterizedTest( 234 String sourceAddr, String destAddr, String localInnerAddr, int family) { 235 mSourceAddr = sourceAddr; 236 mDestinationAddr = destAddr; 237 mLocalInnerAddress = new LinkAddress(localInnerAddr); 238 mFamily = family; 239 } 240 241 @Before setUp()242 public void setUp() throws Exception { 243 mMockNetd = mock(INetd.class); 244 mMockXfrmCtrl = mock(IpSecXfrmController.class); 245 mMockPkgMgr = mock(PackageManager.class); 246 mDeps = makeDependencies(); 247 mIpSecService = new IpSecService(mTestContext, mDeps); 248 249 // PackageManager should always return true (feature flag tests in IpSecServiceTest) 250 when(mMockPkgMgr.hasSystemFeature(anyString())).thenReturn(true); 251 252 // A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED. 253 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(BLESSED_PACKAGE))) 254 .thenReturn(AppOpsManager.MODE_ALLOWED); 255 // A system package will not be granted the app op, so this should fall back to 256 // a permissions check, which should pass. 257 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(SYSTEM_PACKAGE))) 258 .thenReturn(AppOpsManager.MODE_DEFAULT); 259 // A mismatch between the package name and the UID will return MODE_IGNORED. 260 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(BAD_PACKAGE))) 261 .thenReturn(AppOpsManager.MODE_IGNORED); 262 } 263 264 //TODO: Add a test to verify SPI. 265 266 @Test testIpSecServiceReserveSpi()267 public void testIpSecServiceReserveSpi() throws Exception { 268 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) 269 .thenReturn(TEST_SPI); 270 271 IpSecSpiResponse spiResp = 272 mIpSecService.allocateSecurityParameterIndex( 273 mDestinationAddr, TEST_SPI, new Binder()); 274 assertEquals(IpSecManager.Status.OK, spiResp.status); 275 assertEquals(TEST_SPI, spiResp.spi); 276 } 277 278 @Test testReleaseSecurityParameterIndex()279 public void testReleaseSecurityParameterIndex() throws Exception { 280 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) 281 .thenReturn(TEST_SPI); 282 283 IpSecSpiResponse spiResp = 284 mIpSecService.allocateSecurityParameterIndex( 285 mDestinationAddr, TEST_SPI, new Binder()); 286 287 mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId); 288 289 verify(mMockNetd) 290 .ipSecDeleteSecurityAssociation( 291 eq(mUid), 292 anyString(), 293 anyString(), 294 eq(TEST_SPI), 295 anyInt(), 296 anyInt(), 297 anyInt()); 298 299 // Verify quota and RefcountedResource objects cleaned up 300 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); 301 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); 302 try { 303 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId); 304 fail("Expected IllegalArgumentException on attempt to access deleted resource"); 305 } catch (IllegalArgumentException expected) { 306 307 } 308 } 309 310 @Test testSecurityParameterIndexBinderDeath()311 public void testSecurityParameterIndexBinderDeath() throws Exception { 312 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) 313 .thenReturn(TEST_SPI); 314 315 IpSecSpiResponse spiResp = 316 mIpSecService.allocateSecurityParameterIndex( 317 mDestinationAddr, TEST_SPI, new Binder()); 318 319 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); 320 IpSecService.RefcountedResource refcountedRecord = 321 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId); 322 323 refcountedRecord.binderDied(); 324 325 verify(mMockNetd) 326 .ipSecDeleteSecurityAssociation( 327 eq(mUid), 328 anyString(), 329 anyString(), 330 eq(TEST_SPI), 331 anyInt(), 332 anyInt(), 333 anyInt()); 334 335 // Verify quota and RefcountedResource objects cleaned up 336 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); 337 try { 338 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId); 339 fail("Expected IllegalArgumentException on attempt to access deleted resource"); 340 } catch (IllegalArgumentException expected) { 341 342 } 343 } 344 getNewSpiResourceId(String remoteAddress, int returnSpi)345 private int getNewSpiResourceId(String remoteAddress, int returnSpi) throws Exception { 346 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), anyString(), anyInt())) 347 .thenReturn(returnSpi); 348 349 IpSecSpiResponse spi = 350 mIpSecService.allocateSecurityParameterIndex( 351 InetAddresses.parseNumericAddress(remoteAddress).getHostAddress(), 352 IpSecManager.INVALID_SECURITY_PARAMETER_INDEX, 353 new Binder()); 354 return spi.resourceId; 355 } 356 addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config)357 private void addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config) throws Exception { 358 config.setSpiResourceId(getNewSpiResourceId(mDestinationAddr, TEST_SPI)); 359 config.setSourceAddress(mSourceAddr); 360 config.setDestinationAddress(mDestinationAddr); 361 } 362 addAuthAndCryptToIpSecConfig(IpSecConfig config)363 private void addAuthAndCryptToIpSecConfig(IpSecConfig config) throws Exception { 364 config.setEncryption(CRYPT_ALGO); 365 config.setAuthentication(AUTH_ALGO); 366 } 367 addEncapSocketToIpSecConfig(int resourceId, IpSecConfig config)368 private void addEncapSocketToIpSecConfig(int resourceId, IpSecConfig config) throws Exception { 369 config.setEncapType(IpSecTransform.ENCAP_ESPINUDP); 370 config.setEncapSocketResourceId(resourceId); 371 config.setEncapRemotePort(REMOTE_ENCAP_PORT); 372 } 373 verifyTransformNetdCalledForCreatingSA( IpSecConfig config, IpSecTransformResponse resp)374 private void verifyTransformNetdCalledForCreatingSA( 375 IpSecConfig config, IpSecTransformResponse resp) throws Exception { 376 verifyTransformNetdCalledForCreatingSA(config, resp, 0); 377 } 378 verifyTransformNetdCalledForCreatingSA( IpSecConfig config, IpSecTransformResponse resp, int encapSocketPort)379 private void verifyTransformNetdCalledForCreatingSA( 380 IpSecConfig config, IpSecTransformResponse resp, int encapSocketPort) throws Exception { 381 IpSecAlgorithm auth = config.getAuthentication(); 382 IpSecAlgorithm crypt = config.getEncryption(); 383 IpSecAlgorithm authCrypt = config.getAuthenticatedEncryption(); 384 385 verify(mMockNetd, times(1)) 386 .ipSecAddSecurityAssociation( 387 eq(mUid), 388 eq(config.getMode()), 389 eq(mSourceAddr), 390 eq(mDestinationAddr), 391 eq((config.getNetwork() != null) ? config.getNetwork().netId : 0), 392 eq(TEST_SPI), 393 eq(0), 394 eq(0), 395 eq((auth != null) ? auth.getName() : ""), 396 eq((auth != null) ? auth.getKey() : new byte[] {}), 397 eq((auth != null) ? auth.getTruncationLengthBits() : 0), 398 eq((crypt != null) ? crypt.getName() : ""), 399 eq((crypt != null) ? crypt.getKey() : new byte[] {}), 400 eq((crypt != null) ? crypt.getTruncationLengthBits() : 0), 401 eq((authCrypt != null) ? authCrypt.getName() : ""), 402 eq((authCrypt != null) ? authCrypt.getKey() : new byte[] {}), 403 eq((authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0), 404 eq(config.getEncapType()), 405 eq(encapSocketPort), 406 eq(config.getEncapRemotePort()), 407 eq(config.getXfrmInterfaceId())); 408 } 409 410 @Test testCreateTransform()411 public void testCreateTransform() throws Exception { 412 IpSecConfig ipSecConfig = new IpSecConfig(); 413 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 414 addAuthAndCryptToIpSecConfig(ipSecConfig); 415 416 IpSecTransformResponse createTransformResp = 417 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 418 assertEquals(IpSecManager.Status.OK, createTransformResp.status); 419 420 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); 421 } 422 423 @Test testCreateTransformAead()424 public void testCreateTransformAead() throws Exception { 425 IpSecConfig ipSecConfig = new IpSecConfig(); 426 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 427 428 ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO); 429 430 IpSecTransformResponse createTransformResp = 431 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 432 assertEquals(IpSecManager.Status.OK, createTransformResp.status); 433 434 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); 435 } 436 437 @Test testCreateTransportModeTransformWithEncap()438 public void testCreateTransportModeTransformWithEncap() throws Exception { 439 IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder()); 440 441 IpSecConfig ipSecConfig = new IpSecConfig(); 442 ipSecConfig.setMode(IpSecTransform.MODE_TRANSPORT); 443 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 444 addAuthAndCryptToIpSecConfig(ipSecConfig); 445 addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig); 446 447 if (mFamily == AF_INET) { 448 IpSecTransformResponse createTransformResp = 449 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 450 assertEquals(IpSecManager.Status.OK, createTransformResp.status); 451 452 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); 453 } else { 454 try { 455 IpSecTransformResponse createTransformResp = 456 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 457 fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); 458 } catch (IllegalArgumentException expected) { 459 } 460 } 461 } 462 463 @Test testCreateTunnelModeTransformWithEncap()464 public void testCreateTunnelModeTransformWithEncap() throws Exception { 465 IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder()); 466 467 IpSecConfig ipSecConfig = new IpSecConfig(); 468 ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); 469 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 470 addAuthAndCryptToIpSecConfig(ipSecConfig); 471 addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig); 472 473 if (mFamily == AF_INET) { 474 IpSecTransformResponse createTransformResp = 475 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 476 assertEquals(IpSecManager.Status.OK, createTransformResp.status); 477 478 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); 479 } else { 480 try { 481 IpSecTransformResponse createTransformResp = 482 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 483 fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); 484 } catch (IllegalArgumentException expected) { 485 } 486 } 487 } 488 489 @Test testCreateTwoTransformsWithSameSpis()490 public void testCreateTwoTransformsWithSameSpis() throws Exception { 491 IpSecConfig ipSecConfig = new IpSecConfig(); 492 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 493 addAuthAndCryptToIpSecConfig(ipSecConfig); 494 495 IpSecTransformResponse createTransformResp = 496 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 497 assertEquals(IpSecManager.Status.OK, createTransformResp.status); 498 499 // Attempting to create transform a second time with the same SPIs should throw an error... 500 try { 501 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 502 fail("IpSecService should have thrown an error for reuse of SPI"); 503 } catch (IllegalStateException expected) { 504 } 505 506 // ... even if the transform is deleted 507 mIpSecService.deleteTransform(createTransformResp.resourceId); 508 try { 509 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 510 fail("IpSecService should have thrown an error for reuse of SPI"); 511 } catch (IllegalStateException expected) { 512 } 513 } 514 515 @Test getTransformState()516 public void getTransformState() throws Exception { 517 XfrmNetlinkNewSaMessage mockXfrmNewSaMsg = mock(XfrmNetlinkNewSaMessage.class); 518 when(mockXfrmNewSaMsg.getBitmap()).thenReturn(new byte[512]); 519 when(mMockXfrmCtrl.ipSecGetSa(any(InetAddress.class), anyLong())) 520 .thenReturn(mockXfrmNewSaMsg); 521 522 // Create transform 523 IpSecConfig ipSecConfig = new IpSecConfig(); 524 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 525 addAuthAndCryptToIpSecConfig(ipSecConfig); 526 527 IpSecTransformResponse createTransformResp = 528 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 529 assertEquals(IpSecManager.Status.OK, createTransformResp.status); 530 531 // Get transform state 532 mIpSecService.getTransformState(createTransformResp.resourceId); 533 534 // Verifications 535 verify(mMockXfrmCtrl) 536 .ipSecGetSa( 537 eq(InetAddresses.parseNumericAddress(mDestinationAddr)), 538 eq(Integer.toUnsignedLong(TEST_SPI))); 539 } 540 541 @Test testReleaseOwnedSpi()542 public void testReleaseOwnedSpi() throws Exception { 543 IpSecConfig ipSecConfig = new IpSecConfig(); 544 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 545 addAuthAndCryptToIpSecConfig(ipSecConfig); 546 547 IpSecTransformResponse createTransformResp = 548 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 549 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); 550 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); 551 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); 552 verify(mMockNetd, times(0)) 553 .ipSecDeleteSecurityAssociation( 554 eq(mUid), 555 anyString(), 556 anyString(), 557 eq(TEST_SPI), 558 anyInt(), 559 anyInt(), 560 anyInt()); 561 // quota is not released until the SPI is released by the Transform 562 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); 563 } 564 565 @Test testDeleteTransform()566 public void testDeleteTransform() throws Exception { 567 IpSecConfig ipSecConfig = new IpSecConfig(); 568 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 569 addAuthAndCryptToIpSecConfig(ipSecConfig); 570 571 IpSecTransformResponse createTransformResp = 572 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 573 mIpSecService.deleteTransform(createTransformResp.resourceId); 574 575 verify(mMockNetd, times(1)) 576 .ipSecDeleteSecurityAssociation( 577 eq(mUid), 578 anyString(), 579 anyString(), 580 eq(TEST_SPI), 581 anyInt(), 582 anyInt(), 583 anyInt()); 584 585 // Verify quota and RefcountedResource objects cleaned up 586 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); 587 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent); 588 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); 589 590 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); 591 // Verify that ipSecDeleteSa was not called when the SPI was released because the 592 // ownedByTransform property should prevent it; (note, the called count is cumulative). 593 verify(mMockNetd, times(1)) 594 .ipSecDeleteSecurityAssociation( 595 anyInt(), 596 anyString(), 597 anyString(), 598 anyInt(), 599 anyInt(), 600 anyInt(), 601 anyInt()); 602 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); 603 604 try { 605 userRecord.mTransformRecords.getRefcountedResourceOrThrow( 606 createTransformResp.resourceId); 607 fail("Expected IllegalArgumentException on attempt to access deleted resource"); 608 } catch (IllegalArgumentException expected) { 609 610 } 611 } 612 613 @Test testTransportModeTransformBinderDeath()614 public void testTransportModeTransformBinderDeath() throws Exception { 615 IpSecConfig ipSecConfig = new IpSecConfig(); 616 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 617 addAuthAndCryptToIpSecConfig(ipSecConfig); 618 619 IpSecTransformResponse createTransformResp = 620 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 621 622 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); 623 IpSecService.RefcountedResource refcountedRecord = 624 userRecord.mTransformRecords.getRefcountedResourceOrThrow( 625 createTransformResp.resourceId); 626 627 refcountedRecord.binderDied(); 628 629 verify(mMockNetd) 630 .ipSecDeleteSecurityAssociation( 631 eq(mUid), 632 anyString(), 633 anyString(), 634 eq(TEST_SPI), 635 anyInt(), 636 anyInt(), 637 anyInt()); 638 639 // Verify quota and RefcountedResource objects cleaned up 640 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent); 641 try { 642 userRecord.mTransformRecords.getRefcountedResourceOrThrow( 643 createTransformResp.resourceId); 644 fail("Expected IllegalArgumentException on attempt to access deleted resource"); 645 } catch (IllegalArgumentException expected) { 646 647 } 648 } 649 650 @Test testApplyTransportModeTransform()651 public void testApplyTransportModeTransform() throws Exception { 652 verifyApplyTransportModeTransformCommon(false); 653 } 654 655 @Test testApplyTransportModeTransformReleasedSpi()656 public void testApplyTransportModeTransformReleasedSpi() throws Exception { 657 verifyApplyTransportModeTransformCommon(true); 658 } 659 verifyApplyTransportModeTransformCommon( boolean closeSpiBeforeApply)660 public void verifyApplyTransportModeTransformCommon( 661 boolean closeSpiBeforeApply) throws Exception { 662 IpSecConfig ipSecConfig = new IpSecConfig(); 663 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 664 addAuthAndCryptToIpSecConfig(ipSecConfig); 665 666 IpSecTransformResponse createTransformResp = 667 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 668 669 if (closeSpiBeforeApply) { 670 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); 671 } 672 673 Socket socket = new Socket(); 674 socket.bind(null); 675 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); 676 677 int resourceId = createTransformResp.resourceId; 678 mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId); 679 680 verify(mMockNetd) 681 .ipSecApplyTransportModeTransform( 682 eq(pfd), 683 eq(mUid), 684 eq(IpSecManager.DIRECTION_OUT), 685 anyString(), 686 anyString(), 687 eq(TEST_SPI)); 688 } 689 690 @Test testApplyTransportModeTransformWithClosedSpi()691 public void testApplyTransportModeTransformWithClosedSpi() throws Exception { 692 IpSecConfig ipSecConfig = new IpSecConfig(); 693 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 694 addAuthAndCryptToIpSecConfig(ipSecConfig); 695 696 IpSecTransformResponse createTransformResp = 697 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 698 699 // Close SPI record 700 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); 701 702 Socket socket = new Socket(); 703 socket.bind(null); 704 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); 705 706 int resourceId = createTransformResp.resourceId; 707 mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId); 708 709 verify(mMockNetd) 710 .ipSecApplyTransportModeTransform( 711 eq(pfd), 712 eq(mUid), 713 eq(IpSecManager.DIRECTION_OUT), 714 anyString(), 715 anyString(), 716 eq(TEST_SPI)); 717 } 718 719 @Test testRemoveTransportModeTransform()720 public void testRemoveTransportModeTransform() throws Exception { 721 Socket socket = new Socket(); 722 socket.bind(null); 723 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); 724 mIpSecService.removeTransportModeTransforms(pfd); 725 726 verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd); 727 } 728 createAndValidateTunnel( String localAddr, String remoteAddr, String pkgName)729 private IpSecTunnelInterfaceResponse createAndValidateTunnel( 730 String localAddr, String remoteAddr, String pkgName) throws Exception { 731 final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel(); 732 config.flags = new String[] {IF_STATE_DOWN}; 733 when(mMockNetd.interfaceGetCfg(anyString())).thenReturn(config); 734 IpSecTunnelInterfaceResponse createTunnelResp = 735 mIpSecService.createTunnelInterface( 736 mSourceAddr, mDestinationAddr, fakeNetwork, new Binder(), pkgName); 737 738 assertNotNull(createTunnelResp); 739 assertEquals(IpSecManager.Status.OK, createTunnelResp.status); 740 for (int direction : new int[] {DIRECTION_IN, DIRECTION_OUT, DIRECTION_FWD}) { 741 for (int selAddrFamily : ADDRESS_FAMILIES) { 742 verify(mMockNetd).ipSecAddSecurityPolicy( 743 eq(mUid), 744 eq(selAddrFamily), 745 eq(direction), 746 anyString(), 747 anyString(), 748 eq(0), 749 anyInt(), // iKey/oKey 750 anyInt(), // mask 751 eq(createTunnelResp.resourceId)); 752 } 753 } 754 755 return createTunnelResp; 756 } 757 758 @Test testCreateTunnelInterface()759 public void testCreateTunnelInterface() throws Exception { 760 IpSecTunnelInterfaceResponse createTunnelResp = 761 createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); 762 763 // Check that we have stored the tracking object, and retrieve it 764 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); 765 IpSecService.RefcountedResource refcountedRecord = 766 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( 767 createTunnelResp.resourceId); 768 769 assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent); 770 verify(mMockNetd) 771 .ipSecAddTunnelInterface( 772 eq(createTunnelResp.interfaceName), 773 eq(mSourceAddr), 774 eq(mDestinationAddr), 775 anyInt(), 776 anyInt(), 777 anyInt()); 778 verify(mMockNetd).interfaceSetCfg(argThat( 779 config -> Arrays.asList(config.flags).contains(IF_STATE_UP))); 780 } 781 782 @Test testDeleteTunnelInterface()783 public void testDeleteTunnelInterface() throws Exception { 784 IpSecTunnelInterfaceResponse createTunnelResp = 785 createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); 786 787 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); 788 789 mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, BLESSED_PACKAGE); 790 791 // Verify quota and RefcountedResource objects cleaned up 792 assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); 793 verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName)); 794 795 for (int direction : new int[] {DIRECTION_OUT, DIRECTION_IN, DIRECTION_FWD}) { 796 verify(mMockNetd, times(ADDRESS_FAMILIES.length)) 797 .ipSecDeleteSecurityPolicy( 798 anyInt(), anyInt(), eq(direction), anyInt(), anyInt(), anyInt()); 799 } 800 801 try { 802 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( 803 createTunnelResp.resourceId); 804 fail("Expected IllegalArgumentException on attempt to access deleted resource"); 805 } catch (IllegalArgumentException expected) { 806 } 807 } 808 createFakeUnderlyingNetwork(String interfaceName)809 private Network createFakeUnderlyingNetwork(String interfaceName) { 810 final Network fakeNetwork = new Network(1000); 811 final LinkProperties fakeLp = new LinkProperties(); 812 fakeLp.setInterfaceName(interfaceName); 813 when(mMockConnectivityMgr.getLinkProperties(eq(fakeNetwork))).thenReturn(fakeLp); 814 return fakeNetwork; 815 } 816 817 @Test testSetNetworkForTunnelInterface()818 public void testSetNetworkForTunnelInterface() throws Exception { 819 final IpSecTunnelInterfaceResponse createTunnelResp = 820 createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); 821 final Network newFakeNetwork = createFakeUnderlyingNetwork("newFakeNetworkInterface"); 822 final int tunnelIfaceResourceId = createTunnelResp.resourceId; 823 mIpSecService.setNetworkForTunnelInterface( 824 tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE); 825 826 final IpSecService.UserRecord userRecord = 827 mIpSecService.mUserResourceTracker.getUserRecord(mUid); 828 assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent); 829 830 final TunnelInterfaceRecord tunnelInterfaceInfo = 831 userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelIfaceResourceId); 832 assertEquals(newFakeNetwork, tunnelInterfaceInfo.getUnderlyingNetwork()); 833 } 834 835 @Test testSetNetworkForTunnelInterfaceFailsForNullLp()836 public void testSetNetworkForTunnelInterfaceFailsForNullLp() throws Exception { 837 final IpSecTunnelInterfaceResponse createTunnelResp = 838 createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); 839 final Network newFakeNetwork = new Network(1000); 840 final int tunnelIfaceResourceId = createTunnelResp.resourceId; 841 842 try { 843 mIpSecService.setNetworkForTunnelInterface( 844 tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE); 845 fail( 846 "Expected an IllegalArgumentException for underlying network with null" 847 + " LinkProperties"); 848 } catch (IllegalArgumentException expected) { 849 } 850 } 851 852 @Test testSetNetworkForTunnelInterfaceFailsForInvalidResourceId()853 public void testSetNetworkForTunnelInterfaceFailsForInvalidResourceId() throws Exception { 854 final IpSecTunnelInterfaceResponse createTunnelResp = 855 createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); 856 final Network newFakeNetwork = new Network(1000); 857 858 try { 859 mIpSecService.setNetworkForTunnelInterface( 860 IpSecManager.INVALID_RESOURCE_ID, newFakeNetwork, BLESSED_PACKAGE); 861 fail("Expected an IllegalArgumentException for invalid resource ID."); 862 } catch (IllegalArgumentException expected) { 863 } 864 } 865 866 @Test testSetNetworkForTunnelInterfaceFailsWhenSettingTunnelNetwork()867 public void testSetNetworkForTunnelInterfaceFailsWhenSettingTunnelNetwork() throws Exception { 868 final IpSecTunnelInterfaceResponse createTunnelResp = 869 createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); 870 final int tunnelIfaceResourceId = createTunnelResp.resourceId; 871 final IpSecService.UserRecord userRecord = 872 mIpSecService.mUserResourceTracker.getUserRecord(mUid); 873 final TunnelInterfaceRecord tunnelInterfaceInfo = 874 userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelIfaceResourceId); 875 876 final Network newFakeNetwork = 877 createFakeUnderlyingNetwork(tunnelInterfaceInfo.getInterfaceName()); 878 879 try { 880 mIpSecService.setNetworkForTunnelInterface( 881 tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE); 882 fail( 883 "Expected an IllegalArgumentException because the underlying network is the" 884 + " network being exposed by this tunnel."); 885 } catch (IllegalArgumentException expected) { 886 } 887 } 888 889 @Test testTunnelInterfaceBinderDeath()890 public void testTunnelInterfaceBinderDeath() throws Exception { 891 IpSecTunnelInterfaceResponse createTunnelResp = 892 createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); 893 894 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); 895 IpSecService.RefcountedResource refcountedRecord = 896 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( 897 createTunnelResp.resourceId); 898 899 refcountedRecord.binderDied(); 900 901 // Verify quota and RefcountedResource objects cleaned up 902 assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); 903 verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName)); 904 try { 905 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( 906 createTunnelResp.resourceId); 907 fail("Expected IllegalArgumentException on attempt to access deleted resource"); 908 } catch (IllegalArgumentException expected) { 909 } 910 } 911 912 @Test testApplyTunnelModeTransformOutbound()913 public void testApplyTunnelModeTransformOutbound() throws Exception { 914 verifyApplyTunnelModeTransformCommon(false /* closeSpiBeforeApply */, DIRECTION_OUT); 915 } 916 917 @Test testApplyTunnelModeTransformOutboundNonNetworkStack()918 public void testApplyTunnelModeTransformOutboundNonNetworkStack() throws Exception { 919 mTestContext.setAllowedPermissions(android.Manifest.permission.MANAGE_IPSEC_TUNNELS); 920 verifyApplyTunnelModeTransformCommon(false /* closeSpiBeforeApply */, DIRECTION_OUT); 921 } 922 923 @Test testApplyTunnelModeTransformOutboundReleasedSpi()924 public void testApplyTunnelModeTransformOutboundReleasedSpi() throws Exception { 925 verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_OUT); 926 } 927 928 @Test testApplyTunnelModeTransformInbound()929 public void testApplyTunnelModeTransformInbound() throws Exception { 930 verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_IN); 931 } 932 933 @Test testApplyTunnelModeTransformInboundNonNetworkStack()934 public void testApplyTunnelModeTransformInboundNonNetworkStack() throws Exception { 935 mTestContext.setAllowedPermissions(android.Manifest.permission.MANAGE_IPSEC_TUNNELS); 936 verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_IN); 937 } 938 939 @Test testApplyTunnelModeTransformForward()940 public void testApplyTunnelModeTransformForward() throws Exception { 941 verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_FWD); 942 } 943 944 @Test testApplyTunnelModeTransformForwardNonNetworkStack()945 public void testApplyTunnelModeTransformForwardNonNetworkStack() throws Exception { 946 mTestContext.setAllowedPermissions(android.Manifest.permission.MANAGE_IPSEC_TUNNELS); 947 948 try { 949 verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_FWD); 950 fail("Expected security exception due to use of forward policies without NETWORK_STACK" 951 + " or MAINLINE_NETWORK_STACK permission"); 952 } catch (SecurityException expected) { 953 } 954 } 955 956 @Test 957 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) testApplyAndMigrateTunnelModeTransformOutbound()958 public void testApplyAndMigrateTunnelModeTransformOutbound() throws Exception { 959 verifyApplyAndMigrateTunnelModeTransformCommon(false, DIRECTION_OUT); 960 } 961 962 @Test 963 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) testApplyAndMigrateTunnelModeTransformOutboundReleasedSpi()964 public void testApplyAndMigrateTunnelModeTransformOutboundReleasedSpi() throws Exception { 965 verifyApplyAndMigrateTunnelModeTransformCommon(true, DIRECTION_OUT); 966 } 967 968 @Test 969 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) testApplyAndMigrateTunnelModeTransformInbound()970 public void testApplyAndMigrateTunnelModeTransformInbound() throws Exception { 971 verifyApplyAndMigrateTunnelModeTransformCommon(false, DIRECTION_IN); 972 } 973 974 @Test 975 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) testApplyAndMigrateTunnelModeTransformInboundReleasedSpi()976 public void testApplyAndMigrateTunnelModeTransformInboundReleasedSpi() throws Exception { 977 verifyApplyAndMigrateTunnelModeTransformCommon(true, DIRECTION_IN); 978 } 979 980 @Test 981 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) testApplyAndMigrateTunnelModeTransformForward()982 public void testApplyAndMigrateTunnelModeTransformForward() throws Exception { 983 verifyApplyAndMigrateTunnelModeTransformCommon(false, DIRECTION_FWD); 984 } 985 986 @Test 987 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) testApplyAndMigrateTunnelModeTransformForwardReleasedSpi()988 public void testApplyAndMigrateTunnelModeTransformForwardReleasedSpi() throws Exception { 989 verifyApplyAndMigrateTunnelModeTransformCommon(true, DIRECTION_FWD); 990 } 991 verifyApplyTunnelModeTransformCommon(boolean closeSpiBeforeApply, int direction)992 public void verifyApplyTunnelModeTransformCommon(boolean closeSpiBeforeApply, int direction) 993 throws Exception { 994 verifyApplyTunnelModeTransformCommon( 995 new IpSecConfig(), closeSpiBeforeApply, false /* isMigrating */, direction); 996 } 997 verifyApplyAndMigrateTunnelModeTransformCommon( boolean closeSpiBeforeApply, int direction)998 public void verifyApplyAndMigrateTunnelModeTransformCommon( 999 boolean closeSpiBeforeApply, int direction) throws Exception { 1000 verifyApplyTunnelModeTransformCommon( 1001 new IpSecConfig(), closeSpiBeforeApply, true /* isMigrating */, direction); 1002 } 1003 verifyApplyTunnelModeTransformCommon( IpSecConfig ipSecConfig, boolean closeSpiBeforeApply, boolean isMigrating, int direction)1004 public int verifyApplyTunnelModeTransformCommon( 1005 IpSecConfig ipSecConfig, 1006 boolean closeSpiBeforeApply, 1007 boolean isMigrating, 1008 int direction) 1009 throws Exception { 1010 ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); 1011 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 1012 addAuthAndCryptToIpSecConfig(ipSecConfig); 1013 1014 IpSecTransformResponse createTransformResp = 1015 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 1016 IpSecTunnelInterfaceResponse createTunnelResp = 1017 createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); 1018 1019 if (closeSpiBeforeApply) { 1020 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); 1021 } 1022 1023 int transformResourceId = createTransformResp.resourceId; 1024 int tunnelResourceId = createTunnelResp.resourceId; 1025 1026 if (isMigrating) { 1027 mIpSecService.migrateTransform( 1028 transformResourceId, NEW_SRC_ADDRESS, NEW_DST_ADDRESS, BLESSED_PACKAGE); 1029 } 1030 1031 mIpSecService.applyTunnelModeTransform( 1032 tunnelResourceId, direction, transformResourceId, BLESSED_PACKAGE); 1033 1034 for (int selAddrFamily : ADDRESS_FAMILIES) { 1035 verify(mMockNetd) 1036 .ipSecUpdateSecurityPolicy( 1037 eq(mUid), 1038 eq(selAddrFamily), 1039 eq(direction), 1040 anyString(), 1041 anyString(), 1042 eq(direction == DIRECTION_OUT ? TEST_SPI : 0), 1043 anyInt(), // iKey/oKey 1044 anyInt(), // mask 1045 eq(tunnelResourceId)); 1046 } 1047 1048 ipSecConfig.setXfrmInterfaceId(tunnelResourceId); 1049 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); 1050 1051 if (isMigrating) { 1052 verify(mMockNetd, times(ADDRESS_FAMILIES.length)) 1053 .ipSecMigrate(any(IpSecMigrateInfoParcel.class)); 1054 } else { 1055 verify(mMockNetd, never()).ipSecMigrate(any()); 1056 } 1057 1058 return tunnelResourceId; 1059 } 1060 1061 @Test testApplyTunnelModeTransformWithClosedSpi()1062 public void testApplyTunnelModeTransformWithClosedSpi() throws Exception { 1063 IpSecConfig ipSecConfig = new IpSecConfig(); 1064 ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); 1065 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); 1066 addAuthAndCryptToIpSecConfig(ipSecConfig); 1067 1068 IpSecTransformResponse createTransformResp = 1069 mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); 1070 IpSecTunnelInterfaceResponse createTunnelResp = 1071 createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); 1072 1073 // Close SPI record 1074 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); 1075 1076 int transformResourceId = createTransformResp.resourceId; 1077 int tunnelResourceId = createTunnelResp.resourceId; 1078 mIpSecService.applyTunnelModeTransform( 1079 tunnelResourceId, IpSecManager.DIRECTION_OUT, transformResourceId, BLESSED_PACKAGE); 1080 1081 for (int selAddrFamily : ADDRESS_FAMILIES) { 1082 verify(mMockNetd) 1083 .ipSecUpdateSecurityPolicy( 1084 eq(mUid), 1085 eq(selAddrFamily), 1086 eq(IpSecManager.DIRECTION_OUT), 1087 anyString(), 1088 anyString(), 1089 eq(TEST_SPI), 1090 anyInt(), // iKey/oKey 1091 anyInt(), // mask 1092 eq(tunnelResourceId)); 1093 } 1094 1095 ipSecConfig.setXfrmInterfaceId(tunnelResourceId); 1096 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); 1097 } 1098 1099 @Test testAddRemoveAddressFromTunnelInterface()1100 public void testAddRemoveAddressFromTunnelInterface() throws Exception { 1101 for (String pkgName : new String[] {BLESSED_PACKAGE, SYSTEM_PACKAGE}) { 1102 IpSecTunnelInterfaceResponse createTunnelResp = 1103 createAndValidateTunnel(mSourceAddr, mDestinationAddr, pkgName); 1104 mIpSecService.addAddressToTunnelInterface( 1105 createTunnelResp.resourceId, mLocalInnerAddress, pkgName); 1106 verify(mMockNetd, times(1)) 1107 .interfaceAddAddress( 1108 eq(createTunnelResp.interfaceName), 1109 eq(mLocalInnerAddress.getAddress().getHostAddress()), 1110 eq(mLocalInnerAddress.getPrefixLength())); 1111 mIpSecService.removeAddressFromTunnelInterface( 1112 createTunnelResp.resourceId, mLocalInnerAddress, pkgName); 1113 verify(mMockNetd, times(1)) 1114 .interfaceDelAddress( 1115 eq(createTunnelResp.interfaceName), 1116 eq(mLocalInnerAddress.getAddress().getHostAddress()), 1117 eq(mLocalInnerAddress.getPrefixLength())); 1118 mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, pkgName); 1119 } 1120 } 1121 1122 @Ignore 1123 @Test testAddTunnelFailsForBadPackageName()1124 public void testAddTunnelFailsForBadPackageName() throws Exception { 1125 try { 1126 IpSecTunnelInterfaceResponse createTunnelResp = 1127 createAndValidateTunnel(mSourceAddr, mDestinationAddr, BAD_PACKAGE); 1128 fail("Expected a SecurityException for badPackage."); 1129 } catch (SecurityException expected) { 1130 } 1131 } 1132 1133 @Test testFeatureFlagIpSecTunnelsVerification()1134 public void testFeatureFlagIpSecTunnelsVerification() throws Exception { 1135 when(mMockPkgMgr.hasSystemFeature(eq(PackageManager.FEATURE_IPSEC_TUNNELS))) 1136 .thenReturn(false); 1137 1138 try { 1139 String addr = Inet4Address.getLoopbackAddress().getHostAddress(); 1140 mIpSecService.createTunnelInterface( 1141 addr, addr, new Network(0), new Binder(), BLESSED_PACKAGE); 1142 fail("Expected UnsupportedOperationException for disabled feature"); 1143 } catch (UnsupportedOperationException expected) { 1144 } 1145 } 1146 1147 @Test 1148 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) testFeatureFlagIpSecTunnelMigrationVerification()1149 public void testFeatureFlagIpSecTunnelMigrationVerification() throws Exception { 1150 when(mMockPkgMgr.hasSystemFeature(eq(FEATURE_IPSEC_TUNNEL_MIGRATION))).thenReturn(false); 1151 1152 try { 1153 mIpSecService.migrateTransform( 1154 1 /* transformId */, NEW_SRC_ADDRESS, NEW_DST_ADDRESS, BLESSED_PACKAGE); 1155 fail("Expected UnsupportedOperationException for disabled feature"); 1156 } catch (UnsupportedOperationException expected) { 1157 } 1158 } 1159 } 1160