blob: 7c40adfac002a9b7a4ae27b5847334b0fd273bd9 [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;
Brett Chabot1ae2aa62019-03-04 14:14:56 -080021
Nathan Harold2e9a5202017-09-26 11:44:23 -070022import static org.junit.Assert.assertEquals;
Benedict Wongecc9f7c2018-03-01 18:53:07 -080023import static org.junit.Assert.assertNotNull;
Benedict Wong0febe5e2017-08-22 21:42:33 -070024import static org.junit.Assert.fail;
Nathan Harold2e9a5202017-09-26 11:44:23 -070025import static org.mockito.Matchers.anyInt;
Nathan Harold2e9a5202017-09-26 11:44:23 -070026import static org.mockito.Matchers.anyString;
27import static org.mockito.Matchers.eq;
28import static org.mockito.Mockito.mock;
Nathan Harold22795302018-02-27 19:19:40 -080029import static org.mockito.Mockito.times;
Nathan Harold2e9a5202017-09-26 11:44:23 -070030import static org.mockito.Mockito.verify;
31import static org.mockito.Mockito.when;
32
Nathan Harold21208ee2018-03-15 18:06:06 -070033import android.app.AppOpsManager;
Nathan Harold2e9a5202017-09-26 11:44:23 -070034import android.content.Context;
35import android.net.INetd;
36import android.net.IpSecAlgorithm;
37import android.net.IpSecConfig;
38import android.net.IpSecManager;
39import android.net.IpSecSpiResponse;
evitayan0a7d3e32018-03-22 13:42:07 -070040import android.net.IpSecTransform;
Nathan Harold2e9a5202017-09-26 11:44:23 -070041import android.net.IpSecTransformResponse;
Benedict Wongecc9f7c2018-03-01 18:53:07 -080042import android.net.IpSecTunnelInterfaceResponse;
evitayan0a7d3e32018-03-22 13:42:07 -070043import android.net.IpSecUdpEncapResponse;
Benedict Wongecc9f7c2018-03-01 18:53:07 -080044import android.net.LinkAddress;
45import android.net.Network;
Nathan Harold2e9a5202017-09-26 11:44:23 -070046import android.net.NetworkUtils;
47import android.os.Binder;
48import android.os.ParcelFileDescriptor;
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
Brett Chabot1ae2aa62019-03-04 14:14:56 -080052import androidx.test.filters.SmallTest;
Nathan Harold2e9a5202017-09-26 11:44:23 -070053
54import org.junit.Before;
Nathan Harold8c69bcb2018-05-15 19:18:38 -070055import org.junit.Ignore;
Nathan Harold2e9a5202017-09-26 11:44:23 -070056import org.junit.Test;
57import org.junit.runner.RunWith;
58import org.junit.runners.Parameterized;
59
Brett Chabot1ae2aa62019-03-04 14:14:56 -080060import java.net.Socket;
61import java.util.Arrays;
62import java.util.Collection;
63
Nathan Harold2e9a5202017-09-26 11:44:23 -070064/** Unit tests for {@link IpSecService}. */
65@SmallTest
66@RunWith(Parameterized.class)
67public class IpSecServiceParameterizedTest {
68
Nathan Harolda2523312018-01-05 19:25:13 -080069 private static final int TEST_SPI = 0xD1201D;
Nathan Harold2e9a5202017-09-26 11:44:23 -070070
Nathan Harold5676f5f2018-01-16 19:34:01 -080071 private final String mSourceAddr;
evitayane4259d32018-03-22 17:53:08 -070072 private final String mDestinationAddr;
Benedict Wongecc9f7c2018-03-01 18:53:07 -080073 private final LinkAddress mLocalInnerAddress;
evitayane4259d32018-03-22 17:53:08 -070074 private final int mFamily;
Nathan Harold2e9a5202017-09-26 11:44:23 -070075
Benedict Wong781dae62018-09-06 11:31:25 -070076 private static final int[] ADDRESS_FAMILIES =
77 new int[] {AF_INET, AF_INET6};
78
Nathan Harold2e9a5202017-09-26 11:44:23 -070079 @Parameterized.Parameters
80 public static Collection ipSecConfigs() {
Benedict Wongecc9f7c2018-03-01 18:53:07 -080081 return Arrays.asList(
82 new Object[][] {
evitayane4259d32018-03-22 17:53:08 -070083 {"1.2.3.4", "8.8.4.4", "10.0.1.1/24", AF_INET},
84 {"2601::2", "2601::10", "2001:db8::1/64", AF_INET6}
Benedict Wongecc9f7c2018-03-01 18:53:07 -080085 });
Nathan Harold2e9a5202017-09-26 11:44:23 -070086 }
87
Benedict Wong4ebc2c52017-11-01 17:14:25 -070088 private static final byte[] AEAD_KEY = {
89 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
90 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
91 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
92 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
93 0x73, 0x61, 0x6C, 0x74
94 };
Nathan Harold2e9a5202017-09-26 11:44:23 -070095 private static final byte[] CRYPT_KEY = {
96 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
97 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
98 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
99 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
100 };
101 private static final byte[] AUTH_KEY = {
102 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
104 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
106 };
107
Nathan Harold21208ee2018-03-15 18:06:06 -0700108 AppOpsManager mMockAppOps = mock(AppOpsManager.class);
109
110 MockContext mMockContext = new MockContext() {
111 @Override
112 public Object getSystemService(String name) {
113 switch(name) {
114 case Context.APP_OPS_SERVICE:
115 return mMockAppOps;
116 default:
117 return null;
118 }
119 }
120
121 @Override
122 public void enforceCallingOrSelfPermission(String permission, String message) {
123 if (permission == android.Manifest.permission.MANAGE_IPSEC_TUNNELS) {
124 return;
125 }
126 throw new SecurityException("Unavailable permission requested");
127 }
128 };
129
Nathan Harold2e9a5202017-09-26 11:44:23 -0700130 INetd mMockNetd;
131 IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
132 IpSecService mIpSecService;
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800133 Network fakeNetwork = new Network(0xAB);
Benedict Wonga0989622018-07-25 13:06:29 -0700134 int mUid = Os.getuid();
Nathan Harold2e9a5202017-09-26 11:44:23 -0700135
Benedict Wong0febe5e2017-08-22 21:42:33 -0700136 private static final IpSecAlgorithm AUTH_ALGO =
137 new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
138 private static final IpSecAlgorithm CRYPT_ALGO =
139 new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
140 private static final IpSecAlgorithm AEAD_ALGO =
Benedict Wong4ebc2c52017-11-01 17:14:25 -0700141 new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
evitayan0a7d3e32018-03-22 13:42:07 -0700142 private static final int REMOTE_ENCAP_PORT = 4500;
Benedict Wong0febe5e2017-08-22 21:42:33 -0700143
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800144 public IpSecServiceParameterizedTest(
evitayane4259d32018-03-22 17:53:08 -0700145 String sourceAddr, String destAddr, String localInnerAddr, int family) {
Nathan Harold5676f5f2018-01-16 19:34:01 -0800146 mSourceAddr = sourceAddr;
147 mDestinationAddr = destAddr;
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800148 mLocalInnerAddress = new LinkAddress(localInnerAddr);
evitayane4259d32018-03-22 17:53:08 -0700149 mFamily = family;
Nathan Harold2e9a5202017-09-26 11:44:23 -0700150 }
151
152 @Before
153 public void setUp() throws Exception {
Nathan Harold2e9a5202017-09-26 11:44:23 -0700154 mMockNetd = mock(INetd.class);
155 mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
156 mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
157
158 // Injecting mock netd
159 when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
Nathan Harold21208ee2018-03-15 18:06:06 -0700160 // A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED.
161 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("blessedPackage")))
162 .thenReturn(AppOpsManager.MODE_ALLOWED);
163 // A system package will not be granted the app op, so this should fall back to
164 // a permissions check, which should pass.
165 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("systemPackage")))
166 .thenReturn(AppOpsManager.MODE_DEFAULT);
167 // A mismatch between the package name and the UID will return MODE_IGNORED.
168 when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("badPackage")))
169 .thenReturn(AppOpsManager.MODE_IGNORED);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700170 }
171
evitayan0a7d3e32018-03-22 13:42:07 -0700172 //TODO: Add a test to verify SPI.
173
Nathan Harold2e9a5202017-09-26 11:44:23 -0700174 @Test
175 public void testIpSecServiceReserveSpi() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800176 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
177 .thenReturn(TEST_SPI);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700178
179 IpSecSpiResponse spiResp =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800180 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800181 mDestinationAddr, TEST_SPI, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700182 assertEquals(IpSecManager.Status.OK, spiResp.status);
Nathan Harolda2523312018-01-05 19:25:13 -0800183 assertEquals(TEST_SPI, spiResp.spi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700184 }
185
186 @Test
187 public void testReleaseSecurityParameterIndex() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800188 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
189 .thenReturn(TEST_SPI);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700190
191 IpSecSpiResponse spiResp =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800192 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800193 mDestinationAddr, TEST_SPI, new Binder());
Nathan Harold2e9a5202017-09-26 11:44:23 -0700194
195 mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
196
197 verify(mMockNetd)
198 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700199 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800200 anyString(),
201 anyString(),
202 eq(TEST_SPI),
203 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700204 anyInt(),
Di Lu0b611f42018-01-11 11:35:25 -0800205 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800206
207 // Verify quota and RefcountedResource objects cleaned up
Benedict Wonga0989622018-07-25 13:06:29 -0700208 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800209 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
210 try {
211 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
212 fail("Expected IllegalArgumentException on attempt to access deleted resource");
213 } catch (IllegalArgumentException expected) {
214
215 }
216 }
217
218 @Test
219 public void testSecurityParameterIndexBinderDeath() throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800220 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
221 .thenReturn(TEST_SPI);
Benedict Wong344bd622017-11-16 15:27:22 -0800222
223 IpSecSpiResponse spiResp =
Nathan Harold660a3352017-12-14 14:46:46 -0800224 mIpSecService.allocateSecurityParameterIndex(
Nathan Harolda2523312018-01-05 19:25:13 -0800225 mDestinationAddr, TEST_SPI, new Binder());
Benedict Wong344bd622017-11-16 15:27:22 -0800226
Benedict Wonga0989622018-07-25 13:06:29 -0700227 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800228 IpSecService.RefcountedResource refcountedRecord =
229 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
230
231 refcountedRecord.binderDied();
232
233 verify(mMockNetd)
234 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700235 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800236 anyString(),
237 anyString(),
238 eq(TEST_SPI),
239 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700240 anyInt(),
Di Lu0b611f42018-01-11 11:35:25 -0800241 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800242
243 // Verify quota and RefcountedResource objects cleaned up
244 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
245 try {
246 userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId);
247 fail("Expected IllegalArgumentException on attempt to access deleted resource");
248 } catch (IllegalArgumentException expected) {
249
250 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700251 }
252
Nathan Harolda2523312018-01-05 19:25:13 -0800253 private int getNewSpiResourceId(String remoteAddress, int returnSpi) throws Exception {
254 when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), anyString(), anyInt()))
Benedict Wong0febe5e2017-08-22 21:42:33 -0700255 .thenReturn(returnSpi);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700256
Benedict Wong0febe5e2017-08-22 21:42:33 -0700257 IpSecSpiResponse spi =
Jonathan Basseri5fb92902017-11-16 10:58:01 -0800258 mIpSecService.allocateSecurityParameterIndex(
Benedict Wong0febe5e2017-08-22 21:42:33 -0700259 NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(),
260 IpSecManager.INVALID_SECURITY_PARAMETER_INDEX,
261 new Binder());
262 return spi.resourceId;
263 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700264
Benedict Wong0febe5e2017-08-22 21:42:33 -0700265 private void addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config) throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800266 config.setSpiResourceId(getNewSpiResourceId(mDestinationAddr, TEST_SPI));
Nathan Harold5676f5f2018-01-16 19:34:01 -0800267 config.setSourceAddress(mSourceAddr);
Nathan Harolda2523312018-01-05 19:25:13 -0800268 config.setDestinationAddress(mDestinationAddr);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700269 }
270
271 private void addAuthAndCryptToIpSecConfig(IpSecConfig config) throws Exception {
Nathan Harolda2523312018-01-05 19:25:13 -0800272 config.setEncryption(CRYPT_ALGO);
273 config.setAuthentication(AUTH_ALGO);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700274 }
275
evitayan0a7d3e32018-03-22 13:42:07 -0700276 private void addEncapSocketToIpSecConfig(int resourceId, IpSecConfig config) throws Exception {
277 config.setEncapType(IpSecTransform.ENCAP_ESPINUDP);
278 config.setEncapSocketResourceId(resourceId);
279 config.setEncapRemotePort(REMOTE_ENCAP_PORT);
280 }
281
282 private void verifyTransformNetdCalledForCreatingSA(
283 IpSecConfig config, IpSecTransformResponse resp) throws Exception {
284 verifyTransformNetdCalledForCreatingSA(config, resp, 0);
285 }
286
287 private void verifyTransformNetdCalledForCreatingSA(
288 IpSecConfig config, IpSecTransformResponse resp, int encapSocketPort) throws Exception {
289 IpSecAlgorithm auth = config.getAuthentication();
290 IpSecAlgorithm crypt = config.getEncryption();
291 IpSecAlgorithm authCrypt = config.getAuthenticatedEncryption();
292
293 verify(mMockNetd, times(1))
294 .ipSecAddSecurityAssociation(
295 eq(mUid),
296 eq(config.getMode()),
297 eq(config.getSourceAddress()),
298 eq(config.getDestinationAddress()),
299 eq((config.getNetwork() != null) ? config.getNetwork().netId : 0),
300 eq(TEST_SPI),
301 eq(0),
302 eq(0),
303 eq((auth != null) ? auth.getName() : ""),
304 eq((auth != null) ? auth.getKey() : new byte[] {}),
305 eq((auth != null) ? auth.getTruncationLengthBits() : 0),
306 eq((crypt != null) ? crypt.getName() : ""),
307 eq((crypt != null) ? crypt.getKey() : new byte[] {}),
308 eq((crypt != null) ? crypt.getTruncationLengthBits() : 0),
309 eq((authCrypt != null) ? authCrypt.getName() : ""),
310 eq((authCrypt != null) ? authCrypt.getKey() : new byte[] {}),
311 eq((authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0),
312 eq(config.getEncapType()),
313 eq(encapSocketPort),
Benedict Wong781dae62018-09-06 11:31:25 -0700314 eq(config.getEncapRemotePort()),
315 eq(config.getXfrmInterfaceId()));
evitayan0a7d3e32018-03-22 13:42:07 -0700316 }
317
Nathan Harold2e9a5202017-09-26 11:44:23 -0700318 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800319 public void testCreateTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700320 IpSecConfig ipSecConfig = new IpSecConfig();
321 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
322 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700323
324 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700325 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Nathan Harold2e9a5202017-09-26 11:44:23 -0700326 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
327
evitayan0a7d3e32018-03-22 13:42:07 -0700328 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700329 }
330
331 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800332 public void testCreateTransformAead() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700333 IpSecConfig ipSecConfig = new IpSecConfig();
334 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
335
Nathan Harolda2523312018-01-05 19:25:13 -0800336 ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO);
Benedict Wong0febe5e2017-08-22 21:42:33 -0700337
338 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700339 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wong0febe5e2017-08-22 21:42:33 -0700340 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
341
evitayan0a7d3e32018-03-22 13:42:07 -0700342 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
343 }
344
345 @Test
346 public void testCreateTransportModeTransformWithEncap() throws Exception {
347 IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder());
348
349 IpSecConfig ipSecConfig = new IpSecConfig();
350 ipSecConfig.setMode(IpSecTransform.MODE_TRANSPORT);
351 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
352 addAuthAndCryptToIpSecConfig(ipSecConfig);
353 addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig);
354
evitayane4259d32018-03-22 17:53:08 -0700355 if (mFamily == AF_INET) {
356 IpSecTransformResponse createTransformResp =
357 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
358 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
evitayan0a7d3e32018-03-22 13:42:07 -0700359
evitayane4259d32018-03-22 17:53:08 -0700360 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
361 } else {
362 try {
363 IpSecTransformResponse createTransformResp =
364 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
365 fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
366 } catch (IllegalArgumentException expected) {
367 }
368 }
evitayan0a7d3e32018-03-22 13:42:07 -0700369 }
370
371 @Test
372 public void testCreateTunnelModeTransformWithEncap() throws Exception {
373 IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder());
374
375 IpSecConfig ipSecConfig = new IpSecConfig();
376 ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL);
377 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
378 addAuthAndCryptToIpSecConfig(ipSecConfig);
379 addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig);
380
evitayane4259d32018-03-22 17:53:08 -0700381 if (mFamily == AF_INET) {
382 IpSecTransformResponse createTransformResp =
383 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
384 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
evitayan0a7d3e32018-03-22 13:42:07 -0700385
evitayane4259d32018-03-22 17:53:08 -0700386 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
387 } else {
388 try {
389 IpSecTransformResponse createTransformResp =
390 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
391 fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
392 } catch (IllegalArgumentException expected) {
393 }
394 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700395 }
396
Andreas Gampea7b26b52018-02-26 08:06:30 -0800397 @Test
Benedict Wonge6b42772017-12-13 18:26:40 -0800398 public void testCreateTwoTransformsWithSameSpis() throws Exception {
399 IpSecConfig ipSecConfig = new IpSecConfig();
400 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
401 addAuthAndCryptToIpSecConfig(ipSecConfig);
402
403 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700404 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonge6b42772017-12-13 18:26:40 -0800405 assertEquals(IpSecManager.Status.OK, createTransformResp.status);
406
407 // Attempting to create transform a second time with the same SPIs should throw an error...
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 // ... even if the transform is deleted
415 mIpSecService.deleteTransform(createTransformResp.resourceId);
416 try {
Nathan Harold21208ee2018-03-15 18:06:06 -0700417 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonge6b42772017-12-13 18:26:40 -0800418 fail("IpSecService should have thrown an error for reuse of SPI");
419 } catch (IllegalStateException expected) {
420 }
421 }
422
Nathan Harold2e9a5202017-09-26 11:44:23 -0700423 @Test
Nathan Harold22795302018-02-27 19:19:40 -0800424 public void testReleaseOwnedSpi() throws Exception {
425 IpSecConfig ipSecConfig = new IpSecConfig();
426 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
427 addAuthAndCryptToIpSecConfig(ipSecConfig);
428
429 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700430 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wonga0989622018-07-25 13:06:29 -0700431 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Nathan Harold22795302018-02-27 19:19:40 -0800432 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
433 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
434 verify(mMockNetd, times(0))
435 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700436 eq(mUid),
Nathan Harold22795302018-02-27 19:19:40 -0800437 anyString(),
438 anyString(),
439 eq(TEST_SPI),
440 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700441 anyInt(),
Nathan Harold22795302018-02-27 19:19:40 -0800442 anyInt());
443 // quota is not released until the SPI is released by the Transform
444 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
445 }
446
447 @Test
Benedict Wongf33f03132018-01-18 14:38:16 -0800448 public void testDeleteTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700449 IpSecConfig ipSecConfig = new IpSecConfig();
450 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
451 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700452
453 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700454 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wongf33f03132018-01-18 14:38:16 -0800455 mIpSecService.deleteTransform(createTransformResp.resourceId);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700456
Nathan Harold22795302018-02-27 19:19:40 -0800457 verify(mMockNetd, times(1))
Nathan Harold2e9a5202017-09-26 11:44:23 -0700458 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700459 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800460 anyString(),
461 anyString(),
462 eq(TEST_SPI),
463 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700464 anyInt(),
Di Lu0b611f42018-01-11 11:35:25 -0800465 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800466
467 // Verify quota and RefcountedResource objects cleaned up
Benedict Wonga0989622018-07-25 13:06:29 -0700468 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800469 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
Nathan Harold22795302018-02-27 19:19:40 -0800470 assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
471
472 mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
473 // Verify that ipSecDeleteSa was not called when the SPI was released because the
474 // ownedByTransform property should prevent it; (note, the called count is cumulative).
475 verify(mMockNetd, times(1))
476 .ipSecDeleteSecurityAssociation(
477 anyInt(),
478 anyString(),
479 anyString(),
480 anyInt(),
481 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700482 anyInt(),
Nathan Harold22795302018-02-27 19:19:40 -0800483 anyInt());
484 assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
485
Benedict Wong344bd622017-11-16 15:27:22 -0800486 try {
487 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
488 createTransformResp.resourceId);
489 fail("Expected IllegalArgumentException on attempt to access deleted resource");
490 } catch (IllegalArgumentException expected) {
491
492 }
493 }
494
495 @Test
496 public void testTransportModeTransformBinderDeath() throws Exception {
497 IpSecConfig ipSecConfig = new IpSecConfig();
498 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
499 addAuthAndCryptToIpSecConfig(ipSecConfig);
500
501 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700502 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Benedict Wong344bd622017-11-16 15:27:22 -0800503
Benedict Wonga0989622018-07-25 13:06:29 -0700504 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wong344bd622017-11-16 15:27:22 -0800505 IpSecService.RefcountedResource refcountedRecord =
506 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
507 createTransformResp.resourceId);
508
509 refcountedRecord.binderDied();
510
511 verify(mMockNetd)
512 .ipSecDeleteSecurityAssociation(
Benedict Wonga0989622018-07-25 13:06:29 -0700513 eq(mUid),
Di Lu0b611f42018-01-11 11:35:25 -0800514 anyString(),
515 anyString(),
516 eq(TEST_SPI),
517 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700518 anyInt(),
Di Lu0b611f42018-01-11 11:35:25 -0800519 anyInt());
Benedict Wong344bd622017-11-16 15:27:22 -0800520
521 // Verify quota and RefcountedResource objects cleaned up
522 assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
523 try {
524 userRecord.mTransformRecords.getRefcountedResourceOrThrow(
525 createTransformResp.resourceId);
526 fail("Expected IllegalArgumentException on attempt to access deleted resource");
527 } catch (IllegalArgumentException expected) {
528
529 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700530 }
531
532 @Test
533 public void testApplyTransportModeTransform() throws Exception {
Benedict Wong0febe5e2017-08-22 21:42:33 -0700534 IpSecConfig ipSecConfig = new IpSecConfig();
535 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
536 addAuthAndCryptToIpSecConfig(ipSecConfig);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700537
538 IpSecTransformResponse createTransformResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700539 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
Josh Gao42bd8e12018-10-31 12:26:40 -0700540
541 Socket socket = new Socket();
542 socket.bind(null);
543 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700544
545 int resourceId = createTransformResp.resourceId;
Nathan Harolda2523312018-01-05 19:25:13 -0800546 mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700547
548 verify(mMockNetd)
549 .ipSecApplyTransportModeTransform(
Luke Huange8e522b2018-11-23 12:01:41 +0800550 eq(pfd),
Benedict Wonga0989622018-07-25 13:06:29 -0700551 eq(mUid),
Nathan Harolda2523312018-01-05 19:25:13 -0800552 eq(IpSecManager.DIRECTION_OUT),
Nathan Harold2e9a5202017-09-26 11:44:23 -0700553 anyString(),
554 anyString(),
Nathan Harolda2523312018-01-05 19:25:13 -0800555 eq(TEST_SPI));
Nathan Harold2e9a5202017-09-26 11:44:23 -0700556 }
557
558 @Test
559 public void testRemoveTransportModeTransform() throws Exception {
Josh Gao42bd8e12018-10-31 12:26:40 -0700560 Socket socket = new Socket();
561 socket.bind(null);
562 ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket);
Nathan Haroldf73d2522018-01-17 01:00:20 -0800563 mIpSecService.removeTransportModeTransforms(pfd);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700564
Luke Huange8e522b2018-11-23 12:01:41 +0800565 verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd);
Nathan Harold2e9a5202017-09-26 11:44:23 -0700566 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800567
568 private IpSecTunnelInterfaceResponse createAndValidateTunnel(
Nathan Harold21208ee2018-03-15 18:06:06 -0700569 String localAddr, String remoteAddr, String pkgName) {
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800570 IpSecTunnelInterfaceResponse createTunnelResp =
571 mIpSecService.createTunnelInterface(
Nathan Harold21208ee2018-03-15 18:06:06 -0700572 mSourceAddr, mDestinationAddr, fakeNetwork, new Binder(), pkgName);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800573
574 assertNotNull(createTunnelResp);
575 assertEquals(IpSecManager.Status.OK, createTunnelResp.status);
576 return createTunnelResp;
577 }
578
579 @Test
580 public void testCreateTunnelInterface() throws Exception {
581 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700582 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800583
584 // Check that we have stored the tracking object, and retrieve it
Benedict Wonga0989622018-07-25 13:06:29 -0700585 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800586 IpSecService.RefcountedResource refcountedRecord =
587 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
588 createTunnelResp.resourceId);
589
590 assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent);
591 verify(mMockNetd)
Benedict Wong781dae62018-09-06 11:31:25 -0700592 .ipSecAddTunnelInterface(
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800593 eq(createTunnelResp.interfaceName),
594 eq(mSourceAddr),
595 eq(mDestinationAddr),
596 anyInt(),
Benedict Wong781dae62018-09-06 11:31:25 -0700597 anyInt(),
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800598 anyInt());
599 }
600
601 @Test
602 public void testDeleteTunnelInterface() throws Exception {
603 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700604 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800605
Benedict Wonga0989622018-07-25 13:06:29 -0700606 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800607
Nathan Harold21208ee2018-03-15 18:06:06 -0700608 mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800609
610 // Verify quota and RefcountedResource objects cleaned up
611 assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
Benedict Wong781dae62018-09-06 11:31:25 -0700612 verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName));
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800613 try {
614 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
615 createTunnelResp.resourceId);
616 fail("Expected IllegalArgumentException on attempt to access deleted resource");
617 } catch (IllegalArgumentException expected) {
618 }
619 }
620
621 @Test
622 public void testTunnelInterfaceBinderDeath() throws Exception {
623 IpSecTunnelInterfaceResponse createTunnelResp =
Nathan Harold21208ee2018-03-15 18:06:06 -0700624 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800625
Benedict Wonga0989622018-07-25 13:06:29 -0700626 IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800627 IpSecService.RefcountedResource refcountedRecord =
628 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
629 createTunnelResp.resourceId);
630
631 refcountedRecord.binderDied();
632
633 // Verify quota and RefcountedResource objects cleaned up
634 assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
Benedict Wong781dae62018-09-06 11:31:25 -0700635 verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName));
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800636 try {
637 userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
638 createTunnelResp.resourceId);
639 fail("Expected IllegalArgumentException on attempt to access deleted resource");
640 } catch (IllegalArgumentException expected) {
641 }
642 }
643
644 @Test
Benedict Wong781dae62018-09-06 11:31:25 -0700645 public void testApplyTunnelModeTransform() throws Exception {
646 IpSecConfig ipSecConfig = new IpSecConfig();
647 ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL);
648 addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
649 addAuthAndCryptToIpSecConfig(ipSecConfig);
650
651 IpSecTransformResponse createTransformResp =
652 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
653 IpSecTunnelInterfaceResponse createTunnelResp =
654 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
655
656 int transformResourceId = createTransformResp.resourceId;
657 int tunnelResourceId = createTunnelResp.resourceId;
658 mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT,
659 transformResourceId, "blessedPackage");
660
661 for (int selAddrFamily : ADDRESS_FAMILIES) {
662 verify(mMockNetd)
663 .ipSecUpdateSecurityPolicy(
664 eq(mUid),
665 eq(selAddrFamily),
666 eq(IpSecManager.DIRECTION_OUT),
667 anyString(),
668 anyString(),
669 eq(TEST_SPI),
670 anyInt(), // iKey/oKey
671 anyInt(), // mask
672 eq(tunnelResourceId));
673 }
674
675 ipSecConfig.setXfrmInterfaceId(tunnelResourceId);
676 verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
677 }
678
679 @Test
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800680 public void testAddRemoveAddressFromTunnelInterface() throws Exception {
Nathan Harold21208ee2018-03-15 18:06:06 -0700681 for (String pkgName : new String[]{"blessedPackage", "systemPackage"}) {
682 IpSecTunnelInterfaceResponse createTunnelResp =
683 createAndValidateTunnel(mSourceAddr, mDestinationAddr, pkgName);
684 mIpSecService.addAddressToTunnelInterface(
685 createTunnelResp.resourceId, mLocalInnerAddress, pkgName);
686 verify(mMockNetd, times(1))
687 .interfaceAddAddress(
688 eq(createTunnelResp.interfaceName),
689 eq(mLocalInnerAddress.getAddress().getHostAddress()),
690 eq(mLocalInnerAddress.getPrefixLength()));
691 mIpSecService.removeAddressFromTunnelInterface(
692 createTunnelResp.resourceId, mLocalInnerAddress, pkgName);
693 verify(mMockNetd, times(1))
694 .interfaceDelAddress(
695 eq(createTunnelResp.interfaceName),
696 eq(mLocalInnerAddress.getAddress().getHostAddress()),
697 eq(mLocalInnerAddress.getPrefixLength()));
698 mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, pkgName);
699 }
700 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800701
Nathan Harold8c69bcb2018-05-15 19:18:38 -0700702 @Ignore
Nathan Harold21208ee2018-03-15 18:06:06 -0700703 @Test
704 public void testAddTunnelFailsForBadPackageName() throws Exception {
705 try {
706 IpSecTunnelInterfaceResponse createTunnelResp =
707 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "badPackage");
708 fail("Expected a SecurityException for badPackage.");
709 } catch (SecurityException expected) {
710 }
Benedict Wongecc9f7c2018-03-01 18:53:07 -0800711 }
Nathan Harold2e9a5202017-09-26 11:44:23 -0700712}