blob: 9b919abfa41d57b68ab320140fe81ea6ef759d09 [file] [log] [blame]
Nathan Harold2e9a5202017-09-26 11:44:23 -07001/*
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
17package com.android.server;
18
evitayane4259d32018-03-22 17:53:08 -070019import static android.system.OsConstants.AF_INET;
20import static android.system.OsConstants.AF_INET6;
Nathan Harold2e9a5202017-09-26 11:44:23 -070021import static org.junit.Assert.assertEquals;
Benedict Wongecc9f7c2018-03-01 18:53:07 -080022import static org.junit.Assert.assertNotNull;
Benedict Wong0febe5e2017-08-22 21:42:33 -070023import static org.junit.Assert.fail;
Nathan Harold2e9a5202017-09-26 11:44:23 -070024import static org.mockito.Matchers.anyInt;
Nathan Harold2e9a5202017-09-26 11:44:23 -070025import static org.mockito.Matchers.anyString;
26import static org.mockito.Matchers.eq;
27import static org.mockito.Mockito.mock;
Nathan Harold22795302018-02-27 19:19:40 -080028import static org.mockito.Mockito.times;
Nathan Harold2e9a5202017-09-26 11:44:23 -070029import static org.mockito.Mockito.verify;
30import static org.mockito.Mockito.when;
31
Nathan Harold21208ee2018-03-15 18:06:06 -070032import android.app.AppOpsManager;
Nathan Harold2e9a5202017-09-26 11:44:23 -070033import android.content.Context;
34import android.net.INetd;
35import android.net.IpSecAlgorithm;
36import android.net.IpSecConfig;
37import android.net.IpSecManager;
38import android.net.IpSecSpiResponse;
evitayan0a7d3e32018-03-22 13:42:07 -070039import android.net.IpSecTransform;
Nathan Harold2e9a5202017-09-26 11:44:23 -070040import android.net.IpSecTransformResponse;
Benedict Wongecc9f7c2018-03-01 18:53:07 -080041import android.net.IpSecTunnelInterfaceResponse;
evitayan0a7d3e32018-03-22 13:42:07 -070042import android.net.IpSecUdpEncapResponse;
Benedict Wongecc9f7c2018-03-01 18:53:07 -080043import android.net.LinkAddress;
44import android.net.Network;
Nathan Harold2e9a5202017-09-26 11:44:23 -070045import android.net.NetworkUtils;
46import android.os.Binder;
47import android.os.ParcelFileDescriptor;
48import android.support.test.filters.SmallTest;
Benedict Wong344bd622017-11-16 15:27:22 -080049import android.system.Os;
Benedict Wonga0989622018-07-25 13:06:29 -070050import android.test.mock.MockContext;
Nathan Harold2e9a5202017-09-26 11:44:23 -070051
52import java.net.Socket;
53import java.util.Arrays;
54import java.util.Collection;
55
56import org.junit.Before;
Nathan Harold8c69bcb2018-05-15 19:18:38 -070057import org.junit.Ignore;
Nathan Harold2e9a5202017-09-26 11:44:23 -070058import org.junit.Test;
59import org.junit.runner.RunWith;
60import org.junit.runners.Parameterized;
61
62/** Unit tests for {@link IpSecService}. */
63@SmallTest
64@RunWith(Parameterized.class)
65public class IpSecServiceParameterizedTest {
66
Nathan Harolda2523312018-01-05 19:25:13 -080067 private static final int TEST_SPI = 0xD1201D;
Nathan Harold2e9a5202017-09-26 11:44:23 -070068
Nathan Harold5676f5f2018-01-16 19:34:01 -080069 private final String mSourceAddr;
evitayane4259d32018-03-22 17:53:08 -070070 private final String mDestinationAddr;
Benedict Wongecc9f7c2018-03-01 18:53:07 -080071 private final LinkAddress mLocalInnerAddress;
evitayane4259d32018-03-22 17:53:08 -070072 private final int mFamily;
Nathan Harold2e9a5202017-09-26 11:44:23 -070073
74 @Parameterized.Parameters
75 public static Collection ipSecConfigs() {
Benedict Wongecc9f7c2018-03-01 18:53:07 -080076 return Arrays.asList(
77 new Object[][] {
evitayane4259d32018-03-22 17:53:08 -070078 {"1.2.3.4", "8.8.4.4", "10.0.1.1/24", AF_INET},
79 {"2601::2", "2601::10", "2001:db8::1/64", AF_INET6}
Benedict Wongecc9f7c2018-03-01 18:53:07 -080080 });
Nathan Harold2e9a5202017-09-26 11:44:23 -070081 }
82
Benedict Wong4ebc2c52017-11-01 17:14:25 -070083 private static final byte[] AEAD_KEY = {
84 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
85 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
86 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
87 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
88 0x73, 0x61, 0x6C, 0x74
89 };
Nathan Harold2e9a5202017-09-26 11:44:23 -070090 private static final byte[] CRYPT_KEY = {
91 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
92 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
93 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
94 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
95 };
96 private static final byte[] AUTH_KEY = {
97 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
99 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
101 };
102
Nathan Harold21208ee2018-03-15 18:06:06 -0700103 AppOpsManager mMockAppOps = mock(AppOpsManager.class);
104
105 MockContext mMockContext = new MockContext() {
106 @Override
107 public Object getSystemService(String name) {
108 switch(name) {
109 case Context.APP_OPS_SERVICE:
110 return mMockAppOps;
111 default:
112 return null;
113 }
114 }
115
116 @Override
117 public void enforceCallingOrSelfPermission(String permission, String message) {
118 if (permission == android.Manifest.permission.MANAGE_IPSEC_TUNNELS) {
119 return;
120 }
121 throw new SecurityException("Unavailable permission requested");
122 }
123 };
124
Nathan Harold2e9a5202017-09-26 11:44:23 -0700125 INetd mMockNetd;
126 IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
127 IpSecService mIpSecService;
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800128 Network fakeNetwork = new Network(0xAB);
Benedict Wonga0989622018-07-25 13:06:29 -0700129 int mUid = Os.getuid();
Nathan Harold2e9a5202017-09-26 11:44:23 -0700130
Benedict Wong0febe5e2017-08-22 21:42:33 -0700131 private static final IpSecAlgorithm AUTH_ALGO =
132 new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
133 private static final IpSecAlgorithm CRYPT_ALGO =
134 new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
135 private static final IpSecAlgorithm AEAD_ALGO =
Benedict Wong4ebc2c52017-11-01 17:14:25 -0700136 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
evitayan0a7d3e32018-03-22 13:42:07 -0700137 private static final int REMOTE_ENCAP_PORT = 4500;
Benedict Wong0febe5e2017-08-22 21:42:33 -0700138
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800139 public IpSecServiceParameterizedTest(
evitayane4259d32018-03-22 17:53:08 -0700140 String sourceAddr, String destAddr, String localInnerAddr, int family) {
Nathan Harold5676f5f2018-01-16 19:34:01 -0800141 mSourceAddr = sourceAddr;
142 mDestinationAddr = destAddr;
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800143 mLocalInnerAddress = new LinkAddress(localInnerAddr);
evitayane4259d32018-03-22 17:53:08 -0700144 mFamily = family;
Nathan Harold2e9a5202017-09-26 11:44:23 -0700145 }
146
147 @Before
148 public void setUp() throws Exception {
Nathan Harold2e9a5202017-09-26 11:44:23 -0700149 mMockNetd = mock(INetd.class);
150 mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
151 mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
152
153 // Injecting mock netd
154 when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
Nathan Harold21208ee2018-03-15 18:06:06 -0700155 // A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED.
156 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("blessedPackage")))
157 .thenReturn(AppOpsManager.MODE_ALLOWED);
158 // A system package will not be granted the app op, so this should fall back to
159 // a permissions check, which should pass.
160 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("systemPackage")))
161 .thenReturn(AppOpsManager.MODE_DEFAULT);
162 // A mismatch between the package name and the UID will return MODE_IGNORED.
163 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("badPackage")))
164 .thenReturn(AppOpsManager.MODE_IGNORED);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700165 }
166
evitayan0a7d3e32018-03-22 13:42:07 -0700167 //TODO: Add a test to verify SPI.
168
Nathan Harold2e9a5202017-09-26 11:44:23 -0700169 @Test
170 public void testIpSecServiceReserveSpi() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800171 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
172 .thenReturn(TEST_SPI);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700173
174 IpSecSpiResponse spiResp =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800175 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800176 mDestinationAddr, TEST_SPI, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700177 assertEquals(IpSecManager.Status.OK, spiResp.status);
Nathan Harolda2523312018-01-05 19:25:13 -0800178 assertEquals(TEST_SPI, spiResp.spi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700179 }
180
181 @Test
182 public void testReleaseSecurityParameterIndex() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800183 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
184 .thenReturn(TEST_SPI);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700185
186 IpSecSpiResponse spiResp =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800187 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800188 mDestinationAddr, TEST_SPI, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700189
190 mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
191
192 verify(mMockNetd)
193 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700194 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800195 anyString(),
196 anyString(),
197 eq(TEST_SPI),
198 anyInt(),
199 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800200
201 // Verify quota and RefcountedResource objects cleaned up
Benedict Wonga0989622018-07-25 13:06:29 -0700202 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800203 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
204 try {
205 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
206 fail("Expected IllegalArgumentException on attempt to access deleted resource");
207 } catch (IllegalArgumentException expected) {
208
209 }
210 }
211
212 @Test
213 public void testSecurityParameterIndexBinderDeath() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800214 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
215 .thenReturn(TEST_SPI);
Benedict Wong344bd622017-11-16 15:27:22 -0800216
217 IpSecSpiResponse spiResp =
Nathan Harold660a3352017-12-14 14:46:46 -0800218 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800219 mDestinationAddr, TEST_SPI, new Binder());
Benedict Wong344bd622017-11-16 15:27:22 -0800220
Benedict Wonga0989622018-07-25 13:06:29 -0700221 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800222 IpSecService.RefcountedResource refcountedRecord =
223 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
224
225 refcountedRecord.binderDied();
226
227 verify(mMockNetd)
228 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700229 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800230 anyString(),
231 anyString(),
232 eq(TEST_SPI),
233 anyInt(),
234 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800235
236 // Verify quota and RefcountedResource objects cleaned up
237 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
238 try {
239 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
240 fail("Expected IllegalArgumentException on attempt to access deleted resource");
241 } catch (IllegalArgumentException expected) {
242
243 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700244 }
245
Nathan Harolda2523312018-01-05 19:25:13 -0800246 private int getNewSpiResourceId(String remoteAddress, int returnSpi) throws Exception {
247 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), anyString(), anyInt()))
Benedict Wong0febe5e2017-08-22 21:42:33 -0700248 .thenReturn(returnSpi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700249
Benedict Wong0febe5e2017-08-22 21:42:33 -0700250 IpSecSpiResponse spi =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800251 mIpSecService.allocateSecurityParameterIndex(
Benedict Wong0febe5e2017-08-22 21:42:33 -0700252 NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(),
253 IpSecManager.INVALID_SECURITY_PARAMETER_INDEX,
254 new Binder());
255 return spi.resourceId;
256 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700257
Benedict Wong0febe5e2017-08-22 21:42:33 -0700258 private void addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config) throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800259 config.setSpiResourceId(getNewSpiResourceId(mDestinationAddr, TEST_SPI));
Nathan Harold5676f5f2018-01-16 19:34:01 -0800260 config.setSourceAddress(mSourceAddr);
Nathan Harolda2523312018-01-05 19:25:13 -0800261 config.setDestinationAddress(mDestinationAddr);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700262 }
263
264 private void addAuthAndCryptToIpSecConfig(IpSecConfig config) throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800265 config.setEncryption(CRYPT_ALGO);
266 config.setAuthentication(AUTH_ALGO);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700267 }
268
evitayan0a7d3e32018-03-22 13:42:07 -0700269 private void addEncapSocketToIpSecConfig(int resourceId, IpSecConfig config) throws Exception {
270 config.setEncapType(IpSecTransform.ENCAP_ESPINUDP);
271 config.setEncapSocketResourceId(resourceId);
272 config.setEncapRemotePort(REMOTE_ENCAP_PORT);
273 }
274
275 private void verifyTransformNetdCalledForCreatingSA(
276 IpSecConfig config, IpSecTransformResponse resp) throws Exception {
277 verifyTransformNetdCalledForCreatingSA(config, resp, 0);
278 }
279
280 private void verifyTransformNetdCalledForCreatingSA(
281 IpSecConfig config, IpSecTransformResponse resp, int encapSocketPort) throws Exception {
282 IpSecAlgorithm auth = config.getAuthentication();
283 IpSecAlgorithm crypt = config.getEncryption();
284 IpSecAlgorithm authCrypt = config.getAuthenticatedEncryption();
285
286 verify(mMockNetd, times(1))
287 .ipSecAddSecurityAssociation(
288 eq(mUid),
289 eq(config.getMode()),
290 eq(config.getSourceAddress()),
291 eq(config.getDestinationAddress()),
292 eq((config.getNetwork() != null) ? config.getNetwork().netId : 0),
293 eq(TEST_SPI),
294 eq(0),
295 eq(0),
296 eq((auth != null) ? auth.getName() : ""),
297 eq((auth != null) ? auth.getKey() : new byte[] {}),
298 eq((auth != null) ? auth.getTruncationLengthBits() : 0),
299 eq((crypt != null) ? crypt.getName() : ""),
300 eq((crypt != null) ? crypt.getKey() : new byte[] {}),
301 eq((crypt != null) ? crypt.getTruncationLengthBits() : 0),
302 eq((authCrypt != null) ? authCrypt.getName() : ""),
303 eq((authCrypt != null) ? authCrypt.getKey() : new byte[] {}),
304 eq((authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0),
305 eq(config.getEncapType()),
306 eq(encapSocketPort),
307 eq(config.getEncapRemotePort()));
308 }
309
Nathan Harold2e9a5202017-09-26 11:44:23 -0700310 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800311 public void testCreateTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700312 IpSecConfig ipSecConfig = new IpSecConfig();
313 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
314 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700315
316 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700317 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Nathan Harold2e9a5202017-09-26 11:44:23 -0700318 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
319
evitayan0a7d3e32018-03-22 13:42:07 -0700320 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700321 }
322
323 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800324 public void testCreateTransformAead() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700325 IpSecConfig ipSecConfig = new IpSecConfig();
326 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
327
Nathan Harolda2523312018-01-05 19:25:13 -0800328 ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700329
330 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700331 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wong0febe5e2017-08-22 21:42:33 -0700332 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
333
evitayan0a7d3e32018-03-22 13:42:07 -0700334 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
335 }
336
337 @Test
338 public void testCreateTransportModeTransformWithEncap() throws Exception {
339 IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder());
340
341 IpSecConfig ipSecConfig = new IpSecConfig();
342 ipSecConfig.setMode(IpSecTransform.MODE_TRANSPORT);
343 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
344 addAuthAndCryptToIpSecConfig(ipSecConfig);
345 addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig);
346
evitayane4259d32018-03-22 17:53:08 -0700347 if (mFamily == AF_INET) {
348 IpSecTransformResponse createTransformResp =
349 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
350 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
evitayan0a7d3e32018-03-22 13:42:07 -0700351
evitayane4259d32018-03-22 17:53:08 -0700352 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
353 } else {
354 try {
355 IpSecTransformResponse createTransformResp =
356 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
357 fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
358 } catch (IllegalArgumentException expected) {
359 }
360 }
evitayan0a7d3e32018-03-22 13:42:07 -0700361 }
362
363 @Test
364 public void testCreateTunnelModeTransformWithEncap() throws Exception {
365 IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder());
366
367 IpSecConfig ipSecConfig = new IpSecConfig();
368 ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL);
369 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
370 addAuthAndCryptToIpSecConfig(ipSecConfig);
371 addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig);
372
evitayane4259d32018-03-22 17:53:08 -0700373 if (mFamily == AF_INET) {
374 IpSecTransformResponse createTransformResp =
375 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
376 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
evitayan0a7d3e32018-03-22 13:42:07 -0700377
evitayane4259d32018-03-22 17:53:08 -0700378 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
379 } else {
380 try {
381 IpSecTransformResponse createTransformResp =
382 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
383 fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
384 } catch (IllegalArgumentException expected) {
385 }
386 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700387 }
388
Andreas Gampea7b26b52018-02-26 08:06:30 -0800389 @Test
Benedict Wonge6b42772017-12-13 18:26:40 -0800390 public void testCreateTwoTransformsWithSameSpis() throws Exception {
391 IpSecConfig ipSecConfig = new IpSecConfig();
392 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
393 addAuthAndCryptToIpSecConfig(ipSecConfig);
394
395 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700396 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonge6b42772017-12-13 18:26:40 -0800397 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
398
399 // Attempting to create transform a second time with the same SPIs should throw an error...
400 try {
Nathan Harold21208ee2018-03-15 18:06:06 -0700401 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonge6b42772017-12-13 18:26:40 -0800402 fail("IpSecService should have thrown an error for reuse of SPI");
403 } catch (IllegalStateException expected) {
404 }
405
406 // ... even if the transform is deleted
407 mIpSecService.deleteTransform(createTransformResp.resourceId);
408 try {
Nathan Harold21208ee2018-03-15 18:06:06 -0700409 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonge6b42772017-12-13 18:26:40 -0800410 fail("IpSecService should have thrown an error for reuse of SPI");
411 } catch (IllegalStateException expected) {
412 }
413 }
414
Nathan Harold2e9a5202017-09-26 11:44:23 -0700415 @Test
Nathan Harold22795302018-02-27 19:19:40 -0800416 public void testReleaseOwnedSpi() throws Exception {
417 IpSecConfig ipSecConfig = new IpSecConfig();
418 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
419 addAuthAndCryptToIpSecConfig(ipSecConfig);
420
421 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700422 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonga0989622018-07-25 13:06:29 -0700423 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Nathan Harold22795302018-02-27 19:19:40 -0800424 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
425 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
426 verify(mMockNetd, times(0))
427 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700428 eq(mUid),
Nathan Harold22795302018-02-27 19:19:40 -0800429 anyString(),
430 anyString(),
431 eq(TEST_SPI),
432 anyInt(),
433 anyInt());
434 // quota is not released until the SPI is released by the Transform
435 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
436 }
437
438 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800439 public void testDeleteTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700440 IpSecConfig ipSecConfig = new IpSecConfig();
441 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
442 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700443
444 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700445 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wongf33f03132018-01-18 14:38:16 -0800446 mIpSecService.deleteTransform(createTransformResp.resourceId);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700447
Nathan Harold22795302018-02-27 19:19:40 -0800448 verify(mMockNetd, times(1))
Nathan Harold2e9a5202017-09-26 11:44:23 -0700449 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700450 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800451 anyString(),
452 anyString(),
453 eq(TEST_SPI),
454 anyInt(),
455 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800456
457 // Verify quota and RefcountedResource objects cleaned up
Benedict Wonga0989622018-07-25 13:06:29 -0700458 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800459 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
Nathan Harold22795302018-02-27 19:19:40 -0800460 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
461
462 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
463 // Verify that ipSecDeleteSa was not called when the SPI was released because the
464 // ownedByTransform property should prevent it; (note, the called count is cumulative).
465 verify(mMockNetd, times(1))
466 .ipSecDeleteSecurityAssociation(
467 anyInt(),
468 anyString(),
469 anyString(),
470 anyInt(),
471 anyInt(),
472 anyInt());
473 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
474
Benedict Wong344bd622017-11-16 15:27:22 -0800475 try {
476 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
477 createTransformResp.resourceId);
478 fail("Expected IllegalArgumentException on attempt to access deleted resource");
479 } catch (IllegalArgumentException expected) {
480
481 }
482 }
483
484 @Test
485 public void testTransportModeTransformBinderDeath() throws Exception {
486 IpSecConfig ipSecConfig = new IpSecConfig();
487 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
488 addAuthAndCryptToIpSecConfig(ipSecConfig);
489
490 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700491 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wong344bd622017-11-16 15:27:22 -0800492
Benedict Wonga0989622018-07-25 13:06:29 -0700493 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800494 IpSecService.RefcountedResource refcountedRecord =
495 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
496 createTransformResp.resourceId);
497
498 refcountedRecord.binderDied();
499
500 verify(mMockNetd)
501 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700502 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800503 anyString(),
504 anyString(),
505 eq(TEST_SPI),
506 anyInt(),
507 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800508
509 // Verify quota and RefcountedResource objects cleaned up
510 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
511 try {
512 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
513 createTransformResp.resourceId);
514 fail("Expected IllegalArgumentException on attempt to access deleted resource");
515 } catch (IllegalArgumentException expected) {
516
517 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700518 }
519
520 @Test
521 public void testApplyTransportModeTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700522 IpSecConfig ipSecConfig = new IpSecConfig();
523 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
524 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700525
526 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700527 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Nathan Harold2e9a5202017-09-26 11:44:23 -0700528 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
529
530 int resourceId = createTransformResp.resourceId;
Nathan Harolda2523312018-01-05 19:25:13 -0800531 mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700532
533 verify(mMockNetd)
534 .ipSecApplyTransportModeTransform(
535 eq(pfd.getFileDescriptor()),
Benedict Wonga0989622018-07-25 13:06:29 -0700536 eq(mUid),
Nathan Harolda2523312018-01-05 19:25:13 -0800537 eq(IpSecManager.DIRECTION_OUT),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700538 anyString(),
539 anyString(),
Nathan Harolda2523312018-01-05 19:25:13 -0800540 eq(TEST_SPI));
Nathan Harold2e9a5202017-09-26 11:44:23 -0700541 }
542
543 @Test
544 public void testRemoveTransportModeTransform() throws Exception {
545 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
Nathan Haroldf73d2522018-01-17 01:00:20 -0800546 mIpSecService.removeTransportModeTransforms(pfd);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700547
548 verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
549 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800550
551 private IpSecTunnelInterfaceResponse createAndValidateTunnel(
Nathan Harold21208ee2018-03-15 18:06:06 -0700552 String localAddr, String remoteAddr, String pkgName) {
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800553 IpSecTunnelInterfaceResponse createTunnelResp =
554 mIpSecService.createTunnelInterface(
Nathan Harold21208ee2018-03-15 18:06:06 -0700555 mSourceAddr, mDestinationAddr, fakeNetwork, new Binder(), pkgName);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800556
557 assertNotNull(createTunnelResp);
558 assertEquals(IpSecManager.Status.OK, createTunnelResp.status);
559 return createTunnelResp;
560 }
561
562 @Test
563 public void testCreateTunnelInterface() throws Exception {
564 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700565 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800566
567 // Check that we have stored the tracking object, and retrieve it
Benedict Wonga0989622018-07-25 13:06:29 -0700568 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800569 IpSecService.RefcountedResource refcountedRecord =
570 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
571 createTunnelResp.resourceId);
572
573 assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent);
574 verify(mMockNetd)
575 .addVirtualTunnelInterface(
576 eq(createTunnelResp.interfaceName),
577 eq(mSourceAddr),
578 eq(mDestinationAddr),
579 anyInt(),
580 anyInt());
581 }
582
583 @Test
584 public void testDeleteTunnelInterface() throws Exception {
585 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700586 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800587
Benedict Wonga0989622018-07-25 13:06:29 -0700588 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800589
Nathan Harold21208ee2018-03-15 18:06:06 -0700590 mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800591
592 // Verify quota and RefcountedResource objects cleaned up
593 assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
594 verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName));
595 try {
596 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
597 createTunnelResp.resourceId);
598 fail("Expected IllegalArgumentException on attempt to access deleted resource");
599 } catch (IllegalArgumentException expected) {
600 }
601 }
602
603 @Test
604 public void testTunnelInterfaceBinderDeath() throws Exception {
605 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700606 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800607
Benedict Wonga0989622018-07-25 13:06:29 -0700608 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800609 IpSecService.RefcountedResource refcountedRecord =
610 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
611 createTunnelResp.resourceId);
612
613 refcountedRecord.binderDied();
614
615 // Verify quota and RefcountedResource objects cleaned up
616 assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
617 verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName));
618 try {
619 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
620 createTunnelResp.resourceId);
621 fail("Expected IllegalArgumentException on attempt to access deleted resource");
622 } catch (IllegalArgumentException expected) {
623 }
624 }
625
626 @Test
627 public void testAddRemoveAddressFromTunnelInterface() throws Exception {
Nathan Harold21208ee2018-03-15 18:06:06 -0700628 for (String pkgName : new String[]{"blessedPackage", "systemPackage"}) {
629 IpSecTunnelInterfaceResponse createTunnelResp =
630 createAndValidateTunnel(mSourceAddr, mDestinationAddr, pkgName);
631 mIpSecService.addAddressToTunnelInterface(
632 createTunnelResp.resourceId, mLocalInnerAddress, pkgName);
633 verify(mMockNetd, times(1))
634 .interfaceAddAddress(
635 eq(createTunnelResp.interfaceName),
636 eq(mLocalInnerAddress.getAddress().getHostAddress()),
637 eq(mLocalInnerAddress.getPrefixLength()));
638 mIpSecService.removeAddressFromTunnelInterface(
639 createTunnelResp.resourceId, mLocalInnerAddress, pkgName);
640 verify(mMockNetd, times(1))
641 .interfaceDelAddress(
642 eq(createTunnelResp.interfaceName),
643 eq(mLocalInnerAddress.getAddress().getHostAddress()),
644 eq(mLocalInnerAddress.getPrefixLength()));
645 mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, pkgName);
646 }
647 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800648
Nathan Harold8c69bcb2018-05-15 19:18:38 -0700649 @Ignore
Nathan Harold21208ee2018-03-15 18:06:06 -0700650 @Test
651 public void testAddTunnelFailsForBadPackageName() throws Exception {
652 try {
653 IpSecTunnelInterfaceResponse createTunnelResp =
654 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "badPackage");
655 fail("Expected a SecurityException for badPackage.");
656 } catch (SecurityException expected) {
657 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800658 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700659}