blob: 102cb7c77055ecca08ea123b6e8cfd05233f9120 [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
19import static org.junit.Assert.assertEquals;
Benedict Wongecc9f7c2018-03-01 18:53:07 -080020import static org.junit.Assert.assertNotNull;
Benedict Wong0febe5e2017-08-22 21:42:33 -070021import static org.junit.Assert.fail;
Nathan Harold2e9a5202017-09-26 11:44:23 -070022import static org.mockito.Matchers.anyInt;
Nathan Harold2e9a5202017-09-26 11:44:23 -070023import static org.mockito.Matchers.anyString;
24import static org.mockito.Matchers.eq;
25import static org.mockito.Mockito.mock;
Nathan Harold22795302018-02-27 19:19:40 -080026import static org.mockito.Mockito.times;
Nathan Harold2e9a5202017-09-26 11:44:23 -070027import static org.mockito.Mockito.verify;
28import static org.mockito.Mockito.when;
29
Nathan Harold21208ee2018-03-15 18:06:06 -070030import android.app.AppOpsManager;
Nathan Harold2e9a5202017-09-26 11:44:23 -070031import android.content.Context;
32import android.net.INetd;
33import android.net.IpSecAlgorithm;
34import android.net.IpSecConfig;
35import android.net.IpSecManager;
36import android.net.IpSecSpiResponse;
Nathan Harold2e9a5202017-09-26 11:44:23 -070037import android.net.IpSecTransformResponse;
Benedict Wongecc9f7c2018-03-01 18:53:07 -080038import android.net.IpSecTunnelInterfaceResponse;
39import android.net.LinkAddress;
40import android.net.Network;
Nathan Harold2e9a5202017-09-26 11:44:23 -070041import android.net.NetworkUtils;
42import android.os.Binder;
43import android.os.ParcelFileDescriptor;
Nathan Harold21208ee2018-03-15 18:06:06 -070044import android.test.mock.MockContext;
Nathan Harold2e9a5202017-09-26 11:44:23 -070045import android.support.test.filters.SmallTest;
Benedict Wong344bd622017-11-16 15:27:22 -080046import android.system.Os;
Nathan Harold2e9a5202017-09-26 11:44:23 -070047
48import java.net.Socket;
49import java.util.Arrays;
50import java.util.Collection;
51
52import org.junit.Before;
Nathan Harold8c69bcb2018-05-15 19:18:38 -070053import org.junit.Ignore;
Nathan Harold2e9a5202017-09-26 11:44:23 -070054import org.junit.Test;
55import org.junit.runner.RunWith;
56import org.junit.runners.Parameterized;
57
58/** Unit tests for {@link IpSecService}. */
59@SmallTest
60@RunWith(Parameterized.class)
61public class IpSecServiceParameterizedTest {
62
Nathan Harolda2523312018-01-05 19:25:13 -080063 private static final int TEST_SPI = 0xD1201D;
Nathan Harold2e9a5202017-09-26 11:44:23 -070064
Nathan Harolda2523312018-01-05 19:25:13 -080065 private final String mDestinationAddr;
Nathan Harold5676f5f2018-01-16 19:34:01 -080066 private final String mSourceAddr;
Benedict Wongecc9f7c2018-03-01 18:53:07 -080067 private final LinkAddress mLocalInnerAddress;
Nathan Harold2e9a5202017-09-26 11:44:23 -070068
69 @Parameterized.Parameters
70 public static Collection ipSecConfigs() {
Benedict Wongecc9f7c2018-03-01 18:53:07 -080071 return Arrays.asList(
72 new Object[][] {
73 {"1.2.3.4", "8.8.4.4", "10.0.1.1/24"},
74 {"2601::2", "2601::10", "2001:db8::1/64"}
75 });
Nathan Harold2e9a5202017-09-26 11:44:23 -070076 }
77
Benedict Wong4ebc2c52017-11-01 17:14:25 -070078 private static final byte[] AEAD_KEY = {
79 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
80 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
81 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
82 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
83 0x73, 0x61, 0x6C, 0x74
84 };
Nathan Harold2e9a5202017-09-26 11:44:23 -070085 private static final byte[] CRYPT_KEY = {
86 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
87 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
88 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
89 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
90 };
91 private static final byte[] AUTH_KEY = {
92 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
94 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
96 };
97
Nathan Harold21208ee2018-03-15 18:06:06 -070098 AppOpsManager mMockAppOps = mock(AppOpsManager.class);
99
100 MockContext mMockContext = new MockContext() {
101 @Override
102 public Object getSystemService(String name) {
103 switch(name) {
104 case Context.APP_OPS_SERVICE:
105 return mMockAppOps;
106 default:
107 return null;
108 }
109 }
110
111 @Override
112 public void enforceCallingOrSelfPermission(String permission, String message) {
113 if (permission == android.Manifest.permission.MANAGE_IPSEC_TUNNELS) {
114 return;
115 }
116 throw new SecurityException("Unavailable permission requested");
117 }
118 };
119
Nathan Harold2e9a5202017-09-26 11:44:23 -0700120 INetd mMockNetd;
121 IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
122 IpSecService mIpSecService;
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800123 Network fakeNetwork = new Network(0xAB);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700124
Benedict Wong0febe5e2017-08-22 21:42:33 -0700125 private static final IpSecAlgorithm AUTH_ALGO =
126 new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
127 private static final IpSecAlgorithm CRYPT_ALGO =
128 new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
129 private static final IpSecAlgorithm AEAD_ALGO =
Benedict Wong4ebc2c52017-11-01 17:14:25 -0700130 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700131
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800132 public IpSecServiceParameterizedTest(
133 String sourceAddr, String destAddr, String localInnerAddr) {
Nathan Harold5676f5f2018-01-16 19:34:01 -0800134 mSourceAddr = sourceAddr;
135 mDestinationAddr = destAddr;
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800136 mLocalInnerAddress = new LinkAddress(localInnerAddr);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700137 }
138
139 @Before
140 public void setUp() throws Exception {
Nathan Harold2e9a5202017-09-26 11:44:23 -0700141 mMockNetd = mock(INetd.class);
142 mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
143 mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
144
145 // Injecting mock netd
146 when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
Nathan Harold21208ee2018-03-15 18:06:06 -0700147 // A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED.
148 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("blessedPackage")))
149 .thenReturn(AppOpsManager.MODE_ALLOWED);
150 // A system package will not be granted the app op, so this should fall back to
151 // a permissions check, which should pass.
152 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("systemPackage")))
153 .thenReturn(AppOpsManager.MODE_DEFAULT);
154 // A mismatch between the package name and the UID will return MODE_IGNORED.
155 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("badPackage")))
156 .thenReturn(AppOpsManager.MODE_IGNORED);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700157 }
158
159 @Test
160 public void testIpSecServiceReserveSpi() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800161 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
162 .thenReturn(TEST_SPI);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700163
164 IpSecSpiResponse spiResp =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800165 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800166 mDestinationAddr, TEST_SPI, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700167 assertEquals(IpSecManager.Status.OK, spiResp.status);
Nathan Harolda2523312018-01-05 19:25:13 -0800168 assertEquals(TEST_SPI, spiResp.spi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700169 }
170
171 @Test
172 public void testReleaseSecurityParameterIndex() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800173 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
174 .thenReturn(TEST_SPI);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700175
176 IpSecSpiResponse spiResp =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800177 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800178 mDestinationAddr, TEST_SPI, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700179
180 mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
181
182 verify(mMockNetd)
183 .ipSecDeleteSecurityAssociation(
Di Lu0b611f42018-01-11 11:35:25 -0800184 eq(spiResp.resourceId),
185 anyString(),
186 anyString(),
187 eq(TEST_SPI),
188 anyInt(),
189 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800190
191 // Verify quota and RefcountedResource objects cleaned up
192 IpSecService.UserRecord userRecord =
193 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
194 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
195 try {
196 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
197 fail("Expected IllegalArgumentException on attempt to access deleted resource");
198 } catch (IllegalArgumentException expected) {
199
200 }
201 }
202
203 @Test
204 public void testSecurityParameterIndexBinderDeath() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800205 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
206 .thenReturn(TEST_SPI);
Benedict Wong344bd622017-11-16 15:27:22 -0800207
208 IpSecSpiResponse spiResp =
Nathan Harold660a3352017-12-14 14:46:46 -0800209 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800210 mDestinationAddr, TEST_SPI, new Binder());
Benedict Wong344bd622017-11-16 15:27:22 -0800211
212 IpSecService.UserRecord userRecord =
213 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
214 IpSecService.RefcountedResource refcountedRecord =
215 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
216
217 refcountedRecord.binderDied();
218
219 verify(mMockNetd)
220 .ipSecDeleteSecurityAssociation(
Di Lu0b611f42018-01-11 11:35:25 -0800221 eq(spiResp.resourceId),
222 anyString(),
223 anyString(),
224 eq(TEST_SPI),
225 anyInt(),
226 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800227
228 // Verify quota and RefcountedResource objects cleaned up
229 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
230 try {
231 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
232 fail("Expected IllegalArgumentException on attempt to access deleted resource");
233 } catch (IllegalArgumentException expected) {
234
235 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700236 }
237
Nathan Harolda2523312018-01-05 19:25:13 -0800238 private int getNewSpiResourceId(String remoteAddress, int returnSpi) throws Exception {
239 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), anyString(), anyInt()))
Benedict Wong0febe5e2017-08-22 21:42:33 -0700240 .thenReturn(returnSpi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700241
Benedict Wong0febe5e2017-08-22 21:42:33 -0700242 IpSecSpiResponse spi =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800243 mIpSecService.allocateSecurityParameterIndex(
Benedict Wong0febe5e2017-08-22 21:42:33 -0700244 NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(),
245 IpSecManager.INVALID_SECURITY_PARAMETER_INDEX,
246 new Binder());
247 return spi.resourceId;
248 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700249
Benedict Wong0febe5e2017-08-22 21:42:33 -0700250 private void addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config) throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800251 config.setSpiResourceId(getNewSpiResourceId(mDestinationAddr, TEST_SPI));
Nathan Harold5676f5f2018-01-16 19:34:01 -0800252 config.setSourceAddress(mSourceAddr);
Nathan Harolda2523312018-01-05 19:25:13 -0800253 config.setDestinationAddress(mDestinationAddr);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700254 }
255
256 private void addAuthAndCryptToIpSecConfig(IpSecConfig config) throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800257 config.setEncryption(CRYPT_ALGO);
258 config.setAuthentication(AUTH_ALGO);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700259 }
260
261 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800262 public void testCreateTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700263 IpSecConfig ipSecConfig = new IpSecConfig();
264 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
265 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700266
267 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700268 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Nathan Harold2e9a5202017-09-26 11:44:23 -0700269 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
270
271 verify(mMockNetd)
272 .ipSecAddSecurityAssociation(
273 eq(createTransformResp.resourceId),
274 anyInt(),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700275 anyString(),
276 anyString(),
Benedict Wong0fe58a92018-01-19 17:36:02 -0800277 anyInt(),
Nathan Harolda2523312018-01-05 19:25:13 -0800278 eq(TEST_SPI),
Di Lu0b611f42018-01-11 11:35:25 -0800279 anyInt(),
280 anyInt(),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700281 eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
282 eq(AUTH_KEY),
283 anyInt(),
284 eq(IpSecAlgorithm.CRYPT_AES_CBC),
285 eq(CRYPT_KEY),
286 anyInt(),
287 eq(""),
Manoj Boopathi Rajfffa8112017-10-26 11:49:02 -0700288 eq(new byte[] {}),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700289 eq(0),
290 anyInt(),
291 anyInt(),
292 anyInt());
293 }
294
295 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800296 public void testCreateTransformAead() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700297 IpSecConfig ipSecConfig = new IpSecConfig();
298 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
299
Nathan Harolda2523312018-01-05 19:25:13 -0800300 ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700301
302 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700303 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wong0febe5e2017-08-22 21:42:33 -0700304 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
305
306 verify(mMockNetd)
307 .ipSecAddSecurityAssociation(
308 eq(createTransformResp.resourceId),
309 anyInt(),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700310 anyString(),
311 anyString(),
Benedict Wong0fe58a92018-01-19 17:36:02 -0800312 anyInt(),
Nathan Harolda2523312018-01-05 19:25:13 -0800313 eq(TEST_SPI),
Di Lu0b611f42018-01-11 11:35:25 -0800314 anyInt(),
315 anyInt(),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700316 eq(""),
Manoj Boopathi Rajfffa8112017-10-26 11:49:02 -0700317 eq(new byte[] {}),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700318 eq(0),
319 eq(""),
Manoj Boopathi Rajfffa8112017-10-26 11:49:02 -0700320 eq(new byte[] {}),
Benedict Wong0febe5e2017-08-22 21:42:33 -0700321 eq(0),
322 eq(IpSecAlgorithm.AUTH_CRYPT_AES_GCM),
Benedict Wong4ebc2c52017-11-01 17:14:25 -0700323 eq(AEAD_KEY),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700324 anyInt(),
325 anyInt(),
326 anyInt(),
327 anyInt());
328 }
329
Andreas Gampea7b26b52018-02-26 08:06:30 -0800330 @Test
Benedict Wonge6b42772017-12-13 18:26:40 -0800331 public void testCreateTwoTransformsWithSameSpis() throws Exception {
332 IpSecConfig ipSecConfig = new IpSecConfig();
333 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
334 addAuthAndCryptToIpSecConfig(ipSecConfig);
335
336 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700337 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonge6b42772017-12-13 18:26:40 -0800338 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
339
340 // Attempting to create transform a second time with the same SPIs should throw an error...
341 try {
Nathan Harold21208ee2018-03-15 18:06:06 -0700342 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonge6b42772017-12-13 18:26:40 -0800343 fail("IpSecService should have thrown an error for reuse of SPI");
344 } catch (IllegalStateException expected) {
345 }
346
347 // ... even if the transform is deleted
348 mIpSecService.deleteTransform(createTransformResp.resourceId);
349 try {
Nathan Harold21208ee2018-03-15 18:06:06 -0700350 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonge6b42772017-12-13 18:26:40 -0800351 fail("IpSecService should have thrown an error for reuse of SPI");
352 } catch (IllegalStateException expected) {
353 }
354 }
355
Nathan Harold2e9a5202017-09-26 11:44:23 -0700356 @Test
Nathan Harold22795302018-02-27 19:19:40 -0800357 public void testReleaseOwnedSpi() throws Exception {
358 IpSecConfig ipSecConfig = new IpSecConfig();
359 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
360 addAuthAndCryptToIpSecConfig(ipSecConfig);
361
362 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700363 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Nathan Harold22795302018-02-27 19:19:40 -0800364 IpSecService.UserRecord userRecord =
365 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
366 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
367 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
368 verify(mMockNetd, times(0))
369 .ipSecDeleteSecurityAssociation(
370 eq(createTransformResp.resourceId),
371 anyString(),
372 anyString(),
373 eq(TEST_SPI),
374 anyInt(),
375 anyInt());
376 // quota is not released until the SPI is released by the Transform
377 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
378 }
379
380 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800381 public void testDeleteTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700382 IpSecConfig ipSecConfig = new IpSecConfig();
383 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
384 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700385
386 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700387 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wongf33f03132018-01-18 14:38:16 -0800388 mIpSecService.deleteTransform(createTransformResp.resourceId);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700389
Nathan Harold22795302018-02-27 19:19:40 -0800390 verify(mMockNetd, times(1))
Nathan Harold2e9a5202017-09-26 11:44:23 -0700391 .ipSecDeleteSecurityAssociation(
Di Lu0b611f42018-01-11 11:35:25 -0800392 eq(createTransformResp.resourceId),
393 anyString(),
394 anyString(),
395 eq(TEST_SPI),
396 anyInt(),
397 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800398
399 // Verify quota and RefcountedResource objects cleaned up
400 IpSecService.UserRecord userRecord =
401 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
402 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
Nathan Harold22795302018-02-27 19:19:40 -0800403 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
404
405 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
406 // Verify that ipSecDeleteSa was not called when the SPI was released because the
407 // ownedByTransform property should prevent it; (note, the called count is cumulative).
408 verify(mMockNetd, times(1))
409 .ipSecDeleteSecurityAssociation(
410 anyInt(),
411 anyString(),
412 anyString(),
413 anyInt(),
414 anyInt(),
415 anyInt());
416 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
417
Benedict Wong344bd622017-11-16 15:27:22 -0800418 try {
419 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
420 createTransformResp.resourceId);
421 fail("Expected IllegalArgumentException on attempt to access deleted resource");
422 } catch (IllegalArgumentException expected) {
423
424 }
425 }
426
427 @Test
428 public void testTransportModeTransformBinderDeath() throws Exception {
429 IpSecConfig ipSecConfig = new IpSecConfig();
430 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
431 addAuthAndCryptToIpSecConfig(ipSecConfig);
432
433 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700434 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wong344bd622017-11-16 15:27:22 -0800435
436 IpSecService.UserRecord userRecord =
437 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
438 IpSecService.RefcountedResource refcountedRecord =
439 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
440 createTransformResp.resourceId);
441
442 refcountedRecord.binderDied();
443
444 verify(mMockNetd)
445 .ipSecDeleteSecurityAssociation(
Di Lu0b611f42018-01-11 11:35:25 -0800446 eq(createTransformResp.resourceId),
447 anyString(),
448 anyString(),
449 eq(TEST_SPI),
450 anyInt(),
451 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800452
453 // Verify quota and RefcountedResource objects cleaned up
454 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
455 try {
456 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
457 createTransformResp.resourceId);
458 fail("Expected IllegalArgumentException on attempt to access deleted resource");
459 } catch (IllegalArgumentException expected) {
460
461 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700462 }
463
464 @Test
465 public void testApplyTransportModeTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700466 IpSecConfig ipSecConfig = new IpSecConfig();
467 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
468 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700469
470 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700471 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Nathan Harold2e9a5202017-09-26 11:44:23 -0700472 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
473
474 int resourceId = createTransformResp.resourceId;
Nathan Harolda2523312018-01-05 19:25:13 -0800475 mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700476
477 verify(mMockNetd)
478 .ipSecApplyTransportModeTransform(
479 eq(pfd.getFileDescriptor()),
480 eq(resourceId),
Nathan Harolda2523312018-01-05 19:25:13 -0800481 eq(IpSecManager.DIRECTION_OUT),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700482 anyString(),
483 anyString(),
Nathan Harolda2523312018-01-05 19:25:13 -0800484 eq(TEST_SPI));
Nathan Harold2e9a5202017-09-26 11:44:23 -0700485 }
486
487 @Test
488 public void testRemoveTransportModeTransform() throws Exception {
489 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
Nathan Haroldf73d2522018-01-17 01:00:20 -0800490 mIpSecService.removeTransportModeTransforms(pfd);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700491
492 verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
493 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800494
495 private IpSecTunnelInterfaceResponse createAndValidateTunnel(
Nathan Harold21208ee2018-03-15 18:06:06 -0700496 String localAddr, String remoteAddr, String pkgName) {
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800497 IpSecTunnelInterfaceResponse createTunnelResp =
498 mIpSecService.createTunnelInterface(
Nathan Harold21208ee2018-03-15 18:06:06 -0700499 mSourceAddr, mDestinationAddr, fakeNetwork, new Binder(), pkgName);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800500
501 assertNotNull(createTunnelResp);
502 assertEquals(IpSecManager.Status.OK, createTunnelResp.status);
503 return createTunnelResp;
504 }
505
506 @Test
507 public void testCreateTunnelInterface() throws Exception {
508 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700509 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800510
511 // Check that we have stored the tracking object, and retrieve it
512 IpSecService.UserRecord userRecord =
513 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
514 IpSecService.RefcountedResource refcountedRecord =
515 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
516 createTunnelResp.resourceId);
517
518 assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent);
519 verify(mMockNetd)
520 .addVirtualTunnelInterface(
521 eq(createTunnelResp.interfaceName),
522 eq(mSourceAddr),
523 eq(mDestinationAddr),
524 anyInt(),
525 anyInt());
526 }
527
528 @Test
529 public void testDeleteTunnelInterface() throws Exception {
530 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700531 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800532
533 IpSecService.UserRecord userRecord =
534 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
535
Nathan Harold21208ee2018-03-15 18:06:06 -0700536 mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800537
538 // Verify quota and RefcountedResource objects cleaned up
539 assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
540 verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName));
541 try {
542 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
543 createTunnelResp.resourceId);
544 fail("Expected IllegalArgumentException on attempt to access deleted resource");
545 } catch (IllegalArgumentException expected) {
546 }
547 }
548
549 @Test
550 public void testTunnelInterfaceBinderDeath() throws Exception {
551 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700552 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800553
554 IpSecService.UserRecord userRecord =
555 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
556 IpSecService.RefcountedResource refcountedRecord =
557 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
558 createTunnelResp.resourceId);
559
560 refcountedRecord.binderDied();
561
562 // Verify quota and RefcountedResource objects cleaned up
563 assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
564 verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName));
565 try {
566 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
567 createTunnelResp.resourceId);
568 fail("Expected IllegalArgumentException on attempt to access deleted resource");
569 } catch (IllegalArgumentException expected) {
570 }
571 }
572
573 @Test
574 public void testAddRemoveAddressFromTunnelInterface() throws Exception {
Nathan Harold21208ee2018-03-15 18:06:06 -0700575 for (String pkgName : new String[]{"blessedPackage", "systemPackage"}) {
576 IpSecTunnelInterfaceResponse createTunnelResp =
577 createAndValidateTunnel(mSourceAddr, mDestinationAddr, pkgName);
578 mIpSecService.addAddressToTunnelInterface(
579 createTunnelResp.resourceId, mLocalInnerAddress, pkgName);
580 verify(mMockNetd, times(1))
581 .interfaceAddAddress(
582 eq(createTunnelResp.interfaceName),
583 eq(mLocalInnerAddress.getAddress().getHostAddress()),
584 eq(mLocalInnerAddress.getPrefixLength()));
585 mIpSecService.removeAddressFromTunnelInterface(
586 createTunnelResp.resourceId, mLocalInnerAddress, pkgName);
587 verify(mMockNetd, times(1))
588 .interfaceDelAddress(
589 eq(createTunnelResp.interfaceName),
590 eq(mLocalInnerAddress.getAddress().getHostAddress()),
591 eq(mLocalInnerAddress.getPrefixLength()));
592 mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, pkgName);
593 }
594 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800595
Nathan Harold8c69bcb2018-05-15 19:18:38 -0700596 @Ignore
Nathan Harold21208ee2018-03-15 18:06:06 -0700597 @Test
598 public void testAddTunnelFailsForBadPackageName() throws Exception {
599 try {
600 IpSecTunnelInterfaceResponse createTunnelResp =
601 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "badPackage");
602 fail("Expected a SecurityException for badPackage.");
603 } catch (SecurityException expected) {
604 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800605 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700606}