blob: d8f961850906673d2d25954623e56e4582d9c0f3 [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
Benedict Wong781dae62018-09-06 11:31:25 -070074 private static final int[] ADDRESS_FAMILIES =
75 new int[] {AF_INET, AF_INET6};
76
Nathan Harold2e9a5202017-09-26 11:44:23 -070077 @Parameterized.Parameters
78 public static Collection ipSecConfigs() {
Benedict Wongecc9f7c2018-03-01 18:53:07 -080079 return Arrays.asList(
80 new Object[][] {
evitayane4259d32018-03-22 17:53:08 -070081 {"1.2.3.4", "8.8.4.4", "10.0.1.1/24", AF_INET},
82 {"2601::2", "2601::10", "2001:db8::1/64", AF_INET6}
Benedict Wongecc9f7c2018-03-01 18:53:07 -080083 });
Nathan Harold2e9a5202017-09-26 11:44:23 -070084 }
85
Benedict Wong4ebc2c52017-11-01 17:14:25 -070086 private static final byte[] AEAD_KEY = {
87 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
88 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
89 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
90 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
91 0x73, 0x61, 0x6C, 0x74
92 };
Nathan Harold2e9a5202017-09-26 11:44:23 -070093 private static final byte[] CRYPT_KEY = {
94 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
95 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
96 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
97 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
98 };
99 private static final byte[] AUTH_KEY = {
100 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
102 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
104 };
105
Nathan Harold21208ee2018-03-15 18:06:06 -0700106 AppOpsManager mMockAppOps = mock(AppOpsManager.class);
107
108 MockContext mMockContext = new MockContext() {
109 @Override
110 public Object getSystemService(String name) {
111 switch(name) {
112 case Context.APP_OPS_SERVICE:
113 return mMockAppOps;
114 default:
115 return null;
116 }
117 }
118
119 @Override
120 public void enforceCallingOrSelfPermission(String permission, String message) {
121 if (permission == android.Manifest.permission.MANAGE_IPSEC_TUNNELS) {
122 return;
123 }
124 throw new SecurityException("Unavailable permission requested");
125 }
126 };
127
Nathan Harold2e9a5202017-09-26 11:44:23 -0700128 INetd mMockNetd;
129 IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
130 IpSecService mIpSecService;
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800131 Network fakeNetwork = new Network(0xAB);
Benedict Wonga0989622018-07-25 13:06:29 -0700132 int mUid = Os.getuid();
Nathan Harold2e9a5202017-09-26 11:44:23 -0700133
Benedict Wong0febe5e2017-08-22 21:42:33 -0700134 private static final IpSecAlgorithm AUTH_ALGO =
135 new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
136 private static final IpSecAlgorithm CRYPT_ALGO =
137 new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
138 private static final IpSecAlgorithm AEAD_ALGO =
Benedict Wong4ebc2c52017-11-01 17:14:25 -0700139 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
evitayan0a7d3e32018-03-22 13:42:07 -0700140 private static final int REMOTE_ENCAP_PORT = 4500;
Benedict Wong0febe5e2017-08-22 21:42:33 -0700141
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800142 public IpSecServiceParameterizedTest(
evitayane4259d32018-03-22 17:53:08 -0700143 String sourceAddr, String destAddr, String localInnerAddr, int family) {
Nathan Harold5676f5f2018-01-16 19:34:01 -0800144 mSourceAddr = sourceAddr;
145 mDestinationAddr = destAddr;
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800146 mLocalInnerAddress = new LinkAddress(localInnerAddr);
evitayane4259d32018-03-22 17:53:08 -0700147 mFamily = family;
Nathan Harold2e9a5202017-09-26 11:44:23 -0700148 }
149
150 @Before
151 public void setUp() throws Exception {
Nathan Harold2e9a5202017-09-26 11:44:23 -0700152 mMockNetd = mock(INetd.class);
153 mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
154 mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
155
156 // Injecting mock netd
157 when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
Nathan Harold21208ee2018-03-15 18:06:06 -0700158 // A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED.
159 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("blessedPackage")))
160 .thenReturn(AppOpsManager.MODE_ALLOWED);
161 // A system package will not be granted the app op, so this should fall back to
162 // a permissions check, which should pass.
163 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("systemPackage")))
164 .thenReturn(AppOpsManager.MODE_DEFAULT);
165 // A mismatch between the package name and the UID will return MODE_IGNORED.
166 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("badPackage")))
167 .thenReturn(AppOpsManager.MODE_IGNORED);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700168 }
169
evitayan0a7d3e32018-03-22 13:42:07 -0700170 //TODO: Add a test to verify SPI.
171
Nathan Harold2e9a5202017-09-26 11:44:23 -0700172 @Test
173 public void testIpSecServiceReserveSpi() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800174 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
175 .thenReturn(TEST_SPI);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700176
177 IpSecSpiResponse spiResp =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800178 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800179 mDestinationAddr, TEST_SPI, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700180 assertEquals(IpSecManager.Status.OK, spiResp.status);
Nathan Harolda2523312018-01-05 19:25:13 -0800181 assertEquals(TEST_SPI, spiResp.spi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700182 }
183
184 @Test
185 public void testReleaseSecurityParameterIndex() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800186 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
187 .thenReturn(TEST_SPI);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700188
189 IpSecSpiResponse spiResp =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800190 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800191 mDestinationAddr, TEST_SPI, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700192
193 mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
194
195 verify(mMockNetd)
196 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700197 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800198 anyString(),
199 anyString(),
200 eq(TEST_SPI),
201 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700202 anyInt(),
Di Lu0b611f42018-01-11 11:35:25 -0800203 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800204
205 // Verify quota and RefcountedResource objects cleaned up
Benedict Wonga0989622018-07-25 13:06:29 -0700206 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800207 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
208 try {
209 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
210 fail("Expected IllegalArgumentException on attempt to access deleted resource");
211 } catch (IllegalArgumentException expected) {
212
213 }
214 }
215
216 @Test
217 public void testSecurityParameterIndexBinderDeath() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800218 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
219 .thenReturn(TEST_SPI);
Benedict Wong344bd622017-11-16 15:27:22 -0800220
221 IpSecSpiResponse spiResp =
Nathan Harold660a3352017-12-14 14:46:46 -0800222 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800223 mDestinationAddr, TEST_SPI, new Binder());
Benedict Wong344bd622017-11-16 15:27:22 -0800224
Benedict Wonga0989622018-07-25 13:06:29 -0700225 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800226 IpSecService.RefcountedResource refcountedRecord =
227 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
228
229 refcountedRecord.binderDied();
230
231 verify(mMockNetd)
232 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700233 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800234 anyString(),
235 anyString(),
236 eq(TEST_SPI),
237 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700238 anyInt(),
Di Lu0b611f42018-01-11 11:35:25 -0800239 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800240
241 // Verify quota and RefcountedResource objects cleaned up
242 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
243 try {
244 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
245 fail("Expected IllegalArgumentException on attempt to access deleted resource");
246 } catch (IllegalArgumentException expected) {
247
248 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700249 }
250
Nathan Harolda2523312018-01-05 19:25:13 -0800251 private int getNewSpiResourceId(String remoteAddress, int returnSpi) throws Exception {
252 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), anyString(), anyInt()))
Benedict Wong0febe5e2017-08-22 21:42:33 -0700253 .thenReturn(returnSpi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700254
Benedict Wong0febe5e2017-08-22 21:42:33 -0700255 IpSecSpiResponse spi =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800256 mIpSecService.allocateSecurityParameterIndex(
Benedict Wong0febe5e2017-08-22 21:42:33 -0700257 NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(),
258 IpSecManager.INVALID_SECURITY_PARAMETER_INDEX,
259 new Binder());
260 return spi.resourceId;
261 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700262
Benedict Wong0febe5e2017-08-22 21:42:33 -0700263 private void addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config) throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800264 config.setSpiResourceId(getNewSpiResourceId(mDestinationAddr, TEST_SPI));
Nathan Harold5676f5f2018-01-16 19:34:01 -0800265 config.setSourceAddress(mSourceAddr);
Nathan Harolda2523312018-01-05 19:25:13 -0800266 config.setDestinationAddress(mDestinationAddr);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700267 }
268
269 private void addAuthAndCryptToIpSecConfig(IpSecConfig config) throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800270 config.setEncryption(CRYPT_ALGO);
271 config.setAuthentication(AUTH_ALGO);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700272 }
273
evitayan0a7d3e32018-03-22 13:42:07 -0700274 private void addEncapSocketToIpSecConfig(int resourceId, IpSecConfig config) throws Exception {
275 config.setEncapType(IpSecTransform.ENCAP_ESPINUDP);
276 config.setEncapSocketResourceId(resourceId);
277 config.setEncapRemotePort(REMOTE_ENCAP_PORT);
278 }
279
280 private void verifyTransformNetdCalledForCreatingSA(
281 IpSecConfig config, IpSecTransformResponse resp) throws Exception {
282 verifyTransformNetdCalledForCreatingSA(config, resp, 0);
283 }
284
285 private void verifyTransformNetdCalledForCreatingSA(
286 IpSecConfig config, IpSecTransformResponse resp, int encapSocketPort) throws Exception {
287 IpSecAlgorithm auth = config.getAuthentication();
288 IpSecAlgorithm crypt = config.getEncryption();
289 IpSecAlgorithm authCrypt = config.getAuthenticatedEncryption();
290
291 verify(mMockNetd, times(1))
292 .ipSecAddSecurityAssociation(
293 eq(mUid),
294 eq(config.getMode()),
295 eq(config.getSourceAddress()),
296 eq(config.getDestinationAddress()),
297 eq((config.getNetwork() != null) ? config.getNetwork().netId : 0),
298 eq(TEST_SPI),
299 eq(0),
300 eq(0),
301 eq((auth != null) ? auth.getName() : ""),
302 eq((auth != null) ? auth.getKey() : new byte[] {}),
303 eq((auth != null) ? auth.getTruncationLengthBits() : 0),
304 eq((crypt != null) ? crypt.getName() : ""),
305 eq((crypt != null) ? crypt.getKey() : new byte[] {}),
306 eq((crypt != null) ? crypt.getTruncationLengthBits() : 0),
307 eq((authCrypt != null) ? authCrypt.getName() : ""),
308 eq((authCrypt != null) ? authCrypt.getKey() : new byte[] {}),
309 eq((authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0),
310 eq(config.getEncapType()),
311 eq(encapSocketPort),
Benedict Wong781dae62018-09-06 11:31:25 -0700312 eq(config.getEncapRemotePort()),
313 eq(config.getXfrmInterfaceId()));
evitayan0a7d3e32018-03-22 13:42:07 -0700314 }
315
Nathan Harold2e9a5202017-09-26 11:44:23 -0700316 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800317 public void testCreateTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700318 IpSecConfig ipSecConfig = new IpSecConfig();
319 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
320 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700321
322 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700323 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Nathan Harold2e9a5202017-09-26 11:44:23 -0700324 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
325
evitayan0a7d3e32018-03-22 13:42:07 -0700326 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700327 }
328
329 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800330 public void testCreateTransformAead() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700331 IpSecConfig ipSecConfig = new IpSecConfig();
332 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
333
Nathan Harolda2523312018-01-05 19:25:13 -0800334 ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700335
336 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700337 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wong0febe5e2017-08-22 21:42:33 -0700338 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
339
evitayan0a7d3e32018-03-22 13:42:07 -0700340 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
341 }
342
343 @Test
344 public void testCreateTransportModeTransformWithEncap() throws Exception {
345 IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder());
346
347 IpSecConfig ipSecConfig = new IpSecConfig();
348 ipSecConfig.setMode(IpSecTransform.MODE_TRANSPORT);
349 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
350 addAuthAndCryptToIpSecConfig(ipSecConfig);
351 addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig);
352
evitayane4259d32018-03-22 17:53:08 -0700353 if (mFamily == AF_INET) {
354 IpSecTransformResponse createTransformResp =
355 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
356 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
evitayan0a7d3e32018-03-22 13:42:07 -0700357
evitayane4259d32018-03-22 17:53:08 -0700358 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
359 } else {
360 try {
361 IpSecTransformResponse createTransformResp =
362 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
363 fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
364 } catch (IllegalArgumentException expected) {
365 }
366 }
evitayan0a7d3e32018-03-22 13:42:07 -0700367 }
368
369 @Test
370 public void testCreateTunnelModeTransformWithEncap() throws Exception {
371 IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder());
372
373 IpSecConfig ipSecConfig = new IpSecConfig();
374 ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL);
375 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
376 addAuthAndCryptToIpSecConfig(ipSecConfig);
377 addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig);
378
evitayane4259d32018-03-22 17:53:08 -0700379 if (mFamily == AF_INET) {
380 IpSecTransformResponse createTransformResp =
381 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
382 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
evitayan0a7d3e32018-03-22 13:42:07 -0700383
evitayane4259d32018-03-22 17:53:08 -0700384 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
385 } else {
386 try {
387 IpSecTransformResponse createTransformResp =
388 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
389 fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
390 } catch (IllegalArgumentException expected) {
391 }
392 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700393 }
394
Andreas Gampea7b26b52018-02-26 08:06:30 -0800395 @Test
Benedict Wonge6b42772017-12-13 18:26:40 -0800396 public void testCreateTwoTransformsWithSameSpis() throws Exception {
397 IpSecConfig ipSecConfig = new IpSecConfig();
398 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
399 addAuthAndCryptToIpSecConfig(ipSecConfig);
400
401 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700402 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonge6b42772017-12-13 18:26:40 -0800403 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
404
405 // Attempting to create transform a second time with the same SPIs should throw an error...
406 try {
Nathan Harold21208ee2018-03-15 18:06:06 -0700407 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonge6b42772017-12-13 18:26:40 -0800408 fail("IpSecService should have thrown an error for reuse of SPI");
409 } catch (IllegalStateException expected) {
410 }
411
412 // ... even if the transform is deleted
413 mIpSecService.deleteTransform(createTransformResp.resourceId);
414 try {
Nathan Harold21208ee2018-03-15 18:06:06 -0700415 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonge6b42772017-12-13 18:26:40 -0800416 fail("IpSecService should have thrown an error for reuse of SPI");
417 } catch (IllegalStateException expected) {
418 }
419 }
420
Nathan Harold2e9a5202017-09-26 11:44:23 -0700421 @Test
Nathan Harold22795302018-02-27 19:19:40 -0800422 public void testReleaseOwnedSpi() throws Exception {
423 IpSecConfig ipSecConfig = new IpSecConfig();
424 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
425 addAuthAndCryptToIpSecConfig(ipSecConfig);
426
427 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700428 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonga0989622018-07-25 13:06:29 -0700429 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Nathan Harold22795302018-02-27 19:19:40 -0800430 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
431 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
432 verify(mMockNetd, times(0))
433 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700434 eq(mUid),
Nathan Harold22795302018-02-27 19:19:40 -0800435 anyString(),
436 anyString(),
437 eq(TEST_SPI),
438 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700439 anyInt(),
Nathan Harold22795302018-02-27 19:19:40 -0800440 anyInt());
441 // quota is not released until the SPI is released by the Transform
442 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
443 }
444
445 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800446 public void testDeleteTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700447 IpSecConfig ipSecConfig = new IpSecConfig();
448 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
449 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700450
451 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700452 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wongf33f03132018-01-18 14:38:16 -0800453 mIpSecService.deleteTransform(createTransformResp.resourceId);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700454
Nathan Harold22795302018-02-27 19:19:40 -0800455 verify(mMockNetd, times(1))
Nathan Harold2e9a5202017-09-26 11:44:23 -0700456 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700457 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800458 anyString(),
459 anyString(),
460 eq(TEST_SPI),
461 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700462 anyInt(),
Di Lu0b611f42018-01-11 11:35:25 -0800463 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800464
465 // Verify quota and RefcountedResource objects cleaned up
Benedict Wonga0989622018-07-25 13:06:29 -0700466 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800467 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
Nathan Harold22795302018-02-27 19:19:40 -0800468 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
469
470 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
471 // Verify that ipSecDeleteSa was not called when the SPI was released because the
472 // ownedByTransform property should prevent it; (note, the called count is cumulative).
473 verify(mMockNetd, times(1))
474 .ipSecDeleteSecurityAssociation(
475 anyInt(),
476 anyString(),
477 anyString(),
478 anyInt(),
479 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700480 anyInt(),
Nathan Harold22795302018-02-27 19:19:40 -0800481 anyInt());
482 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
483
Benedict Wong344bd622017-11-16 15:27:22 -0800484 try {
485 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
486 createTransformResp.resourceId);
487 fail("Expected IllegalArgumentException on attempt to access deleted resource");
488 } catch (IllegalArgumentException expected) {
489
490 }
491 }
492
493 @Test
494 public void testTransportModeTransformBinderDeath() throws Exception {
495 IpSecConfig ipSecConfig = new IpSecConfig();
496 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
497 addAuthAndCryptToIpSecConfig(ipSecConfig);
498
499 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700500 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wong344bd622017-11-16 15:27:22 -0800501
Benedict Wonga0989622018-07-25 13:06:29 -0700502 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800503 IpSecService.RefcountedResource refcountedRecord =
504 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
505 createTransformResp.resourceId);
506
507 refcountedRecord.binderDied();
508
509 verify(mMockNetd)
510 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700511 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800512 anyString(),
513 anyString(),
514 eq(TEST_SPI),
515 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700516 anyInt(),
Di Lu0b611f42018-01-11 11:35:25 -0800517 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800518
519 // Verify quota and RefcountedResource objects cleaned up
520 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
521 try {
522 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
523 createTransformResp.resourceId);
524 fail("Expected IllegalArgumentException on attempt to access deleted resource");
525 } catch (IllegalArgumentException expected) {
526
527 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700528 }
529
530 @Test
531 public void testApplyTransportModeTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700532 IpSecConfig ipSecConfig = new IpSecConfig();
533 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
534 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700535
536 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700537 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Nathan Harold2e9a5202017-09-26 11:44:23 -0700538 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
539
540 int resourceId = createTransformResp.resourceId;
Nathan Harolda2523312018-01-05 19:25:13 -0800541 mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700542
543 verify(mMockNetd)
544 .ipSecApplyTransportModeTransform(
Luke Huange8e522b2018-11-23 12:01:41 +0800545 eq(pfd),
Benedict Wonga0989622018-07-25 13:06:29 -0700546 eq(mUid),
Nathan Harolda2523312018-01-05 19:25:13 -0800547 eq(IpSecManager.DIRECTION_OUT),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700548 anyString(),
549 anyString(),
Nathan Harolda2523312018-01-05 19:25:13 -0800550 eq(TEST_SPI));
Nathan Harold2e9a5202017-09-26 11:44:23 -0700551 }
552
553 @Test
554 public void testRemoveTransportModeTransform() throws Exception {
555 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
Nathan Haroldf73d2522018-01-17 01:00:20 -0800556 mIpSecService.removeTransportModeTransforms(pfd);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700557
Luke Huange8e522b2018-11-23 12:01:41 +0800558 verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700559 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800560
561 private IpSecTunnelInterfaceResponse createAndValidateTunnel(
Nathan Harold21208ee2018-03-15 18:06:06 -0700562 String localAddr, String remoteAddr, String pkgName) {
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800563 IpSecTunnelInterfaceResponse createTunnelResp =
564 mIpSecService.createTunnelInterface(
Nathan Harold21208ee2018-03-15 18:06:06 -0700565 mSourceAddr, mDestinationAddr, fakeNetwork, new Binder(), pkgName);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800566
567 assertNotNull(createTunnelResp);
568 assertEquals(IpSecManager.Status.OK, createTunnelResp.status);
569 return createTunnelResp;
570 }
571
572 @Test
573 public void testCreateTunnelInterface() throws Exception {
574 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700575 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800576
577 // Check that we have stored the tracking object, and retrieve it
Benedict Wonga0989622018-07-25 13:06:29 -0700578 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800579 IpSecService.RefcountedResource refcountedRecord =
580 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
581 createTunnelResp.resourceId);
582
583 assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent);
584 verify(mMockNetd)
Benedict Wong781dae62018-09-06 11:31:25 -0700585 .ipSecAddTunnelInterface(
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800586 eq(createTunnelResp.interfaceName),
587 eq(mSourceAddr),
588 eq(mDestinationAddr),
589 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700590 anyInt(),
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800591 anyInt());
592 }
593
594 @Test
595 public void testDeleteTunnelInterface() throws Exception {
596 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700597 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800598
Benedict Wonga0989622018-07-25 13:06:29 -0700599 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800600
Nathan Harold21208ee2018-03-15 18:06:06 -0700601 mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800602
603 // Verify quota and RefcountedResource objects cleaned up
604 assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
Benedict Wong781dae62018-09-06 11:31:25 -0700605 verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName));
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800606 try {
607 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
608 createTunnelResp.resourceId);
609 fail("Expected IllegalArgumentException on attempt to access deleted resource");
610 } catch (IllegalArgumentException expected) {
611 }
612 }
613
614 @Test
615 public void testTunnelInterfaceBinderDeath() throws Exception {
616 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700617 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800618
Benedict Wonga0989622018-07-25 13:06:29 -0700619 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800620 IpSecService.RefcountedResource refcountedRecord =
621 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
622 createTunnelResp.resourceId);
623
624 refcountedRecord.binderDied();
625
626 // Verify quota and RefcountedResource objects cleaned up
627 assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
Benedict Wong781dae62018-09-06 11:31:25 -0700628 verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName));
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800629 try {
630 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
631 createTunnelResp.resourceId);
632 fail("Expected IllegalArgumentException on attempt to access deleted resource");
633 } catch (IllegalArgumentException expected) {
634 }
635 }
636
637 @Test
Benedict Wong781dae62018-09-06 11:31:25 -0700638 public void testApplyTunnelModeTransform() throws Exception {
639 IpSecConfig ipSecConfig = new IpSecConfig();
640 ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL);
641 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
642 addAuthAndCryptToIpSecConfig(ipSecConfig);
643
644 IpSecTransformResponse createTransformResp =
645 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
646 IpSecTunnelInterfaceResponse createTunnelResp =
647 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
648
649 int transformResourceId = createTransformResp.resourceId;
650 int tunnelResourceId = createTunnelResp.resourceId;
651 mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT,
652 transformResourceId, "blessedPackage");
653
654 for (int selAddrFamily : ADDRESS_FAMILIES) {
655 verify(mMockNetd)
656 .ipSecUpdateSecurityPolicy(
657 eq(mUid),
658 eq(selAddrFamily),
659 eq(IpSecManager.DIRECTION_OUT),
660 anyString(),
661 anyString(),
662 eq(TEST_SPI),
663 anyInt(), // iKey/oKey
664 anyInt(), // mask
665 eq(tunnelResourceId));
666 }
667
668 ipSecConfig.setXfrmInterfaceId(tunnelResourceId);
669 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
670 }
671
672 @Test
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800673 public void testAddRemoveAddressFromTunnelInterface() throws Exception {
Nathan Harold21208ee2018-03-15 18:06:06 -0700674 for (String pkgName : new String[]{"blessedPackage", "systemPackage"}) {
675 IpSecTunnelInterfaceResponse createTunnelResp =
676 createAndValidateTunnel(mSourceAddr, mDestinationAddr, pkgName);
677 mIpSecService.addAddressToTunnelInterface(
678 createTunnelResp.resourceId, mLocalInnerAddress, pkgName);
679 verify(mMockNetd, times(1))
680 .interfaceAddAddress(
681 eq(createTunnelResp.interfaceName),
682 eq(mLocalInnerAddress.getAddress().getHostAddress()),
683 eq(mLocalInnerAddress.getPrefixLength()));
684 mIpSecService.removeAddressFromTunnelInterface(
685 createTunnelResp.resourceId, mLocalInnerAddress, pkgName);
686 verify(mMockNetd, times(1))
687 .interfaceDelAddress(
688 eq(createTunnelResp.interfaceName),
689 eq(mLocalInnerAddress.getAddress().getHostAddress()),
690 eq(mLocalInnerAddress.getPrefixLength()));
691 mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, pkgName);
692 }
693 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800694
Nathan Harold8c69bcb2018-05-15 19:18:38 -0700695 @Ignore
Nathan Harold21208ee2018-03-15 18:06:06 -0700696 @Test
697 public void testAddTunnelFailsForBadPackageName() throws Exception {
698 try {
699 IpSecTunnelInterfaceResponse createTunnelResp =
700 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "badPackage");
701 fail("Expected a SecurityException for badPackage.");
702 } catch (SecurityException expected) {
703 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800704 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700705}