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