diff options
Diffstat (limited to 'tests/net/java/com/android/server/IpSecServiceParameterizedTest.java')
-rw-r--r-- | tests/net/java/com/android/server/IpSecServiceParameterizedTest.java | 1004 |
1 files changed, 0 insertions, 1004 deletions
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java deleted file mode 100644 index cf2c9c783ac7..000000000000 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static android.content.pm.PackageManager.PERMISSION_DENIED; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.INetd.IF_STATE_DOWN; -import static android.net.INetd.IF_STATE_UP; -import static android.net.IpSecManager.DIRECTION_FWD; -import static android.net.IpSecManager.DIRECTION_IN; -import static android.net.IpSecManager.DIRECTION_OUT; -import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.AF_INET6; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.INetd; -import android.net.InetAddresses; -import android.net.InterfaceConfigurationParcel; -import android.net.IpSecAlgorithm; -import android.net.IpSecConfig; -import android.net.IpSecManager; -import android.net.IpSecSpiResponse; -import android.net.IpSecTransform; -import android.net.IpSecTransformResponse; -import android.net.IpSecTunnelInterfaceResponse; -import android.net.IpSecUdpEncapResponse; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.os.Binder; -import android.os.ParcelFileDescriptor; -import android.system.Os; -import android.test.mock.MockContext; -import android.util.ArraySet; - -import androidx.test.filters.SmallTest; - -import com.android.server.IpSecService.TunnelInterfaceRecord; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.net.Inet4Address; -import java.net.Socket; -import java.util.Arrays; -import java.util.Collection; -import java.util.Set; - -/** Unit tests for {@link IpSecService}. */ -@SmallTest -@RunWith(Parameterized.class) -public class IpSecServiceParameterizedTest { - - private static final int TEST_SPI = 0xD1201D; - - private final String mSourceAddr; - private final String mDestinationAddr; - private final LinkAddress mLocalInnerAddress; - private final int mFamily; - - private static final int[] ADDRESS_FAMILIES = - new int[] {AF_INET, AF_INET6}; - - @Parameterized.Parameters - public static Collection ipSecConfigs() { - return Arrays.asList( - new Object[][] { - {"1.2.3.4", "8.8.4.4", "10.0.1.1/24", AF_INET}, - {"2601::2", "2601::10", "2001:db8::1/64", AF_INET6} - }); - } - - private static final byte[] AEAD_KEY = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x73, 0x61, 0x6C, 0x74 - }; - private static final byte[] CRYPT_KEY = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F - }; - private static final byte[] AUTH_KEY = { - 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, - 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F - }; - - AppOpsManager mMockAppOps = mock(AppOpsManager.class); - ConnectivityManager mMockConnectivityMgr = mock(ConnectivityManager.class); - - TestContext mTestContext = new TestContext(); - - private class TestContext extends MockContext { - private Set<String> mAllowedPermissions = new ArraySet<>(Arrays.asList( - android.Manifest.permission.MANAGE_IPSEC_TUNNELS, - android.Manifest.permission.NETWORK_STACK, - PERMISSION_MAINLINE_NETWORK_STACK)); - - private void setAllowedPermissions(String... permissions) { - mAllowedPermissions = new ArraySet<>(permissions); - } - - @Override - public Object getSystemService(String name) { - switch(name) { - case Context.APP_OPS_SERVICE: - return mMockAppOps; - case Context.CONNECTIVITY_SERVICE: - return mMockConnectivityMgr; - default: - return null; - } - } - - @Override - public String getSystemServiceName(Class<?> serviceClass) { - if (ConnectivityManager.class == serviceClass) { - return Context.CONNECTIVITY_SERVICE; - } - return null; - } - - @Override - public PackageManager getPackageManager() { - return mMockPkgMgr; - } - - @Override - public void enforceCallingOrSelfPermission(String permission, String message) { - if (mAllowedPermissions.contains(permission)) { - return; - } else { - throw new SecurityException("Unavailable permission requested"); - } - } - - @Override - public int checkCallingOrSelfPermission(String permission) { - if (mAllowedPermissions.contains(permission)) { - return PERMISSION_GRANTED; - } else { - return PERMISSION_DENIED; - } - } - } - - INetd mMockNetd; - PackageManager mMockPkgMgr; - IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; - IpSecService mIpSecService; - Network fakeNetwork = new Network(0xAB); - int mUid = Os.getuid(); - - private static final IpSecAlgorithm AUTH_ALGO = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4); - private static final IpSecAlgorithm CRYPT_ALGO = - new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - private static final IpSecAlgorithm AEAD_ALGO = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); - private static final int REMOTE_ENCAP_PORT = 4500; - - private static final String BLESSED_PACKAGE = "blessedPackage"; - private static final String SYSTEM_PACKAGE = "systemPackage"; - private static final String BAD_PACKAGE = "badPackage"; - - public IpSecServiceParameterizedTest( - String sourceAddr, String destAddr, String localInnerAddr, int family) { - mSourceAddr = sourceAddr; - mDestinationAddr = destAddr; - mLocalInnerAddress = new LinkAddress(localInnerAddr); - mFamily = family; - } - - @Before - public void setUp() throws Exception { - mMockNetd = mock(INetd.class); - mMockPkgMgr = mock(PackageManager.class); - mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mTestContext, mMockIpSecSrvConfig); - - // Injecting mock netd - when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); - - // PackageManager should always return true (feature flag tests in IpSecServiceTest) - when(mMockPkgMgr.hasSystemFeature(anyString())).thenReturn(true); - - // A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED. - when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(BLESSED_PACKAGE))) - .thenReturn(AppOpsManager.MODE_ALLOWED); - // A system package will not be granted the app op, so this should fall back to - // a permissions check, which should pass. - when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(SYSTEM_PACKAGE))) - .thenReturn(AppOpsManager.MODE_DEFAULT); - // A mismatch between the package name and the UID will return MODE_IGNORED. - when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(BAD_PACKAGE))) - .thenReturn(AppOpsManager.MODE_IGNORED); - } - - //TODO: Add a test to verify SPI. - - @Test - public void testIpSecServiceReserveSpi() throws Exception { - when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) - .thenReturn(TEST_SPI); - - IpSecSpiResponse spiResp = - mIpSecService.allocateSecurityParameterIndex( - mDestinationAddr, TEST_SPI, new Binder()); - assertEquals(IpSecManager.Status.OK, spiResp.status); - assertEquals(TEST_SPI, spiResp.spi); - } - - @Test - public void testReleaseSecurityParameterIndex() throws Exception { - when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) - .thenReturn(TEST_SPI); - - IpSecSpiResponse spiResp = - mIpSecService.allocateSecurityParameterIndex( - mDestinationAddr, TEST_SPI, new Binder()); - - mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId); - - verify(mMockNetd) - .ipSecDeleteSecurityAssociation( - eq(mUid), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), - anyInt(), - anyInt()); - - // Verify quota and RefcountedResource objects cleaned up - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); - try { - userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - - } - } - - @Test - public void testSecurityParameterIndexBinderDeath() throws Exception { - when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) - .thenReturn(TEST_SPI); - - IpSecSpiResponse spiResp = - mIpSecService.allocateSecurityParameterIndex( - mDestinationAddr, TEST_SPI, new Binder()); - - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - IpSecService.RefcountedResource refcountedRecord = - userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId); - - refcountedRecord.binderDied(); - - verify(mMockNetd) - .ipSecDeleteSecurityAssociation( - eq(mUid), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), - anyInt(), - anyInt()); - - // Verify quota and RefcountedResource objects cleaned up - assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); - try { - userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - - } - } - - private int getNewSpiResourceId(String remoteAddress, int returnSpi) throws Exception { - when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), anyString(), anyInt())) - .thenReturn(returnSpi); - - IpSecSpiResponse spi = - mIpSecService.allocateSecurityParameterIndex( - InetAddresses.parseNumericAddress(remoteAddress).getHostAddress(), - IpSecManager.INVALID_SECURITY_PARAMETER_INDEX, - new Binder()); - return spi.resourceId; - } - - private void addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config) throws Exception { - config.setSpiResourceId(getNewSpiResourceId(mDestinationAddr, TEST_SPI)); - config.setSourceAddress(mSourceAddr); - config.setDestinationAddress(mDestinationAddr); - } - - private void addAuthAndCryptToIpSecConfig(IpSecConfig config) throws Exception { - config.setEncryption(CRYPT_ALGO); - config.setAuthentication(AUTH_ALGO); - } - - private void addEncapSocketToIpSecConfig(int resourceId, IpSecConfig config) throws Exception { - config.setEncapType(IpSecTransform.ENCAP_ESPINUDP); - config.setEncapSocketResourceId(resourceId); - config.setEncapRemotePort(REMOTE_ENCAP_PORT); - } - - private void verifyTransformNetdCalledForCreatingSA( - IpSecConfig config, IpSecTransformResponse resp) throws Exception { - verifyTransformNetdCalledForCreatingSA(config, resp, 0); - } - - private void verifyTransformNetdCalledForCreatingSA( - IpSecConfig config, IpSecTransformResponse resp, int encapSocketPort) throws Exception { - IpSecAlgorithm auth = config.getAuthentication(); - IpSecAlgorithm crypt = config.getEncryption(); - IpSecAlgorithm authCrypt = config.getAuthenticatedEncryption(); - - verify(mMockNetd, times(1)) - .ipSecAddSecurityAssociation( - eq(mUid), - eq(config.getMode()), - eq(config.getSourceAddress()), - eq(config.getDestinationAddress()), - eq((config.getNetwork() != null) ? config.getNetwork().netId : 0), - eq(TEST_SPI), - eq(0), - eq(0), - eq((auth != null) ? auth.getName() : ""), - eq((auth != null) ? auth.getKey() : new byte[] {}), - eq((auth != null) ? auth.getTruncationLengthBits() : 0), - eq((crypt != null) ? crypt.getName() : ""), - eq((crypt != null) ? crypt.getKey() : new byte[] {}), - eq((crypt != null) ? crypt.getTruncationLengthBits() : 0), - eq((authCrypt != null) ? authCrypt.getName() : ""), - eq((authCrypt != null) ? authCrypt.getKey() : new byte[] {}), - eq((authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0), - eq(config.getEncapType()), - eq(encapSocketPort), - eq(config.getEncapRemotePort()), - eq(config.getXfrmInterfaceId())); - } - - @Test - public void testCreateTransform() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - assertEquals(IpSecManager.Status.OK, createTransformResp.status); - - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); - } - - @Test - public void testCreateTransformAead() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - - ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - assertEquals(IpSecManager.Status.OK, createTransformResp.status); - - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); - } - - @Test - public void testCreateTransportModeTransformWithEncap() throws Exception { - IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - - IpSecConfig ipSecConfig = new IpSecConfig(); - ipSecConfig.setMode(IpSecTransform.MODE_TRANSPORT); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig); - - if (mFamily == AF_INET) { - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - assertEquals(IpSecManager.Status.OK, createTransformResp.status); - - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); - } else { - try { - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); - } catch (IllegalArgumentException expected) { - } - } - } - - @Test - public void testCreateTunnelModeTransformWithEncap() throws Exception { - IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - - IpSecConfig ipSecConfig = new IpSecConfig(); - ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig); - - if (mFamily == AF_INET) { - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - assertEquals(IpSecManager.Status.OK, createTransformResp.status); - - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); - } else { - try { - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); - } catch (IllegalArgumentException expected) { - } - } - } - - @Test - public void testCreateTwoTransformsWithSameSpis() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - assertEquals(IpSecManager.Status.OK, createTransformResp.status); - - // Attempting to create transform a second time with the same SPIs should throw an error... - try { - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - fail("IpSecService should have thrown an error for reuse of SPI"); - } catch (IllegalStateException expected) { - } - - // ... even if the transform is deleted - mIpSecService.deleteTransform(createTransformResp.resourceId); - try { - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - fail("IpSecService should have thrown an error for reuse of SPI"); - } catch (IllegalStateException expected) { - } - } - - @Test - public void testReleaseOwnedSpi() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - verify(mMockNetd, times(0)) - .ipSecDeleteSecurityAssociation( - eq(mUid), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), - anyInt(), - anyInt()); - // quota is not released until the SPI is released by the Transform - assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); - } - - @Test - public void testDeleteTransform() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - mIpSecService.deleteTransform(createTransformResp.resourceId); - - verify(mMockNetd, times(1)) - .ipSecDeleteSecurityAssociation( - eq(mUid), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), - anyInt(), - anyInt()); - - // Verify quota and RefcountedResource objects cleaned up - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent); - assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); - - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - // Verify that ipSecDeleteSa was not called when the SPI was released because the - // ownedByTransform property should prevent it; (note, the called count is cumulative). - verify(mMockNetd, times(1)) - .ipSecDeleteSecurityAssociation( - anyInt(), - anyString(), - anyString(), - anyInt(), - anyInt(), - anyInt(), - anyInt()); - assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); - - try { - userRecord.mTransformRecords.getRefcountedResourceOrThrow( - createTransformResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - - } - } - - @Test - public void testTransportModeTransformBinderDeath() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - IpSecService.RefcountedResource refcountedRecord = - userRecord.mTransformRecords.getRefcountedResourceOrThrow( - createTransformResp.resourceId); - - refcountedRecord.binderDied(); - - verify(mMockNetd) - .ipSecDeleteSecurityAssociation( - eq(mUid), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), - anyInt(), - anyInt()); - - // Verify quota and RefcountedResource objects cleaned up - assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent); - try { - userRecord.mTransformRecords.getRefcountedResourceOrThrow( - createTransformResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - - } - } - - @Test - public void testApplyTransportModeTransform() throws Exception { - verifyApplyTransportModeTransformCommon(false); - } - - @Test - public void testApplyTransportModeTransformReleasedSpi() throws Exception { - verifyApplyTransportModeTransformCommon(true); - } - - public void verifyApplyTransportModeTransformCommon( - boolean closeSpiBeforeApply) throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - - if (closeSpiBeforeApply) { - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - } - - Socket socket = new Socket(); - socket.bind(null); - ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); - - int resourceId = createTransformResp.resourceId; - mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId); - - verify(mMockNetd) - .ipSecApplyTransportModeTransform( - eq(pfd), - eq(mUid), - eq(IpSecManager.DIRECTION_OUT), - anyString(), - anyString(), - eq(TEST_SPI)); - } - - @Test - public void testApplyTransportModeTransformWithClosedSpi() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - - // Close SPI record - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - - Socket socket = new Socket(); - socket.bind(null); - ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); - - int resourceId = createTransformResp.resourceId; - mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId); - - verify(mMockNetd) - .ipSecApplyTransportModeTransform( - eq(pfd), - eq(mUid), - eq(IpSecManager.DIRECTION_OUT), - anyString(), - anyString(), - eq(TEST_SPI)); - } - - @Test - public void testRemoveTransportModeTransform() throws Exception { - Socket socket = new Socket(); - socket.bind(null); - ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); - mIpSecService.removeTransportModeTransforms(pfd); - - verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd); - } - - private IpSecTunnelInterfaceResponse createAndValidateTunnel( - String localAddr, String remoteAddr, String pkgName) throws Exception { - final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel(); - config.flags = new String[] {IF_STATE_DOWN}; - when(mMockNetd.interfaceGetCfg(anyString())).thenReturn(config); - IpSecTunnelInterfaceResponse createTunnelResp = - mIpSecService.createTunnelInterface( - mSourceAddr, mDestinationAddr, fakeNetwork, new Binder(), pkgName); - - assertNotNull(createTunnelResp); - assertEquals(IpSecManager.Status.OK, createTunnelResp.status); - for (int direction : new int[] {DIRECTION_IN, DIRECTION_OUT, DIRECTION_FWD}) { - for (int selAddrFamily : ADDRESS_FAMILIES) { - verify(mMockNetd).ipSecAddSecurityPolicy( - eq(mUid), - eq(selAddrFamily), - eq(direction), - anyString(), - anyString(), - eq(0), - anyInt(), // iKey/oKey - anyInt(), // mask - eq(createTunnelResp.resourceId)); - } - } - - return createTunnelResp; - } - - @Test - public void testCreateTunnelInterface() throws Exception { - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - - // Check that we have stored the tracking object, and retrieve it - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - IpSecService.RefcountedResource refcountedRecord = - userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( - createTunnelResp.resourceId); - - assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent); - verify(mMockNetd) - .ipSecAddTunnelInterface( - eq(createTunnelResp.interfaceName), - eq(mSourceAddr), - eq(mDestinationAddr), - anyInt(), - anyInt(), - anyInt()); - verify(mMockNetd).interfaceSetCfg(argThat( - config -> Arrays.asList(config.flags).contains(IF_STATE_UP))); - } - - @Test - public void testDeleteTunnelInterface() throws Exception { - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - - mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, BLESSED_PACKAGE); - - // Verify quota and RefcountedResource objects cleaned up - assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); - verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName)); - try { - userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( - createTunnelResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - } - } - - private Network createFakeUnderlyingNetwork(String interfaceName) { - final Network fakeNetwork = new Network(1000); - final LinkProperties fakeLp = new LinkProperties(); - fakeLp.setInterfaceName(interfaceName); - when(mMockConnectivityMgr.getLinkProperties(eq(fakeNetwork))).thenReturn(fakeLp); - return fakeNetwork; - } - - @Test - public void testSetNetworkForTunnelInterface() throws Exception { - final IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - final Network newFakeNetwork = createFakeUnderlyingNetwork("newFakeNetworkInterface"); - final int tunnelIfaceResourceId = createTunnelResp.resourceId; - mIpSecService.setNetworkForTunnelInterface( - tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE); - - final IpSecService.UserRecord userRecord = - mIpSecService.mUserResourceTracker.getUserRecord(mUid); - assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent); - - final TunnelInterfaceRecord tunnelInterfaceInfo = - userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelIfaceResourceId); - assertEquals(newFakeNetwork, tunnelInterfaceInfo.getUnderlyingNetwork()); - } - - @Test - public void testSetNetworkForTunnelInterfaceFailsForInvalidResourceId() throws Exception { - final IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - final Network newFakeNetwork = new Network(1000); - - try { - mIpSecService.setNetworkForTunnelInterface( - IpSecManager.INVALID_RESOURCE_ID, newFakeNetwork, BLESSED_PACKAGE); - fail("Expected an IllegalArgumentException for invalid resource ID."); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testSetNetworkForTunnelInterfaceFailsWhenSettingTunnelNetwork() throws Exception { - final IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - final int tunnelIfaceResourceId = createTunnelResp.resourceId; - final IpSecService.UserRecord userRecord = - mIpSecService.mUserResourceTracker.getUserRecord(mUid); - final TunnelInterfaceRecord tunnelInterfaceInfo = - userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelIfaceResourceId); - - final Network newFakeNetwork = - createFakeUnderlyingNetwork(tunnelInterfaceInfo.getInterfaceName()); - - try { - mIpSecService.setNetworkForTunnelInterface( - tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE); - fail( - "Expected an IllegalArgumentException because the underlying network is the" - + " network being exposed by this tunnel."); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testTunnelInterfaceBinderDeath() throws Exception { - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - IpSecService.RefcountedResource refcountedRecord = - userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( - createTunnelResp.resourceId); - - refcountedRecord.binderDied(); - - // Verify quota and RefcountedResource objects cleaned up - assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); - verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName)); - try { - userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( - createTunnelResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testApplyTunnelModeTransformOutbound() throws Exception { - verifyApplyTunnelModeTransformCommon(false /* closeSpiBeforeApply */, DIRECTION_OUT); - } - - @Test - public void testApplyTunnelModeTransformOutboundNonNetworkStack() throws Exception { - mTestContext.setAllowedPermissions(android.Manifest.permission.MANAGE_IPSEC_TUNNELS); - verifyApplyTunnelModeTransformCommon(false /* closeSpiBeforeApply */, DIRECTION_OUT); - } - - @Test - public void testApplyTunnelModeTransformOutboundReleasedSpi() throws Exception { - verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_OUT); - } - - @Test - public void testApplyTunnelModeTransformInbound() throws Exception { - verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_IN); - } - - @Test - public void testApplyTunnelModeTransformInboundNonNetworkStack() throws Exception { - mTestContext.setAllowedPermissions(android.Manifest.permission.MANAGE_IPSEC_TUNNELS); - verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_IN); - } - - @Test - public void testApplyTunnelModeTransformForward() throws Exception { - verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_FWD); - } - - @Test - public void testApplyTunnelModeTransformForwardNonNetworkStack() throws Exception { - mTestContext.setAllowedPermissions(android.Manifest.permission.MANAGE_IPSEC_TUNNELS); - - try { - verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_FWD); - fail("Expected security exception due to use of forward policies without NETWORK_STACK" - + " or MAINLINE_NETWORK_STACK permission"); - } catch (SecurityException expected) { - } - } - - public void verifyApplyTunnelModeTransformCommon(boolean closeSpiBeforeApply, int direction) - throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - - if (closeSpiBeforeApply) { - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - } - - int transformResourceId = createTransformResp.resourceId; - int tunnelResourceId = createTunnelResp.resourceId; - mIpSecService.applyTunnelModeTransform( - tunnelResourceId, direction, transformResourceId, BLESSED_PACKAGE); - - for (int selAddrFamily : ADDRESS_FAMILIES) { - verify(mMockNetd) - .ipSecUpdateSecurityPolicy( - eq(mUid), - eq(selAddrFamily), - eq(direction), - anyString(), - anyString(), - eq(direction == DIRECTION_OUT ? TEST_SPI : 0), - anyInt(), // iKey/oKey - anyInt(), // mask - eq(tunnelResourceId)); - } - - ipSecConfig.setXfrmInterfaceId(tunnelResourceId); - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); - } - - - @Test - public void testApplyTunnelModeTransformWithClosedSpi() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - - // Close SPI record - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - - int transformResourceId = createTransformResp.resourceId; - int tunnelResourceId = createTunnelResp.resourceId; - mIpSecService.applyTunnelModeTransform( - tunnelResourceId, IpSecManager.DIRECTION_OUT, transformResourceId, BLESSED_PACKAGE); - - for (int selAddrFamily : ADDRESS_FAMILIES) { - verify(mMockNetd) - .ipSecUpdateSecurityPolicy( - eq(mUid), - eq(selAddrFamily), - eq(IpSecManager.DIRECTION_OUT), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), // iKey/oKey - anyInt(), // mask - eq(tunnelResourceId)); - } - - ipSecConfig.setXfrmInterfaceId(tunnelResourceId); - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); - } - - @Test - public void testAddRemoveAddressFromTunnelInterface() throws Exception { - for (String pkgName : new String[] {BLESSED_PACKAGE, SYSTEM_PACKAGE}) { - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, pkgName); - mIpSecService.addAddressToTunnelInterface( - createTunnelResp.resourceId, mLocalInnerAddress, pkgName); - verify(mMockNetd, times(1)) - .interfaceAddAddress( - eq(createTunnelResp.interfaceName), - eq(mLocalInnerAddress.getAddress().getHostAddress()), - eq(mLocalInnerAddress.getPrefixLength())); - mIpSecService.removeAddressFromTunnelInterface( - createTunnelResp.resourceId, mLocalInnerAddress, pkgName); - verify(mMockNetd, times(1)) - .interfaceDelAddress( - eq(createTunnelResp.interfaceName), - eq(mLocalInnerAddress.getAddress().getHostAddress()), - eq(mLocalInnerAddress.getPrefixLength())); - mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, pkgName); - } - } - - @Ignore - @Test - public void testAddTunnelFailsForBadPackageName() throws Exception { - try { - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BAD_PACKAGE); - fail("Expected a SecurityException for badPackage."); - } catch (SecurityException expected) { - } - } - - @Test - public void testFeatureFlagVerification() throws Exception { - when(mMockPkgMgr.hasSystemFeature(eq(PackageManager.FEATURE_IPSEC_TUNNELS))) - .thenReturn(false); - - try { - String addr = Inet4Address.getLoopbackAddress().getHostAddress(); - mIpSecService.createTunnelInterface( - addr, addr, new Network(0), new Binder(), BLESSED_PACKAGE); - fail("Expected UnsupportedOperationException for disabled feature"); - } catch (UnsupportedOperationException expected) { - } - } -} |